Skip to content
Open
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
16 changes: 12 additions & 4 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -903,8 +903,12 @@ def analyze_type_with_type_info(
if info.special_alias:
return instantiate_type_alias(
info.special_alias,
# TODO: should we allow NamedTuples generic in ParamSpec?
self.anal_array(args, allow_unpack=True),
self.anal_array(
args,
allow_unpack=True,
allow_param_spec=True,
allow_param_spec_literals=True,
),
self.fail,
False,
ctx,
Expand All @@ -921,8 +925,12 @@ def analyze_type_with_type_info(
if info.special_alias:
return instantiate_type_alias(
info.special_alias,
# TODO: should we allow TypedDicts generic in ParamSpec?
self.anal_array(args, allow_unpack=True),
self.anal_array(
args,
allow_unpack=True,
allow_param_spec=True,
allow_param_spec_literals=True,
),
self.fail,
False,
ctx,
Expand Down
32 changes: 32 additions & 0 deletions test-data/unit/check-parameter-specification.test
Original file line number Diff line number Diff line change
Expand Up @@ -2756,3 +2756,35 @@ reveal_type(Sneaky(f8, 1, y='').kwargs) # N: Revealed type is "builtins.dict[bu
reveal_type(Sneaky(f9, 1, y=0).kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y': builtins.int, 'z'?: builtins.str})"
reveal_type(Sneaky(f9, 1, y=0, z='').kwargs) # N: Revealed type is "TypedDict('builtins.dict', {'x'?: builtins.int, 'y': builtins.int, 'z'?: builtins.str})"
[builtins fixtures/paramspec.pyi]

[case testNamedTupleAndTypedDictParamSpecInteraction]
# https://github.com/python/mypy/issues/21039
from typing import Callable, NamedTuple, TypedDict, ParamSpec, Generic

P = ParamSpec("P")

class X(TypedDict, Generic[P]):
c: Callable[P, None]

def f1(y: X[P]) -> None: ...
def f2(y: X[[int]]) -> None: ...
def f3(y: X[...]) -> None: ...

x1: X[[str]]
f1(x1)
f2(x1) # E: Argument 1 to "f2" has incompatible type "X[[str]]"; expected "X[[int]]"
f3(x1)

class Y(NamedTuple, Generic[P]):
c: Callable[P, None]

def g1(y: Y[P]) -> None: ...
def g2(y: Y[[int]]) -> None: ...
def g3(y: Y[...]) -> None: ...

y1: Y[[str]]
g1(y1)
g2(y1) # E: Argument 1 to "g2" has incompatible type "Y[[str]]"; expected "Y[[int]]"
g3(y1)
[builtins fixtures/paramspec.pyi]
[typing fixtures/typing-full.pyi]
4 changes: 1 addition & 3 deletions test-data/unit/fixtures/paramspec.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ class tuple(Sequence[T_co], Generic[T_co]):
def __len__(self) -> int: ...
def count(self, obj: object) -> int: ...

class _ItemsView(Iterable[Tuple[KT, VT]]): ...
Copy link
Collaborator Author

@A5rocks A5rocks Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting this error:

  tmp/builtins.pyi:54: error: Class builtins._ItemsView has abstract attributes "__iter__" (diff)
  tmp/builtins.pyi:54: note: If it is meant to be abstract, add 'abc.ABCMeta' as an explicit metacl[snipped]

due to how full typing + this were interacting. I didn't feel like investigating, so I just inlined this type.


class dict(Mapping[KT, VT]):
@overload
def __init__(self, **kwargs: VT) -> None: ...
Expand All @@ -71,7 +69,7 @@ class dict(Mapping[KT, VT]):
def get(self, key: KT, default: T, /) -> Union[VT, T]: ...
def __len__(self) -> int: ...
def pop(self, k: KT) -> VT: ...
def items(self) -> _ItemsView[KT, VT]: ...
def items(self) -> Iterable[Tuple[KT, VT]]: ...

def isinstance(x: object, t: type) -> bool: ...

Expand Down
Loading