hydraflow 0.3.1__tar.gz → 0.3.2__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. {hydraflow-0.3.1 → hydraflow-0.3.2}/PKG-INFO +1 -1
  2. {hydraflow-0.3.1 → hydraflow-0.3.2}/mkdocs.yml +1 -1
  3. {hydraflow-0.3.1 → hydraflow-0.3.2}/pyproject.toml +1 -1
  4. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/param.py +1 -1
  5. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/run_collection.py +17 -13
  6. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_app.py +11 -4
  7. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_run_collection.py +39 -39
  8. {hydraflow-0.3.1 → hydraflow-0.3.2}/.devcontainer/devcontainer.json +0 -0
  9. {hydraflow-0.3.1 → hydraflow-0.3.2}/.devcontainer/postCreate.sh +0 -0
  10. {hydraflow-0.3.1 → hydraflow-0.3.2}/.devcontainer/starship.toml +0 -0
  11. {hydraflow-0.3.1 → hydraflow-0.3.2}/.gitattributes +0 -0
  12. {hydraflow-0.3.1 → hydraflow-0.3.2}/.gitignore +0 -0
  13. {hydraflow-0.3.1 → hydraflow-0.3.2}/LICENSE +0 -0
  14. {hydraflow-0.3.1 → hydraflow-0.3.2}/README.md +0 -0
  15. /hydraflow-0.3.1/apps/hello.py → /hydraflow-0.3.2/apps/quickstart.py +0 -0
  16. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/__init__.py +0 -0
  17. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/asyncio.py +0 -0
  18. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/config.py +0 -0
  19. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/context.py +0 -0
  20. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/mlflow.py +0 -0
  21. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/progress.py +0 -0
  22. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/py.typed +0 -0
  23. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/run_data.py +0 -0
  24. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/run_info.py +0 -0
  25. {hydraflow-0.3.1 → hydraflow-0.3.2}/src/hydraflow/utils.py +0 -0
  26. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/__init__.py +0 -0
  27. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/scripts/__init__.py +0 -0
  28. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/scripts/app.py +0 -0
  29. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/scripts/progress.py +0 -0
  30. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/scripts/watch.py +0 -0
  31. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_asyncio.py +0 -0
  32. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_config.py +0 -0
  33. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_context.py +0 -0
  34. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_log_run.py +0 -0
  35. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_mlflow.py +0 -0
  36. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_param.py +0 -0
  37. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_progress.py +0 -0
  38. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_run_data.py +0 -0
  39. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_run_info.py +0 -0
  40. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_version.py +0 -0
  41. {hydraflow-0.3.1 → hydraflow-0.3.2}/tests/test_watch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hydraflow
3
- Version: 0.3.1
3
+ Version: 0.3.2
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
@@ -52,5 +52,5 @@ markdown_extensions:
52
52
  nav:
53
53
  - Home: index.md
54
54
  - Usage:
55
- - Hydra application: usage/hydra.md
55
+ - usage/quickstart.md
56
56
  - Reference: $api/hydraflow.**
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hydraflow"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "Hydraflow integrates Hydra and MLflow to manage and track machine learning experiments."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -72,4 +72,4 @@ def _match_tuple(param: str, value: tuple) -> bool | None:
72
72
  if type(value[0]) is not type(value[1]):
73
73
  return None
74
74
 
75
- return value[0] <= type(value[0])(param) < value[1] # type: ignore
75
+ return value[0] <= type(value[0])(param) <= value[1] # type: ignore
@@ -239,8 +239,8 @@ class RunCollection:
239
239
  The filtering supports:
240
240
  - Exact matches for single values.
241
241
  - Membership checks for lists of values.
242
- - Range checks for tuples of two values (inclusive of the lower bound
243
- and exclusive of the upper bound).
242
+ - Range checks for tuples of two values (inclusive of both the lower
243
+ and upper bound).
244
244
 
245
245
  Args:
246
246
  config (object | None): The configuration object to filter the runs.
