Skip to content

Commit

Permalink
Sync typeshed (#17246)
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed May 15, 2024
1 parent 35fbd2a commit b4f9869
Show file tree
Hide file tree
Showing 59 changed files with 2,469 additions and 143 deletions.
25 changes: 25 additions & 0 deletions mypy/typeshed/stdlib/@tests/test_cases/asyncio/check_coroutines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from __future__ import annotations

from asyncio import iscoroutinefunction
from collections.abc import Awaitable, Callable, Coroutine
from typing import Any
from typing_extensions import assert_type


def test_iscoroutinefunction(
x: Callable[[str, int], Coroutine[str, int, bytes]],
y: Callable[[str, int], Awaitable[bytes]],
z: Callable[[str, int], str | Awaitable[bytes]],
xx: object,
) -> None:
if iscoroutinefunction(x):
assert_type(x, Callable[[str, int], Coroutine[str, int, bytes]])

if iscoroutinefunction(y):
assert_type(y, Callable[[str, int], Coroutine[Any, Any, bytes]])

if iscoroutinefunction(z):
assert_type(z, Callable[[str, int], Coroutine[Any, Any, Any]])

if iscoroutinefunction(xx):
assert_type(xx, Callable[..., Coroutine[Any, Any, Any]])
38 changes: 38 additions & 0 deletions mypy/typeshed/stdlib/@tests/test_cases/asyncio/check_gather.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from __future__ import annotations

import asyncio
from typing import Awaitable, List, Tuple, Union
from typing_extensions import assert_type


async def coro1() -> int:
return 42


async def coro2() -> str:
return "spam"


async def test_gather(awaitable1: Awaitable[int], awaitable2: Awaitable[str]) -> None:
a = await asyncio.gather(awaitable1)
assert_type(a, Tuple[int])

b = await asyncio.gather(awaitable1, awaitable2, return_exceptions=True)
assert_type(b, Tuple[Union[int, BaseException], Union[str, BaseException]])

c = await asyncio.gather(awaitable1, awaitable2, awaitable1, awaitable1, awaitable1, awaitable1)
assert_type(c, Tuple[int, str, int, int, int, int])

d = await asyncio.gather(awaitable1, awaitable1, awaitable1, awaitable1, awaitable1, awaitable1, awaitable1)
assert_type(d, List[int])

awaitables_list: list[Awaitable[int]] = [awaitable1]
e = await asyncio.gather(*awaitables_list)
assert_type(e, List[int])

# this case isn't reliable between typecheckers, no one would ever call it with no args anyway
# f = await asyncio.gather()
# assert_type(f, list[Any])


asyncio.run(test_gather(coro1(), coro2()))
28 changes: 28 additions & 0 deletions mypy/typeshed/stdlib/@tests/test_cases/asyncio/check_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from __future__ import annotations

import asyncio


class Waiter:
def __init__(self) -> None:
self.tasks: list[asyncio.Task[object]] = []

def add(self, t: asyncio.Task[object]) -> None:
self.tasks.append(t)

async def join(self) -> None:
await asyncio.wait(self.tasks)


async def foo() -> int:
return 42


async def main() -> None:
# asyncio.Task is covariant in its type argument, which is unusual since its parent class
# asyncio.Future is invariant in its type argument. This is only sound because asyncio.Task
# is not actually Liskov substitutable for asyncio.Future: it does not implement set_result.
w = Waiter()
t: asyncio.Task[int] = asyncio.create_task(foo())
w.add(t)
await w.join()
67 changes: 67 additions & 0 deletions mypy/typeshed/stdlib/@tests/test_cases/builtins/check_dict-py39.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
Tests for `dict.__(r)or__`.
`dict.__or__` and `dict.__ror__` were only added in py39,
hence why these are in a separate file to the other test cases for `dict`.
"""

from __future__ import annotations

import os
import sys
from typing import Mapping, TypeVar, Union
from typing_extensions import Self, assert_type

_KT = TypeVar("_KT")
_VT = TypeVar("_VT")

if sys.version_info >= (3, 9):

class CustomDictSubclass(dict[_KT, _VT]):
pass

class CustomMappingWithDunderOr(Mapping[_KT, _VT]):
def __or__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
return {}

def __ror__(self, other: Mapping[_KT, _VT]) -> dict[_KT, _VT]:
return {}

def __ior__(self, other: Mapping[_KT, _VT]) -> Self:
return self

def test_dict_dot_or(
a: dict[int, int],
b: CustomDictSubclass[int, int],
c: dict[str, str],
d: Mapping[int, int],
e: CustomMappingWithDunderOr[str, str],
) -> None:
# dict.__(r)or__ always returns a dict, even if called on a subclass of dict:
assert_type(a | b, dict[int, int])
assert_type(b | a, dict[int, int])

assert_type(a | c, dict[Union[int, str], Union[int, str]])

# arbitrary mappings are not accepted by `dict.__or__`;
# it has to be a subclass of `dict`
a | d # type: ignore

# but Mappings such as `os._Environ` or `CustomMappingWithDunderOr`,
# which define `__ror__` methods that accept `dict`, are fine:
assert_type(a | os.environ, dict[Union[str, int], Union[str, int]])
assert_type(os.environ | a, dict[Union[str, int], Union[str, int]])

assert_type(c | os.environ, dict[str, str])
assert_type(c | e, dict[str, str])

assert_type(os.environ | c, dict[str, str])
assert_type(e | c, dict[str, str])

e |= c
e |= a # type: ignore

# TODO: this test passes mypy, but fails pyright for some reason:
# c |= e

c |= a # type: ignore
58 changes: 58 additions & 0 deletions mypy/typeshed/stdlib/@tests/test_cases/builtins/check_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from __future__ import annotations

from typing import Dict, Generic, Iterable, TypeVar
from typing_extensions import assert_type

# These do follow `__init__` overloads order:
# mypy and pyright have different opinions about this one:
# mypy raises: 'Need type annotation for "bad"'
# pyright is fine with it.
# bad = dict()
good: dict[str, str] = dict()
assert_type(good, Dict[str, str])

assert_type(dict(arg=1), Dict[str, int])

_KT = TypeVar("_KT")
_VT = TypeVar("_VT")


class KeysAndGetItem(Generic[_KT, _VT]):
data: dict[_KT, _VT]

def __init__(self, data: dict[_KT, _VT]) -> None:
self.data = data

def keys(self) -> Iterable[_KT]:
return self.data.keys()

def __getitem__(self, __k: _KT) -> _VT:
return self.data[__k]


kt1: KeysAndGetItem[int, str] = KeysAndGetItem({0: ""})
assert_type(dict(kt1), Dict[int, str])
dict(kt1, arg="a") # type: ignore

kt2: KeysAndGetItem[str, int] = KeysAndGetItem({"": 0})
assert_type(dict(kt2, arg=1), Dict[str, int])


def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str]:
return dict(x)


i1: Iterable[tuple[int, str]] = [(1, "a"), (2, "b")]
test_iterable_tuple_overload(i1)
dict(i1, arg="a") # type: ignore

i2: Iterable[tuple[str, int]] = [("a", 1), ("b", 2)]
assert_type(dict(i2, arg=1), Dict[str, int])

i3: Iterable[str] = ["a.b"]
i4: Iterable[bytes] = [b"a.b"]
assert_type(dict(string.split(".") for string in i3), Dict[str, str])
assert_type(dict(string.split(b".") for string in i4), Dict[bytes, bytes])

dict(["foo", "bar", "baz"]) # type: ignore
dict([b"foo", b"bar", b"baz"]) # type: ignore
Loading

0 comments on commit b4f9869

Please sign in to comment.