liblaf-cherries 0.4.3__py3-none-any.whl → 0.5.1__py3-none-any.whl

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 (49) hide show
  1. liblaf/cherries/__init__.py +1 -0
  2. liblaf/cherries/__init__.pyi +5 -7
  3. liblaf/cherries/_entrypoint.py +11 -10
  4. liblaf/cherries/_version.py +2 -2
  5. liblaf/cherries/config/__init__.py +1 -0
  6. liblaf/cherries/config/__init__.pyi +16 -4
  7. liblaf/cherries/config/_config.py +1 -2
  8. liblaf/cherries/{paths → config/asset}/__init__.py +1 -0
  9. liblaf/cherries/config/asset/__init__.pyi +34 -0
  10. liblaf/cherries/config/asset/_meta.py +98 -0
  11. liblaf/cherries/config/asset/_registry.py +25 -0
  12. liblaf/cherries/config/asset/resolvers/__init__.py +4 -0
  13. liblaf/cherries/config/asset/resolvers/__init__.pyi +5 -0
  14. liblaf/cherries/config/asset/resolvers/_abc.py +17 -0
  15. liblaf/cherries/config/asset/resolvers/_series.py +18 -0
  16. liblaf/cherries/config/asset/resolvers/_vtk.py +33 -0
  17. liblaf/cherries/core/__init__.py +1 -0
  18. liblaf/cherries/core/__init__.pyi +15 -3
  19. liblaf/cherries/core/_impl.py +20 -7
  20. liblaf/cherries/core/_plugin.py +53 -50
  21. liblaf/cherries/core/_run.py +22 -52
  22. liblaf/cherries/core/_spec.py +10 -11
  23. liblaf/cherries/core/_utils.py +44 -1
  24. liblaf/cherries/meta/__init__.py +1 -0
  25. liblaf/cherries/meta/_git.py +3 -3
  26. liblaf/cherries/meta/_name.py +3 -3
  27. liblaf/cherries/path_utils/__init__.py +4 -0
  28. liblaf/cherries/{paths → path_utils}/__init__.pyi +2 -3
  29. liblaf/cherries/{paths → path_utils}/_convert.py +1 -1
  30. liblaf/cherries/path_utils/_path.py +43 -0
  31. liblaf/cherries/plugins/__init__.py +1 -0
  32. liblaf/cherries/plugins/comet.py +16 -9
  33. liblaf/cherries/plugins/dvc.py +1 -1
  34. liblaf/cherries/plugins/git_.py +17 -21
  35. liblaf/cherries/plugins/local.py +3 -3
  36. liblaf/cherries/plugins/logging.py +2 -2
  37. liblaf/cherries/profiles/__init__.py +1 -0
  38. liblaf/cherries/profiles/_factory.py +2 -3
  39. liblaf/cherries/utils/__init__.py +1 -0
  40. {liblaf_cherries-0.4.3.dist-info → liblaf_cherries-0.5.1.dist-info}/METADATA +2 -2
  41. liblaf_cherries-0.5.1.dist-info/RECORD +56 -0
  42. liblaf/cherries/config/_asset.py +0 -92
  43. liblaf/cherries/paths/_path.py +0 -70
  44. liblaf_cherries-0.4.3.dist-info/RECORD +0 -48
  45. /liblaf/cherries/core/{typed.py → typing.py} +0 -0
  46. /liblaf/cherries/{paths → path_utils}/_special.py +0 -0
  47. /liblaf/cherries/{typed.py → typing.py} +0 -0
  48. {liblaf_cherries-0.4.3.dist-info → liblaf_cherries-0.5.1.dist-info}/WHEEL +0 -0
  49. {liblaf_cherries-0.4.3.dist-info → liblaf_cherries-0.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,18 +1,17 @@
1
1
  import contextlib
2
2
  import datetime
3
- import functools
4
3
  from collections.abc import Mapping
5
4
  from pathlib import Path
6
5
  from typing import Any
7
6
 
8
7
  import attrs
9
- import git
10
8
 
11
- from liblaf.cherries import paths
12
- from liblaf.cherries.typed import PathLike
9
+ from liblaf.cherries import path_utils
10
+ from liblaf.cherries.typing import PathLike
13
11
 
14
12
  from ._plugin import Plugin
15
13
  from ._spec import spec
14
+ from ._utils import plugin_cached_property, plugin_property
16
15
 
17
16
 
18
17
  @attrs.define
@@ -25,69 +24,41 @@ class Run(Plugin):
25
24
  3. [MLflow Tracking APIs | MLflow](https://www.mlflow.org/docs/latest/ml/tracking/tracking-api/)
26
25
  """
27
26
 
28
- @functools.cached_property
27
+ @plugin_cached_property
29
28
  def data_dir(self) -> Path:
30
- if self._plugin_parent is not None:
31
- return self.plugin_root.data_dir
32
- return paths.data()
29
+ return path_utils.data()
33
30
 
34
- @functools.cached_property
31
+ @plugin_cached_property
35
32
  def entrypoint(self) -> Path:
36
- if self._plugin_parent is not None:
37
- return self.plugin_root.entrypoint
38
- return paths.entrypoint()
33
+ return path_utils.entrypoint()
39
34
 
40
- @functools.cached_property
35
+ @plugin_cached_property
41
36
  def exp_dir(self) -> Path:
42
- if self._plugin_parent is not None:
43
- return self.plugin_root.exp_dir
44
- return paths.exp_dir()
37
+ return path_utils.exp_dir()
45
38
 
46
- @functools.cached_property
39
+ @plugin_cached_property
47
40
  def name(self) -> str:
48
- if self._plugin_parent is not None:
49
- return self.plugin_root.name
50
41
  return self.start_time.strftime("%Y-%m-%dT%H%M%S")
51
42
 
52
- @property
43
+ @plugin_property
53
44
  def params(self) -> Mapping[str, Any]:
54
- if self._plugin_parent is not None:
55
- return self.plugin_root.params
56
- return self.get_params()
45
+ return self.plugin_root.get_params()
57
46
 
58
- @functools.cached_property
47
+ @plugin_cached_property
59
48
  def project_name(self) -> str | None:
60
- if self._plugin_parent is not None:
61
- 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
68
-
69
- @functools.cached_property
70
- def root_dir(self) -> Path:
71
- 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()
79
-
80
- @functools.cached_property
49
+ return self.project_dir.name
50
+
51
+ @plugin_cached_property
52
+ def project_dir(self) -> Path:
53
+ return path_utils.project_dir()
54
+
55
+ @plugin_cached_property
81
56
  def start_time(self) -> datetime.datetime:
82
- if self._plugin_parent is not None:
83
- return self.plugin_root.start_time
84
57
  return datetime.datetime.now().astimezone()
85
58
 
86
- @functools.cached_property
59
+ @plugin_property
87
60
  def url(self) -> str:
88
- if self._plugin_parent is not None:
89
- return self.plugin_root.url
90
- return self.get_url()
61
+ return self.plugin_root.get_url()
91
62
 
92
63
  @spec
93
64
  def end(self, *args, **kwargs) -> None: ...
@@ -181,7 +152,6 @@ class Run(Plugin):
181
152
 
182
153
  @spec(delegate=False)
183
154
  def start(self, *args, **kwargs) -> None:
184
- self._plugins_prepare()
185
155
  self.delegate("start", args, kwargs)
186
156
 
187
157
 
@@ -4,11 +4,10 @@ from collections.abc import Callable, Mapping, Sequence
4
4
  from typing import Any, Protocol, overload
5
5
 
6
6
  import attrs
7
- import wrapt
8
7
 
9
8
  from liblaf import grapes
10
9
 
11
- from .typed import MethodName
10
+ from .typing import MethodName
12
11
 
13
12
 
14
13
  class Plugin(Protocol):
@@ -48,27 +47,27 @@ def spec(
48
47
 
49
48
  info = SpecInfo(delegate=delegate, first_result=first_result)
50
49
 
51
- @wrapt.decorator
52
- def wrapper(
53
- wrapped: Callable, instance: Plugin, args: tuple, kwargs: dict[str, Any]
54
- ) -> Any:
50
+ @grapes.decorator
51
+ def wrapper[**P, T](
52
+ wrapped: Callable[P, T], instance: Plugin, args: tuple, kwargs: dict[str, Any]
53
+ ) -> T:
55
54
  if info.delegate:
56
55
  return instance.delegate(
57
56
  wrapped.__name__, args, kwargs, first_result=info.first_result
58
57
  )
59
58
  return wrapped(*args, **kwargs)
60
59
 
61
- proxy: Any = wrapper(func) # pyright: ignore[reportCallIssue]
62
- proxy._self_spec = SpecInfo(delegate=delegate, first_result=first_result) # noqa: SLF001
63
- return proxy
60
+ func: Any = wrapper(func)
61
+ grapes.wrapt_setattr(func, "spec", info)
62
+ return func
64
63
 
65
64
 
66
65
  def collect_specs(cls: type[Plugin] | Plugin) -> dict[str, SpecInfo]:
67
66
  if isinstance(cls, type):
68
67
  cls = type(cls)
69
68
  return {
70
- name: grapes.unbind_getattr(method, "_self_spec")
69
+ name: grapes.wrapt_getattr(method, "spec")
71
70
  for name, method in inspect.getmembers(
72
- cls, lambda m: grapes.unbind_getattr(m, "_self_spec", None) is not None
71
+ cls, lambda m: grapes.wrapt_getattr(m, "spec", None) is not None
73
72
  )
74
73
  }
@@ -1,5 +1,6 @@
1
+ import functools
1
2
  from collections.abc import Callable
2
- from typing import TYPE_CHECKING, Any
3
+ from typing import TYPE_CHECKING, Any, Self, overload, override
3
4
 
4
5
  import wrapt
5
6
 
@@ -18,3 +19,45 @@ def delegate_property_to_root[C: Callable](func: C) -> C:
18
19
  return getattr(instance.plugin_root, wrapped.__name__)
19
20
 
20
21
  return func
22
+
23
+
24
+ class PluginCachedProperty[T](functools.cached_property[T]):
25
+ @overload
26
+ def __get__(self, instance: None, owner: type | None = None) -> Self: ...
27
+ @overload
28
+ def __get__(self, instance: object, owner: type | None = None) -> T: ...
29
+ @override
30
+ def __get__(self, instance: object | None, owner: type | None = None) -> Self | T:
31
+ if instance is None:
32
+ return super().__get__(instance, owner)
33
+ if (parent := getattr(instance, "_plugin_parent", None)) is not None:
34
+ instance = parent
35
+ return super().__get__(instance, owner)
36
+
37
+ @override
38
+ def __set__(self, instance: object, value: T) -> None:
39
+ assert self.attrname is not None
40
+ instance.__dict__[self.attrname] = value
41
+
42
+
43
+ class PluginProperty[T](property):
44
+ @overload
45
+ def __get__(self, instance: None, owner: type, /) -> Self: ...
46
+ @overload
47
+ def __get__(self, instance: Any, owner: type | None = None, /) -> Any: ...
48
+ def __get__(
49
+ self, instance: object | None, owner: type | None = None, /
50
+ ) -> Self | T:
51
+ if instance is None:
52
+ return super().__get__(instance, owner)
53
+ if (parent := getattr(instance, "_plugin_parent", None)) is not None:
54
+ instance = parent
55
+ return super().__get__(instance, owner)
56
+
57
+
58
+ def plugin_cached_property[T](func: Callable[[Any], T]) -> PluginCachedProperty[T]:
59
+ return PluginCachedProperty(func)
60
+
61
+
62
+ def plugin_property[T](fget: Callable[[Any], T]) -> PluginProperty[T]:
63
+ return PluginProperty(fget)
@@ -1,3 +1,4 @@
1
1
  import lazy_loader as lazy
2
2
 
3
3
  __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
4
+ del lazy
@@ -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 path_utils
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
+ path_utils.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(path_utils.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 path_utils
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 = path_utils.exp_dir(absolute=False)
22
+ exp_name: str = path_utils.as_posix(exp_dir)
23
23
  exp_name = exp_name.removeprefix("exp")
24
24
  exp_name = exp_name.removeprefix("/")
25
25
  return exp_name
@@ -0,0 +1,4 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
4
+ del lazy
@@ -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)
@@ -1,3 +1,4 @@
1
1
  import lazy_loader as lazy
2
2
 
3
3
  __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
4
+ del lazy
@@ -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, path_utils
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 = path_utils.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",))
@@ -121,8 +128,8 @@ class Comet(core.Run):
121
128
  @core.impl(after=("Logging",))
122
129
  def start(self, *args, **kwargs) -> None:
123
130
  self.exp = comet_ml.start(
124
- project_name=self.plugin_root.project_name,
131
+ project_name=self.project_name,
125
132
  experiment_config=comet_ml.ExperimentConfig(
126
- disabled=self.disabled, name=self.plugin_root.name
133
+ disabled=self.disabled, name=self.name
127
134
  ),
128
135
  )
@@ -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,25 +44,27 @@ 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
- name: str = self.plugin_root.name
55
+ name: str = self.name
62
56
  message: str = f"chore(cherries): {name}\n\n"
63
- metadata: dict[str, Any] = {}
64
- metadata["cmd"] = shlex.join(sys.orig_argv)
65
- if url := self.plugin_root.url:
66
- metadata["url"] = url
67
- if params := self.plugin_root.get_params():
68
- metadata["params"] = params
57
+ meta: dict[str, Any] = {}
58
+ if url := self.url:
59
+ meta["url"] = url
60
+ meta["exp_dir"] = self.exp_dir.relative_to(self.project_dir)
61
+ meta["cwd"] = Path.cwd().relative_to(self.project_dir)
62
+ meta["cmd"] = shlex.join(sys.orig_argv)
63
+ if params := self.params:
64
+ meta["params"] = params
69
65
  if inputs := self.inputs:
70
- metadata["inputs"] = inputs
66
+ meta["inputs"] = inputs
71
67
  if outputs := self.outputs:
72
- metadata["outputs"] = outputs
73
- message += msgspec.yaml.encode(metadata, enc_hook=enc_hook).decode()
68
+ meta["outputs"] = outputs
69
+ message += grapes.yaml.encode(meta).decode()
74
70
  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:
@@ -11,7 +11,7 @@ from liblaf.cherries import core
11
11
  class Logging(core.Run):
12
12
  @property
13
13
  def log_file(self) -> Path:
14
- return self.plugin_root.exp_dir / "run.log"
14
+ return self.exp_dir / "run.log"
15
15
 
16
16
  @override
17
17
  @core.impl
@@ -21,4 +21,4 @@ class Logging(core.Run):
21
21
  @override
22
22
  @core.impl
23
23
  def end(self, *args, **kwargs) -> None:
24
- self.plugin_root.log_asset(self.log_file)
24
+ self.log_asset(self.log_file)
@@ -1,3 +1,4 @@
1
1
  import lazy_loader as lazy
2
2
 
3
3
  __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
4
+ del lazy
@@ -8,16 +8,15 @@ from ._abc import Profile
8
8
  from ._default import ProfileDefault # noqa: F401
9
9
  from ._playground import ProfilePlayground # noqa: F401
10
10
 
11
- # for code-completion
12
11
  type ProfileName = Literal["default", "playground"] | str # noqa: PYI051
13
12
  type ProfileLike = ProfileName | Profile | type[Profile]
14
13
 
15
14
 
16
15
  def factory(profile: ProfileLike | None = None) -> Profile:
17
- if profile is None and env.bool("DEBUG", default=False):
16
+ if profile is None and env.bool("DEBUG", False):
18
17
  profile = "playground"
19
18
  if profile is None:
20
- profile = env.str("PROFILE", default="default")
19
+ profile = env.str("PROFILE", "default")
21
20
  if isinstance(profile, str):
22
21
  return Profile[profile]()
23
22
  if isinstance(profile, Profile):
@@ -1,3 +1,4 @@
1
1
  import lazy_loader as lazy
2
2
 
3
3
  __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
4
+ del lazy
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblaf-cherries
3
- Version: 0.4.3
3
+ Version: 0.5.1
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/
@@ -37,7 +37,7 @@ Requires-Dist: dvc[all]<4,>=3
37
37
  Requires-Dist: environs<15,>=14
38
38
  Requires-Dist: gitpython<4,>=3
39
39
  Requires-Dist: lazy-loader<0.5,>=0.4
40
- Requires-Dist: liblaf-grapes<5,>=4
40
+ Requires-Dist: liblaf-grapes<6,>=5
41
41
  Requires-Dist: loguru<0.8,>=0.7
42
42
  Requires-Dist: networkx<4,>=3
43
43
  Requires-Dist: pydantic-settings<3,>=2
@@ -0,0 +1,56 @@
1
+ liblaf/cherries/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
2
+ liblaf/cherries/__init__.pyi,sha256=A7MFyMZodmbEPTCe44P1M8JoDYyFHJLjjWqwpoq8zGg,1047
3
+ liblaf/cherries/_entrypoint.py,sha256=mUTxSaIztxgZbnqRjPJdZOepurdb8es6M3cb6T3vQns,2317
4
+ liblaf/cherries/_version.py,sha256=cYMOhuaBHd0MIZmumuccsEQ-AxM8LIJy9dsBAWgOpqE,704
5
+ liblaf/cherries/_version.pyi,sha256=Pnv4Bxw13LHeuVkPLPsTtnp4N4jOGcAfFJw05uMMgBY,108
6
+ liblaf/cherries/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ liblaf/cherries/typing.py,sha256=mim8QVtwczTSHyw5mhEdfFcXis9o32n0CZyu8BrEorE,50
8
+ liblaf/cherries/config/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
9
+ liblaf/cherries/config/__init__.pyi,sha256=T7qc9AMlDlI9tTLx2V-3FTeYV_CFGZoS74H9Zm1WoeY,686
10
+ liblaf/cherries/config/_config.py,sha256=xqm-jDyo0aEQoiwx6P4TQiB1xGuwy01k8t8QjalzREw,111
11
+ liblaf/cherries/config/asset/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
12
+ liblaf/cherries/config/asset/__init__.pyi,sha256=B1aEmUTqzk4ItYd4oiQKJhJsJkEhY-ODeNNaeYSq-44,701
13
+ liblaf/cherries/config/asset/_meta.py,sha256=Kc2IALf30PO5UOB3QGGS48ecJ51hsCtEV2sAiEiGi70,3076
14
+ liblaf/cherries/config/asset/_registry.py,sha256=0oz_mFbKkVamWcgRUbrxLD5Y_KRzR7y91S76tIt3dcg,772
15
+ liblaf/cherries/config/asset/resolvers/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
16
+ liblaf/cherries/config/asset/resolvers/__init__.pyi,sha256=eqvh9oPwnQenPs5KvzoZWrTEXwf31fd0lGlFJkIM2FU,180
17
+ liblaf/cherries/config/asset/resolvers/_abc.py,sha256=Z2JVGV1p4BJbftGJ3vVfGnHdlAWThWcMBimYdXT0f08,382
18
+ liblaf/cherries/config/asset/resolvers/_series.py,sha256=KBJsgmbsck_8uyPNpA8ZhkK0K1bCWOPm3SAV4IqStkQ,492
19
+ liblaf/cherries/config/asset/resolvers/_vtk.py,sha256=nOrUO9YwkmbV58zPf9xWw75sF9dWzH9YHcrn6mPrgso,722
20
+ liblaf/cherries/core/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
21
+ liblaf/cherries/core/__init__.pyi,sha256=L6acWsE350FQUx14RF94tttvrcvs5EpdA3WHVGmsOSo,1022
22
+ liblaf/cherries/core/_impl.py,sha256=YdUR7Kf68z3JERHB3_2bYSMEe1OCqEwZL3bPP802jjs,1763
23
+ liblaf/cherries/core/_plugin.py,sha256=hPdsKK_XwZSTNtIJwZIAlFgoelY7aqLXlBWsc5y6wIY,3297
24
+ liblaf/cherries/core/_run.py,sha256=BzbGxNFsVhv5j2G8FcAXCwrQKl97wfVC9Xfo89R605M,4255
25
+ liblaf/cherries/core/_spec.py,sha256=YyKQh6CJf3Yn2SuTnQXwCLN8OflnTh9t2FYP-tn5yEE,1850
26
+ liblaf/cherries/core/_utils.py,sha256=ElNiHkrxhntmtF_6kgoCnIvSx1nJBt71XLfRTrYC9a4,2144
27
+ liblaf/cherries/core/typing.py,sha256=razpiUtLAGFD9J4H5RbIEHKEXWzxFHFjtOBBRllhea4,42
28
+ liblaf/cherries/meta/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
29
+ liblaf/cherries/meta/__init__.pyi,sha256=kQFneP3IiV9rBIzpep_uX0z-5IRPrXkPmyNRt19j8fg,282
30
+ liblaf/cherries/meta/_git.py,sha256=4EM8txj7HZ93VP-lkedxh6f7DxiZmjea65b9Y3U0AZM,1228
31
+ liblaf/cherries/meta/_name.py,sha256=-uzzeXkjnKExm_xqsfOQPctwb6cZg7i-tR4fdXMYKjs,562
32
+ liblaf/cherries/path_utils/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
33
+ liblaf/cherries/path_utils/__init__.pyi,sha256=fxSfaa4GaYvlVbeXvdyavbrryeY7QjgPV6q1hLrQaA8,337
34
+ liblaf/cherries/path_utils/_convert.py,sha256=aIrFYE3UoZ9m85-0uYaS_eXmBqZbeJbTgezstbUQrFM,808
35
+ liblaf/cherries/path_utils/_path.py,sha256=PikGdRMF3b3ajrHCMIakXPaIwixC8ObMjXGa8n_ucvM,1102
36
+ liblaf/cherries/path_utils/_special.py,sha256=HVmH6lCnj1TVzjAEmO93MGMTQi7JQWss4sHSNMieczY,1100
37
+ liblaf/cherries/plugins/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
38
+ liblaf/cherries/plugins/__init__.pyi,sha256=dyTB5ZS78Kg_7oWeChk_h7Ry_gU9k1sDiL5YOmnoG7I,177
39
+ liblaf/cherries/plugins/comet.py,sha256=9nFk4QS7TFmp_8FNgUv0dwQD3DYmGEdDnhnUI3_LWZE,3994
40
+ liblaf/cherries/plugins/dvc.py,sha256=1ktBxHIPhAYoN_Bto1c5BOn9VxKVBDK85s5rmlB2vvE,1053
41
+ liblaf/cherries/plugins/git_.py,sha256=E8lPFEZjmiHy5CBADBvRa9eBHFz6BbvwL82Y_rOcP-w,2113
42
+ liblaf/cherries/plugins/local.py,sha256=m01v9ifvoAza8z_LiIWlZNNK2b-69wcWS29N54X1Vio,1679
43
+ liblaf/cherries/plugins/logging.py,sha256=lhs6Xm2WAh8t13mqjBs1su4gJMANFrKIm4vCqUz39xw,509
44
+ liblaf/cherries/profiles/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
45
+ liblaf/cherries/profiles/__init__.pyi,sha256=qXxy2LOG9hE0LKCnECdJSv2VoHhOTMVDE3sUKIuZKmw,292
46
+ liblaf/cherries/profiles/_abc.py,sha256=1tpRrocBZNHonWaj3a264GnL5UoGS_HqU06aNZpruqY,193
47
+ liblaf/cherries/profiles/_default.py,sha256=cfV003HBA5aGAZkgDDaHAyongFcxCWYsEFpSQNICcMs,440
48
+ liblaf/cherries/profiles/_factory.py,sha256=OONaNS5cuHpPL-GwpkQp4jio9ce4fgAGr7pDB9JvOs0,720
49
+ liblaf/cherries/profiles/_playground.py,sha256=Aru-7RVoxNhomPLUxDLiM5wD5ZCPLy5Eymw0xQL2F9g,384
50
+ liblaf/cherries/utils/__init__.py,sha256=MfsYnXmbxgr6l1QHFkUgtppkaBNzkeRle6dMNcWGdxk,106
51
+ liblaf/cherries/utils/__init__.pyi,sha256=F5aTcXpWVmUoctPbLfmQXKyuXYRspAIjaIzfL1_3Lrw,51
52
+ liblaf/cherries/utils/_functools.py,sha256=0Puwvj1Wq4kp3S--hI-CXwUBZ56AtfkqIzFHllQtuug,181
53
+ liblaf_cherries-0.5.1.dist-info/METADATA,sha256=ZMgBQeyRp7uyRBJFec-MbQPBUki9D1ky4266C2unX80,7023
54
+ liblaf_cherries-0.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
55
+ liblaf_cherries-0.5.1.dist-info/licenses/LICENSE,sha256=Ph4NzyU3lGVDeYv-mf8aRmImH8v9rVL9F362FV4G6Ow,1063
56
+ liblaf_cherries-0.5.1.dist-info/RECORD,,