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.
No longer reproducible.
(Missed the CLI argument).
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.
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...
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.
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
Looks like Mapping defines an __eq__ that allows two mappings to compare equal.
OK, so it's just a typeshed issue? If so, I'll look at making a fix tomorrow.
python/typeshed#10297
Activity
Dreamsorcerer commented on Jun 9, 2023
No longer reproducible.
(Missed the CLI argument).
JelleZijlstra commented on Jun 9, 2023
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.
Dreamsorcerer commented on Jun 9, 2023
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 commented on Jun 9, 2023
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 commented on 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() == {}) # TrueJelleZijlstra commented on Jun 9, 2023
Looks like Mapping defines an __eq__ that allows two mappings to compare equal.
Dreamsorcerer commented on Jun 10, 2023
OK, so it's just a typeshed issue? If so, I'll look at making a fix tomorrow.
Dreamsorcerer commented on Jun 10, 2023
python/typeshed#10297