[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

AltStyle によって変換されたページ (->オリジナル) /