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