pypa / pipenv

Python Development Workflow for Humans.
https://pipenv.pypa.io
MIT License
24.85k stars 1.87k forks source link

Issue resolving of python version with point python version check #5908

Open matejsp opened 1 year ago

matejsp commented 1 year ago

Issue description

Requires is not correctly resolved for minor python version (or when specifiying full version).

[requires]
python_version = "3.11"

[packages]
redis = "==5.0.0"
# async-timeout = "==4.0.3"  # uncomment after pipenv bugfix needed by redis for 3.11.2 and less

I then I generate lock file using python 3.11.2 and 3.11.5. Now 3.11.5 does not lock async-timeout when 3.11.2 does. Ideally python version that I run pipenv with should be irrelevant.

But I set that I require python version 3.11 so I should always get async-timeout and shouldn't be related to python version that I run pipenv with.

https://github.com/redis/redis-py/blob/master/setup.py

    install_requires=[
        'importlib-metadata >= 1.0; python_version < "3.8"',
        'typing-extensions; python_version<"3.8"',
        'async-timeout>=4.0.2; python_full_version<="3.11.2"',
    ],

I tried various changes like: python_full_version = "3.11.0"

Expected result

Get requirements based on python version not version that I run pipenv with. So for 3.11 we should have also this dependency locked with correct marker.

        "async-timeout": {
            "hashes": [
                "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f",
                "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"
            ],
            "index": "pypi",
            "markers": "python_full_version<='3.11.2'",
            "version": "==4.0.3"
        },

Actual result

pipenv thinks async-timeout is not needed for python 3.11.

Steps to replicate

[[source]]
 name = "pypi"
 url = "https://pypi.python.org/simple"
 verify_ssl = true

[requires]
python_full_version = "3.11.0"
# python_version = "3.10"

[packages]
redis = "==5.0.0"
# async-timeout = "==4.0.3"  # uncomment after pipenv bugfix needed by redis for 3.11.2 and less

PIPENV_IGNORE_VIRTUALENVS=1 pipenv lock

matteius commented 1 year ago

The resolver uses the virtualenv python version, which will be what pip uses to resolve packages against.

matejsp commented 1 year ago

Any workarounds to detect such issues. I guess monkey patching of virtualenv to change the python build version would not work.

matteius commented 1 year ago

@matejsp you got me thinking about some possible workarounds to these types of issues, and I have opened a draft PR of something I have been playing with: https://github.com/pypa/pipenv/pull/5931

This does patch the vendored packaging library, and reserves the named category "resolver" so that additional directives can be passed to the pip resolver. For example:

[resolver]
python_full_version = "3.7.13"  # Markers evaluate to True that require any python_full_version markers in this range (in theory)
python_version = "3.7"   # Markers evaluate to True that require any python_version markers in this range (in theory)
finder_python = "3.7"  # The base python version to resolve against (used in the package finder)
os_name="win32"  # What operating system markers should evaluate to true (in theory)
matteius commented 1 year ago

@matejsp I couldn't get the version ranges to work reasonable well with a first pass because it required me to change how the markers evaluate, and I learned its quite hard to evaluate python version markers against a range of python versions, so for a first pass, I've updated my above example to show overriding just the resolver's environment data using my linked branch.