diff --git a/dvc/repo/live.py b/dvc/repo/live.py index f53007e890..f860c41907 100644 --- a/dvc/repo/live.py +++ b/dvc/repo/live.py @@ -12,12 +12,17 @@ from dvc.repo import Repo -def create_summary(out): +LIVE_IMAGES_PATH = "images" +LIVE_HTML_PATH = "html" +LIVE_SCALARS_PATH = "scalars" + + +def create_live_html(out): assert out.live and out.live["html"] metrics, plots = out.repo.live.show(str(out.path_info)) - html_path = out.path_info.fspath + "_dvc_plots" + html_path = out.path_info / LIVE_HTML_PATH index_path = render( out.repo, plots, metrics=metrics, path=html_path, refresh_seconds=5 @@ -46,8 +51,15 @@ def show(self, target: str, revs: List[str] = None): revs = ["workspace", *revs] metrics_path = target + ".json" + images_path = os.path.join(target, LIVE_IMAGES_PATH) + scalars_path = os.path.join(target, LIVE_SCALARS_PATH) metrics = self.repo.metrics.show(targets=[metrics_path]) - plots = self.repo.plots.show(target, recursive=True, revs=revs) + + plots = self.repo.plots.show( + targets=[str(scalars_path), str(images_path)], + recursive=True, + revs=revs, + ) return metrics, plots diff --git a/dvc/stage/monitor.py b/dvc/stage/monitor.py index 9461c6022a..06eaa14015 100644 --- a/dvc/stage/monitor.py +++ b/dvc/stage/monitor.py @@ -6,7 +6,7 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Callable, List -from dvc.repo.live import create_summary +from dvc.repo.live import create_live_html from dvc.stage.decorators import relock_repo from dvc.stage.exceptions import StageCmdFailedError @@ -86,7 +86,7 @@ class LiveTask(MonitorTask): error_cls = LiveKilledError def __init__(self, stage: "Stage", out: "Output", proc: subprocess.Popen): - super().__init__(stage, functools.partial(create_summary, out), proc) + super().__init__(stage, functools.partial(create_live_html, out), proc) def after_run(self): # make sure summary is prepared for all the data diff --git a/dvc/stage/utils.py b/dvc/stage/utils.py index 462f761253..ba33a7ec86 100644 --- a/dvc/stage/utils.py +++ b/dvc/stage/utils.py @@ -90,6 +90,7 @@ def _load_live_output( assert bool(live) != bool(live_no_cache) path = live or live_no_cache + outs += loads_from( stage, [path], diff --git a/tests/func/test_live.py b/tests/func/test_live.py index f6989895fc..f1a8bd759a 100644 --- a/tests/func/test_live.py +++ b/tests/func/test_live.py @@ -7,6 +7,7 @@ from dvc import stage as stage_module from dvc.render.utils import get_files +from dvc.repo.live import LIVE_HTML_PATH, LIVE_SCALARS_PATH LIVE_SCRIPT = dedent( """ @@ -111,6 +112,8 @@ def test_export_config(tmp_dir, dvc, mocker, live_stage, summary, html): def test_live_provides_metrics(tmp_dir, dvc, live_stage): live_stage(summary=True, live="logs") + assert (tmp_dir / "logs").is_dir() + assert (tmp_dir / "logs.json").is_file() assert dvc.metrics.show() == { "": { @@ -122,24 +125,24 @@ def test_live_provides_metrics(tmp_dir, dvc, live_stage): } } - assert (tmp_dir / "logs").is_dir() plots_data = dvc.plots.show() files = get_files(plots_data) - assert os.path.join("logs", "accuracy.tsv") in files - assert os.path.join("logs", "loss.tsv") in files + assert os.path.join("logs", LIVE_SCALARS_PATH, "accuracy.tsv") in files + assert os.path.join("logs", LIVE_SCALARS_PATH, "loss.tsv") in files def test_live_provides_no_metrics(tmp_dir, dvc, live_stage): live_stage(summary=False, live="logs") + assert (tmp_dir / "logs").is_dir() + assert not (tmp_dir / "logs.json").is_file() assert dvc.metrics.show() == {"": {}} - assert (tmp_dir / "logs").is_dir() plots_data = dvc.plots.show() files = get_files(plots_data) - assert os.path.join("logs", "accuracy.tsv") in files - assert os.path.join("logs", "loss.tsv") in files + assert os.path.join("logs", LIVE_SCALARS_PATH, "accuracy.tsv") in files + assert os.path.join("logs", LIVE_SCALARS_PATH, "loss.tsv") in files @pytest.mark.parametrize("typ", ("live", "live_no_cache")) @@ -159,10 +162,15 @@ def test_experiments_track_summary(tmp_dir, scm, dvc, live_stage, typ): def test_live_html(tmp_dir, dvc, live_stage, html): live_stage(html=html, live="logs") - assert (tmp_dir / "logs_dvc_plots" / "index.html").is_file() == html + print((tmp_dir / "logs" / LIVE_HTML_PATH)) + assert (tmp_dir / "logs" / LIVE_HTML_PATH / "index.html").is_file() == html if html: - html_text = (tmp_dir / "logs_dvc_plots" / "index.html").read_text() + html_text = ( + tmp_dir / "logs" / LIVE_HTML_PATH / "index.html" + ).read_text() assert 'http-equiv="refresh"' in html_text + assert "logs.json" in html_text + assert f"plot_logs_{LIVE_SCALARS_PATH}" in html_text @pytest.fixture