Skip to content

Commit d96a414

Browse files
committed
Add failing tests for gh-75723
Based on @asottle branch !asottle-gh-75723 but refactored for `main`. This will need a different backport.
1 parent 63df6bd commit d96a414

1 file changed

Lines changed: 61 additions & 39 deletions

File tree

Lib/test/test_site.py

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ def pth_file_tests(self, pth_file):
118118
"%s not in sys.modules" % pth_file.imported)
119119
self.assertIn(site.makepath(pth_file.good_dir_path)[0], sys.path)
120120
self.assertFalse(os.path.exists(pth_file.bad_dir_path))
121-
self.assertFalse(os.path.exists(pth_file.idempotent_fail_path))
122121

123122
def test_addpackage(self):
124123
# Make sure addpackage() imports if the line starts with 'import',
@@ -197,22 +196,13 @@ def test_addsitedir_explicit_flush(self):
197196
pth_file.cleanup(prep=True)
198197
with pth_file.create():
199198
# Pass defer_processing_start_files=True to prevent flushing.
200-
site.addsitedir(pth_file.base_dir, set(),
201-
defer_processing_start_files=True)
199+
site.addsitedir(
200+
pth_file.base_dir, set(),
201+
defer_processing_start_files=True)
202202
self.assertNotIn(pth_file.imported, sys.modules)
203203
site.process_startup_files()
204204
self.pth_file_tests(pth_file)
205205

206-
def test_addsitedir_idempotent(self):
207-
pth_file = PthFile()
208-
pth_file.cleanup(prep=True)
209-
210-
with pth_file.create():
211-
dirs = set()
212-
dirs = site.addsitedir(pth_file.base_dir, dirs)
213-
dirs = site.addsitedir(pth_file.base_dir, dirs)
214-
self.pth_file_tests(pth_file)
215-
216206
def test_addsitedir_dotfile(self):
217207
pth_file = PthFile('.dotfile')
218208
# Ensure we have a clean slate.
@@ -422,7 +412,6 @@ def __init__(self, filename_base=TESTFN, imported="time",
422412
self.bad_dirname = bad_dirname
423413
self.good_dir_path = os.path.join(self.base_dir, self.good_dirname)
424414
self.bad_dir_path = os.path.join(self.base_dir, self.bad_dirname)
425-
self.idempotent_fail_path = os.path.join(self.base_dir, 'idempotent')
426415

427416
@contextlib.contextmanager
428417
def create(self):
@@ -435,22 +424,14 @@ def create(self):
435424
436425
Used as a context manager: self.cleanup() is called on exit.
437426
"""
438-
FILE = open(self.file_path, 'w')
439-
try:
440-
print("#import @bad module name", file=FILE)
441-
print("\n", file=FILE)
442-
443-
PROG = f'''\
444-
if {self.imported!r} in sys.modules:
445-
open({self.idempotent_fail_path!r}, 'a+').close()
446-
'''
447-
print(f"import sys; exec({PROG!r})", file=FILE)
448-
449-
print("import %s" % self.imported, file=FILE)
450-
print(self.good_dirname, file=FILE)
451-
print(self.bad_dirname, file=FILE)
452-
finally:
453-
FILE.close()
427+
with open(self.file_path, 'w') as fp:
428+
print(f"""\
429+
#import @bad module name
430+
import {self.imported}
431+
{self.good_dirname}
432+
{self.bad_dirname}
433+
""", file=fp)
434+
454435
os.mkdir(self.good_dir_path)
455436
try:
456437
yield self
@@ -474,8 +455,6 @@ def cleanup(self, prep=False):
474455
os.rmdir(self.good_dir_path)
475456
if os.path.exists(self.bad_dir_path):
476457
os.rmdir(self.bad_dir_path)
477-
if os.path.exists(self.idempotent_fail_path):
478-
os.remove(self.idempotent_fail_path)
479458

480459
class ImportSideEffectTests(unittest.TestCase):
481460
"""Test side-effects from importing 'site'."""
@@ -965,6 +944,16 @@ def _make_pth(self, content, name='testpkg'):
965944
f.write(content)
966945
return basename
967946

947+
def _make_mod(self, contents, name='mod'):
948+
"""Write an importable <mod>.py, returning the module directory."""
949+
extdir = os.path.join(self.sitedir, 'extdir')
950+
os.mkdir(extdir)
951+
modpath = os.path.join(extdir, f'{name}.py')
952+
with open(modpath, 'w') as fp:
953+
fp.write(contents)
954+
self.addCleanup(sys.modules.pop, name, None)
955+
return extdir
956+
968957
def _all_entrypoints(self):
969958
"""Flatten _pending_entrypoints dict into a list of (filename, entry) tuples."""
970959
result = []
@@ -1441,18 +1430,12 @@ def test_pth_path_is_available_to_start_entrypoint(self):
14411430
# point may live in a module reachable only via a .pth-extended
14421431
# path. If the flush phases were inverted, resolving the entry
14431432
# point would fail with ModuleNotFoundError.
1444-
extdir = os.path.join(self.sitedir, 'extdir')
1445-
os.mkdir(extdir)
1446-
modpath = os.path.join(extdir, 'mod.py')
1447-
with open(modpath, 'w') as f:
1448-
f.write("""\
1433+
extdir = self._make_mod("""\
14491434
called = False
14501435
def hook():
14511436
global called
14521437
called = True
14531438
""")
1454-
self.addCleanup(sys.modules.pop, 'mod', None)
1455-
14561439
# extdir is not on sys.path; only the .pth file makes it so.
14571440
self.assertNotIn(extdir, sys.path)
14581441
self._make_pth("extdir\n", name='extlib')
@@ -1468,6 +1451,45 @@ def hook():
14681451
"entry point did not run; .pth path was likely not applied "
14691452
"before .start entry-point execution")
14701453

1454+
# --- bugs ---
1455+
1456+
# gh-75723
1457+
def test_addsitdir_idempotent_pth(self):
1458+
# Adding the same sitedir twice with a known_paths, should not
1459+
# process .pth files twice.
1460+
extdir = self._make_mod("""\
1461+
_pth_count = 0
1462+
""")
1463+
self._make_pth(f"""\
1464+
{extdir}
1465+
import mod; mod._pth_count += 1
1466+
""")
1467+
dirs = set()
1468+
dirs = site.addsitedir(self.sitedir, dirs)
1469+
dirs = site.addsitedir(self.sitedir, dirs)
1470+
import mod
1471+
self.assertEqual(mod._pth_count, 1)
1472+
1473+
def test_addsitdir_idempotent_start(self):
1474+
# Adding the same sitedir twice with a known_paths, should not
1475+
# process .pth files twice.
1476+
extdir = self._make_mod("""\
1477+
_pth_count = 0
1478+
def increment():
1479+
global _pth_count
1480+
_pth_count += 1
1481+
""")
1482+
self._make_pth(f"""\
1483+
{extdir}
1484+
""")
1485+
self._make_start("""\
1486+
mod:increment
1487+
""")
1488+
dirs = set()
1489+
dirs = site.addsitedir(self.sitedir, dirs)
1490+
dirs = site.addsitedir(self.sitedir, dirs)
1491+
import mod
1492+
self.assertEqual(mod._pth_count, 1)
14711493

14721494
if __name__ == "__main__":
14731495
unittest.main()

0 commit comments

Comments
 (0)