liblaf-cherries 0.3.0__py3-none-any.whl → 0.3.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.
@@ -1,7 +1,14 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
5
12
 
6
13
  TYPE_CHECKING = False
7
14
  if TYPE_CHECKING:
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
9
16
  from typing import Union
10
17
 
11
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
12
20
  else:
13
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
14
23
 
15
24
  version: str
16
25
  __version__: str
17
26
  __version_tuple__: VERSION_TUPLE
18
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
19
30
 
20
- __version__ = version = '0.3.0'
21
- __version_tuple__ = version_tuple = (0, 3, 0)
31
+ __version__ = version = '0.3.1'
32
+ __version_tuple__ = version_tuple = (0, 3, 1)
33
+
34
+ __commit_id__ = commit_id = None
@@ -79,6 +79,7 @@ def model_dump_without_assets(
79
79
  value = model_dump_without_assets(value)
80
80
  for meta in info.metadata:
81
81
  if isinstance(meta, MetaAsset):
82
+ del data[name]
82
83
  break
83
84
  else:
84
85
  data[name] = value
@@ -75,18 +75,22 @@ class Plugin:
75
75
  for plugin_id, plugin in self.plugins.items()
76
76
  if (info := get_impl_info(getattr(plugin, method, None))) is not None
77
77
  }
78
+
79
+ def key_fn(node: str) -> int:
80
+ return plugin_infos[node].priority
81
+
78
82
  graph = nx.DiGraph()
79
83
  for plugin_id, impl_info in plugin_infos.items():
80
84
  graph.add_node(plugin_id)
81
85
  for after in impl_info.after:
82
- graph.add_edge(after, plugin_id)
86
+ if after in plugin_infos:
87
+ graph.add_edge(after, plugin_id)
83
88
  for before in impl_info.before:
84
- graph.add_edge(plugin_id, before)
89
+ if before in plugin_infos:
90
+ graph.add_edge(plugin_id, before)
85
91
  self._sort_plugins_cache[method] = tuple(
86
92
  plugin
87
- for plugin_id in nx.lexicographical_topological_sort(
88
- graph, key=lambda node: plugin_infos[node].priority
89
- )
93
+ for plugin_id in nx.lexicographical_topological_sort(graph, key=key_fn)
90
94
  if (plugin := self.plugins.get(plugin_id)) is not None
91
95
  )
92
96
  return self._sort_plugins_cache[method]
@@ -13,7 +13,6 @@ from liblaf.cherries.typed import PathLike
13
13
 
14
14
  from ._plugin import Plugin
15
15
  from ._spec import spec
16
- from ._utils import delegate_property_to_root
17
16
 
18
17
 
19
18
  @attrs.define
@@ -27,28 +26,39 @@ class Run(Plugin):
27
26
  """
28
27
 
29
28
  @functools.cached_property
30
- @delegate_property_to_root
31
29
  def data_dir(self) -> Path:
30
+ if self._plugin_parent is not None:
31
+ return self.plugin_root.data_dir
32
32
  return paths.data()
33
33
 
34
34
  @functools.cached_property
35
- @delegate_property_to_root
36
35
  def entrypoint(self) -> Path:
36
+ if self._plugin_parent is not None:
37
+ return self.plugin_root.entrypoint
37
38
  return paths.entrypoint()
38
39
 
39
40
  @functools.cached_property
40
- @delegate_property_to_root
41
41
  def exp_dir(self) -> Path:
42
+ if self._plugin_parent is not None:
43
+ return self.plugin_root.exp_dir
42
44
  return paths.exp_dir()
43
45
 
44
46
  @functools.cached_property
45
- @delegate_property_to_root
46
47
  def name(self) -> str:
48
+ if self._plugin_parent is not None:
49
+ return self.plugin_root.name
47
50
  return self.start_time.strftime("%Y-%m-%dT%H%M%S")
48
51
 
52
+ @property
53
+ 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()
57
+
49
58
  @functools.cached_property
50
- @delegate_property_to_root
51
59
  def project_name(self) -> str | None:
60
+ if self._plugin_parent is not None:
61
+ return self.plugin_root.project_name
52
62
  try:
53
63
  repo: git.Repo = git.Repo(search_parent_directories=True)
54
64
  except git.InvalidGitRepositoryError:
@@ -57,8 +67,9 @@ class Run(Plugin):
57
67
  return Path(repo.working_dir).name
58
68
 
59
69
  @functools.cached_property
60
- @delegate_property_to_root
61
70
  def root_dir(self) -> Path:
71
+ if self._plugin_parent is not None:
72
+ return self.plugin_root.root_dir
62
73
  try:
63
74
  repo: git.Repo = git.Repo(search_parent_directories=True)
64
75
  except git.InvalidGitRepositoryError:
@@ -67,18 +78,26 @@ class Run(Plugin):
67
78
  return Path(repo.working_dir).absolute()
68
79
 
69
80
  @functools.cached_property
70
- @delegate_property_to_root
71
81
  def start_time(self) -> datetime.datetime:
82
+ if self._plugin_parent is not None:
83
+ return self.plugin_root.start_time
72
84
  return datetime.datetime.now().astimezone()
73
85
 
74
86
  @functools.cached_property
75
- @delegate_property_to_root
76
87
  def url(self) -> str:
88
+ if self._plugin_parent is not None:
89
+ return self.plugin_root.url
77
90
  return self.get_url()
78
91
 
79
92
  @spec
80
93
  def end(self, *args, **kwargs) -> None: ...
81
94
 
95
+ @spec(first_result=True)
96
+ def get_others(self) -> Mapping[str, Any]: ...
97
+
98
+ @spec(first_result=True)
99
+ def get_params(self) -> Mapping[str, Any]: ...
100
+
82
101
  @spec(first_result=True)
83
102
  def get_url(self) -> str: ...
84
103
 
@@ -1,6 +1,7 @@
1
1
  from .comet import Comet
2
2
  from .dvc import Dvc
3
+ from .git_ import Git
3
4
  from .local import Local
4
5
  from .logging import Logging
5
6
 
6
- __all__ = ["Comet", "Dvc", "Local", "Logging"]
7
+ __all__ = ["Comet", "Dvc", "Git", "Local", "Logging"]
@@ -13,6 +13,7 @@ from liblaf.cherries.typed import PathLike
13
13
 
14
14
  @attrs.define
15
15
  class Comet(core.Run):
16
+ disabled: bool = attrs.field(default=False)
16
17
  exp: comet_ml.CometExperiment = attrs.field(default=None)
17
18
 
18
19
  @override
@@ -20,6 +21,16 @@ class Comet(core.Run):
20
21
  def end(self, *args, **kwargs) -> None:
21
22
  return self.exp.end()
22
23
 
24
+ @override
25
+ @core.impl
26
+ def get_others(self) -> Mapping[str, Any]:
27
+ return self.exp.others
28
+
29
+ @override
30
+ @core.impl
31
+ def get_params(self) -> Mapping[str, Any]:
32
+ return self.exp.params
33
+
23
34
  @override
24
35
  @core.impl
25
36
  def get_url(self) -> str:
@@ -55,7 +66,8 @@ class Comet(core.Run):
55
66
  **kwargs,
56
67
  ) -> None:
57
68
  if name is None:
58
- name = f"inputs/{Path(path).name}"
69
+ path = Path(path)
70
+ name = f"inputs/{path.name}"
59
71
  metadata = toolz.assoc(metadata or {}, "type", "input")
60
72
  self.log_asset(path, name, metadata=metadata, **kwargs)
61
73
 
@@ -90,7 +102,8 @@ class Comet(core.Run):
90
102
  **kwargs,
91
103
  ) -> None:
92
104
  if name is None:
93
- name = f"outputs/{Path(path).name}"
105
+ path = Path(path)
106
+ name = f"outputs/{path.name}"
94
107
  metadata = toolz.assoc(metadata or {}, "type", "output")
95
108
  self.log_asset(path, name, metadata=metadata, **kwargs)
96
109
 
@@ -109,5 +122,7 @@ class Comet(core.Run):
109
122
  def start(self, *args, **kwargs) -> None:
110
123
  self.exp = comet_ml.start(
111
124
  project_name=self.plugin_root.project_name,
112
- experiment_config=comet_ml.ExperimentConfig(name=self.plugin_root.name),
125
+ experiment_config=comet_ml.ExperimentConfig(
126
+ disabled=self.disabled, name=self.plugin_root.name
127
+ ),
113
128
  )
@@ -0,0 +1,73 @@
1
+ import shlex
2
+ import subprocess
3
+ import sys
4
+ from pathlib import Path
5
+ from typing import Any, override
6
+
7
+ import attrs
8
+ import git
9
+ import msgspec
10
+
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
19
+
20
+
21
+ @attrs.define
22
+ class Git(core.Run):
23
+ inputs: list[Path] = attrs.field(factory=list)
24
+ outputs: list[Path] = attrs.field(factory=list)
25
+ repo: git.Repo = attrs.field(default=None)
26
+
27
+ @override
28
+ @core.impl(after=("Dvc",))
29
+ def end(self, *args, **kwargs) -> None:
30
+ if not self.repo.is_dirty(untracked_files=True):
31
+ return
32
+ self.repo.git.add(all=True)
33
+ subprocess.run(["git", "status"], check=False)
34
+ message: str = self._make_commit_message()
35
+ self.repo.git.commit(message=message)
36
+
37
+ @override
38
+ @core.impl
39
+ def log_input(self, path: PathLike, *args, **kwargs) -> None:
40
+ path: Path = Path(path)
41
+ self.inputs.append(path.relative_to(self.repo.working_dir))
42
+
43
+ @override
44
+ @core.impl
45
+ def log_output(
46
+ self,
47
+ path: PathLike,
48
+ name: PathLike | None = None,
49
+ **kwargs,
50
+ ) -> None:
51
+ path: Path = Path(path)
52
+ self.outputs.append(path.relative_to(self.repo.working_dir))
53
+
54
+ @override
55
+ @core.impl
56
+ def start(self, *args, **kwargs) -> None:
57
+ self.repo = git.Repo(self.plugin_root.exp_dir, search_parent_directories=True)
58
+
59
+ def _make_commit_message(self) -> str:
60
+ name: str = self.plugin_root.name
61
+ message: str = f"chore(cherries): {name}\n\n"
62
+ metadata: dict[str, Any] = {}
63
+ metadata["cmd"] = shlex.join(sys.orig_argv)
64
+ if url := self.plugin_root.url:
65
+ metadata["url"] = url
66
+ if params := self.plugin_root.get_params():
67
+ metadata["params"] = params
68
+ if inputs := self.inputs:
69
+ metadata["inputs"] = inputs
70
+ if outputs := self.outputs:
71
+ metadata["outputs"] = outputs
72
+ message += msgspec.yaml.encode(metadata, enc_hook=enc_hook).decode()
73
+ return message
@@ -2,13 +2,16 @@ from typing import override
2
2
 
3
3
  from liblaf.cherries import core, plugins
4
4
 
5
- from ._playground import ProfilePlayground
5
+ from ._abc import Profile
6
6
 
7
7
 
8
- class ProfileDefault(ProfilePlayground):
8
+ class ProfileDefault(Profile):
9
9
  @override # impl Profile
10
10
  def init(self) -> core.Run:
11
- run: core.Run = super().init()
11
+ run: core.Run = core.active_run
12
12
  run.register(plugins.Comet())
13
13
  run.register(plugins.Dvc())
14
+ run.register(plugins.Git())
15
+ run.register(plugins.Local())
16
+ run.register(plugins.Logging())
14
17
  return run
@@ -1,9 +1,11 @@
1
1
  from typing import Literal
2
2
 
3
+ from environs import env
4
+
3
5
  from ._abc import Profile
4
6
 
5
7
  # ensure profiles are registered
6
- from ._default import ProfileDefault
8
+ from ._default import ProfileDefault # noqa: F401
7
9
  from ._playground import ProfilePlayground # noqa: F401
8
10
 
9
11
  # for code-completion
@@ -12,8 +14,10 @@ type ProfileLike = ProfileName | Profile | type[Profile]
12
14
 
13
15
 
14
16
  def factory(profile: ProfileLike | None = None) -> Profile:
17
+ if profile is None and env.bool("DEBUG", default=False):
18
+ profile = "playground"
15
19
  if profile is None:
16
- return ProfileDefault()
20
+ profile = env.str("PROFILE", default="default")
17
21
  if isinstance(profile, str):
18
22
  return Profile[profile]()
19
23
  if isinstance(profile, Profile):
@@ -9,6 +9,7 @@ class ProfilePlayground(Profile):
9
9
  @override # impl Profile
10
10
  def init(self) -> core.Run:
11
11
  run: core.Run = core.active_run
12
+ run.register(plugins.Comet(disabled=True))
12
13
  run.register(plugins.Local())
13
14
  run.register(plugins.Logging())
14
15
  return run
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblaf-cherries
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Add your description here
5
5
  Project-URL: Changelog, https://github.com/liblaf/cherries/blob/main/CHANGELOG.md
6
6
  Project-URL: Documentation, https://liblaf.github.io/cherries/
@@ -31,19 +31,19 @@ Classifier: Topic :: System :: Logging
31
31
  Classifier: Topic :: Utilities
32
32
  Classifier: Typing :: Typed
33
33
  Requires-Python: >=3.12
34
- Requires-Dist: attrs<26,>=25.0.0
35
- Requires-Dist: comet-ml<4,>=3.0.0
36
- Requires-Dist: dvc[webdav]<4,>=3.0.0
37
- Requires-Dist: environs<15,>=14.0.0
38
- Requires-Dist: gitpython<4,>=3.0.0
34
+ Requires-Dist: attrs<26,>=25
35
+ Requires-Dist: comet-ml<4,>=3
36
+ Requires-Dist: dvc[all]<4,>=3
37
+ Requires-Dist: environs<15,>=14
38
+ Requires-Dist: gitpython<4,>=3
39
39
  Requires-Dist: lazy-loader<0.5,>=0.4
40
- Requires-Dist: liblaf-grapes<2,>=1.0.0
41
- Requires-Dist: loguru<0.8,>=0.7.0
42
- Requires-Dist: networkx<4,>=3.0.0
43
- Requires-Dist: pydantic-settings<3,>=2.0.0
44
- Requires-Dist: pydantic<3,>=2.0.0
45
- Requires-Dist: rich<15,>=14.0.0
46
- Requires-Dist: wrapt<2,>=1.0.0
40
+ Requires-Dist: liblaf-grapes<2,>=1
41
+ Requires-Dist: loguru<0.8,>=0.7
42
+ Requires-Dist: networkx<4,>=3
43
+ Requires-Dist: pydantic-settings<3,>=2
44
+ Requires-Dist: pydantic<3,>=2
45
+ Requires-Dist: rich<15,>=14
46
+ Requires-Dist: wrapt<2,>=1
47
47
  Description-Content-Type: text/markdown
48
48
 
49
49
  <!-- -*- mode: markdown; -*- -->
@@ -1,19 +1,19 @@
1
1
  liblaf/cherries/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
2
2
  liblaf/cherries/__init__.pyi,sha256=vQIYxi3iwe0Uij8Q8RCFlzN5MCCDuWgcnyox01C_nJo,1066
3
3
  liblaf/cherries/_entrypoint.py,sha256=pSRbOCuMhUnYrAsZTEideVbUDEmGocvKlMgGt_MX_Z0,2262
4
- liblaf/cherries/_version.py,sha256=AGmG_Lx0-9ztFw_7d9mYbaYuC-2abxE1oXOUNAY29YY,511
4
+ liblaf/cherries/_version.py,sha256=gGLpQUQx-ty9SEy9PYw9OgJWWzJLBnCpfJOfzL7SjlI,704
5
5
  liblaf/cherries/_version.pyi,sha256=Pnv4Bxw13LHeuVkPLPsTtnp4N4jOGcAfFJw05uMMgBY,108
6
6
  liblaf/cherries/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  liblaf/cherries/typed.py,sha256=mim8QVtwczTSHyw5mhEdfFcXis9o32n0CZyu8BrEorE,50
8
8
  liblaf/cherries/config/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
9
9
  liblaf/cherries/config/__init__.pyi,sha256=Tl-GCtMEtQOcYC5poH3qzQxR91A1RcjYDP3fEdJ9Qzc,425
10
- liblaf/cherries/config/_asset.py,sha256=DaM-uDgZvFcvQSakdei8qfJZEXzzmlTs8cfbkXIcOJY,3088
10
+ liblaf/cherries/config/_asset.py,sha256=pKHlzjOBc5yso3zJ18QfPzMwNETq1557E13qberoWZ0,3119
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=24nXWLUFBL2eeHn2fUImo-45A7a8XB3CsCjyvLYk2z8,3074
16
- liblaf/cherries/core/_run.py,sha256=1R16v88qFv3ncx9hZeiTpgoXJqRBIVbHENlR7ZoXICw,4647
15
+ liblaf/cherries/core/_plugin.py,sha256=LcCxNQkkInOOrPnSd5ZwKhnKQiUl4T-YicE9PEvF3XI,3198
16
+ liblaf/cherries/core/_run.py,sha256=GNJEHGldjbvURkN5nAy8K9u1mWwxYHd-vkbnvfaOw8U,5403
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
@@ -27,21 +27,22 @@ liblaf/cherries/paths/_convert.py,sha256=IrXN_9s-rfH7EKk0_ilr1giGmfN8FlvB_edm2kI
27
27
  liblaf/cherries/paths/_path.py,sha256=36T4eE8OdT83LDwEaKjcBWS5r4jZEGBXFxeJqiB7-IQ,1604
28
28
  liblaf/cherries/paths/_special.py,sha256=w6bflcWiYzx3B_wr88JcZiUNrFRoviSLwqotYZ8XXII,1099
29
29
  liblaf/cherries/plugins/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
30
- liblaf/cherries/plugins/__init__.pyi,sha256=110kRPqeN0Lif68DUkxMpIwdQIhK3Zah-Q2RXoEfAPw,148
31
- liblaf/cherries/plugins/comet.py,sha256=r_Mhm8KpWDQK5m0GuqgKcr0Xc9dSjQrVvNRuoXg_gkQ,3241
30
+ liblaf/cherries/plugins/__init__.pyi,sha256=dyTB5ZS78Kg_7oWeChk_h7Ry_gU9k1sDiL5YOmnoG7I,177
31
+ liblaf/cherries/plugins/comet.py,sha256=DzQ-ktyFO6JeV1di89J3P38Ok4X07mTVtAgUZDm0FLc,3607
32
32
  liblaf/cherries/plugins/dvc.py,sha256=2HslDy_8gcFehly2CNCSZpRs0Wet7RTGMwbxxlo9IVc,1052
33
+ liblaf/cherries/plugins/git_.py,sha256=F6JLsfkNLKseCIRrpusysW_VFhcW_44Bwfck9u8J2TI,2142
33
34
  liblaf/cherries/plugins/local.py,sha256=WHBJo6HIJOoTBRedd2a6nKoTJsaSUxhGN0jSAV94de8,1714
34
35
  liblaf/cherries/plugins/logging.py,sha256=xgK41wUQjm-jqW_d4kDbzn9m-V1sdeIX5_-d0yS32hM,758
35
36
  liblaf/cherries/profiles/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
36
37
  liblaf/cherries/profiles/__init__.pyi,sha256=qXxy2LOG9hE0LKCnECdJSv2VoHhOTMVDE3sUKIuZKmw,292
37
38
  liblaf/cherries/profiles/_abc.py,sha256=1tpRrocBZNHonWaj3a264GnL5UoGS_HqU06aNZpruqY,193
38
- liblaf/cherries/profiles/_default.py,sha256=hGHdnOeyL5yusKiF5M_a6nfodEdI9YPnU9jbigr20nw,352
39
- liblaf/cherries/profiles/_factory.py,sha256=FhYfHBmWe0uPOhRmCCg8zilUggHIPIllrPDx4Gkc8C8,602
40
- liblaf/cherries/profiles/_playground.py,sha256=B11N0S8gSOHGQ7jHimkfZ5EwSYk0KjsJYWGpKRja6Gs,333
39
+ liblaf/cherries/profiles/_default.py,sha256=cfV003HBA5aGAZkgDDaHAyongFcxCWYsEFpSQNICcMs,440
40
+ liblaf/cherries/profiles/_factory.py,sha256=d-PaE8JYllkzcqQDiyi5aP52lFJOkFdLai3XXgSKAE8,758
41
+ liblaf/cherries/profiles/_playground.py,sha256=Aru-7RVoxNhomPLUxDLiM5wD5ZCPLy5Eymw0xQL2F9g,384
41
42
  liblaf/cherries/utils/__init__.py,sha256=OHb6Xou2v6u42swTgjRfzej4CIlRg4OmgOIQXUiRjKA,97
42
43
  liblaf/cherries/utils/__init__.pyi,sha256=F5aTcXpWVmUoctPbLfmQXKyuXYRspAIjaIzfL1_3Lrw,51
43
44
  liblaf/cherries/utils/_functools.py,sha256=0Puwvj1Wq4kp3S--hI-CXwUBZ56AtfkqIzFHllQtuug,181
44
- liblaf_cherries-0.3.0.dist-info/METADATA,sha256=J_DaZSjQdIb_Wio4WEd9EoP_73MoMB2z8aQu9N5k5lc,6304
45
- liblaf_cherries-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
46
- liblaf_cherries-0.3.0.dist-info/licenses/LICENSE,sha256=Ph4NzyU3lGVDeYv-mf8aRmImH8v9rVL9F362FV4G6Ow,1063
47
- liblaf_cherries-0.3.0.dist-info/RECORD,,
45
+ liblaf_cherries-0.3.1.dist-info/METADATA,sha256=1POgWN8FnT3SDBN2fm3XUUI01A6VfMeECZwcGbskUrk,6255
46
+ liblaf_cherries-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
47
+ liblaf_cherries-0.3.1.dist-info/licenses/LICENSE,sha256=Ph4NzyU3lGVDeYv-mf8aRmImH8v9rVL9F362FV4G6Ow,1063
48
+ liblaf_cherries-0.3.1.dist-info/RECORD,,