Skip to content

fix: tolerate None __file__ in _distutils_hack frame detector - #5316

Open
wahajahmed010 wants to merge 1 commit into
pypa:mainfrom
wahajahmed010:fix/5263-distutils-hack-none-file
Open

fix: tolerate None __file__ in _distutils_hack frame detector#5316
wahajahmed010 wants to merge 1 commit into
pypa:mainfrom
wahajahmed010:fix/5263-distutils-hack-none-file

Conversation

@wahajahmed010

Copy link
Copy Markdown

Summary

_distutils_hack.DistutilsMetaFinder.frame_file_is_setup can crash during pip startup on Python 3.14+ when a frame's f_globals carries a __file__ set to None. The previous implementation used frame.f_globals.get('__file__', '').endswith('setup.py'), which only handles the missing-key case; when the key is present and the value is None, the .endswith call raises AttributeError: 'NoneType' object has no attribute 'endswith'. This is the same root cause behind the report in #5263: with a legacy setuptools installed, pip itself becomes unusable because the shim can't be imported.

The fix treats None and other non-string values the same as a missing __file__ (i.e. "not a setup.py frame"). The frame walker in pip_imported_during_build therefore completes without raising, and the rest of _distutils_hack continues to work as before.

How to reproduce (without my fix)

class Frame:
    @property
    def f_globals(self):
        return {"__file__": None}

# On current main:
from _distutils_hack import DistutilsMetaFinder
DistutilsMetaFinder.frame_file_is_setup(Frame())
# AttributeError: 'NoneType' object has no attribute 'endswith'

With this branch loaded instead, the same call returns False cleanly.

Pull Request Checklist

  • Changes have tests (added test_frame_file_is_setup_handles_missing_file in setuptools/tests/test_distutils_adoption.py, covering missing key, None, a real setup.py path, and a non-matching path)
  • News fragment added in newsfragments/5263.bugfix.rst

Closes #5263

On Python 3.14+, a frame's f_globals can carry a None __file__ (for
example, during pip startup, where the pip shim is loaded via a
__script__.py with __file__ set to None). The previous code used
frame.f_globals.get('__file__', '').endswith('setup.py'), which
crashes with AttributeError: 'NoneType' object has no attribute
'endswith' when __file__ is present but None. Treat None and other
non-string values the same as missing. pypa#5263
@mergify

mergify Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@abravalheri

Copy link
Copy Markdown
Contributor

Hi @wahajahmed010 thank you very much for the contribution.

Would you be able to provide a real world reproducer that does not rely on a mock/stub for us to assess this issue?

You mentioned changes on Python 3.14+... Do you have a reference for that? I checked the release notes and I couldn't find any specific changes in __file__ that allow it to be None, the docs still say it has to be a string when present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Running pip 26.1.2 failed after installing legacy versions of setuptools

2 participants