Home | History | Annotate | Download | only in test
      1 import unittest
      2 import sys
      3 import _ast
      4 from test import test_support
      5 import textwrap
      6 
      7 class TestSpecifics(unittest.TestCase):
      8 
      9     def test_no_ending_newline(self):
     10         compile("hi", "<test>", "exec")
     11         compile("hi\r", "<test>", "exec")
     12 
     13     def test_empty(self):
     14         compile("", "<test>", "exec")
     15 
     16     def test_other_newlines(self):
     17         compile("\r\n", "<test>", "exec")
     18         compile("\r", "<test>", "exec")
     19         compile("hi\r\nstuff\r\ndef f():\n    pass\r", "<test>", "exec")
     20         compile("this_is\rreally_old_mac\rdef f():\n    pass", "<test>", "exec")
     21 
     22     def test_debug_assignment(self):
     23         # catch assignments to __debug__
     24         self.assertRaises(SyntaxError, compile, '__debug__ = 1', '?', 'single')
     25         import __builtin__
     26         prev = __builtin__.__debug__
     27         setattr(__builtin__, '__debug__', 'sure')
     28         setattr(__builtin__, '__debug__', prev)
     29 
     30     def test_argument_handling(self):
     31         # detect duplicate positional and keyword arguments
     32         self.assertRaises(SyntaxError, eval, 'lambda a,a:0')
     33         self.assertRaises(SyntaxError, eval, 'lambda a,a=1:0')
     34         self.assertRaises(SyntaxError, eval, 'lambda a=1,a=1:0')
     35         try:
     36             exec 'def f(a, a): pass'
     37             self.fail("duplicate arguments")
     38         except SyntaxError:
     39             pass
     40         try:
     41             exec 'def f(a = 0, a = 1): pass'
     42             self.fail("duplicate keyword arguments")
     43         except SyntaxError:
     44             pass
     45         try:
     46             exec 'def f(a): global a; a = 1'
     47             self.fail("variable is global and local")
     48         except SyntaxError:
     49             pass
     50 
     51     def test_syntax_error(self):
     52         self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
     53 
     54     def test_none_keyword_arg(self):
     55         self.assertRaises(SyntaxError, compile, "f(None=1)", "<string>", "exec")
     56 
     57     def test_duplicate_global_local(self):
     58         try:
     59             exec 'def f(a): global a; a = 1'
     60             self.fail("variable is global and local")
     61         except SyntaxError:
     62             pass
     63 
     64     def test_exec_functional_style(self):
     65         # Exec'ing a tuple of length 2 works.
     66         g = {'b': 2}
     67         exec("a = b + 1", g)
     68         self.assertEqual(g['a'], 3)
     69 
     70         # As does exec'ing a tuple of length 3.
     71         l = {'b': 3}
     72         g = {'b': 5, 'c': 7}
     73         exec("a = b + c", g, l)
     74         self.assertNotIn('a', g)
     75         self.assertEqual(l['a'], 10)
     76 
     77         # Tuples not of length 2 or 3 are invalid.
     78         with self.assertRaises(TypeError):
     79             exec("a = b + 1",)
     80 
     81         with self.assertRaises(TypeError):
     82             exec("a = b + 1", {}, {}, {})
     83 
     84         # Can't mix and match the two calling forms.
     85         g = {'a': 3, 'b': 4}
     86         l = {}
     87         with self.assertRaises(TypeError):
     88             exec("a = b + 1", g) in g
     89         with self.assertRaises(TypeError):
     90             exec("a = b + 1", g, l) in g, l
     91 
     92     def test_exec_with_general_mapping_for_locals(self):
     93 
     94         class M:
     95             "Test mapping interface versus possible calls from eval()."
     96             def __getitem__(self, key):
     97                 if key == 'a':
     98                     return 12
     99                 raise KeyError
    100             def __setitem__(self, key, value):
    101                 self.results = (key, value)
    102             def keys(self):
    103                 return list('xyz')
    104 
    105         m = M()
    106         g = globals()
    107         exec 'z = a' in g, m
    108         self.assertEqual(m.results, ('z', 12))
    109         try:
    110             exec 'z = b' in g, m
    111         except NameError:
    112             pass
    113         else:
    114             self.fail('Did not detect a KeyError')
    115         exec 'z = dir()' in g, m
    116         self.assertEqual(m.results, ('z', list('xyz')))
    117         exec 'z = globals()' in g, m
    118         self.assertEqual(m.results, ('z', g))
    119         exec 'z = locals()' in g, m
    120         self.assertEqual(m.results, ('z', m))
    121         try:
    122             exec 'z = b' in m
    123         except TypeError:
    124             pass
    125         else:
    126             self.fail('Did not validate globals as a real dict')
    127 
    128         class A:
    129             "Non-mapping"
    130             pass
    131         m = A()
    132         try:
    133             exec 'z = a' in g, m
    134         except TypeError:
    135             pass
    136         else:
    137             self.fail('Did not validate locals as a mapping')
    138 
    139         # Verify that dict subclasses work as well
    140         class D(dict):
    141             def __getitem__(self, key):
    142                 if key == 'a':
    143                     return 12
    144                 return dict.__getitem__(self, key)
    145         d = D()
    146         exec 'z = a' in g, d
    147         self.assertEqual(d['z'], 12)
    148 
    149     def test_extended_arg(self):
    150         longexpr = 'x = x or ' + '-x' * 2500
    151         code = '''
    152 def f(x):
    153     %s
    154     %s
    155     %s
    156     %s
    157     %s
    158     %s
    159     %s
    160     %s
    161     %s
    162     %s
    163     # the expressions above have no effect, x == argument
    164     while x:
    165         x -= 1
    166         # EXTENDED_ARG/JUMP_ABSOLUTE here
    167     return x
    168 ''' % ((longexpr,)*10)
    169         exec code
    170         self.assertEqual(f(5), 0)
    171 
    172     def test_complex_args(self):
    173 
    174         with test_support.check_py3k_warnings(
    175                 ("tuple parameter unpacking has been removed", SyntaxWarning)):
    176             exec textwrap.dedent('''
    177         def comp_args((a, b)):
    178             return a,b
    179         self.assertEqual(comp_args((1, 2)), (1, 2))
    180 
    181         def comp_args((a, b)=(3, 4)):
    182             return a, b
    183         self.assertEqual(comp_args((1, 2)), (1, 2))
    184         self.assertEqual(comp_args(), (3, 4))
    185 
    186         def comp_args(a, (b, c)):
    187             return a, b, c
    188         self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3))
    189 
    190         def comp_args(a=2, (b, c)=(3, 4)):
    191             return a, b, c
    192         self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3))
    193         self.assertEqual(comp_args(), (2, 3, 4))
    194         ''')
    195 
    196     def test_argument_order(self):
    197         try:
    198             exec 'def f(a=1, (b, c)): pass'
    199             self.fail("non-default args after default")
    200         except SyntaxError:
    201             pass
    202 
    203     def test_float_literals(self):
    204         # testing bad float literals
    205         self.assertRaises(SyntaxError, eval, "2e")
    206         self.assertRaises(SyntaxError, eval, "2.0e+")
    207         self.assertRaises(SyntaxError, eval, "1e-")
    208         self.assertRaises(SyntaxError, eval, "3-4e/21")
    209 
    210     def test_indentation(self):
    211         # testing compile() of indented block w/o trailing newline"
    212         s = """
    213 if 1:
    214     if 2:
    215         pass"""
    216         compile(s, "<string>", "exec")
    217 
    218     # This test is probably specific to CPython and may not generalize
    219     # to other implementations.  We are trying to ensure that when
    220     # the first line of code starts after 256, correct line numbers
    221     # in tracebacks are still produced.
    222     def test_leading_newlines(self):
    223         s256 = "".join(["\n"] * 256 + ["spam"])
    224         co = compile(s256, 'fn', 'exec')
    225         self.assertEqual(co.co_firstlineno, 257)
    226         self.assertEqual(co.co_lnotab, '')
    227 
    228     def test_literals_with_leading_zeroes(self):
    229         for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000",
    230                     "080000000000000", "000000000000009", "000000000000008",
    231                     "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
    232                     "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0o8", "0o78"]:
    233             self.assertRaises(SyntaxError, eval, arg)
    234 
    235         self.assertEqual(eval("0777"), 511)
    236         self.assertEqual(eval("0777L"), 511)
    237         self.assertEqual(eval("000777"), 511)
    238         self.assertEqual(eval("0xff"), 255)
    239         self.assertEqual(eval("0xffL"), 255)
    240         self.assertEqual(eval("0XfF"), 255)
    241         self.assertEqual(eval("0777."), 777)
    242         self.assertEqual(eval("0777.0"), 777)
    243         self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
    244         self.assertEqual(eval("0777e1"), 7770)
    245         self.assertEqual(eval("0e0"), 0)
    246         self.assertEqual(eval("0000E-012"), 0)
    247         self.assertEqual(eval("09.5"), 9.5)
    248         self.assertEqual(eval("0777j"), 777j)
    249         self.assertEqual(eval("00j"), 0j)
    250         self.assertEqual(eval("00.0"), 0)
    251         self.assertEqual(eval("0e3"), 0)
    252         self.assertEqual(eval("090000000000000."), 90000000000000.)
    253         self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
    254         self.assertEqual(eval("090000000000000e0"), 90000000000000.)
    255         self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
    256         self.assertEqual(eval("090000000000000j"), 90000000000000j)
    257         self.assertEqual(eval("000000000000007"), 7)
    258         self.assertEqual(eval("000000000000008."), 8.)
    259         self.assertEqual(eval("000000000000009."), 9.)
    260         self.assertEqual(eval("0b101010"), 42)
    261         self.assertEqual(eval("-0b000000000010"), -2)
    262         self.assertEqual(eval("0o777"), 511)
    263         self.assertEqual(eval("-0o0000010"), -8)
    264         self.assertEqual(eval("020000000000.0"), 20000000000.0)
    265         self.assertEqual(eval("037777777777e0"), 37777777777.0)
    266         self.assertEqual(eval("01000000000000000000000.0"),
    267                          1000000000000000000000.0)
    268 
    269     def test_unary_minus(self):
    270         # Verify treatment of unary minus on negative numbers SF bug #660455
    271         if sys.maxint == 2147483647:
    272             # 32-bit machine
    273             all_one_bits = '0xffffffff'
    274             self.assertEqual(eval(all_one_bits), 4294967295L)
    275             self.assertEqual(eval("-" + all_one_bits), -4294967295L)
    276         elif sys.maxint == 9223372036854775807:
    277             # 64-bit machine
    278             all_one_bits = '0xffffffffffffffff'
    279             self.assertEqual(eval(all_one_bits), 18446744073709551615L)
    280             self.assertEqual(eval("-" + all_one_bits), -18446744073709551615L)
    281         else:
    282             self.fail("How many bits *does* this machine have???")
    283         # Verify treatment of constant folding on -(sys.maxint+1)
    284         # i.e. -2147483648 on 32 bit platforms.  Should return int, not long.
    285         self.assertIsInstance(eval("%s" % (-sys.maxint - 1)), int)
    286         self.assertIsInstance(eval("%s" % (-sys.maxint - 2)), long)
    287 
    288     if sys.maxint == 9223372036854775807:
    289         def test_32_63_bit_values(self):
    290             a = +4294967296  # 1 << 32
    291             b = -4294967296  # 1 << 32
    292             c = +281474976710656  # 1 << 48
    293             d = -281474976710656  # 1 << 48
    294             e = +4611686018427387904  # 1 << 62
    295             f = -4611686018427387904  # 1 << 62
    296             g = +9223372036854775807  # 1 << 63 - 1
    297             h = -9223372036854775807  # 1 << 63 - 1
    298 
    299             for variable in self.test_32_63_bit_values.func_code.co_consts:
    300                 if variable is not None:
    301                     self.assertIsInstance(variable, int)
    302 
    303     def test_sequence_unpacking_error(self):
    304         # Verify sequence packing/unpacking with "or".  SF bug #757818
    305         i,j = (1, -1) or (-1, 1)
    306         self.assertEqual(i, 1)
    307         self.assertEqual(j, -1)
    308 
    309     def test_none_assignment(self):
    310         stmts = [
    311             'None = 0',
    312             'None += 0',
    313             '__builtins__.None = 0',
    314             'def None(): pass',
    315             'class None: pass',
    316             '(a, None) = 0, 0',
    317             'for None in range(10): pass',
    318             'def f(None): pass',
    319             'import None',
    320             'import x as None',
    321             'from x import None',
    322             'from x import y as None'
    323         ]
    324         for stmt in stmts:
    325             stmt += "\n"
    326             self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
    327             self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
    328         # This is ok.
    329         compile("from None import x", "tmp", "exec")
    330         compile("from x import None as y", "tmp", "exec")
    331         compile("import None as x", "tmp", "exec")
    332 
    333     def test_import(self):
    334         succeed = [
    335             'import sys',
    336             'import os, sys',
    337             'import os as bar',
    338             'import os.path as bar',
    339             'from __future__ import nested_scopes, generators',
    340             'from __future__ import (nested_scopes,\ngenerators)',
    341             'from __future__ import (nested_scopes,\ngenerators,)',
    342             'from sys import stdin, stderr, stdout',
    343             'from sys import (stdin, stderr,\nstdout)',
    344             'from sys import (stdin, stderr,\nstdout,)',
    345             'from sys import (stdin\n, stderr, stdout)',
    346             'from sys import (stdin\n, stderr, stdout,)',
    347             'from sys import stdin as si, stdout as so, stderr as se',
    348             'from sys import (stdin as si, stdout as so, stderr as se)',
    349             'from sys import (stdin as si, stdout as so, stderr as se,)',
    350             ]
    351         fail = [
    352             'import (os, sys)',
    353             'import (os), (sys)',
    354             'import ((os), (sys))',
    355             'import (sys',
    356             'import sys)',
    357             'import (os,)',
    358             'import os As bar',
    359             'import os.path a bar',
    360             'from sys import stdin As stdout',
    361             'from sys import stdin a stdout',
    362             'from (sys) import stdin',
    363             'from __future__ import (nested_scopes',
    364             'from __future__ import nested_scopes)',
    365             'from __future__ import nested_scopes,\ngenerators',
    366             'from sys import (stdin',
    367             'from sys import stdin)',
    368             'from sys import stdin, stdout,\nstderr',
    369             'from sys import stdin si',
    370             'from sys import stdin,'
    371             'from sys import (*)',
    372             'from sys import (stdin,, stdout, stderr)',
    373             'from sys import (stdin, stdout),',
    374             ]
    375         for stmt in succeed:
    376             compile(stmt, 'tmp', 'exec')
    377         for stmt in fail:
    378             self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
    379 
    380     def test_for_distinct_code_objects(self):
    381         # SF bug 1048870
    382         def f():
    383             f1 = lambda x=1: x
    384             f2 = lambda x=2: x
    385             return f1, f2
    386         f1, f2 = f()
    387         self.assertNotEqual(id(f1.func_code), id(f2.func_code))
    388 
    389     def test_lambda_doc(self):
    390         l = lambda: "foo"
    391         self.assertIsNone(l.__doc__)
    392 
    393     def test_unicode_encoding(self):
    394         code = u"# -*- coding: utf-8 -*-\npass\n"
    395         self.assertRaises(SyntaxError, compile, code, "tmp", "exec")
    396 
    397     def test_subscripts(self):
    398         # SF bug 1448804
    399         # Class to make testing subscript results easy
    400         class str_map(object):
    401             def __init__(self):
    402                 self.data = {}
    403             def __getitem__(self, key):
    404                 return self.data[str(key)]
    405             def __setitem__(self, key, value):
    406                 self.data[str(key)] = value
    407             def __delitem__(self, key):
    408                 del self.data[str(key)]
    409             def __contains__(self, key):
    410                 return str(key) in self.data
    411         d = str_map()
    412         # Index
    413         d[1] = 1
    414         self.assertEqual(d[1], 1)
    415         d[1] += 1
    416         self.assertEqual(d[1], 2)
    417         del d[1]
    418         self.assertNotIn(1, d)
    419         # Tuple of indices
    420         d[1, 1] = 1
    421         self.assertEqual(d[1, 1], 1)
    422         d[1, 1] += 1
    423         self.assertEqual(d[1, 1], 2)
    424         del d[1, 1]
    425         self.assertNotIn((1, 1), d)
    426         # Simple slice
    427         d[1:2] = 1
    428         self.assertEqual(d[1:2], 1)
    429         d[1:2] += 1
    430         self.assertEqual(d[1:2], 2)
    431         del d[1:2]
    432         self.assertNotIn(slice(1, 2), d)
    433         # Tuple of simple slices
    434         d[1:2, 1:2] = 1
    435         self.assertEqual(d[1:2, 1:2], 1)
    436         d[1:2, 1:2] += 1
    437         self.assertEqual(d[1:2, 1:2], 2)
    438         del d[1:2, 1:2]
    439         self.assertNotIn((slice(1, 2), slice(1, 2)), d)
    440         # Extended slice
    441         d[1:2:3] = 1
    442         self.assertEqual(d[1:2:3], 1)
    443         d[1:2:3] += 1
    444         self.assertEqual(d[1:2:3], 2)
    445         del d[1:2:3]
    446         self.assertNotIn(slice(1, 2, 3), d)
    447         # Tuple of extended slices
    448         d[1:2:3, 1:2:3] = 1
    449         self.assertEqual(d[1:2:3, 1:2:3], 1)
    450         d[1:2:3, 1:2:3] += 1
    451         self.assertEqual(d[1:2:3, 1:2:3], 2)
    452         del d[1:2:3, 1:2:3]
    453         self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
    454         # Ellipsis
    455         d[...] = 1
    456         self.assertEqual(d[...], 1)
    457         d[...] += 1
    458         self.assertEqual(d[...], 2)
    459         del d[...]
    460         self.assertNotIn(Ellipsis, d)
    461         # Tuple of Ellipses
    462         d[..., ...] = 1
    463         self.assertEqual(d[..., ...], 1)
    464         d[..., ...] += 1
    465         self.assertEqual(d[..., ...], 2)
    466         del d[..., ...]
    467         self.assertNotIn((Ellipsis, Ellipsis), d)
    468 
    469     def test_mangling(self):
    470         class A:
    471             def f():
    472                 __mangled = 1
    473                 __not_mangled__ = 2
    474                 import __mangled_mod
    475                 import __package__.module
    476 
    477         self.assertIn("_A__mangled", A.f.func_code.co_varnames)
    478         self.assertIn("__not_mangled__", A.f.func_code.co_varnames)
    479         self.assertIn("_A__mangled_mod", A.f.func_code.co_varnames)
    480         self.assertIn("__package__", A.f.func_code.co_varnames)
    481 
    482     def test_compile_ast(self):
    483         fname = __file__
    484         if fname.lower().endswith(('pyc', 'pyo')):
    485             fname = fname[:-1]
    486         with open(fname, 'r') as f:
    487             fcontents = f.read()
    488         sample_code = [
    489             ['<assign>', 'x = 5'],
    490             ['<print1>', 'print 1'],
    491             ['<printv>', 'print v'],
    492             ['<printTrue>', 'print True'],
    493             ['<printList>', 'print []'],
    494             ['<ifblock>', """if True:\n    pass\n"""],
    495             ['<forblock>', """for n in [1, 2, 3]:\n    print n\n"""],
    496             ['<deffunc>', """def foo():\n    pass\nfoo()\n"""],
    497             [fname, fcontents],
    498         ]
    499 
    500         for fname, code in sample_code:
    501             co1 = compile(code, '%s1' % fname, 'exec')
    502             ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
    503             self.assertTrue(type(ast) == _ast.Module)
    504             co2 = compile(ast, '%s3' % fname, 'exec')
    505             self.assertEqual(co1, co2)
    506             # the code object's filename comes from the second compilation step
    507             self.assertEqual(co2.co_filename, '%s3' % fname)
    508 
    509         # raise exception when node type doesn't match with compile mode
    510         co1 = compile('print 1', '<string>', 'exec', _ast.PyCF_ONLY_AST)
    511         self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
    512 
    513         # raise exception when node type is no start node
    514         self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
    515 
    516         # raise exception when node has invalid children
    517         ast = _ast.Module()
    518         ast.body = [_ast.BoolOp()]
    519         self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
    520 
    521 
    522 def test_main():
    523     test_support.run_unittest(TestSpecifics)
    524 
    525 if __name__ == "__main__":
    526     test_main()
    527