diff options
8 files changed, 47 insertions, 4 deletions
diff --git a/astroid/modutils.py b/astroid/modutils.py index 77081b5b..3334e1e3 100644 --- a/astroid/modutils.py +++ b/astroid/modutils.py @@ -742,6 +742,22 @@ class ImpFinder(Finder): return path +class DynamicImpFinder(ImpFinder): + + def find_module(self, modname, module_parts, processed, submodule_path): + if _is_namespace(modname) and modname in sys.modules: + submodule_path = sys.modules[modname].__path__ + return ModuleSpec(name=modname, location='', + origin='namespace', + type=ModuleType.PY_NAMESPACE, + submodule_search_locations=submodule_path) + + + def contribute_to_path(self, spec, processed): + return spec.submodule_search_locations + + + class ZipFinder(Finder): def __init__(self, path): @@ -776,12 +792,17 @@ class PEP420SpecFinder(Finder): return spec.submodule_search_locations return None +_SPEC_FINDERS = ( + ImpFinder, + ZipFinder, +) +if _HAS_MACHINERY and sys.version_info[:2] > (3, 3): + _SPEC_FINDERS += (PEP420SpecFinder, ) +_SPEC_FINDERS += (DynamicImpFinder, ) -def _find_spec_with_path(search_path, modname, module_parts, processed, submodule_path): - finders = [finder(search_path) for finder in (ImpFinder, ZipFinder)] - if _HAS_MACHINERY and sys.version_info[:2] > (3, 3): - finders.append(PEP420SpecFinder(search_path)) +def _find_spec_with_path(search_path, modname, module_parts, processed, submodule_path): + finders = [finder(search_path) for finder in _SPEC_FINDERS] for finder in finders: spec = finder.find_module(modname, module_parts, processed, submodule_path) if spec is None: diff --git a/astroid/tests/testdata/python2/data/foogle/fax/__init__.py b/astroid/tests/testdata/python2/data/foogle/fax/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/astroid/tests/testdata/python2/data/foogle/fax/__init__.py diff --git a/astroid/tests/testdata/python2/data/foogle/fax/a.py b/astroid/tests/testdata/python2/data/foogle/fax/a.py new file mode 100644 index 00000000..3d2b4b14 --- /dev/null +++ b/astroid/tests/testdata/python2/data/foogle/fax/a.py @@ -0,0 +1 @@ +x = 1
\ No newline at end of file diff --git a/astroid/tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth b/astroid/tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth new file mode 100644 index 00000000..d3cb4591 --- /dev/null +++ b/astroid/tests/testdata/python2/data/foogle_fax-0.12.5-py2.7-nspkg.pth @@ -0,0 +1 @@ +import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('foogle',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('foogle', types.ModuleType('foogle'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/astroid/tests/testdata/python3/data/foogle/fax/__init__.py b/astroid/tests/testdata/python3/data/foogle/fax/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/astroid/tests/testdata/python3/data/foogle/fax/__init__.py diff --git a/astroid/tests/testdata/python3/data/foogle/fax/a.py b/astroid/tests/testdata/python3/data/foogle/fax/a.py new file mode 100644 index 00000000..3d2b4b14 --- /dev/null +++ b/astroid/tests/testdata/python3/data/foogle/fax/a.py @@ -0,0 +1 @@ +x = 1
\ No newline at end of file diff --git a/astroid/tests/testdata/python3/data/foogle_fax-0.12.5-py2.7-nspkg.pth b/astroid/tests/testdata/python3/data/foogle_fax-0.12.5-py2.7-nspkg.pth new file mode 100644 index 00000000..d3cb4591 --- /dev/null +++ b/astroid/tests/testdata/python3/data/foogle_fax-0.12.5-py2.7-nspkg.pth @@ -0,0 +1 @@ +import sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('foogle',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('foogle', types.ModuleType('foogle'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/astroid/tests/unittest_manager.py b/astroid/tests/unittest_manager.py index 34c9ef8f..3b145853 100644 --- a/astroid/tests/unittest_manager.py +++ b/astroid/tests/unittest_manager.py @@ -7,9 +7,11 @@ import os import platform +import site import sys import unittest +import pkg_resources import six import astroid @@ -120,6 +122,22 @@ class AstroidManagerTest(resources.SysPathSetup, for _ in range(2): sys.path.pop(0) + def test_namespace_package_pth_support(self): + directory = os.path.join(resources.DATA_DIR, 'data') + pth = 'foogle_fax-0.12.5-py2.7-nspkg.pth' + site.addpackage(directory, pth, []) + pkg_resources._namespace_packages['foogle'] = [] + try: + module = self.manager.ast_from_module_name('foogle.fax') + submodule = next(module.igetattr('a')) + value = next(submodule.igetattr('x')) + self.assertIsInstance(value, astroid.Const) + with self.assertRaises(exceptions.AstroidImportError): + self.manager.ast_from_module_name('foogle.moogle') + finally: + del pkg_resources._namespace_packages['foogle'] + sys.modules.pop('foogle') + def _test_ast_from_zip(self, archive): origpath = sys.path[:] sys.modules.pop('mypypa', None) |