Skip to content

coverage.files._possible_pth_dirs algorithm isn't quite right #2006

@glyph

Description

@glyph

Describe the bug

When writing a .pth file, coverage uses slightly invalid heuristics which will usually be correct, but become invalid in the face of things like PYTHONPATH entries or working directories (in scenarios where coverage is run with -m or in another configuration which adds the current directory to the path) with .pth files in them.

To Reproduce
How can we reproduce the problem? Please be specific. Don't link to a failing CI job. Answer the questions below:

  1. What version of Python are you using?: 3.13.5
  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful.: 7.10.0
  3. What versions of what packages do you have installed? The output of pip freeze is helpful.: N/A
  4. What code shows the problem? Give us a specific commit of a specific repo that we can check out. If you've already worked around the problem, please provide a commit before that fix.: N/A
  5. What commands should we run to reproduce the problem? Be specific. Include everything, even git clone, pip install, and so on. Explain like we're five!
$ touch sample.pth
$ python -c 'from coverage.files import create_pth_file; create_pth_file()'
$ ls *.pth
sample.pth   subcover.pth

Expected behavior

$ ls *.pth
sample.pth

The .pth file will not be processed in this location.

Additional context
Python has specific rules for which directories will and will not honor .pth files, that are subtly distinct from the rules around which directories can import Python code. Specifically, Python will evaluate .pth files in site directories, which are enumerated by some squirrelly environment-dependent logic in site.main.

This list of processed site directories is (as far as I know) never even actually stored anywhere; but, even if it were, subtle subprocess configuration changes (for example, a parent process with user-site enabled spawning a subprocess with user-site disabled) could potentially make this configuration wrong.

There are other potential consequences in unusual configurations, such as coverage reporting in a --system-site-packages virtualenv attempting to write its .pth file into the system location. This would work for the individual test run in question, but could cause confusion if the system environment doesn't have coverage installed. The system packages location (not site-packages!) could also get picked up if something else were to write a .pth file there.

I believe the most correct API to avoid these issues is to take the first writable value in site.getsitepackages(). Most of the time this would be the same value as the existing fallback sysconfig.get_path("purelib") query; I think that using this value blindly would actually be better than attempting this heuristic, since it would be easier for users with weird setups to investigate where & when it failed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions