@@ -97,7 +97,6 @@ def require_frozen(module, *, skip=True):
97
97
def require_pure_python (module , * , skip = False ):
98
98
_require_loader (module , SourceFileLoader , skip )
99
99
100
-
101
100
def remove_files (name ):
102
101
for f in (name + ".py" ,
103
102
name + ".pyc" ,
@@ -128,19 +127,34 @@ def _ready_to_import(name=None, source=""):
128
127
del sys .modules [name ]
129
128
130
129
131
- def requires_subinterpreters (meth ):
132
- """Decorator to skip a test if subinterpreters are not supported."""
133
- return unittest .skipIf (_interpreters is None ,
134
- 'subinterpreters required' )(meth )
130
+ if _testsinglephase is not None :
131
+ def restore__testsinglephase (* , _orig = _testsinglephase ):
132
+ # We started with the module imported and want to restore
133
+ # it to its nominal state.
134
+ _orig ._clear_globals ()
135
+ _testinternalcapi .clear_extension ('_testsinglephase' , _orig .__file__ )
136
+ import _testsinglephase
135
137
136
138
137
139
def requires_singlephase_init (meth ):
138
140
"""Decorator to skip if single-phase init modules are not supported."""
141
+ if not isinstance (meth , type ):
142
+ def meth (self , _meth = meth ):
143
+ try :
144
+ return _meth (self )
145
+ finally :
146
+ restore__testsinglephase ()
139
147
meth = cpython_only (meth )
140
148
return unittest .skipIf (_testsinglephase is None ,
141
149
'test requires _testsinglephase module' )(meth )
142
150
143
151
152
+ def requires_subinterpreters (meth ):
153
+ """Decorator to skip a test if subinterpreters are not supported."""
154
+ return unittest .skipIf (_interpreters is None ,
155
+ 'subinterpreters required' )(meth )
156
+
157
+
144
158
class ModuleSnapshot (types .SimpleNamespace ):
145
159
"""A representation of a module for testing.
146
160
@@ -1943,6 +1957,20 @@ def test_isolated_config(self):
1943
1957
with self .subTest (f'{ module } : strict, fresh' ):
1944
1958
self .check_compatible_fresh (module , strict = True , isolated = True )
1945
1959
1960
+ @requires_subinterpreters
1961
+ @requires_singlephase_init
1962
+ def test_disallowed_reimport (self ):
1963
+ # See https://github.com/python/cpython/issues/104621.
1964
+ script = textwrap .dedent ('''
1965
+ import _testsinglephase
1966
+ print(_testsinglephase)
1967
+ ''' )
1968
+ interpid = _interpreters .create ()
1969
+ with self .assertRaises (_interpreters .RunFailedError ):
1970
+ _interpreters .run_string (interpid , script )
1971
+ with self .assertRaises (_interpreters .RunFailedError ):
1972
+ _interpreters .run_string (interpid , script )
1973
+
1946
1974
1947
1975
class TestSinglePhaseSnapshot (ModuleSnapshot ):
1948
1976
@@ -2002,6 +2030,10 @@ def setUpClass(cls):
2002
2030
# Start fresh.
2003
2031
cls .clean_up ()
2004
2032
2033
+ @classmethod
2034
+ def tearDownClass (cls ):
2035
+ restore__testsinglephase ()
2036
+
2005
2037
def tearDown (self ):
2006
2038
# Clean up the module.
2007
2039
self .clean_up ()
0 commit comments