hydraflow 0.7.4__tar.gz → 0.7.5__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {hydraflow-0.7.4 → hydraflow-0.7.5}/PKG-INFO +2 -2
- {hydraflow-0.7.4 → hydraflow-0.7.5}/README.md +1 -1
- {hydraflow-0.7.4 → hydraflow-0.7.5}/pyproject.toml +1 -1
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/__init__.py +9 -1
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/mlflow.py +87 -32
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/test_mlflow.py +7 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.devcontainer/devcontainer.json +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.devcontainer/postCreate.sh +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.devcontainer/starship.toml +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.gitattributes +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.github/workflows/ci.yaml +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.github/workflows/docs.yaml +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/.gitignore +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/LICENSE +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/apps/quickstart.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/docs/index.md +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/docs/usage/quickstart.md +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/hydraflow.yaml +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/mkdocs.yaml +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/cli.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/config.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/context.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/main.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/param.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/py.typed +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/run_collection.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/run_data.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/run_info.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/src/hydraflow/utils.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/cli/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/cli/conftest.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/cli/test_run.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/cli/test_show.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/cli/test_version.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/config/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/config/overrides.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/config/test_config.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/config/test_overrides.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/config/test_params.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/conftest.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/chdir.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/context.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/logging.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/rerun.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/test_chdir.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/test_context.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/test_logging.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/context/test_rerun.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/base.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/force_new_run.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/restart.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/skip.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/test_base.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/test_force_new_run.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/test_restart.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/main/test_skip.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/param/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/param/params.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/param/test_param.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/param/test_params.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/filter.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/run.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/test_collection.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/test_data.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/test_filter.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/test_info.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/run/test_run.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/utils/__init__.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/utils/test_run.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/utils/test_utils.py +0 -0
- {hydraflow-0.7.4 → hydraflow-0.7.5}/tests/utils/utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hydraflow
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.5
|
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
|
@@ -55,7 +55,7 @@ Description-Content-Type: text/markdown
|
|
55
55
|
[pypi-v-link]: https://pypi.org/project/hydraflow/
|
56
56
|
[python-v-image]: https://img.shields.io/pypi/pyversions/hydraflow.svg
|
57
57
|
[python-v-link]: https://pypi.org/project/hydraflow
|
58
|
-
[GHAction-image]: https://github.com/daizutabi/hydraflow/actions/workflows/ci.
|
58
|
+
[GHAction-image]: https://github.com/daizutabi/hydraflow/actions/workflows/ci.yaml/badge.svg?branch=main&event=push
|
59
59
|
[GHAction-link]: https://github.com/daizutabi/hydraflow/actions?query=event%3Apush+branch%3Amain
|
60
60
|
[codecov-image]: https://codecov.io/github/daizutabi/hydraflow/coverage.svg?branch=main
|
61
61
|
[codecov-link]: https://codecov.io/github/daizutabi/hydraflow?branch=main
|
@@ -10,7 +10,7 @@
|
|
10
10
|
[pypi-v-link]: https://pypi.org/project/hydraflow/
|
11
11
|
[python-v-image]: https://img.shields.io/pypi/pyversions/hydraflow.svg
|
12
12
|
[python-v-link]: https://pypi.org/project/hydraflow
|
13
|
-
[GHAction-image]: https://github.com/daizutabi/hydraflow/actions/workflows/ci.
|
13
|
+
[GHAction-image]: https://github.com/daizutabi/hydraflow/actions/workflows/ci.yaml/badge.svg?branch=main&event=push
|
14
14
|
[GHAction-link]: https://github.com/daizutabi/hydraflow/actions?query=event%3Apush+branch%3Amain
|
15
15
|
[codecov-image]: https://codecov.io/github/daizutabi/hydraflow/coverage.svg?branch=main
|
16
16
|
[codecov-link]: https://codecov.io/github/daizutabi/hydraflow?branch=main
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "hydraflow"
|
7
|
-
version = "0.7.
|
7
|
+
version = "0.7.5"
|
8
8
|
description = "Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments."
|
9
9
|
readme = "README.md"
|
10
10
|
license = { file = "LICENSE" }
|
@@ -3,7 +3,13 @@
|
|
3
3
|
from hydraflow.config import select_config, select_overrides
|
4
4
|
from hydraflow.context import chdir_artifact, log_run, start_run
|
5
5
|
from hydraflow.main import main
|
6
|
-
from hydraflow.mlflow import
|
6
|
+
from hydraflow.mlflow import (
|
7
|
+
list_run_ids,
|
8
|
+
list_run_paths,
|
9
|
+
list_runs,
|
10
|
+
search_runs,
|
11
|
+
set_experiment,
|
12
|
+
)
|
7
13
|
from hydraflow.run_collection import RunCollection
|
8
14
|
from hydraflow.utils import (
|
9
15
|
get_artifact_dir,
|
@@ -22,6 +28,8 @@ __all__ = [
|
|
22
28
|
"get_artifact_path",
|
23
29
|
"get_hydra_output_dir",
|
24
30
|
"get_overrides",
|
31
|
+
"list_run_ids",
|
32
|
+
"list_run_paths",
|
25
33
|
"list_runs",
|
26
34
|
"load_config",
|
27
35
|
"load_overrides",
|
@@ -153,18 +153,17 @@ def search_runs( # noqa: PLR0913
|
|
153
153
|
return RunCollection(runs) # type: ignore
|
154
154
|
|
155
155
|
|
156
|
-
def
|
156
|
+
def list_run_paths(
|
157
157
|
experiment_names: str | list[str] | None = None,
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
"""List all runs for the specified experiments.
|
158
|
+
*other: str,
|
159
|
+
) -> list[Path]:
|
160
|
+
"""List all run paths for the specified experiments.
|
162
161
|
|
163
|
-
This function retrieves all
|
162
|
+
This function retrieves all run paths for the given list of experiment names.
|
164
163
|
If no experiment names are provided (None), it defaults to searching all runs
|
165
164
|
for the currently active experiment. If an empty list is provided, the function
|
166
165
|
will search all runs for all experiments except the "Default" experiment.
|
167
|
-
The function returns the results as a `
|
166
|
+
The function returns the results as a list of `Path` objects.
|
168
167
|
|
169
168
|
Note:
|
170
169
|
The returned runs are sorted by their start time in ascending order.
|
@@ -174,27 +173,12 @@ def list_runs(
|
|
174
173
|
for runs. If None or an empty list is provided, the function will
|
175
174
|
search the currently active experiment or all experiments except
|
176
175
|
the "Default" experiment.
|
177
|
-
|
178
|
-
will search runs sequentially.
|
179
|
-
status (str | list[str] | int | list[int] | None): The status of the runs
|
180
|
-
to filter.
|
176
|
+
other (str): The parts of the run directory to join.
|
181
177
|
|
182
178
|
Returns:
|
183
|
-
|
184
|
-
specified experiments.
|
179
|
+
list[Path]: A list of run paths for the specified experiments.
|
185
180
|
|
186
181
|
"""
|
187
|
-
rc = _list_runs(experiment_names, n_jobs)
|
188
|
-
if status is None:
|
189
|
-
return rc
|
190
|
-
|
191
|
-
return rc.filter(status=status)
|
192
|
-
|
193
|
-
|
194
|
-
def _list_runs(
|
195
|
-
experiment_names: str | list[str] | None = None,
|
196
|
-
n_jobs: int = 0,
|
197
|
-
) -> RunCollection:
|
198
182
|
if isinstance(experiment_names, str):
|
199
183
|
experiment_names = [experiment_names]
|
200
184
|
|
@@ -202,14 +186,11 @@ def _list_runs(
|
|
202
186
|
experiments = mlflow.search_experiments()
|
203
187
|
experiment_names = [e.name for e in experiments if e.name != "Default"]
|
204
188
|
|
205
|
-
if n_jobs == 0:
|
206
|
-
return search_runs(experiment_names=experiment_names)
|
207
|
-
|
208
189
|
if experiment_names is None:
|
209
190
|
experiment_id = _get_experiment_id()
|
210
191
|
experiment_names = [mlflow.get_experiment(experiment_id).name]
|
211
192
|
|
212
|
-
|
193
|
+
run_paths: list[Path] = []
|
213
194
|
|
214
195
|
for name in experiment_names:
|
215
196
|
if experiment := mlflow.get_experiment_by_name(name):
|
@@ -217,9 +198,83 @@ def _list_runs(
|
|
217
198
|
|
218
199
|
if isinstance(uri, str):
|
219
200
|
path = get_artifact_dir(uri=uri)
|
220
|
-
|
201
|
+
run_paths.extend(p for p in path.iterdir() if p.is_dir())
|
202
|
+
|
203
|
+
if other:
|
204
|
+
return [p.joinpath(*other) for p in run_paths]
|
205
|
+
|
206
|
+
return run_paths
|
207
|
+
|
208
|
+
|
209
|
+
def list_run_ids(experiment_names: str | list[str] | None = None) -> list[str]:
|
210
|
+
"""List all run IDs for the specified experiments.
|
211
|
+
|
212
|
+
This function retrieves all runs for the given list of experiment names.
|
213
|
+
If no experiment names are provided (None), it defaults to searching all runs
|
214
|
+
for the currently active experiment. If an empty list is provided, the function
|
215
|
+
will search all runs for all experiments except the "Default" experiment.
|
216
|
+
The function returns the results as a list of string.
|
217
|
+
|
218
|
+
Note:
|
219
|
+
The returned runs are sorted by their start time in ascending order.
|
220
|
+
|
221
|
+
Args:
|
222
|
+
experiment_names (list[str] | None): List of experiment names to search
|
223
|
+
for runs. If None or an empty list is provided, the function will
|
224
|
+
search the currently active experiment or all experiments except
|
225
|
+
the "Default" experiment.
|
226
|
+
|
227
|
+
Returns:
|
228
|
+
list[str]: A list of run IDs for the specified experiments.
|
229
|
+
|
230
|
+
"""
|
231
|
+
return [run_dir.stem for run_dir in list_run_paths(experiment_names)]
|
232
|
+
|
233
|
+
|
234
|
+
def list_runs(
|
235
|
+
experiment_names: str | list[str] | None = None,
|
236
|
+
n_jobs: int = 0,
|
237
|
+
status: str | list[str] | int | list[int] | None = None,
|
238
|
+
) -> RunCollection:
|
239
|
+
"""List all runs for the specified experiments.
|
240
|
+
|
241
|
+
This function retrieves all runs for the given list of experiment names.
|
242
|
+
If no experiment names are provided (None), it defaults to searching all runs
|
243
|
+
for the currently active experiment. If an empty list is provided, the function
|
244
|
+
will search all runs for all experiments except the "Default" experiment.
|
245
|
+
The function returns the results as a `RunCollection` object.
|
246
|
+
|
247
|
+
Note:
|
248
|
+
The returned runs are sorted by their start time in ascending order.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
experiment_names (list[str] | None): List of experiment names to search
|
252
|
+
for runs. If None or an empty list is provided, the function will
|
253
|
+
search the currently active experiment or all experiments except
|
254
|
+
the "Default" experiment.
|
255
|
+
n_jobs (int): The number of jobs to run in parallel. If 0, the function
|
256
|
+
will search runs sequentially.
|
257
|
+
status (str | list[str] | int | list[int] | None): The status of the runs
|
258
|
+
to filter.
|
259
|
+
|
260
|
+
Returns:
|
261
|
+
RunCollection: A `RunCollection` instance containing the runs for the
|
262
|
+
specified experiments.
|
263
|
+
|
264
|
+
"""
|
265
|
+
run_ids = list_run_ids(experiment_names)
|
266
|
+
|
267
|
+
if n_jobs == 0:
|
268
|
+
runs = [mlflow.get_run(run_id) for run_id in run_ids]
|
269
|
+
|
270
|
+
else:
|
271
|
+
it = (joblib.delayed(mlflow.get_run)(run_id) for run_id in run_ids)
|
272
|
+
runs = joblib.Parallel(n_jobs, prefer="threads")(it)
|
221
273
|
|
222
|
-
it = (joblib.delayed(mlflow.get_run)(run_id) for run_id in run_ids)
|
223
|
-
runs = joblib.Parallel(n_jobs, prefer="threads")(it)
|
224
274
|
runs = sorted(runs, key=lambda run: run.info.start_time) # type: ignore
|
225
|
-
|
275
|
+
rc = RunCollection(runs) # type: ignore
|
276
|
+
|
277
|
+
if status is None:
|
278
|
+
return rc
|
279
|
+
|
280
|
+
return rc.filter(status=status)
|
@@ -92,3 +92,10 @@ def test_list_runs(experiment: Experiment, status, n, n_jobs, func):
|
|
92
92
|
experiment_names = func(experiment.name)
|
93
93
|
rc = list_runs(experiment_names=experiment_names, status=status, n_jobs=n_jobs)
|
94
94
|
assert len(rc) == n
|
95
|
+
|
96
|
+
|
97
|
+
def test_list_run_dirs(experiment: Experiment):
|
98
|
+
from hydraflow.mlflow import list_run_paths
|
99
|
+
|
100
|
+
dirs = list_run_paths(experiment.name, "artifacts")
|
101
|
+
assert all(d.is_dir() for d in dirs)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|