Skip to content

Commit

Permalink
switching to StableSetEq
Browse files Browse the repository at this point in the history
  • Loading branch information
seperman committed May 17, 2024
1 parent 872a45a commit e04a5e5
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 76 deletions.
4 changes: 2 additions & 2 deletions deepdiff/anyset.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from deepdiff.deephash import DeepHash
from deepdiff.helper import dict_, SortedSet
from deepdiff.helper import dict_, SetOrdered


class AnySet:
Expand All @@ -10,7 +10,7 @@ class AnySet:
However one the AnySet object is deleted, all those traces will be gone too.
"""
def __init__(self, items=None):
self._set = SortedSet()
self._set = SetOrdered()
self._hashes = dict_()
self._hash_to_objects = dict_()
if items:
Expand Down
8 changes: 4 additions & 4 deletions deepdiff/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from deepdiff.helper import strings, numbers, SortedSet
from deepdiff.helper import strings, numbers, SetOrdered


DEFAULT_SIGNIFICANT_DIGITS_WHEN_IGNORE_NUMERIC_TYPES = 12
Expand Down Expand Up @@ -30,18 +30,18 @@ def get_ignore_types_in_groups(self, ignore_type_in_groups,

result = []
for item_group in ignore_type_in_groups:
new_item_group = SortedSet()
new_item_group = SetOrdered()
for item in item_group:
item = type(item) if item is None or not isinstance(item, type) else item
new_item_group.add(item)
result.append(new_item_group)
ignore_type_in_groups = result

if ignore_string_type_changes and self.strings not in ignore_type_in_groups:
ignore_type_in_groups.append(SortedSet(self.strings))
ignore_type_in_groups.append(SetOrdered(self.strings))

if ignore_numeric_type_changes and self.numbers not in ignore_type_in_groups:
ignore_type_in_groups.append(SortedSet(self.numbers))
ignore_type_in_groups.append(SetOrdered(self.numbers))

if not ignore_type_subclasses:
# is_instance method needs tuples. When we look for subclasses, we need them to be tuples
Expand Down
4 changes: 2 additions & 2 deletions deepdiff/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
Opcode, FlatDeltaRow, UnkownValueCode, FlatDataAction,
OPCODE_TAG_TO_FLAT_DATA_ACTION,
FLAT_DATA_ACTION_TO_OPCODE_TAG,
SortedSet,
SetOrdered,
)
from deepdiff.path import (
_path_to_elements, _get_nested_obj, _get_nested_obj_and_force,
Expand Down Expand Up @@ -744,7 +744,7 @@ def _do_ignore_order(self):
"""
fixed_indexes = self.diff.get('iterable_items_added_at_indexes', dict_())
remove_indexes = self.diff.get('iterable_items_removed_at_indexes', dict_())
paths = SortedSet(fixed_indexes.keys()) | SortedSet(remove_indexes.keys())
paths = SetOrdered(fixed_indexes.keys()) | SetOrdered(remove_indexes.keys())
for path in paths:
# In the case of ignore_order reports, we are pointing to the container object.
# Thus we add a [0] to the elements so we can get the required objects and discard what we don't need.
Expand Down
46 changes: 23 additions & 23 deletions deepdiff/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
np_ndarray, np_floating, get_numpy_ndarray_rows, RepeatedTimer,
TEXT_VIEW, TREE_VIEW, DELTA_VIEW, detailed__dict__, add_root_to_paths,
np, get_truncate_datetime, dict_, CannotCompare, ENUM_INCLUDE_KEYS,
PydanticBaseModel, Opcode, SortedSet)
PydanticBaseModel, Opcode, SetOrdered)
from deepdiff.serialization import SerializationMixin
from deepdiff.distance import DistanceMixin
from deepdiff.model import (
Expand Down Expand Up @@ -566,16 +566,16 @@ def _diff_dict(
rel_class = DictRelationship

if self.ignore_private_variables:
t1_keys = SortedSet([key for key in t1 if not(isinstance(key, str) and key.startswith('__'))])
t2_keys = SortedSet([key for key in t2 if not(isinstance(key, str) and key.startswith('__'))])
t1_keys = SetOrdered([key for key in t1 if not(isinstance(key, str) and key.startswith('__'))])
t2_keys = SetOrdered([key for key in t2 if not(isinstance(key, str) and key.startswith('__'))])
else:
t1_keys = SortedSet(t1.keys())
t2_keys = SortedSet(t2.keys())
t1_keys = SetOrdered(t1.keys())
t2_keys = SetOrdered(t2.keys())
if self.ignore_string_type_changes or self.ignore_numeric_type_changes or self.ignore_string_case:
t1_clean_to_keys = self._get_clean_to_keys_mapping(keys=t1_keys, level=level)
t2_clean_to_keys = self._get_clean_to_keys_mapping(keys=t2_keys, level=level)
t1_keys = SortedSet(t1_clean_to_keys.keys())
t2_keys = SortedSet(t2_clean_to_keys.keys())
t1_keys = SetOrdered(t1_clean_to_keys.keys())
t2_keys = SetOrdered(t2_clean_to_keys.keys())
else:
t1_clean_to_keys = t2_clean_to_keys = None

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

Expand Down Expand Up @@ -1183,7 +1183,7 @@ def defaultdict_orderedset():
pairs_of_item[_distance].add(removed_hash)
used_to_hashes = set()

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

full_t1_hashtable = self._create_hashtable(level, 't1')
full_t2_hashtable = self._create_hashtable(level, 't2')
t1_hashes = SortedSet(full_t1_hashtable.keys())
t2_hashes = SortedSet(full_t2_hashtable.keys())
t1_hashes = SetOrdered(full_t1_hashtable.keys())
t2_hashes = SetOrdered(full_t2_hashtable.keys())
hashes_added = t2_hashes - t1_hashes
hashes_removed = t1_hashes - t2_hashes

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

elif isinstance(level.t1, (set, frozenset, SortedSet)):
elif isinstance(level.t1, (set, frozenset, SetOrdered)):
self._diff_set(level, local_tree=local_tree)

elif isinstance(level.t1, np_ndarray):
Expand Down Expand Up @@ -1750,19 +1750,19 @@ def affected_paths(self):
'iterable_item_added': {'root[3][1]': 4},
'values_changed': {'root[2]': {'new_value': 4, 'old_value': 2}}}
>>> ddiff.affected_paths
SortedSet(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
SetOrdered(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
>>> ddiff.affected_root_keys
SortedSet([3, 4, 5, 6, 2])
SetOrdered([3, 4, 5, 6, 2])
"""
result = SortedSet()
result = SetOrdered()
for key in REPORT_KEYS:
value = self.get(key)
if value:
if isinstance(value, SortedSet):
if isinstance(value, SetOrdered):
result |= value
else:
result |= SortedSet(value.keys())
result |= SetOrdered(value.keys())
return result

@property
Expand All @@ -1782,18 +1782,18 @@ def affected_root_keys(self):
'iterable_item_added': {'root[3][1]': 4},
'values_changed': {'root[2]': {'new_value': 4, 'old_value': 2}}}
>>> ddiff.affected_paths
SortedSet(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
SetOrdered(['root[3][1]', 'root[4]', 'root[5]', 'root[6]', 'root[2]'])
>>> ddiff.affected_root_keys
SortedSet([3, 4, 5, 6, 2])
SetOrdered([3, 4, 5, 6, 2])
"""
result = SortedSet()
result = SetOrdered()
for key in REPORT_KEYS:
value = self.tree.get(key)
if value:
if isinstance(value, SortedSet):
result |= SortedSet([i.get_root_key() for i in value])
if isinstance(value, SetOrdered):
result |= SetOrdered([i.get_root_key() for i in value])
else:
result |= SortedSet([i.get_root_key() for i in value.keys()])
result |= SetOrdered([i.get_root_key() for i in value.keys()])
return result


Expand Down
12 changes: 6 additions & 6 deletions deepdiff/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
from ast import literal_eval
from decimal import Decimal, localcontext, InvalidOperation as InvalidDecimalOperation
from itertools import repeat
# from orderly_set import OrderlySet as OrderedSetModule # median: 0.806 s, some tests are failing
# from orderly_set import SortedSet as OrderedSetModule # median 1.011 s, didn't work for tests
from orderly_set import StableSetEq as OrderedSetModule # median: 1.0867 s for cache test, 5.63s for all tests
# from orderly_set import OrderedSet as OrderedSetModule # median 1.1256 s for cache test, 5.63s for all tests
# from orderly_set import OrderlySet as SetOrderedBase # median: 0.806 s, some tests are failing
# from orderly_set import SetOrdered as SetOrderedBase # median 1.011 s, didn't work for tests
from orderly_set import StableSetEq as SetOrderedBase # median: 1.0867 s for cache test, 5.63s for all tests
# from orderly_set import OrderedSet as SetOrderedBase # median 1.1256 s for cache test, 5.63s for all tests
from threading import Timer


Expand All @@ -27,7 +27,7 @@ class pydantic_base_model_type:
pass


class SortedSet(OrderedSetModule):
class SetOrdered(SetOrderedBase):
def __repr__(self):
return str(list(self))

Expand Down Expand Up @@ -326,7 +326,7 @@ def add_root_to_paths(paths):
"""
if paths is None:
return
result = SortedSet()
result = SetOrdered()
for path in paths:
if path.startswith('root'):
result.add(path)
Expand Down
4 changes: 2 additions & 2 deletions deepdiff/lfucache.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
from collections import defaultdict
from threading import Lock
from statistics import mean
from deepdiff.helper import not_found, dict_, SortedSet
from deepdiff.helper import not_found, dict_, SetOrdered


class CacheNode:
def __init__(self, key, report_type, value, freq_node, pre, nxt):
self.key = key
if report_type:
self.content = defaultdict(SortedSet)
self.content = defaultdict(SetOrdered)
self.content[report_type].add(value)
else:
self.content = value
Expand Down
20 changes: 10 additions & 10 deletions deepdiff/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from copy import copy
from deepdiff.helper import (
RemapDict, strings, short_repr, notpresent, get_type, numpy_numbers, np, literal_eval_extended,
dict_, SortedSet)
dict_, SetOrdered)
from deepdiff.path import stringify_element

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -50,7 +50,7 @@ def remove_empty_keys(self):
class TreeResult(ResultDict):
def __init__(self):
for key in REPORT_KEYS:
self[key] = SortedSet()
self[key] = SetOrdered()

def mutual_add_removes_to_become_value_changes(self):
"""
Expand All @@ -68,7 +68,7 @@ def mutual_add_removes_to_become_value_changes(self):
mutual_paths = set(added_paths) & set(removed_paths)

if mutual_paths and 'values_changed' not in self:
self['values_changed'] = SortedSet()
self['values_changed'] = SetOrdered()
for path in mutual_paths:
level_before = removed_paths[path]
self['iterable_item_removed'].remove(level_before)
Expand All @@ -84,11 +84,11 @@ def mutual_add_removes_to_become_value_changes(self):

def __getitem__(self, item):
if item not in self:
self[item] = SortedSet()
self[item] = SetOrdered()
return self.get(item)

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


class TextResult(ResultDict):
Expand All @@ -108,16 +108,16 @@ def __init__(self, tree_results=None, verbose_level=1):
"iterable_item_moved": dict_(),
"attribute_added": self.__set_or_dict(),
"attribute_removed": self.__set_or_dict(),
"set_item_removed": SortedSet(),
"set_item_added": SortedSet(),
"set_item_removed": SetOrdered(),
"set_item_added": SetOrdered(),
"repetition_change": dict_()
})

if tree_results:
self._from_tree_results(tree_results)

def __set_or_dict(self):
return {} if self.verbose_level >= 2 else SortedSet()
return {} if self.verbose_level >= 2 else SetOrdered()

def _from_tree_results(self, tree):
"""
Expand Down Expand Up @@ -162,7 +162,7 @@ def _from_tree_default(self, tree, report_type, ignore_if_in_iterable_opcodes=Fa

# do the reporting
report = self[report_type]
if isinstance(report, SortedSet):
if isinstance(report, SetOrdered):
report.add(change.path(force=FORCE_DEFAULT))
elif isinstance(report, dict):
report[change.path(force=FORCE_DEFAULT)] = item
Expand Down Expand Up @@ -264,7 +264,7 @@ def _from_tree_deep_distance(self, tree):
def _from_tree_custom_results(self, tree):
for k, _level_list in tree.items():
if k not in REPORT_KEYS:
if not isinstance(_level_list, SortedSet):
if not isinstance(_level_list, SetOrdered):
continue

# if len(_level_list) == 0:
Expand Down
10 changes: 5 additions & 5 deletions deepdiff/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,15 @@ def extract(obj, path):
Note that even if DeepDiff tried gives you a path to an item in a set,
there is no such thing in Python and hence you will get an error trying
to extract that item from a set.
If you want to be able to get items from sets, use the SortedSet module
If you want to be able to get items from sets, use the SetOrdered module
to generate the sets.
In fact Deepdiff uses SortedSet as a dependency.
In fact Deepdiff uses SetOrdered as a dependency.
>>> from deepdiff import grep, extract
>>> obj = {"a", "b"}
>>> obj | grep("b")
Set item detected in the path.'set' objects do NOT support indexing. But DeepSearch will still report a path.
{'matched_values': SortedSet(['root[0]'])}
{'matched_values': SetOrdered(['root[0]'])}
>>> extract(obj, 'root[0]')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Expand All @@ -219,8 +219,8 @@ def extract(obj, path):
File "deepdiff/deepdiff/path.py", line 84, in _get_nested_obj
obj = obj[elem]
TypeError: 'set' object is not subscriptable
>>> from orderly_set import SortedSet
>>> obj = SortedSet(["a", "b"])
>>> from orderly_set import SetOrdered
>>> obj = SetOrdered(["a", "b"])
>>> extract(obj, 'root[0]')
'a'
Expand Down
16 changes: 8 additions & 8 deletions deepdiff/search.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
import re
from collections.abc import MutableMapping, Iterable
from deepdiff.helper import SortedSet
from deepdiff.helper import SetOrdered
import logging

from deepdiff.helper import (
Expand Down Expand Up @@ -85,9 +85,9 @@ class DeepSearch(dict):
def __init__(self,
obj,
item,
exclude_paths=SortedSet(),
exclude_regex_paths=SortedSet(),
exclude_types=SortedSet(),
exclude_paths=SetOrdered(),
exclude_regex_paths=SetOrdered(),
exclude_types=SetOrdered(),
verbose_level=1,
case_sensitive=False,
match_string=False,
Expand All @@ -104,9 +104,9 @@ def __init__(self,
self.obj = obj
self.case_sensitive = case_sensitive if isinstance(item, strings) else True
item = item if self.case_sensitive else item.lower()
self.exclude_paths = SortedSet(exclude_paths)
self.exclude_paths = SetOrdered(exclude_paths)
self.exclude_regex_paths = [re.compile(exclude_regex_path) for exclude_regex_path in exclude_regex_paths]
self.exclude_types = SortedSet(exclude_types)
self.exclude_types = SetOrdered(exclude_types)
self.exclude_types_tuple = tuple(
exclude_types) # we need tuple for checking isinstance
self.verbose_level = verbose_level
Expand Down Expand Up @@ -135,7 +135,7 @@ def __init__(self,
del self[k]

def __set_or_dict(self):
return dict_() if self.verbose_level >= 2 else SortedSet()
return dict_() if self.verbose_level >= 2 else SetOrdered()

def __report(self, report_key, key, value):
if self.verbose_level >= 2:
Expand Down Expand Up @@ -202,7 +202,7 @@ def __search_dict(self,
else:
parent_text = "%s[%s]"

obj_keys = SortedSet(obj.keys())
obj_keys = SetOrdered(obj.keys())

for item_key in obj_keys:
if not print_as_attribute and isinstance(item_key, strings):
Expand Down
Loading

0 comments on commit e04a5e5

Please sign in to comment.