@@ -476,7 +476,7 @@ class RunCollection:
476
476
  """
477
477
  return (func(run, *args, **kwargs) for run in self)
478
478
 
479
- def map_run_id(
479
+ def map_id(
480
480
  self,
481
481
  func: Callable[Concatenate[str, P], T],
482
482
  *args: P.args,
@@ -569,8 +569,8 @@ class RunCollection:
569
569
 
570
570
  def group_by(
571
571
  self,
572
- *names: str | list[str],
573
- ) -> dict[tuple[str | None, ...], RunCollection]:
572
+ names: str | list[str],
573
+ ) -> dict[str | None | tuple[str | None, ...], RunCollection]:
574
574
  """Group runs by specified parameter names.
575
575
 
576
576
  Group the runs in the collection based on the values of the
@@ -578,19 +578,23 @@ class RunCollection:
578
578
  form a key in the returned dictionary.
579
579
 
580
580
  Args:
581
- *names (str | list[str]): The names of the parameters to group by.
581
+ names (str | list[str]): The names of the parameters to group by.
582
582
  This can be a single parameter name or multiple names provided
583
583
  as separate arguments or as a list.
584
584
 
585
585
  Returns:
586
- dict[tuple[str | None, ...], RunCollection]: A dictionary where the keys
587
- are tuples of parameter values and the values are RunCollection objects
588
- containing the runs that match those parameter values.
586
+ dict[str | None | tuple[str | None, ...], RunCollection]: A
587
+ dictionary where the keys are tuples of parameter values and the
588
+ values are `RunCollection` objects containing the runs that match
589
+ those parameter values.
589
590
 
