pypa / pipenv

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

The Python version from Pipfile and Pipfile.lock is ignored when a venv is already present #6096

Open GeorchW opened 6 months ago

GeorchW commented 6 months ago

I think this is rather straightforward, but I couldn't find an existing bug like this.

Description

Pipenv ignores the Python version once the virtualenv is installed.

I think it would be nice to show a warning or similar when the Python versions diverge.

Context

When collaborating with multiple people, this can lead to unexpected bugs, since one person might have upgraded the Python version in the pipfile without the others noticing. Their local development environments will happily continue to use the old Python version.

We did, in fact, just have this problem that we could not reproduce a production bug since our local installations ran on a different version of Python and we were accidentally relying on unintended edge-case behavior in the standard library that had subsequently been fixed. We did not believe the bug report at first, since we could not replicate it.

Steps to reproduce

Make sure that you have two versions of Python installed, in this example 3.11 and 3.12.

  1. Create a simple Pipfile with the following content (in a fresh folder):

    [requires]
    python_version = "3.11"
  2. Run pipenv install.

  3. Change the Pipenv file to require a new Python version:

    [requires]
    python_version = "3.12"
  4. Run pipenv install again.

Expected behavior: Pipenv would complain in some way or another that the Python version has changed. The version in the venv has have diverged from the one in the Pipfile.

Actual behavior:

$ pipenv install
Pipfile.lock (51d3e4) out of date, updating to (2110f5)...
Locking [packages] dependencies...
Locking [dev-packages] dependencies...
Updated Pipfile.lock (702ad05de9bc9de99a4807c8dde1686f31e0041d7b5f6f6b74861195a52110f5)!
Installing dependencies from Pipfile.lock (2110f5)...
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

There is no indication that we're on a different Python version right now, but it is:

$ pipenv run python --version
Python 3.11.7
Full Bash script to reproduce ```bash mkdir pipenv-bug-demo cd pipenv-bug-demo cat > Pipfile < Pipfile <

The other pipenv commands, e.g. clean, verify or sync also provide no indication that anything is wrong. pipenv sync even says All dependencies are now up-to-date!, which is just not true -- Python itself, as a dependency, is not up to date.

Edit: Oh, and you can delete the Pipfile.lock as well or change the version inside it, none of it will change anything about this.

Alternatives

Pipenv could also force-recreate the venvs with the correct version, but I think this would be too agressive, at least as a default.

$ pipenv --support Pipenv version: `'2023.10.3'` Pipenv location: `'~/.local/lib/python3.11/site-packages/pipenv'` Python location: `'/usr/bin/python3.11'` OS Name: `'posix'` User pip version: `'23.2.1'` user Python installations found: PEP 508 Information: ``` {'implementation_name': 'cpython', 'implementation_version': '3.11.7', 'os_name': 'posix', 'platform_machine': 'x86_64', 'platform_python_implementation': 'CPython', 'platform_release': '6.5.0-17-generic', 'platform_system': 'Linux', 'platform_version': '#17~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 16 ' '14:32:32 UTC 2', 'python_full_version': '3.11.7', 'python_version': '3.11', 'sys_platform': 'linux'} ```
GeorchW commented 6 months ago

The pyvenv.cfg file inside the venv folder contains the Python version already, so Pipenv would just need to check against it.

matteius commented 5 months ago

I am not sure on this one as I would also expect you could use a vitualenv of your choosing outside of what is defined in the Pipfile -- say you want to test upgrading Python versions, its more flexible to be able to create and work with a virtualelnv of your choosing without having to rigidly define or change the Python version yet in the Pipile, but on the other hand I think you bring up a fair point.