mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-12 07:18:23 +01:00
* params/metrics/plots/exp show: introduce onerror * fixup * plots/metrics/params: removing errors * removing more errors * removing errors * some more removing * new plots ux * new ux for metrics * new ux for params * fixing tests * fixups * minor test fixes * minor test fixes * commands: plots/params: fix ui imports * working on error handlng decorator, stopped at show checkpoints * error_handler, further dvelopment * plots just before moving loading to collect * appending errors to results: initial passing * fixup * onerror: remove onerror fixture * fixups * plots/metrics/params/experiments: temporarily remove error warnings * plots: extract parsing out of class method * metrics/experiments: provide exception serializer for show-json * params/plots/metrics: signal errors * rebase fixups * fix TODOs * fixup * skshetry's review refactor
103 lines
2.3 KiB
Python
103 lines
2.3 KiB
Python
import json
|
|
from collections import defaultdict
|
|
|
|
from .flatten import flatten
|
|
|
|
|
|
def _parse(raw):
|
|
if raw is None or isinstance(raw, (dict, list, int, float)):
|
|
return raw
|
|
|
|
assert isinstance(raw, str)
|
|
try:
|
|
return json.loads(raw)
|
|
except json.JSONDecodeError:
|
|
return raw
|
|
|
|
|
|
def _diff_vals(old, new, with_unchanged):
|
|
if (
|
|
isinstance(new, list)
|
|
and isinstance(old, list)
|
|
and len(old) == len(new) == 1
|
|
):
|
|
return _diff_vals(old[0], new[0], with_unchanged)
|
|
|
|
if not with_unchanged and old == new:
|
|
return {}
|
|
|
|
res = {"old": old, "new": new}
|
|
if isinstance(new, (int, float)) and isinstance(old, (int, float)):
|
|
res["diff"] = new - old
|
|
return res
|
|
|
|
|
|
def _flatten(d):
|
|
if not d:
|
|
return defaultdict(lambda: None)
|
|
|
|
if isinstance(d, dict):
|
|
return defaultdict(lambda: None, flatten(d))
|
|
|
|
return defaultdict(lambda: "unable to parse")
|
|
|
|
|
|
def _diff_dicts(old_dict, new_dict, with_unchanged):
|
|
new = _flatten(new_dict)
|
|
old = _flatten(old_dict)
|
|
|
|
res = defaultdict(dict)
|
|
|
|
xpaths = set(old.keys())
|
|
xpaths.update(set(new.keys()))
|
|
for xpath in xpaths:
|
|
old_val = old[xpath]
|
|
new_val = new[xpath]
|
|
val_diff = _diff_vals(old_val, new_val, with_unchanged)
|
|
if val_diff:
|
|
res[xpath] = val_diff
|
|
return dict(res)
|
|
|
|
|
|
def _diff(old_raw, new_raw, with_unchanged):
|
|
old = _parse(old_raw)
|
|
new = _parse(new_raw)
|
|
|
|
if isinstance(new, dict) or isinstance(old, dict):
|
|
return _diff_dicts(old, new, with_unchanged)
|
|
|
|
val_diff = _diff_vals(old, new, with_unchanged)
|
|
if val_diff:
|
|
return {"": val_diff}
|
|
|
|
return {}
|
|
|
|
|
|
def diff(old, new, with_unchanged=False):
|
|
paths = set(old.keys())
|
|
paths.update(set(new.keys()))
|
|
|
|
res = defaultdict(dict)
|
|
for path in paths:
|
|
path_diff = _diff(
|
|
old.get(path, {}).get("data", {}),
|
|
new.get(path, {}).get("data", {}),
|
|
with_unchanged,
|
|
)
|
|
if path_diff:
|
|
res[path] = path_diff
|
|
return dict(res)
|
|
|
|
|
|
def format_dict(d):
|
|
ret = {}
|
|
for key, val in d.items():
|
|
if isinstance(val, dict):
|
|
new_val = format_dict(val)
|
|
elif isinstance(val, list):
|
|
new_val = str(val)
|
|
else:
|
|
new_val = val
|
|
ret[key] = new_val
|
|
return ret
|