cachier 2.0.2__py2.py3-none-any.whl → 2.1.0__py2.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.
- cachier/_version.py +2 -2
- cachier/base_core.py +20 -9
- cachier/core.py +27 -11
- cachier/memory_core.py +2 -2
- cachier/mongo_core.py +2 -4
- cachier/pickle_core.py +3 -7
- {cachier-2.0.2.dist-info → cachier-2.1.0.dist-info}/METADATA +53 -7
- cachier-2.1.0.dist-info/RECORD +15 -0
- cachier-2.0.2.dist-info/RECORD +0 -15
- {cachier-2.0.2.dist-info → cachier-2.1.0.dist-info}/LICENSE +0 -0
- {cachier-2.0.2.dist-info → cachier-2.1.0.dist-info}/WHEEL +0 -0
- {cachier-2.0.2.dist-info → cachier-2.1.0.dist-info}/entry_points.txt +0 -0
- {cachier-2.0.2.dist-info → cachier-2.1.0.dist-info}/top_level.txt +0 -0
cachier/_version.py
CHANGED
@@ -11,8 +11,8 @@ version_json = '''
|
|
11
11
|
{
|
12
12
|
"dirty": false,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "2.0
|
14
|
+
"full-revisionid": "7be769b78acf3a0e0aff8d528476913571d79749",
|
15
|
+
"version": "2.1.0"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
cachier/base_core.py
CHANGED
@@ -9,26 +9,31 @@
|
|
9
9
|
import abc # for the _BaseCore abstract base class
|
10
10
|
import functools
|
11
11
|
import hashlib
|
12
|
+
import inspect
|
13
|
+
import pickle # nosec: B403
|
12
14
|
|
13
15
|
|
14
|
-
def
|
16
|
+
def _default_hash_func(args, kwds):
|
15
17
|
# pylint: disable-next=protected-access
|
16
|
-
key = functools._make_key(args, kwds, typed=
|
17
|
-
|
18
|
+
key = functools._make_key(args, kwds, typed=True)
|
19
|
+
hash = hashlib.sha256()
|
20
|
+
for item in key:
|
21
|
+
hash.update(pickle.dumps(item))
|
22
|
+
return hash.hexdigest()
|
18
23
|
|
19
24
|
|
20
25
|
class _BaseCore():
|
21
26
|
__metaclass__ = abc.ABCMeta
|
22
27
|
|
23
|
-
def __init__(self,
|
24
|
-
self.
|
25
|
-
self.next_time = next_time
|
26
|
-
self.hash_func = hash_params if hash_params else _default_hash_params
|
28
|
+
def __init__(self, hash_func):
|
29
|
+
self.hash_func = hash_func if hash_func else _default_hash_func
|
27
30
|
self.func = None
|
28
31
|
|
29
32
|
def set_func(self, func):
|
30
|
-
"""Sets the function this core will use. This has to be set before
|
31
|
-
|
33
|
+
"""Sets the function this core will use. This has to be set before any
|
34
|
+
method is called. Also determine if the funtion is an object method."""
|
35
|
+
func_params = list(inspect.signature(func).parameters)
|
36
|
+
self.func_is_method = func_params and func_params[0] == 'self'
|
32
37
|
self.func = func
|
33
38
|
|
34
39
|
def get_entry(self, args, kwds):
|
@@ -37,6 +42,12 @@ class _BaseCore():
|
|
37
42
|
key = self.hash_func(args, kwds)
|
38
43
|
return self.get_entry_by_key(key)
|
39
44
|
|
45
|
+
def precache_value(self, args, kwds, value_to_cache):
|
46
|
+
"""Writes a precomputed value into the cache."""
|
47
|
+
key = self.hash_func(args, kwds)
|
48
|
+
self.set_entry(key, value_to_cache)
|
49
|
+
return value_to_cache
|
50
|
+
|
40
51
|
@abc.abstractmethod
|
41
52
|
def get_entry_by_key(self, key):
|
42
53
|
"""Returns the result mapped to the given key in this core's cache,
|
cachier/core.py
CHANGED
@@ -14,6 +14,7 @@ from __future__ import print_function
|
|
14
14
|
|
15
15
|
import os
|
16
16
|
from functools import wraps
|
17
|
+
from warnings import warn
|
17
18
|
|
18
19
|
import datetime
|
19
20
|
from concurrent.futures import ThreadPoolExecutor
|
@@ -85,6 +86,7 @@ def cachier(
|
|
85
86
|
backend=None,
|
86
87
|
mongetter=None,
|
87
88
|
cache_dir=None,
|
89
|
+
hash_func=None,
|
88
90
|
hash_params=None,
|
89
91
|
wait_for_calc_timeout=0,
|
90
92
|
separate_files=False,
|
@@ -125,7 +127,7 @@ def cachier(
|
|
125
127
|
A fully qualified path to a file directory to be used for cache files.
|
126
128
|
The running process must have running permissions to this folder. If
|
127
129
|
not provided, a default directory at `~/.cachier/` is used.
|
128
|
-
|
130
|
+
hash_func : callable, optional
|
129
131
|
A callable that gets the args and kwargs from the decorated function
|
130
132
|
and returns a hash key for them. This parameter can be used to enable
|
131
133
|
the use of cachier with functions that get arguments that are not
|
@@ -141,15 +143,19 @@ def cachier(
|
|
141
143
|
split between several files, one for each argument set. This can help
|
142
144
|
if you per-function cache files become too large.
|
143
145
|
"""
|
146
|
+
# Check for deprecated parameters
|
147
|
+
if hash_params is not None:
|
148
|
+
message = 'hash_params will be removed in a future release, ' \
|
149
|
+
'please use hash_func instead'
|
150
|
+
warn(message, DeprecationWarning, stacklevel=2)
|
151
|
+
hash_func = hash_params
|
144
152
|
# The default is calculated dynamically to maintain previous behavior
|
145
153
|
# to default to pickle unless the ``mongetter`` argument is given.
|
146
154
|
if backend is None:
|
147
155
|
backend = 'pickle' if mongetter is None else 'mongo'
|
148
156
|
if backend == 'pickle':
|
149
157
|
core = _PickleCore( # pylint: disable=R0204
|
150
|
-
|
151
|
-
next_time=next_time,
|
152
|
-
hash_params=hash_params,
|
158
|
+
hash_func=hash_func,
|
153
159
|
reload=pickle_reload,
|
154
160
|
cache_dir=cache_dir,
|
155
161
|
separate_files=separate_files,
|
@@ -161,16 +167,12 @@ def cachier(
|
|
161
167
|
'must specify ``mongetter`` when using the mongo core')
|
162
168
|
core = _MongoCore(
|
163
169
|
mongetter=mongetter,
|
164
|
-
|
165
|
-
next_time=next_time,
|
166
|
-
hash_params=hash_params,
|
170
|
+
hash_func=hash_func,
|
167
171
|
wait_for_calc_timeout=wait_for_calc_timeout,
|
168
172
|
)
|
169
173
|
elif backend == 'memory':
|
170
174
|
core = _MemoryCore(
|
171
|
-
|
172
|
-
next_time=next_time,
|
173
|
-
hash_params=hash_params,
|
175
|
+
hash_func=hash_func,
|
174
176
|
)
|
175
177
|
elif backend == 'redis':
|
176
178
|
raise NotImplementedError(
|
@@ -194,7 +196,10 @@ def cachier(
|
|
194
196
|
_print = print
|
195
197
|
if ignore_cache:
|
196
198
|
return func(*args, **kwds)
|
197
|
-
|
199
|
+
if core.func_is_method:
|
200
|
+
key, entry = core.get_entry(args[1:], kwds)
|
201
|
+
else:
|
202
|
+
key, entry = core.get_entry(args, kwds)
|
198
203
|
if overwrite_cache:
|
199
204
|
return _calc_entry(core, key, func, args, kwds)
|
200
205
|
if entry is not None: # pylint: disable=R0101
|
@@ -259,9 +264,20 @@ def cachier(
|
|
259
264
|
except AttributeError:
|
260
265
|
return None
|
261
266
|
|
267
|
+
def precache_value(*args, value_to_cache, **kwds):
|
268
|
+
"""Add an initial value to the cache.
|
269
|
+
|
270
|
+
Arguments
|
271
|
+
---------
|
272
|
+
value : any
|
273
|
+
entry to be written into the cache
|
274
|
+
"""
|
275
|
+
return core.precache_value(args, kwds, value_to_cache)
|
276
|
+
|
262
277
|
func_wrapper.clear_cache = clear_cache
|
263
278
|
func_wrapper.clear_being_calculated = clear_being_calculated
|
264
279
|
func_wrapper.cache_dpath = cache_dpath
|
280
|
+
func_wrapper.precache_value = precache_value
|
265
281
|
return func_wrapper
|
266
282
|
|
267
283
|
return _cachier_decorator
|
cachier/memory_core.py
CHANGED
@@ -17,8 +17,8 @@ class _MemoryCore(_BaseCore):
|
|
17
17
|
See :class:`_BaseCore` documentation.
|
18
18
|
"""
|
19
19
|
|
20
|
-
def __init__(self,
|
21
|
-
super().__init__(
|
20
|
+
def __init__(self, hash_func):
|
21
|
+
super().__init__(hash_func)
|
22
22
|
self.cache = {}
|
23
23
|
self.lock = threading.RLock()
|
24
24
|
|
cachier/mongo_core.py
CHANGED
@@ -37,14 +37,12 @@ class _MongoCore(_BaseCore):
|
|
37
37
|
|
38
38
|
_INDEX_NAME = 'func_1_key_1'
|
39
39
|
|
40
|
-
def __init__(
|
41
|
-
self, mongetter, stale_after, next_time,
|
42
|
-
hash_params, wait_for_calc_timeout):
|
40
|
+
def __init__(self, mongetter, hash_func, wait_for_calc_timeout):
|
43
41
|
if 'pymongo' not in sys.modules:
|
44
42
|
warnings.warn((
|
45
43
|
"Cachier warning: pymongo was not found. "
|
46
44
|
"MongoDB cores will not function."))
|
47
|
-
super().__init__(
|
45
|
+
super().__init__(hash_func)
|
48
46
|
self.mongetter = mongetter
|
49
47
|
self.mongo_collection = self.mongetter()
|
50
48
|
self.wait_for_calc_timeout = wait_for_calc_timeout
|
cachier/pickle_core.py
CHANGED
@@ -29,10 +29,6 @@ class _PickleCore(_BaseCore):
|
|
29
29
|
|
30
30
|
Parameters
|
31
31
|
----------
|
32
|
-
stale_after : datetime.timedelta, optional
|
33
|
-
See _BaseCore documentation.
|
34
|
-
next_time : bool, optional
|
35
|
-
See _BaseCore documentation.
|
36
32
|
pickle_reload : bool, optional
|
37
33
|
See core.cachier() documentation.
|
38
34
|
cache_dir : str, optional.
|
@@ -84,10 +80,10 @@ class _PickleCore(_BaseCore):
|
|
84
80
|
self._check_calculation()
|
85
81
|
|
86
82
|
def __init__(
|
87
|
-
self,
|
88
|
-
|
83
|
+
self, hash_func, reload, cache_dir,
|
84
|
+
separate_files, wait_for_calc_timeout,
|
89
85
|
):
|
90
|
-
super().__init__(
|
86
|
+
super().__init__(hash_func)
|
91
87
|
self.cache = None
|
92
88
|
self.reload = reload
|
93
89
|
self.cache_dir = DEF_CACHIER_DIR
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: cachier
|
3
|
-
Version: 2.0
|
3
|
+
Version: 2.1.0
|
4
4
|
Summary: Persistent, stale-free, local and cross-machine caching for Python functions.
|
5
5
|
Home-page: https://github.com/python-cachier/cachier
|
6
6
|
Author: Shay Palachy
|
@@ -128,6 +128,33 @@ You can add a default, pickle-based, persistent cache to your function - meaning
|
|
128
128
|
"""Your function now has a persistent cache mapped by argument values!"""
|
129
129
|
return {'arg1': arg1, 'arg2': arg2}
|
130
130
|
|
131
|
+
Class and object methods can also be cached. Cachier will automatically ignore the `self` parameter when determining the cache key for an object method. **This means that methods will be cached across all instances of an object, which may not be what you want.**
|
132
|
+
|
133
|
+
.. code-block:: python
|
134
|
+
|
135
|
+
from cachier import cachier
|
136
|
+
|
137
|
+
class Foo():
|
138
|
+
@staticmethod
|
139
|
+
@cachier()
|
140
|
+
def good_static_usage(arg_1, arg_2):
|
141
|
+
return arg_1 + arg_2
|
142
|
+
|
143
|
+
# Instance method does not depend on object's internal state, so good to cache
|
144
|
+
@cachier()
|
145
|
+
def good_usage_1(self, arg_1, arg_2)
|
146
|
+
return arg_1 + arg_2
|
147
|
+
|
148
|
+
# Instance method is calling external service, probably okay to cache
|
149
|
+
@cachier()
|
150
|
+
def good_usage_2(self, arg_1, arg_2)
|
151
|
+
result = self.call_api(arg_1, arg_2)
|
152
|
+
return result
|
153
|
+
|
154
|
+
# Instance method relies on object attribute, NOT good to cache
|
155
|
+
@cachier()
|
156
|
+
def bad_usage(self, arg_1, arg_2)
|
157
|
+
return arg_1 + arg_2 + self.arg_3
|
131
158
|
|
132
159
|
|
133
160
|
Resetting a Cache
|
@@ -138,7 +165,7 @@ The Cachier wrapper adds a ``clear_cache()`` function to each wrapped function.
|
|
138
165
|
|
139
166
|
foo.clear_cache()
|
140
167
|
|
141
|
-
|
168
|
+
General Configuration
|
142
169
|
----------------------
|
143
170
|
|
144
171
|
Threads Limit
|
@@ -180,11 +207,15 @@ Further function calls made while the calculation is being performed will not tr
|
|
180
207
|
Working with unhashable arguments
|
181
208
|
---------------------------------
|
182
209
|
|
183
|
-
As mentioned above, the positional and keyword arguments to the wrapped function must be hashable (i.e. Python's immutable built-in objects, not mutable containers). To get around this limitation the ``
|
210
|
+
As mentioned above, the positional and keyword arguments to the wrapped function must be hashable (i.e. Python's immutable built-in objects, not mutable containers). To get around this limitation the ``hash_func`` parameter of the ``cachier`` decorator can be provided with a callable that gets the args and kwargs from the decorated function and returns a hash key for them.
|
184
211
|
|
185
212
|
.. code-block:: python
|
186
213
|
|
187
|
-
|
214
|
+
def calculate_hash(args, kwds):
|
215
|
+
key = ... # compute a hash key here based on arguments
|
216
|
+
return key
|
217
|
+
|
218
|
+
@cachier(hash_func=calculate_hash)
|
188
219
|
def calculate_super_complex_stuff(custom_obj):
|
189
220
|
# amazing code goes here
|
190
221
|
|
@@ -193,6 +224,23 @@ See here for an example:
|
|
193
224
|
`Question: How to work with unhashable arguments <https://github.com/python-cachier/cachier/issues/91>`_
|
194
225
|
|
195
226
|
|
227
|
+
Precaching values
|
228
|
+
---------------------------------
|
229
|
+
|
230
|
+
If you want to load a value into the cache without calling the underlying function, this can be done with the `precache_value` function.
|
231
|
+
|
232
|
+
.. code-block:: python
|
233
|
+
|
234
|
+
@cachier()
|
235
|
+
def add(arg1, arg2):
|
236
|
+
return arg1 + arg2
|
237
|
+
|
238
|
+
add.precache_value(2, 2, value_to_cache=5)
|
239
|
+
|
240
|
+
result = add(2, 2)
|
241
|
+
print(result) # prints 5
|
242
|
+
|
243
|
+
|
196
244
|
Per-function call arguments
|
197
245
|
---------------------------
|
198
246
|
|
@@ -382,7 +430,7 @@ Other major contributors:
|
|
382
430
|
|
383
431
|
* `cthoyt <https://github.com/cthoyt>`_ - Base memory core implementation.
|
384
432
|
|
385
|
-
* `amarczew <https://github.com/amarczew>`_ - The ``
|
433
|
+
* `amarczew <https://github.com/amarczew>`_ - The ``hash_func`` kwarg.
|
386
434
|
|
387
435
|
* `non-senses <https://github.com/non-senses>`_ - The ``wait_for_calc_timeout`` kwarg.
|
388
436
|
|
@@ -428,5 +476,3 @@ Notable bugfixers:
|
|
428
476
|
.. _watchdog: https://github.com/gorakhargosh/watchdog
|
429
477
|
|
430
478
|
|
431
|
-
|
432
|
-
|
@@ -0,0 +1,15 @@
|
|
1
|
+
cachier/__init__.py,sha256=znE73J-Sg_4tjDmfKaJ5Cabg_kWhus9yhq1LJmM8B6Q,133
|
2
|
+
cachier/_version.py,sha256=Gk55atXZn9Zmgvi_28RCi_UXaHw85U1VAatxQ7cEXK0,471
|
3
|
+
cachier/base_core.py,sha256=3TJOmzCwtoGAGsMj-4zo91C6eP69cSB-40Lru3MFgBg,2663
|
4
|
+
cachier/core.py,sha256=L0dWlbERd-8RiGPP3Iw1sbNzgclO7wSSflS4QbkaQmY,11454
|
5
|
+
cachier/memory_core.py,sha256=do4aKTxcNaoaCpLx6w2bhhLIAze8tEo9gPNAekwWrHo,3020
|
6
|
+
cachier/mongo_core.py,sha256=Tbe-fpWyvlYK_WQq02-K2WDGqtoz90rwcTS_DFT146I,5114
|
7
|
+
cachier/pickle_core.py,sha256=4-sji-yQNfTvutpxHBHzZbourHyby_7ykGQFLf8dC58,10150
|
8
|
+
cachier/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
cachier/scripts/cli.py,sha256=tMwq1IaD_lxhcc8WMgWh4P0gpi5l6-twCS2YeAKAM98,429
|
10
|
+
cachier-2.1.0.dist-info/LICENSE,sha256=-2WrMJkIa0gVP6YQHXXDT7ws-S3M2NEVEF4XF3K8qrY,1069
|
11
|
+
cachier-2.1.0.dist-info/METADATA,sha256=ysQu-4vNtUdDT2wQjGAsrgfzZNOWaEWKPKdTinfOM_8,16470
|
12
|
+
cachier-2.1.0.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
|
13
|
+
cachier-2.1.0.dist-info/entry_points.txt,sha256=HZPL3TEoT-aieCOvQvsLEDBAuPBSbDNrIjMiDA8h6zE,71
|
14
|
+
cachier-2.1.0.dist-info/top_level.txt,sha256=_rW_HiJumDCch67YT-WAgzcyvKg5RiYDMZq9d-0ZpaE,8
|
15
|
+
cachier-2.1.0.dist-info/RECORD,,
|
cachier-2.0.2.dist-info/RECORD
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
cachier/__init__.py,sha256=znE73J-Sg_4tjDmfKaJ5Cabg_kWhus9yhq1LJmM8B6Q,133
|
2
|
-
cachier/_version.py,sha256=_r_v0NgI9oOYWtcdA8kJvbdmbzJ6jVUStmVJ8q6JQNA,471
|
3
|
-
cachier/base_core.py,sha256=gS2BrCv87Xr6lVzaXPAqtgYHNJGUYMjWIelp7eXblow,2257
|
4
|
-
cachier/core.py,sha256=h3dCDlBdUYSsJ2AOUVl-IbNjE6H5NH9y-nlzlxXWYoI,10869
|
5
|
-
cachier/memory_core.py,sha256=5PGm1avW_nHlctvJrYWlerLWgttKpP69epOt2e5r1O0,3072
|
6
|
-
cachier/mongo_core.py,sha256=-YOjOOMVCu1bVb26nge2b4vatxFwafAyA52RKzhL9xc,5191
|
7
|
-
cachier/pickle_core.py,sha256=b7QtVjuRvcUnC2ecabMmH7Zu8JYXF251cWWTFv4Iv48,10354
|
8
|
-
cachier/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
cachier/scripts/cli.py,sha256=tMwq1IaD_lxhcc8WMgWh4P0gpi5l6-twCS2YeAKAM98,429
|
10
|
-
cachier-2.0.2.dist-info/LICENSE,sha256=-2WrMJkIa0gVP6YQHXXDT7ws-S3M2NEVEF4XF3K8qrY,1069
|
11
|
-
cachier-2.0.2.dist-info/METADATA,sha256=KyH95H8-1mKmsgc1VaykLYGOIQpZQX-4OoCFQrNC72s,15045
|
12
|
-
cachier-2.0.2.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
|
13
|
-
cachier-2.0.2.dist-info/entry_points.txt,sha256=HZPL3TEoT-aieCOvQvsLEDBAuPBSbDNrIjMiDA8h6zE,71
|
14
|
-
cachier-2.0.2.dist-info/top_level.txt,sha256=_rW_HiJumDCch67YT-WAgzcyvKg5RiYDMZq9d-0ZpaE,8
|
15
|
-
cachier-2.0.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|