Skip to content

update imp.py from CPython 3.11 #5054

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Lib/imp.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from _imp import (lock_held, acquire_lock, release_lock,
get_frozen_object, is_frozen_package,
init_frozen, is_builtin, is_frozen,
_fix_co_filename)
_fix_co_filename, _frozen_module_names)
try:
from _imp import create_dynamic
except ImportError:
Expand Down Expand Up @@ -226,7 +226,7 @@ def load_module(name, file, filename, details):

"""
suffix, mode, type_ = details
if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
if mode and (not mode.startswith('r') or '+' in mode):
raise ValueError('invalid file open mode {!r}'.format(mode))
elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
msg = 'file object required for import (type code {})'.format(type_)
Expand Down
64 changes: 49 additions & 15 deletions Lib/test/test_imp.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import gc
import importlib
import importlib.util
import os
Expand All @@ -8,19 +9,21 @@
from test.support import import_helper
from test.support import os_helper
from test.support import script_helper
from test.support import warnings_helper
import unittest
import warnings
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
import imp
imp = warnings_helper.import_deprecated('imp')
import _imp


OS_PATH_NAME = os.path.__name__


def requires_load_dynamic(meth):
"""Decorator to skip a test if not running under CPython or lacking
imp.load_dynamic()."""
meth = support.cpython_only(meth)
return unittest.skipIf(not hasattr(imp, 'load_dynamic'),
return unittest.skipIf(getattr(imp, 'load_dynamic', None) is None,
'imp.load_dynamic() required')(meth)


Expand Down Expand Up @@ -216,15 +219,17 @@ def test_load_from_source(self):
# state after reversion. Reinitialising the module contents
# and just reverting os.environ to its previous state is an OK
# workaround
orig_path = os.path
orig_getenv = os.getenv
with os_helper.EnvironmentVarGuard():
x = imp.find_module("os")
self.addCleanup(x[0].close)
new_os = imp.load_module("os", *x)
self.assertIs(os, new_os)
self.assertIs(orig_path, new_os.path)
self.assertIsNot(orig_getenv, new_os.getenv)
with import_helper.CleanImport('os', 'os.path', OS_PATH_NAME):
import os
orig_path = os.path
orig_getenv = os.getenv
with os_helper.EnvironmentVarGuard():
x = imp.find_module("os")
self.addCleanup(x[0].close)
new_os = imp.load_module("os", *x)
self.assertIs(os, new_os)
self.assertIs(orig_path, new_os.path)
self.assertIsNot(orig_getenv, new_os.getenv)

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

def test_pyc_invalidation_mode_from_cmdline(self):
cases = [
Expand Down Expand Up @@ -384,6 +389,35 @@ def test_find_and_load_checked_pyc(self):
self.assertEqual(mod.x, 42)


@support.cpython_only
def test_create_builtin_subinterp(self):
# gh-99578: create_builtin() behavior changes after the creation of the
# first sub-interpreter. Test both code paths, before and after the
# creation of a sub-interpreter. Previously, create_builtin() had
# a reference leak after the creation of the first sub-interpreter.

import builtins
create_builtin = support.get_attribute(_imp, "create_builtin")
class Spec:
name = "builtins"
spec = Spec()

def check_get_builtins():
refcnt = sys.getrefcount(builtins)
mod = _imp.create_builtin(spec)
self.assertIs(mod, builtins)
self.assertEqual(sys.getrefcount(builtins), refcnt + 1)
# Check that a GC collection doesn't crash
gc.collect()

check_get_builtins()

ret = support.run_in_subinterp("import builtins")
self.assertEqual(ret, 0)

check_get_builtins()


class ReloadTests(unittest.TestCase):

"""Very basic tests to make sure that imp.reload() operates just like
Expand Down
5 changes: 5 additions & 0 deletions vm/src/stdlib/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ mod _imp {
// TODO:
}

#[pyfunction]
fn _frozen_module_names(_code: PyObjectRef) {
// TODO:
}

#[allow(clippy::type_complexity)]
#[pyfunction]
fn find_frozen(
Expand Down