cachekit 0.10.1__tar.gz → 0.11.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.10.1 → cachekit-0.11.1}/Cargo.lock +3 -3
- {cachekit-0.10.1 → cachekit-0.11.1}/PKG-INFO +5 -4
- {cachekit-0.10.1 → cachekit-0.11.1}/README.md +1 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/pyproject.toml +9 -3
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/Cargo.toml +1 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/README.md +1 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/__init__.py +1 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/cache_handler.py +1 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/config/singleton.py +20 -3
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/__init__.py +30 -6
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/encryption_wrapper.py +1 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/orjson_serializer.py +6 -1
- {cachekit-0.10.1 → cachekit-0.11.1}/Cargo.toml +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/LICENSE +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/Makefile +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/TEST_EXPANSION_SUMMARY.md +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/src/lib.rs +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/src/python_bindings.rs +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/supply-chain/audits.toml +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/supply-chain/config.toml +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/supply-chain/imports.lock +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/rust/tsan_suppressions.txt +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/base.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/base_config.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/cachekitio/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/cachekitio/backend.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/cachekitio/client.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/cachekitio/config.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/cachekitio/error_handler.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/cachekitio/session.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/errors.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/file/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/file/backend.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/file/config.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/memcached/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/memcached/backend.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/memcached/config.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/memcached/error_handler.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/provider.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/redis/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/redis/backend.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/redis/client.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/redis/config.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/redis/error_handler.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/backends/redis/provider.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/config/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/config/decorator.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/config/nested.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/config/settings.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/config/validation.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/intent.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/local_wrapper.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/main.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/orchestrator.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/session.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/stats_context.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/tenant_context.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/utils/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/decorators/wrapper.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/di.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/hash_utils.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/health.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/hiredis_compat.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/imports.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/invalidation/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/invalidation/channel.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/invalidation/event.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/invalidation/redis_channel.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/key_generator.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/l1_cache.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/logging.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/monitoring/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/monitoring/correlation_tracking.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/monitoring/pool_monitor.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/monitoring/protocols.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/object_cache.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/py.typed +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/__init__.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/adaptive_timeout.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/async_metrics.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/circuit_breaker.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/error_classification.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/load_control.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/metrics_collection.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/reliability/profiles.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/arrow_serializer.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/auto_serializer.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/base.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/standard_serializer.py +0 -0
- {cachekit-0.10.1 → cachekit-0.11.1}/src/cachekit/serializers/wrapper.py +0 -0
|
@@ -271,7 +271,7 @@ dependencies = [
|
|
|
271
271
|
|
|
272
272
|
[[package]]
|
|
273
273
|
name = "cachekit-rs"
|
|
274
|
-
version = "0.
|
|
274
|
+
version = "0.11.1"
|
|
275
275
|
dependencies = [
|
|
276
276
|
"cachekit-core",
|
|
277
277
|
"criterion",
|
|
@@ -954,9 +954,9 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
|
954
954
|
|
|
955
955
|
[[package]]
|
|
956
956
|
name = "memmap2"
|
|
957
|
-
version = "0.9.
|
|
957
|
+
version = "0.9.11"
|
|
958
958
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
959
|
-
checksum = "
|
|
959
|
+
checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0"
|
|
960
960
|
dependencies = [
|
|
961
961
|
"libc",
|
|
962
962
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachekit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.1
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -26,15 +26,16 @@ Requires-Dist: tenacity>=8.0.0
|
|
|
26
26
|
Requires-Dist: prometheus-client>=0.22.1
|
|
27
27
|
Requires-Dist: psutil>=7.0.0
|
|
28
28
|
Requires-Dist: blake3>=1.0.5
|
|
29
|
-
Requires-Dist: msgpack>=1.1
|
|
30
|
-
Requires-Dist: orjson>=3.9.0
|
|
29
|
+
Requires-Dist: msgpack>=1.2.1
|
|
31
30
|
Requires-Dist: xxhash>=3.5.0
|
|
32
31
|
Requires-Dist: httpx[http2]>=0.28.1
|
|
33
32
|
Requires-Dist: numpy>=2.0.2 ; extra == 'data'
|
|
34
33
|
Requires-Dist: pandas>=1.3.0 ; extra == 'data'
|
|
35
34
|
Requires-Dist: pyarrow>=21.0.0 ; extra == 'data'
|
|
35
|
+
Requires-Dist: orjson>=3.9.0 ; extra == 'json'
|
|
36
36
|
Requires-Dist: pymemcache>=4.0.0 ; extra == 'memcached'
|
|
37
37
|
Provides-Extra: data
|
|
38
|
+
Provides-Extra: json
|
|
38
39
|
Provides-Extra: memcached
|
|
39
40
|
License-File: LICENSE
|
|
40
41
|
Summary: Production-ready Redis caching for Python with intelligent reliability features and Rust-powered performance
|
|
@@ -302,7 +303,7 @@ def test_cached_function():
|
|
|
302
303
|
| Serializer | Speed | Use Case |
|
|
303
304
|
|:-----------|:-----:|:---------|
|
|
304
305
|
| **StandardSerializer** | ★★★★☆ | General Python types, NumPy, Pandas |
|
|
305
|
-
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) |
|
|
306
|
+
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) — requires `cachekit[json]` |
|
|
306
307
|
| **ArrowSerializer** | ★★★★★ | Large DataFrames (6-23x faster for 10K+ rows) |
|
|
307
308
|
| **EncryptionWrapper** | ★★★★☆ | Wraps any serializer with AES-256-GCM |
|
|
308
309
|
|
|
@@ -249,7 +249,7 @@ def test_cached_function():
|
|
|
249
249
|
| Serializer | Speed | Use Case |
|
|
250
250
|
|:-----------|:-----:|:---------|
|
|
251
251
|
| **StandardSerializer** | ★★★★☆ | General Python types, NumPy, Pandas |
|
|
252
|
-
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) |
|
|
252
|
+
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) — requires `cachekit[json]` |
|
|
253
253
|
| **ArrowSerializer** | ★★★★★ | Large DataFrames (6-23x faster for 10K+ rows) |
|
|
254
254
|
| **EncryptionWrapper** | ★★★★☆ | Wraps any serializer with AES-256-GCM |
|
|
255
255
|
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cachekit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.11.1"
|
|
8
8
|
description = "Production-ready Redis caching for Python with intelligent reliability features and Rust-powered performance"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -64,8 +64,7 @@ dependencies = [
|
|
|
64
64
|
"psutil>=7.0.0",
|
|
65
65
|
# Serialization and hashing
|
|
66
66
|
"blake3>=1.0.5",
|
|
67
|
-
"msgpack>=1.1
|
|
68
|
-
"orjson>=3.9.0",
|
|
67
|
+
"msgpack>=1.2.1",
|
|
69
68
|
"xxhash>=3.5.0",
|
|
70
69
|
# HTTP client for SaaS backend (cachekit.io)
|
|
71
70
|
"httpx[http2]>=0.28.1",
|
|
@@ -78,6 +77,10 @@ data = [
|
|
|
78
77
|
"pandas>=1.3.0",
|
|
79
78
|
"pyarrow>=21.0.0",
|
|
80
79
|
]
|
|
80
|
+
json = [
|
|
81
|
+
# OrjsonSerializer (serializer="orjson") — fast JSON via orjson
|
|
82
|
+
"orjson>=3.9.0",
|
|
83
|
+
]
|
|
81
84
|
memcached = [
|
|
82
85
|
"pymemcache>=4.0.0",
|
|
83
86
|
]
|
|
@@ -228,6 +231,9 @@ dev = [
|
|
|
228
231
|
"numpy>=2.0.2",
|
|
229
232
|
"pandas>=1.3.0",
|
|
230
233
|
"pyarrow>=21.0.0",
|
|
234
|
+
# OrjsonSerializer support — now the [json] optional extra; kept here so the
|
|
235
|
+
# orjson tests, doctests, and markdown-docs still resolve it in dev/CI.
|
|
236
|
+
"orjson>=3.9.0",
|
|
231
237
|
"pytest-xdist>=3.8.0",
|
|
232
238
|
"time-machine>=2.19.0",
|
|
233
239
|
]
|
|
@@ -249,7 +249,7 @@ def test_cached_function():
|
|
|
249
249
|
| Serializer | Speed | Use Case |
|
|
250
250
|
|:-----------|:-----:|:---------|
|
|
251
251
|
| **StandardSerializer** | ★★★★☆ | General Python types, NumPy, Pandas |
|
|
252
|
-
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) |
|
|
252
|
+
| **OrjsonSerializer** | ★★★★★ | JSON APIs (2-5x faster than stdlib) — requires `cachekit[json]` |
|
|
253
253
|
| **ArrowSerializer** | ★★★★★ | Large DataFrames (6-23x faster for 10K+ rows) |
|
|
254
254
|
| **EncryptionWrapper** | ★★★★☆ | Wraps any serializer with AES-256-GCM |
|
|
255
255
|
|
|
@@ -308,7 +308,7 @@ class CacheSerializationHandler:
|
|
|
308
308
|
deployment_uuid: Optional deployment-specific UUID for single-tenant mode.
|
|
309
309
|
If not provided, uses env var or persistent file.
|
|
310
310
|
master_key: Optional master key for encryption (hex-encoded). If not provided,
|
|
311
|
-
reads from
|
|
311
|
+
reads from CACHEKIT_MASTER_KEY environment variable.
|
|
312
312
|
enable_integrity_checking: Enable integrity checking (default: True)
|
|
313
313
|
Uses xxHash3-64 (8 bytes) for all serializers.
|
|
314
314
|
Set to False for @cache.minimal (speed-first, no checksums)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Thread-safe singleton pattern for global cachekit settings."""
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
import threading
|
|
4
5
|
from typing import Optional
|
|
5
6
|
|
|
@@ -43,9 +44,25 @@ def get_settings() -> CachekitConfig:
|
|
|
43
44
|
"""
|
|
44
45
|
global _settings_instance
|
|
45
46
|
|
|
46
|
-
# Fast path -
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
# Fast path - snapshot the global once. A concurrent reset_settings() can null _settings_instance
|
|
48
|
+
# at any time, so the unlocked self-heal check below reads the snapshot, never the global, or it
|
|
49
|
+
# could dereference None between the not-None check and the .master_key access.
|
|
50
|
+
instance = _settings_instance
|
|
51
|
+
if instance is not None:
|
|
52
|
+
# Self-heal the keyless-then-key-set ordering trap (#195): if the config was first built
|
|
53
|
+
# before CACHEKIT_MASTER_KEY entered the environment (e.g. an import-time cache decorator
|
|
54
|
+
# evaluated before the app loaded its secrets), it froze master_key=None — encryption would
|
|
55
|
+
# then silently never activate. Re-read once the key appears, so it turns on without an
|
|
56
|
+
# explicit reset_settings(). Idempotent: after the rebuild master_key is set, so this never
|
|
57
|
+
# fires again (no per-call churn once a key is present).
|
|
58
|
+
if instance.master_key is None and os.environ.get("CACHEKIT_MASTER_KEY"):
|
|
59
|
+
with _settings_lock:
|
|
60
|
+
# Re-read the global under the lock: a peer may have rebuilt it (key now set) or
|
|
61
|
+
# reset_settings() may have cleared it (back to None). Rebuild only if still keyless.
|
|
62
|
+
if _settings_instance is None or _settings_instance.master_key is None:
|
|
63
|
+
_settings_instance = CachekitConfig.from_env()
|
|
64
|
+
return _settings_instance
|
|
65
|
+
return instance
|
|
49
66
|
|
|
50
67
|
# Slow path - create instance with lock
|
|
51
68
|
with _settings_lock:
|
|
@@ -15,11 +15,11 @@ from .base import (
|
|
|
15
15
|
SerializerProtocol,
|
|
16
16
|
)
|
|
17
17
|
from .encryption_wrapper import EncryptionWrapper
|
|
18
|
-
from .orjson_serializer import OrjsonSerializer
|
|
19
18
|
from .standard_serializer import StandardSerializer
|
|
20
19
|
|
|
21
20
|
if TYPE_CHECKING:
|
|
22
21
|
from .arrow_serializer import ArrowSerializer
|
|
22
|
+
from .orjson_serializer import OrjsonSerializer
|
|
23
23
|
|
|
24
24
|
logger = logging.getLogger(__name__)
|
|
25
25
|
|
|
@@ -37,6 +37,20 @@ def _get_arrow_serializer() -> type:
|
|
|
37
37
|
return _ArrowSerializer
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
# Lazy import for optional OrjsonSerializer (requires orjson from [json] extra)
|
|
41
|
+
_OrjsonSerializer: type | None = None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _get_orjson_serializer() -> type:
|
|
45
|
+
"""Lazy-load OrjsonSerializer. Raises ImportError if orjson not installed."""
|
|
46
|
+
global _OrjsonSerializer
|
|
47
|
+
if _OrjsonSerializer is None:
|
|
48
|
+
from .orjson_serializer import OrjsonSerializer
|
|
49
|
+
|
|
50
|
+
_OrjsonSerializer = OrjsonSerializer
|
|
51
|
+
return _OrjsonSerializer
|
|
52
|
+
|
|
53
|
+
|
|
40
54
|
# Validate ByteStorage works correctly
|
|
41
55
|
test_storage = ByteStorage("msgpack")
|
|
42
56
|
test_data = b"test validation data"
|
|
@@ -57,7 +71,7 @@ SERIALIZER_REGISTRY = {
|
|
|
57
71
|
"default": StandardSerializer, # Language-agnostic MessagePack for multi-language caches
|
|
58
72
|
"std": StandardSerializer, # Explicit StandardSerializer alias
|
|
59
73
|
"arrow": None, # Lazy-loaded: requires pyarrow from [data] extra
|
|
60
|
-
"orjson":
|
|
74
|
+
"orjson": None, # Lazy-loaded: requires orjson from [json] extra
|
|
61
75
|
"encrypted": EncryptionWrapper, # StandardSerializer + AES-256-GCM encryption
|
|
62
76
|
}
|
|
63
77
|
|
|
@@ -116,9 +130,11 @@ def get_serializer(name: str, enable_integrity_checking: bool = True) -> Seriali
|
|
|
116
130
|
f"@cache(serializer=MySerializer())"
|
|
117
131
|
)
|
|
118
132
|
|
|
119
|
-
# Get serializer class (lazy-load
|
|
133
|
+
# Get serializer class (lazy-load optional serializers if needed)
|
|
120
134
|
if name == "arrow":
|
|
121
135
|
serializer_class = _get_arrow_serializer()
|
|
136
|
+
elif name == "orjson":
|
|
137
|
+
serializer_class = _get_orjson_serializer()
|
|
122
138
|
else:
|
|
123
139
|
serializer_class = SERIALIZER_REGISTRY[name]
|
|
124
140
|
|
|
@@ -177,9 +193,15 @@ def get_serializer_info() -> dict[str, dict[str, Any]]:
|
|
|
177
193
|
if hasattr(instance, "get_info"):
|
|
178
194
|
info[name].update(instance.get_info()) # type: ignore[attr-defined]
|
|
179
195
|
except ImportError as e:
|
|
196
|
+
# Optional serializer whose backing dependency (pyarrow / orjson) is absent.
|
|
197
|
+
optional_modules = {
|
|
198
|
+
"arrow": ("ArrowSerializer", "cachekit.serializers.arrow_serializer"),
|
|
199
|
+
"orjson": ("OrjsonSerializer", "cachekit.serializers.orjson_serializer"),
|
|
200
|
+
}
|
|
201
|
+
cls, module = optional_modules.get(name, ("Unknown", "unknown"))
|
|
180
202
|
info[name] = {
|
|
181
|
-
"class":
|
|
182
|
-
"module":
|
|
203
|
+
"class": cls,
|
|
204
|
+
"module": module,
|
|
183
205
|
"available": False,
|
|
184
206
|
"error": str(e),
|
|
185
207
|
}
|
|
@@ -194,9 +216,11 @@ def get_serializer_info() -> dict[str, dict[str, Any]]:
|
|
|
194
216
|
|
|
195
217
|
|
|
196
218
|
def __getattr__(name: str) -> Any:
|
|
197
|
-
"""Lazy attribute access for optional ArrowSerializer."""
|
|
219
|
+
"""Lazy attribute access for optional ArrowSerializer / OrjsonSerializer."""
|
|
198
220
|
if name == "ArrowSerializer":
|
|
199
221
|
return _get_arrow_serializer()
|
|
222
|
+
if name == "OrjsonSerializer":
|
|
223
|
+
return _get_orjson_serializer()
|
|
200
224
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
201
225
|
|
|
202
226
|
|
|
@@ -128,7 +128,7 @@ class EncryptionWrapper:
|
|
|
128
128
|
settings = get_settings()
|
|
129
129
|
if not settings.master_key:
|
|
130
130
|
raise EncryptionError(
|
|
131
|
-
"Master key required. Set
|
|
131
|
+
"Master key required. Set CACHEKIT_MASTER_KEY environment variable or pass master_key parameter."
|
|
132
132
|
)
|
|
133
133
|
try:
|
|
134
134
|
master_key = bytes.fromhex(settings.master_key.get_secret_value())
|
|
@@ -14,7 +14,12 @@ from __future__ import annotations
|
|
|
14
14
|
|
|
15
15
|
from typing import Any, ClassVar
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# Required dependency: orjson (fail-fast with install hint when the [json] extra is absent)
|
|
18
|
+
try:
|
|
19
|
+
import orjson
|
|
20
|
+
except ImportError as e: # pragma: no cover - only reachable without the [json] extra (behavior tested via subprocess)
|
|
21
|
+
raise ImportError("orjson is not installed. OrjsonSerializer requires the [json] extra: pip install 'cachekit[json]'") from e
|
|
22
|
+
|
|
18
23
|
import xxhash
|
|
19
24
|
|
|
20
25
|
from .base import SerializationError, SerializationFormat, SerializationMetadata
|
|
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
|
|
File without changes
|