cool-easter-32542
08/20/2023, 3:15 AMpython_distribution containing a native extension (and therefore using manual setup.py). The distribution also depends on a third party package. Packaging works fine. When trying to run tests set up to consume the distribution, pants fails with an error about Failure to resolve the third party dependency requirements from the PEX Environment when 'Building pytest_runner.pex'. Detailed reproduction steps and preliminary investigation below.
Ran into this issue while trying to port the simple example distribution from https://www.manning.com/books/publishing-python-packages into pants.
Pants version
2.16.0
OS
MacOS Ventura 13.0
Additional info
Reproduction
A repo to reproduce the situation is here: https://github.com/gauthamnair/pants-example-local-dist/tree/main
Run pants package :: and it will work fine, producing a wheel that can be installed in a clean virtualenv elsewhere and it pulls in the extra dep automatically.
But pants test :: fails with:
$ pants --no-local-cache test ::
15:35:20.56 [INFO] Initialization options changed: reinitializing scheduler...
15:35:24.66 [INFO] Scheduler initialized.
15:35:26.45 [INFO] Canceled: Building pytest.pex from <resource://pants.backend.python.subsystems/pytest.lock>
15:35:27.05 [INFO] Completed: Building 1 requirement for requirements.pex from the main_resolve.lock resolve: tabulate
15:35:27.28 [INFO] Completed: Building pytest.pex from <resource://pants.backend.python.subsystems/pytest.lock>
15:35:28.45 [INFO] Completed: Building 3 requirements for build_backend.pex from the setuptools.lock resolve: cython, setuptools, wheel
15:35:30.14 [INFO] Completed: List contents of artifacts produced by //:foodist
15:35:32.04 [INFO] Completed: Building local_dists.pex with 1 requirement: foo-0.0.1-cp39-cp39-macosx_10_9_universal2.whl
15:35:32.66 [INFO] Completed: Building pytest_runner.pex
15:35:32.66 [ERROR] 1 Exception encountered:
Engine traceback:
in `test` goal
ProcessExecutionFailure: Process 'Building pytest_runner.pex' failed with exit code 1.
stdout:
stderr:
Failed to resolve requirements from PEX environment @ /Users/gauthamnair/.cache/pants/named_caches/pex_root/unzipped_pexes/4e96679a2dc078756a2200d65211ed056ad32e7e.
Needed cp39-cp39-macosx_13_0_arm64 compatible dependencies for:
1: tabulate
Required by:
foo 0.0.1
But this pex had no ProjectName(raw='tabulate', normalized='tabulate') distributions.
Description of setup
.
├── BUILD # defines the python_distribution, generate_setup = False
├── LICENSE
├── README.md
├── dist # these generated packages install fine
│ ├── foo-0.0.1-cp39-cp39-macosx_10_9_universal2.whl
│ └── foo-0.0.1.tar.gz
├── main_resolve.lock # contains the third party dep
├── pants.toml
├── requirements.txt # contains the third-party dep
├── setup.py # contains the third-party dep in the install_requires
├── setuptools-requirements.txt # custom setuptools lockfile to include Cython in the setuptools ExternalTool
├── setuptools.lock
├── src
│ └── foo
│ ├── BUILD
│ ├── __init__.py
│ ├── bar.pyx # trivial cython module
│ └── main.py # consumes bar and the thirdparty dep
└── test
├── BUILD # instructs the tests here to depend on the python_distribution
├── test_foo.py
└── test_main.py
This project defines a distribution package "foo". foo contains a native extension (built with Cython). foo also depends on a third party library (tabulate).
The tests depend on the distribution as a matter of necessity, but also to simulate the behavior seen by a user who installs the package. It uses the capability introduced in #12573 to depend on a distribution via the local_dists mechanism.
Preliminary debugging
Failure happens when building the pytest_runner pex. The sandbox looks like this at the moment of failure:
/private/var/folders/z4/dvm2try15dg7gl1vcc_6pv140000gn/T/pants-sandbox-Xlkblq
├── .cache
│ └── pex_root -> /Users/gauthamnair/.cache/pants/named_caches/pex_root
├── .python-build-standalone -> /private/var/folders/z4/dvm2try15dg7gl1vcc_6pv140000gn/T/immutable_inputsMuvD08/.tmpRwZekH/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
├── .tmp
├── __run.sh
├── local_dists.pex
│ ├── .bootstrap
│ ├── .deps
│ │ └── foo-0.0.1-cp39-cp39-macosx_10_9_universal2.whl
│ ├── PEX-INFO
│ ├── __main__.py
│ └── __pex__
│ └── __init__.py
├── pex
├── pytest.pex
│ ├── .bootstrap
│ ├── .deps
│ │ ├── attrs-22.2.0-py3-none-any.whl
...
│ │ ├── pytest_xdist-2.5.0-py3-none-any.whl
│ │ └── tomli-2.0.1-py3-none-any.whl
│ ├── PEX-INFO
│ ├── __main__.py
│ └── __pex__
│ └── __init__.py
├── requirements.pex
│ ├── .bootstrap
│ ├── .deps
│ │ └── tabulate-0.9.0-py3-none-any.whl
│ ├── PEX-INFO
│ ├── __main__.py
│ └── __pex__
│ └── __init__.py
└── source_files
foo is in the local_dists.pex, alone, and the third party dep tabulate is in the requirements.pex.
modifying the __run.sh to have PEX_VERBOSE=1 and running in the sandbox
...
pex: Failed to resolve a requirement: tabulate
pex: Unresolved requirements:
pex: - tabulate
pex: Distributions contained within this pex:
pex: - foo-0.0.1-cp39-cp39-macosx_10_9_universal2.whl
Traceback (most recent call last):
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/result.py", line 105, in catch
return func(*args, **kwargs)
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/bin/pex.py", line 856, in do_main
pex_builder = build_pex(
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/bin/pex.py", line 767, in build_pex
pex_builder.set_script(options.script)
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/pex_builder.py", line 360, in set_script
distributions.update(PEX(pex, interpreter=self._interpreter).resolve())
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/orderedset.py", line 45, in update
for key in iterable:
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/pex.py", line 215, in resolve
for dist in env.resolve():
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/environment.py", line 502, in resolve
for fingerprinted_distribution in self.resolve_dists(all_reqs)
File "/<some_long_path>/pex-2.1.134-py2.py3-none-any.whl/pex/environment.py", line 589, in resolve_dists
raise ResolveError(
pex.environment.ResolveError: Failed to resolve requirements from PEX environment @ /Users/gauthamnair/.cache/pants/named_caches/pex_root/unzipped_pexes/b87e8afec3011a2eb8ceb0ef15f6c0abc9097f6c.
Needed cp39-cp39-macosx_13_0_arm64 compatible dependencies for:
1: tabulate
Required by:
foo 0.0.1
But this pex had no ProjectName(raw='tabulate', normalized='tabulate') distributions.
It appears the builder is trying to "resolve" the local_dists pex while trying to determine what the script should be for the pytest runner pex. The resolve is expecting that the third-party dep is within the local_dists pex, but it isn't - its in the requirements.pex only.
pantsbuild/pants