1# Test various flavors of legal and illegal future statements
2
3import __future__
4import ast
5import unittest
6from test import support
7from test.support import import_helper
8from textwrap import dedent
9import os
10import re
11import sys
12
13rx = re.compile(r'\((\S+).py, line (\d+)')
14
15def get_error_location(msg):
16    mo = rx.search(str(msg))
17    return mo.group(1, 2)
18
19class FutureTest(unittest.TestCase):
20
21    def check_syntax_error(self, err, basename, lineno, offset=1):
22        self.assertIn('%s.py, line %d' % (basename, lineno), str(err))
23        self.assertEqual(os.path.basename(err.filename), basename + '.py')
24        self.assertEqual(err.lineno, lineno)
25        self.assertEqual(err.offset, offset)
26
27    def test_future1(self):
28        with import_helper.CleanImport('future_test1'):
29            from test import future_test1
30            self.assertEqual(future_test1.result, 6)
31
32    def test_future2(self):
33        with import_helper.CleanImport('future_test2'):
34            from test import future_test2
35            self.assertEqual(future_test2.result, 6)
36
37    def test_future3(self):
38        with import_helper.CleanImport('test_future3'):
39            from test import test_future3
40
41    def test_badfuture3(self):
42        with self.assertRaises(SyntaxError) as cm:
43            from test import badsyntax_future3
44        self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
45
46    def test_badfuture4(self):
47        with self.assertRaises(SyntaxError) as cm:
48            from test import badsyntax_future4
49        self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
50
51    def test_badfuture5(self):
52        with self.assertRaises(SyntaxError) as cm:
53            from test import badsyntax_future5
54        self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
55
56    def test_badfuture6(self):
57        with self.assertRaises(SyntaxError) as cm:
58            from test import badsyntax_future6
59        self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
60
61    def test_badfuture7(self):
62        with self.assertRaises(SyntaxError) as cm:
63            from test import badsyntax_future7
64        self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
65
66    def test_badfuture8(self):
67        with self.assertRaises(SyntaxError) as cm:
68            from test import badsyntax_future8
69        self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
70
71    def test_badfuture9(self):
72        with self.assertRaises(SyntaxError) as cm:
73            from test import badsyntax_future9
74        self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
75
76    def test_badfuture10(self):
77        with self.assertRaises(SyntaxError) as cm:
78            from test import badsyntax_future10
79        self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
80
81    def test_ensure_flags_dont_clash(self):
82        # bpo-39562: test that future flags and compiler flags doesn't clash
83
84        # obtain future flags (CO_FUTURE_***) from the __future__ module
85        flags = {
86            f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag
87            for future in __future__.all_feature_names
88        }
89        # obtain some of the exported compiler flags (PyCF_***) from the ast module
90        flags |= {
91            flag: getattr(ast, flag)
92            for flag in dir(ast) if flag.startswith("PyCF_")
93        }
94        self.assertCountEqual(set(flags.values()), flags.values())
95
96    def test_parserhack(self):
97        # test that the parser.c::future_hack function works as expected
98        # Note: although this test must pass, it's not testing the original
99        #       bug as of 2.6 since the with statement is not optional and
100        #       the parser hack disabled. If a new keyword is introduced in
101        #       2.6, change this to refer to the new future import.
102        try:
103            exec("from __future__ import print_function; print 0")
104        except SyntaxError:
105            pass
106        else:
107            self.fail("syntax error didn't occur")
108
109        try:
110            exec("from __future__ import (print_function); print 0")
111        except SyntaxError:
112            pass
113        else:
114            self.fail("syntax error didn't occur")
115
116    def test_multiple_features(self):
117        with import_helper.CleanImport("test.test_future5"):
118            from test import test_future5
119
120    def test_unicode_literals_exec(self):
121        scope = {}
122        exec("from __future__ import unicode_literals; x = ''", {}, scope)
123        self.assertIsInstance(scope["x"], str)
124
125class AnnotationsFutureTestCase(unittest.TestCase):
126    template = dedent(
127        """
128        from __future__ import annotations
129        def f() -> {ann}:
130            ...
131        def g(arg: {ann}) -> None:
132            ...
133        async def f2() -> {ann}:
134            ...
135        async def g2(arg: {ann}) -> None:
136            ...
137        class H:
138            var: {ann}
139            object.attr: {ann}
140        var: {ann}
141        var2: {ann} = None
142        object.attr: {ann}
143        """
144    )
145
146    def getActual(self, annotation):
147        scope = {}
148        exec(self.template.format(ann=annotation), {}, scope)
149        func_ret_ann = scope['f'].__annotations__['return']
150        func_arg_ann = scope['g'].__annotations__['arg']
151        async_func_ret_ann = scope['f2'].__annotations__['return']
152        async_func_arg_ann = scope['g2'].__annotations__['arg']
153        var_ann1 = scope['__annotations__']['var']
154        var_ann2 = scope['__annotations__']['var2']
155        self.assertEqual(func_ret_ann, func_arg_ann)
156        self.assertEqual(func_ret_ann, async_func_ret_ann)
157        self.assertEqual(func_ret_ann, async_func_arg_ann)
158        self.assertEqual(func_ret_ann, var_ann1)
159        self.assertEqual(func_ret_ann, var_ann2)
160        return func_ret_ann
161
162    def assertAnnotationEqual(
163        self, annotation, expected=None, drop_parens=False, is_tuple=False,
164    ):
165        actual = self.getActual(annotation)
166        if expected is None:
167            expected = annotation if not is_tuple else annotation[1:-1]
168        if drop_parens:
169            self.assertNotEqual(actual, expected)
170            actual = actual.replace("(", "").replace(")", "")
171
172        self.assertEqual(actual, expected)
173
174    def _exec_future(self, code):
175        scope = {}
176        exec(
177            "from __future__ import annotations\n"
178            + code, {}, scope
179        )
180        return scope
181
182    def test_annotations(self):
183        eq = self.assertAnnotationEqual
184        eq('...')
185        eq("'some_string'")
186        eq("u'some_string'")
187        eq("b'\\xa3'")
188        eq('Name')
189        eq('None')
190        eq('True')
191        eq('False')
192        eq('1')
193        eq('1.0')
194        eq('1j')
195        eq('True or False')
196        eq('True or False or None')
197        eq('True and False')
198        eq('True and False and None')
199        eq('Name1 and Name2 or Name3')
200        eq('Name1 and (Name2 or Name3)')
201        eq('Name1 or Name2 and Name3')
202        eq('(Name1 or Name2) and Name3')
203        eq('Name1 and Name2 or Name3 and Name4')
204        eq('Name1 or Name2 and Name3 or Name4')
205        eq('a + b + (c + d)')
206        eq('a * b * (c * d)')
207        eq('(a ** b) ** c ** d')
208        eq('v1 << 2')
209        eq('1 >> v2')
210        eq('1 % finished')
211        eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
212        eq('not great')
213        eq('not not great')
214        eq('~great')
215        eq('+value')
216        eq('++value')
217        eq('-1')
218        eq('~int and not v1 ^ 123 + v2 | True')
219        eq('a + (not b)')
220        eq('lambda: None')
221        eq('lambda arg: None')
222        eq('lambda a=True: a')
223        eq('lambda a, b, c=True: a')
224        eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
225        eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
226        eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
227        eq('lambda x, /: x')
228        eq('lambda x=1, /: x')
229        eq('lambda x, /, y: x + y')
230        eq('lambda x=1, /, y=2: x + y')
231        eq('lambda x, /, y=1: x + y')
232        eq('lambda x, /, y=1, *, z=3: x + y + z')
233        eq('lambda x=1, /, y=2, *, z=3: x + y + z')
234        eq('lambda x=1, /, y=2, *, z: x + y + z')
235        eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
236        eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
237        eq('lambda x, /, y=1, *, z: x + y + z')
238        eq('lambda x: lambda y: x + y')
239        eq('1 if True else 2')
240        eq('str or None if int or True else str or bytes or None')
241        eq('str or None if (1 if True else 2) else str or bytes or None')
242        eq("0 if not x else 1 if x > 0 else -1")
243        eq("(1 if x > 0 else -1) if x else 0")
244        eq("{'2.7': dead, '3.7': long_live or die_hard}")
245        eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
246        eq("{**a, **b, **c}")
247        eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
248        eq("{*a, *b, *c}")
249        eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
250        eq("()")
251        eq("(a,)")
252        eq("(a, b)")
253        eq("(a, b, c)")
254        eq("(*a, *b, *c)")
255        eq("[]")
256        eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
257        eq("[*a, *b, *c]")
258        eq("{i for i in (1, 2, 3)}")
259        eq("{i ** 2 for i in (1, 2, 3)}")
260        eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
261        eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
262        eq("[i for i in (1, 2, 3)]")
263        eq("[i ** 2 for i in (1, 2, 3)]")
264        eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
265        eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
266        eq("(i for i in (1, 2, 3))")
267        eq("(i ** 2 for i in (1, 2, 3))")
268        eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
269        eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
270        eq("{i: 0 for i in (1, 2, 3)}")
271        eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
272        eq("[(x, y) for x, y in (a, b)]")
273        eq("[(x,) for x, in (a,)]")
274        eq("Python3 > Python2 > COBOL")
275        eq("Life is Life")
276        eq("call()")
277        eq("call(arg)")
278        eq("call(kwarg='hey')")
279        eq("call(arg, kwarg='hey')")
280        eq("call(arg, *args, another, kwarg='hey')")
281        eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
282        eq("lukasz.langa.pl")
283        eq("call.me(maybe)")
284        eq("1 .real")
285        eq("1.0.real")
286        eq("....__class__")
287        eq("list[str]")
288        eq("dict[str, int]")
289        eq("set[str,]")
290        eq("tuple[str, ...]")
291        eq("tuple[(str, *types)]")
292        eq("tuple[str, int, (str, int)]")
293        eq("tuple[(*int, str, str, (str, int))]")
294        eq("tuple[str, int, float, dict[str, int]]")
295        eq("slice[0]")
296        eq("slice[0:1]")
297        eq("slice[0:1:2]")
298        eq("slice[:]")
299        eq("slice[:-1]")
300        eq("slice[1:]")
301        eq("slice[::-1]")
302        eq("slice[:,]")
303        eq("slice[1:2,]")
304        eq("slice[1:2:3,]")
305        eq("slice[1:2, 1]")
306        eq("slice[1:2, 2, 3]")
307        eq("slice[()]")
308        eq("slice[a, b:c, d:e:f]")
309        eq("slice[(x for x in a)]")
310        eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
311        eq("f'f-string without formatted values is just a string'")
312        eq("f'{{NOT a formatted value}}'")
313        eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
314        eq('''f"{f'{nested} inner'} outer"''')
315        eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
316        eq("f'{(lambda x: x)}'")
317        eq("f'{(None if a else lambda x: x)}'")
318        eq("f'{x}'")
319        eq("f'{x!r}'")
320        eq("f'{x!a}'")
321        eq('[x for x in (a if b else c)]')
322        eq('[x for x in a if (b if c else d)]')
323        eq('f(x for x in a)')
324        eq('f(1, (x for x in a))')
325        eq('f((x for x in a), 2)')
326        eq('(((a)))', 'a')
327        eq('(((a, b)))', '(a, b)')
328        eq("1 + 2 + 3")
329
330    def test_fstring_debug_annotations(self):
331        # f-strings with '=' don't round trip very well, so set the expected
332        # result explicitly.
333        self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
334        self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
335        self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
336        self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
337        self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
338        self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
339
340    def test_infinity_numbers(self):
341        inf = "1e" + repr(sys.float_info.max_10_exp + 1)
342        infj = f"{inf}j"
343        self.assertAnnotationEqual("1e1000", expected=inf)
344        self.assertAnnotationEqual("1e1000j", expected=infj)
345        self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
346        self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
347        self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
348        self.assertAnnotationEqual("'inf'")
349        self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
350        self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
351
352    def test_annotation_with_complex_target(self):
353        with self.assertRaises(SyntaxError):
354            exec(
355                "from __future__ import annotations\n"
356                "object.__debug__: int"
357            )
358
359    def test_annotations_symbol_table_pass(self):
360        namespace = self._exec_future(dedent("""
361        from __future__ import annotations
362
363        def foo():
364            outer = 1
365            def bar():
366                inner: outer = 1
367            return bar
368        """))
369
370        foo = namespace.pop("foo")
371        self.assertIsNone(foo().__closure__)
372        self.assertEqual(foo.__code__.co_cellvars, ())
373        self.assertEqual(foo().__code__.co_freevars, ())
374
375    def test_annotations_forbidden(self):
376        with self.assertRaises(SyntaxError):
377            self._exec_future("test: (yield)")
378
379        with self.assertRaises(SyntaxError):
380            self._exec_future("test.test: (yield a + b)")
381
382        with self.assertRaises(SyntaxError):
383            self._exec_future("test[something]: (yield from x)")
384
385        with self.assertRaises(SyntaxError):
386            self._exec_future("def func(test: (yield from outside_of_generator)): pass")
387
388        with self.assertRaises(SyntaxError):
389            self._exec_future("def test() -> (await y): pass")
390
391        with self.assertRaises(SyntaxError):
392            self._exec_future("async def test() -> something((a := b)): pass")
393
394        with self.assertRaises(SyntaxError):
395            self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)")
396
397        with self.assertRaises(SyntaxError):
398            self._exec_future("test: f'{(x := 10):=10}'")
399
400        with self.assertRaises(SyntaxError):
401            self._exec_future(dedent("""\
402            def foo():
403                def bar(arg: (yield)): pass
404            """))
405
406
407if __name__ == "__main__":
408    unittest.main()
409