persistent-function-cache 0.2.0__tar.gz → 0.2.2__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.0/src/persistent_function_cache.egg-info → persistent_function_cache-0.2.2}/PKG-INFO +1 -1
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/pyproject.toml +1 -1
- persistent_function_cache-0.2.2/src/persistent_cache/main/cache_slot.py +100 -0
- persistent_function_cache-0.2.2/src/persistent_cache/main/decorator.py +91 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/main/hashing.py +6 -5
- persistent_function_cache-0.2.2/src/persistent_cache/models/__init__.py +1 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2/src/persistent_function_cache.egg-info}/PKG-INFO +1 -1
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_function_cache.egg-info/SOURCES.txt +1 -2
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/tests/test_cache.py +42 -0
- persistent_function_cache-0.2.0/src/persistent_cache/main/cacheslot.py +0 -42
- persistent_function_cache-0.2.0/src/persistent_cache/main/decorator.py +0 -122
- persistent_function_cache-0.2.0/src/persistent_cache/models/__init__.py +0 -2
- persistent_function_cache-0.2.0/src/persistent_cache/models/function.py +0 -4
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/LICENSE +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/README.md +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/setup.cfg +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/__init__.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/caches/__init__.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/caches/deep_learning.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/caches/speedup_deep_learning.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/cli/__init__.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/cli/clear_cache.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/main/__init__.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/models/path.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/py.typed +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/reducers/__init__.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/reducers/base.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/reducers/deep_learning.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_cache/reducers/speedup_deep_learning.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_function_cache.egg-info/dependency_links.txt +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_function_cache.egg-info/entry_points.txt +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_function_cache.egg-info/requires.txt +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/src/persistent_function_cache.egg-info/top_level.txt +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/tests/test_clear_cache.py +0 -0
- {persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/tests/test_deep_learning_cache.py +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import pickle
|
|
3
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from functools import cached_property
|
|
6
|
+
from inspect import BoundArguments
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from persistent_cache.models import Path
|
|
10
|
+
from persistent_cache.reducers.base import Reducer
|
|
11
|
+
|
|
12
|
+
from . import hashing
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class CacheSlot:
|
|
17
|
+
function: Callable[..., Any]
|
|
18
|
+
args: tuple[Any, ...]
|
|
19
|
+
kwargs: dict[str, Any]
|
|
20
|
+
directory: Path
|
|
21
|
+
key_arguments: Iterable[str] | str | None
|
|
22
|
+
argument_reducers: dict[str, Callable[[Any], Any]] | None
|
|
23
|
+
extra_keys: Any
|
|
24
|
+
key_reducer: type[Reducer] | None
|
|
25
|
+
deep_learning: bool
|
|
26
|
+
speedup_deep_learning: bool
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def value(self) -> Any:
|
|
30
|
+
try:
|
|
31
|
+
with self.path.open("rb") as fp:
|
|
32
|
+
return pickle.Unpickler(fp).load() # noqa: S301
|
|
33
|
+
except (pickle.UnpicklingError, EOFError):
|
|
34
|
+
# discard values of corrupted or empty slots
|
|
35
|
+
raise KeyError from None
|
|
36
|
+
|
|
37
|
+
@value.setter
|
|
38
|
+
def value(self, value: Any) -> None:
|
|
39
|
+
self.path.byte_content = pickle.dumps(value)
|
|
40
|
+
|
|
41
|
+
@cached_property
|
|
42
|
+
def path(self) -> Path:
|
|
43
|
+
return (
|
|
44
|
+
self.directory
|
|
45
|
+
/ self.function.__module__.replace(".", "_")
|
|
46
|
+
/ self.function.__name__
|
|
47
|
+
/ hashing.compute_hash(self.reducer, self.keys)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def keys(self) -> Iterator[Any]:
|
|
52
|
+
yield self.function
|
|
53
|
+
is_iterable = isinstance(self.extra_keys, Iterable) and not isinstance(
|
|
54
|
+
self.extra_keys,
|
|
55
|
+
str | bytes | bytearray,
|
|
56
|
+
)
|
|
57
|
+
if is_iterable:
|
|
58
|
+
yield from self.extra_keys
|
|
59
|
+
else:
|
|
60
|
+
yield self.extra_keys
|
|
61
|
+
yield from self.argument_values
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def argument_values(self) -> Iterator[Any]:
|
|
65
|
+
if self.key_arguments is None and self.argument_reducers is None:
|
|
66
|
+
yield from self.args
|
|
67
|
+
yield from self.kwargs.values()
|
|
68
|
+
else:
|
|
69
|
+
arguments = inspect.signature(self.function).bind(*self.args, **self.kwargs)
|
|
70
|
+
arguments.apply_defaults()
|
|
71
|
+
yield from self.extract_argument_values(arguments)
|
|
72
|
+
|
|
73
|
+
def extract_argument_values(self, arguments: BoundArguments) -> Iterator[Any]:
|
|
74
|
+
if self.key_arguments is not None:
|
|
75
|
+
if isinstance(self.key_arguments, str):
|
|
76
|
+
yield arguments.arguments.get(self.key_arguments)
|
|
77
|
+
else:
|
|
78
|
+
for name in self.key_arguments:
|
|
79
|
+
yield arguments.arguments.get(name)
|
|
80
|
+
if self.argument_reducers is not None:
|
|
81
|
+
for argument_name, reducer in self.argument_reducers.items():
|
|
82
|
+
argument = arguments.arguments.get(argument_name)
|
|
83
|
+
yield reducer(argument)
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def reducer(self) -> type[Reducer]:
|
|
87
|
+
if self.key_reducer is not None:
|
|
88
|
+
return self.key_reducer
|
|
89
|
+
if self.deep_learning:
|
|
90
|
+
from persistent_cache.reducers.deep_learning import Reducer as Reducer_
|
|
91
|
+
|
|
92
|
+
return Reducer_
|
|
93
|
+
if self.speedup_deep_learning:
|
|
94
|
+
from persistent_cache.reducers.speedup_deep_learning import (
|
|
95
|
+
Reducer as Reducer_,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return Reducer_
|
|
99
|
+
|
|
100
|
+
return Reducer
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from collections.abc import Callable, Iterable
|
|
2
|
+
from functools import wraps
|
|
3
|
+
from typing import Any, TypeVar, cast, overload
|
|
4
|
+
|
|
5
|
+
from persistent_cache.models import Path
|
|
6
|
+
from persistent_cache.reducers.base import Reducer
|
|
7
|
+
|
|
8
|
+
from .cache_slot import CacheSlot
|
|
9
|
+
|
|
10
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@overload
|
|
14
|
+
def cache(
|
|
15
|
+
function: F,
|
|
16
|
+
*,
|
|
17
|
+
cache_directory: Path = Path.cache,
|
|
18
|
+
cache_key_arguments: Iterable[str] | str | None = None,
|
|
19
|
+
argument_reducers: dict[str, Callable[[Any], Any]] | None = None,
|
|
20
|
+
extra_cache_keys: Iterable[Any] | None = None,
|
|
21
|
+
key_reducer: type[Reducer] = Reducer,
|
|
22
|
+
deep_learning: bool = False,
|
|
23
|
+
speedup_deep_learning: bool = False,
|
|
24
|
+
) -> F: ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@overload
|
|
28
|
+
def cache(
|
|
29
|
+
function: None = None,
|
|
30
|
+
*,
|
|
31
|
+
cache_directory: Path = Path.cache,
|
|
32
|
+
cache_key_arguments: Iterable[str] | str | None = None,
|
|
33
|
+
argument_reducers: dict[str, Callable[[Any], Any]] | None = None,
|
|
34
|
+
extra_cache_keys: Any = None,
|
|
35
|
+
key_reducer: type[Reducer] = Reducer,
|
|
36
|
+
deep_learning: bool = False,
|
|
37
|
+
speedup_deep_learning: bool = False,
|
|
38
|
+
) -> Callable[[F], F]: ...
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def cache( # noqa: PLR0913
|
|
42
|
+
function: F | None = None,
|
|
43
|
+
*,
|
|
44
|
+
cache_directory: Path = Path.cache,
|
|
45
|
+
cache_key_arguments: Iterable[str] | str | None = None,
|
|
46
|
+
argument_reducers: dict[str, Callable[[Any], Any]] | None = None,
|
|
47
|
+
extra_cache_keys: Any = None,
|
|
48
|
+
key_reducer: type[Reducer] | None = None,
|
|
49
|
+
deep_learning: bool = False,
|
|
50
|
+
speedup_deep_learning: bool = False,
|
|
51
|
+
) -> F | Callable[[F], F]:
|
|
52
|
+
"""A decorator to cache function results. Decorated functions are only executed if
|
|
53
|
+
result is not present in cache. The arguments of the function can be any nested
|
|
54
|
+
complex object.
|
|
55
|
+
|
|
56
|
+
Use as:
|
|
57
|
+
|
|
58
|
+
from persistent_cache import cache
|
|
59
|
+
|
|
60
|
+
@cache
|
|
61
|
+
def long_function(complex_object):
|
|
62
|
+
...
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def cache_decorator(function_: F) -> F:
|
|
66
|
+
@wraps(function_)
|
|
67
|
+
def wrapped_function(*args: Any, **kwargs: Any) -> Any:
|
|
68
|
+
cache_slot = CacheSlot(
|
|
69
|
+
function_,
|
|
70
|
+
args,
|
|
71
|
+
kwargs,
|
|
72
|
+
cache_directory,
|
|
73
|
+
cache_key_arguments,
|
|
74
|
+
argument_reducers,
|
|
75
|
+
extra_cache_keys,
|
|
76
|
+
key_reducer,
|
|
77
|
+
deep_learning,
|
|
78
|
+
speedup_deep_learning,
|
|
79
|
+
)
|
|
80
|
+
try:
|
|
81
|
+
result = cache_slot.value
|
|
82
|
+
except KeyError:
|
|
83
|
+
result = function_(*args, **kwargs)
|
|
84
|
+
cache_slot.value = result
|
|
85
|
+
return result
|
|
86
|
+
|
|
87
|
+
return cast(F, wrapped_function)
|
|
88
|
+
|
|
89
|
+
if function is not None:
|
|
90
|
+
cache_decorator = cache_decorator(function)
|
|
91
|
+
return cache_decorator
|
|
@@ -54,7 +54,7 @@ class HashPickler(pickle.Pickler):
|
|
|
54
54
|
reduction = NotImplemented
|
|
55
55
|
else:
|
|
56
56
|
mapping = reducer(obj)
|
|
57
|
-
str_mapping = str(
|
|
57
|
+
str_mapping = str(item_to_bytes(self.reducer, mapping))
|
|
58
58
|
reduction = str, (str_mapping,)
|
|
59
59
|
return reduction
|
|
60
60
|
|
|
@@ -65,15 +65,16 @@ class HashPickler(pickle.Pickler):
|
|
|
65
65
|
yield reducer
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def compute_hash(key_reducer: type[Reducer],
|
|
69
|
-
data =
|
|
68
|
+
def compute_hash(key_reducer: type[Reducer], items: Iterator[Any]) -> str:
|
|
69
|
+
data = item_to_bytes(key_reducer, tuple(items))
|
|
70
70
|
# use fast hash function because it is not used for security
|
|
71
71
|
return hashlib.new("sha1", data=data, usedforsecurity=False).hexdigest()
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
def
|
|
74
|
+
def item_to_bytes(key_reducer: type[Reducer], item: Any) -> bytes:
|
|
75
75
|
with io.BytesIO() as fp:
|
|
76
76
|
# Use custom pickler to generate bytes from complex structures
|
|
77
|
-
HashPickler(fp, key_reducer)
|
|
77
|
+
pickler = HashPickler(fp, key_reducer)
|
|
78
|
+
pickler.dump(item)
|
|
78
79
|
fp.seek(0)
|
|
79
80
|
return fp.read()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .path import Path
|
|
@@ -9,11 +9,10 @@ src/persistent_cache/caches/speedup_deep_learning.py
|
|
|
9
9
|
src/persistent_cache/cli/__init__.py
|
|
10
10
|
src/persistent_cache/cli/clear_cache.py
|
|
11
11
|
src/persistent_cache/main/__init__.py
|
|
12
|
-
src/persistent_cache/main/
|
|
12
|
+
src/persistent_cache/main/cache_slot.py
|
|
13
13
|
src/persistent_cache/main/decorator.py
|
|
14
14
|
src/persistent_cache/main/hashing.py
|
|
15
15
|
src/persistent_cache/models/__init__.py
|
|
16
|
-
src/persistent_cache/models/function.py
|
|
17
16
|
src/persistent_cache/models/path.py
|
|
18
17
|
src/persistent_cache/reducers/__init__.py
|
|
19
18
|
src/persistent_cache/reducers/base.py
|
|
@@ -7,6 +7,7 @@ import cli
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
9
|
from persistent_cache import cache, deep_learning, speedup_deep_learning
|
|
10
|
+
from persistent_cache.reducers import Reducer
|
|
10
11
|
|
|
11
12
|
caches = [cache, deep_learning.cache, speedup_deep_learning.cache]
|
|
12
13
|
|
|
@@ -53,3 +54,44 @@ def test_cache_with_argument_names(cache_decorator: Callable[..., Any]) -> None:
|
|
|
53
54
|
cache_key_arguments=cache_key_arguments,
|
|
54
55
|
)
|
|
55
56
|
cached_function("test")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.mark.parametrize("cache_decorator", caches)
|
|
60
|
+
def test_cache_with_extra_cache_key(
|
|
61
|
+
cache_decorator: Callable[..., Any],
|
|
62
|
+
) -> None:
|
|
63
|
+
cached_function = cache_decorator(calculate_with_name, extra_cache_keys="value")
|
|
64
|
+
cached_function("test")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.mark.parametrize("cache_decorator", caches)
|
|
68
|
+
def test_cache_with_extra_cache_keys(
|
|
69
|
+
cache_decorator: Callable[..., Any],
|
|
70
|
+
) -> None:
|
|
71
|
+
cached_function = cache_decorator(
|
|
72
|
+
calculate_with_name,
|
|
73
|
+
extra_cache_keys=("value",),
|
|
74
|
+
)
|
|
75
|
+
cached_function("test")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.mark.parametrize("cache_decorator", caches)
|
|
79
|
+
def test_cache_with_reducer(
|
|
80
|
+
cache_decorator: Callable[..., Any],
|
|
81
|
+
) -> None:
|
|
82
|
+
cached_function = cache_decorator(
|
|
83
|
+
calculate_with_name,
|
|
84
|
+
key_reducer=Reducer,
|
|
85
|
+
)
|
|
86
|
+
cached_function("test")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@pytest.mark.parametrize("cache_decorator", caches)
|
|
90
|
+
def test_cache_with_argument_reducer(
|
|
91
|
+
cache_decorator: Callable[..., Any],
|
|
92
|
+
) -> None:
|
|
93
|
+
cached_function = cache_decorator(
|
|
94
|
+
calculate_with_name,
|
|
95
|
+
argument_reducers={"value": lambda x: x.strip()},
|
|
96
|
+
)
|
|
97
|
+
cached_function("test")
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import pickle
|
|
2
|
-
from collections.abc import Callable
|
|
3
|
-
from typing import Any, Generic, TypeVar, cast
|
|
4
|
-
|
|
5
|
-
from persistent_cache.models import Path
|
|
6
|
-
from persistent_cache.reducers.base import Reducer
|
|
7
|
-
|
|
8
|
-
from . import hashing
|
|
9
|
-
|
|
10
|
-
T = TypeVar("T")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class CacheSlot(Generic[T]):
|
|
14
|
-
def __init__(
|
|
15
|
-
self,
|
|
16
|
-
function: Callable[..., T],
|
|
17
|
-
args: tuple[Any, ...],
|
|
18
|
-
key_reducer: type[Reducer] = Reducer,
|
|
19
|
-
cache_path: Path = Path.cache,
|
|
20
|
-
) -> None:
|
|
21
|
-
# change cache key when implementation changes
|
|
22
|
-
cache_keys = (function, args)
|
|
23
|
-
self.location = (
|
|
24
|
-
cache_path
|
|
25
|
-
/ function.__module__.replace(".", "_")
|
|
26
|
-
/ function.__name__
|
|
27
|
-
/ hashing.compute_hash(key_reducer, cache_keys)
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def value(self) -> T:
|
|
32
|
-
try:
|
|
33
|
-
with self.location.open("rb") as fp:
|
|
34
|
-
value = pickle.Unpickler(fp).load() # noqa: S301
|
|
35
|
-
except (pickle.UnpicklingError, EOFError):
|
|
36
|
-
# discard values of corrupted or empty slots
|
|
37
|
-
raise KeyError from None
|
|
38
|
-
return cast(T, value)
|
|
39
|
-
|
|
40
|
-
@value.setter
|
|
41
|
-
def value(self, value: T) -> None:
|
|
42
|
-
self.location.byte_content = pickle.dumps(value)
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
from collections.abc import Callable, Iterator
|
|
3
|
-
from functools import wraps
|
|
4
|
-
from typing import Any, cast, overload
|
|
5
|
-
|
|
6
|
-
from persistent_cache.models import F, Path
|
|
7
|
-
from persistent_cache.reducers.base import Reducer
|
|
8
|
-
|
|
9
|
-
from .cacheslot import CacheSlot
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@overload
|
|
13
|
-
def cache(
|
|
14
|
-
function: F,
|
|
15
|
-
*,
|
|
16
|
-
cache_path: Path = Path.cache,
|
|
17
|
-
cache_key_arguments: tuple[str, ...] | str | None = None,
|
|
18
|
-
key_reducer: type[Reducer] = Reducer,
|
|
19
|
-
deep_learning: bool = False,
|
|
20
|
-
speedup_deep_learning: bool = False,
|
|
21
|
-
) -> F: ...
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@overload
|
|
25
|
-
def cache(
|
|
26
|
-
function: None = None,
|
|
27
|
-
*,
|
|
28
|
-
cache_path: Path = Path.cache,
|
|
29
|
-
cache_key_arguments: tuple[str, ...] | str | None = None,
|
|
30
|
-
key_reducer: type[Reducer] = Reducer,
|
|
31
|
-
deep_learning: bool = False,
|
|
32
|
-
speedup_deep_learning: bool = False,
|
|
33
|
-
) -> Callable[[F], F]: ...
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def cache( # noqa: PLR0913
|
|
37
|
-
function: F | None = None,
|
|
38
|
-
*,
|
|
39
|
-
cache_path: Path = Path.cache,
|
|
40
|
-
cache_key_arguments: tuple[str, ...] | str | None = None,
|
|
41
|
-
key_reducer: type[Reducer] | None = None,
|
|
42
|
-
deep_learning: bool = False,
|
|
43
|
-
speedup_deep_learning: bool = False,
|
|
44
|
-
) -> F | Callable[[F], F]:
|
|
45
|
-
"""A decorator to cache function results. Decorated functions are only executed if
|
|
46
|
-
result is not present in cache. The arguments of the function can be any nested
|
|
47
|
-
complex object.
|
|
48
|
-
|
|
49
|
-
Use as:
|
|
50
|
-
|
|
51
|
-
from persistent_cache import cache
|
|
52
|
-
|
|
53
|
-
@cache
|
|
54
|
-
def long_function(complex_object):
|
|
55
|
-
...
|
|
56
|
-
"""
|
|
57
|
-
|
|
58
|
-
reducer = extract_reducer(
|
|
59
|
-
key_reducer,
|
|
60
|
-
deep_learning=deep_learning,
|
|
61
|
-
speedup_deep_learning=speedup_deep_learning,
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
def cache_decorator(function: F) -> F:
|
|
65
|
-
@wraps(function)
|
|
66
|
-
def wrapped_function(*args: Any, **kwargs: Any) -> Any:
|
|
67
|
-
arguments = tuple(
|
|
68
|
-
extract_argument_values(function, args, kwargs, cache_key_arguments),
|
|
69
|
-
)
|
|
70
|
-
cache_slot = CacheSlot(function, arguments, reducer, cache_path)
|
|
71
|
-
try:
|
|
72
|
-
value = cache_slot.value
|
|
73
|
-
except KeyError:
|
|
74
|
-
value = function(*args, **kwargs)
|
|
75
|
-
cache_slot.value = value
|
|
76
|
-
return value
|
|
77
|
-
|
|
78
|
-
return cast(F, wrapped_function)
|
|
79
|
-
|
|
80
|
-
if function is not None:
|
|
81
|
-
cache_decorator = cache_decorator(function)
|
|
82
|
-
return cache_decorator
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def extract_argument_values(
|
|
86
|
-
function: F,
|
|
87
|
-
args: tuple[Any, ...],
|
|
88
|
-
kwargs: dict[str, Any],
|
|
89
|
-
cache_key_arguments: tuple[str, ...] | str | None = None,
|
|
90
|
-
) -> Iterator[Any]:
|
|
91
|
-
if cache_key_arguments is None:
|
|
92
|
-
yield from (args, kwargs)
|
|
93
|
-
else:
|
|
94
|
-
arguments = inspect.signature(function).bind(*args, **kwargs)
|
|
95
|
-
arguments.apply_defaults()
|
|
96
|
-
if isinstance(cache_key_arguments, str):
|
|
97
|
-
yield arguments.arguments.get(cache_key_arguments)
|
|
98
|
-
else:
|
|
99
|
-
for name in cache_key_arguments:
|
|
100
|
-
yield arguments.arguments.get(name)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def extract_reducer(
|
|
104
|
-
reducer: type[Reducer] | None,
|
|
105
|
-
*,
|
|
106
|
-
deep_learning: bool,
|
|
107
|
-
speedup_deep_learning: bool,
|
|
108
|
-
) -> type[Reducer]:
|
|
109
|
-
if reducer is None:
|
|
110
|
-
if deep_learning:
|
|
111
|
-
from persistent_cache.reducers.deep_learning import Reducer as Reducer_
|
|
112
|
-
|
|
113
|
-
reducer = Reducer_
|
|
114
|
-
elif speedup_deep_learning:
|
|
115
|
-
from persistent_cache.reducers.speedup_deep_learning import (
|
|
116
|
-
Reducer as Reducer_,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
reducer = Reducer_
|
|
120
|
-
else:
|
|
121
|
-
reducer = Reducer
|
|
122
|
-
return reducer
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/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
|
|
File without changes
|
{persistent_function_cache-0.2.0 → persistent_function_cache-0.2.2}/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.0 → persistent_function_cache-0.2.2}/tests/test_clear_cache.py
RENAMED
|
File without changes
|
|
File without changes
|