hydraflow 0.12.2__py3-none-any.whl → 0.12.4__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/cli.py CHANGED
@@ -8,8 +8,6 @@ import typer
8
8
  from rich.console import Console
9
9
  from typer import Argument, Option
10
10
 
11
- from hydraflow.executor.io import get_job, load_config
12
-
13
11
  app = typer.Typer(add_completion=False)
14
12
  console = Console()
15
13
 
@@ -24,16 +22,20 @@ def run(
24
22
  ] = False,
25
23
  ) -> None:
26
24
  """Run a job."""
27
- import mlflow
28
25
 
26
+ from hydraflow.executor.io import get_job
29
27
  from hydraflow.executor.job import multirun, to_text
30
28
 
31
29
  job = get_job(name)
30
+
32
31
  if dry_run:
33
32
  typer.echo(to_text(job))
34
- else:
35
- mlflow.set_experiment(job.name)
36
- multirun(job)
33
+ raise typer.Exit
34
+
35
+ import mlflow
36
+
37
+ mlflow.set_experiment(job.name)
38
+ multirun(job)
37
39
 
38
40
 
39
41
  @app.command()
@@ -43,6 +45,8 @@ def show(
43
45
  """Show the hydraflow config."""
44
46
  from omegaconf import OmegaConf
45
47
 
48
+ from hydraflow.executor.io import get_job, load_config
49
+
46
50
  if name:
47
51
  cfg = get_job(name)
48
52
  else:
hydraflow/core/context.py CHANGED
@@ -8,8 +8,6 @@ from contextlib import contextmanager
8
8
  from pathlib import Path
9
9
  from typing import TYPE_CHECKING
10
10
 
11
- import mlflow
12
- import mlflow.artifacts
13
11
  from hydra.core.hydra_config import HydraConfig
14
12
 
15
13
  from hydraflow.core.io import get_artifact_dir
@@ -52,6 +50,8 @@ def log_run(
52
50
  ```
53
51
 
54
52
  """
53
+ import mlflow
54
+
55
55
  if config:
56
56
  log_params(config, synchronous=synchronous)
57
57
 
@@ -114,6 +114,8 @@ def start_run(
114
114
  Run: An MLflow Run object representing the started run.
115
115
 
116
116
  """
117
+ import mlflow
118
+
117
119
  with (
118
120
  mlflow.start_run(
119
121
  run_id=run_id,
hydraflow/core/io.py CHANGED
@@ -8,14 +8,13 @@ import urllib.request
8
8
  from pathlib import Path
9
9
  from typing import TYPE_CHECKING
10
10
 
11
- import mlflow
12
- import mlflow.artifacts
13
11
  from hydra.core.hydra_config import HydraConfig
14
- from mlflow.entities import Run
15
12
  from omegaconf import DictConfig, ListConfig, OmegaConf
16
13
 
17
14
  if TYPE_CHECKING:
18
- from collections.abc import Iterable, Iterator
15
+ from collections.abc import Callable, Iterable, Iterator
16
+
17
+ from mlflow.entities import Run
19
18
 
20
19
 
21
20
  def file_uri_to_path(uri: str) -> Path:
@@ -39,6 +38,8 @@ def get_artifact_dir(run: Run | None = None) -> Path:
39
38
  The local path to the directory where the artifacts are downloaded.
40
39
 
41
40
  """
41
+ import mlflow
42
+
42
43
  if run is None:
43
44
  uri = mlflow.get_artifact_uri()
44
45
  else:
@@ -141,6 +142,8 @@ def load_overrides(run: Run) -> ListConfig:
141
142
 
142
143
  def remove_run(run: Run | Iterable[Run]) -> None:
143
144
  """Remove the given run from the MLflow tracking server."""
145
+ from mlflow.entities import Run
146
+
144
147
  if not isinstance(run, Run):
145
148
  for r in run:
146
149
  remove_run(r)
@@ -151,6 +154,8 @@ def remove_run(run: Run | Iterable[Run]) -> None:
151
154
 
152
155
  def get_root_dir(uri: str | Path | None = None) -> Path:
153
156
  """Get the root directory for the MLflow tracking server."""
157
+ import mlflow
158
+
154
159
  if uri is not None:
155
160
  return Path(uri).absolute()
156
161
 
@@ -174,8 +179,29 @@ def get_experiment_name(path: Path) -> str | None:
174
179
  return None
175
180
 
176
181
 
182
+ def predicate_experiment_dir(
183
+ path: Path,
184
+ experiment_names: list[str] | Callable[[str], bool] | None = None,
185
+ ) -> bool:
186
+ """Predicate an experiment directory based on the path and experiment names."""
187
+ if not path.is_dir() or path.name in [".trash", "0"]:
188
+ return False
189
+
190
+ name = get_experiment_name(path)
191
+ if not name:
192
+ return False
193
+
194
+ if experiment_names is None:
195
+ return True
196
+
197
+ if isinstance(experiment_names, list):
198
+ return name in experiment_names
199
+
200
+ return experiment_names(name)
201
+
202
+
177
203
  def iter_experiment_dirs(
178
- experiment_names: str | list[str] | None = None,
204
+ experiment_names: str | list[str] | Callable[[str], bool] | None = None,
179
205
  root_dir: str | Path | None = None,
180
206
  ) -> Iterator[Path]:
181
207
  """Iterate over the experiment directories in the root directory."""
@@ -184,14 +210,12 @@ def iter_experiment_dirs(
184
210
 
185
211
  root_dir = get_root_dir(root_dir)
186
212
  for path in root_dir.iterdir():
187
- if path.is_dir() and path.name not in [".trash", "0"]:
188
- if name := get_experiment_name(path):
189
- if experiment_names is None or name in experiment_names:
190
- yield path
213
+ if predicate_experiment_dir(path, experiment_names):
214
+ yield path
191
215
 
192
216
 
193
217
  def iter_run_dirs(
194
- experiment_names: str | list[str] | None = None,
218
+ experiment_names: str | list[str] | Callable[[str], bool] | None = None,
195
219
  root_dir: str | Path | None = None,
196
220
  ) -> Iterator[Path]:
197
221
  """Iterate over the run directories in the root directory."""
@@ -202,7 +226,7 @@ def iter_run_dirs(
202
226
 
203
227
 
204
228
  def iter_artifacts_dirs(
205
- experiment_names: str | list[str] | None = None,
229
+ experiment_names: str | list[str] | Callable[[str], bool] | None = None,
206
230
  root_dir: str | Path | None = None,
207
231
  ) -> Iterator[Path]:
208
232
  """Iterate over the artifacts directories in the root directory."""
@@ -212,7 +236,7 @@ def iter_artifacts_dirs(
212
236
 
213
237
  def iter_artifact_paths(
214
238
  artifact_path: str | Path,
215
- experiment_names: str | list[str] | None = None,
239
+ experiment_names: str | list[str] | Callable[[str], bool] | None = None,
216
240
  root_dir: str | Path | None = None,
217
241
  ) -> Iterator[Path]:
218
242
  """Iterate over the artifact paths in the root directory."""
hydraflow/core/main.py CHANGED
@@ -39,13 +39,11 @@ from functools import wraps
39
39
  from typing import TYPE_CHECKING, TypeVar
40
40
 
41
41
  import hydra
42
- import mlflow
43
42
  from hydra.core.config_store import ConfigStore
44
43
  from hydra.core.hydra_config import HydraConfig
45
- from mlflow.entities import RunStatus
46
44
  from omegaconf import OmegaConf
47
45
 
48
- import hydraflow
46
+ from hydraflow.core.context import start_run
49
47
  from hydraflow.core.io import file_uri_to_path
50
48
 
51
49
  if TYPE_CHECKING:
@@ -55,7 +53,6 @@ if TYPE_CHECKING:
55
53
 
56
54
  from mlflow.entities import Run
57
55
 
58
- FINISHED = RunStatus.to_string(RunStatus.FINISHED)
59
56
 
60
57
  T = TypeVar("T")
61
58
 
@@ -88,6 +85,10 @@ def main(
88
85
  False.
89
86
 
90
87
  """
88
+ import mlflow
89
+ from mlflow.entities import RunStatus
90
+
91
+ finished = RunStatus.to_string(RunStatus.FINISHED)
91
92
 
92
93
  def decorator(app: Callable[[Run, T], None]) -> Callable[[], None]:
93
94
  ConfigStore.instance().store(config_name, node)
@@ -107,10 +108,10 @@ def main(
107
108
 
108
109
  if run_id and not rerun_finished:
109
110
  run = mlflow.get_run(run_id)
110
- if run.info.status == FINISHED:
111
+ if run.info.status == finished:
111
112
  return
112
113
 
113
- with hydraflow.start_run(config, run_id=run_id, chdir=chdir) as run:
114
+ with start_run(config, run_id=run_id, chdir=chdir) as run:
114
115
  app(run, config)
115
116
 
116
117
  return inner_decorator
hydraflow/core/mlflow.py CHANGED
@@ -10,8 +10,6 @@ from __future__ import annotations
10
10
  from typing import TYPE_CHECKING
11
11
 
12
12
  import joblib
13
- import mlflow
14
- import mlflow.artifacts
15
13
 
16
14
  from hydraflow.core.io import file_uri_to_path, get_artifact_dir
17
15
  from hydraflow.entities.run_collection import RunCollection
@@ -36,6 +34,8 @@ def log_params(config: Any, *, synchronous: bool | None = None) -> None:
36
34
  Defaults to None.
37
35
 
38
36
  """
37
+ import mlflow
38
+
39
39
  for key, value in iter_params(config):
40
40
  mlflow.log_param(key, value, synchronous=synchronous)
41
41
 
@@ -50,6 +50,8 @@ def log_text(from_dir: Path, pattern: str = "*.log") -> None:
50
50
  pattern (str): The pattern to match the logs.
51
51
 
52
52
  """
53
+ import mlflow
54
+
53
55
  artifact_dir = get_artifact_dir()
54
56
 
55
57
  for file in from_dir.glob(pattern):
@@ -88,6 +90,8 @@ def list_run_paths(
88
90
  list[Path]: A list of run paths for the specified experiments.
89
91
 
90
92
  """
93
+ import mlflow
94
+
91
95
  if isinstance(experiment_names, str):
92
96
  experiment_names = [experiment_names]
93
97
 
@@ -155,6 +159,8 @@ def list_runs(
155
159
  specified experiments.
156
160
 
157
161
  """
162
+ import mlflow
163
+
158
164
  run_ids = list_run_ids(experiment_names)
159
165
 
160
166
  if n_jobs == 0:
@@ -23,8 +23,6 @@ from dataclasses import dataclass, field
23
23
  from itertools import chain
24
24
  from typing import TYPE_CHECKING, Any, overload
25
25
 
26
- from mlflow.entities import RunStatus
27
-
28
26
  import hydraflow.core.param
29
27
  from hydraflow.core.config import iter_params, select_config, select_overrides
30
28
  from hydraflow.core.io import load_config
@@ -560,6 +558,8 @@ def filter_runs_by_status(
560
558
  A list of runs that match the specified status.
561
559
 
562
560
  """
561
+ from mlflow.entities import RunStatus
562
+
563
563
  if isinstance(status, str):
564
564
  if status.startswith("!"):
565
565
  status = status[1:].lower()
@@ -575,6 +575,8 @@ def filter_runs_by_status(
575
575
 
576
576
 
577
577
  def _to_lower(status: str | int) -> str:
578
+ from mlflow.entities import RunStatus
579
+
578
580
  if isinstance(status, str):
579
581
  return status.lower()
580
582
 
@@ -4,8 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from pandas import DataFrame
8
-
9
7
  from hydraflow.core.config import iter_params
10
8
  from hydraflow.core.io import load_config
11
9
 
@@ -13,6 +11,8 @@ if TYPE_CHECKING:
13
11
  from collections.abc import Iterable
14
12
  from typing import Any
15
13
 
14
+ from pandas import DataFrame
15
+
16
16
  from .run_collection import RunCollection
17
17
 
18
18
 
@@ -40,6 +40,8 @@ class RunCollectionData:
40
40
  A DataFrame containing the runs' configurations.
41
41
 
42
42
  """
43
+ from pandas import DataFrame
44
+
43
45
  values = [dict(iter_params(load_config(r))) for r in self._runs]
44
46
  return DataFrame(values)
45
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydraflow
3
- Version: 0.12.2
3
+ Version: 0.12.4
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
@@ -1,24 +1,24 @@
1
1
  hydraflow/__init__.py,sha256=f2KO2iF7um-nNmayNyEr7TWG4UICOXy7YAN1d3qu0OY,936
2
- hydraflow/cli.py,sha256=b-M368amGUblOOqOi7JuBsnzLuaNqgpTit9ZRj0qqac,1410
2
+ hydraflow/cli.py,sha256=clQ7PD_okuGhbrgQ0q8Ldbb8xY3u3He5hI_uBI4h1Q4,1470
3
3
  hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  hydraflow/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  hydraflow/core/config.py,sha256=SJzjgsO_kzB78_whJ3lmy7GlZvTvwZONH1BJBn8zCuI,3817
6
- hydraflow/core/context.py,sha256=QPyPg1xrTlmhviKNn-0nDY9bXcVky1zInqRqPN-VNhc,4741
7
- hydraflow/core/io.py,sha256=C207DsGAU4CLvlHySyyIl0_aKZ83ysJ-W_wNM2n4RPI,6754
8
- hydraflow/core/main.py,sha256=66-X2-IJVEcJ4XrEC2BIKNzdd_M1RfVIAHME8k70Jo0,5131
9
- hydraflow/core/mlflow.py,sha256=M3MhiChnMzKnKRmjBl4h_SRGkAZKL7GAmFr3DdzwRuQ,5666
6
+ hydraflow/core/context.py,sha256=L4OygMLbITwlWzq17Lh8VoXKKtjOJ3DBEVsBddKPSJ8,4741
7
+ hydraflow/core/io.py,sha256=6ZQYqxPUkIinFYqSQXJPzTSnuhfP1KfFchTNeNn-g6A,7311
8
+ hydraflow/core/main.py,sha256=dY8uUykS_AbzverrSWkXLyj98TjBPHAiMUf_l5met1U,5162
9
+ hydraflow/core/mlflow.py,sha256=OQJ3f2wkHJRb11ZK__HF4R8FyBEje7-NOqObpoanGhU,5704
10
10
  hydraflow/core/param.py,sha256=LHU9j9_7oA99igasoOyKofKClVr9FmGA3UABJ-KmyS0,4538
11
11
  hydraflow/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- hydraflow/entities/run_collection.py,sha256=E8IRBgxCnJE_IPCaSmS2mc9GtDXXLBfc7GHv07d2j98,19635
13
- hydraflow/entities/run_data.py,sha256=Y2_Lc-BdQ7nXhcEIjdHGHIkLrXsmAktOftESEwYOY8o,1602
12
+ hydraflow/entities/run_collection.py,sha256=4sfZWXaS7kqnVCo9GyB3pN6BaSUCkA-ZqSSl5JBLNhk,19682
13
+ hydraflow/entities/run_data.py,sha256=lz8HPxG0iz1Jf9FU6HTFW4gcAc3N2pgMyAPqAIK6I74,1644
14
14
  hydraflow/entities/run_info.py,sha256=FRC6ICOlzB2u_xi_33Qs-YZLt677UotuNbYqI7XSmHY,1017
15
15
  hydraflow/executor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  hydraflow/executor/conf.py,sha256=2dv6_PlsynRmia-fGZlmBEVt8GopT0f32N13qY7tYnM,402
17
17
  hydraflow/executor/io.py,sha256=yZMcBVmAbPZZ82cAXhgiJfj9p8WvHmzOCMBg_vtEVek,1509
18
18
  hydraflow/executor/job.py,sha256=IL7ek0Vwa3Bl_gANq0wCbldNCUclo8YBckeEeO6W6xg,4852
19
19
  hydraflow/executor/parser.py,sha256=_Rfund3FDgrXitTt_znsTpgEtMDqZ_ICynaB_Zje14Q,14561
20
- hydraflow-0.12.2.dist-info/METADATA,sha256=8i5Ejzdakw6X9t6ddhuNGW0DaeQT9N3-xVCWrmX1QfQ,4549
21
- hydraflow-0.12.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
- hydraflow-0.12.2.dist-info/entry_points.txt,sha256=XI0khPbpCIUo9UPqkNEpgh-kqK3Jy8T7L2VCWOdkbSM,48
23
- hydraflow-0.12.2.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
24
- hydraflow-0.12.2.dist-info/RECORD,,
20
+ hydraflow-0.12.4.dist-info/METADATA,sha256=CT9bb--1HhyO_tcahfCTzSUBH2nWt7i2lY2pS3Dac38,4549
21
+ hydraflow-0.12.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
+ hydraflow-0.12.4.dist-info/entry_points.txt,sha256=XI0khPbpCIUo9UPqkNEpgh-kqK3Jy8T7L2VCWOdkbSM,48
23
+ hydraflow-0.12.4.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
24
+ hydraflow-0.12.4.dist-info/RECORD,,