persistent-function-cache 0.2.2__tar.gz → 0.3.0__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.
- {persistent_function_cache-0.2.2/src/persistent_function_cache.egg-info → persistent_function_cache-0.3.0}/PKG-INFO +10 -9
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/README.md +1 -1
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/pyproject.toml +14 -7
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/cli/clear_cache.py +2 -2
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/main/cache_slot.py +4 -2
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/main/decorator.py +1 -1
- persistent_function_cache-0.3.0/src/persistent_cache/main/hashing.py +54 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/models/path.py +4 -4
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/reducers/speedup_deep_learning.py +0 -4
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0/src/persistent_function_cache.egg-info}/PKG-INFO +10 -9
- persistent_function_cache-0.3.0/src/persistent_function_cache.egg-info/requires.txt +9 -0
- persistent_function_cache-0.2.2/src/persistent_cache/main/hashing.py +0 -80
- persistent_function_cache-0.2.2/src/persistent_function_cache.egg-info/requires.txt +0 -9
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/LICENSE +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/setup.cfg +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/__init__.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/caches/__init__.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/caches/deep_learning.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/caches/speedup_deep_learning.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/cli/__init__.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/main/__init__.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/models/__init__.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/py.typed +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/reducers/__init__.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/reducers/base.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/reducers/deep_learning.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_function_cache.egg-info/SOURCES.txt +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_function_cache.egg-info/dependency_links.txt +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_function_cache.egg-info/entry_points.txt +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_function_cache.egg-info/top_level.txt +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/tests/test_cache.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/tests/test_clear_cache.py +0 -0
- {persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/tests/test_deep_learning_cache.py +0 -0
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: persistent-function-cache
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Persistent cache for expensive functions
|
|
5
5
|
Author-email: Quinten Roets <qdr2104@columbia.edu>
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Source Code, https://github.com/quintenroets/persistent-cache
|
|
8
|
-
Requires-Python:
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
|
-
Requires-Dist: package-utils<1,>=0.
|
|
12
|
-
Requires-Dist: powercli<1,>=0.
|
|
13
|
-
Requires-Dist: superpathlib<3,>=2.0.
|
|
11
|
+
Requires-Dist: package-utils<1,>=0.8.5
|
|
12
|
+
Requires-Dist: powercli<1,>=0.4.0
|
|
13
|
+
Requires-Dist: superpathlib<3,>=2.0.13
|
|
14
14
|
Provides-Extra: dev
|
|
15
|
-
Requires-Dist: package-dev-tools<1,>=0.
|
|
15
|
+
Requires-Dist: package-dev-tools<1,>=0.8.1; extra == "dev"
|
|
16
16
|
Requires-Dist: package-dev-utils<1,>=0.1.6; extra == "dev"
|
|
17
17
|
Requires-Dist: numpy<3,>=1.26.0; extra == "dev"
|
|
18
18
|
Requires-Dist: torch<3,>=1.26.0; extra == "dev"
|
|
19
|
+
Dynamic: license-file
|
|
19
20
|
|
|
20
21
|
# Cache
|
|
21
22
|
[](https://badge.fury.io/py/persistent-function-cache)
|
|
22
23
|

|
|
23
|
-

|
|
24
25
|

|
|
25
26
|

|
|
26
27
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Cache
|
|
2
2
|
[](https://badge.fury.io/py/persistent-function-cache)
|
|
3
3
|

|
|
4
|
-

|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "persistent-function-cache"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Persistent cache for expensive functions"
|
|
5
5
|
authors = [{name = "Quinten Roets", email = "qdr2104@columbia.edu"}]
|
|
6
|
-
license =
|
|
6
|
+
license = "MIT"
|
|
7
7
|
readme = "README.md"
|
|
8
|
-
requires-python = ">=3.
|
|
8
|
+
requires-python = ">=3.11"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"package-utils >=0.
|
|
11
|
-
"powercli >=0.
|
|
12
|
-
"superpathlib >=2.0.
|
|
10
|
+
"package-utils >=0.8.5, <1",
|
|
11
|
+
"powercli >=0.4.0, <1",
|
|
12
|
+
"superpathlib >=2.0.13, <3",
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
[project.optional-dependencies]
|
|
16
16
|
dev = [
|
|
17
|
-
"package-dev-tools >=0.
|
|
17
|
+
"package-dev-tools >=0.8.1, <1",
|
|
18
18
|
"package-dev-utils >=0.1.6, <1",
|
|
19
19
|
"numpy >=1.26.0, <3",
|
|
20
20
|
"torch >=1.26.0, <3",
|
|
@@ -53,7 +53,14 @@ fix = true
|
|
|
53
53
|
select = ["ALL"]
|
|
54
54
|
ignore = [
|
|
55
55
|
"ANN401", # annotated with Any
|
|
56
|
+
"CPY001", # missing copyright notice
|
|
56
57
|
"D", # docstrings
|
|
58
|
+
"D1", # missing docstrings
|
|
59
|
+
"D200", # one-line docstring
|
|
60
|
+
"D203", # conflicts with D211
|
|
61
|
+
"D205", # blank line between summary and description
|
|
62
|
+
"D212", # conflicts with D213
|
|
63
|
+
"D401", # imperative first line
|
|
57
64
|
"G004", # logging f-string
|
|
58
65
|
]
|
|
59
66
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
from datetime import
|
|
3
|
+
from datetime import UTC, datetime
|
|
4
4
|
from functools import cached_property
|
|
5
5
|
from typing import Annotated
|
|
6
6
|
|
|
@@ -43,7 +43,7 @@ def main(options: Options) -> None:
|
|
|
43
43
|
if options.verbose:
|
|
44
44
|
relative_path = path.relative_to(Options.cache_path)
|
|
45
45
|
timestamp = datetime.fromtimestamp(path.mtime).astimezone(
|
|
46
|
-
tz=
|
|
46
|
+
tz=UTC,
|
|
47
47
|
)
|
|
48
48
|
message = f"{relative_path} ({timestamp})"
|
|
49
49
|
cli.console.print(message)
|
|
@@ -87,11 +87,13 @@ class CacheSlot:
|
|
|
87
87
|
if self.key_reducer is not None:
|
|
88
88
|
return self.key_reducer
|
|
89
89
|
if self.deep_learning:
|
|
90
|
-
from persistent_cache.reducers.deep_learning import
|
|
90
|
+
from persistent_cache.reducers.deep_learning import ( # noqa: PLC0415
|
|
91
|
+
Reducer as Reducer_,
|
|
92
|
+
)
|
|
91
93
|
|
|
92
94
|
return Reducer_
|
|
93
95
|
if self.speedup_deep_learning:
|
|
94
|
-
from persistent_cache.reducers.speedup_deep_learning import (
|
|
96
|
+
from persistent_cache.reducers.speedup_deep_learning import ( # noqa: PLC0415
|
|
95
97
|
Reducer as Reducer_,
|
|
96
98
|
)
|
|
97
99
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import inspect
|
|
5
|
+
import io
|
|
6
|
+
import pickle
|
|
7
|
+
from functools import cache
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
|
+
|
|
10
|
+
from package_utils.annotations import first_parameter_types
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Callable, Iterator # pragma: nocover
|
|
14
|
+
from typing import BinaryIO # pragma: nocover
|
|
15
|
+
|
|
16
|
+
from persistent_cache.reducers.base import Reducer # pragma: nocover
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def compute_hash(key_reducer: type[Reducer], items: Iterator[Any]) -> str:
|
|
20
|
+
with io.BytesIO() as fp:
|
|
21
|
+
HashPickler(fp, key_reducer).dump(tuple(items))
|
|
22
|
+
data = fp.getvalue()
|
|
23
|
+
# use fast hash function because it is not used for security
|
|
24
|
+
return hashlib.new("sha1", data=data, usedforsecurity=False).hexdigest()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class HashPickler(pickle.Pickler):
|
|
28
|
+
def __init__(self, file_pointer: BinaryIO, reducer: type[Reducer]) -> None:
|
|
29
|
+
super().__init__(file_pointer)
|
|
30
|
+
self.reducers = load_reducers(reducer) # type: ignore[arg-type]
|
|
31
|
+
|
|
32
|
+
def reducer_override(self, obj: Any) -> Any:
|
|
33
|
+
"""The goal of this pickler is to create hashes of complex objects, not to
|
|
34
|
+
reconstruct complex objects.
|
|
35
|
+
|
|
36
|
+
So mapping does not need to be reversible.
|
|
37
|
+
"""
|
|
38
|
+
reducer = next(self.determine_reducer(obj), None)
|
|
39
|
+
return NotImplemented if reducer is None else (tuple, (reducer(obj),))
|
|
40
|
+
|
|
41
|
+
def determine_reducer(self, obj: Any) -> Iterator[Callable[[Any], Any]]:
|
|
42
|
+
if obj is not tuple:
|
|
43
|
+
for obj_type, reducer in self.reducers.items():
|
|
44
|
+
if isinstance(obj, obj_type):
|
|
45
|
+
yield reducer
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@cache
|
|
49
|
+
def load_reducers(reducer: type[Reducer]) -> dict[type, Callable[[Any], Any]]:
|
|
50
|
+
return {
|
|
51
|
+
parameter_type: method
|
|
52
|
+
for _, method in inspect.getmembers(reducer, predicate=inspect.ismethod)
|
|
53
|
+
for parameter_type in first_parameter_types(method)
|
|
54
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TypeVar, cast
|
|
1
|
+
from typing import Self, TypeVar, cast
|
|
2
2
|
|
|
3
3
|
import superpathlib
|
|
4
4
|
from simple_classproperty import classproperty
|
|
@@ -9,11 +9,11 @@ T = TypeVar("T", bound="Path")
|
|
|
9
9
|
class Path(superpathlib.Path):
|
|
10
10
|
@classmethod
|
|
11
11
|
@classproperty
|
|
12
|
-
def source_root(cls
|
|
12
|
+
def source_root(cls) -> Self:
|
|
13
13
|
return cls(__file__).parent.parent
|
|
14
14
|
|
|
15
15
|
@classmethod
|
|
16
16
|
@classproperty
|
|
17
|
-
def cache(cls
|
|
17
|
+
def cache(cls) -> Self:
|
|
18
18
|
path = cls.script_assets / cls.source_root.name
|
|
19
|
-
return cast(
|
|
19
|
+
return cast("Self", path)
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: persistent-function-cache
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Persistent cache for expensive functions
|
|
5
5
|
Author-email: Quinten Roets <qdr2104@columbia.edu>
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Source Code, https://github.com/quintenroets/persistent-cache
|
|
8
|
-
Requires-Python:
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
|
-
Requires-Dist: package-utils<1,>=0.
|
|
12
|
-
Requires-Dist: powercli<1,>=0.
|
|
13
|
-
Requires-Dist: superpathlib<3,>=2.0.
|
|
11
|
+
Requires-Dist: package-utils<1,>=0.8.5
|
|
12
|
+
Requires-Dist: powercli<1,>=0.4.0
|
|
13
|
+
Requires-Dist: superpathlib<3,>=2.0.13
|
|
14
14
|
Provides-Extra: dev
|
|
15
|
-
Requires-Dist: package-dev-tools<1,>=0.
|
|
15
|
+
Requires-Dist: package-dev-tools<1,>=0.8.1; extra == "dev"
|
|
16
16
|
Requires-Dist: package-dev-utils<1,>=0.1.6; extra == "dev"
|
|
17
17
|
Requires-Dist: numpy<3,>=1.26.0; extra == "dev"
|
|
18
18
|
Requires-Dist: torch<3,>=1.26.0; extra == "dev"
|
|
19
|
+
Dynamic: license-file
|
|
19
20
|
|
|
20
21
|
# Cache
|
|
21
22
|
[](https://badge.fury.io/py/persistent-function-cache)
|
|
22
23
|

|
|
23
|
-

|
|
24
25
|

|
|
25
26
|

|
|
26
27
|
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import hashlib
|
|
4
|
-
import inspect
|
|
5
|
-
import io
|
|
6
|
-
import pickle
|
|
7
|
-
from types import UnionType
|
|
8
|
-
from typing import TYPE_CHECKING, Any, get_args, get_origin, get_type_hints
|
|
9
|
-
|
|
10
|
-
from persistent_cache.reducers.base import Reducer
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from collections.abc import Callable, Iterator # pragma: nocover
|
|
14
|
-
from typing import BinaryIO # pragma: nocover
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def extract_types(method: Callable[[Any], Any]) -> Iterator[type]:
|
|
18
|
-
type_hints = get_type_hints(method).values()
|
|
19
|
-
if type_hints:
|
|
20
|
-
argument_type = next(iter(type_hints))
|
|
21
|
-
origin = get_origin(argument_type)
|
|
22
|
-
arguments = get_args(argument_type)
|
|
23
|
-
if origin is UnionType:
|
|
24
|
-
yield from arguments
|
|
25
|
-
elif origin is not None:
|
|
26
|
-
yield origin
|
|
27
|
-
else:
|
|
28
|
-
yield argument_type
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class HashPickler(pickle.Pickler):
|
|
32
|
-
def __init__(
|
|
33
|
-
self,
|
|
34
|
-
file_pointer: BinaryIO,
|
|
35
|
-
reducer: type[Reducer] = Reducer,
|
|
36
|
-
) -> None:
|
|
37
|
-
super().__init__(file_pointer)
|
|
38
|
-
self.reducer = reducer
|
|
39
|
-
self.reducers = {}
|
|
40
|
-
for _, method in inspect.getmembers(reducer, predicate=inspect.ismethod):
|
|
41
|
-
argument_types = extract_types(method)
|
|
42
|
-
for argument_type in argument_types:
|
|
43
|
-
self.reducers[argument_type] = method
|
|
44
|
-
|
|
45
|
-
def reducer_override(self, obj: Any) -> Any:
|
|
46
|
-
"""The goal of this pickler is to create hashes of complex objects, not to
|
|
47
|
-
reconstruct complex objects.
|
|
48
|
-
|
|
49
|
-
So mapping does not need to be reversible.
|
|
50
|
-
"""
|
|
51
|
-
reducer = next(self.determine_reducer(obj), None)
|
|
52
|
-
reduction: Any
|
|
53
|
-
if reducer is None:
|
|
54
|
-
reduction = NotImplemented
|
|
55
|
-
else:
|
|
56
|
-
mapping = reducer(obj)
|
|
57
|
-
str_mapping = str(item_to_bytes(self.reducer, mapping))
|
|
58
|
-
reduction = str, (str_mapping,)
|
|
59
|
-
return reduction
|
|
60
|
-
|
|
61
|
-
def determine_reducer(self, obj: Any) -> Iterator[Callable[[Any], Any]]:
|
|
62
|
-
if obj is not str:
|
|
63
|
-
for obj_type, reducer in self.reducers.items():
|
|
64
|
-
if isinstance(obj, obj_type):
|
|
65
|
-
yield reducer
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def compute_hash(key_reducer: type[Reducer], items: Iterator[Any]) -> str:
|
|
69
|
-
data = item_to_bytes(key_reducer, tuple(items))
|
|
70
|
-
# use fast hash function because it is not used for security
|
|
71
|
-
return hashlib.new("sha1", data=data, usedforsecurity=False).hexdigest()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def item_to_bytes(key_reducer: type[Reducer], item: Any) -> bytes:
|
|
75
|
-
with io.BytesIO() as fp:
|
|
76
|
-
# Use custom pickler to generate bytes from complex structures
|
|
77
|
-
pickler = HashPickler(fp, key_reducer)
|
|
78
|
-
pickler.dump(item)
|
|
79
|
-
fp.seek(0)
|
|
80
|
-
return fp.read()
|
|
File without changes
|
|
File without changes
|
{persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/src/persistent_cache/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{persistent_function_cache-0.2.2 → persistent_function_cache-0.3.0}/tests/test_clear_cache.py
RENAMED
|
File without changes
|
|
File without changes
|