File: annotate-basic.test

package info (click to toggle)
mypy 1.19.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,412 kB
  • sloc: python: 114,754; ansic: 13,343; cpp: 11,380; makefile: 257; sh: 28
file content (477 lines) | stat: -rw-r--r-- 12,204 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
[case testAnnotateNonNativeAttribute]
from typing import Any

def f1(x):
    return x.foo  # A: Get non-native attribute "foo".

def f2(x: Any) -> object:
    return x.foo  # A: Get non-native attribute "foo".

def f3(x):
    x.bar = 1  # A: Set non-native attribute "bar".

class C:
    foo: int

    def method(self) -> int:
        return self.foo

def good1(x: C) -> int:
    return x.foo

[case testAnnotateMethod]
class C:
    def method(self, x):
        return x + "y"  # A: Generic "+" operation.

[case testAnnotateGenericBinaryOperations]
def generic_add(x):
    return x + 1  # A: Generic "+" operation.

def generic_sub(x):
    return x - 1  # A: Generic "-" operation.

def generic_mul(x):
    return x * 1  # A: Generic "*" operation.

def generic_div(x):
    return x / 1  # A: Generic "/" operation.

def generic_floor_div(x):
    return x // 1  # A: Generic "//" operation.

def generic_unary_plus(x):
    return +x  # A: Generic unary "+" operation.

def generic_unary_minus(x):
    return -x  # A: Generic unary "-" operation.

def native_int_ops(x: int, y: int) -> int:
    a = x + 1 - y
    return x * a // y

[case testAnnotateGenericBitwiseOperations]
def generic_and(x):
    return x & 1  # A: Generic "&" operation.

def generic_or(x):
    return x | 1  # A: Generic "|" operation.

def generic_xor(x):
    return x ^ 1  # A: Generic "^" operation.

def generic_left_shift(x):
    return x << 1  # A: Generic "<<" operation.

def generic_right_shift(x):
    return x >> 1  # A: Generic ">>" operation.

def generic_invert(x):
    return ~x  # A: Generic "~" operation.

def native_int_ops(x: int, y: int) -> int:
    a = (x & 1) << y
    return (x | a) >> (y ^ 1)

[case testAnnotateGenericComparisonOperations]
def generic_eq(x, y):
    return x == y  # A: Generic comparison operation.

def generic_ne(x, y):
    return x != y  # A: Generic comparison operation.

def generic_lt(x, y):
    return x < y  # A: Generic comparison operation.

def generic_le(x, y):
    return x <= y  # A: Generic comparison operation.

def generic_gt(x, y):
    return x > y  # A: Generic comparison operation.

def generic_ge(x, y):
    return x >= y  # A: Generic comparison operation.

def int_comparisons(x: int, y: int) -> int:
    if x == y:
        return 0
    if x < y:
        return 1
    if x > y:
        return 2
    return 3

[case testAnnotateTwoOperationsOnLine]
def f(x):
    return x.foo + 1  # A: Get non-native attribute "foo". Generic "+" operation.

[case testAnnotateNonNativeMethod]
from typing import Any

def f1(x):
    return x.foo()  # A: Call non-native method "foo" (it may be defined in a non-native class, or decorated).

def f2(x: Any) -> None:
    x.foo(1)  # A: Call non-native method "foo" (it may be defined in a non-native class, or decorated).
    x.foo(a=1)  # A: Call non-native method "foo" (it may be defined in a non-native class, or decorated).
    t = (1, 'x')
    x.foo(*t)  # A: Get non-native attribute "foo". Generic call operation.
    d = {"a": 1}
    x.foo(*d)  # A: Get non-native attribute "foo". Generic call operation.

class C:
    def foo(self) -> int:
        return 0

def g(c: C) -> int:
    return c.foo()

[case testAnnotateGlobalVariableAccess]
from typing import Final
import nonnative

x = 0
y: Final = 0

def read() -> int:
    return x  # A: Access global "x" through namespace dictionary (hint: access is faster if you can make it Final).

def assign(a: int) -> None:
    global x
    x = a  # A: Access global "x" through namespace dictionary (hint: access is faster if you can make it Final).

def read_final() -> int:
    return y

def read_nonnative() -> int:
    return nonnative.z  # A: Get non-native attribute "z".

[file nonnative.py]
z = 2

[case testAnnotateNestedFunction]
def f1() -> None:
    def g() -> None:  # A: A nested function object is allocated each time statement is executed. A module-level function would be faster.
        pass

    g()

def f2() -> int:
    l = lambda: 1  # A: A new object is allocated for lambda each time it is evaluated. A module-level function would be faster.
    return l()

[case testAnnotateGetSetItem]
from typing import List, Dict

def f1(x, y):
    return x[y]  # A: Generic indexing operation.

def f2(x, y, z):
    x[y] = z  # A: Generic indexed assignment.

def list_get_item(x: List[int], y: int) -> int:
    return x[y]

def list_set_item(x: List[int], y: int) -> None:
    x[y] = 5

def dict_get_item(d: Dict[str, str]) -> str:
    return d['x']

def dict_set_item(d: Dict[str, str]) -> None:
    d['x'] = 'y'

[case testAnnotateStrMethods]
def startswith(x: str) -> bool:
    return x.startswith('foo')

def islower(x: str) -> bool:
    return x.islower()  # A: Call non-native method "islower" (it may be defined in a non-native class, or decorated).

[case testAnnotateSpecificStdlibFeatures]
import functools
import itertools
from functools import partial
from itertools import chain, groupby, islice

def f(x: int, y: int) -> None: pass

def use_partial1() -> None:
    p = partial(f, 1)  # A: "functools.partial" is inefficient in compiled code.
    p(2)

def use_partial2() -> None:
    p = functools.partial(f, 1)  # A: "functools.partial" is inefficient in compiled code.
    p(2)

def use_chain1() -> None:
    for x in chain([1, 3], [4, 5]):  # A: "itertools.chain" is inefficient in compiled code (hint: replace with for loops).
        pass

def use_chain2() -> None:
    for x in itertools.chain([1, 3], [4, 5]):  # A: "itertools.chain" is inefficient in compiled code (hint: replace with for loops).
        pass

def use_groupby1() -> None:
    for a, b in groupby([('A', 'B')]):  # A: "itertools.groupby" is inefficient in compiled code.
        pass

def use_groupby2() -> None:
    for a, b in itertools.groupby([('A', 'B')]):  # A: "itertools.groupby" is inefficient in compiled code.
        pass

def use_islice() -> None:
    for x in islice([1, 2, 3], 1, 2):  # A: "itertools.islice" is inefficient in compiled code (hint: replace with for loop over index range).
        pass

[case testAnnotateGenericForLoop]
from typing import Iterable, Sequence, Iterator, List

def f1(a):
    for x in a:  # A: For loop uses generic operations (iterable has type "Any").
        pass

def f2(a: Iterable[str]) -> None:
    for x in a:  # A: For loop uses generic operations (iterable has the abstract type "typing.Iterable").
        pass

def f3(a: Sequence[str]) -> None:
    for x in a:  # A: For loop uses generic operations (iterable has the abstract type "typing.Sequence").
        pass

def f4(a: Iterator[str]) -> None:
    for x in a:  # A: For loop uses generic operations (iterable has the abstract type "typing.Iterator").
        pass

def good1(a: List[str]) -> None:
    for x in a:
        pass

class C:
    def __iter__(self) -> Iterator[str]:
        assert False

def good2(a: List[str]) -> None:
    for x in a:
        pass

[case testAnnotateGenericComprehensionOrGenerator]
from typing import List, Iterable

def f1(a):
    return [x for x in a]  # A: Comprehension or generator uses generic operations (iterable has type "Any").

def f2(a: Iterable[int]):
    return {x for x in a}  # A: Comprehension or generator uses generic operations (iterable has the abstract type "typing.Iterable").

def f3(a):
    return {x: 1 for x in a}  # A: Comprehension uses generic operations (iterable has type "Any").

def f4(a):
    return (x for x in a)  # A: Comprehension or generator uses generic operations (iterable has type "Any").

def good1(a: List[int]) -> List[int]:
    return [x + 1 for x in a]

[case testAnnotateIsinstance]
from typing import Protocol, runtime_checkable, Union

@runtime_checkable
class P(Protocol):
    def foo(self) -> None: ...

class C: pass

class D(C):
    def bar(self) -> None: pass

def bad1(x: object) -> bool:
    return isinstance(x, P)  # A: Expensive isinstance() check against protocol "P".

def bad2(x: object) -> bool:
    return isinstance(x, (str, P))  # A: Expensive isinstance() check against protocol "P".

def good1(x: C) -> bool:
    if isinstance(x, D):
        x.bar()
    return isinstance(x, D)

def good2(x: Union[int, str]) -> int:
    if isinstance(x, int):
        return x + 1
    else:
        return int(x + "1")
[typing fixtures/typing-full.pyi]

[case testAnnotateDeepcopy]
from typing import Any
import copy

def f(x: Any) -> Any:
    return copy.deepcopy(x)  # A: "copy.deepcopy" tends to be slow. Make a shallow copy if possible.

[case testAnnotateContextManager]
from typing import Iterator
from contextlib import contextmanager

@contextmanager
def slow_ctx_manager() -> Iterator[None]:
    yield

class FastCtxManager:
    def __enter__(self) -> None: pass
    def __exit__(self, a, b, c) -> None: pass

def f1(x) -> None:
    with slow_ctx_manager():  # A: "slow_ctx_manager" uses @contextmanager, which is slow in compiled code. Use a native class with "__enter__" and "__exit__" methods instead.
        x.foo  # A: Get non-native attribute "foo".

def f2(x) -> None:
    with FastCtxManager():
        x.foo  # A: Get non-native attribute "foo".

[case testAnnotateAvoidNoiseAtTopLevel]
from typing import Final

class C(object):
    x = "s"
    y: Final = 1

x = "s"
y: Final = 1

def f1() -> None:
    x = object  # A: Get non-native attribute "object".

[case testAnnotateCreateNonNativeInstance]
from typing import NamedTuple
from dataclasses import dataclass

from nonnative import C

def f1() -> None:
    c = C()  # A: Creating an instance of non-native class "C" is slow.
    c.foo()  # A: Call non-native method "foo" (it may be defined in a non-native class, or decorated).

class NT(NamedTuple):
    x: int
    y: str

def f2() -> int:
    o = NT(1, "x")  # A: Creating an instance of non-native class "NT" is slow.
    return o.x

def f3() -> int:
    o = NT(x=1, y="x")  # A: Creating an instance of non-native class "NT" is slow.
    a, b = o
    return a

@dataclass
class D:
    x: int

def f4() -> int:
    o = D(1)  # A: Class "D" is only partially native, and constructing an instance is slow.
    return o.x

class Nat:
    x: int

class Deriv(Nat):
    def __init__(self, y: int) -> None:
        self.y = y

def good1() -> int:
    n = Nat()
    d = Deriv(y=1)
    return n.x + d.x + d.y

[file nonnative.py]
class C:
    def foo(self) -> None: pass

[case testAnnotateGetAttrAndSetAttrBuiltins]
def f1(x, s: str):
    return getattr("x", s)  # A: Dynamic attribute lookup.

def f2(x, s: str):
    setattr(x, s, None)  # A: Dynamic attribute set.

[case testAnnotateSpecialAssignments]
from typing import TypeVar, NamedTuple, List, TypedDict, NewType

# Even though these are slow, we don't complain about them since there is generally
# no better way (and at module top level these are very unlikely to be bottlenecks)
A = List[int]
T = TypeVar("T", bound=List[int])
NT = NamedTuple("NT", [("x", List[int])])
TD = TypedDict("TD", {"x": List[int]})
New = NewType("New", List[int])
[typing fixtures/typing-full.pyi]

[case testAnnotateCallDecoratedNativeFunctionOrMethod]
from typing import TypeVar, Callable, Any

F = TypeVar("F", bound=Callable[..., Any])

def mydeco(f: F) -> F:
    return f

@mydeco
def d(x: int) -> int:
    return x

def f1() -> int:
    return d(1)  # A: Calling a decorated function ("d") is inefficient, even if it's native.

class C:
    @mydeco
    def d(self) -> None:
        pass


def f2() -> None:
    c = C()
    c.d()  # A: Call non-native method "d" (it may be defined in a non-native class, or decorated).

[case testAnnotateCallDifferentKindsOfMethods]
from abc import ABC, abstractmethod

class C:
    @staticmethod
    def s() -> None: ...

    @classmethod
    def c(cls) -> None: ...

    @property
    def p(self) -> int:
        return 0

    @property
    def p2(self) -> int:
        return 0

    @p2.setter
    def p2(self, x: int) -> None:
        pass

def f1() -> int:
    c = C()
    c.s()
    c.c()
    c.p2 = 1
    return c.p + c.p2

class A(ABC):
    @abstractmethod
    def m(self) -> int:
        raise NotImplementedError  # A: Get non-native attribute "NotImplementedError".

class D(A):
    def m(self) -> int:
        return 1

def f2() -> int:
    d = D()
    return d.m()