Skip to content

Sync typeshed #17246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading