Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding pytest-cov dependency to project breaks Pants commands #21851

Open
ruslan-roboto opened this issue Jan 17, 2025 · 17 comments · May be fixed by #21895
Open

Adding pytest-cov dependency to project breaks Pants commands #21851

ruslan-roboto opened this issue Jan 17, 2025 · 17 comments · May be fixed by #21895
Labels
backend: Python Python backend-related issues bug

Comments

@ruslan-roboto
Copy link

Describe the bug
We recently added pytest-cov to our repo to measure test coverage. For some engineers on the team working specifically on Mac laptops, this causes a 100%-repro failure when running any Pants command, e.g. pants fmt :::

10:09:05.55 [INFO] Completed: Building black.pex
10:09:05.56 [ERROR] 1 Exception encountered:

Engine traceback:
  in `fmt` goal

ProcessExecutionFailure: Process 'Building black.pex' failed with exit code 1.
stdout:

stderr:
Invalid version: '3.10.16+'

Use `--keep-sandboxes=on_failure` to preserve the process chroot for inspection.

Other issues on the Internet indicate that 3.10.16+ is an untagged CPython version string, but rerunning the command with --print-stacktrace -ldebug didn't indicate to me where this version gets picked up from. Our project uses pyenv, and .python_version is set to 3.10. python --version returns 3.10.15 for me.

I've tried:

  • running with --no-pantsd and --no-local-cache - no effect
  • playing around with the versions of pytest and pytest-cov - no effect, but whenever I regenerate our lockfile, the pytest-cov dependency is shown in red in the update summary, and I don't know what that means
  • moving pytest and pytest-cov to their own resolve as per some suggestions on the Pants website - no effect

Pants version
From our pants.toml:

[GLOBAL]
pants_version = "2.21.0"

The issue repros if I change this to 2.22 or 2.23, haven't tried 2.24.

OS
This repros on MacOS, but not on Linux. Also anecdotally not on all MacOS laptops within the team. I'm on MacOS Sonoma 14.7

Additional info
Add any other information about the problem here, such as attachments or links to gists, if relevant.

Output of python -VV run from the root of our repo:

Python 3.10.15 (main, Jan 16 2025, 13:14:27) [Clang 16.0.0 (clang-1600.0.26.3)]

@cburroughs
Copy link
Contributor

If you preserve the sandbox (ex with --keep-sandboxes=on_failure) and poke around, are you able to see what (pip? black? pex? pants?) is emitting the stderr message?

@ruslan-roboto
Copy link
Author

@cburroughs where in the sandbox would I find that? The sandbox contents look like:

total 8064
drwxr-xr-x    9 ruslan  staff      288 Jan 17 12:25 .
drwx------@ 423 ruslan  staff    13536 Jan 17 12:25 ..
drwxr-xr-x    3 ruslan  staff       96 Jan 17 12:25 .cache
lrwxr-xr-x    1 ruslan  staff       63 Jan 17 12:25 .python-build-standalone -> /Users/ruslan/.cache/pants/named_caches/python_build_standalone
drwxr-xr-x    2 ruslan  staff       64 Jan 17 12:25 .tmp
-rwxr-xr-x    1 ruslan  staff     2117 Jan 17 12:25 __run.sh
drwxr-xr-x    3 ruslan  staff       96 Jan 17 12:25 build-support
-r-xr-xr-x    1 ruslan  staff  4124530 Jan 17 12:24 pex
drwxr-xr-x    2 ruslan  staff       64 Jan 17 12:25 source_files

source_files is empty, .tmp is empty, build-support has a lockfile - do I look in .cache?

@ruslan-roboto
Copy link
Author

I'm attaching the stack trace and debug log when running pants fmt ::.

pants-debug-and-stacktrace.txt

@ruslan-roboto
Copy link
Author

Not sure if it's relevant, but running pants export --py-resolve-format=symlinked_immutable_virtualenv --resolve=python-default picks a more recent patch version of Python 3.10 than what I have installed with pyenv:

Wrote symlink to immutable virtualenv for python-default (using Python 3.10.16) to dist/export/python/virtualenvs/python-default/3.10.16

