Author: Armin Rigo <[email protected]>
Branch:
Changeset: r86650:9332dfa6e22e
Date: 2016-08-28 21:08 +0200
http://bitbucket.org/pypy/pypy/changeset/9332dfa6e22e/
Log: Issue #2382: fixed the import logic. The main difference is that if
we call an import hook via sys.meta_path, it succeeds (a bit
brokenly, like CPython) even if the load_module() method doesn't add
the module in sys.modules.
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -123,5 +123,4 @@
pathname = code.co_filename
w_mod = importing.add_module(space, w_name)
space.setattr(w_mod, space.wrap('__file__'), space.wrap(pathname))
- importing.exec_code_module(space, w_mod, code)
- return w_mod
+ return importing.exec_code_module(space, w_mod, code, w_name)
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -597,6 +597,11 @@
@jit.dont_look_inside
def load_module(space, w_modulename, find_info, reuse=False):
+ """Like load_module() in CPython's import.c, this will normally
+ make a module object, store it in sys.modules, execute code in it,
+ and then fetch it again from sys.modules. But this logic is not
+ used if we're calling a PEP302 loader.
+ """
if find_info is None:
return
@@ -625,17 +630,15 @@
try:
if find_info.modtype == PY_SOURCE:
- load_source_module(
+ return load_source_module(
space, w_modulename, w_mod,
find_info.filename, find_info.stream.readall(),
find_info.stream.try_to_find_file_descriptor())
- return w_mod
elif find_info.modtype == PY_COMPILED:
magic = _r_long(find_info.stream)
timestamp = _r_long(find_info.stream)
- load_compiled_module(space, w_modulename, w_mod,
find_info.filename,
+ return load_compiled_module(space, w_modulename, w_mod,
find_info.filename,
magic, timestamp,
find_info.stream.readall())
- return w_mod
elif find_info.modtype == PKG_DIRECTORY:
w_path = space.newlist([space.wrap(find_info.filename)])
space.setattr(w_mod, space.wrap('__path__'), w_path)
@@ -644,14 +647,13 @@
if find_info is None:
return w_mod
try:
- load_module(space, w_modulename, find_info, reuse=True)
+ w_mod = load_module(space, w_modulename, find_info,
+ reuse=True)
finally:
try:
find_info.stream.close()
except StreamErrors:
pass
- # fetch the module again, in case of "substitution"
- w_mod = check_sys_modules(space, w_modulename)
return w_mod
elif find_info.modtype == C_EXTENSION and has_so_extension(space):
load_c_extension(space, find_info.filename,
space.str_w(w_modulename))
@@ -677,13 +679,6 @@
try:
if find_info:
w_mod = load_module(space, w_modulename, find_info)
- try:
- w_mod = space.getitem(space.sys.get("modules"),
- w_modulename)
- except OperationError as oe:
- if not oe.match(space, space.w_KeyError):
- raise
- raise OperationError(space.w_ImportError, w_modulename)
if w_parent is not None:
space.setattr(w_parent, space.wrap(partname), w_mod)
return w_mod
@@ -875,20 +870,32 @@
pycode = ec.compiler.compile(source, pathname, 'exec', 0)
return pycode
-def exec_code_module(space, w_mod, code_w):
+def exec_code_module(space, w_mod, code_w, w_modulename,
check_afterwards=True):
+ """
+ Execute a code object in the module's dict. Returns
+ 'sys.modules[modulename]', which must exist.
+ """
w_dict = space.getattr(w_mod, space.wrap('__dict__'))
space.call_method(w_dict, 'setdefault',
space.wrap('__builtins__'),
space.wrap(space.builtin))
code_w.exec_code(space, w_dict, w_dict)
+ if check_afterwards:
+ w_mod = check_sys_modules(space, w_modulename)
+ if w_mod is None:
+ raise oefmt(space.w_ImportError,
+ "Loaded module %R not found in sys.modules",
+ w_modulename)
+ return w_mod
+
@jit.dont_look_inside
def load_source_module(space, w_modulename, w_mod, pathname, source, fd,
- write_pyc=True):
+ write_pyc=True, check_afterwards=True):
"""
- Load a source module from a given file and return its module
- object.
+ Load a source module from a given file. Returns the result
+ of sys.modules[modulename], which must exist.
"""
w = space.wrap
@@ -927,9 +934,8 @@
code_w.remove_docstrings(space)
update_code_filenames(space, code_w, pathname)
- exec_code_module(space, w_mod, code_w)
-
- return w_mod
+ return exec_code_module(space, w_mod, code_w, w_modulename,
+ check_afterwards=check_afterwards)
def update_code_filenames(space, code_w, pathname, oldname=None):
assert isinstance(code_w, PyCode)
@@ -1012,10 +1018,10 @@
@jit.dont_look_inside
def load_compiled_module(space, w_modulename, w_mod, cpathname, magic,
- timestamp, source):
+ timestamp, source, check_afterwards=True):
"""
- Load a module from a compiled file, execute it, and return its
- module object.
+ Load a module from a compiled file and execute it. Returns
+ 'sys.modules[modulename]', which must exist.
"""
log_pyverbose(space, 1, "import %s # compiled from %s\n" %
(space.str_w(w_modulename), cpathname))
@@ -1032,9 +1038,8 @@
if optimize >= 2:
code_w.remove_docstrings(space)
- exec_code_module(space, w_mod, code_w)
-
- return w_mod
+ return exec_code_module(space, w_mod, code_w, w_modulename,
+ check_afterwards=check_afterwards)
def open_exclusive(space, cpathname, mode):
try:
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -98,33 +98,35 @@
w_mod = space.wrap(Module(space, w_modulename))
importing._prepare_module(space, w_mod, filename, None)
- importing.load_source_module(
+ w_mod = importing.load_source_module(
space, w_modulename, w_mod,
filename, stream.readall(), stream.try_to_find_file_descriptor())
if space.is_none(w_file):
stream.close()
return w_mod
-@unwrap_spec(filename='str0')
-def _run_compiled_module(space, w_modulename, filename, w_file, w_module):
+@unwrap_spec(filename='str0', check_afterwards=int)
+def _run_compiled_module(space, w_modulename, filename, w_file, w_module,
+ check_afterwards=False):
# the function 'imp._run_compiled_module' is a pypy-only extension
stream = get_file(space, w_file, filename, 'rb')
magic = importing._r_long(stream)
timestamp = importing._r_long(stream)
- importing.load_compiled_module(
+ w_mod = importing.load_compiled_module(
space, w_modulename, w_module, filename, magic, timestamp,
- stream.readall())
+ stream.readall(), check_afterwards=check_afterwards)
if space.is_none(w_file):
stream.close()
+ return w_mod
@unwrap_spec(filename='str0')
def load_compiled(space, w_modulename, filename, w_file=None):
w_mod = space.wrap(Module(space, w_modulename))
importing._prepare_module(space, w_mod, filename, None)
- _run_compiled_module(space, w_modulename, filename, w_file, w_mod)
- return w_mod
+ return _run_compiled_module(space, w_modulename, filename, w_file, w_mod,
+ check_afterwards=True)
@unwrap_spec(filename=str)
def load_dynamic(space, w_modulename, filename, w_file=None):
diff --git a/pypy/module/imp/test/test_import.py
b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -118,7 +118,7 @@
filename = str(p.join("x.py"))
stream = streamio.open_file_as_stream(filename, "r")
try:
- importing.load_source_module(
+ _load_source_module(
space, w_modname, w(importing.Module(space, w_modname)),
filename, stream.readall(),
stream.try_to_find_file_descriptor())
@@ -139,6 +139,15 @@
return str(root)
+def _load_source_module(space, w_modname, w_mod, *args, **kwds):
+ kwds.setdefault('check_afterwards', False)
+ return importing.load_source_module(space, w_modname, w_mod, *args, **kwds)
+
+def _load_compiled_module(space, w_modname, w_mod, *args, **kwds):
+ kwds.setdefault('check_afterwards', False)
+ return importing.load_compiled_module(space, w_modname, w_mod,
+ *args, **kwds)
+
def _setup(space):
dn = setup_directory_structure(space)
@@ -887,8 +896,7 @@
w_mod = space.wrap(Module(space, w_modulename))
magic = importing._r_long(stream)
timestamp = importing._r_long(stream)
- w_ret = importing.load_compiled_module(space,
- w_modulename,
+ w_ret = _load_compiled_module(space, w_modulename,
w_mod,
cpathname,
magic,
@@ -946,7 +954,7 @@
pathname = _testfilesource()
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(
+ w_ret = _load_source_module(
space, w_modulename, w_mod,
pathname, stream.readall(),
stream.try_to_find_file_descriptor())
@@ -968,7 +976,7 @@
pathname = _testfilesource()
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(
+ w_ret = _load_source_module(
space, w_modulename, w_mod,
pathname, stream.readall(),
stream.try_to_find_file_descriptor(),
@@ -987,7 +995,7 @@
try:
space.setattr(space.sys, space.wrap('dont_write_bytecode'),
space.w_True)
- w_ret = importing.load_source_module(
+ w_ret = _load_source_module(
space, w_modulename, w_mod,
pathname, stream.readall(),
stream.try_to_find_file_descriptor())
@@ -1006,7 +1014,7 @@
pathname = _testfilesource(source="<Syntax Error>")
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(
+ w_ret = _load_source_module(
space, w_modulename, w_mod,
pathname, stream.readall(),
stream.try_to_find_file_descriptor())
@@ -1026,7 +1034,7 @@
pathname = _testfilesource(source="a = unknown_name")
stream = streamio.open_file_as_stream(pathname, "r")
try:
- w_ret = importing.load_source_module(
+ w_ret = _load_source_module(
space, w_modulename, w_mod,
pathname, stream.readall(),
stream.try_to_find_file_descriptor())
@@ -1114,7 +1122,7 @@
magic = importing._r_long(stream)
timestamp = importing._r_long(stream)
space2.raises_w(space2.w_ImportError,
- importing.load_compiled_module,
+ _load_compiled_module,
space2,
w_modulename,
w_mod,
@@ -1326,10 +1334,7 @@
# use an import hook that doesn't update sys.modules, then the
# import succeeds; but at the same time, you can have the same
# result without an import hook (see test_del_from_sys_modules)
- # and then the import fails. This looks like even more mess
- # to replicate, so we ignore it until someone really hits this
- # case...
- skip("looks like an inconsistency in CPython")
+ # and then the import fails. Mess mess mess.
class ImportHook(object):
def find_module(self, fullname, path=None):
diff --git a/pypy/module/zipimport/interp_zipimport.py
b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -152,8 +152,7 @@
importing._prepare_module(space, w_mod, real_name, pkgpath)
co_filename = self.make_co_filename(filename)
code_w = importing.parse_source_module(space, co_filename, buf)
- importing.exec_code_module(space, w_mod, code_w)
- return w_mod
+ return importing.exec_code_module(space, w_mod, code_w, w(modname))
def _parse_mtime(self, space, filename):
w = space.wrap
@@ -205,10 +204,10 @@
real_name = self.filename + os.path.sep + self.corr_zname(filename)
space.setattr(w_mod, w('__loader__'), space.wrap(self))
importing._prepare_module(space, w_mod, real_name, pkgpath)
- result = importing.load_compiled_module(space, w(modname), w_mod,
+ w_result = importing.load_compiled_module(space, w(modname), w_mod,
filename, magic, timestamp,
buf)
- return result
+ return w_result
def have_modulefile(self, space, filename):
if ZIPSEP != os.path.sep:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit