cachify 0.2.1__tar.gz → 0.3.1__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.
- {cachify-0.2.1 → cachify-0.3.1}/PKG-INFO +9 -8
- {cachify-0.2.1 → cachify-0.3.1}/README.md +8 -7
- {cachify-0.2.1 → cachify-0.3.1}/cachify/__init__.py +5 -4
- {cachify-0.2.1 → cachify-0.3.1}/cachify/cache.py +14 -6
- {cachify-0.2.1 → cachify-0.3.1}/cachify/features/never_die.py +3 -3
- {cachify-0.2.1 → cachify-0.3.1}/cachify/memory_cache.py +11 -6
- {cachify-0.2.1 → cachify-0.3.1}/cachify/redis/config.py +15 -10
- {cachify-0.2.1 → cachify-0.3.1}/cachify/redis_cache.py +4 -3
- {cachify-0.2.1 → cachify-0.3.1}/cachify/utils/arguments.py +5 -10
- cachify-0.3.1/cachify/utils/errors.py +2 -0
- cachify-0.3.1/cachify/utils/hash.py +18 -0
- {cachify-0.2.1 → cachify-0.3.1}/pyproject.toml +1 -1
- cachify-0.2.1/cachify/utils/decorator_factory.py +0 -44
- cachify-0.2.1/cachify/utils/locks.py +0 -6
- {cachify-0.2.1 → cachify-0.3.1}/LICENSE +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/config/__init__.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/features/__init__.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/redis/__init__.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/redis/lock.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/storage/__init__.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/storage/memory_storage.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/storage/redis_storage.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/types/__init__.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/utils/__init__.py +0 -0
- {cachify-0.2.1 → cachify-0.3.1}/cachify/utils/functions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachify
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A simple cache library with sync/async support, Memory and Redis backend
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -86,12 +86,13 @@ async def another_calculation(url):
|
|
|
86
86
|
|
|
87
87
|
### Decorator Parameters
|
|
88
88
|
|
|
89
|
-
| Parameter | Type
|
|
90
|
-
| ---------------- |
|
|
91
|
-
| `ttl` | `int \| float`
|
|
92
|
-
| `never_die` | `bool`
|
|
93
|
-
| `cache_key_func` | `Callable`
|
|
94
|
-
| `ignore_fields` | `
|
|
89
|
+
| Parameter | Type | Default | Description |
|
|
90
|
+
| ---------------- | --------------- | ------- | -------------------------------------------------------------- |
|
|
91
|
+
| `ttl` | `int \| float` | `300` | Time to live for cached items in seconds |
|
|
92
|
+
| `never_die` | `bool` | `False` | If True, cache refreshes automatically in background |
|
|
93
|
+
| `cache_key_func` | `Callable` | `None` | Custom function to generate cache keys |
|
|
94
|
+
| `ignore_fields` | `Sequence[str]` | `()` | Function parameters to exclude from cache key |
|
|
95
|
+
| `no_self` | `bool` | `False` | If True, ignores the first parameter (usually `self` or `cls`) |
|
|
95
96
|
|
|
96
97
|
### Custom Cache Key Function
|
|
97
98
|
|
|
@@ -134,7 +135,7 @@ from cachify import setup_redis_config, rcache
|
|
|
134
135
|
# Configure Redis (call once at startup)
|
|
135
136
|
setup_redis_config(
|
|
136
137
|
sync_client=redis.from_url("redis://localhost:6379/0"),
|
|
137
|
-
key_prefix="myapp", # default: "cachify", prefix searchable on redis "PREFIX:*"
|
|
138
|
+
key_prefix="{myapp}", # default: "{cachify}", prefix searchable on redis "PREFIX:*"
|
|
138
139
|
lock_timeout=10, # default: 10, maximum lock lifetime in seconds
|
|
139
140
|
on_error="silent", # "silent" (default) or "raise" in case of redis errors
|
|
140
141
|
)
|
|
@@ -60,12 +60,13 @@ async def another_calculation(url):
|
|
|
60
60
|
|
|
61
61
|
### Decorator Parameters
|
|
62
62
|
|
|
63
|
-
| Parameter | Type
|
|
64
|
-
| ---------------- |
|
|
65
|
-
| `ttl` | `int \| float`
|
|
66
|
-
| `never_die` | `bool`
|
|
67
|
-
| `cache_key_func` | `Callable`
|
|
68
|
-
| `ignore_fields` | `
|
|
63
|
+
| Parameter | Type | Default | Description |
|
|
64
|
+
| ---------------- | --------------- | ------- | -------------------------------------------------------------- |
|
|
65
|
+
| `ttl` | `int \| float` | `300` | Time to live for cached items in seconds |
|
|
66
|
+
| `never_die` | `bool` | `False` | If True, cache refreshes automatically in background |
|
|
67
|
+
| `cache_key_func` | `Callable` | `None` | Custom function to generate cache keys |
|
|
68
|
+
| `ignore_fields` | `Sequence[str]` | `()` | Function parameters to exclude from cache key |
|
|
69
|
+
| `no_self` | `bool` | `False` | If True, ignores the first parameter (usually `self` or `cls`) |
|
|
69
70
|
|
|
70
71
|
### Custom Cache Key Function
|
|
71
72
|
|
|
@@ -108,7 +109,7 @@ from cachify import setup_redis_config, rcache
|
|
|
108
109
|
# Configure Redis (call once at startup)
|
|
109
110
|
setup_redis_config(
|
|
110
111
|
sync_client=redis.from_url("redis://localhost:6379/0"),
|
|
111
|
-
key_prefix="myapp", # default: "cachify", prefix searchable on redis "PREFIX:*"
|
|
112
|
+
key_prefix="{myapp}", # default: "{cachify}", prefix searchable on redis "PREFIX:*"
|
|
112
113
|
lock_timeout=10, # default: 10, maximum lock lifetime in seconds
|
|
113
114
|
on_error="silent", # "silent" (default) or "raise" in case of redis errors
|
|
114
115
|
)
|
|
@@ -12,12 +12,13 @@ rcache = redis_cache
|
|
|
12
12
|
|
|
13
13
|
__all__ = [
|
|
14
14
|
"__version__",
|
|
15
|
-
"cache",
|
|
16
15
|
"rcache",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
16
|
+
"clear_never_die_registry",
|
|
17
|
+
"cache",
|
|
18
|
+
"DEFAULT_KEY_PREFIX",
|
|
19
19
|
"get_redis_config",
|
|
20
20
|
"reset_redis_config",
|
|
21
|
-
"
|
|
21
|
+
"setup_redis_config",
|
|
22
|
+
"redis_cache",
|
|
22
23
|
"CacheKwargs",
|
|
23
24
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import inspect
|
|
3
|
-
from typing import Any, Callable, cast
|
|
3
|
+
from typing import Any, Callable, Sequence, cast
|
|
4
4
|
|
|
5
5
|
from cachify.features.never_die import register_never_die_function
|
|
6
6
|
from cachify.types import CacheConfig, CacheKeyFunction, F, Number
|
|
@@ -73,7 +73,8 @@ def base_cache(
|
|
|
73
73
|
ttl: Number,
|
|
74
74
|
never_die: bool,
|
|
75
75
|
cache_key_func: CacheKeyFunction | None,
|
|
76
|
-
ignore_fields:
|
|
76
|
+
ignore_fields: Sequence[str],
|
|
77
|
+
no_self: bool,
|
|
77
78
|
config: CacheConfig,
|
|
78
79
|
) -> Callable[[F], F]:
|
|
79
80
|
"""
|
|
@@ -83,7 +84,8 @@ def base_cache(
|
|
|
83
84
|
ttl: Time to live for cached items in seconds
|
|
84
85
|
never_die: If True, the cache will never expire and will be recalculated based on the ttl
|
|
85
86
|
cache_key_func: Custom cache key function, used for more complex cache scenarios
|
|
86
|
-
ignore_fields:
|
|
87
|
+
ignore_fields: Sequence of strings with the function params to ignore when creating the cache key
|
|
88
|
+
no_self: if True, the first parameter (typically 'self' for methods) will be ignored when creating the cache key
|
|
87
89
|
config: Cache configuration specifying storage, locks, and never_die registration
|
|
88
90
|
|
|
89
91
|
Features:
|
|
@@ -91,17 +93,23 @@ def base_cache(
|
|
|
91
93
|
- Only allows one execution at a time per function+args
|
|
92
94
|
- Makes subsequent calls wait for the first call to complete
|
|
93
95
|
"""
|
|
94
|
-
|
|
96
|
+
|
|
97
|
+
if cache_key_func and (ignore_fields or no_self):
|
|
95
98
|
raise ValueError("Either cache_key_func or ignore_fields can be provided, but not both")
|
|
96
99
|
|
|
97
100
|
def decorator(function: F) -> F:
|
|
101
|
+
ignore = tuple(ignore_fields)
|
|
102
|
+
|
|
103
|
+
if no_self:
|
|
104
|
+
ignore += function.__code__.co_varnames[:1]
|
|
105
|
+
|
|
98
106
|
if inspect.iscoroutinefunction(function):
|
|
99
107
|
return _async_decorator(
|
|
100
108
|
function=function,
|
|
101
109
|
ttl=ttl,
|
|
102
110
|
never_die=never_die,
|
|
103
111
|
cache_key_func=cache_key_func,
|
|
104
|
-
ignore_fields=
|
|
112
|
+
ignore_fields=ignore,
|
|
105
113
|
config=config,
|
|
106
114
|
)
|
|
107
115
|
return _sync_decorator(
|
|
@@ -109,7 +117,7 @@ def base_cache(
|
|
|
109
117
|
ttl=ttl,
|
|
110
118
|
never_die=never_die,
|
|
111
119
|
cache_key_func=cache_key_func,
|
|
112
|
-
ignore_fields=
|
|
120
|
+
ignore_fields=ignore,
|
|
113
121
|
config=config,
|
|
114
122
|
)
|
|
115
123
|
|
|
@@ -140,19 +140,19 @@ def _refresh_never_die_caches():
|
|
|
140
140
|
|
|
141
141
|
if entry.loop.is_closed():
|
|
142
142
|
logger.debug(
|
|
143
|
-
|
|
143
|
+
"Loop is closed, skipping future creation",
|
|
144
144
|
extra={"function": entry.function.__qualname__},
|
|
145
145
|
exc_info=True,
|
|
146
146
|
)
|
|
147
147
|
continue
|
|
148
148
|
|
|
149
|
+
coroutine = _run_async_function_and_cache(entry)
|
|
149
150
|
try:
|
|
150
|
-
coroutine = _run_async_function_and_cache(entry)
|
|
151
151
|
future = asyncio.run_coroutine_threadsafe(coroutine, entry.loop)
|
|
152
152
|
except RuntimeError:
|
|
153
153
|
coroutine.close()
|
|
154
154
|
logger.debug(
|
|
155
|
-
|
|
155
|
+
"Loop is closed, skipping future creation",
|
|
156
156
|
extra={"function": entry.function.__qualname__},
|
|
157
157
|
exc_info=True,
|
|
158
158
|
)
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import threading
|
|
2
|
-
from
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from typing import Callable, Sequence
|
|
3
5
|
|
|
4
6
|
from cachify.cache import base_cache
|
|
5
7
|
from cachify.storage.memory_storage import MemoryStorage
|
|
6
8
|
from cachify.types import CacheConfig, CacheKeyFunction, F, Number
|
|
7
|
-
from cachify.utils.locks import ASYNC_LOCKS, SYNC_LOCKS
|
|
8
9
|
|
|
9
10
|
_CACHE_CLEAR_THREAD: threading.Thread | None = None
|
|
10
11
|
_CACHE_CLEAR_LOCK: threading.Lock = threading.Lock()
|
|
11
12
|
|
|
13
|
+
_ASYNC_LOCKS: defaultdict[str, asyncio.Lock] = defaultdict(asyncio.Lock)
|
|
14
|
+
_SYNC_LOCKS: defaultdict[str, threading.Lock] = defaultdict(threading.Lock)
|
|
15
|
+
|
|
12
16
|
_MEMORY_CONFIG = CacheConfig(
|
|
13
17
|
storage=MemoryStorage,
|
|
14
|
-
sync_lock=
|
|
15
|
-
async_lock=
|
|
18
|
+
sync_lock=_SYNC_LOCKS.__getitem__,
|
|
19
|
+
async_lock=_ASYNC_LOCKS.__getitem__,
|
|
16
20
|
)
|
|
17
21
|
|
|
18
22
|
|
|
@@ -30,8 +34,9 @@ def cache(
|
|
|
30
34
|
ttl: Number = 300,
|
|
31
35
|
never_die: bool = False,
|
|
32
36
|
cache_key_func: CacheKeyFunction | None = None,
|
|
33
|
-
ignore_fields:
|
|
37
|
+
ignore_fields: Sequence[str] = (),
|
|
38
|
+
no_self: bool = False,
|
|
34
39
|
) -> Callable[[F], F]:
|
|
35
40
|
"""In-memory cache decorator. See `base_cache` for full documentation."""
|
|
36
41
|
_start_cache_clear_thread()
|
|
37
|
-
return base_cache(ttl, never_die, cache_key_func, ignore_fields, _MEMORY_CONFIG)
|
|
42
|
+
return base_cache(ttl, never_die, cache_key_func, ignore_fields, no_self, _MEMORY_CONFIG)
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import TYPE_CHECKING, Literal, get_args, overload
|
|
4
|
+
from typing import TYPE_CHECKING, Literal, TypeAlias, get_args, overload
|
|
5
5
|
|
|
6
6
|
if TYPE_CHECKING:
|
|
7
7
|
from redis import Redis
|
|
8
8
|
from redis.asyncio import Redis as AsyncRedis
|
|
9
|
+
from redis.cluster import RedisCluster
|
|
10
|
+
from redis.asyncio.cluster import RedisCluster as AsyncRedisCluster
|
|
11
|
+
|
|
12
|
+
SyncRedisClient: TypeAlias = "Redis | RedisCluster"
|
|
13
|
+
AsyncRedisClient: TypeAlias = "AsyncRedis | AsyncRedisCluster"
|
|
9
14
|
|
|
10
15
|
OnErrorType = Literal["silent", "raise"]
|
|
11
16
|
|
|
12
|
-
DEFAULT_KEY_PREFIX = "cachify"
|
|
17
|
+
DEFAULT_KEY_PREFIX = "{cachify}"
|
|
13
18
|
DEFAULT_LOCK_TIMEOUT = 10
|
|
14
19
|
|
|
15
20
|
|
|
@@ -17,19 +22,19 @@ DEFAULT_LOCK_TIMEOUT = 10
|
|
|
17
22
|
class RedisConfig:
|
|
18
23
|
"""Configuration for Redis cache backend."""
|
|
19
24
|
|
|
20
|
-
sync_client:
|
|
21
|
-
async_client:
|
|
25
|
+
sync_client: SyncRedisClient | None
|
|
26
|
+
async_client: AsyncRedisClient | None
|
|
22
27
|
key_prefix: str
|
|
23
28
|
lock_timeout: int
|
|
24
29
|
on_error: OnErrorType
|
|
25
30
|
|
|
26
31
|
@overload
|
|
27
|
-
def get_client(self, is_async: Literal[True]) ->
|
|
32
|
+
def get_client(self, is_async: Literal[True]) -> AsyncRedisClient: ...
|
|
28
33
|
|
|
29
34
|
@overload
|
|
30
|
-
def get_client(self, is_async: Literal[False]) ->
|
|
35
|
+
def get_client(self, is_async: Literal[False]) -> SyncRedisClient: ...
|
|
31
36
|
|
|
32
|
-
def get_client(self, is_async: bool) ->
|
|
37
|
+
def get_client(self, is_async: bool) -> SyncRedisClient | AsyncRedisClient:
|
|
33
38
|
"""Get the appropriate Redis client based on is_async flag."""
|
|
34
39
|
if is_async:
|
|
35
40
|
client = self.async_client
|
|
@@ -49,8 +54,8 @@ _redis_config: RedisConfig | None = None
|
|
|
49
54
|
|
|
50
55
|
|
|
51
56
|
def setup_redis_config(
|
|
52
|
-
sync_client:
|
|
53
|
-
async_client:
|
|
57
|
+
sync_client: SyncRedisClient | None = None,
|
|
58
|
+
async_client: AsyncRedisClient | None = None,
|
|
54
59
|
key_prefix: str = DEFAULT_KEY_PREFIX,
|
|
55
60
|
lock_timeout: int = DEFAULT_LOCK_TIMEOUT,
|
|
56
61
|
on_error: OnErrorType = "silent",
|
|
@@ -64,7 +69,7 @@ def setup_redis_config(
|
|
|
64
69
|
Args:
|
|
65
70
|
sync_client: Redis sync client instance (redis.Redis)
|
|
66
71
|
async_client: Redis async client instance (redis.asyncio.Redis)
|
|
67
|
-
key_prefix: Prefix for all cache keys in Redis (default: "
|
|
72
|
+
key_prefix: Prefix for all cache keys in Redis (default: "{cachify}")
|
|
68
73
|
lock_timeout: Timeout in seconds for distributed locks (default: 10)
|
|
69
74
|
on_error: Error handling mode - "silent" treats errors as cache miss,
|
|
70
75
|
"raise" propagates exceptions (default: "silent")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Callable
|
|
1
|
+
from typing import Callable, Sequence
|
|
2
2
|
|
|
3
3
|
from cachify.cache import base_cache
|
|
4
4
|
from cachify.redis.lock import RedisLockManager
|
|
@@ -16,7 +16,8 @@ def redis_cache(
|
|
|
16
16
|
ttl: Number = 300,
|
|
17
17
|
never_die: bool = False,
|
|
18
18
|
cache_key_func: CacheKeyFunction | None = None,
|
|
19
|
-
ignore_fields:
|
|
19
|
+
ignore_fields: Sequence[str] = (),
|
|
20
|
+
no_self: bool = False,
|
|
20
21
|
) -> Callable[[F], F]:
|
|
21
22
|
"""
|
|
22
23
|
Redis cache decorator. See `base_cache` for full documentation.
|
|
@@ -24,4 +25,4 @@ def redis_cache(
|
|
|
24
25
|
Requires setup_redis_config() to be called before use.
|
|
25
26
|
Uses Redis for distributed caching across multiple processes/machines.
|
|
26
27
|
"""
|
|
27
|
-
return base_cache(ttl, never_die, cache_key_func, ignore_fields, _REDIS_CONFIG)
|
|
28
|
+
return base_cache(ttl, never_die, cache_key_func, ignore_fields, no_self, _REDIS_CONFIG)
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import hashlib
|
|
2
1
|
import inspect
|
|
3
|
-
import pickle
|
|
4
2
|
from collections.abc import Callable, Generator
|
|
5
3
|
from inspect import Signature
|
|
6
4
|
from typing import Any
|
|
7
5
|
|
|
8
6
|
from cachify.types import CacheKeyFunction
|
|
7
|
+
from cachify.utils.errors import CacheKeyError
|
|
9
8
|
from cachify.utils.functions import get_function_id
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def _cache_key_fingerprint(value: object) -> str:
|
|
13
|
-
payload = pickle.dumps(value, protocol=pickle.HIGHEST_PROTOCOL)
|
|
14
|
-
return hashlib.blake2b(payload, digest_size=16).hexdigest()
|
|
9
|
+
from cachify.utils.hash import object_hash
|
|
15
10
|
|
|
16
11
|
|
|
17
12
|
def _iter_arguments(
|
|
@@ -54,12 +49,12 @@ def create_cache_key(
|
|
|
54
49
|
if not cache_key_func:
|
|
55
50
|
function_signature = inspect.signature(function)
|
|
56
51
|
items = tuple(_iter_arguments(function_signature, args, kwargs, ignore_fields))
|
|
57
|
-
return f"{function_id}:{
|
|
52
|
+
return f"{function_id}:{object_hash(items)}"
|
|
58
53
|
|
|
59
54
|
cache_key = cache_key_func(args, kwargs)
|
|
60
55
|
try:
|
|
61
|
-
return f"{function_id}:{
|
|
56
|
+
return f"{function_id}:{object_hash(cache_key)}"
|
|
62
57
|
except TypeError as exc:
|
|
63
|
-
raise
|
|
58
|
+
raise CacheKeyError(
|
|
64
59
|
"Cache key function must return a hashable cache key - be careful with mutable types (list, dict, set) and non built-in types"
|
|
65
60
|
) from exc
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import pickle
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from cachify.utils.errors import CacheKeyError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def object_hash(value: Any) -> str:
|
|
9
|
+
try:
|
|
10
|
+
payload = pickle.dumps(value, protocol=pickle.HIGHEST_PROTOCOL)
|
|
11
|
+
|
|
12
|
+
except Exception as exc:
|
|
13
|
+
raise CacheKeyError(
|
|
14
|
+
"Unable to serialize object for hashing - ensure all parts of the object are pickleable. "
|
|
15
|
+
"Hint: create a custom __reduce__ method for the suspected object if necessary."
|
|
16
|
+
) from exc
|
|
17
|
+
|
|
18
|
+
return hashlib.blake2b(payload, digest_size=16).hexdigest()
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import inspect
|
|
2
|
-
from typing import Callable
|
|
3
|
-
|
|
4
|
-
from cachify._async import async_decorator
|
|
5
|
-
from cachify._sync import sync_decorator
|
|
6
|
-
from cachify.types import CacheConfig, CacheKeyFunction, F, Number
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def create_cache_decorator(
|
|
10
|
-
ttl: Number,
|
|
11
|
-
never_die: bool,
|
|
12
|
-
cache_key_func: CacheKeyFunction | None,
|
|
13
|
-
ignore_fields: tuple[str, ...],
|
|
14
|
-
config: CacheConfig,
|
|
15
|
-
) -> Callable[[F], F]:
|
|
16
|
-
"""
|
|
17
|
-
Create a cache decorator with the given configuration.
|
|
18
|
-
|
|
19
|
-
This is a shared factory used by both memory_cache and redis_cache
|
|
20
|
-
to avoid code duplication.
|
|
21
|
-
"""
|
|
22
|
-
if cache_key_func and ignore_fields:
|
|
23
|
-
raise ValueError("Either cache_key_func or ignore_fields can be provided, but not both")
|
|
24
|
-
|
|
25
|
-
def decorator(function: F) -> F:
|
|
26
|
-
if inspect.iscoroutinefunction(function):
|
|
27
|
-
return async_decorator(
|
|
28
|
-
function=function,
|
|
29
|
-
ttl=ttl,
|
|
30
|
-
never_die=never_die,
|
|
31
|
-
cache_key_func=cache_key_func,
|
|
32
|
-
ignore_fields=ignore_fields,
|
|
33
|
-
config=config,
|
|
34
|
-
)
|
|
35
|
-
return sync_decorator(
|
|
36
|
-
function=function,
|
|
37
|
-
ttl=ttl,
|
|
38
|
-
never_die=never_die,
|
|
39
|
-
cache_key_func=cache_key_func,
|
|
40
|
-
ignore_fields=ignore_fields,
|
|
41
|
-
config=config,
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
return decorator
|
|
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
|
|
File without changes
|
|
File without changes
|