python (3.11.7)

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