From a675ef1141e2533bd5596222d0a64b6a3f74d2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Mon, 24 Mar 2008 00:50:58 +0000 Subject: [PATCH] Merged revisions 61825 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ................ r61825 | martin.v.loewis | 2008-03-24 01:46:53 +0100 (Mo, 24 Mär 2008) | 17 lines Merged revisions 61724-61824 via svnmerge from svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3 ........ r61730 | martin.v.loewis | 2008-03-22 02:20:58 +0100 (Sa, 22 Mär 2008) | 2 lines More explicit relative imports. ........ r61755 | david.wolever | 2008-03-22 21:33:52 +0100 (Sa, 22 Mär 2008) | 1 line Fixing #2446 -- 2to3 now translates 'import foo' to 'from . import foo' ........ r61824 | david.wolever | 2008-03-24 01:30:24 +0100 (Mo, 24 Mär 2008) | 3 lines Fixed a bug where 'from itertools import izip' would return 'from itertools import' ........ ................ --- Lib/lib2to3/fixes/fix_import.py | 29 +++++++++++++--------- Lib/lib2to3/fixes/fix_itertools_imports.py | 14 ++++++----- Lib/lib2to3/fixes/util.py | 20 +++++++++++++++ Lib/lib2to3/tests/benchmark.py | 2 +- Lib/lib2to3/tests/pytree_idempotency.py | 2 +- Lib/lib2to3/tests/test_fixers.py | 18 +++++++++++--- 6 files changed, 62 insertions(+), 23 deletions(-) diff --git a/Lib/lib2to3/fixes/fix_import.py b/Lib/lib2to3/fixes/fix_import.py index 52e84084c47..c188fce9406 100644 --- a/Lib/lib2to3/fixes/fix_import.py +++ b/Lib/lib2to3/fixes/fix_import.py @@ -7,19 +7,20 @@ Becomes: And this import: import spam Becomes: - import .spam + from . import spam """ # Local imports from . import basefix from os.path import dirname, join, exists, pathsep +from .util import FromImport class FixImport(basefix.BaseFix): PATTERN = """ - import_from< 'from' imp=any 'import' any > + import_from< type='from' imp=any 'import' any > | - import_name< 'import' imp=any > + import_name< type='import' imp=any > """ def transform(self, node, results): @@ -33,15 +34,19 @@ class FixImport(basefix.BaseFix): # I guess this is a global import -- skip it! return - # Some imps are top-level (eg: 'import ham') - # some are first level (eg: 'import ham.eggs') - # some are third level (eg: 'import ham.eggs as spam') - # Hence, the loop - while not hasattr(imp, 'value'): - imp = imp.children[0] - - imp.value = "." + imp.value - node.changed() + if results['type'].value == 'from': + # Some imps are top-level (eg: 'import ham') + # some are first level (eg: 'import ham.eggs') + # some are third level (eg: 'import ham.eggs as spam') + # Hence, the loop + while not hasattr(imp, 'value'): + imp = imp.children[0] + imp.value = "." + imp.value + node.changed() + else: + new = FromImport('.', getattr(imp, 'content', None) or [imp]) + new.prefix = node.get_prefix() + node = new return node def probably_a_local_import(imp_name, file_path): diff --git a/Lib/lib2to3/fixes/fix_itertools_imports.py b/Lib/lib2to3/fixes/fix_itertools_imports.py index 7adf6437206..e60ec200e0e 100644 --- a/Lib/lib2to3/fixes/fix_itertools_imports.py +++ b/Lib/lib2to3/fixes/fix_itertools_imports.py @@ -17,6 +17,9 @@ class FixItertoolsImports(basefix.BaseFix): # Handle 'import ... as ...' continue if child.value in ('imap', 'izip', 'ifilter'): + # The value must be set to none in case child == import, + # so that the test for empty imports will work out + child.value = None child.remove() elif child.value == 'ifilterfalse': node.changed() @@ -34,10 +37,9 @@ class FixItertoolsImports(basefix.BaseFix): if str(children[-1]) == ',': children[-1].remove() - # If there is nothing left, return a blank line + # If there are no imports left, just get rid of the entire statement if not (imports.children or getattr(imports, 'value', None)): - new = BlankLine() - new.prefix = node.get_prefix() - else: - new = node - return new + p = node.get_prefix() + node = BlankLine() + node.prefix = p + return node diff --git a/Lib/lib2to3/fixes/util.py b/Lib/lib2to3/fixes/util.py index 806bf287e31..b48aeb32a07 100644 --- a/Lib/lib2to3/fixes/util.py +++ b/Lib/lib2to3/fixes/util.py @@ -108,6 +108,26 @@ def ListComp(xp, fp, it, test=None): inner, Leaf(token.RBRACE, "]")]) +def FromImport(package_name, name_leafs): + """ Return an import statement in the form: + from package import name_leafs""" + # XXX: May not handle dotted imports properly (eg, package_name='foo.bar') + assert package_name == '.' or '.' not in package.name, "FromImport has "\ + "not been tested with dotted package names -- use at your own "\ + "peril!" + + for leaf in name_leafs: + # Pull the leaves out of their old tree + leaf.remove() + + children = [Leaf(token.NAME, 'from'), + Leaf(token.NAME, package_name, prefix=" "), + Leaf(token.NAME, 'import', prefix=" "), + Node(syms.import_as_names, name_leafs)] + imp = Node(syms.import_from, children) + return imp + + ########################################################### ### Determine whether a node represents a given literal ########################################################### diff --git a/Lib/lib2to3/tests/benchmark.py b/Lib/lib2to3/tests/benchmark.py index 1c4b8fcfca5..e1b293fd890 100644 --- a/Lib/lib2to3/tests/benchmark.py +++ b/Lib/lib2to3/tests/benchmark.py @@ -13,7 +13,7 @@ import sys from time import time # Test imports -from support import adjust_path +from .support import adjust_path adjust_path() # Local imports diff --git a/Lib/lib2to3/tests/pytree_idempotency.py b/Lib/lib2to3/tests/pytree_idempotency.py index ca5441a0704..3f3ab92133b 100755 --- a/Lib/lib2to3/tests/pytree_idempotency.py +++ b/Lib/lib2to3/tests/pytree_idempotency.py @@ -7,7 +7,7 @@ __author__ = "Guido van Rossum " # Support imports (need to be imported first) -import support +from . import support # Python imports import os diff --git a/Lib/lib2to3/tests/test_fixers.py b/Lib/lib2to3/tests/test_fixers.py index 056e95b7af3..34ea3e5e132 100755 --- a/Lib/lib2to3/tests/test_fixers.py +++ b/Lib/lib2to3/tests/test_fixers.py @@ -3036,6 +3036,10 @@ class Test_itertools_imports(FixerTestCase): a = "" self.check(b, a) + b = "from itertools import izip" + a = "" + self.check(b, a) + def test_import_as(self): b = "from itertools import izip, bar as bang, imap" a = "from itertools import bar as bang" @@ -3105,6 +3109,10 @@ class Test_import(FixerTestCase): self.failUnlessEqual(set(self.files_checked), expected_checks) def test_from(self): + b = "from foo import bar, baz" + a = "from .foo import bar, baz" + self.check_both(b, a) + b = "from foo import bar" a = "from .foo import bar" self.check_both(b, a) @@ -3121,17 +3129,21 @@ class Test_import(FixerTestCase): def test_import(self): b = "import foo" - a = "import .foo" + a = "from . import foo" + self.check_both(b, a) + + b = "import foo, bar" + a = "from . import foo, bar" self.check_both(b, a) def test_dotted_import(self): b = "import foo.bar" - a = "import .foo.bar" + a = "from . import foo.bar" self.check_both(b, a) def test_dotted_import_as(self): b = "import foo.bar as bang" - a = "import .foo.bar as bang" + a = "from . import foo.bar as bang" self.check_both(b, a)