Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 5 additions & 3 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2126,7 +2126,9 @@ def check_argument_types(
if actual_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(
actual_type
):
is_mapping = is_subtype(actual_type, self.chk.named_type("typing.Mapping"))
is_mapping = is_subtype(
actual_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem")
)
self.msg.invalid_keyword_var_arg(actual_type, is_mapping, context)
expanded_actual = mapper.expand_actual_type(
actual_type, actual_kind, callee.arg_names[i], callee_arg_kind
Expand Down Expand Up @@ -4936,14 +4938,14 @@ def is_valid_keyword_var_arg(self, typ: Type) -> bool:
is_subtype(
typ,
self.chk.named_generic_type(
"typing.Mapping",
"_typeshed.SupportsKeysAndGetItem",
[self.named_type("builtins.str"), AnyType(TypeOfAny.special_form)],
),
)
or is_subtype(
typ,
self.chk.named_generic_type(
"typing.Mapping", [UninhabitedType(), UninhabitedType()]
"_typeshed.SupportsKeysAndGetItem", [UninhabitedType(), UninhabitedType()]
),
)
or isinstance(typ, ParamSpecType)
Expand Down
6 changes: 6 additions & 0 deletions mypy/test/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ def parse_test_case(case: DataDrivenTestCase) -> None:
src_path = join(os.path.dirname(case.file), item.arg)
with open(src_path, encoding="utf8") as f:
files.append((join(base_path, "typing.pyi"), f.read()))
elif item.id == "_typeshed":
# Use an alternative stub file for the typing module.
Comment thread
bryanforbes marked this conversation as resolved.
Outdated
assert item.arg is not None
src_path = join(os.path.dirname(case.file), item.arg)
with open(src_path, encoding="utf8") as f:
files.append((join(base_path, "_typeshed.pyi"), f.read()))
elif re.match(r"stale[0-9]*$", item.id):
passnum = 1 if item.id == "stale" else int(item.id[len("stale") :])
assert passnum > 0
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/check-generic-subtyping.test
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ main:13: note: Revealed type is "builtins.dict[builtins.int, builtins.str]"
main:14: error: Keywords must be strings
main:14: error: Argument 1 to "func_with_kwargs" has incompatible type "**X1[str, int]"; expected "int"
[builtins fixtures/dict.pyi]
[typing fixtures/typing-medium.pyi]

[case testSubtypingMappingUnpacking3]
from typing import Generic, TypeVar, Mapping, Iterable
Expand Down
16 changes: 8 additions & 8 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -3699,8 +3699,8 @@ cache_fine_grained = False
[file mypy.ini.2]
\[mypy]
cache_fine_grained = True
[rechecked a, builtins, typing]
[stale a, builtins, typing]
[rechecked _typeshed, a, builtins, typing]
[stale _typeshed, a, builtins, typing]
[builtins fixtures/tuple.pyi]

[case testIncrementalPackageNameOverload]
Expand Down Expand Up @@ -3751,8 +3751,8 @@ Signature: 8a477f597d28d172789f06886806bc55
[file b.py.2]
# uh
-- Every file should get reloaded, since the cache was invalidated
[stale a, b, builtins, typing]
[rechecked a, b, builtins, typing]
[stale _typeshed, a, b, builtins, typing]
[rechecked _typeshed, a, b, builtins, typing]
[builtins fixtures/tuple.pyi]

[case testIncrementalBustedFineGrainedCache2]
Expand All @@ -3764,8 +3764,8 @@ import b
[file b.py.2]
# uh
-- Every file should get reloaded, since the settings changed
[stale a, b, builtins, typing]
[rechecked a, b, builtins, typing]
[stale _typeshed, a, b, builtins, typing]
[rechecked _typeshed, a, b, builtins, typing]
[builtins fixtures/tuple.pyi]

[case testIncrementalBustedFineGrainedCache3]
Expand All @@ -3780,8 +3780,8 @@ import b
[file b.py.2]
# uh
-- Every file should get reloaded, since the cache was invalidated
[stale a, b, builtins, typing]
[rechecked a, b, builtins, typing]
[stale _typeshed, a, b, builtins, typing]
[rechecked _typeshed, a, b, builtins, typing]
[builtins fixtures/tuple.pyi]

[case testIncrementalWorkingFineGrainedCache]
Expand Down
22 changes: 15 additions & 7 deletions test-data/unit/check-kwargs.test
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ g(**{})

[case testKeywordUnpackWithDifferentTypes]
# https://github.com/python/mypy/issues/11144
from typing import Dict, Generic, TypeVar, Mapping
from typing import Dict, Generic, TypeVar, Mapping, Iterable

T = TypeVar("T")
T2 = TypeVar("T2")
Expand All @@ -516,21 +516,29 @@ class C(Generic[T, T2]):
class D:
...

class E:
def keys(self) -> Iterable[str]:
...
def __getitem__(self, key: str) -> float:
...

def foo(**i: float) -> float:
...

a: A[str, str]
b: B[str, str]
c: C[str, float]
d: D
e = {"a": "b"}
e: E
f = {"a": "b"}

foo(k=1.5)
foo(**a)
foo(**b)
foo(**c)
foo(**d)
foo(**e)
foo(**f)

# Correct:

Expand All @@ -544,9 +552,9 @@ foo(**good1)
foo(**good2)
foo(**good3)
[out]
main:29: error: Argument 1 to "foo" has incompatible type "**A[str, str]"; expected "float"
main:30: error: Argument 1 to "foo" has incompatible type "**B[str, str]"; expected "float"
main:31: error: Argument after ** must be a mapping, not "C[str, float]"
main:32: error: Argument after ** must be a mapping, not "D"
main:33: error: Argument 1 to "foo" has incompatible type "**Dict[str, str]"; expected "float"
main:36: error: Argument 1 to "foo" has incompatible type "**A[str, str]"; expected "float"
main:37: error: Argument 1 to "foo" has incompatible type "**B[str, str]"; expected "float"
main:38: error: Argument after ** must be a mapping, not "C[str, float]"
main:39: error: Argument after ** must be a mapping, not "D"
main:41: error: Argument 1 to "foo" has incompatible type "**Dict[str, str]"; expected "float"
[builtins fixtures/dict.pyi]
1 change: 1 addition & 0 deletions test-data/unit/fixtures/args.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Builtins stub used to support *args, **kwargs.

import _typeshed
from typing import TypeVar, Generic, Iterable, Sequence, Tuple, Dict, Any, overload, Mapping

Tco = TypeVar('Tco', covariant=True)
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/dataclasses.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _typeshed
from typing import (
Generic, Iterator, Iterable, Mapping, Optional, Sequence, Tuple,
TypeVar, Union, overload,
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/dict.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Builtins stub used in dictionary-related test cases.

import _typeshed
from typing import (
TypeVar, Generic, Iterable, Iterator, Mapping, Tuple, overload, Optional, Union, Sequence
)
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/paramspec.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# builtins stub for paramspec-related test cases

import _typeshed
from typing import (
Sequence, Generic, TypeVar, Iterable, Iterator, Tuple, Mapping, Optional, Union, Type, overload,
Protocol
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/primitives.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# builtins stub with non-generic primitive types
import _typeshed
from typing import Generic, TypeVar, Sequence, Iterator, Mapping, Iterable, Tuple, Union

T = TypeVar('T')
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/tuple.pyi
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Builtins stub used in tuple-related test cases.

import _typeshed
from typing import Iterable, Iterator, TypeVar, Generic, Sequence, Optional, overload, Tuple, Type

T = TypeVar("T")
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/typing-medium.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class Sequence(Iterable[T_co]):
def __getitem__(self, n: Any) -> T_co: pass

class Mapping(Iterable[T], Generic[T, T_co]):
def keys(self) -> Iterable[T]: pass # Approximate return type
def __getitem__(self, key: T) -> T_co: pass

class SupportsInt(Protocol):
Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/typing-typeddict.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Sequence(Iterable[T_co]):
def __getitem__(self, n: Any) -> T_co: pass # type: ignore[misc]

class Mapping(Iterable[T], Generic[T, T_co], metaclass=ABCMeta):
def keys(self) -> Iterable[T]: pass # Approximate return type
def __getitem__(self, key: T) -> T_co: pass
@overload
def get(self, k: T) -> Optional[T_co]: pass
Expand Down
8 changes: 8 additions & 0 deletions test-data/unit/lib-stub/_typeshed.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import Protocol, TypeVar, Iterable

_KT = TypeVar("_KT")
_VT_co = TypeVar("_VT_co", covariant=True)

class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]):
def keys(self) -> Iterable[_KT]: ...
def __getitem__(self, __key: _KT) -> _VT_co: ...
2 changes: 2 additions & 0 deletions test-data/unit/lib-stub/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#
# Use [builtins fixtures/...pyi] if you need more features.

import _typeshed

class object:
def __init__(self) -> None: pass

Expand Down
4 changes: 3 additions & 1 deletion test-data/unit/lib-stub/typing.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ class Sequence(Iterable[T_co]):
def __getitem__(self, n: Any) -> T_co: pass

# Mapping type is oversimplified intentionally.
class Mapping(Iterable[T], Generic[T, T_co]): pass
class Mapping(Iterable[T], Generic[T, T_co]):
def keys(self) -> Iterable[T]: pass # Approximate return type
def __getitem__(self, key: T) -> T_co: pass

class Awaitable(Protocol[T]):
def __await__(self) -> Generator[Any, Any, T]: pass
Expand Down