|
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 libdir = os.path.dirname(unittest.__file__) |
|
27 testdir = os.path.dirname(test.test_support.__file__) |
|
28 |
|
29 for dir in [libdir, testdir]: |
|
30 for basename in os.listdir(dir): |
|
31 # Print still working message since this test can be really slow |
|
32 if next_time <= time.time(): |
|
33 next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL |
|
34 print >>sys.__stdout__, \ |
|
35 ' testCompileLibrary still working, be patient...' |
|
36 sys.__stdout__.flush() |
|
37 |
|
38 if not basename.endswith(".py"): |
|
39 continue |
|
40 if not TEST_ALL and random() < 0.98: |
|
41 continue |
|
42 path = os.path.join(dir, basename) |
|
43 if test.test_support.verbose: |
|
44 print "compiling", path |
|
45 f = open(path, "U") |
|
46 buf = f.read() |
|
47 f.close() |
|
48 if "badsyntax" in basename or "bad_coding" in basename: |
|
49 self.assertRaises(SyntaxError, compiler.compile, |
|
50 buf, basename, "exec") |
|
51 else: |
|
52 try: |
|
53 compiler.compile(buf, basename, "exec") |
|
54 except Exception, e: |
|
55 args = list(e.args) |
|
56 args.append("in file %s]" % basename) |
|
57 #args[0] += "[in file %s]" % basename |
|
58 e.args = tuple(args) |
|
59 raise |
|
60 |
|
61 def testNewClassSyntax(self): |
|
62 compiler.compile("class foo():pass\n\n","<string>","exec") |
|
63 |
|
64 def testYieldExpr(self): |
|
65 compiler.compile("def g(): yield\n\n", "<string>", "exec") |
|
66 |
|
67 def testKeywordAfterStarargs(self): |
|
68 def f(*args, **kwargs): |
|
69 self.assertEqual((args, kwargs), ((2,3), {'x': 1, 'y': 4})) |
|
70 c = compiler.compile('f(x=1, *(2, 3), y=4)', '<string>', 'exec') |
|
71 exec c in {'f': f} |
|
72 |
|
73 self.assertRaises(SyntaxError, compiler.parse, "foo(a=1, b)") |
|
74 self.assertRaises(SyntaxError, compiler.parse, "foo(1, *args, 3)") |
|
75 |
|
76 def testTryExceptFinally(self): |
|
77 # Test that except and finally clauses in one try stmt are recognized |
|
78 c = compiler.compile("try:\n 1/0\nexcept:\n e = 1\nfinally:\n f = 1", |
|
79 "<string>", "exec") |
|
80 dct = {} |
|
81 exec c in dct |
|
82 self.assertEquals(dct.get('e'), 1) |
|
83 self.assertEquals(dct.get('f'), 1) |
|
84 |
|
85 def testDefaultArgs(self): |
|
86 self.assertRaises(SyntaxError, compiler.parse, "def foo(a=1, b): pass") |
|
87 |
|
88 def testDocstrings(self): |
|
89 c = compiler.compile('"doc"', '<string>', 'exec') |
|
90 self.assert_('__doc__' in c.co_names) |
|
91 c = compiler.compile('def f():\n "doc"', '<string>', 'exec') |
|
92 g = {} |
|
93 exec c in g |
|
94 self.assertEquals(g['f'].__doc__, "doc") |
|
95 |
|
96 def testLineNo(self): |
|
97 # Test that all nodes except Module have a correct lineno attribute. |
|
98 filename = __file__ |
|
99 if filename.endswith((".pyc", ".pyo")): |
|
100 filename = filename[:-1] |
|
101 tree = compiler.parseFile(filename) |
|
102 self.check_lineno(tree) |
|
103 |
|
104 def check_lineno(self, node): |
|
105 try: |
|
106 self._check_lineno(node) |
|
107 except AssertionError: |
|
108 print node.__class__, node.lineno |
|
109 raise |
|
110 |
|
111 def _check_lineno(self, node): |
|
112 if not node.__class__ in NOLINENO: |
|
113 self.assert_(isinstance(node.lineno, int), |
|
114 "lineno=%s on %s" % (node.lineno, node.__class__)) |
|
115 self.assert_(node.lineno > 0, |
|
116 "lineno=%s on %s" % (node.lineno, node.__class__)) |
|
117 for child in node.getChildNodes(): |
|
118 self.check_lineno(child) |
|
119 |
|
120 def testFlatten(self): |
|
121 self.assertEquals(flatten([1, [2]]), [1, 2]) |
|
122 self.assertEquals(flatten((1, (2,))), [1, 2]) |
|
123 |
|
124 def testNestedScope(self): |
|
125 c = compiler.compile('def g():\n' |
|
126 ' a = 1\n' |
|
127 ' def f(): return a + 2\n' |
|
128 ' return f()\n' |
|
129 'result = g()', |
|
130 '<string>', |
|
131 'exec') |
|
132 dct = {} |
|
133 exec c in dct |
|
134 self.assertEquals(dct.get('result'), 3) |
|
135 |
|
136 def testGenExp(self): |
|
137 c = compiler.compile('list((i,j) for i in range(3) if i < 3' |
|
138 ' for j in range(4) if j > 2)', |
|
139 '<string>', |
|
140 'eval') |
|
141 self.assertEquals(eval(c), [(0, 3), (1, 3), (2, 3)]) |
|
142 |
|
143 def testWith(self): |
|
144 # SF bug 1638243 |
|
145 c = compiler.compile('from __future__ import with_statement\n' |
|
146 'def f():\n' |
|
147 ' with TrivialContext():\n' |
|
148 ' return 1\n' |
|
149 'result = f()', |
|
150 '<string>', |
|
151 'exec' ) |
|
152 dct = {'TrivialContext': TrivialContext} |
|
153 exec c in dct |
|
154 self.assertEquals(dct.get('result'), 1) |
|
155 |
|
156 def testWithAss(self): |
|
157 c = compiler.compile('from __future__ import with_statement\n' |
|
158 'def f():\n' |
|
159 ' with TrivialContext() as tc:\n' |
|
160 ' return 1\n' |
|
161 'result = f()', |
|
162 '<string>', |
|
163 'exec' ) |
|
164 dct = {'TrivialContext': TrivialContext} |
|
165 exec c in dct |
|
166 self.assertEquals(dct.get('result'), 1) |
|
167 |
|
168 |
|
169 def testPrintFunction(self): |
|
170 c = compiler.compile('from __future__ import print_function\n' |
|
171 'print("a", "b", sep="**", end="++", ' |
|
172 'file=output)', |
|
173 '<string>', |
|
174 'exec' ) |
|
175 dct = {'output': StringIO()} |
|
176 exec c in dct |
|
177 self.assertEquals(dct['output'].getvalue(), 'a**b++') |
|
178 |
|
179 def _testErrEnc(self, src, text, offset): |
|
180 try: |
|
181 compile(src, "", "exec") |
|
182 except SyntaxError, e: |
|
183 self.assertEquals(e.offset, offset) |
|
184 self.assertEquals(e.text, text) |
|
185 |
|
186 def testSourceCodeEncodingsError(self): |
|
187 # Test SyntaxError with encoding definition |
|
188 sjis = "print '\x83\x70\x83\x43\x83\x5c\x83\x93', '\n" |
|
189 ascii = "print '12345678', '\n" |
|
190 encdef = "#! -*- coding: ShiftJIS -*-\n" |
|
191 |
|
192 # ascii source without encdef |
|
193 self._testErrEnc(ascii, ascii, 19) |
|
194 |
|
195 # ascii source with encdef |
|
196 self._testErrEnc(encdef+ascii, ascii, 19) |
|
197 |
|
198 # non-ascii source with encdef |
|
199 self._testErrEnc(encdef+sjis, sjis, 19) |
|
200 |
|
201 # ShiftJIS source without encdef |
|
202 self._testErrEnc(sjis, sjis, 19) |
|
203 |
|
204 |
|
205 NOLINENO = (compiler.ast.Module, compiler.ast.Stmt, compiler.ast.Discard) |
|
206 |
|
207 ############################################################################### |
|
208 # code below is just used to trigger some possible errors, for the benefit of |
|
209 # testLineNo |
|
210 ############################################################################### |
|
211 |
|
212 class Toto: |
|
213 """docstring""" |
|
214 pass |
|
215 |
|
216 a, b = 2, 3 |
|
217 [c, d] = 5, 6 |
|
218 l = [(x, y) for x, y in zip(range(5), range(5,10))] |
|
219 l[0] |
|
220 l[3:4] |
|
221 d = {'a': 2} |
|
222 d = {} |
|
223 t = () |
|
224 t = (1, 2) |
|
225 l = [] |
|
226 l = [1, 2] |
|
227 if l: |
|
228 pass |
|
229 else: |
|
230 a, b = b, a |
|
231 |
|
232 try: |
|
233 print yo |
|
234 except: |
|
235 yo = 3 |
|
236 else: |
|
237 yo += 3 |
|
238 |
|
239 try: |
|
240 a += b |
|
241 finally: |
|
242 b = 0 |
|
243 |
|
244 from math import * |
|
245 |
|
246 ############################################################################### |
|
247 |
|
248 def test_main(): |
|
249 global TEST_ALL |
|
250 TEST_ALL = test.test_support.is_resource_enabled("compiler") |
|
251 test.test_support.run_unittest(CompilerTest) |
|
252 |
|
253 if __name__ == "__main__": |
|
254 test_main() |