can anyone point me to info on how (whether) trans...
# general
n
can anyone point me to info on how (whether) transitive dependencies resolved and stored in pants lockfiles end up with version constraints in packaged artifacts? My instinct is that if I use
generate-lockfiles
to create a lockfile and then
pants package
some code, the resulting artifact should demand that transitive dependencies are frozen at the versions resolved in my lockfile -- because that's what would make consuming that output downstream repeatable based on what was built (and tested). That doesn't seem to be what's happening, and I don't know whether there's some
pants
config that would make it be true, or whether I'm looking in the wrong place, or indeed -- given that I am not well-versed in the python ecosystem -- whether I am wanting something unreasonable or unpythonic. Example of what I'm doing in the thread so I don't make the chat too noisy 🧵
I have a lockfile which includes:
Copy code
# default.lock
...
          "project_name": "pytest",
          "requires_dists": [
            "argcomplete; extra == \"testing\"",
            "atomicwrites>=1.0; sys_platform == \"win32\"",
            "attrs>=19.2.0",
            "colorama; sys_platform == \"win32\"",
            "hypothesis>=3.56; extra == \"testing\"",
            "importlib-metadata>=0.12; python_version < \"3.8\"",
            "iniconfig",
            "mock; extra == \"testing\"",
            "nose; extra == \"testing\"",
            "packaging",
            "pluggy<2.0,>=0.12",
            "py>=1.8.2",
            "pygments>=2.7.2; extra == \"testing\"",
            "requests; extra == \"testing\"",
            "tomli>=1.0.0",
            "xmlschema; extra == \"testing\""
          ],
I have a python file which (for the purposes of demonstration) includes an
import pytest
... and I have a pants rule:
Copy code
python_distribution(
    name="dist",
    dependencies=[
        ":sources",
    ],
    provides=python_artifact(
        name="whatever",
        version="v0.0.1",
        description="Whatever",
    ),
)
... which, when built, only fixes a version of
pytest
, but not of any other dependencies which
pytest
needs
Copy code
❯ unzip -p dist/whatever-0.0.1-py3-none-any.whl whatever-0.0.1.dist-info/METADATA
Metadata-Version: 2.1
Name: whatever
Version: 0.0.1
Summary: Whatever
Requires-Python: ==3.9.13
Requires-Dist: pytest (==7.1.0)
I would have expected to additionally see some constraints around the versions of e.g.
argcomplete
,
atomicwrites
, and so on in that file based on what I resolved in the lockfile.
c
doing what you suggest would end up with a library that is very difficult to consume. Say I need you library and some other library, both of whom depend transitively on
atomicwrites
Now, unless they where released about the same time, the version of atomicwrites may be pinned to different versions, which would require one or both of my deps to have to make a new release simply to have them both agree on which version of all transient deps to use. Does that make sense to you?
h
If you build a pex, it will contain the exact pinned transitive deps, as you expect.
When you build a distribution though, it only specifies your direct deps (which is how distribution metadata is supposed to work) and it uses the loose constraints, e.g., from your requirements.txt, for the reason Andreas stated
It sounds like you could benefit from deploying a pex though?
Or if it had to be a dist, you could script something up to turn the lockfile into a requirements.txt and then use that as an input to setup.py, but that's abusing setup.py, dists weren't intended to pin their transitive deps afaik
c
I would likely go with distributing the locked requirements as a optional
constraints.txt
for consumers to use as appropriate.