Skip to content

Commit e04a5e5

Browse files
committed
switching to StableSetEq
1 parent 872a45a commit e04a5e5

15 files changed

+87
-76
lines changed

deepdiff/anyset.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from deepdiff.deephash import DeepHash
2-
from deepdiff.helper import dict_, SortedSet
2+
from deepdiff.helper import dict_, SetOrdered
33

44

55
class AnySet:
@@ -10,7 +10,7 @@ class AnySet:
1010
However one the AnySet object is deleted, all those traces will be gone too.
1111
"""
1212
def __init__(self, items=None):
13-
self._set = SortedSet()
13+
self._set = SetOrdered()
1414
self._hashes = dict_()
1515
self._hash_to_objects = dict_()
1616
if items:

deepdiff/base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from deepdiff.helper import strings, numbers, SortedSet
1+
from deepdiff.helper import strings, numbers, SetOrdered
22

33

44
DEFAULT_SIGNIFICANT_DIGITS_WHEN_IGNORE_NUMERIC_TYPES = 12
@@ -30,18 +30,18 @@ def get_ignore_types_in_groups(self, ignore_type_in_groups,
3030

3131
result = []
3232
for item_group in ignore_type_in_groups:
33-
new_item_group = SortedSet()
33+
new_item_group = SetOrdered()
3434
for item in item_group:
3535
item = type(item) if item is None or not isinstance(item, type) else item
3636
new_item_group.add(item)
3737
result.append(new_item_group)
3838
ignore_type_in_groups = result
3939

4040
if ignore_string_type_changes and self.strings not in ignore_type_in_groups:
41-
ignore_type_in_groups.append(SortedSet(self.strings))
41+
ignore_type_in_groups.append(SetOrdered(self.strings))
4242

4343
if ignore_numeric_type_changes and self.numbers not in ignore_type_in_groups:
44-
ignore_type_in_groups.append(SortedSet(self.numbers))
44+
ignore_type_in_groups.append(SetOrdered(self.numbers))
4545

4646
if not ignore_type_subclasses:
4747
# is_instance method needs tuples. When we look for subclasses, we need them to be tuples

deepdiff/delta.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Opcode, FlatDeltaRow, UnkownValueCode, FlatDataAction,
1414
OPCODE_TAG_TO_FLAT_DATA_ACTION,
1515
FLAT_DATA_ACTION_TO_OPCODE_TAG,
16-
SortedSet,
16+
SetOrdered,
1717
)
1818
from deepdiff.path import (
1919
_path_to_elements, _get_nested_obj, _get_nested_obj_and_force,
@@ -744,7 +744,7 @@ def _do_ignore_order(self):
744744
"""
745745
fixed_indexes = self.diff.get('iterable_items_added_at_indexes', dict_())
746746
remove_indexes = self.diff.get('iterable_items_removed_at_indexes', dict_())
747-
paths = SortedSet(fixed_indexes.keys()) | SortedSet(remove_indexes.keys())
747+
paths = SetOrdered(fixed_indexes.keys()) | SetOrdered(remove_indexes.keys())
748748
for path in paths:
749749
# In the case of ignore_order reports, we are pointing to the container object.
750750
# Thus we add a [0] to the elements so we can get the required objects and discard what we don't need.

