init the project
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# YAML/JSON 差异对比工具
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
def compute_diff(doc_a: dict | str, doc_b: dict | str) -> dict:
|
||||
"""Compute diff between two dicts or YAML strings."""
|
||||
if isinstance(doc_a, str):
|
||||
try:
|
||||
doc_a = yaml.safe_load(doc_a) or {}
|
||||
except yaml.YAMLError:
|
||||
doc_a = {}
|
||||
if isinstance(doc_b, str):
|
||||
try:
|
||||
doc_b = yaml.safe_load(doc_b) or {}
|
||||
except yaml.YAMLError:
|
||||
doc_b = {}
|
||||
|
||||
added, removed, modified = _recursive_diff(doc_a, doc_b, "")
|
||||
return {
|
||||
"added": added,
|
||||
"removed": removed,
|
||||
"modified": modified,
|
||||
}
|
||||
|
||||
|
||||
def _recursive_diff(a: dict | list, b: dict | list, path: str) -> tuple[list, list, list]:
|
||||
added, removed, modified = [], [], []
|
||||
|
||||
if isinstance(a, dict) and isinstance(b, dict):
|
||||
all_keys = set(a.keys()) | set(b.keys())
|
||||
for key in sorted(all_keys):
|
||||
new_path = f"{path}.{key}" if path else key
|
||||
if key not in a:
|
||||
added.append({"path": new_path, "value": b[key]})
|
||||
elif key not in b:
|
||||
removed.append({"path": new_path, "value": a[key]})
|
||||
elif a[key] != b[key]:
|
||||
if isinstance(a[key], (dict, list)) and isinstance(b[key], (dict, list)):
|
||||
a_sub, r_sub, m_sub = _recursive_diff(a[key], b[key], new_path)
|
||||
added.extend(a_sub)
|
||||
removed.extend(r_sub)
|
||||
modified.extend(m_sub)
|
||||
else:
|
||||
modified.append({
|
||||
"path": new_path,
|
||||
"old_value": a[key],
|
||||
"new_value": b[key],
|
||||
})
|
||||
|
||||
elif isinstance(a, list) and isinstance(b, list):
|
||||
for i in range(max(len(a), len(b))):
|
||||
new_path = f"{path}[{i}]"
|
||||
if i >= len(a):
|
||||
added.append({"path": new_path, "value": b[i]})
|
||||
elif i >= len(b):
|
||||
removed.append({"path": new_path, "value": a[i]})
|
||||
elif a[i] != b[i]:
|
||||
if isinstance(a[i], (dict, list)) and isinstance(b[i], (dict, list)):
|
||||
a_sub, r_sub, m_sub = _recursive_diff(a[i], b[i], new_path)
|
||||
added.extend(a_sub)
|
||||
removed.extend(r_sub)
|
||||
modified.extend(m_sub)
|
||||
else:
|
||||
modified.append({
|
||||
"path": new_path,
|
||||
"old_value": a[i],
|
||||
"new_value": b[i],
|
||||
})
|
||||
|
||||
return added, removed, modified
|
||||
Reference in New Issue
Block a user