I have 3.10.15, which as previously mentioned is also what python -VV reports.

@cburroughs
Copy link
Contributor

Within the sandbox __run.sh should mimic exactly what pants would have done. It's a bash script so you can make change to it or otherwise debug.

The pants export oddity is -- I think -- #21716

@jsirois
Copy link
Contributor

jsirois commented Jan 19, 2025

@ruslan-roboto, in your debug output:

12:32:26.31 [DEBUG] Completed: Find Python interpreter for constraints - CPython==3.10.* - Selected /Users/ruslan/.pyenv/versions/3.10-dev/bin/python3.10 to run PEXes with.

Clearly suspicious.

Sure enough, I find on my machine:

:; pyenv install --list | grep 3.10-dev
  3.10-dev
  cinder-3.10-dev

:; pyenv install 3.10-dev
Cloning https://github.com/python/cpython...
Installing Python-3.10-dev...
Installed Python-3.10-dev to /home/jsirois/.pyenv/versions/3.10-dev

# ~/dev/pex-tool/pex on  sh-boot/more:main [$?⇡] via  v3.13.1 took 1m28s 
:; /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 -V
Python 3.10.16+

Other issues on the Internet indicate that 3.10.16+ is an untagged CPython version string

Yes.

So "Adding pytest-cov dependency to project..." seems to have ~nothing to do with this. It may have caused some sort of shuffle that exposed the 3.10.16+ Python interpreter version issue, but that's surely the actual issue here.

Now, checking Pex (I maintain Pex so this issue caught my eye as a potential bug in Pex code):

:; pex -V
2.29.0

:; pex --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 cowsay -ccowsay -- -t Moo!
  ____
| Moo! |
  ====
    \
     \
       ^__^
       (oo)\_______
       (__)\       )\/\
           ||----w |
           ||     ||

:; pex3 interpreter inspect --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 -v --indent 2
{
  "path": "/home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10",
  "version": "3.10.16",
  "requirement": "CPython==3.10.16",
  "sys_path": [
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python310.zip",
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python3.10",
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python3.10/lib-dynload",
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python3.10/site-packages"
  ],
  "platform": "manylinux_2_40_x86_64-cp-3.10.16-cp310",
  "venv": false
}

So current Pex handles this fine.
It looks like your Pants version uses Pex 2.3.1:

class PexCli(TemplatedExternalTool):
options_scope = "pex-cli"
name = "pex"
help = "The PEX (Python EXecutable) tool (https://github.com/pex-tool/pex)."
default_version = "v2.3.1"

So, trying that:

:; rm -rf ~/.cache/pex/ ~/.pex

:; pex pex==2.3.1 -cpex -- --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 cowsay -ccowsay -- -t Moo
  ___
| Moo |
  ===
   \
    \
      ^__^
      (oo)\_______
      (__)\       )\/\
          ||----w |
          ||     ||

:; pex pex==2.3.1 -cpex3 -- interpreter inspect --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 -v --indent 2
{
  "path": "/home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10",
  "version": "3.10.16",
  "requirement": "CPython==3.10.16",
  "sys_path": [
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python310.zip",
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python3.10",
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python3.10/lib-dynload",
    "/home/jsirois/.pyenv/versions/3.10-dev/lib/python3.10/site-packages"
  ],
  "platform": "manylinux_2_40_x86_64-cp-3.10.16-cp310",
  "venv": false
}

So, as far as I can tell, this would seem to rule out Pex handling 3.10.16+ badly here.
To nail this down, here's the supposedly failing command line as best as I can reproduce:

:; pex pex==2.3.1 -cpex -- black==23.3.0 -cblack --python-path /home/jsirois/.pyenv/versions/3.10-dev/bin --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 -o black.pex --venv prepend --seed verbose --venv-site-packages-copies --layout packed --no-pre-install-wheels
{"pex_root": "/home/jsirois/.pex", "python": "/home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10", "pex": "/home/jsirois/.pex/venvs/ec68ab02f17cbb2f5defa8480ccf28241ea417fb/8902948047df79eb01bd149fc48673ac6cb58184/pex"}

