Skip to content

Fixed #493 include_paths, when only certain keys are included #499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions deepdiff/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,32 @@ def _skip_this(self, level):

return skip

def _skip_this_key(self, level, key):
# if include_paths is not set, than treet every path as included
if self.include_paths is None:
return False
if "{}['{}']".format(level.path(), key) in self.include_paths:
return False
if level.path() in self.include_paths:
# matches e.g. level+key root['foo']['bar']['veg'] include_paths ["root['foo']['bar']"]
return False
for prefix in self.include_paths:
if "{}['{}']".format(level.path(), key) in prefix:
# matches as long the prefix is longer than this object key
# eg.: level+key root['foo']['bar'] matches prefix root['foo']['bar'] from include paths
# level+key root['foo'] matches prefix root['foo']['bar'] from include_paths
# level+key root['foo']['bar'] DOES NOT match root['foo'] from include_paths This needs to be handled afterwards
return False
# check if a higher level is included as a whole (=without any sublevels specified)
# matches e.g. level+key root['foo']['bar']['veg'] include_paths ["root['foo']"]
# but does not match, if it is level+key root['foo']['bar']['veg'] include_paths ["root['foo']['bar']['fruits']"]
up = level.up
while up is not None:
if up.path() in self.include_paths:
return False
up = up.up
return True

def _get_clean_to_keys_mapping(self, keys, level):
"""
Get a dictionary of cleaned value of keys to the keys themselves.
Expand Down Expand Up @@ -570,11 +596,11 @@ def _diff_dict(
rel_class = DictRelationship

if self.ignore_private_variables:
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('__'))])
t1_keys = SetOrdered([key for key in t1 if not(isinstance(key, str) and key.startswith('__')) and not self._skip_this_key(level, key)])
t2_keys = SetOrdered([key for key in t2 if not(isinstance(key, str) and key.startswith('__')) and not self._skip_this_key(level, key)])
else:
t1_keys = SetOrdered(t1.keys())
t2_keys = SetOrdered(t2.keys())
t1_keys = SetOrdered([key for key in t1 if not self._skip_this_key(level, key)])
t2_keys = SetOrdered([key for key in t2 if not self._skip_this_key(level, key)])
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)
Expand Down
File renamed without changes.
160 changes: 160 additions & 0 deletions tests/test_diff_include_paths_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import pytest
from deepdiff import DeepDiff

@pytest.mark.parametrize(
"data, result",
[
(
{
"old": {
'name': 'Testname Old',
'desciption': 'Desc Old',
'sub_path': {
'name': 'Testname Subpath old',
'desciption': 'Desc Subpath old',
},
},
"new": {
'name': 'Testname New',
'desciption': 'Desc New',
'new_attribute': 'New Value',
'sub_path': {
'name': 'Testname Subpath old',
'desciption': 'Desc Subpath old',
},
},
"include_paths": "root['sub_path']",
},
{}
),
(
{
"old": {
'name': 'Testname Old',
'desciption': 'Desc Old',
'sub_path': {
'name': 'Testname Subpath old',
'desciption': 'Desc Subpath old',
},
},
"new": {
'name': 'Testname New',
'desciption': 'Desc New',
'new_attribute': 'New Value',
'sub_path': {
'name': 'Testname Subpath New',
'desciption': 'Desc Subpath old',
},
},
"include_paths": "root['sub_path']",
},
{"values_changed": {"root['sub_path']['name']": {"old_value": "Testname Subpath old", "new_value": "Testname Subpath New"}}}
),
(
{
"old": {
'name': 'Testname Old',
'desciption': 'Desc Old',
'sub_path': {
'name': 'Testname Subpath old',
'desciption': 'Desc Subpath old',
'old_attr': 'old attr value',
},
},
"new": {
'name': 'Testname New',
'desciption': 'Desc New',
'new_attribute': 'New Value',
'sub_path': {
'name': 'Testname Subpath old',
'desciption': 'Desc Subpath New',
'new_sub_path_attr': 'new sub path attr value',
},
},
"include_paths": "root['sub_path']['name']",
},
{}
),
(
{
"old": {
'name': 'Testname old',
'desciption': 'Desc old',
'new_attribute': 'old Value',
'sub_path': {
'name': 'Testname',
'removed_attr': 'revemod attr value',
},
},
"new": {
'name': 'Testname new',
'desciption': 'Desc new',
'new_attribute': 'new Value',
'sub_path': {
'added_attr': 'Added Attr Value',
'name': 'Testname',
},
},
"include_paths": "root['sub_path']['name']",
},
{}
),
(
{
"old": {
'name': 'Testname',
'removed_attr': 'revemod attr value',
},
"new": {
'added_attr': 'Added Attr Value',
'name': 'Testname',
},
"include_paths": "root['name']",
},
{}
),
(
{
"old": {
'name': 'Testname',
'removed_attr': 'revemod attr value',
'removed_attr_2': 'revemod attr value',
},
"new": {
'added_attr': 'Added Attr Value',
'name': 'Testname',
},
"include_paths": "root['name']",
},
{}
),
(
{
"old": {
'name': 'Testname old',
'desciption': 'Desc old',
'new_attribute': 'old Value',
'sub_path': {
'name': 'Testname',
'removed_attr': 'revemod attr value',
'removed_attr_2': 'blu',
},
},
"new": {
'name': 'Testname new',
'desciption': 'Desc new',
'new_attribute': 'new Value',
'sub_path': {
'added_attr': 'Added Attr Value',
'name': 'Testname',
},
},
"include_paths": "root['sub_path']['name']",
},
{}
),
]
)
def test_diff_include_paths_root(data, result):
diff = DeepDiff(data["old"], data["new"], include_paths=data["include_paths"])
assert diff == result
Loading