Skip to content

Commit 3d5588d

Browse files
authored
Merge pull request #3386 from pypa/bugfix/3383-cpython-sensitive-tests
Create additional workarounds for failing tests in CPython
2 parents 9ae9334 + b86a122 commit 3d5588d

File tree

2 files changed

+42
-6
lines changed

2 files changed

+42
-6
lines changed

_distutils_hack/__init__.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,26 @@ def warn_distutils_present():
1414
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
1515
return
1616
import warnings
17+
1718
warnings.warn(
1819
"Distutils was imported before Setuptools, but importing Setuptools "
1920
"also replaces the `distutils` module in `sys.modules`. This may lead "
2021
"to undesirable behaviors or errors. To avoid these issues, avoid "
2122
"using distutils directly, ensure that setuptools is installed in the "
2223
"traditional way (e.g. not an editable install), and/or make sure "
23-
"that setuptools is always imported before distutils.")
24+
"that setuptools is always imported before distutils."
25+
)
2426

2527

2628
def clear_distutils():
2729
if 'distutils' not in sys.modules:
2830
return
2931
import warnings
32+
3033
warnings.warn("Setuptools is replacing distutils.")
3134
mods = [
32-
name for name in sys.modules
35+
name
36+
for name in sys.modules
3337
if name == "distutils" or name.startswith("distutils.")
3438
]
3539
for name in mods:
@@ -46,6 +50,7 @@ def enabled():
4650

4751
def ensure_local_distutils():
4852
import importlib
53+
4954
clear_distutils()
5055

5156
# With the DistutilsMetaFinder in place,
@@ -82,7 +87,9 @@ def match(self, string):
8287

8388
class DistutilsMetaFinder:
8489
def find_spec(self, fullname, path, target=None):
85-
if path is not None:
90+
# optimization: only consider top level modules and those
91+
# found in the CPython test suite.
92+
if path is not None and not fullname.startswith('test.'):
8693
return
8794

8895
method_name = 'spec_for_{fullname}'.format(**locals())
@@ -111,7 +118,6 @@ def spec_for_distutils(self):
111118
return
112119

113120
class DistutilsLoader(importlib.abc.Loader):
114-
115121
def create_module(self, spec):
116122
mod.__name__ = 'distutils'
117123
return mod
@@ -147,9 +153,9 @@ def pip_imported_during_build(cls):
147153
Detect if pip is being imported in a build script. Ref #2355.
148154
"""
149155
import traceback
156+
150157
return any(
151-
cls.frame_file_is_setup(frame)
152-
for frame, line in traceback.walk_stack(None)
158+
cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None)
153159
)
154160

155161
@staticmethod
@@ -160,6 +166,35 @@ def frame_file_is_setup(frame):
160166
# some frames may not have __file__ (#2940)
161167
return frame.f_globals.get('__file__', '').endswith('setup.py')
162168

169+
def spec_for_sensitive_tests(self):
170+
"""
171+
Ensure stdlib distutils when running select tests under CPython.
172+
173+
python/cpython#91169
174+
"""
175+
clear_distutils()
176+
self.spec_for_distutils = lambda: None
177+
178+
sensitive_tests = (
179+
[
180+
'test.test_distutils',
181+
'test.test_peg_generator',
182+
'test.test_importlib',
183+
]
184+
if sys.version_info < (3, 10)
185+
else [
186+
'test.test_distutils',
187+
]
188+
)
189+
190+
191+
for name in DistutilsMetaFinder.sensitive_tests:
192+
setattr(
193+
DistutilsMetaFinder,
194+
f'spec_for_{name}',
195+
DistutilsMetaFinder.spec_for_sensitive_tests,
196+
)
197+
163198

164199
DISTUTILS_FINDER = DistutilsMetaFinder()
165200

changelog.d/3383.change.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
In _distutils_hack, suppress/undo the use of local distutils when select tests are imported in CPython.

0 commit comments

Comments
 (0)