django-cachex 0.4.2__tar.gz → 0.5.0__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.
- {django_cachex-0.4.2 → django_cachex-0.5.0}/.gitignore +0 -5
- {django_cachex-0.4.2 → django_cachex-0.5.0}/PKG-INFO +4 -15
- {django_cachex-0.4.2 → django_cachex-0.5.0}/README.md +3 -12
- {django_cachex-0.4.2 → django_cachex-0.5.0}/benchmarks/README.md +24 -37
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/__init__.py +1 -9
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/__init__.py +2 -22
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/pipeline.py +2 -4
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/protocols.py +0 -1
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/valkey_py.py +2 -2
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/__init__.py +0 -8
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/resp.py +0 -1
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/stream.py +1 -1
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/exceptions.py +1 -1
- django_cachex-0.5.0/django_cachex/lock.py +11 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/semaphore.py +1 -1
- {django_cachex-0.4.2 → django_cachex-0.5.0}/pyproject.toml +2 -14
- django_cachex-0.4.2/crates/django-cachex-redis-rs/LICENSE +0 -21
- django_cachex-0.4.2/crates/django-cachex-redis-rs/README.md +0 -23
- django_cachex-0.4.2/crates/django-cachex-redis-rs/pyproject.toml +0 -45
- django_cachex-0.4.2/django_cachex/adapters/_async_helpers.py +0 -150
- django_cachex-0.4.2/django_cachex/adapters/redis_rs.py +0 -196
- django_cachex-0.4.2/django_cachex/cache/redis_rs.py +0 -38
- django_cachex-0.4.2/django_cachex/lock.py +0 -291
- {django_cachex-0.4.2 → django_cachex-0.5.0}/LICENSE +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/_pipeline_parsers.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/redis_py.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/adapters/valkey_glide.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/__init__.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/admin.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/apps.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/cas.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/helpers.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/models.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/queryset.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/cache/change_form.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/cache/change_list.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/cache/styles.css +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/_key_detail_actions.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/add_form.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/change_form.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/change_list.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_hash.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_list.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_pagination.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_set.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_stream.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_string.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_value_input.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/templates/admin/django_cachex/key/key_detail_zset.html +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/views/__init__.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/views/base.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/views/cache_detail.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/views/key_add.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/admin/views/key_detail.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/_semaphore_lua.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/base.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/database.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/locmem.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/redis_py.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/tiered.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/valkey_glide.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/cache/valkey_py.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/__init__.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/base.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/gzip.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/lz4.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/lzma.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/zlib.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/compressors/zstd.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/py.typed +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/script.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/__init__.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/base.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/json.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/msgpack.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/orjson.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/ormsgpack.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/serializers/pickle.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/stampede.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/types.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/django_cachex/utils.py +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/examples/README.md +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/examples/full/README.md +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/examples/full/pyproject.toml +0 -0
- {django_cachex-0.4.2 → django_cachex-0.5.0}/examples/simple/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: django-cachex
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Full featured Valkey and Redis cache backend for Django
|
|
5
5
|
Project-URL: Homepage, https://github.com/oliverhaas/django-cachex
|
|
6
6
|
Project-URL: Documentation, https://oliverhaas.github.io/django-cachex/
|
|
@@ -43,8 +43,6 @@ Provides-Extra: ormsgpack
|
|
|
43
43
|
Requires-Dist: ormsgpack>=1.10.0; extra == 'ormsgpack'
|
|
44
44
|
Provides-Extra: redis-py
|
|
45
45
|
Requires-Dist: redis<9,>=6; extra == 'redis-py'
|
|
46
|
-
Provides-Extra: redis-rs
|
|
47
|
-
Requires-Dist: django-cachex-redis-rs==0.4.2; extra == 'redis-rs'
|
|
48
46
|
Provides-Extra: valkey-glide
|
|
49
47
|
Requires-Dist: valkey-glide-sync<3,>=2.3; extra == 'valkey-glide'
|
|
50
48
|
Requires-Dist: valkey-glide<3,>=2.3; extra == 'valkey-glide'
|
|
@@ -90,7 +88,6 @@ CACHES = {
|
|
|
90
88
|
- Cache stampede prevention (TTL-based XFetch).
|
|
91
89
|
- Two composite backends: `StreamCache` (cross-pod stream-synchronized in-memory cache) and `TieredCache` (L1/L2 with TTL propagation).
|
|
92
90
|
- Django `LocMemCache` and `DatabaseCache` extensions with the same data-structure ops and admin support.
|
|
93
|
-
- Optional Rust I/O driver (PyO3 + tokio + redis-rs) under the same `RespCache` API. Free-threaded CPython (3.14t) supported. Experimental.
|
|
94
91
|
- Optional `valkey-glide` adapter: Valkey's official Rust-cored client, exposed as `ValkeyGlideCache`. Experimental.
|
|
95
92
|
- Django admin UI for browsing keys, inspecting values, editing, and flushing. See below.
|
|
96
93
|
|
|
@@ -132,17 +129,9 @@ Full documentation at [oliverhaas.github.io/django-cachex](https://oliverhaas.gi
|
|
|
132
129
|
- Valkey 7.0+ or Redis 6.0+ on the server (the admin's compare-and-swap
|
|
133
130
|
edits use `SET ... KEEPTTL`, which lands in Redis 6.0)
|
|
134
131
|
|
|
135
|
-
The
|
|
132
|
+
The `valkey-glide` adapter is optional and experimental: interfaces and
|
|
136
133
|
behavior may still change, and it has seen less production testing than
|
|
137
|
-
the redis-py/valkey-py paths.
|
|
138
|
-
extra (`pip install django-cachex[redis-rs]`); this pulls in the
|
|
139
|
-
`django-cachex-redis-rs` companion package. Prebuilt wheels are published
|
|
140
|
-
for Linux x86_64, Linux aarch64, macOS arm64, and Windows amd64, on
|
|
141
|
-
both cp314 and cp314t (free-threaded). Without the extra, the
|
|
142
|
-
`RedisRsCache` backends are unavailable but everything else works.
|
|
143
|
-
|
|
144
|
-
The `valkey-glide` adapter is also optional and experimental, with the
|
|
145
|
-
same caveats. Install with the `valkey-glide` extra
|
|
134
|
+
the redis-py/valkey-py paths. Install with the `valkey-glide` extra
|
|
146
135
|
(`pip install django-cachex[valkey-glide]`) to enable
|
|
147
136
|
`ValkeyGlideCache`; it pulls in `valkey-glide-sync` and `valkey-glide`,
|
|
148
137
|
the official Rust-cored Valkey client. cp314 GIL only; no free-threaded
|
|
@@ -154,7 +143,7 @@ client).
|
|
|
154
143
|
|
|
155
144
|
This project started from [django-redis](https://github.com/jazzband/django-redis) and Django's official [Redis cache backend](https://docs.djangoproject.com/en/stable/topics/cache/#redis). Some serializer and compressor utility code is derived from django-redis, licensed under BSD-3-Clause. The admin UI was inspired by [django-redisboard](https://github.com/ionelmc/django-redisboard).
|
|
156
145
|
|
|
157
|
-
The
|
|
146
|
+
The ASGI benchmark follows the shape of [django-vcache](https://gitlab.com/glitchtip/django-vcache)'s `bench_compare.py` (MIT, by David Burke / GlitchTip), so the numbers are directly comparable.
|
|
158
147
|
|
|
159
148
|
I also want to mention [django-valkey](https://github.com/django-commons/django-valkey) and [dj-cache-panel](https://github.com/yassi/dj-cache-panel), which I never really used, but are newer and interesting efforts of similar goals as this package has.
|
|
160
149
|
|
|
@@ -36,7 +36,6 @@ CACHES = {
|
|
|
36
36
|
- Cache stampede prevention (TTL-based XFetch).
|
|
37
37
|
- Two composite backends: `StreamCache` (cross-pod stream-synchronized in-memory cache) and `TieredCache` (L1/L2 with TTL propagation).
|
|
38
38
|
- Django `LocMemCache` and `DatabaseCache` extensions with the same data-structure ops and admin support.
|
|
39
|
-
- Optional Rust I/O driver (PyO3 + tokio + redis-rs) under the same `RespCache` API. Free-threaded CPython (3.14t) supported. Experimental.
|
|
40
39
|
- Optional `valkey-glide` adapter: Valkey's official Rust-cored client, exposed as `ValkeyGlideCache`. Experimental.
|
|
41
40
|
- Django admin UI for browsing keys, inspecting values, editing, and flushing. See below.
|
|
42
41
|
|
|
@@ -78,17 +77,9 @@ Full documentation at [oliverhaas.github.io/django-cachex](https://oliverhaas.gi
|
|
|
78
77
|
- Valkey 7.0+ or Redis 6.0+ on the server (the admin's compare-and-swap
|
|
79
78
|
edits use `SET ... KEEPTTL`, which lands in Redis 6.0)
|
|
80
79
|
|
|
81
|
-
The
|
|
80
|
+
The `valkey-glide` adapter is optional and experimental: interfaces and
|
|
82
81
|
behavior may still change, and it has seen less production testing than
|
|
83
|
-
the redis-py/valkey-py paths.
|
|
84
|
-
extra (`pip install django-cachex[redis-rs]`); this pulls in the
|
|
85
|
-
`django-cachex-redis-rs` companion package. Prebuilt wheels are published
|
|
86
|
-
for Linux x86_64, Linux aarch64, macOS arm64, and Windows amd64, on
|
|
87
|
-
both cp314 and cp314t (free-threaded). Without the extra, the
|
|
88
|
-
`RedisRsCache` backends are unavailable but everything else works.
|
|
89
|
-
|
|
90
|
-
The `valkey-glide` adapter is also optional and experimental, with the
|
|
91
|
-
same caveats. Install with the `valkey-glide` extra
|
|
82
|
+
the redis-py/valkey-py paths. Install with the `valkey-glide` extra
|
|
92
83
|
(`pip install django-cachex[valkey-glide]`) to enable
|
|
93
84
|
`ValkeyGlideCache`; it pulls in `valkey-glide-sync` and `valkey-glide`,
|
|
94
85
|
the official Rust-cored Valkey client. cp314 GIL only; no free-threaded
|
|
@@ -100,7 +91,7 @@ client).
|
|
|
100
91
|
|
|
101
92
|
This project started from [django-redis](https://github.com/jazzband/django-redis) and Django's official [Redis cache backend](https://docs.djangoproject.com/en/stable/topics/cache/#redis). Some serializer and compressor utility code is derived from django-redis, licensed under BSD-3-Clause. The admin UI was inspired by [django-redisboard](https://github.com/ionelmc/django-redisboard).
|
|
102
93
|
|
|
103
|
-
The
|
|
94
|
+
The ASGI benchmark follows the shape of [django-vcache](https://gitlab.com/glitchtip/django-vcache)'s `bench_compare.py` (MIT, by David Burke / GlitchTip), so the numbers are directly comparable.
|
|
104
95
|
|
|
105
96
|
I also want to mention [django-valkey](https://github.com/django-commons/django-valkey) and [dj-cache-panel](https://github.com/yassi/dj-cache-panel), which I never really used, but are newer and interesting efforts of similar goals as this package has.
|
|
106
97
|
|
|
@@ -15,16 +15,15 @@ depends on letting workloads run).
|
|
|
15
15
|
- `redis-py+hiredis`: C parser
|
|
16
16
|
- `valkey-py`: pure-Python parser
|
|
17
17
|
- `valkey-py+libvalkey`: C parser
|
|
18
|
-
- `
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
but with a thread-pool transport instead of multiplexed). Only available
|
|
22
|
-
on cp314 GIL. No cp314t (free-threaded) wheels yet.
|
|
18
|
+
- `valkey-glide`: `valkey/valkey-glide` Python wheels, Rust-cored with a
|
|
19
|
+
thread-pool transport. Only available on cp314 GIL. No cp314t
|
|
20
|
+
(free-threaded) wheels yet.
|
|
23
21
|
- `django (builtin)`: Django's official built-in `django.core.cache.backends.redis.RedisCache`
|
|
24
22
|
(since 4.0). Not the third-party `jazzband/django-redis` package, which is
|
|
25
23
|
unrelated. Included as an external reference point.
|
|
26
24
|
|
|
27
|
-
**Serializers** (with `
|
|
25
|
+
**Serializers** (with the `valkey-py+libvalkey` adapter, the fastest one that
|
|
26
|
+
is always installed):
|
|
28
27
|
|
|
29
28
|
- `pickle`: stdlib default
|
|
30
29
|
- `json`: Django's `DjangoJSONEncoder`
|
|
@@ -32,7 +31,7 @@ depends on letting workloads run).
|
|
|
32
31
|
- `orjson`: Rust-backed JSON
|
|
33
32
|
- `ormsgpack`: Rust-backed MessagePack
|
|
34
33
|
|
|
35
|
-
**Compressors** get two views, both with `
|
|
34
|
+
**Compressors** get two views, both with `valkey-py+libvalkey` + `pickle`:
|
|
36
35
|
|
|
37
36
|
- *Macro* (`test_compressors_macro`): end-to-end Django cache ops on a
|
|
38
37
|
~14 KiB queryset-shaped payload. Captures the cost of compress/decompress
|
|
@@ -128,7 +127,7 @@ uv run pytest benchmarks/test_throughput.py::test_adapters_async_concurrent -c b
|
|
|
128
127
|
uv run pytest benchmarks/test_throughput.py::test_adapters_asgi -c benchmarks/pytest.ini
|
|
129
128
|
|
|
130
129
|
# A single config
|
|
131
|
-
uv run pytest 'benchmarks/test_throughput.py::test_adapters_sync[
|
|
130
|
+
uv run pytest 'benchmarks/test_throughput.py::test_adapters_sync[valkey-glide]' -c benchmarks/pytest.ini
|
|
132
131
|
```
|
|
133
132
|
|
|
134
133
|
`test_compressors_micro` is the only test that doesn't need Docker, which
|
|
@@ -141,7 +140,7 @@ A summary table prints at the end of the session.
|
|
|
141
140
|
|
|
142
141
|
- **No xdist.** Parallel runs make timings noisy; benchmarks run sequentially.
|
|
143
142
|
- **Redis vs Valkey.** Each adapter is paired with its natural server
|
|
144
|
-
(redis-py → redis, valkey-py /
|
|
143
|
+
(redis-py → redis, valkey-py / valkey-glide → valkey,
|
|
145
144
|
django (builtin) → redis). Cross-pairings are intentionally not in the
|
|
146
145
|
matrix: both servers speak the same protocol, so the comparison is
|
|
147
146
|
mostly a wash.
|
|
@@ -164,7 +163,6 @@ run; ordering is what matters.
|
|
|
164
163
|
| redis-py+hiredis | 2,332 | 2,480 | 2,281 | 1,515 | 1,345 | 2,506 | 1,209 | 51 |
|
|
165
164
|
| valkey-py | 2,783 | 2,956 | 2,695 | 1,595 | 1,418 | 2,978 | 1,437 | 109 |
|
|
166
165
|
| valkey-py+libvalkey | 2,821 | 2,973 | 2,741 | 1,695 | 1,508 | 3,040 | 1,465 | 48 |
|
|
167
|
-
| **redis-rs** | 9,651 | 13,396 | 11,151 | 2,967 | 4,520 | 13,226 | 5,894 | 29 |
|
|
168
166
|
| **valkey-glide** | 6,982 | 8,783 | 6,982 | 2,030 | 1,916 | 8,901 | 3,994 | 29 |
|
|
169
167
|
| django (builtin) | 2,307 | 2,459 | 2,269 | 1,501 | 1,347 | 1,947 | 1,199 | 51 |
|
|
170
168
|
|
|
@@ -178,7 +176,6 @@ One cache op per request through the full middleware/URL/view path.
|
|
|
178
176
|
| redis-py+hiredis | 1,065 | 1,181 | 1,131 | 866 | 807 | 1,168 | 1,173 |
|
|
179
177
|
| valkey-py | 1,089 | 1,299 | 1,241 | 891 | 836 | 1,276 | 1,282 |
|
|
180
178
|
| valkey-py+libvalkey | 1,053 | 1,306 | 1,248 | 924 | 861 | 1,290 | 1,300 |
|
|
181
|
-
| **redis-rs** | 1,382 | 2,044 | 2,001 | 1,265 | 1,490 | 1,995 | 2,005 |
|
|
182
179
|
| **valkey-glide** | 1,237 | 1,863 | 1,753 | 1,023 | 994 | 1,816 | 1,838 |
|
|
183
180
|
| django (builtin) | 861 | 1,177 | 1,133 | 859 | 806 | 1,016 | 1,169 |
|
|
184
181
|
|
|
@@ -192,7 +189,6 @@ One `await` at a time.
|
|
|
192
189
|
| redis-py+hiredis | 1,815 | 1,913 | 1,729 | 1,199 | 849 | 1,911 | 915 |
|
|
193
190
|
| valkey-py | 2,080 | 2,184 | 2,039 | 1,331 | 854 | 2,190 | 1,055 |
|
|
194
191
|
| valkey-py+libvalkey | 2,075 | 2,187 | 2,029 | 1,329 | 852 | 2,176 | 1,049 |
|
|
195
|
-
| **redis-rs** | 6,862 | 8,238 | 7,517 | 2,474 | 3,560 | 8,265 | 3,952 |
|
|
196
192
|
| **valkey-glide** | 3,300 | 3,738 | 3,297 | 1,725 | 1,678 | 3,693 | 1,735 |
|
|
197
193
|
| django (builtin) | 1,948 | 1,995 | 1,929 | 199 | 197 | 989 | 992 |
|
|
198
194
|
|
|
@@ -207,7 +203,6 @@ actually generate.
|
|
|
207
203
|
| redis-py+hiredis | 2,121 | 2,254 | 2,047 | 1,347 | 931 | 2,149 | 979 | 106 |
|
|
208
204
|
| valkey-py | 2,465 | 2,591 | 2,327 | 1,229 | 920 | 2,569 | 1,130 | 58 |
|
|
209
205
|
| valkey-py+libvalkey | 2,467 | 2,588 | 2,329 | 1,223 | 917 | 2,564 | 1,129 | 108 |
|
|
210
|
-
| **redis-rs** | 22,335 | 35,848 | 28,528 | 2,508 | 6,533 | 39,406 | 5,543 | 108 |
|
|
211
206
|
| **valkey-glide** | 10,149 | 12,575 | 10,045 | 2,074 | 2,607 | 12,232 | 2,627 | 109 |
|
|
212
207
|
| django (builtin) | 2,078 | 2,177 | 2,076 | 212 | 210 | 1,051 | 1,018 | 107 |
|
|
213
208
|
|
|
@@ -222,36 +217,28 @@ six async cache ops, the shape closest to real production load.
|
|
|
222
217
|
| redis-py+hiredis | 467 | 213 | 1,509 | 414 | 209 | 209 |
|
|
223
218
|
| valkey-py | 519 | 192 | 1,375 | 420 | 211 | 211 |
|
|
224
219
|
| valkey-py+libvalkey | 498 | 200 | 1,599 | 432 | 211 | 211 |
|
|
225
|
-
| **redis-rs** | 607 | 164 | 1,152 | 430 | 115 | 115 |
|
|
226
220
|
| **valkey-glide** | 553 | 180 | 1,395 | 446 | 172 | 172 |
|
|
227
221
|
| django (builtin) | 156 | 634 | 3,117 | 466 | 337 | 337 |
|
|
228
222
|
|
|
229
223
|
### Takeaways
|
|
230
224
|
|
|
231
|
-
- **Sync direct.** `
|
|
232
|
-
/
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
-
|
|
242
|
-
Python
|
|
243
|
-
is also faster than Python (~1.5–1.8×) but trails `redis-rs`.
|
|
244
|
-
- **Async concurrent (50 in flight).** `redis-rs` peaks at **22k get /
|
|
245
|
-
36k get-miss / 39k incr** ops/sec, which is **9–18×** the fastest Python
|
|
246
|
-
adapter. `valkey-glide` is half that rate but still **~4×** ahead of
|
|
247
|
-
the Python adapters.
|
|
225
|
+
- **Sync direct.** `valkey-glide` leads every phase at **~7k get / 7k set
|
|
226
|
+
/ 8.9k incr / 4k delete** ops/sec, ~2.5× the fastest pure-Python adapter,
|
|
227
|
+
and uses ~4× less Python memory.
|
|
228
|
+
- **Django request cycle.** `valkey-glide` leads at ~1.2–1.9k ops/sec.
|
|
229
|
+
An earlier version failed this benchmark entirely because ``close()``
|
|
230
|
+
was tearing down the connection on every ``request_finished`` signal;
|
|
231
|
+
now it outperforms the Python adapters.
|
|
232
|
+
- **Async serial.** `valkey-glide` runs ~1.5–1.8× faster than the C-parser
|
|
233
|
+
Python adapters on every phase (3.3k get, 3.7k incr).
|
|
234
|
+
- **Async concurrent (50 in flight).** `valkey-glide` peaks at **10k get /
|
|
235
|
+
12.5k get-miss / 12.2k incr** ops/sec, roughly **4–5×** the fastest
|
|
236
|
+
Python adapter.
|
|
248
237
|
- **ASGI full-stack** (granian × 4 workers, httpx × 100 concurrent).
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
surfaced 1,111 / 4,577 conn counts) brought the Rust adapters in
|
|
254
|
-
line with the multiplexed-transport claim.
|
|
238
|
+
`valkey-glide` leads on req/s at 553 (180 ms avg, 1.4 s p99) and uses
|
|
239
|
+
fewer connections than every Python adapter (172 vs ~210). Process-wide
|
|
240
|
+
client sharing, added after this benchmark first surfaced 4,577 conn
|
|
241
|
+
counts, brought it in line with its transport's claim.
|
|
255
242
|
- **Connection stability.** Across every shape the cachex path keeps
|
|
256
243
|
`Δ` at 0 between phases, so there are no per-phase connection leaks on
|
|
257
244
|
any adapter.
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
-
from pkgutil import extend_path
|
|
3
|
-
|
|
4
|
-
# Extend the package path so the optional django-cachex-redis-rs binary package
|
|
5
|
-
# (which ships ``adapters/_redis_rs*`` files into this namespace) is
|
|
6
|
-
# discovered when both packages are installed side by side.
|
|
7
|
-
__path__ = extend_path(__path__, __name__)
|
|
8
2
|
|
|
9
3
|
try:
|
|
10
4
|
__version__ = version("django-cachex")
|
|
@@ -19,7 +13,7 @@ from django_cachex.exceptions import (
|
|
|
19
13
|
SerializerError,
|
|
20
14
|
WrongTypeError,
|
|
21
15
|
)
|
|
22
|
-
from django_cachex.lock import
|
|
16
|
+
from django_cachex.lock import LockError, LockNotOwnedError
|
|
23
17
|
from django_cachex.script import (
|
|
24
18
|
ScriptHelpers,
|
|
25
19
|
decode_list_post,
|
|
@@ -35,11 +29,9 @@ from django_cachex.semaphore import (
|
|
|
35
29
|
from django_cachex.stampede import StampedeConfig
|
|
36
30
|
|
|
37
31
|
__all__ = [
|
|
38
|
-
"AsyncLock",
|
|
39
32
|
"AsyncPipeline",
|
|
40
33
|
"CachexError",
|
|
41
34
|
"CompressorError",
|
|
42
|
-
"Lock",
|
|
43
35
|
"LockError",
|
|
44
36
|
"LockNotOwnedError",
|
|
45
37
|
"NotSupportedError",
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
"""Adapter layer: low-level Redis/Valkey ops per driver.
|
|
2
2
|
|
|
3
3
|
Each adapter wraps a specific underlying client library (redis-py,
|
|
4
|
-
valkey-py,
|
|
5
|
-
|
|
4
|
+
valkey-py, valkey-glide) and exposes the operation surface that
|
|
5
|
+
``RespCache`` delegates to.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from pkgutil import extend_path
|
|
9
|
-
|
|
10
|
-
# Extend the sub-package path so the optional ``django-cachex-redis-rs``
|
|
11
|
-
# binary package (which ships ``_redis_rs*`` files into this namespace)
|
|
12
|
-
# is discovered when the two packages are installed under different
|
|
13
|
-
# prefixes.
|
|
14
|
-
__path__ = extend_path(__path__, __name__)
|
|
15
|
-
|
|
16
8
|
from django_cachex.adapters.pipeline import AsyncPipeline, Pipeline
|
|
17
9
|
from django_cachex.adapters.protocols import (
|
|
18
10
|
RespAdapterProtocol,
|
|
@@ -26,13 +18,6 @@ from django_cachex.adapters.redis_py import (
|
|
|
26
18
|
RedisPyPipelineAdapter,
|
|
27
19
|
RedisPySentinelAdapter,
|
|
28
20
|
)
|
|
29
|
-
from django_cachex.adapters.redis_rs import (
|
|
30
|
-
RedisRsAdapter,
|
|
31
|
-
RedisRsAsyncPipelineAdapter,
|
|
32
|
-
RedisRsClusterAdapter,
|
|
33
|
-
RedisRsPipelineAdapter,
|
|
34
|
-
RedisRsSentinelAdapter,
|
|
35
|
-
)
|
|
36
21
|
from django_cachex.adapters.valkey_glide import (
|
|
37
22
|
ValkeyGlideAdapter,
|
|
38
23
|
ValkeyGlideAsyncPipelineAdapter,
|
|
@@ -55,11 +40,6 @@ __all__ = [
|
|
|
55
40
|
"RedisPyClusterAdapter",
|
|
56
41
|
"RedisPyPipelineAdapter",
|
|
57
42
|
"RedisPySentinelAdapter",
|
|
58
|
-
"RedisRsAdapter",
|
|
59
|
-
"RedisRsAsyncPipelineAdapter",
|
|
60
|
-
"RedisRsClusterAdapter",
|
|
61
|
-
"RedisRsPipelineAdapter",
|
|
62
|
-
"RedisRsSentinelAdapter",
|
|
63
43
|
"RespAdapterProtocol",
|
|
64
44
|
"RespAsyncPipelineProtocol",
|
|
65
45
|
"RespPipelineProtocol",
|
|
@@ -8,8 +8,6 @@ implementation, one per driver:
|
|
|
8
8
|
- :class:`~django_cachex.adapters.valkey_py.ValkeyPyPipelineAdapter` /
|
|
9
9
|
:class:`~django_cachex.adapters.redis_py.RedisPyPipelineAdapter`: wrap a
|
|
10
10
|
redis-py / valkey-py / cluster ``Pipeline`` object.
|
|
11
|
-
- :class:`~django_cachex.adapters.redis_rs.RedisRsPipelineAdapter`:
|
|
12
|
-
buffers RESP wire commands for the Rust driver's ``pipeline_exec``.
|
|
13
11
|
- :class:`~django_cachex.adapters.valkey_glide.ValkeyGlidePipelineAdapter`:
|
|
14
12
|
drives ``valkey-glide``'s ``Batch``.
|
|
15
13
|
|
|
@@ -1606,8 +1604,8 @@ class Pipeline:
|
|
|
1606
1604
|
class AsyncPipeline(Pipeline):
|
|
1607
1605
|
"""Async sibling of :class:`Pipeline`: same chainable API, awaitable ``execute()``.
|
|
1608
1606
|
|
|
1609
|
-
Driver async pipelines (``redis.asyncio`` ``Pipeline``, glide async ``Batch
|
|
1610
|
-
|
|
1607
|
+
Driver async pipelines (``redis.asyncio`` ``Pipeline``, glide async ``Batch``)
|
|
1608
|
+
all expose the same chainable command surface
|
|
1611
1609
|
as their sync counterparts; only execution does I/O. So this subclass
|
|
1612
1610
|
inherits every queueing method from :class:`Pipeline` and only overrides
|
|
1613
1611
|
the lifecycle (``__aenter__/__aexit__``) and ``execute()`` to be async.
|
|
@@ -11,7 +11,6 @@ pipeline layers rely on.
|
|
|
11
11
|
:class:`~django_cachex.cache.resp.RespCache` calls on its
|
|
12
12
|
underlying adapter. Concrete adapters
|
|
13
13
|
(:class:`~django_cachex.adapters.valkey_py.ValkeyPyAdapter`,
|
|
14
|
-
:class:`~django_cachex.adapters.redis_rs.RedisRsAdapter`,
|
|
15
14
|
:class:`~django_cachex.adapters.valkey_glide.ValkeyGlideAdapter`)
|
|
16
15
|
inherit from this Protocol so the contract is explicit at the class
|
|
17
16
|
declaration; the inherited method bodies (``...``) are shadowed by each
|
|
@@ -67,7 +67,7 @@ _set = set
|
|
|
67
67
|
# process-wide registry every async cache call would open a brand-new
|
|
68
68
|
# TCP connection, which is slow on the hot path and noisy on the server. Sharing
|
|
69
69
|
# pools at the module level by event loop + config keeps connections
|
|
70
|
-
# reused across tasks
|
|
70
|
+
# reused across tasks.
|
|
71
71
|
#
|
|
72
72
|
# The registry itself lives on each driver-specific adapter class as the
|
|
73
73
|
# ``_async_pools`` class attribute (see :mod:`~django_cachex.adapters.redis_py`
|
|
@@ -375,7 +375,7 @@ class ValkeyPyAdapter(RespAdapterProtocol):
|
|
|
375
375
|
"""Get an async client connection.
|
|
376
376
|
|
|
377
377
|
``async def`` for Protocol uniformity: adapters whose async-client
|
|
378
|
-
construction is genuinely async (glide
|
|
378
|
+
construction is genuinely async (glide) ``await`` here;
|
|
379
379
|
for redis-py / valkey-py the body is sync (pool lookup +
|
|
380
380
|
``Redis(connection_pool=...)``) since the connection opens
|
|
381
381
|
lazily on the first awaited command.
|
|
@@ -10,11 +10,6 @@ from django_cachex.cache.redis_py import (
|
|
|
10
10
|
RedisClusterCache,
|
|
11
11
|
RedisSentinelCache,
|
|
12
12
|
)
|
|
13
|
-
from django_cachex.cache.redis_rs import (
|
|
14
|
-
RedisRsCache,
|
|
15
|
-
RedisRsClusterCache,
|
|
16
|
-
RedisRsSentinelCache,
|
|
17
|
-
)
|
|
18
13
|
from django_cachex.cache.resp import RespCache, RespClusterCache, RespSentinelCache
|
|
19
14
|
from django_cachex.cache.stream import StreamCache
|
|
20
15
|
from django_cachex.cache.tiered import TieredCache
|
|
@@ -30,9 +25,6 @@ __all__ = [
|
|
|
30
25
|
"LocMemCache",
|
|
31
26
|
"RedisCache",
|
|
32
27
|
"RedisClusterCache",
|
|
33
|
-
"RedisRsCache",
|
|
34
|
-
"RedisRsClusterCache",
|
|
35
|
-
"RedisRsSentinelCache",
|
|
36
28
|
"RedisSentinelCache",
|
|
37
29
|
"RespCache",
|
|
38
30
|
"RespClusterCache",
|
|
@@ -7,7 +7,6 @@ concrete subclasses live in:
|
|
|
7
7
|
|
|
8
8
|
- :mod:`django_cachex.cache.valkey_py`: ``valkey-py``
|
|
9
9
|
- :mod:`django_cachex.cache.redis_py`: ``redis-py``
|
|
10
|
-
- :mod:`django_cachex.cache.redis_rs`: Rust ``redis-rs`` driver
|
|
11
10
|
- :mod:`django_cachex.cache.valkey_glide`: ``valkey-glide``
|
|
12
11
|
"""
|
|
13
12
|
|
|
@@ -72,7 +72,7 @@ class WrongTypeError(CachexError, TypeError):
|
|
|
72
72
|
of value``. Subclasses both :class:`CachexError` and :class:`TypeError`,
|
|
73
73
|
so ``except CachexError`` and existing ``except TypeError`` callers both
|
|
74
74
|
keep working while new code can catch this specifically across backends
|
|
75
|
-
(LocMem, redis-py, valkey-py, valkey-glide
|
|
75
|
+
(LocMem, redis-py, valkey-py, valkey-glide).
|
|
76
76
|
"""
|
|
77
77
|
|
|
78
78
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Exceptions every adapter's ``cache.lock()`` object raises, whichever it is."""
|
|
2
|
+
|
|
3
|
+
from django_cachex.exceptions import CachexError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LockError(CachexError):
|
|
7
|
+
"""Raised when a lock operation fails."""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LockNotOwnedError(LockError):
|
|
11
|
+
"""Raised when releasing or extending a lock the caller no longer owns."""
|
|
@@ -7,7 +7,7 @@ rest of the project's convention (``foo``/``afoo``):
|
|
|
7
7
|
``_SemaphoreRegistry`` shared by every cache with the same LOCATION;
|
|
8
8
|
standalone instances share a process-wide registry.
|
|
9
9
|
- :class:`RespSemaphore`: backed by Lua scripts dispatched through any
|
|
10
|
-
``RespAdapterProtocol`` (redis-py,
|
|
10
|
+
``RespAdapterProtocol`` (redis-py, valkey-py, valkey-glide).
|
|
11
11
|
Constructed by ``cache.semaphore(...)`` / ``cache.asemaphore(...)`` and not
|
|
12
12
|
exposed at the package root.
|
|
13
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "django-cachex"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = "Full featured Valkey and Redis cache backend for Django"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -32,9 +32,6 @@ valkey-py = ["valkey>=6.1.0,<7"]
|
|
|
32
32
|
libvalkey = ["valkey[libvalkey]>=6.1.0,<7"]
|
|
33
33
|
redis-py = ["redis>=6,<9"]
|
|
34
34
|
hiredis = ["redis[hiredis]<9,>=6"]
|
|
35
|
-
# Rust I/O driver: separate binary package, prebuilt wheels for Linux x86_64/aarch64,
|
|
36
|
-
# macOS arm64, and Windows amd64 (cp314 and cp314t).
|
|
37
|
-
redis-rs = ["django-cachex-redis-rs==0.4.2"]
|
|
38
35
|
# valkey-glide: Rust-cored Valkey client. Sync and async are separate distributions.
|
|
39
36
|
valkey-glide = ["valkey-glide-sync>=2.3,<3", "valkey-glide>=2.3,<3"]
|
|
40
37
|
# Compressors
|
|
@@ -58,7 +55,6 @@ dev = [
|
|
|
58
55
|
"django-stubs==6.1.0",
|
|
59
56
|
"djlint==1.44.2",
|
|
60
57
|
"lz4==4.4.5",
|
|
61
|
-
"maturin==1.14.1",
|
|
62
58
|
"msgpack==1.2.1",
|
|
63
59
|
"ormsgpack==1.12.2",
|
|
64
60
|
"mypy==2.3.0",
|
|
@@ -77,8 +73,6 @@ dev = [
|
|
|
77
73
|
# ASGI benchmark only: granian (real ASGI server) plus httpx (load gen).
|
|
78
74
|
"granian>=2.6,<3",
|
|
79
75
|
"httpx>=0.28,<0.29",
|
|
80
|
-
# Rust I/O driver: workspace member so `uv sync` builds it for tests/benchmarks
|
|
81
|
-
"django-cachex-redis-rs",
|
|
82
76
|
# Full example: workspace member so its deps (notably celery) survive
|
|
83
77
|
# ``uv sync``, which the pre-commit hook runs on every commit.
|
|
84
78
|
"django-cachex-full-example",
|
|
@@ -96,20 +90,14 @@ build-backend = "hatchling.build"
|
|
|
96
90
|
|
|
97
91
|
[tool.hatch.build.targets.wheel]
|
|
98
92
|
packages = ["django_cachex"]
|
|
99
|
-
# _redis_rs.pyi is the type stub for the optional Rust extension. It lives
|
|
100
|
-
# alongside django_cachex source so type checkers find it during dev, but
|
|
101
|
-
# it ships with the django-cachex-redis-rs binary package, not this one.
|
|
102
|
-
exclude = ["**/_redis_rs.pyi"]
|
|
103
93
|
|
|
104
94
|
[tool.hatch.build.targets.sdist]
|
|
105
95
|
include = ["django_cachex/**", "README.md", "LICENSE", "pyproject.toml"]
|
|
106
|
-
exclude = ["**/_redis_rs.pyi"]
|
|
107
96
|
|
|
108
97
|
[tool.uv.workspace]
|
|
109
|
-
members = ["
|
|
98
|
+
members = ["examples/full"]
|
|
110
99
|
|
|
111
100
|
[tool.uv.sources]
|
|
112
|
-
django-cachex-redis-rs = { workspace = true }
|
|
113
101
|
django-cachex-full-example = { workspace = true }
|
|
114
102
|
|
|
115
103
|
[tool.ruff]
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Oliver Haas <ohaas@e1plus.de>
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# django-cachex-redis-rs
|
|
2
|
-
|
|
3
|
-
Rust adapter for [django-cachex], built on PyO3 + tokio + [redis-rs].
|
|
4
|
-
|
|
5
|
-
This is a binary-only companion package that ships the compiled
|
|
6
|
-
`_redis_rs` extension module into the `django_cachex.adapters`
|
|
7
|
-
namespace. Install via the `redis-rs` extra on the main package:
|
|
8
|
-
|
|
9
|
-
```console
|
|
10
|
-
pip install django-cachex[redis-rs]
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Prebuilt wheels are published for Linux x86_64, Linux aarch64, macOS
|
|
14
|
-
arm64, and Windows amd64, on both cp314 and cp314t (free-threaded). On
|
|
15
|
-
other platforms there's no wheel, so pip will try to build from source
|
|
16
|
-
(requires the Rust toolchain) or fail clearly.
|
|
17
|
-
|
|
18
|
-
The pure-Python `django-cachex` package is fully usable on its own; this
|
|
19
|
-
binary just unlocks the `RedisRsCache` family of
|
|
20
|
-
backends.
|
|
21
|
-
|
|
22
|
-
[django-cachex]: https://github.com/oliverhaas/django-cachex
|
|
23
|
-
[redis-rs]: https://github.com/redis-rs/redis-rs
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "django-cachex-redis-rs"
|
|
3
|
-
version = "0.4.2"
|
|
4
|
-
description = "Rust adapter (PyO3 + tokio + redis-rs) for django-cachex"
|
|
5
|
-
readme = "README.md"
|
|
6
|
-
license = { text = "MIT" }
|
|
7
|
-
requires-python = ">=3.14"
|
|
8
|
-
authors = [{ name = "Oliver Haas", email = "ohaas@e1plus.de" }]
|
|
9
|
-
keywords = ["django", "valkey", "redis", "cache", "rust"]
|
|
10
|
-
classifiers = [
|
|
11
|
-
"Development Status :: 4 - Beta",
|
|
12
|
-
"Environment :: Web Environment",
|
|
13
|
-
"Framework :: Django",
|
|
14
|
-
"Framework :: Django :: 6.0",
|
|
15
|
-
"Intended Audience :: Developers",
|
|
16
|
-
"License :: OSI Approved :: MIT License",
|
|
17
|
-
"Operating System :: MacOS",
|
|
18
|
-
"Operating System :: Microsoft :: Windows",
|
|
19
|
-
"Operating System :: POSIX :: Linux",
|
|
20
|
-
"Programming Language :: Python",
|
|
21
|
-
"Programming Language :: Python :: 3",
|
|
22
|
-
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
-
"Programming Language :: Python :: 3.14",
|
|
24
|
-
"Programming Language :: Python :: Free Threading :: 1 - Unstable",
|
|
25
|
-
"Programming Language :: Rust",
|
|
26
|
-
"Topic :: Internet :: WWW/HTTP",
|
|
27
|
-
"Topic :: Software Development :: Libraries",
|
|
28
|
-
"Topic :: Utilities",
|
|
29
|
-
"Typing :: Typed",
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
[project.urls]
|
|
33
|
-
Homepage = "https://github.com/oliverhaas/django-cachex"
|
|
34
|
-
Repository = "https://github.com/oliverhaas/django-cachex.git"
|
|
35
|
-
|
|
36
|
-
[build-system]
|
|
37
|
-
requires = ["maturin>=1.13,<2.0"]
|
|
38
|
-
build-backend = "maturin"
|
|
39
|
-
|
|
40
|
-
[tool.maturin]
|
|
41
|
-
module-name = "django_cachex.adapters._redis_rs"
|
|
42
|
-
features = ["pyo3/extension-module"]
|
|
43
|
-
python-source = "python"
|
|
44
|
-
manifest-path = "Cargo.toml"
|
|
45
|
-
include = ["LICENSE"]
|