[Python-checkins] distutils2: Expand tests and fix bugs in util.resolve_name.

eric.araujo python-checkins at python.org
Mon Nov 14 15:24:07 CET 2011


http://hg.python.org/distutils2/rev/5df1065ddb8b
changeset:   1232:5df1065ddb8b
user:        Éric Araujo <merwok at netwok.org>
date:        Fri Nov 11 23:26:49 2011 +0100
summary:
  Expand tests and fix bugs in util.resolve_name.

The code is still ugly, but at least it works better now.  Patches to
make it easier to read are welcome, as well as support in #12915.

files:
  distutils2/tests/test_util.py |  65 +++++++++++++---------
  distutils2/util.py            |  24 ++++++--
  2 files changed, 57 insertions(+), 32 deletions(-)


diff --git a/distutils2/tests/test_util.py b/distutils2/tests/test_util.py
--- a/distutils2/tests/test_util.py
+++ b/distutils2/tests/test_util.py
@@ -380,35 +380,48 @@
                                         'pkg1.pkg3.pkg6']))
 
     def test_resolve_name(self):
-        self.assertIs(str, resolve_name('__builtin__.str'))
-        self.assertEqual(
-            UtilTestCase.__name__,
-            resolve_name("distutils2.tests.test_util.UtilTestCase").__name__)
-        self.assertEqual(
-            UtilTestCase.test_resolve_name.__name__,
-            resolve_name("distutils2.tests.test_util.UtilTestCase."
-                         "test_resolve_name").__name__)
+        # test raw module name
+        tmpdir = self.mkdtemp()
+        sys.path.append(tmpdir)
+        self.addCleanup(sys.path.remove, tmpdir)
+        self.write_file((tmpdir, 'hello.py'), '')
 
-        self.assertRaises(ImportError, resolve_name,
-                          "distutils2.tests.test_util.UtilTestCaseNot")
-        self.assertRaises(ImportError, resolve_name,
-                          "distutils2.tests.test_util.UtilTestCase."
-                          "nonexistent_attribute")
+        os.makedirs(os.path.join(tmpdir, 'a', 'b'))
+        self.write_file((tmpdir, 'a', '__init__.py'), '')
+        self.write_file((tmpdir, 'a', 'b', '__init__.py'), '')
+        self.write_file((tmpdir, 'a', 'b', 'c.py'), 'class Foo: pass')
+        self.write_file((tmpdir, 'a', 'b', 'd.py'), textwrap.dedent("""\
+                         class FooBar:
+                             class Bar:
+                                 def baz(self):
+                                     pass
+                            """))
 
-    def test_import_nested_first_time(self):
-        tmp_dir = self.mkdtemp()
-        os.makedirs(os.path.join(tmp_dir, 'a', 'b'))
-        self.write_file(os.path.join(tmp_dir, 'a', '__init__.py'), '')
-        self.write_file(os.path.join(tmp_dir, 'a', 'b', '__init__.py'), '')
-        self.write_file(os.path.join(tmp_dir, 'a', 'b', 'c.py'),
-                                    'class Foo: pass')
+        # check Python, C and built-in module
+        self.assertEqual(resolve_name('hello').__name__, 'hello')
+        self.assertEqual(resolve_name('_csv').__name__, '_csv')
+        self.assertEqual(resolve_name('sys').__name__, 'sys')
 
-        try:
-            sys.path.append(tmp_dir)
-            resolve_name("a.b.c.Foo")
-            # assert nothing raised
-        finally:
-            sys.path.remove(tmp_dir)
+        # test module.attr
+        self.assertIs(resolve_name('__builtin__.str'), str)
+        self.assertIsNone(resolve_name('hello.__doc__'))
+        self.assertEqual(resolve_name('a.b.c.Foo').__name__, 'Foo')
+        self.assertEqual(resolve_name('a.b.d.FooBar.Bar.baz').__name__, 'baz')
+
+        # error if module not found
+        self.assertRaises(ImportError, resolve_name, 'nonexistent')
+        self.assertRaises(ImportError, resolve_name, 'non.existent')
+        self.assertRaises(ImportError, resolve_name, 'a.no')
+        self.assertRaises(ImportError, resolve_name, 'a.b.no')
+        self.assertRaises(ImportError, resolve_name, 'a.b.no.no')
+        self.assertRaises(ImportError, resolve_name, 'inva-lid')
+
+        # looking up built-in names is not supported
+        self.assertRaises(ImportError, resolve_name, 'str')
+
+        # error if module found but not attr
+        self.assertRaises(ImportError, resolve_name, 'a.b.Spam')
+        self.assertRaises(ImportError, resolve_name, 'a.b.c.Spam')
 
     @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher')
     def test_run_2to3_on_code(self):
diff --git a/distutils2/util.py b/distutils2/util.py
--- a/distutils2/util.py
+++ b/distutils2/util.py
@@ -638,22 +638,35 @@
 def resolve_name(name):
     """Resolve a name like ``module.object`` to an object and return it.
 
-    Raise ImportError if the module or name is not found.
+    This functions supports packages and attributes without depth limitation:
+    ``package.package.module.class.class.function.attr`` is valid input.
+    However, looking up builtins is not directly supported: use
+    ``builtins.name``.
+
+    Raises ImportError if importing the module fails or if one requested
+    attribute is not found.
     """
+    if '.' not in name:
+        # shortcut
+        __import__(name)
+        return sys.modules[name]
+
+    # FIXME clean up this code!
     parts = name.split('.')
     cursor = len(parts)
     module_name = parts[:cursor]
+    ret = ''
 
     while cursor > 0:
         try:
             ret = __import__('.'.join(module_name))
             break
         except ImportError:
-            if cursor == 0:
-                raise
             cursor -= 1
             module_name = parts[:cursor]
-            ret = ''
+
+    if ret == '':
+        raise ImportError(parts[0])
 
     for part in parts[1:]:
         try:
@@ -1469,8 +1482,7 @@
 
     Returns (content_type: bytes, body: bytes) ready for httplib.HTTP.
     """
-    # Taken from
-    # http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/
+    # Taken from http://code.activestate.com/recipes/146306
 
     if boundary is None:
         boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'

-- 
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list