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_with_general_mapping_for_locals(self):
     65 
     66         class M:
     67             "Test mapping interface versus possible calls from eval()."
     68             def __getitem__(self, key):
     69                 if key == 'a':
     70                     return 12
     71                 raise KeyError
     72             def __setitem__(self, key, value):
     73                 self.results = (key, value)
     74             def keys(self):
     75                 return list('xyz')
     76 
     77         m = M()
     78         g = globals()
     79         exec 'z = a' in g, m
     80         self.assertEqual(m.results, ('z', 12))
     81         try:
     82             exec 'z = b' in g, m
     83         except NameError:
     84             pass
     85         else:
     86             self.fail('Did not detect a KeyError')
     87         exec 'z = dir()' in g, m
     88         self.assertEqual(m.results, ('z', list('xyz')))
     89         exec 'z = globals()' in g, m
     90         self.assertEqual(m.results, ('z', g))
     91         exec 'z = locals()' in g, m
     92         self.assertEqual(m.results, ('z', m))
     93         try:
     94             exec 'z = b' in m
     95         except TypeError:
     96             pass
     97         else:
     98             self.fail('Did not validate globals as a real dict')
     99 
    100         class A:
    101             "Non-mapping"
    102             pass
    103         m = A()
    104         try:
    105             exec 'z = a' in g, m
    106         except TypeError:
    107             pass
    108         else:
    109             self.fail('Did not validate locals as a mapping')
    110 
    111         # Verify that dict subclasses work as well

    112         class D(dict):
    113             def __getitem__(self, key):
    114                 if key == 'a':
    115                     return 12
    116                 return dict.__getitem__(self, key)
    117         d = D()
    118         exec 'z = a' in g, d
    119         self.assertEqual(d['z'], 12)
    120 
    121     def test_extended_arg(self):
    122         longexpr = 'x = x or ' + '-x' * 2500
    123         code = '''
    124 def f(x):
    125     %s
    126     %s
    127     %s
    128     %s
    129     %s
    130     %s
    131     %s
    132     %s
    133     %s
    134     %s
    135     # the expressions above have no effect, x == argument
    136     while x:
    137         x -= 1
    138         # EXTENDED_ARG/JUMP_ABSOLUTE here
    139     return x
    140 ''' % ((longexpr,)*10)
    141         exec code
    142         self.assertEqual(f(5), 0)
    143 
    144     def test_complex_args(self):
    145 
    146         with test_support.check_py3k_warnings(
    147                 ("tuple parameter unpacking has been removed", SyntaxWarning)):
    148             exec textwrap.dedent('''
    149         def comp_args((a, b)):
    150             return a,b
    151         self.assertEqual(comp_args((1, 2)), (1, 2))
    152 
    153         def comp_args((a, b)=(3, 4)):
    154             return a, b
    155         self.assertEqual(comp_args((1, 2)), (1, 2))
    156         self.assertEqual(comp_args(), (3, 4))
    157 
    158         def comp_args(a, (b, c)):
    159             return a, b, c
    160         self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3))
    161 
    162         def comp_args(a=2, (b, c)=(3, 4)):
    163             return a, b, c
    164         self.assertEqual(comp_args(1, (2, 3)), (1, 2, 3))
    165         self.assertEqual(comp_args(), (2, 3, 4))
    166         ''')
    167 
    168     def test_argument_order(self):
    169         try:
    170             exec 'def f(a=1, (b, c)): pass'
    171             self.fail("non-default args after default")
    172         except SyntaxError:
    173             pass
    174 
    175     def test_float_literals(self):
    176         # testing bad float literals

    177         self.assertRaises(SyntaxError, eval, "2e")
    178         self.assertRaises(SyntaxError, eval, "2.0e+")
    179         self.assertRaises(SyntaxError, eval, "1e-")
    180         self.assertRaises(SyntaxError, eval, "3-4e/21")
    181 
    182     def test_indentation(self):
    183         # testing compile() of indented block w/o trailing newline"

    184         s = """
    185 if 1:
    186     if 2:
    187         pass"""
    188         compile(s, "<string>", "exec")
    189 
    190     # This test is probably specific to CPython and may not generalize

    191     # to other implementations.  We are trying to ensure that when

    192     # the first line of code starts after 256, correct line numbers

    193     # in tracebacks are still produced.

    194     def test_leading_newlines(self):
    195         s256 = "".join(["\n"] * 256 + ["spam"])
    196         co = compile(s256, 'fn', 'exec')
    197         self.assertEqual(co.co_firstlineno, 257)
    198         self.assertEqual(co.co_lnotab, '')
    199 
    200     def test_literals_with_leading_zeroes(self):
    201         for arg in ["077787", "0xj", "0x.", "0e",  "090000000000000",
    202                     "080000000000000", "000000000000009", "000000000000008",
    203                     "0b42", "0BADCAFE", "0o123456789", "0b1.1", "0o4.2",
    204                     "0b101j2", "0o153j2", "0b100e1", "0o777e1", "0o8", "0o78"]:
    205             self.assertRaises(SyntaxError, eval, arg)
    206 
    207         self.assertEqual(eval("0777"), 511)
    208         self.assertEqual(eval("0777L"), 511)
    209         self.assertEqual(eval("000777"), 511)
    210         self.assertEqual(eval("0xff"), 255)
    211         self.assertEqual(eval("0xffL"), 255)
    212         self.assertEqual(eval("0XfF"), 255)
    213         self.assertEqual(eval("0777."), 777)
    214         self.assertEqual(eval("0777.0"), 777)
    215         self.assertEqual(eval("000000000000000000000000000000000000000000000000000777e0"), 777)
    216         self.assertEqual(eval("0777e1"), 7770)
    217         self.assertEqual(eval("0e0"), 0)
    218         self.assertEqual(eval("0000E-012"), 0)
    219         self.assertEqual(eval("09.5"), 9.5)
    220         self.assertEqual(eval("0777j"), 777j)
    221         self.assertEqual(eval("00j"), 0j)
    222         self.assertEqual(eval("00.0"), 0)
    223         self.assertEqual(eval("0e3"), 0)
    224         self.assertEqual(eval("090000000000000."), 90000000000000.)
    225         self.assertEqual(eval("090000000000000.0000000000000000000000"), 90000000000000.)
    226         self.assertEqual(eval("090000000000000e0"), 90000000000000.)
    227         self.assertEqual(eval("090000000000000e-0"), 90000000000000.)
    228         self.assertEqual(eval("090000000000000j"), 90000000000000j)
    229         self.assertEqual(eval("000000000000007"), 7)
    230         self.assertEqual(eval("000000000000008."), 8.)
    231         self.assertEqual(eval("000000000000009."), 9.)
    232         self.assertEqual(eval("0b101010"), 42)
    233         self.assertEqual(eval("-0b000000000010"), -2)
    234         self.assertEqual(eval("0o777"), 511)
    235         self.assertEqual(eval("-0o0000010"), -8)
    236         self.assertEqual(eval("020000000000.0"), 20000000000.0)
    237         self.assertEqual(eval("037777777777e0"), 37777777777.0)
    238         self.assertEqual(eval("01000000000000000000000.0"),
    239                          1000000000000000000000.0)
    240 
    241     def test_unary_minus(self):
    242         # Verify treatment of unary minus on negative numbers SF bug #660455

    243         if sys.maxint == 2147483647:
    244             # 32-bit machine

    245             all_one_bits = '0xffffffff'
    246             self.assertEqual(eval(all_one_bits), 4294967295L)
    247             self.assertEqual(eval("-" + all_one_bits), -4294967295L)
    248         elif sys.maxint == 9223372036854775807:
    249             # 64-bit machine

    250             all_one_bits = '0xffffffffffffffff'
    251             self.assertEqual(eval(all_one_bits), 18446744073709551615L)
    252             self.assertEqual(eval("-" + all_one_bits), -18446744073709551615L)
    253         else:
    254             self.fail("How many bits *does* this machine have???")
    255         # Verify treatment of constant folding on -(sys.maxint+1)

    256         # i.e. -2147483648 on 32 bit platforms.  Should return int, not long.

    257         self.assertIsInstance(eval("%s" % (-sys.maxint - 1)), int)
    258         self.assertIsInstance(eval("%s" % (-sys.maxint - 2)), long)
    259 
    260     if sys.maxint == 9223372036854775807:
    261         def test_32_63_bit_values(self):
    262             a = +4294967296  # 1 << 32

    263             b = -4294967296  # 1 << 32

    264             c = +281474976710656  # 1 << 48

    265             d = -281474976710656  # 1 << 48

    266             e = +4611686018427387904  # 1 << 62

    267             f = -4611686018427387904  # 1 << 62

    268             g = +9223372036854775807  # 1 << 63 - 1

    269             h = -9223372036854775807  # 1 << 63 - 1

    270 
    271             for variable in self.test_32_63_bit_values.func_code.co_consts:
    272                 if variable is not None:
    273                     self.assertIsInstance(variable, int)
    274 
    275     def test_sequence_unpacking_error(self):
    276         # Verify sequence packing/unpacking with "or".  SF bug #757818

    277         i,j = (1, -1) or (-1, 1)
    278         self.assertEqual(i, 1)
    279         self.assertEqual(j, -1)
    280 
    281     def test_none_assignment(self):
    282         stmts = [
    283             'None = 0',
    284             'None += 0',
    285             '__builtins__.None = 0',
    286             'def None(): pass',
    287             'class None: pass',
    288             '(a, None) = 0, 0',
    289             'for None in range(10): pass',
    290             'def f(None): pass',
    291             'import None',
    292             'import x as None',
    293             'from x import None',
    294             'from x import y as None'
    295         ]
    296         for stmt in stmts:
    297             stmt += "\n"
    298             self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'single')
    299             self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
    300         # This is ok.

    301         compile("from None import x", "tmp", "exec")
    302         compile("from x import None as y", "tmp", "exec")
    303         compile("import None as x", "tmp", "exec")
    304 
    305     def test_import(self):
    306         succeed = [
    307             'import sys',
    308             'import os, sys',
    309             'import os as bar',
    310             'import os.path as bar',
    311             'from __future__ import nested_scopes, generators',
    312             'from __future__ import (nested_scopes,\ngenerators)',
    313             'from __future__ import (nested_scopes,\ngenerators,)',
    314             'from sys import stdin, stderr, stdout',
    315             'from sys import (stdin, stderr,\nstdout)',
    316             'from sys import (stdin, stderr,\nstdout,)',
    317             'from sys import (stdin\n, stderr, stdout)',
    318             'from sys import (stdin\n, stderr, stdout,)',
    319             'from sys import stdin as si, stdout as so, stderr as se',
    320             'from sys import (stdin as si, stdout as so, stderr as se)',
    321             'from sys import (stdin as si, stdout as so, stderr as se,)',
    322             ]
    323         fail = [
    324             'import (os, sys)',
    325             'import (os), (sys)',
    326             'import ((os), (sys))',
    327             'import (sys',
    328             'import sys)',
    329             'import (os,)',
    330             'import os As bar',
    331             'import os.path a bar',
    332             'from sys import stdin As stdout',
    333             'from sys import stdin a stdout',
    334             'from (sys) import stdin',
    335             'from __future__ import (nested_scopes',
    336             'from __future__ import nested_scopes)',
    337             'from __future__ import nested_scopes,\ngenerators',
    338             'from sys import (stdin',
    339             'from sys import stdin)',
    340             'from sys import stdin, stdout,\nstderr',
    341             'from sys import stdin si',
    342             'from sys import stdin,'
    343             'from sys import (*)',
    344             'from sys import (stdin,, stdout, stderr)',
    345             'from sys import (stdin, stdout),',
    346             ]
    347         for stmt in succeed:
    348             compile(stmt, 'tmp', 'exec')
    349         for stmt in fail:
    350             self.assertRaises(SyntaxError, compile, stmt, 'tmp', 'exec')
    351 
    352     def test_for_distinct_code_objects(self):
    353         # SF bug 1048870

    354         def f():
    355             f1 = lambda x=1: x
    356             f2 = lambda x=2: x
    357             return f1, f2
    358         f1, f2 = f()
    359         self.assertNotEqual(id(f1.func_code), id(f2.func_code))
    360 
    361     def test_lambda_doc(self):
    362         l = lambda: "foo"
    363         self.assertIsNone(l.__doc__)
    364 
    365     def test_unicode_encoding(self):
    366         code = u"# -*- coding: utf-8 -*-\npass\n"
    367         self.assertRaises(SyntaxError, compile, code, "tmp", "exec")
    368 
    369     def test_subscripts(self):
    370         # SF bug 1448804

    371         # Class to make testing subscript results easy

    372         class str_map(object):
    373             def __init__(self):
    374                 self.data = {}
    375             def __getitem__(self, key):
    376                 return self.data[str(key)]
    377             def __setitem__(self, key, value):
    378                 self.data[str(key)] = value
    379             def __delitem__(self, key):
    380                 del self.data[str(key)]
    381             def __contains__(self, key):
    382                 return str(key) in self.data
    383         d = str_map()
    384         # Index

    385         d[1] = 1
    386         self.assertEqual(d[1], 1)
    387         d[1] += 1
    388         self.assertEqual(d[1], 2)
    389         del d[1]
    390         self.assertNotIn(1, d)
    391         # Tuple of indices

    392         d[1, 1] = 1
    393         self.assertEqual(d[1, 1], 1)
    394         d[1, 1] += 1
    395         self.assertEqual(d[1, 1], 2)
    396         del d[1, 1]
    397         self.assertNotIn((1, 1), d)
    398         # Simple slice

    399         d[1:2] = 1
    400         self.assertEqual(d[1:2], 1)
    401         d[1:2] += 1
    402         self.assertEqual(d[1:2], 2)
    403         del d[1:2]
    404         self.assertNotIn(slice(1, 2), d)
    405         # Tuple of simple slices

    406         d[1:2, 1:2] = 1
    407         self.assertEqual(d[1:2, 1:2], 1)
    408         d[1:2, 1:2] += 1
    409         self.assertEqual(d[1:2, 1:2], 2)
    410         del d[1:2, 1:2]
    411         self.assertNotIn((slice(1, 2), slice(1, 2)), d)
    412         # Extended slice

    413         d[1:2:3] = 1
    414         self.assertEqual(d[1:2:3], 1)
    415         d[1:2:3] += 1
    416         self.assertEqual(d[1:2:3], 2)
    417         del d[1:2:3]
    418         self.assertNotIn(slice(1, 2, 3), d)
    419         # Tuple of extended slices

    420         d[1:2:3, 1:2:3] = 1
    421         self.assertEqual(d[1:2:3, 1:2:3], 1)
    422         d[1:2:3, 1:2:3] += 1
    423         self.assertEqual(d[1:2:3, 1:2:3], 2)
    424         del d[1:2:3, 1:2:3]
    425         self.assertNotIn((slice(1, 2, 3), slice(1, 2, 3)), d)
    426         # Ellipsis

    427         d[...] = 1
    428         self.assertEqual(d[...], 1)
    429         d[...] += 1
    430         self.assertEqual(d[...], 2)
    431         del d[...]
    432         self.assertNotIn(Ellipsis, d)
    433         # Tuple of Ellipses

    434         d[..., ...] = 1
    435         self.assertEqual(d[..., ...], 1)
    436         d[..., ...] += 1
    437         self.assertEqual(d[..., ...], 2)
    438         del d[..., ...]
    439         self.assertNotIn((Ellipsis, Ellipsis), d)
    440 
    441     def test_mangling(self):
    442         class A:
    443             def f():
    444                 __mangled = 1
    445                 __not_mangled__ = 2
    446                 import __mangled_mod
    447                 import __package__.module
    448 
    449         self.assertIn("_A__mangled", A.f.func_code.co_varnames)
    450         self.assertIn("__not_mangled__", A.f.func_code.co_varnames)
    451         self.assertIn("_A__mangled_mod", A.f.func_code.co_varnames)
    452         self.assertIn("__package__", A.f.func_code.co_varnames)
    453 
    454     def test_compile_ast(self):
    455         fname = __file__
    456         if fname.lower().endswith(('pyc', 'pyo')):
    457             fname = fname[:-1]
    458         with open(fname, 'r') as f:
    459             fcontents = f.read()
    460         sample_code = [
    461             ['<assign>', 'x = 5'],
    462             ['<print1>', 'print 1'],
    463             ['<printv>', 'print v'],
    464             ['<printTrue>', 'print True'],
    465             ['<printList>', 'print []'],
    466             ['<ifblock>', """if True:\n    pass\n"""],
    467             ['<forblock>', """for n in [1, 2, 3]:\n    print n\n"""],
    468             ['<deffunc>', """def foo():\n    pass\nfoo()\n"""],
    469             [fname, fcontents],
    470         ]
    471 
    472         for fname, code in sample_code:
    473             co1 = compile(code, '%s1' % fname, 'exec')
    474             ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST)
    475             self.assertTrue(type(ast) == _ast.Module)
    476             co2 = compile(ast, '%s3' % fname, 'exec')
    477             self.assertEqual(co1, co2)
    478             # the code object's filename comes from the second compilation step

    479             self.assertEqual(co2.co_filename, '%s3' % fname)
    480 
    481         # raise exception when node type doesn't match with compile mode

    482         co1 = compile('print 1', '<string>', 'exec', _ast.PyCF_ONLY_AST)
    483         self.assertRaises(TypeError, compile, co1, '<ast>', 'eval')
    484 
    485         # raise exception when node type is no start node

    486         self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec')
    487 
    488         # raise exception when node has invalid children

    489         ast = _ast.Module()
    490         ast.body = [_ast.BoolOp()]
    491         self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
    492 
    493 
    494 def test_main():
    495     test_support.run_unittest(TestSpecifics)
    496 
    497 if __name__ == "__main__":
    498     test_main()
    499