| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,7 +12,7 @@ def import_singlephase(): | |||
| 12 | 12 | try: | |
| 13 | 13 | import _testsinglephase | |
| 14 | 14 | except ImportError: | |
| 15 | - sys.modules.pop('_testsinglephase') | ||
| 15 | + sys.modules.pop('_testsinglephase', None) | ||
| 16 | 16 | return False | |
| 17 | 17 | else: | |
| 18 | 18 | del sys.modules['_testsinglephase'] | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -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", | |
@@ -147,19 +146,34 @@ def _ready_to_import(name=None, source=""): | |||
| 147 | 146 | del sys.modules[name] | |
| 148 | 147 | ||
| 149 | 148 | ||
| 150 | - def requires_subinterpreters(meth): | ||
| 151 | - """Decorator to skip a test if subinterpreters are not supported.""" | ||
| 152 | - return unittest.skipIf(_interpreters is None, | ||
| 153 | - 'subinterpreters required')(meth) | ||
| 149 | + if _testsinglephase is not None: | ||
| 150 | + def restore__testsinglephase(*, _orig=_testsinglephase): | ||
| 151 | + # We started with the module imported and want to restore | ||
| 152 | + # it to its nominal state. | ||
| 153 | + _orig._clear_globals() | ||
| 154 | + _testinternalcapi.clear_extension('_testsinglephase', _orig.__file__) | ||
| 155 | + import _testsinglephase | ||
| 154 | 156 | ||
| 155 | 157 | ||
| 156 | 158 | def requires_singlephase_init(meth): | |
| 157 | 159 | """Decorator to skip if single-phase init modules are not supported.""" | |
| 160 | + if not isinstance(meth, type): | ||
| 161 | + def meth(self, _meth=meth): | ||
| 162 | + try: | ||
| 163 | + return _meth(self) | ||
| 164 | + finally: | ||
| 165 | + restore__testsinglephase() | ||
| 158 | 166 | meth = cpython_only(meth) | |
| 159 | 167 | return unittest.skipIf(_testsinglephase is None, | |
| 160 | 168 | 'test requires _testsinglephase module')(meth) | |
| 161 | 169 | ||
| 162 | 170 | ||
| 171 | + def requires_subinterpreters(meth): | ||
| 172 | + """Decorator to skip a test if subinterpreters are not supported.""" | ||
| 173 | + return unittest.skipIf(_interpreters is None, | ||
| 174 | + 'subinterpreters required')(meth) | ||
| 175 | + | ||
| 176 | + | ||
| 163 | 177 | class ModuleSnapshot(types.SimpleNamespace): | |
| 164 | 178 | """A representation of a module for testing. | |
| 165 | 179 | ||
@@ -1962,6 +1976,20 @@ def test_isolated_config(self): | |||
| 1962 | 1976 | with self.subTest(f'{module}: strict, fresh'): | |
| 1963 | 1977 | self.check_compatible_fresh(module, strict=True, isolated=True) | |
| 1964 | 1978 | ||
| 1979 | + @requires_subinterpreters | ||
| 1980 | + @requires_singlephase_init | ||
| 1981 | + def test_disallowed_reimport(self): | ||
| 1982 | + # See https://github.com/python/cpython/issues/104621. | ||
| 1983 | + script = textwrap.dedent(''' | ||
| 1984 | + import _testsinglephase | ||
| 1985 | + print(_testsinglephase) | ||
| 1986 | + ''') | ||
| 1987 | + interpid = _interpreters.create() | ||
| 1988 | + with self.assertRaises(_interpreters.RunFailedError): | ||
| 1989 | + _interpreters.run_string(interpid, script) | ||
| 1990 | + with self.assertRaises(_interpreters.RunFailedError): | ||
| 1991 | + _interpreters.run_string(interpid, script) | ||
| 1992 | + | ||
| 1965 | 1993 | ||
| 1966 | 1994 | class TestSinglePhaseSnapshot(ModuleSnapshot): | |
| 1967 | 1995 | ||
@@ -2017,6 +2045,10 @@ def setUpClass(cls): | |||
| 2017 | 2045 | # Start fresh. | |
| 2018 | 2046 | cls.clean_up() | |
| 2019 | 2047 | ||
| 2048 | + @classmethod | ||
| 2049 | + def tearDownClass(cls): | ||
| 2050 | + restore__testsinglephase() | ||
| 2051 | + | ||
| 2020 | 2052 | def tearDown(self): | |
| 2021 | 2053 | # Clean up the module. | |
| 2022 | 2054 | self.clean_up() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Unsupported modules now always fail to be imported. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1215,6 +1215,15 @@ import_find_extension(PyThreadState *tstate, PyObject *name, | |||
| 1215 | 1215 | return NULL; | |
| 1216 | 1216 | } | |
| 1217 | 1217 | ||
| 1218 | + /* It may have been successfully imported previously | ||
| 1219 | + in an interpreter that allows legacy modules | ||
| 1220 | + but is not allowed in the current interpreter. */ | ||
| 1221 | + const char *name_buf = PyUnicode_AsUTF8(name); | ||
| 1222 | + assert(name_buf != NULL); | ||
| 1223 | + if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) { | ||
| 1224 | + return NULL; | ||
| 1225 | + } | ||
| 1226 | + | ||
| 1218 | 1227 | PyObject *mod, *mdict; | |
| 1219 | 1228 | PyObject *modules = MODULES(tstate->interp); | |
| 1220 | 1229 | ||
@@ -3704,16 +3713,8 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) | |||
| 3704 | 3713 | ||
| 3705 | 3714 | PyThreadState *tstate = _PyThreadState_GET(); | |
| 3706 | 3715 | mod = import_find_extension(tstate, name, path); | |
| 3707 | - if (mod != NULL) { | ||
| 3708 | - const char *name_buf = PyUnicode_AsUTF8(name); | ||
| 3709 | - assert(name_buf != NULL); | ||
| 3710 | - if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) { | ||
| 3711 | - Py_DECREF(mod); | ||
| 3712 | - mod = NULL; | ||
| 3713 | - } | ||
| 3714 | - goto finally; | ||
| 3715 | - } | ||
| 3716 | - else if (PyErr_Occurred()) { | ||
| 3716 | + if (mod != NULL || _PyErr_Occurred(tstate)) { | ||
| 3717 | + assert(mod == NULL || !_PyErr_Occurred(tstate)); | ||
| 3717 | 3718 | goto finally; | |
| 3718 | 3719 | } | |
| 3719 | 3720 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments