Skip to content

Non-overlapping comparison with Dict and MutableMapping subclass #10275

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

Closed
Dreamsorcerer opened this issue Apr 2, 2021 · 8 comments
Closed
Labels
bug mypy got something wrong topic-overlap Overlapping equality check

Comments

@Dreamsorcerer
Copy link
Contributor

Dreamsorcerer commented Apr 2, 2021

Trivial reproducer (with --strict-equality):

class A(MutableMapping[str, Any]): pass
def something() -> A: pass
something() == {}

Outputs:

error: Non-overlapping equality check (left operand type: "A", right operand type: "Dict[<nothing>, <nothing>]")  [comparison-overlap]

It seems that it believes a dictionary cannot be equal to a class which inherits from MutableMapping.

@Dreamsorcerer Dreamsorcerer added the bug mypy got something wrong label Apr 2, 2021
@Dreamsorcerer
Copy link
Contributor Author

Dreamsorcerer commented Jun 9, 2023

No longer reproducible.

(Missed the CLI argument).

@JelleZijlstra
Copy link
Member

Mypy seems correct here. dict.__eq__ never returns True for a non-dict, and there's no __eq__ in A's MRO that would make it return equal.

@AlexWaygood AlexWaygood added the topic-overlap Overlapping equality check label Jun 9, 2023
@Dreamsorcerer
Copy link
Contributor Author

You're right, it works fine with __eq__() defined. Now if I can just remember what code I was looking at when I filed the issue...

@Dreamsorcerer Dreamsorcerer closed this as not planned Won't fix, can't repro, duplicate, stale Jun 9, 2023
@Dreamsorcerer
Copy link
Contributor Author

Found it: https://github.com/aio-libs/aiohttp-session/blob/master/tests/test_encrypted_cookie_storage.py#L115

The test seems to pass, even though there is no __eq__() defined.

@Dreamsorcerer
Copy link
Contributor Author

Dreamsorcerer commented Jun 9, 2023

OK, it seems like dict.__eq__ calls __iter__(), so it does work with non-dict types.

This works at runtime:

from typing import Any, MutableMapping

class A(MutableMapping[str, Any]):
    def __delitem__(self, *args):
        ...
    def __getitem__(self, *args):
        ...
    def __iter__(self):
        return iter(())
    def __len__(self):
        ...
    def __setitem__(self, *args):
        ...

print(A() == {})  # True

@Dreamsorcerer Dreamsorcerer reopened this Jun 9, 2023
@JelleZijlstra
Copy link
Member

Looks like Mapping defines an __eq__ that allows two mappings to compare equal.

@Dreamsorcerer
Copy link
Contributor Author

OK, so it's just a typeshed issue? If so, I'll look at making a fix tomorrow.

@Dreamsorcerer
Copy link
Contributor Author

python/typeshed#10297

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-overlap Overlapping equality check
Projects
None yet
Development

No branches or pull requests

3 participants