Merge remote-tracking branch 'origin/dmw'

* origin/dmw:
  issue #310: fix test failures, teach old import method new tricks
  master: handle crazy non-modules in sys.modules again; closes #310.
  issue #349: update Changelog.
  docs: add unused import to Changelog.
issue510
David Wilson 6 years ago
commit 9cd94e7327

@ -246,6 +246,15 @@ Core Library
causing Mitogen to install itself at the end of the importer chain rather
than the front.
* `#310 <https://github.com/dw/mitogen/issues/310>`_: support has returned for
trying to figure out the real source of non-module objects installed in
:data:`sys.modules`, so they can be imported. This is needed to handle syntax
sugar used by packages like :mod:`plumbum`.
* `#349 <https://github.com/dw/mitogen/issues/349>`_: an incorrect format
string could cause large stack traces when attempting to import built-in
modules on Python 3.
* `#387 <https://github.com/dw/mitogen/issues/387>`_,
`#413 <https://github.com/dw/mitogen/issues/413>`_: dead messages include an
optional reason in their body. This is used to cause
@ -367,6 +376,10 @@ Core Library
raised by the import hook were updated to include probable reasons for
a failure.
* `57b652ed <https://github.com/dw/mitogen/commit/57b652ed>`_: a stray import
meant an extra roundtrip and ~20KiB of data was wasted for any context that
imported :mod:`mitogen.parent`.
Thanks!
~~~~~~~
@ -379,6 +392,7 @@ bug reports, testing, features and fixes in this release contributed by
`Duane Zamrok <https://github.com/dewthefifth>`_,
`Eric Chang <https://github.com/changchichung>`_,
`Guy Knights <https://github.com/knightsg>`_,
`Jesse London <https://github.com/jesteria>`_,
`Jiří Vávra <https://github.com/Houbovo>`_,
`Jonathan Rosser <https://github.com/jrosser>`_,
`Johan Beisser <https://github.com/jbeisser>`_,
@ -386,6 +400,7 @@ bug reports, testing, features and fixes in this release contributed by
`Mehdi <https://github.com/mehdisat7>`_,
`Michael DeHaan <https://github.com/mpdehaan>`_,
`Mohammed Naser <https://github.com/mnaser/>`_,
`Peter V. Saveliev <https://github.com/svinota/>`_,
`Stéphane <https://github.com/sboisson/>`_,
`@whky <https://github.com/whky/>`_,
`@syntonym <https://github.com/syntonym/>`_,

@ -453,8 +453,47 @@ class ModuleFinder(object):
return path, source, is_pkg
def _get_module_via_parent_enumeration(self, fullname):
"""
Attempt to fetch source code by examining the module's (hopefully less
insane) parent package. Required for older versions of
ansible.compat.six and plumbum.colors.
"""
if fullname not in sys.modules:
# Don't attempt this unless a module really exists in sys.modules,
# else we could return junk.
return
pkgname, _, modname = fullname.rpartition('.')
pkg = sys.modules.get(pkgname)
if pkg is None or not hasattr(pkg, '__file__'):
return
pkg_path = os.path.dirname(pkg.__file__)
try:
fp, path, ext = imp.find_module(modname, [pkg_path])
try:
path = self._py_filename(path)
if not path:
fp.close()
return
source = fp.read()
finally:
fp.close()
if isinstance(source, mitogen.core.UnicodeType):
# get_source() returns "string" according to PEP-302, which was
# reinterpreted for Python 3 to mean a Unicode string.
source = source.encode('utf-8')
return path, source, False
except ImportError:
e = sys.exc_info()[1]
LOG.debug('imp.find_module(%r, %r) -> %s', modname, [pkg_path], e)
get_module_methods = [_get_module_via_pkgutil,
_get_module_via_sys_modules]
_get_module_via_sys_modules,
_get_module_via_parent_enumeration]
def get_module_source(self, fullname):
"""Given the name of a loaded module `fullname`, attempt to find its
@ -471,6 +510,7 @@ class ModuleFinder(object):
for method in self.get_module_methods:
tup = method(self, fullname)
if tup:
#LOG.debug('%r returned %r', method, tup)
break
else:
tup = None, None, None

@ -0,0 +1,15 @@
# coding=utf-8
import sys
# £
class EvilObject(object):
"""
Wild cackles! I have come to confuse perplex your importer with rainbows!
"""
sys.modules[__name__] = EvilObject()

@ -105,6 +105,39 @@ class GetModuleViaSysModulesTest(testlib.TestCase):
self.assertIsNone(tup)
class GetModuleViaParentEnumerationTest(testlib.TestCase):
klass = mitogen.master.ModuleFinder
def call(self, fullname):
return self.klass()._get_module_via_parent_enumeration(fullname)
def test_main_fails(self):
import __main__
self.assertIsNone(self.call('__main__'))
def test_dylib_fails(self):
# _socket comes from a .so
import _socket
tup = self.call('_socket')
self.assertIsNone(tup)
def test_builtin_fails(self):
# sys is built-in
tup = self.call('sys')
self.assertIsNone(tup)
def test_plumbum_colors_like_pkg_succeeds(self):
# plumbum has been eating too many rainbow-colored pills
import pkg_like_plumbum.colors
path, src, is_pkg = self.call('pkg_like_plumbum.colors')
self.assertEquals(path,
testlib.data_path('pkg_like_plumbum/colors.py'))
s = open(testlib.data_path('pkg_like_plumbum/colors.py'), 'rb').read()
self.assertEquals(src, s)
self.assertFalse(is_pkg)
class ResolveRelPathTest(testlib.TestCase):
klass = mitogen.master.ModuleFinder

Loading…
Cancel
Save