Skip to content

Commit 22d70ce

Browse files
committed
gh-149671: Restore compatibility with setuptools nspkg.pth files in site module
Inject "sitedir" variable in the frame which executes pth code.
1 parent 2d33810 commit 22d70ce

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

Lib/site.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ class StartupState:
254254
'_path_entries',
255255
'_importexecs',
256256
'_entrypoints',
257+
'_sitedir',
257258
)
258259

259260
def __init__(self, known_paths=None):
@@ -286,6 +287,7 @@ def __init__(self, known_paths=None):
286287
# when an entry fails.
287288
self._importexecs = {}
288289
self._entrypoints = {}
290+
self._sitedir = None
289291

290292
def addsitedir(self, sitedir):
291293
"""Add a site directory and accumulate its .pth and .start startup data.
@@ -397,6 +399,8 @@ def _read_pth_file(self, sitedir, name):
397399
accepted paths are added to it so that subsequent .pth files in
398400
the same batch don't add them more than once.
399401
"""
402+
self._sitedir = sitedir
403+
400404
lines, filename = _read_pthstart_file(sitedir, name, ".pth")
401405
if lines is None:
402406
return
@@ -500,6 +504,11 @@ def _extend_syspath(self):
500504
)
501505

502506
def _exec_imports(self):
507+
# Inject 'sitedir' local variable in the current frame for
508+
# compatibility with Python 3.14. Especially, "-nspkg.pth" files
509+
# generated by setuptools use: sys._getframe(1).f_locals['sitedir'].
510+
sitedir = self._sitedir
511+
503512
# For each `import` line we've seen in a .pth file, exec() it in
504513
# order, unless the .pth has a matching .start file in this same
505514
# batch. In that case, PEP 829 says the import lines are

Lib/test/test_site.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,22 @@ def test_addsitedir_hidden_file_attribute(self):
233233
self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
234234
self.assertIn(pth_file.base_dir, sys.path)
235235

236+
def test_sitedir_variable(self):
237+
# gh-149671: Provide 'sitedir' local variable for compatibility with
238+
# Python 3.14
239+
custom_path = '/my/custom/path'
240+
code = '; '.join((
241+
"import sys",
242+
# Code used by "-nspkg.pth" files generated by setuptools
243+
"sitedir = sys._getframe(1).f_locals['sitedir']",
244+
"print(sitedir)",
245+
))
246+
pth_dir, pth_fn = self.make_pth(code)
247+
with support.captured_stdout() as stdout:
248+
known_paths = site.addpackage(pth_dir, pth_fn, set())
249+
sitedir = stdout.getvalue().rstrip()
250+
self.assertEqual(sitedir, pth_dir)
251+
236252
# This tests _getuserbase, hence the double underline
237253
# to distinguish from a test for getuserbase
238254
def test__getuserbase(self):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Restore compatibility with setuptools ``nspkg.pth`` files in the :mod:`site`
2+
module. Inject ``sitedir`` variable in the frame which executes pth code.
3+
Patch by Victor Stinner.

0 commit comments

Comments
 (0)