blob: 3e6b709fb4f1e3f582cb2fa06c17455903da202a [file] [log] [blame]
Batuhan Taskaya044a1042020-10-06 23:03:02 +03001import unittest
2import sys
3from textwrap import dedent
4
5class PostponedAnnotationsTestCase(unittest.TestCase):
6 template = dedent(
7 """
8 def f() -> {ann}:
9 ...
10 def g(arg: {ann}) -> None:
11 ...
12 async def f2() -> {ann}:
13 ...
14 async def g2(arg: {ann}) -> None:
15 ...
16 var: {ann}
17 var2: {ann} = None
18 """
19 )
20
21 def getActual(self, annotation):
22 scope = {}
23 exec(self.template.format(ann=annotation), {}, scope)
24 func_ret_ann = scope['f'].__annotations__['return']
25 func_arg_ann = scope['g'].__annotations__['arg']
26 async_func_ret_ann = scope['f2'].__annotations__['return']
27 async_func_arg_ann = scope['g2'].__annotations__['arg']
28 var_ann1 = scope['__annotations__']['var']
29 var_ann2 = scope['__annotations__']['var2']
30 self.assertEqual(func_ret_ann, func_arg_ann)
31 self.assertEqual(func_ret_ann, async_func_ret_ann)
32 self.assertEqual(func_ret_ann, async_func_arg_ann)
33 self.assertEqual(func_ret_ann, var_ann1)
34 self.assertEqual(func_ret_ann, var_ann2)
35 return func_ret_ann
36
37 def assertAnnotationEqual(
38 self, annotation, expected=None, drop_parens=False, is_tuple=False,
39 ):
40 actual = self.getActual(annotation)
41 if expected is None:
42 expected = annotation if not is_tuple else annotation[1:-1]
43 if drop_parens:
44 self.assertNotEqual(actual, expected)
45 actual = actual.replace("(", "").replace(")", "")
46
47 self.assertEqual(actual, expected)
48
49 def test_annotations(self):
50 eq = self.assertAnnotationEqual
51 eq('...')
52 eq("'some_string'")
53 eq("u'some_string'")
54 eq("b'\\xa3'")
55 eq('Name')
56 eq('None')
57 eq('True')
58 eq('False')
59 eq('1')
60 eq('1.0')
61 eq('1j')
62 eq('True or False')
63 eq('True or False or None')
64 eq('True and False')
65 eq('True and False and None')
66 eq('Name1 and Name2 or Name3')
67 eq('Name1 and (Name2 or Name3)')
68 eq('Name1 or Name2 and Name3')
69 eq('(Name1 or Name2) and Name3')
70 eq('Name1 and Name2 or Name3 and Name4')
71 eq('Name1 or Name2 and Name3 or Name4')
72 eq('a + b + (c + d)')
73 eq('a * b * (c * d)')
74 eq('(a ** b) ** c ** d')
75 eq('v1 << 2')
76 eq('1 >> v2')
77 eq('1 % finished')
78 eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8')
79 eq('not great')
80 eq('not not great')
81 eq('~great')
82 eq('+value')
83 eq('++value')
84 eq('-1')
85 eq('~int and not v1 ^ 123 + v2 | True')
86 eq('a + (not b)')
87 eq('lambda: None')
88 eq('lambda arg: None')
89 eq('lambda a=True: a')
90 eq('lambda a, b, c=True: a')
91 eq("lambda a, b, c=True, *, d=1 << v2, e='str': a")
92 eq("lambda a, b, c=True, *vararg, d, e='str', **kwargs: a + b")
93 eq("lambda a, /, b, c=True, *vararg, d, e='str', **kwargs: a + b")
94 eq('lambda x, /: x')
95 eq('lambda x=1, /: x')
96 eq('lambda x, /, y: x + y')
97 eq('lambda x=1, /, y=2: x + y')
98 eq('lambda x, /, y=1: x + y')
99 eq('lambda x, /, y=1, *, z=3: x + y + z')
100 eq('lambda x=1, /, y=2, *, z=3: x + y + z')
101 eq('lambda x=1, /, y=2, *, z: x + y + z')
102 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2: x + y + z + w + l + l2')
103 eq('lambda x=1, y=2, z=3, /, w=4, *, l, l2, **kwargs: x + y + z + w + l + l2')
104 eq('lambda x, /, y=1, *, z: x + y + z')
105 eq('lambda x: lambda y: x + y')
106 eq('1 if True else 2')
107 eq('str or None if int or True else str or bytes or None')
108 eq('str or None if (1 if True else 2) else str or bytes or None')
109 eq("0 if not x else 1 if x > 0 else -1")
110 eq("(1 if x > 0 else -1) if x else 0")
111 eq("{'2.7': dead, '3.7': long_live or die_hard}")
112 eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}")
113 eq("{**a, **b, **c}")
114 eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}")
115 eq("{*a, *b, *c}")
116 eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None")
117 eq("()")
118 eq("(a,)")
119 eq("(a, b)")
120 eq("(a, b, c)")
121 eq("(*a, *b, *c)")
122 eq("[]")
123 eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]")
124 eq("[*a, *b, *c]")
125 eq("{i for i in (1, 2, 3)}")
126 eq("{i ** 2 for i in (1, 2, 3)}")
127 eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}")
128 eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}")
129 eq("[i for i in (1, 2, 3)]")
130 eq("[i ** 2 for i in (1, 2, 3)]")
131 eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]")
132 eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]")
133 eq("(i for i in (1, 2, 3))")
134 eq("(i ** 2 for i in (1, 2, 3))")
135 eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))")
136 eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
137 eq("{i: 0 for i in (1, 2, 3)}")
138 eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
139 eq("[(x, y) for x, y in (a, b)]")
140 eq("[(x,) for x, in (a,)]")
141 eq("Python3 > Python2 > COBOL")
142 eq("Life is Life")
143 eq("call()")
144 eq("call(arg)")
145 eq("call(kwarg='hey')")
146 eq("call(arg, kwarg='hey')")
147 eq("call(arg, *args, another, kwarg='hey')")
148 eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')")
149 eq("lukasz.langa.pl")
150 eq("call.me(maybe)")
151 eq("1 .real")
152 eq("1.0.real")
153 eq("....__class__")
154 eq("list[str]")
155 eq("dict[str, int]")
156 eq("set[str,]")
157 eq("tuple[str, ...]")
158 eq("tuple[(str, *types)]")
159 eq("tuple[str, int, (str, int)]")
160 eq("tuple[(*int, str, str, (str, int))]")
161 eq("tuple[str, int, float, dict[str, int]]")
162 eq("slice[0]")
163 eq("slice[0:1]")
164 eq("slice[0:1:2]")
165 eq("slice[:]")
166 eq("slice[:-1]")
167 eq("slice[1:]")
168 eq("slice[::-1]")
169 eq("slice[:,]")
170 eq("slice[1:2,]")
171 eq("slice[1:2:3,]")
172 eq("slice[1:2, 1]")
173 eq("slice[1:2, 2, 3]")
174 eq("slice[()]")
175 eq("slice[a, b:c, d:e:f]")
176 eq("slice[(x for x in a)]")
177 eq('str or None if sys.version_info[0] > (3,) else str or bytes or None')
178 eq("f'f-string without formatted values is just a string'")
179 eq("f'{{NOT a formatted value}}'")
180 eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'")
181 eq('''f"{f'{nested} inner'} outer"''')
182 eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'")
183 eq("f'{(lambda x: x)}'")
184 eq("f'{(None if a else lambda x: x)}'")
185 eq("f'{x}'")
186 eq("f'{x!r}'")
187 eq("f'{x!a}'")
188 eq('(yield from outside_of_generator)')
189 eq('(yield)')
190 eq('(yield a + b)')
191 eq('await some.complicated[0].call(with_args=True or 1 is not 1)')
192 eq('[x for x in (a if b else c)]')
193 eq('[x for x in a if (b if c else d)]')
194 eq('f(x for x in a)')
195 eq('f(1, (x for x in a))')
196 eq('f((x for x in a), 2)')
197 eq('(((a)))', 'a')
198 eq('(((a, b)))', '(a, b)')
199 eq("(x := 10)")
200 eq("f'{(x := 10):=10}'")
201 eq("1 + 2")
202 eq("1 + 2 + 3")
203
204 def test_fstring_debug_annotations(self):
205 # f-strings with '=' don't round trip very well, so set the expected
206 # result explicitely.
207 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
208 self.assertAnnotationEqual("f'{x=:}'", expected="f'x={x:}'")
209 self.assertAnnotationEqual("f'{x=:.2f}'", expected="f'x={x:.2f}'")
210 self.assertAnnotationEqual("f'{x=!r}'", expected="f'x={x!r}'")
211 self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'")
212 self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'")
213
214 def test_infinity_numbers(self):
215 inf = "1e" + repr(sys.float_info.max_10_exp + 1)
216 infj = f"{inf}j"
217 self.assertAnnotationEqual("1e1000", expected=inf)
218 self.assertAnnotationEqual("1e1000j", expected=infj)
219 self.assertAnnotationEqual("-1e1000", expected=f"-{inf}")
220 self.assertAnnotationEqual("3+1e1000j", expected=f"3 + {infj}")
221 self.assertAnnotationEqual("(1e1000, 1e1000j)", expected=f"({inf}, {infj})")
222 self.assertAnnotationEqual("'inf'")
223 self.assertAnnotationEqual("('inf', 1e1000, 'infxxx', 1e1000j)", expected=f"('inf', {inf}, 'infxxx', {infj})")
224 self.assertAnnotationEqual("(1e1000, (1e1000j,))", expected=f"({inf}, ({infj},))")
225
226
227if __name__ == "__main__":
228 unittest.main()