1"""
2   Test cases for codeop.py
3   Nick Mathewson
4"""
5import sys
6import unittest
7import warnings
8from test import support
9from test.support import warnings_helper
10
11from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT
12import io
13
14if support.is_jython:
15
16    def unify_callables(d):
17        for n,v in d.items():
18            if hasattr(v, '__call__'):
19                d[n] = True
20        return d
21
22class CodeopTests(unittest.TestCase):
23
24    def assertValid(self, str, symbol='single'):
25        '''succeed iff str is a valid piece of code'''
26        if support.is_jython:
27            code = compile_command(str, "<input>", symbol)
28            self.assertTrue(code)
29            if symbol == "single":
30                d,r = {},{}
31                saved_stdout = sys.stdout
32                sys.stdout = io.StringIO()
33                try:
34                    exec(code, d)
35                    exec(compile(str,"<input>","single"), r)
36                finally:
37                    sys.stdout = saved_stdout
38            elif symbol == 'eval':
39                ctx = {'a': 2}
40                d = { 'value': eval(code,ctx) }
41                r = { 'value': eval(str,ctx) }
42            self.assertEqual(unify_callables(r),unify_callables(d))
43        else:
44            expected = compile(str, "<input>", symbol, PyCF_DONT_IMPLY_DEDENT)
45            self.assertEqual(compile_command(str, "<input>", symbol), expected)
46
47    def assertIncomplete(self, str, symbol='single'):
48        '''succeed iff str is the start of a valid piece of code'''
49        self.assertEqual(compile_command(str, symbol=symbol), None)
50
51    def assertInvalid(self, str, symbol='single', is_syntax=1):
52        '''succeed iff str is the start of an invalid piece of code'''
53        try:
54            compile_command(str,symbol=symbol)
55            self.fail("No exception raised for invalid code")
56        except SyntaxError:
57            self.assertTrue(is_syntax)
58        except OverflowError:
59            self.assertTrue(not is_syntax)
60
61    def test_valid(self):
62        av = self.assertValid
63
64        # special case
65        if not support.is_jython:
66            self.assertEqual(compile_command(""),
67                             compile("pass", "<input>", 'single',
68                                     PyCF_DONT_IMPLY_DEDENT))
69            self.assertEqual(compile_command("\n"),
70                             compile("pass", "<input>", 'single',
71                                     PyCF_DONT_IMPLY_DEDENT))
72        else:
73            av("")
74            av("\n")
75
76        av("a = 1")
77        av("\na = 1")
78        av("a = 1\n")
79        av("a = 1\n\n")
80        av("\n\na = 1\n\n")
81
82        av("def x():\n  pass\n")
83        av("if 1:\n pass\n")
84
85        av("\n\nif 1: pass\n")
86        av("\n\nif 1: pass\n\n")
87
88        av("def x():\n\n pass\n")
89        av("def x():\n  pass\n  \n")
90        av("def x():\n  pass\n \n")
91
92        av("pass\n")
93        av("3**3\n")
94
95        av("if 9==3:\n   pass\nelse:\n   pass\n")
96        av("if 1:\n pass\n if 1:\n  pass\n else:\n  pass\n")
97
98        av("#a\n#b\na = 3\n")
99        av("#a\n\n   \na=3\n")
100        av("a=3\n\n")
101        av("a = 9+ \\\n3")
102
103        av("3**3","eval")
104        av("(lambda z: \n z**3)","eval")
105
106        av("9+ \\\n3","eval")
107        av("9+ \\\n3\n","eval")
108
109        av("\n\na**3","eval")
110        av("\n \na**3","eval")
111        av("#a\n#b\na**3","eval")
112
113        av("\n\na = 1\n\n")
114        av("\n\nif 1: a=1\n\n")
115
116        av("if 1:\n pass\n if 1:\n  pass\n else:\n  pass\n")
117        av("#a\n\n   \na=3\n\n")
118
119        av("\n\na**3","eval")
120        av("\n \na**3","eval")
121        av("#a\n#b\na**3","eval")
122
123        av("def f():\n try: pass\n finally: [x for x in (1,2)]\n")
124        av("def f():\n pass\n#foo\n")
125        av("@a.b.c\ndef f():\n pass\n")
126
127    def test_incomplete(self):
128        ai = self.assertIncomplete
129
130        ai("(a **")
131        ai("(a,b,")
132        ai("(a,b,(")
133        ai("(a,b,(")
134        ai("a = (")
135        ai("a = {")
136        ai("b + {")
137
138        ai("print([1,\n2,")
139        ai("print({1:1,\n2:3,")
140        ai("print((1,\n2,")
141
142        ai("if 9==3:\n   pass\nelse:")
143        ai("if 9==3:\n   pass\nelse:\n")
144        ai("if 9==3:\n   pass\nelse:\n   pass")
145        ai("if 1:")
146        ai("if 1:\n")
147        ai("if 1:\n pass\n if 1:\n  pass\n else:")
148        ai("if 1:\n pass\n if 1:\n  pass\n else:\n")
149        ai("if 1:\n pass\n if 1:\n  pass\n else:\n  pass")
150
151        ai("def x():")
152        ai("def x():\n")
153        ai("def x():\n\n")
154
155        ai("def x():\n  pass")
156        ai("def x():\n  pass\n ")
157        ai("def x():\n  pass\n  ")
158        ai("\n\ndef x():\n  pass")
159
160        ai("a = 9+ \\")
161        ai("a = 'a\\")
162        ai("a = '''xy")
163
164        ai("","eval")
165        ai("\n","eval")
166        ai("(","eval")
167        ai("(9+","eval")
168        ai("9+ \\","eval")
169        ai("lambda z: \\","eval")
170
171        ai("if True:\n if True:\n  if True:   \n")
172
173        ai("@a(")
174        ai("@a(b")
175        ai("@a(b,")
176        ai("@a(b,c")
177        ai("@a(b,c,")
178
179        ai("from a import (")
180        ai("from a import (b")
181        ai("from a import (b,")
182        ai("from a import (b,c")
183        ai("from a import (b,c,")
184
185        ai("[")
186        ai("[a")
187        ai("[a,")
188        ai("[a,b")
189        ai("[a,b,")
190
191        ai("{")
192        ai("{a")
193        ai("{a:")
194        ai("{a:b")
195        ai("{a:b,")
196        ai("{a:b,c")
197        ai("{a:b,c:")
198        ai("{a:b,c:d")
199        ai("{a:b,c:d,")
200
201        ai("a(")
202        ai("a(b")
203        ai("a(b,")
204        ai("a(b,c")
205        ai("a(b,c,")
206
207        ai("a[")
208        ai("a[b")
209        ai("a[b,")
210        ai("a[b:")
211        ai("a[b:c")
212        ai("a[b:c:")
213        ai("a[b:c:d")
214
215        ai("def a(")
216        ai("def a(b")
217        ai("def a(b,")
218        ai("def a(b,c")
219        ai("def a(b,c,")
220
221        ai("(")
222        ai("(a")
223        ai("(a,")
224        ai("(a,b")
225        ai("(a,b,")
226
227        ai("if a:\n pass\nelif b:")
228        ai("if a:\n pass\nelif b:\n pass\nelse:")
229
230        ai("while a:")
231        ai("while a:\n pass\nelse:")
232
233        ai("for a in b:")
234        ai("for a in b:\n pass\nelse:")
235
236        ai("try:")
237        ai("try:\n pass\nexcept:")
238        ai("try:\n pass\nfinally:")
239        ai("try:\n pass\nexcept:\n pass\nfinally:")
240
241        ai("with a:")
242        ai("with a as b:")
243
244        ai("class a:")
245        ai("class a(")
246        ai("class a(b")
247        ai("class a(b,")
248        ai("class a():")
249
250        ai("[x for")
251        ai("[x for x in")
252        ai("[x for x in (")
253
254        ai("(x for")
255        ai("(x for x in")
256        ai("(x for x in (")
257
258    def test_invalid(self):
259        ai = self.assertInvalid
260        ai("a b")
261
262        ai("a @")
263        ai("a b @")
264        ai("a ** @")
265
266        ai("a = ")
267        ai("a = 9 +")
268
269        ai("def x():\n\npass\n")
270
271        ai("\n\n if 1: pass\n\npass")
272
273        ai("a = 9+ \\\n")
274        ai("a = 'a\\ ")
275        ai("a = 'a\\\n")
276
277        ai("a = 1","eval")
278        ai("]","eval")
279        ai("())","eval")
280        ai("[}","eval")
281        ai("9+","eval")
282        ai("lambda z:","eval")
283        ai("a b","eval")
284
285        ai("return 2.3")
286        ai("if (a == 1 and b = 2): pass")
287
288        ai("del 1")
289        ai("del (1,)")
290        ai("del [1]")
291        ai("del '1'")
292
293        ai("[i for i in range(10)] = (1, 2, 3)")
294
295    def test_invalid_exec(self):
296        ai = self.assertInvalid
297        ai("raise = 4", symbol="exec")
298        ai('def a-b', symbol='exec')
299        ai('await?', symbol='exec')
300        ai('=!=', symbol='exec')
301        ai('a await raise b', symbol='exec')
302        ai('a await raise b?+1', symbol='exec')
303
304    def test_filename(self):
305        self.assertEqual(compile_command("a = 1\n", "abc").co_filename,
306                         compile("a = 1\n", "abc", 'single').co_filename)
307        self.assertNotEqual(compile_command("a = 1\n", "abc").co_filename,
308                            compile("a = 1\n", "def", 'single').co_filename)
309
310    def test_warning(self):
311        # Test that the warning is only returned once.
312        with warnings_helper.check_warnings(
313                (".*literal", SyntaxWarning),
314                (".*invalid", DeprecationWarning),
315                ) as w:
316            compile_command(r"'\e' is 0")
317            self.assertEqual(len(w.warnings), 2)
318
319        # bpo-41520: check SyntaxWarning treated as an SyntaxError
320        with warnings.catch_warnings(), self.assertRaises(SyntaxError):
321            warnings.simplefilter('error', SyntaxWarning)
322            compile_command('1 is 1', symbol='exec')
323
324
325if __name__ == "__main__":
326    unittest.main()
327