Commit eca85181 authored by Antoine Pitrou's avatar Antoine Pitrou

Merge heads

parents ec9bac42 d76bc7ab
...@@ -984,12 +984,12 @@ def _find_and_load(name, import_): ...@@ -984,12 +984,12 @@ def _find_and_load(name, import_):
loader = _find_module(name, path) loader = _find_module(name, path)
if loader is None: if loader is None:
raise ImportError(_ERR_MSG.format(name), name=name) raise ImportError(_ERR_MSG.format(name), name=name)
elif name in sys.modules: elif name not in sys.modules:
# The parent module already imported this module. # The parent import may have already imported this module.
module = sys.modules[name] loader.load_module(name)
else:
module = loader.load_module(name)
verbose_message('import {!r} # {!r}', name, loader) verbose_message('import {!r} # {!r}', name, loader)
# Backwards-compatibility; be nicer to skip the dict lookup.
module = sys.modules[name]
if parent: if parent:
# Set the module as an attribute on its parent. # Set the module as an attribute on its parent.
parent_module = sys.modules[parent] parent_module = sys.modules[parent]
...@@ -1088,11 +1088,7 @@ def __import__(name, globals={}, locals={}, fromlist=[], level=0): ...@@ -1088,11 +1088,7 @@ def __import__(name, globals={}, locals={}, fromlist=[], level=0):
# Return up to the first dot in 'name'. This is complicated by the fact # Return up to the first dot in 'name'. This is complicated by the fact
# that 'name' may be relative. # that 'name' may be relative.
if level == 0: if level == 0:
index = name.find('.') return sys.modules[name.partition('.')[0]]
if index == -1:
return module
else:
return sys.modules[name[:index]]
elif not name: elif not name:
return module return module
else: else:
......
...@@ -47,12 +47,36 @@ class UseCache(unittest.TestCase): ...@@ -47,12 +47,36 @@ class UseCache(unittest.TestCase):
mock.load_module = MethodType(load_module, mock) mock.load_module = MethodType(load_module, mock)
return mock return mock
def test_using_loader_return(self): # __import__ inconsistent between loaders and built-in import when it comes
loader_return = 'hi there!' # to when to use the module in sys.modules and when not to.
with self.create_mock('module', return_=loader_return) as mock: @import_util.importlib_only
def test_using_cache_after_loader(self):
# [from cache on return]
with self.create_mock('module') as mock:
with util.import_state(meta_path=[mock]): with util.import_state(meta_path=[mock]):
module = import_util.import_('module') module = import_util.import_('module')
self.assertEqual(module, loader_return) self.assertEqual(id(module), id(sys.modules['module']))
# See test_using_cache_after_loader() for reasoning.
@import_util.importlib_only
def test_using_cache_for_assigning_to_attribute(self):
# [from cache to attribute]
with self.create_mock('pkg.__init__', 'pkg.module') as importer:
with util.import_state(meta_path=[importer]):
module = import_util.import_('pkg.module')
self.assertTrue(hasattr(module, 'module'))
self.assertTrue(id(module.module), id(sys.modules['pkg.module']))
# See test_using_cache_after_loader() for reasoning.
@import_util.importlib_only
def test_using_cache_for_fromlist(self):
# [from cache for fromlist]
with self.create_mock('pkg.__init__', 'pkg.module') as importer:
with util.import_state(meta_path=[importer]):
module = import_util.import_('pkg', fromlist=['module'])
self.assertTrue(hasattr(module, 'module'))
self.assertEqual(id(module.module),
id(sys.modules['pkg.module']))
def test_main(): def test_main():
......
...@@ -23,9 +23,6 @@ Core and Builtins ...@@ -23,9 +23,6 @@ Core and Builtins
fails to import now uses the new path and name attributes from fails to import now uses the new path and name attributes from
Issue #1559549. Issue #1559549.
- Issue #14582: Import directly returns the module as returned by a loader when
possible instead of fetching it from sys.modules.
- Issue #13889: Check and (if necessary) set FPU control word before calling - Issue #13889: Check and (if necessary) set FPU control word before calling
any of the dtoa.c string <-> float conversion functions, on MSVC builds of any of the dtoa.c string <-> float conversion functions, on MSVC builds of
Python. This fixes issues when embedding Python in a Delphi app. Python. This fixes issues when embedding Python in a Delphi app.
......
...@@ -2447,22 +2447,15 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, ...@@ -2447,22 +2447,15 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
Py_DECREF(partition); Py_DECREF(partition);
if (level == 0) { if (level == 0) {
if (PyUnicode_GET_LENGTH(name) == final_mod = PyDict_GetItem(interp->modules, front);
PyUnicode_GET_LENGTH(front)) {
final_mod = mod;
}
else {
final_mod = PyDict_GetItem(interp->modules, front);
if (final_mod == NULL) {
PyErr_Format(PyExc_KeyError,
"%R not in sys.modules as expected", front);
}
}
Py_DECREF(front); Py_DECREF(front);
if (final_mod == NULL) { if (final_mod == NULL) {
goto error_with_unlock; PyErr_Format(PyExc_KeyError,
"%R not in sys.modules as expected", front);
}
else {
Py_INCREF(final_mod);
} }
Py_INCREF(final_mod);
} }
else { else {
Py_ssize_t cut_off = PyUnicode_GET_LENGTH(name) - Py_ssize_t cut_off = PyUnicode_GET_LENGTH(name) -
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment