mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Issue 19851: Fix a regression in reloading submodules.
This commit is contained in:
parent
fc25d629ab
commit
c1e7c747f9
3 changed files with 81 additions and 4 deletions
|
@ -153,10 +153,17 @@ def reload(module):
|
||||||
_RELOADING[name] = module
|
_RELOADING[name] = module
|
||||||
try:
|
try:
|
||||||
parent_name = name.rpartition('.')[0]
|
parent_name = name.rpartition('.')[0]
|
||||||
if parent_name and parent_name not in sys.modules:
|
if parent_name:
|
||||||
msg = "parent {!r} not in sys.modules"
|
try:
|
||||||
raise ImportError(msg.format(parent_name), name=parent_name)
|
parent = sys.modules[parent_name]
|
||||||
spec = module.__spec__ = _bootstrap._find_spec(name, None, module)
|
except KeyError:
|
||||||
|
msg = "parent {!r} not in sys.modules"
|
||||||
|
raise ImportError(msg.format(parent_name), name=parent_name)
|
||||||
|
else:
|
||||||
|
pkgpath = parent.__path__
|
||||||
|
else:
|
||||||
|
pkgpath = None
|
||||||
|
spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, module)
|
||||||
methods = _bootstrap._SpecMethods(spec)
|
methods = _bootstrap._SpecMethods(spec)
|
||||||
methods.exec(module)
|
methods.exec(module)
|
||||||
# The module may have replaced itself in sys.modules!
|
# The module may have replaced itself in sys.modules!
|
||||||
|
|
|
@ -4,6 +4,7 @@ frozen_init, source_init = util.import_importlib('importlib')
|
||||||
frozen_util, source_util = util.import_importlib('importlib.util')
|
frozen_util, source_util = util.import_importlib('importlib.util')
|
||||||
frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
|
frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
|
||||||
|
|
||||||
|
from contextlib import contextmanager
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
from test import support
|
from test import support
|
||||||
|
@ -11,6 +12,37 @@ import types
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def temp_module(name, content='', *, pkg=False):
|
||||||
|
conflicts = [n for n in sys.modules if n.partition('.')[0] == name]
|
||||||
|
with support.temp_cwd(None) as cwd:
|
||||||
|
with util.uncache(name, *conflicts):
|
||||||
|
with support.DirsOnSysPath(cwd):
|
||||||
|
frozen_init.invalidate_caches()
|
||||||
|
|
||||||
|
location = os.path.join(cwd, name)
|
||||||
|
if pkg:
|
||||||
|
modpath = os.path.join(location, '__init__.py')
|
||||||
|
os.mkdir(name)
|
||||||
|
else:
|
||||||
|
modpath = location + '.py'
|
||||||
|
if content is None:
|
||||||
|
# Make sure the module file gets created.
|
||||||
|
content = ''
|
||||||
|
if content is not None:
|
||||||
|
# not a namespace package
|
||||||
|
with open(modpath, 'w') as modfile:
|
||||||
|
modfile.write(content)
|
||||||
|
yield location
|
||||||
|
|
||||||
|
|
||||||
|
def submodule(parent, name, pkg_dir, content=''):
|
||||||
|
path = os.path.join(pkg_dir, name + '.py')
|
||||||
|
with open(path, 'w') as subfile:
|
||||||
|
subfile.write(content)
|
||||||
|
return '{}.{}'.format(parent, name), path
|
||||||
|
|
||||||
|
|
||||||
class ImportModuleTests:
|
class ImportModuleTests:
|
||||||
|
|
||||||
"""Test importlib.import_module."""
|
"""Test importlib.import_module."""
|
||||||
|
@ -246,6 +278,32 @@ class FindSpecTests:
|
||||||
# None is returned upon failure to find a loader.
|
# None is returned upon failure to find a loader.
|
||||||
self.assertIsNone(self.init.find_spec('nevergoingtofindthismodule'))
|
self.assertIsNone(self.init.find_spec('nevergoingtofindthismodule'))
|
||||||
|
|
||||||
|
def test_find_submodule(self):
|
||||||
|
name = 'spam'
|
||||||
|
subname = 'ham'
|
||||||
|
with temp_module(name, pkg=True) as pkg_dir:
|
||||||
|
fullname, _ = submodule(name, subname, pkg_dir)
|
||||||
|
spec = self.init.find_spec(fullname, [pkg_dir])
|
||||||
|
self.assertIsNot(spec, None)
|
||||||
|
self.assertNotIn(name, sorted(sys.modules))
|
||||||
|
# Ensure successive calls behave the same.
|
||||||
|
spec_again = self.init.find_spec(fullname, [pkg_dir])
|
||||||
|
# XXX Once #19927 is resolved, uncomment this line.
|
||||||
|
#self.assertEqual(spec_again, spec)
|
||||||
|
|
||||||
|
def test_find_submodule_missing_path(self):
|
||||||
|
name = 'spam'
|
||||||
|
subname = 'ham'
|
||||||
|
with temp_module(name, pkg=True) as pkg_dir:
|
||||||
|
fullname, _ = submodule(name, subname, pkg_dir)
|
||||||
|
spec = self.init.find_spec(fullname)
|
||||||
|
self.assertIs(spec, None)
|
||||||
|
self.assertNotIn(name, sorted(sys.modules))
|
||||||
|
# Ensure successive calls behave the same.
|
||||||
|
spec = self.init.find_spec(fullname)
|
||||||
|
self.assertIs(spec, None)
|
||||||
|
|
||||||
|
|
||||||
class Frozen_FindSpecTests(FindSpecTests, unittest.TestCase):
|
class Frozen_FindSpecTests(FindSpecTests, unittest.TestCase):
|
||||||
init = frozen_init
|
init = frozen_init
|
||||||
machinery = frozen_machinery
|
machinery = frozen_machinery
|
||||||
|
@ -410,6 +468,16 @@ class ReloadTests:
|
||||||
self.assertEqual(loader.path, init_path)
|
self.assertEqual(loader.path, init_path)
|
||||||
self.assertEqual(ns, expected)
|
self.assertEqual(ns, expected)
|
||||||
|
|
||||||
|
def test_reload_submodule(self):
|
||||||
|
# See #19851.
|
||||||
|
name = 'spam'
|
||||||
|
subname = 'ham'
|
||||||
|
with temp_module(name, pkg=True) as pkg_dir:
|
||||||
|
fullname, _ = submodule(name, subname, pkg_dir)
|
||||||
|
ham = self.init.import_module(fullname)
|
||||||
|
reloaded = self.init.reload(ham)
|
||||||
|
self.assertIs(reloaded, ham)
|
||||||
|
|
||||||
|
|
||||||
class Frozen_ReloadTests(ReloadTests, unittest.TestCase):
|
class Frozen_ReloadTests(ReloadTests, unittest.TestCase):
|
||||||
init = frozen_init
|
init = frozen_init
|
||||||
|
|
|
@ -114,6 +114,8 @@ Library
|
||||||
- Issue #6477: Added support for pickling the types of built-in singletons
|
- Issue #6477: Added support for pickling the types of built-in singletons
|
||||||
(i.e., Ellipsis, NotImplemented, None).
|
(i.e., Ellipsis, NotImplemented, None).
|
||||||
|
|
||||||
|
- Issue #19851: Fixed a regression in reloading sub-modules.
|
||||||
|
|
||||||
- ssl.create_default_context() sets OP_NO_COMPRESSION to prevent CRIME.
|
- ssl.create_default_context() sets OP_NO_COMPRESSION to prevent CRIME.
|
||||||
|
|
||||||
- Issue #19802: Add socket.SO_PRIORITY.
|
- Issue #19802: Add socket.SO_PRIORITY.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue