blob: 4ef11232a336819dbea468218d751be21a5c0b91 [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
Hai Shi3ddc6342020-06-30 21:46:06 +08007from test.support import import_helper
Guido van Rossum95e4d582018-01-26 08:20:18 -08008from textwrap import dedent
Serhiy Storchaka8b583392016-12-11 14:39:01 +02009import os
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000010import re
Batuhan Taşkaya258f5172020-04-14 01:51:31 +030011import sys
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000012
R David Murray44b548d2016-09-08 13:59:53 -040013rx = re.compile(r'\((\S+).py, line (\d+)')
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000014
Neal Norwitz328f3382003-12-13 22:43:34 +000015def get_error_location(msg):
16 mo = rx.search(str(msg))
17 return mo.group(1, 2)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000018
Neal Norwitz328f3382003-12-13 22:43:34 +000019class FutureTest(unittest.TestCase):
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000020
Ammar Askar025eb982018-09-24 17:12:49 -040021 def check_syntax_error(self, err, basename, lineno, offset=1):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020022 self.assertIn('%s.py, line %d' % (basename, lineno), str(err))
23 self.assertEqual(os.path.basename(err.filename), basename + '.py')
24 self.assertEqual(err.lineno, lineno)
25 self.assertEqual(err.offset, offset)
26
Neal Norwitz328f3382003-12-13 22:43:34 +000027 def test_future1(self):
Hai Shi3ddc6342020-06-30 21:46:06 +080028 with import_helper.CleanImport('future_test1'):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020029 from test import future_test1
30 self.assertEqual(future_test1.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000031
Neal Norwitz328f3382003-12-13 22:43:34 +000032 def test_future2(self):
Hai Shi3ddc6342020-06-30 21:46:06 +080033 with import_helper.CleanImport('future_test2'):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020034 from test import future_test2
35 self.assertEqual(future_test2.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000036
Neal Norwitz328f3382003-12-13 22:43:34 +000037 def test_future3(self):
Hai Shi3ddc6342020-06-30 21:46:06 +080038 with import_helper.CleanImport('test_future3'):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020039 from test import test_future3
Jeremy Hylton8471a352001-08-20 20:33:42 +000040
Neal Norwitz328f3382003-12-13 22:43:34 +000041 def test_badfuture3(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020042 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000043 from test import badsyntax_future3
Serhiy Storchaka8b583392016-12-11 14:39:01 +020044 self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000045
Neal Norwitz328f3382003-12-13 22:43:34 +000046 def test_badfuture4(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020047 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000048 from test import badsyntax_future4
Serhiy Storchaka8b583392016-12-11 14:39:01 +020049 self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000050
Neal Norwitz328f3382003-12-13 22:43:34 +000051 def test_badfuture5(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020052 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000053 from test import badsyntax_future5
Serhiy Storchaka8b583392016-12-11 14:39:01 +020054 self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000055
Neal Norwitz328f3382003-12-13 22:43:34 +000056 def test_badfuture6(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020057 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000058 from test import badsyntax_future6
Serhiy Storchaka8b583392016-12-11 14:39:01 +020059 self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000060
Neal Norwitz328f3382003-12-13 22:43:34 +000061 def test_badfuture7(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020062 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000063 from test import badsyntax_future7
Serhiy Storchaka8b583392016-12-11 14:39:01 +020064 self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
Neal Norwitz328f3382003-12-13 22:43:34 +000065
66 def test_badfuture8(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020067 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000068 from test import badsyntax_future8
Serhiy Storchaka8b583392016-12-11 14:39:01 +020069 self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000070
71 def test_badfuture9(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020072 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000073 from test import badsyntax_future9
Ammar Askar025eb982018-09-24 17:12:49 -040074 self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000075
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070076 def test_badfuture10(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020077 with self.assertRaises(SyntaxError) as cm:
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070078 from test import badsyntax_future10
Ammar Askar025eb982018-09-24 17:12:49 -040079 self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070080
Batuhan Taşkaya44540572020-04-22 19:09:03 +030081 def test_ensure_flags_dont_clash(self):
82 # bpo-39562: test that future flags and compiler flags doesn't clash
83
84 # obtain future flags (CO_FUTURE_***) from the __future__ module
85 flags = {
86 f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag
87 for future in __future__.all_feature_names
88 }
89 # obtain some of the exported compiler flags (PyCF_***) from the ast module
90 flags |= {
91 flag: getattr(ast, flag)
92 for flag in dir(ast) if flag.startswith("PyCF_")
93 }
94 self.assertCountEqual(set(flags.values()), flags.values())
95
Thomas Wouters89f507f2006-12-13 04:49:30 +000096 def test_parserhack(self):
97 # test that the parser.c::future_hack function works as expected
98 # Note: although this test must pass, it's not testing the original
99 # bug as of 2.6 since the with statement is not optional and
100 # the parser hack disabled. If a new keyword is introduced in
101 # 2.6, change this to refer to the new future import.
102 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000103 exec("from __future__ import print_function; print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000104 except SyntaxError:
105 pass
106 else:
107 self.fail("syntax error didn't occur")
108
109 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000110 exec("from __future__ import (print_function); print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000111 except SyntaxError:
112 pass
113 else:
114 self.fail("syntax error didn't occur")
115
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000116 def test_multiple_features(self):
Hai Shi3ddc6342020-06-30 21:46:06 +0800117 with import_helper.CleanImport("test.test_future5"):
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200118 from test import test_future5
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000119
Benjamin Petersonf216c942008-10-31 02:28:05 +0000120 def test_unicode_literals_exec(self):
121 scope = {}
122 exec("from __future__ import unicode_literals; x = ''", {}, scope)
Ezio Melottie9615932010-01-24 19:26:24 +0000123 self.assertIsInstance(scope["x"], str)
Benjamin Petersonf216c942008-10-31 02:28:05 +0000124
Guido van Rossum95e4d582018-01-26 08:20:18 -0800125class AnnotationsFutureTestCase(unittest.TestCase):
126 template = dedent(
127 """
128 from __future__ import annotations
129 def f() -> {ann}:
130 ...
131 def g(arg: {ann}) -> None:
132 ...
Pablo Galindod112c602020-03-18 23:02:09 +0000133 async def f2() -> {ann}:
134 ...
135 async def g2(arg: {ann}) -> None:
136 ...
Batuhan Taskaya8cc3cfa2021-04-25 05:31:20 +0300137 class H:
138 var: {ann}
139 object.attr: {ann}
Guido van Rossum95e4d582018-01-26 08:20:18 -0800140 var: {ann}
141 var2: {ann} = None
Batuhan Taskaya8cc3cfa2021-04-25 05:31:20 +0300142 object.attr: {ann}
Guido van Rossum95e4d582018-01-26 08:20:18 -0800143 """
144 )
145
146 def getActual(self, annotation):
147 scope = {}
148 exec(self.template.format(ann=annotation), {}, scope)
149 func_ret_ann = scope['f'].__annotations__['return']
150 func_arg_ann = scope['g'].__annotations__['arg']
Pablo Galindod112c602020-03-18 23:02:09 +0000151 async_func_ret_ann = scope['f2'].__annotations__['return']
152 async_func_arg_ann = scope['g2'].__annotations__['arg']
Guido van Rossum95e4d582018-01-26 08:20:18 -0800153 var_ann1 = scope['__annotations__']['var']
154 var_ann2 = scope['__annotations__']['var2']
155 self.assertEqual(func_ret_ann, func_arg_ann)
Pablo Galindod112c602020-03-18 23:02:09 +0000156 self.assertEqual(func_ret_ann, async_func_ret_ann)
157 self.assertEqual(func_ret_ann, async_func_arg_ann)
Guido van Rossum95e4d582018-01-26 08:20:18 -0800158 self.assertEqual(func_ret_ann, var_ann1)
159 self.assertEqual(func_ret_ann, var_ann2)
160 return func_ret_ann
161
162 def assertAnnotationEqual(
163 self, annotation, expected=None, drop_parens=False, is_tuple=False,
164 ):
165 actual = self.getActual(annotation)
166 if expected is None:
167 expected = annotation if not is_tuple else annotation[1:-1]
168 if drop_parens:
169 self.assertNotEqual(actual, expected)
170 actual = actual.replace("(", "").replace(")", "")
171
172 self.assertEqual(actual, expected)
173
Batuhan Taskayaad106c62021-05-03 10:43:00 +0300174 def _exec_future(self, code):
175 scope = {}
176 exec(
177 "from __future__ import annotations\n"
178 + code, {}, scope
179 )
180 return scope
181
Guido van Rossum95e4d582018-01-26 08:20:18 -0800182 def test_annotations(self):
183 eq = self.assertAnnotationEqual
184 eq('...')
185 eq("'some_string'")
Batuhan Taşkayaaade1cc2020-04-14 21:55:01 +0300186 eq("u'some_string'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800187 eq("b'\\xa3'")
188 eq('Name')
189 eq('None')
190 eq('True')
191 eq('False')
192 eq('1')
193 eq('1.0')
194 eq('1j')
195 eq('True or False')
196 eq('True or False or None')
197 eq('True and False')
198 eq('True and False and None')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300199 eq('Name1 and Name2 or Name3')
200 eq('Name1 and (Name2 or Name3)')
201 eq('Name1 or Name2 and Name3')
202 eq('(Name1 or Name2) and Name3')
203 eq('Name1 and Name2 or Name3 and Name4')
204 eq('Name1 or Name2 and Name3 or Name4')
205 eq('a + b + (c + d)')
206 eq('a * b * (c * d)')
207 eq('(a ** b) ** c ** d')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800208 eq('v1 << 2')
209 eq('1 >> v2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300210 eq('1 % finished')
211 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800212 eq('not great')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300213 eq('not not great')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800214 eq('~great')
215 eq('+value')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300216 eq('++value')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800217 eq('-1')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300218 eq('~int and not v1 ^ 123 + v2 | True')
219 eq('a + (not b)')
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300220 eq('lambda: None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800221 eq('lambda arg: None')
222 eq('lambda a=True: a')
223 eq('lambda a, b, c=True: a')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300224 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
Serhiy Storchaka2a2940e2018-09-30 21:07:05 +0300225 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
Pablo Galindoda6129e2019-05-18 23:40:22 +0100226 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
227 eq('lambda x, /: x')
228 eq('lambda x=1, /: x')
229 eq('lambda x, /, y: x + y')
230 eq('lambda x=1, /, y=2: x + y')
231 eq('lambda x, /, y=1: x + y')
232 eq('lambda x, /, y=1, *, z=3: x + y + z')
233 eq('lambda x=1, /, y=2, *, z=3: x + y + z')
234 eq('lambda x=1, /, y=2, *, z: x + y + z')
235 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
236 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
237 eq('lambda x, /, y=1, *, z: x + y + z')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300238 eq('lambda x: lambda y: x + y')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800239 eq('1 if True else 2')
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300240 eq('str or None if int or True else str or bytes or None')
241 eq('str or None if (1 if True else 2) else str or bytes or None')
242 eq("0 if not x else 1 if x > 0 else -1")
243 eq("(1 if x > 0 else -1) if x else 0")
244 eq("{'2.7': dead, '3.7': long_live or die_hard}")
245 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800246 eq("{**a, **b, **c}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300247 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
248 eq("{*a, *b, *c}")
249 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800250 eq("()")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300251 eq("(a,)")
252 eq("(a, b)")
253 eq("(a, b, c)")
254 eq("(*a, *b, *c)")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800255 eq("[]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300256 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
257 eq("[*a, *b, *c]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800258 eq("{i for i in (1, 2, 3)}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300259 eq("{i ** 2 for i in (1, 2, 3)}")
260 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
261 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800262 eq("[i for i in (1, 2, 3)]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300263 eq("[i ** 2 for i in (1, 2, 3)]")
264 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
265 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
266 eq("(i for i in (1, 2, 3))")
267 eq("(i ** 2 for i in (1, 2, 3))")
268 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
269 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
270 eq("{i: 0 for i in (1, 2, 3)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800271 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300272 eq("[(x, y) for x, y in (a, b)]")
273 eq("[(x,) for x, in (a,)]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800274 eq("Python3 > Python2 > COBOL")
275 eq("Life is Life")
276 eq("call()")
277 eq("call(arg)")
278 eq("call(kwarg='hey')")
279 eq("call(arg, kwarg='hey')")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300280 eq("call(arg, *args, another, kwarg='hey')")
281 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800282 eq("lukasz.langa.pl")
283 eq("call.me(maybe)")
284 eq("1 .real")
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300285 eq("1.0.real")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800286 eq("....__class__")
287 eq("list[str]")
288 eq("dict[str, int]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300289 eq("set[str,]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800290 eq("tuple[str, ...]")
Batuhan Taskaya2135e102020-05-18 21:23:48 +0300291 eq("tuple[(str, *types)]")
292 eq("tuple[str, int, (str, int)]")
293 eq("tuple[(*int, str, str, (str, int))]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800294 eq("tuple[str, int, float, dict[str, int]]")
295 eq("slice[0]")
296 eq("slice[0:1]")
297 eq("slice[0:1:2]")
298 eq("slice[:]")
299 eq("slice[:-1]")
300 eq("slice[1:]")
301 eq("slice[::-1]")
Batuhan Taşkaya185903d2020-03-01 23:07:22 +0300302 eq("slice[:,]")
303 eq("slice[1:2,]")
304 eq("slice[1:2:3,]")
305 eq("slice[1:2, 1]")
306 eq("slice[1:2, 2, 3]")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300307 eq("slice[()]")
308 eq("slice[a, b:c, d:e:f]")
309 eq("slice[(x for x in a)]")
310 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800311 eq("f'f-string without formatted values is just a string'")
312 eq("f'{{NOT a formatted value}}'")
313 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
314 eq('''f"{f'{nested} inner'} outer"''')
315 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300316 eq("f'{(lambda x: x)}'")
317 eq("f'{(None if a else lambda x: x)}'")
Eric V. Smith9a4135e2019-05-08 16:28:48 -0400318 eq("f'{x}'")
319 eq("f'{x!r}'")
320 eq("f'{x!a}'")
Serhiy Storchaka64fddc42018-05-17 06:17:48 +0300321 eq('[x for x in (a if b else c)]')
322 eq('[x for x in a if (b if c else d)]')
323 eq('f(x for x in a)')
324 eq('f(1, (x for x in a))')
325 eq('f((x for x in a), 2)')
326 eq('(((a)))', 'a')
327 eq('(((a, b)))', '(a, b)')
Pablo Galindod112c602020-03-18 23:02:09 +0000328 eq("1 + 2 + 3")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000329
Eric V. Smithf83d1db2019-05-29 03:55:44 -0400330 def test_fstring_debug_annotations(self):
Eric V. Smith6f6ff8a2019-05-27 15:31:52 -0400331 # f-strings with '=' don't round trip very well, so set the expected
332 # result explicitely.
333 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
334 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
335 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
336 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
337 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
338 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
339
Batuhan Taşkaya258f5172020-04-14 01:51:31 +0300340 def test_infinity_numbers(self):
341 inf = "1e" + repr(sys.float_info.max_10_exp + 1)
342 infj = f"{inf}j"
343 self.assertAnnotationEqual("1e1000", expected=inf)
344 self.assertAnnotationEqual("1e1000j", expected=infj)
345 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
346 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
347 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
348 self.assertAnnotationEqual("'inf'")
349 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
350 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
351
Batuhan Taskaya8cc3cfa2021-04-25 05:31:20 +0300352 def test_annotation_with_complex_target(self):
353 with self.assertRaises(SyntaxError):
354 exec(
355 "from __future__ import annotations\n"
356 "object.__debug__: int"
357 )
358
Batuhan Taskayaad106c62021-05-03 10:43:00 +0300359 def test_annotations_symbol_table_pass(self):
360 namespace = self._exec_future(dedent("""
361 from __future__ import annotations
362
363 def foo():
364 outer = 1
365 def bar():
366 inner: outer = 1
367 return bar
368 """))
369
370 foo = namespace.pop("foo")
371 self.assertIsNone(foo().__closure__)
372 self.assertEqual(foo.__code__.co_cellvars, ())
373 self.assertEqual(foo().__code__.co_freevars, ())
374
375 def test_annotations_forbidden(self):
376 with self.assertRaises(SyntaxError):
377 self._exec_future("test: (yield)")
378
379 with self.assertRaises(SyntaxError):
380 self._exec_future("test.test: (yield a + b)")
381
382 with self.assertRaises(SyntaxError):
383 self._exec_future("test[something]: (yield from x)")
384
385 with self.assertRaises(SyntaxError):
386 self._exec_future("def func(test: (yield from outside_of_generator)): pass")
387
388 with self.assertRaises(SyntaxError):
389 self._exec_future("def test() -> (await y): pass")
390
391 with self.assertRaises(SyntaxError):
392 self._exec_future("async def test() -> something((a := b)): pass")
393
394 with self.assertRaises(SyntaxError):
395 self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)")
396
397 with self.assertRaises(SyntaxError):
398 self._exec_future("test: f'{(x := 10):=10}'")
399
400 with self.assertRaises(SyntaxError):
401 self._exec_future(dedent("""\
402 def foo():
403 def bar(arg: (yield)): pass
404 """))
405
Batuhan Taşkaya258f5172020-04-14 01:51:31 +0300406
Neal Norwitz328f3382003-12-13 22:43:34 +0000407if __name__ == "__main__":
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200408 unittest.main()