Skip to content
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

feat: handle fixtures #15

Merged
merged 1 commit into from
Aug 23, 2024
Merged
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
118 changes: 105 additions & 13 deletions frappe_schema_json_diff.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
from dataclasses import dataclass
import difflib
import os
import json
from typing import Optional
Expand Down Expand Up @@ -48,11 +49,18 @@ def prep_table(self) -> None:
self.table = table

def print(self):
self.tree = self.dict_diff(
self.label,
self.base_obj,
self.head_obj,
)
if isinstance(self.base_obj, list):
self.tree = self.list_diff(
self.label,
self.base_obj,
self.head_obj,
)
elif isinstance(self.base_obj, dict):
self.tree = self.dict_diff(
self.label,
self.base_obj,
self.head_obj,
)
if self.tree.children:
console.log(self.tree)
elif self.table and self.table.rows:
Expand Down Expand Up @@ -150,35 +158,36 @@ def list_diff(
name: str,
base_list: list,
head_list: list,
b_path: str,
h_path: str,
b_path: str="",
h_path: str="",
) -> Tree:

list_tree = Tree(name)

# one (and only one) list may be empty
mt_handler = base_list or head_list
if isdict := type(mt_handler[0]) is dict:
self.common_key = self.get_common_key(name, mt_handler)
# New common_key per call of list_diff.
common_key = self.get_common_key(name, mt_handler)

if base_list and head_list and isdict:
# Create sets of values of common keys for lists of dicts
head_dicts = {k[self.common_key] for k in head_list}
base_dicts = {k[self.common_key] for k in base_list}
head_dicts = {k[common_key] for k in head_list}
base_dicts = {k[common_key] for k in base_list}
deleted_dict_keys, added_dict_keys = symmetric_diff_sep(
base_dicts, head_dicts
)
diff_dict_keys = head_dicts - added_dict_keys

for i, bd in enumerate(base_list):
bd_kv = bd[self.common_key]
bd_kv = bd[common_key]
conc_b_path = f"{b_path}/{i}"
if bd_kv in deleted_dict_keys:
self.red_dict(bd, conc_b_path, list_tree)
deleted_dict_keys.remove(bd_kv)
else:
for j, hd in enumerate(head_list):
hd_kv = hd[self.common_key]
hd_kv = hd[common_key]
conc_h_path = f"{h_path}/{j}"
if bd_kv == hd_kv and bd_kv in diff_dict_keys:
rtree = self.dict_diff(
Expand Down Expand Up @@ -208,6 +217,81 @@ def list_diff(

return list_tree

def pf_diff(
self,
name: str,
base_list: list,
head_list: list,
b_path: str,
h_path: str,
) -> Tree:

return
list_tree = Tree(name)
# each list contains dicts with keys "fieldname" and "fieldtype", and any number of additions, deletions, modifications, and duplications
# feed difflib with the rendered version of each list; need to expand the 'options' field for Custom HTML dicts and put it in the list
json.loads(base_str) # dict value =


for i, bd in enumerate(base_list):
if bd["fieldtype"] == "Custom HTML":
bd_kv = bd["fieldname"]
conc_b_path = f"{b_path}/{i}"
if (len(head_list) - 1) > i and head_list[i]["fieldtype"] == "Custom HTML":
hd_kv = head_list[i]["fieldname"]
conc_h_path = f"{h_path}/{i}"
if bd_kv == hd_kv:
rtree = self.dict_diff(
bd_kv, bd, head_list[i], conc_b_path, conc_h_path
)
if rtree.children:
list_tree.add(rtree)
for j, hd in enumerate(head_list):
if hd["fieldtype"] == "Custom HTML":
hd_kv = hd["fieldname"]
conc_h_path = f"{h_path}/{j}"
if bd_kv == hd_kv:
rtree = self.dict_diff(
bd_kv, bd, hd, conc_b_path, conc_h_path
)
if rtree.children:
list_tree.add(rtree)
conc_b_path = f"{b_path}/{i}"
if bd_kv in deleted_dict_keys:
self.red_dict(bd, conc_b_path, list_tree)
deleted_dict_keys.remove(bd_kv)
else:
for j, hd in enumerate(head_list):
hd_kv = hd[self.common_key]
conc_h_path = f"{h_path}/{j}"
if bd_kv == hd_kv and bd_kv in diff_dict_keys:
rtree = self.dict_diff(
bd_kv, bd, hd, conc_b_path, conc_h_path
)
diff_dict_keys.remove(bd_kv)
if rtree.children:
list_tree.add(rtree)
elif hd_kv in added_dict_keys:
self.grn_dict(hd, conc_h_path, list_tree)
added_dict_keys.remove(hd_kv)
#elif isdict:
# for i, d in enumerate(base_list):
# self.red_dict(d, f"{b_path}/{i}", list_tree)
# for i, d in enumerate(head_list):
# self.grn_dict(d, f"{h_path}/{i}", list_tree)
#else:
# del_set, add_set = symmetric_diff_sep(set(base_list), set(head_list))
# for i, e in enumerate(base_list):
# if e in del_set:
# self.red_elem(e, f"{b_path}/{i}", list_tree)
# del_set.remove(e)
# for i, e in enumerate(head_list):
# if e in add_set:
# self.grn_elem(e, f"{h_path}/{i}", list_tree)
# add_set.remove(e)

#return list_tree

def get_common_key(self, name: str, dict_list: list) -> True:
common_keys = {
"custom_fields": "fieldname",
Expand All @@ -220,12 +304,14 @@ def get_common_key(self, name: str, dict_list: list) -> True:
}
if (key := common_keys.get(name)) is not None:
return key
elif '.json' in name:
return 'name'
else:
# Find common keys then return the first one with all unique values.
# https://stackoverflow.com/a/13985856/14410691
common_keys = set.intersection(*map(set, dict_list))
for key in common_keys:
if len(dict_list) == len(set(d[key] for d in dict_list)):
if len(dict_list) == len(set(d[key] for d in dict_list if d[key] is not None)):
return key
print(
"No unique common_key : values - dictionaries can't be diffed based on content"
Expand Down Expand Up @@ -332,6 +418,12 @@ def symmetric_diff_sep(
exclusive_set2 = set2 - set1
return exclusive_set1, exclusive_set2

def is_json(text):
try:
json.loads(text)
except ValueError as e:
return False
return True

if __name__ == "__main__":

Expand Down