[pypy-commit] pypy py3.3: Merged in marky1991/pypy_new/fix_module_repr (pull request #404)
mjacob
pypy.commits at gmail.com
Wed Feb 24 04:06:41 EST 2016
Author: Manuel Jacob <me at manueljacob.de>
Branch: py3.3
Changeset: r82477:79680cd9c664
Date: 2016-02-24 10:05 +0100
http://bitbucket.org/pypy/pypy/changeset/79680cd9c664/
Log: Merged in marky1991/pypy_new/fix_module_repr (pull request #404)
3.3: Fix_module_repr to match PEP 420 and fix reload_builtin
diff --git a/pypy/interpreter/module.py b/pypy/interpreter/module.py
--- a/pypy/interpreter/module.py
+++ b/pypy/interpreter/module.py
@@ -121,19 +121,32 @@
return space.newtuple(tup_return)
def descr_module__repr__(self, space):
- from pypy.interpreter.mixedmodule import MixedModule
- if self.w_name is not None:
- name = space.unicode_w(space.repr(self.w_name))
- else:
+ w_loader = space.finditem(self.w_dict, space.wrap('__loader__'))
+ if w_loader is not None:
+ try:
+ return space.call_method(w_loader, "module_repr",
+ space.wrap(self))
+ except OperationError:
+ pass
+ try:
+ w_name = space.getattr(self, space.wrap('__name__'))
+ name = space.unicode_w(space.repr(w_name))
+ except OperationError:
name = u"'?'"
- if isinstance(self, MixedModule):
- return space.wrap(u"<module %s (built-in)>" % name)
+
try:
w___file__ = space.getattr(self, space.wrap('__file__'))
+ except OperationError:
+ w___file__ = space.w_None
+ if not space.isinstance_w(w___file__, space.w_unicode):
+ if w_loader is not None:
+ w_loader_repr = space.unicode_w(space.repr(w_loader))
+ return space.wrap(u"<module %s (%s)>" % (name, w_loader_repr))
+ else:
+ return space.wrap(u"<module %s>" % (name,))
+ else:
__file__ = space.unicode_w(space.repr(w___file__))
- except OperationError:
- __file__ = u'?'
- return space.wrap(u"<module %s from %s>" % (name, __file__))
+ return space.wrap(u"<module %s from %s>" % (name, __file__))
def descr_module__dir__(self, space):
w_dict = space.getattr(self, space.wrap('__dict__'))
diff --git a/pypy/interpreter/test/test_module.py b/pypy/interpreter/test/test_module.py
--- a/pypy/interpreter/test/test_module.py
+++ b/pypy/interpreter/test/test_module.py
@@ -74,11 +74,88 @@
r'lib_pypy\\_pypy_interact.py' in r.lower()) and
r.endswith('>'))
nofile = type(_pypy_interact)('nofile', 'foo')
- assert repr(nofile) == "<module 'nofile' from ?>"
+ assert repr(nofile) == "<module 'nofile'>"
m = type(_pypy_interact).__new__(type(_pypy_interact))
assert repr(m).startswith("<module '?'")
+ def test_repr_with_loader_with_valid_module_repr(self):
+ import sys
+ test_module = type(sys)("test_module", "doc")
+
+ # If the module has a __loader__ and that loader has a module_repr()
+ # method, call it with a single argument, which is the module object.
+ # The value returned is used as the module’s repr.
+ class CustomLoader:
+ @classmethod
+ def module_repr(cls, module):
+ mod_repr = ("<module {mod_name}: "
+ "{cls} Test>".format(mod_name=repr(module.__name__),
+ cls=repr(cls.__name__)))
+ return mod_repr
+ test_module.__loader__ = CustomLoader
+ assert repr(test_module) == "<module 'test_module': 'CustomLoader' Test>"
+
+ def test_repr_with_loader_with_module_repr_wrong_type(self):
+ import sys
+ test_module = type(sys)("test_module", "doc")
+
+ # This return value must be a string.
+ class BuggyCustomLoader:
+ @classmethod
+ def module_repr(cls, module):
+ return 5
+
+ test_module.__loader__ = BuggyCustomLoader
+ raises(TypeError, repr, test_module)
+
+ def test_repr_with_loader_with_raising_module_repr(self):
+ import sys
+ test_module = type(sys)("test_module", "doc")
+ # If an exception occurs in module_repr(), the exception is caught
+ # and discarded, and the calculation of the module’s repr continues
+ # as if module_repr() did not exist.
+ class CustomLoaderWithRaisingRepr:
+ @classmethod
+ def module_repr(cls, module):
+ return repr(1/0)
+
+ test_module.__loader__ = CustomLoaderWithRaisingRepr
+ mod_repr = repr(test_module)
+
+ # The module has no __file__ attribute, so the repr should use
+ # the loader and name
+ loader_repr = repr(test_module.__loader__)
+ expected_repr = "<module 'test_module' ({})>".format(loader_repr)
+ assert mod_repr == expected_repr
+
+ def test_repr_with_raising_loader_and___file__(self):
+ import sys
+ test_module = type(sys)("test_module", "doc")
+ test_module.__file__ = "/fake_dir/test_module.py"
+ class CustomLoaderWithRaisingRepr:
+ """Operates just like the builtin importer, but implements a
+ module_repr method that raises an exception."""
+ @classmethod
+ def module_repr(cls, module):
+ return repr(1/0)
+
+ test_module.__loader__ = CustomLoaderWithRaisingRepr
+
+ # If the module has an __file__ attribute, this is used as part
+ # of the module's repr.
+ # (If we have a loader that doesn't correctly implement module_repr,
+ # if we have a path, we always just use name and path.
+ expected_repr = "<module 'test_module' from '/fake_dir/test_module.py'>"
+ assert repr(test_module) == expected_repr
+
+ def test_repr_with_missing_name(self):
+ import sys
+ test_module = type(sys)("test_module", "doc")
+ del test_module.__name__
+ mod_repr = repr(test_module)
+ assert mod_repr == "<module '?'>"
+
def test_dir(self):
import sys
items = sys.__dir__()
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
@@ -86,7 +86,11 @@
return
# force_init is needed to make reload actually reload instead of just
# using the already-present module in sys.modules.
- return space.getbuiltinmodule(name, force_init=True, reuse=False)
+
+ # If the module is already in sys.modules, it must be a reload, so
+ # we want to reuse (and reinitialize) the existing module object
+ reuse = space.finditem(space.sys.get('modules'), w_name) is not None
+ return space.getbuiltinmodule(name, force_init=True, reuse=reuse)
def init_frozen(space, w_name):
return None
More information about the pypy-commit
mailing list