Skip to content

Commit e352ed8

Browse files
committed
- deephash.py: corrected exclude_paths/include_paths type to SetOrdered
- helper.py: relaxed add_to_frozen_set to Any (callers use both int and str ids); changed type_in_type_group/type_is_subclass_of_type_group to accept Iterable[Type] - delta.py: added elem is not None guard, narrowed tag type, type-ignored namedtuple _replace/summarize - diff.py: typed _compare_in_order index params as Optional[int] with early return; fixed real bug len(other.indexes > 1) → len(other.indexes) > 1; cast UUID arg to str - distance.py: handled iterable_compare_func None check; widened max_/replace_inf_with to float; switched memoryview-incompatible strings to str - path.py: fixed real bug obj.append(_guess_type(...), next_element) (misplaced paren); coerced setattr name to str - serialization.py: type-ignored namedtuple _fields access
1 parent 8a607be commit e352ed8

7 files changed

Lines changed: 35 additions & 30 deletions

File tree

deepdiff/deephash.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
convert_item_or_items_into_compiled_regexes_else_none,
1515
get_id, type_is_subclass_of_type_group, type_in_type_group,
1616
number_to_string, datetime_normalize, KEY_TO_VAL_STR,
17-
get_truncate_datetime, dict_, add_root_to_paths, PydanticBaseModel)
17+
get_truncate_datetime, dict_, add_root_to_paths, PydanticBaseModel,
18+
SetOrdered)
1819

1920
from deepdiff.base import Base
2021

@@ -159,8 +160,8 @@ class DeepHash(Base):
159160
hashes: Dict[Any, Any]
160161
exclude_types_tuple: Tuple[type, ...]
161162
ignore_repetition: bool
162-
exclude_paths: Optional[Set[str]]
163-
include_paths: Optional[Set[str]]
163+
exclude_paths: Optional[SetOrdered]
164+
include_paths: Optional[SetOrdered]
164165
exclude_regex_paths: Optional[List[re.Pattern[str]]]
165166
hasher: Callable[[Union[str, bytes]], str]
166167
use_enum_value: bool

deepdiff/delta.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def _deserializer(obj, safe_to_import=None):
167167
self.reset()
168168

169169
def __repr__(self):
170-
return "<Delta: {}>".format(summarize(self.diff, max_length=100))
170+
return "<Delta: {}>".format(summarize(self.diff, max_length=100)) # type: ignore[arg-type]
171171

172172
def reset(self):
173173
self.post_process_paths_to_convert = dict_()
@@ -289,7 +289,7 @@ def _simple_set_elem_value(self, obj, path_for_err_reporting, elem=None, value=N
289289
except IndexError:
290290
if elem == len(obj):
291291
obj.append(value)
292-
elif self.fill is not not_found and elem > len(obj):
292+
elif self.fill is not not_found and elem is not None and elem > len(obj):
293293
while len(obj) < elem:
294294
if callable(self.fill):
295295
obj.append(self.fill(obj, value, path_for_err_reporting))
@@ -334,7 +334,7 @@ def _set_new_value(self, parent, parent_to_obj_elem, parent_to_obj_action,
334334
# Check if it's a NamedTuple and use _replace() to generate a new copy with the change
335335
if hasattr(obj, '_fields') and hasattr(obj, '_replace'):
336336
if action == GETATTR:
337-
obj = obj._replace(**{elem: new_value})
337+
obj = obj._replace(**{elem: new_value}) # type: ignore[attr-defined]
338338
if parent:
339339
self._simple_set_elem_value(obj=parent, path_for_err_reporting=path,
340340
elem=parent_to_obj_elem, value=obj,
@@ -887,7 +887,7 @@ def _get_reverse_diff(self):
887887
for path, op_codes in info.items():
888888
r_diff[action][path] = []
889889
for op_code in op_codes:
890-
tag = op_code.tag
890+
tag: str = op_code.tag
891891
tag = {'delete': 'insert', 'insert': 'delete'}.get(tag, tag)
892892
new_op_code = Opcode(
893893
tag=tag,

deepdiff/diff.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,8 @@ def _diff_dict(
638638
parents_ids: FrozenSet[int]=frozenset([]),
639639
print_as_attribute: bool=False,
640640
override: bool=False,
641-
override_t1: Optional[Any]=None,
642-
override_t2: Optional[Any]=None,
641+
override_t1: Any=None,
642+
override_t2: Any=None,
643643
local_tree: Optional[Any]=None,
644644
) -> None:
645645
"""Difference of 2 dictionaries"""
@@ -788,14 +788,14 @@ def _diff_iterable(self, level: Any, parents_ids: FrozenSet[int]=frozenset(), _o
788788

789789
def _compare_in_order(
790790
self, level,
791-
t1_from_index=None, t1_to_index=None,
792-
t2_from_index=None, t2_to_index=None
791+
t1_from_index: Optional[int]=None, t1_to_index: Optional[int]=None,
792+
t2_from_index: Optional[int]=None, t2_to_index: Optional[int]=None
793793
) -> List[Tuple[Tuple[int, int], Tuple[Any, Any]]]:
794794
"""
795795
Default compare if `iterable_compare_func` is not provided.
796796
This will compare in sequence order.
797797
"""
798-
if t1_from_index is None:
798+
if t1_from_index is None or t2_from_index is None:
799799
return [((i, i), (x, y)) for i, (x, y) in enumerate(
800800
zip_longest(
801801
level.t1, level.t2, fillvalue=ListItemRemovedOrAdded))]
@@ -1432,7 +1432,7 @@ def get_other_pair(hash_value, in_t1=True):
14321432
# When we report repetitions, we want the child_relationship_param2 only if there is no repetition.
14331433
# Because when there is a repetition, we report it in a different way (iterable_items_added_at_indexes for example).
14341434
# When there is no repetition, we want child_relationship_param2 so that we report the "new_path" correctly.
1435-
if other.item is notpresent or len(other.indexes > 1):
1435+
if other.item is notpresent or len(other.indexes) > 1:
14361436
index2 = None
14371437
else:
14381438
index2 = other.indexes[0]
@@ -1759,7 +1759,7 @@ def _diff(self, level, parents_ids=frozenset(), _original_type=None, local_tree=
17591759
if self.ignore_uuid_types and isinstance(level.t2, uuids):
17601760
try:
17611761
# Convert string to UUID for comparison
1762-
t1_uuid = uuid.UUID(level.t1)
1762+
t1_uuid = uuid.UUID(str(level.t1))
17631763
if t1_uuid.int != level.t2.int:
17641764
self._report_result('values_changed', level, local_tree=local_tree)
17651765
except (ValueError, AttributeError):

deepdiff/distance.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,13 @@ def __calculate_item_deephash(self: "DistanceProtocol", item: Any) -> None:
107107
def _precalculate_distance_by_custom_compare_func(
108108
self: "DistanceProtocol", hashes_added, hashes_removed, t1_hashtable, t2_hashtable, _original_type):
109109
pre_calced_distances = dict_()
110+
if self.iterable_compare_func is None:
111+
return pre_calced_distances
112+
compare_func = self.iterable_compare_func
110113
for added_hash in hashes_added:
111114
for removed_hash in hashes_removed:
112115
try:
113-
is_close_distance = self.iterable_compare_func(t2_hashtable[added_hash].item, t1_hashtable[removed_hash].item)
116+
is_close_distance = compare_func(t2_hashtable[added_hash].item, t1_hashtable[removed_hash].item)
114117
except CannotCompare:
115118
pass
116119
else:
@@ -189,8 +192,8 @@ def _get_item_length(item, parents_ids=frozenset([])):
189192

190193
# internal keys such as _numpy_paths should not count towards the distance.
191194
# old_type and old_value are metadata about the previous state, not additional operations.
192-
if isinstance(key, strings) and (key.startswith('_') or key == 'deep_distance' or key == 'new_path'
193-
or key == 'old_type' or key == 'old_value'):
195+
if isinstance(key, str) and (key.startswith('_') or key == 'deep_distance' or key == 'new_path'
196+
or key == 'old_type' or key == 'old_value'):
194197
continue
195198

196199
item_id = id(subitem)
@@ -250,7 +253,7 @@ def _get_numbers_distance(num1, num2, max_=1, use_log_scale=False, log_scale_sim
250253
return max_ # pragma: no cover
251254

252255

253-
def _numpy_div(a, b, replace_inf_with=1):
256+
def _numpy_div(a, b, replace_inf_with: float=1):
254257
max_array = np.full(shape=a.shape, fill_value=replace_inf_with, dtype=np_float64)
255258
result = np.divide(a, b, out=max_array, where=b != 0, dtype=np_float64)
256259
# wherever 2 numbers are the same, make sure the distance is zero. This is mainly for 0 divided by zero.
@@ -284,15 +287,15 @@ def logarithmic_similarity(a: NumberType, b: NumberType, threshold: float=0.1) -
284287

285288
def logarithmic_distance(a: NumberType, b: NumberType) -> float:
286289
# Apply logarithm to the absolute values and consider the sign
287-
a = float(a)
288-
b = float(b)
290+
a = float(a) # type: ignore[arg-type]
291+
b = float(b) # type: ignore[arg-type]
289292
log_a = math.copysign(math.log(abs(a) + MATH_LOG_OFFSET), a)
290293
log_b = math.copysign(math.log(abs(b) + MATH_LOG_OFFSET), b)
291294

292295
return abs(log_a - log_b)
293296

294297

295-
def _get_numpy_array_distance(num1, num2, max_=1, use_log_scale=False, log_scale_similarity_threshold=0.1):
298+
def _get_numpy_array_distance(num1, num2, max_: float=1, use_log_scale=False, log_scale_similarity_threshold=0.1):
296299
"""
297300
Get the distance of 2 numbers. The output is a number between 0 to the max.
298301
The reason is the

deepdiff/helper.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class indexed_set(set):
313313
"""
314314

315315

316-
def add_to_frozen_set(parents_ids: FrozenSet[int], item_id: int) -> FrozenSet[int]:
316+
def add_to_frozen_set(parents_ids: FrozenSet[Any], item_id: Any) -> FrozenSet[Any]:
317317
return parents_ids | {item_id}
318318

319319

@@ -386,14 +386,15 @@ def numpy_dtype_string_to_type(dtype_str: str) -> Type[Any]:
386386
return numpy_dtype_str_to_type[dtype_str]
387387

388388

389-
def type_in_type_group(item: Any, type_group: Tuple[Type[Any], ...]) -> bool:
389+
def type_in_type_group(item: Any, type_group: Iterable[Type[Any]]) -> bool:
390390
return get_type(item) in type_group
391391

392392

393-
def type_is_subclass_of_type_group(item: Any, type_group: Tuple[Type[Any], ...]) -> bool:
394-
return isinstance(item, type_group) \
395-
or (isinstance(item, type) and issubclass(item, type_group)) \
396-
or type_in_type_group(item, type_group)
393+
def type_is_subclass_of_type_group(item: Any, type_group: Iterable[Type[Any]]) -> bool:
394+
type_group_tuple = tuple(type_group)
395+
return isinstance(item, type_group_tuple) \
396+
or (isinstance(item, type) and issubclass(item, type_group_tuple)) \
397+
or type_in_type_group(item, type_group_tuple)
397398

398399

399400
def get_doc(doc_filename: str) -> str:

deepdiff/path.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def _get_nested_obj_and_force(obj, elements, next_element=None):
158158
except IndexError:
159159
if isinstance(obj, list) and isinstance(elem, int) and elem >= len(obj):
160160
obj.extend([None] * (elem - len(obj)))
161-
obj.append(_guess_type(elements, elem, index), next_element)
161+
obj.append(_guess_type(elements, elem, index, next_element))
162162
obj = obj[-1]
163163
prev_obj = _prev_obj
164164
elif isinstance(obj, list) and len(obj) == 0 and prev_elem:
@@ -168,7 +168,7 @@ def _get_nested_obj_and_force(obj, elements, next_element=None):
168168
if prev_action == GET:
169169
prev_obj[prev_elem] = obj
170170
else:
171-
setattr(prev_obj, prev_elem, obj)
171+
setattr(prev_obj, str(prev_elem), obj)
172172
obj = obj[elem]
173173
elif action == GETATTR:
174174
obj = getattr(obj, elem)

deepdiff/serialization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,7 @@ def _convert_oversized_ints(obj):
807807
converted = [_convert_oversized_ints(v) for v in obj]
808808
if hasattr(obj, '_fields'):
809809
# NamedTuple: reconstruct using keyword arguments
810-
return type(obj)(**dict(zip(obj._fields, converted)))
810+
return type(obj)(**dict(zip(obj._fields, converted))) # type: ignore[attr-defined]
811811
return type(obj)(converted)
812812
return obj
813813

0 commit comments

Comments
 (0)