hydraflow 0.4.5__tar.gz → 0.4.6__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. {hydraflow-0.4.5 → hydraflow-0.4.6}/.devcontainer/devcontainer.json +1 -0
  2. {hydraflow-0.4.5 → hydraflow-0.4.6}/.devcontainer/postCreate.sh +4 -3
  3. {hydraflow-0.4.5 → hydraflow-0.4.6}/PKG-INFO +3 -2
  4. {hydraflow-0.4.5 → hydraflow-0.4.6}/pyproject.toml +8 -3
  5. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/__init__.py +2 -0
  6. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/utils.py +16 -6
  7. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_app.py +9 -5
  8. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_log_run.py +9 -3
  9. hydraflow-0.4.6/tests/test_utils.py +34 -0
  10. {hydraflow-0.4.5 → hydraflow-0.4.6}/.devcontainer/starship.toml +0 -0
  11. {hydraflow-0.4.5 → hydraflow-0.4.6}/.gitattributes +0 -0
  12. {hydraflow-0.4.5 → hydraflow-0.4.6}/.gitignore +0 -0
  13. {hydraflow-0.4.5 → hydraflow-0.4.6}/LICENSE +0 -0
  14. {hydraflow-0.4.5 → hydraflow-0.4.6}/README.md +0 -0
  15. {hydraflow-0.4.5 → hydraflow-0.4.6}/apps/quickstart.py +0 -0
  16. {hydraflow-0.4.5 → hydraflow-0.4.6}/mkdocs.yml +0 -0
  17. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/asyncio.py +0 -0
  18. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/config.py +0 -0
  19. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/context.py +0 -0
  20. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/mlflow.py +0 -0
  21. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/param.py +0 -0
  22. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/progress.py +0 -0
  23. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/py.typed +0 -0
  24. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/run_collection.py +0 -0
  25. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/run_data.py +0 -0
  26. {hydraflow-0.4.5 → hydraflow-0.4.6}/src/hydraflow/run_info.py +0 -0
  27. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/__init__.py +0 -0
  28. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/integ/__init__.py +0 -0
  29. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/integ/app.py +0 -0
  30. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/scripts/__init__.py +0 -0
  31. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/scripts/app.py +0 -0
  32. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/scripts/progress.py +0 -0
  33. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/scripts/watch.py +0 -0
  34. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_asyncio.py +0 -0
  35. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_config.py +0 -0
  36. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_context.py +0 -0
  37. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_mlflow.py +0 -0
  38. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_param.py +0 -0
  39. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_progress.py +0 -0
  40. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_run_collection.py +0 -0
  41. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_run_data.py +0 -0
  42. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_run_info.py +0 -0
  43. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_version.py +0 -0
  44. {hydraflow-0.4.5 → hydraflow-0.4.6}/tests/test_watch.py +0 -0
@@ -8,6 +8,7 @@
8
8
  "extensions": [
9
9
  "charliermarsh.ruff",
10
10
  "fill-labs.dependi",
11
+ "markis.code-coverage",
11
12
  "ms-python.python",
12
13
  "ms-python.vscode-pylance",
13
14
  "tamasfe.even-better-toml"
@@ -1,10 +1,11 @@
1
1
  #!/bin/bash
2
2
 
3
3
  echo 'eval "$(starship init bash)"' >> ~/.bashrc
4
- echo "alias ll='ls -alF'" >> ~/.bashrc
5
4
  mkdir -p ~/.config
6
5
  cp .devcontainer/starship.toml ~/.config
7
6
 
8
7
  curl -LsSf https://astral.sh/uv/install.sh | sh
9
- source $HOME/.cargo/env
10
- echo 'eval "$(uv generate-shell-completion bash)"' >> ~/.bashrc
8
+ echo 'eval "$(uv generate-shell-completion bash)"' >> ~/.bashrc
9
+ uv tool install ruff@latest
10
+ uv python install
11
+ uv sync -U
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: hydraflow
3
- Version: 0.4.5
3
+ Version: 0.4.6
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
@@ -27,6 +27,7 @@ License: MIT License
27
27
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
28
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
29
  SOFTWARE.
30
+ License-File: LICENSE
30
31
  Classifier: Development Status :: 4 - Beta
31
32
  Classifier: License :: OSI Approved :: MIT License
32
33
  Classifier: Programming Language :: Python
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hydraflow"
7
- version = "0.4.5"
7
+ version = "0.4.6"
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" }
@@ -45,7 +45,6 @@ dev-dependencies = [
45
45
  "pytest-cov",
46
46
  "pytest-randomly",
47
47
  "pytest-xdist",
48
- "ruff",
49
48
  ]
50
49
 
51
50
  [tool.hatch.build.targets.sdist]
@@ -61,11 +60,16 @@ addopts = [
61
60
  "--cov-report=lcov:lcov.info",
62
61
  ]
63
62
  doctest_optionflags = ["NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
64
- filterwarnings = ['ignore:pkg_resources is deprecated:DeprecationWarning']
63
+ filterwarnings = [
64
+ "ignore:pkg_resources is deprecated:DeprecationWarning",
65
+ "ignore:Support for class-based `config` is deprecated",
66
+ "ignore:Pydantic V1 style",
67
+ ]
65
68
  asyncio_default_fixture_loop_scope = "function"
66
69
 
67
70
  [tool.coverage.report]
68
71
  exclude_lines = ["no cov", "raise NotImplementedError", "if TYPE_CHECKING:"]
72
+ skip_covered = true
69
73
 
70
74
  [tool.ruff]
71
75
  line-length = 88
@@ -75,6 +79,7 @@ target-version = "py310"
75
79
  select = ["ALL"]
76
80
  unfixable = ["F401"]
77
81
  ignore = [
82
+ "A005",
78
83
  "ANN003",
79
84
  "ANN401",
80
85
  "ARG002",
@@ -11,6 +11,7 @@ from .utils import (
11
11
  get_overrides,
12
12
  load_config,
13
13
  load_overrides,
14
+ remove_run,
14
15
  )
15
16
 
16
17
  __all__ = [
@@ -26,6 +27,7 @@ __all__ = [
26
27
  "log_run",
27
28
  "multi_tasks_progress",
28
29
  "parallel_progress",
30
+ "remove_run",
29
31
  "search_runs",
30
32
  "select_config",
31
33
  "select_overrides",
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import shutil
5
6
  from pathlib import Path
6
7
  from typing import TYPE_CHECKING
7
8
 
@@ -9,11 +10,10 @@ import mlflow
9
10
  import mlflow.artifacts
10
11
  from hydra.core.hydra_config import HydraConfig
11
12
  from mlflow.entities import Run
12
- from mlflow.tracking import artifact_utils
13
13
  from omegaconf import DictConfig, OmegaConf
14
14
 
15
15
  if TYPE_CHECKING:
16
- from mlflow.entities import Run
16
+ from collections.abc import Iterable
17
17
 
18
18
 
19
19
  def get_artifact_dir(run: Run | None = None) -> Path:
@@ -28,10 +28,10 @@ def get_artifact_dir(run: Run | None = None) -> Path:
28
28
  The local path to the directory where the artifacts are downloaded.
29
29
 
30
30
  """
31
- if run is None:
32
- uri = mlflow.get_artifact_uri()
33
- else:
34
- uri = artifact_utils.get_artifact_uri(run.info.run_id)
31
+ uri = mlflow.get_artifact_uri() if run is None else run.info.artifact_uri
32
+
33
+ if not (isinstance(uri, str) and uri.startswith("file://")):
34
+ raise NotImplementedError
35
35
 
36
36
  return Path(mlflow.artifacts.download_artifacts(uri))
37
37
 
@@ -112,3 +112,13 @@ def load_overrides(run: Run) -> list[str]:
112
112
  """
113
113
  path = get_artifact_dir(run) / ".hydra/overrides.yaml"
114
114
  return [str(x) for x in OmegaConf.load(path)]
115
+
116
+
117
+ def remove_run(run: Run | Iterable[Run]) -> None:
118
+ """Remove the given run from the MLflow tracking server."""
119
+ if not isinstance(run, Run):
120
+ for r in run:
121
+ remove_run(r)
122
+ return
123
+
124
+ shutil.rmtree(get_artifact_dir(run).parent)
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import os
3
4
  import subprocess
4
5
  import sys
5
6
  from pathlib import Path
@@ -16,12 +17,14 @@ if TYPE_CHECKING:
16
17
  from hydraflow.run_collection import RunCollection
17
18
 
18
19
 
19
- @pytest.fixture
20
- def rc(monkeypatch, tmp_path):
20
+ @pytest.fixture(scope="module")
21
+ def rc(tmp_path_factory: pytest.TempPathFactory):
21
22
  import hydraflow
22
23
 
24
+ cwd = Path.cwd()
25
+
23
26
  file = Path("tests/scripts/app.py").absolute()
24
- monkeypatch.chdir(tmp_path)
27
+ os.chdir(tmp_path_factory.mktemp("test_app"))
25
28
 
26
29
  args = [sys.executable, file.as_posix(), "-m"]
27
30
  args += ["host=x,y", "port=1,2", "hydra.job.name=info"]
@@ -30,6 +33,8 @@ def rc(monkeypatch, tmp_path):
30
33
  mlflow.set_experiment("_info_")
31
34
  yield hydraflow.list_runs()
32
35
 
36
+ os.chdir(cwd)
37
+
33
38
 
34
39
  def test_list_runs_all(rc: RunCollection):
35
40
  from hydraflow.mlflow import list_runs
@@ -203,8 +208,7 @@ def test_log_run_error(monkeypatch, tmp_path):
203
208
  args = [sys.executable, file.as_posix()]
204
209
  args += ["host=error", "hydra.job.name=error"]
205
210
  cp = subprocess.run(args, check=False, capture_output=True)
206
- assert cp.returncode == 1
207
- assert b"Error during log_run: error" in cp.stdout
211
+ assert cp.returncode
208
212
 
209
213
 
210
214
  def test_chdir_artifact(rc: RunCollection):
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import os
3
4
  import subprocess
4
5
  import sys
5
6
  from pathlib import Path
@@ -10,10 +11,12 @@ from mlflow.artifacts import download_artifacts
10
11
  from mlflow.entities.run import Run
11
12
 
12
13
 
13
- @pytest.fixture
14
- def runs(monkeypatch, tmp_path):
14
+ @pytest.fixture(scope="module")
15
+ def runs(tmp_path_factory: pytest.TempPathFactory):
15
16
  file = Path("tests/scripts/app.py").absolute()
16
- monkeypatch.chdir(tmp_path)
17
+
18
+ cwd = Path.cwd()
19
+ os.chdir(tmp_path_factory.mktemp("test_log_run"))
17
20
 
18
21
  args = [sys.executable, file.as_posix(), "-m"]
19
22
  args += ["host=x,y", "port=1,2", "hydra.job.name=log_run"]
@@ -21,10 +24,13 @@ def runs(monkeypatch, tmp_path):
21
24
 
22
25
  mlflow.set_experiment("_log_run_")
23
26
  runs = mlflow.search_runs(output_format="list")
27
+
24
28
  assert len(runs) == 4
25
29
  assert isinstance(runs, list)
26
30
  yield runs
27
31
 
32
+ os.chdir(cwd)
33
+
28
34
 
29
35
  @pytest.fixture(params=range(4))
30
36
  def run(runs, request):
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+
3
+ import mlflow
4
+ import pytest
5
+
6
+ from hydraflow.run_collection import RunCollection
7
+
8
+
9
+ @pytest.fixture
10
+ def rc(monkeypatch, tmp_path):
11
+ from hydraflow.mlflow import search_runs
12
+
13
+ monkeypatch.chdir(tmp_path)
14
+
15
+ mlflow.set_experiment("test_run")
16
+ for x in range(4):
17
+ with mlflow.start_run(run_name=f"{x}"):
18
+ pass
19
+
20
+ x = search_runs()
21
+ assert isinstance(x, RunCollection)
22
+ yield x
23
+
24
+
25
+ def test_remove_run(rc: RunCollection):
26
+ from hydraflow.utils import get_artifact_dir, remove_run
27
+
28
+ paths = [get_artifact_dir(r).parent for r in rc]
29
+
30
+ assert all(path.exists() for path in paths)
31
+
32
+ remove_run(rc)
33
+
34
+ assert not any(path.exists() for path in paths)
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