hydraflow 0.7.3__tar.gz → 0.7.4__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- hydraflow-0.7.4/.github/workflows/ci.yaml +51 -0
- hydraflow-0.7.4/.github/workflows/docs.yaml +25 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/PKG-INFO +4 -1
- hydraflow-0.7.4/docs/index.md +10 -0
- hydraflow-0.7.4/docs/usage/quickstart.md +150 -0
- hydraflow-0.7.4/hydraflow.yaml +5 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/pyproject.toml +12 -17
- hydraflow-0.7.4/src/hydraflow/cli.py +75 -0
- hydraflow-0.7.4/tests/cli/conftest.py +9 -0
- hydraflow-0.7.4/tests/cli/test_run.py +18 -0
- hydraflow-0.7.4/tests/cli/test_show.py +52 -0
- hydraflow-0.7.4/tests/cli/test_version.py +20 -0
- hydraflow-0.7.4/tests/utils/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/.devcontainer/devcontainer.json +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/.devcontainer/postCreate.sh +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/.devcontainer/starship.toml +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/.gitattributes +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/.gitignore +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/LICENSE +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/README.md +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/apps/quickstart.py +0 -0
- /hydraflow-0.7.3/mkdocs.yml → /hydraflow-0.7.4/mkdocs.yaml +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/config.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/context.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/main.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/mlflow.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/param.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/py.typed +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/run_collection.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/run_data.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/run_info.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/src/hydraflow/utils.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/__init__.py +0 -0
- {hydraflow-0.7.3/tests/config → hydraflow-0.7.4/tests/cli}/__init__.py +0 -0
- {hydraflow-0.7.3/tests/context → hydraflow-0.7.4/tests/config}/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/config/overrides.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/config/test_config.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/config/test_overrides.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/config/test_params.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/conftest.py +0 -0
- {hydraflow-0.7.3/tests/main → hydraflow-0.7.4/tests/context}/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/chdir.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/context.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/logging.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/rerun.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/test_chdir.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/test_context.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/test_logging.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/context/test_rerun.py +0 -0
- {hydraflow-0.7.3/tests/param → hydraflow-0.7.4/tests/main}/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/base.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/force_new_run.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/restart.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/skip.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/test_base.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/test_force_new_run.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/test_restart.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/main/test_skip.py +0 -0
- {hydraflow-0.7.3/tests/run → hydraflow-0.7.4/tests/param}/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/param/params.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/param/test_param.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/param/test_params.py +0 -0
- {hydraflow-0.7.3/tests/utils → hydraflow-0.7.4/tests/run}/__init__.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/filter.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/run.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/test_collection.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/test_data.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/test_filter.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/test_info.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/run/test_run.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/test_mlflow.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/utils/test_run.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/utils/test_utils.py +0 -0
- {hydraflow-0.7.3 → hydraflow-0.7.4}/tests/utils/utils.py +0 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [main]
|
6
|
+
pull_request:
|
7
|
+
|
8
|
+
concurrency:
|
9
|
+
group: test-${{ github.head_ref }}
|
10
|
+
cancel-in-progress: true
|
11
|
+
|
12
|
+
env:
|
13
|
+
PYTHONUNBUFFERED: "1"
|
14
|
+
FORCE_COLOR: "1"
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
run:
|
18
|
+
name: Python ${{ matrix.python-version }} on ${{ startsWith(matrix.os, 'macos-') && 'macOS' || startsWith(matrix.os, 'windows-') && 'Windows' || 'Linux' }}
|
19
|
+
runs-on: ${{ matrix.os }}
|
20
|
+
strategy:
|
21
|
+
fail-fast: false
|
22
|
+
matrix:
|
23
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
24
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
25
|
+
|
26
|
+
steps:
|
27
|
+
- uses: actions/checkout@v4
|
28
|
+
- name: Set up Python ${{ matrix.python-version }}
|
29
|
+
uses: actions/setup-python@v5
|
30
|
+
with:
|
31
|
+
python-version: ${{ matrix.python-version }}
|
32
|
+
allow-prereleases: true
|
33
|
+
- name: Install uv and ruff
|
34
|
+
run: pip install uv ruff
|
35
|
+
- name: Install the project
|
36
|
+
run: uv sync
|
37
|
+
- name: Ruff check
|
38
|
+
run: ruff check
|
39
|
+
- name: Run test
|
40
|
+
run: uv run pytest -v --junitxml=junit.xml
|
41
|
+
- name: Upload Codecov Results
|
42
|
+
if: success()
|
43
|
+
uses: codecov/codecov-action@v4
|
44
|
+
with:
|
45
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
46
|
+
file: lcov.info
|
47
|
+
- name: Upload test results to Codecov
|
48
|
+
if: ${{ !cancelled() }}
|
49
|
+
uses: codecov/test-results-action@v1
|
50
|
+
with:
|
51
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Documentation
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: [main]
|
5
|
+
tags: ["*"]
|
6
|
+
permissions:
|
7
|
+
contents: write
|
8
|
+
jobs:
|
9
|
+
deploy:
|
10
|
+
name: Documentation
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v4
|
14
|
+
- name: Configure Git Credentials
|
15
|
+
run: |
|
16
|
+
git config user.name github-actions[bot]
|
17
|
+
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
18
|
+
- name: Set up Python 3.11
|
19
|
+
uses: actions/setup-python@v5
|
20
|
+
with:
|
21
|
+
python-version: 3.11
|
22
|
+
- name: Install package
|
23
|
+
run: pip install -e . mkapi markdown-exec[ansi]
|
24
|
+
- name: Deploy documentation
|
25
|
+
run: mkdocs gh-deploy --force
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: hydraflow
|
3
|
-
Version: 0.7.
|
3
|
+
Version: 0.7.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
|
@@ -38,6 +38,9 @@ Classifier: Programming Language :: Python :: 3.13
|
|
38
38
|
Requires-Python: >=3.10
|
39
39
|
Requires-Dist: hydra-core>=1.3
|
40
40
|
Requires-Dist: mlflow>=2.15
|
41
|
+
Requires-Dist: omegaconf
|
42
|
+
Requires-Dist: rich
|
43
|
+
Requires-Dist: typer
|
41
44
|
Description-Content-Type: text/markdown
|
42
45
|
|
43
46
|
# Hydraflow
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# Quickstart
|
2
|
+
|
3
|
+
## Hydra application
|
4
|
+
|
5
|
+
The following example demonstrates how to use Hydraflow with a Hydra application.
|
6
|
+
There are two main steps to using Hydraflow:
|
7
|
+
|
8
|
+
1. Set the MLflow experiment using the Hydra job name.
|
9
|
+
2. Start a new MLflow run that logs the Hydra configuration.
|
10
|
+
|
11
|
+
```python title="apps/quickstart.py" linenums="1" hl_lines="24 26"
|
12
|
+
--8<-- "apps/quickstart.py"
|
13
|
+
```
|
14
|
+
|
15
|
+
### Set the MLflow experiment
|
16
|
+
|
17
|
+
[`hydraflow.set_experiment`][] sets the MLflow experiment using the Hydra job name.
|
18
|
+
Optionally, it can also set the tracking URI with `uri` argument.
|
19
|
+
For example,
|
20
|
+
|
21
|
+
```python
|
22
|
+
hydraflow.set_experiment(uri="sqlite:///mlruns.db")
|
23
|
+
```
|
24
|
+
|
25
|
+
### Start a new MLflow run
|
26
|
+
|
27
|
+
[`hydraflow.start_run`][] starts a new MLflow run that logs the Hydra configuration.
|
28
|
+
It returns the started run so that it can be used to log metrics, parameters, and artifacts
|
29
|
+
within the context of the run.
|
30
|
+
|
31
|
+
```python
|
32
|
+
with hydraflow.start_run(cfg) as run:
|
33
|
+
pass
|
34
|
+
```
|
35
|
+
|
36
|
+
## Run the application
|
37
|
+
|
38
|
+
```bash exec="on"
|
39
|
+
rm -rf mlruns outputs multirun
|
40
|
+
```
|
41
|
+
|
42
|
+
### Single-run
|
43
|
+
|
44
|
+
Run the Hydra application as a normal Python script.
|
45
|
+
|
46
|
+
```console exec="1" source="console"
|
47
|
+
$ python apps/quickstart.py
|
48
|
+
```
|
49
|
+
|
50
|
+
Check the MLflow CLI to view the experiment.
|
51
|
+
|
52
|
+
```console exec="1" source="console"
|
53
|
+
$ mlflow experiments search
|
54
|
+
```
|
55
|
+
|
56
|
+
### Multi-run
|
57
|
+
|
58
|
+
```console exec="1" source="console"
|
59
|
+
$ python apps/quickstart.py -m width=400,600 height=100,200,300
|
60
|
+
```
|
61
|
+
|
62
|
+
## Use Hydraflow API
|
63
|
+
|
64
|
+
### Run collection
|
65
|
+
|
66
|
+
```pycon exec="1" source="console" session="quickstart"
|
67
|
+
>>> import mlflow
|
68
|
+
>>> mlflow.set_experiment("quickstart")
|
69
|
+
>>> import hydraflow
|
70
|
+
>>> rc = hydraflow.list_runs()
|
71
|
+
>>> print(rc)
|
72
|
+
```
|
73
|
+
|
74
|
+
### Retrieve a run
|
75
|
+
|
76
|
+
```pycon exec="1" source="console" session="quickstart"
|
77
|
+
>>> run = rc.first()
|
78
|
+
>>> print(type(run))
|
79
|
+
```
|
80
|
+
|
81
|
+
```pycon exec="1" source="console" session="quickstart"
|
82
|
+
>>> cfg = hydraflow.load_config(run)
|
83
|
+
>>> print(type(cfg))
|
84
|
+
>>> print(cfg)
|
85
|
+
```
|
86
|
+
|
87
|
+
```pycon exec="1" source="console" session="quickstart"
|
88
|
+
>>> run = rc.last()
|
89
|
+
>>> cfg = hydraflow.load_config(run)
|
90
|
+
>>> print(cfg)
|
91
|
+
```
|
92
|
+
|
93
|
+
### Filter runs
|
94
|
+
|
95
|
+
```pycon exec="1" source="console" session="quickstart"
|
96
|
+
>>> filtered = rc.filter(width=400)
|
97
|
+
>>> print(filtered)
|
98
|
+
```
|
99
|
+
|
100
|
+
```pycon exec="1" source="console" session="quickstart"
|
101
|
+
>>> filtered = rc.filter(height=[100, 300])
|
102
|
+
>>> print(filtered)
|
103
|
+
```
|
104
|
+
|
105
|
+
```pycon exec="1" source="console" session="quickstart"
|
106
|
+
>>> filtered = rc.filter(height=(100, 300))
|
107
|
+
>>> print(filtered)
|
108
|
+
```
|
109
|
+
|
110
|
+
```pycon exec="1" source="console" session="quickstart"
|
111
|
+
>>> run = rc.find(height=100)
|
112
|
+
>>> print(run.data.params)
|
113
|
+
```
|
114
|
+
|
115
|
+
```pycon exec="1" source="console" session="quickstart"
|
116
|
+
>>> run = rc.find_last(height=100)
|
117
|
+
>>> print(run.data.params)
|
118
|
+
```
|
119
|
+
|
120
|
+
### Map runs
|
121
|
+
|
122
|
+
```pycon exec="1" source="console" session="quickstart"
|
123
|
+
>>> params = rc.map(lambda x: x.data.params)
|
124
|
+
>>> for p in params:
|
125
|
+
... print(p)
|
126
|
+
```
|
127
|
+
|
128
|
+
```pycon exec="1" source="console" session="quickstart"
|
129
|
+
>>> list(rc.map_id(print))
|
130
|
+
```
|
131
|
+
|
132
|
+
### Group runs
|
133
|
+
|
134
|
+
```pycon exec="1" source="console" session="quickstart"
|
135
|
+
>>> grouped = rc.groupby("width")
|
136
|
+
>>> for key, group in grouped.items():
|
137
|
+
... print(key, group)
|
138
|
+
```
|
139
|
+
|
140
|
+
```pycon exec="1" source="console" session="quickstart"
|
141
|
+
>>> grouped = rc.groupby(["height"])
|
142
|
+
>>> for key, group in grouped.items():
|
143
|
+
... print(key, group)
|
144
|
+
```
|
145
|
+
|
146
|
+
### Config dataframe
|
147
|
+
|
148
|
+
```pycon exec="1" source="console" session="quickstart"
|
149
|
+
>>> print(rc.data.config)
|
150
|
+
```
|
@@ -1,10 +1,10 @@
|
|
1
1
|
[build-system]
|
2
|
-
requires = ["hatchling
|
2
|
+
requires = ["hatchling"]
|
3
3
|
build-backend = "hatchling.build"
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "hydraflow"
|
7
|
-
version = "0.7.
|
7
|
+
version = "0.7.4"
|
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" }
|
@@ -19,40 +19,34 @@ classifiers = [
|
|
19
19
|
"Programming Language :: Python :: 3.13",
|
20
20
|
]
|
21
21
|
requires-python = ">=3.10"
|
22
|
-
dependencies = ["hydra-core>=1.3", "mlflow>=2.15"]
|
22
|
+
dependencies = ["hydra-core>=1.3", "mlflow>=2.15", "omegaconf", "rich", "typer"]
|
23
23
|
|
24
24
|
[project.urls]
|
25
25
|
Documentation = "https://daizutabi.github.io/hydraflow/"
|
26
26
|
Source = "https://github.com/daizutabi/hydraflow"
|
27
27
|
Issues = "https://github.com/daizutabi/hydraflow/issues"
|
28
28
|
|
29
|
-
[
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
"
|
29
|
+
[project.scripts]
|
30
|
+
hydraflow = "hydraflow.cli:app"
|
31
|
+
|
32
|
+
[dependency-groups]
|
33
|
+
dev = [
|
34
|
+
"pytest-clarity",
|
35
35
|
"pytest-cov",
|
36
36
|
"pytest-order",
|
37
37
|
"pytest-randomly",
|
38
38
|
"pytest-xdist",
|
39
39
|
]
|
40
|
-
|
41
|
-
[tool.hatch.build.targets.sdist]
|
42
|
-
exclude = ["/.github", "/docs"]
|
43
|
-
|
44
|
-
[tool.hatch.build.targets.wheel]
|
45
|
-
packages = ["src/hydraflow"]
|
40
|
+
docs = ["markdown-exec[ansi]", "mkapi", "mkdocs-material"]
|
46
41
|
|
47
42
|
[tool.pytest.ini_options]
|
48
43
|
addopts = [
|
49
44
|
"--cov=hydraflow",
|
50
45
|
"--cov-report=lcov:lcov.info",
|
51
|
-
"-n8",
|
52
46
|
"--dist=loadgroup",
|
47
|
+
"-n8",
|
53
48
|
]
|
54
49
|
filterwarnings = [
|
55
|
-
"ignore:pkg_resources is deprecated:DeprecationWarning",
|
56
50
|
"ignore:Support for class-based `config` is deprecated",
|
57
51
|
"ignore:Pydantic V1 style",
|
58
52
|
]
|
@@ -98,3 +92,4 @@ ignore = [
|
|
98
92
|
]
|
99
93
|
"apps/*.py" = ["D", "G", "INP"]
|
100
94
|
"src/hydraflow/main.py" = ["ANN201", "D401", "PLR0913"]
|
95
|
+
"src/hydraflow/cli.py" = ["ANN", "D"]
|
@@ -0,0 +1,75 @@
|
|
1
|
+
"""Hydraflow CLI."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from pathlib import Path
|
6
|
+
from typing import Annotated
|
7
|
+
|
8
|
+
import typer
|
9
|
+
from omegaconf import DictConfig, OmegaConf
|
10
|
+
from rich.console import Console
|
11
|
+
from typer import Argument, Option
|
12
|
+
|
13
|
+
app = typer.Typer(add_completion=False)
|
14
|
+
console = Console()
|
15
|
+
|
16
|
+
|
17
|
+
@app.command()
|
18
|
+
def run(
|
19
|
+
names: Annotated[
|
20
|
+
list[str] | None,
|
21
|
+
Argument(help="Job names.", show_default=False),
|
22
|
+
] = None,
|
23
|
+
) -> None:
|
24
|
+
"""Run jobs."""
|
25
|
+
typer.echo(names)
|
26
|
+
|
27
|
+
cfg = load_config()
|
28
|
+
typer.echo(cfg)
|
29
|
+
|
30
|
+
|
31
|
+
@app.command()
|
32
|
+
def show() -> None:
|
33
|
+
"""Show the config."""
|
34
|
+
from rich.syntax import Syntax
|
35
|
+
|
36
|
+
cfg = load_config()
|
37
|
+
code = OmegaConf.to_yaml(cfg)
|
38
|
+
syntax = Syntax(code, "yaml")
|
39
|
+
console.print(syntax)
|
40
|
+
|
41
|
+
|
42
|
+
@app.callback(invoke_without_command=True)
|
43
|
+
def callback(
|
44
|
+
*,
|
45
|
+
version: Annotated[
|
46
|
+
bool,
|
47
|
+
Option("--version", help="Show the version and exit."),
|
48
|
+
] = False,
|
49
|
+
) -> None:
|
50
|
+
if version:
|
51
|
+
import importlib.metadata
|
52
|
+
|
53
|
+
typer.echo(f"hydraflow {importlib.metadata.version('hydraflow')}")
|
54
|
+
raise typer.Exit
|
55
|
+
|
56
|
+
|
57
|
+
def find_config() -> Path:
|
58
|
+
if Path("hydraflow.yaml").exists():
|
59
|
+
return Path("hydraflow.yaml")
|
60
|
+
|
61
|
+
if Path("hydraflow.yml").exists():
|
62
|
+
return Path("hydraflow.yml")
|
63
|
+
|
64
|
+
typer.echo("No config file found.")
|
65
|
+
raise typer.Exit(code=1)
|
66
|
+
|
67
|
+
|
68
|
+
def load_config() -> DictConfig:
|
69
|
+
cfg = OmegaConf.load(find_config())
|
70
|
+
|
71
|
+
if isinstance(cfg, DictConfig):
|
72
|
+
return cfg
|
73
|
+
|
74
|
+
typer.echo("Invalid config file.")
|
75
|
+
raise typer.Exit(code=1)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
from typer.testing import CliRunner
|
4
|
+
|
5
|
+
from hydraflow.cli import app
|
6
|
+
|
7
|
+
runner = CliRunner()
|
8
|
+
|
9
|
+
|
10
|
+
def test_invoke_error():
|
11
|
+
result = runner.invoke(app, ["run"])
|
12
|
+
assert result.exit_code == 1
|
13
|
+
|
14
|
+
|
15
|
+
def test_invoke():
|
16
|
+
Path("hydraflow.yaml").write_text("a:\n b: [1, 2]")
|
17
|
+
result = runner.invoke(app, ["run"])
|
18
|
+
assert result.exit_code == 0
|
@@ -0,0 +1,52 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
import typer
|
5
|
+
from typer.testing import CliRunner
|
6
|
+
|
7
|
+
from hydraflow.cli import app
|
8
|
+
|
9
|
+
runner = CliRunner()
|
10
|
+
|
11
|
+
|
12
|
+
@pytest.mark.parametrize("file", ["hydraflow.yaml", "hydraflow.yml"])
|
13
|
+
def test_find_config(file):
|
14
|
+
from hydraflow.cli import find_config
|
15
|
+
|
16
|
+
Path(file).touch()
|
17
|
+
assert find_config() == Path(file)
|
18
|
+
|
19
|
+
|
20
|
+
def test_find_config_error():
|
21
|
+
from hydraflow.cli import find_config
|
22
|
+
|
23
|
+
with pytest.raises(typer.Exit):
|
24
|
+
find_config()
|
25
|
+
|
26
|
+
|
27
|
+
def test_load_config():
|
28
|
+
from hydraflow.cli import load_config
|
29
|
+
|
30
|
+
Path("hydraflow.yaml").write_text("a:\n b: 1")
|
31
|
+
cfg = load_config()
|
32
|
+
assert cfg["a"]["b"] == 1
|
33
|
+
|
34
|
+
|
35
|
+
def test_load_config_error():
|
36
|
+
from hydraflow.cli import load_config
|
37
|
+
|
38
|
+
Path("hydraflow.yml").write_text("- 1\n- 2")
|
39
|
+
|
40
|
+
with pytest.raises(typer.Exit):
|
41
|
+
load_config()
|
42
|
+
|
43
|
+
|
44
|
+
def test_invoke_error():
|
45
|
+
result = runner.invoke(app, ["show"])
|
46
|
+
assert result.exit_code == 1
|
47
|
+
|
48
|
+
|
49
|
+
def test_invoke():
|
50
|
+
Path("hydraflow.yaml").write_text("a:\n b: [1, 2]")
|
51
|
+
result = runner.invoke(app, ["show"])
|
52
|
+
assert result.exit_code == 0
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import subprocess
|
2
|
+
|
3
|
+
from typer.testing import CliRunner
|
4
|
+
|
5
|
+
from hydraflow.cli import app
|
6
|
+
|
7
|
+
runner = CliRunner()
|
8
|
+
|
9
|
+
|
10
|
+
def test_invoke():
|
11
|
+
result = runner.invoke(app, ["--version"])
|
12
|
+
assert result.exit_code == 0
|
13
|
+
assert "hydraflow" in result.stdout
|
14
|
+
assert result.stdout.count(".") == 2
|
15
|
+
|
16
|
+
|
17
|
+
def test_command():
|
18
|
+
out = subprocess.check_output(["hydraflow", "--version"], text=True)
|
19
|
+
assert "hydraflow" in out
|
20
|
+
assert out.count(".") == 2
|
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
|