Skip to content

Commit

Permalink
metrics: rework metrics implementation (#3658)
Browse files Browse the repository at this point in the history
Dropping support for all types except json and yaml. No more xpath
support.

Fixes #3572
  • Loading branch information
efiop authored Apr 22, 2020
1 parent 52369bd commit 45944dd
Show file tree
Hide file tree
Showing 17 changed files with 376 additions and 1,436 deletions.
133 changes: 38 additions & 95 deletions dvc/command/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
def show_metrics(
metrics, all_branches=False, all_tags=False, all_commits=False
):
"""
Args:
metrics (list): Where each element is either a `list`
if an xpath was specified, otherwise a `str`
"""
from flatten_json import flatten
from dvc.utils.diff import format_dict

# When `metrics` contains a `None` key, it means that some files
# specified as `targets` in `repo.metrics.show` didn't contain any metrics.
missing = metrics.pop(None, None)
Expand All @@ -28,21 +26,13 @@ def show_metrics(
logger.info("{branch}:".format(branch=branch))

for fname, metric in val.items():
if isinstance(metric, dict):
lines = list(metric.values())
elif isinstance(metric, list):
lines = metric
else:
lines = metric.splitlines()
if not isinstance(metric, dict):
logger.info("\t{}: {}".format(fname, str(metric)))
continue

if len(lines) > 1:
logger.info("\t{fname}:".format(fname=fname))

for line in lines:
logger.info("\t\t{content}".format(content=line))

else:
logger.info("\t{}: {}".format(fname, metric))
logger.info("\t{}:".format(fname))
for key, value in flatten(format_dict(metric), ".").items():
logger.info("\t\t{}: {}".format(key, value))

if missing:
raise BadMetricError(missing)
Expand All @@ -53,35 +43,25 @@ def run(self):
try:
metrics = self.repo.metrics.show(
self.args.targets,
typ=self.args.type,
xpath=self.args.xpath,
all_branches=self.args.all_branches,
all_tags=self.args.all_tags,
all_commits=self.args.all_commits,
recursive=self.args.recursive,
)

show_metrics(
metrics,
self.args.all_branches,
self.args.all_tags,
self.args.all_commits,
)
except DvcException:
logger.exception("failed to show metrics")
return 1

return 0

if self.args.show_json:
import json

class CmdMetricsModify(CmdBase):
def run(self):
try:
self.repo.metrics.modify(
self.args.path, typ=self.args.type, xpath=self.args.xpath
)
logger.info(json.dumps(metrics))
else:
show_metrics(
metrics,
self.args.all_branches,
self.args.all_tags,
self.args.all_commits,
)
except DvcException:
logger.exception("failed to modify metric file settings")
logger.exception("failed to show metrics")
return 1

return 0
Expand All @@ -90,9 +70,7 @@ def run(self):
class CmdMetricsAdd(CmdBase):
def run(self):
try:
self.repo.metrics.add(
self.args.path, self.args.type, self.args.xpath
)
self.repo.metrics.add(self.args.path)
except DvcException:
msg = "failed to add metric file '{}'".format(self.args.path)
logger.exception(msg)
Expand All @@ -114,11 +92,14 @@ def run(self):


def _show_diff(diff):
from collections import OrderedDict

from dvc.utils.diff import table

rows = []
for fname, mdiff in diff.items():
for metric, change in mdiff.items():
sorted_mdiff = OrderedDict(sorted(mdiff.items()))
for metric, change in sorted_mdiff.items():
rows.append(
[
fname,
Expand All @@ -138,9 +119,8 @@ def run(self):
a_rev=self.args.a_rev,
b_rev=self.args.b_rev,
targets=self.args.targets,
typ=self.args.type,
xpath=self.args.xpath,
recursive=self.args.recursive,
all=self.args.all,
)

if self.args.show_json:
Expand Down Expand Up @@ -185,32 +165,9 @@ def add_parser(subparsers, parent_parser):
help=METRICS_ADD_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
metrics_add_parser.add_argument(
"-t", "--type", help="Type of metrics (json/yaml).", metavar="<type>",
)
metrics_add_parser.add_argument(
"-x", "--xpath", help="json/yaml path.", metavar="<path>",
)
metrics_add_parser.add_argument("path", help="Path to a metric file.")
metrics_add_parser.set_defaults(func=CmdMetricsAdd)

METRICS_MODIFY_HELP = "Modify metric default formatting."
metrics_modify_parser = metrics_subparsers.add_parser(
"modify",
parents=[parent_parser],
description=append_doc_link(METRICS_MODIFY_HELP, "metrics/modify"),
help=METRICS_MODIFY_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
metrics_modify_parser.add_argument(
"-t", "--type", help="Type of metrics (json/yaml).", metavar="<type>",
)
metrics_modify_parser.add_argument(
"-x", "--xpath", help="json/yaml path.", metavar="<path>",
)
metrics_modify_parser.add_argument("path", help="Path to a metric file.")
metrics_modify_parser.set_defaults(func=CmdMetricsModify)

METRICS_SHOW_HELP = "Print metrics, with optional formatting."
metrics_show_parser = metrics_subparsers.add_parser(
"show",
Expand All @@ -224,19 +181,6 @@ def add_parser(subparsers, parent_parser):
nargs="*",
help="Metric files or directories (see -R) to show",
)
metrics_show_parser.add_argument(
"-t",
"--type",
help=(
"Type of metrics (json/yaml). "
"It can be detected by the file extension automatically. "
"Unsupported types will be treated as raw."
),
metavar="<type>",
)
metrics_show_parser.add_argument(
"-x", "--xpath", help="json/yaml path.", metavar="<path>",
)
metrics_show_parser.add_argument(
"-a",
"--all-branches",
Expand Down Expand Up @@ -267,6 +211,12 @@ def add_parser(subparsers, parent_parser):
"metric files."
),
)
metrics_show_parser.add_argument(
"--show-json",
action="store_true",
default=False,
help="Show output in JSON format.",
)
metrics_show_parser.set_defaults(func=CmdMetricsShow)

METRICS_DIFF_HELP = "Show changes in metrics between commits"
Expand Down Expand Up @@ -295,19 +245,6 @@ def add_parser(subparsers, parent_parser):
),
metavar="<paths>",
)
metrics_diff_parser.add_argument(
"-t",
"--type",
help=(
"Type of metrics (json/yaml). "
"It can be detected by the file extension automatically. "
"Unsupported types will be treated as raw."
),
metavar="<type>",
)
metrics_diff_parser.add_argument(
"-x", "--xpath", help="json/yaml path.", metavar="<path>",
)
metrics_diff_parser.add_argument(
"-R",
"--recursive",
Expand All @@ -318,6 +255,12 @@ def add_parser(subparsers, parent_parser):
"metric files."
),
)
metrics_diff_parser.add_argument(
"--all",
action="store_true",
default=False,
help="Show unchanged metrics as well.",
)
metrics_diff_parser.add_argument(
"--show-json",
action="store_true",
Expand Down
1 change: 1 addition & 0 deletions dvc/remote/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def get(self, md5):
return self.checksum_to_path_info(md5).url

def exists(self, path_info):
assert is_working_tree(self.repo.tree)
assert path_info.scheme == "local"
return self.repo.tree.exists(fspath_py35(path_info))

Expand Down
5 changes: 0 additions & 5 deletions dvc/repo/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ def add(self, *args, **kwargs):

return add(self.repo, *args, **kwargs)

def modify(self, *args, **kwargs):
from dvc.repo.metrics.modify import modify

return modify(self.repo, *args, **kwargs)

def show(self, *args, **kwargs):
from dvc.repo.metrics.show import show

Expand Down
6 changes: 2 additions & 4 deletions dvc/repo/metrics/add.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from dvc.repo.metrics.modify import modify


def add(repo, path, typ=None, xpath=None):
if not typ:
typ = "raw"
modify(repo, path, typ, xpath)
def add(repo, path):
modify(repo, path)
8 changes: 6 additions & 2 deletions dvc/repo/metrics/diff.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import dvc.utils.diff
from dvc.utils.diff import format_dict, diff as _diff
from dvc.exceptions import NoMetricsError


Expand All @@ -13,7 +13,11 @@ def _get_metrics(repo, *args, rev=None, **kwargs):


def diff(repo, *args, a_rev=None, b_rev=None, **kwargs):
with_unchanged = kwargs.pop("all", False)

old = _get_metrics(repo, *args, **kwargs, rev=(a_rev or "HEAD"))
new = _get_metrics(repo, *args, **kwargs, rev=b_rev)

return dvc.utils.diff.diff(old, new)
return _diff(
format_dict(old), format_dict(new), with_unchanged=with_unchanged
)
22 changes: 1 addition & 21 deletions dvc/repo/metrics/modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@


@locked
def modify(repo, path, typ=None, xpath=None, delete=False):
supported_types = ["raw", "json", "csv", "tsv", "hcsv", "htsv"]
def modify(repo, path, delete=False):
outs = repo.find_outs_by_path(path)
assert len(outs) == 1
out = outs[0]
Expand All @@ -14,25 +13,6 @@ def modify(repo, path, typ=None, xpath=None, delete=False):
msg = "output '{}' scheme '{}' is not supported for metrics"
raise DvcException(msg.format(out.path, out.path_info.scheme))

if typ is not None:
typ = typ.lower().strip()
if typ not in ["raw", "json", "csv", "tsv", "hcsv", "htsv"]:
msg = (
"metric type '{typ}' is not supported, "
"must be one of [{types}]"
)
raise DvcException(
msg.format(typ=typ, types=", ".join(supported_types))
)
if not isinstance(out.metric, dict):
out.metric = {}
out.metric[out.PARAM_METRIC_TYPE] = typ

if xpath is not None:
if not isinstance(out.metric, dict):
out.metric = {}
out.metric[out.PARAM_METRIC_XPATH] = xpath

if delete:
out.metric = None

Expand Down
Loading

0 comments on commit 45944dd

Please sign in to comment.