1# Test various flavors of legal and illegal future statements 2 3import __future__ 4import ast 5import unittest 6from test import support 7from textwrap import dedent 8import os 9import re 10import sys 11 12rx = re.compile(r'\((\S+).py, line (\d+)') 13 14def get_error_location(msg): 15 mo = rx.search(str(msg)) 16 return mo.group(1, 2) 17 18class FutureTest(unittest.TestCase): 19 20 def check_syntax_error(self, err, basename, lineno, offset=1): 21 self.assertIn('%s.py, line %d' % (basename, lineno), str(err)) 22 self.assertEqual(os.path.basename(err.filename), basename + '.py') 23 self.assertEqual(err.lineno, lineno) 24 self.assertEqual(err.offset, offset) 25 26 def test_future1(self): 27 with support.CleanImport('future_test1'): 28 from test import future_test1 29 self.assertEqual(future_test1.result, 6) 30 31 def test_future2(self): 32 with support.CleanImport('future_test2'): 33 from test import future_test2 34 self.assertEqual(future_test2.result, 6) 35 36 def test_future3(self): 37 with support.CleanImport('test_future3'): 38 from test import test_future3 39 40 def test_badfuture3(self): 41 with self.assertRaises(SyntaxError) as cm: 42 from test import badsyntax_future3 43 self.check_syntax_error(cm.exception, "badsyntax_future3", 3) 44 45 def test_badfuture4(self): 46 with self.assertRaises(SyntaxError) as cm: 47 from test import badsyntax_future4 48 self.check_syntax_error(cm.exception, "badsyntax_future4", 3) 49 50 def test_badfuture5(self): 51 with self.assertRaises(SyntaxError) as cm: 52 from test import badsyntax_future5 53 self.check_syntax_error(cm.exception, "badsyntax_future5", 4) 54 55 def test_badfuture6(self): 56 with self.assertRaises(SyntaxError) as cm: 57 from test import badsyntax_future6 58 self.check_syntax_error(cm.exception, "badsyntax_future6", 3) 59 60 def test_badfuture7(self): 61 with self.assertRaises(SyntaxError) as cm: 62 from test import badsyntax_future7 63 self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53) 64 65 def test_badfuture8(self): 66 with self.assertRaises(SyntaxError) as cm: 67 from test import badsyntax_future8 68 self.check_syntax_error(cm.exception, "badsyntax_future8", 3) 69 70 def test_badfuture9(self): 71 with self.assertRaises(SyntaxError) as cm: 72 from test import badsyntax_future9 73 self.check_syntax_error(cm.exception, "badsyntax_future9", 3) 74 75 def test_badfuture10(self): 76 with self.assertRaises(SyntaxError) as cm: 77 from test import badsyntax_future10 78 self.check_syntax_error(cm.exception, "badsyntax_future10", 3) 79 80 def test_ensure_flags_dont_clash(self): 81 # bpo-39562: test that future flags and compiler flags doesn't clash 82 83 # obtain future flags (CO_FUTURE_***) from the __future__ module 84 flags = { 85 f"CO_FUTURE_{future.upper()}": getattr(__future__, future).compiler_flag 86 for future in __future__.all_feature_names 87 } 88 # obtain some of the exported compiler flags (PyCF_***) from the ast module 89 flags |= { 90 flag: getattr(ast, flag) 91 for flag in dir(ast) if flag.startswith("PyCF_") 92 } 93 self.assertCountEqual(set(flags.values()), flags.values()) 94 95 def test_parserhack(self): 96 # test that the parser.c::future_hack function works as expected 97 # Note: although this test must pass, it's not testing the original 98 # bug as of 2.6 since the with statement is not optional and 99 # the parser hack disabled. If a new keyword is introduced in 100 # 2.6, change this to refer to the new future import. 101 try: 102 exec("from __future__ import print_function; print 0") 103 except SyntaxError: 104 pass 105 else: 106 self.fail("syntax error didn't occur") 107 108 try: 109 exec("from __future__ import (print_function); print 0") 110 except SyntaxError: 111 pass 112 else: 113 self.fail("syntax error didn't occur") 114 115 def test_multiple_features(self): 116 with support.CleanImport("test.test_future5"): 117 from test import test_future5 118 119 def test_unicode_literals_exec(self): 120 scope = {} 121 exec("from __future__ import unicode_literals; x = ''", {}, scope) 122 self.assertIsInstance(scope["x"], str) 123 124class AnnotationsFutureTestCase(unittest.TestCase): 125 template = dedent( 126 """ 127 from __future__ import annotations 128 def f() -> {ann}: 129 ... 130 def g(arg: {ann}) -> None: 131 ... 132 async def f2() -> {ann}: 133 ... 134 async def g2(arg: {ann}) -> None: 135 ... 136 var: {ann} 137 var2: {ann} = None 138 """ 139 ) 140 141 def getActual(self, annotation): 142 scope = {} 143 exec(self.template.format(ann=annotation), {}, scope) 144 func_ret_ann = scope['f'].__annotations__['return'] 145 func_arg_ann = scope['g'].__annotations__['arg'] 146 async_func_ret_ann = scope['f2'].__annotations__['return'] 147 async_func_arg_ann = scope['g2'].__annotations__['arg'] 148 var_ann1 = scope['__annotations__']['var'] 149 var_ann2 = scope['__annotations__']['var2'] 150 self.assertEqual(func_ret_ann, func_arg_ann) 151 self.assertEqual(func_ret_ann, async_func_ret_ann) 152 self.assertEqual(func_ret_ann, async_func_arg_ann) 153 self.assertEqual(func_ret_ann, var_ann1) 154 self.assertEqual(func_ret_ann, var_ann2) 155 return func_ret_ann 156 157 def assertAnnotationEqual( 158 self, annotation, expected=None, drop_parens=False, is_tuple=False, 159 ): 160 actual = self.getActual(annotation) 161 if expected is None: 162 expected = annotation if not is_tuple else annotation[1:-1] 163 if drop_parens: 164 self.assertNotEqual(actual, expected) 165 actual = actual.replace("(", "").replace(")", "") 166 167 self.assertEqual(actual, expected) 168 169 def test_annotations(self): 170 eq = self.assertAnnotationEqual 171 eq('...') 172 eq("'some_string'") 173 eq("u'some_string'") 174 eq("b'\\xa3'") 175 eq('Name') 176 eq('None') 177 eq('True') 178 eq('False') 179 eq('1') 180 eq('1.0') 181 eq('1j') 182 eq('True or False') 183 eq('True or False or None') 184 eq('True and False') 185 eq('True and False and None') 186 eq('Name1 and Name2 or Name3') 187 eq('Name1 and (Name2 or Name3)') 188 eq('Name1 or Name2 and Name3') 189 eq('(Name1 or Name2) and Name3') 190 eq('Name1 and Name2 or Name3 and Name4') 191 eq('Name1 or Name2 and Name3 or Name4') 192 eq('a + b + (c + d)') 193 eq('a * b * (c * d)') 194 eq('(a ** b) ** c ** d') 195 eq('v1 << 2') 196 eq('1 >> v2') 197 eq('1 % finished') 198 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') 199 eq('not great') 200 eq('not not great') 201 eq('~great') 202 eq('+value') 203 eq('++value') 204 eq('-1') 205 eq('~int and not v1 ^ 123 + v2 | True') 206 eq('a + (not b)') 207 eq('lambda: None') 208 eq('lambda arg: None') 209 eq('lambda a=True: a') 210 eq('lambda a, b, c=True: a') 211 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") 212 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b") 213 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b") 214 eq('lambda x, /: x') 215 eq('lambda x=1, /: x') 216 eq('lambda x, /, y: x + y') 217 eq('lambda x=1, /, y=2: x + y') 218 eq('lambda x, /, y=1: x + y') 219 eq('lambda x, /, y=1, *, z=3: x + y + z') 220 eq('lambda x=1, /, y=2, *, z=3: x + y + z') 221 eq('lambda x=1, /, y=2, *, z: x + y + z') 222 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2') 223 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2') 224 eq('lambda x, /, y=1, *, z: x + y + z') 225 eq('lambda x: lambda y: x + y') 226 eq('1 if True else 2') 227 eq('str or None if int or True else str or bytes or None') 228 eq('str or None if (1 if True else 2) else str or bytes or None') 229 eq("0 if not x else 1 if x > 0 else -1") 230 eq("(1 if x > 0 else -1) if x else 0") 231 eq("{'2.7': dead, '3.7': long_live or die_hard}") 232 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") 233 eq("{**a, **b, **c}") 234 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") 235 eq("{*a, *b, *c}") 236 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") 237 eq("()") 238 eq("(a,)") 239 eq("(a, b)") 240 eq("(a, b, c)") 241 eq("(*a, *b, *c)") 242 eq("[]") 243 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") 244 eq("[*a, *b, *c]") 245 eq("{i for i in (1, 2, 3)}") 246 eq("{i ** 2 for i in (1, 2, 3)}") 247 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") 248 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") 249 eq("[i for i in (1, 2, 3)]") 250 eq("[i ** 2 for i in (1, 2, 3)]") 251 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") 252 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") 253 eq("(i for i in (1, 2, 3))") 254 eq("(i ** 2 for i in (1, 2, 3))") 255 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") 256 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") 257 eq("{i: 0 for i in (1, 2, 3)}") 258 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") 259 eq("[(x, y) for x, y in (a, b)]") 260 eq("[(x,) for x, in (a,)]") 261 eq("Python3 > Python2 > COBOL") 262 eq("Life is Life") 263 eq("call()") 264 eq("call(arg)") 265 eq("call(kwarg='hey')") 266 eq("call(arg, kwarg='hey')") 267 eq("call(arg, *args, another, kwarg='hey')") 268 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") 269 eq("lukasz.langa.pl") 270 eq("call.me(maybe)") 271 eq("1 .real") 272 eq("1.0.real") 273 eq("....__class__") 274 eq("list[str]") 275 eq("dict[str, int]") 276 eq("set[str,]") 277 eq("tuple[str, ...]") 278 eq("tuple[(str, *types)]") 279 eq("tuple[str, int, (str, int)]") 280 eq("tuple[(*int, str, str, (str, int))]") 281 eq("tuple[str, int, float, dict[str, int]]") 282 eq("slice[0]") 283 eq("slice[0:1]") 284 eq("slice[0:1:2]") 285 eq("slice[:]") 286 eq("slice[:-1]") 287 eq("slice[1:]") 288 eq("slice[::-1]") 289 eq("slice[:,]") 290 eq("slice[1:2,]") 291 eq("slice[1:2:3,]") 292 eq("slice[1:2, 1]") 293 eq("slice[1:2, 2, 3]") 294 eq("slice[()]") 295 eq("slice[a, b:c, d:e:f]") 296 eq("slice[(x for x in a)]") 297 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') 298 eq("f'f-string without formatted values is just a string'") 299 eq("f'{{NOT a formatted value}}'") 300 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") 301 eq('''f"{f'{nested} inner'} outer"''') 302 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") 303 eq("f'{(lambda x: x)}'") 304 eq("f'{(None if a else lambda x: x)}'") 305 eq("f'{x}'") 306 eq("f'{x!r}'") 307 eq("f'{x!a}'") 308 eq('(yield from outside_of_generator)') 309 eq('(yield)') 310 eq('(yield a + b)') 311 eq('await some.complicated[0].call(with_args=True or 1 is not 1)') 312 eq('[x for x in (a if b else c)]') 313 eq('[x for x in a if (b if c else d)]') 314 eq('f(x for x in a)') 315 eq('f(1, (x for x in a))') 316 eq('f((x for x in a), 2)') 317 eq('(((a)))', 'a') 318 eq('(((a, b)))', '(a, b)') 319 eq("(x := 10)") 320 eq("f'{(x := 10):=10}'") 321 eq("1 + 2 + 3") 322 323 def test_fstring_debug_annotations(self): 324 # f-strings with '=' don't round trip very well, so set the expected 325 # result explicitely. 326 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") 327 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'") 328 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'") 329 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'") 330 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'") 331 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'") 332 333 def test_infinity_numbers(self): 334 inf = "1e" + repr(sys.float_info.max_10_exp + 1) 335 infj = f"{inf}j" 336 self.assertAnnotationEqual("1e1000", expected=inf) 337 self.assertAnnotationEqual("1e1000j", expected=infj) 338 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}") 339 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}") 340 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})") 341 self.assertAnnotationEqual("'inf'") 342 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})") 343 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))") 344 345 346if __name__ == "__main__": 347 unittest.main() 348