summaryrefslogtreecommitdiff
path: root/astroid/modutils.py
diff options
context:
space:
mode:
authorClaudiu Popa <cpopa@cloudbasesolutions.com>2015-07-02 16:41:49 +0300
committerClaudiu Popa <cpopa@cloudbasesolutions.com>2015-07-02 16:41:49 +0300
commitebeb9ef360ababc9b7b5b46488fa1bdd80bb4e61 (patch)
treeec1181efd022cd1498333bddffdb5debf6086e2f /astroid/modutils.py
parent0ef9c937732cc29fdf063f896a090ec10287dea3 (diff)
downloadastroid-git-ebeb9ef360ababc9b7b5b46488fa1bdd80bb4e61.tar.gz
Update modutils.py from logilab.common and add support for namespace packages
This patch is mostly a backport from logilab.common. The addition is the support for pkg_resources.declare_namespace, which created a good deal of problems so far with regard to virtualenvs.
Diffstat (limited to 'astroid/modutils.py')
-rw-r--r--astroid/modutils.py43
1 files changed, 30 insertions, 13 deletions
diff --git a/astroid/modutils.py b/astroid/modutils.py
index be8580ad..bd24d26c 100644
--- a/astroid/modutils.py
+++ b/astroid/modutils.py
@@ -85,8 +85,7 @@ except DistutilsPlatformError:
EXT_LIB_DIR = get_python_lib()
IS_JYTHON = platform.python_implementation() == 'Jython'
-BUILTIN_MODULES = dict(zip(sys.builtin_module_names,
- [1]*len(sys.builtin_module_names)))
+BUILTIN_MODULES = dict.fromkeys(sys.builtin_module_names, True)
class NoSourceFile(Exception):
@@ -127,7 +126,7 @@ def _cache_normalize_path(path):
result = _NORM_PATH_CACHE[path] = _normalize_path(path)
return result
-def load_module_from_name(dotted_name, path=None, use_sys=1):
+def load_module_from_name(dotted_name, path=None, use_sys=True):
"""Load a Python module from its name.
:type dotted_name: str
@@ -199,14 +198,16 @@ def load_module_from_modpath(parts, path=None, use_sys=1):
if prevmodule:
setattr(prevmodule, part, module)
_file = getattr(module, '__file__', '')
+ prevmodule = module
+ if not _file and _is_namespace(curname):
+ continue
if not _file and len(modpath) != len(parts):
raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]))
- path = [os.path.dirname(_file)]
- prevmodule = module
+ path = [os.path.dirname(_file)]
return module
-def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None):
+def load_module_from_file(filepath, path=None, use_sys=True, extrapath=None):
"""Load a Python module from it's path.
:type filepath: str
@@ -234,9 +235,11 @@ def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None):
def _check_init(path, mod_path):
"""check there are some __init__.py all along the way"""
+ modpath = []
for part in mod_path:
+ modpath.append(part)
path = os.path.join(path, part)
- if not _has_init(path):
+ if not _is_namespace('.'.join(modpath)) and not _has_init(path):
return False
return True
@@ -482,7 +485,8 @@ def is_standard_module(modname, std_path=None):
# modules which are not living in a file are considered standard
# (sys and __builtin__ for instance)
if filename is None:
- return True
+ # we assume there are no namespaces in stdlib
+ return not _is_namespace(modname)
filename = _normalize_path(filename)
if filename.startswith(_cache_normalize_path(EXT_LIB_DIR)):
return False
@@ -567,6 +571,16 @@ def _search_zip(modpath, pic):
filepath)
raise ImportError('No module named %s' % '.'.join(modpath))
+try:
+ import pkg_resources
+except ImportError:
+ pkg_resources = None
+
+
+def _is_namespace(modname):
+ return (pkg_resources is not None
+ and modname in pkg_resources._namespace_packages)
+
def _module_file(modpath, path=None):
"""get a module type / file path
@@ -599,14 +613,13 @@ def _module_file(modpath, path=None):
except AttributeError:
checkeggs = False
# pkg_resources support (aka setuptools namespace packages)
- if (pkg_resources is not None
- and modpath[0] in pkg_resources._namespace_packages
- and modpath[0] in sys.modules
- and len(modpath) > 1):
+ if (_is_namespace(modpath[0]) and modpath[0] in sys.modules):
# setuptools has added into sys.modules a module object with proper
# __path__, get back information from there
module = sys.modules[modpath.pop(0)]
path = module.__path__
+ if not modpath:
+ return imp.C_BUILTIN, None
imported = []
while modpath:
modname = modpath[0]
@@ -659,7 +672,11 @@ def _module_file(modpath, path=None):
except IOError:
path = [mp_filename]
else:
- if b'pkgutil' in data and b'extend_path' in data:
+ extend_path = b'pkgutil' in data and b'extend_path' in data
+ declare_namespace = (
+ b"pkg_resources" in data
+ and b"declare_namespace(__name__)" in data)
+ if extend_path or declare_namespace:
# extend_path is called, search sys.path for module/packages
# of this name see pkgutil.extend_path documentation
path = [os.path.join(p, *imported) for p in sys.path