Home | History | Annotate | Download | only in parser
      1 import unittest
      2 from test import test_support
      3 import cStringIO
      4 import sys
      5 import os
      6 import tokenize
      7 import ast
      8 import unparse
      9 
     10 def read_pyfile(filename):
     11     """Read and return the contents of a Python source file (as a
     12     string), taking into account the file encoding."""
     13     with open(filename, "r") as pyfile:
     14         source = pyfile.read()
     15     return source
     16 
     17 for_else = """\
     18 def f():
     19     for x in range(10):
     20         break
     21     else:
     22         y = 2
     23     z = 3
     24 """
     25 
     26 while_else = """\
     27 def g():
     28     while True:
     29         break
     30     else:
     31         y = 2
     32     z = 3
     33 """
     34 
     35 relative_import = """\
     36 from . import fred
     37 from .. import barney
     38 from .australia import shrimp as prawns
     39 """
     40 
     41 class_decorator = """\
     42 @f1(arg)
     43 @f2
     44 class Foo: pass
     45 """
     46 
     47 elif1 = """\
     48 if cond1:
     49     suite1
     50 elif cond2:
     51     suite2
     52 else:
     53     suite3
     54 """
     55 
     56 elif2 = """\
     57 if cond1:
     58     suite1
     59 elif cond2:
     60     suite2
     61 """
     62 
     63 try_except_finally = """\
     64 try:
     65     suite1
     66 except ex1:
     67     suite2
     68 except ex2:
     69     suite3
     70 else:
     71     suite4
     72 finally:
     73     suite5
     74 """
     75 
     76 class ASTTestCase(unittest.TestCase):
     77     def assertASTEqual(self, ast1, ast2):
     78         dump1 = ast.dump(ast1)
     79         dump2 = ast.dump(ast2)
     80         self.assertEqual(ast.dump(ast1), ast.dump(ast2))
     81 
     82     def check_roundtrip(self, code1, filename="internal"):
     83         ast1 = compile(code1, filename, "exec", ast.PyCF_ONLY_AST)
     84         unparse_buffer = cStringIO.StringIO()
     85         unparse.Unparser(ast1, unparse_buffer)
     86         code2 = unparse_buffer.getvalue()
     87         ast2 = compile(code2, filename, "exec", ast.PyCF_ONLY_AST)
     88         self.assertASTEqual(ast1, ast2)
     89 
     90 class UnparseTestCase(ASTTestCase):
     91     # Tests for specific bugs found in earlier versions of unparse

     92 
     93     def test_del_statement(self):
     94         self.check_roundtrip("del x, y, z")
     95 
     96     def test_shifts(self):
     97         self.check_roundtrip("45 << 2")
     98         self.check_roundtrip("13 >> 7")
     99 
    100     def test_for_else(self):
    101         self.check_roundtrip(for_else)
    102 
    103     def test_while_else(self):
    104         self.check_roundtrip(while_else)
    105 
    106     def test_unary_parens(self):
    107         self.check_roundtrip("(-1)**7")
    108         self.check_roundtrip("(-1.)**8")
    109         self.check_roundtrip("(-1j)**6")
    110         self.check_roundtrip("not True or False")
    111         self.check_roundtrip("True or not False")
    112 
    113     def test_integer_parens(self):
    114         self.check_roundtrip("3 .__abs__()")
    115 
    116     def test_huge_float(self):
    117         self.check_roundtrip("1e1000")
    118         self.check_roundtrip("-1e1000")
    119         self.check_roundtrip("1e1000j")
    120         self.check_roundtrip("-1e1000j")
    121 
    122     def test_min_int(self):
    123         self.check_roundtrip(str(-sys.maxint-1))
    124         self.check_roundtrip("-(%s)" % (sys.maxint + 1))
    125 
    126     def test_imaginary_literals(self):
    127         self.check_roundtrip("7j")
    128         self.check_roundtrip("-7j")
    129         self.check_roundtrip("-(7j)")
    130         self.check_roundtrip("0j")
    131         self.check_roundtrip("-0j")
    132         self.check_roundtrip("-(0j)")
    133 
    134     def test_negative_zero(self):
    135         self.check_roundtrip("-0")
    136         self.check_roundtrip("-(0)")
    137         self.check_roundtrip("-0b0")
    138         self.check_roundtrip("-(0b0)")
    139         self.check_roundtrip("-0o0")
    140         self.check_roundtrip("-(0o0)")
    141         self.check_roundtrip("-0x0")
    142         self.check_roundtrip("-(0x0)")
    143 
    144     def test_lambda_parentheses(self):
    145         self.check_roundtrip("(lambda: int)()")
    146 
    147     def test_chained_comparisons(self):
    148         self.check_roundtrip("1 < 4 <= 5")
    149         self.check_roundtrip("a is b is c is not d")
    150 
    151     def test_function_arguments(self):
    152         self.check_roundtrip("def f(): pass")
    153         self.check_roundtrip("def f(a): pass")
    154         self.check_roundtrip("def f(b = 2): pass")
    155         self.check_roundtrip("def f(a, b): pass")
    156         self.check_roundtrip("def f(a, b = 2): pass")
    157         self.check_roundtrip("def f(a = 5, b = 2): pass")
    158         self.check_roundtrip("def f(*args, **kwargs): pass")
    159 
    160     def test_relative_import(self):
    161         self.check_roundtrip(relative_import)
    162 
    163     def test_bytes(self):
    164         self.check_roundtrip("b'123'")
    165 
    166     def test_set_literal(self):
    167         self.check_roundtrip("{'a', 'b', 'c'}")
    168 
    169     def test_set_comprehension(self):
    170         self.check_roundtrip("{x for x in range(5)}")
    171 
    172     def test_dict_comprehension(self):
    173         self.check_roundtrip("{x: x*x for x in range(10)}")
    174 
    175     def test_class_decorators(self):
    176         self.check_roundtrip(class_decorator)
    177 
    178     def test_elifs(self):
    179         self.check_roundtrip(elif1)
    180         self.check_roundtrip(elif2)
    181 
    182     def test_try_except_finally(self):
    183         self.check_roundtrip(try_except_finally)
    184 
    185 class DirectoryTestCase(ASTTestCase):
    186     """Test roundtrip behaviour on all files in Lib and Lib/test."""
    187 
    188     # test directories, relative to the root of the distribution

    189     test_directories = 'Lib', os.path.join('Lib', 'test')
    190 
    191     def test_files(self):
    192         # get names of files to test

    193         dist_dir = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
    194 
    195         names = []
    196         for d in self.test_directories:
    197             test_dir = os.path.join(dist_dir, d)
    198             for n in os.listdir(test_dir):
    199                 if n.endswith('.py') and not n.startswith('bad'):
    200                     names.append(os.path.join(test_dir, n))
    201 
    202         for filename in names:
    203             if test_support.verbose:
    204                 print('Testing %s' % filename)
    205             source = read_pyfile(filename)
    206             self.check_roundtrip(source)
    207 
    208 
    209 def test_main():
    210     test_support.run_unittest(UnparseTestCase, DirectoryTestCase)
    211 
    212 if __name__ == '__main__':
    213     test_main()
    214