(root)/
Python-3.12.0/
Lib/
test/
test_future.py
       1  # Test various flavors of legal and illegal future statements
       2  
       3  import __future__
       4  import ast
       5  import unittest
       6  from test.support import import_helper
       7  from test.support.script_helper import spawn_python, kill_python
       8  from textwrap import dedent
       9  import os
      10  import re
      11  import sys
      12  
      13  rx = re.compile(r'\((\S+).py, line (\d+)')
      14  
      15  def get_error_location(msg):
      16      mo = rx.search(str(msg))
      17      return mo.group(1, 2)
      18  
      19  class ESC[4;38;5;81mFutureTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      20  
      21      def check_syntax_error(self, err, basename, lineno, offset=1):
      22          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  
      27      def test_future1(self):
      28          with import_helper.CleanImport('future_test1'):
      29              from test import future_test1
      30              self.assertEqual(future_test1.result, 6)
      31  
      32      def test_future2(self):
      33          with import_helper.CleanImport('future_test2'):
      34              from test import future_test2
      35              self.assertEqual(future_test2.result, 6)
      36  
      37      def test_future3(self):
      38          with import_helper.CleanImport('test_future3'):
      39              from test import test_future3
      40  
      41      def test_badfuture3(self):
      42          with self.assertRaises(SyntaxError) as cm:
      43              from test import badsyntax_future3
      44          self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
      45  
      46      def test_badfuture4(self):
      47          with self.assertRaises(SyntaxError) as cm:
      48              from test import badsyntax_future4
      49          self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
      50  
      51      def test_badfuture5(self):
      52          with self.assertRaises(SyntaxError) as cm:
      53              from test import badsyntax_future5
      54          self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
      55  
      56      def test_badfuture6(self):
      57          with self.assertRaises(SyntaxError) as cm:
      58              from test import badsyntax_future6
      59          self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
      60  
      61      def test_badfuture7(self):
      62          with self.assertRaises(SyntaxError) as cm:
      63              from test import badsyntax_future7
      64          self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 54)
      65  
      66      def test_badfuture8(self):
      67          with self.assertRaises(SyntaxError) as cm:
      68              from test import badsyntax_future8
      69          self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
      70  
      71      def test_badfuture9(self):
      72          with self.assertRaises(SyntaxError) as cm:
      73              from test import badsyntax_future9
      74          self.check_syntax_error(cm.exception, "badsyntax_future9", 3)
      75  
      76      def test_badfuture10(self):
      77          with self.assertRaises(SyntaxError) as cm:
      78              from test import badsyntax_future10
      79          self.check_syntax_error(cm.exception, "badsyntax_future10", 3)
      80  
      81      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  
      96      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:
     103              exec("from __future__ import print_function; print 0")
     104          except SyntaxError:
     105              pass
     106          else:
     107              self.fail("syntax error didn't occur")
     108  
     109          try:
     110              exec("from __future__ import (print_function); print 0")
     111          except SyntaxError:
     112              pass
     113          else:
     114              self.fail("syntax error didn't occur")
     115  
     116      def test_multiple_features(self):
     117          with import_helper.CleanImport("test.test_future5"):
     118              from test import test_future5
     119  
     120      def test_unicode_literals_exec(self):
     121          scope = {}
     122          exec("from __future__ import unicode_literals; x = ''", {}, scope)
     123          self.assertIsInstance(scope["x"], str)
     124  
     125      def test_syntactical_future_repl(self):
     126          p = spawn_python('-i')
     127          p.stdin.write(b"from __future__ import barry_as_FLUFL\n")
     128          p.stdin.write(b"2 <> 3\n")
     129          out = kill_python(p)
     130          self.assertNotIn(b'SyntaxError: invalid syntax', out)
     131  
     132  class ESC[4;38;5;81mAnnotationsFutureTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     133      template = dedent(
     134          """
     135          from __future__ import annotations
     136          def f() -> {ann}:
     137              ...
     138          def g(arg: {ann}) -> None:
     139              ...
     140          async def f2() -> {ann}:
     141              ...
     142          async def g2(arg: {ann}) -> None:
     143              ...
     144          class H:
     145              var: {ann}
     146              object.attr: {ann}
     147          var: {ann}
     148          var2: {ann} = None
     149          object.attr: {ann}
     150          """
     151      )
     152  
     153      def getActual(self, annotation):
     154          scope = {}
     155          exec(self.template.format(ann=annotation), {}, scope)
     156          func_ret_ann = scope['f'].__annotations__['return']
     157          func_arg_ann = scope['g'].__annotations__['arg']
     158          async_func_ret_ann = scope['f2'].__annotations__['return']
     159          async_func_arg_ann = scope['g2'].__annotations__['arg']
     160          var_ann1 = scope['__annotations__']['var']
     161          var_ann2 = scope['__annotations__']['var2']
     162          self.assertEqual(func_ret_ann, func_arg_ann)
     163          self.assertEqual(func_ret_ann, async_func_ret_ann)
     164          self.assertEqual(func_ret_ann, async_func_arg_ann)
     165          self.assertEqual(func_ret_ann, var_ann1)
     166          self.assertEqual(func_ret_ann, var_ann2)
     167          return func_ret_ann
     168  
     169      def assertAnnotationEqual(
     170          self, annotation, expected=None, drop_parens=False, is_tuple=False,
     171      ):
     172          actual = self.getActual(annotation)
     173          if expected is None:
     174              expected = annotation if not is_tuple else annotation[1:-1]
     175          if drop_parens:
     176              self.assertNotEqual(actual, expected)
     177              actual = actual.replace("(", "").replace(")", "")
     178  
     179          self.assertEqual(actual, expected)
     180  
     181      def _exec_future(self, code):
     182          scope = {}
     183          exec(
     184              "from __future__ import annotations\n"
     185              + code, scope
     186          )
     187          return scope
     188  
     189      def test_annotations(self):
     190          eq = self.assertAnnotationEqual
     191          eq('...')
     192          eq("'some_string'")
     193          eq("u'some_string'")
     194          eq("b'\\xa3'")
     195          eq('Name')
     196          eq('None')
     197          eq('True')
     198          eq('False')
     199          eq('1')
     200          eq('1.0')
     201          eq('1j')
     202          eq('True or False')
     203          eq('True or False or None')
     204          eq('True and False')
     205          eq('True and False and None')
     206          eq('Name1 and Name2 or Name3')
     207          eq('Name1 and (Name2 or Name3)')
     208          eq('Name1 or Name2 and Name3')
     209          eq('(Name1 or Name2) and Name3')
     210          eq('Name1 and Name2 or Name3 and Name4')
     211          eq('Name1 or Name2 and Name3 or Name4')
     212          eq('a + b + (c + d)')
     213          eq('a * b * (c * d)')
     214          eq('(a ** b) ** c ** d')
     215          eq('v1 << 2')
     216          eq('1 >> v2')
     217          eq('1 % finished')
     218          eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
     219          eq('not great')
     220          eq('not not great')
     221          eq('~great')
     222          eq('+value')
     223          eq('++value')
     224          eq('-1')
     225          eq('~int and not v1 ^ 123 + v2 | True')
     226          eq('a + (not b)')
     227          eq('lambda: None')
     228          eq('lambda arg: None')
     229          eq('lambda a=True: a')
     230          eq('lambda a, b, c=True: a')
     231          eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
     232          eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
     233          eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
     234          eq('lambda x, /: x')
     235          eq('lambda x=1, /: x')
     236          eq('lambda x, /, y: x + y')
     237          eq('lambda x=1, /, y=2: x + y')
     238          eq('lambda x, /, y=1: x + y')
     239          eq('lambda x, /, y=1, *, z=3: x + y + z')
     240          eq('lambda x=1, /, y=2, *, z=3: x + y + z')
     241          eq('lambda x=1, /, y=2, *, z: x + y + z')
     242          eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
     243          eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
     244          eq('lambda x, /, y=1, *, z: x + y + z')
     245          eq('lambda x: lambda y: x + y')
     246          eq('1 if True else 2')
     247          eq('str or None if int or True else str or bytes or None')
     248          eq('str or None if (1 if True else 2) else str or bytes or None')
     249          eq("0 if not x else 1 if x > 0 else -1")
     250          eq("(1 if x > 0 else -1) if x else 0")
     251          eq("{'2.7': dead, '3.7': long_live or die_hard}")
     252          eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
     253          eq("{**a, **b, **c}")
     254          eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
     255          eq("{*a, *b, *c}")
     256          eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
     257          eq("()")
     258          eq("(a,)")
     259          eq("(a, b)")
     260          eq("(a, b, c)")
     261          eq("(*a, *b, *c)")
     262          eq("[]")
     263          eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
     264          eq("[*a, *b, *c]")
     265          eq("{i for i in (1, 2, 3)}")
     266          eq("{i ** 2 for i in (1, 2, 3)}")
     267          eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
     268          eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
     269          eq("[i for i in (1, 2, 3)]")
     270          eq("[i ** 2 for i in (1, 2, 3)]")
     271          eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
     272          eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
     273          eq("(i for i in (1, 2, 3))")
     274          eq("(i ** 2 for i in (1, 2, 3))")
     275          eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
     276          eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
     277          eq("{i: 0 for i in (1, 2, 3)}")
     278          eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
     279          eq("[(x, y) for x, y in (a, b)]")
     280          eq("[(x,) for x, in (a,)]")
     281          eq("Python3 > Python2 > COBOL")
     282          eq("Life is Life")
     283          eq("call()")
     284          eq("call(arg)")
     285          eq("call(kwarg='hey')")
     286          eq("call(arg, kwarg='hey')")
     287          eq("call(arg, *args, another, kwarg='hey')")
     288          eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
     289          eq("lukasz.langa.pl")
     290          eq("call.me(maybe)")
     291          eq("1 .real")
     292          eq("1.0.real")
     293          eq("....__class__")
     294          eq("list[str]")
     295          eq("dict[str, int]")
     296          eq("set[str,]")
     297          eq("tuple[()]")
     298          eq("tuple[str, ...]")
     299          eq("tuple[str, *types]")
     300          eq("tuple[str, int, (str, int)]")
     301          eq("tuple[*int, str, str, (str, int)]")
     302          eq("tuple[str, int, float, dict[str, int]]")
     303          eq("slice[0]")
     304          eq("slice[0:1]")
     305          eq("slice[0:1:2]")
     306          eq("slice[:]")
     307          eq("slice[:-1]")
     308          eq("slice[1:]")
     309          eq("slice[::-1]")
     310          eq("slice[:,]")
     311          eq("slice[1:2,]")
     312          eq("slice[1:2:3,]")
     313          eq("slice[1:2, 1]")
     314          eq("slice[1:2, 2, 3]")
     315          eq("slice[()]")
     316          # Note that `slice[*Ts]`, `slice[*Ts,]`, and `slice[(*Ts,)]` all have
     317          # the same AST, but only `slice[*Ts,]` passes this test, because that's
     318          # what the unparser produces.
     319          eq("slice[*Ts,]")
     320          eq("slice[1, *Ts]")
     321          eq("slice[*Ts, 2]")
     322          eq("slice[1, *Ts, 2]")
     323          eq("slice[*Ts, *Ts]")
     324          eq("slice[1, *Ts, *Ts]")
     325          eq("slice[*Ts, 1, *Ts]")
     326          eq("slice[*Ts, *Ts, 1]")
     327          eq("slice[1, *Ts, *Ts, 2]")
     328          eq("slice[1:2, *Ts]")
     329          eq("slice[*Ts, 1:2]")
     330          eq("slice[1:2, *Ts, 3:4]")
     331          eq("slice[a, b:c, d:e:f]")
     332          eq("slice[(x for x in a)]")
     333          eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
     334          eq("f'f-string without formatted values is just a string'")
     335          eq("f'{{NOT a formatted value}}'")
     336          eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
     337          eq('''f"{f'{nested} inner'} outer"''')
     338          eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
     339          eq("f'{(lambda x: x)}'")
     340          eq("f'{(None if a else lambda x: x)}'")
     341          eq("f'{x}'")
     342          eq("f'{x!r}'")
     343          eq("f'{x!a}'")
     344          eq('[x for x in (a if b else c)]')
     345          eq('[x for x in a if (b if c else d)]')
     346          eq('f(x for x in a)')
     347          eq('f(1, (x for x in a))')
     348          eq('f((x for x in a), 2)')
     349          eq('(((a)))', 'a')
     350          eq('(((a, b)))', '(a, b)')
     351          eq("1 + 2 + 3")
     352  
     353      def test_fstring_debug_annotations(self):
     354          # f-strings with '=' don't round trip very well, so set the expected
     355          # result explicitly.
     356          self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
     357          self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
     358          self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
     359          self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
     360          self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
     361          self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
     362  
     363      def test_infinity_numbers(self):
     364          inf = "1e" + repr(sys.float_info.max_10_exp + 1)
     365          infj = f"{inf}j"
     366          self.assertAnnotationEqual("1e1000", expected=inf)
     367          self.assertAnnotationEqual("1e1000j", expected=infj)
     368          self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
     369          self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
     370          self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
     371          self.assertAnnotationEqual("'inf'")
     372          self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
     373          self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
     374  
     375      def test_annotation_with_complex_target(self):
     376          with self.assertRaises(SyntaxError):
     377              exec(
     378                  "from __future__ import annotations\n"
     379                  "object.__debug__: int"
     380              )
     381  
     382      def test_annotations_symbol_table_pass(self):
     383          namespace = self._exec_future(dedent("""
     384          from __future__ import annotations
     385  
     386          def foo():
     387              outer = 1
     388              def bar():
     389                  inner: outer = 1
     390              return bar
     391          """))
     392  
     393          foo = namespace.pop("foo")
     394          self.assertIsNone(foo().__closure__)
     395          self.assertEqual(foo.__code__.co_cellvars, ())
     396          self.assertEqual(foo().__code__.co_freevars, ())
     397  
     398      def test_annotations_forbidden(self):
     399          with self.assertRaises(SyntaxError):
     400              self._exec_future("test: (yield)")
     401  
     402          with self.assertRaises(SyntaxError):
     403              self._exec_future("test.test: (yield a + b)")
     404  
     405          with self.assertRaises(SyntaxError):
     406              self._exec_future("test[something]: (yield from x)")
     407  
     408          with self.assertRaises(SyntaxError):
     409              self._exec_future("def func(test: (yield from outside_of_generator)): pass")
     410  
     411          with self.assertRaises(SyntaxError):
     412              self._exec_future("def test() -> (await y): pass")
     413  
     414          with self.assertRaises(SyntaxError):
     415              self._exec_future("async def test() -> something((a := b)): pass")
     416  
     417          with self.assertRaises(SyntaxError):
     418              self._exec_future("test: await some.complicated[0].call(with_args=True or 1 is not 1)")
     419  
     420          with self.assertRaises(SyntaxError):
     421              self._exec_future("test: f'{(x := 10):=10}'")
     422  
     423          with self.assertRaises(SyntaxError):
     424              self._exec_future(dedent("""\
     425              def foo():
     426                  def bar(arg: (yield)): pass
     427              """))
     428  
     429      def test_get_type_hints_on_func_with_variadic_arg(self):
     430          # `typing.get_type_hints` might break on a function with a variadic
     431          # annotation (e.g. `f(*args: *Ts)`) if `from __future__ import
     432          # annotations`, because it could try to evaluate `*Ts` as an expression,
     433          # which on its own isn't value syntax.
     434          namespace = self._exec_future(dedent("""\
     435          class StarredC: pass
     436          class C:
     437            def __iter__(self):
     438              yield StarredC()
     439          c = C()
     440          def f(*args: *c): pass
     441          import typing
     442          hints = typing.get_type_hints(f)
     443          """))
     444  
     445          hints = namespace.pop('hints')
     446          self.assertIsInstance(hints['args'], namespace['StarredC'])
     447  
     448  
     449  if __name__ == "__main__":
     450      unittest.main()