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.
Files changed (88) hide show
  1. {cachekit-0.24.0 → cachekit-0.24.1}/Cargo.lock +1 -1
  2. {cachekit-0.24.0 → cachekit-0.24.1}/PKG-INFO +2 -1
  3. {cachekit-0.24.0 → cachekit-0.24.1}/README.md +1 -0
  4. {cachekit-0.24.0 → cachekit-0.24.1}/pyproject.toml +7 -1
  5. {cachekit-0.24.0 → cachekit-0.24.1}/rust/Cargo.toml +1 -1
  6. {cachekit-0.24.0 → cachekit-0.24.1}/rust/README.md +1 -0
  7. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/__init__.py +1 -1
  8. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/provider.py +7 -6
  9. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/wrapper.py +16 -10
  10. {cachekit-0.24.0 → cachekit-0.24.1}/Cargo.toml +0 -0
  11. {cachekit-0.24.0 → cachekit-0.24.1}/LICENSE +0 -0
  12. {cachekit-0.24.0 → cachekit-0.24.1}/rust/Makefile +0 -0
  13. {cachekit-0.24.0 → cachekit-0.24.1}/rust/TEST_EXPANSION_SUMMARY.md +0 -0
  14. {cachekit-0.24.0 → cachekit-0.24.1}/rust/src/lib.rs +0 -0
  15. {cachekit-0.24.0 → cachekit-0.24.1}/rust/src/msgpack_bounds.rs +0 -0
  16. {cachekit-0.24.0 → cachekit-0.24.1}/rust/src/python_bindings.rs +0 -0
  17. {cachekit-0.24.0 → cachekit-0.24.1}/rust/tsan_suppressions.txt +0 -0
  18. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/_fork.py +0 -0
  19. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/__init__.py +0 -0
  20. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/_uninterrupted.py +0 -0
  21. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/base.py +0 -0
  22. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/base_config.py +0 -0
  23. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/__init__.py +0 -0
  24. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/backend.py +0 -0
  25. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/client.py +0 -0
  26. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/config.py +0 -0
  27. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/error_handler.py +0 -0
  28. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/cachekitio/session.py +0 -0
  29. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/errors.py +0 -0
  30. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/file/__init__.py +0 -0
  31. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/file/backend.py +0 -0
  32. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/file/config.py +0 -0
  33. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/__init__.py +0 -0
  34. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/backend.py +0 -0
  35. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/config.py +0 -0
  36. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/memcached/error_handler.py +0 -0
  37. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/__init__.py +0 -0
  38. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/backend.py +0 -0
  39. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/client.py +0 -0
  40. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/config.py +0 -0
  41. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/error_handler.py +0 -0
  42. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/backends/redis/provider.py +0 -0
  43. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/cache_handler.py +0 -0
  44. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/__init__.py +0 -0
  45. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/decorator.py +0 -0
  46. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/nested.py +0 -0
  47. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/settings.py +0 -0
  48. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/singleton.py +0 -0
  49. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/config/validation.py +0 -0
  50. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/__init__.py +0 -0
  51. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/intent.py +0 -0
  52. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/local_wrapper.py +0 -0
  53. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/main.py +0 -0
  54. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/orchestrator.py +0 -0
  55. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/session.py +0 -0
  56. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/single_flight.py +0 -0
  57. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/stats_context.py +0 -0
  58. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/tenant_context.py +0 -0
  59. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/decorators/utils/__init__.py +0 -0
  60. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/di.py +0 -0
  61. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/hash_utils.py +0 -0
  62. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/health.py +0 -0
  63. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/hiredis_compat.py +0 -0
  64. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/imports.py +0 -0
  65. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/interop.py +0 -0
  66. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/invalidation.py +0 -0
  67. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/key_generator.py +0 -0
  68. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/l1_cache.py +0 -0
  69. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/logging.py +0 -0
  70. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/monitoring/__init__.py +0 -0
  71. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/monitoring/protocols.py +0 -0
  72. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/object_cache.py +0 -0
  73. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/py.typed +0 -0
  74. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/__init__.py +0 -0
  75. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/async_metrics.py +0 -0
  76. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/circuit_breaker.py +0 -0
  77. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/error_classification.py +0 -0
  78. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/load_control.py +0 -0
  79. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/reliability/metrics_collection.py +0 -0
  80. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/__init__.py +0 -0
  81. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/arrow_serializer.py +0 -0
  82. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/auto_serializer.py +0 -0
  83. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/base.py +0 -0
  84. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/encryption_wrapper.py +0 -0
  85. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/interop_serializer.py +0 -0
  86. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/orjson_serializer.py +0 -0
  87. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/standard_serializer.py +0 -0
  88. {cachekit-0.24.0 → cachekit-0.24.1}/src/cachekit/serializers/wrapper.py +0 -0
@@ -280,7 +280,7 @@ dependencies = [
280
280
 
281
281
  [[package]]
282
282
  name = "cachekit-rs"
283
- version = "0.24.0"
283
+ version = "0.24.1"
284
284
  dependencies = [
285
285
  "cachekit-core",
286
286
  "criterion 0.8.2",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cachekit
3
- Version: 0.24.0
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.0"
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
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "cachekit-rs"
3
- version = "0.24.0"
3
+ version = "0.24.1"
4
4
  edition = "2021"
5
5
  authors = ["cachekit Contributors"]
6
6
  description = "High-performance storage engine for caching with compression and encryption"
@@ -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
 
@@ -68,7 +68,7 @@ Example Usage:
68
68
  ```
69
69
  """
70
70
 
71
- __version__ = "0.24.0"
71
+ __version__ = "0.24.1"
72
72
 
73
73
  from collections.abc import Callable
74
74
  from typing import Any, TypeVar
@@ -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
- Read through pydantic-settings with ``case_sensitive=False``, exactly as ``RedisBackendConfig``
255
- reads them: a lowercase ``redis_url`` always reached that Redis through ``get_backend()``'s
256
- fallback. ``_detect()`` stays case-sensitive on purpose: a lowercase prefixed selector counts as
257
- configured here and still resolves Redis there, as before; aligning either method changes routing.
258
- A selector ``_detect()`` matches always counts too: with two spellings set, pydantic keeps one
259
- (an empty one can win), while ``_detect()`` still routes on the exact-case one.
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 with hits, misses, maxsize, currsize
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