1# Test various flavors of legal and illegal future statements 2 3import __future__ 4import ast 5import unittest 6from test.support import import_helper 7from test.support.script_helper import spawn_python, kill_python 8from textwrap import dedent 9import os 10import re 11import sys 12 13TOP_LEVEL_MSG = 'from __future__ imports must occur at the beginning of the file' 14 15rx = re.compile(r'\((\S+).py, line (\d+)') 16 17def get_error_location(msg): 18 mo = rx.search(str(msg)) 19 return mo.group(1, 2) 20 21class FutureTest(unittest.TestCase): 22 23 def check_syntax_error(self, err, basename, 24 *, 25 lineno, 26 message=TOP_LEVEL_MSG, offset=1): 27 if basename != '<string>': 28 basename += '.py' 29 30 self.assertEqual(f'{message} ({basename}, line {lineno})', str(err)) 31 self.assertEqual(os.path.basename(err.filename), basename) 32 self.assertEqual(err.lineno, lineno) 33 self.assertEqual(err.offset, offset) 34 35 def assertSyntaxError(self, code, 36 *, 37 lineno=1, 38 message=TOP_LEVEL_MSG, offset=1, 39 parametrize_docstring=True): 40 code = dedent(code.lstrip('\n')) 41 for add_docstring in ([False, True] if parametrize_docstring else [False]): 42 with self.subTest(code=code, add_docstring=add_docstring): 43 if add_docstring: 44 code = '"""Docstring"""\n' + code 45 lineno += 1 46 with self.assertRaises(SyntaxError) as cm: 47 exec(code) 48 self.check_syntax_error(cm.exception, "<string>", 49 lineno=lineno, 50 message=message, 51 offset=offset) 52 53 def test_import_nested_scope_twice(self): 54 # Import the name nested_scopes twice to trigger SF bug #407394 55 with import_helper.CleanImport( 56 'test.test_future_stmt.import_nested_scope_twice', 57 ): 58 from test.test_future_stmt import import_nested_scope_twice 59 self.assertEqual(import_nested_scope_twice.result, 6) 60 61 def test_nested_scope(self): 62 with import_helper.CleanImport('test.test_future_stmt.nested_scope'): 63 from test.test_future_stmt import nested_scope 64 self.assertEqual(nested_scope.result, 6) 65 66 def test_future_single_import(self): 67 with import_helper.CleanImport( 68 'test.test_future_stmt.test_future_single_import', 69 ): 70 from test.test_future_stmt import test_future_single_import 71 72 def test_future_multiple_imports(self): 73 with import_helper.CleanImport( 74 'test.test_future_stmt.test_future_multiple_imports', 75 ): 76 from test.test_future_stmt import test_future_multiple_imports 77 78 def test_future_multiple_features(self): 79 with import_helper.CleanImport( 80 "test.test_future_stmt.test_future_multiple_features", 81 ): 82 from test.test_future_stmt import test_future_multiple_features 83 84 def test_unknown_future_flag(self): 85 code = """ 86 from __future__ import nested_scopes 87 from __future__ import rested_snopes # typo error here: nested => rested 88 """ 89 self.assertSyntaxError( 90 code, lineno=2, 91 message='future feature rested_snopes is not defined', offset=24, 92 ) 93 94 def test_future_import_not_on_top(self): 95 code = """ 96 import some_module 97 from __future__ import annotations 98 """ 99 self.assertSyntaxError(code, lineno=2) 100 101 code = """ 102 import __future__ 103 from __future__ import annotations 104 """ 105 self.assertSyntaxError(code, lineno=2) 106 107 code = """ 108 from __future__ import absolute_import 109 "spam, bar, blah" 110 from __future__ import print_function 111 """ 112 self.assertSyntaxError(code, lineno=3) 113 114 def test_future_import_with_extra_string(self): 115 code = """ 116 '''Docstring''' 117 "this isn't a doc string" 118 from __future__ import nested_scopes 119 """ 120 self.assertSyntaxError(code, lineno=3, parametrize_docstring=False) 121 122 def test_multiple_import_statements_on_same_line(self): 123 # With `\`: 124 code = """ 125 from __future__ import nested_scopes; import string; from __future__ import \ 126 nested_scopes 127 """ 128 self.assertSyntaxError(code, offset=54) 129 130 # Without `\`: 131 code = """ 132 from __future__ import nested_scopes; import string; from __future__ import nested_scopes 133 """ 134 self.assertSyntaxError(code, offset=54) 135 136 def test_future_import_star(self): 137 code = """ 138 from __future__ import * 139 """ 140 self.assertSyntaxError(code, message='future feature * is not defined', offset=24) 141 142 def test_future_import_braces(self): 143 code = """ 144 from __future__ import braces 145 """ 146 # Congrats, you found an easter egg! 147 self.assertSyntaxError(code, message='not a chance', offset=24) 148 149 code = """ 150 from __future__ import nested_scopes, braces 151 """ 152 self.assertSyntaxError(code, message='not a chance', offset=39) 153 154 def test_module_with_future_import_not_on_top(self): 155 with self.assertRaises(SyntaxError) as cm: 156 from test.test_future_stmt import badsyntax_future 157 self.check_syntax_error(cm.exception, "badsyntax_future", lineno=3) 158 159 def test_ensure_flags_dont_clash(self): 160 # bpo-39562: test that future flags and compiler flags doesn't clash 161 162 # obtain future flags (CO_FUTURE_***) from the __future__ module 163 flags = { 164 f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag 165 for future in __future__.all_feature_names 166 } 167 # obtain some of the exported compiler flags (PyCF_***) from the ast module 168 flags |= { 169 flag: getattr(ast, flag) 170 for flag in dir(ast) if flag.startswith("PyCF_") 171 } 172 self.assertCountEqual(set(flags.values()), flags.values()) 173 174 def test_unicode_literals_exec(self): 175 scope = {} 176 exec("from __future__ import unicode_literals; x = ''", {}, scope) 177 self.assertIsInstance(scope["x"], str) 178 179 def test_syntactical_future_repl(self): 180 p = spawn_python('-i') 181 p.stdin.write(b"from __future__ import barry_as_FLUFL\n") 182 p.stdin.write(b"2 <> 3\n") 183 out = kill_python(p) 184 self.assertNotIn(b'SyntaxError: invalid syntax', out) 185 186 def test_future_dotted_import(self): 187 with self.assertRaises(ImportError): 188 exec("from .__future__ import spam") 189 190 code = dedent( 191 """ 192 from __future__ import print_function 193 from ...__future__ import ham 194 """ 195 ) 196 with self.assertRaises(ImportError): 197 exec(code) 198 199 code = """ 200 from .__future__ import nested_scopes 201 from __future__ import barry_as_FLUFL 202 """ 203 self.assertSyntaxError(code, lineno=2) 204 205class AnnotationsFutureTestCase(unittest.TestCase): 206 template = dedent( 207 """ 208 from __future__ import annotations 209 def f() -> {ann}: 210 ... 211 def g(arg: {ann}) -> None: 212 ... 213 async def f2() -> {ann}: 214 ... 215 async def g2(arg: {ann}) -> None: 216 ... 217 class H: 218 var: {ann} 219 object.attr: {ann} 220 var: {ann} 221 var2: {ann} = None 222 object.attr: {ann} 223 """ 224 ) 225 226 def getActual(self, annotation): 227 scope = {} 228 exec(self.template.format(ann=annotation), {}, scope) 229 func_ret_ann = scope['f'].__annotations__['return'] 230 func_arg_ann = scope['g'].__annotations__['arg'] 231 async_func_ret_ann = scope['f2'].__annotations__['return'] 232 async_func_arg_ann = scope['g2'].__annotations__['arg'] 233 var_ann1 = scope['__annotations__']['var'] 234 var_ann2 = scope['__annotations__']['var2'] 235 self.assertEqual(func_ret_ann, func_arg_ann) 236 self.assertEqual(func_ret_ann, async_func_ret_ann) 237 self.assertEqual(func_ret_ann, async_func_arg_ann) 238 self.assertEqual(func_ret_ann, var_ann1) 239 self.assertEqual(func_ret_ann, var_ann2) 240 return func_ret_ann 241 242 def assertAnnotationEqual( 243 self, annotation, expected=None, drop_parens=False, is_tuple=False, 244 ): 245 actual = self.getActual(annotation) 246 if expected is None: 247 expected = annotation if not is_tuple else annotation[1:-1] 248 if drop_parens: 249 self.assertNotEqual(actual, expected) 250 actual = actual.replace("(", "").replace(")", "") 251 252 self.assertEqual(actual, expected) 253 254 def _exec_future(self, code): 255 scope = {} 256 exec( 257 "from __future__ import annotations\n" 258 + code, scope 259 ) 260 return scope 261 262 def test_annotations(self): 263 eq = self.assertAnnotationEqual 264 eq('...') 265 eq("'some_string'") 266 eq("u'some_string'") 267 eq("b'\\xa3'") 268 eq('Name') 269 eq('None') 270 eq('True') 271 eq('False') 272 eq('1') 273 eq('1.0') 274 eq('1j') 275 eq('True or False') 276 eq('True or False or None') 277 eq('True and False') 278 eq('True and False and None') 279 eq('Name1 and Name2 or Name3') 280 eq('Name1 and (Name2 or Name3)') 281 eq('Name1 or Name2 and Name3') 282 eq('(Name1 or Name2) and Name3') 283 eq('Name1 and Name2 or Name3 and Name4') 284 eq('Name1 or Name2 and Name3 or Name4') 285 eq('a + b + (c + d)') 286 eq('a * b * (c * d)') 287 eq('(a ** b) ** c ** d') 288 eq('v1 << 2') 289 eq('1 >> v2') 290 eq('1 % finished') 291 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') 292 eq('not great') 293 eq('not not great') 294 eq('~great') 295 eq('+value') 296 eq('++value') 297 eq('-1') 298 eq('~int and not v1 ^ 123 + v2 | True') 299 eq('a + (not b)') 300 eq('lambda: None') 301 eq('lambda arg: None') 302 eq('lambda a=True: a') 303 eq('lambda a, b, c=True: a') 304 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") 305 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b") 306 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b") 307 eq('lambda x, /: x') 308 eq('lambda x=1, /: x') 309 eq('lambda x, /, y: x + y') 310 eq('lambda x=1, /, y=2: x + y') 311 eq('lambda x, /, y=1: x + y') 312 eq('lambda x, /, y=1, *, z=3: x + y + z') 313 eq('lambda x=1, /, y=2, *, z=3: x + y + z') 314 eq('lambda x=1, /, y=2, *, z: x + y + z') 315 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2') 316 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2') 317 eq('lambda x, /, y=1, *, z: x + y + z') 318 eq('lambda x: lambda y: x + y') 319 eq('1 if True else 2') 320 eq('str or None if int or True else str or bytes or None') 321 eq('str or None if (1 if True else 2) else str or bytes or None') 322 eq("0 if not x else 1 if x > 0 else -1") 323 eq("(1 if x > 0 else -1) if x else 0") 324 eq("{'2.7': dead, '3.7': long_live or die_hard}") 325 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") 326 eq("{**a, **b, **c}") 327 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") 328 eq("{*a, *b, *c}") 329 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") 330 eq("()") 331 eq("(a,)") 332 eq("(a, b)") 333 eq("(a, b, c)") 334 eq("(*a, *b, *c)") 335 eq("[]") 336 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") 337 eq("[*a, *b, *c]") 338 eq("{i for i in (1, 2, 3)}") 339 eq("{i ** 2 for i in (1, 2, 3)}") 340 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") 341 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") 342 eq("[i for i in (1, 2, 3)]") 343 eq("[i ** 2 for i in (1, 2, 3)]") 344 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") 345 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") 346 eq("(i for i in (1, 2, 3))") 347 eq("(i ** 2 for i in (1, 2, 3))") 348 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") 349 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") 350 eq("{i: 0 for i in (1, 2, 3)}") 351 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") 352 eq("[(x, y) for x, y in (a, b)]") 353 eq("[(x,) for x, in (a,)]") 354 eq("Python3 > Python2 > COBOL") 355 eq("Life is Life") 356 eq("call()") 357 eq("call(arg)") 358 eq("call(kwarg='hey')") 359 eq("call(arg, kwarg='hey')") 360 eq("call(arg, *args, another, kwarg='hey')") 361 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") 362 eq("lukasz.langa.pl") 363 eq("call.me(maybe)") 364 eq("1 .real") 365 eq("1.0.real") 366 eq("....__class__") 367 eq("list[str]") 368 eq("dict[str, int]") 369 eq("set[str,]") 370 eq("tuple[()]") 371 eq("tuple[str, ...]") 372 eq("tuple[str, *types]") 373 eq("tuple[str, int, (str, int)]") 374 eq("tuple[*int, str, str, (str, int)]") 375 eq("tuple[str, int, float, dict[str, int]]") 376 eq("slice[0]") 377 eq("slice[0:1]") 378 eq("slice[0:1:2]") 379 eq("slice[:]") 380 eq("slice[:-1]") 381 eq("slice[1:]") 382 eq("slice[::-1]") 383 eq("slice[:,]") 384 eq("slice[1:2,]") 385 eq("slice[1:2:3,]") 386 eq("slice[1:2, 1]") 387 eq("slice[1:2, 2, 3]") 388 eq("slice[()]") 389 # Note that `slice[*Ts]`, `slice[*Ts,]`, and `slice[(*Ts,)]` all have 390 # the same AST, but only `slice[*Ts,]` passes this test, because that's 391 # what the unparser produces. 392 eq("slice[*Ts,]") 393 eq("slice[1, *Ts]") 394 eq("slice[*Ts, 2]") 395 eq("slice[1, *Ts, 2]") 396 eq("slice[*Ts, *Ts]") 397 eq("slice[1, *Ts, *Ts]") 398 eq("slice[*Ts, 1, *Ts]") 399 eq("slice[*Ts, *Ts, 1]") 400 eq("slice[1, *Ts, *Ts, 2]") 401 eq("slice[1:2, *Ts]") 402 eq("slice[*Ts, 1:2]") 403 eq("slice[1:2, *Ts, 3:4]") 404 eq("slice[a, b:c, d:e:f]") 405 eq("slice[(x for x in a)]") 406 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') 407 eq("f'f-string without formatted values is just a string'") 408 eq("f'{{NOT a formatted value}}'") 409 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") 410 eq('''f"{f'{nested} inner'} outer"''') 411 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") 412 eq("f'{(lambda x: x)}'") 413 eq("f'{(None if a else lambda x: x)}'") 414 eq("f'{x}'") 415 eq("f'{x!r}'") 416 eq("f'{x!a}'") 417 eq('[x for x in (a if b else c)]') 418 eq('[x for x in a if (b if c else d)]') 419 eq('f(x for x in a)') 420 eq('f(1, (x for x in a))') 421 eq('f((x for x in a), 2)') 422 eq('(((a)))', 'a') 423 eq('(((a, b)))', '(a, b)') 424 eq("1 + 2 + 3") 425 426 def test_fstring_debug_annotations(self): 427 # f-strings with '=' don't round trip very well, so set the expected 428 # result explicitly. 429 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") 430 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'") 431 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'") 432 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") 433 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'") 434 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'") 435 436 def test_infinity_numbers(self): 437 inf = "1e" + repr(sys.float_info.max_10_exp + 1) 438 infj = f"{inf}j" 439 self.assertAnnotationEqual("1e1000", expected=inf) 440 self.assertAnnotationEqual("1e1000j", expected=infj) 441 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}") 442 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}") 443 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})") 444 self.assertAnnotationEqual("'inf'") 445 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})") 446 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))") 447 448 def test_annotation_with_complex_target(self): 449 with self.assertRaises(SyntaxError): 450 exec( 451 "from __future__ import annotations\n" 452 "object.__debug__: int" 453 ) 454 455 def test_annotations_symbol_table_pass(self): 456 namespace = self._exec_future(dedent(""" 457 from __future__ import annotations 458 459 def foo(): 460 outer = 1 461 def bar(): 462 inner: outer = 1 463 return bar 464 """)) 465 466 foo = namespace.pop("foo") 467 self.assertIsNone(foo().__closure__) 468 self.assertEqual(foo.__code__.co_cellvars, ()) 469 self.assertEqual(foo().__code__.co_freevars, ()) 470 471 def test_annotations_forbidden(self): 472 with self.assertRaises(SyntaxError): 473 self._exec_future("test: (yield)") 474 475 with self.assertRaises(SyntaxError): 476 self._exec_future("test.test: (yield a + b)") 477 478 with self.assertRaises(SyntaxError): 479 self._exec_future("test[something]: (yield from x)") 480 481 with self.assertRaises(SyntaxError): 482 self._exec_future("def func(test: (yield from outside_of_generator)): pass") 483 484 with self.assertRaises(SyntaxError): 485 self._exec_future("def test() -> (await y): pass") 486 487 with self.assertRaises(SyntaxError): 488 self._exec_future("async def test() -> something((a := b)): pass") 489 490 with self.assertRaises(SyntaxError): 491 self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)") 492 493 with self.assertRaises(SyntaxError): 494 self._exec_future("test: f'{(x := 10):=10}'") 495 496 with self.assertRaises(SyntaxError): 497 self._exec_future(dedent("""\ 498 def foo(): 499 def bar(arg: (yield)): pass 500 """)) 501 502 def test_get_type_hints_on_func_with_variadic_arg(self): 503 # `typing.get_type_hints` might break on a function with a variadic 504 # annotation (e.g. `f(*args: *Ts)`) if `from __future__ import 505 # annotations`, because it could try to evaluate `*Ts` as an expression, 506 # which on its own isn't value syntax. 507 namespace = self._exec_future(dedent("""\ 508 class StarredC: pass 509 class C: 510 def __iter__(self): 511 yield StarredC() 512 c = C() 513 def f(*args: *c): pass 514 import typing 515 hints = typing.get_type_hints(f) 516 """)) 517 518 hints = namespace.pop('hints') 519 self.assertIsInstance(hints['args'], namespace['StarredC']) 520 521 522if __name__ == "__main__": 523 unittest.main() 524