mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
live: Remove html generation
Remove commands/live. Remove LiveTask. Bump dvclive.
This commit is contained in:
@@ -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,
|
||||
]
|
||||
|
||||
|
||||
@@ -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="<path>",
|
||||
).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="<commit>",
|
||||
)
|
||||
live_diff_parser.set_defaults(func=CmdLiveDiff)
|
||||
@@ -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]
|
||||
|
||||
+1
-48
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user