Convert test_global, test_scope and test_grammar to unittest.

I tried to enclose all tests which must be run at the toplevel
(instead of inside a method) in exec statements.
This commit is contained in:
Georg Brandl 2006-10-28 13:10:17 +00:00
parent 3a3d8ea497
commit c6fdec6d7e
8 changed files with 1203 additions and 1228 deletions

View file

@ -379,8 +379,8 @@ test_support provides the following useful objects:
point numbers when you expect them to only be approximately equal point numbers when you expect them to only be approximately equal
withing a fuzz factor (``test_support.FUZZ``, which defaults to 1e-6). withing a fuzz factor (``test_support.FUZZ``, which defaults to 1e-6).
* ``check_syntax(statement)`` - make sure that the statement is *not* * ``check_syntax_error(testcase, statement)`` - make sure that the
correct Python syntax. statement is *not* correct Python syntax.
Python and C statement coverage results are currently available at Python and C statement coverage results are currently available at

View file

@ -1,5 +0,0 @@
test_global
got SyntaxError as expected
got SyntaxError as expected
got SyntaxError as expected
as expected, no SyntaxError

View file

@ -1,69 +0,0 @@
test_grammar
1. Parser
1.1 Tokens
1.1.1 Backslashes
1.1.2 Numeric literals
1.1.2.1 Plain integers
1.1.2.2 Long integers
1.1.2.3 Floating point
1.1.3 String literals
1.2 Grammar
single_input
file_input
expr_input
eval_input
funcdef
lambdef
simple_stmt
expr_stmt
print_stmt
1 2 3
1 2 3
1 1 1
extended print_stmt
1 2 3
1 2 3
1 1 1
hello world
del_stmt
pass_stmt
flow_stmt
break_stmt
continue_stmt
continue + try/except ok
continue + try/finally ok
testing continue and break in try/except in loop
return_stmt
yield_stmt
raise_stmt
import_name
import_from
global_stmt
exec_stmt
assert_stmt
if_stmt
while_stmt
for_stmt
try_stmt
suite
test
comparison
binary mask ops
shift ops
additive ops
multiplicative ops
unary ops
selectors
[1, (1,), (1, 2), (1, 2, 3)]
atoms
classdef
['Apple', 'Banana', 'Coco nut']
[3, 6, 9, 12, 15]
[3, 4, 5]
[(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]
[(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), (5, 'Banana'), (5, 'Coconut')]
[[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]
[False, False, False]
[[1, 2], [3, 4], [5, 6]]
[('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')]

View file

@ -1,24 +0,0 @@
test_scope
1. simple nesting
2. extra nesting
3. simple nesting + rebinding
4. nesting with global but no free
5. nesting through class
6. nesting plus free ref to global
7. nearest enclosing scope
8. mixed freevars and cellvars
9. free variable in method
10. recursion
11. unoptimized namespaces
12. lambdas
13. UnboundLocal
14. complex definitions
15. scope of global statements
16. check leaks
17. class and global
18. verify that locals() works
19. var is bound and free in class
20. interaction with trace function
20. eval and exec with free variables
21. list comprehension with local variables
22. eval with free variables

View file

@ -1,51 +1,51 @@
"""Verify that warnings are issued for global statements following use.""" """Verify that warnings are issued for global statements following use."""
from test.test_support import check_syntax from test.test_support import run_unittest, check_syntax_error
import unittest
import warnings import warnings
warnings.filterwarnings("error", module="<test string>")
warnings.filterwarnings("error", module="<test code>") class GlobalTests(unittest.TestCase):
def compile_and_check(text, should_fail=1): def test1(self):
try: prog_text_1 = """\
compile(text, "<test code>", "exec")
except SyntaxError, msg:
if should_fail:
print "got SyntaxError as expected"
else:
print "raised unexpected SyntaxError:", text
else:
if should_fail:
print "should have raised SyntaxError:", text
else:
print "as expected, no SyntaxError"
prog_text_1 = """
def wrong1(): def wrong1():
a = 1 a = 1
b = 2 b = 2
global a global a
global b global b
""" """
compile_and_check(prog_text_1) check_syntax_error(self, prog_text_1)
prog_text_2 = """ def test2(self):
prog_text_2 = """\
def wrong2(): def wrong2():
print x print x
global x global x
""" """
compile_and_check(prog_text_2) check_syntax_error(self, prog_text_2)
prog_text_3 = """ def test3(self):
prog_text_3 = """\
def wrong3(): def wrong3():
print x print x
x = 2 x = 2
global x global x
""" """
compile_and_check(prog_text_3) check_syntax_error(self, prog_text_3)
prog_text_4 = """ def test4(self):
prog_text_4 = """\
global x global x
x = 2 x = 2
""" """
compile_and_check(prog_text_4, 0) # this should work
compile(prog_text_4, "<test string>", "exec")
def test_main():
run_unittest(GlobalTests)
if __name__ == "__main__":
test_main()

View file

@ -8,61 +8,53 @@
# 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 TestFailed, verify, vereq, check_syntax from test.test_support import run_unittest, check_syntax_error
import unittest
import sys import sys
# testing import *
from sys import *
print '1. Parser' class TokenTests(unittest.TestCase):
print '1.1 Tokens'
print '1.1.1 Backslashes'
def testBackslash(self):
# Backslash means line continuation: # Backslash means line continuation:
x = 1 \ x = 1 \
+ 1 + 1
if x != 2: raise TestFailed, 'backslash for line continuation' self.assertEquals(x, 2, 'backslash for line continuation')
# Backslash does not means continuation in comments :\ # Backslash does not means continuation in comments :\
x = 0 x = 0
if x != 0: raise TestFailed, 'backslash ending comment' self.assertEquals(x, 0, 'backslash ending comment')
print '1.1.2 Numeric literals' def testPlainIntegers(self):
self.assertEquals(0xff, 255)
print '1.1.2.1 Plain integers' self.assertEquals(0377, 255)
if 0xff != 255: raise TestFailed, 'hex int' self.assertEquals(2147483647, 017777777777)
if 0377 != 255: raise TestFailed, 'octal int'
if 2147483647 != 017777777777: raise TestFailed, 'large positive int'
try:
from sys import maxint from sys import maxint
except ImportError:
maxint = 2147483647
if maxint == 2147483647: if maxint == 2147483647:
# The following test will start to fail in Python 2.4; self.assertEquals(-2147483647-1, -020000000000)
# change the 020000000000 to -020000000000
if -2147483647-1 != -020000000000: raise TestFailed, 'max negative int'
# XXX -2147483648 # XXX -2147483648
if 037777777777 < 0: raise TestFailed, 'large oct' self.assert_(037777777777 > 0)
if 0xffffffff < 0: raise TestFailed, 'large hex' self.assert_(0xffffffff > 0)
for s in '2147483648', '040000000000', '0x100000000': for s in '2147483648', '040000000000', '0x100000000':
try: try:
x = eval(s) x = eval(s)
except OverflowError: except OverflowError:
print "OverflowError on huge integer literal " + repr(s) self.fail("OverflowError on huge integer literal %r" % s)
elif eval('maxint == 9223372036854775807'): elif maxint == 9223372036854775807:
if eval('-9223372036854775807-1 != -01000000000000000000000'): self.assertEquals(-9223372036854775807-1, -01000000000000000000000)
raise TestFailed, 'max negative int' self.assert_(01777777777777777777777 > 0)
if eval('01777777777777777777777') < 0: raise TestFailed, 'large oct' self.assert_(0xffffffffffffffff > 0)
if eval('0xffffffffffffffff') < 0: raise TestFailed, 'large hex'
for s in '9223372036854775808', '02000000000000000000000', \ for s in '9223372036854775808', '02000000000000000000000', \
'0x10000000000000000': '0x10000000000000000':
try: try:
x = eval(s) x = eval(s)
except OverflowError: except OverflowError:
print "OverflowError on huge integer literal " + repr(s) self.fail("OverflowError on huge integer literal %r" % s)
else: else:
print 'Weird maxint value', maxint self.fail('Weird maxint value %r' % maxint)
print '1.1.2.2 Long integers' def testLongIntegers(self):
x = 0L x = 0L
x = 0l x = 0l
x = 0xffffffffffffffffL x = 0xffffffffffffffffL
@ -72,7 +64,7 @@
x = 123456789012345678901234567890L x = 123456789012345678901234567890L
x = 123456789012345678901234567890l x = 123456789012345678901234567890l
print '1.1.2.3 Floating point' def testFloats(self):
x = 3.14 x = 3.14
x = 314. x = 314.
x = 0.314 x = 0.314
@ -86,17 +78,16 @@
x = .3e14 x = .3e14
x = 3.1e4 x = 3.1e4
print '1.1.3 String literals' def testStringLiterals(self):
x = ''; y = ""; self.assert_(len(x) == 0 and x == y)
x = ''; y = ""; verify(len(x) == 0 and x == y) x = '\''; y = "'"; self.assert_(len(x) == 1 and x == y and ord(x) == 39)
x = '\''; y = "'"; verify(len(x) == 1 and x == y and ord(x) == 39) x = '"'; y = "\""; self.assert_(len(x) == 1 and x == y and ord(x) == 34)
x = '"'; y = "\""; verify(len(x) == 1 and x == y and ord(x) == 34)
x = "doesn't \"shrink\" does it" x = "doesn't \"shrink\" does it"
y = 'doesn\'t "shrink" does it' y = 'doesn\'t "shrink" does it'
verify(len(x) == 24 and x == y) self.assert_(len(x) == 24 and x == y)
x = "does \"shrink\" doesn't it" x = "does \"shrink\" doesn't it"
y = 'does "shrink" doesn\'t it' y = 'does "shrink" doesn\'t it'
verify(len(x) == 24 and x == y) self.assert_(len(x) == 24 and x == y)
x = """ x = """
The "quick" The "quick"
brown fox brown fox
@ -104,42 +95,46 @@
the 'lazy' dog. the 'lazy' dog.
""" """
y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n' y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n'
verify(x == y) self.assertEquals(x, y)
y = ''' y = '''
The "quick" The "quick"
brown fox brown fox
jumps over jumps over
the 'lazy' dog. the 'lazy' dog.
'''; verify(x == y) '''
self.assertEquals(x, y)
y = "\n\ y = "\n\
The \"quick\"\n\ The \"quick\"\n\
brown fox\n\ brown fox\n\
jumps over\n\ jumps over\n\
the 'lazy' dog.\n\ the 'lazy' dog.\n\
"; verify(x == y) "
self.assertEquals(x, y)
y = '\n\ y = '\n\
The \"quick\"\n\ The \"quick\"\n\
brown fox\n\ brown fox\n\
jumps over\n\ jumps over\n\
the \'lazy\' dog.\n\ the \'lazy\' dog.\n\
'; verify(x == y) '
self.assertEquals(x, y)
print '1.2 Grammar' class GrammarTests(unittest.TestCase):
print 'single_input' # NEWLINE | simple_stmt | compound_stmt NEWLINE # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
# XXX can't test in a script -- this rule is only used when interactive # XXX can't test in a script -- this rule is only used when interactive
print 'file_input' # (NEWLINE | stmt)* ENDMARKER # file_input: (NEWLINE | stmt)* ENDMARKER
# Being tested as this very moment this very module # Being tested as this very moment this very module
print 'expr_input' # testlist NEWLINE # expr_input: testlist NEWLINE
# XXX Hard to test -- used only in calls to input() # XXX Hard to test -- used only in calls to input()
print 'eval_input' # testlist ENDMARKER def testEvalInput(self):
# testlist ENDMARKER
x = eval('1, 0 or 1') x = eval('1, 0 or 1')
print 'funcdef' def testFuncdef(self):
### 'def' NAME parameters ':' suite ### 'def' NAME parameters ':' suite
### parameters: '(' [varargslist] ')' ### parameters: '(' [varargslist] ')'
### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME] ### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME]
@ -157,18 +152,18 @@ def f2(one_argument): pass
def f3(two, arguments): pass def f3(two, arguments): pass
def f4(two, (compound, (argument, list))): pass def f4(two, (compound, (argument, list))): pass
def f5((compound, first), two): pass def f5((compound, first), two): pass
vereq(f2.func_code.co_varnames, ('one_argument',)) self.assertEquals(f2.func_code.co_varnames, ('one_argument',))
vereq(f3.func_code.co_varnames, ('two', 'arguments')) self.assertEquals(f3.func_code.co_varnames, ('two', 'arguments'))
if sys.platform.startswith('java'): if sys.platform.startswith('java'):
vereq(f4.func_code.co_varnames, self.assertEquals(f4.func_code.co_varnames,
('two', '(compound, (argument, list))', 'compound', 'argument', ('two', '(compound, (argument, list))', 'compound', 'argument',
'list',)) 'list',))
vereq(f5.func_code.co_varnames, self.assertEquals(f5.func_code.co_varnames,
('(compound, first)', 'two', 'compound', 'first')) ('(compound, first)', 'two', 'compound', 'first'))
else: else:
vereq(f4.func_code.co_varnames, self.assertEquals(f4.func_code.co_varnames,
('two', '.1', 'compound', 'argument', 'list')) ('two', '.1', 'compound', 'argument', 'list'))
vereq(f5.func_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
@ -176,13 +171,38 @@ 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, (b, c), *rest): return a, b, c, rest def v3(a, (b, c), *rest): return a, b, c, rest
f1()
f2(1)
f2(1,)
f3(1, 2)
f3(1, 2,)
f4(1, (2, (3, 4)))
v0()
v0(1)
v0(1,)
v0(1,2)
v0(1,2,3,4,5,6,7,8,9,0)
v1(1)
v1(1,)
v1(1,2)
v1(1,2,3)
v1(1,2,3,4,5,6,7,8,9,0)
v2(1,2)
v2(1,2,3)
v2(1,2,3,4)
v2(1,2,3,4,5,6,7,8,9,0)
v3(1,(2,3))
v3(1,(2,3),4)
v3(1,(2,3),4,5,6,7,8,9,0)
# 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'):
verify(v3.func_code.co_varnames == ('a', '(b, c)', 'rest', 'b', 'c')) self.assertEquals(v3.func_code.co_varnames, ('a', '(b, c)', 'rest', 'b', 'c'))
else: else:
vereq(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c')) self.assertEquals(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c'))
verify(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()
d01(1) d01(1)
@ -260,25 +280,25 @@ def d31v((x)): pass
def d32v((x,)): pass def d32v((x,)): pass
d32v((1,)) d32v((1,))
def testLambdef(self):
### lambdef: 'lambda' [varargslist] ':' test ### lambdef: 'lambda' [varargslist] ':' test
print 'lambdef'
l1 = lambda : 0 l1 = lambda : 0
verify(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, 0L]] l3 = lambda : [2 < x for x in [-1, 3, 0L]]
verify(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()
verify(l4() == 1) self.assertEquals(l4(), 1)
l5 = lambda x, y, z=2: x + y + z l5 = lambda x, y, z=2: x + y + z
verify(l5(1, 2) == 5) self.assertEquals(l5(1, 2), 5)
verify(l5(1, 2, 3) == 6) self.assertEquals(l5(1, 2, 3), 6)
check_syntax("lambda x: x = 2") check_syntax_error(self, "lambda x: x = 2")
### stmt: simple_stmt | compound_stmt ### stmt: simple_stmt | compound_stmt
# Tested below # Tested below
def testSimpleStmt(self):
### simple_stmt: small_stmt (';' small_stmt)* [';'] ### simple_stmt: small_stmt (';' small_stmt)* [';']
print 'simple_stmt'
x = 1; pass; del x x = 1; pass; del x
def foo(): def foo():
# verify statments that end with semi-colons # verify statments that end with semi-colons
@ -288,7 +308,8 @@ def foo():
### small_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt ### small_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
# Tested below # Tested below
print 'expr_stmt' # (exprlist '=')* exprlist def testExprStmt(self):
# (exprlist '=')* exprlist
1 1
1, 2, 3 1, 2, 3
x = 1 x = 1
@ -296,20 +317,26 @@ def foo():
x = y = z = 1, 2, 3 x = y = z = 1, 2, 3
x, y, z = 1, 2, 3 x, y, z = 1, 2, 3
abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4) abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4)
# NB these variables are deleted below
check_syntax("x + 1 = 1") check_syntax_error(self, "x + 1 = 1")
check_syntax("a + 1 = b + 2") check_syntax_error(self, "a + 1 = b + 2")
def testPrintStmt(self):
# 'print' (test ',')* [test]
import StringIO
# Can't test printing to real stdout without comparing output
# which is not available in unittest.
save_stdout = sys.stdout
sys.stdout = StringIO.StringIO()
print 'print_stmt' # 'print' (test ',')* [test]
print 1, 2, 3 print 1, 2, 3
print 1, 2, 3, print 1, 2, 3,
print print
print 0 or 1, 0 or 1, print 0 or 1, 0 or 1,
print 0 or 1 print 0 or 1
print 'extended print_stmt' # 'print' '>>' test ',' # 'print' '>>' test ','
import sys
print >> sys.stdout, 1, 2, 3 print >> sys.stdout, 1, 2, 3
print >> sys.stdout, 1, 2, 3, print >> sys.stdout, 1, 2, 3,
print >> sys.stdout print >> sys.stdout
@ -349,36 +376,56 @@ def tellme(file=None):
driver() driver()
# syntax errors self.assertEqual(sys.stdout.getvalue(), '''\
check_syntax('print ,') 1 2 3
check_syntax('print >> x,') 1 2 3
1 1 1
1 2 3
1 2 3
1 1 1
hello world
''')
sys.stdout = save_stdout
# syntax errors
check_syntax_error(self, 'print ,')
check_syntax_error(self, 'print >> x,')
def testDelStmt(self):
# 'del' exprlist
abc = [1,2,3]
x, y, z = abc
xyz = x, y, z
print 'del_stmt' # 'del' exprlist
del abc del abc
del x, y, (z, xyz) del x, y, (z, xyz)
print 'pass_stmt' # 'pass' def testPassStmt(self):
# 'pass'
pass pass
print 'flow_stmt' # break_stmt | continue_stmt | return_stmt | raise_stmt # flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt
# Tested below # Tested below
print 'break_stmt' # 'break' def testBreakStmt(self):
# 'break'
while 1: break while 1: break
print 'continue_stmt' # 'continue' def testContinueStmt(self):
# 'continue'
i = 1 i = 1
while i: i = 0; continue while i: i = 0; continue
msg = "" msg = ""
while not msg: while not msg:
msg = "continue + try/except ok" msg = "ok"
try: try:
continue continue
msg = "continue failed to continue inside try" msg = "continue failed to continue inside try"
except: except:
msg = "continue inside try called except block" msg = "continue inside try called except block"
print msg if msg != "ok":
self.fail(msg)
msg = "" msg = ""
while not msg: while not msg:
@ -386,10 +433,11 @@ def tellme(file=None):
try: try:
continue continue
finally: finally:
msg = "continue + try/finally ok" msg = "ok"
print msg if msg != "ok":
self.fail(msg)
def test_break_continue_loop(self):
# This test warrants an explanation. It is a test specifically for SF bugs # This test warrants an explanation. It is a test specifically for SF bugs
# #463359 and #462937. The bug is that a 'break' statement executed or # #463359 and #462937. The bug is that a 'break' statement executed or
# exception raised inside a try/except inside a loop, *after* a continue # exception raised inside a try/except inside a loop, *after* a continue
@ -399,8 +447,7 @@ def tellme(file=None):
# *must* written as a function, and the tracking vars *must* be function # *must* written as a function, and the tracking vars *must* be function
# arguments with default values. Otherwise, the test will loop and loop. # arguments with default values. Otherwise, the test will loop and loop.
print "testing continue and break in try/except in loop" def test_inner(extra_burning_oil = 1, count=0):
def test_break_continue_loop(extra_burning_oil = 1, count=0):
big_hippo = 2 big_hippo = 2
while big_hippo: while big_hippo:
count += 1 count += 1
@ -413,67 +460,69 @@ def test_break_continue_loop(extra_burning_oil = 1, count=0):
except: except:
raise raise
if count > 2 or big_hippo <> 1: if count > 2 or big_hippo <> 1:
print "continue then break in try/except in loop broken!" self.fail("continue then break in try/except in loop broken!")
test_break_continue_loop() test_inner()
print 'return_stmt' # 'return' [testlist] def testReturn(self):
# 'return' [testlist]
def g1(): return def g1(): return
def g2(): return 1 def g2(): return 1
g1() g1()
x = g2() x = g2()
check_syntax("class foo:return 1") check_syntax_error(self, "class foo:return 1")
print 'yield_stmt' def testYield(self):
check_syntax("class foo:yield 1") check_syntax_error(self, "class foo:yield 1")
print 'raise_stmt' # 'raise' test [',' test] def testRaise(self):
# '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
print 'import_name' # 'import' dotted_as_names def testImport(self):
# 'import' dotted_as_names
import sys import sys
import time, sys import time, sys
print 'import_from' # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names) # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names)
from time import time from time import time
from time import (time) from time import (time)
from sys import * # not testable inside a function, but already done at top of the module
# from sys import *
from sys import path, argv from sys import path, argv
from sys import (path, argv) from sys import (path, argv)
from sys import (path, argv,) from sys import (path, argv,)
print 'global_stmt' # 'global' NAME (',' NAME)* def testGlobal(self):
def f(): # 'global' NAME (',' NAME)*
global a global a
global a, b global a, b
global one, two, three, four, five, six, seven, eight, nine, ten global one, two, three, four, five, six, seven, eight, nine, ten
print 'exec_stmt' # 'exec' expr ['in' expr [',' expr]] def testExec(self):
def f(): # '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: raise TestFailed, '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: raise TestFailed, '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: raise TestFailed, '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: raise TestFailed, 'exec u\'z=1+1\'' if z != 2: self.fail('exec u\'z=1+1\'')"""
"""
f()
g = {} g = {}
exec 'z = 1' in g exec 'z = 1' in g
if g.has_key('__builtins__'): del g['__builtins__'] if g.has_key('__builtins__'): del g['__builtins__']
if g != {'z': 1}: raise TestFailed, 'exec \'z = 1\' in g' if g != {'z': 1}: self.fail('exec \'z = 1\' in g')
g = {} g = {}
l = {} l = {}
@ -482,19 +531,27 @@ def f():
exec 'global a; a = 1; b = 2' in g, l exec 'global a; a = 1; b = 2' in g, l
if g.has_key('__builtins__'): del g['__builtins__'] if g.has_key('__builtins__'): del g['__builtins__']
if l.has_key('__builtins__'): del l['__builtins__'] if l.has_key('__builtins__'): del l['__builtins__']
if (g, l) != ({'a':1}, {'b':2}): raise TestFailed, 'exec ... in g (%s), l (%s)' %(g,l) if (g, l) != ({'a':1}, {'b':2}):
self.fail('exec ... in g (%s), l (%s)' %(g,l))
def testAssert(self):
print "assert_stmt" # assert_stmt: 'assert' test [',' test] # assert_stmt: 'assert' test [',' test]
assert 1 assert 1
assert 1, 1 assert 1, 1
assert lambda x:x assert lambda x:x
assert 1, lambda x:x+1 assert 1, lambda x:x+1
try:
assert 0, "msg"
except AssertionError, e:
self.assertEquals(e.args[0], "msg")
else:
self.fail("AssertionError not raised by assert 0")
### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
# Tested below # Tested below
print 'if_stmt' # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] def testIf(self):
# 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
if 1: pass if 1: pass
if 1: pass if 1: pass
else: pass else: pass
@ -506,12 +563,14 @@ def f():
elif 0: pass elif 0: pass
else: pass else: pass
print 'while_stmt' # 'while' test ':' suite ['else' ':' suite] def testWhile(self):
# 'while' test ':' suite ['else' ':' suite]
while 0: pass while 0: pass
while 0: pass while 0: pass
else: pass else: pass
print 'for_stmt' # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] def testFor(self):
# 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
for i in 1, 2, 3: pass for i in 1, 2, 3: pass
for i, j, k in (): pass for i, j, k in (): pass
else: pass else: pass
@ -529,14 +588,15 @@ def __getitem__(self, i):
return self.sofar[i] return self.sofar[i]
n = 0 n = 0
for x in Squares(10): n = n+x for x in Squares(10): n = n+x
if n != 285: raise TestFailed, 'for over growing sequence' if n != 285:
self.fail('for over growing sequence')
result = [] result = []
for x, in [(1,), (2,), (3,)]: for x, in [(1,), (2,), (3,)]:
result.append(x) result.append(x)
vereq(result, [1, 2, 3]) self.assertEqual(result, [1, 2, 3])
print 'try_stmt' 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 [',' expr]]
@ -559,7 +619,8 @@ def __getitem__(self, i):
try: pass try: pass
finally: pass finally: pass
print 'suite' # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT def testSuite(self):
# simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
if 1: pass if 1: pass
if 1: if 1:
pass pass
@ -573,7 +634,7 @@ def __getitem__(self, i):
pass pass
# #
print 'test' def testTest(self):
### and_test ('or' and_test)* ### and_test ('or' and_test)*
### and_test: not_test ('and' not_test)* ### and_test: not_test ('and' not_test)*
### not_test: 'not' not_test | comparison ### not_test: 'not' not_test | comparison
@ -584,7 +645,7 @@ def __getitem__(self, i):
if not 1 and 1 and 1: pass if not 1 and 1 and 1: pass
if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass
print 'comparison' def testComparison(self):
### comparison: expr (comp_op expr)* ### comparison: expr (comp_op expr)*
### comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' ### comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
if 1: pass if 1: pass
@ -602,62 +663,39 @@ def __getitem__(self, i):
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
print 'binary mask ops' def testBinaryMaskOps(self):
x = 1 & 1 x = 1 & 1
x = 1 ^ 1 x = 1 ^ 1
x = 1 | 1 x = 1 | 1
print 'shift ops' def testShiftOps(self):
x = 1 << 1 x = 1 << 1
x = 1 >> 1 x = 1 >> 1
x = 1 << 1 >> 1 x = 1 << 1 >> 1
print 'additive ops' def testAdditiveOps(self):
x = 1 x = 1
x = 1 + 1 x = 1 + 1
x = 1 - 1 - 1 x = 1 - 1 - 1
x = 1 - 1 + 1 - 1 + 1 x = 1 - 1 + 1 - 1 + 1
print 'multiplicative ops' def testMultiplicativeOps(self):
x = 1 * 1 x = 1 * 1
x = 1 / 1 x = 1 / 1
x = 1 % 1 x = 1 % 1
x = 1 / 1 * 1 % 1 x = 1 / 1 * 1 % 1
print 'unary ops' def testUnaryOps(self):
x = +1 x = +1
x = -1 x = -1
x = ~1 x = ~1
x = ~1 ^ 1 & 1 | 1 & 1 ^ -1 x = ~1 ^ 1 & 1 | 1 & 1 ^ -1
x = -1*1/1 + 1*1 - ---1*1 x = -1*1/1 + 1*1 - ---1*1
print 'selectors' def testSelectors(self):
### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
### subscript: expr | [expr] ':' [expr] ### subscript: expr | [expr] ':' [expr]
f1()
f2(1)
f2(1,)
f3(1, 2)
f3(1, 2,)
f4(1, (2, (3, 4)))
v0()
v0(1)
v0(1,)
v0(1,2)
v0(1,2,3,4,5,6,7,8,9,0)
v1(1)
v1(1,)
v1(1,2)
v1(1,2,3)
v1(1,2,3,4,5,6,7,8,9,0)
v2(1,2)
v2(1,2,3)
v2(1,2,3,4)
v2(1,2,3,4,5,6,7,8,9,0)
v3(1,(2,3))
v3(1,(2,3),4)
v3(1,(2,3),4,5,6,7,8,9,0)
print
import sys, time import sys, time
c = sys.path[0] c = sys.path[0]
x = time.time() x = time.time()
@ -682,10 +720,9 @@ def __getitem__(self, i):
d[1,2,3] = 4 d[1,2,3] = 4
L = list(d) L = list(d)
L.sort() L.sort()
print L self.assertEquals(str(L), '[1, (1,), (1, 2), (1, 2, 3)]')
def testAtoms(self):
print 'atoms'
### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING
### dictmaker: test ':' test (',' test ':' test)* [','] ### dictmaker: test ':' test (',' test ':' test)* [',']
@ -717,7 +754,8 @@ def __getitem__(self, i):
### testlist: test (',' test)* [','] ### testlist: test (',' test)* [',']
# These have been exercised enough above # These have been exercised enough above
print 'classdef' # 'class' NAME ['(' [testlist] ')'] ':' suite def testClassdef(self):
# 'class' NAME ['(' [testlist] ')'] ':' suite
class B: pass class B: pass
class B2(): pass class B2(): pass
class C1(B): pass class C1(B): pass
@ -728,30 +766,41 @@ 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
def testListcomps(self):
# list comprehension tests # list comprehension tests
nums = [1, 2, 3, 4, 5] nums = [1, 2, 3, 4, 5]
strs = ["Apple", "Banana", "Coconut"] strs = ["Apple", "Banana", "Coconut"]
spcs = [" Apple", " Banana ", "Coco nut "] spcs = [" Apple", " Banana ", "Coco nut "]
print [s.strip() for s in spcs] self.assertEqual([s.strip() for s in spcs], ['Apple', 'Banana', 'Coco nut'])
print [3 * x for x in nums] self.assertEqual([3 * x for x in nums], [3, 6, 9, 12, 15])
print [x for x in nums if x > 2] self.assertEqual([x for x in nums if x > 2], [3, 4, 5])
print [(i, s) for i in nums for s in strs] self.assertEqual([(i, s) for i in nums for s in strs],
print [(i, s) for i in nums for s in [f for f in strs if "n" in f]] [(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'),
print [(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)] (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'),
(3, 'Apple'), (3, 'Banana'), (3, 'Coconut'),
(4, 'Apple'), (4, 'Banana'), (4, 'Coconut'),
(5, 'Apple'), (5, 'Banana'), (5, 'Coconut')])
self.assertEqual([(i, s) for i in nums for s in [f for f in strs if "n" in f]],
[(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'),
(3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'),
(5, 'Banana'), (5, 'Coconut')])
self.assertEqual([(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)],
[[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]])
def test_in_func(l): def test_in_func(l):
return [None < x < 3 for x in l if x > 2] return [None < x < 3 for x in l if x > 2]
print test_in_func(nums) self.assertEqual(test_in_func(nums), [False, False, False])
def test_nested_front(): def test_nested_front():
print [[y for y in [x, x + 1]] for x in [1,3,5]] self.assertEqual([[y for y in [x, x + 1]] for x in [1,3,5]],
[[1, 2], [3, 4], [5, 6]])
test_nested_front() test_nested_front()
check_syntax("[i, s for i in nums for s in strs]") check_syntax_error(self, "[i, s for i in nums for s in strs]")
check_syntax("[x if y]") check_syntax_error(self, "[x if y]")
suppliers = [ suppliers = [
(1, "Boeing"), (1, "Boeing"),
@ -769,7 +818,7 @@ def test_nested_front():
(1, 10), (1, 20), (2, 20), (3, 30) (1, 10), (1, 20), (2, 20), (3, 30)
] ]
print [ x = [
(sname, pname) (sname, pname)
for (sno, sname) in suppliers for (sno, sname) in suppliers
for (pno, pname) in parts for (pno, pname) in parts
@ -777,12 +826,16 @@ def test_nested_front():
if sno == sp_sno and pno == sp_pno if sno == sp_sno and pno == sp_pno
] ]
self.assertEqual(x, [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'),
('Macdonalds', 'Cheeseburger')])
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))
verify(g.next() == [x for x in range(10)]) self.assertEqual(g.next(), [x for x in range(10)])
try: try:
g.next() g.next()
raise TestFailed, 'should produce StopIteration exception' self.fail('should produce StopIteration exception')
except StopIteration: except StopIteration:
pass pass
@ -790,66 +843,75 @@ def test_nested_front():
try: try:
g = (a for d in a) g = (a for d in a)
g.next() g.next()
raise TestFailed, 'should produce TypeError' self.fail('should produce TypeError')
except TypeError: except TypeError:
pass pass
verify(list((x, y) for x in 'abcd' for y in 'abcd') == [(x, y) for x in 'abcd' for y in 'abcd']) self.assertEqual(list((x, y) for x in 'abcd' for y in 'abcd'), [(x, y) for x in 'abcd' for y in 'abcd'])
verify(list((x, y) for x in 'ab' for y in 'xy') == [(x, y) for x in 'ab' for y in 'xy']) self.assertEqual(list((x, y) for x in 'ab' for y in 'xy'), [(x, y) for x in 'ab' for y in 'xy'])
a = [x for x in range(10)] a = [x for x in range(10)]
b = (x for x in (y for y in a)) b = (x for x in (y for y in a))
verify(sum(b) == sum([x for x in range(10)])) self.assertEqual(sum(b), sum([x for x in range(10)]))
verify(sum(x**2 for x in range(10)) == sum([x**2 for x in range(10)])) self.assertEqual(sum(x**2 for x in range(10)), sum([x**2 for x in range(10)]))
verify(sum(x*x for x in range(10) if x%2) == sum([x*x for x in range(10) if x%2])) self.assertEqual(sum(x*x for x in range(10) if x%2), sum([x*x for x in range(10) if x%2]))
verify(sum(x for x in (y for y in range(10))) == sum([x for x in range(10)])) self.assertEqual(sum(x for x in (y for y in range(10))), sum([x for x in range(10)]))
verify(sum(x for x in (y for y in (z for z in range(10)))) == sum([x for x in range(10)])) self.assertEqual(sum(x for x in (y for y in (z for z in range(10)))), sum([x for x in range(10)]))
verify(sum(x for x in [y for y in (z for z in range(10))]) == sum([x for x in range(10)])) self.assertEqual(sum(x for x in [y for y in (z for z in range(10))]), sum([x for x in range(10)]))
verify(sum(x for x in (y for y in (z for z in range(10) if True)) if True) == sum([x for x in range(10)])) self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True)) if True), sum([x for x in range(10)]))
verify(sum(x for x in (y for y in (z for z in range(10) if True) if False) if True) == 0) self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True) if False) if True), 0)
check_syntax("foo(x for x in range(10), 100)") check_syntax_error(self, "foo(x for x in range(10), 100)")
check_syntax("foo(100, x for x in range(10))") check_syntax_error(self, "foo(100, x for x in range(10))")
def testComprehensionSpecials(self):
# test for outmost iterable precomputation # test for outmost iterable precomputation
x = 10; g = (i for i in range(x)); x = 5 x = 10; g = (i for i in range(x)); x = 5
verify(len(list(g)) == 10) self.assertEqual(len(list(g)), 10)
# This should hold, since we're only precomputing outmost iterable. # This should hold, since we're only precomputing outmost iterable.
x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x)) x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x))
x = 5; t = True; x = 5; t = True;
verify([(i,j) for i in range(10) for j in range(5)] == list(g)) self.assertEqual([(i,j) for i in range(10) for j in range(5)], list(g))
# Grammar allows multiple adjacent 'if's in listcomps and genexps, # Grammar allows multiple adjacent 'if's in listcomps and genexps,
# even though it's silly. Make sure it works (ifelse broke this.) # even though it's silly. Make sure it works (ifelse broke this.)
verify([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7]) self.assertEqual([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7])
verify((x for x in range(10) if x % 2 if x % 3), [1, 5, 7]) self.assertEqual(list(x for x in range(10) if x % 2 if x % 3), [1, 5, 7])
# Verify unpacking single element tuples in listcomp/genexp. # verify unpacking single element tuples in listcomp/genexp.
vereq([x for x, in [(4,), (5,), (6,)]], [4, 5, 6]) self.assertEqual([x for x, in [(4,), (5,), (6,)]], [4, 5, 6])
vereq(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9]) self.assertEqual(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9])
def testIfElseExpr(self):
# 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
verify([ x() for x in lambda: True, lambda: False if x() ] == [True]) self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
verify([ x() for x in (lambda: True, lambda: False) if x() ] == [True]) self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True])
verify([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ] == [True]) self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True])
verify((5 if 1 else _checkeval("check 1", 0)) == 5) self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5)
verify((_checkeval("check 2", 0) if 0 else 5) == 5) self.assertEqual((_checkeval("check 2", 0) if 0 else 5), 5)
verify((5 and 6 if 0 else 1) == 1) self.assertEqual((5 and 6 if 0 else 1), 1)
verify(((5 and 6) if 0 else 1) == 1) self.assertEqual(((5 and 6) if 0 else 1), 1)
verify((5 and (6 if 1 else 1)) == 6) self.assertEqual((5 and (6 if 1 else 1)), 6)
verify((0 or _checkeval("check 3", 2) if 0 else 3) == 3) self.assertEqual((0 or _checkeval("check 3", 2) if 0 else 3), 3)
verify((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)) == 1) self.assertEqual((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1)
verify((0 or 5 if 1 else _checkeval("check 6", 3)) == 5) self.assertEqual((0 or 5 if 1 else _checkeval("check 6", 3)), 5)
verify((not 5 if 1 else 1) == False) self.assertEqual((not 5 if 1 else 1), False)
verify((not 5 if 0 else 1) == 1) self.assertEqual((not 5 if 0 else 1), 1)
verify((6 + 1 if 1 else 2) == 7) self.assertEqual((6 + 1 if 1 else 2), 7)
verify((6 - 1 if 1 else 2) == 5) self.assertEqual((6 - 1 if 1 else 2), 5)
verify((6 * 2 if 1 else 4) == 12) self.assertEqual((6 * 2 if 1 else 4), 12)
verify((6 / 2 if 1 else 3) == 3) self.assertEqual((6 / 2 if 1 else 3), 3)
verify((6 < 4 if 0 else 2) == 2) self.assertEqual((6 < 4 if 0 else 2), 2)
def test_main():
run_unittest(TokenTests, GrammarTests)
if __name__ == '__main__':
test_main()

View file

@ -1,9 +1,13 @@
from test.test_support import verify, TestFailed, check_syntax, vereq import unittest
from test.test_support import check_syntax_error, run_unittest
import warnings import warnings
warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<test string>")
warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<string>") warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<string>")
print "1. simple nesting" class ScopeTests(unittest.TestCase):
def testSimpleNesting(self):
def make_adder(x): def make_adder(x):
def adder(y): def adder(y):
@ -13,10 +17,10 @@ def adder(y):
inc = make_adder(1) inc = make_adder(1)
plus10 = make_adder(10) plus10 = make_adder(10)
vereq(inc(1), 2) self.assertEqual(inc(1), 2)
vereq(plus10(-2), 8) self.assertEqual(plus10(-2), 8)
print "2. extra nesting" def testExtraNesting(self):
def make_adder2(x): def make_adder2(x):
def extra(): # check freevars passing through non-use scopes def extra(): # check freevars passing through non-use scopes
@ -28,10 +32,10 @@ def adder(y):
inc = make_adder2(1) inc = make_adder2(1)
plus10 = make_adder2(10) plus10 = make_adder2(10)
vereq(inc(1), 2) self.assertEqual(inc(1), 2)
vereq(plus10(-2), 8) self.assertEqual(plus10(-2), 8)
print "3. simple nesting + rebinding" def testSimpleAndRebinding(self):
def make_adder3(x): def make_adder3(x):
def adder(y): def adder(y):
@ -42,10 +46,10 @@ def adder(y):
inc = make_adder3(0) inc = make_adder3(0)
plus10 = make_adder3(9) plus10 = make_adder3(9)
vereq(inc(1), 2) self.assertEqual(inc(1), 2)
vereq(plus10(-2), 8) self.assertEqual(plus10(-2), 8)
print "4. nesting with global but no free" def testNestingGlobalNoFree(self):
def make_adder4(): # XXX add exta level of indirection def make_adder4(): # XXX add exta level of indirection
def nest(): def nest():
@ -58,12 +62,12 @@ def adder(y):
global_x = 1 global_x = 1
adder = make_adder4() adder = make_adder4()
vereq(adder(1), 2) self.assertEqual(adder(1), 2)
global_x = 10 global_x = 10
vereq(adder(-2), 8) self.assertEqual(adder(-2), 8)
print "5. nesting through class" def testNestingThroughClass(self):
def make_adder5(x): def make_adder5(x):
class Adder: class Adder:
@ -74,10 +78,10 @@ def __call__(self, y):
inc = make_adder5(1) inc = make_adder5(1)
plus10 = make_adder5(10) plus10 = make_adder5(10)
vereq(inc(1), 2) self.assertEqual(inc(1), 2)
vereq(plus10(-2), 8) self.assertEqual(plus10(-2), 8)
print "6. nesting plus free ref to global" def testNestingPlusFreeRefToGlobal(self):
def make_adder6(x): def make_adder6(x):
global global_nest_x global global_nest_x
@ -89,10 +93,10 @@ def adder(y):
inc = make_adder6(1) inc = make_adder6(1)
plus10 = make_adder6(10) plus10 = make_adder6(10)
vereq(inc(1), 11) # there's only one global self.assertEqual(inc(1), 11) # there's only one global
vereq(plus10(-2), 8) self.assertEqual(plus10(-2), 8)
print "7. nearest enclosing scope" def testNearestEnclosingScope(self):
def f(x): def f(x):
def g(y): def g(y):
@ -103,9 +107,9 @@ def h(z):
return g(2) return g(2)
test_func = f(10) test_func = f(10)
vereq(test_func(5), 47) self.assertEqual(test_func(5), 47)
print "8. mixed freevars and cellvars" def testMixedFreevarsAndCellvars(self):
def identity(x): def identity(x):
return x return x
@ -123,9 +127,9 @@ def h():
g = f(1, 2, 3) g = f(1, 2, 3)
h = g(2, 4, 6) h = g(2, 4, 6)
vereq(h(), 39) self.assertEqual(h(), 39)
print "9. free variable in method" def testFreeVarInMethod(self):
def test(): def test():
method_and_var = "var" method_and_var = "var"
@ -141,9 +145,9 @@ def str(self):
return Test() return Test()
t = test() t = test()
vereq(t.test(), "var") self.assertEqual(t.test(), "var")
vereq(t.method_and_var(), "method") self.assertEqual(t.method_and_var(), "method")
vereq(t.actual_global(), "global") self.assertEqual(t.actual_global(), "global")
method_and_var = "var" method_and_var = "var"
class Test: class Test:
@ -158,11 +162,11 @@ def str(self):
return str(self) return str(self)
t = Test() t = Test()
vereq(t.test(), "var") self.assertEqual(t.test(), "var")
vereq(t.method_and_var(), "method") self.assertEqual(t.method_and_var(), "method")
vereq(t.actual_global(), "global") self.assertEqual(t.actual_global(), "global")
print "10. recursion" def testRecursion(self):
def f(x): def f(x):
def fact(n): def fact(n):
@ -175,12 +179,12 @@ def fact(n):
else: else:
raise ValueError, "x must be >= 0" raise ValueError, "x must be >= 0"
vereq(f(6), 720) self.assertEqual(f(6), 720)
print "11. unoptimized namespaces" def testUnoptimizedNamespaces(self):
check_syntax("""\ check_syntax_error(self, """\
def unoptimized_clash1(strip): def unoptimized_clash1(strip):
def f(s): def f(s):
from string import * from string import *
@ -188,7 +192,7 @@ def f(s):
return f return f
""") """)
check_syntax("""\ check_syntax_error(self, """\
def unoptimized_clash2(): def unoptimized_clash2():
from string import * from string import *
def f(s): def f(s):
@ -196,7 +200,7 @@ def f(s):
return f return f
""") """)
check_syntax("""\ check_syntax_error(self, """\
def unoptimized_clash2(): def unoptimized_clash2():
from string import * from string import *
def g(): def g():
@ -206,7 +210,7 @@ def f(s):
""") """)
# XXX could allow this for exec with const argument, but what's the point # XXX could allow this for exec with const argument, but what's the point
check_syntax("""\ check_syntax_error(self, """\
def error(y): def error(y):
exec "a = 1" exec "a = 1"
def f(x): def f(x):
@ -214,14 +218,14 @@ def f(x):
return f return f
""") """)
check_syntax("""\ check_syntax_error(self, """\
def f(x): def f(x):
def g(): def g():
return x return x
del x # can't del name del x # can't del name
""") """)
check_syntax("""\ check_syntax_error(self, """\
def f(): def f():
def g(): def g():
from string import * from string import *
@ -247,31 +251,31 @@ def f(x):
y = x y = x
""" """
print "12. lambdas" def testLambdas(self):
f1 = lambda x: lambda y: x + y f1 = lambda x: lambda y: x + y
inc = f1(1) inc = f1(1)
plus10 = f1(10) plus10 = f1(10)
vereq(inc(1), 2) self.assertEqual(inc(1), 2)
vereq(plus10(5), 15) self.assertEqual(plus10(5), 15)
f2 = lambda x: (lambda : lambda y: x + y)() f2 = lambda x: (lambda : lambda y: x + y)()
inc = f2(1) inc = f2(1)
plus10 = f2(10) plus10 = f2(10)
vereq(inc(1), 2) self.assertEqual(inc(1), 2)
vereq(plus10(5), 15) self.assertEqual(plus10(5), 15)
f3 = lambda x: lambda y: global_x + y f3 = lambda x: lambda y: global_x + y
global_x = 1 global_x = 1
inc = f3(None) inc = f3(None)
vereq(inc(2), 3) self.assertEqual(inc(2), 3)
f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y) f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
g = f8(1, 2, 3) g = f8(1, 2, 3)
h = g(2, 4, 6) h = g(2, 4, 6)
vereq(h(), 18) self.assertEqual(h(), 18)
print "13. UnboundLocal" def testUnboundLocal(self):
def errorInOuter(): def errorInOuter():
print y print y
@ -290,16 +294,17 @@ def inner():
except UnboundLocalError: except UnboundLocalError:
pass pass
else: else:
raise TestFailed self.fail()
try: try:
errorInInner() errorInInner()
except NameError: except NameError:
pass pass
else: else:
raise TestFailed self.fail()
# test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation
exec """
global_x = 1 global_x = 1
def f(): def f():
global_x += 1 global_x += 1
@ -308,34 +313,36 @@ def f():
except UnboundLocalError: except UnboundLocalError:
pass pass
else: else:
raise TestFailed, 'scope of global_x not correctly determined' fail('scope of global_x not correctly determined')
""" in {'fail': self.fail}
print "14. complex definitions" def testComplexDefinitions(self):
def makeReturner(*lst): def makeReturner(*lst):
def returner(): def returner():
return lst return lst
return returner return returner
vereq(makeReturner(1,2,3)(), (1,2,3)) self.assertEqual(makeReturner(1,2,3)(), (1,2,3))
def makeReturner2(**kwargs): def makeReturner2(**kwargs):
def returner(): def returner():
return kwargs return kwargs
return returner return returner
vereq(makeReturner2(a=11)()['a'], 11) self.assertEqual(makeReturner2(a=11)()['a'], 11)
def makeAddPair((a, b)): def makeAddPair((a, b)):
def addPair((c, d)): def addPair((c, d)):
return (a + c, b + d) return (a + c, b + d)
return addPair return addPair
vereq(makeAddPair((1, 2))((100, 200)), (101,202)) self.assertEqual(makeAddPair((1, 2))((100, 200)), (101,202))
print "15. scope of global statements" def testScopeOfGlobalStmt(self):
# Examples posted by Samuele Pedroni to python-dev on 3/1/2001 # Examples posted by Samuele Pedroni to python-dev on 3/1/2001
exec """\
# I # I
x = 7 x = 7
def f(): def f():
@ -348,8 +355,8 @@ def h():
return h() return h()
return i() return i()
return g() return g()
vereq(f(), 7) self.assertEqual(f(), 7)
vereq(x, 7) self.assertEqual(x, 7)
# II # II
x = 7 x = 7
@ -363,8 +370,8 @@ def h():
return h() return h()
return i() return i()
return g() return g()
vereq(f(), 2) self.assertEqual(f(), 2)
vereq(x, 7) self.assertEqual(x, 7)
# III # III
x = 7 x = 7
@ -379,8 +386,8 @@ def h():
return h() return h()
return i() return i()
return g() return g()
vereq(f(), 2) self.assertEqual(f(), 2)
vereq(x, 2) self.assertEqual(x, 2)
# IV # IV
x = 7 x = 7
@ -395,8 +402,8 @@ def h():
return h() return h()
return i() return i()
return g() return g()
vereq(f(), 2) self.assertEqual(f(), 2)
vereq(x, 2) self.assertEqual(x, 2)
# XXX what about global statements in class blocks? # XXX what about global statements in class blocks?
# do they affect methods? # do they affect methods?
@ -411,11 +418,12 @@ def get(self):
return x return x
g = Global() g = Global()
vereq(g.get(), 13) self.assertEqual(g.get(), 13)
g.set(15) g.set(15)
vereq(g.get(), 13) self.assertEqual(g.get(), 13)
"""
print "16. check leaks" def testLeaks(self):
class Foo: class Foo:
count = 0 count = 0
@ -435,10 +443,11 @@ def f2():
for i in range(100): for i in range(100):
f1() f1()
vereq(Foo.count, 0) self.assertEqual(Foo.count, 0)
print "17. class and global" def testClassAndGlobal(self):
exec """\
def test(x): def test(x):
class Foo: class Foo:
global x global x
@ -447,9 +456,9 @@ def __call__(self, y):
return Foo() return Foo()
x = 0 x = 0
vereq(test(6)(2), 8) self.assertEqual(test(6)(2), 8)
x = -1 x = -1
vereq(test(3)(2), 5) self.assertEqual(test(3)(2), 5)
looked_up_by_load_name = False looked_up_by_load_name = False
class X: class X:
@ -458,9 +467,10 @@ class X:
locals()['looked_up_by_load_name'] = True locals()['looked_up_by_load_name'] = True
passed = looked_up_by_load_name passed = looked_up_by_load_name
verify(X.passed) self.assert_(X.passed)
"""
print "18. verify that locals() works" def testLocalsFunction(self):
def f(x): def f(x):
def g(y): def g(y):
@ -472,11 +482,12 @@ def h(z):
return g return g
d = f(2)(4) d = f(2)(4)
verify(d.has_key('h')) self.assert_(d.has_key('h'))
del d['h'] del d['h']
vereq(d, {'x': 2, 'y': 7, 'w': 6}) self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6})
print "19. var is bound and free in class" def testBoundAndFree(self):
# var is bound and free in class
def f(x): def f(x):
class C: class C:
@ -486,9 +497,9 @@ def m(self):
return C return C
inst = f(3)() inst = f(3)()
vereq(inst.a, inst.m()) self.assertEqual(inst.a, inst.m())
print "20. interaction with trace function" def testInteractionWithTraceFunc(self):
import sys import sys
def tracer(a,b,c): def tracer(a,b,c):
@ -508,31 +519,24 @@ class TestClass:
adaptgetter("foo", TestClass, (1, "")) adaptgetter("foo", TestClass, (1, ""))
sys.settrace(None) sys.settrace(None)
try: sys.settrace() self.assertRaises(TypeError, sys.settrace)
except TypeError: pass
else: raise TestFailed, 'sys.settrace() did not raise TypeError'
print "20. eval and exec with free variables" def testEvalExecFreeVars(self):
def f(x): def f(x):
return lambda: x + 1 return lambda: x + 1
g = f(3) g = f(3)
self.assertRaises(TypeError, eval, g.func_code)
try: try:
eval(g.func_code) exec g.func_code in {}
except TypeError: except TypeError:
pass pass
else: else:
print "eval() should have failed, because code contained free vars" self.fail("exec should have failed, because code contained free vars")
try: def testListCompLocalVars(self):
exec g.func_code
except TypeError:
pass
else:
print "exec should have failed, because code contained free vars"
print "21. list comprehension with local variables"
try: try:
print bad print bad
@ -550,7 +554,7 @@ def x():
except NameError: except NameError:
pass pass
print "22. eval with free variables" def testEvalFreeVars(self):
def f(x): def f(x):
def g(): def g():
@ -559,3 +563,10 @@ def g():
return g return g
f(4)() f(4)()
def test_main():
run_unittest(ScopeTests)
if __name__ == '__main__':
test_main()

View file

@ -245,13 +245,13 @@ def sortdict(dict):
withcommas = ", ".join(reprpairs) withcommas = ", ".join(reprpairs)
return "{%s}" % withcommas return "{%s}" % withcommas
def check_syntax(statement): def check_syntax_error(testcase, statement):
try: try:
compile(statement, '<string>', 'exec') compile(statement, '<test string>', 'exec')
except SyntaxError: except SyntaxError:
pass pass
else: else:
print 'Missing SyntaxError: "%s"' % statement testcase.fail('Missing SyntaxError: "%s"' % statement)
def open_urlresource(url): def open_urlresource(url):
import urllib, urlparse import urllib, urlparse