blob: 0f40357b3a7310aec2eff565ed4bce058595fb8a [file] [log] [blame]
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00001# Test various flavors of legal and illegal future statements
2
Batuhan Taşkaya44540572020-04-22 19:09:03 +03003import __future__
4import ast
Neal Norwitz328f3382003-12-13 22:43:34 +00005import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Guido van Rossum95e4d582018-01-26 08:20:18 -08007from textwrap import dedent
Serhiy Storchaka8b583392016-12-11 14:39:01 +02008import os
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00009import re
Batuhan Taşkaya258f5172020-04-14 01:51:31 +030010import sys
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000011
R David Murray44b548d2016-09-08 13:59:53 -040012rx = re.compile(r'\((\S+).py, line (\d+)')
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000013
Neal Norwitz328f3382003-12-13 22:43:34 +000014def get_error_location(msg):
15 mo = rx.search(str(msg))
16 return mo.group(1, 2)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000017
Neal Norwitz328f3382003-12-13 22:43:34 +000018class FutureTest(unittest.TestCase):
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000019
Ammar Askar025eb982018-09-24 17:12:49 -040020 def check_syntax_error(self, err, basename, lineno, offset=1):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020021 self.assertIn('%s.py, line %d' % (basename, lineno), str(err))
22 self.assertEqual(os.path.basename(err.filename), basename + '.py')
23 self.assertEqual(err.lineno, lineno)
24 self.assertEqual(err.offset, offset)
25
Neal Norwitz328f3382003-12-13 22:43:34 +000026 def test_future1(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020027 with support.CleanImport('future_test1'):
28 from test import future_test1
29 self.assertEqual(future_test1.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000030
Neal Norwitz328f3382003-12-13 22:43:34 +000031 def test_future2(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020032 with support.CleanImport('future_test2'):
33 from test import future_test2
34 self.assertEqual(future_test2.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000035
Neal Norwitz328f3382003-12-13 22:43:34 +000036 def test_future3(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020037 with support.CleanImport('test_future3'):
38 from test import test_future3
Jeremy Hylton8471a352001-08-20 20:33:42 +000039
Neal Norwitz328f3382003-12-13 22:43:34 +000040 def test_badfuture3(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020041 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000042 from test import badsyntax_future3
Serhiy Storchaka8b583392016-12-11 14:39:01 +020043 self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000044
Neal Norwitz328f3382003-12-13 22:43:34 +000045 def test_badfuture4(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020046 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000047 from test import badsyntax_future4
Serhiy Storchaka8b583392016-12-11 14:39:01 +020048 self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000049
Neal Norwitz328f3382003-12-13 22:43:34 +000050 def test_badfuture5(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020051 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000052 from test import badsyntax_future5
Serhiy Storchaka8b583392016-12-11 14:39:01 +020053 self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000054
Neal Norwitz328f3382003-12-13 22:43:34 +000055 def test_badfuture6(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020056 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000057 from test import badsyntax_future6
Serhiy Storchaka8b583392016-12-11 14:39:01 +020058 self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000059
Neal Norwitz328f3382003-12-13 22:43:34 +000060 def test_badfuture7(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020061 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000062 from test import badsyntax_future7
Serhiy Storchaka8b583392016-12-11 14:39:01 +020063 self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
Neal Norwitz328f3382003-12-13 22:43:34 +000064
65 def test_badfuture8(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020066 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000067 from test import badsyntax_future8
Serhiy Storchaka8b583392016-12-11 14:39:01 +020068 self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000069
70 def test_badfuture9(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020071 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000072 from test import badsyntax_future9
Ammar Askar025eb982018-09-24 17:12:49 -040073 self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000074
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070075 def test_badfuture10(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020076 with self.assertRaises(SyntaxError) as cm:
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070077 from test import badsyntax_future10
Ammar Askar025eb982018-09-24 17:12:49 -040078 self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070079
Batuhan Taşkaya44540572020-04-22 19:09:03 +030080 def test_ensure_flags_dont_clash(self):
81 # bpo-39562: test that future flags and compiler flags doesn't clash
82
83 # obtain future flags (CO_FUTURE_***) from the __future__ module
84 flags = {
85 f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag
86 for future in __future__.all_feature_names
87 }
88 # obtain some of the exported compiler flags (PyCF_***) from the ast module
89 flags |= {
90 flag: getattr(ast, flag)
91 for flag in dir(ast) if flag.startswith("PyCF_")
92 }
93 self.assertCountEqual(set(flags.values()), flags.values())
94
Thomas Wouters89f507f2006-12-13 04:49:30 +000095 def test_parserhack(self):
96 # test that the parser.c::future_hack function works as expected
97 # Note: although this test must pass, it's not testing the original
98 # bug as of 2.6 since the with statement is not optional and
99 # the parser hack disabled. If a new keyword is introduced in
100 # 2.6, change this to refer to the new future import.
101 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000102 exec("from __future__ import print_function; print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000103 except SyntaxError:
104 pass
105 else:
106 self.fail("syntax error didn't occur")
107
108 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000109 exec("from __future__ import (print_function); print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000110 except SyntaxError:
111 pass
112 else:
113 self.fail("syntax error didn't occur")
114
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000115 def test_multiple_features(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200116 with support.CleanImport("test.test_future5"):
117 from test import test_future5
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000118
Benjamin Petersonf216c942008-10-31 02:28:05 +0000119 def test_unicode_literals_exec(self):
120 scope = {}
121 exec("from __future__ import unicode_literals; x = ''", {}, scope)
Ezio Melottie9615932010-01-24 19:26:24 +0000122 self.assertIsInstance(scope["x"], str)
Benjamin Petersonf216c942008-10-31 02:28:05 +0000123
Guido van Rossum95e4d582018-01-26 08:20:18 -0800124class AnnotationsFutureTestCase(unittest.TestCase):
125 template = dedent(
126 """
127 from __future__ import annotations
128 def f() -> {ann}:
129 ...
130 def g(arg: {ann}) -> None:
131 ...
Pablo Galindod112c602020-03-18 23:02:09 +0000132 async def f2() -> {ann}:
133 ...
134 async def g2(arg: {ann}) -> None:
135 ...
Guido van Rossum95e4d582018-01-26 08:20:18 -0800136 var: {ann}
137 var2: {ann} = None
138 """
139 )
140
141 def getActual(self, annotation):
142 scope = {}
143 exec(self.template.format(ann=annotation), {}, scope)
144 func_ret_ann = scope['f'].__annotations__['return']
145 func_arg_ann = scope['g'].__annotations__['arg']
Pablo Galindod112c602020-03-18 23:02:09 +0000146 async_func_ret_ann = scope['f2'].__annotations__['return']
147 async_func_arg_ann = scope['g2'].__annotations__['arg']
Guido van Rossum95e4d582018-01-26 08:20:18 -0800148 var_ann1 = scope['__annotations__']['var']
149 var_ann2 = scope['__annotations__']['var2']
150 self.assertEqual(func_ret_ann, func_arg_ann)
Pablo Galindod112c602020-03-18 23:02:09 +0000151 self.assertEqual(func_ret_ann, async_func_ret_ann)
152 self.assertEqual(func_ret_ann, async_func_arg_ann)
Guido van Rossum95e4d582018-01-26 08:20:18 -0800153 self.assertEqual(func_ret_ann, var_ann1)
154 self.assertEqual(func_ret_ann, var_ann2)
155 return func_ret_ann
156
157 def assertAnnotationEqual(
158 self, annotation, expected=None, drop_parens=False, is_tuple=False,
159 ):
160 actual = self.getActual(annotation)
161 if expected is None:
162 expected = annotation if not is_tuple else annotation[1:-1]
163 if drop_parens:
164 self.assertNotEqual(actual, expected)
165 actual = actual.replace("(", "").replace(")", "")
166
167 self.assertEqual(actual, expected)
168
169 def test_annotations(self):
170 eq = self.assertAnnotationEqual
171 eq('...')
172 eq("'some_string'")
Batuhan Taşkayaaade1cc2020-04-14 21:55:01 +0300173 eq("u'some_string'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800174 eq("b'\\xa3'")
175 eq('Name')
176 eq('None')
177 eq('True')
178 eq('False')
179 eq('1')
180 eq('1.0')
181 eq('1j')
182 eq('True or False')
183 eq('True or False or None')
184 eq('True and False')
185 eq('True and False and None')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300186 eq('Name1 and Name2 or Name3')
187 eq('Name1 and (Name2 or Name3)')
188 eq('Name1 or Name2 and Name3')
189 eq('(Name1 or Name2) and Name3')
190 eq('Name1 and Name2 or Name3 and Name4')
191 eq('Name1 or Name2 and Name3 or Name4')
192 eq('a + b + (c + d)')
193 eq('a * b * (c * d)')
194 eq('(a ** b) ** c ** d')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800195 eq('v1 << 2')
196 eq('1 >> v2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300197 eq('1 % finished')
198 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800199 eq('not great')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300200 eq('not not great')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800201 eq('~great')
202 eq('+value')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300203 eq('++value')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800204 eq('-1')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300205 eq('~int and not v1 ^ 123 + v2 | True')
206 eq('a + (not b)')
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300207 eq('lambda: None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800208 eq('lambda arg: None')
209 eq('lambda a=True: a')
210 eq('lambda a, b, c=True: a')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300211 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300212 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
Pablo Galindoda6129e2019-05-18 23:40:22 +0100213 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
214 eq('lambda x, /: x')
215 eq('lambda x=1, /: x')
216 eq('lambda x, /, y: x + y')
217 eq('lambda x=1, /, y=2: x + y')
218 eq('lambda x, /, y=1: x + y')
219 eq('lambda x, /, y=1, *, z=3: x + y + z')
220 eq('lambda x=1, /, y=2, *, z=3: x + y + z')
221 eq('lambda x=1, /, y=2, *, z: x + y + z')
222 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
223 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
224 eq('lambda x, /, y=1, *, z: x + y + z')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300225 eq('lambda x: lambda y: x + y')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800226 eq('1 if True else 2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300227 eq('str or None if int or True else str or bytes or None')
228 eq('str or None if (1 if True else 2) else str or bytes or None')
229 eq("0 if not x else 1 if x > 0 else -1")
230 eq("(1 if x > 0 else -1) if x else 0")
231 eq("{'2.7': dead, '3.7': long_live or die_hard}")
232 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800233 eq("{**a, **b, **c}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300234 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
235 eq("{*a, *b, *c}")
236 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800237 eq("()")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300238 eq("(a,)")
239 eq("(a, b)")
240 eq("(a, b, c)")
241 eq("(*a, *b, *c)")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800242 eq("[]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300243 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
244 eq("[*a, *b, *c]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800245 eq("{i for i in (1, 2, 3)}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300246 eq("{i ** 2 for i in (1, 2, 3)}")
247 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
248 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800249 eq("[i for i in (1, 2, 3)]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300250 eq("[i ** 2 for i in (1, 2, 3)]")
251 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
252 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
253 eq("(i for i in (1, 2, 3))")
254 eq("(i ** 2 for i in (1, 2, 3))")
255 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
256 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
257 eq("{i: 0 for i in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800258 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300259 eq("[(x, y) for x, y in (a, b)]")
260 eq("[(x,) for x, in (a,)]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800261 eq("Python3 > Python2 > COBOL")
262 eq("Life is Life")
263 eq("call()")
264 eq("call(arg)")
265 eq("call(kwarg='hey')")
266 eq("call(arg, kwarg='hey')")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300267 eq("call(arg, *args, another, kwarg='hey')")
268 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800269 eq("lukasz.langa.pl")
270 eq("call.me(maybe)")
271 eq("1 .real")
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300272 eq("1.0.real")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800273 eq("....__class__")
274 eq("list[str]")
275 eq("dict[str, int]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300276 eq("set[str,]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800277 eq("tuple[str, ...]")
Batuhan Taskaya2135e102020-05-18 21:23:48 +0300278 eq("tuple[(str, *types)]")
279 eq("tuple[str, int, (str, int)]")
280 eq("tuple[(*int, str, str, (str, int))]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800281 eq("tuple[str, int, float, dict[str, int]]")
282 eq("slice[0]")
283 eq("slice[0:1]")
284 eq("slice[0:1:2]")
285 eq("slice[:]")
286 eq("slice[:-1]")
287 eq("slice[1:]")
288 eq("slice[::-1]")
Batuhan Taşkaya185903d2020-03-01 23:07:22 +0300289 eq("slice[:,]")
290 eq("slice[1:2,]")
291 eq("slice[1:2:3,]")
292 eq("slice[1:2, 1]")
293 eq("slice[1:2, 2, 3]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300294 eq("slice[()]")
295 eq("slice[a, b:c, d:e:f]")
296 eq("slice[(x for x in a)]")
297 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800298 eq("f'f-string without formatted values is just a string'")
299 eq("f'{{NOT a formatted value}}'")
300 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
301 eq('''f"{f'{nested} inner'} outer"''')
302 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300303 eq("f'{(lambda x: x)}'")
304 eq("f'{(None if a else lambda x: x)}'")
Eric V. Smith9a4135e2019-05-08 16:28:48 -0400305 eq("f'{x}'")
306 eq("f'{x!r}'")
307 eq("f'{x!a}'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800308 eq('(yield from outside_of_generator)')
309 eq('(yield)')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300310 eq('(yield a + b)')
311 eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
312 eq('[x for x in (a if b else c)]')
313 eq('[x for x in a if (b if c else d)]')
314 eq('f(x for x in a)')
315 eq('f(1, (x for x in a))')
316 eq('f((x for x in a), 2)')
317 eq('(((a)))', 'a')
318 eq('(((a, b)))', '(a, b)')
Hakan Çelikce578832020-04-18 19:17:19 +0300319 eq("(x := 10)")
320 eq("f'{(x := 10):=10}'")
Pablo Galindod112c602020-03-18 23:02:09 +0000321 eq("1 + 2 + 3")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000322
Eric V. Smithf83d1db2019-05-29 03:55:44 -0400323 def test_fstring_debug_annotations(self):
Eric V. Smith6f6ff8a2019-05-27 15:31:52 -0400324 # f-strings with '=' don't round trip very well, so set the expected
325 # result explicitely.
326 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
327 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
328 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
329 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
330 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
331 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
332
Batuhan Taşkaya258f5172020-04-14 01:51:31 +0300333 def test_infinity_numbers(self):
334 inf = "1e" + repr(sys.float_info.max_10_exp + 1)
335 infj = f"{inf}j"
336 self.assertAnnotationEqual("1e1000", expected=inf)
337 self.assertAnnotationEqual("1e1000j", expected=infj)
338 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
339 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
340 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
341 self.assertAnnotationEqual("'inf'")
342 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
343 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
344
345
Neal Norwitz328f3382003-12-13 22:43:34 +0000346if __name__ == "__main__":
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200347 unittest.main()