What I'm missing here from your setup is --lock build-support/lockfiles/python-default.lock, which is apparently the lock that holds the black subset being used. If you can provide that, or just try the command line yourself - as @cburroughs pointed out, easiest using the sandbox run script.

@huonw huonw added the backend: Python Python backend-related issues label Jan 19, 2025
@ruslan-roboto
Copy link
Author

@jsirois Here's the contents of __run.sh:

#!/usr/bin/env bash
# This command line should execute the same process as pants did internally.
cd /private/var/folders/7c/3ny04jh95k9fmjxtksxqyh2m0000gn/T/pants-sandbox-cRuNR7
env -i CPPFLAGS= LANG=en_US.UTF-8 LDFLAGS= PATH=$'/opt/homebrew/opt/make/libexec/gnubin:/Users/ruslan/.pyenv/shims:/Users/ruslan/.nvm/versions/node/v22.9.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/ruslan/.local/bin' PEX_IGNORE_RCFILES=true PEX_PYTHON=/Users/ruslan/Library/Caches/nce/42dd077dd7c2238e60a71f8ccd2c52fce17bd09daa7b30d19c26707cc4443668/bindings/venvs/2.21.0/bin/python3.9 PEX_ROOT=.cache/pex_root /Users/ruslan/Library/Caches/nce/42dd077dd7c2238e60a71f8ccd2c52fce17bd09daa7b30d19c26707cc4443668/bindings/venvs/2.21.0/bin/python3.9 ./pex --tmpdir .tmp --jobs 8 --no-emit-warnings --pip-version 24.0 --python-path $'/Users/ruslan/.pyenv/versions/3.10-dev/bin:/Users/ruslan/.pyenv/versions/3.10.15/bin:/Users/ruslan/.pyenv/versions/3.10.9/bin:/Users/ruslan/.pyenv/versions/3.12.6/bin:/opt/homebrew/opt/make/libexec/gnubin:/Users/ruslan/.pyenv/shims:/Users/ruslan/.nvm/versions/node/v22.9.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/ruslan/.local/bin' --output-file black.pex --venv prepend --seed verbose --venv-site-packages-copies --python /Users/ruslan/.pyenv/versions/3.10-dev/bin/python3.10 --console-script black --no-pre-install-wheels $'--sources-directory=source_files' --lock build-support/lockfiles/python-default.lock --no-pypi $'--index=https://pypi.org/simple/' --manylinux manylinux2014 --layout packed

As for the lockfile, here's the section about black:

        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d",
              "url": "https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f",
              "url": "https://files.pythonhosted.org/packages/6e/c5/9023b7673904a5188f9be81f5e129fff69f51f5515655fbd1d5a4e80a47b/black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812",
              "url": "https://files.pythonhosted.org/packages/a3/f3/465c0eb5cddf7dbbfe1fecd9b875d1dcf51b88923cd2c1d7e9ab95c6336b/black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875",
              "url": "https://files.pythonhosted.org/packages/d8/0d/cc2fb42b8c50d80143221515dd7e4766995bd07c56c9a3ed30baf080b6dc/black-24.10.0.tar.gz"
            },
            {
              "algorithm": "sha256",
              "hash": "1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea",
              "url": "https://files.pythonhosted.org/packages/df/57/b6d2da7d200773fdfcc224ffb87052cf283cec4d7102fab450b4a05996d8/black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl"
            }
          ],
          "project_name": "black",
          "requires_dists": [
            "aiohttp>=3.10; extra == \"d\"",
            "click>=8.0.0",
            "colorama>=0.4.3; extra == \"colorama\"",
            "ipython>=7.8.0; extra == \"jupyter\"",
            "mypy-extensions>=0.4.3",
            "packaging>=22.0",
            "pathspec>=0.9.0",
            "platformdirs>=2",
            "tokenize-rt>=3.2.0; extra == \"jupyter\"",
            "tomli>=1.1.0; python_version < \"3.11\"",
            "typing-extensions>=4.0.1; python_version < \"3.11\"",
            "uvloop>=0.15.2; extra == \"uvloop\""
          ],
          "requires_python": ">=3.9",
          "version": "24.10.0"
        },

