hydraflow 0.6.0__py3-none-any.whl → 0.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hydraflow/__init__.py +1 -2
- hydraflow/context.py +20 -42
- hydraflow/mlflow.py +6 -10
- hydraflow/utils.py +18 -6
- {hydraflow-0.6.0.dist-info → hydraflow-0.6.1.dist-info}/METADATA +1 -1
- hydraflow-0.6.1.dist-info/RECORD +14 -0
- hydraflow-0.6.0.dist-info/RECORD +0 -14
- {hydraflow-0.6.0.dist-info → hydraflow-0.6.1.dist-info}/WHEEL +0 -0
- {hydraflow-0.6.0.dist-info → hydraflow-0.6.1.dist-info}/licenses/LICENSE +0 -0
hydraflow/__init__.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
"""Integrate Hydra and MLflow to manage and track machine learning experiments."""
|
2
2
|
|
3
3
|
from .config import select_config, select_overrides
|
4
|
-
from .context import chdir_artifact,
|
4
|
+
from .context import chdir_artifact, log_run, start_run
|
5
5
|
from .mlflow import list_runs, search_runs, set_experiment
|
6
6
|
from .run_collection import RunCollection
|
7
7
|
from .utils import (
|
@@ -17,7 +17,6 @@ from .utils import (
|
|
17
17
|
__all__ = [
|
18
18
|
"RunCollection",
|
19
19
|
"chdir_artifact",
|
20
|
-
"chdir_hydra_output",
|
21
20
|
"get_artifact_dir",
|
22
21
|
"get_artifact_path",
|
23
22
|
"get_hydra_output_dir",
|
hydraflow/context.py
CHANGED
@@ -13,6 +13,7 @@ import mlflow.artifacts
|
|
13
13
|
from hydra.core.hydra_config import HydraConfig
|
14
14
|
|
15
15
|
from hydraflow.mlflow import log_params
|
16
|
+
from hydraflow.utils import get_artifact_dir
|
16
17
|
|
17
18
|
if TYPE_CHECKING:
|
18
19
|
from collections.abc import Iterator
|
@@ -69,24 +70,26 @@ def log_run(
|
|
69
70
|
raise
|
70
71
|
|
71
72
|
finally:
|
72
|
-
|
73
|
+
log_text(output_dir)
|
73
74
|
|
74
75
|
|
75
|
-
def
|
76
|
-
"""Log
|
76
|
+
def log_text(directory: Path, pattern: str = "*.log") -> None:
|
77
|
+
"""Log text files in the given directory as artifacts.
|
78
|
+
|
79
|
+
Append the text files to the existing text file in the artifact directory.
|
77
80
|
|
78
81
|
Args:
|
79
|
-
|
82
|
+
directory (Path): The directory to find the logs in.
|
83
|
+
pattern (str): The pattern to match the logs.
|
80
84
|
|
81
85
|
"""
|
82
|
-
|
83
|
-
artifact_dir = Path(mlflow.artifacts.download_artifacts(uri))
|
86
|
+
artifact_dir = get_artifact_dir()
|
84
87
|
|
85
|
-
for
|
86
|
-
if not
|
88
|
+
for file in directory.glob(pattern):
|
89
|
+
if not file.is_file():
|
87
90
|
continue
|
88
91
|
|
89
|
-
file_artifact = artifact_dir /
|
92
|
+
file_artifact = artifact_dir / file.name
|
90
93
|
if file_artifact.exists():
|
91
94
|
text = file_artifact.read_text()
|
92
95
|
if not text.endswith("\n"):
|
@@ -94,8 +97,8 @@ def log_hydra(output_dir: Path) -> None:
|
|
94
97
|
else:
|
95
98
|
text = ""
|
96
99
|
|
97
|
-
text +=
|
98
|
-
mlflow.log_text(text,
|
100
|
+
text += file.read_text()
|
101
|
+
mlflow.log_text(text, file.name)
|
99
102
|
|
100
103
|
|
101
104
|
@contextmanager
|
@@ -174,29 +177,7 @@ def start_run( # noqa: PLR0913
|
|
174
177
|
|
175
178
|
|
176
179
|
@contextmanager
|
177
|
-
def
|
178
|
-
"""Change the current working directory to the hydra output directory.
|
179
|
-
|
180
|
-
This context manager changes the current working directory to the hydra output
|
181
|
-
directory. It ensures that the directory is changed back to the original
|
182
|
-
directory after the context is exited.
|
183
|
-
"""
|
184
|
-
curdir = Path.cwd()
|
185
|
-
path = HydraConfig.get().runtime.output_dir
|
186
|
-
|
187
|
-
os.chdir(path)
|
188
|
-
try:
|
189
|
-
yield Path(path)
|
190
|
-
|
191
|
-
finally:
|
192
|
-
os.chdir(curdir)
|
193
|
-
|
194
|
-
|
195
|
-
@contextmanager
|
196
|
-
def chdir_artifact(
|
197
|
-
run: Run,
|
198
|
-
artifact_path: str | None = None,
|
199
|
-
) -> Iterator[Path]:
|
180
|
+
def chdir_artifact(run: Run | None = None) -> Iterator[Path]:
|
200
181
|
"""Change the current working directory to the artifact directory of the given run.
|
201
182
|
|
202
183
|
This context manager changes the current working directory to the artifact
|
@@ -204,19 +185,16 @@ def chdir_artifact(
|
|
204
185
|
to the original directory after the context is exited.
|
205
186
|
|
206
187
|
Args:
|
207
|
-
run (Run): The run to get the artifact directory from.
|
208
|
-
artifact_path (str | None): The artifact path.
|
188
|
+
run (Run | None): The run to get the artifact directory from.
|
209
189
|
|
210
190
|
"""
|
211
191
|
curdir = Path.cwd()
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
)
|
192
|
+
artifact_dir = get_artifact_dir(run)
|
193
|
+
|
194
|
+
os.chdir(artifact_dir)
|
216
195
|
|
217
|
-
os.chdir(path)
|
218
196
|
try:
|
219
|
-
yield
|
197
|
+
yield artifact_dir
|
220
198
|
|
221
199
|
finally:
|
222
200
|
os.chdir(curdir)
|
hydraflow/mlflow.py
CHANGED
@@ -16,7 +16,6 @@ Key Features:
|
|
16
16
|
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
-
from pathlib import Path
|
20
19
|
from typing import TYPE_CHECKING
|
21
20
|
|
22
21
|
import joblib
|
@@ -28,8 +27,11 @@ from mlflow.tracking.fluent import SEARCH_MAX_RESULTS_PANDAS, _get_experiment_id
|
|
28
27
|
|
29
28
|
from hydraflow.config import iter_params
|
30
29
|
from hydraflow.run_collection import RunCollection
|
30
|
+
from hydraflow.utils import get_artifact_dir
|
31
31
|
|
32
32
|
if TYPE_CHECKING:
|
33
|
+
from pathlib import Path
|
34
|
+
|
33
35
|
from mlflow.entities.experiment import Experiment
|
34
36
|
|
35
37
|
|
@@ -211,16 +213,10 @@ def _list_runs(
|
|
211
213
|
|
212
214
|
for name in experiment_names:
|
213
215
|
if experiment := mlflow.get_experiment_by_name(name):
|
214
|
-
|
215
|
-
|
216
|
-
if isinstance(loc, str):
|
217
|
-
if loc.startswith("file:"):
|
218
|
-
path = Path(mlflow.artifacts.download_artifacts(loc))
|
219
|
-
elif Path(loc).is_dir():
|
220
|
-
path = Path(loc)
|
221
|
-
else:
|
222
|
-
continue # no cov
|
216
|
+
uri = experiment.artifact_location
|
223
217
|
|
218
|
+
if isinstance(uri, str):
|
219
|
+
path = get_artifact_dir(uri=uri)
|
224
220
|
run_ids.extend(file.stem for file in path.iterdir() if file.is_dir())
|
225
221
|
|
226
222
|
it = (joblib.delayed(mlflow.get_run)(run_id) for run_id in run_ids)
|
hydraflow/utils.py
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import shutil
|
6
|
+
import urllib.parse
|
7
|
+
import urllib.request
|
6
8
|
from pathlib import Path
|
7
9
|
from typing import TYPE_CHECKING
|
8
10
|
|
@@ -16,30 +18,40 @@ if TYPE_CHECKING:
|
|
16
18
|
from collections.abc import Iterable
|
17
19
|
|
18
20
|
|
19
|
-
def get_artifact_dir(run: Run | None = None) -> Path:
|
21
|
+
def get_artifact_dir(run: Run | None = None, uri: str | None = None) -> Path:
|
20
22
|
"""Retrieve the artifact directory for the given run.
|
21
23
|
|
22
24
|
This function uses MLflow to get the artifact directory for the given run.
|
23
25
|
|
24
26
|
Args:
|
25
27
|
run (Run | None): The run object. Defaults to None.
|
28
|
+
uri (str | None): The URI of the artifact. Defaults to None.
|
26
29
|
|
27
30
|
Returns:
|
28
31
|
The local path to the directory where the artifacts are downloaded.
|
29
32
|
|
30
33
|
"""
|
31
|
-
|
34
|
+
if run is not None and uri is not None:
|
35
|
+
raise ValueError("Cannot provide both run and uri")
|
36
|
+
|
37
|
+
if run is None and uri is None:
|
38
|
+
uri = mlflow.get_artifact_uri()
|
39
|
+
elif run:
|
40
|
+
uri = run.info.artifact_uri
|
32
41
|
|
33
42
|
if not isinstance(uri, str):
|
34
43
|
raise NotImplementedError
|
35
44
|
|
36
45
|
if uri.startswith("file:"):
|
37
|
-
return
|
46
|
+
return file_uri_to_path(uri)
|
47
|
+
|
48
|
+
return Path(uri)
|
38
49
|
|
39
|
-
if Path(uri).is_dir():
|
40
|
-
return Path(uri)
|
41
50
|
|
42
|
-
|
51
|
+
def file_uri_to_path(uri: str) -> Path:
|
52
|
+
"""Convert a file URI to a local path."""
|
53
|
+
path = urllib.parse.urlparse(uri).path
|
54
|
+
return Path(urllib.request.url2pathname(path)) # for Windows
|
43
55
|
|
44
56
|
|
45
57
|
def get_artifact_path(run: Run | None, path: str) -> Path:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hydraflow
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.1
|
4
4
|
Summary: Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments.
|
5
5
|
Project-URL: Documentation, https://daizutabi.github.io/hydraflow/
|
6
6
|
Project-URL: Source, https://github.com/daizutabi/hydraflow
|
@@ -0,0 +1,14 @@
|
|
1
|
+
hydraflow/__init__.py,sha256=VPIPNNCyjMAkWBbdvB7Ltwe3QWoc2FwuqkV8uJM5JoM,809
|
2
|
+
hydraflow/config.py,sha256=MNX9da5bPVDcjnpji7Cm9ndK6ura92pt361m4PRh6_E,4326
|
3
|
+
hydraflow/context.py,sha256=3xfKhMozkKFqtWeOp9Gie0A5o5URMta4US6iVD5TcLU,6002
|
4
|
+
hydraflow/mlflow.py,sha256=imD3XL0RTlpnKrkyvO8FNy_Bv6hwSfLiOu1yJuL40ck,8773
|
5
|
+
hydraflow/param.py,sha256=yu1aMNXRLegXGDL-68vwIkfeDF9CaU784WZENGLwl7Q,4572
|
6
|
+
hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
hydraflow/run_collection.py,sha256=2GRVOy87_2SPjHuCzzUvRNugO_grtFUVjtTfhznwBAc,27444
|
8
|
+
hydraflow/run_data.py,sha256=dpyyfnuH9mCtIZeigMo1iFQo9bafMdEL4i4uI2l0UqY,1525
|
9
|
+
hydraflow/run_info.py,sha256=Jf5wrIjRLIV1-k-obHDqwKHa6j_ZonrY8od-rXlbtMo,1024
|
10
|
+
hydraflow/utils.py,sha256=a9i5PEJn8Ssowv9dqHadAihZXlsqtVjHZ9MZvkPq1bY,4747
|
11
|
+
hydraflow-0.6.1.dist-info/METADATA,sha256=FzLPE3L9VlZdrYOicnzTda7BhHuLTU0-WRz02TLgt6c,4700
|
12
|
+
hydraflow-0.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
13
|
+
hydraflow-0.6.1.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
|
14
|
+
hydraflow-0.6.1.dist-info/RECORD,,
|
hydraflow-0.6.0.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
hydraflow/__init__.py,sha256=9XO9FD3uiTTPN6X6UAC9FtkJjEqUQZNqpoAmSrjUHfI,855
|
2
|
-
hydraflow/config.py,sha256=MNX9da5bPVDcjnpji7Cm9ndK6ura92pt361m4PRh6_E,4326
|
3
|
-
hydraflow/context.py,sha256=rc43zvE2ueki0zEzorCMIthD9cho_PkbLLJYF9WgDqY,6562
|
4
|
-
hydraflow/mlflow.py,sha256=h2S_A2wElr_1lAq0D1wkoEfdtDZpPuWFNRcO8mV_VrA,8932
|
5
|
-
hydraflow/param.py,sha256=yu1aMNXRLegXGDL-68vwIkfeDF9CaU784WZENGLwl7Q,4572
|
6
|
-
hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
hydraflow/run_collection.py,sha256=2GRVOy87_2SPjHuCzzUvRNugO_grtFUVjtTfhznwBAc,27444
|
8
|
-
hydraflow/run_data.py,sha256=dpyyfnuH9mCtIZeigMo1iFQo9bafMdEL4i4uI2l0UqY,1525
|
9
|
-
hydraflow/run_info.py,sha256=Jf5wrIjRLIV1-k-obHDqwKHa6j_ZonrY8od-rXlbtMo,1024
|
10
|
-
hydraflow/utils.py,sha256=oXjcyfQBbPzJNTh3_CbZfl23zgJS-mbNM9GAWBwsn8c,4349
|
11
|
-
hydraflow-0.6.0.dist-info/METADATA,sha256=xUib1EsbG3Es5jFx0cSkF1QItfTuciBHYM1040GqFzA,4700
|
12
|
-
hydraflow-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
13
|
-
hydraflow-0.6.0.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
|
14
|
-
hydraflow-0.6.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|