Skip to content

Commit 3900a08

Browse files
authored
update imp.py from CPython 3.11 (#5054)
1 parent 64c66e0 commit 3900a08

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

Lib/imp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from _imp import (lock_held, acquire_lock, release_lock,
1010
get_frozen_object, is_frozen_package,
1111
init_frozen, is_builtin, is_frozen,
12-
_fix_co_filename)
12+
_fix_co_filename, _frozen_module_names)
1313
try:
1414
from _imp import create_dynamic
1515
except ImportError:
@@ -226,7 +226,7 @@ def load_module(name, file, filename, details):
226226
227227
"""
228228
suffix, mode, type_ = details
229-
if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
229+
if mode and (not mode.startswith('r') or '+' in mode):
230230
raise ValueError('invalid file open mode {!r}'.format(mode))
231231
elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
232232
msg = 'file object required for import (type code {})'.format(type_)

Lib/test/test_imp.py

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import gc
12
import importlib
23
import importlib.util
34
import os
@@ -8,19 +9,21 @@
89
from test.support import import_helper
910
from test.support import os_helper
1011
from test.support import script_helper
12+
from test.support import warnings_helper
1113
import unittest
1214
import warnings
13-
with warnings.catch_warnings():
14-
warnings.simplefilter('ignore', DeprecationWarning)
15-
import imp
15+
imp = warnings_helper.import_deprecated('imp')
1616
import _imp
1717

1818

19+
OS_PATH_NAME = os.path.__name__
20+
21+
1922
def requires_load_dynamic(meth):
2023
"""Decorator to skip a test if not running under CPython or lacking
2124
imp.load_dynamic()."""
2225
meth = support.cpython_only(meth)
23-
return unittest.skipIf(not hasattr(imp, 'load_dynamic'),
26+
return unittest.skipIf(getattr(imp, 'load_dynamic', None) is None,
2427
'imp.load_dynamic() required')(meth)
2528

2629

@@ -216,15 +219,17 @@ def test_load_from_source(self):
216219
# state after reversion. Reinitialising the module contents
217220
# and just reverting os.environ to its previous state is an OK
218221
# workaround
219-
orig_path = os.path
220-
orig_getenv = os.getenv
221-
with os_helper.EnvironmentVarGuard():
222-
x = imp.find_module("os")
223-
self.addCleanup(x[0].close)
224-
new_os = imp.load_module("os", *x)
225-
self.assertIs(os, new_os)
226-
self.assertIs(orig_path, new_os.path)
227-
self.assertIsNot(orig_getenv, new_os.getenv)
222+
with import_helper.CleanImport('os', 'os.path', OS_PATH_NAME):
223+
import os
224+
orig_path = os.path
225+
orig_getenv = os.getenv
226+
with os_helper.EnvironmentVarGuard():
227+
x = imp.find_module("os")
228+
self.addCleanup(x[0].close)
229+
new_os = imp.load_module("os", *x)
230+
self.assertIs(os, new_os)
231+
self.assertIs(orig_path, new_os.path)
232+
self.assertIsNot(orig_getenv, new_os.getenv)
228233

229234
@requires_load_dynamic
230235
def test_issue15828_load_extensions(self):
@@ -351,8 +356,8 @@ def test_issue_35321(self):
351356
# TODO: RUSTPYTHON
352357
@unittest.expectedFailure
353358
def test_source_hash(self):
354-
self.assertEqual(_imp.source_hash(42, b'hi'), b'\xc6\xe7Z\r\x03:}\xab')
355-
self.assertEqual(_imp.source_hash(43, b'hi'), b'\x85\x9765\xf8\x9a\x8b9')
359+
self.assertEqual(_imp.source_hash(42, b'hi'), b'\xfb\xd9G\x05\xaf$\x9b~')
360+
self.assertEqual(_imp.source_hash(43, b'hi'), b'\xd0/\x87C\xccC\xff\xe2')
356361

357362
def test_pyc_invalidation_mode_from_cmdline(self):
358363
cases = [
@@ -384,6 +389,35 @@ def test_find_and_load_checked_pyc(self):
384389
self.assertEqual(mod.x, 42)
385390

386391

392+
@support.cpython_only
393+
def test_create_builtin_subinterp(self):
394+
# gh-99578: create_builtin() behavior changes after the creation of the
395+
# first sub-interpreter. Test both code paths, before and after the
396+
# creation of a sub-interpreter. Previously, create_builtin() had
397+
# a reference leak after the creation of the first sub-interpreter.
398+
399+
import builtins
400+
create_builtin = support.get_attribute(_imp, "create_builtin")
401+
class Spec:
402+
name = "builtins"
403+
spec = Spec()
404+
405+
def check_get_builtins():
406+
refcnt = sys.getrefcount(builtins)
407+
mod = _imp.create_builtin(spec)
408+
self.assertIs(mod, builtins)
409+
self.assertEqual(sys.getrefcount(builtins), refcnt + 1)
410+
# Check that a GC collection doesn't crash
411+
gc.collect()
412+
413+
check_get_builtins()
414+
415+
ret = support.run_in_subinterp("import builtins")
416+
self.assertEqual(ret, 0)
417+
418+
check_get_builtins()
419+
420+
387421
class ReloadTests(unittest.TestCase):
388422

389423
"""Very basic tests to make sure that imp.reload() operates just like

vm/src/stdlib/imp.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ mod _imp {
154154
// TODO:
155155
}
156156

157+
#[pyfunction]
158+
fn _frozen_module_names(_code: PyObjectRef) {
159+
// TODO:
160+
}
161+
157162
#[allow(clippy::type_complexity)]
158163
#[pyfunction]
159164
fn find_frozen(

0 commit comments

Comments
 (0)