Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add global defaults including enable/disable #120

Merged
merged 5 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[run]
branch = True
dynamic_context = test_function
omit =
tests/*
cachier/_version.py
Expand All @@ -13,4 +14,4 @@ exclude_lines =
pragma: no cover

# Don't complain if tests don't hit defensive assertion code:
raise NotImplementedError
raise NotImplementedError
31 changes: 31 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,43 @@ The Cachier wrapper adds a ``clear_cache()`` function to each wrapped function.
General Configuration
----------------------

Global Defaults
~~~~~~~~~~~~~~~

Settings can be globally configured across all Cachier wrappers through the use of the `set_default_params` function. This function takes the same keyword parameters as the ones defined in the decorator, which can be passed all at once or with multiple calls. Parameters given directly to a decorator take precedence over any values set by this function.

The following parameters will only be applied to decorators defined after `set_default_params` is called:

* `hash_func`
* `backend`
* `mongetter`
* `cache_dir`
* `pickle_reload`
* `separate_files`

These parameters can be changed at any time and they will apply to all decorators:

* `caching_enabled`
* `stale_after`
* `next_time`
* `wait_for_calc_timeout`

The current defaults can be fetched by calling `get_default_params`.

Threads Limit
~~~~~~~~~~~~~

To limit the number of threads Cachier is allowed to spawn, set the ``CACHIER_MAX_WORKERS`` with the desired number. The defeault is 8, so to enable Cachier to spawn even more threads, you'll have to set a higher limit explicitly.


Global Enable/Disable
---------------------

Caching can be turned off across all decorators by calling `disable_caching`, and then re-activated by calling `enable_caching`.

These functions are convenience wrappers around the `caching_enabled` default setting.


Cache Shelf Life
----------------

Expand Down
9 changes: 8 additions & 1 deletion cachier/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
from .core import cachier
from .core import (
cachier,
set_default_params,
get_default_params,
enable_caching,
disable_caching,
)

from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
Expand Down
38 changes: 23 additions & 15 deletions cachier/base_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,19 @@
# Copyright (c) 2016, Shay Palachy <shaypal5@gmail.com>

import abc # for the _BaseCore abstract base class
import functools
import hashlib
import inspect
import pickle # nosec: B403


def _default_hash_func(args, kwds):
# pylint: disable-next=protected-access
key = functools._make_key(args, kwds, typed=True)
hash = hashlib.sha256()
for item in key:
hash.update(pickle.dumps(item))
return hash.hexdigest()
class RecalculationNeeded(Exception):
pass


class _BaseCore():
__metaclass__ = abc.ABCMeta

def __init__(self, hash_func):
self.hash_func = hash_func if hash_func else _default_hash_func
self.func = None
def __init__(self, hash_func, default_params):
self.default_params = default_params
self.hash_func = hash_func

def set_func(self, func):
"""Sets the function this core will use. This has to be set before any
Expand All @@ -36,18 +28,34 @@ def set_func(self, func):
self.func_is_method = func_params and func_params[0] == 'self'
self.func = func

def get_key(self, args, kwds):
"""Returns a unique key based on the arguments provided."""
if self.hash_func is not None:
return self.hash_func(args, kwds)
else:
return self.default_params['hash_func'](args, kwds)

def get_entry(self, args, kwds):
"""Returns the result mapped to the given arguments in this core's
cache, if such a mapping exists."""
key = self.hash_func(args, kwds)
key = self.get_key(args, kwds)
return self.get_entry_by_key(key)

def precache_value(self, args, kwds, value_to_cache):
"""Writes a precomputed value into the cache."""
key = self.hash_func(args, kwds)
key = self.get_key(args, kwds)
self.set_entry(key, value_to_cache)
return value_to_cache

def check_calc_timeout(self, time_spent):
"""Raise an exception if a recalulation is needed."""
if self.wait_for_calc_timeout is not None:
calc_timeout = self.wait_for_calc_timeout
else:
calc_timeout = self.default_params['wait_for_calc_timeout']
if calc_timeout > 0 and (time_spent >= calc_timeout):
raise RecalculationNeeded()

@abc.abstractmethod
def get_entry_by_key(self, key):
"""Returns the result mapped to the given key in this core's cache,
Expand Down