diff options
author | Neil Schemenauer <nascheme@enme.ucalgary.ca> | 2009-10-14 19:23:53 (GMT) |
---|---|---|
committer | Neil Schemenauer <nascheme@enme.ucalgary.ca> | 2009-10-14 19:23:53 (GMT) |
commit | e6039f09781bee1e37c8a9fb6436b6df5b8d16b8 (patch) | |
tree | ce18a68c1befc14213c7acbb09bced70043b3a89 /Lib/ihooks.py | |
parent | 04437ebadd8f3c086ecc920d98c4868ae1d27a35 (diff) | |
download | cpython-e6039f09781bee1e37c8a9fb6436b6df5b8d16b8.zip cpython-e6039f09781bee1e37c8a9fb6436b6df5b8d16b8.tar.gz cpython-e6039f09781bee1e37c8a9fb6436b6df5b8d16b8.tar.bz2 |
Add support to the ihooks module for relative imports.
Diffstat (limited to 'Lib/ihooks.py')
-rw-r--r-- | Lib/ihooks.py | 74 |
1 files changed, 53 insertions, 21 deletions
diff --git a/Lib/ihooks.py b/Lib/ihooks.py index 86b0f65..8761dac 100644 --- a/Lib/ihooks.py +++ b/Lib/ihooks.py @@ -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(). """ -from warnings import warnpy3k +from warnings import warnpy3k, warn warnpy3k("the ihooks module has been removed in Python 3.0", stacklevel=2) del warnpy3k @@ -401,8 +401,9 @@ class ModuleImporter(BasicModuleImporter): """A module importer that supports packages.""" - def import_module(self, name, globals=None, locals=None, fromlist=None): - parent = self.determine_parent(globals) + def import_module(self, name, globals=None, locals=None, fromlist=None, + level=-1): + parent = self.determine_parent(globals, level) q, tail = self.find_head_package(parent, str(name)) m = self.load_tail(q, tail) if not fromlist: @@ -411,21 +412,50 @@ class ModuleImporter(BasicModuleImporter): self.ensure_fromlist(m, fromlist) return m - def determine_parent(self, globals): - if not globals or not "__name__" in globals: + def determine_parent(self, globals, level=-1): + if not globals or not level: return None - pname = globals['__name__'] - if "__path__" in globals: - parent = self.modules[pname] - assert globals is parent.__dict__ - return parent - if '.' in pname: - i = pname.rfind('.') - pname = pname[:i] - parent = self.modules[pname] - assert parent.__name__ == pname - return parent - return None + pkgname = globals.get('__package__') + if pkgname is not None: + if not pkgname and level > 0: + raise ValueError, 'Attempted relative import in non-package' + else: + # __package__ not set, figure it out and set it + modname = globals.get('__name__') + if modname is None: + return None + if "__path__" in globals: + # __path__ is set so modname is already the package name + 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): if '.' in name: @@ -446,7 +476,7 @@ class ModuleImporter(BasicModuleImporter): parent = None q = self.import_it(head, qname, parent) if q: return q, tail - raise ImportError, "No module named " + qname + raise ImportError, "No module named '%s'" % qname def load_tail(self, q, tail): m = q @@ -457,7 +487,7 @@ class ModuleImporter(BasicModuleImporter): mname = "%s.%s" % (m.__name__, head) m = self.import_it(head, mname, m) if not m: - raise ImportError, "No module named " + mname + raise ImportError, "No module named '%s'" % mname return m def ensure_fromlist(self, m, fromlist, recursive=0): @@ -475,11 +505,13 @@ class ModuleImporter(BasicModuleImporter): subname = "%s.%s" % (m.__name__, sub) submod = self.import_it(sub, subname, m) 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): 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: try: return self.modules[fqname] |