Skip to content

Commit b4f9869

Browse files
Sync typeshed (#17246)
Source commit: python/typeshed@a9d7e86
1 parent 35fbd2a commit b4f9869

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2469
-143
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from __future__ import annotations
2+
3+
from asyncio import iscoroutinefunction
4+
from collections.abc import Awaitable, Callable, Coroutine
5+
from typing import Any
6+
from typing_extensions import assert_type
7+
8+
9+
def test_iscoroutinefunction(
10+
x: Callable[[str, int], Coroutine[str, int, bytes]],
11+
y: Callable[[str, int], Awaitable[bytes]],
12+
z: Callable[[str, int], str | Awaitable[bytes]],
13+
xx: object,
14+
) -> None:
15+
if iscoroutinefunction(x):
16+
assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]])
17+
18+
if iscoroutinefunction(y):
19+
assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]])
20+
21+
if iscoroutinefunction(z):
22+
assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]])
23+
24+
if iscoroutinefunction(xx):
25+
assert_type(xx, Callable[..., Coroutine[Any, Any, Any]])
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from __future__ import annotations
2+
3+
import asyncio
4+
from typing import Awaitable, List, Tuple, Union
5+
from typing_extensions import assert_type
6+
7+
8+
async def coro1() -> int:
9+
return 42
10+
11+
12+
async def coro2() -> str:
13+
return "spam"
14+
15+
16+
async def test_gather(awaitable1: Awaitable[int], awaitable2: Awaitable[str]) -> None:
17+
a = await asyncio.gather(awaitable1)
18+
assert_type(a, Tuple[int])
19+
20+
b = await asyncio.gather(awaitable1, awaitable2, return_exceptions=True)
21+
assert_type(b, Tuple[Union[int, BaseException], Union[str, BaseException]])
22+
23+
c = await asyncio.gather(awaitable1, awaitable2, awaitable1, awaitable1, awaitable1, awaitable1)
24+
assert_type(c, Tuple[int, str, int, int, int, int])
25+
26+
d = await asyncio.gather(awaitable1, awaitable1, awaitable1, awaitable1, awaitable1, awaitable1, awaitable1)
27+
assert_type(d, List[int])
28+
29+
awaitables_list: list[Awaitable[int]] = [awaitable1]
30+
e = await asyncio.gather(*awaitables_list)
31+
assert_type(e, List[int])
32+
33+
# this case isn't reliable between typecheckers, no one would ever call it with no args anyway
34+
# f = await asyncio.gather()
35+
# assert_type(f, list[Any])
36+
37+
38+
asyncio.run(test_gather(coro1(), coro2()))
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from __future__ import annotations
2+
3+
import asyncio
4+
5+
6+
class Waiter:
7+
def __init__(self) -> None:
8+
self.tasks: list[asyncio.Task[object]] = []
9+
10+
def add(self, t: asyncio.Task[object]) -> None:
11+
self.tasks.append(t)
12+
13+
async def join(self) -> None:
14+
await asyncio.wait(self.tasks)
15+
16+
17+
async def foo() -> int:
18+
return 42
19+
20+
21+
async def main() -> None:
22+
# asyncio.Task is covariant in its type argument, which is unusual since its parent class
23+
# asyncio.Future is invariant in its type argument. This is only sound because asyncio.Task
24+
# is not actually Liskov substitutable for asyncio.Future: it does not implement set_result.
25+
w = Waiter()
26+
t: asyncio.Task[int] = asyncio.create_task(foo())
27+
w.add(t)
28+
await w.join()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
Tests for `dict.__(r)or__`.
3+
4+
`dict.__or__` and `dict.__ror__` were only added in py39,
5+
hence why these are in a separate file to the other test cases for `dict`.
6+
"""
7+
8+
from __future__ import annotations
9+
10+
import os
11+
import sys
12+
from typing import Mapping, TypeVar, Union
13+
from typing_extensions import Self, assert_type
14+
15+
_KT = TypeVar("_KT")
16+
_VT = TypeVar("_VT")
17+
18+
if sys.version_info >= (3, 9):
19+
20+
class CustomDictSubclass(dict[_KT, _VT]):
21+
pass
22+
23+
class CustomMappingWithDunderOr(Mapping[_KT, _VT]):
24+
def __or__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
25+
return {}
26+
27+
def __ror__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
28+
return {}
29+
30+
def __ior__(self, other: Mapping[_KT, _VT]) -> Self:
31+
return self
32+
33+
def test_dict_dot_or(
34+
a: dict[int, int],
35+
b: CustomDictSubclass[int, int],
36+
c: dict[str, str],
37+
d: Mapping[int, int],
38+
e: CustomMappingWithDunderOr[str, str],
39+
) -> None:
40+
# dict.__(r)or__ always returns a dict, even if called on a subclass of dict:
41+
assert_type(a | b, dict[int, int])
42+
assert_type(b | a, dict[int, int])
43+
44+
assert_type(a | c, dict[Union[int, str], Union[int, str]])
45+
46+
# arbitrary mappings are not accepted by `dict.__or__`;
47+
# it has to be a subclass of `dict`
48+
a | d # type: ignore
49+
50+
# but Mappings such as `os._Environ` or `CustomMappingWithDunderOr`,
51+
# which define `__ror__` methods that accept `dict`, are fine:
52+
assert_type(a | os.environ, dict[Union[str, int], Union[str, int]])
53+
assert_type(os.environ | a, dict[Union[str, int], Union[str, int]])
54+
55+
assert_type(c | os.environ, dict[str, str])
56+
assert_type(c | e, dict[str, str])
57+
58+
assert_type(os.environ | c, dict[str, str])
59+
assert_type(e | c, dict[str, str])
60+
61+
e |= c
62+
e |= a # type: ignore
63+
64+
# TODO: this test passes mypy, but fails pyright for some reason:
65+
# c |= e
66+
67+
c |= a # type: ignore
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from __future__ import annotations
2+
3+
from typing import Dict, Generic, Iterable, TypeVar
4+
from typing_extensions import assert_type
5+
6+
# These do follow `__init__` overloads order:
7+
# mypy and pyright have different opinions about this one:
8+
# mypy raises: 'Need type annotation for "bad"'
9+
# pyright is fine with it.
10+
# bad = dict()
11+
good: dict[str, str] = dict()
12+
assert_type(good, Dict[str, str])
13+
14+
assert_type(dict(arg=1), Dict[str, int])
15+
16+
_KT = TypeVar("_KT")
17+
_VT = TypeVar("_VT")
18+
19+
20+
class KeysAndGetItem(Generic[_KT, _VT]):
21+
data: dict[_KT, _VT]
22+
23+
def __init__(self, data: dict[_KT, _VT]) -> None:
24+
self.data = data
25+
26+
def keys(self) -> Iterable[_KT]:
27+
return self.data.keys()
28+
29+
def __getitem__(self, __k: _KT) -> _VT:
30+
return self.data[__k]
31+
32+
33+
kt1: KeysAndGetItem[int, str] = KeysAndGetItem({0: ""})
34+
assert_type(dict(kt1), Dict[int, str])
35+
dict(kt1, arg="a") # type: ignore
36+
37+
kt2: KeysAndGetItem[str, int] = KeysAndGetItem({"": 0})
38+
assert_type(dict(kt2, arg=1), Dict[str, int])
39+
40+
41+
def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str]:
42+
return dict(x)
43+
44+
45+
i1: Iterable[tuple[int, str]] = [(1, "a"), (2, "b")]
46+
test_iterable_tuple_overload(i1)
47+
dict(i1, arg="a") # type: ignore
48+
49+
i2: Iterable[tuple[str, int]] = [("a", 1), ("b", 2)]
50+
assert_type(dict(i2, arg=1), Dict[str, int])
51+
52+
i3: Iterable[str] = ["a.b"]
53+
i4: Iterable[bytes] = [b"a.b"]
54+
assert_type(dict(string.split(".") for string in i3), Dict[str, str])
55+
assert_type(dict(string.split(b".") for string in i4), Dict[bytes, bytes])
56+
57+
dict(["foo", "bar", "baz"]) # type: ignore
58+
dict([b"foo", b"bar", b"baz"]) # type: ignore

0 commit comments

Comments
 (0)