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

Installing namespaced wheels creates .pth files that inject invalid modules into sys.modules. #12965

Closed
1 task done
defnull opened this issue Sep 13, 2024 · 3 comments
Closed
1 task done
Labels
S: needs triage Issues/PRs that need to be triaged type: bug A confirmed bug or unintended behavior

Comments

@defnull
Copy link

defnull commented Sep 13, 2024

Description

Installing a wheel with a namespace_packages.txt trigger file (e.g. sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl) will generate an executable .pth file (e.g. .../site-packages/sphinxcontrib_jsmath-1.0.1-py3.7-nspkg.pth) that dynamically creates a namespace module and injects it into sys.modules. This module has an invalid __file__ property. If defined, this property must be a string. but it is None in this case, breaking other tools that depend on this property to be a string, if present.

Expected behavior

The __file__ attribute of all loaded modules should be either a string, or missing completely, but never None.

pip version

24.0

Python version

3.12

OS

Linux

How to Reproduce

  1. Install some package that lives inside a namespace package: pip install sphinxcontrib-jsmath
  2. Run python3 -c 'import sys; mfile = getattr(sys.modules.get("sphinxcontrib"), "__file__", "UNSET"); print(f"sphinxcontrib.__file__ = {mfile!r}")'

Output

This prints sphinxcontrib.__file__ = None. Note that sphinxcontrib does not need to be imported, it is injected during runtime initialization by a .pth file.

Code of Conduct

@defnull defnull added S: needs triage Issues/PRs that need to be triaged type: bug A confirmed bug or unintended behavior labels Sep 13, 2024
@defnull
Copy link
Author

defnull commented Sep 13, 2024

The sphinxcontrib_jsmath-1.0.1-py3.7-nspkg.pth file looks like this (line-breaks added by me):

import sys, types, os;
has_mfs = sys.version_info > (3, 5);
p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('sphinxcontrib',));
importlib = has_mfs and __import__('importlib.util');
has_mfs and __import__('importlib.machinery');
m = has_mfs and sys.modules.setdefault('sphinxcontrib',
    importlib.util.module_from_spec(
        importlib.machinery.PathFinder.find_spec('sphinxcontrib', [os.path.dirname(p)])
    )
);
m = m or sys.modules.setdefault('sphinxcontrib', types.ModuleType('sphinxcontrib'));
mp = (m or []) and m.__dict__.setdefault('__path__',[]);
(p not in mp) and mp.append(p);

@pfmoore
Copy link
Member

pfmoore commented Sep 13, 2024

The .pth file is created by setuptools, not by pip. You should raise this on the setuptools tracker.

@defnull
Copy link
Author

defnull commented Sep 14, 2024

I dug into it and yes, the .pth file in question is already part of the .whl and was created by a 6+ years old version of setuptools using a hack for namespace packages that is no longer necessary since Python 3.3 (PEP-420). I incorrectly assumed that the .pth file was generated at install-time. Looks like I just have to accept that old packages may be broken in this way and have to account for that.

Thanks for the hint, I'll close this now.

@defnull defnull closed this as completed Sep 14, 2024
@pradyunsg pradyunsg changed the title Installing namespaced wheels creates .pht files that inject invalid modules into sys.modules. Installing namespaced wheels creates .pth files that inject invalid modules into sys.modules. Sep 15, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
S: needs triage Issues/PRs that need to be triaged type: bug A confirmed bug or unintended behavior
Projects
None yet
Development

No branches or pull requests

2 participants