[Python-checkins] r61543 - in sandbox/trunk/2to3/lib2to3: fixes/fix_map.py fixes/util.py tests/test_util.py
david.wolever
python-checkins at python.org
Tue Mar 18 20:24:06 CET 2008
Author: david.wolever
Date: Tue Mar 18 20:24:06 2008
New Revision: 61543
Modified:
sandbox/trunk/2to3/lib2to3/fixes/fix_map.py
sandbox/trunk/2to3/lib2to3/fixes/util.py
sandbox/trunk/2to3/lib2to3/tests/test_util.py
Log:
Added a does_tree_import function to util, which determines wether or not a top-level import statement exists.
Modified: sandbox/trunk/2to3/lib2to3/fixes/fix_map.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/fixes/fix_map.py (original)
+++ sandbox/trunk/2to3/lib2to3/fixes/fix_map.py Tue Mar 18 20:24:06 2008
@@ -24,7 +24,7 @@
from .. import patcomp
from ..pgen2 import token
from . import basefix
-from .util import Name, Call, ListComp, attr_chain, find_binding
+from .util import Name, Call, ListComp, attr_chain, does_tree_import
from ..pygram import python_symbols as syms
class FixMap(basefix.BaseFix):
@@ -63,21 +63,7 @@
def has_future_map(self, node):
if self._future_map_found is not None:
return self._future_map_found
-
- # Scamper up to the top level namespace
- top = node
- while top.type != syms.file_input:
- assert top.parent, "Tree is insane! root found before "\
- "file_input node was found."
- top = top.parent
- top=top.children[0]
-
- self._future_map_found = False
-
- binding = find_binding('map', top, 'future_builtins')
-
- self._future_map_found = bool(binding)
-
+ self._future_map_found = does_tree_import('future_builtins', 'map', node)
return self._future_map_found
def transform(self, node, results):
Modified: sandbox/trunk/2to3/lib2to3/fixes/util.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/fixes/util.py (original)
+++ sandbox/trunk/2to3/lib2to3/fixes/util.py Tue Mar 18 20:24:06 2008
@@ -193,23 +193,26 @@
suite.parent = parent
return suite
+def does_tree_import(package, name, node):
+ """ Returns true if name is imported from package at the
+ top level of the tree which node belongs to.
+ To cover the case of an import like 'import foo', use
+ Null for the package and 'foo' for the name. """
+ # Scamper up to the top level namespace
+ while node.type != syms.file_input:
+ assert node.parent, "Tree is insane! root found before "\
+ "file_input node was found."
+ node = node.parent
+
+ binding = find_binding(name, node, package)
+ return bool(binding)
+
_def_syms = set([syms.classdef, syms.funcdef])
def find_binding(name, node, package=None):
""" Returns the node which binds variable name, otherwise None.
If optional argument package is supplied, only imports will
be returned.
- >>> for args in (('map', 'map = 3'),
- ('map', 'from foo import map'),
- ('map', 'from foo import map', 'foo'),
- ('map', 'from bar import map', 'foo'),
- ('map', 'map = 3', 'foo')):
- print bool(find_binding(*args))
- True
- True
- True
- False
- False
- >>> """
+ See test cases for examples."""
for child in node.children:
ret = None
if child.type == syms.for_stmt:
@@ -233,17 +236,18 @@
elif child.type in _def_syms and child.children[1].value == name:
ret = child
elif _is_import_binding(child, name, package):
- return child
+ ret = child
elif child.type == syms.simple_stmt:
ret = find_binding(name, child, package)
elif child.type == syms.expr_stmt:
if _find(name, child.children[0]):
ret = child
- if not package and ret:
- # Because the _is_import_binding returns directly, we don't want
- # to return here if a package is defined.
- return ret
+ if ret:
+ if not package:
+ return ret
+ if ret.type in (syms.import_name, syms.import_from):
+ return ret
return None
_block_syms = set([syms.funcdef, syms.classdef, syms.trailer])
@@ -260,20 +264,9 @@
def _is_import_binding(node, name, package=None):
""" Will reuturn node if node will import name, or node
will import * from package. None is returned otherwise.
- >>> for n in ('from datetime import date',
- 'from datetime import *',
- 'import date',
- 'from spam import date'):
- print bool(_is_import_binding(n, 'date', 'datetime'))
- True
- True
- True
- False
- >>> bool(_is_import_binding('from spam import date', 'date')
- True
- >>> """
+ See test cases for examples. """
- if node.type == syms.import_name:
+ if node.type == syms.import_name and not package:
imp = node.children[1]
if imp.type == syms.dotted_as_names:
for child in imp.children:
@@ -289,10 +282,15 @@
elif imp.type == token.NAME and imp.value == name:
return node
elif node.type == syms.import_from:
- if package and node.children[1].value != package:
+ # unicode(...) is used to make life easier here, because
+ # from a.b import parses to ['import', ['a', '.', 'b'], ...]
+ if package and unicode(node.children[1]).strip() != package:
return None
n = node.children[3]
- if n.type == syms.import_as_names and _find(name, n):
+ if package and _find('as', n):
+ # See test_from_import_as for explanation
+ return None
+ elif n.type == syms.import_as_names and _find(name, n):
return node
elif n.type == syms.import_as_name:
child = n.children[2]
Modified: sandbox/trunk/2to3/lib2to3/tests/test_util.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/tests/test_util.py (original)
+++ sandbox/trunk/2to3/lib2to3/tests/test_util.py Tue Mar 18 20:24:06 2008
@@ -84,9 +84,53 @@
self.assertStr(Name("a", prefix="b"), "ba")
+class Test_does_tree_import(support.TestCase):
+ def _find_bind_rec(self, name, node):
+ # Search a tree for a binding -- used to find the starting
+ # point for these tests.
+ c = util.find_binding(name, node)
+ if c: return c
+ for child in node.children:
+ c = self._find_bind_rec(name, child)
+ if c: return c
+
+ def does_tree_import(self, package, name, string):
+ node = parse(string)
+ # Find the binding of start -- that's what we'll go from
+ node = self._find_bind_rec('start', node)
+ return util.does_tree_import(package, name, node)
+
+ def try_with(self, string):
+ failing_tests = (("a", "a", "from a import b"),
+ ("a.d", "a", "from a.d import b"),
+ ("d.a", "a", "from d.a import b"),
+ (None, "a", "import b"),
+ (None, "a", "import b, c, d"))
+ for package, name, import_ in failing_tests:
+ n = self.does_tree_import(package, name, import_ + "\n" + string)
+ self.failIf(n)
+ n = self.does_tree_import(package, name, string + "\n" + import_)
+ self.failIf(n)
+
+ passing_tests = (("a", "a", "from a import a"),
+ ("x", "a", "from x import a"),
+ ("x", "a", "from x import b, c, a, d"),
+ ("x.b", "a", "from x.b import a"),
+ ("x.b", "a", "from x.b import b, c, a, d"),
+ (None, "a", "import a"),
+ (None, "a", "import b, c, a, d"))
+ for package, name, import_ in passing_tests:
+ n = self.does_tree_import(package, name, import_ + "\n" + string)
+ self.failUnless(n)
+ n = self.does_tree_import(package, name, string + "\n" + import_)
+ self.failUnless(n)
+
+ def test_in_function(self):
+ self.try_with("def foo():\n\tbar.baz()\n\tstart=3")
+
class Test_find_binding(support.TestCase):
- def find_binding(self, name, string):
- return util.find_binding(name, parse(string))
+ def find_binding(self, name, string, package=None):
+ return util.find_binding(name, parse(string), package)
def test_simple_assignment(self):
self.failUnless(self.find_binding("a", "a = b"))
@@ -149,6 +193,42 @@
self.failIf(self.find_binding("a", "from a.d import b as t"))
self.failIf(self.find_binding("a", "from d.a import b as t"))
+ def test_simple_import_with_package(self):
+ self.failUnless(self.find_binding("b", "import b"))
+ self.failUnless(self.find_binding("b", "import b, c, d"))
+ self.failIf(self.find_binding("b", "import b", "b"))
+ self.failIf(self.find_binding("b", "import b, c, d", "c"))
+
+ def test_from_import_with_package(self):
+ self.failUnless(self.find_binding("a", "from x import a", "x"))
+ self.failUnless(self.find_binding("a", "from a import a", "a"))
+ self.failUnless(self.find_binding("a", "from x import *", "x"))
+ self.failUnless(self.find_binding("a", "from x import b, c, a, d", "x"))
+ self.failUnless(self.find_binding("a", "from x.b import a", "x.b"))
+ self.failUnless(self.find_binding("a", "from x.b import *", "x.b"))
+ self.failUnless(self.find_binding("a", "from x.b import b, c, a, d", "x.b"))
+ self.failIf(self.find_binding("a", "from a import b", "a"))
+ self.failIf(self.find_binding("a", "from a.d import b", "a.d"))
+ self.failIf(self.find_binding("a", "from d.a import b", "a.d"))
+ self.failIf(self.find_binding("a", "from x.y import *", "a.b"))
+
+ def test_import_as_with_package(self):
+ self.failIf(self.find_binding("a", "import b.c as a", "b.c"))
+ self.failIf(self.find_binding("a", "import a as f", "f"))
+ self.failIf(self.find_binding("a", "import a as f", "a"))
+
+ def test_from_import_as_with_package(self):
+ # Because it would take a lot of special-case code in the fixers
+ # to deal with from foo import bar as baz, we'll simply always
+ # fail if there is an "from ... import ... as ..."
+ self.failIf(self.find_binding("a", "from x import b as a", "x"))
+ self.failIf(self.find_binding("a", "from x import g as a, d as b", "x"))
+ self.failIf(self.find_binding("a", "from x.b import t as a", "x.b"))
+ self.failIf(self.find_binding("a", "from x.b import g as a, d", "x.b"))
+ self.failIf(self.find_binding("a", "from a import b as t", "a"))
+ self.failIf(self.find_binding("a", "from a import b as t", "b"))
+ self.failIf(self.find_binding("a", "from a import b as t", "t"))
+
def test_function_def(self):
self.failUnless(self.find_binding("a", "def a(): pass"))
self.failUnless(self.find_binding("a", "def a(b, c, d): pass"))
More information about the Python-checkins
mailing list