Thank you for your analysis so far! There are a couple of things I don't understand:

  1. Why the 3.10-dev interpreter is being picked, even though our .python-version specifies 3.10
  2. If pytest-cov is a red herring, why adding it as a dependency makes this issue surface, and removing it as a dependency makes the issue go away.

@ruslan-roboto
Copy link
Author

Note: I'm using pants fmt as an example here. Any pants command that wants to use PEX fails, e.g. pants check :::

12:53:22.44 [INFO] Completed: Building mypy.pex
12:53:22.44 [ERROR] 1 Exception encountered:

Engine traceback:
  in `check` goal

ProcessExecutionFailure: Process 'Building mypy.pex' failed with exit code 1.
stdout:

stderr:
Invalid version: '3.10.16+'

The script for that is:

#!/usr/bin/env bash
# This command line should execute the same process as pants did internally.
cd /private/var/folders/7c/3ny04jh95k9fmjxtksxqyh2m0000gn/T/pants-sandbox-bjpk4I
env -i CPPFLAGS= LANG=en_US.UTF-8 LDFLAGS= PATH=$'/opt/homebrew/opt/make/libexec/gnubin:/Users/ruslan/.pyenv/shims:/Users/ruslan/.nvm/versions/node/v22.9.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/ruslan/.local/bin' PEX_IGNORE_RCFILES=true PEX_PYTHON=/Users/ruslan/Library/Caches/nce/42dd077dd7c2238e60a71f8ccd2c52fce17bd09daa7b30d19c26707cc4443668/bindings/venvs/2.21.0/bin/python3.9 PEX_ROOT=.cache/pex_root /Users/ruslan/Library/Caches/nce/42dd077dd7c2238e60a71f8ccd2c52fce17bd09daa7b30d19c26707cc4443668/bindings/venvs/2.21.0/bin/python3.9 ./pex --tmpdir .tmp --jobs 4 --no-emit-warnings --pip-version 24.0 --python-path $'/Users/ruslan/.pyenv/versions/3.10-dev/bin:/Users/ruslan/.pyenv/versions/3.10.15/bin:/Users/ruslan/.pyenv/versions/3.10.9/bin:/Users/ruslan/.pyenv/versions/3.12.6/bin:/opt/homebrew/opt/make/libexec/gnubin:/Users/ruslan/.pyenv/shims:/Users/ruslan/.nvm/versions/node/v22.9.0/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/Users/ruslan/.local/bin' --output-file mypy.pex --venv prepend --seed verbose --venv-site-packages-copies --python /Users/ruslan/.pyenv/versions/3.10-dev/bin/python3.10 --console-script mypy --no-pre-install-wheels $'--sources-directory=source_files' --lock build-support/lockfiles/python-default.lock --no-pypi $'--index=https://pypi.org/simple/' --manylinux manylinux2014 --layout packed

@jsirois
Copy link
Contributor

jsirois commented Jan 22, 2025

@ruslan-roboto you must provide the whole lockfile to repro, or at least a complete subgraph. You only supplied one locked requirement entry, that of black. You included 0 of its dependencies. The complete subgraph is needed. But in that path lies madness, please just supply your lockfile instead. It's hard to imagine a lock file is proprietary.

Without a lockfile, the best I can do is like so:

# Prove I'm using the same Pex PEX (Downloaded from here: https://github.com/pex-tool/pex/releases/download/v2.3.1/pex):
:; python3.9 ~/Downloads/pex -V
2.3.1

# Run the ~same command:
:; rm -rf ~/.pex ~/.cache/pex && env -i CPPFLAGS= LANG=en_US.UTF-8 LDFLAGS= PATH=/home/jsirois/.pyenv/shims:$PATH PEX_IGNORE_RCFILES=true PEX_PYTHON=python3.9 PEX_ROOT=.cache/pex_root python3.9 ~/Downloads/pex --tmpdir .tmp --jobs 4 --no-emit-warnings --pip-version 24.0 --python-path /home/jsirois/.pyenv/versions/3.10-dev/bin:/home/jsirois/.pyenv/shims --output-file mypy.pex --venv prepend --seed verbose --venv-site-packages-copies --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 mypy --console-script mypy --no-pre-install-wheels --manylinux manylinux2014 --layout packed
{"pex_root": "/home/jsirois/dev/pex-tool/pex/.cache/pex_root", "python": "/home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10", "pex": "/home/jsirois/dev/pex-tool/pex/.cache/pex_root/venvs/1bd9a579f43403aaed22d4101d48391a6c37e0fc/8902948047df79eb01bd149fc48673ac6cb58184/pex"}

