blob: ebeb833d7e25b029f43c591618aa439c1678d7a2 [file] [log] [blame]
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00001# Test various flavors of legal and illegal future statements
2
Neal Norwitz328f3382003-12-13 22:43:34 +00003import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Guido van Rossum95e4d582018-01-26 08:20:18 -08005from textwrap import dedent
Serhiy Storchaka8b583392016-12-11 14:39:01 +02006import os
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00007import re
Batuhan Taşkaya258f5172020-04-14 01:51:31 +03008import sys
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00009
R David Murray44b548d2016-09-08 13:59:53 -040010rx = re.compile(r'\((\S+).py, line (\d+)')
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000011
Neal Norwitz328f3382003-12-13 22:43:34 +000012def get_error_location(msg):
13 mo = rx.search(str(msg))
14 return mo.group(1, 2)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000015
Neal Norwitz328f3382003-12-13 22:43:34 +000016class FutureTest(unittest.TestCase):
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000017
Ammar Askar025eb982018-09-24 17:12:49 -040018 def check_syntax_error(self, err, basename, lineno, offset=1):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020019 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
Neal Norwitz328f3382003-12-13 22:43:34 +000024 def test_future1(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020025 with support.CleanImport('future_test1'):
26 from test import future_test1
27 self.assertEqual(future_test1.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000028
Neal Norwitz328f3382003-12-13 22:43:34 +000029 def test_future2(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020030 with support.CleanImport('future_test2'):
31 from test import future_test2
32 self.assertEqual(future_test2.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000033
Neal Norwitz328f3382003-12-13 22:43:34 +000034 def test_future3(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020035 with support.CleanImport('test_future3'):
36 from test import test_future3
Jeremy Hylton8471a352001-08-20 20:33:42 +000037
Neal Norwitz328f3382003-12-13 22:43:34 +000038 def test_badfuture3(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020039 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000040 from test import badsyntax_future3
Serhiy Storchaka8b583392016-12-11 14:39:01 +020041 self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000042
Neal Norwitz328f3382003-12-13 22:43:34 +000043 def test_badfuture4(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020044 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000045 from test import badsyntax_future4
Serhiy Storchaka8b583392016-12-11 14:39:01 +020046 self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000047
Neal Norwitz328f3382003-12-13 22:43:34 +000048 def test_badfuture5(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020049 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000050 from test import badsyntax_future5
Serhiy Storchaka8b583392016-12-11 14:39:01 +020051 self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000052
Neal Norwitz328f3382003-12-13 22:43:34 +000053 def test_badfuture6(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020054 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000055 from test import badsyntax_future6
Serhiy Storchaka8b583392016-12-11 14:39:01 +020056 self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000057
Neal Norwitz328f3382003-12-13 22:43:34 +000058 def test_badfuture7(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020059 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000060 from test import badsyntax_future7
Serhiy Storchaka8b583392016-12-11 14:39:01 +020061 self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
Neal Norwitz328f3382003-12-13 22:43:34 +000062
63 def test_badfuture8(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020064 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000065 from test import badsyntax_future8
Serhiy Storchaka8b583392016-12-11 14:39:01 +020066 self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000067
68 def test_badfuture9(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020069 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000070 from test import badsyntax_future9
Ammar Askar025eb982018-09-24 17:12:49 -040071 self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000072
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070073 def test_badfuture10(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020074 with self.assertRaises(SyntaxError) as cm:
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070075 from test import badsyntax_future10
Ammar Askar025eb982018-09-24 17:12:49 -040076 self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070077
Thomas Wouters89f507f2006-12-13 04:49:30 +000078 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:
Benjamin Peterson9aebc612008-10-26 20:58:53 +000085 exec("from __future__ import print_function; print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +000086 except SyntaxError:
87 pass
88 else:
89 self.fail("syntax error didn't occur")
90
91 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +000092 exec("from __future__ import (print_function); print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +000093 except SyntaxError:
94 pass
95 else:
96 self.fail("syntax error didn't occur")
97
Benjamin Peterson9aebc612008-10-26 20:58:53 +000098 def test_multiple_features(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020099 with support.CleanImport("test.test_future5"):
100 from test import test_future5
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000101
Benjamin Petersonf216c942008-10-31 02:28:05 +0000102 def test_unicode_literals_exec(self):
103 scope = {}
104 exec("from __future__ import unicode_literals; x = ''", {}, scope)
Ezio Melottie9615932010-01-24 19:26:24 +0000105 self.assertIsInstance(scope["x"], str)
Benjamin Petersonf216c942008-10-31 02:28:05 +0000106
Guido van Rossum95e4d582018-01-26 08:20:18 -0800107class AnnotationsFutureTestCase(unittest.TestCase):
108 template = dedent(
109 """
110 from __future__ import annotations
111 def f() -> {ann}:
112 ...
113 def g(arg: {ann}) -> None:
114 ...
Pablo Galindod112c602020-03-18 23:02:09 +0000115 async def f2() -> {ann}:
116 ...
117 async def g2(arg: {ann}) -> None:
118 ...
Guido van Rossum95e4d582018-01-26 08:20:18 -0800119 var: {ann}
120 var2: {ann} = None
121 """
122 )
123
124 def getActual(self, annotation):
125 scope = {}
126 exec(self.template.format(ann=annotation), {}, scope)
127 func_ret_ann = scope['f'].__annotations__['return']
128 func_arg_ann = scope['g'].__annotations__['arg']
Pablo Galindod112c602020-03-18 23:02:09 +0000129 async_func_ret_ann = scope['f2'].__annotations__['return']
130 async_func_arg_ann = scope['g2'].__annotations__['arg']
Guido van Rossum95e4d582018-01-26 08:20:18 -0800131 var_ann1 = scope['__annotations__']['var']
132 var_ann2 = scope['__annotations__']['var2']
133 self.assertEqual(func_ret_ann, func_arg_ann)
Pablo Galindod112c602020-03-18 23:02:09 +0000134 self.assertEqual(func_ret_ann, async_func_ret_ann)
135 self.assertEqual(func_ret_ann, async_func_arg_ann)
Guido van Rossum95e4d582018-01-26 08:20:18 -0800136 self.assertEqual(func_ret_ann, var_ann1)
137 self.assertEqual(func_ret_ann, var_ann2)
138 return func_ret_ann
139
140 def assertAnnotationEqual(
141 self, annotation, expected=None, drop_parens=False, is_tuple=False,
142 ):
143 actual = self.getActual(annotation)
144 if expected is None:
145 expected = annotation if not is_tuple else annotation[1:-1]
146 if drop_parens:
147 self.assertNotEqual(actual, expected)
148 actual = actual.replace("(", "").replace(")", "")
149
150 self.assertEqual(actual, expected)
151
152 def test_annotations(self):
153 eq = self.assertAnnotationEqual
154 eq('...')
155 eq("'some_string'")
156 eq("b'\\xa3'")
157 eq('Name')
158 eq('None')
159 eq('True')
160 eq('False')
161 eq('1')
162 eq('1.0')
163 eq('1j')
164 eq('True or False')
165 eq('True or False or None')
166 eq('True and False')
167 eq('True and False and None')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300168 eq('Name1 and Name2 or Name3')
169 eq('Name1 and (Name2 or Name3)')
170 eq('Name1 or Name2 and Name3')
171 eq('(Name1 or Name2) and Name3')
172 eq('Name1 and Name2 or Name3 and Name4')
173 eq('Name1 or Name2 and Name3 or Name4')
174 eq('a + b + (c + d)')
175 eq('a * b * (c * d)')
176 eq('(a ** b) ** c ** d')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800177 eq('v1 << 2')
178 eq('1 >> v2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300179 eq('1 % finished')
180 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800181 eq('not great')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300182 eq('not not great')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800183 eq('~great')
184 eq('+value')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300185 eq('++value')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800186 eq('-1')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300187 eq('~int and not v1 ^ 123 + v2 | True')
188 eq('a + (not b)')
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300189 eq('lambda: None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800190 eq('lambda arg: None')
191 eq('lambda a=True: a')
192 eq('lambda a, b, c=True: a')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300193 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300194 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
Pablo Galindoda6129e2019-05-18 23:40:22 +0100195 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
196 eq('lambda x, /: x')
197 eq('lambda x=1, /: x')
198 eq('lambda x, /, y: x + y')
199 eq('lambda x=1, /, y=2: x + y')
200 eq('lambda x, /, y=1: x + y')
201 eq('lambda x, /, y=1, *, z=3: x + y + z')
202 eq('lambda x=1, /, y=2, *, z=3: x + y + z')
203 eq('lambda x=1, /, y=2, *, z: x + y + z')
204 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
205 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
206 eq('lambda x, /, y=1, *, z: x + y + z')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300207 eq('lambda x: lambda y: x + y')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800208 eq('1 if True else 2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300209 eq('str or None if int or True else str or bytes or None')
210 eq('str or None if (1 if True else 2) else str or bytes or None')
211 eq("0 if not x else 1 if x > 0 else -1")
212 eq("(1 if x > 0 else -1) if x else 0")
213 eq("{'2.7': dead, '3.7': long_live or die_hard}")
214 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800215 eq("{**a, **b, **c}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300216 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
217 eq("{*a, *b, *c}")
218 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800219 eq("()")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300220 eq("(a,)")
221 eq("(a, b)")
222 eq("(a, b, c)")
223 eq("(*a, *b, *c)")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800224 eq("[]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300225 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
226 eq("[*a, *b, *c]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800227 eq("{i for i in (1, 2, 3)}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300228 eq("{i ** 2 for i in (1, 2, 3)}")
229 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
230 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800231 eq("[i for i in (1, 2, 3)]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300232 eq("[i ** 2 for i in (1, 2, 3)]")
233 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
234 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
235 eq("(i for i in (1, 2, 3))")
236 eq("(i ** 2 for i in (1, 2, 3))")
237 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
238 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
239 eq("{i: 0 for i in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800240 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300241 eq("[(x, y) for x, y in (a, b)]")
242 eq("[(x,) for x, in (a,)]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800243 eq("Python3 > Python2 > COBOL")
244 eq("Life is Life")
245 eq("call()")
246 eq("call(arg)")
247 eq("call(kwarg='hey')")
248 eq("call(arg, kwarg='hey')")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300249 eq("call(arg, *args, another, kwarg='hey')")
250 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800251 eq("lukasz.langa.pl")
252 eq("call.me(maybe)")
253 eq("1 .real")
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300254 eq("1.0.real")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800255 eq("....__class__")
256 eq("list[str]")
257 eq("dict[str, int]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300258 eq("set[str,]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800259 eq("tuple[str, ...]")
260 eq("tuple[str, int, float, dict[str, int]]")
261 eq("slice[0]")
262 eq("slice[0:1]")
263 eq("slice[0:1:2]")
264 eq("slice[:]")
265 eq("slice[:-1]")
266 eq("slice[1:]")
267 eq("slice[::-1]")
Batuhan Taşkaya185903d2020-03-01 23:07:22 +0300268 eq("slice[:,]")
269 eq("slice[1:2,]")
270 eq("slice[1:2:3,]")
271 eq("slice[1:2, 1]")
272 eq("slice[1:2, 2, 3]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300273 eq("slice[()]")
274 eq("slice[a, b:c, d:e:f]")
275 eq("slice[(x for x in a)]")
276 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800277 eq("f'f-string without formatted values is just a string'")
278 eq("f'{{NOT a formatted value}}'")
279 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
280 eq('''f"{f'{nested} inner'} outer"''')
281 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300282 eq("f'{(lambda x: x)}'")
283 eq("f'{(None if a else lambda x: x)}'")
Eric V. Smith9a4135e2019-05-08 16:28:48 -0400284 eq("f'{x}'")
285 eq("f'{x!r}'")
286 eq("f'{x!a}'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800287 eq('(yield from outside_of_generator)')
288 eq('(yield)')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300289 eq('(yield a + b)')
290 eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
291 eq('[x for x in (a if b else c)]')
292 eq('[x for x in a if (b if c else d)]')
293 eq('f(x for x in a)')
294 eq('f(1, (x for x in a))')
295 eq('f((x for x in a), 2)')
296 eq('(((a)))', 'a')
297 eq('(((a, b)))', '(a, b)')
Batuhan Taşkayafa19a252019-05-19 01:10:20 +0300298 eq("(x:=10)")
299 eq("f'{(x:=10):=10}'")
Pablo Galindod112c602020-03-18 23:02:09 +0000300 eq("1 + 2 + 3")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000301
Eric V. Smithf83d1db2019-05-29 03:55:44 -0400302 def test_fstring_debug_annotations(self):
Eric V. Smith6f6ff8a2019-05-27 15:31:52 -0400303 # f-strings with '=' don't round trip very well, so set the expected
304 # result explicitely.
305 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
306 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
307 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
308 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
309 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
310 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
311
Batuhan Taşkaya258f5172020-04-14 01:51:31 +0300312 def test_infinity_numbers(self):
313 inf = "1e" + repr(sys.float_info.max_10_exp + 1)
314 infj = f"{inf}j"
315 self.assertAnnotationEqual("1e1000", expected=inf)
316 self.assertAnnotationEqual("1e1000j", expected=infj)
317 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
318 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
319 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
320 self.assertAnnotationEqual("'inf'")
321 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
322 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
323
324
Neal Norwitz328f3382003-12-13 22:43:34 +0000325if __name__ == "__main__":
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200326 unittest.main()