Merged revisions 66707,66775,66782 via svnmerge from

svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3

........
  r66707 | benjamin.peterson | 2008-09-30 18:27:10 -0500 (Tue, 30 Sep 2008) | 1 line

  fix #4001: fix_imports didn't check for __init__.py before converting to relative imports
........
  r66775 | collin.winter | 2008-10-03 12:08:26 -0500 (Fri, 03 Oct 2008) | 4 lines

  Add an alternative iterative pattern matching system that, while slower, correctly parses files that cause the faster recursive pattern matcher to fail with a recursion error. lib2to3 falls back to the iterative matcher if the recursive one fails.

  Fixes http://bugs.python.org/issue2532. Thanks to Nick Edds.
........
  r66782 | benjamin.peterson | 2008-10-03 17:51:36 -0500 (Fri, 03 Oct 2008) | 1 line

  add Victor Stinner's fixer for os.getcwdu -> os.getcwd #4023
........
This commit is contained in:
Benjamin Peterson 2008-10-04 20:55:50 +00:00
parent 34211e91ef
commit 4d164158d6
6 changed files with 2833 additions and 11 deletions

View File

@ -0,0 +1,18 @@
"""
Fixer that changes os.getcwdu() to os.getcwd().
"""
# Author: Victor Stinner
# Local imports
from .. import fixer_base
from ..fixer_util import Name
class FixGetcwdu(fixer_base.BaseFix):
PATTERN = """
power< 'os' trailer< dot='.' name='getcwdu' > any* >
"""
def transform(self, node, results):
name = results["name"]
name.replace(Name("getcwd", prefix=name.get_prefix()))

View File

@ -54,6 +54,10 @@ def probably_a_local_import(imp_name, file_path):
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')):
return False
for ext in ['.py', pathsep, '.pyc', '.so', '.sl', '.pyd']:
if exists(base_path + ext):
return True

View File

@ -655,10 +655,47 @@ class WildcardPattern(BasePattern):
elif self.name == "bare_name":
yield self._bare_name_matches(nodes)
else:
for count, r in self._recursive_matches(nodes, 0):
if self.name:
r[self.name] = nodes[:count]
yield count, r
try:
for count, r in self._recursive_matches(nodes, 0):
if self.name:
r[self.name] = nodes[:count]
yield count, r
except RuntimeError:
# We fall back to the iterative pattern matching scheme if the recursive
# scheme hits the recursion limit.
for count, r in self._iterative_matches(nodes):
if self.name:
r[self.name] = nodes[:count]
yield count, r
def _iterative_matches(self, nodes):
"""Helper to iteratively yield the matches."""
nodelen = len(nodes)
if 0 >= self.min:
yield 0, {}
results = []
# generate matches that use just one alt from self.content
for alt in self.content:
for c, r in generate_matches(alt, nodes):
yield c, r
results.append((c, r))
# for each match, iterate down the nodes
while results:
new_results = []
for c0, r0 in results:
# stop if the entire set of nodes has been matched
if c0 < nodelen and c0 <= self.max:
for alt in self.content:
for c1, r1 in generate_matches(alt, nodes[c0:]):
if c1 > 0:
r = {}
r.update(r0)
r.update(r1)
yield c0 + c1, r
new_results.append((c0 + c1, r))
results = new_results
def _bare_name_matches(self, nodes):
"""Special optimized matcher for bare_name."""

View File

@ -0,0 +1,5 @@
Files in this directory:
- py2_test_grammar.py -- test file that exercises most/all of Python 2.x's grammar.
- py3_test_grammar.py -- test file that exercises most/all of Python 3.x's grammar.
- infinite_recursion.py -- test file that causes lib2to3's faster recursive pattern matching
scheme to fail, but passes when lib2to3 falls back to iterative pattern matching.

File diff suppressed because it is too large Load Diff

View File

@ -9,10 +9,10 @@ except ImportError:
import support
# Python imports
import os
import unittest
from itertools import chain
from operator import itemgetter
from os.path import dirname, pathsep
# Local imports
from .. import pygram
@ -3274,14 +3274,19 @@ class Test_import(FixerTestCase):
# Need to replace fix_import's exists method
# so we can check that it's doing the right thing
self.files_checked = []
self.present_files = set()
self.always_exists = True
def fake_exists(name):
self.files_checked.append(name)
return self.always_exists
return self.always_exists or (name in self.present_files)
from ..fixes import fix_import
fix_import.exists = fake_exists
def tearDown(self):
from lib2to3.fixes import fix_import
fix_import.exists = os.path.exists
def check_both(self, b, a):
self.always_exists = True
FixerTestCase.check(self, b, a)
@ -3291,10 +3296,12 @@ class Test_import(FixerTestCase):
def test_files_checked(self):
def p(path):
# Takes a unix path and returns a path with correct separators
return pathsep.join(path.split("/"))
return os.path.pathsep.join(path.split("/"))
self.always_exists = False
expected_extensions = ('.py', pathsep, '.pyc', '.so', '.sl', '.pyd')
self.present_files = set(['__init__.py'])
expected_extensions = ('.py', os.path.pathsep, '.pyc', '.so',
'.sl', '.pyd')
names_to_test = (p("/spam/eggs.py"), "ni.py", p("../../shrubbery.py"))
for name in names_to_test:
@ -3302,11 +3309,32 @@ class Test_import(FixerTestCase):
self.filename = name
self.unchanged("import jam")
if dirname(name): name = dirname(name) + '/jam'
else: name = 'jam'
if os.path.dirname(name):
name = os.path.dirname(name) + '/jam'
else:
name = 'jam'
expected_checks = set(name + ext for ext in expected_extensions)
expected_checks.add("__init__.py")
self.failUnlessEqual(set(self.files_checked), expected_checks)
self.assertEqual(set(self.files_checked), expected_checks)
def test_not_in_package(self):
s = "import bar"
self.always_exists = False
self.present_files = set(["bar.py"])
self.unchanged(s)
def test_in_package(self):
b = "import bar"
a = "from . import bar"
self.always_exists = False
self.present_files = set(["__init__.py", "bar.py"])
self.check(b, a)
def test_comments_and_indent(self):
b = "import bar # Foo"
a = "from . import bar # Foo"
self.check(b, a)
def test_from(self):
b = "from foo import bar, baz"
@ -3577,6 +3605,67 @@ class Test_metaclass(FixerTestCase):
self.check(b, a)
class Test_getcwdu(FixerTestCase):
fixer = 'getcwdu'
def test_basic(self):
b = """os.getcwdu"""
a = """os.getcwd"""
self.check(b, a)
b = """os.getcwdu()"""
a = """os.getcwd()"""
self.check(b, a)
b = """meth = os.getcwdu"""
a = """meth = os.getcwd"""
self.check(b, a)
b = """os.getcwdu(args)"""
a = """os.getcwd(args)"""
self.check(b, a)
def test_comment(self):
b = """os.getcwdu() # Foo"""
a = """os.getcwd() # Foo"""
self.check(b, a)
def test_unchanged(self):
s = """os.getcwd()"""
self.unchanged(s)
s = """getcwdu()"""
self.unchanged(s)
s = """os.getcwdb()"""
self.unchanged(s)
def test_indentation(self):
b = """
if 1:
os.getcwdu()
"""
a = """
if 1:
os.getcwd()
"""
self.check(b, a)
def test_multilation(self):
b = """os .getcwdu()"""
a = """os .getcwd()"""
self.check(b, a)
b = """os. getcwdu"""
a = """os. getcwd"""
self.check(b, a)
b = """os.getcwdu ( )"""
a = """os.getcwd ( )"""
self.check(b, a)
if __name__ == "__main__":
import __main__
support.run_all_tests(__main__)