checkpointer 2.14.2__tar.gz → 2.14.4__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 (21) hide show
  1. {checkpointer-2.14.2 → checkpointer-2.14.4}/PKG-INFO +1 -1
  2. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/__init__.py +1 -0
  3. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/checkpoint.py +6 -4
  4. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/storages/memory_storage.py +10 -0
  5. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/storages/pickle_storage.py +15 -1
  6. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/utils.py +3 -0
  7. {checkpointer-2.14.2 → checkpointer-2.14.4}/pyproject.toml +2 -1
  8. {checkpointer-2.14.2 → checkpointer-2.14.4}/uv.lock +17 -1
  9. {checkpointer-2.14.2 → checkpointer-2.14.4}/.gitignore +0 -0
  10. {checkpointer-2.14.2 → checkpointer-2.14.4}/.python-version +0 -0
  11. {checkpointer-2.14.2 → checkpointer-2.14.4}/ATTRIBUTION.md +0 -0
  12. {checkpointer-2.14.2 → checkpointer-2.14.4}/LICENSE +0 -0
  13. {checkpointer-2.14.2 → checkpointer-2.14.4}/README.md +0 -0
  14. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/fn_ident.py +0 -0
  15. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/fn_string.py +0 -0
  16. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/import_mappings.py +0 -0
  17. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/object_hash.py +0 -0
  18. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/print_checkpoint.py +0 -0
  19. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/storages/__init__.py +0 -0
  20. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/storages/storage.py +0 -0
  21. {checkpointer-2.14.2 → checkpointer-2.14.4}/checkpointer/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: checkpointer
3
- Version: 2.14.2
3
+ Version: 2.14.4
4
4
  Summary: checkpointer adds code-aware caching to Python functions, maintaining correctness and speeding up execution as your code changes.
5
5
  Project-URL: Repository, https://github.com/Reddan/checkpointer.git
6
6
  Author: Hampus Hallman
@@ -5,6 +5,7 @@ from typing import Callable
5
5
  from .checkpoint import CachedFunction, Checkpointer, CheckpointError, FunctionIdent
6
6
  from .object_hash import ObjectHash
7
7
  from .storages import MemoryStorage, PickleStorage, Storage
8
+ from .storages.memory_storage import cleanup_memory_storage
8
9
  from .types import AwaitableValue, Captured, CapturedOnce, CaptureMe, CaptureMeOnce, HashBy, NoHash
9
10
 
10
11
  checkpoint = Checkpointer()
@@ -12,8 +12,8 @@ from .fn_ident import Capturable, RawFunctionIdent, get_fn_ident
12
12
  from .object_hash import ObjectHash
13
13
  from .print_checkpoint import print_checkpoint
14
14
  from .storages import STORAGE_MAP, Storage, StorageType
15
- from .types import AwaitableValue, C, Coro, Fn, P, R, hash_by_from_annotation
16
- from .utils import flatten
15
+ from .types import AwaitableValue, C, Coro, Fn, P, R, T, hash_by_from_annotation
16
+ from .utils import flatten, to_coroutine
17
17
 
18
18
  DEFAULT_DIR = Path.home() / ".cache/checkpoints"
19
19
 
@@ -211,6 +211,8 @@ class CachedFunction(Generic[Fn]):
211
211
  try:
212
212
  data = storage.load(call_hash)
213
213
  print_checkpoint(params.verbosity >= 2, "REMEMBERED", call_id, "green")
214
+ if isinstance(data, AwaitableValue):
215
+ return to_coroutine(data.value) # type: ignore
214
216
  return data
215
217
  except (EOFError, FileNotFoundError):
216
218
  pass
@@ -242,9 +244,9 @@ class CachedFunction(Generic[Fn]):
242
244
  raise CheckpointError("Could not load checkpoint") from ex
243
245
 
244
246
  @overload
245
- def get_or(self: Callable[P, Coro[R]], default: R, *args: P.args, **kw: P.kwargs) -> R: ...
247
+ def get_or(self: Callable[P, Coro[R]], default: T, *args: P.args, **kw: P.kwargs) -> R | T: ...
246
248
  @overload
247
- def get_or(self: Callable[P, R], default: R, *args: P.args, **kw: P.kwargs) -> R: ...
249
+ def get_or(self: Callable[P, R], default: T, *args: P.args, **kw: P.kwargs) -> R | T: ...
248
250
  def get_or(self, default, *args, **kw):
249
251
  try:
250
252
  return self.get(*args, **kw) # type: ignore
@@ -1,3 +1,4 @@
1
+ import gc
1
2
  from typing import Any
2
3
  from pathlib import Path
3
4
  from datetime import datetime
@@ -41,3 +42,12 @@ class MemoryStorage(Storage):
41
42
  for key in list(item_map.keys()):
42
43
  if key.parent == fn_path:
43
44
  del item_map[key]
45
+
46
+ def cleanup_memory_storage():
47
+ gc.collect()
48
+ memory_stores = [obj for obj in gc.get_objects() if isinstance(obj, MemoryStorage)]
49
+ storage_keys = {store.fn_dir() for store in memory_stores}
50
+ for key in item_map.keys() - storage_keys:
51
+ del item_map[key]
52
+ for store in memory_stores:
53
+ store.cleanup(invalidated=False)
@@ -1,13 +1,27 @@
1
1
  import pickle
2
2
  import shutil
3
3
  from datetime import datetime
4
+ from io import BytesIO
4
5
  from pathlib import Path
5
6
  from ..utils import clear_directory
6
7
  from .storage import Storage
7
8
 
9
+ try:
10
+ import polars as pl
11
+ except:
12
+ pl = None
13
+
8
14
  def filedate(path: Path) -> datetime:
9
15
  return datetime.fromtimestamp(path.stat().st_mtime)
10
16
 
17
+ class ExtendedPickler(pickle.Pickler):
18
+ def reducer_override(self, obj): # type: ignore
19
+ if pl and isinstance(obj, pl.DataFrame):
20
+ buffer = BytesIO()
21
+ obj.rechunk().write_parquet(buffer)
22
+ return pl.read_parquet, (buffer.getvalue(),)
23
+ return NotImplemented
24
+
11
25
  class PickleStorage(Storage):
12
26
  def get_path(self, call_hash: str):
13
27
  return self.fn_dir() / f"{call_hash[:2]}/{call_hash[2:]}.pkl"
@@ -16,7 +30,7 @@ class PickleStorage(Storage):
16
30
  path = self.get_path(call_hash)
17
31
  path.parent.mkdir(parents=True, exist_ok=True)
18
32
  with path.open("wb") as file:
19
- pickle.dump(data, file, -1)
33
+ ExtendedPickler(file, -1).dump(data)
20
34
  return data
21
35
 
22
36
  def exists(self, call_hash):
@@ -10,6 +10,9 @@ from .types import T
10
10
  cwd = Path.cwd().resolve()
11
11
  flatten = chain.from_iterable
12
12
 
13
+ async def to_coroutine(value: T) -> T:
14
+ return value
15
+
13
16
  def is_class(obj) -> TypeGuard[Type]:
14
17
  return isinstance(obj, type)
15
18
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "checkpointer"
3
- version = "2.14.2"
3
+ version = "2.14.4"
4
4
  requires-python = ">=3.11"
5
5
  dependencies = []
6
6
  authors = [
@@ -38,6 +38,7 @@ dev = [
38
38
  "numpy>=2.2.1",
39
39
  "omg>=1.3.6",
40
40
  "poethepoet>=0.30.0",
41
+ "polars>=1.31.0",
41
42
  "pytest>=8.3.5",
42
43
  "pytest-asyncio>=0.26.0",
43
44
  "rich>=14.0.0",
@@ -8,7 +8,7 @@ resolution-markers = [
8
8
 
9
9
  [[package]]
10
10
  name = "checkpointer"
11
- version = "2.14.2"
11
+ version = "2.14.4"
12
12
  source = { editable = "." }
13
13
 
14
14
  [package.dev-dependencies]
@@ -16,6 +16,7 @@ dev = [
16
16
  { name = "numpy" },
17
17
  { name = "omg" },
18
18
  { name = "poethepoet" },
19
+ { name = "polars" },
19
20
  { name = "pytest" },
20
21
  { name = "pytest-asyncio" },
21
22
  { name = "rich" },
@@ -29,6 +30,7 @@ dev = [
29
30
  { name = "numpy", specifier = ">=2.2.1" },
30
31
  { name = "omg", specifier = ">=1.3.6" },
31
32
  { name = "poethepoet", specifier = ">=0.30.0" },
33
+ { name = "polars", specifier = ">=1.31.0" },
32
34
  { name = "pytest", specifier = ">=8.3.5" },
33
35
  { name = "pytest-asyncio", specifier = ">=0.26.0" },
34
36
  { name = "rich", specifier = ">=14.0.0" },
@@ -388,6 +390,20 @@ wheels = [
388
390
  { url = "https://files.pythonhosted.org/packages/06/e1/04f56c9d848d6135ca3328c5a2ca84d3303c358ad7828db290385e36a8cc/poethepoet-0.31.1-py3-none-any.whl", hash = "sha256:7fdfa0ac6074be9936723e7231b5bfaad2923e96c674a9857e81d326cf8ccdc2", size = 80238 },
389
391
  ]
390
392
 
393
+ [[package]]
394
+ name = "polars"
395
+ version = "1.31.0"
396
+ source = { registry = "https://pypi.org/simple" }
397
+ sdist = { url = "https://files.pythonhosted.org/packages/fd/f5/de1b5ecd7d0bd0dd87aa392937f759f9cc3997c5866a9a7f94eabf37cd48/polars-1.31.0.tar.gz", hash = "sha256:59a88054a5fc0135386268ceefdbb6a6cc012d21b5b44fed4f1d3faabbdcbf32", size = 4681224 }
398
+ wheels = [
399
+ { url = "https://files.pythonhosted.org/packages/3d/6e/bdd0937653c1e7a564a09ae3bc7757ce83fedbf19da600c8b35d62c0182a/polars-1.31.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:ccc68cd6877deecd46b13cbd2663ca89ab2a2cb1fe49d5cfc66a9cef166566d9", size = 34511354 },
400
+ { url = "https://files.pythonhosted.org/packages/77/fe/81aaca3540c1a5530b4bc4fd7f1b6f77100243d7bb9b7ad3478b770d8b3e/polars-1.31.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:a94c5550df397ad3c2d6adc212e59fd93d9b044ec974dd3653e121e6487a7d21", size = 31377712 },
401
+ { url = "https://files.pythonhosted.org/packages/b8/d9/5e2753784ea30d84b3e769a56f5e50ac5a89c129e87baa16ac0773eb4ef7/polars-1.31.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ada7940ed92bea65d5500ae7ac1f599798149df8faa5a6db150327c9ddbee4f1", size = 35050729 },
402
+ { url = "https://files.pythonhosted.org/packages/20/e8/a6bdfe7b687c1fe84bceb1f854c43415eaf0d2fdf3c679a9dc9c4776e462/polars-1.31.0-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:b324e6e3e8c6cc6593f9d72fe625f06af65e8d9d47c8686583585533a5e731e1", size = 32260836 },
403
+ { url = "https://files.pythonhosted.org/packages/6e/f6/9d9ad9dc4480d66502497e90ce29efc063373e1598f4bd9b6a38af3e08e7/polars-1.31.0-cp39-abi3-win_amd64.whl", hash = "sha256:3fd874d3432fc932863e8cceff2cff8a12a51976b053f2eb6326a0672134a632", size = 35156211 },
404
+ { url = "https://files.pythonhosted.org/packages/40/4b/0673a68ac4d6527fac951970e929c3b4440c654f994f0c957bd5556deb38/polars-1.31.0-cp39-abi3-win_arm64.whl", hash = "sha256:62ef23bb9d10dca4c2b945979f9a50812ac4ace4ed9e158a6b5d32a7322e6f75", size = 31469078 },
405
+ ]
406
+
391
407
  [[package]]
392
408
  name = "pygments"
393
409
  version = "2.19.1"
File without changes
File without changes
File without changes