blob: 70da0cf57040603c1cbf43261da3be0eec9a7c13 [file] [log] [blame]
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00001# Test various flavors of legal and illegal future statements
2
Guido van Rossum95e4d582018-01-26 08:20:18 -08003from functools import partial
Neal Norwitz328f3382003-12-13 22:43:34 +00004import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Guido van Rossum95e4d582018-01-26 08:20:18 -08006from textwrap import dedent
Serhiy Storchaka8b583392016-12-11 14:39:01 +02007import os
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +00008import re
9
R David Murray44b548d2016-09-08 13:59:53 -040010rx = re.compile(r'\((\S+).py, line (\d+)')
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000011
Neal Norwitz328f3382003-12-13 22:43:34 +000012def get_error_location(msg):
13 mo = rx.search(str(msg))
14 return mo.group(1, 2)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000015
Neal Norwitz328f3382003-12-13 22:43:34 +000016class FutureTest(unittest.TestCase):
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000017
Serhiy Storchaka8b583392016-12-11 14:39:01 +020018 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
Neal Norwitz328f3382003-12-13 22:43:34 +000024 def test_future1(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020025 with support.CleanImport('future_test1'):
26 from test import future_test1
27 self.assertEqual(future_test1.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000028
Neal Norwitz328f3382003-12-13 22:43:34 +000029 def test_future2(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020030 with support.CleanImport('future_test2'):
31 from test import future_test2
32 self.assertEqual(future_test2.result, 6)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000033
Neal Norwitz328f3382003-12-13 22:43:34 +000034 def test_future3(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020035 with support.CleanImport('test_future3'):
36 from test import test_future3
Jeremy Hylton8471a352001-08-20 20:33:42 +000037
Neal Norwitz328f3382003-12-13 22:43:34 +000038 def test_badfuture3(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020039 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000040 from test import badsyntax_future3
Serhiy Storchaka8b583392016-12-11 14:39:01 +020041 self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000042
Neal Norwitz328f3382003-12-13 22:43:34 +000043 def test_badfuture4(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020044 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000045 from test import badsyntax_future4
Serhiy Storchaka8b583392016-12-11 14:39:01 +020046 self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000047
Neal Norwitz328f3382003-12-13 22:43:34 +000048 def test_badfuture5(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020049 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000050 from test import badsyntax_future5
Serhiy Storchaka8b583392016-12-11 14:39:01 +020051 self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000052
Neal Norwitz328f3382003-12-13 22:43:34 +000053 def test_badfuture6(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020054 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000055 from test import badsyntax_future6
Serhiy Storchaka8b583392016-12-11 14:39:01 +020056 self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
Jeremy Hylton62e2c7e2001-02-28 17:48:06 +000057
Neal Norwitz328f3382003-12-13 22:43:34 +000058 def test_badfuture7(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020059 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000060 from test import badsyntax_future7
Serhiy Storchaka8b583392016-12-11 14:39:01 +020061 self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
Neal Norwitz328f3382003-12-13 22:43:34 +000062
63 def test_badfuture8(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020064 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000065 from test import badsyntax_future8
Serhiy Storchaka8b583392016-12-11 14:39:01 +020066 self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
Neal Norwitz328f3382003-12-13 22:43:34 +000067
68 def test_badfuture9(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020069 with self.assertRaises(SyntaxError) as cm:
Neal Norwitz328f3382003-12-13 22:43:34 +000070 from test import badsyntax_future9
Serhiy Storchaka8b583392016-12-11 14:39:01 +020071 self.check_syntax_error(cm.exception, "badsyntax_future9", 3, 0)
Neal Norwitz328f3382003-12-13 22:43:34 +000072
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070073 def test_badfuture10(self):
Serhiy Storchaka8b583392016-12-11 14:39:01 +020074 with self.assertRaises(SyntaxError) as cm:
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070075 from test import badsyntax_future10
Serhiy Storchaka8b583392016-12-11 14:39:01 +020076 self.check_syntax_error(cm.exception, "badsyntax_future10", 3, 0)
Benjamin Peterson2d6acd22013-03-16 09:15:47 -070077
Thomas Wouters89f507f2006-12-13 04:49:30 +000078 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:
Benjamin Peterson9aebc612008-10-26 20:58:53 +000085 exec("from __future__ import print_function; print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +000086 except SyntaxError:
87 pass
88 else:
89 self.fail("syntax error didn't occur")
90
91 try:
Benjamin Peterson9aebc612008-10-26 20:58:53 +000092 exec("from __future__ import (print_function); print 0")
Thomas Wouters89f507f2006-12-13 04:49:30 +000093 except SyntaxError:
94 pass
95 else:
96 self.fail("syntax error didn't occur")
97
Benjamin Peterson9aebc612008-10-26 20:58:53 +000098 def test_multiple_features(self):
Ezio Melotti1ed6be32013-02-27 10:00:03 +020099 with support.CleanImport("test.test_future5"):
100 from test import test_future5
Benjamin Peterson9aebc612008-10-26 20:58:53 +0000101
Benjamin Petersonf216c942008-10-31 02:28:05 +0000102 def test_unicode_literals_exec(self):
103 scope = {}
104 exec("from __future__ import unicode_literals; x = ''", {}, scope)
Ezio Melottie9615932010-01-24 19:26:24 +0000105 self.assertIsInstance(scope["x"], str)
Benjamin Petersonf216c942008-10-31 02:28:05 +0000106
Guido van Rossum95e4d582018-01-26 08:20:18 -0800107class 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')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300160 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')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800169 eq('v1 << 2')
170 eq('1 >> v2')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300171 eq('1 % finished')
172 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800173 eq('not great')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300174 eq('not not great')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800175 eq('~great')
176 eq('+value')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300177 eq('++value')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800178 eq('-1')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300179 eq('~int and not v1 ^ 123 + v2 | True')
180 eq('a + (not b)')
Miss Islington (bot)0f161b32018-09-30 11:19:15 -0700181 eq('lambda: None')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800182 eq('lambda arg: None')
183 eq('lambda a=True: a')
184 eq('lambda a, b, c=True: a')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300185 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
Miss Islington (bot)0f161b32018-09-30 11:19:15 -0700186 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300187 eq('lambda x: lambda y: x + y')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800188 eq('1 if True else 2')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300189 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}}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800195 eq("{**a, **b, **c}")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300196 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")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800199 eq("()")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300200 eq("(a,)")
201 eq("(a, b)")
202 eq("(a, b, c)")
203 eq("(*a, *b, *c)")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800204 eq("[]")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300205 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
206 eq("[*a, *b, *c]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800207 eq("{i for i in (1, 2, 3)}")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300208 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)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800211 eq("[i for i in (1, 2, 3)]")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300212 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)}")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800220 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300221 eq("[(x, y) for x, y in (a, b)]")
222 eq("[(x,) for x, in (a,)]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800223 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')")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300229 eq("call(arg, *args, another, kwarg='hey')")
230 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800231 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]")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300238 eq("set[str,]")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800239 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]")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300248 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')
Guido van Rossum95e4d582018-01-26 08:20:18 -0800252 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)}}'")
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300257 eq("f'{(lambda x: x)}'")
258 eq("f'{(None if a else lambda x: x)}'")
Guido van Rossum95e4d582018-01-26 08:20:18 -0800259 eq('(yield from outside_of_generator)')
260 eq('(yield)')
Serhiy Storchakab32f8892018-05-20 18:06:08 +0300261 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)')
Thomas Wouters89f507f2006-12-13 04:49:30 +0000270
Neal Norwitz328f3382003-12-13 22:43:34 +0000271
272if __name__ == "__main__":
Ezio Melotti1ed6be32013-02-27 10:00:03 +0200273 unittest.main()