deepdiff/diff.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
np_ndarray, np_floating, get_numpy_ndarray_rows, RepeatedTimer,
2626
TEXT_VIEW, TREE_VIEW, DELTA_VIEW, detailed__dict__, add_root_to_paths,
2727
np, get_truncate_datetime, dict_, CannotCompare, ENUM_INCLUDE_KEYS,
28-
PydanticBaseModel, Opcode, SortedSet)
28+
PydanticBaseModel, Opcode, SetOrdered)
2929
from deepdiff.serialization import SerializationMixin
3030
from deepdiff.distance import DistanceMixin
3131
from deepdiff.model import (
@@ -566,16 +566,16 @@ def _diff_dict(
566566
rel_class = DictRelationship
567567

568568
if self.ignore_private_variables:
569-
t1_keys = SortedSet([key for key in t1 if not(isinstance(key, str) and key.startswith('__'))])
570-
t2_keys = SortedSet([key for key in t2 if not(isinstance(key, str) and key.startswith('__'))])
569+
t1_keys = SetOrdered([key for key in t1 if not(isinstance(key, str) and key.startswith('__'))])
570+
t2_keys = SetOrdered([key for key in t2 if not(isinstance(key, str) and key.startswith('__'))])
571571
else:
572-
t1_keys = SortedSet(t1.keys())
573-
t2_keys = SortedSet(t2.keys())
572+
t1_keys = SetOrdered(t1.keys())
573+
t2_keys = SetOrdered(t2.keys())
574574
if self.ignore_string_type_changes or self.ignore_numeric_type_changes or self.ignore_string_case:
575575
t1_clean_to_keys = self._get_clean_to_keys_mapping(keys=t1_keys, level=level)
576576
t2_clean_to_keys = self._get_clean_to_keys_mapping(keys=t2_keys, level=level)
577-
t1_keys = SortedSet(t1_clean_to_keys.keys())
578-
t2_keys = SortedSet(t2_clean_to_keys.keys())
577+
t1_keys = SetOrdered(t1_clean_to_keys.keys())
578+
t2_keys = SetOrdered(t2_clean_to_keys.keys())
579579
else:
580580
t1_clean_to_keys = t2_clean_to_keys = None
581581

@@ -1140,7 +1140,7 @@ def _get_most_in_common_pairs_in_iterables(
11401140
# It also includes a "max" key that is just the value of the biggest current distance in the
11411141
# most_in_common_pairs dictionary.
11421142
def defaultdict_orderedset():
1143-
return defaultdict(SortedSet)
1143+
return defaultdict(SetOrdered)
11441144
most_in_common_pairs = defaultdict(defaultdict_orderedset)
11451145
pairs = dict_()
11461146

@@ -1183,7 +1183,7 @@ def defaultdict_orderedset():
11831183
pairs_of_item[_distance].add(removed_hash)
11841184
used_to_hashes = set()
11851185

1186-
distances_to_from_hashes = defaultdict(SortedSet)
1186+
distances_to_from_hashes = defaultdict(SetOrdered)
11871187
for from_hash, distances_to_to_hashes in most_in_common_pairs.items():
11881188
# del distances_to_to_hashes['max']
11891189
for dist in distances_to_to_hashes:
@@ -1215,8 +1215,8 @@ def _diff_iterable_with_deephash(self, level, parents_ids, _original_type=None,
12151215

12161216
full_t1_hashtable = self._create_hashtable(level, 't1')
12171217
full_t2_hashtable = self._create_hashtable(level, 't2')
1218-
t1_hashes = SortedSet(full_t1_hashtable.keys())
1219-
t2_hashes = SortedSet(full_t2_hashtable.keys())
1218+
t1_hashes = SetOrdered(full_t1_hashtable.keys())
1219+
t2_hashes = SetOrdered(full_t2_hashtable.keys())
12201220
hashes_added = t2_hashes - t1_hashes
12211221
hashes_removed = t1_hashes - t2_hashes
12221222

@@ -1628,7 +1628,7 @@ def _diff(self, level, parents_ids=frozenset(), _original_type=None, local_tree=
16281628
elif isinstance(level.t1, tuple):
16291629
self._diff_tuple(level, parents_ids, local_tree=local_tree)
16301630

1631-
elif isinstance(level.t1, (set, frozenset, SortedSet)):
1631+
elif isinstance(level.t1, (set, frozenset, SetOrdered)):
16321632
self._diff_set(level, local_tree=local_tree)
16331633

16341634
elif isinstance(level.t1, np_ndarray):
@@ -1750,19 +1750,19 @@ def affected_paths(self):
17501750
'iterable_item_added': {'root[3][1]': 4},
17511751
'values_changed': {'root[2]': {'new_value': 4, 'old_value': 2}}}
17521752
>>> ddiff.affected_paths
1753-
SortedSet(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
1753+
SetOrdered(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
17541754
>>> ddiff.affected_root_keys
1755-
SortedSet([3, 4, 5, 6, 2])
1755+
SetOrdered([3, 4, 5, 6, 2])
17561756
17571757
"""
1758-
result = SortedSet()
1758+
result = SetOrdered()
17591759
for key in REPORT_KEYS:
17601760
value = self.get(key)
17611761
if value:
1762-
if isinstance(value, SortedSet):
1762+
if isinstance(value, SetOrdered):
17631763
result |= value
17641764
else:
1765-
result |= SortedSet(value.keys())
1765+
result |= SetOrdered(value.keys())
17661766
return result
17671767

17681768
@property
@@ -1782,18 +1782,18 @@ def affected_root_keys(self):
17821782
'iterable_item_added': {'root[3][1]': 4},
17831783
'values_changed': {'root[2]': {'new_value': 4, 'old_value': 2}}}
17841784
>>> ddiff.affected_paths
1785-
SortedSet(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
1785+
SetOrdered(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
17861786
>>> ddiff.affected_root_keys
1787-
SortedSet([3, 4, 5, 6, 2])
1787+
SetOrdered([3, 4, 5, 6, 2])
17881788
"""
1789-
result = SortedSet()
1789+
result = SetOrdered()
17901790
for key in REPORT_KEYS:
17911791
value = self.tree.get(key)
17921792
if value:
1793-
if isinstance(value, SortedSet):
1794-
result |= SortedSet([i.get_root_key() for i in value])
1793+
if isinstance(value, SetOrdered):
1794+
result |= SetOrdered([i.get_root_key() for i in value])
17951795
else:
1796-
result |= SortedSet([i.get_root_key() for i in value.keys()])
1796+
result |= SetOrdered([i.get_root_key() for i in value.keys()])
17971797
return result
17981798

17991799

deepdiff/helper.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
from ast import literal_eval
1313
from decimal import Decimal, localcontext, InvalidOperation as InvalidDecimalOperation
1414
from itertools import repeat
15-
# from orderly_set import OrderlySet as OrderedSetModule # median: 0.806 s, some tests are failing
16-
# from orderly_set import SortedSet as OrderedSetModule # median 1.011 s, didn't work for tests
17-
from orderly_set import StableSetEq as OrderedSetModule # median: 1.0867 s for cache test, 5.63s for all tests
18-
# from orderly_set import OrderedSet as OrderedSetModule # median 1.1256 s for cache test, 5.63s for all tests
15+
# from orderly_set import OrderlySet as SetOrderedBase # median: 0.806 s, some tests are failing
16+
# from orderly_set import SetOrdered as SetOrderedBase # median 1.011 s, didn't work for tests
17+
from orderly_set import StableSetEq as SetOrderedBase # median: 1.0867 s for cache test, 5.63s for all tests
18+
# from orderly_set import OrderedSet as SetOrderedBase # median 1.1256 s for cache test, 5.63s for all tests
1919
from threading import Timer
2020

2121

@@ -27,7 +27,7 @@ class pydantic_base_model_type:
2727
pass
2828

2929

30-
class SortedSet(OrderedSetModule):
30+
class SetOrdered(SetOrderedBase):
3131
def __repr__(self):
3232
return str(list(self))
3333

@@ -326,7 +326,7 @@ def add_root_to_paths(paths):
326326
"""
327327
if paths is None:
328328
return
329-
result = SortedSet()
329+
result = SetOrdered()
330330
for path in paths:
331331
if path.startswith('root'):
332332
result.add(path)

deepdiff/lfucache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
from collections import defaultdict
88
from threading import Lock
99
from statistics import mean
10-
from deepdiff.helper import not_found, dict_, SortedSet
10+
from deepdiff.helper import not_found, dict_, SetOrdered
1111

1212

1313
class CacheNode:
1414
def __init__(self, key, report_type, value, freq_node, pre, nxt):
1515
self.key = key
1616
if report_type:
17-
self.content = defaultdict(SortedSet)
17+
self.content = defaultdict(SetOrdered)
1818
self.content[report_type].add(value)
1919
else:
2020
self.content = value

deepdiff/model.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from copy import copy
44
from deepdiff.helper import (
55
RemapDict, strings, short_repr, notpresent, get_type, numpy_numbers, np, literal_eval_extended,
6-
dict_, SortedSet)
6+
dict_, SetOrdered)
77
from deepdiff.path import stringify_element
88

99
logger = logging.getLogger(__name__)
@@ -50,7 +50,7 @@ def remove_empty_keys(self):
5050
class TreeResult(ResultDict):
5151
def __init__(self):
5252
for key in REPORT_KEYS:
53-
self[key] = SortedSet()
53+
self[key] = SetOrdered()
5454

5555
def mutual_add_removes_to_become_value_changes(self):
5656
"""
@@ -68,7 +68,7 @@ def mutual_add_removes_to_become_value_changes(self):
6868
mutual_paths = set(added_paths) & set(removed_paths)
6969

7070
if mutual_paths and 'values_changed' not in self:
71-
self['values_changed'] = SortedSet()
71+
self['values_changed'] = SetOrdered()
7272
for path in mutual_paths:
7373
level_before = removed_paths[path]
7474
self['iterable_item_removed'].remove(level_before)
@@ -84,11 +84,11 @@ def mutual_add_removes_to_become_value_changes(self):
8484

8585
def __getitem__(self, item):
8686
if item not in self:
87-
self[item] = SortedSet()
87+
self[item] = SetOrdered()
8888
return self.get(item)
8989

9090
def __len__(self):
91-
return sum([len(i) for i in self.values() if isinstance(i, SortedSet)])
91+
return sum([len(i) for i in self.values() if isinstance(i, SetOrdered)])
9292

9393

9494
class TextResult(ResultDict):
@@ -108,16 +108,16 @@ def __init__(self, tree_results=None, verbose_level=1):
108108
"iterable_item_moved": dict_(),
109109
"attribute_added": self.__set_or_dict(),
110110
"attribute_removed": self.__set_or_dict(),
111-
"set_item_removed": SortedSet(),
112-
"set_item_added": SortedSet(),
111+
"set_item_removed": SetOrdered(),
112+
"set_item_added": SetOrdered(),
113113
"repetition_change": dict_()
114114
})
115115

116116
if tree_results:
117117
self._from_tree_results(tree_results)
118118

119119
def __set_or_dict(self):
120-
return {} if self.verbose_level >= 2 else SortedSet()
120+
return {} if self.verbose_level >= 2 else SetOrdered()
121121

122122
def _from_tree_results(self, tree):
123123
"""
@@ -162,7 +162,7 @@ def _from_tree_default(self, tree, report_type, ignore_if_in_iterable_opcodes=Fa
162162

163163
# do the reporting
164164
report = self[report_type]
165-
if isinstance(report, SortedSet):
165+
if isinstance(report, SetOrdered):
166166
report.add(change.path(force=FORCE_DEFAULT))
167167
elif isinstance(report, dict):
168168
report[change.path(force=FORCE_DEFAULT)] = item
@@ -264,7 +264,7 @@ def _from_tree_deep_distance(self, tree):
264264
def _from_tree_custom_results(self, tree):
265265
for k, _level_list in tree.items():
266266
if k not in REPORT_KEYS:
267-
if not isinstance(_level_list, SortedSet):
267+
if not isinstance(_level_list, SetOrdered):
268268
continue
269269

270270
# if len(_level_list) == 0:

deepdiff/path.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,15 @@ def extract(obj, path):
202202
Note that even if DeepDiff tried gives you a path to an item in a set,
203203
there is no such thing in Python and hence you will get an error trying
204204
to extract that item from a set.
205-
If you want to be able to get items from sets, use the SortedSet module
205+
If you want to be able to get items from sets, use the SetOrdered module
206206
to generate the sets.
207-
In fact Deepdiff uses SortedSet as a dependency.
207+
In fact Deepdiff uses SetOrdered as a dependency.
208208
209209
>>> from deepdiff import grep, extract
210210
>>> obj = {"a", "b"}
211211
>>> obj | grep("b")
212212
Set item detected in the path.'set' objects do NOT support indexing. But DeepSearch will still report a path.
213-
{'matched_values': SortedSet(['root[0]'])}
213+
{'matched_values': SetOrdered(['root[0]'])}
214214
>>> extract(obj, 'root[0]')
215215
Traceback (most recent call last):
216216
File "<stdin>", line 1, in <module>
@@ -219,8 +219,8 @@ def extract(obj, path):
219219
File "deepdiff/deepdiff/path.py", line 84, in _get_nested_obj
220220
obj = obj[elem]
221221
TypeError: 'set' object is not subscriptable
222-
>>> from orderly_set import SortedSet
223-
>>> obj = SortedSet(["a", "b"])
222+
>>> from orderly_set import SetOrdered
223+
>>> obj = SetOrdered(["a", "b"])
224224
>>> extract(obj, 'root[0]')
225225
'a'
226226

deepdiff/search.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python
22
import re
33
from collections.abc import MutableMapping, Iterable
4-
from deepdiff.helper import SortedSet
4+
from deepdiff.helper import SetOrdered
55
import logging
66

77
from deepdiff.helper import (
@@ -85,9 +85,9 @@ class DeepSearch(dict):
8585
def __init__(self,
8686
obj,
8787
item,
88-
exclude_paths=SortedSet(),
89-
exclude_regex_paths=SortedSet(),
90-
exclude_types=SortedSet(),
88+
exclude_paths=SetOrdered(),
89+
exclude_regex_paths=SetOrdered(),
90+
exclude_types=SetOrdered(),
9191
verbose_level=1,
9292
case_sensitive=False,
9393
match_string=False,
@@ -104,9 +104,9 @@ def __init__(self,
104104
self.obj = obj
105105
self.case_sensitive = case_sensitive if isinstance(item, strings) else True
106106
item = item if self.case_sensitive else item.lower()
107-
self.exclude_paths = SortedSet(exclude_paths)
107+
self.exclude_paths = SetOrdered(exclude_paths)
108108
self.exclude_regex_paths = [re.compile(exclude_regex_path) for exclude_regex_path in exclude_regex_paths]
109-
self.exclude_types = SortedSet(exclude_types)
109+
self.exclude_types = SetOrdered(exclude_types)
110110
self.exclude_types_tuple = tuple(
111111
exclude_types) # we need tuple for checking isinstance
112112
self.verbose_level = verbose_level
@@ -135,7 +135,7 @@ def __init__(self,
135135
del self[k]
136136

137137
def __set_or_dict(self):
138-
return dict_() if self.verbose_level >= 2 else SortedSet()
138+
return dict_() if self.verbose_level >= 2 else SetOrdered()
139139

140140
def __report(self, report_key, key, value):
141141
if self.verbose_level >= 2:
@@ -202,7 +202,7 @@ def __search_dict(self,
202202
else:
203203
parent_text = "%s[%s]"
204204

205-
obj_keys = SortedSet(obj.keys())
205+
obj_keys = SetOrdered(obj.keys())
206206

207207
for item_key in obj_keys:
208208
if not print_as_attribute and isinstance(item_key, strings):

0 commit comments

Comments
 (0)