checkpointer 2.9.1__py3-none-any.whl → 2.9.2__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.
checkpointer/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import gc
2
2
  import tempfile
3
3
  from typing import Callable
4
- from .checkpoint import Checkpointer, CheckpointError, CheckpointFn
4
+ from .checkpoint import CachedFunction, Checkpointer, CheckpointError
5
5
  from .object_hash import ObjectHash
6
6
  from .storages import MemoryStorage, PickleStorage, Storage
7
7
 
@@ -14,8 +14,8 @@ static_checkpoint = Checkpointer(fn_hash=ObjectHash())
14
14
 
15
15
  def cleanup_all(invalidated=True, expired=True):
16
16
  for obj in gc.get_objects():
17
- if isinstance(obj, CheckpointFn):
17
+ if isinstance(obj, CachedFunction):
18
18
  obj.cleanup(invalidated=invalidated, expired=expired)
19
19
 
20
20
  def get_function_hash(fn: Callable, capture=False) -> str:
21
- return CheckpointFn(Checkpointer(capture=capture), fn).fn_hash
21
+ return CachedFunction(Checkpointer(capture=capture), fn).fn_hash
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
  import inspect
3
3
  import re
4
- from contextlib import suppress
5
4
  from datetime import datetime
6
5
  from functools import cached_property, update_wrapper
7
6
  from pathlib import Path
@@ -43,17 +42,17 @@ class Checkpointer:
43
42
  self.fn_hash = opts.get("fn_hash")
44
43
 
45
44
  @overload
46
- def __call__(self, fn: Fn, **override_opts: Unpack[CheckpointerOpts]) -> CheckpointFn[Fn]: ...
45
+ def __call__(self, fn: Fn, **override_opts: Unpack[CheckpointerOpts]) -> CachedFunction[Fn]: ...
47
46
  @overload
48
47
  def __call__(self, fn: None=None, **override_opts: Unpack[CheckpointerOpts]) -> Checkpointer: ...
49
- def __call__(self, fn: Fn | None=None, **override_opts: Unpack[CheckpointerOpts]) -> Checkpointer | CheckpointFn[Fn]:
48
+ def __call__(self, fn: Fn | None=None, **override_opts: Unpack[CheckpointerOpts]) -> Checkpointer | CachedFunction[Fn]:
50
49
  if override_opts:
51
50
  opts = CheckpointerOpts(**{**self.__dict__, **override_opts})
52
51
  return Checkpointer(**opts)(fn)
53
52
 
54
- return CheckpointFn(self, fn) if callable(fn) else self
53
+ return CachedFunction(self, fn) if callable(fn) else self
55
54
 
56
- class CheckpointFn(Generic[Fn]):
55
+ class CachedFunction(Generic[Fn]):
57
56
  def __init__(self, checkpointer: Checkpointer, fn: Fn):
58
57
  wrapped = unwrap_fn(fn)
59
58
  fn_file = Path(wrapped.__code__.co_filename).name
@@ -80,15 +79,15 @@ class CheckpointFn(Generic[Fn]):
80
79
 
81
80
  @cached_property
82
81
  def fn_hash(self) -> str:
83
- fn_hash = self.checkpointer.fn_hash
84
82
  deep_hashes = [depend.fn_hash_raw for depend in self.deep_depends()]
85
- return str(fn_hash or ObjectHash(digest_size=16).write_text(self.fn_hash_raw, *deep_hashes))[:32]
83
+ fn_hash = ObjectHash(digest_size=16).write_text(self.fn_hash_raw, *deep_hashes)
84
+ return str(self.checkpointer.fn_hash or fn_hash)[:32]
86
85
 
87
- def reinit(self, recursive=False) -> CheckpointFn[Fn]:
86
+ def reinit(self, recursive=False) -> CachedFunction[Fn]:
88
87
  depends = list(self.deep_depends()) if recursive else [self]
89
88
  for depend in depends:
90
- with suppress(AttributeError):
91
- del depend.ident_tuple, depend.fn_hash
89
+ self.__dict__.pop("fn_hash", None)
90
+ self.__dict__.pop("ident_tuple", None)
92
91
  for depend in depends:
93
92
  depend.fn_hash
94
93
  return self
@@ -150,21 +149,21 @@ class CheckpointFn(Generic[Fn]):
150
149
  raise CheckpointError("Could not load checkpoint") from ex
