Skip to content

Subtype of mapping is not compatible type in .update() method #10970

Closed
python/typeshed
#14593

Description

@Dreamsorcerer
    async def psubscribe(self, *args: ChannelT, **kwargs: PubSubHandler):
        new_patterns: Dict[ChannelT, Optional[PubSubHandler]] = dict.fromkeys(args)
        new_patterns.update(kwargs)

This code (taken from aioredis) produces this error:
error: Argument 1 to "update" of "dict" has incompatible type "Dict[str, Callable[[Dict[str, str]], None]]"; expected "Mapping[Union[bytes, str, memoryview], Optional[Callable[[Dict[str, str]], None]]]" [arg-type]

But, the types are compatible as the keys and values are part of the expected union, I can't think of any operation that would make this unsafe. I understand it could be unsafe if the expectation was MutableMapping, as the function might assign any of the unioned types, but for Mapping this looks completely safe to me.

Activity

  1. JelleZijlstra commented on Aug 11, 2021

    @JelleZijlstra
    Member

    For reference, dict.update is defined in typeshed as:

        @overload
        def update(self, __m: Mapping[_KT, _VT], **kwargs: _VT) -> None: ...
        @overload
        def update(self, __m: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ...
        @overload
        def update(self, **kwargs: _VT) -> None: ...
    

    I need to think about this more but I guess it has to do with the invariant key type argument to Mapping.

  2. Dreamsorcerer commented on Aug 21, 2021

    @Dreamsorcerer
    ContributorAuthor

    For reference, errors come from this file: https://github.com/aio-libs/aioredis-py/blob/f5a8e80882c3dfa70cf9cc2e44d110faeb579d74/aioredis/client.py
    Just search for the issue number (10970) to find them.

  3. mzapotoczny commented on Nov 9, 2021

    @mzapotoczny

    I stumbled across similar problem.

    X = {(1, 2): 0, (1,): 1}
    Y = {(1, 3): 2, (1, 4): 3}
    X.update(Y)

    causes

    Argument 1 to "update" of "dict" has incompatible type "Dict[Tuple[int, int], int]"; expected "Mapping[Tuple[int, ...], int]"
    

    while if we use other update definition:

    X = {(1, 2): 0, (1,): 1}
    Y = {(1, 3): 2, (1, 4): 3}
    X.update(Y.items())

    mypy passes.

  4. Dreamsorcerer commented on Nov 9, 2021

    @Dreamsorcerer
    ContributorAuthor

    Think that's a different issue. It doesn't recognise that Tuple[int, int] is compatible with Tuple[int, ...]. I don't think it has anything to do with Mapping.

    You can just add an annotation to make it work:
    Y: Dict[Tuple[int, ...], int]

    Although interesting that it accepts ItemsView[Tuple[int, int], ...], but not Dict[Tuple[int, int], ...]... Maybe it is related...

  5. Dreamsorcerer commented on Jul 14, 2025

    @Dreamsorcerer
    ContributorAuthor

    Annotations seem to have changed to expect SupportsKeysAndGetItem, but otherwise this error still seems reproducible.

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