Home | History | Annotate | Download | only in test
      1 import test.test_support
      2 compiler = test.test_support.import_module('compiler', deprecated=True)
      3 from compiler.ast import flatten
      4 import os, sys, time, unittest
      5 from random import random
      6 from StringIO import StringIO
      7 
      8 # How much time in seconds can pass before we print a 'Still working' message.
      9 _PRINT_WORKING_MSG_INTERVAL = 5 * 60
     10 
     11 class TrivialContext(object):
     12     def __enter__(self):
     13         return self
     14     def __exit__(self, *exc_info):
     15         pass
     16 
     17 class CompilerTest(unittest.TestCase):
     18 
     19     def testCompileLibrary(self):
     20         # A simple but large test.  Compile all the code in the
     21         # standard library and its test suite.  This doesn't verify
     22         # that any of the code is correct, merely the compiler is able
     23         # to generate some kind of code for it.
     24 
     25         next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL
     26         # warning: if 'os' or 'test_support' are moved in some other dir,
     27         # they should be changed here.
     28         libdir = os.path.dirname(os.__file__)
     29         testdir = os.path.dirname(test.test_support.__file__)
     30 
     31         for dir in [testdir]:
     32             for basename in "test_os.py",:
     33                 # Print still working message since this test can be really slow
     34                 if next_time <= time.time():
     35                     next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL
     36                     print >>sys.__stdout__, \
     37                        '  testCompileLibrary still working, be patient...'
     38                     sys.__stdout__.flush()
     39 
     40                 if not basename.endswith(".py"):
     41                     continue
     42                 if not TEST_ALL and random() < 0.98:
     43                     continue
     44                 path = os.path.join(dir, basename)
     45                 if test.test_support.verbose:
     46                     print "compiling", path
     47                 f = open(path, "U")
     48                 buf = f.read()
     49                 f.close()
     50                 if "badsyntax" in basename or "bad_coding" in basename:
     51                     self.assertRaises(SyntaxError, compiler.compile,
     52                                       buf, basename, "exec")
     53                 else:
     54                     try:
     55                         compiler.compile(buf, basename, "exec")
     56                     except Exception, e:
     57                         args = list(e.args)
     58                         args.append("in file %s]" % basename)
     59                         #args[0] += "[in file %s]" % basename
     60                         e.args = tuple(args)
     61                         raise
     62 
     63     def testNewClassSyntax(self):
     64         compiler.compile("class foo():pass\n\n","<string>","exec")
     65 
     66     def testYieldExpr(self):
     67         compiler.compile("def g(): yield\n\n", "<string>", "exec")
     68 
     69     def testKeywordAfterStarargs(self):
     70         def f(*args, **kwargs):
     71             self.assertEqual((args, kwargs), ((2,3), {'x': 1, 'y': 4}))
     72         c = compiler.compile('f(x=1, *(2, 3), y=4)', '<string>', 'exec')
     73         exec c in {'f': f}
     74 
     75         self.assertRaises(SyntaxError, compiler.parse, "foo(a=1, b)")
     76         self.assertRaises(SyntaxError, compiler.parse, "foo(1, *args, 3)")
     77 
     78     def testTryExceptFinally(self):
     79         # Test that except and finally clauses in one try stmt are recognized
     80         c = compiler.compile("try:\n 1//0\nexcept:\n e = 1\nfinally:\n f = 1",
     81                              "<string>", "exec")
     82         dct = {}
     83         exec c in dct
     84         self.assertEqual(dct.get('e'), 1)
     85         self.assertEqual(dct.get('f'), 1)
     86 
     87     def testDefaultArgs(self):
     88         self.assertRaises(SyntaxError, compiler.parse, "def foo(a=1, b): pass")
     89 
     90     def testDocstrings(self):
     91         c = compiler.compile('"doc"', '<string>', 'exec')
     92         self.assertIn('__doc__', c.co_names)
     93         c = compiler.compile('def f():\n "doc"', '<string>', 'exec')
     94         g = {}
     95         exec c in g
     96         self.assertEqual(g['f'].__doc__, "doc")
     97 
     98     def testLineNo(self):
     99         # Test that all nodes except Module have a correct lineno attribute.
    100         filename = __file__
    101         if filename.endswith((".pyc", ".pyo")):
    102             filename = filename[:-1]
    103         tree = compiler.parseFile(filename)
    104         self.check_lineno(tree)
    105 
    106     def check_lineno(self, node):
    107         try:
    108             self._check_lineno(node)
    109         except AssertionError:
    110             print node.__class__, node.lineno
    111             raise
    112 
    113     def _check_lineno(self, node):
    114         if not node.__class__ in NOLINENO:
    115             self.assertIsInstance(node.lineno, int,
    116                 "lineno=%s on %s" % (node.lineno, node.__class__))
    117             self.assertTrue(node.lineno > 0,
    118                 "lineno=%s on %s" % (node.lineno, node.__class__))
    119         for child in node.getChildNodes():
    120             self.check_lineno(child)
    121 
    122     def testFlatten(self):
    123         self.assertEqual(flatten([1, [2]]), [1, 2])
    124         self.assertEqual(flatten((1, (2,))), [1, 2])
    125 
    126     def testNestedScope(self):
    127         c = compiler.compile('def g():\n'
    128                              '    a = 1\n'
    129                              '    def f(): return a + 2\n'
    130                              '    return f()\n'
    131                              'result = g()',
    132                              '<string>',
    133                              'exec')
    134         dct = {}
    135         exec c in dct
    136         self.assertEqual(dct.get('result'), 3)
    137 
    138     def testGenExp(self):
    139         c = compiler.compile('list((i,j) for i in range(3) if i < 3'
    140                              '           for j in range(4) if j > 2)',
    141                              '<string>',
    142                              'eval')
    143         self.assertEqual(eval(c), [(0, 3), (1, 3), (2, 3)])
    144 
    145     def testSetLiteral(self):
    146         c = compiler.compile('{1, 2, 3}', '<string>', 'eval')
    147         self.assertEqual(eval(c), {1,2,3})
    148         c = compiler.compile('{1, 2, 3,}', '<string>', 'eval')
    149         self.assertEqual(eval(c), {1,2,3})
    150 
    151     def testDictLiteral(self):
    152         c = compiler.compile('{1:2, 2:3, 3:4}', '<string>', 'eval')
    153         self.assertEqual(eval(c), {1:2, 2:3, 3:4})
    154         c = compiler.compile('{1:2, 2:3, 3:4,}', '<string>', 'eval')
    155         self.assertEqual(eval(c), {1:2, 2:3, 3:4})
    156 
    157     def testSetComp(self):
    158         c = compiler.compile('{x for x in range(1, 4)}', '<string>', 'eval')
    159         self.assertEqual(eval(c), {1, 2, 3})
    160         c = compiler.compile('{x * y for x in range(3) if x != 0'
    161                              '       for y in range(4) if y != 0}',
    162                              '<string>',
    163                              'eval')
    164         self.assertEqual(eval(c), {1, 2, 3, 4, 6})
    165 
    166     def testDictComp(self):
    167         c = compiler.compile('{x:x+1 for x in range(1, 4)}', '<string>', 'eval')
    168         self.assertEqual(eval(c), {1:2, 2:3, 3:4})
    169         c = compiler.compile('{(x, y) : y for x in range(2) if x != 0'
    170                              '            for y in range(3) if y != 0}',
    171                              '<string>',
    172                              'eval')
    173         self.assertEqual(eval(c), {(1, 2): 2, (1, 1): 1})
    174 
    175     def testWith(self):
    176         # SF bug 1638243
    177         c = compiler.compile('from __future__ import with_statement\n'
    178                              'def f():\n'
    179                              '    with TrivialContext():\n'
    180                              '        return 1\n'
    181                              'result = f()',
    182                              '<string>',
    183                              'exec' )
    184         dct = {'TrivialContext': TrivialContext}
    185         exec c in dct
    186         self.assertEqual(dct.get('result'), 1)
    187 
    188     def testWithAss(self):
    189         c = compiler.compile('from __future__ import with_statement\n'
    190                              'def f():\n'
    191                              '    with TrivialContext() as tc:\n'
    192                              '        return 1\n'
    193                              'result = f()',
    194                              '<string>',
    195                              'exec' )
    196         dct = {'TrivialContext': TrivialContext}
    197         exec c in dct
    198         self.assertEqual(dct.get('result'), 1)
    199 
    200     def testWithMult(self):
    201         events = []
    202         class Ctx:
    203             def __init__(self, n):
    204                 self.n = n
    205             def __enter__(self):
    206                 events.append(self.n)
    207             def __exit__(self, *args):
    208                 pass
    209         c = compiler.compile('from __future__ import with_statement\n'
    210                              'def f():\n'
    211                              '    with Ctx(1) as tc, Ctx(2) as tc2:\n'
    212                              '        return 1\n'
    213                              'result = f()',
    214                              '<string>',
    215                              'exec' )
    216         dct = {'Ctx': Ctx}
    217         exec c in dct
    218         self.assertEqual(dct.get('result'), 1)
    219         self.assertEqual(events, [1, 2])
    220 
    221     def testGlobal(self):
    222         code = compiler.compile('global x\nx=1', '<string>', 'exec')
    223         d1 = {'__builtins__': {}}
    224         d2 = {}
    225         exec code in d1, d2
    226         # x should be in the globals dict
    227         self.assertEqual(d1.get('x'), 1)
    228 
    229     def testPrintFunction(self):
    230         c = compiler.compile('from __future__ import print_function\n'
    231                              'print("a", "b", sep="**", end="++", '
    232                                     'file=output)',
    233                              '<string>',
    234                              'exec' )
    235         dct = {'output': StringIO()}
    236         exec c in dct
    237         self.assertEqual(dct['output'].getvalue(), 'a**b++')
    238 
    239     def _testErrEnc(self, src, text, offset):
    240         try:
    241             compile(src, "", "exec")
    242         except SyntaxError, e:
    243             self.assertEqual(e.offset, offset)
    244             self.assertEqual(e.text, text)
    245 
    246     def testSourceCodeEncodingsError(self):
    247         # Test SyntaxError with encoding definition
    248         sjis = "print '\x83\x70\x83\x43\x83\x5c\x83\x93', '\n"
    249         ascii = "print '12345678', '\n"
    250         encdef = "#! -*- coding: ShiftJIS -*-\n"
    251 
    252         # ascii source without encdef
    253         self._testErrEnc(ascii, ascii, 19)
    254 
    255         # ascii source with encdef
    256         self._testErrEnc(encdef+ascii, ascii, 19)
    257 
    258         # non-ascii source with encdef
    259         self._testErrEnc(encdef+sjis, sjis, 19)
    260 
    261         # ShiftJIS source without encdef
    262         self._testErrEnc(sjis, sjis, 19)
    263 
    264 
    265 NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard)
    266 
    267 ###############################################################################
    268 # code below is just used to trigger some possible errors, for the benefit of
    269 # testLineNo
    270 ###############################################################################
    271 
    272 class Toto:
    273     """docstring"""
    274     pass
    275 
    276 a, b = 2, 3
    277 [c, d] = 5, 6
    278 l = [(x, y) for x, y in zip(range(5), range(5,10))]
    279 l[0]
    280 l[3:4]
    281 d = {'a': 2}
    282 d = {}
    283 d = {x: y for x, y in zip(range(5), range(5,10))}
    284 s = {x for x in range(10)}
    285 s = {1}
    286 t = ()
    287 t = (1, 2)
    288 l = []
    289 l = [1, 2]
    290 if l:
    291     pass
    292 else:
    293     a, b = b, a
    294 
    295 try:
    296     print yo
    297 except:
    298     yo = 3
    299 else:
    300     yo += 3
    301 
    302 try:
    303     a += b
    304 finally:
    305     b = 0
    306 
    307 from math import *
    308 
    309 ###############################################################################
    310 
    311 def test_main():
    312     global TEST_ALL
    313     TEST_ALL = test.test_support.is_resource_enabled("cpu")
    314     test.test_support.run_unittest(CompilerTest)
    315 
    316 if __name__ == "__main__":
    317     test_main()
    318