UCROE (Use Cached Results On Exception)
UCROE (Use Cached Results On Exception) provides Python decorators that cache a function’s return value and reuse it if the function raises an exception on subsequent calls.
Features:
- decorators to cache function return values and return them if subsequent calls raise an exception
- multiple built-in cache backends (supports cachetools, Django)
- compatible with tenacity, a retry library
- configurable via decorator parameters, environment variables, and Django settings (if available)
UCROE is a standalone library. It doesn't require Django but works well with it.
To be implemented:
- support async functions
- support methods
Getting Started
Installation
pip install ucroe
Basic Usage
from ucroe import cached_result_on_exception
@cached_result_on_exception
def f1(): ...
Expected Behaviour When Cached Value Is Present
from ucroe import cached_result_on_exception
from unittest.mock import MagicMock
mock_http_call = MagicMock(side_effect=[1, 2, ValueError, 3, 4])
@cached_result_on_exception
def f():
return mock_http_call()
assert f() == 1
assert f() == 2
assert f() == 2 # cached value is returned
assert f() == 3
assert f() == 4
Expected Behaviour When There Is No Cached Value
from unittest.mock import MagicMock
from ucroe import cached_result_on_exception
gen_fn = MagicMock(side_effect=[ValueError]) # raises during the 1st invocation
@cached_result_on_exception
def f():
return gen_fn()
f() # raises ValueError
Supported Configuration
UCROE supports the following configs, they can be configured as environment variables or Django settings, if available. In case of conflict, Django settings will take precedence.
UCROE_LOG_EXCEPTION_BY_DEFAULT: (default:False) when set, exception raised within the wrapped function will be logged with log levelwarning.UCROE_BACKEND: (default:ucroe.cache_backend.cachetools.LRUBackend) the cache backend to useUCROE_BACKEND_CONFIG: (default:'{"maxsize": 100}') JSON serialized string that will be used to instantiate the cache backend
Configuring Cache Backend
By default, @cached_result_on_exception uses ucroe.cache_backend.cachetools.LRUBackend, which itself is a wrapper
of cachetools.LRUCache.
UCROE comes with a set of built-in backends:
ucroe.cache_backend.cachetools.FIFOBackenducroe.cache_backend.cachetools.LFUBackenducroe.cache_backend.cachetools.LRUBackenducroe.cache_backend.cachetools.RRBackenducroe.cache_backend.cachetools.TTLBackenducroe.cache_backend.cachetools.TLRUBackenducroe.cache_backend.django.DjangoBackend
Each cachetools backend is merely a wrapper to the corresponding cache provided by cachetools.
Using Django Backend
This library can be configured to use Django cache framework.
To do so, simple specify ucroe.cache_backend.django.DjangoBackend as the cache backend. Eg:
# in your Django settings
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
"ucroe": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
"KEY_PREFIX": "ucroe_",
},
}
# Add the following settings:
UCROE_BACKEND = "ucroe.cache_backend.django.DjangoBackend"
# Optionally, you can also specify the Django cache to use.
# When unspecified, the `default` cache will be used
UCROE_BACKEND_CONFIG = {"cache_name": "ucroe"}
In other parts of your code, simple import and decorate your functions with @cached_results_on_exception:
from ucroe import cached_result_on_exception
@cached_result_on_exception
def my_func(*args):
...
Using the decorators
It can be used with or without parenthesis
from ucroe import cached_result_on_exception
@cached_result_on_exception
def f1(): ...
@cached_result_on_exception()
def f2(): ...
It also accepts the following parameters:
log_exception: bool: when set toTrue, a warning log will emit when the wrapped function raises an exceptionfrom ucroe import cached_result_on_exception @cached_result_on_exception(log_exception=True) def f1(): ...
on_exception: Callable[[Exception], None]: a hook that will be called when the wrapped function raisesimport logging from ucroe import cached_result_on_exception logger = logging.getLogger(__name__) def on_exception(exc): logger.error("BOOM!", exc_info=exc) @cached_result_on_exception(on_exception=on_exception) def f1(): ... f1() # If f1() raises, a log with message `error: BOOM!` and the stack trace will be emitted.
Metadata
Release files for ucroe 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ucroe-0.1.0.tar.gz | 7.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ucroe-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.6 kB
Release files / ucroe-0.1.0.tar.gz
| Download URL | ucroe-0.1.0.tar.gz |
|---|---|
| Size | 7.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
21d49a49553b18bd121978d22abf683dcff41d9e7641562d9c6797e1398d7301
|
|
BLAKE2b-256 checksum How to use checksums |
88aa98f86cd25cdd33dcdca30ca60ace2b93e9eeeaaa892e92c89ac99e2d7262
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.4 CPython/3.10.12 Linux/6.5.0-1025-azure
|
Release files / ucroe-0.1.0-py3-none-any.whl
| Download URL | ucroe-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
79f95c032c385e19ec5fc425f545910cf97650740ad82aa84575aaa2c65b769c
|
|
BLAKE2b-256 checksum How to use checksums |
40e7698e6458f281ae2f535b15933e0cf3337b01513cac3ce3a5a83686249bcc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.4 CPython/3.10.12 Linux/6.5.0-1025-azure
|
Security for ucroe 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.