There are a couple of things I don't understand:

  1. Why the 3.10-dev interpreter is being picked, even though our .python-version specifies 3.10

What makes you think Pants respects .python-version? Are you configuring <PYENV_LOCAL> as described here?: https://www.pantsbuild.org/stable/docs/python/overview/interpreter-compatibility#changing-the-interpreter-search-path

  1. If pytest-cov is a red herring, why adding it as a dependency makes this issue surface, and > removing it as a dependency makes the issue go away.

I have absolutely no idea why ptest-cov triggers the issue. My only point is that is almost certainly a cause, but not the real cause. If you think it is the real cause, then it must be code in pytest-cov's dependency graph that raises the error. Have you done that search? I did a middling version of that search and came up empty in the pytest-cov codebase and the coverage codebase and neither depends on packaging and the error looks like it comes from the packaging.version.Version class on the surface. For example:

:; pex packaging
Pex 2.30.0 ephemeral hermetic environment with 1 requirement and 1 activated distribution.
Python 3.11.11 (main, Dec  4 2024, 07:56:52) [GCC 14.2.0] on linux
Type "help", "pex", "copyright", "credits" or "license" for more information.
>>> from packaging.version import Version
>>> Version("3.10.16+")
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/jsirois/.cache/pex/installed_wheels/0/09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759/packaging-24.2-py3-none-any.whl/packaging/version.py", line 202, in __init__
    raise InvalidVersion(f"Invalid version: {version!r}")
packaging.version.InvalidVersion: Invalid version: '3.10.16+'
>>>

Going back to the OP:

For some engineers on the team working specifically on Mac laptops, this causes a 100%-repro failure when running any Pants command

@ruslan-roboto is it also the case that for every Mac laptop with the issue it also has 3.10-dev (3.10.16+) installed in pyenv? Can you confirm uninstalling 3.10-dev fixes ones of these machines? Etc., basically run through the obvious permutations to make this process of whittling down more efficient.

@ruslan-roboto unless you can provide a real whole lockfile, I've reproed in as much detail as possible and Pex continues to be ruled out. I think you should try to pull a Pants person - perhaps @cburroughs - closer in to the problem since I'm pretty confident now its not a Pex problem and I maintain just Pex, I do not work on Pants.

@ruslan-roboto
Copy link
Author

ruslan-roboto commented Jan 23, 2025

Here's a scoped-down lockfile which contains the versions of our tools dependencies - I found that it's sufficient for a repro (file extension changed to .txt so Github allows me to upload it)

python-tools.txt

[I]s it also the case that for every Mac laptop with the issue it also has 3.10-dev (3.10.16+) installed in pyenv?

It looks like the engineer who did not face this issue on a Mac also did not have 3.10-dev installed, and the rest of us do.

@jsirois
Copy link
Contributor

jsirois commented Jan 24, 2025

@ruslan-roboto I don't repro with that lock file (after removing the @#$%! invalid-JSON header Pants puts on it):

:; rm -rf ~/.pex ~/.cache/pex && env -i CPPFLAGS= LANG=en_US.UTF-8 LDFLAGS= PATH=/home/jsirois/.pyenv/shims:$PATH PEX_IGNORE_RCFILES=true PEX_PYTHON=python3.9 PEX_ROOT=.cache/pex_root python3.9 ~/Downloads/pex --tmpdir .tmp --jobs 4 --no-emit-warnings --pip-version 24.0 --python-path /home/jsirois/.pyenv/versions/3.10-dev/bin:/home/jsirois/.pyenv/shims --output-file mypy.pex --venv prepend --seed verbose --venv-site-packages-copies --python /home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10 black --console-script black --no-pre-install-wheels --manylinux manylinux2014 --layout packed --lock ~/Downloads/python-tools.txt 
{"pex_root": "/home/jsirois/dev/pex-tool/pex/.cache/pex_root", "python": "/home/jsirois/.pyenv/versions/3.10-dev/bin/python3.10", "pex": "/home/jsirois/dev/pex-tool/pex/.cache/pex_root/venvs/dd098b2d6024ad79688c7be021ef0521bd6d468c/8902948047df79eb01bd149fc48673ac6cb58184/pex"}

