Skip to content

Commit 80102a6

Browse files
authored
Merge pull request #360 from seperman/dev
6.2.2
2 parents 093949f + 2a2bd73 commit 80102a6

File tree

13 files changed

+141
-48
lines changed

13 files changed

+141
-48
lines changed

.github/workflows/main.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
python-version: [3.7, 3.8, 3.9, "3.10"]
15+
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
1616
architecture: ["x64"]
1717
steps:
1818
- uses: actions/checkout@v2

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ Authors in order of the timeline of their contributions:
4747
- Mikhail Khviyuzov [mskhviyu](https://github.com/mskhviyu) for Exclude obj callback strict.
4848
- [dtorres-sf](https://github.com/dtorres-sf) for the fix for diffing using iterable_compare_func with nested objects.
4949
- [Enric Pou](https://github.com/epou) for bug fix of ValueError when using Decimal 0.x
50+
- [Uwe Fladrich](https://github.com/uwefladrich) for fixing bug when diff'ing non-sequence iterables

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# DeepDiff Change log
22

3+
- v6-2-2
4+
- Enum test fix for python 3.11
5+
- Adding support for dateutils rrules
36
- v6-2-1
47
- Removed the print statements.
58
- v6-2-0

deepdiff/diff.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from enum import Enum
1212
from copy import deepcopy
1313
from math import isclose as is_close
14-
from collections.abc import Mapping, Iterable
14+
from collections.abc import Mapping, Iterable, Sequence
1515
from collections import defaultdict
1616
from itertools import zip_longest
1717
from ordered_set import OrderedSet
@@ -23,7 +23,7 @@
2323
number_to_string, datetime_normalize, KEY_TO_VAL_STR, booleans,
2424
np_ndarray, get_numpy_ndarray_rows, OrderedSetPlus, RepeatedTimer,
2525
TEXT_VIEW, TREE_VIEW, DELTA_VIEW, detailed__dict__, add_root_to_paths,
26-
np, get_truncate_datetime, dict_, CannotCompare, ENUM_IGNORE_KEYS)
26+
np, get_truncate_datetime, dict_, CannotCompare, ENUM_INCLUDE_KEYS)
2727
from deepdiff.serialization import SerializationMixin
2828
from deepdiff.distance import DistanceMixin
2929
from deepdiff.model import (
@@ -395,8 +395,8 @@ def unmangle(attribute):
395395
return {i: getattr(object, unmangle(i)) for i in all_slots}
396396

397397
def _diff_enum(self, level, parents_ids=frozenset(), local_tree=None):
398-
t1 = detailed__dict__(level.t1, ignore_private_variables=self.ignore_private_variables, ignore_keys=ENUM_IGNORE_KEYS)
399-
t2 = detailed__dict__(level.t2, ignore_private_variables=self.ignore_private_variables, ignore_keys=ENUM_IGNORE_KEYS)
398+
t1 = detailed__dict__(level.t1, include_keys=ENUM_INCLUDE_KEYS)
399+
t2 = detailed__dict__(level.t2, include_keys=ENUM_INCLUDE_KEYS)
400400

401401
self._diff_dict(
402402
level,
@@ -727,7 +727,13 @@ def _diff_iterable_in_order(self, level, parents_ids=frozenset(), _original_type
727727
else:
728728
child_relationship_class = NonSubscriptableIterableRelationship
729729

730-
if self._all_values_basic_hashable(level.t1) and self._all_values_basic_hashable(level.t2) and self.iterable_compare_func is None:
730+
if (
731+
isinstance(level.t1, Sequence)
732+
and isinstance(level.t2, Sequence)
733+
and self._all_values_basic_hashable(level.t1)
734+
and self._all_values_basic_hashable(level.t2)
735+
and self.iterable_compare_func is None
736+
):
731737
local_tree_pass = TreeResult()
732738
self._diff_ordered_iterable_by_difflib(
733739
level,

deepdiff/helper.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class np_type:
133133
TEXT_VIEW = 'text'
134134
DELTA_VIEW = '_delta'
135135

136-
ENUM_IGNORE_KEYS = frozenset(['_name_', '_value_', '_sort_order_'])
136+
ENUM_INCLUDE_KEYS = ['__objclass__', 'name', 'value']
137137

138138

139139
def short_repr(item, max_length=15):
@@ -630,26 +630,37 @@ def get_homogeneous_numpy_compatible_type_of_seq(seq):
630630
return False
631631

632632

633-
def detailed__dict__(obj, ignore_private_variables=True, ignore_keys=frozenset()):
633+
def detailed__dict__(obj, ignore_private_variables=True, ignore_keys=frozenset(), include_keys=None):
634634
"""
635635
Get the detailed dictionary of an object.
636636
637637
This is used so we retrieve object properties too.
638638
"""
639-
result = obj.__dict__.copy() # A shallow copy
640-
private_var_prefix = f"_{obj.__class__.__name__}__" # The semi private variables in Python get this prefix
641-
for key in ignore_keys:
642-
if key in result or (
643-
ignore_private_variables and key.startswith('__') and not key.startswith(private_var_prefix)
644-
):
645-
del result[key]
646-
for key in dir(obj):
647-
if key not in result and key not in ignore_keys and (
648-
not ignore_private_variables or (
649-
ignore_private_variables and not key.startswith('__') and not key.startswith(private_var_prefix)
650-
)
651-
):
652-
value = getattr(obj, key)
653-
if not callable(value):
654-
result[key] = value
639+
if include_keys:
640+
result = {}
641+
for key in include_keys:
642+
try:
643+
value = getattr(obj, key)
644+
except Exception:
645+
pass
646+
else:
647+
if not callable(value) or key == '__objclass__': # We don't want to compare functions, however for backward compatibility, __objclass__ needs to be reported.
648+
result[key] = value
649+
else:
650+
result = obj.__dict__.copy() # A shallow copy
651+
private_var_prefix = f"_{obj.__class__.__name__}__" # The semi private variables in Python get this prefix
652+
for key in ignore_keys:
653+
if key in result or (
654+
ignore_private_variables and key.startswith('__') and not key.startswith(private_var_prefix)
655+
):
656+
del result[key]
657+
for key in dir(obj):
658+
if key not in result and key not in ignore_keys and (
659+
not ignore_private_variables or (
660+
ignore_private_variables and not key.startswith('__') and not key.startswith(private_var_prefix)
661+
)
662+
):
663+
value = getattr(obj, key)
664+
if not callable(value):
665+
result[key] = value
655666
return result

deepdiff/serialization.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
toml = None # pragma: no cover.
2222
try:
2323
import clevercsv
24+
csv = None
2425
except ImportError: # pragma: no cover.
26+
import csv
2527
clevercsv = None # pragma: no cover.
2628
from copy import deepcopy
2729
from functools import partial
@@ -424,9 +426,11 @@ def load_path_content(path, file_type=None):
424426
content = the_file.read()
425427
content = pickle_load(content)
426428
elif file_type in {'csv', 'tsv'}:
427-
if clevercsv is None: # pragma: no cover.
428-
raise ImportError('CleverCSV needs to be installed.') # pragma: no cover.
429-
content = clevercsv.read_dicts(path)
429+
if clevercsv: # pragma: no cover.
430+
content = clevercsv.read_dicts(path)
431+
else:
432+
with open(path, 'r') as the_file:
433+
content = list(csv.DictReader(the_file))
430434
logger.info(f"NOTE: CSV content was empty in {path}")
431435

432436
# Everything in csv is string but we try to automatically convert any numbers we find
@@ -485,11 +489,13 @@ def _save_content(content, path, file_type, keep_backup=True):
485489
with open(path, 'wb') as the_file:
486490
content = pickle_dump(content, file_obj=the_file)
487491
elif file_type in {'csv', 'tsv'}:
488-
if clevercsv is None: # pragma: no cover.
489-
raise ImportError('CleverCSV needs to be installed.') # pragma: no cover.
492+
if clevercsv: # pragma: no cover.
493+
dict_writer = clevercsv.DictWriter
494+
else:
495+
dict_writer = csv.DictWriter
490496
with open(path, 'w', newline='') as csvfile:
491497
fieldnames = list(content[0].keys())
492-
writer = clevercsv.DictWriter(csvfile, fieldnames=fieldnames)
498+
writer = dict_writer(csvfile, fieldnames=fieldnames)
493499
writer.writeheader()
494500
writer.writerows(content)
495501
else:

docs/authors.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ Authors in order of the timeline of their contributions:
6060
- `dtorres-sf`_ for the fix for diffing using iterable_compare_func with nested objects.
6161
- `Enric Pou <https://github.com/epou>`__ for bug fix of ValueError
6262
when using Decimal 0.x
63+
- `Uwe Fladrich <https://github.com/uwefladrich>`__ for fixing bug when diff'ing non-sequence iterables
64+
6365

6466
.. _Sep Dehpour (Seperman): http://www.zepworks.com
6567
.. _Victor Hahn Castell: http://hahncastell.de

docs/changelog.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,39 @@ Changelog
55

66
DeepDiff Changelog
77

8+
- v6-2-2
9+
10+
- Enum test fix for python 3.11
11+
- Adding support for dateutils rrules
12+
13+
- v6-2-1
14+
15+
- Removed the print statements.
16+
17+
- v6-2-0
18+
19+
- Major improvement in the diff report for lists when items are all
20+
hashable and the order of items is important.
21+
22+
- v6-1-0
23+
24+
- DeepDiff.affected_paths can be used to get the list of all paths
25+
where a change, addition, or deletion was reported for.
26+
- DeepDiff.affected_root_keys can be used to get the list of all
27+
paths where a change, addition, or deletion was reported for.
28+
- Bugfix: ValueError when using Decimal 0.x #339 by `Enric
29+
Pou <https://github.com/epou>`__
30+
- Serialization of UUID
31+
32+
- v6-0-0
33+
34+
- `Exclude obj callback
35+
strict <https://github.com/seperman/deepdiff/pull/320/files>`__
36+
parameter is added to DeepDiff by Mikhail Khviyuzov
37+
`mskhviyu <https://github.com/mskhviyu>`__.
38+
- A fix for diffing using ``iterable_compare_func`` with nested
39+
objects by `dtorres-sf <https://github.com/dtorres-sf>`__ who
40+
originally contributed this feature.
841
- v5-7-0:
942

1043
- https://github.com/seperman/deepdiff/pull/284 Bug-Fix: TypeError

requirements-cli.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
click==8.1.3
22
pyyaml==6.0
3-
toml==0.10.2
4-
clevercsv==0.7.4

requirements-dev-3.7.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ ipdb==0.13.9
77
numpy==1.21.6
88
pytest==7.1.2
99
python-dotenv==0.20.0
10+
python-dateutil==2.8.2

0 commit comments

Comments
 (0)