From e99933b5200e0531025eb6fcfd2ed890624a6156 Mon Sep 17 00:00:00 2001 From: Alison Marczewski Date: Sun, 8 Mar 2020 16:58:07 -0300 Subject: [PATCH] Creating a callable param (hash_params) to generate key when positional and/or keywords arguments are not hashable. It can work as a workaround in scenarios that positional and keywords args are not hashable but one can be generated with a properly method for each case --- cachier/base_core.py | 2 +- cachier/core.py | 8 +++++++- cachier/mongo_core.py | 4 ++-- cachier/pickle_core.py | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cachier/base_core.py b/cachier/base_core.py index 99b1d9a..6a9bb01 100644 --- a/cachier/base_core.py +++ b/cachier/base_core.py @@ -28,7 +28,7 @@ class _BaseCore(): if such a mapping exists.""" @abc.abstractmethod - def get_entry(self, args, kwds): + def get_entry(self, args, kwds, hash_params): """Returns the result mapped to the given arguments in this core's cache, if such a mapping exists.""" diff --git a/cachier/core.py b/cachier/core.py index 793fe38..a909915 100644 --- a/cachier/core.py +++ b/cachier/core.py @@ -79,6 +79,7 @@ def cachier( pickle_reload=True, mongetter=None, cache_dir=None, + hash_params=None, ): """A persistent, stale-free memoization decorator. @@ -112,6 +113,11 @@ def cachier( A fully qualified path to a file directory to be used for cache files. The running process must have running permissions to this folder. If not provided, a default directory at `~/.cachier/` is used. + hash_params : callable, optional + A callable that takes args and kwargs from main function and returns + a hash key of these params. If unset, default transformation is + applied. It is valuable and works as workaround in scenarios + that positional and keyword arguments are not hashable. """ # print('Inside the wrapper maker') # print('mongetter={}'.format(mongetter)) @@ -142,7 +148,7 @@ def cachier( _print = print if ignore_cache: return func(*args, **kwds) - key, entry = core.get_entry(args, kwds) + key, entry = core.get_entry(args, kwds, hash_params) if overwrite_cache: return _calc_entry(core, key, func, args, kwds) if entry is not None: # pylint: disable=R0101 diff --git a/cachier/mongo_core.py b/cachier/mongo_core.py index 2d2077d..e05b6da 100644 --- a/cachier/mongo_core.py +++ b/cachier/mongo_core.py @@ -79,8 +79,8 @@ class _MongoCore(_BaseCore): return key, entry return key, None - def get_entry(self, args, kwds): - key = pickle.dumps(args + tuple(sorted(kwds.items()))) + def get_entry(self, args, kwds, hash_params): + key = pickle.dumps(args + tuple(sorted(kwds.items())) if hash_params is None else hash_params(args, kwds)) return self.get_entry_by_key(key) def set_entry(self, key, func_res): diff --git a/cachier/pickle_core.py b/cachier/pickle_core.py index e6bdea0..fed5bb4 100644 --- a/cachier/pickle_core.py +++ b/cachier/pickle_core.py @@ -146,8 +146,8 @@ class _PickleCore(_BaseCore): self._reload_cache() return key, self._get_cache().get(key, None) - def get_entry(self, args, kwds): - key = args + tuple(sorted(kwds.items())) + def get_entry(self, args, kwds, hash_params): + key = args + tuple(sorted(kwds.items())) if hash_params is None else hash_params(args, kwds) # print('key type={}, key={}'.format(type(key), key)) return self.get_entry_by_key(key)