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