cardinal_pythonlib.dogpile_cache
Original code copyright (C) 2009-2022 Rudolf Cardinal (rudolf@pobox.com).
This file is part of cardinal_pythonlib.
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Extensions to dogpile.cache.
The basic cache objects.
FIX FOR DOGPILE.CACHE FOR DECORATED FUNCTIONS, 2017-07-28 (PLUS SOME OTHER IMPROVEMENTS). SEE
This fixes a crash using type-hinted functions under Python 3.5 with
dogpile.cache==0.6.4
:Traceback (most recent call last): File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main "__main__", mod_spec) File "/usr/lib/python3.5/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/rudolf/Documents/code/camcops/server/camcops_server/cc_modules/cc_cache.py", line 64, in <module> unit_test_cache() File "/home/rudolf/Documents/code/camcops/server/camcops_server/cc_modules/cc_cache.py", line 50, in unit_test_cache def testfunc() -> str: File "/home/rudolf/dev/venvs/camcops/lib/python3.5/site-packages/dogpile/cache/region.py", line 1215, in decorator key_generator = function_key_generator(namespace, fn) File "/home/rudolf/dev/venvs/camcops/lib/python3.5/site-packages/dogpile/cache/util.py", line 31, in function_key_generator args = inspect.getargspec(fn) File "/usr/lib/python3.5/inspect.py", line 1045, in getargspec raise ValueError("Function has keyword-only arguments or annotations" ValueError: Function has keyword-only arguments or annotations, use getfullargspec() API which can support them
Other improvements include:
- the cache decorators operate as:
PER-INSTANCE caches for class instances, provided the first parameter is named “self”;
PER-CLASS caches for classmethods, provided the first parameter is named “cls”;
PER-FUNCTION caches for staticmethods and plain functions
keyword arguments are supported
properties are supported (the @property decorator must be ABOVE the cache decorator)
Note that this sort of cache relies on the generation of a STRING KEY from the function arguments. It uses the
hex(id())
function forself
/cls
arguments, and theto_str()
function, passed as a parameter, for others (for which the default is"repr"
; see discussion below as to why"repr"
is suitable while"str"
is not).
- cardinal_pythonlib.dogpile_cache.fkg(namespace: str | None, fn: ~typing.Callable, to_str: ~typing.Callable[[~typing.Any], str] = <built-in function repr>) Callable[[Any], str]
As for
fkg_allowing_type_hints()
, but allowing keyword arguments.For
kwargs
passed in, we will build adict
of all argname (key) to argvalue (values) pairs, including default args from the argspec, and then alphabetize the list before generating the key.NOTE ALSO that once we have keyword arguments, we should be using
repr()
, because we need to distinguishkwargs = {'p': 'another', 'q': 'thing'} # ... which compat.string_type will make into # p=another q=thing # ... from kwargs = {'p': 'another q=thing'}
Also modified to make the cached function unique per INSTANCE for normal methods of a class.
- cardinal_pythonlib.dogpile_cache.fkg_allowing_type_hints(namespace: str | None, fn: ~typing.Callable, to_str: ~typing.Callable[[~typing.Any], str] = <built-in function repr>) Callable[[Any], str] [source]
Replacement for
dogpile.cache.util.function_key_generator()
that handles type-hinted functions likedef testfunc(param: str) -> str: return param + "hello"
… at which
inspect.getargspec()
balks; plusinspect.getargspec()
is deprecated in Python 3.Used as an argument to e.g.
@cache_region_static.cache_on_arguments()
.Also modified to make the cached function unique per INSTANCE for normal methods of a class.
- Parameters:
namespace¶ – optional namespace, as per
get_namespace()
fn¶ – function to generate a key for (usually the function being decorated)
to_str¶ – function to apply to map arguments to a string (to make a unique key for a particular call to the function); by default it is
repr()
- Returns:
a function that generates a string key, based on a given function as well as arguments to the returned function itself.
- cardinal_pythonlib.dogpile_cache.get_namespace(fn: Callable, namespace: str | None) str [source]
Returns a representation of a function’s name (perhaps within a namespace), like
mymodule:MyClass.myclassfunc # with no namespace mymodule:MyClass.myclassfunc|somenamespace # with a namespace
- Parameters:
fn¶ – a function
namespace¶ – an optional namespace, which can be of any type but is normally a
str
; if notNone
,str(namespace)
will be added to the result. See https://dogpilecache.readthedocs.io/en/latest/api.html#dogpile.cache.region.CacheRegion.cache_on_arguments
- cardinal_pythonlib.dogpile_cache.kw_fkg_allowing_type_hints(namespace: str | None, fn: ~typing.Callable, to_str: ~typing.Callable[[~typing.Any], str] = <built-in function repr>) Callable[[Any], str] [source]
As for
fkg_allowing_type_hints()
, but allowing keyword arguments.For
kwargs
passed in, we will build adict
of all argname (key) to argvalue (values) pairs, including default args from the argspec, and then alphabetize the list before generating the key.NOTE ALSO that once we have keyword arguments, we should be using
repr()
, because we need to distinguishkwargs = {'p': 'another', 'q': 'thing'} # ... which compat.string_type will make into # p=another q=thing # ... from kwargs = {'p': 'another q=thing'}
Also modified to make the cached function unique per INSTANCE for normal methods of a class.
- cardinal_pythonlib.dogpile_cache.multikey_fkg_allowing_type_hints(namespace: str | None, fn: ~typing.Callable, to_str: ~typing.Callable[[~typing.Any], str] = <built-in function repr>) Callable[[Any], List[str]] [source]
Equivalent of
dogpile.cache.util.function_multi_key_generator()
, but usinginspect.signature()
instead.Also modified to make the cached function unique per INSTANCE for normal methods of a class.