blob: ea13533b5143dedebe6a31d259d4c8753fa4560b [file] [log] [blame]
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00001# Test various flavors of legal and illegal future statements
2
Pablo Galindo5055c272020-05-01 15:18:27 +01003import __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
10
R David Murray44b548d2016-09-08 13:59:53 -040011rx = re.compile(r'\((\S+).py, line (\d+)')
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000012
Neal Norwitz328f3382003-12-13 22:43:34 +000013def get_error_location(msg):
14 mo = rx.search(str(msg))
15 return mo.group(1, 2)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000016
Neal Norwitz328f3382003-12-13 22:43:34 +000017class FutureTest(unittest.TestCase):
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000018
Ammar Askar025eb982018-09-24 17:12:49 -040019 def check_syntax_error(self, err, basename, lineno, offset=1):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020020 self.assertIn('%s.py, line %d' % (basename, lineno), str(err))
21 self.assertEqual(os.path.basename(err.filename), basename + '.py')
22 self.assertEqual(err.lineno, lineno)
23 self.assertEqual(err.offset, offset)
24
Neal Norwitz328f3382003-12-13 22:43:34 +000025 def test_future1(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020026 with support.CleanImport('future_test1'):
27 from test import future_test1
28 self.assertEqual(future_test1.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000029
Neal Norwitz328f3382003-12-13 22:43:34 +000030 def test_future2(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020031 with support.CleanImport('future_test2'):
32 from test import future_test2
33 self.assertEqual(future_test2.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000034
Neal Norwitz328f3382003-12-13 22:43:34 +000035 def test_future3(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020036 with support.CleanImport('test_future3'):
37 from test import test_future3
Jeremy Hylton8471a352001-08-20 20:33:42 +000038
Neal Norwitz328f3382003-12-13 22:43:34 +000039 def test_badfuture3(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020040 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000041 from test import badsyntax_future3
Serhiy Storchaka8b583392016-12-11 14:39:01 +020042 self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000043
Neal Norwitz328f3382003-12-13 22:43:34 +000044 def test_badfuture4(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020045 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000046 from test import badsyntax_future4
Serhiy Storchaka8b583392016-12-11 14:39:01 +020047 self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000048
Neal Norwitz328f3382003-12-13 22:43:34 +000049 def test_badfuture5(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020050 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000051 from test import badsyntax_future5
Serhiy Storchaka8b583392016-12-11 14:39:01 +020052 self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000053
Neal Norwitz328f3382003-12-13 22:43:34 +000054 def test_badfuture6(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020055 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000056 from test import badsyntax_future6
Serhiy Storchaka8b583392016-12-11 14:39:01 +020057 self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000058
Neal Norwitz328f3382003-12-13 22:43:34 +000059 def test_badfuture7(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020060 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000061 from test import badsyntax_future7
Serhiy Storchaka8b583392016-12-11 14:39:01 +020062 self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
Neal Norwitz328f3382003-12-13 22:43:34 +000063
64 def test_badfuture8(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020065 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000066 from test import badsyntax_future8
Serhiy Storchaka8b583392016-12-11 14:39:01 +020067 self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000068
69 def test_badfuture9(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020070 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000071 from test import badsyntax_future9
Ammar Askar025eb982018-09-24 17:12:49 -040072 self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000073
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070074 def test_badfuture10(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020075 with self.assertRaises(SyntaxError) as cm:
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070076 from test import badsyntax_future10
Ammar Askar025eb982018-09-24 17:12:49 -040077 self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070078
Pablo Galindo5055c272020-05-01 15:18:27 +010079 def test_ensure_flags_dont_clash(self):
80 # bpo-39562: test that future flags and compiler flags doesn't clash
81
82 # obtain future flags (CO_FUTURE_***) from the __future__ module
83 flags = {
84 f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag
85 for future in __future__.all_feature_names
86 }
87 # obtain some of the exported compiler flags (PyCF_***) from the ast module
88 flags.update({
89 flag: getattr(ast, flag)
90 for flag in dir(ast) if flag.startswith("PyCF_")
91 })
92 self.assertCountEqual(set(flags.values()), flags.values())
93
Thomas Wouters89f507f2006-12-13 04:49:30 +000094 def test_parserhack(self):
95 # test that the parser.c::future_hack function works as expected
96 # Note: although this test must pass, it's not testing the original
97 # bug as of 2.6 since the with statement is not optional and
98 # the parser hack disabled. If a new keyword is introduced in
99 # 2.6, change this to refer to the new future import.
100 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000101 exec("from __future__ import print_function; print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000102 except SyntaxError:
103 pass
104 else:
105 self.fail("syntax error didn't occur")
106
107 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000108 exec("from __future__ import (print_function); print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000109 except SyntaxError:
110 pass
111 else:
112 self.fail("syntax error didn't occur")
113
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000114 def test_multiple_features(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200115 with support.CleanImport("test.test_future5"):
116 from test import test_future5
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000117
Benjamin Petersonf216c942008-10-31 02:28:05 +0000118 def test_unicode_literals_exec(self):
119 scope = {}
120 exec("from __future__ import unicode_literals; x = ''", {}, scope)
Ezio Melottie9615932010-01-24 19:26:24 +0000121 self.assertIsInstance(scope["x"], str)
Benjamin Petersonf216c942008-10-31 02:28:05 +0000122
Guido van Rossum95e4d582018-01-26 08:20:18 -0800123class AnnotationsFutureTestCase(unittest.TestCase):
124 template = dedent(
125 """
126 from __future__ import annotations
127 def f() -> {ann}:
128 ...
129 def g(arg: {ann}) -> None:
130 ...
131 var: {ann}
132 var2: {ann} = None
133 """
134 )
135
136 def getActual(self, annotation):
137 scope = {}
138 exec(self.template.format(ann=annotation), {}, scope)
139 func_ret_ann = scope['f'].__annotations__['return']
140 func_arg_ann = scope['g'].__annotations__['arg']
141 var_ann1 = scope['__annotations__']['var']
142 var_ann2 = scope['__annotations__']['var2']
143 self.assertEqual(func_ret_ann, func_arg_ann)
144 self.assertEqual(func_ret_ann, var_ann1)
145 self.assertEqual(func_ret_ann, var_ann2)
146 return func_ret_ann
147
148 def assertAnnotationEqual(
149 self, annotation, expected=None, drop_parens=False, is_tuple=False,
150 ):
151 actual = self.getActual(annotation)
152 if expected is None:
153 expected = annotation if not is_tuple else annotation[1:-1]
154 if drop_parens:
155 self.assertNotEqual(actual, expected)
156 actual = actual.replace("(", "").replace(")", "")
157
158 self.assertEqual(actual, expected)
159
160 def test_annotations(self):
161 eq = self.assertAnnotationEqual
162 eq('...')
163 eq("'some_string'")
164 eq("b'\\xa3'")
165 eq('Name')
166 eq('None')
167 eq('True')
168 eq('False')
169 eq('1')
170 eq('1.0')
171 eq('1j')
172 eq('True or False')
173 eq('True or False or None')
174 eq('True and False')
175 eq('True and False and None')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300176 eq('Name1 and Name2 or Name3')
177 eq('Name1 and (Name2 or Name3)')
178 eq('Name1 or Name2 and Name3')
179 eq('(Name1 or Name2) and Name3')
180 eq('Name1 and Name2 or Name3 and Name4')
181 eq('Name1 or Name2 and Name3 or Name4')
182 eq('a + b + (c + d)')
183 eq('a * b * (c * d)')
184 eq('(a ** b) ** c ** d')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800185 eq('v1 << 2')
186 eq('1 >> v2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300187 eq('1 % finished')
188 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800189 eq('not great')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300190 eq('not not great')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800191 eq('~great')
192 eq('+value')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300193 eq('++value')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800194 eq('-1')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300195 eq('~int and not v1 ^ 123 + v2 | True')
196 eq('a + (not b)')
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300197 eq('lambda: None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800198 eq('lambda arg: None')
199 eq('lambda a=True: a')
200 eq('lambda a, b, c=True: a')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300201 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300202 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
Pablo Galindoda6129e2019-05-18 23:40:22 +0100203 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
204 eq('lambda x, /: x')
205 eq('lambda x=1, /: x')
206 eq('lambda x, /, y: x + y')
207 eq('lambda x=1, /, y=2: x + y')
208 eq('lambda x, /, y=1: x + y')
209 eq('lambda x, /, y=1, *, z=3: x + y + z')
210 eq('lambda x=1, /, y=2, *, z=3: x + y + z')
211 eq('lambda x=1, /, y=2, *, z: x + y + z')
212 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
213 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
214 eq('lambda x, /, y=1, *, z: x + y + z')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300215 eq('lambda x: lambda y: x + y')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800216 eq('1 if True else 2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300217 eq('str or None if int or True else str or bytes or None')
218 eq('str or None if (1 if True else 2) else str or bytes or None')
219 eq("0 if not x else 1 if x > 0 else -1")
220 eq("(1 if x > 0 else -1) if x else 0")
221 eq("{'2.7': dead, '3.7': long_live or die_hard}")
222 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800223 eq("{**a, **b, **c}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300224 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
225 eq("{*a, *b, *c}")
226 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800227 eq("()")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300228 eq("(a,)")
229 eq("(a, b)")
230 eq("(a, b, c)")
231 eq("(*a, *b, *c)")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800232 eq("[]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300233 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
234 eq("[*a, *b, *c]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800235 eq("{i for i in (1, 2, 3)}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300236 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)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800239 eq("[i for i in (1, 2, 3)]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300240 eq("[i ** 2 for i in (1, 2, 3)]")
241 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
242 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
243 eq("(i for i in (1, 2, 3))")
244 eq("(i ** 2 for i in (1, 2, 3))")
245 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
246 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
247 eq("{i: 0 for i in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800248 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300249 eq("[(x, y) for x, y in (a, b)]")
250 eq("[(x,) for x, in (a,)]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800251 eq("Python3 > Python2 > COBOL")
252 eq("Life is Life")
253 eq("call()")
254 eq("call(arg)")
255 eq("call(kwarg='hey')")
256 eq("call(arg, kwarg='hey')")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300257 eq("call(arg, *args, another, kwarg='hey')")
258 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800259 eq("lukasz.langa.pl")
260 eq("call.me(maybe)")
261 eq("1 .real")
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300262 eq("1.0.real")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800263 eq("....__class__")
264 eq("list[str]")
265 eq("dict[str, int]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300266 eq("set[str,]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800267 eq("tuple[str, ...]")
268 eq("tuple[str, int, float, dict[str, int]]")
269 eq("slice[0]")
270 eq("slice[0:1]")
271 eq("slice[0:1:2]")
272 eq("slice[:]")
273 eq("slice[:-1]")
274 eq("slice[1:]")
275 eq("slice[::-1]")
Miss Islington (bot)cd07b4d2020-03-11 13:18:01 -0700276 eq("slice[:,]")
277 eq("slice[1:2,]")
278 eq("slice[1:2:3,]")
279 eq("slice[1:2, 1]")
280 eq("slice[1:2, 2, 3]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300281 eq("slice[()]")
282 eq("slice[a, b:c, d:e:f]")
283 eq("slice[(x for x in a)]")
284 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800285 eq("f'f-string without formatted values is just a string'")
286 eq("f'{{NOT a formatted value}}'")
287 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
288 eq('''f"{f'{nested} inner'} outer"''')
289 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300290 eq("f'{(lambda x: x)}'")
291 eq("f'{(None if a else lambda x: x)}'")
Eric V. Smith9a4135e2019-05-08 16:28:48 -0400292 eq("f'{x}'")
293 eq("f'{x!r}'")
294 eq("f'{x!a}'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800295 eq('(yield from outside_of_generator)')
296 eq('(yield)')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300297 eq('(yield a + b)')
298 eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
299 eq('[x for x in (a if b else c)]')
300 eq('[x for x in a if (b if c else d)]')
301 eq('f(x for x in a)')
302 eq('f(1, (x for x in a))')
303 eq('f((x for x in a), 2)')
304 eq('(((a)))', 'a')
305 eq('(((a, b)))', '(a, b)')
Batuhan Taşkayafa19a252019-05-19 01:10:20 +0300306 eq("(x:=10)")
307 eq("f'{(x:=10):=10}'")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000308
Eric V. Smithf83d1db2019-05-29 03:55:44 -0400309 def test_fstring_debug_annotations(self):
Eric V. Smith6f6ff8a2019-05-27 15:31:52 -0400310 # f-strings with '=' don't round trip very well, so set the expected
311 # result explicitely.
312 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
313 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
314 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
315 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
316 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
317 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
318
Neal Norwitz328f3382003-12-13 22:43:34 +0000319
320if __name__ == "__main__":
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200321 unittest.main()