From ae65c7e2b368bc420e6206368a5c0598291505d4 Mon Sep 17 00:00:00 2001 From: pabszero <88653327+pabszero@users.noreply.github.com> Date: Mon, 19 Oct 2026 18:47:53 +0300 Subject: [PATCH 1/2] Fix Index equality with non-mappings --- diskcache/persistent.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/diskcache/persistent.py b/diskcache/persistent.py index 522bb74..25ad9e0 100644 --- a/diskcache/persistent.py +++ b/diskcache/persistent.py @@ -6,6 +6,7 @@ from collections.abc import ( ItemsView, KeysView, + Mapping, MutableMapping, Sequence, ValuesView, @@ -1117,6 +1118,9 @@ def __eq__(self, other): :return: True if index equals other """ + if not isinstance(other, Mapping): + return NotImplemented + if len(self) != len(other): return False @@ -1149,7 +1153,10 @@ def __ne__(self, other): :return: True if index does not equal other """ - return not self == other + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + return not result def memoize(self, name=None, typed=False, ignore=()): """Memoizing cache decorator. From 416f3b07f40675557f14864afc9591d9a7091cfc Mon Sep 17 00:00:00 2001 From: pabszero <88653327+pabszero@users.noreply.github.com> Date: Mon, 19 Oct 2026 18:49:36 +0300 Subject: [PATCH 2/2] Test Index comparison dispatch and mapping order --- tests/test_index.py | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/test_index.py b/tests/test_index.py index 742daf3..e3119c6 100644 --- a/tests/test_index.py +++ b/tests/test_index.py @@ -3,12 +3,71 @@ import pickle import shutil import tempfile +from collections import OrderedDict, UserDict +from types import MappingProxyType import pytest import diskcache as dc +@pytest.mark.parametrize('items', [[], [('a', 1)]]) +@pytest.mark.parametrize('other', [None, 0, object(), [], [1], (), '', 'a']) +def test_comparison_non_mapping(tmp_path, items, other): + index = dc.Index(str(tmp_path), items) + try: + assert index.__eq__(other) is NotImplemented + assert index.__ne__(other) is NotImplemented + assert (index == other) is False + assert (other == index) is False + assert (index != other) is True + assert (other != index) is True + finally: + index.cache.close() + + +def test_comparison_reflected(tmp_path): + equal = object() + unequal = object() + + class Other: + def __len__(self): + raise AssertionError('non-mapping length must not be consulted') + + def __eq__(self, other): + return equal + + def __ne__(self, other): + return unequal + + index = dc.Index(str(tmp_path), a=1) + try: + other = Other() + assert (index == other) is equal + assert (index != other) is unequal + finally: + index.cache.close() + + +@pytest.mark.parametrize( + 'factory', [dict, UserDict, MappingProxyType, OrderedDict] +) +def test_comparison_mapping_order(tmp_path, factory): + index = dc.Index(str(tmp_path), [('a', 1), ('b', 2)]) + try: + matching = factory({'a': 1, 'b': 2}) + reversed_order = factory({'b': 2, 'a': 1}) + different = factory({'a': 1, 'b': 3}) + assert index == matching + assert not index != matching + assert index != different + assert not index == different + assert (index == reversed_order) is (factory is not OrderedDict) + assert (index != reversed_order) is (factory is OrderedDict) + finally: + index.cache.close() + + def rmdir(directory): try: shutil.rmtree(directory)