I will leave you to the Pants people, but remind you to answer my question about <PYENV_LOCAL>, since, if Pants honoring .python-version were to be functioning, it would seem your problems would go away since Python 3.10.16+ would not be selected. Likewise, it appears if there is no good reason for you or other devs to have python3.10-dev installed via pyenv, your problems would also go away. Either of those two "solutions" really just side-step the underlying issue, which would be good to fully understand and solve. But, at this point, I leave that to you and others.

jsirois added a commit to jsirois/pants-issue-21851 that referenced this issue Jan 24, 2025
@jsirois
Copy link
Contributor

jsirois commented Jan 24, 2025

More attempts this am to repro. Still nothing. Here's my efforts for posterity: https://github.com/jsirois/pants-issue-21851

@ruslan-roboto
Copy link
Author

ruslan-roboto commented Jan 27, 2025

Hi @jsirois ,

I was able to repro the issue with your Github repository after making two changes:

  1. In the [black] section in pants.toml, I only kept the install_from_resolve = "python-tools" setting, removing the requirements list. That's how our project's pants.toml is set up as well.
  2. I created an explicit .python-version file with the contents 3.10 and removed the python-bootstrap section, since we don't use this in our project's pants.toml.

I suspect that the first change is the important one. EDIT: confirmed - all you need to do for a repro is remove requirements from [black].

Thanks,
Ruslan

@jsirois
Copy link
Contributor

jsirois commented Jan 28, 2025

@ruslan-roboto thanks for helping narrow down the repro - I also now repro. The underlying issue is here (Pex uses packaging 23.1 where the issue is not fixed): pypa/packaging#678

So, the pytest-cov dep does trigger this, but has nothing to do with it. The issue is that pytest-cov depends on coverage and coverage uses the python_full_version environment marker in one of its dependencies. Its using a python_full_version environment marker + using a development version of Python + using packaging pre-24.1 that is the required mix to trigger this:
https://github.com/jsirois/pants-issue-21851/blob/02cc35538e05fd100fdac6dabe3b3877581139d8/python-tools.lock#L793-L798

Minimal repro:

:; ~/.pyenv/versions/3.10-dev/bin/python -mvenv experiment.venv

:; source experiment.venv/bin/activate

:; pip install packaging==23.1

:; python
Python 3.10.16+ (heads/3.10:8773554, Jan 18 2025, 17:51:15) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from packaging.requirements import Requirement
>>> req = Requirement('tomli; python_full_version <= "3.11.0"')
>>> req.marker.evaluate()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/tmp/pants-sandbox-oVFXfr/experiment.venv/lib/python3.10/site-packages/packaging/markers.py", line 252, in evaluate
    return _evaluate_markers(self._markers, current_environment)
  File "/tmp/pants-sandbox-oVFXfr/experiment.venv/lib/python3.10/site-packages/packaging/markers.py", line 158, in _evaluate_markers
    groups[-1].append(_eval_op(lhs_value, op, rhs_value))
  File "/tmp/pants-sandbox-oVFXfr/experiment.venv/lib/python3.10/site-packages/packaging/markers.py", line 116, in _eval_op
    return spec.contains(lhs, prereleases=True)
  File "/tmp/pants-sandbox-oVFXfr/experiment.venv/lib/python3.10/site-packages/packaging/specifiers.py", line 568, in contains
    normalized_item = _coerce_version(item)
  File "/tmp/pants-sandbox-oVFXfr/experiment.venv/lib/python3.10/site-packages/packaging/specifiers.py", line 36, in _coerce_version
    version = Version(version)
  File "/tmp/pants-sandbox-oVFXfr/experiment.venv/lib/python3.10/site-packages/packaging/version.py", line 198, in __init__
    raise InvalidVersion(f"Invalid version: '{version}'")
