Index: lib2to3/tests/test_fixers.py =================================================================== --- lib2to3/tests/test_fixers.py (revision 62470) +++ lib2to3/tests/test_fixers.py (working copy) @@ -360,20 +360,6 @@ s = """print('')""" self.unchanged(s) - def test_idempotency_print_as_function(self): - print_stmt = pygram.python_grammar.keywords.pop("print") - try: - s = """print(1, 1+1, 1+1+1)""" - self.unchanged(s) - - s = """print()""" - self.unchanged(s) - - s = """print('')""" - self.unchanged(s) - finally: - pygram.python_grammar.keywords["print"] = print_stmt - def test_1(self): b = """print 1, 1+1, 1+1+1""" a = """print(1, 1+1, 1+1+1)""" @@ -435,28 +421,39 @@ # With from __future__ import print_function def test_with_future_print_function(self): - # XXX: These tests won't actually do anything until the parser - # is fixed so it won't crash when it sees print(x=y). - # When #2412 is fixed, the try/except block can be taken - # out and the tests can be run like normal. - try: - s = "from __future__ import print_function\n"\ - "print('Hai!', end=' ')" - self.unchanged(s) + s = "from __future__ import print_function\n"\ + "print('Hai!', end=' ')" + self.unchanged(s) + # A normal test is run, just to make sure the print + # keyword is put back in afterwards + self.test_1() - b = "print 'Hello, world!'" - a = "print('Hello, world!')" - self.check(b, a) - + # Make sure that the print keyword is put back + # in place after an exception during parsing. + try: s = "from __future__ import *\n"\ - "print('Hai!', end=' ')" + "invalid stuff" self.unchanged(s) - except: - return + except AssertionError: + pass # Expect an error from the invalid syntax else: - self.assertFalse(True, "#2421 has been fixed -- printing tests "\ - "need to be updated!") + # This should probably never happen... + raise Exception ("Invalid line didn't raise an exception") + self.test_1() + s = "from __future__ import *\n"\ + "print('Hai!', end=' ')" + self.unchanged(s) + + # Check that comments are ignored when parsing the + # __future__ import line + b = "from __future__ import foo # *\n"\ + "print 'eggs'" + a = "from __future__ import foo # *\n"\ + "print('eggs')" + self.check(b, a) + + class Test_exec(FixerTestCase): fixer = "exec" Index: lib2to3/refactor.py =================================================================== --- lib2to3/refactor.py (revision 62470) +++ lib2to3/refactor.py (working copy) @@ -18,6 +18,7 @@ import difflib import optparse import logging +import re from collections import defaultdict from itertools import chain @@ -46,8 +47,6 @@ help="Each FIX specifies a transformation; default all") parser.add_option("-l", "--list-fixes", action="store_true", help="List available transformations (fixes/fix_*.py)") - parser.add_option("-p", "--print-function", action="store_true", - help="Modify the grammar so that print() is a function") parser.add_option("-v", "--verbose", action="store_true", help="More verbose logging") parser.add_option("-w", "--write", action="store_true", @@ -147,8 +146,6 @@ self.errors = [] self.logger = logging.getLogger("RefactoringTool") self.fixer_log = [] - if self.options.print_function: - del pygram.python_grammar.keywords["print"] self.driver = driver.Driver(pygram.python_grammar, convert=pytree.convert, logger=self.logger) @@ -287,12 +284,34 @@ An AST corresponding to the refactored input stream; None if there were errors during the parse. """ + + # XXX: I am assuming that the grammer will always contain + # the print keyword. + # Is that a safe assumption? + old_print = pygram.python_grammar.keywords["print"] + for line in data.splitlines(): + line = line.split() + if line[:2] != ["from", "__future__"]: + continue + if line[0] in ("import", "def", "class", "if"): + break + + for word in line: + if 'print_function' in word or '*' in word: + del pygram.python_grammar.keywords["print"] + break + elif '#' in word: # Stop searching if a comment is found + break + try: tree = self.driver.parse_string(data,1) except Exception, err: self.log_error("Can't parse %s: %s: %s", name, err.__class__.__name__, err) return + finally: + pygram.python_grammar.keywords["print"] = old_print + if self.options.verbose: self.log_message("Refactoring %s", name) self.refactor_tree(tree, name)