From 75bb4d312d2e915addba3cdc85fa1b7ebb8c6ab5 Mon Sep 17 00:00:00 2001 From: Peter Lobsinger Date: Fri, 1 Aug 2025 10:58:58 -0400 Subject: [PATCH 1/2] Support building PEX archives to inherit from the sys.path By default PEX archives are built to operate fully hermetically, which is usually a good idea. However, sometimes it is necessary to use packages from the hosting environment. One such example is AWS Lambda; the recommended approach for using PEX to run on Lambda is to build in this way.[^1] Mapping of this flag through from the build system largely follows the equivalent feature in Pants.[^2] [^1]: https://github.com/pex-tool/lambdex/blob/main/MIGRATING.md [^2]: https://www.pantsbuild.org/stable/reference/targets/pex_binary#inherit_path --- py/private/py_pex_binary.bzl | 12 ++++++++++++ py/tools/pex/main.py | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/py/private/py_pex_binary.bzl b/py/private/py_pex_binary.bzl index e3d99609..354cb45c 100644 --- a/py/private/py_pex_binary.bzl +++ b/py/private/py_pex_binary.bzl @@ -106,6 +106,9 @@ def _py_python_pex_impl(ctx): args.add(ctx.attr.python_shebang, format = "--python-shebang=%s") args.add(py_toolchain.python, format = "--python=%s") + if ctx.attr.inherit_path != "": + args.add(ctx.attr.inherit_path, format = "--inherit-path=%s") + py_version = py_toolchain.interpreter_version_info args.add_all( [ @@ -135,6 +138,15 @@ _attrs = dict({ doc = "Environment variables to set when running the pex binary.", default = {}, ), + "inherit_path": attr.string( + doc = """\ +Whether to inherit the `sys.path` (aka PYTHONPATH) of the environment that the binary runs in. + +Use `false` to not inherit `sys.path`; use `fallback` to inherit `sys.path` after packaged +dependencies; and use `prefer` to inherit `sys.path` before packaged dependencies. +""", + values = ["false", "fallback", "prefer"], + ), "python_shebang": attr.string(default = "#!/usr/bin/env python3"), "python_interpreter_constraints": attr.string_list( default = ["CPython=={major}.{minor}.*"], diff --git a/py/tools/pex/main.py b/py/tools/pex/main.py index e2880e1d..996da25b 100644 --- a/py/tools/pex/main.py +++ b/py/tools/pex/main.py @@ -9,6 +9,7 @@ import sys from pex.pex_builder import Check,PEXBuilder +from pex.inherit_path import InheritPath from pex.interpreter import PythonInterpreter from pex.interpreter_constraints import InterpreterConstraint from pex.layout import Layout @@ -26,6 +27,13 @@ def __call__(self, parser, namespace, value, option_str=None): ) self.default.append(tuple(components)) + +class InheritPathAction(Action): + def __call__(self, parser, namespace, value, option_str=None): + value = InheritPath.for_value(value) + setattr(namespace, self.dest, value) + + parser = ArgumentParser(fromfile_prefix_chars='@') parser.add_argument( @@ -107,6 +115,13 @@ def __call__(self, parser, namespace, value, option_str=None): action="append", ) +parser.add_argument( + "--inherit-path", + dest="inherit_path", + default=None, + action=InheritPathAction, +) + options = parser.parse_args(args = sys.argv[1:]) # Monkey patch bootstrap template to inject some templated environment variables. @@ -157,6 +172,8 @@ def __call__(self, parser, namespace, value, option_str=None): InterpreterConstraint.parse(constraint) for constraint in options.constraints ] +if options.inherit_path is not None: + pex_info.inherit_path = options.inherit_path for dep in options.dependencies: dist = Distribution.load(dep) From 619186d5edcca3112739e1fd1e8c137b2b1edf51 Mon Sep 17 00:00:00 2001 From: Peter Lobsinger Date: Fri, 1 Aug 2025 11:10:24 -0400 Subject: [PATCH 2/2] bazel run docs:update --- docs/pex.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/pex.md b/docs/pex.md index 92504a3e..590eaadd 100644 --- a/docs/pex.md +++ b/docs/pex.md @@ -25,7 +25,8 @@ py_pex_binary( ## py_pex_binary
-py_pex_binary(name, binary, inject_env, python_interpreter_constraints, python_shebang)
+py_pex_binary(name, binary, inherit_path, inject_env, python_interpreter_constraints,
+              python_shebang)
 
Build a pex executable from a py_binary @@ -37,6 +38,7 @@ Build a pex executable from a py_binary | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | binary | A py_binary target | Label | required | | +| inherit_path | Whether to inherit the sys.path (aka PYTHONPATH) of the environment that the binary runs in.

Use false to not inherit sys.path; use fallback to inherit sys.path after packaged dependencies; and use prefer to inherit sys.path before packaged dependencies. | String | optional | "" | | inject_env | Environment variables to set when running the pex binary. | Dictionary: String -> String | optional | {} | | python_interpreter_constraints | Python interpreter versions this PEX binary is compatible with. A list of semver strings. The placeholder strings {major}, {minor}, {patch} can be used for gathering version information from the hermetic python toolchain. | List of strings | optional | ["CPython=={major}.{minor}.*"] | | python_shebang | - | String | optional | "#!/usr/bin/env python3" |