liblaf-cherries 0.4.2__py3-none-any.whl → 0.5.0__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.
@@ -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.2'
32
- __version_tuple__ = version_tuple = (0, 4, 2)
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
@@ -23,6 +17,7 @@ class Git(core.Run):
23
17
  inputs: list[Path] = attrs.field(factory=list)
24
18
  outputs: list[Path] = attrs.field(factory=list)
25
19
  repo: git.Repo = attrs.field(default=None)
20
+ verify: bool = False
26
21
 
27
22
  @override
28
23
  @core.impl(after=("Dvc",))
@@ -32,13 +27,13 @@ class Git(core.Run):
32
27
  self.repo.git.add(all=True)
33
28
  subprocess.run(["git", "status"], check=False)
34
29
  message: str = self._make_commit_message()
35
- self.repo.git.commit(message=message)
30
+ self.repo.git.commit(message=message, no_verify=not self.verify)
36
31
 
37
32
  @override
38
33
  @core.impl
39
34
  def log_input(self, path: PathLike, *args, **kwargs) -> None:
40
35
  path: Path = Path(path)
41
- self.inputs.append(path.relative_to(self.repo.working_dir))
36
+ self.inputs.append(path.relative_to(self.project_dir))
42
37
 
43
38
  @override
44
39
  @core.impl
@@ -49,12 +44,12 @@ class Git(core.Run):
49
44
  **kwargs,
50
45
  ) -> None:
51
46
  path: Path = Path(path)
52
- self.outputs.append(path.relative_to(self.repo.working_dir))
47
+ self.outputs.append(path.relative_to(self.project_dir))
53
48
 
54
49
  @override
55
50
  @core.impl
56
51
  def start(self, *args, **kwargs) -> None:
57
- 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)
58
53
 
59
54
  def _make_commit_message(self) -> str:
60
55
  name: str = self.plugin_root.name
@@ -69,5 +64,5 @@ class Git(core.Run):
69
64
  metadata["inputs"] = inputs
70
65
  if outputs := self.outputs:
71
66
  metadata["outputs"] = outputs
72
- message += msgspec.yaml.encode(metadata, enc_hook=enc_hook).decode()
67
+ message += grapes.yaml.encode(metadata).decode()
73
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblaf-cherries
3
- Version: 0.4.2
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,37 +1,37 @@
1
1
  liblaf/cherries/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
2
- liblaf/cherries/__init__.pyi,sha256=vQIYxi3iwe0Uij8Q8RCFlzN5MCCDuWgcnyox01C_nJo,1066
3
- liblaf/cherries/_entrypoint.py,sha256=pSRbOCuMhUnYrAsZTEideVbUDEmGocvKlMgGt_MX_Z0,2262
4
- liblaf/cherries/_version.py,sha256=A45grTqzrHuDn1CT9K5GVUbY4_Q3OSTcXAl3zdHzcEI,704
2
+ liblaf/cherries/__init__.pyi,sha256=lbens0QYeWVUsnCHZ6fyAh51dXuUPX5nU_f-VUK16jo,1044
3
+ liblaf/cherries/_entrypoint.py,sha256=6tUIM1SX__UcMonzPzqXMcbMhD1rif7Oc7FFtMKIM0Q,2268
4
+ liblaf/cherries/_version.py,sha256=fvHpBU3KZKRinkriKdtAt3crenOyysELF-M9y3ozg3U,704
5
5
  liblaf/cherries/_version.pyi,sha256=Pnv4Bxw13LHeuVkPLPsTtnp4N4jOGcAfFJw05uMMgBY,108
6
6
  liblaf/cherries/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- liblaf/cherries/typed.py,sha256=mim8QVtwczTSHyw5mhEdfFcXis9o32n0CZyu8BrEorE,50
7
+ liblaf/cherries/typing.py,sha256=mim8QVtwczTSHyw5mhEdfFcXis9o32n0CZyu8BrEorE,50
8
8
  liblaf/cherries/config/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
9
- liblaf/cherries/config/__init__.pyi,sha256=Tl-GCtMEtQOcYC5poH3qzQxR91A1RcjYDP3fEdJ9Qzc,425
10
- liblaf/cherries/config/_asset.py,sha256=pKHlzjOBc5yso3zJ18QfPzMwNETq1557E13qberoWZ0,3119
9
+ liblaf/cherries/config/__init__.pyi,sha256=qD-iWfQVHg1vDcCpHg28LvHHxagMsS2bQT6CZE7mrH0,469
10
+ liblaf/cherries/config/_asset.py,sha256=alEOKiXlYC6wnLZOARSmYMGjFFvGf0sXJ1_hBSK0cts,3463
11
11
  liblaf/cherries/config/_config.py,sha256=WPwwk-3O96FyHGb2W8__LDfHpXBHLQM44aOcrMPjDL4,171
12
12
  liblaf/cherries/core/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
13
13
  liblaf/cherries/core/__init__.pyi,sha256=jgmGgzlTDlyFKHnSjNw3g22ZBuBQ07NmeRiq4qKZFdg,727
14
14
  liblaf/cherries/core/_impl.py,sha256=LCd4f5oX5bEMa4uX37r0yiPntqZM1Lwqrd7vKL1oc7w,1459
15
- liblaf/cherries/core/_plugin.py,sha256=LcCxNQkkInOOrPnSd5ZwKhnKQiUl4T-YicE9PEvF3XI,3198
16
- liblaf/cherries/core/_run.py,sha256=GNJEHGldjbvURkN5nAy8K9u1mWwxYHd-vkbnvfaOw8U,5403
15
+ liblaf/cherries/core/_plugin.py,sha256=wv_G-cZK1WHPX5JSLPvKrnFJRnEwRxPuS5szN7DTRTc,3187
16
+ liblaf/cherries/core/_run.py,sha256=kNU04SxQSpZzWvx_tCUlfR-7ll3-LuQqFJD2gfcWyhQ,5039
17
17
  liblaf/cherries/core/_spec.py,sha256=F73wxygkc_3v0hOKwfFSGaLRHEDhhENWLQZakruuRq8,1950
18
18
  liblaf/cherries/core/_utils.py,sha256=WpS79yqTH0Kl9ewzCIAiUcxamHKzJOB7ZWhjq_13bzY,572
19
19
  liblaf/cherries/core/typed.py,sha256=razpiUtLAGFD9J4H5RbIEHKEXWzxFHFjtOBBRllhea4,42
20
20
  liblaf/cherries/meta/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
21
21
  liblaf/cherries/meta/__init__.pyi,sha256=kQFneP3IiV9rBIzpep_uX0z-5IRPrXkPmyNRt19j8fg,282
22
- liblaf/cherries/meta/_git.py,sha256=HhxqwKY52KahvAYU0R3BTRNT7lMJIjJLpnuSYfm02W4,1219
23
- liblaf/cherries/meta/_name.py,sha256=7sUZMYpGzW8ZKSNPITybrjnD2vLY57O91aK6Gd7Ud5M,550
24
- liblaf/cherries/paths/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
25
- liblaf/cherries/paths/__init__.pyi,sha256=Xf6-Igmj2K8hmLsJ3sXCj2Lrm0gIWcbARQB4oMP1zps,367
26
- liblaf/cherries/paths/_convert.py,sha256=IrXN_9s-rfH7EKk0_ilr1giGmfN8FlvB_edm2kI-k3I,807
27
- liblaf/cherries/paths/_path.py,sha256=36T4eE8OdT83LDwEaKjcBWS5r4jZEGBXFxeJqiB7-IQ,1604
28
- liblaf/cherries/paths/_special.py,sha256=HVmH6lCnj1TVzjAEmO93MGMTQi7JQWss4sHSNMieczY,1100
22
+ liblaf/cherries/meta/_git.py,sha256=89isF_ur7qvI4YSmiBTim8ds7DtCtHUfeiCkoK0g6G8,1225
23
+ liblaf/cherries/meta/_name.py,sha256=igjQ8TLxQbTesvWKakQDpytAheNhZ-R1d1MRZhgMPxM,559
24
+ liblaf/cherries/pathutils/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
25
+ liblaf/cherries/pathutils/__init__.pyi,sha256=fxSfaa4GaYvlVbeXvdyavbrryeY7QjgPV6q1hLrQaA8,337
26
+ liblaf/cherries/pathutils/_convert.py,sha256=aIrFYE3UoZ9m85-0uYaS_eXmBqZbeJbTgezstbUQrFM,808
27
+ liblaf/cherries/pathutils/_path.py,sha256=PikGdRMF3b3ajrHCMIakXPaIwixC8ObMjXGa8n_ucvM,1102
28
+ liblaf/cherries/pathutils/_special.py,sha256=HVmH6lCnj1TVzjAEmO93MGMTQi7JQWss4sHSNMieczY,1100
29
29
  liblaf/cherries/plugins/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
30
30
  liblaf/cherries/plugins/__init__.pyi,sha256=dyTB5ZS78Kg_7oWeChk_h7Ry_gU9k1sDiL5YOmnoG7I,177
31
- liblaf/cherries/plugins/comet.py,sha256=DzQ-ktyFO6JeV1di89J3P38Ok4X07mTVtAgUZDm0FLc,3607
32
- liblaf/cherries/plugins/dvc.py,sha256=2HslDy_8gcFehly2CNCSZpRs0Wet7RTGMwbxxlo9IVc,1052
33
- liblaf/cherries/plugins/git_.py,sha256=F6JLsfkNLKseCIRrpusysW_VFhcW_44Bwfck9u8J2TI,2142
34
- liblaf/cherries/plugins/local.py,sha256=WHBJo6HIJOoTBRedd2a6nKoTJsaSUxhGN0jSAV94de8,1714
31
+ liblaf/cherries/plugins/comet.py,sha256=LquXaN4hTUhbSwKVeWtErWUeys5aoRK8nP38yETmJfU,4016
32
+ liblaf/cherries/plugins/dvc.py,sha256=1ktBxHIPhAYoN_Bto1c5BOn9VxKVBDK85s5rmlB2vvE,1053
33
+ liblaf/cherries/plugins/git_.py,sha256=UBXwEbU8FJ59aAZf99JPE6d56ULMXdkzRpUCyZKM7cM,2051
34
+ liblaf/cherries/plugins/local.py,sha256=m01v9ifvoAza8z_LiIWlZNNK2b-69wcWS29N54X1Vio,1679
35
35
  liblaf/cherries/plugins/logging.py,sha256=A2-fd7H96Jtg1eOOmMYp7AmT3133vDHd4HAklhjH6n0,533
36
36
  liblaf/cherries/profiles/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
37
37
  liblaf/cherries/profiles/__init__.pyi,sha256=qXxy2LOG9hE0LKCnECdJSv2VoHhOTMVDE3sUKIuZKmw,292
@@ -42,7 +42,7 @@ liblaf/cherries/profiles/_playground.py,sha256=Aru-7RVoxNhomPLUxDLiM5wD5ZCPLy5Ey
42
42
  liblaf/cherries/utils/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
43
43
  liblaf/cherries/utils/__init__.pyi,sha256=F5aTcXpWVmUoctPbLfmQXKyuXYRspAIjaIzfL1_3Lrw,51
44
44
  liblaf/cherries/utils/_functools.py,sha256=0Puwvj1Wq4kp3S--hI-CXwUBZ56AtfkqIzFHllQtuug,181
45
- liblaf_cherries-0.4.2.dist-info/METADATA,sha256=XUlqhoGEIaT6jaiQPRLO3x17vJI2bgV_uFIMh59oqQ4,7023
46
- liblaf_cherries-0.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
- liblaf_cherries-0.4.2.dist-info/licenses/LICENSE,sha256=Ph4NzyU3lGVDeYv-mf8aRmImH8v9rVL9F362FV4G6Ow,1063
48
- liblaf_cherries-0.4.2.dist-info/RECORD,,
45
+ liblaf_cherries-0.5.0.dist-info/METADATA,sha256=rgnXriF6xt__GYW-nOb9K1ywv1irJJI7EWh9KFHa_gA,7023
46
+ liblaf_cherries-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
+ liblaf_cherries-0.5.0.dist-info/licenses/LICENSE,sha256=Ph4NzyU3lGVDeYv-mf8aRmImH8v9rVL9F362FV4G6Ow,1063
48
+ liblaf_cherries-0.5.0.dist-info/RECORD,,
@@ -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
File without changes
File without changes