blob: fdca2312fab7c277f85baaa7cfea641a262b4790 [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'")
Batuhan Taşkayaaade1cc2020-04-14 21:55:01 +0300156 eq("u'some_string'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800157 eq("b'\\xa3'")
158 eq('Name')
159 eq('None')
160 eq('True')
161 eq('False')
162 eq('1')
163 eq('1.0')
164 eq('1j')
165 eq('True or False')
166 eq('True or False or None')
167 eq('True and False')
168 eq('True and False and None')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300169 eq('Name1 and Name2 or Name3')
170 eq('Name1 and (Name2 or Name3)')
171 eq('Name1 or Name2 and Name3')
172 eq('(Name1 or Name2) and Name3')
173 eq('Name1 and Name2 or Name3 and Name4')
174 eq('Name1 or Name2 and Name3 or Name4')
175 eq('a + b + (c + d)')
176 eq('a * b * (c * d)')
177 eq('(a ** b) ** c ** d')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800178 eq('v1 << 2')
179 eq('1 >> v2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300180 eq('1 % finished')
181 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800182 eq('not great')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300183 eq('not not great')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800184 eq('~great')
185 eq('+value')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300186 eq('++value')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800187 eq('-1')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300188 eq('~int and not v1 ^ 123 + v2 | True')
189 eq('a + (not b)')
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300190 eq('lambda: None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800191 eq('lambda arg: None')
192 eq('lambda a=True: a')
193 eq('lambda a, b, c=True: a')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300194 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300195 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
Pablo Galindoda6129e2019-05-18 23:40:22 +0100196 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
197 eq('lambda x, /: x')
198 eq('lambda x=1, /: x')
199 eq('lambda x, /, y: x + y')
200 eq('lambda x=1, /, y=2: x + y')
201 eq('lambda x, /, y=1: x + y')
202 eq('lambda x, /, y=1, *, z=3: x + y + z')
203 eq('lambda x=1, /, y=2, *, z=3: x + y + z')
204 eq('lambda x=1, /, y=2, *, z: x + y + z')
205 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
206 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
207 eq('lambda x, /, y=1, *, z: x + y + z')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300208 eq('lambda x: lambda y: x + y')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800209 eq('1 if True else 2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300210 eq('str or None if int or True else str or bytes or None')
211 eq('str or None if (1 if True else 2) else str or bytes or None')
212 eq("0 if not x else 1 if x > 0 else -1")
213 eq("(1 if x > 0 else -1) if x else 0")
214 eq("{'2.7': dead, '3.7': long_live or die_hard}")
215 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800216 eq("{**a, **b, **c}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300217 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
218 eq("{*a, *b, *c}")
219 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800220 eq("()")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300221 eq("(a,)")
222 eq("(a, b)")
223 eq("(a, b, c)")
224 eq("(*a, *b, *c)")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800225 eq("[]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300226 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
227 eq("[*a, *b, *c]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800228 eq("{i for i in (1, 2, 3)}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300229 eq("{i ** 2 for i in (1, 2, 3)}")
230 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
231 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800232 eq("[i for i in (1, 2, 3)]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300233 eq("[i ** 2 for i in (1, 2, 3)]")
234 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
235 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
236 eq("(i for i in (1, 2, 3))")
237 eq("(i ** 2 for i in (1, 2, 3))")
238 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
239 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
240 eq("{i: 0 for i in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800241 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300242 eq("[(x, y) for x, y in (a, b)]")
243 eq("[(x,) for x, in (a,)]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800244 eq("Python3 > Python2 > COBOL")
245 eq("Life is Life")
246 eq("call()")
247 eq("call(arg)")
248 eq("call(kwarg='hey')")
249 eq("call(arg, kwarg='hey')")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300250 eq("call(arg, *args, another, kwarg='hey')")
251 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800252 eq("lukasz.langa.pl")
253 eq("call.me(maybe)")
254 eq("1 .real")
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300255 eq("1.0.real")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800256 eq("....__class__")
257 eq("list[str]")
258 eq("dict[str, int]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300259 eq("set[str,]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800260 eq("tuple[str, ...]")
261 eq("tuple[str, int, float, dict[str, int]]")
262 eq("slice[0]")
263 eq("slice[0:1]")
264 eq("slice[0:1:2]")
265 eq("slice[:]")
266 eq("slice[:-1]")
267 eq("slice[1:]")
268 eq("slice[::-1]")
Batuhan Taşkaya185903d2020-03-01 23:07:22 +0300269 eq("slice[:,]")
270 eq("slice[1:2,]")
271 eq("slice[1:2:3,]")
272 eq("slice[1:2, 1]")
273 eq("slice[1:2, 2, 3]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300274 eq("slice[()]")
275 eq("slice[a, b:c, d:e:f]")
276 eq("slice[(x for x in a)]")
277 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800278 eq("f'f-string without formatted values is just a string'")
279 eq("f'{{NOT a formatted value}}'")
280 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
281 eq('''f"{f'{nested} inner'} outer"''')
282 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300283 eq("f'{(lambda x: x)}'")
284 eq("f'{(None if a else lambda x: x)}'")
Eric V. Smith9a4135e2019-05-08 16:28:48 -0400285 eq("f'{x}'")
286 eq("f'{x!r}'")
287 eq("f'{x!a}'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800288 eq('(yield from outside_of_generator)')
289 eq('(yield)')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300290 eq('(yield a + b)')
291 eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
292 eq('[x for x in (a if b else c)]')
293 eq('[x for x in a if (b if c else d)]')
294 eq('f(x for x in a)')
295 eq('f(1, (x for x in a))')
296 eq('f((x for x in a), 2)')
297 eq('(((a)))', 'a')
298 eq('(((a, b)))', '(a, b)')
Hakan Çelikce578832020-04-18 19:17:19 +0300299 eq("(x := 10)")
300 eq("f'{(x := 10):=10}'")
Pablo Galindod112c602020-03-18 23:02:09 +0000301 eq("1 + 2 + 3")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000302
Eric V. Smithf83d1db2019-05-29 03:55:44 -0400303 def test_fstring_debug_annotations(self):
Eric V. Smith6f6ff8a2019-05-27 15:31:52 -0400304 # f-strings with '=' don't round trip very well, so set the expected
305 # result explicitely.
306 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
307 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
308 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
309 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
310 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
311 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
312
Batuhan Taşkaya258f5172020-04-14 01:51:31 +0300313 def test_infinity_numbers(self):
314 inf = "1e" + repr(sys.float_info.max_10_exp + 1)
315 infj = f"{inf}j"
316 self.assertAnnotationEqual("1e1000", expected=inf)
317 self.assertAnnotationEqual("1e1000j", expected=infj)
318 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
319 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
320 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
321 self.assertAnnotationEqual("'inf'")
322 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
323 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
324
325
Neal Norwitz328f3382003-12-13 22:43:34 +0000326if __name__ == "__main__":
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200327 unittest.main()