[Python-checkins] r67928 - in sandbox/trunk/2to3/lib2to3: fixes/fix_import.py tests/test_fixers.py
benjamin.peterson
python-checkins at python.org
Sat Dec 27 03:49:31 CET 2008
Author: benjamin.peterson
Date: Sat Dec 27 03:49:30 2008
New Revision: 67928
Log:
don't be so idiot about multiple local imports in fix_import; still won't handle absolute and local imports on the same line
Modified:
sandbox/trunk/2to3/lib2to3/fixes/fix_import.py
sandbox/trunk/2to3/lib2to3/tests/test_fixers.py
Modified: sandbox/trunk/2to3/lib2to3/fixes/fix_import.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/fixes/fix_import.py (original)
+++ sandbox/trunk/2to3/lib2to3/fixes/fix_import.py Sat Dec 27 03:49:30 2008
@@ -13,55 +13,78 @@
# Local imports
from .. import fixer_base
from os.path import dirname, join, exists, pathsep
-from ..fixer_util import FromImport, syms
+from ..fixer_util import FromImport, syms, token
+
+
+def traverse_imports(names):
+ """
+ Walks over all the names imported in a dotted_as_names node.
+ """
+ pending = [names]
+ while pending:
+ node = pending.pop()
+ if node.type == token.NAME:
+ yield node.value
+ elif node.type == syms.dotted_name:
+ yield "".join([ch.value for ch in node.children])
+ elif node.type == syms.dotted_as_name:
+ pending.append(node.children[0])
+ elif node.type == syms.dotted_as_names:
+ pending.extend(node.children[::-2])
+ else:
+ raise AssertionError("unkown node type")
+
class FixImport(fixer_base.BaseFix):
PATTERN = """
- import_from< type='from' imp=any 'import' ['('] any [')'] >
+ import_from< 'from' imp=any 'import' ['('] any [')'] >
|
- import_name< type='import' imp=any >
+ import_name< 'import' imp=any >
"""
def transform(self, node, results):
imp = results['imp']
- mod_name = unicode(imp.children[0] if imp.type == syms.dotted_as_name \
- else imp)
-
- if mod_name.startswith('.'):
- # Already a new-style import
- return
-
- if not probably_a_local_import(mod_name, self.filename):
- # I guess this is a global import -- skip it!
- return
-
- if results['type'].value == 'from':
+ if node.type == syms.import_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()
+ if self.probably_a_local_import(imp.value):
+ imp.value = "." + imp.value
+ imp.changed()
+ return node
else:
- new = FromImport('.', getattr(imp, 'content', None) or [imp])
+ have_local = False
+ have_absolute = False
+ for mod_name in traverse_imports(imp):
+ if self.probably_a_local_import(mod_name):
+ have_local = True
+ else:
+ have_absolute = True
+ if have_absolute:
+ if have_local:
+ # We won't handle both sibling and absolute imports in the
+ # same statement at the moment.
+ self.warning(node, "absolute and local imports together")
+ return
+
+ new = FromImport('.', [imp])
new.set_prefix(node.get_prefix())
- node = new
- return node
+ return new
-def probably_a_local_import(imp_name, file_path):
- # Must be stripped because the right space is included by the parser
- imp_name = imp_name.split('.', 1)[0].strip()
- base_path = dirname(file_path)
- base_path = join(base_path, imp_name)
- # If there is no __init__.py next to the file its not in a package
- # so can't be a relative import.
- if not exists(join(dirname(base_path), '__init__.py')):
+ def probably_a_local_import(self, imp_name):
+ imp_name = imp_name.split('.', 1)[0]
+ base_path = dirname(self.filename)
+ base_path = join(base_path, imp_name)
+ # If there is no __init__.py next to the file its not in a package
+ # so can't be a relative import.
+ if not exists(join(dirname(base_path), '__init__.py')):
+ return False
+ for ext in ['.py', pathsep, '.pyc', '.so', '.sl', '.pyd']:
+ if exists(base_path + ext):
+ return True
return False
- for ext in ['.py', pathsep, '.pyc', '.so', '.sl', '.pyd']:
- if exists(base_path + ext):
- return True
- return False
Modified: sandbox/trunk/2to3/lib2to3/tests/test_fixers.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/tests/test_fixers.py (original)
+++ sandbox/trunk/2to3/lib2to3/tests/test_fixers.py Sat Dec 27 03:49:30 2008
@@ -3503,11 +3503,30 @@
a = "from . import foo, bar"
self.check_both(b, a)
+ b = "import foo, bar, x"
+ a = "from . import foo, bar, x"
+ self.check_both(b, a)
+
+ b = "import x, y, z"
+ a = "from . import x, y, z"
+ self.check_both(b, a)
+
def test_import_as(self):
b = "import foo as x"
a = "from . import foo as x"
self.check_both(b, a)
+ b = "import a as b, b as c, c as d"
+ a = "from . import a as b, b as c, c as d"
+ self.check_both(b, a)
+
+ def test_local_and_absolute(self):
+ self.always_exists = False
+ self.present_files = set(["foo.py", "__init__.py"])
+
+ s = "import foo, bar"
+ self.warns_unchanged(s, "absolute and local imports together")
+
def test_dotted_import(self):
b = "import foo.bar"
a = "from . import foo.bar"
More information about the Python-checkins
mailing list