Skip to content
Merged
17 changes: 16 additions & 1 deletion dvc/command/experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,12 @@ def baseline_styler(typ):


def show_experiments(
all_experiments, pager=True, no_timestamp=False, csv=False, **kwargs
all_experiments,
pager=True,
no_timestamp=False,
csv=False,
markdown=False,
**kwargs,
):
from funcy.seqs import flatten as flatten_list

Expand Down Expand Up @@ -473,6 +478,7 @@ def show_experiments(
header_styles=styles,
row_styles=row_styles,
csv=csv,
markdown=markdown,
)


Expand Down Expand Up @@ -530,6 +536,7 @@ def run(self):
iso=iso,
pager=not self.args.no_pager,
csv=self.args.csv,
markdown=self.args.markdown,
)
return 0

Expand Down Expand Up @@ -989,6 +996,14 @@ def add_parser(subparsers, parent_parser):
default=False,
help="Print output in csv format instead of a human-readable table.",
)
experiments_show_parser.add_argument(
"--md",
"--show-md",
action="store_true",
default=False,
dest="markdown",
help="Show tabulated output in the Markdown format (GFM).",
)
experiments_show_parser.add_argument(
"--precision",
type=int,
Expand Down
1 change: 1 addition & 0 deletions tests/unit/command/test_compat_flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def _id_gen(val) -> str:
(["experiments", "diff", "--show-md"], "markdown"),
(["experiments", "show", "--show-json"], "json"),
(["experiments", "show", "--show-csv"], "csv"),
(["experiments", "show", "--show-md"], "markdown"),
(["ls", "--show-json", "."], "json"),
(["metrics", "diff", "--show-json"], "json"),
(["metrics", "diff", "--show-md"], "markdown"),
Expand Down
227 changes: 138 additions & 89 deletions tests/unit/command/test_experiments.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import csv
import textwrap
from datetime import datetime

import pytest
Expand Down Expand Up @@ -283,104 +284,121 @@ def test_experiments_remove(dvc, scm, mocker, queue, clear_all, remote):
)


all_experiments = {
"workspace": {
"baseline": {
"data": {
"timestamp": None,
"params": {
"params.yaml": {
"data": {
"featurize": {"max_features": 3000, "ngrams": 1},
"parent": 20170428,
"train": {
"n_est": 100,
"min_split": 36,
},
def test_show_experiments_csv(capsys):
all_experiments = {
"workspace": {
"baseline": {
"data": {
"timestamp": None,
"params": {
"params.yaml": {
"data": {
"featurize": {
"max_features": 3000,
"ngrams": 1,
},
"parent": 20170428,
"train": {
"n_est": 100,
"min_split": 36,
},
}
}
}
},
"queued": False,
"running": False,
"executor": None,
"metrics": {
"scores.json": {
"data": {
"featurize": {"max_features": 3000, "ngrams": 1},
"avg_prec": 0.5843640011189556,
"roc_auc": 0.9544670443829399,
},
"queued": False,
"running": False,
"executor": None,
"metrics": {
"scores.json": {
"data": {
"featurize": {
"max_features": 3000,
"ngrams": 1,
},
"avg_prec": 0.5843640011189556,
"roc_auc": 0.9544670443829399,
}
}
}
},
},
}
}
}
},
"b05eecc666734e899f79af228ff49a7ae5a18cc0": {
"baseline": {
"data": {
"timestamp": datetime(2021, 8, 2, 16, 48, 14),
"params": {
"params.yaml": {
"data": {
"featurize": {"max_features": 3000, "ngrams": 1},
"parent": 20170428,
"train": {
"n_est": 100,
"min_split": 2,
},
},
"b05eecc666734e899f79af228ff49a7ae5a18cc0": {
"baseline": {
"data": {
"timestamp": datetime(2021, 8, 2, 16, 48, 14),
"params": {
"params.yaml": {
"data": {
"featurize": {
"max_features": 3000,
"ngrams": 1,
},
"parent": 20170428,
"train": {
"n_est": 100,
"min_split": 2,
},
}
}
}
},
"queued": False,
"running": False,
"executor": None,
"metrics": {
"scores.json": {
"data": {
"featurize": {"max_features": 3000, "ngrams": 1},
"avg_prec": 0.5325162867864254,
"roc_auc": 0.9106964878520005,
},
"queued": False,
"running": False,
"executor": None,
"metrics": {
"scores.json": {
"data": {
"featurize": {
"max_features": 3000,
"ngrams": 1,
},
"avg_prec": 0.5325162867864254,
"roc_auc": 0.9106964878520005,
}
}
}
},
"name": "master",
}
},
"ae99936461d6c3092934160f8beafe66a294f98d": {
"data": {
"timestamp": datetime(2021, 8, 31, 14, 56, 55),
"params": {
"params.yaml": {
"data": {
"featurize": {"max_features": 3000, "ngrams": 1},
"parent": 20170428,
"train": {
"n_est": 100,
"min_split": 36,
},
},
"name": "master",
}
},
"ae99936461d6c3092934160f8beafe66a294f98d": {
"data": {
"timestamp": datetime(2021, 8, 31, 14, 56, 55),
"params": {
"params.yaml": {
"data": {
"featurize": {
"max_features": 3000,
"ngrams": 1,
},
"parent": 20170428,
"train": {
"n_est": 100,
"min_split": 36,
},
}
}
}
},
"queued": True,
"running": True,
"executor": None,
"metrics": {
"scores.json": {
"data": {
"featurize": {"max_features": 3000, "ngrams": 1},
"avg_prec": 0.5843640011189556,
"roc_auc": 0.9544670443829399,
},
"queued": True,
"running": True,
"executor": None,
"metrics": {
"scores.json": {
"data": {
"featurize": {
"max_features": 3000,
"ngrams": 1,
},
"avg_prec": 0.5843640011189556,
"roc_auc": 0.9544670443829399,
}
}
}
},
"name": "exp-44136",
}
},
"name": "exp-44136",
}
},
},
},
}

}

def test_show_experiments(capsys):
show_experiments(
all_experiments, precision=None, fill_value="", iso=True, csv=True
)
Expand Down Expand Up @@ -408,6 +426,37 @@ def test_show_experiments(capsys):
)


def test_show_experiments_md(capsys):
all_experiments = {
"workspace": {
"baseline": {
"data": {
"timestamp": None,
"params": {"params.yaml": {"data": {"foo": 1}}},
"queued": False,
"running": False,
"executor": None,
"metrics": {
"scores.json": {"data": {"bar": 0.9544670443829399}}
},
}
}
},
}
show_experiments(
all_experiments, precision=None, fill_value="", iso=True, markdown=True
)
cap = capsys.readouterr()

assert cap.out == textwrap.dedent(
"""\
| Experiment | Created | bar | foo |
|--------------|-----------|--------------------|-------|
| workspace | | 0.9544670443829399 | 1 |\n
"""
)


@pytest.mark.parametrize("sort_order", ["asc", "desc"])
def test_show_experiments_sort_by(capsys, sort_order):
sort_experiments = {
Expand Down