[Python-checkins] r52744 - sandbox/trunk/import_in_py/importer.py sandbox/trunk/import_in_py/test_importer.py

brett.cannon python-checkins at python.org
Wed Nov 15 00:38:57 CET 2006


Author: brett.cannon
Date: Wed Nov 15 00:38:56 2006
New Revision: 52744

Modified:
   sandbox/trunk/import_in_py/importer.py
   sandbox/trunk/import_in_py/test_importer.py
Log:
Add support for Py3K relative imports.

At this point one still needs to go through and make sure all edge cases are
implemented.  After that everything should be done to be semantically complete
short of having a way to read and write marshalled longs.


Modified: sandbox/trunk/import_in_py/importer.py
==============================================================================
--- sandbox/trunk/import_in_py/importer.py	(original)
+++ sandbox/trunk/import_in_py/importer.py	Wed Nov 15 00:38:56 2006
@@ -71,13 +71,6 @@
   still have the full name of the module passed in)
   [pep 302 and introspection(Python/import.c:1278)].
   
-XXX Need to Implement
----------------------
-#. Relative imports.
-    + Py3K semantics.
-    + 2.x semantics.
-    + From within a package's __init__ module.
-
 
 Things to be exposed at the Python level
 ========================================
@@ -679,6 +672,18 @@
                 base_name = caller_name.rsplit('.', 1)[0]
         return base_name + '.' + name
 
+    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."""
+        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
+
     def __call__(self, name, globals={}, locals={}, fromlist=[], level=-1):
         """Import a module.
 

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	Wed Nov 15 00:38:56 2006
@@ -763,6 +763,48 @@
                                                                 False)
         self.failUnlessEqual(resolved_name, self.full_child_name)
 
+    def test_relative_import_in_package(self):
+        # Trying to import a single level within a package within it's __init__
+        # module should stay within the 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):
+        # Importing from within a module in a package should try to import from
+        # within the same directory as the module requesting the import.
+        calling_from = self.parent_name + '.' + '<calling from>'
+        resolved_name = self.importer.resolve_name(self.child_name,
+                                                    calling_from, False, 1)
+        self.failUnlessEqual(resolved_name, self.full_child_name)
+
+    def test_relative_import_deep_in_package(self):
+        # Calling from a deep point in the package should still work.
+        depth = 10
+        name_extension = (str(x) for x in xrange(10))
+        calling_from = self.parent_name + '.' + '.'.join(name_extension)
+        resolved_name = self.importer.resolve_name(self.child_name,
+                calling_from, False, depth)
+        self.failUnlessEqual(resolved_name, self.full_child_name)
+
+    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.
+        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.
+        calling_from = self.parent_name + '.' + '<calling from>'
+        self.failUnlessRaises(ImportError, self.importer.resolve_name,
+                                self.child_name, calling_from, False, 2)
+
+    def test_relative_import_in_top_level(self):
+        # Attempting a relative import in a top-level location should raise
+        # ImportError.
+        self.failUnlessRaises(ImportError, self.importer.resolve_name,
+                                self.child_name, self.parent_name, False, 1)
           
 class ImportMetaPathTests(ImportHelper):
     
@@ -1046,7 +1088,12 @@
                                 package_module_globals, level=-1)
         self.verify_package(module)
         self.failUnlessEqual(module.__name__, self.top_level_module_name)
-        
+
+    def XXX_test_relative_import_in_package_init(self):
+        pass
+
+    def XXX_test_relative_import_in_package(self):
+        pass
 
 
 def test_main():


More information about the Python-checkins mailing list