hydraflow 0.6.1__tar.gz → 0.7.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. {hydraflow-0.6.1 → hydraflow-0.7.0}/PKG-INFO +1 -1
  2. {hydraflow-0.6.1 → hydraflow-0.7.0}/pyproject.toml +1 -1
  3. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/run_collection.py +43 -119
  4. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/preemption.py +3 -8
  5. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/rerun.py +1 -1
  6. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/test_collection.py +6 -38
  7. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/utils/test_utils.py +1 -1
  8. {hydraflow-0.6.1 → hydraflow-0.7.0}/.devcontainer/devcontainer.json +0 -0
  9. {hydraflow-0.6.1 → hydraflow-0.7.0}/.devcontainer/postCreate.sh +0 -0
  10. {hydraflow-0.6.1 → hydraflow-0.7.0}/.devcontainer/starship.toml +0 -0
  11. {hydraflow-0.6.1 → hydraflow-0.7.0}/.gitattributes +0 -0
  12. {hydraflow-0.6.1 → hydraflow-0.7.0}/.gitignore +0 -0
  13. {hydraflow-0.6.1 → hydraflow-0.7.0}/LICENSE +0 -0
  14. {hydraflow-0.6.1 → hydraflow-0.7.0}/README.md +0 -0
  15. {hydraflow-0.6.1 → hydraflow-0.7.0}/apps/quickstart.py +0 -0
  16. {hydraflow-0.6.1 → hydraflow-0.7.0}/mkdocs.yml +0 -0
  17. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/__init__.py +0 -0
  18. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/config.py +0 -0
  19. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/context.py +0 -0
  20. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/mlflow.py +0 -0
  21. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/param.py +0 -0
  22. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/py.typed +0 -0
  23. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/run_data.py +0 -0
  24. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/run_info.py +0 -0
  25. {hydraflow-0.6.1 → hydraflow-0.7.0}/src/hydraflow/utils.py +0 -0
  26. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/__init__.py +0 -0
  27. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/config/__init__.py +0 -0
  28. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/config/overrides.py +0 -0
  29. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/config/test_config.py +0 -0
  30. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/config/test_overrides.py +0 -0
  31. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/config/test_params.py +0 -0
  32. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/conftest.py +0 -0
  33. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/__init__.py +0 -0
  34. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/chdir.py +0 -0
  35. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/context.py +0 -0
  36. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/logging.py +0 -0
  37. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/test_chdir.py +0 -0
  38. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/test_context.py +0 -0
  39. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/test_logging.py +0 -0
  40. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/test_preemption.py +0 -0
  41. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/context/test_rerun.py +0 -0
  42. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/param/__init__.py +0 -0
  43. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/param/params.py +0 -0
  44. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/param/test_param.py +0 -0
  45. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/param/test_params.py +0 -0
  46. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/__init__.py +0 -0
  47. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/filter.py +0 -0
  48. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/run.py +0 -0
  49. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/test_data.py +0 -0
  50. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/test_filter.py +0 -0
  51. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/test_info.py +0 -0
  52. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/run/test_run.py +0 -0
  53. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/test_mlflow.py +0 -0
  54. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/utils/__init__.py +0 -0
  55. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/utils/test_run.py +0 -0
  56. {hydraflow-0.6.1 → hydraflow-0.7.0}/tests/utils/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydraflow
3
- Version: 0.6.1
3
+ Version: 0.7.0
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hydraflow"
7
- version = "0.6.1"
7
+ version = "0.7.0"
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" }
@@ -236,7 +236,7 @@ class RunCollection:
236
236
 
237
237
  def filter(
238
238
  self,
239
- config: object | None = None,
239
+ config: object | Callable[[Run], bool] | None = None,
240
240
  *,
241
241
  override: bool = False,
242
242
  select: list[str] | None = None,
@@ -257,11 +257,13 @@ class RunCollection:
257
257
  - Membership checks for lists of values.
258
258
  - Range checks for tuples of two values (inclusive of both the lower
259
259
  and upper bound).
260
+ - Callable that takes a `Run` object and returns a boolean value.
260
261
 
261
262
  Args:
262
- config (object | None): The configuration object to filter the runs.
263
- This can be any object that provides key-value pairs through
264
- the `iter_params` function.
263
+ config (object | Callable[[Run], bool] | None): The configuration object
264
+ to filter the runs. This can be any object that provides key-value
265
+ pairs through the `iter_params` function, or a callable that
266
+ takes a `Run` object and returns a boolean value.
265
267
  override (bool): If True, override the configuration object with the
266
268
  provided key-value pairs.
267
269
  select (list[str] | None): The list of parameters to select.
@@ -284,105 +286,11 @@ class RunCollection:
284
286
  ),
285
287
  )
286
288
 
287
- def find(self, config: object | None = None, **kwargs) -> Run:
288
- """Find the first `Run` instance based on the provided configuration.
289
-
290
- This method filters the runs in the collection according to the
291
- specified configuration object and returns the first run that matches
292
- the provided parameters. If no run matches the criteria, a `ValueError`
293
- is raised.
294
-
295
- Args:
296
- config (object | None): The configuration object to identify the run.
297
- **kwargs: Additional key-value pairs to filter the runs.
298
-
299
- Returns:
300
- The first `Run` instance that matches the provided configuration.
301
-
302
- Raises:
303
- ValueError: If no run matches the criteria.
304
-
305
- See Also:
306
- `filter`: Perform the actual filtering logic.
307
-
308
- """
309
- try:
310
- return self.filter(config, **kwargs).first()
311
- except ValueError:
312
- raise ValueError("No run matches the provided configuration.")
313
-
314
- def try_find(self, config: object | None = None, **kwargs) -> Run | None:
315
- """Try to find the first `Run` instance based on the provided configuration.
316
-
317
- This method filters the runs in the collection according to the
318
- specified configuration object and returns the first run that matches
319
- the provided parameters. If no run matches the criteria, None is
320
- returned.
321
-
322
- Args:
323
- config (object | None): The configuration object to identify the run.
324
- **kwargs: Additional key-value pairs to filter the runs.
325
-
326
- Returns:
327
- The first `Run` instance that matches the provided configuration, or
328
- None if no runs match the criteria.
329
-
330
- See Also:
331
- `filter`: Perform the actual filtering logic.
332
-
333
- """
334
- return self.filter(config, **kwargs).try_first()
335
-
336
- def find_last(self, config: object | None = None, **kwargs) -> Run:
337
- """Find the last `Run` instance based on the provided configuration.
338
-
339
- This method filters the runs in the collection according to the
340
- specified configuration object and returns the last run that matches
341
- the provided parameters. If no run matches the criteria, a `ValueError`
342
- is raised.
343
-
344
- Args:
345
- config (object | None): The configuration object to identify the run.
346
- **kwargs: Additional key-value pairs to filter the runs.
347
-
348
- Returns:
349
- The last `Run` instance that matches the provided configuration.
350
-
351
- Raises:
352
- ValueError: If no run matches the criteria.
353
-
354
- See Also:
355
- `filter`: Perform the actual filtering logic.
356
-
357
- """
358
- try:
359
- return self.filter(config, **kwargs).last()
360
- except ValueError:
361
- raise ValueError("No run matches the provided configuration.")
362
-
363
- def try_find_last(self, config: object | None = None, **kwargs) -> Run | None:
364
- """Try to find the last `Run` instance based on the provided configuration.
365
-
366
- This method filters the runs in the collection according to the
367
- specified configuration object and returns the last run that matches
368
- the provided parameters. If no run matches the criteria, None is
369
- returned.
370
-
371
- Args:
372
- config (object | None): The configuration object to identify the run.
373
- **kwargs: Additional key-value pairs to filter the runs.
374
-
375
- Returns:
376
- The last `Run` instance that matches the provided configuration, or
377
- None if no runs match the criteria.
378
-
379
- See Also:
380
- `filter`: Perform the actual filtering logic.
381
-
382
- """
383
- return self.filter(config, **kwargs).try_last()
384
-
385
- def get(self, config: object | None = None, **kwargs) -> Run:
289
+ def get(
290
+ self,
291
+ config: object | Callable[[Run], bool] | None = None,
292
+ **kwargs,
293
+ ) -> Run:
386
294
  """Retrieve a specific `Run` instance based on the provided configuration.
387
295
 
388
296
  This method filters the runs in the collection according to the
@@ -391,7 +299,10 @@ class RunCollection:
391
299
  one run matches the criteria, a `ValueError` is raised.
392
300
 
393
301
  Args:
394
- config (object | None): The configuration object to identify the run.
302
+ config (object | Callable[[Run], bool] | None): The configuration object
303
+ to identify the run. This can be any object that provides key-value
304
+ pairs through the `iter_params` function, or a callable that
305
+ takes a `Run` object and returns a boolean value.
395
306
  **kwargs: Additional key-value pairs to filter the runs.
396
307
 
397
308
  Returns:
@@ -411,7 +322,11 @@ class RunCollection:
411
322
  msg = "The filtered collection does not contain exactly one run."
412
323
  raise ValueError(msg)
413
324
 
414
- def try_get(self, config: object | None = None, **kwargs) -> Run | None:
325
+ def try_get(
326
+ self,
327
+ config: object | Callable[[Run], bool] | None = None,
328
+ **kwargs,
329
+ ) -> Run | None:
415
330
  """Try to get a specific `Run` instance based on the provided configuration.
416
331
 
417
332
  This method filters the runs in the collection according to the
@@ -420,7 +335,10 @@ class RunCollection:
420
335
  If more than one run matches the criteria, a `ValueError` is raised.
421
336
 
422
337
  Args:
423
- config (object | None): The configuration object to identify the run.
338
+ config (object | Callable[[Run], bool] | None): The configuration object
339
+ to identify the run. This can be any object that provides key-value
340
+ pairs through the `iter_params` function, or a callable that
341
+ takes a `Run` object and returns a boolean value.
424
342
  **kwargs: Additional key-value pairs to filter the runs.
425
343
 
426
344
  Returns:
@@ -711,7 +629,7 @@ def _param_matches(run: Run, key: str, value: Any) -> bool:
711
629
 
712
630
  def filter_runs(
713
631
  runs: list[Run],
714
- config: object | None = None,
632
+ config: object | Callable[[Run], bool] | None = None,
715
633
  *,
716
634
  override: bool = False,
717
635
  select: list[str] | None = None,
@@ -735,9 +653,11 @@ def filter_runs(
735
653
 
736
654
  Args:
737
655
  runs (list[Run]): The list of runs to filter.
738
- config (object | None, optional): The configuration object to filter the
739
- runs. This can be any object that provides key-value pairs through
740
- the `iter_params` function. Defaults to None.
656
+ config (object | Callable[[Run], bool] | None, optional): The
657
+ configuration object to filter the runs. This can be any object
658
+ that provides key-value pairs through the `iter_params` function.
659
+ This can also be a callable that takes a `Run` object and returns
660
+ a boolean value. Defaults to None.
741
661
  override (bool, optional): If True, filter the runs based on
742
662
  the overrides. Defaults to False.
743
663
  select (list[str] | None, optional): The list of parameters to select.
@@ -750,15 +670,19 @@ def filter_runs(
750
670
  A list of runs that match the specified configuration and key-value pairs.
751
671
 
752
672
  """
753
- if override:
754
- config = select_overrides(config)
755
- elif select:
756
- config = select_config(config, select)
757
-
758
- for key, value in chain(iter_params(config), kwargs.items()):
759
- runs = [run for run in runs if _param_matches(run, key, value)]
760
- if not runs:
761
- return []
673
+ if callable(config):
674
+ runs = [run for run in runs if config(run)]
675
+
676
+ else:
677
+ if override:
678
+ config = select_overrides(config)
679
+ elif select:
680
+ config = select_config(config, select)
681
+
682
+ for key, value in chain(iter_params(config), kwargs.items()):
683
+ runs = [run for run in runs if _param_matches(run, key, value)]
684
+ if not runs:
685
+ return []
762
686
 
763
687
  if status is None:
764
688
  return runs
@@ -24,17 +24,12 @@ ConfigStore.instance().store(name="config", node=Config)
24
24
  def app(cfg: Config):
25
25
  hydraflow.set_experiment()
26
26
 
27
- rc = hydraflow.list_runs()
27
+ rc = hydraflow.list_runs().filter(cfg, override=True)
28
28
 
29
- if rc.filter(cfg, status="finished", override=True):
29
+ if rc.filter(status="finished"):
30
30
  return
31
31
 
32
- if run := rc.try_find(cfg, override=True):
33
- run_id = run.info.run_id
34
- else:
35
- run_id = None
36
-
37
- with hydraflow.start_run(cfg, run_id=run_id) as run:
32
+ with hydraflow.start_run(cfg, run=rc.try_one()) as run:
38
33
  log(hydraflow.get_artifact_dir(run))
39
34
 
40
35
 
@@ -24,7 +24,7 @@ ConfigStore.instance().store(name="config", node=Config)
24
24
  def app(cfg: Config):
25
25
  hydraflow.set_experiment()
26
26
 
27
- run = hydraflow.list_runs().try_find(cfg, override=True)
27
+ run = hydraflow.list_runs().try_get(cfg, override=True)
28
28
 
29
29
  with hydraflow.start_run(cfg, run=run) as run:
30
30
  log(hydraflow.get_artifact_dir(run))
@@ -129,6 +129,12 @@ def test_filter_list_none(runs: list[Run]):
129
129
  assert not filter_runs(runs, ["invalid=0"])
130
130
 
131
131
 
132
+ def test_filter_callable(runs: list[Run]):
133
+ runs = filter_runs(runs, lambda run: run.data.params["r"] == "0")
134
+ assert len(runs) == 2
135
+ assert all(run.data.params["q"] == "0" for run in runs)
136
+
137
+
132
138
  @pytest.mark.parametrize(
133
139
  ("status", "n"),
134
140
  [
@@ -326,44 +332,6 @@ def test_get_param_dict_drop_const(rc: RunCollection):
326
332
  assert "r" in params
327
333
 
328
334
 
329
- def test_find_dict(rc: RunCollection):
330
- run = rc.find({"r": 0})
331
- assert run.data.params["p"] == "0"
332
-
333
-
334
- def test_find_kwarg(rc: RunCollection):
335
- run = rc.find(r=2)
336
- assert run.data.params["p"] == "2"
337
-
338
-
339
- def test_find_none(rc: RunCollection):
340
- with pytest.raises(ValueError):
341
- rc.find({"r": 10})
342
-
343
-
344
- def test_try_find_none(rc: RunCollection):
345
- assert rc.try_find({"r": 10}) is None
346
-
347
-
348
- def test_find_last_dict(rc: RunCollection):
349
- run = rc.find_last({"r": 0})
350
- assert run.data.params["p"] == "3"
351
-
352
-
353
- def test_find_last_kwarg(rc: RunCollection):
354
- run = rc.find_last(r=2)
355
- assert run.data.params["p"] == "5"
356
-
357
-
358
- def test_find_last_none(rc: RunCollection):
359
- with pytest.raises(ValueError):
360
- rc.find_last({"p": 10})
361
-
362
-
363
- def test_try_find_last_none(rc: RunCollection):
364
- assert rc.try_find_last({"p": 10}) is None
365
-
366
-
367
335
  @pytest.mark.parametrize("n_jobs", [0, 1, 2])
368
336
  def test_list_runs(rc: RunCollection, n_jobs: int):
369
337
  assert len(list_runs(n_jobs=n_jobs)) == 6
@@ -39,7 +39,7 @@ def test_file_uri_to_path(uri, path):
39
39
 
40
40
 
41
41
  @pytest.mark.skipif(sys.platform != "win32", reason="This test is for Windows")
42
- def test_file_uri_to_path_win10_11():
42
+ def test_file_uri_to_path_win_python_310_311():
43
43
  from hydraflow.utils import file_uri_to_path
44
44
 
45
45
  assert file_uri_to_path("file:///C:/a/b/c").as_posix() == "C:/a/b/c"
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