From db8d65df672dbde9fe7e0db5db63809fde93e4ae Mon Sep 17 00:00:00 2001 From: Chris Novakovic Date: Mon, 27 Oct 2025 16:07:49 +0000 Subject: [PATCH] Break mutual dependency between please_pex and test runners The please_pex tool depends on various third-party modules for the built-in test runner bootstraps, which in turn require please_pex in order to be built. This circular dependency prevents the plugin from being built entirely from source - see #265. The root cause of this circular dependency is the presence of the entry points in `//third_party/python:{behave,pytest}` - `python_wheel` doesn't require please_pex per se, but the use of the `binary` or `entry_points` parameters results in `python_binary` being used to build the outputs, which does require please_pex in order to make them executable. The entry points aren't actually necessary on these targets, though, because the generated .pex files aren't executed directly - they are just unzipped and concatenated onto the please_pex binary to form the bootstrap archive containing the built-in test runners and their transitive dependencies. Remove the `entry_points` parameters from the behave and pytest targets, and refactor the `//tools/please_pex` dependency tree so that the test runners and all of their transitive dependencies are present when the bootstrap archive is concatenated onto the main please_pex binary. The bootstrap archive's contents remain the same, with the following omissions: - `.bootstrap/plz.py` - This is written by please_pex when creating an executable .pex - its presence isn't meaningful or required in the bootstrap archive. - `.bootstrap/py/_vendored_packages/apipkg-2.0.0.dist-info/__init__.py` - `.bootstrap/py/_vendored_packages/iniconfig-1.1.1.dist-info/__init__.py` - These empty files were created by please_pex when creating the executable .pex for pytest - their presence isn't meaningful or required in the bootstrap archive. Fixes #265. --- third_party/python/BUILD | 13 ++++--------- tools/please_pex/BUILD | 16 ++++++++-------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/third_party/python/BUILD b/third_party/python/BUILD index 8ed7ae0..6513b4e 100644 --- a/third_party/python/BUILD +++ b/third_party/python/BUILD @@ -232,7 +232,6 @@ python_wheel( "_pytest", "pytest", ], - entry_points = "pytest:main", hashes = ["1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"], licences = ["MIT"], version = "7.4.2", @@ -271,10 +270,6 @@ python_wheel( outs = [ "behave", ], - entry_points = { - "behave": "behave.__main__:main", - "behave_test": "setuptools_behave:behave_test", - }, hashes = ["ebda1a6c9e5bfe95c5f9f0a2794e01c7098b3dde86c10a95d8621c5907ff6f1c"], licences = ["BSD-2-Clause"], version = "1.2.6", @@ -417,7 +412,7 @@ python_wheel( # This is the minimum set of third-party packages required for the built-in test runners to work # with "plz test" and "plz cover". All built-in test runners should include this as a source. -filegroup( +python_library( name = "test_bootstrap", deps = [ ":coverage", @@ -425,7 +420,7 @@ filegroup( ], ) -filegroup( +python_library( name = "unittest_bootstrap", deps = [ ":test_bootstrap", @@ -433,7 +428,7 @@ filegroup( ], ) -filegroup( +python_library( name = "pytest_bootstrap", deps = [ ":pytest", @@ -441,7 +436,7 @@ filegroup( ], ) -filegroup( +python_library( name = "behave_bootstrap", deps = [ ":behave", diff --git a/tools/please_pex/BUILD b/tools/please_pex/BUILD index e54b1dc..d641609 100644 --- a/tools/please_pex/BUILD +++ b/tools/please_pex/BUILD @@ -22,30 +22,30 @@ go_binary( genrule( name = "please_pex", srcs = { - "bootstraps": [ - "//third_party/python:coverage", - "//third_party/python:portalocker", - "//third_party/python:pytest", - "//third_party/python:xmlrunner", - "//third_party/python:behave", - ], "main": [":pex_main"], }, outs = ["please_pex"], binary = True, cmd = [ - 'for i in $SRCS_BOOTSTRAPS; do if echo "$i" | grep -q \'\\.pex$\'; then "$TOOL" x -o . "$i"; rm -f "$i"; fi; done', + 'for i in third_party/python/*.pex.zip; do "$TOOL" x -o . "$i"; rm -f "$i"; done', "rm -f third_party/python/__*_main__.py*", # Have to make sure these exist. "touch third_party/__init__.py third_party/python/__init__.py", "touch tools/__init__.py tools/please_pex/__init__.py", + "mkdir -p .bootstrap", "mv third_party/python/* .bootstrap", # A little cleanup. "rm -rf third_party .bootstrap/xmlrunner/extra .bootstrap/coverage/htmlfiles .bootstrap/.*.pex.zip", '"$TOOL" z -d -i .bootstrap -o "$OUTS" --preamble_file $(location :pex_main)', ], + needs_transitive_deps = True, tools = [CONFIG.ARCAT_TOOL], visibility = ["PUBLIC"], + deps = [ + "//third_party/python:behave_bootstrap", + "//third_party/python:pytest_bootstrap", + "//third_party/python:unittest_bootstrap", + ], ) python_test(