Skip to content

Commit de3f105

Browse files
committed
adding detailed__dict__ to address #312
1 parent 25546ce commit de3f105

File tree

4 files changed

+57
-4
lines changed

4 files changed

+57
-4
lines changed

deepdiff/diff.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
type_is_subclass_of_type_group, type_in_type_group, get_doc,
2121
number_to_string, datetime_normalize, KEY_TO_VAL_STR, booleans,
2222
np_ndarray, get_numpy_ndarray_rows, OrderedSetPlus, RepeatedTimer,
23-
TEXT_VIEW, TREE_VIEW, DELTA_VIEW,
23+
TEXT_VIEW, TREE_VIEW, DELTA_VIEW, detailed__dict__,
2424
np, get_truncate_datetime, dict_, CannotCompare)
2525
from deepdiff.serialization import SerializationMixin
2626
from deepdiff.distance import DistanceMixin
@@ -394,8 +394,8 @@ def _diff_obj(self, level, parents_ids=frozenset(),
394394
t1 = level.t1._asdict()
395395
t2 = level.t2._asdict()
396396
else:
397-
t1 = level.t1.__dict__
398-
t2 = level.t2.__dict__
397+
t1 = detailed__dict__(level.t1)
398+
t2 = detailed__dict__(level.t2)
399399
except AttributeError:
400400
try:
401401
t1 = self._dict_from_slots(level.t1)

deepdiff/helper.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,22 @@ def get_homogeneous_numpy_compatible_type_of_seq(seq):
582582
return PYTHON_TYPE_TO_NUMPY_TYPE.get(type_, False)
583583
else:
584584
return False
585+
586+
587+
def detailed__dict__(obj, ignore_private_variables=True):
588+
"""
589+
Get the detailed dictionary of an object.
590+
591+
This is used so we retrieve object properties too.
592+
"""
593+
result = obj.__dict__.copy() # A shallow copy
594+
for key in dir(obj):
595+
if key not in result and (
596+
not ignore_private_variables or (
597+
ignore_private_variables and not key.startswith('__')
598+
)
599+
):
600+
value = getattr(obj, key)
601+
if not callable(value):
602+
result[key] = value
603+
return result

docs/deephash_doc.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ truncate_datetime: string, default = None
149149
If your object is nested, it will build hashes of all the objects it contains too.
150150

151151

152+
.. note::
153+
DeepHash output is not like conventional hash functions. It is a dictionary of object IDs to their hashes. This happens because DeepHash calculates the hash of the object and any other objects found within the object in a recursive manner. If you only need the hash of the object you are passing, all you need to do is to do:
154+
155+
>>> DeepHash(obj)[obj]
156+
157+
152158
**Examples**
153159

154160
Let's say you have a dictionary object.

tests/test_diff_text.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44
import logging
55
import uuid
6+
import numpy as np
67
from decimal import Decimal
78
from deepdiff import DeepDiff
89
from deepdiff.helper import pypy3
@@ -569,7 +570,15 @@ class MyEnum(Enum):
569570
'root._value_': {
570571
'old_value': 1,
571572
'new_value': 2
572-
}
573+
},
574+
'root.name': {
575+
'old_value': 'A',
576+
'new_value': 'B'
577+
},
578+
'root.value': {
579+
'old_value': 1,
580+
'new_value': 2
581+
},
573582
}
574583
}
575584
assert ddiff == result
@@ -1594,3 +1603,22 @@ def test_datetime_in_key(self):
15941603
expected = {'values_changed': {f'root[{repr(now)}]': {'new_value': 2, 'old_value': 1}}}
15951604

15961605
assert expected == diff
1606+
1607+
def test_property_values(self):
1608+
1609+
class A:
1610+
_thing = 0
1611+
1612+
def __init__(self, a):
1613+
self.a = a
1614+
1615+
@property
1616+
def thing(self):
1617+
A._thing += 1
1618+
return A._thing
1619+
1620+
diff = DeepDiff(A(1), A(1))
1621+
expected = {'values_changed': {'root._thing': {'new_value': 1, 'old_value': 0},
1622+
'root.thing': {'new_value': 2, 'old_value': 1}}}
1623+
1624+
assert expected == diff

0 commit comments

Comments
 (0)