liblaf-cherries 0.4.3__tar.gz → 0.5.0__tar.gz

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.
Files changed (50) hide show
  1. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/PKG-INFO +1 -1
  2. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/__init__.pyi +5 -7
  3. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/_entrypoint.py +2 -2
  4. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/_version.py +2 -2
  5. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/config/__init__.pyi +2 -0
  6. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/config/_asset.py +36 -13
  7. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/_plugin.py +4 -4
  8. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/_run.py +9 -20
  9. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/meta/_git.py +3 -3
  10. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/meta/_name.py +3 -3
  11. {liblaf_cherries-0.4.3/src/liblaf/cherries/paths → liblaf_cherries-0.5.0/src/liblaf/cherries/pathutils}/__init__.pyi +2 -3
  12. {liblaf_cherries-0.4.3/src/liblaf/cherries/paths → liblaf_cherries-0.5.0/src/liblaf/cherries/pathutils}/_convert.py +1 -1
  13. liblaf_cherries-0.5.0/src/liblaf/cherries/pathutils/_path.py +43 -0
  14. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/comet.py +14 -7
  15. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/dvc.py +1 -1
  16. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/git_.py +6 -12
  17. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/local.py +3 -3
  18. liblaf_cherries-0.4.3/src/liblaf/cherries/paths/_path.py +0 -70
  19. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/.gitignore +0 -0
  20. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/LICENSE +0 -0
  21. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/README.md +0 -0
  22. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/pyproject.toml +0 -0
  23. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/__init__.py +0 -0
  24. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/_version.pyi +0 -0
  25. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/config/__init__.py +0 -0
  26. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/config/_config.py +0 -0
  27. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/__init__.py +0 -0
  28. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/__init__.pyi +0 -0
  29. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/_impl.py +0 -0
  30. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/_spec.py +0 -0
  31. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/_utils.py +0 -0
  32. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/core/typed.py +0 -0
  33. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/meta/__init__.py +0 -0
  34. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/meta/__init__.pyi +0 -0
  35. {liblaf_cherries-0.4.3/src/liblaf/cherries/paths → liblaf_cherries-0.5.0/src/liblaf/cherries/pathutils}/__init__.py +0 -0
  36. {liblaf_cherries-0.4.3/src/liblaf/cherries/paths → liblaf_cherries-0.5.0/src/liblaf/cherries/pathutils}/_special.py +0 -0
  37. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/__init__.py +0 -0
  38. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/__init__.pyi +0 -0
  39. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/plugins/logging.py +0 -0
  40. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/profiles/__init__.py +0 -0
  41. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/profiles/__init__.pyi +0 -0
  42. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/profiles/_abc.py +0 -0
  43. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/profiles/_default.py +0 -0
  44. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/profiles/_factory.py +0 -0
  45. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/profiles/_playground.py +0 -0
  46. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/py.typed +0 -0
  47. /liblaf_cherries-0.4.3/src/liblaf/cherries/typed.py → /liblaf_cherries-0.5.0/src/liblaf/cherries/typing.py +0 -0
  48. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/utils/__init__.py +0 -0
  49. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/utils/__init__.pyi +0 -0
  50. {liblaf_cherries-0.4.3 → liblaf_cherries-0.5.0}/src/liblaf/cherries/utils/_functools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblaf-cherries
3
- Version: 0.4.3
3
+ Version: 0.5.0
4
4
  Summary: 🍒 Sweet experiment tracking with Comet, DVC, and Git integration.
5
5
  Project-URL: Changelog, https://github.com/liblaf/cherries/blob/main/CHANGELOG.md
6
6
  Project-URL: Documentation, https://cherries.readthedocs.io/
@@ -1,4 +1,4 @@
1
- from . import config, core, meta, paths, plugins
1
+ from . import config, core, meta, pathutils, plugins
2
2
  from ._entrypoint import end, run, start
3
3
  from .config import BaseConfig, input, output # noqa: A004
4
4
  from .core import (
@@ -15,17 +15,16 @@ from .core import (
15
15
  log_parameter,
16
16
  log_parameters,
17
17
  )
18
- from .paths import (
18
+ from .pathutils import (
19
19
  as_os_path,
20
20
  as_path,
21
21
  as_posix,
22
22
  data,
23
23
  entrypoint,
24
24
  exp_dir,
25
- git_root,
26
- git_root_safe,
27
25
  params,
28
26
  path,
27
+ project_dir,
29
28
  src,
30
29
  )
31
30
 
@@ -43,8 +42,6 @@ __all__ = [
43
42
  "end",
44
43
  "entrypoint",
45
44
  "exp_dir",
46
- "git_root",
47
- "git_root_safe",
48
45
  "input",
49
46
  "log_asset",
50
47
  "log_input",
@@ -59,8 +56,9 @@ __all__ = [
59
56
  "output",
60
57
  "params",
61
58
  "path",
62
- "paths",
59
+ "pathutils",
63
60
  "plugins",
61
+ "project_dir",
64
62
  "run",
65
63
  "src",
66
64
  "start",
@@ -40,8 +40,8 @@ def start(
40
40
  ) -> core.Run:
41
41
  run: core.Run = profiles.factory(profile).init()
42
42
  run.start()
43
- run.log_other("cherries.entrypoint", run.entrypoint.relative_to(run.root_dir))
44
- run.log_other("cherries.exp_dir", run.exp_dir.relative_to(run.root_dir))
43
+ run.log_other("cherries.entrypoint", run.entrypoint.relative_to(run.project_dir))
44
+ run.log_other("cherries.exp_dir", run.exp_dir.relative_to(run.project_dir))
45
45
  run.log_other("cherries.start_time", run.start_time)
46
46
  return run
47
47
 
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.4.3'
32
- __version_tuple__ = version_tuple = (0, 4, 3)
31
+ __version__ = version = '0.5.0'
32
+ __version_tuple__ = version_tuple = (0, 5, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -8,6 +8,7 @@ from ._asset import (
8
8
  input, # noqa: A004
9
9
  model_dump_without_assets,
10
10
  output,
11
+ path_generators,
11
12
  )
12
13
  from ._config import BaseConfig
13
14
 
@@ -22,4 +23,5 @@ __all__ = [
22
23
  "input",
23
24
  "model_dump_without_assets",
24
25
  "output",
26
+ "path_generators",
25
27
  ]
@@ -6,8 +6,8 @@ from typing import Any, Literal
6
6
  import pydantic
7
7
 
8
8
  from liblaf import grapes
9
- from liblaf.cherries import paths
10
- from liblaf.cherries.typed import PathLike
9
+ from liblaf.cherries import pathutils
10
+ from liblaf.cherries.typing import PathLike
11
11
 
12
12
 
13
13
  class AssetKind(enum.StrEnum):
@@ -20,6 +20,21 @@ type PathGenerator = (
20
20
  )
21
21
 
22
22
 
23
+ path_generators: dict[str, PathGenerator] = {}
24
+
25
+
26
+ def _path_generator_series(path: PathLike) -> list[Path]:
27
+ path = Path(path)
28
+ if (folder := path.with_suffix(".d")).exists():
29
+ return [folder]
30
+ if (folder := path.with_suffix("")).exists():
31
+ return [folder]
32
+ return []
33
+
34
+
35
+ path_generators[".series"] = _path_generator_series
36
+
37
+
23
38
  class MetaAsset:
24
39
  kind: AssetKind
25
40
  _extra: PathGenerator | None = None
@@ -29,15 +44,27 @@ class MetaAsset:
29
44
  self._extra = extra
30
45
 
31
46
  def get_extra(self, value: Path) -> list[Path]:
32
- if self._extra is None:
47
+ extra: PathGenerator | None = self._extra
48
+ if extra is None:
49
+ extra = path_generators.get(value.suffix)
50
+ if extra is None:
33
51
  return []
34
- if callable(self._extra):
35
- extra: Iterable[PathLike] = grapes.as_iterable(self._extra(value))
36
- return [Path(p) for p in extra]
37
- extra: Iterable[PathLike] = grapes.as_iterable(self._extra)
52
+ if callable(extra):
53
+ extra = extra(value)
54
+ extra = grapes.as_iterable(extra)
38
55
  return [Path(p) for p in extra]
39
56
 
40
57
 
58
+ def asset(
59
+ path: PathLike, extra: PathGenerator | None = None, *, kind: AssetKind, **kwargs
60
+ ) -> Path:
61
+ field_info: pydantic.fields.FieldInfo = pydantic.Field(
62
+ pathutils.data(path), **kwargs
63
+ ) # pyright: ignore[reportAssignmentType]
64
+ field_info.metadata.append(MetaAsset(kind=kind, extra=extra))
65
+ return field_info # pyright: ignore[reportReturnType]
66
+
67
+
41
68
  def get_assets(cfg: pydantic.BaseModel, kind: AssetKind) -> list[Path]:
42
69
  assets: list[Path] = []
43
70
  for name, info in type(cfg).model_fields.items():
@@ -61,9 +88,7 @@ def get_outputs(cfg: pydantic.BaseModel) -> list[Path]:
61
88
 
62
89
 
63
90
  def input(path: PathLike, extra: PathGenerator | None = None, **kwargs) -> Path: # noqa: A001
64
- field_info: pydantic.fields.FieldInfo = pydantic.Field(paths.data(path), **kwargs) # pyright: ignore[reportAssignmentType]
65
- field_info.metadata.append(MetaAsset(kind=AssetKind.INPUT, extra=extra))
66
- return field_info # pyright: ignore[reportReturnType]
91
+ return asset(path, extra=extra, kind=AssetKind.INPUT, **kwargs)
67
92
 
68
93
 
69
94
  def model_dump_without_assets(
@@ -87,6 +112,4 @@ def model_dump_without_assets(
87
112
 
88
113
 
89
114
  def output(path: PathLike, extra: PathGenerator | None = None, **kwargs) -> Path:
90
- field_info: pydantic.fields.FieldInfo = pydantic.Field(paths.data(path), **kwargs) # pyright: ignore[reportAssignmentType]
91
- field_info.metadata.append(MetaAsset(kind=AssetKind.OUTPUT, extra=extra))
92
- return field_info # pyright: ignore[reportReturnType]
115
+ return asset(path, extra=extra, kind=AssetKind.OUTPUT, **kwargs)
@@ -1,4 +1,4 @@
1
- from collections.abc import Mapping, MutableMapping, Sequence
1
+ from collections.abc import Mapping, Sequence
2
2
  from typing import Any, Self
3
3
 
4
4
  import attrs
@@ -6,15 +6,15 @@ import networkx as nx
6
6
 
7
7
  from ._impl import ImplInfo, get_impl_info
8
8
  from ._spec import SpecInfo, collect_specs
9
- from .typed import MethodName
9
+ from .typed import MethodName, PluginId
10
10
 
11
11
 
12
12
  @attrs.define
13
13
  class Plugin:
14
- plugins: dict[str, "Plugin"] = attrs.field(factory=dict, kw_only=True)
14
+ plugins: dict[PluginId, "Plugin"] = attrs.field(factory=dict, kw_only=True)
15
15
 
16
16
  _plugin_parent: Self | None = attrs.field(default=None, kw_only=True)
17
- _sort_plugins_cache: MutableMapping[MethodName, Sequence["Plugin"]] = attrs.field(
17
+ _sort_plugins_cache: dict[MethodName, Sequence["Plugin"]] = attrs.field(
18
18
  factory=dict, init=False
19
19
  )
20
20
 
@@ -6,10 +6,9 @@ from pathlib import Path
6
6
  from typing import Any
7
7
 
8
8
  import attrs
9
- import git
10
9
 
11
- from liblaf.cherries import paths
12
- from liblaf.cherries.typed import PathLike
10
+ from liblaf.cherries import pathutils
11
+ from liblaf.cherries.typing import PathLike
13
12
 
14
13
  from ._plugin import Plugin
15
14
  from ._spec import spec
@@ -29,19 +28,19 @@ class Run(Plugin):
29
28
  def data_dir(self) -> Path:
30
29
  if self._plugin_parent is not None:
31
30
  return self.plugin_root.data_dir
32
- return paths.data()
31
+ return pathutils.data()
33
32
 
34
33
  @functools.cached_property
35
34
  def entrypoint(self) -> Path:
36
35
  if self._plugin_parent is not None:
37
36
  return self.plugin_root.entrypoint
38
- return paths.entrypoint()
37
+ return pathutils.entrypoint()
39
38
 
40
39
  @functools.cached_property
41
40
  def exp_dir(self) -> Path:
42
41
  if self._plugin_parent is not None:
43
42
  return self.plugin_root.exp_dir
44
- return paths.exp_dir()
43
+ return pathutils.exp_dir()
45
44
 
46
45
  @functools.cached_property
47
46
  def name(self) -> str:
@@ -59,23 +58,13 @@ class Run(Plugin):
59
58
  def project_name(self) -> str | None:
60
59
  if self._plugin_parent is not None:
61
60
  return self.plugin_root.project_name
62
- try:
63
- repo: git.Repo = git.Repo(search_parent_directories=True)
64
- except git.InvalidGitRepositoryError:
65
- return None
66
- else:
67
- return Path(repo.working_dir).name
61
+ return self.project_dir.name
68
62
 
69
63
  @functools.cached_property
70
- def root_dir(self) -> Path:
64
+ def project_dir(self) -> Path:
71
65
  if self._plugin_parent is not None:
72
- return self.plugin_root.root_dir
73
- try:
74
- repo: git.Repo = git.Repo(search_parent_directories=True)
75
- except git.InvalidGitRepositoryError:
76
- return self.entrypoint.parent
77
- else:
78
- return Path(repo.working_dir).absolute()
66
+ return self.plugin_root.project_dir
67
+ return pathutils.project_dir()
79
68
 
80
69
  @functools.cached_property
81
70
  def start_time(self) -> datetime.datetime:
@@ -3,7 +3,7 @@ import subprocess as sp
3
3
  import git
4
4
 
5
5
  from liblaf import grapes
6
- from liblaf.cherries import paths
6
+ from liblaf.cherries import pathutils
7
7
 
8
8
 
9
9
  def git_auto_commit(
@@ -40,10 +40,10 @@ def git_commit_url(sha: str | None = None) -> str:
40
40
 
41
41
  def git_info() -> grapes.git.GitInfo:
42
42
  info: grapes.git.GitInfo = grapes.git.info(
43
- paths.entrypoint(absolute=True), search_parent_directories=True
43
+ pathutils.exp_dir(absolute=True), search_parent_directories=True
44
44
  )
45
45
  return info
46
46
 
47
47
 
48
48
  def _repo() -> git.Repo:
49
- return git.Repo(paths.entrypoint(absolute=True), search_parent_directories=True)
49
+ return git.Repo(pathutils.exp_dir(absolute=True), search_parent_directories=True)
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
  import git.exc
4
4
 
5
5
  from liblaf import grapes
6
- from liblaf.cherries import paths
6
+ from liblaf.cherries import pathutils
7
7
 
8
8
  from ._git import git_info
9
9
 
@@ -18,8 +18,8 @@ def project_name() -> str | None:
18
18
 
19
19
 
20
20
  def exp_name() -> str:
21
- exp_dir: Path = paths.entrypoint(absolute=False)
22
- exp_name: str = paths.as_posix(exp_dir)
21
+ exp_dir: Path = pathutils.exp_dir(absolute=False)
22
+ exp_name: str = pathutils.as_posix(exp_dir)
23
23
  exp_name = exp_name.removeprefix("exp")
24
24
  exp_name = exp_name.removeprefix("/")
25
25
  return exp_name
@@ -1,5 +1,5 @@
1
1
  from ._convert import as_os_path, as_path, as_posix
2
- from ._path import entrypoint, exp_dir, git_root, git_root_safe
2
+ from ._path import entrypoint, exp_dir, project_dir
3
3
  from ._special import config, data, params, path, src
4
4
 
5
5
  __all__ = [
@@ -10,9 +10,8 @@ __all__ = [
10
10
  "data",
11
11
  "entrypoint",
12
12
  "exp_dir",
13
- "git_root",
14
- "git_root_safe",
15
13
  "params",
16
14
  "path",
15
+ "project_dir",
17
16
  "src",
18
17
  ]
@@ -1,7 +1,7 @@
1
1
  from pathlib import Path
2
2
  from typing import overload
3
3
 
4
- from liblaf.cherries.typed import PathLike
4
+ from liblaf.cherries.typing import PathLike
5
5
 
6
6
 
7
7
  @overload
@@ -0,0 +1,43 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ import git
5
+ import git.exc
6
+ from loguru import logger
7
+
8
+ from liblaf.cherries import utils
9
+
10
+
11
+ @utils.cache
12
+ def entrypoint(*, absolute: bool = True) -> Path:
13
+ path = Path(sys.argv[0])
14
+ if absolute:
15
+ return path.absolute()
16
+ return path.relative_to(project_dir())
17
+
18
+
19
+ EXP_DIR_NAMES: set[str] = {"exp", "experiment", "experiments", "exps", "src"}
20
+
21
+
22
+ @utils.cache
23
+ def exp_dir(*, absolute: bool = True) -> Path:
24
+ entrypoint_: Path = entrypoint(absolute=True)
25
+ parent: Path = entrypoint_.parent
26
+ exp_dir: Path
27
+ exp_dir = parent.parent if parent.name in EXP_DIR_NAMES else parent
28
+ if absolute:
29
+ return exp_dir
30
+ exp_dir = exp_dir.relative_to(project_dir())
31
+ return exp_dir
32
+
33
+
34
+ @utils.cache
35
+ def project_dir() -> Path:
36
+ exp_dir_: Path = exp_dir(absolute=True)
37
+ try:
38
+ repo = git.Repo(exp_dir_, search_parent_directories=True)
39
+ except git.exc.InvalidGitRepositoryError:
40
+ logger.warning("Not in a git repository, using current directory", once=True)
41
+ return exp_dir_
42
+ else:
43
+ return Path(repo.working_dir)
@@ -5,10 +5,12 @@ from typing import Any, override
5
5
  import attrs
6
6
  import comet_ml
7
7
  import cytoolz as toolz
8
+ import dvc.api
9
+ import dvc.exceptions
8
10
 
9
11
  from liblaf import grapes
10
- from liblaf.cherries import core, paths
11
- from liblaf.cherries.typed import PathLike
12
+ from liblaf.cherries import core, pathutils
13
+ from liblaf.cherries.typing import PathLike
12
14
 
13
15
 
14
16
  @attrs.define
@@ -47,13 +49,18 @@ class Comet(core.Run):
47
49
  **kwargs,
48
50
  ) -> None:
49
51
  path = Path(path)
50
- name = paths.as_posix(name)
51
- dvc_file: Path = path.with_name(path.name + ".dvc")
52
- if dvc_file.exists():
53
- path = dvc_file
52
+ name = pathutils.as_posix(name)
53
+ try:
54
+ # ? I don't know why, but `dvc.api.get_url` only works with this. Maybe a DVC bug?
55
+ dvc_path: Path = path.absolute().relative_to(Path.cwd())
56
+ uri: str = dvc.api.get_url(str(dvc_path))
57
+ except dvc.exceptions.OutputNotFoundError:
58
+ self.exp.log_asset(path, name, metadata=metadata, **kwargs) # pyright: ignore[reportArgumentType]
59
+ else:
60
+ dvc_file: Path = path.with_name(path.name + ".dvc")
54
61
  dvc_meta: Mapping[str, Any] = grapes.yaml.load(dvc_file)
55
62
  metadata = toolz.merge(metadata or {}, dvc_meta["outs"][0])
56
- self.exp.log_asset(path, name, metadata=metadata, **kwargs) # pyright: ignore[reportArgumentType]
63
+ self.exp.log_remote_asset(uri, name, metadata=metadata, **kwargs) # pyright: ignore[reportArgumentType]
57
64
 
58
65
  @override
59
66
  @core.impl(after=("Dvc",))
@@ -5,7 +5,7 @@ from typing import override
5
5
  import attrs
6
6
 
7
7
  from liblaf.cherries import core
8
- from liblaf.cherries.typed import PathLike
8
+ from liblaf.cherries.typing import PathLike
9
9
 
10
10
 
11
11
  @attrs.define
@@ -6,16 +6,10 @@ from typing import Any, override
6
6
 
7
7
  import attrs
8
8
  import git
9
- import msgspec
10
9
 
10
+ from liblaf import grapes
11
11
  from liblaf.cherries import core
12
- from liblaf.cherries.typed import PathLike
13
-
14
-
15
- def enc_hook(obj: Any) -> Any:
16
- if isinstance(obj, Path):
17
- return str(obj)
18
- raise NotImplementedError
12
+ from liblaf.cherries.typing import PathLike
19
13
 
20
14
 
21
15
  @attrs.define
@@ -39,7 +33,7 @@ class Git(core.Run):
39
33
  @core.impl
40
34
  def log_input(self, path: PathLike, *args, **kwargs) -> None:
41
35
  path: Path = Path(path)
42
- self.inputs.append(path.relative_to(self.repo.working_dir))
36
+ self.inputs.append(path.relative_to(self.project_dir))
43
37
 
44
38
  @override
45
39
  @core.impl
@@ -50,12 +44,12 @@ class Git(core.Run):
50
44
  **kwargs,
51
45
  ) -> None:
52
46
  path: Path = Path(path)
53
- self.outputs.append(path.relative_to(self.repo.working_dir))
47
+ self.outputs.append(path.relative_to(self.project_dir))
54
48
 
55
49
  @override
56
50
  @core.impl
57
51
  def start(self, *args, **kwargs) -> None:
58
- self.repo = git.Repo(self.plugin_root.exp_dir, search_parent_directories=True)
52
+ self.repo = git.Repo(self.project_dir, search_parent_directories=True)
59
53
 
60
54
  def _make_commit_message(self) -> str:
61
55
  name: str = self.plugin_root.name
@@ -70,5 +64,5 @@ class Git(core.Run):
70
64
  metadata["inputs"] = inputs
71
65
  if outputs := self.outputs:
72
66
  metadata["outputs"] = outputs
73
- message += msgspec.yaml.encode(metadata, enc_hook=enc_hook).decode()
67
+ message += grapes.yaml.encode(metadata).decode()
74
68
  return message
@@ -5,7 +5,7 @@ from typing import override
5
5
  import attrs
6
6
 
7
7
  from liblaf.cherries import core
8
- from liblaf.cherries.typed import PathLike
8
+ from liblaf.cherries.typing import PathLike
9
9
 
10
10
 
11
11
  @attrs.define
@@ -54,8 +54,8 @@ class Local(core.Run):
54
54
  @override
55
55
  @core.impl
56
56
  def start(self, *args, **kwargs) -> None:
57
- self.folder = self.plugin_root.exp_dir / ".cherries" / self.plugin_root.name
58
- entrypoint: Path = self.plugin_root.entrypoint
57
+ self.folder = self.exp_dir / ".cherries" / self.name
58
+ entrypoint: Path = self.entrypoint
59
59
  self.log_asset(entrypoint, f"src/{entrypoint.name}")
60
60
 
61
61
  def _copy(self, source: PathLike, target: PathLike) -> None:
@@ -1,70 +0,0 @@
1
- import sys
2
- from collections.abc import Container
3
- from pathlib import Path
4
-
5
- import git
6
- import git.exc
7
- from loguru import logger
8
-
9
- from liblaf.cherries import utils
10
-
11
-
12
- @utils.cache
13
- def entrypoint(*, absolute: bool = True) -> Path:
14
- if absolute:
15
- return _entrypoint_absolute()
16
- return _entrypoint_relative()
17
-
18
-
19
- @utils.cache
20
- def git_root() -> Path:
21
- entrypoint: Path = _entrypoint_absolute()
22
- repo = git.Repo(entrypoint, search_parent_directories=True)
23
- return Path(repo.working_dir)
24
-
25
-
26
- @utils.cache
27
- def git_root_safe() -> Path:
28
- try:
29
- return git_root()
30
- except git.exc.InvalidGitRepositoryError:
31
- logger.warning("Not in a git repository, using current directory", once=True)
32
- return _entrypoint_absolute().parent
33
-
34
-
35
- @utils.cache
36
- def exp_dir(*, absolute: bool = True) -> Path:
37
- if absolute:
38
- return _exp_dir_absolute()
39
- return _exp_dir_relative()
40
-
41
-
42
- @utils.cache
43
- def _entrypoint_absolute() -> Path:
44
- path = Path(sys.argv[0])
45
- return path.absolute()
46
-
47
-
48
- @utils.cache
49
- def _entrypoint_relative() -> Path:
50
- path: Path = _entrypoint_absolute()
51
- return path.relative_to(git_root_safe())
52
-
53
-
54
- EXP_DIR_NAMES: Container[str] = {"exp", "experiment", "experiments", "exps", "src"}
55
-
56
-
57
- @utils.cache
58
- def _exp_dir_absolute() -> Path:
59
- entrypoint: Path = _entrypoint_absolute()
60
- parent: Path = entrypoint.parent
61
- if parent.name in EXP_DIR_NAMES:
62
- return parent.parent
63
- return parent
64
-
65
-
66
- @utils.cache
67
- def _exp_dir_relative() -> Path:
68
- absolute: Path = _exp_dir_absolute()
69
- root: Path = git_root_safe()
70
- return absolute.relative_to(root)
File without changes