Commit 3a2fb144 authored by Benjamin Peterson's avatar Benjamin Peterson

Merged revisions 66453 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

................
  r66453 | benjamin.peterson | 2008-09-13 12:43:19 -0500 (Sat, 13 Sep 2008) | 24 lines

  Merged revisions 66191,66418,66438,66445 via svnmerge from
  svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3

  ........
    r66191 | benjamin.peterson | 2008-09-03 17:00:52 -0500 (Wed, 03 Sep 2008) | 1 line

    update the Grammar file after recent syntax changes
  ........
    r66418 | benjamin.peterson | 2008-09-12 18:49:48 -0500 (Fri, 12 Sep 2008) | 1 line

    a trival fix to get a few more print corner cases #2899
  ........
    r66438 | benjamin.peterson | 2008-09-12 21:32:30 -0500 (Fri, 12 Sep 2008) | 5 lines

    add Jack Diederich's fixer for metaclass syntax #2366

    my contribution to this was adding a few tests and fixing a few bugs
    I also reviewed it (Jack is a committer)
  ........
    r66445 | benjamin.peterson | 2008-09-13 10:50:00 -0500 (Sat, 13 Sep 2008) | 1 line

    add a few more tests concerning int literals and weird spacing
  ........
................
parent c575c906
...@@ -138,7 +138,9 @@ dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | ...@@ -138,7 +138,9 @@ dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) arglist: (argument ',')* (argument [',']
|'*' test (',' argument)* [',' '**' test]
|'**' test)
argument: test [comp_for] | test '=' test # Really [keyword '='] test argument: test [comp_for] | test '=' test # Really [keyword '='] test
comp_iter: comp_for | comp_if comp_iter: comp_for | comp_if
......
"""Fixer for __metaclass__ = X -> (metaclass=X) methods.
The various forms of classef (inherits nothing, inherits once, inherints
many) don't parse the same in the CST so we look at ALL classes for
a __metaclass__ and if we find one normalize the inherits to all be
an arglist.
For one-liner classes ('class X: pass') there is no indent/dedent so
we normalize those into having a suite.
Moving the __metaclass__ into the classdef can also cause the class
body to be empty so there is some special casing for that as well.
This fixer also tries very hard to keep original indenting and spacing
in all those corner cases.
"""
# Author: Jack Diederich
import os
# Local imports
from .. import fixer_base
from ..pygram import token
from ..fixer_util import Name, syms, Node, Leaf
def has_metaclass(parent):
""" we have to check the cls_node without changing it.
There are two possiblities:
1) clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta')
2) clsdef => simple_stmt => expr_stmt => Leaf('__meta')
"""
for node in parent.children:
if node.type == syms.suite:
return has_metaclass(node)
elif node.type == syms.simple_stmt and node.children:
expr_node = node.children[0]
if expr_node.type == syms.expr_stmt and expr_node.children:
leaf_node = expr_node.children[0]
if leaf_node.value == '__metaclass__':
return True
return False
def fixup_parse_tree(cls_node):
""" one-line classes don't get a suite in the parse tree so we add
one to normalize the tree
"""
for node in cls_node.children:
if node.type == syms.suite:
# already in the prefered format, do nothing
return
# !%@#! oneliners have no suite node, we have to fake one up
for i, node in enumerate(cls_node.children):
if node.type == token.COLON:
break
else:
raise ValueError("No class suite and no ':'!")
# move everything into a suite node
suite = Node(syms.suite, [])
while cls_node.children[i+1:]:
move_node = cls_node.children[i+1]
suite.append_child(move_node.clone())
move_node.remove()
cls_node.append_child(suite)
node = suite
def fixup_simple_stmt(parent, i, stmt_node):
""" if there is a semi-colon all the parts count as part of the same
simple_stmt. We just want the __metaclass__ part so we move
everything efter the semi-colon into its own simple_stmt node
"""
for semi_ind, node in enumerate(stmt_node.children):
if node.type == token.SEMI: # *sigh*
break
else:
return
node.remove() # kill the semicolon
new_expr = Node(syms.expr_stmt, [])
new_stmt = Node(syms.simple_stmt, [new_expr])
while stmt_node.children[semi_ind:]:
move_node = stmt_node.children[semi_ind]
new_expr.append_child(move_node.clone())
move_node.remove()
parent.insert_child(i, new_stmt)
new_leaf1 = new_stmt.children[0].children[0]
old_leaf1 = stmt_node.children[0].children[0]
new_leaf1.set_prefix(old_leaf1.get_prefix())
def remove_trailing_newline(node):
if node.children and node.children[-1].type == token.NEWLINE:
node.children[-1].remove()
def find_metas(cls_node):
# find the suite node (Mmm, sweet nodes)
for node in cls_node.children:
if node.type == syms.suite:
break
else:
raise ValueError("No class suite!")
# look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ]
for i, simple_node in list(enumerate(node.children)):
if simple_node.type == syms.simple_stmt and simple_node.children:
expr_node = simple_node.children[0]
if expr_node.type == syms.expr_stmt and expr_node.children:
leaf_node = expr_node.children[0]
if leaf_node.value == '__metaclass__':
fixup_simple_stmt(node, i, simple_node)
remove_trailing_newline(simple_node)
yield (node, i, simple_node)
def fixup_indent(suite):
""" If an INDENT is followed by a thing with a prefix then nuke the prefix
Otherwise we get in trouble when removing __metaclass__ at suite start
"""
kids = suite.children[::-1]
# find the first indent
while kids:
node = kids.pop()
if node.type == token.INDENT:
break
# find the first Leaf
while kids:
node = kids.pop()
if isinstance(node, Leaf) and node.type != token.DEDENT:
if node.prefix:
node.set_prefix('')
return
else:
kids.extend(node.children[::-1])
class FixMetaclass(fixer_base.BaseFix):
PATTERN = """
classdef<any*>
"""
def transform(self, node, results):
if not has_metaclass(node):
return node
fixup_parse_tree(node)
# find metaclasses, keep the last one
last_metaclass = None
for suite, i, stmt in find_metas(node):
last_metaclass = stmt
stmt.remove()
text_type = node.children[0].type # always Leaf(nnn, 'class')
# figure out what kind of classdef we have
if len(node.children) == 7:
# Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite])
# 0 1 2 3 4 5 6
if node.children[3].type == syms.arglist:
arglist = node.children[3]
# Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite])
elif isinstance(node.children[3], Leaf):
parent = node.children[3].clone()
arglist = Node(syms.arglist, [parent])
node.set_child(3, arglist)
else:
raise ValueError("Unexpected class inheritance arglist")
elif len(node.children) == 6:
# Node(classdef, ['class', 'name', '(', ')', ':', suite])
# 0 1 2 3 4 5
arglist = Node(syms.arglist, [])
node.insert_child(3, arglist)
elif len(node.children) == 4:
# Node(classdef, ['class', 'name', ':', suite])
# 0 1 2 3
arglist = Node(syms.arglist, [])
node.insert_child(2, Leaf(token.RPAR, ')'))
node.insert_child(2, arglist)
node.insert_child(2, Leaf(token.LPAR, '('))
else:
raise ValueError("Unexpected class definition")
# now stick the metaclass in the arglist
meta_txt = last_metaclass.children[0].children[0]
meta_txt.value = 'metaclass'
orig_meta_prefix = meta_txt.get_prefix()
if arglist.children:
arglist.append_child(Leaf(token.COMMA, ','))
meta_txt.set_prefix(' ')
else:
meta_txt.set_prefix('')
# compact the expression "metaclass = Meta" -> "metaclass=Meta"
expr_stmt = last_metaclass.children[0]
assert expr_stmt.type == syms.expr_stmt
expr_stmt.children[1].set_prefix('')
expr_stmt.children[2].set_prefix('')
arglist.append_child(last_metaclass)
fixup_indent(suite)
# check for empty suite
if not suite.children:
# one-liner that was just __metaclass_
suite.remove()
pass_leaf = Leaf(text_type, 'pass')
pass_leaf.set_prefix(orig_meta_prefix)
node.append_child(pass_leaf)
node.append_child(Leaf(token.NEWLINE, os.linesep))
elif len(suite.children) > 1 and \
(suite.children[-2].type == token.INDENT and
suite.children[-1].type == token.DEDENT):
# there was only one line in the class body and it was __metaclass__
pass_leaf = Leaf(text_type, 'pass')
suite.insert_child(-1, pass_leaf)
suite.insert_child(-1, Leaf(token.NEWLINE, os.linesep))
...@@ -29,7 +29,7 @@ parend_expr = patcomp.compile_pattern( ...@@ -29,7 +29,7 @@ parend_expr = patcomp.compile_pattern(
class FixPrint(fixer_base.ConditionalFix): class FixPrint(fixer_base.ConditionalFix):
PATTERN = """ PATTERN = """
simple_stmt< bare='print' any > | print_stmt simple_stmt< any* bare='print' any* > | print_stmt
""" """
skip_on = '__future__.print_function' skip_on = '__future__.print_function'
......
# Python 2's Lib/test/test_grammar.py (r54061) # Python 2's Lib/test/test_grammar.py (r66189)
# Python test set -- part 1, grammar. # Python test set -- part 1, grammar.
# This just tests whether the parser accepts them all. # This just tests whether the parser accepts them all.
...@@ -30,13 +30,15 @@ class TokenTests(unittest.TestCase): ...@@ -30,13 +30,15 @@ class TokenTests(unittest.TestCase):
def testPlainIntegers(self): def testPlainIntegers(self):
self.assertEquals(0xff, 255) self.assertEquals(0xff, 255)
self.assertEquals(0o377, 255) self.assertEquals(0377, 255)
self.assertEquals(2147483647, 0o17777777777) self.assertEquals(2147483647, 017777777777)
from sys import maxsize # "0x" is not a valid literal
self.assertRaises(SyntaxError, eval, "0x")
from sys import maxint
if maxint == 2147483647: if maxint == 2147483647:
self.assertEquals(-2147483647-1, -0o20000000000) self.assertEquals(-2147483647-1, -020000000000)
# XXX -2147483648 # XXX -2147483648
self.assert_(0o37777777777 > 0) self.assert_(037777777777 > 0)
self.assert_(0xffffffff > 0) self.assert_(0xffffffff > 0)
for s in '2147483648', '040000000000', '0x100000000': for s in '2147483648', '040000000000', '0x100000000':
try: try:
...@@ -44,8 +46,8 @@ class TokenTests(unittest.TestCase): ...@@ -44,8 +46,8 @@ class TokenTests(unittest.TestCase):
except OverflowError: except OverflowError:
self.fail("OverflowError on huge integer literal %r" % s) self.fail("OverflowError on huge integer literal %r" % s)
elif maxint == 9223372036854775807: elif maxint == 9223372036854775807:
self.assertEquals(-9223372036854775807-1, -0o1000000000000000000000) self.assertEquals(-9223372036854775807-1, -01000000000000000000000)
self.assert_(0o1777777777777777777777 > 0) self.assert_(01777777777777777777777 > 0)
self.assert_(0xffffffffffffffff > 0) self.assert_(0xffffffffffffffff > 0)
for s in '9223372036854775808', '02000000000000000000000', \ for s in '9223372036854775808', '02000000000000000000000', \
'0x10000000000000000': '0x10000000000000000':
...@@ -57,14 +59,14 @@ class TokenTests(unittest.TestCase): ...@@ -57,14 +59,14 @@ class TokenTests(unittest.TestCase):
self.fail('Weird maxint value %r' % maxint) self.fail('Weird maxint value %r' % maxint)
def testLongIntegers(self): def testLongIntegers(self):
x = 0 x = 0L
x = 0 x = 0l
x = 0xffffffffffffffff x = 0xffffffffffffffffL
x = 0xffffffffffffffff x = 0xffffffffffffffffl
x = 0o77777777777777777 x = 077777777777777777L
x = 0o77777777777777777 x = 077777777777777777l
x = 123456789012345678901234567890 x = 123456789012345678901234567890L
x = 123456789012345678901234567890 x = 123456789012345678901234567890l
def testFloats(self): def testFloats(self):
x = 3.14 x = 3.14
...@@ -152,27 +154,27 @@ class GrammarTests(unittest.TestCase): ...@@ -152,27 +154,27 @@ class GrammarTests(unittest.TestCase):
f1(*(), **{}) f1(*(), **{})
def f2(one_argument): pass def f2(one_argument): pass
def f3(two, arguments): pass def f3(two, arguments): pass
def f4(two, xxx_todo_changeme): (compound, (argument, list)) = xxx_todo_changeme; pass def f4(two, (compound, (argument, list))): pass
def f5(xxx_todo_changeme1, two): (compound, first) = xxx_todo_changeme1; pass def f5((compound, first), two): pass
self.assertEquals(f2.__code__.co_varnames, ('one_argument',)) self.assertEquals(f2.func_code.co_varnames, ('one_argument',))
self.assertEquals(f3.__code__.co_varnames, ('two', 'arguments')) self.assertEquals(f3.func_code.co_varnames, ('two', 'arguments'))
if sys.platform.startswith('java'): if sys.platform.startswith('java'):
self.assertEquals(f4.__code__.co_varnames, self.assertEquals(f4.func_code.co_varnames,
('two', '(compound, (argument, list))', 'compound', 'argument', ('two', '(compound, (argument, list))', 'compound', 'argument',
'list',)) 'list',))
self.assertEquals(f5.__code__.co_varnames, self.assertEquals(f5.func_code.co_varnames,
('(compound, first)', 'two', 'compound', 'first')) ('(compound, first)', 'two', 'compound', 'first'))
else: else:
self.assertEquals(f4.__code__.co_varnames, self.assertEquals(f4.func_code.co_varnames,
('two', '.1', 'compound', 'argument', 'list')) ('two', '.1', 'compound', 'argument', 'list'))
self.assertEquals(f5.__code__.co_varnames, self.assertEquals(f5.func_code.co_varnames,
('.0', 'two', 'compound', 'first')) ('.0', 'two', 'compound', 'first'))
def a1(one_arg,): pass def a1(one_arg,): pass
def a2(two, args,): pass def a2(two, args,): pass
def v0(*rest): pass def v0(*rest): pass
def v1(a, *rest): pass def v1(a, *rest): pass
def v2(a, b, *rest): pass def v2(a, b, *rest): pass
def v3(a, xxx_todo_changeme2, *rest): (b, c) = xxx_todo_changeme2; return a, b, c, rest def v3(a, (b, c), *rest): return a, b, c, rest
f1() f1()
f2(1) f2(1)
...@@ -201,9 +203,9 @@ class GrammarTests(unittest.TestCase): ...@@ -201,9 +203,9 @@ class GrammarTests(unittest.TestCase):
# ceval unpacks the formal arguments into the first argcount names; # ceval unpacks the formal arguments into the first argcount names;
# thus, the names nested inside tuples must appear after these names. # thus, the names nested inside tuples must appear after these names.
if sys.platform.startswith('java'): if sys.platform.startswith('java'):
self.assertEquals(v3.__code__.co_varnames, ('a', '(b, c)', 'rest', 'b', 'c')) self.assertEquals(v3.func_code.co_varnames, ('a', '(b, c)', 'rest', 'b', 'c'))
else: else:
self.assertEquals(v3.__code__.co_varnames, ('a', '.1', 'rest', 'b', 'c')) self.assertEquals(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c'))
self.assertEquals(v3(1, (2, 3), 4), (1, 2, 3, (4,))) self.assertEquals(v3(1, (2, 3), 4), (1, 2, 3, (4,)))
def d01(a=1): pass def d01(a=1): pass
d01() d01()
...@@ -277,17 +279,29 @@ class GrammarTests(unittest.TestCase): ...@@ -277,17 +279,29 @@ class GrammarTests(unittest.TestCase):
d22v(*(1, 2, 3, 4)) d22v(*(1, 2, 3, 4))
d22v(1, 2, *(3, 4, 5)) d22v(1, 2, *(3, 4, 5))
d22v(1, *(2, 3), **{'d': 4}) d22v(1, *(2, 3), **{'d': 4})
def d31v(xxx_todo_changeme3): (x) = xxx_todo_changeme3; pass def d31v((x)): pass
d31v(1) d31v(1)
def d32v(xxx_todo_changeme4): (x,) = xxx_todo_changeme4; pass def d32v((x,)): pass
d32v((1,)) d32v((1,))
# keyword arguments after *arglist
def f(*args, **kwargs):
return args, kwargs
self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4),
{'x':2, 'y':5}))
self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)")
self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)")
# Check ast errors in *args and *kwargs
check_syntax_error(self, "f(*g(1=2))")
check_syntax_error(self, "f(**g(1=2))")
def testLambdef(self): def testLambdef(self):
### lambdef: 'lambda' [varargslist] ':' test ### lambdef: 'lambda' [varargslist] ':' test
l1 = lambda : 0 l1 = lambda : 0
self.assertEquals(l1(), 0) self.assertEquals(l1(), 0)
l2 = lambda : a[d] # XXX just testing the expression l2 = lambda : a[d] # XXX just testing the expression
l3 = lambda : [2 < x for x in [-1, 3, 0]] l3 = lambda : [2 < x for x in [-1, 3, 0L]]
self.assertEquals(l3(), [0, 1, 0]) self.assertEquals(l3(), [0, 1, 0])
l4 = lambda x = lambda y = lambda z=1 : z : y() : x() l4 = lambda x = lambda y = lambda z=1 : z : y() : x()
self.assertEquals(l4(), 1) self.assertEquals(l4(), 1)
...@@ -295,6 +309,7 @@ class GrammarTests(unittest.TestCase): ...@@ -295,6 +309,7 @@ class GrammarTests(unittest.TestCase):
self.assertEquals(l5(1, 2), 5) self.assertEquals(l5(1, 2), 5)
self.assertEquals(l5(1, 2, 3), 6) self.assertEquals(l5(1, 2, 3), 6)
check_syntax_error(self, "lambda x: x = 2") check_syntax_error(self, "lambda x: x = 2")
check_syntax_error(self, "lambda (None,): None")
### stmt: simple_stmt | compound_stmt ### stmt: simple_stmt | compound_stmt
# Tested below # Tested below
...@@ -325,36 +340,36 @@ class GrammarTests(unittest.TestCase): ...@@ -325,36 +340,36 @@ class GrammarTests(unittest.TestCase):
def testPrintStmt(self): def testPrintStmt(self):
# 'print' (test ',')* [test] # 'print' (test ',')* [test]
import io import StringIO
# Can't test printing to real stdout without comparing output # Can't test printing to real stdout without comparing output
# which is not available in unittest. # which is not available in unittest.
save_stdout = sys.stdout save_stdout = sys.stdout
sys.stdout = io.StringIO() sys.stdout = StringIO.StringIO()
print(1, 2, 3) print 1, 2, 3
print(1, 2, 3, end=' ') print 1, 2, 3,
print() print
print(0 or 1, 0 or 1, end=' ') print 0 or 1, 0 or 1,
print(0 or 1) print 0 or 1
# 'print' '>>' test ',' # 'print' '>>' test ','
print(1, 2, 3, file=sys.stdout) print >> sys.stdout, 1, 2, 3
print(1, 2, 3, end=' ', file=sys.stdout) print >> sys.stdout, 1, 2, 3,
print(file=sys.stdout) print >> sys.stdout
print(0 or 1, 0 or 1, end=' ', file=sys.stdout) print >> sys.stdout, 0 or 1, 0 or 1,
print(0 or 1, file=sys.stdout) print >> sys.stdout, 0 or 1
# test printing to an instance # test printing to an instance
class Gulp: class Gulp:
def write(self, msg): pass def write(self, msg): pass
gulp = Gulp() gulp = Gulp()
print(1, 2, 3, file=gulp) print >> gulp, 1, 2, 3
print(1, 2, 3, end=' ', file=gulp) print >> gulp, 1, 2, 3,
print(file=gulp) print >> gulp
print(0 or 1, 0 or 1, end=' ', file=gulp) print >> gulp, 0 or 1, 0 or 1,
print(0 or 1, file=gulp) print >> gulp, 0 or 1
# test print >> None # test print >> None
def driver(): def driver():
...@@ -368,13 +383,13 @@ class GrammarTests(unittest.TestCase): ...@@ -368,13 +383,13 @@ class GrammarTests(unittest.TestCase):
# we should see this once # we should see this once
def tellme(file=sys.stdout): def tellme(file=sys.stdout):
print('hello world', file=file) print >> file, 'hello world'
driver() driver()
# we should not see this at all # we should not see this at all
def tellme(file=None): def tellme(file=None):
print('goodbye universe', file=file) print >> file, 'goodbye universe'
driver() driver()
...@@ -461,7 +476,7 @@ hello world ...@@ -461,7 +476,7 @@ hello world
continue continue
except: except:
raise raise
if count > 2 or big_hippo != 1: if count > 2 or big_hippo <> 1:
self.fail("continue then break in try/except in loop broken!") self.fail("continue then break in try/except in loop broken!")
test_inner() test_inner()
...@@ -478,7 +493,7 @@ hello world ...@@ -478,7 +493,7 @@ hello world
def testRaise(self): def testRaise(self):
# 'raise' test [',' test] # 'raise' test [',' test]
try: raise RuntimeError('just testing') try: raise RuntimeError, 'just testing'
except RuntimeError: pass except RuntimeError: pass
try: raise KeyboardInterrupt try: raise KeyboardInterrupt
except KeyboardInterrupt: pass except KeyboardInterrupt: pass
...@@ -506,33 +521,33 @@ hello world ...@@ -506,33 +521,33 @@ hello world
# 'exec' expr ['in' expr [',' expr]] # 'exec' expr ['in' expr [',' expr]]
z = None z = None
del z del z
exec('z=1+1\n') exec 'z=1+1\n'
if z != 2: self.fail('exec \'z=1+1\'\\n') if z != 2: self.fail('exec \'z=1+1\'\\n')
del z del z
exec('z=1+1') exec 'z=1+1'
if z != 2: self.fail('exec \'z=1+1\'') if z != 2: self.fail('exec \'z=1+1\'')
z = None z = None
del z del z
import types import types
if hasattr(types, "UnicodeType"): if hasattr(types, "UnicodeType"):
exec(r"""if 1: exec r"""if 1:
exec u'z=1+1\n' exec u'z=1+1\n'
if z != 2: self.fail('exec u\'z=1+1\'\\n') if z != 2: self.fail('exec u\'z=1+1\'\\n')
del z del z
exec u'z=1+1' exec u'z=1+1'
if z != 2: self.fail('exec u\'z=1+1\'')""") if z != 2: self.fail('exec u\'z=1+1\'')"""
g = {} g = {}
exec('z = 1', g) exec 'z = 1' in g
if '__builtins__' in g: del g['__builtins__'] if g.has_key('__builtins__'): del g['__builtins__']
if g != {'z': 1}: self.fail('exec \'z = 1\' in g') if g != {'z': 1}: self.fail('exec \'z = 1\' in g')
g = {} g = {}
l = {} l = {}
import warnings import warnings
warnings.filterwarnings("ignore", "global statement", module="<string>") warnings.filterwarnings("ignore", "global statement", module="<string>")
exec('global a; a = 1; b = 2', g, l) exec 'global a; a = 1; b = 2' in g, l
if '__builtins__' in g: del g['__builtins__'] if g.has_key('__builtins__'): del g['__builtins__']
if '__builtins__' in l: del l['__builtins__'] if l.has_key('__builtins__'): del l['__builtins__']
if (g, l) != ({'a':1}, {'b':2}): if (g, l) != ({'a':1}, {'b':2}):
self.fail('exec ... in g (%s), l (%s)' %(g,l)) self.fail('exec ... in g (%s), l (%s)' %(g,l))
...@@ -544,7 +559,7 @@ hello world ...@@ -544,7 +559,7 @@ hello world
assert 1, lambda x:x+1 assert 1, lambda x:x+1
try: try:
assert 0, "msg" assert 0, "msg"
except AssertionError as e: except AssertionError, e:
self.assertEquals(e.args[0], "msg") self.assertEquals(e.args[0], "msg")
else: else:
if __debug__: if __debug__:
...@@ -572,6 +587,15 @@ hello world ...@@ -572,6 +587,15 @@ hello world
while 0: pass while 0: pass
else: pass else: pass
# Issue1920: "while 0" is optimized away,
# ensure that the "else" clause is still present.
x = 0
while 0:
x = 1
else:
x = 2
self.assertEquals(x, 2)
def testFor(self): def testFor(self):
# 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
for i in 1, 2, 3: pass for i in 1, 2, 3: pass
...@@ -602,7 +626,7 @@ hello world ...@@ -602,7 +626,7 @@ hello world
def testTry(self): def testTry(self):
### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] ### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
### | 'try' ':' suite 'finally' ':' suite ### | 'try' ':' suite 'finally' ':' suite
### except_clause: 'except' [expr [',' expr]] ### except_clause: 'except' [expr [('as' | ',') expr]]
try: try:
1/0 1/0
except ZeroDivisionError: except ZeroDivisionError:
...@@ -611,7 +635,7 @@ hello world ...@@ -611,7 +635,7 @@ hello world
pass pass
try: 1/0 try: 1/0
except EOFError: pass except EOFError: pass
except TypeError, msg: pass except TypeError as msg: pass
except RuntimeError, msg: pass except RuntimeError, msg: pass
except: pass except: pass
else: pass else: pass
...@@ -655,7 +679,7 @@ hello world ...@@ -655,7 +679,7 @@ hello world
x = (1 == 1) x = (1 == 1)
if 1 == 1: pass if 1 == 1: pass
if 1 != 1: pass if 1 != 1: pass
if 1 != 1: pass if 1 <> 1: pass
if 1 < 1: pass if 1 < 1: pass
if 1 > 1: pass if 1 > 1: pass
if 1 <= 1: pass if 1 <= 1: pass
...@@ -664,7 +688,7 @@ hello world ...@@ -664,7 +688,7 @@ hello world
if 1 is not 1: pass if 1 is not 1: pass
if 1 in (): pass if 1 in (): pass
if 1 not in (): pass if 1 not in (): pass
if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 != 1 in 1 not in 1 is 1 is not 1: pass if 1 < 1 > 1 == 1 >= 1 <= 1 <> 1 != 1 in 1 not in 1 is 1 is not 1: pass
def testBinaryMaskOps(self): def testBinaryMaskOps(self):
x = 1 & 1 x = 1 & 1
...@@ -747,9 +771,9 @@ hello world ...@@ -747,9 +771,9 @@ hello world
x = {'one': 1, 'two': 2,} x = {'one': 1, 'two': 2,}
x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6} x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6}
x = repr(x) x = `x`
x = repr(1 or 2 or 3) x = `1 or 2 or 3`
self.assertEqual(repr((1,2)), '(1, 2)') self.assertEqual(`1,2`, '(1, 2)')
x = x x = x
x = 'x' x = 'x'
...@@ -770,6 +794,16 @@ hello world ...@@ -770,6 +794,16 @@ hello world
def meth1(self): pass def meth1(self): pass
def meth2(self, arg): pass def meth2(self, arg): pass
def meth3(self, a1, a2): pass def meth3(self, a1, a2): pass
# decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
# decorators: decorator+
# decorated: decorators (classdef | funcdef)
def class_decorator(x):
x.decorated = True
return x
@class_decorator
class G:
pass
self.assertEqual(G.decorated, True)
def testListcomps(self): def testListcomps(self):
# list comprehension tests # list comprehension tests
...@@ -837,9 +871,9 @@ hello world ...@@ -837,9 +871,9 @@ hello world
def testGenexps(self): def testGenexps(self):
# generator expression tests # generator expression tests
g = ([x for x in range(10)] for x in range(1)) g = ([x for x in range(10)] for x in range(1))
self.assertEqual(next(g), [x for x in range(10)]) self.assertEqual(g.next(), [x for x in range(10)])
try: try:
next(g) g.next()
self.fail('should produce StopIteration exception') self.fail('should produce StopIteration exception')
except StopIteration: except StopIteration:
pass pass
...@@ -847,7 +881,7 @@ hello world ...@@ -847,7 +881,7 @@ hello world
a = 1 a = 1
try: try:
g = (a for d in a) g = (a for d in a)
next(g) g.next()
self.fail('should produce TypeError') self.fail('should produce TypeError')
except TypeError: except TypeError:
pass pass
...@@ -892,7 +926,7 @@ hello world ...@@ -892,7 +926,7 @@ hello world
# Test ifelse expressions in various cases # Test ifelse expressions in various cases
def _checkeval(msg, ret): def _checkeval(msg, ret):
"helper to check that evaluation of expressions is done correctly" "helper to check that evaluation of expressions is done correctly"
print(x) print x
return ret return ret
self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True]) self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# regression test, the filterwarnings() call has been added to # regression test, the filterwarnings() call has been added to
# regrtest.py. # regrtest.py.
from test.test_support import run_unittest, check_syntax_error from test.support import run_unittest, check_syntax_error
import unittest import unittest
import sys import sys
# testing import * # testing import *
...@@ -32,8 +32,10 @@ class TokenTests(unittest.TestCase): ...@@ -32,8 +32,10 @@ class TokenTests(unittest.TestCase):
self.assertEquals(0o377, 255) self.assertEquals(0o377, 255)
self.assertEquals(2147483647, 0o17777777777) self.assertEquals(2147483647, 0o17777777777)
self.assertEquals(0b1001, 9) self.assertEquals(0b1001, 9)
# "0x" is not a valid literal
self.assertRaises(SyntaxError, eval, "0x")
from sys import maxsize from sys import maxsize
if maxint == 2147483647: if maxsize == 2147483647:
self.assertEquals(-2147483647-1, -0o20000000000) self.assertEquals(-2147483647-1, -0o20000000000)
# XXX -2147483648 # XXX -2147483648
self.assert_(0o37777777777 > 0) self.assert_(0o37777777777 > 0)
...@@ -45,7 +47,7 @@ class TokenTests(unittest.TestCase): ...@@ -45,7 +47,7 @@ class TokenTests(unittest.TestCase):
x = eval(s) x = eval(s)
except OverflowError: except OverflowError:
self.fail("OverflowError on huge integer literal %r" % s) self.fail("OverflowError on huge integer literal %r" % s)
elif maxint == 9223372036854775807: elif maxsize == 9223372036854775807:
self.assertEquals(-9223372036854775807-1, -0o1000000000000000000000) self.assertEquals(-9223372036854775807-1, -0o1000000000000000000000)
self.assert_(0o1777777777777777777777 > 0) self.assert_(0o1777777777777777777777 > 0)
self.assert_(0xffffffffffffffff > 0) self.assert_(0xffffffffffffffff > 0)
...@@ -58,7 +60,7 @@ class TokenTests(unittest.TestCase): ...@@ -58,7 +60,7 @@ class TokenTests(unittest.TestCase):
except OverflowError: except OverflowError:
self.fail("OverflowError on huge integer literal %r" % s) self.fail("OverflowError on huge integer literal %r" % s)
else: else:
self.fail('Weird maxint value %r' % maxint) self.fail('Weird maxsize value %r' % maxsize)
def testLongIntegers(self): def testLongIntegers(self):
x = 0 x = 0
...@@ -263,6 +265,14 @@ class GrammarTests(unittest.TestCase): ...@@ -263,6 +265,14 @@ class GrammarTests(unittest.TestCase):
d22v(*(1, 2, 3, 4)) d22v(*(1, 2, 3, 4))
d22v(1, 2, *(3, 4, 5)) d22v(1, 2, *(3, 4, 5))
d22v(1, *(2, 3), **{'d': 4}) d22v(1, *(2, 3), **{'d': 4})
# keyword argument type tests
try:
str('x', **{b'foo':1 })
except TypeError:
pass
else:
self.fail('Bytes should not work as keyword argument names')
# keyword only argument tests # keyword only argument tests
def pos0key1(*, key): return key def pos0key1(*, key): return key
pos0key1(key=100) pos0key1(key=100)
...@@ -274,6 +284,14 @@ class GrammarTests(unittest.TestCase): ...@@ -274,6 +284,14 @@ class GrammarTests(unittest.TestCase):
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200) pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100) pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
# keyword arguments after *arglist
def f(*args, **kwargs):
return args, kwargs
self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4),
{'x':2, 'y':5}))
self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)")
self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)")
# argument annotation tests # argument annotation tests
def f(x) -> list: pass def f(x) -> list: pass
self.assertEquals(f.__annotations__, {'return': list}) self.assertEquals(f.__annotations__, {'return': list})
...@@ -308,6 +326,10 @@ class GrammarTests(unittest.TestCase): ...@@ -308,6 +326,10 @@ class GrammarTests(unittest.TestCase):
def f(*, k=1): return closure def f(*, k=1): return closure
def f() -> int: return closure def f() -> int: return closure
# Check ast errors in *args and *kwargs
check_syntax_error(self, "f(*g(1=2))")
check_syntax_error(self, "f(**g(1=2))")
def testLambdef(self): def testLambdef(self):
### lambdef: 'lambda' [varargslist] ':' test ### lambdef: 'lambda' [varargslist] ':' test
l1 = lambda : 0 l1 = lambda : 0
...@@ -321,6 +343,7 @@ class GrammarTests(unittest.TestCase): ...@@ -321,6 +343,7 @@ class GrammarTests(unittest.TestCase):
self.assertEquals(l5(1, 2), 5) self.assertEquals(l5(1, 2), 5)
self.assertEquals(l5(1, 2, 3), 6) self.assertEquals(l5(1, 2, 3), 6)
check_syntax_error(self, "lambda x: x = 2") check_syntax_error(self, "lambda x: x = 2")
check_syntax_error(self, "lambda (None,): None")
l6 = lambda x, y, *, k=20: x+y+k l6 = lambda x, y, *, k=20: x+y+k
self.assertEquals(l6(1,2), 1+2+20) self.assertEquals(l6(1,2), 1+2+20)
self.assertEquals(l6(1,2,k=10), 1+2+10) self.assertEquals(l6(1,2,k=10), 1+2+10)
...@@ -498,6 +521,15 @@ class GrammarTests(unittest.TestCase): ...@@ -498,6 +521,15 @@ class GrammarTests(unittest.TestCase):
while 0: pass while 0: pass
else: pass else: pass
# Issue1920: "while 0" is optimized away,
# ensure that the "else" clause is still present.
x = 0
while 0:
x = 1
else:
x = 2
self.assertEquals(x, 2)
def testFor(self): def testFor(self):
# 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
for i in 1, 2, 3: pass for i in 1, 2, 3: pass
......
...@@ -385,6 +385,16 @@ class Test_print(FixerTestCase): ...@@ -385,6 +385,16 @@ class Test_print(FixerTestCase):
a = """print()""" a = """print()"""
self.check(b, a) self.check(b, a)
def test_4(self):
# from bug 3000
b = """print whatever; print"""
a = """print(whatever); print()"""
self.check(b, a)
def test_5(self):
b = """print; print whatever;"""
a = """print(); print(whatever);"""
def test_tuple(self): def test_tuple(self):
b = """print (a, b, c)""" b = """print (a, b, c)"""
a = """print((a, b, c))""" a = """print((a, b, c))"""
...@@ -2379,6 +2389,15 @@ class Test_numliterals(FixerTestCase): ...@@ -2379,6 +2389,15 @@ class Test_numliterals(FixerTestCase):
a = """b = 0x12""" a = """b = 0x12"""
self.check(b, a) self.check(b, a)
def test_comments_and_spacing(self):
b = """b = 0x12L"""
a = """b = 0x12"""
self.check(b, a)
b = """b = 0755 # spam"""
a = """b = 0o755 # spam"""
self.check(b, a)
def test_unchanged_int(self): def test_unchanged_int(self):
s = """5""" s = """5"""
self.unchanged(s) self.unchanged(s)
...@@ -3430,6 +3449,133 @@ class Test_paren(FixerTestCase): ...@@ -3430,6 +3449,133 @@ class Test_paren(FixerTestCase):
s = """[i for i in m]""" s = """[i for i in m]"""
self.unchanged(s) self.unchanged(s)
class Test_metaclass(FixerTestCase):
fixer = 'metaclass'
def test_unchanged(self):
self.unchanged("class X(): pass")
self.unchanged("class X(object): pass")
self.unchanged("class X(object1, object2): pass")
self.unchanged("class X(object1, object2, object3): pass")
self.unchanged("class X(metaclass=Meta): pass")
self.unchanged("class X(b, arg=23, metclass=Meta): pass")
self.unchanged("class X(b, arg=23, metaclass=Meta, other=42): pass")
s = """
class X:
def __metaclass__(self): pass
"""
self.unchanged(s)
def test_comments(self):
b = """
class X:
# hi
__metaclass__ = AppleMeta
"""
a = """
class X(metaclass=AppleMeta):
# hi
pass
"""
self.check(b, a)
b = """
class X:
__metaclass__ = Meta
# Bedtime!
"""
a = """
class X(metaclass=Meta):
pass
# Bedtime!
"""
self.check(b, a)
def test_meta(self):
# no-parent class, odd body
b = """
class X():
__metaclass__ = Q
pass
"""
a = """
class X(metaclass=Q):
pass
"""
self.check(b, a)
# one parent class, no body
b = """class X(object): __metaclass__ = Q"""
a = """class X(object, metaclass=Q): pass"""
self.check(b, a)
# one parent, simple body
b = """
class X(object):
__metaclass__ = Meta
bar = 7
"""
a = """
class X(object, metaclass=Meta):
bar = 7
"""
self.check(b, a)
b = """
class X:
__metaclass__ = Meta; x = 4; g = 23
"""
a = """
class X(metaclass=Meta):
x = 4; g = 23
"""
self.check(b, a)
# one parent, simple body, __metaclass__ last
b = """
class X(object):
bar = 7
__metaclass__ = Meta
"""
a = """
class X(object, metaclass=Meta):
bar = 7
"""
self.check(b, a)
# redefining __metaclass__
b = """
class X():
__metaclass__ = A
__metaclass__ = B
bar = 7
"""
a = """
class X(metaclass=B):
bar = 7
"""
self.check(b, a)
# multiple inheritance, simple body
b = """
class X(clsA, clsB):
__metaclass__ = Meta
bar = 7
"""
a = """
class X(clsA, clsB, metaclass=Meta):
bar = 7
"""
self.check(b, a)
# keywords in the class statement
b = """class m(a, arg=23): __metaclass__ = Meta"""
a = """class m(a, arg=23, metaclass=Meta): pass"""
self.check(b, a)
if __name__ == "__main__": if __name__ == "__main__":
import __main__ import __main__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment