Hi, I have just upgraded from 2.10 to 2.14 pants. ...
# general
m
Hi, I have just upgraded from 2.10 to 2.14 pants. We used to have empty BUILD files earlier. Somewhat like
Copy code
python_sources()

python_tests(
name="tests",
)
And pants used to figure out all the dependencies. But now after the upgrade, all the test cases with above BUILD files are failing since pants is not able to figure out the dependencies. Is there a setting I am missing or this is no longer supported?
h
Hi, sorry for the trouble. Dependency inference is definitely still a major feature of Pants, so obviously something is awry. Are you seeing any warnings logged?
m
Example of failing test case. This below was working earlier:
Copy code
python_tests(
    name="dummy_test.py",
    sources=["test_dummy.py"],
    dependencies=[":dum"],
)
But now it throws exception:
ModuleNotFoundError: No module named 'pkg_resources'
Even though I have this in my project BUILD file
Copy code
python_requirement(
    name="setuptools",
    requirements=["setuptools"],
)
My pants.toml looks like:
Copy code
[python]
enable_resolves = true
resolves_generate_lockfiles = false

[python.resolves]
python-default = "requirements.txt"
I ran .
/pants filter --target-type=python_requirement ::
and see //:reqs#setuptools //:setuptools
r
What are the 3rd party packages being used in your dummy_test?
Some 3rdparty packages don't define well their dependencies on Setuptools
So pants can't infer it. But this should have been happening before too. So I'm not sure why you only see it now
So defining them just as a
python_requirement
isn’t enough if the package which you are using doesn’t define that it has its own dependency on it. So in this case, you need to put an explicit dependency on target associated with
setuptools
Copy code
python_tests(
    name="dummy_test.py",
    sources=["test_dummy.py"],
    dependencies=[":dum", ":reqs#setuptools"],
)
You don’t need to define it again as
python_requirement
. Just use the existing one.
m
Yeah, though I have two virtualenvs one with poetry 1.1.14, pants 2.10 and another with poetry 1.3.1 and pants 2.14. I have not added explicit "`:reqs#setuptools`" in both `python_tests`() but have
python_requirement
with setuptools in project level BUILD file. Only other changes are in pants.toml. Now the test in first environment is working, whereas the second environment with upgraded pants is failing with below error.
E   ModuleNotFoundError: No module named 'pkg_resources'
r
I would run it with same version of poetry to just rule out if it’s something related to poetry version itself.
h
I think I see the problem
There are two targets providing pkg_resources:
Copy code
//:reqs#setuptools
//:setuptools
So Pants doesn't know which one to pick
This looks suspicious:
Copy code
[python.resolves]
python-default = "requirements.txt"
How is that
requirements.txt
created? Is at an existing file?
m
requirements.txt is created manually via
Copy code
poetry export -f requirements.txt -o requirements.txt  --without-hashes
We anyways will have setuptools in requirements.txt so I can try removing it from the project BUILD file here
Copy code
python_requirement(
    name="setuptools",
    requirements=["setuptools"],
)
So, that //:reqs#setuptools is only option.
@happy-kitchen-89482 I have removed setuptools from project BUILD file as there were duplicate targets. But I have two more dependencies in BUILD file which are not present in pyproject.toml or requirements.txt. They are only added in BUILD file as a
python_requirement
, shouldn't pants install them via pip and use them as dependency? These are the dependencies.
Copy code
python_requirement(
    name="torch",
    requirements=["torch==1.10.0+cpu"],
    dependencies=[":setuptools"],
)

python_requirement(
    name="pytorch-lightning",
    requirements=["pytorch-lightning"],
    dependencies=[":torch"],
)
And this is the exception it's leading to.
I am seeing this issue only after upgrade to 2.14 version, the tests were working fine with 2.10 with same BUILD file.
h
So you're using a poetry-generated
requirements.txt
as your lockfile. What is the BUILD file target that wraps that? And is
pytorch-lightning
in that requirements.txt?
Your config is slightly confusing, because usually the name
requirements.txt
is used to describe the inputs from which a lockfile is generated, not the lockfile itself...
m
Yep, that's correct. We are using poetry-generated requirements.txt as a lockfile. Here's my pants.toml config:
Copy code
[poetry]
version = "poetry==1.3.1"

[python]
interpreter_constraints = ["==3.7.*"]
enable_resolves = true
resolves_generate_lockfiles = false

[python.resolves]
python-default = "requirements.txt"

[pytest]
extra_requirements = ["pytest-mock==3.8.2", "pytest-pgsql==1.1.2", "pytest-icdiff==0.6", "pygments==2.12.0", "pytest-cov==3.0.0", "pytest-bdd==6.0.1"]
lockfile = "pytest_lockfile.txt"
And this is my project level BUILD file.
Copy code
python_requirement(
    name="torch",
    requirements=["torch==1.10.0+cpu"],
    dependencies=["//:reqs#setuptools"],
)

python_requirement(
    name="pytorch-lightning",
    requirements=["pytorch-lightning"],
    dependencies=[":torch"],
)

python_requirements(
    name="reqs",
    module_mapping={
        "python-constraint": ["constraint"],
        "google-api-core": ["google.api_core"],
        "grpcio": ["grpc"],
        "grpcio-health-checking": ["grpc_health"],
        "python-json-logger": ["pythonjsonlogger"],
    },
)
requirements.txt
doesn't contain torch or pytorch-lightning, these are only present in BUILD file.
h
Gotcha. So that explains the problem. The lockfile must include all the requirements you're using... That's easy to achieve when Pants generates the lockfiles for you, but if using external lockfiles, as you are, you have to keep them in sync manually.
The way to think about this is: The BUILD file requirements are the ingredients to the lockfile.
They say what you want to use, and the lockfile locks down the exact versions of those and all their transitive deps.
m
Thanks @happy-kitchen-89482. Does that mean adding
pytorch-lightning==1.5.0
as a python_requirement in BUILD file is same as adding adding
pytorch-lightning==1.5.0 ; python_version >= "3.7" and python_version < "4.0"
in requirements.txt. Another question I have is, does pants try to download the requirement mentioned in BUILD file's python_requirement via pip? In above case, should torch and pytorch-lightning be added to requirements.txt to resolve the issue? And if I do add them then is there a use of having them in BUILD file at all?
h
Not quite. The BUILD files are necessary, they tell Pants what requirements you want to make available to your code.
You can work with no lockfile at all. But that is not recommended because you won't get consistent, repeatable results, and there can be security implications.
So we recommend working with a lockfile. The lockfile says, in effect, "for all the requirements you specified in the BUILD files, and for their transitive dependencies, here are the exact SHA-locked wheels you should use"
So everything in the BUILD files should be used as input when generating the lockfile.
When you let Pants generate lockfiles for you, it knows how to do this automatically when you run
./pants generate-lockfiles --resolve=python-default
But since you're using an external lockfile, you have to be responsible for ensuring it contains all the things you need
For example, since you're using poetry, you could replace those BUILD file requirements with a
poetry_requirements()
target that wraps your pyproject.toml
That says to Pants "Make the requirements in pyproject.toml available to code", and then the lockfile generated from those requirements by poetry will naturally contain them all
So you'd add
pytorch-lightning
and whatever else you're currently manually configuring in BUILD files to your pyproject.toml
Alternatively, you can use Pants to generate your lockfiles, which is what I'd recommend
m
Thanks Benjy, a quick clarification. You mean pants to generate lock files via:
./pants generate-lockfiles
, right?
h
Exactly