[Python-checkins] r52960 - sandbox/trunk/import_in_py/importer.py sandbox/trunk/import_in_py/test_importer.py
brett.cannon
python-checkins at python.org
Thu Dec 7 22:32:33 CET 2006
Author: brett.cannon
Date: Thu Dec 7 22:32:32 2006
New Revision: 52960
Modified:
sandbox/trunk/import_in_py/importer.py
sandbox/trunk/import_in_py/test_importer.py
Log:
Add proper support for ``from . import ...``. Required tweaking allowing the
empty string for a module name and relative name resolution.
Also beefed up tests for absolute import support when doing a relative name.
Modified: sandbox/trunk/import_in_py/importer.py
==============================================================================
--- sandbox/trunk/import_in_py/importer.py (original)
+++ sandbox/trunk/import_in_py/importer.py Thu Dec 7 22:32:32 2006
@@ -713,14 +713,24 @@
def resolve_name(self, name, caller_name, caller_is_package, level):
"""Return the absolute name of the module specified by 'name' based on
where the module is being imported and the requested change in dotted
- name level."""
+ name level.
+
+ Absolute imports always take the form of ``from <name> import ...``.
+ This means that the number of leading dots in '<name>' becomes 'level'
+ and the rest of '<name>' becomes 'name'. This leads to the possibility
+ that 'name' is the empty string, representing the current package.
+
+ """
if caller_is_package:
level -= 1
if caller_name.count('.') < level:
raise ImportError("attempted relative import beyond top-level "
"pacakge")
base_name = caller_name.rsplit('.', level)[0]
- return base_name + '.' + name
+ if name:
+ return base_name + '.' + name
+ else:
+ return base_name
def return_module(self, absolute_name, relative_name, fromlist):
"""Return the proper module based on what module was requested (and its
@@ -810,8 +820,7 @@
(e.g. has a value of 2 for ``from .. import foo``).
"""
- if not name:
- #print repr(name), globals['__name__'], fromlist, level
+ if not name and level < 1:
raise ValueError("Empty module name")
is_pkg = True if '__path__' in globals else False
caller_name = globals.get('__name__')
@@ -846,7 +855,7 @@
else:
imported_name = name
self.import_full_module(name)
- relative_name = '' if imported_name != name else name
- return self.return_module(imported_name, name, fromlist)
+ relative_name = '' if imported_name == name else name
+ return self.return_module(imported_name, relative_name, fromlist)
finally:
imp.release_lock()
Modified: sandbox/trunk/import_in_py/test_importer.py
==============================================================================
--- sandbox/trunk/import_in_py/test_importer.py (original)
+++ sandbox/trunk/import_in_py/test_importer.py Thu Dec 7 22:32:32 2006
@@ -785,16 +785,18 @@
False)
self.failUnlessEqual(resolved_name, self.full_child_name)
- def test_relative_import_in_package(self):
+ def test_relative_import_in_package_for_a_module(self):
# Trying to import a single level within a package within it's __init__
# module should stay within the package.
+ # ``from .child_name import ...`` in a package.
resolved_name = self.importer.resolve_name(self.child_name,
self.parent_name, True, 1)
self.failUnlessEqual(resolved_name, self.full_child_name)
- def test_relative_import_in_module(self):
+ def test_relative_import_in_module_for_a_module(self):
# Importing from within a module in a package should try to import from
# within the same directory as the module requesting the import.
+ # ``from .child_name import ...`` in a package module.
calling_from = self.parent_name + '.' + '<calling from>'
resolved_name = self.importer.resolve_name(self.child_name,
calling_from, False, 1)
@@ -812,12 +814,14 @@
def test_attempt_to_escape_out_of_package_init(self):
# Attempting to go too high out of a package in its __init__ file
# should raise ImportError.
+ # ``from ..child_name import ...`` in a top-level package.
self.failUnlessRaises(ImportError, self.importer.resolve_name,
self.child_name, self.parent_name, True, 2)
def test_attempt_to_escape_out_of_package_module(self):
# Attempting to go too high in the package from a module should raise
# ImportError.
+ # ``from ..child_name import ...`` in a top-level package module.
calling_from = self.parent_name + '.' + '<calling from>'
self.failUnlessRaises(ImportError, self.importer.resolve_name,
self.child_name, calling_from, False, 2)
@@ -825,8 +829,21 @@
def test_relative_import_in_top_level(self):
# Attempting a relative import in a top-level location should raise
# ImportError.
+ # ``from .child_name import ...`` outside of a package.
self.failUnlessRaises(ImportError, self.importer.resolve_name,
self.child_name, self.parent_name, False, 1)
+
+ def test_relative_import_in_package_init(self):
+ # ``from . import ...`` in a package.
+ resolved_name = self.importer.resolve_name('', self.parent_name, True,
+ 1)
+ self.failUnlessEqual(resolved_name, self.parent_name)
+
+ def test_relative_import_in_package_module(self):
+ # ``from . import ...`` in a package module.
+ resolved_name = self.importer.resolve_name('', self.full_child_name,
+ False, 1)
+ self.failUnlessEqual(resolved_name, self.parent_name)
def test_relative_import_redirection(self):
# Having a relative module name resolve to a name that has a value of
@@ -1345,18 +1362,37 @@
def test_relative_import_in_package_init(self):
# Importing a module with a relative name in a package's __init__ file
# should work.
- # XXX
- package_globals = {'__name__':self.pkg_name, '__path__':self.pkg_path}
- module = self.import_(self.module_name, package_globals, level=1)
- self.verify_package(module, self.pkg_module_name)
+ # ``from . import module`` for 'package'.
+ caller_globals = {'__name__':self.pkg_name, '__path__':[self.pkg_path]}
+ module = self.import_('', caller_globals, fromlist=[self.module_name],
+ level=1)
+ self.verify_package(module, self.pkg_name)
def test_relative_import_in_package(self):
# Importing a module with a relative name in another module should
# work.
+ # ``from . import module`` for 'package.module'.
+ caller_globals = {'__name__':self.pkg_module_name}
+ module = self.import_('', caller_globals, fromlist=[self.module_name],
+ level=1)
+ self.verify_package(module, self.pkg_name)
+
+ def test_relative_import_in_subpackages(self):
+ # ``from .. import module`` in 'package.subpackage'.
+ caller_globals = {'__name__':self.sub_pkg_name,
+ '__path__':[self.sub_pkg_path]}
+ module = self.import_('', caller_globals, fromlist=[self.module_name],
+ level=2)
+ self.verify_package(module, self.pkg_name)
+
+ def test_relative_import_of_package(self):
+ # ``from ..subpackage import module`` in 'package.subpackage'.
# XXX
- module_globals = {'__name__':self.pkg_name + '.another_module'}
- module = self.import_(self.module_name, module_globals, level=1)
- self.verify_package(module, self.pkg_module_name)
+ caller_globals = {'__name__':self.sub_pkg_name,
+ '__path__':[self.sub_pkg_path]}
+ module = self.import_(self.sub_pkg_tail_name, caller_globals,
+ fromlist=[self.module_name], level=2)
+ self.verify_package(module, self.sub_pkg_name)
def test_relative_import_return(self):
# When importing from a relative name, the module up to the first dot
More information about the Python-checkins
mailing list