590
591
  """
591
- grouped_runs: dict[tuple[str | None, ...], list[Run]] = {}
592
+ grouped_runs: dict[str | None | tuple[str | None, ...], list[Run]] = {}
593
+ is_list = isinstance(names, list)
592
594
  for run in self._runs:
593
- key = get_params(run, *names)
595
+ key = get_params(run, names)
596
+ if not is_list:
597
+ key = key[0]
594
598
  grouped_runs.setdefault(key, []).append(run)
595
599
 
596
600
  return {key: RunCollection(runs) for key, runs in grouped_runs.items()}
@@ -637,8 +641,8 @@ def filter_runs(
637
641
  The filtering supports:
638
642
  - Exact matches for single values.
639
643
  - Membership checks for lists of values.
640
- - Range checks for tuples of two values (inclusive of the lower bound and
641
- exclusive of the upper bound).
644
+ - Range checks for tuples of two values (inclusive of both the lower and
645
+ upper bound).
642
646
 
643
647
  Args:
644
648
  runs (list[Run]): The list of runs to filter.
@@ -161,13 +161,20 @@ def test_app_group_by(rc: RunCollection):
161
161
  grouped = rc.group_by("host")
162
162
  assert len(grouped) == 2
163
163
  x = {"port": "1", "host": "x", "values": "[1, 2, 3]"}
164
- assert grouped[("x",)].data.params[0] == x
164
+ assert grouped["x"].data.params[0] == x
165
165
  x = {"port": "2", "host": "x", "values": "[1, 2, 3]"}
166
- assert grouped[("x",)].data.params[1] == x
166
+ assert grouped["x"].data.params[1] == x
167
167
  x = {"port": "1", "host": "y", "values": "[1, 2, 3]"}
168
- assert grouped[("y",)].data.params[0] == x
168
+ assert grouped["y"].data.params[0] == x
169
169
  x = {"port": "2", "host": "y", "values": "[1, 2, 3]"}
170
- assert grouped[("y",)].data.params[1] == x
170
+ assert grouped["y"].data.params[1] == x
171
+
172
+
173
+ def test_app_group_by_list(rc: RunCollection):
174
+ grouped = rc.group_by(["host"])
175
+ assert len(grouped) == 2
176
+ assert ("x",) in grouped
177
+ assert ("y",) in grouped
171
178
 
172
179
 
173
180
  def test_app_filter_list(rc: RunCollection):
@@ -28,12 +28,12 @@ def rc(monkeypatch, tmp_path):
28
28
  return x
29
29
 
30
30
 
31
- def test_run_collection_bool_false():
31
+ def test_bool_false():
32
32
  assert not RunCollection([])
33
33
  assert bool(RunCollection.from_list([])) is False
34
34
 
35
35
 
36
- def test_run_collection_bool_true(rc: RunCollection):
36
+ def test_bool_true(rc: RunCollection):
37
37
  assert rc
38
38
  assert bool(rc) is True
39
39
 
@@ -90,7 +90,7 @@ def test_filter_tuple(run_list: list[Run]):
90
90
  from hydraflow.run_collection import filter_runs
91
91
 
92
92
  x = filter_runs(run_list, p=(1, 3))
93
- assert len(x) == 2
93
+ assert len(x) == 3
94
94
 
95
95
 
96
96
  def test_filter_invalid_param(run_list: list[Run]):
@@ -139,45 +139,45 @@ def test_chdir_artifact_list(i: int, run_list: list[Run]):
139
139
  assert not Path("abc.txt").exists()
140
140
 
141
141
 
142
- def test_runs_repr(rc: RunCollection):
142
+ def test_repr(rc: RunCollection):
143
143
  assert repr(rc) == "RunCollection(6)"
144
144
 
145
145
 
146
- def test_runs_first(rc: RunCollection):
146
+ def test_first(rc: RunCollection):
147
147
  run = rc.first()
148
148
  assert isinstance(run, Run)
149
149
  assert run.data.params["p"] == "0"
150
150
 
151
151
 
152
- def test_runs_first_empty(rc: RunCollection):
152
+ def test_first_empty(rc: RunCollection):
153
153
  rc._runs = []
154
154
  with pytest.raises(ValueError):
155
155
  rc.first()
156
156
 
157
157
 
158
- def test_runs_try_first_none(rc: RunCollection):
158
+ def test_try_first_none(rc: RunCollection):
159
159
  rc._runs = []
160
160
  assert rc.try_first() is None
161
161
 
162
162
 
163
- def test_runs_last(rc: RunCollection):
163
+ def test_last(rc: RunCollection):
164
164
  run = rc.last()
165
165
  assert isinstance(run, Run)
166
166
  assert run.data.params["p"] == "5"
167
167
 
168
168
 
169
- def test_runs_last_empty(rc: RunCollection):
169
+ def test_last_empty(rc: RunCollection):
170
170
  rc._runs = []
171
171
  with pytest.raises(ValueError):
172
172
  rc.last()
173
173
 
174
174
 
175
- def test_runs_try_last_none(rc: RunCollection):
175
+ def test_try_last_none(rc: RunCollection):
176
176
  rc._runs = []
177
177
  assert rc.try_last() is None
178
178
 
179
179
 
180
- def test_runs_filter(rc: RunCollection):
180
+ def test_filter(rc: RunCollection):
181
181
  assert len(rc.filter()) == 6
182
182
  assert len(rc.filter({})) == 6
183
183
  assert len(rc.filter({"p": 1})) == 1
@@ -192,14 +192,14 @@ def test_runs_filter(rc: RunCollection):
192
192
  assert len(rc.filter(r=0)) == 2
193
193
 
194
194
 
195
- def test_runs_get(rc: RunCollection):
195
+ def test_get(rc: RunCollection):
196
196
  run = rc.get({"p": 4})
197
197
  assert isinstance(run, Run)
198
198
  run = rc.get(p=2)
199
199
  assert isinstance(run, Run)
200
200
 
201
201
 
202
- def test_runs_try_get(rc: RunCollection):
202
+ def test_try_get(rc: RunCollection):
203
203
  run = rc.try_get({"p": 5})
204
204
  assert isinstance(run, Run)
205
205
  run = rc.try_get(p=1)
@@ -208,7 +208,7 @@ def test_runs_try_get(rc: RunCollection):
208
208
  assert run is None
209
209
 
210
210
 
211
- def test_runs_get_params_names(rc: RunCollection):
211
+ def test_get_param_names(rc: RunCollection):
212
212
  names = rc.get_param_names()
213
213
  assert len(names) == 3
214
214
  assert "p" in names
@@ -216,14 +216,14 @@ def test_runs_get_params_names(rc: RunCollection):
216
216
  assert "r" in names
217
217
 
218
218
 
219
- def test_runs_get_params_dict(rc: RunCollection):
219
+ def test_get_param_dict(rc: RunCollection):
220
220
  params = rc.get_param_dict()
221
221
  assert params["p"] == ["0", "1", "2", "3", "4", "5"]
222
222
  assert params["q"] == ["0", "None"]
223
223
  assert params["r"] == ["0", "1", "2"]
224
224
 
225
225
 
226
- def test_runs_get_params_dict_drop_const(rc: RunCollection):
226
+ def test_get_param_dict_drop_const(rc: RunCollection):
227
227
  rc_ = rc.filter(q=0)
228
228
  params = rc_.get_param_dict(drop_const=True)
229
229
  assert len(params) == 2
@@ -232,7 +232,7 @@ def test_runs_get_params_dict_drop_const(rc: RunCollection):
232
232
  assert "r" in params
233
233
 
234
234
 
235
- def test_runs_find(rc: RunCollection):
235
+ def test_find(rc: RunCollection):
236
236
  run = rc.find({"r": 0})
237
237
  assert isinstance(run, Run)
238
238
  assert run.data.params["p"] == "0"
@@ -241,17 +241,17 @@ def test_runs_find(rc: RunCollection):
241
241
  assert run.data.params["p"] == "2"
242
242
 
243
243
 
244
- def test_runs_find_none(rc: RunCollection):
244
+ def test_find_none(rc: RunCollection):
245
245
  with pytest.raises(ValueError):
246
246
  rc.find({"r": 10})
247
247
 
248
248
 
249
- def test_runs_try_find_none(rc: RunCollection):
249
+ def test_try_find_none(rc: RunCollection):
250
250
  run = rc.try_find({"r": 10})
251
251
  assert run is None
252
252
 
253
253
 
254
- def test_runs_find_last(rc: RunCollection):
254
+ def test_find_last(rc: RunCollection):
255
255
  run = rc.find_last({"r": 0})
256
256
  assert isinstance(run, Run)
257
257
  assert run.data.params["p"] == "3"
@@ -260,12 +260,12 @@ def test_runs_find_last(rc: RunCollection):
260
260
  assert run.data.params["p"] == "5"
261
261
 
262
262
 
263
- def test_runs_find_last_none(rc: RunCollection):
263
+ def test_find_last_none(rc: RunCollection):
264
264
  with pytest.raises(ValueError):
265
265
  rc.find_last({"p": 10})
266
266
 
267
267
 
268
- def test_runs_try_find_last_none(rc: RunCollection):
268
+ def test_try_find_last_none(rc: RunCollection):
269
269
  run = rc.try_find_last({"p": 10})
270
270
  assert run is None
271
271
 
@@ -313,42 +313,42 @@ def test_list_runs_none(rc, runs2):
313
313
  assert not no_runs
314
314
 
315
315
 
316
- def test_run_collection_map(rc: RunCollection):
316
+ def test_map(rc: RunCollection):
317
317
  results = list(rc.map(lambda run: run.info.run_id))
318
318
  assert len(results) == len(rc._runs)
319
319
  assert all(isinstance(run_id, str) for run_id in results)
320
320
 
321
321
 
322
- def test_run_collection_map_args(rc: RunCollection):
322
+ def test_map_args(rc: RunCollection):
323
323
  results = list(rc.map(lambda run, x: run.info.run_id + x, "test"))
324
324
  assert all(x.endswith("test") for x in results)
325
325
 
326
326
 
327
- def test_run_collection_map_run_id(rc: RunCollection):
328
- results = list(rc.map_run_id(lambda run_id: run_id))
327
+ def test_map_id(rc: RunCollection):
328
+ results = list(rc.map_id(lambda run_id: run_id))
329
329
  assert len(results) == len(rc._runs)
330
330
  assert all(isinstance(run_id, str) for run_id in results)
331
331
 
332
332
 
333
- def test_run_collection_map_run_id_kwargs(rc: RunCollection):
334
- results = list(rc.map_run_id(lambda run_id, x: x + run_id, x="test"))
333
+ def test_map_id_kwargs(rc: RunCollection):
334
+ results = list(rc.map_id(lambda run_id, x: x + run_id, x="test"))
335
335
  assert all(x.startswith("test") for x in results)
336
336
 
337
337
 
338
- def test_run_collection_map_uri(rc: RunCollection):
338
+ def test_map_uri(rc: RunCollection):
339
339
  results = list(rc.map_uri(lambda uri: uri))
340
340
  assert len(results) == len(rc._runs)
341
341
  assert all(isinstance(uri, str | type(None)) for uri in results)
342
342
 
343
343
 
344
- def test_run_collection_map_dir(rc: RunCollection):
344
+ def test_map_dir(rc: RunCollection):
345
345
  results = list(rc.map_dir(lambda dir_path, x: dir_path / x, "a.csv"))
346
346
  assert len(results) == len(rc._runs)
347
347
  assert all(isinstance(dir_path, Path) for dir_path in results)
348
348
  assert all(dir_path.stem == "a" for dir_path in results)
349
349
 
350
350
 
351
- def test_run_collection_sort(rc: RunCollection):
351
+ def test_sort(rc: RunCollection):
352
352
  rc.sort(key=lambda x: x.data.params["p"])
353
353
  assert [run.data.params["p"] for run in rc] == ["0", "1", "2", "3", "4", "5"]
354
354
 
@@ -356,7 +356,7 @@ def test_run_collection_sort(rc: RunCollection):
356
356
  assert [run.data.params["p"] for run in rc] == ["5", "4", "3", "2", "1", "0"]
357
357
 
358
358
 
359
- def test_run_collection_iter(rc: RunCollection):
359
+ def test_iter(rc: RunCollection):
360
360
  assert list(rc) == rc._runs
361
361
 
362
362
 
@@ -366,39 +366,39 @@ def test_run_collection_getitem(rc: RunCollection, i: int):
366
366
 
367
367
 
368
368
  @pytest.mark.parametrize("i", range(6))
369
- def test_run_collection_getitem_slice(rc: RunCollection, i: int):
369
+ def test_getitem_slice(rc: RunCollection, i: int):
370
370
  assert rc[i : i + 2]._runs == rc._runs[i : i + 2]
371
371
 
372
372
 
373
373
  @pytest.mark.parametrize("i", range(6))
374
- def test_run_collection_getitem_slice_step(rc: RunCollection, i: int):
374
+ def test_getitem_slice_step(rc: RunCollection, i: int):
375
375
  assert rc[i::2]._runs == rc._runs[i::2]
376
376
 
377
377
 
378
378
  @pytest.mark.parametrize("i", range(6))
379
- def test_run_collection_getitem_slice_step_neg(rc: RunCollection, i: int):
379
+ def test_getitem_slice_step_neg(rc: RunCollection, i: int):
380
380
  assert rc[i::-2]._runs == rc._runs[i::-2]
381
381
 
382
382
 
383
- def test_run_collection_take(rc: RunCollection):
383
+ def test_take(rc: RunCollection):
384
384
  assert rc.take(3)._runs == rc._runs[:3]
385
385
  assert len(rc.take(4)) == 4
386
386
  assert rc.take(10)._runs == rc._runs
387
387
 
388
388
 
389
- def test_run_collection_take_neg(rc: RunCollection):
389
+ def test_take_neg(rc: RunCollection):
390
390
  assert rc.take(-3)._runs == rc._runs[-3:]
391
391
  assert len(rc.take(-4)) == 4
392
392
  assert rc.take(-10)._runs == rc._runs
393
393
 
394
394
 
395
395
  @pytest.mark.parametrize("i", range(6))
396
- def test_run_collection_contains(rc: RunCollection, i: int):
396
+ def test_contains(rc: RunCollection, i: int):
397
397
  assert rc[i] in rc
398
398
  assert rc._runs[i] in rc
399
399
 
400
400
 
401
- def test_run_collection_group_by(rc: RunCollection):
401
+ def test_group_by(rc: RunCollection):
402
402
  grouped = rc.group_by(["p"])
403
403
  assert len(grouped) == 6
404
404
  assert all(isinstance(group, RunCollection) for group in grouped.values())
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes