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