cachekit 0.24.0__tar.gz → 0.24.1__tar.gz
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.
- {cachekit-0.24.0 → cachekit-0.24.1}/Cargo.lock +1 -1
- {cachekit-0.24.0 → cachekit-0.24.1}/PKG-INFO +2 -1
- {cachekit-0.24.0 → cachekit-0.24.1}/README.md +1 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/pyproject.toml +7 -1
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/Cargo.toml +1 -1
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/README.md +1 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/__init__.py +1 -1
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/provider.py +7 -6
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/wrapper.py +16 -10
- {cachekit-0.24.0 → cachekit-0.24.1}/Cargo.toml +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/LICENSE +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/Makefile +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/TEST_EXPANSION_SUMMARY.md +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/src/lib.rs +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/src/msgpack_bounds.rs +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/src/python_bindings.rs +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/rust/tsan_suppressions.txt +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/_fork.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/_uninterrupted.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/base.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/base_config.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/backend.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/client.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/config.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/error_handler.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/session.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/errors.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/file/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/file/backend.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/file/config.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/backend.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/config.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/error_handler.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/backend.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/client.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/config.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/error_handler.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/provider.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/cache_handler.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/decorator.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/nested.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/settings.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/singleton.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/validation.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/intent.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/local_wrapper.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/main.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/orchestrator.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/session.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/single_flight.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/stats_context.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/tenant_context.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/utils/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/di.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/hash_utils.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/health.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/hiredis_compat.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/imports.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/interop.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/invalidation.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/key_generator.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/l1_cache.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/logging.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/monitoring/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/monitoring/protocols.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/object_cache.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/py.typed +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/async_metrics.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/circuit_breaker.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/error_classification.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/load_control.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/metrics_collection.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/__init__.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/arrow_serializer.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/auto_serializer.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/base.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/encryption_wrapper.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/interop_serializer.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/orjson_serializer.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/standard_serializer.py +0 -0
- {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/wrapper.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachekit
|
|
3
|
-
Version: 0.24.
|
|
3
|
+
Version: 0.24.1
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -456,6 +456,7 @@ get_score(2) # served from cache
|
|
|
456
456
|
info = get_score.cache_info()
|
|
457
457
|
# CacheInfo has 9 fields: hits, misses, l1_hits, l2_hits, maxsize,
|
|
458
458
|
# currsize, l2_avg_latency_ms, last_operation_at, session_id
|
|
459
|
+
assert (info.hits, info.misses) == (1, 1) # the second call was a hit
|
|
459
460
|
assert info.l1_hits + info.l2_hits == info.hits # every hit is L1 or L2
|
|
460
461
|
```
|
|
461
462
|
|
|
@@ -402,6 +402,7 @@ get_score(2) # served from cache
|
|
|
402
402
|
info = get_score.cache_info()
|
|
403
403
|
# CacheInfo has 9 fields: hits, misses, l1_hits, l2_hits, maxsize,
|
|
404
404
|
# currsize, l2_avg_latency_ms, last_operation_at, session_id
|
|
405
|
+
assert (info.hits, info.misses) == (1, 1) # the second call was a hit
|
|
405
406
|
assert info.l1_hits + info.l2_hits == info.hits # every hit is L1 or L2
|
|
406
407
|
```
|
|
407
408
|
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cachekit"
|
|
7
|
-
version = "0.24.
|
|
7
|
+
version = "0.24.1"
|
|
8
8
|
description = "Backend-agnostic caching for Python — intent-based decorators with circuit breaker, distributed locking, Prometheus metrics, and optional zero-knowledge AES-256-GCM encryption, on a Rust-powered core. Zero-config L1 in-memory; scales to Redis, Memcached, File, or CachekitIO."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -158,6 +158,8 @@ python_classes = ["Test*"]
|
|
|
158
158
|
python_functions = ["test_*"]
|
|
159
159
|
asyncio_mode = "auto"
|
|
160
160
|
asyncio_default_fixture_loop_scope = "function"
|
|
161
|
+
# An xfail that starts passing fails the run, so a fixed defect cannot hide behind its marker.
|
|
162
|
+
xfail_strict = true
|
|
161
163
|
addopts = [
|
|
162
164
|
"--strict-markers",
|
|
163
165
|
"--verbose",
|
|
@@ -276,4 +278,8 @@ constraint-dependencies = [
|
|
|
276
278
|
# confusion) and GHSA-jp4c-xjxw-mgf9 (self-update import ordering); 26.2 fixes
|
|
277
279
|
# PYSEC-2026-3721 (doubly-encoded index URLs install to arbitrary paths).
|
|
278
280
|
"pip>=26.2",
|
|
281
|
+
# certifi is a dev-only transitive dep (pip-audit -> requests -> certifi).
|
|
282
|
+
# 2026.10.19 fixes PYSEC-2026-4320 (distrusts the emSign ECC Root CA - G3,
|
|
283
|
+
# whose intermediates had compromised keys).
|
|
284
|
+
"certifi>=2026.10.19",
|
|
279
285
|
]
|
|
@@ -402,6 +402,7 @@ get_score(2) # served from cache
|
|
|
402
402
|
info = get_score.cache_info()
|
|
403
403
|
# CacheInfo has 9 fields: hits, misses, l1_hits, l2_hits, maxsize,
|
|
404
404
|
# currsize, l2_avg_latency_ms, last_operation_at, session_id
|
|
405
|
+
assert (info.hits, info.misses) == (1, 1) # the second call was a hit
|
|
405
406
|
assert info.l1_hits + info.l2_hits == info.hits # every hit is L1 or L2
|
|
406
407
|
```
|
|
407
408
|
|
|
@@ -251,12 +251,13 @@ class DefaultBackendProvider(BackendProviderInterface):
|
|
|
251
251
|
def _is_configured(self) -> bool:
|
|
252
252
|
"""Whether the environment names a backend: any prefixed selector, or ``REDIS_URL``.
|
|
253
253
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
254
|
+
A selector ``_matched()`` finds counts first, because ``_detect()`` routes on it: with two
|
|
255
|
+
spellings of one set, pydantic keeps one (an empty one can win), while ``_detect()`` still routes
|
|
256
|
+
on the exact-case one. Then ``_BackendEnv`` reads every name through pydantic-settings with
|
|
257
|
+
``case_sensitive=False``, exactly as ``RedisBackendConfig`` reads them: a lowercase ``redis_url``
|
|
258
|
+
always reached that Redis through ``get_backend()``'s fallback. ``_detect()`` stays case-sensitive
|
|
259
|
+
on purpose: a lowercase prefixed selector counts as configured here and still resolves Redis
|
|
260
|
+
there, as before; aligning either method changes routing.
|
|
260
261
|
Never raises: two selectors count as configured, so ``get_backend()`` raises the ambiguity
|
|
261
262
|
error where the decorator already handles a backend that fails to build.
|
|
262
263
|
"""
|
|
@@ -288,6 +288,21 @@ class CacheInfo(NamedTuple):
|
|
|
288
288
|
>>> total = info.hits + info.misses
|
|
289
289
|
>>> round(info.hits / total, 2)
|
|
290
290
|
0.83
|
|
291
|
+
|
|
292
|
+
Read a decorated function's statistics with ``cache_info()``. With nothing configured, the
|
|
293
|
+
second call is an L1 hit:
|
|
294
|
+
|
|
295
|
+
>>> from cachekit import cache
|
|
296
|
+
>>> @cache()
|
|
297
|
+
... def square(x):
|
|
298
|
+
... return x * x
|
|
299
|
+
>>> square(4), square(4)
|
|
300
|
+
(16, 16)
|
|
301
|
+
>>> info = square.cache_info()
|
|
302
|
+
>>> info.hits, info.misses, info.l1_hits, info.l2_hits
|
|
303
|
+
(1, 1, 1, 0)
|
|
304
|
+
>>> info.maxsize is None and info.currsize is None
|
|
305
|
+
True
|
|
291
306
|
"""
|
|
292
307
|
|
|
293
308
|
hits: int # Total cache hits (L1 + L2)
|
|
@@ -3143,16 +3158,7 @@ def create_cache_wrapper(
|
|
|
3143
3158
|
are unaffected.
|
|
3144
3159
|
|
|
3145
3160
|
Returns:
|
|
3146
|
-
CacheInfo: Named tuple
|
|
3147
|
-
|
|
3148
|
-
Examples:
|
|
3149
|
-
>>> @cache()
|
|
3150
|
-
... def factorial(n):
|
|
3151
|
-
... return n * factorial(n-1) if n else 1
|
|
3152
|
-
>>> factorial(5)
|
|
3153
|
-
120
|
|
3154
|
-
>>> factorial.cache_info()
|
|
3155
|
-
CacheInfo(hits=4, misses=6, maxsize=None, currsize=6)
|
|
3161
|
+
CacheInfo: Named tuple of nine fields; see ``CacheInfo`` for them and an example.
|
|
3156
3162
|
"""
|
|
3157
3163
|
return _stats.get_info()
|
|
3158
3164
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|