mirror of https://github.com/python/cpython
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 ........ ................
This commit is contained in:
parent
c575c90647
commit
3a2fb1444a
|
@ -138,7 +138,9 @@ dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
|
|||
|
||||
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
|
||||
|
||||
comp_iter: comp_for | comp_if
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
"""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(
|
|||
class FixPrint(fixer_base.ConditionalFix):
|
||||
|
||||
PATTERN = """
|
||||
simple_stmt< bare='print' any > | print_stmt
|
||||
simple_stmt< any* bare='print' any* > | print_stmt
|
||||
"""
|
||||
|
||||
skip_on = '__future__.print_function'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Python 2's Lib/test/test_grammar.py (r54061)
|
||||
# Python 2's Lib/test/test_grammar.py (r66189)
|
||||
|
||||
# Python test set -- part 1, grammar.
|
||||
# This just tests whether the parser accepts them all.
|
||||
|
@ -30,13 +30,15 @@ class TokenTests(unittest.TestCase):
|
|||
|
||||
def testPlainIntegers(self):
|
||||
self.assertEquals(0xff, 255)
|
||||
self.assertEquals(0o377, 255)
|
||||
self.assertEquals(2147483647, 0o17777777777)
|
||||
from sys import maxsize
|
||||
self.assertEquals(0377, 255)
|
||||
self.assertEquals(2147483647, 017777777777)
|
||||
# "0x" is not a valid literal
|
||||
self.assertRaises(SyntaxError, eval, "0x")
|
||||
from sys import maxint
|
||||
if maxint == 2147483647:
|
||||
self.assertEquals(-2147483647-1, -0o20000000000)
|
||||
self.assertEquals(-2147483647-1, -020000000000)
|
||||
# XXX -2147483648
|
||||
self.assert_(0o37777777777 > 0)
|
||||
self.assert_(037777777777 > 0)
|
||||
self.assert_(0xffffffff > 0)
|
||||
for s in '2147483648', '040000000000', '0x100000000':
|
||||
try:
|
||||
|
@ -44,8 +46,8 @@ class TokenTests(unittest.TestCase):
|
|||
except OverflowError:
|
||||
self.fail("OverflowError on huge integer literal %r" % s)
|
||||
elif maxint == 9223372036854775807:
|
||||
self.assertEquals(-9223372036854775807-1, -0o1000000000000000000000)
|
||||
self.assert_(0o1777777777777777777777 > 0)
|
||||
self.assertEquals(-9223372036854775807-1, -01000000000000000000000)
|
||||
self.assert_(01777777777777777777777 > 0)
|
||||
self.assert_(0xffffffffffffffff > 0)
|
||||
for s in '9223372036854775808', '02000000000000000000000', \
|
||||
'0x10000000000000000':
|
||||
|
@ -57,14 +59,14 @@ class TokenTests(unittest.TestCase):
|
|||
self.fail('Weird maxint value %r' % maxint)
|
||||
|
||||
def testLongIntegers(self):
|
||||
x = 0
|
||||
x = 0
|
||||
x = 0xffffffffffffffff
|
||||
x = 0xffffffffffffffff
|
||||
x = 0o77777777777777777
|
||||
x = 0o77777777777777777
|
||||
x = 123456789012345678901234567890
|
||||
x = 123456789012345678901234567890
|
||||
x = 0L
|
||||
x = 0l
|
||||
x = 0xffffffffffffffffL
|
||||
x = 0xffffffffffffffffl
|
||||
x = 077777777777777777L
|
||||
x = 077777777777777777l
|
||||
x = 123456789012345678901234567890L
|
||||
x = 123456789012345678901234567890l
|
||||
|
||||
def testFloats(self):
|
||||
x = 3.14
|
||||
|
@ -152,27 +154,27 @@ class GrammarTests(unittest.TestCase):
|
|||
f1(*(), **{})
|
||||
def f2(one_argument): pass
|
||||
def f3(two, arguments): pass
|
||||
def f4(two, xxx_todo_changeme): (compound, (argument, list)) = xxx_todo_changeme; pass
|
||||
def f5(xxx_todo_changeme1, two): (compound, first) = xxx_todo_changeme1; pass
|
||||
self.assertEquals(f2.__code__.co_varnames, ('one_argument',))
|
||||
self.assertEquals(f3.__code__.co_varnames, ('two', 'arguments'))
|
||||
def f4(two, (compound, (argument, list))): pass
|
||||
def f5((compound, first), two): pass
|
||||
self.assertEquals(f2.func_code.co_varnames, ('one_argument',))
|
||||
self.assertEquals(f3.func_code.co_varnames, ('two', 'arguments'))
|
||||
if sys.platform.startswith('java'):
|
||||
self.assertEquals(f4.__code__.co_varnames,
|
||||
self.assertEquals(f4.func_code.co_varnames,
|
||||
('two', '(compound, (argument, list))', 'compound', 'argument',
|
||||
'list',))
|
||||
self.assertEquals(f5.__code__.co_varnames,
|
||||
self.assertEquals(f5.func_code.co_varnames,
|
||||
('(compound, first)', 'two', 'compound', 'first'))
|
||||
else:
|
||||
self.assertEquals(f4.__code__.co_varnames,
|
||||
self.assertEquals(f4.func_code.co_varnames,
|
||||
('two', '.1', 'compound', 'argument', 'list'))
|
||||
self.assertEquals(f5.__code__.co_varnames,
|
||||
self.assertEquals(f5.func_code.co_varnames,
|
||||
('.0', 'two', 'compound', 'first'))
|
||||
def a1(one_arg,): pass
|
||||
def a2(two, args,): pass
|
||||
def v0(*rest): pass
|
||||
def v1(a, *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()
|
||||
f2(1)
|
||||
|
@ -201,9 +203,9 @@ class GrammarTests(unittest.TestCase):
|
|||
# ceval unpacks the formal arguments into the first argcount names;
|
||||
# thus, the names nested inside tuples must appear after these names.
|
||||
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:
|
||||
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,)))
|
||||
def d01(a=1): pass
|
||||
d01()
|
||||
|
@ -277,17 +279,29 @@ class GrammarTests(unittest.TestCase):
|
|||
d22v(*(1, 2, 3, 4))
|
||||
d22v(1, 2, *(3, 4, 5))
|
||||
d22v(1, *(2, 3), **{'d': 4})
|
||||
def d31v(xxx_todo_changeme3): (x) = xxx_todo_changeme3; pass
|
||||
def d31v((x)): pass
|
||||
d31v(1)
|
||||
def d32v(xxx_todo_changeme4): (x,) = xxx_todo_changeme4; pass
|
||||
def d32v((x,)): pass
|
||||
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):
|
||||
### lambdef: 'lambda' [varargslist] ':' test
|
||||
l1 = lambda : 0
|
||||
self.assertEquals(l1(), 0)
|
||||
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])
|
||||
l4 = lambda x = lambda y = lambda z=1 : z : y() : x()
|
||||
self.assertEquals(l4(), 1)
|
||||
|
@ -295,6 +309,7 @@ class GrammarTests(unittest.TestCase):
|
|||
self.assertEquals(l5(1, 2), 5)
|
||||
self.assertEquals(l5(1, 2, 3), 6)
|
||||
check_syntax_error(self, "lambda x: x = 2")
|
||||
check_syntax_error(self, "lambda (None,): None")
|
||||
|
||||
### stmt: simple_stmt | compound_stmt
|
||||
# Tested below
|
||||
|
@ -325,36 +340,36 @@ class GrammarTests(unittest.TestCase):
|
|||
|
||||
def testPrintStmt(self):
|
||||
# 'print' (test ',')* [test]
|
||||
import io
|
||||
import StringIO
|
||||
|
||||
# Can't test printing to real stdout without comparing output
|
||||
# which is not available in unittest.
|
||||
save_stdout = sys.stdout
|
||||
sys.stdout = io.StringIO()
|
||||
sys.stdout = StringIO.StringIO()
|
||||
|
||||
print(1, 2, 3)
|
||||
print(1, 2, 3, end=' ')
|
||||
print()
|
||||
print(0 or 1, 0 or 1, end=' ')
|
||||
print(0 or 1)
|
||||
print 1, 2, 3
|
||||
print 1, 2, 3,
|
||||
print
|
||||
print 0 or 1, 0 or 1,
|
||||
print 0 or 1
|
||||
|
||||
# 'print' '>>' test ','
|
||||
print(1, 2, 3, file=sys.stdout)
|
||||
print(1, 2, 3, end=' ', file=sys.stdout)
|
||||
print(file=sys.stdout)
|
||||
print(0 or 1, 0 or 1, end=' ', file=sys.stdout)
|
||||
print(0 or 1, file=sys.stdout)
|
||||
print >> sys.stdout, 1, 2, 3
|
||||
print >> sys.stdout, 1, 2, 3,
|
||||
print >> sys.stdout
|
||||
print >> sys.stdout, 0 or 1, 0 or 1,
|
||||
print >> sys.stdout, 0 or 1
|
||||
|
||||
# test printing to an instance
|
||||
class Gulp:
|
||||
def write(self, msg): pass
|
||||
|
||||
gulp = Gulp()
|
||||
print(1, 2, 3, file=gulp)
|
||||
print(1, 2, 3, end=' ', file=gulp)
|
||||
print(file=gulp)
|
||||
print(0 or 1, 0 or 1, end=' ', file=gulp)
|
||||
print(0 or 1, file=gulp)
|
||||
print >> gulp, 1, 2, 3
|
||||
print >> gulp, 1, 2, 3,
|
||||
print >> gulp
|
||||
print >> gulp, 0 or 1, 0 or 1,
|
||||
print >> gulp, 0 or 1
|
||||
|
||||
# test print >> None
|
||||
def driver():
|
||||
|
@ -368,13 +383,13 @@ class GrammarTests(unittest.TestCase):
|
|||
|
||||
# we should see this once
|
||||
def tellme(file=sys.stdout):
|
||||
print('hello world', file=file)
|
||||
print >> file, 'hello world'
|
||||
|
||||
driver()
|
||||
|
||||
# we should not see this at all
|
||||
def tellme(file=None):
|
||||
print('goodbye universe', file=file)
|
||||
print >> file, 'goodbye universe'
|
||||
|
||||
driver()
|
||||
|
||||
|
@ -461,7 +476,7 @@ hello world
|
|||
continue
|
||||
except:
|
||||
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!")
|
||||
test_inner()
|
||||
|
||||
|
@ -478,7 +493,7 @@ hello world
|
|||
|
||||
def testRaise(self):
|
||||
# 'raise' test [',' test]
|
||||
try: raise RuntimeError('just testing')
|
||||
try: raise RuntimeError, 'just testing'
|
||||
except RuntimeError: pass
|
||||
try: raise KeyboardInterrupt
|
||||
except KeyboardInterrupt: pass
|
||||
|
@ -506,33 +521,33 @@ hello world
|
|||
# 'exec' expr ['in' expr [',' expr]]
|
||||
z = None
|
||||
del z
|
||||
exec('z=1+1\n')
|
||||
exec 'z=1+1\n'
|
||||
if z != 2: self.fail('exec \'z=1+1\'\\n')
|
||||
del z
|
||||
exec('z=1+1')
|
||||
exec 'z=1+1'
|
||||
if z != 2: self.fail('exec \'z=1+1\'')
|
||||
z = None
|
||||
del z
|
||||
import types
|
||||
if hasattr(types, "UnicodeType"):
|
||||
exec(r"""if 1:
|
||||
exec r"""if 1:
|
||||
exec u'z=1+1\n'
|
||||
if z != 2: self.fail('exec u\'z=1+1\'\\n')
|
||||
del z
|
||||
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 = {}
|
||||
exec('z = 1', g)
|
||||
if '__builtins__' in g: del g['__builtins__']
|
||||
exec 'z = 1' in g
|
||||
if g.has_key('__builtins__'): del g['__builtins__']
|
||||
if g != {'z': 1}: self.fail('exec \'z = 1\' in g')
|
||||
g = {}
|
||||
l = {}
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore", "global statement", module="<string>")
|
||||
exec('global a; a = 1; b = 2', g, l)
|
||||
if '__builtins__' in g: del g['__builtins__']
|
||||
if '__builtins__' in l: del l['__builtins__']
|
||||
exec 'global a; a = 1; b = 2' in g, l
|
||||
if g.has_key('__builtins__'): del g['__builtins__']
|
||||
if l.has_key('__builtins__'): del l['__builtins__']
|
||||
if (g, l) != ({'a':1}, {'b':2}):
|
||||
self.fail('exec ... in g (%s), l (%s)' %(g,l))
|
||||
|
||||
|
@ -544,7 +559,7 @@ hello world
|
|||
assert 1, lambda x:x+1
|
||||
try:
|
||||
assert 0, "msg"
|
||||
except AssertionError as e:
|
||||
except AssertionError, e:
|
||||
self.assertEquals(e.args[0], "msg")
|
||||
else:
|
||||
if __debug__:
|
||||
|
@ -572,6 +587,15 @@ hello world
|
|||
while 0: 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):
|
||||
# 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
|
||||
for i in 1, 2, 3: pass
|
||||
|
@ -602,7 +626,7 @@ hello world
|
|||
def testTry(self):
|
||||
### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
|
||||
### | 'try' ':' suite 'finally' ':' suite
|
||||
### except_clause: 'except' [expr [',' expr]]
|
||||
### except_clause: 'except' [expr [('as' | ',') expr]]
|
||||
try:
|
||||
1/0
|
||||
except ZeroDivisionError:
|
||||
|
@ -611,7 +635,7 @@ hello world
|
|||
pass
|
||||
try: 1/0
|
||||
except EOFError: pass
|
||||
except TypeError, msg: pass
|
||||
except TypeError as msg: pass
|
||||
except RuntimeError, msg: pass
|
||||
except: pass
|
||||
else: pass
|
||||
|
@ -655,7 +679,7 @@ hello world
|
|||
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
|
||||
|
@ -664,7 +688,7 @@ hello world
|
|||
if 1 is not 1: pass
|
||||
if 1 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):
|
||||
x = 1 & 1
|
||||
|
@ -747,9 +771,9 @@ hello world
|
|||
x = {'one': 1, 'two': 2,}
|
||||
x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6}
|
||||
|
||||
x = repr(x)
|
||||
x = repr(1 or 2 or 3)
|
||||
self.assertEqual(repr((1,2)), '(1, 2)')
|
||||
x = `x`
|
||||
x = `1 or 2 or 3`
|
||||
self.assertEqual(`1,2`, '(1, 2)')
|
||||
|
||||
x = x
|
||||
x = 'x'
|
||||
|
@ -770,6 +794,16 @@ hello world
|
|||
def meth1(self): pass
|
||||
def meth2(self, arg): 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):
|
||||
# list comprehension tests
|
||||
|
@ -837,9 +871,9 @@ hello world
|
|||
def testGenexps(self):
|
||||
# generator expression tests
|
||||
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:
|
||||
next(g)
|
||||
g.next()
|
||||
self.fail('should produce StopIteration exception')
|
||||
except StopIteration:
|
||||
pass
|
||||
|
@ -847,7 +881,7 @@ hello world
|
|||
a = 1
|
||||
try:
|
||||
g = (a for d in a)
|
||||
next(g)
|
||||
g.next()
|
||||
self.fail('should produce TypeError')
|
||||
except TypeError:
|
||||
pass
|
||||
|
@ -892,7 +926,7 @@ hello world
|
|||
# Test ifelse expressions in various cases
|
||||
def _checkeval(msg, ret):
|
||||
"helper to check that evaluation of expressions is done correctly"
|
||||
print(x)
|
||||
print x
|
||||
return ret
|
||||
|
||||
self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# regression test, the filterwarnings() call has been added to
|
||||
# regrtest.py.
|
||||
|
||||
from test.test_support import run_unittest, check_syntax_error
|
||||
from test.support import run_unittest, check_syntax_error
|
||||
import unittest
|
||||
import sys
|
||||
# testing import *
|
||||
|
@ -32,8 +32,10 @@ class TokenTests(unittest.TestCase):
|
|||
self.assertEquals(0o377, 255)
|
||||
self.assertEquals(2147483647, 0o17777777777)
|
||||
self.assertEquals(0b1001, 9)
|
||||
# "0x" is not a valid literal
|
||||
self.assertRaises(SyntaxError, eval, "0x")
|
||||
from sys import maxsize
|
||||
if maxint == 2147483647:
|
||||
if maxsize == 2147483647:
|
||||
self.assertEquals(-2147483647-1, -0o20000000000)
|
||||
# XXX -2147483648
|
||||
self.assert_(0o37777777777 > 0)
|
||||
|
@ -45,7 +47,7 @@ class TokenTests(unittest.TestCase):
|
|||
x = eval(s)
|
||||
except OverflowError:
|
||||
self.fail("OverflowError on huge integer literal %r" % s)
|
||||
elif maxint == 9223372036854775807:
|
||||
elif maxsize == 9223372036854775807:
|
||||
self.assertEquals(-9223372036854775807-1, -0o1000000000000000000000)
|
||||
self.assert_(0o1777777777777777777777 > 0)
|
||||
self.assert_(0xffffffffffffffff > 0)
|
||||
|
@ -58,7 +60,7 @@ class TokenTests(unittest.TestCase):
|
|||
except OverflowError:
|
||||
self.fail("OverflowError on huge integer literal %r" % s)
|
||||
else:
|
||||
self.fail('Weird maxint value %r' % maxint)
|
||||
self.fail('Weird maxsize value %r' % maxsize)
|
||||
|
||||
def testLongIntegers(self):
|
||||
x = 0
|
||||
|
@ -263,6 +265,14 @@ class GrammarTests(unittest.TestCase):
|
|||
d22v(*(1, 2, 3, 4))
|
||||
d22v(1, 2, *(3, 4, 5))
|
||||
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
|
||||
def pos0key1(*, key): return key
|
||||
pos0key1(key=100)
|
||||
|
@ -274,6 +284,14 @@ class GrammarTests(unittest.TestCase):
|
|||
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
|
||||
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
|
||||
def f(x) -> list: pass
|
||||
self.assertEquals(f.__annotations__, {'return': list})
|
||||
|
@ -308,6 +326,10 @@ class GrammarTests(unittest.TestCase):
|
|||
def f(*, k=1): 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):
|
||||
### lambdef: 'lambda' [varargslist] ':' test
|
||||
l1 = lambda : 0
|
||||
|
@ -321,6 +343,7 @@ class GrammarTests(unittest.TestCase):
|
|||
self.assertEquals(l5(1, 2), 5)
|
||||
self.assertEquals(l5(1, 2, 3), 6)
|
||||
check_syntax_error(self, "lambda x: x = 2")
|
||||
check_syntax_error(self, "lambda (None,): None")
|
||||
l6 = lambda x, y, *, k=20: x+y+k
|
||||
self.assertEquals(l6(1,2), 1+2+20)
|
||||
self.assertEquals(l6(1,2,k=10), 1+2+10)
|
||||
|
@ -498,6 +521,15 @@ class GrammarTests(unittest.TestCase):
|
|||
while 0: 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):
|
||||
# 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
|
||||
for i in 1, 2, 3: pass
|
||||
|
|
|
@ -385,6 +385,16 @@ class Test_print(FixerTestCase):
|
|||
a = """print()"""
|
||||
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):
|
||||
b = """print (a, b, c)"""
|
||||
a = """print((a, b, c))"""
|
||||
|
@ -2379,6 +2389,15 @@ class Test_numliterals(FixerTestCase):
|
|||
a = """b = 0x12"""
|
||||
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):
|
||||
s = """5"""
|
||||
self.unchanged(s)
|
||||
|
@ -3430,6 +3449,133 @@ class Test_paren(FixerTestCase):
|
|||
s = """[i for i in m]"""
|
||||
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__":
|
||||
import __main__
|
||||
|
|
Loading…
Reference in New Issue