We have three projects A, B and C. Project C is a ...
# general
d
We have three projects A, B and C. Project C is a common util project which is used by projects A and B. We are using
pex_binaries
and
python_distribution
targets in all projects using a macro. Before adding
python_distribution
,
pants repl
used to work fine. After adding
python_distribution
, we are seeing a resolve error
Copy code
pex.environment.ResolveError: Failed to resolve requirements from PEX environment @ /path/to/.cache/pants/named_caches/pex_root/unzipped_pexes/d5bb451b67b4592376d4f6e8dde708facaf22sf7.
Needed cp39-cp39-manylinux_2_31_x86_64 compatible dependencies for:
 1: project-c==0.0.1
    Required by:
      project-a 0.0.1
    But this pex had no ProjectName(raw='project-c', normalized='project-c') distributions.
 2: numpy>=1.24.0
    Required by:
      project-a 0.0.1
    But this pex had no ProjectName(raw='numpy', normalized='numpy') distributions.
A couple of questions: 1. When only using
pex_binaries
, the repl command works fine but when adding
python_distribution
it breaks. Why is this happening? 2. numpy is a direct dependency added in the
dependencies
field in
python_distribution
and
project-c
should be an inferred dependency from the code. Why is it not resolving these dependencies? I verified they were added successfully to the wheel file. Thanks Edit: we are using pants 2.16.0rc4
h
Why do you need a pex and a distribution? Those are in at least conceptual conflict: a pex contains everything it neeeds to run, including all transitive deps. A distribution contains just its own code, and its metadata lists the other distributions it requires.
It would help if you could publish a github repo with an example of what you're doing, including the relevant parts of pants.toml and the actual BUILD files (redacted as needed)
b
Benjy, is the Pants thinking that a
python_distribution
is only needed when it's an external artifact (e.g. publishing wheels), rather than for consumption within the repo by `pex_binary`ies etc.?
h
Something vaguely like that šŸ™‚ I'd like to see the specific example to be sure
d
Hi @happy-kitchen-89482, Andrew and I work together. We need the
python_distribution
defined so we can build wheels for pushing to our artifact store. We use
pex
for things like that whole "run our code on a remote host" thing I outlined here.
We spent more time debugging this. It seems like Pants is struggling to infer owners of imports. Our monorepo has multiple resolves. Pants is spitting out messages like this:
Copy code
Pants cannot infer owners for the following imports in the target ...
* numpy (line: 3)
and earlier in the logs, it complains like so:
Copy code
imports `numpy`, but Pants cannot safely infer a dependency because more than one target owns this module, so it is ambiguous which to use
We have multiple directories with their own BUILD files. Each of these directories has a
requirements.txt
file defined with a corresponding
python_requirements
target. Is it problematic if multiple
requirements.txt
files specify the same dependency? Does that prevent dependency inference from working properly?
h
It is, and it does.
Are these all in the same resolve? or are you using multiple resolves?
Basically, you have multiple targets providing the
numpy
package, and pants doesn't know which one to select
Except, a recent change will now resolve those based on source roots
So code in a source root will take the dep provided by the target in the same source root (assuming there is only one)
What is your layout of these directories wrt source roots? And which Pants version are you using?
This is the change in question: https://github.com/pantsbuild/pants/pull/17489
it will be in 2.16.x (you can try the just-released 2.16.0rc6 to see if that solves the issue)
d
That's good to know. We are on Pants 2.16.0rc6 and seeing this behavior. Here's a trimmed down version of our tree structure for this repo ATM:
Copy code
.
ā”œā”€ā”€ locks
│   ā”œā”€ā”€ real_stuff.lock.jsonc (numpy 1.25)
│   ā”œā”€ā”€ pants-plugins.lock.jsonc
│   ā”œā”€ā”€ resolve_example_1.lock.jsonc (numpy 1.23)
│   └── resolve_example_2.lock.jsonc (numpy 1.24)
ā”œā”€ā”€ pants-plugins
│   ā”œā”€ā”€ BUILD
│   ā”œā”€ā”€ plugin_1
│   │   ā”œā”€ā”€ rules.py
│   │   ā”œā”€ā”€ register.py
│   ā”œā”€ā”€ plugin_2
│   │   ā”œā”€ā”€ register.py
│   │   └── rules.py
│   ā”œā”€ā”€ macros.py
ā”œā”€ā”€ pants.toml
ā”œā”€ā”€ projects
│   ā”œā”€ā”€ examples
│   │   ā”œā”€ā”€ example_project_1
│   │   │   ā”œā”€ā”€ BUILD (resolve=resolve_example_1)
│   │   │   ā”œā”€ā”€ example_project_1
│   │   │   │   └── f1.py (imports example_util_library.sample)
│   │   │   ā”œā”€ā”€ requirements.txt (numpy < 1.24)
│   │   ā”œā”€ā”€ example_project_2
│   │   │   ā”œā”€ā”€ BUILD (resolve=resolve_example_2)
│   │   │   ā”œā”€ā”€ example_project_2
│   │   │   │   └── f2.py (imports example_util_library.sample)
│   │   │   ā”œā”€ā”€ requirements.txt (numpy >= 1.24)
│   │   └── example_util_library
│   │       ā”œā”€ā”€ BUILD (resolves=[resolve_example_1, resolve_example_2])
│   │       ā”œā”€ā”€ example_util_library
│   │       │   └── sample.py (imports numpy)
│   │       ā”œā”€ā”€ requirements.txt (numpy < 1.25)
│   └── real_stuff
│       ā”œā”€ā”€ groceries
│       │   └── shopping
│       │       ā”œā”€ā”€ BUILD (resolve=real_stuff)
│       │       ā”œā”€ā”€ requirements.txt
│       │       ā”œā”€ā”€ shopping
│       │       │   ā”œā”€ā”€ buy.py (references grocery_utils.make_a_list)
│       │   └── grocery_utils (resolve=real_stuff)
│       │       ā”œā”€ā”€ BUILD
│       │       ā”œā”€ā”€ requirements.txt (numpy)
│       │       ā”œā”€ā”€ grocery_utils
│       │       │   ā”œā”€ā”€ make_a_list.py (imports numpy)
└── pyproject.toml
Things seem to be working fine for the two "example" resolves, but maybe that's just because all three BUILD files specify something about
numpy
? For the
real_stuff
resolve,
shopping
references
grocery_utils
, but doesn't know about numpy. At runtime though, when invoking
make_a_list
, things fail because the numpy dependency isn't inferred. For now, we've worked around this by adding an explicit entry in our
python_sources
dependencies list to point to the
python_requirements
in the same
BUILD
file. This allows us to keep moving forward, but isn't ideal as every source file in a
python_sources
now depends on every line in a
requirements.txt
which will lead to more cache-misses even when that's not actually necessary
h
What are your source roots?
Run
pants roots
to see them.
d
Something like this:
Copy code
.
pants-plugins
projects/examples/example_project_1
projects/examples/example_project_2
projects/examples/example_util_library
projects/real_stuff/groceries/shopping
projects/real_stuff/groceries/grocery_utils