hydraflow 0.3.2__py3-none-any.whl → 0.3.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/__init__.py CHANGED
@@ -1,19 +1,27 @@
1
1
  """Integrate Hydra and MLflow to manage and track machine learning experiments."""
2
2
 
3
- from .context import chdir_artifact, chdir_hydra, log_run, start_run, watch
3
+ from .context import chdir_artifact, chdir_hydra_output, log_run, start_run, watch
4
4
  from .mlflow import list_runs, search_runs, set_experiment
5
5
  from .progress import multi_tasks_progress, parallel_progress
6
6
  from .run_collection import RunCollection
7
- from .utils import get_artifact_dir, get_hydra_output_dir, load_config
7
+ from .utils import (
8
+ get_artifact_dir,
9
+ get_hydra_output_dir,
10
+ get_overrides,
11
+ load_config,
12
+ load_overrides,
13
+ )
8
14
 
9
15
  __all__ = [
10
16
  "RunCollection",
11
17
  "chdir_artifact",
12
- "chdir_hydra",
18
+ "chdir_hydra_output",
13
19
  "get_artifact_dir",
14
20
  "get_hydra_output_dir",
21
+ "get_overrides",
15
22
  "list_runs",
16
23
  "load_config",
24
+ "load_overrides",
17
25
  "log_run",
18
26
  "multi_tasks_progress",
19
27
  "parallel_progress",
hydraflow/config.py CHANGED
@@ -44,12 +44,25 @@ def iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
44
44
  if config is None:
45
45
  return
46
46
 
47
+ if isinstance(config, list) and all(isinstance(x, str) for x in config):
48
+ config = _from_dotlist(config)
49
+
47
50
  if not isinstance(config, DictConfig | ListConfig):
48
51
  config = OmegaConf.create(config) # type: ignore
49
52
 
50
53
  yield from _iter_params(config, prefix)
51
54
 
52
55
 
56
+ def _from_dotlist(config: list[str]) -> dict[str, str]:
57
+ result = {}
58
+ for item in config:
59
+ if "=" in item:
60
+ key, value = item.split("=", 1)
61
+ result[key.strip()] = value.strip()
62
+
63
+ return result
64
+
65
+
53
66
  def _iter_params(config: object, prefix: str = "") -> Iterator[tuple[str, Any]]:
54
67
  if isinstance(config, DictConfig):
55
68
  for key, value in config.items():
hydraflow/context.py CHANGED
@@ -239,7 +239,7 @@ class Handler(PatternMatchingEventHandler):
239
239
 
240
240
 
241
241
  @contextmanager
242
- def chdir_hydra() -> Iterator[Path]:
242
+ def chdir_hydra_output() -> Iterator[Path]:
243
243
  """Change the current working directory to the hydra output directory.
244
244
 
245
245
  This context manager changes the current working directory to the hydra output
hydraflow/param.py CHANGED
@@ -34,7 +34,10 @@ def match(param: str, value: Any) -> bool:
34
34
  if isinstance(value, tuple) and (m := _match_tuple(param, value)) is not None:
35
35
  return m
36
36
 
37
- if isinstance(value, int | float | str):
37
+ if isinstance(value, str):
38
+ return param == value
39
+
40
+ if isinstance(value, int | float):
38
41
  return type(value)(param) == value
39
42
 
40
43
  return param == str(value)
@@ -24,12 +24,12 @@ from itertools import chain
24
24
  from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, overload
25
25
 
26
26
  from mlflow.entities import RunStatus
27
- from polars.dataframe import DataFrame
28
27
 
29
28
  import hydraflow.param
30
- from hydraflow.config import collect_params, iter_params
29
+ from hydraflow.config import iter_params
31
30
  from hydraflow.run_data import RunCollectionData
32
31
  from hydraflow.run_info import RunCollectionInfo
32
+ from hydraflow.utils import load_config
33
33
 
34
34
  if TYPE_CHECKING:
35
35
  from collections.abc import Callable, Iterator
@@ -516,7 +516,7 @@ class RunCollection:
516
516
  in the collection.
517
517
 
518
518
  """
519
- return (func(config, *args, **kwargs) for config in self.data.config)
519
+ return (func(load_config(run), *args, **kwargs) for run in self)
520
520
 
521
521
  def map_uri(
522
522
  self,
@@ -599,16 +599,6 @@ class RunCollection:
599
599
 
600
600
  return {key: RunCollection(runs) for key, runs in grouped_runs.items()}
601
601
 
602
- @property
603
- def config(self) -> DataFrame:
604
- """Get the runs' configurations as a polars DataFrame.
605
-
606
- Returns:
607
- A polars DataFrame containing the runs' configurations.
608
-
609
- """
610
- return DataFrame(self.map_config(collect_params))
611
-
612
602
 
613
603
  def _param_matches(run: Run, key: str, value: Any) -> bool:
614
604
  params = run.data.params
hydraflow/run_data.py CHANGED
@@ -4,10 +4,13 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from hydraflow.utils import load_config
7
+ from polars.dataframe import DataFrame
8
+
9
+ from hydraflow.config import collect_params
8
10
 
9
11
  if TYPE_CHECKING:
10
- from omegaconf import DictConfig
12
+ from collections.abc import Iterable
13
+ from typing import Any
11
14
 
12
15
  from hydraflow.run_collection import RunCollection
13
16
 
@@ -19,16 +22,36 @@ class RunCollectionData:
19
22
  self._runs = runs
20
23
 
21
24
  @property
22
- def params(self) -> list[dict[str, str]]:
25
+ def params(self) -> dict[str, list[str]]:
23
26
  """Get the parameters for each run in the collection."""
24
- return [run.data.params for run in self._runs]
27
+ return _to_dict(run.data.params for run in self._runs)
25
28
 
26
29
  @property
27
- def metrics(self) -> list[dict[str, float]]:
30
+ def metrics(self) -> dict[str, list[float]]:
28
31
  """Get the metrics for each run in the collection."""
29
- return [run.data.metrics for run in self._runs]
32
+ return _to_dict(run.data.metrics for run in self._runs)
30
33
 
31
34
  @property
32
- def config(self) -> list[DictConfig]:
33
- """Get the configuration for each run in the collection."""
34
- return [load_config(run) for run in self._runs]
35
+ def config(self) -> DataFrame:
36
+ """Get the runs' configurations as a polars DataFrame.
37
+
38
+ Returns:
39
+ A polars DataFrame containing the runs' configurations.
40
+
41
+ """
42
+ return DataFrame(self._runs.map_config(collect_params))
43
+
44
+
45
+ def _to_dict(it: Iterable[dict[str, Any]]) -> dict[str, list[Any]]:
46
+ """Convert an iterable of dictionaries to a dictionary of lists."""
47
+ data = list(it)
48
+ if not data:
49
+ return {}
50
+
51
+ keys = []
52
+ for d in data:
53
+ for key in d:
54
+ if key not in keys:
55
+ keys.append(key)
56
+
57
+ return {key: [x.get(key) for x in data] for key in keys}
hydraflow/utils.py CHANGED
@@ -86,3 +86,28 @@ def load_config(run: Run) -> DictConfig:
86
86
  """
87
87
  path = get_artifact_dir(run) / ".hydra/config.yaml"
88
88
  return OmegaConf.load(path) # type: ignore
89
+
90
+
91
+ def get_overrides() -> list[str]:
92
+ """Retrieve the overrides for the current run."""
93
+ return HydraConfig.get().overrides.task
94
+
95
+
96
+ def load_overrides(run: Run) -> list[str]:
97
+ """Load the overrides for a given run.
98
+
99
+ This function loads the overrides for the provided Run instance
100
+ by downloading the overrides file from the MLflow artifacts and
101
+ loading it using OmegaConf. It returns an empty config if
102
+ `.hydra/overrides.yaml` is not found in the run's artifact directory.
103
+
104
+ Args:
105
+ run (Run): The Run instance for which to load the overrides.
106
+
107
+ Returns:
108
+ The loaded overrides as a list of strings. Returns an empty list
109
+ if the overrides file is not found.
110
+
111
+ """
112
+ path = get_artifact_dir(run) / ".hydra/overrides.yaml"
113
+ return [str(x) for x in OmegaConf.load(path)]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hydraflow
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments.
5
5
  Project-URL: Documentation, https://github.com/daizutabi/hydraflow
6
6
  Project-URL: Source, https://github.com/daizutabi/hydraflow
@@ -0,0 +1,16 @@
1
+ hydraflow/__init__.py,sha256=HVVsSRK2BXtHdoueFNRva924th49_lCV5zYb2c8qdaw,811
2
+ hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
3
+ hydraflow/config.py,sha256=dRG4cFqDH0vBX109q0C46jiXdvbYoYgu651D6KlmmxQ,3021
4
+ hydraflow/context.py,sha256=p1UYHvSCPrp10cBn9TUI9mXMv0h_I0Eou24Wp1rZZ0k,8740
5
+ hydraflow/mlflow.py,sha256=JELqXFCJ9MsEJaQWT5dyleTFk8BHL7cQwW_gzhkPoIg,8729
6
+ hydraflow/param.py,sha256=CO-6PRlnHo-7hlY_P6j_cGlC7vPY6t-Rr7p3OqeqDyU,1995
7
+ hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
8
+ hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ hydraflow/run_collection.py,sha256=OiPibp8zM4gpsvqpHr9sBh4_1zmHRuXfPcmen7xND-s,24792
10
+ hydraflow/run_data.py,sha256=qeFX1iRvNAorXA9QQIjzr0o2_82TI44eZKp7llKG8GI,1549
11
+ hydraflow/run_info.py,sha256=sMXOo20ClaRIommMEzuAbO_OrcXx7M1Yt4FMV7spxz0,998
12
+ hydraflow/utils.py,sha256=qNN0JDbQJweTkcRMpZwMXTIuK_LVpoDJ2rOwfe01f3U,3500
13
+ hydraflow-0.3.4.dist-info/METADATA,sha256=DJuHernRtS9IjpWRqCIt-yDXdFBDioSf3f3-T15D-yI,3840
14
+ hydraflow-0.3.4.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
15
+ hydraflow-0.3.4.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
16
+ hydraflow-0.3.4.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- hydraflow/__init__.py,sha256=6sfM1ashUkfrNf7lOR7raFYhG8YdOAJR-JgRNL_IVo8,698
2
- hydraflow/asyncio.py,sha256=-i1C8KAmNDImrjHnk92Csaa1mpjdK8Vp4ZVaQV-l94s,6634
3
- hydraflow/config.py,sha256=6V5omJ3-h9-ZwVpM5rTA4FqE_mu8urTy9OqV4zG79gw,2671
4
- hydraflow/context.py,sha256=412884e84qIEYtbxJT4roYsKfldGaTKzgo6Q1FAsT5U,8733
5
- hydraflow/mlflow.py,sha256=JELqXFCJ9MsEJaQWT5dyleTFk8BHL7cQwW_gzhkPoIg,8729
6
- hydraflow/param.py,sha256=QkLeQvt5ZF3GyRGnhP66o0GElc1ZOOCxCL7PdyfIUbA,1939
7
- hydraflow/progress.py,sha256=zvKX1HCN8_xDOsgYOEcLLhkhdPdep-U8vHrc0XZ-6SQ,6163
8
- hydraflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- hydraflow/run_collection.py,sha256=0SCParNkSoXw7Ule-FH3az578Hhu-1TKGyrFNXxTciU,25082
10
- hydraflow/run_data.py,sha256=ZXVr0PHyufH9wwyQYWtpE4_MheAC2ArTW_J1TTMQ4iI,983
11
- hydraflow/run_info.py,sha256=sMXOo20ClaRIommMEzuAbO_OrcXx7M1Yt4FMV7spxz0,998
12
- hydraflow/utils.py,sha256=aRdBdToKfvHhN2qFiRzPHIdQxS7cTpZREQeP8HreAfI,2676
13
- hydraflow-0.3.2.dist-info/METADATA,sha256=RktfWMufNqrMU2CBSbmVxwE_e7VPbLhVYQHgBKXuh9Q,3840
14
- hydraflow-0.3.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
15
- hydraflow-0.3.2.dist-info/licenses/LICENSE,sha256=IGdDrBPqz1O0v_UwCW-NJlbX9Hy9b3uJ11t28y2srmY,1062
16
- hydraflow-0.3.2.dist-info/RECORD,,