# Python test set -- part 1, grammar. # This just tests whether the parser accepts them all. from test.test_support import run_unittest, check_syntax_error, \ check_py3k_warnings import unittest import sys import warnings # testing import * from sys import * class TokenTests(unittest.TestCase): def test_backslash(self): # Backslash means line continuation: x = 1 \ + 1 self.assertEqual(x, 2, 'backslash for line continuation') # Backslash does not means continuation in comments :\ x = 0 self.assertEqual(x, 0, 'backslash ending comment') def test_plain_integers(self): self.assertEqual(type(000), type(0)) self.assertEqual(0xff, 255) self.assertEqual(0377, 255) self.assertEqual(0o377, 255) self.assertEqual(2147483647, 017777777777) self.assertEqual(2147483647, 0o17777777777) self.assertEqual(0b1001, 9) # "0x" is not a valid literal self.assertRaises(SyntaxError, eval, "0x") from sys import maxint if maxint == 2147483647: self.assertEqual(-2147483647-1, -0o20000000000) # XXX -2147483648 self.assertTrue(037777777777 > 0) self.assertTrue(0o37777777777 > 0) self.assertTrue(0xffffffff > 0) self.assertTrue(0b1111111111111111111111111111111 > 0) for s in ('2147483648', '040000000000', '0o40000000000', '0x100000000', '0b10000000000000000000000000000000'): try: x = eval(s) except OverflowError: self.fail("OverflowError on huge integer literal %r" % s) elif maxint == 9223372036854775807: self.assertEqual(-9223372036854775807-1, -01000000000000000000000) self.assertEqual(-9223372036854775807-1, -0o1000000000000000000000) self.assertTrue(01777777777777777777777 > 0) self.assertTrue(0o1777777777777777777777 > 0) self.assertTrue(0xffffffffffffffff > 0) self.assertTrue(0b11111111111111111111111111111111111111111111111111111111111111 > 0) for s in '9223372036854775808', '02000000000000000000000', \ '0o2000000000000000000000', \ '0x10000000000000000', \ '0b100000000000000000000000000000000000000000000000000000000000000': try: x = eval(s) except OverflowError: self.fail("OverflowError on huge integer literal %r" % s) else: self.fail('Weird maxint value %r' % maxint) def test_long_integers(self): x = 0L x = 0l x = 0xffffffffffffffffL x = 0xffffffffffffffffl x = 077777777777777777L x = 077777777777777777l x = 123456789012345678901234567890L x = 123456789012345678901234567890l def test_floats(self): x = 3.14 x = 314. x = 0.314 # XXX x = 000.314 x = .314 x = 3e14 x = 3E14 x = 3e-14 x = 3e+14 x = 3.e14 x = .3e14 x = 3.1e4 def test_float_exponent_tokenization(self): # See issue 21642. self.assertEqual(1 if 1else 0, 1) self.assertEqual(1 if 0else 0, 0) self.assertRaises(SyntaxError, eval, "0 if 1Else 0") def test_string_literals(self): x = ''; y = ""; self.assertTrue(len(x) == 0 and x == y) x = '\''; y = "'"; self.assertTrue(len(x) == 1 and x == y and ord(x) == 39) x = '"'; y = "\""; self.assertTrue(len(x) == 1 and x == y and ord(x) == 34) x = "doesn't \"shrink\" does it" y = 'doesn\'t "shrink" does it' self.assertTrue(len(x) == 24 and x == y) x = "does \"shrink\" doesn't it" y = 'does "shrink" doesn\'t it' self.assertTrue(len(x) == 24 and x == y) x = """ The "quick" brown fox jumps over the 'lazy' dog. """ y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n' self.assertEqual(x, y) y = ''' The "quick" brown fox jumps over the 'lazy' dog. ''' self.assertEqual(x, y) y = "\n\ The \"quick\"\n\ brown fox\n\ jumps over\n\ the 'lazy' dog.\n\ " self.assertEqual(x, y) y = '\n\ The \"quick\"\n\ brown fox\n\ jumps over\n\ the \'lazy\' dog.\n\ ' self.assertEqual(x, y) class GrammarTests(unittest.TestCase): # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE # XXX can't test in a script -- this rule is only used when interactive # file_input: (NEWLINE | stmt)* ENDMARKER # Being tested as this very moment this very module # expr_input: testlist NEWLINE # XXX Hard to test -- used only in calls to input() def test_eval_input(self): # testlist ENDMARKER x = eval('1, 0 or 1') def test_funcdef(self): ### 'def' NAME parameters ':' suite ### parameters: '(' [varargslist] ')' ### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME] ### | ('**'|'*' '*') NAME) ### | fpdef ['=' test] (',' fpdef ['=' test])* [','] ### fpdef: NAME | '(' fplist ')' ### fplist: fpdef (',' fpdef)* [','] ### arglist: (argument ',')* (argument | *' test [',' '**' test] | '**' test) ### argument: [test '='] test # Really [keyword '='] test def f1(): pass f1() f1(*()) f1(*(), **{}) def f2(one_argument): pass def f3(two, arguments): pass with check_py3k_warnings(('tuple parameter unpacking has been removed', SyntaxWarning)): exec('def f4(two, (compound, (argument, list))): pass') exec('def f5((compound, first), two): pass') self.assertEqual(f2.func_code.co_varnames, ('one_argument',)) self.assertEqual(f3.func_code.co_varnames, ('two', 'arguments')) if sys.platform.startswith('java'): self.assertEqual(f4.func_code.co_varnames, ('two', '(compound, (argument, list))', 'compound', 'argument', 'list',)) self.assertEqual(f5.func_code.co_varnames, ('(compound, first)', 'two', 'compound', 'first')) else: self.assertEqual(f4.func_code.co_varnames, ('two', '.1', 'compound', 'argument', 'list')) self.assertEqual(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 with check_py3k_warnings(('tuple parameter unpacking has been removed', SyntaxWarning)): exec('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; # thus, the names nested inside tuples must appear after these names. if sys.platform.startswith('java'): self.assertEqual(v3.func_code.co_varnames, ('a', '(b, c)', 'rest', 'b', 'c')) else: self.assertEqual(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c')) self.assertEqual(v3(1, (2, 3), 4), (1, 2, 3, (4,))) def d01(a=1): pass d01() d01(1) d01(*(1,)) d01(*[] or [2]) d01(**{'a':2}) d01(**{'a':2} or {}) def d11(a, b=1): pass d11(1) d11(1, 2) d11(1, **{'b':2}) def d21(a, b, c=1): pass d21(1, 2) d21(1, 2, 3) d21(*(1, 2, 3)) d21(1, *(2, 3)) d21(1, 2, *(3,)) d21(1, 2, **{'c':3}) def d02(a=1, b=2): pass d02() d02(1) d02(1, 2) d02(*(1, 2)) d02(1, *(2,)) d02(1, **{'b':2}) d02(**{'a': 1, 'b': 2}) def d12(a, b=1, c=2): pass d12(1) d12(1, 2) d12(1, 2, 3) def d22(a, b, c=1, d=2): pass d22(1, 2) d22(1, 2, 3) d22(1, 2, 3, 4) def d01v(a=1, *rest): pass d01v() d01v(1) d01v(1, 2) d01v(*(1, 2, 3, 4)) d01v(*(1,)) d01v(**{'a':2}) def d11v(a, b=1, *rest): pass d11v(1) d11v(1, 2) d11v(1, 2, 3) def d21v(a, b, c=1, *rest): pass d21v(1, 2) d21v(1, 2, 3) d21v(1, 2, 3, 4) d21v(*(1, 2, 3, 4)) d21v(1, 2, **{'c': 3}) def d02v(a=1, b=2, *rest): pass d02v() d02v(1) d02v(1, 2) d02v(1, 2, 3) d02v(1, *(2, 3, 4)) d02v(**{'a': 1, 'b': 2}) def d12v(a, b=1, c=2, *rest): pass d12v(1) d12v(1, 2) d12v(1, 2, 3) d12v(1, 2, 3, 4) d12v(*(1, 2, 3, 4)) d12v(1, 2, *(3, 4, 5)) d12v(1, *(2,), **{'c': 3}) def d22v(a, b, c=1, d=2, *rest): pass d22v(1, 2) d22v(1, 2, 3) d22v(1, 2, 3, 4) d22v(1, 2, 3, 4, 5) d22v(*(1, 2, 3, 4)) d22v(1, 2, *(3, 4, 5)) d22v(1, *(2, 3), **{'d': 4}) with check_py3k_warnings(('parenthesized argument names are invalid', SyntaxWarning)): exec('def d31v((x)): pass') with check_py3k_warnings(('tuple parameter unpacking has been removed', SyntaxWarning)): exec('def d32v((x,)): pass') d31v(1) d32v((1,)) # keyword arguments after *arglist def f(*args, **kwargs): return args, kwargs self.assertEqual(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)") self.assertEqual(f(**{'eggs':'scrambled', 'spam':'fried'}), ((), {'eggs':'scrambled', 'spam':'fried'})) self.assertEqual(f(spam='fried', **{'eggs':'scrambled'}), ((), {'eggs':'scrambled', 'spam':'fried'})) # Check ast errors in *args and *kwargs check_syntax_error(self, "f(*g(1=2))") check_syntax_error(self, "f(**g(1=2))") # Check trailing commas are permitted in funcdef argument list def f(a,): pass def test_lambdef(self): ### lambdef: 'lambda' [varargslist] ':' test l1 = lambda : 0 self.assertEqual(l1(), 0) l2 = lambda : a[d] # XXX just testing the expression l3 = lambda : [2 < x for x in [-1, 3, 0L]] self.assertEqual(l3(), [0, 1, 0]) l4 = lambda x = lambda y = lambda z=1 : z : y() : x() self.assertEqual(l4(), 1) l5 = lambda x, y, z=2: x + y + z self.assertEqual(l5(1, 2), 5) self.assertEqual(l5(1, 2, 3), 6) check_syntax_error(self, "lambda x: x = 2") with check_py3k_warnings(('tuple parameter unpacking has been removed', SyntaxWarning)): check_syntax_error(self, "lambda (None,): None") # check that trailing commas are permitted l10 = lambda a,: 0 ### stmt: simple_stmt | compound_stmt # Tested below def test_simple_stmt(self): ### simple_stmt: small_stmt (';' small_stmt)* [';'] x = 1; pass; del x def foo(): # verify statements that end with semi-colons x = 1; pass; del x; foo() ### small_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt # Tested below def test_expr_stmt(self): # (exprlist '=')* exprlist 1 1, 2, 3 x = 1 x = 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) check_syntax_error(self, "x + 1 = 1") check_syntax_error(self, "a + 1 = b + 2") def test_print_stmt(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 1, 2, 3 print 1, 2, 3, print print 0 or 1, 0 or 1, print 0 or 1 # 'print' '>>' test ',' 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 >> 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(): oldstdout = sys.stdout sys.stdout = Gulp() try: tellme(Gulp()) tellme() finally: sys.stdout = oldstdout # we should see this once def tellme(file=sys.stdout): print >> file, 'hello world' driver() # we should not see this at all def tellme(file=None): print >> file, 'goodbye universe' driver() self.assertEqual(sys.stdout.getvalue(), '''\ 1 2 3 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 test_del_stmt(self): # 'del' exprlist abc = [1,2,3] x, y, z = abc xyz = x, y, z del abc del x, y, (z, xyz) def test_pass_stmt(self): # 'pass' pass # flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt # Tested below def test_break_stmt(self): # 'break' while 1: break def test_continue_stmt(self): # 'continue' i = 1 while i: i = 0; continue msg = "" while not msg: msg = "ok" try: continue msg = "continue failed to continue inside try" except: msg = "continue inside try called except block" if msg != "ok": self.fail(msg) msg = "" while not msg: msg = "finally block not called" try: continue finally: msg = "ok" 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 # #463359 and #462937. The bug is that a 'break' statement executed or # exception raised inside a try/except inside a loop, *after* a continue # statement has been executed in that loop, will cause the wrong number of # arguments to be popped off the stack and the instruction pointer reset to # a very small number (usually 0.) Because of this, the following test # *must* written as a function, and the tracking vars *must* be function # arguments with default values. Otherwise, the test will loop and loop. def test_inner(extra_burning_oil = 1, count=0): big_hippo = 2 while big_hippo: count += 1 try: if extra_burning_oil and big_hippo == 1: extra_burning_oil -= 1 break big_hippo -= 1 continue except: raise if count > 2 or big_hippo != 1: self.fail("continue then break in try/except in loop broken!") test_inner() def test_return(self): # 'return' [testlist] def g1(): return def g2(): return 1 g1() x = g2() check_syntax_error(self, "class foo:return 1") def test_break_in_finally(self): count = 0 while count < 2: count += 1 try: pass finally: break self.assertEqual(count, 1) count = 0 while count < 2: count += 1 try: continue finally: break self.assertEqual(count, 1) count = 0 while count < 2: count += 1 try: 1.0/0.0 finally: break self.assertEqual(count, 1) for count in [0, 1]: self.assertEqual(count, 0) try: pass finally: break self.assertEqual(count, 0) for count in [0, 1]: self.assertEqual(count, 0) try: continue finally: break self.assertEqual(count, 0) for count in [0, 1]: self.assertEqual(count, 0) try: 1.0/0.0 finally: break self.assertEqual(count, 0) def test_return_in_finally(self): def g1(): try: pass finally: return 1 self.assertEqual(g1(), 1) def g2(): try: return 2 finally: return 3 self.assertEqual(g2(), 3) def g3(): try: 1.0/0.0 finally: return 4 self.assertEqual(g3(), 4) def test_yield(self): # Allowed as standalone statement def g(): yield 1 # Allowed as RHS of assignment def g(): x = yield 1 # Ordinary yield accepts implicit tuples def g(): yield 1, 1 def g(): x = yield 1, 1 # Requires parentheses as subexpression def g(): 1, (yield 1) check_syntax_error(self, "def g(): 1, yield 1") # Requires parentheses as call argument def g(): f((yield 1)) def g(): f((yield 1), 1) check_syntax_error(self, "def g(): f(yield 1)") check_syntax_error(self, "def g(): f(yield 1, 1)") # Not allowed at top level check_syntax_error(self, "yield") # Not allowed at class scope check_syntax_error(self, "class foo:yield 1") # Check annotation refleak on SyntaxError check_syntax_error(self, "def g(a:(yield)): pass") def test_yield_in_comprehensions(self): # Check yield in comprehensions def g(): [x for x in [(yield 1)]] def check(code, warntext): with check_py3k_warnings((warntext, DeprecationWarning)): compile(code, '', 'exec') if sys.py3kwarning: with warnings.catch_warnings(): warnings.filterwarnings('error', category=DeprecationWarning) with self.assertRaises(SyntaxError) as cm: compile(code, '', 'exec') self.assertIn(warntext, str(cm.exception)) check("def g(): [(yield x) for x in ()]", "'yield' inside list comprehension") check("def g(): [x for x in () if not (yield x)]", "'yield' inside list comprehension") check("def g(): [y for x in () for y in [(yield x)]]", "'yield' inside list comprehension") check("def g(): {(yield x) for x in ()}", "'yield' inside set comprehension") check("def g(): {(yield x): x for x in ()}", "'yield' inside dict comprehension") check("def g(): {x: (yield x) for x in ()}", "'yield' inside dict comprehension") check("def g(): ((yield x) for x in ())", "'yield' inside generator expression") with check_py3k_warnings(("'yield' inside list comprehension", DeprecationWarning)): check_syntax_error(self, "class C: [(yield x) for x in ()]") check("class C: ((yield x) for x in ())", "'yield' inside generator expression") with check_py3k_warnings(("'yield' inside list comprehension", DeprecationWarning)): check_syntax_error(self, "[(yield x) for x in ()]") check("((yield x) for x in ())", "'yield' inside generator expression") def test_raise(self): # 'raise' test [',' test] try: raise RuntimeError, 'just testing' except RuntimeError: pass try: raise KeyboardInterrupt except KeyboardInterrupt: pass def test_import(self): # 'import' dotted_as_names import sys import time, sys # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names) from time import time from time import (time) # 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,) def test_global(self): # 'global' NAME (',' NAME)* global a global a, b global one, two, three, four, five, six, seven, eight, nine, ten def test_exec(self): # 'exec' expr ['in' expr [',' expr]] z = None del z exec 'z=1+1\n' if z != 2: self.fail('exec \'z=1+1\'\\n') del z 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 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\'')""" g = {} exec 'z = 1' in g if '__builtins__' in g: del g['__builtins__'] if g != {'z': 1}: self.fail('exec \'z = 1\' in g') g = {} l = {} exec 'global a; a = 1; b = 2' in g, l if '__builtins__' in g: del g['__builtins__'] if '__builtins__' in l: del l['__builtins__'] if (g, l) != ({'a':1}, {'b':2}): self.fail('exec ... in g (%s), l (%s)' %(g,l)) def test_assert(self): # assertTruestmt: 'assert' test [',' test] assert 1 assert 1, 1 assert lambda x:x assert 1, lambda x:x+1 try: assert True except AssertionError as e: self.fail("'assert True' should not have raised an AssertionError") try: assert True, 'this should always pass' except AssertionError as e: self.fail("'assert True, msg' should not have " "raised an AssertionError") # these tests fail if python is run with -O, so check __debug__ @unittest.skipUnless(__debug__, "Won't work if __debug__ is False") def testAssert2(self): try: assert 0, "msg" except AssertionError, e: self.assertEqual(e.args[0], "msg") else: self.fail("AssertionError not raised by assert 0") try: assert False except AssertionError as e: self.assertEqual(len(e.args), 0) else: self.fail("AssertionError not raised by 'assert False'") ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef # Tested below def test_if(self): # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] if 1: pass if 1: pass else: pass if 0: pass elif 0: pass if 0: pass elif 0: pass elif 0: pass elif 0: pass else: pass def test_while(self): # 'while' test ':' suite ['else' ':' suite] while 0: pass 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.assertEqual(x, 2) def test_for(self): # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] for i in 1, 2, 3: pass for i, j, k in (): pass else: pass class Squares: def __init__(self, max): self.max = max self.sofar = [] def __len__(self): return len(self.sofar) def __getitem__(self, i): if not 0 <= i < self.max: raise IndexError n = len(self.sofar) while n <= i: self.sofar.append(n*n) n = n+1 return self.sofar[i] n = 0 for x in Squares(10): n = n+x if n != 285: self.fail('for over growing sequence') result = [] for x, in [(1,), (2,), (3,)]: result.append(x) self.assertEqual(result, [1, 2, 3]) def test_try(self): ### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] ### | 'try' ':' suite 'finally' ':' suite ### except_clause: 'except' [expr [('as' | ',') expr]] try: 1/0.0 except ZeroDivisionError: pass else: pass try: 1/0.0 except EOFError: pass except TypeError as msg: pass except RuntimeError, msg: pass except: pass else: pass try: 1/0.0 except (EOFError, TypeError, ZeroDivisionError): pass try: 1/0.0 except (EOFError, TypeError, ZeroDivisionError), msg: pass try: pass finally: pass def test_suite(self): # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT if 1: pass if 1: pass if 1: # # # pass pass # pass # def test_test(self): ### and_test ('or' and_test)* ### and_test: not_test ('and' not_test)* ### not_test: 'not' not_test | comparison if not 1: pass if 1 and 1: pass if 1 or 1: pass if not not not 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 def test_comparison(self): ### comparison: expr (comp_op expr)* ### comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' if 1: pass 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 is 1: pass if 1 is not 1: pass if 1 in (): pass if 1 not in (): pass if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in 1 is 1 is not 1: pass with check_py3k_warnings(('<> not supported in 3.x; use !=', DeprecationWarning)): if eval('1 <> 1'): pass with check_py3k_warnings(('<> not supported in 3.x; use !=', DeprecationWarning)): if eval('1 < 1 > 1 == 1 >= 1 <= 1 <> 1 != 1 in 1 not in 1 is 1 is not 1'): pass if sys.py3kwarning: with warnings.catch_warnings(): warnings.filterwarnings('error', category=DeprecationWarning) with self.assertRaises(DeprecationWarning) as cm: compile('1 <> 1', '', 'eval') self.assertIn('<> not supported in 3.x; use !=', str(cm.exception)) def test_binary_mask_ops(self): x = 1 & 1 x = 1 ^ 1 x = 1 | 1 def test_shift_ops(self): x = 1 << 1 x = 1 >> 1 x = 1 << 1 >> 1 def test_additive_ops(self): x = 1 x = 1 + 1 x = 1 - 1 - 1 x = 1 - 1 + 1 - 1 + 1 def test_multiplicative_ops(self): x = 1 * 1 with check_py3k_warnings(('classic int division', DeprecationWarning)): x = 1 / 1 x = 1 / 1.0 x = 1 % 1 with check_py3k_warnings(('classic int division', DeprecationWarning)): x = 1 / 1 * 1 % 1 x = 1 / 1.0 * 1 % 1 def test_unary_ops(self): x = +1 x = -1 x = ~1 x = ~1 ^ 1 & 1 | 1 & 1 ^ -1 with check_py3k_warnings(('classic int division', DeprecationWarning)): x = -1*1/1 + 1*1 - ---1*1 x = -1*1/1.0 + 1*1 - ---1*1 def test_selectors(self): ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME ### subscript: expr | [expr] ':' [expr] import sys, time c = sys.path[0] x = time.time() x = sys.modules['time'].time() a = '01234' c = a[0] c = a[-1] s = a[0:5] s = a[:5] s = a[0:] s = a[:] s = a[-5:] s = a[:-1] s = a[-4:-3] # A rough test of SF bug 1333982. http://python.org/sf/1333982 # The testing here is fairly incomplete. # Test cases should include: commas with 1 and 2 colons d = {} d[1] = 1 d[1,] = 2 d[1,2] = 3 d[1,2,3] = 4 L = list(d) L.sort(key=lambda x: (type(x).__name__, x)) self.assertEqual(str(L), '[1, (1,), (1, 2), (1, 2, 3)]') def test_atoms(self): ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING ### dictorsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [',']) x = (1) x = (1 or 2 or 3) x = (1 or 2 or 3, 2, 3) x = [] x = [1] x = [1 or 2 or 3] x = [1 or 2 or 3, 2, 3] x = [] x = {} x = {'one': 1} x = {'one': 1,} x = {'one' or 'two': 1 or 2} 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'} x = {'one', 1,} x = {'one', 'two', 'three'} x = {2, 3, 4,} with check_py3k_warnings(('backquote not supported', SyntaxWarning)): x = eval('`x`') x = eval('`1 or 2 or 3`') self.assertEqual(eval('`1,2`'), '(1, 2)') x = x x = 'x' x = 123 ### exprlist: expr (',' expr)* [','] ### testlist: test (',' test)* [','] # These have been exercised enough above def test_classdef(self): # 'class' NAME ['(' [testlist] ')'] ':' suite class B: pass class B2(): pass class C1(B): pass class C2(B): pass class D(C1, C2, B): pass class C: 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 test_dictcomps(self): # dictorsetmaker: ( (test ':' test (comp_for | # (',' test ':' test)* [','])) | # (test (comp_for | (',' test)* [','])) ) nums = [1, 2, 3] self.assertEqual({i:i+1 for i in nums}, {1: 2, 2: 3, 3: 4}) def test_listcomps(self): # list comprehension tests nums = [1, 2, 3, 4, 5] strs = ["Apple", "Banana", "Coconut"] spcs = [" Apple", " Banana ", "Coco nut "] self.assertEqual([s.strip() for s in spcs], ['Apple', 'Banana', 'Coco nut']) self.assertEqual([3 * x for x in nums], [3, 6, 9, 12, 15]) self.assertEqual([x for x in nums if x > 2], [3, 4, 5]) self.assertEqual([(i, s) for i in nums for s in strs], [(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')]) 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): return [0 < x < 3 for x in l if x > 2] self.assertEqual(test_in_func(nums), [False, False, False]) def test_nested_front(): self.assertEqual([[y for y in [x, x + 1]] for x in [1,3,5]], [[1, 2], [3, 4], [5, 6]]) test_nested_front() check_syntax_error(self, "[i, s for i in nums for s in strs]") check_syntax_error(self, "[x if y]") suppliers = [ (1, "Boeing"), (2, "Ford"), (3, "Macdonalds") ] parts = [ (10, "Airliner"), (20, "Engine"), (30, "Cheeseburger") ] suppart = [ (1, 10), (1, 20), (2, 20), (3, 30) ] x = [ (sname, pname) for (sno, sname) in suppliers for (pno, pname) in parts for (sp_sno, sp_pno) in suppart if sno == sp_sno and pno == sp_pno ] self.assertEqual(x, [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')]) def test_genexps(self): # generator expression tests g = ([x for x in range(10)] for x in range(1)) self.assertEqual(g.next(), [x for x in range(10)]) try: g.next() self.fail('should produce StopIteration exception') except StopIteration: pass a = 1 try: g = (a for d in a) g.next() self.fail('should produce TypeError') except TypeError: pass self.assertEqual(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 'ab' for y in 'xy'), [(x, y) for x in 'ab' for y in 'xy']) a = [x for x in range(10)] b = (x for x in (y for y in a)) self.assertEqual(sum(b), sum([x for x in range(10)])) self.assertEqual(sum(x**2 for x in range(10)), sum([x**2 for x in range(10)])) self.assertEqual(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 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 (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)])) 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)])) 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_error(self, "foo(x for x in range(10), 100)") check_syntax_error(self, "foo(100, x for x in range(10))") def test_comprehension_specials(self): # test for outmost iterable precomputation x = 10; g = (i for i in range(x)); x = 5 self.assertEqual(len(list(g)), 10) # 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 = 5; t = True; 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, # even though it's silly. Make sure it works (ifelse broke this.) self.assertEqual([ 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. self.assertEqual([x for x, in [(4,), (5,), (6,)]], [4, 5, 6]) self.assertEqual(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9]) def test_with_statement(self): class manager(object): def __enter__(self): return (1, 2) def __exit__(self, *args): pass with manager(): pass with manager() as x: pass with manager() as (x, y): pass with manager(), manager(): pass with manager() as x, manager() as y: pass with manager() as x, manager(): pass def test_if_else_expr(self): # Test ifelse expressions in various cases def _checkeval(msg, ret): "helper to check that evaluation of expressions is done correctly" print(msg) 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]) 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]) self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5) self.assertEqual((_checkeval("check 2", 0) if 0 else 5), 5) self.assertEqual((5 and 6 if 0 else 1), 1) self.assertEqual(((5 and 6) if 0 else 1), 1) self.assertEqual((5 and (6 if 1 else 1)), 6) self.assertEqual((0 or _checkeval("check 3", 2) if 0 else 3), 3) self.assertEqual((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1) self.assertEqual((0 or 5 if 1 else _checkeval("check 6", 3)), 5) self.assertEqual((not 5 if 1 else 1), False) self.assertEqual((not 5 if 0 else 1), 1) self.assertEqual((6 + 1 if 1 else 2), 7) self.assertEqual((6 - 1 if 1 else 2), 5) self.assertEqual((6 * 2 if 1 else 4), 12) with check_py3k_warnings(('classic int division', DeprecationWarning)): self.assertEqual((6 / 2 if 1 else 3), 3) self.assertEqual((6 < 4 if 0 else 2), 2) def test_paren_evaluation(self): self.assertEqual(16 // (4 // 2), 8) self.assertEqual((16 // 4) // 2, 2) self.assertEqual(16 // 4 // 2, 2) self.assertTrue(False is (2 is 3)) self.assertFalse((False is 2) is 3) self.assertFalse(False is 2 is 3) def test_main(): run_unittest(TokenTests, GrammarTests) if __name__ == '__main__': test_main()