151
150
 
152
151
  def exists(self: Callable[P, R], *args: P.args, **kw: P.kwargs) -> bool: # type: ignore
153
- self = cast(CheckpointFn, self)
152
+ self = cast(CachedFunction, self)
154
153
  return self.storage.exists(self.get_call_id(args, kw))
155
154
 
156
155
  def delete(self: Callable[P, R], *args: P.args, **kw: P.kwargs): # type: ignore
157
- self = cast(CheckpointFn, self)
156
+ self = cast(CachedFunction, self)
158
157
  self.storage.delete(self.get_call_id(args, kw))
159
158
 
160
159
  def __repr__(self) -> str:
161
160
  return f"<CheckpointFn {self.fn.__name__} {self.fn_hash[:6]}>"
162
161
 
163
- def deep_depends(self, visited: set[CheckpointFn] = set()) -> Iterable[CheckpointFn]:
162
+ def deep_depends(self, visited: set[CachedFunction] = set()) -> Iterable[CachedFunction]:
164
163
  if self not in visited:
165
164
  yield self
166
165
  visited = visited or set()
167
166
  visited.add(self)
168
167
  for depend in self.depends:
169
- if isinstance(depend, CheckpointFn):
168
+ if isinstance(depend, CachedFunction):
170
169
  yield from depend.deep_depends(visited)
checkpointer/fn_ident.py CHANGED
@@ -8,7 +8,7 @@ from typing import Any, Iterable, Type, TypeGuard
8
8
  from .object_hash import ObjectHash
9
9
  from .utils import AttrDict, distinct, get_cell_contents, iterate_and_upcoming, transpose, unwrap_fn
10
10
 
11
- cwd = Path.cwd()
11
+ cwd = Path.cwd().resolve()
12
12
 
13
13
  def is_class(obj) -> TypeGuard[Type]:
14
14
  # isinstance works too, but needlessly triggers _lazyinit()
@@ -72,23 +72,23 @@ def is_user_fn(candidate_fn) -> TypeGuard[Callable]:
72
72
  return cwd in fn_path.parents and ".venv" not in fn_path.parts
73
73
 
74
74
  def get_depend_fns(fn: Callable, capture: bool, captured_vals_by_fn: dict[Callable, list[Any]] = {}) -> dict[Callable, list[Any]]:
75
- from .checkpoint import CheckpointFn
75
+ from .checkpoint import CachedFunction
76
76
  captured_vals_by_fn = captured_vals_by_fn or {}
77
77
  captured_vals = get_fn_captured_vals(fn)
78
78
  captured_vals_by_fn[fn] = [val for val in captured_vals if not callable(val)] * capture
79
- child_fns = (unwrap_fn(val, checkpoint_fn=True) for val in captured_vals if callable(val))
79
+ child_fns = (unwrap_fn(val, cached_fn=True) for val in captured_vals if callable(val))
80
80
  for child_fn in child_fns:
81
- if isinstance(child_fn, CheckpointFn):
81
+ if isinstance(child_fn, CachedFunction):
82
82
  captured_vals_by_fn[child_fn] = []
83
83
  elif child_fn not in captured_vals_by_fn and is_user_fn(child_fn):
84
84
  get_depend_fns(child_fn, capture, captured_vals_by_fn)
85
85
  return captured_vals_by_fn
86
86
 
87
87
  def get_fn_ident(fn: Callable, capture: bool) -> tuple[str, list[Callable]]:
88
- from .checkpoint import CheckpointFn
88
+ from .checkpoint import CachedFunction
89
89
  captured_vals_by_fn = get_depend_fns(fn, capture)
90
90
  depends, depend_captured_vals = transpose(captured_vals_by_fn.items(), 2)
91
91
  depends = distinct(fn.__func__ if isinstance(fn, MethodType) else fn for fn in depends)
92
- unwrapped_depends = [fn for fn in depends if not isinstance(fn, CheckpointFn)]
92
+ unwrapped_depends = [fn for fn in depends if not isinstance(fn, CachedFunction)]
93
93
  fn_hash = str(ObjectHash(fn, unwrapped_depends).update(depend_captured_vals, tolerate_errors=True))
94
94
  return fn_hash, depends
@@ -34,11 +34,11 @@ class PickleStorage(Storage):
34
34
  old_dirs = [path for path in fn_path.iterdir() if path.is_dir() and path != version_path]
35
35
  for path in old_dirs:
36
36
  shutil.rmtree(path)
37
- print(f"Removed {len(old_dirs)} invalidated directories for {self.checkpoint_fn.__qualname__}")
37
+ print(f"Removed {len(old_dirs)} invalidated directories for {self.cached_fn.__qualname__}")
38
38
  if expired and self.checkpointer.should_expire:
39
39
  count = 0
40
- for pkl_path in fn_path.rglob("*.pkl"):
40
+ for pkl_path in fn_path.glob("**/*.pkl"):
41
41
  if self.checkpointer.should_expire(self.checkpoint_date(pkl_path.stem)):
42
42
  count += 1
43
43
  self.delete(pkl_path.stem)
44
- print(f"Removed {count} expired checkpoints for {self.checkpoint_fn.__qualname__}")
44
+ print(f"Removed {count} expired checkpoints for {self.cached_fn.__qualname__}")
@@ -4,18 +4,18 @@ from pathlib import Path
4
4
  from datetime import datetime
5
5
 
6
6
  if TYPE_CHECKING:
7
- from ..checkpoint import Checkpointer, CheckpointFn
7
+ from ..checkpoint import Checkpointer, CachedFunction
8
8
 
9
9
  class Storage:
10
10
  checkpointer: Checkpointer
11
- checkpoint_fn: CheckpointFn
11
+ cached_fn: CachedFunction
12
12
 
13
- def __init__(self, checkpoint_fn: CheckpointFn):
14
- self.checkpointer = checkpoint_fn.checkpointer
15
- self.checkpoint_fn = checkpoint_fn
13
+ def __init__(self, cached_fn: CachedFunction):
14
+ self.checkpointer = cached_fn.checkpointer
15
+ self.cached_fn = cached_fn
16
16
 
17
17
  def fn_id(self) -> str:
18
- return f"{self.checkpoint_fn.fn_dir}/{self.checkpoint_fn.fn_hash}"
18
+ return f"{self.cached_fn.fn_dir}/{self.cached_fn.fn_hash}"
19
19
 
20
20
  def fn_dir(self) -> Path:
21
21
  return self.checkpointer.root_path / self.fn_id()
checkpointer/utils.py CHANGED
@@ -32,10 +32,10 @@ def get_cell_contents(fn: Callable) -> Iterable[tuple[str, Any]]:
32
32
  except ValueError:
33
33
  pass
34
34
 
35
- def unwrap_fn(fn: Fn, checkpoint_fn=False) -> Fn:
36
- from .checkpoint import CheckpointFn
35
+ def unwrap_fn(fn: Fn, cached_fn=False) -> Fn:
36
+ from .checkpoint import CachedFunction
37
37
  while True:
38
- if (checkpoint_fn and isinstance(fn, CheckpointFn)) or not hasattr(fn, "__wrapped__"):
38
+ if (cached_fn and isinstance(fn, CachedFunction)) or not hasattr(fn, "__wrapped__"):
39
39
  return cast(Fn, fn)
40
40
  fn = getattr(fn, "__wrapped__")
41
41
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: checkpointer
3
- Version: 2.9.1
3
+ Version: 2.9.2
4
4
  Summary: A Python library for memoizing function results with support for multiple storage backends, async runtimes, and automatic cache invalidation
5
5
  Project-URL: Repository, https://github.com/Reddan/checkpointer.git
6
6
  Author: Hampus Hallman
@@ -76,7 +76,7 @@ def helper(x):
76
76
 
77
77
  @checkpoint
78
78
  def compute(a, b):
79
- # Depends on `helper`
79
+ # Depends on `helper` and `multiply`
80
80
  return helper(a) + helper(b)
81
81
  ```
82
82
 
@@ -0,0 +1,16 @@
1
+ checkpointer/__init__.py,sha256=bzb3aZ7iQsRTmzggBdnfowxwj1pNiux2UGpMzKriGPw,838
2
+ checkpointer/checkpoint.py,sha256=3e11K-6Kq_OVGTFzsGmYYO3bK7U3j-y0oDYWvmjSMI4,6235
3
+ checkpointer/fn_ident.py,sha256=hiPvm1lw9Aol6v-d5bjteWdg0VhrPQH4r1Wiow-Wzpo,4311
4
+ checkpointer/object_hash.py,sha256=cxuWRDrg4F9wC18aC12zOZYOPv3bk2Qf6tZ0_WgAb6Y,7484
5
+ checkpointer/print_checkpoint.py,sha256=aJCeWMRJiIR3KpyPk_UOKTaD906kArGrmLGQ3LqcVgo,1369
6
+ checkpointer/test_checkpointer.py,sha256=6gLFggsTDNdG2V9ruFlIM8weixd7ES66e5UQYdFX7Dw,3839
7
+ checkpointer/utils.py,sha256=_zvbkno7221_4l_FbROJMRrs-enx8BRS4FGxn8et9Ns,2751
8
+ checkpointer/storages/__init__.py,sha256=Kl4Og5jhYxn6m3tB_kTMsabf4_eWVLmFVAoC-pikNQE,301
9
+ checkpointer/storages/bcolz_storage.py,sha256=3QkSUSeG5s2kFuVV_LZpzMn1A5E7kqC7jk7w35c0NyQ,2314
10
+ checkpointer/storages/memory_storage.py,sha256=zfN2B_BgPmI1IcYQPo4ICr2AO6ne_UsEc_tvhbDtXBA,1093
11
+ checkpointer/storages/pickle_storage.py,sha256=mCmEsA-FBfNUs9P8NKHL9NZeawYJvIq51Kgaj0_HzcI,1535
12
+ checkpointer/storages/storage.py,sha256=8_2qQCjtIPOerkYGhzqBZnf1A77-hzINKluiIAIvjcQ,890
13
+ checkpointer-2.9.2.dist-info/METADATA,sha256=1sg_J_lNDWVwxGiYeElq5PjCVUwb6FkWiWaA10Ke8lI,10992
14
+ checkpointer-2.9.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
+ checkpointer-2.9.2.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
16
+ checkpointer-2.9.2.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- checkpointer/__init__.py,sha256=HRLsQ24ZhxgmDcHchZ-hX6wA0NMCSedGA0NmCnUdS_c,832
2
- checkpointer/checkpoint.py,sha256=pbg62Q8gKhx21XEn5kPW95C7ERdQifAg-GAPQN6aWDk,6245
3
- checkpointer/fn_ident.py,sha256=SWaksNCTlskMom0ztqjECSRjZYPWXUA1p1ZCb-9tWo0,4297
4
- checkpointer/object_hash.py,sha256=cxuWRDrg4F9wC18aC12zOZYOPv3bk2Qf6tZ0_WgAb6Y,7484
5
- checkpointer/print_checkpoint.py,sha256=aJCeWMRJiIR3KpyPk_UOKTaD906kArGrmLGQ3LqcVgo,1369
6
- checkpointer/test_checkpointer.py,sha256=6gLFggsTDNdG2V9ruFlIM8weixd7ES66e5UQYdFX7Dw,3839
7
- checkpointer/utils.py,sha256=2yk1ksKszXofwnSqBrNCFRSR4C3YLPEAdHUFf-cviRU,2755
8
- checkpointer/storages/__init__.py,sha256=Kl4Og5jhYxn6m3tB_kTMsabf4_eWVLmFVAoC-pikNQE,301
9
- checkpointer/storages/bcolz_storage.py,sha256=3QkSUSeG5s2kFuVV_LZpzMn1A5E7kqC7jk7w35c0NyQ,2314
10
- checkpointer/storages/memory_storage.py,sha256=zfN2B_BgPmI1IcYQPo4ICr2AO6ne_UsEc_tvhbDtXBA,1093
11
- checkpointer/storages/pickle_storage.py,sha256=WwNg7kmE2on68-6uSPh1JAZLO6gi-P-3VmeBdklKnL0,1541
12
- checkpointer/storages/storage.py,sha256=hXzHf1i4Vb_JCeUhY2sVIZlpS049YkM1ya1SAW_x7Ls,912
13
- checkpointer-2.9.1.dist-info/METADATA,sha256=cbv49N5LRSbc-7ejHNEHJn_fSZWaA_1nFNJUuR-IH8E,10977
14
- checkpointer-2.9.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
15
- checkpointer-2.9.1.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
16
- checkpointer-2.9.1.dist-info/RECORD,,