summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémi Cardona <remi.cardona@logilab.fr>2015-05-28 15:44:02 +0200
committerRémi Cardona <remi.cardona@logilab.fr>2015-05-28 15:44:02 +0200
commita51bcc2dedf7b886ba9ebeadeb6357eb6f7bcfdf (patch)
tree801f8d9f8d760b544229598159e0c05a6dc12b6c
parent1323bb0ec9ce09728b23126d017eaab5e2604d7f (diff)
downloadlogilab-common-a51bcc2dedf7b886ba9ebeadeb6357eb6f7bcfdf.tar.gz
[modutils] Add basic support for namespace packages
Nested namespaces (zope is a big fan) probably don't work. Closes #122443.
-rw-r--r--logilab/common/modutils.py25
1 files changed, 17 insertions, 8 deletions
diff --git a/logilab/common/modutils.py b/logilab/common/modutils.py
index 158c09b..3bcda8a 100644
--- a/logilab/common/modutils.py
+++ b/logilab/common/modutils.py
@@ -170,10 +170,12 @@ def load_module_from_modpath(parts, path=None, use_sys=True):
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 = [dirname( _file )]
- prevmodule = module
return module
@@ -205,9 +207,11 @@ def load_module_from_file(filepath, path=None, use_sys=True, 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 = join(path, part)
- if not _has_init(path):
+ if not _is_namespace('.'.join(modpath)) and not _has_init(path):
return False
return True
@@ -476,7 +480,6 @@ def is_python_source(filename):
return splitext(filename)[1][1:] in PY_SOURCE_EXTS
-
def is_standard_module(modname, std_path=(STD_LIB_DIR,)):
"""try to guess if a module is a standard python module (by default,
see `std_path` parameter's description)
@@ -504,7 +507,8 @@ def is_standard_module(modname, std_path=(STD_LIB_DIR,)):
# 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 = abspath(filename)
if filename.startswith(EXT_LIB_DIR):
return False
@@ -585,6 +589,12 @@ try:
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
@@ -616,14 +626,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 C_BUILTIN, None
imported = []
while modpath:
modname = modpath[0]