packaging.version.InvalidVersion: Invalid version: '3.10.16+'
>>> 

:; pip install packaging==24.1

:; python
Python 3.10.16+ (heads/3.10:8773554, Jan 18 2025, 17:51:15) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from packaging.requirements import Requirement
>>> req = Requirement('tomli; python_full_version <= "3.11.0"')
>>> req.marker.evaluate()
True
>>>

I'll update more after I figure out how best to get at the fix in packaging 24.1. That said, it continues to be very frustrating that you have not answered the <PYENV_LOCAL> question or the related question about removing 3.10-dev from your pyenv installs as workarounds. Could you please comment on these? In short, this issue is triggered due to using a development version of Python. Do you actually intend / need to be using one at all?

@ruslan-roboto
Copy link
Author

Hi @jsirois ,

Thanks for pinning down the root cause!

As for PYENV_LOCAL, sorry I didn't update the thread - attempting to use it via [python-bootstrap] ends up causing this issue in my local setup:

ProcessExecutionFailure: Process 'Find interpreter for constraints: CPython==3.10.*' failed with exit code 102.
stdout:

stderr:
Could not find a compatible interpreter.

Examined the following working interpreters:
1.) /Users/ruslan/Library/Caches/nce/bf0cd90204a2cc6da48cae1e4b32f48c9f7031fbe1238c5972104ccb0155d368/cpython-3.9.18+20240107-aarch64-apple-darwin-install_only.tar.gz/python/bin/python3.9 CPython==3.9.18
2.)                                                                                        /opt/homebrew/Cellar/[email protected]/3.13.1/Frameworks/Python.framework/Versions/3.13/bin/python3.13 CPython==3.13.1
3.)                                                                                        /opt/homebrew/Cellar/[email protected]/3.12.6/Frameworks/Python.framework/Versions/3.12/bin/python3.12 CPython==3.12.6
4.)                                                                                     /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/python3.9 CPython==3.9.6

Skipped the following broken interpreters:
1.) /Users/ruslan/.pyenv/shims/python:
pyenv: python: command not found

The `python' command exists in these Python versions:
  3.10-dev
  3.10.15
  3.12.6

Note: See 'pyenv help global' for tips on allowing both
      python2 and python3 to be found.
2.) /Users/ruslan/.pyenv/shims/python3.10:
pyenv: python3.10: command not found

The `python3.10' command exists in these Python versions:
  3.10-dev
  3.10.15

Note: See 'pyenv help global' for tips on allowing both
      python2 and python3 to be found.

(See https://github.com/pex-tool/pex/issues/1027 for a list of known breaks and workarounds.)

No working interpreter compatible with the requested constraints was found:

  Version matches CPython==3.10.*

Running pyenv uninstall 3.10-dev makes the issue go away, as expected, regardless of there being a [python-bootstrap] section in pants.toml. We can use this workaround for now, since the inclusion of 3.10-dev into our standard dev setup seems to have been more forward-looking than something strictly needed at present.

Thanks,
Ruslan

@jsirois
Copy link
Contributor

jsirois commented Jan 30, 2025

@ruslan-roboto the fix is available in Pex 2.23.1: https://github.com/pex-tool/pex/releases/tag/v2.32.1

Instructions for upgrading on your own so you don't have to wait for a Pants release are here: https://www.pantsbuild.org/stable/docs/python/overview/pex#setting-pex-and-pip-versions

@ruslan-roboto
Copy link
Author

Thanks @jsirois !

cburroughs added a commit to cburroughs/pants that referenced this issue Jan 31, 2025
```
Lockfile diff: 3rdparty/python/user_reqs.lock [python-default]

==                    Upgraded dependencies                     ==

  certifi                        2024.12.14   -->   2025.1.31
```

fixes pantsbuild#21851
@cburroughs cburroughs linked a pull request Jan 31, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend: Python Python backend-related issues bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants