Skip to content

Incompatible override with **kwargs TypedDict and Any #13491

Closed

Description

@cdce8p

Bug Report
Came across this override error while testing **kwargs unpack from #13471.
/CC: @ilevkivskyi

To Reproduce

from typing import Any, TypedDict
from typing_extensions import Unpack


class Details(TypedDict, total=False):
    arg: str
    value: int

class Parent:
    def turn_on(self, **kwargs: Any) -> None: ...

class Child(Parent):
    def turn_on(self, **kwargs: Unpack[Details]) -> None: ...  # <-- error

Expected Behavior

The parent methods uses Any as annotation for **kwargs. Any override with Upack[_TypedDict_] should be compatible.

Actual Behavior

test.py:13: error: Signature of "turn_on" incompatible with supertype "Parent"  [override]
test.py:13: note:      Superclass:
test.py:13: note:          def turn_on(self, **kwargs: Any) -> None
test.py:13: note:      Subclass:
test.py:13: note:          def turn_on(*, arg: str = ..., value: int = ...) -> None

Your Environment

  • Mypy version used: mypy 0.980+dev.0c0f071ef5d41c24182a5a94a5db882f9e917802 (compiled: no)
  • Mypy command-line flags: --enable-incomplete-features
  • Python version used: 3.10

Activity

  1. ilevkivskyi commented on Aug 23, 2022

    @ilevkivskyi
    Member

    This is not a bug. This actually violates Liskov. The suppertype can accept arbitrary keywords, while subtype only some.

    If you really want to express "I don't care about arguments", use *args: Any, **kwargs: Any. Mypy special-cases this as "whatever works".

  2. cdce8p commented on Aug 23, 2022

    @cdce8p
    CollaboratorAuthor

    This is not a bug. This actually violates Liskov. The suppertype can accept arbitrary keywords, while subtype only some.

    Doesn't that depend on the definition of completeness? I.e. the TypedDict defines the keyword arguments which must be present, but just technically you can still pass any other arguments to it, as well. The code wouldn't break.

    I also checked pyright, which does not emit an error, at the moment.

    If you really want to express "I don't care about arguments", use *args: Any, **kwargs: Any. Mypy special-cases this as "whatever works".

    Adding *args isn't an option in this case, unfortunately.

  3. ilevkivskyi commented on Aug 23, 2022

    @ilevkivskyi
    Member

    Allowing arbitrary keywords will significantly reduce safety. Imagine:

    class Spec(TypedDict, total=False):
        one: int
        other: str
    
    def foo(**kwargs: Spec) -> None: ...
    foo(ohter=42)  # Oops, a typo, makes the type error unnoticed

    I also checked pyright, which does not emit an error, at the moment.

    Well, use pyright then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions