1# Test various flavors of legal and illegal future statements
2
3from functools import partial
4import unittest
5from test import support
6from textwrap import dedent
7import os
8import re
9
10rx = re.compile(r'\((\S+).py, line (\d+)')
11
12def get_error_location(msg):
13    mo = rx.search(str(msg))
14    return mo.group(1, 2)
15
16class FutureTest(unittest.TestCase):
17
18    def check_syntax_error(self, err, basename, lineno, offset=0):
19        self.assertIn('%s.py, line %d' % (basename, lineno), str(err))
20        self.assertEqual(os.path.basename(err.filename), basename + '.py')
21        self.assertEqual(err.lineno, lineno)
22        self.assertEqual(err.offset, offset)
23
24    def test_future1(self):
25        with support.CleanImport('future_test1'):
26            from test import future_test1
27            self.assertEqual(future_test1.result, 6)
28
29    def test_future2(self):
30        with support.CleanImport('future_test2'):
31            from test import future_test2
32            self.assertEqual(future_test2.result, 6)
33
34    def test_future3(self):
35        with support.CleanImport('test_future3'):
36            from test import test_future3
37
38    def test_badfuture3(self):
39        with self.assertRaises(SyntaxError) as cm:
40            from test import badsyntax_future3
41        self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
42
43    def test_badfuture4(self):
44        with self.assertRaises(SyntaxError) as cm:
45            from test import badsyntax_future4
46        self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
47
48    def test_badfuture5(self):
49        with self.assertRaises(SyntaxError) as cm:
50            from test import badsyntax_future5
51        self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
52
53    def test_badfuture6(self):
54        with self.assertRaises(SyntaxError) as cm:
55            from test import badsyntax_future6
56        self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
57
58    def test_badfuture7(self):
59        with self.assertRaises(SyntaxError) as cm:
60            from test import badsyntax_future7
61        self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
62
63    def test_badfuture8(self):
64        with self.assertRaises(SyntaxError) as cm:
65            from test import badsyntax_future8
66        self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
67
68    def test_badfuture9(self):
69        with self.assertRaises(SyntaxError) as cm:
70            from test import badsyntax_future9
71        self.check_syntax_error(cm.exception, "badsyntax_future9", 3, 0)
72
73    def test_badfuture10(self):
74        with self.assertRaises(SyntaxError) as cm:
75            from test import badsyntax_future10
76        self.check_syntax_error(cm.exception, "badsyntax_future10", 3, 0)
77
78    def test_parserhack(self):
79        # test that the parser.c::future_hack function works as expected
80        # Note: although this test must pass, it's not testing the original
81        #       bug as of 2.6 since the with statement is not optional and
82        #       the parser hack disabled. If a new keyword is introduced in
83        #       2.6, change this to refer to the new future import.
84        try:
85            exec("from __future__ import print_function; print 0")
86        except SyntaxError:
87            pass
88        else:
89            self.fail("syntax error didn't occur")
90
91        try:
92            exec("from __future__ import (print_function); print 0")
93        except SyntaxError:
94            pass
95        else:
96            self.fail("syntax error didn't occur")
97
98    def test_multiple_features(self):
99        with support.CleanImport("test.test_future5"):
100            from test import test_future5
101
102    def test_unicode_literals_exec(self):
103        scope = {}
104        exec("from __future__ import unicode_literals; x = ''", {}, scope)
105        self.assertIsInstance(scope["x"], str)
106
107class AnnotationsFutureTestCase(unittest.TestCase):
108    template = dedent(
109        """
110        from __future__ import annotations
111        def f() -> {ann}:
112            ...
113        def g(arg: {ann}) -> None:
114            ...
115        var: {ann}
116        var2: {ann} = None
117        """
118    )
119
120    def getActual(self, annotation):
121        scope = {}
122        exec(self.template.format(ann=annotation), {}, scope)
123        func_ret_ann = scope['f'].__annotations__['return']
124        func_arg_ann = scope['g'].__annotations__['arg']
125        var_ann1 = scope['__annotations__']['var']
126        var_ann2 = scope['__annotations__']['var2']
127        self.assertEqual(func_ret_ann, func_arg_ann)
128        self.assertEqual(func_ret_ann, var_ann1)
129        self.assertEqual(func_ret_ann, var_ann2)
130        return func_ret_ann
131
132    def assertAnnotationEqual(
133        self, annotation, expected=None, drop_parens=False, is_tuple=False,
134    ):
135        actual = self.getActual(annotation)
136        if expected is None:
137            expected = annotation if not is_tuple else annotation[1:-1]
138        if drop_parens:
139            self.assertNotEqual(actual, expected)
140            actual = actual.replace("(", "").replace(")", "")
141
142        self.assertEqual(actual, expected)
143
144    def test_annotations(self):
145        eq = self.assertAnnotationEqual
146        eq('...')
147        eq("'some_string'")
148        eq("b'\\xa3'")
149        eq('Name')
150        eq('None')
151        eq('True')
152        eq('False')
153        eq('1')
154        eq('1.0')
155        eq('1j')
156        eq('True or False')
157        eq('True or False or None')
158        eq('True and False')
159        eq('True and False and None')
160        eq('Name1 and Name2 or Name3')
161        eq('Name1 and (Name2 or Name3)')
162        eq('Name1 or Name2 and Name3')
163        eq('(Name1 or Name2) and Name3')
164        eq('Name1 and Name2 or Name3 and Name4')
165        eq('Name1 or Name2 and Name3 or Name4')
166        eq('a + b + (c + d)')
167        eq('a * b * (c * d)')
168        eq('(a ** b) ** c ** d')
169        eq('v1 << 2')
170        eq('1 >> v2')
171        eq('1 % finished')
172        eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
173        eq('not great')
174        eq('not not great')
175        eq('~great')
176        eq('+value')
177        eq('++value')
178        eq('-1')
179        eq('~int and not v1 ^ 123 + v2 | True')
180        eq('a + (not b)')
181        eq('lambda: None')
182        eq('lambda arg: None')
183        eq('lambda a=True: a')
184        eq('lambda a, b, c=True: a')
185        eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
186        eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
187        eq('lambda x: lambda y: x + y')
188        eq('1 if True else 2')
189        eq('str or None if int or True else str or bytes or None')
190        eq('str or None if (1 if True else 2) else str or bytes or None')
191        eq("0 if not x else 1 if x > 0 else -1")
192        eq("(1 if x > 0 else -1) if x else 0")
193        eq("{'2.7': dead, '3.7': long_live or die_hard}")
194        eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
195        eq("{**a, **b, **c}")
196        eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
197        eq("{*a, *b, *c}")
198        eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
199        eq("()")
200        eq("(a,)")
201        eq("(a, b)")
202        eq("(a, b, c)")
203        eq("(*a, *b, *c)")
204        eq("[]")
205        eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
206        eq("[*a, *b, *c]")
207        eq("{i for i in (1, 2, 3)}")
208        eq("{i ** 2 for i in (1, 2, 3)}")
209        eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
210        eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
211        eq("[i for i in (1, 2, 3)]")
212        eq("[i ** 2 for i in (1, 2, 3)]")
213        eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
214        eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
215        eq("(i for i in (1, 2, 3))")
216        eq("(i ** 2 for i in (1, 2, 3))")
217        eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
218        eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
219        eq("{i: 0 for i in (1, 2, 3)}")
220        eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
221        eq("[(x, y) for x, y in (a, b)]")
222        eq("[(x,) for x, in (a,)]")
223        eq("Python3 > Python2 > COBOL")
224        eq("Life is Life")
225        eq("call()")
226        eq("call(arg)")
227        eq("call(kwarg='hey')")
228        eq("call(arg, kwarg='hey')")
229        eq("call(arg, *args, another, kwarg='hey')")
230        eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
231        eq("lukasz.langa.pl")
232        eq("call.me(maybe)")
233        eq("1 .real")
234        eq("1.0 .real")
235        eq("....__class__")
236        eq("list[str]")
237        eq("dict[str, int]")
238        eq("set[str,]")
239        eq("tuple[str, ...]")
240        eq("tuple[(str, *types)]")
241        eq("tuple[xx:yy, (*types,)]")
242        eq("tuple[str, int, (str, int)]")
243        eq("tuple[(*int, str, str, (str, int))]")
244        eq("tuple[str, int, float, dict[str, int]]")
245        eq("slice[0]")
246        eq("slice[0:1]")
247        eq("slice[0:1:2]")
248        eq("slice[:]")
249        eq("slice[:-1]")
250        eq("slice[1:]")
251        eq("slice[::-1]")
252        eq("slice[:,]")
253        eq("slice[1:2,]")
254        eq("slice[1:2:3,]")
255        eq("slice[1:2, 1]")
256        eq("slice[1:2, 2, 3]")
257        eq("slice[()]")
258        eq("slice[a, b:c, d:e:f]")
259        eq("slice[(x for x in a)]")
260        eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
261        eq("f'f-string without formatted values is just a string'")
262        eq("f'{{NOT a formatted value}}'")
263        eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
264        eq('''f"{f'{nested} inner'} outer"''')
265        eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
266        eq("f'{(lambda x: x)}'")
267        eq("f'{(None if a else lambda x: x)}'")
268        eq('(yield from outside_of_generator)')
269        eq('(yield)')
270        eq('(yield a + b)')
271        eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
272        eq('[x for x in (a if b else c)]')
273        eq('[x for x in a if (b if c else d)]')
274        eq('f(x for x in a)')
275        eq('f(1, (x for x in a))')
276        eq('f((x for x in a), 2)')
277        eq('(((a)))', 'a')
278        eq('(((a, b)))', '(a, b)')
279
280
281if __name__ == "__main__":
282    unittest.main()
283