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 causing Mitogen to install itself at the end of the importer chain rather
than the front. 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>`_, * `#387 <https://github.com/dw/mitogen/issues/387>`_,
`#413 <https://github.com/dw/mitogen/issues/413>`_: dead messages include an `#413 <https://github.com/dw/mitogen/issues/413>`_: dead messages include an
optional reason in their body. This is used to cause 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 raised by the import hook were updated to include probable reasons for
a failure. 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! Thanks!
~~~~~~~ ~~~~~~~
@ -379,6 +392,7 @@ bug reports, testing, features and fixes in this release contributed by
`Duane Zamrok <https://github.com/dewthefifth>`_, `Duane Zamrok <https://github.com/dewthefifth>`_,
`Eric Chang <https://github.com/changchichung>`_, `Eric Chang <https://github.com/changchichung>`_,
`Guy Knights <https://github.com/knightsg>`_, `Guy Knights <https://github.com/knightsg>`_,
`Jesse London <https://github.com/jesteria>`_,
`Jiří Vávra <https://github.com/Houbovo>`_, `Jiří Vávra <https://github.com/Houbovo>`_,
`Jonathan Rosser <https://github.com/jrosser>`_, `Jonathan Rosser <https://github.com/jrosser>`_,
`Johan Beisser <https://github.com/jbeisser>`_, `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>`_, `Mehdi <https://github.com/mehdisat7>`_,
`Michael DeHaan <https://github.com/mpdehaan>`_, `Michael DeHaan <https://github.com/mpdehaan>`_,
`Mohammed Naser <https://github.com/mnaser/>`_, `Mohammed Naser <https://github.com/mnaser/>`_,
`Peter V. Saveliev <https://github.com/svinota/>`_,
`Stéphane <https://github.com/sboisson/>`_, `Stéphane <https://github.com/sboisson/>`_,
`@whky <https://github.com/whky/>`_, `@whky <https://github.com/whky/>`_,
`@syntonym <https://github.com/syntonym/>`_, `@syntonym <https://github.com/syntonym/>`_,

@ -453,8 +453,47 @@ class ModuleFinder(object):
return path, source, is_pkg 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_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): def get_module_source(self, fullname):
"""Given the name of a loaded module `fullname`, attempt to find its """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: for method in self.get_module_methods:
tup = method(self, fullname) tup = method(self, fullname)
if tup: if tup:
#LOG.debug('%r returned %r', method, tup)
break break
else: else:
tup = None, None, None 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) 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): class ResolveRelPathTest(testlib.TestCase):
klass = mitogen.master.ModuleFinder klass = mitogen.master.ModuleFinder

Loading…
Cancel
Save