Skip to content

Commit 9eb04c2

Browse files
authored
studio: add subdir to live metrics post messages to support live experiments in monorepos (#787)
1 parent 7305452 commit 9eb04c2

File tree

5 files changed

+35
-7
lines changed

5 files changed

+35
-7
lines changed

pyproject.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ classifiers = [
3131
]
3232
dynamic = ["version"]
3333
dependencies = [
34-
"dvc>=3.33.3",
34+
"dvc>=3.47.0",
3535
"dvc-render>=1.0.0,<2",
36-
"dvc-studio-client>=0.17.1,<1",
36+
"dvc-studio-client>=0.20,<1",
3737
"funcy",
3838
"gto",
3939
"ruamel.yaml",
40-
"scmrepo"
40+
"scmrepo>=3,<4"
4141
]
4242

4343
[project.optional-dependencies]

src/dvclive/live.py

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import PIL
1818

1919
from dvc.exceptions import DvcException
20+
from dvc.utils.studio import get_subrepo_relpath
2021
from funcy import set_in
2122
from ruamel.yaml.representer import RepresenterError
2223

@@ -141,6 +142,7 @@ def __init__(
141142
self._baseline_rev: str = os.getenv(env.DVC_EXP_BASELINE_REV, NULL_SHA)
142143
self._exp_name: Optional[str] = exp_name or os.getenv(env.DVC_EXP_NAME)
143144
self._exp_message: Optional[str] = exp_message
145+
self._subdir: Optional[str] = None
144146
self._experiment_rev: Optional[str] = None
145147
self._inside_dvc_exp: bool = False
146148
self._inside_dvc_pipeline: bool = False
@@ -240,6 +242,8 @@ def _init_dvc(self): # noqa: C901
240242
if self._inside_dvc_pipeline:
241243
return
242244

245+
self._subdir = get_subrepo_relpath(self._dvc_repo)
246+
243247
if self._save_dvc_exp:
244248
mark_dvclive_only_started(self._exp_name)
245249
self._include_untracked.append(self.dir)

src/dvclive/studio.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,16 @@ def get_dvc_studio_config(live: Live):
9696
return get_studio_config(dvc_studio_config=config)
9797

9898

99-
def post_to_studio(live: Live, event: Literal["start", "data", "done"]):
99+
def post_to_studio(live: Live, event: Literal["start", "data", "done"]): # noqa: C901
100100
if event in live._studio_events_to_skip:
101101
return
102102

103103
kwargs = {}
104-
if event == "start" and live._exp_message:
105-
kwargs["message"] = live._exp_message
104+
if event == "start":
105+
if message := live._exp_message:
106+
kwargs["message"] = message
107+
if subdir := live._subdir:
108+
kwargs["subdir"] = subdir
106109
elif event == "data":
107110
metrics, params, plots = get_studio_updates(live)
108111
kwargs["step"] = live.step # type: ignore

tests/conftest.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import pytest
55
from dvc_studio_client.env import DVC_STUDIO_TOKEN, DVC_STUDIO_URL, STUDIO_REPO_URL
66

7+
from dvclive.utils import rel_path
8+
79

810
@pytest.fixture()
911
def tmp_dir(tmp_path, monkeypatch):
@@ -19,12 +21,19 @@ def mocked_dvc_repo(tmp_dir, mocker):
1921
_dvc_repo.scm.get_ref.return_value = None
2022
_dvc_repo.scm.no_commits = False
2123
_dvc_repo.experiments.save.return_value = "e" * 40
22-
_dvc_repo.root_dir = tmp_dir
24+
_dvc_repo.root_dir = _dvc_repo.scm.root_dir = tmp_dir
25+
_dvc_repo.fs.relpath = rel_path
2326
_dvc_repo.config = {}
2427
mocker.patch("dvclive.live.get_dvc_repo", return_value=_dvc_repo)
2528
return _dvc_repo
2629

2730

31+
@pytest.fixture()
32+
def mocked_dvc_subrepo(tmp_dir, mocker, mocked_dvc_repo):
33+
mocked_dvc_repo.root_dir = tmp_dir / "subdir"
34+
return mocked_dvc_repo
35+
36+
2837
@pytest.fixture()
2938
def dvc_repo(tmp_dir):
3039
from dvc.repo import Repo

tests/test_post_to_studio.py

+12
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ def test_post_to_studio(tmp_dir, mocked_dvc_repo, mocked_studio_post):
8181
)
8282

8383

84+
def test_post_to_studio_subrepo(tmp_dir, mocked_dvc_subrepo, mocked_studio_post):
85+
live = Live()
86+
live.log_param("fooparam", 1)
87+
88+
mocked_post, _ = mocked_studio_post
89+
90+
mocked_post.assert_called_with(
91+
"https://0.0.0.0/api/live",
92+
**get_studio_call("start", exp_name=live._exp_name, subdir="subdir"),
93+
)
94+
95+
8496
def test_post_to_studio_failed_data_request(
8597
tmp_dir, mocker, mocked_dvc_repo, mocked_studio_post
8698
):

0 commit comments

Comments
 (0)