From 70b57d4703348d17447e9d95626b1d5c151605e9 Mon Sep 17 00:00:00 2001 From: David de la Iglesia Castro Date: Tue, 5 Apr 2022 11:14:54 +0200 Subject: [PATCH] live: Remove html generation Remove commands/live. Remove LiveTask. Bump dvclive. --- dvc/cli/parser.py | 2 - dvc/commands/live.py | 101 -------------------------------- dvc/repo/__init__.py | 2 - dvc/repo/live.py | 49 +--------------- dvc/stage/monitor.py | 21 ------- dvc/stage/run.py | 8 --- setup.cfg | 3 +- tests/func/test_live.py | 34 ----------- tests/unit/command/test_live.py | 40 ------------- 9 files changed, 3 insertions(+), 257 deletions(-) delete mode 100644 dvc/commands/live.py delete mode 100644 tests/unit/command/test_live.py diff --git a/dvc/cli/parser.py b/dvc/cli/parser.py index 007908c4e..012b6cb73 100644 --- a/dvc/cli/parser.py +++ b/dvc/cli/parser.py @@ -27,7 +27,6 @@ from dvc.commands import ( imp_url, init, install, - live, ls, machine, metrics, @@ -86,7 +85,6 @@ COMMANDS = [ stage, experiments, check_ignore, - live, machine, ] diff --git a/dvc/commands/live.py b/dvc/commands/live.py deleted file mode 100644 index e08e6d21e..000000000 --- a/dvc/commands/live.py +++ /dev/null @@ -1,101 +0,0 @@ -import argparse - -from dvc.cli.command import CmdBase -from dvc.cli.utils import fix_subparsers -from dvc.commands import completion -from dvc.ui import ui - - -class CmdLive(CmdBase): - UNINITIALIZED = True - - def _run(self, target, revs=None): - from dvc_render import render_html - - from dvc.render.match import match_renderers - - metrics, plots = self.repo.live.show(target=target, revs=revs) - - if plots: - from pathlib import Path - - output = Path.cwd() / (self.args.target + "_html") / "index.html" - - renderers = match_renderers( - plots, templates_dir=self.repo.plots.templates_dir - ) - index_path = render_html(renderers, output, metrics) - ui.write(index_path.as_uri()) - return 0 - return 1 - - -class CmdLiveShow(CmdLive): - def run(self): - return self._run(self.args.target) - - -class CmdLiveDiff(CmdLive): - def run(self): - return self._run(self.args.target, self.args.revs) - - -def shared_parent_parser(): - parent_parser = argparse.ArgumentParser(add_help=False) - parent_parser.add_argument( - "target", help="Logs dir to produce summary from" - ).complete = completion.DIR - parent_parser.add_argument( - "-o", - "--out", - default=None, - help="Destination path to save plots to", - metavar="", - ).complete = completion.DIR - return parent_parser - - -def add_parser(subparsers, parent_parser): - LIVE_DESCRIPTION = ( - "Commands to visualize and compare dvclive-produced logs." - ) - live_parser = subparsers.add_parser( - "live", - parents=[parent_parser], - formatter_class=argparse.RawDescriptionHelpFormatter, - description=LIVE_DESCRIPTION, - ) - live_subparsers = live_parser.add_subparsers( - dest="cmd", - help="Use `dvc live CMD --help` to display command-specific help.", - ) - - fix_subparsers(live_subparsers) - - SHOW_HELP = "Visualize dvclive directory content." - live_show_parser = live_subparsers.add_parser( - "show", - parents=[parent_parser, shared_parent_parser()], - help=SHOW_HELP, - formatter_class=argparse.RawDescriptionHelpFormatter, - ) - live_show_parser.set_defaults(func=CmdLiveShow) - - DIFF_HELP = ( - "Show multiple versions of dvclive data, " - "by plotting it in single view." - ) - live_diff_parser = live_subparsers.add_parser( - "diff", - parents=[parent_parser, shared_parent_parser()], - help=DIFF_HELP, - formatter_class=argparse.RawDescriptionHelpFormatter, - ) - live_diff_parser.add_argument( - "--revs", - nargs="*", - default=None, - help="Git revision (e.g. SHA, branch, tag)", - metavar="", - ) - live_diff_parser.set_defaults(func=CmdLiveDiff) diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index dbbf08e08..e807d8c01 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -155,7 +155,6 @@ class Repo: from dvc.fs.git import GitFileSystem from dvc.fs.local import localfs from dvc.lock import LockNoop, make_lock - from dvc.repo.live import Live from dvc.repo.metrics import Metrics from dvc.repo.params import Params from dvc.repo.plots import Plots @@ -209,7 +208,6 @@ class Repo: self.metrics = Metrics(self) self.plots = Plots(self) self.params = Params(self) - self.live = Live(self) self.stage_collection_error_handler: Optional[ Callable[[str, Exception], None] diff --git a/dvc/repo/live.py b/dvc/repo/live.py index 40a349de0..b339c7363 100644 --- a/dvc/repo/live.py +++ b/dvc/repo/live.py @@ -1,41 +1,10 @@ import logging -import os -from typing import TYPE_CHECKING, List, Optional - -from dvc_render import render_html -from funcy import once_per_args - -from dvc.render.match import match_renderers +from typing import TYPE_CHECKING, Optional logger = logging.getLogger(__name__) if TYPE_CHECKING: from dvc.output import Output - from dvc.repo import Repo - - -@once_per_args -def webbrowser_open(url: str) -> int: - from dvc.ui import ui - - return ui.open_browser(url) - - -def create_summary(out): - assert out.live and out.live["html"] - - metrics, plots = out.repo.live.show(out.fs_path) - - html_path = os.path.join(out.fs_path + "_dvc_plots", "index.html") - - renderers = match_renderers( - plots, templates_dir=out.repo.plots.templates_dir - ) - index_path = render_html( - renderers, output_file=html_path, metrics=metrics, refresh_seconds=5 - ) - if out.repo.config["plots"].get("auto_open", False): - webbrowser_open(index_path) def summary_fs_path(out: "Output") -> Optional[str]: @@ -48,19 +17,3 @@ def summary_fs_path(out: "Output") -> Optional[str]: if has_summary: return out.fs.path.with_suffix(out.fs_path, ".json") return None - - -class Live: - def __init__(self, repo: "Repo"): - self.repo = repo - - def show(self, target: str, revs: List[str] = None): - if revs: - revs = ["workspace", *revs] - - metrics_path = target + ".json" - - metrics = self.repo.metrics.show(targets=[metrics_path]) - plots = self.repo.plots.show(target, recursive=True, revs=revs) - - return metrics, plots diff --git a/dvc/stage/monitor.py b/dvc/stage/monitor.py index 44e48c77c..c7e2f22e4 100644 --- a/dvc/stage/monitor.py +++ b/dvc/stage/monitor.py @@ -6,13 +6,10 @@ import threading from dataclasses import dataclass from typing import TYPE_CHECKING, Callable, List -from dvc.repo.live import create_summary from dvc.stage.decorators import relock_repo from dvc.stage.exceptions import StageCmdFailedError -from dvc.ui import ui if TYPE_CHECKING: - from dvc.output import Output from dvc.stage import Stage @@ -81,24 +78,6 @@ class CheckpointTask(MonitorTask): callback_func() -class LiveTask(MonitorTask): - name = "live" - SIGNAL_FILE = "DVC_LIVE" - error_cls = LiveKilledError - - def __init__(self, stage: "Stage", out: "Output", proc: subprocess.Popen): - self.output_path = os.path.join( - os.getcwd(), out.fs_path + "_dvc_plots", "index.html" - ) - ui.write(f"Live summary will be created at:\n{self.output_path}") - super().__init__(stage, functools.partial(create_summary, out), proc) - - def after_run(self): - # make sure summary is prepared for all the data - self.execute() - ui.write(f"Live summary has been created at:\n{self.output_path}") - - class Monitor: AWAIT: float = 1.0 diff --git a/dvc/stage/run.py b/dvc/stage/run.py index 4b77cdde9..7287fe76a 100644 --- a/dvc/stage/run.py +++ b/dvc/stage/run.py @@ -4,8 +4,6 @@ import signal import subprocess import threading -from funcy import first - from dvc.stage.monitor import Monitor from dvc.utils import fix_env @@ -116,12 +114,6 @@ def _get_monitor_tasks(stage, checkpoint_func, proc): result.append(CheckpointTask(stage, checkpoint_func, proc)) - live = first(o for o in stage.outs if (o.live and o.live["html"])) - if live: - from .monitor import LiveTask - - result.append(LiveTask(stage, live, proc)) - return result diff --git a/setup.cfg b/setup.cfg index adb038031..d3db330b4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -74,6 +74,7 @@ install_requires = jaraco.windows>=5.7.0; python_version < '3.8' and sys_platform == 'win32' scmrepo==0.0.18 dvc-render==0.0.4 + dvclive>=0.7.2 [options.extras_require] all = @@ -148,7 +149,7 @@ tests = types-toml>=0.10.4 # optional dependencies pywin32>=225; sys_platform == 'win32' - dvclive[image]==0.6.0 + dvclive[image]==0.7.2 [options.packages.find] exclude = diff --git a/tests/func/test_live.py b/tests/func/test_live.py index b3186ba97..236b1b08c 100644 --- a/tests/func/test_live.py +++ b/tests/func/test_live.py @@ -215,40 +215,6 @@ def test_live_checkpoints_resume( assert checkpoints_metric(results, "logs.json", "metric2") == [8, 6, 4, 2] -@pytest.mark.parametrize("auto_open", [False, True]) -def test_dvc_generates_html_during_run( - tmp_dir, dvc, mocker, live_stage, auto_open -): - if auto_open: - with dvc.config.edit() as conf: - conf["plots"]["auto_open"] = True - - show_spy = mocker.spy(dvc.live, "show") - webbrowser_open = mocker.patch("dvc.repo.live.webbrowser_open") - - # make sure script takes more time to execute than one monitor sleep cycle - monitor_await_time = 0.01 - mocker.patch("dvc.stage.run.Monitor.AWAIT", monitor_await_time) - - script = dedent( - """ - from dvclive import Live - import sys - import time - metrics_logger = Live() - metrics_logger.log("loss", 1/2) - metrics_logger.log("accuracy", 1/2) - metrics_logger.next_step() - time.sleep({})""".format( - str(monitor_await_time * 10) - ) - ) - live_stage(live="logs", code=script) - - assert show_spy.call_count == 2 - assert webbrowser_open.call_count == (2 if auto_open else 0) - - def test_dvclive_stage_with_different_wdir(tmp_dir, scm, dvc): (tmp_dir / "subdir").gen("train.py", LIVE_SCRIPT) (tmp_dir / "subdir" / "params.yaml").dump({"foo": 1}) diff --git a/tests/unit/command/test_live.py b/tests/unit/command/test_live.py deleted file mode 100644 index 18911f3dd..000000000 --- a/tests/unit/command/test_live.py +++ /dev/null @@ -1,40 +0,0 @@ -from dvc.cli import parse_args -from dvc.commands.live import CmdLiveDiff, CmdLiveShow - - -def test_live_diff(dvc, mocker): - cli_args = parse_args( - [ - "live", - "diff", - "--out", - "result.extension", - "target", - "--revs", - "HEAD", - "rev1", - ] - ) - assert cli_args.func == CmdLiveDiff - - cmd = cli_args.func(cli_args) - m = mocker.patch("dvc.repo.live.Live.show", return_value=({}, {})) - - assert cmd.run() == 1 - - m.assert_called_once_with(target="target", revs=["HEAD", "rev1"]) - - -def test_live_show(dvc, mocker): - cli_args = parse_args( - ["live", "show", "-o", "result.extension", "datafile"] - ) - assert cli_args.func == CmdLiveShow - - cmd = cli_args.func(cli_args) - - m = mocker.patch("dvc.repo.live.Live.show", return_value=({}, {})) - - assert cmd.run() == 1 - - m.assert_called_once_with(target="datafile", revs=None)