Kaydet (Commit) e6039f09 authored tarafından Neil Schemenauer's avatar Neil Schemenauer

Add support to the ihooks module for relative imports.

üst 04437eba
...@@ -49,7 +49,7 @@ by the way the __import__ hook is used by the Python interpreter.) It ...@@ -49,7 +49,7 @@ by the way the __import__ hook is used by the Python interpreter.) It
would also do wise to install a different version of reload(). would also do wise to install a different version of reload().
""" """
from warnings import warnpy3k from warnings import warnpy3k, warn
warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2) warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2)
del warnpy3k del warnpy3k
...@@ -401,8 +401,9 @@ class ModuleImporter(BasicModuleImporter): ...@@ -401,8 +401,9 @@ class ModuleImporter(BasicModuleImporter):
"""A module importer that supports packages.""" """A module importer that supports packages."""
def import_module(self, name, globals=None, locals=None, fromlist=None): def import_module(self, name, globals=None, locals=None, fromlist=None,
parent = self.determine_parent(globals) level=-1):
parent = self.determine_parent(globals, level)
q, tail = self.find_head_package(parent, str(name)) q, tail = self.find_head_package(parent, str(name))
m = self.load_tail(q, tail) m = self.load_tail(q, tail)
if not fromlist: if not fromlist:
...@@ -411,21 +412,50 @@ class ModuleImporter(BasicModuleImporter): ...@@ -411,21 +412,50 @@ class ModuleImporter(BasicModuleImporter):
self.ensure_fromlist(m, fromlist) self.ensure_fromlist(m, fromlist)
return m return m
def determine_parent(self, globals): def determine_parent(self, globals, level=-1):
if not globals or not "__name__" in globals: if not globals or not level:
return None return None
pname = globals['__name__'] pkgname = globals.get('__package__')
if "__path__" in globals: if pkgname is not None:
parent = self.modules[pname] if not pkgname and level > 0:
assert globals is parent.__dict__ raise ValueError, 'Attempted relative import in non-package'
return parent else:
if '.' in pname: # __package__ not set, figure it out and set it
i = pname.rfind('.') modname = globals.get('__name__')
pname = pname[:i] if modname is None:
parent = self.modules[pname] return None
assert parent.__name__ == pname if "__path__" in globals:
return parent # __path__ is set so modname is already the package name
return None pkgname = modname
else:
# normal module, work out package name if any
if '.' not in modname:
if level > 0:
raise ValueError, ('Attempted relative import in '
'non-package')
globals['__package__'] = None
return None
pkgname = modname.rpartition('.')[0]
globals['__package__'] = pkgname
if level > 0:
dot = len(pkgname)
for x in range(level, 1, -1):
try:
dot = pkgname.rindex('.', 0, dot)
except ValueError:
raise ValueError('attempted relative import beyond '
'top-level package')
pkgname = pkgname[:dot]
try:
return sys.modules[pkgname]
except KeyError:
if level < 1:
warn("Parent module '%s' not found while handling "
"absolute import" % pkgname, RuntimeWarning, 1)
return None
else:
raise SystemError, ("Parent module '%s' not loaded, cannot "
"perform relative import" % pkgname)
def find_head_package(self, parent, name): def find_head_package(self, parent, name):
if '.' in name: if '.' in name:
...@@ -446,7 +476,7 @@ class ModuleImporter(BasicModuleImporter): ...@@ -446,7 +476,7 @@ class ModuleImporter(BasicModuleImporter):
parent = None parent = None
q = self.import_it(head, qname, parent) q = self.import_it(head, qname, parent)
if q: return q, tail if q: return q, tail
raise ImportError, "No module named " + qname raise ImportError, "No module named '%s'" % qname
def load_tail(self, q, tail): def load_tail(self, q, tail):
m = q m = q
...@@ -457,7 +487,7 @@ class ModuleImporter(BasicModuleImporter): ...@@ -457,7 +487,7 @@ class ModuleImporter(BasicModuleImporter):
mname = "%s.%s" % (m.__name__, head) mname = "%s.%s" % (m.__name__, head)
m = self.import_it(head, mname, m) m = self.import_it(head, mname, m)
if not m: if not m:
raise ImportError, "No module named " + mname raise ImportError, "No module named '%s'" % mname
return m return m
def ensure_fromlist(self, m, fromlist, recursive=0): def ensure_fromlist(self, m, fromlist, recursive=0):
...@@ -475,11 +505,13 @@ class ModuleImporter(BasicModuleImporter): ...@@ -475,11 +505,13 @@ class ModuleImporter(BasicModuleImporter):
subname = "%s.%s" % (m.__name__, sub) subname = "%s.%s" % (m.__name__, sub)
submod = self.import_it(sub, subname, m) submod = self.import_it(sub, subname, m)
if not submod: if not submod:
raise ImportError, "No module named " + subname raise ImportError, "No module named '%s'" % subname
def import_it(self, partname, fqname, parent, force_load=0): def import_it(self, partname, fqname, parent, force_load=0):
if not partname: if not partname:
raise ValueError, "Empty module name" # completely empty module name should only happen in
# 'from . import' or __import__("")
return parent
if not force_load: if not force_load:
try: try:
return self.modules[fqname] return self.modules[fqname]
......
...@@ -405,6 +405,8 @@ Core and Builtins ...@@ -405,6 +405,8 @@ Core and Builtins
Library Library
------- -------
- Add support to the `ihooks` module for relative imports.
- Issue #6894: Fixed the issue urllib2 doesn't respect "no_proxy" environment - Issue #6894: Fixed the issue urllib2 doesn't respect "no_proxy" environment
- Issue #7086: Added TCP support to SysLogHandler, and tidied up some - Issue #7086: Added TCP support to SysLogHandler, and tidied up some
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment