coredis 4.24.0__tar.gz → 5.0.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.
Potentially problematic release.
This version of coredis might be problematic. Click here for more details.
- {coredis-4.24.0 → coredis-5.0.0}/HISTORY.rst +60 -0
- {coredis-4.24.0/coredis.egg-info → coredis-5.0.0}/PKG-INFO +4 -9
- {coredis-4.24.0 → coredis-5.0.0}/README.md +1 -5
- {coredis-4.24.0 → coredis-5.0.0}/coredis/__init__.py +1 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/_packer.py +10 -10
- coredis-5.0.0/coredis/_protocols.py +50 -0
- coredis-5.0.0/coredis/_py_311_typing.py +20 -0
- coredis-5.0.0/coredis/_py_312_typing.py +17 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/_utils.py +49 -55
- {coredis-4.24.0 → coredis-5.0.0}/coredis/_version.py +3 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/cache.py +57 -82
- coredis-5.0.0/coredis/client/__init__.py +6 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/client/basic.py +129 -56
- {coredis-4.24.0 → coredis-5.0.0}/coredis/client/cluster.py +147 -70
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/__init__.py +27 -7
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/_key_spec.py +11 -10
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/_utils.py +1 -1
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/_validators.py +30 -20
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/_wrappers.py +19 -99
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/bitfield.py +10 -2
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/constants.py +20 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/core.py +1674 -1251
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/function.py +21 -19
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/monitor.py +0 -71
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/pubsub.py +7 -142
- coredis-5.0.0/coredis/commands/request.py +108 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/script.py +21 -22
- {coredis-4.24.0 → coredis-5.0.0}/coredis/commands/sentinel.py +60 -49
- {coredis-4.24.0 → coredis-5.0.0}/coredis/connection.py +14 -15
- {coredis-4.24.0 → coredis-5.0.0}/coredis/exceptions.py +2 -2
- coredis-5.0.0/coredis/experimental/__init__.py +1 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/globals.py +3 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/autocomplete.py +28 -30
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/base.py +15 -31
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/filters.py +269 -245
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/graph.py +61 -62
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/json.py +172 -140
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/_callbacks/autocomplete.py +5 -4
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/_callbacks/graph.py +34 -29
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/_callbacks/json.py +5 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/_callbacks/search.py +49 -53
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/_callbacks/timeseries.py +18 -30
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/types.py +1 -5
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/search.py +186 -169
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/timeseries.py +184 -164
- {coredis-4.24.0 → coredis-5.0.0}/coredis/parser.py +6 -19
- {coredis-4.24.0 → coredis-5.0.0}/coredis/pipeline.py +477 -521
- {coredis-4.24.0 → coredis-5.0.0}/coredis/pool/basic.py +7 -7
- {coredis-4.24.0 → coredis-5.0.0}/coredis/pool/cluster.py +3 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/pool/nodemanager.py +10 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/__init__.py +76 -57
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/acl.py +0 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/cluster.py +25 -16
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/command.py +8 -6
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/connection.py +4 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/geo.py +17 -13
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/hash.py +13 -11
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/keys.py +9 -5
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/module.py +2 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/script.py +6 -8
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/sentinel.py +21 -17
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/server.py +36 -14
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/sets.py +3 -4
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/sorted_set.py +27 -24
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/streams.py +22 -13
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_callbacks/strings.py +7 -6
- coredis-5.0.0/coredis/response/_callbacks/vector_sets.py +159 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/types.py +13 -4
- {coredis-4.24.0 → coredis-5.0.0}/coredis/retry.py +12 -13
- {coredis-4.24.0 → coredis-5.0.0}/coredis/sentinel.py +11 -1
- {coredis-4.24.0 → coredis-5.0.0}/coredis/stream.py +4 -3
- {coredis-4.24.0 → coredis-5.0.0}/coredis/tokens.py +348 -16
- coredis-5.0.0/coredis/typing.py +580 -0
- {coredis-4.24.0 → coredis-5.0.0/coredis.egg-info}/PKG-INFO +4 -9
- {coredis-4.24.0 → coredis-5.0.0}/coredis.egg-info/SOURCES.txt +4 -2
- {coredis-4.24.0 → coredis-5.0.0}/coredis.egg-info/requires.txt +2 -2
- {coredis-4.24.0 → coredis-5.0.0}/pyproject.toml +3 -2
- {coredis-4.24.0 → coredis-5.0.0}/requirements/dev.txt +1 -1
- {coredis-4.24.0 → coredis-5.0.0}/requirements/docs.txt +1 -1
- {coredis-4.24.0 → coredis-5.0.0}/requirements/main.txt +2 -2
- {coredis-4.24.0 → coredis-5.0.0}/setup.py +0 -1
- coredis-4.24.0/coredis/_protocols.py +0 -82
- coredis-4.24.0/coredis/client/__init__.py +0 -7
- coredis-4.24.0/coredis/client/keydb.py +0 -336
- coredis-4.24.0/coredis/experimental/__init__.py +0 -5
- coredis-4.24.0/coredis/pipeline.pyi +0 -2103
- coredis-4.24.0/coredis/typing.py +0 -229
- {coredis-4.24.0 → coredis-5.0.0}/LICENSE +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/MANIFEST.in +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/_json.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/_sidecar.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/config.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/constants.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/credentials.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/modules/response/_callbacks/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/pool/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/py.typed +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/credentials/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/credentials/iam_provider.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/locks/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/locks/extend.lua +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/locks/lua_lock.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/recipes/locks/release.lua +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/__init__.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/response/_utils.py +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/speedups.c +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis/speedups.pyi +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis.egg-info/dependency_links.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/coredis.egg-info/top_level.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/requirements/ci.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/requirements/dev_extra.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/requirements/publishing.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/requirements/recipes.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/requirements/test.txt +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/setup.cfg +0 -0
- {coredis-4.24.0 → coredis-5.0.0}/versioneer.py +0 -0
|
@@ -3,6 +3,63 @@
|
|
|
3
3
|
Changelog
|
|
4
4
|
=========
|
|
5
5
|
|
|
6
|
+
v5.0.0
|
|
7
|
+
------
|
|
8
|
+
Release Date: 2025-07-16
|
|
9
|
+
|
|
10
|
+
* Features
|
|
11
|
+
|
|
12
|
+
* Add support for using custom types with redis commands
|
|
13
|
+
by registering serializers and deserializers
|
|
14
|
+
* Allow stacking pipeline commands synchronously
|
|
15
|
+
* Expose statically typed responses for pipeline commands
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
* Compatibility
|
|
19
|
+
|
|
20
|
+
* Redis command methods are no longer coroutines and instead
|
|
21
|
+
synchronous methods that return subclasses of ``Awaitable``
|
|
22
|
+
(``CommandRequest``) which can be awaited as before.
|
|
23
|
+
* Add support for redis 8.0 vector set commands
|
|
24
|
+
* Add support for redis 8.0 hash expiry commands
|
|
25
|
+
* Remove deprecated pubsub ``listen`` and threaded worker APIs
|
|
26
|
+
* Remove support for KeyDB
|
|
27
|
+
|
|
28
|
+
* Performance
|
|
29
|
+
|
|
30
|
+
* Streamline client side cache shrinking
|
|
31
|
+
|
|
32
|
+
v5.0.0rc2
|
|
33
|
+
---------
|
|
34
|
+
Release Date: 2025-07-10
|
|
35
|
+
|
|
36
|
+
* Bug Fix
|
|
37
|
+
|
|
38
|
+
* Fix duplicate command error in using ``transform`` with pipeline
|
|
39
|
+
|
|
40
|
+
v5.0.0rc1
|
|
41
|
+
---------
|
|
42
|
+
Release Date: 2025-07-07
|
|
43
|
+
|
|
44
|
+
* Features
|
|
45
|
+
|
|
46
|
+
* Add support for using custom types with redis commands
|
|
47
|
+
by registering serializers and deserializers
|
|
48
|
+
* Allow stacking pipeline commands syncronously
|
|
49
|
+
* Expose statically types responses for pipeline commands
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
* Compatibility
|
|
53
|
+
|
|
54
|
+
* Add support for redis 8.0 vector set commands
|
|
55
|
+
* Add support for redis 8.0 hash expiry commands
|
|
56
|
+
* Remove deprecated pubsub ``listen`` and threaded worker APIs
|
|
57
|
+
* Remove support for KeyDB
|
|
58
|
+
|
|
59
|
+
* Performance
|
|
60
|
+
|
|
61
|
+
* Streamline client side cache shrinking
|
|
62
|
+
|
|
6
63
|
v4.24.0
|
|
7
64
|
-------
|
|
8
65
|
Release Date: 2025-07-05
|
|
@@ -1939,3 +1996,6 @@ v1.0.1
|
|
|
1939
1996
|
|
|
1940
1997
|
|
|
1941
1998
|
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coredis
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.0
|
|
4
4
|
Summary: Python async client for Redis key-value store
|
|
5
5
|
Home-page: https://github.com/alisaifee/coredis
|
|
6
6
|
Author: Ali-Akber Saifee
|
|
@@ -14,7 +14,6 @@ Project-URL: Documentation, https://coredis.readthedocs.org
|
|
|
14
14
|
Keywords: Redis,key-value store,asyncio
|
|
15
15
|
Classifier: Development Status :: 5 - Production/Stable
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
|
17
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
18
17
|
Classifier: Operating System :: OS Independent
|
|
19
18
|
Classifier: Programming Language :: Python
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -26,11 +25,11 @@ Requires-Python: >=3.10
|
|
|
26
25
|
Description-Content-Type: text/markdown
|
|
27
26
|
License-File: LICENSE
|
|
28
27
|
Requires-Dist: async_timeout<6,>4
|
|
28
|
+
Requires-Dist: beartype>=0.20
|
|
29
29
|
Requires-Dist: deprecated>=1.2
|
|
30
|
-
Requires-Dist: typing_extensions>=4.
|
|
30
|
+
Requires-Dist: typing_extensions>=4.13
|
|
31
31
|
Requires-Dist: packaging<26,>=21
|
|
32
32
|
Requires-Dist: pympler<2,>1
|
|
33
|
-
Requires-Dist: wrapt<2,>=1.1.0
|
|
34
33
|
Provides-Extra: recipes
|
|
35
34
|
Requires-Dist: aiobotocore>=2.15.2; extra == "recipes"
|
|
36
35
|
Requires-Dist: asyncache>=0.3.1; extra == "recipes"
|
|
@@ -80,9 +79,6 @@ coredis is an async redis client with support for redis server, cluster & sentin
|
|
|
80
79
|
and the [API Documentation](https://coredis.readthedocs.io/en/latest/api/index.html)
|
|
81
80
|
for more details.
|
|
82
81
|
|
|
83
|
-
> **Warning**
|
|
84
|
-
> The command API does NOT mirror the official python [redis client](https://github.com/redis/redis-py). For details about the high level differences refer to [Divergence from aredis & redis-py](https://coredis.readthedocs.io/en/latest/history.html#divergence-from-aredis-redis-py)
|
|
85
|
-
|
|
86
82
|
______________________________________________________________________
|
|
87
83
|
|
|
88
84
|
<!-- TOC depthFrom:2 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
|
|
@@ -201,7 +197,7 @@ Details about supported Redis modules and their commands can be found
|
|
|
201
197
|
|
|
202
198
|
## Compatibility
|
|
203
199
|
|
|
204
|
-
coredis is tested against redis versions >= `
|
|
200
|
+
coredis is tested against redis versions >= `7.0`
|
|
205
201
|
The test matrix status can be reviewed
|
|
206
202
|
[here](https://github.com/alisaifee/coredis/actions/workflows/main.yml)
|
|
207
203
|
|
|
@@ -221,7 +217,6 @@ coredis is additionally tested against:
|
|
|
221
217
|
|
|
222
218
|
**coredis** is known to work with the following databases that have redis protocol compatibility:
|
|
223
219
|
|
|
224
|
-
- [KeyDB](https://docs.keydb.dev/)
|
|
225
220
|
- [Dragonfly](https://dragonflydb.io/)
|
|
226
221
|
- [Redict](https://redict.io/)
|
|
227
222
|
- [Valkey](https://github.com/valkey-io/valkey)
|
|
@@ -27,9 +27,6 @@ coredis is an async redis client with support for redis server, cluster & sentin
|
|
|
27
27
|
and the [API Documentation](https://coredis.readthedocs.io/en/latest/api/index.html)
|
|
28
28
|
for more details.
|
|
29
29
|
|
|
30
|
-
> **Warning**
|
|
31
|
-
> The command API does NOT mirror the official python [redis client](https://github.com/redis/redis-py). For details about the high level differences refer to [Divergence from aredis & redis-py](https://coredis.readthedocs.io/en/latest/history.html#divergence-from-aredis-redis-py)
|
|
32
|
-
|
|
33
30
|
______________________________________________________________________
|
|
34
31
|
|
|
35
32
|
<!-- TOC depthFrom:2 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 -->
|
|
@@ -148,7 +145,7 @@ Details about supported Redis modules and their commands can be found
|
|
|
148
145
|
|
|
149
146
|
## Compatibility
|
|
150
147
|
|
|
151
|
-
coredis is tested against redis versions >= `
|
|
148
|
+
coredis is tested against redis versions >= `7.0`
|
|
152
149
|
The test matrix status can be reviewed
|
|
153
150
|
[here](https://github.com/alisaifee/coredis/actions/workflows/main.yml)
|
|
154
151
|
|
|
@@ -168,7 +165,6 @@ coredis is additionally tested against:
|
|
|
168
165
|
|
|
169
166
|
**coredis** is known to work with the following databases that have redis protocol compatibility:
|
|
170
167
|
|
|
171
|
-
- [KeyDB](https://docs.keydb.dev/)
|
|
172
168
|
- [Dragonfly](https://dragonflydb.io/)
|
|
173
169
|
- [Redict](https://redict.io/)
|
|
174
170
|
- [Valkey](https://github.com/valkey-io/valkey)
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
from typing import cast
|
|
12
12
|
|
|
13
|
-
from coredis.client import
|
|
13
|
+
from coredis.client import Redis, RedisCluster
|
|
14
14
|
from coredis.config import Config
|
|
15
15
|
from coredis.connection import (
|
|
16
16
|
BaseConnection,
|
|
@@ -30,8 +30,6 @@ from . import _version
|
|
|
30
30
|
|
|
31
31
|
__all__ = [
|
|
32
32
|
"Config",
|
|
33
|
-
"KeyDB",
|
|
34
|
-
"KeyDBCluster",
|
|
35
33
|
"Redis",
|
|
36
34
|
"RedisCluster",
|
|
37
35
|
"BaseConnection",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from coredis.constants import SYM_CRLF, SYM_DOLLAR, SYM_EMPTY, SYM_STAR
|
|
4
|
-
from coredis.typing import
|
|
4
|
+
from coredis.typing import RedisValueT
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class Packer:
|
|
8
8
|
def __init__(self, encoding: str):
|
|
9
9
|
self.encoding = encoding
|
|
10
10
|
|
|
11
|
-
def encode(self, value:
|
|
11
|
+
def encode(self, value: RedisValueT) -> bytes:
|
|
12
12
|
"""Returns a bytestring representation of the value"""
|
|
13
13
|
if isinstance(value, str):
|
|
14
14
|
return value.encode(self.encoding)
|
|
@@ -18,7 +18,7 @@ class Packer:
|
|
|
18
18
|
return b"%.15g" % value
|
|
19
19
|
return value
|
|
20
20
|
|
|
21
|
-
def pack_command(self, command: bytes, *args:
|
|
21
|
+
def pack_command(self, command: bytes, *args: RedisValueT) -> list[bytes]:
|
|
22
22
|
"Pack a series of arguments into the Redis protocol"
|
|
23
23
|
output: list[bytes] = []
|
|
24
24
|
# the client might have included 1 or more literal arguments in
|
|
@@ -50,22 +50,22 @@ class Packer:
|
|
|
50
50
|
output.append(buff)
|
|
51
51
|
return output
|
|
52
52
|
|
|
53
|
-
def pack_commands(self, commands: list[tuple[
|
|
53
|
+
def pack_commands(self, commands: list[tuple[RedisValueT, ...]]) -> list[bytes]:
|
|
54
54
|
output: list[bytes] = []
|
|
55
|
-
|
|
55
|
+
command_arguments: list[bytes] = []
|
|
56
56
|
buffer_length = 0
|
|
57
57
|
|
|
58
58
|
for cmd in commands:
|
|
59
59
|
for chunk in self.pack_command(self.encode(cmd[0]), *cmd[1:]):
|
|
60
|
-
|
|
60
|
+
command_arguments.append(chunk)
|
|
61
61
|
buffer_length += len(chunk)
|
|
62
62
|
|
|
63
63
|
if buffer_length > 6000:
|
|
64
|
-
output.append(SYM_EMPTY.join(
|
|
64
|
+
output.append(SYM_EMPTY.join(command_arguments))
|
|
65
65
|
buffer_length = 0
|
|
66
|
-
|
|
66
|
+
command_arguments = []
|
|
67
67
|
|
|
68
|
-
if
|
|
69
|
-
output.append(SYM_EMPTY.join(
|
|
68
|
+
if command_arguments:
|
|
69
|
+
output.append(SYM_EMPTY.join(command_arguments))
|
|
70
70
|
|
|
71
71
|
return output
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
from typing_extensions import runtime_checkable
|
|
6
|
+
|
|
7
|
+
from coredis.response._callbacks import NoopCallback
|
|
8
|
+
from coredis.typing import (
|
|
9
|
+
TYPE_CHECKING,
|
|
10
|
+
Awaitable,
|
|
11
|
+
Callable,
|
|
12
|
+
ExecutionParameters,
|
|
13
|
+
Protocol,
|
|
14
|
+
R,
|
|
15
|
+
RedisCommandP,
|
|
16
|
+
ResponseType,
|
|
17
|
+
TypeVar,
|
|
18
|
+
Unpack,
|
|
19
|
+
ValueT,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
T_co = TypeVar("T_co", covariant=True)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from coredis.commands import CommandRequest
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AbstractExecutor(Protocol):
|
|
30
|
+
def execute_command(
|
|
31
|
+
self,
|
|
32
|
+
command: RedisCommandP,
|
|
33
|
+
callback: Callable[..., R] = NoopCallback(),
|
|
34
|
+
**options: Unpack[ExecutionParameters],
|
|
35
|
+
) -> Awaitable[R]: ...
|
|
36
|
+
|
|
37
|
+
def create_request(
|
|
38
|
+
self,
|
|
39
|
+
name: bytes,
|
|
40
|
+
*arguments: ValueT,
|
|
41
|
+
callback: Callable[..., R],
|
|
42
|
+
execution_parameters: ExecutionParameters | None = None,
|
|
43
|
+
) -> CommandRequest[R]: ...
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@runtime_checkable
|
|
47
|
+
class ConnectionP(Protocol):
|
|
48
|
+
decode_responses: bool
|
|
49
|
+
encoding: str
|
|
50
|
+
push_messages: asyncio.Queue[ResponseType]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Hashable
|
|
4
|
+
from typing import Any, TypeAlias
|
|
5
|
+
|
|
6
|
+
from .typing import MutableSet, RedisError, ResponsePrimitive
|
|
7
|
+
|
|
8
|
+
#: Represents the total structure of any response for any redis command.
|
|
9
|
+
ResponseType: TypeAlias = (
|
|
10
|
+
ResponsePrimitive
|
|
11
|
+
| list[Any]
|
|
12
|
+
| MutableSet[Hashable]
|
|
13
|
+
| dict[
|
|
14
|
+
Hashable,
|
|
15
|
+
Any,
|
|
16
|
+
]
|
|
17
|
+
| RedisError
|
|
18
|
+
)
|
|
19
|
+
#: Type alias for valid python types that can be represented as json
|
|
20
|
+
JsonType: TypeAlias = str | int | float | bool | dict[str, Any] | list[Any] | None
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Hashable
|
|
4
|
+
|
|
5
|
+
from .typing import MutableSet, RedisError, ResponsePrimitive
|
|
6
|
+
|
|
7
|
+
#: Type alias for valid python types that can be represented as json
|
|
8
|
+
type JsonType = str | int | float | bool | dict[str, JsonType] | list[JsonType] | None
|
|
9
|
+
|
|
10
|
+
#: Represents the total structure of any response for any redis command.
|
|
11
|
+
type ResponseType = (
|
|
12
|
+
ResponsePrimitive
|
|
13
|
+
| RedisError
|
|
14
|
+
| list[ResponseType]
|
|
15
|
+
| MutableSet[Hashable]
|
|
16
|
+
| dict[Hashable, ResponseType]
|
|
17
|
+
)
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import enum
|
|
4
|
+
from collections import UserDict
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
6
|
-
from wrapt import ObjectProxy
|
|
7
|
-
|
|
8
7
|
from coredis.typing import (
|
|
9
8
|
Hashable,
|
|
10
9
|
Iterable,
|
|
11
10
|
Mapping,
|
|
11
|
+
MutableMapping,
|
|
12
12
|
ResponseType,
|
|
13
13
|
StringT,
|
|
14
14
|
TypeVar,
|
|
@@ -18,61 +18,59 @@ T = TypeVar("T")
|
|
|
18
18
|
U = TypeVar("U")
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
class EncodingInsensitiveDict(
|
|
21
|
+
class EncodingInsensitiveDict(UserDict[Any, Any]):
|
|
22
22
|
def __init__(
|
|
23
23
|
self,
|
|
24
|
-
|
|
24
|
+
initial: MutableMapping[Any, Any] | None = None,
|
|
25
25
|
encoding: str = "utf-8",
|
|
26
26
|
):
|
|
27
|
-
|
|
28
|
-
super().__init__(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def __getitem__(self, item: StringT) -> Any:
|
|
32
|
-
if isinstance(item, str) and item not in self.__wrapped__:
|
|
33
|
-
return self.__wrapped__.get(
|
|
34
|
-
item, self.__wrapped__.get(item.encode(self._self_encoding))
|
|
35
|
-
)
|
|
36
|
-
elif isinstance(item, bytes) and item not in self.__wrapped__:
|
|
37
|
-
return self.__wrapped__.get(
|
|
38
|
-
item, self.__wrapped__.get(item.decode(self._self_encoding))
|
|
39
|
-
)
|
|
40
|
-
return self.__wrapped__[item]
|
|
41
|
-
|
|
42
|
-
def get(self, item: StringT, default: object | None = None) -> Any:
|
|
43
|
-
return self.__getitem__(item) or default
|
|
44
|
-
|
|
45
|
-
def pop(self, item: StringT, default: object | None = None) -> Any:
|
|
46
|
-
if item in self.__wrapped__:
|
|
47
|
-
return self.__wrapped__.pop(item)
|
|
48
|
-
if isinstance(item, str):
|
|
49
|
-
return self.__wrapped__.pop(item.encode(self._self_encoding), default)
|
|
50
|
-
|
|
51
|
-
def clear(self) -> None:
|
|
52
|
-
self.__wrapped__.clear()
|
|
53
|
-
|
|
54
|
-
def update(self, updates: Mapping[Any, Any]) -> None:
|
|
55
|
-
self.__wrapped__.update(updates)
|
|
56
|
-
|
|
57
|
-
def __setitem__(self, item: StringT, value: object) -> None:
|
|
58
|
-
if item in self.__wrapped__:
|
|
59
|
-
self.__wrapped__[item] = value
|
|
60
|
-
elif isinstance(item, str) and item.encode(self._self_encoding) in self.__wrapped__:
|
|
61
|
-
self.__wrapped__[item.encode(self._self_encoding)] = value
|
|
62
|
-
elif isinstance(item, bytes) and item.decode(self._self_encoding) in self.__wrapped__:
|
|
63
|
-
self.__wrapped__[item.decode(self._self_encoding)] = value
|
|
64
|
-
else:
|
|
65
|
-
self.__wrapped__[item] = value
|
|
66
|
-
|
|
67
|
-
def __contains__(self, key: StringT) -> bool:
|
|
27
|
+
self._encoding = encoding
|
|
28
|
+
super().__init__(initial or {})
|
|
29
|
+
|
|
30
|
+
def _alt_key(self, key: StringT) -> StringT:
|
|
68
31
|
if isinstance(key, str):
|
|
69
|
-
|
|
32
|
+
try:
|
|
33
|
+
byte_alt = key.encode(self._encoding)
|
|
34
|
+
if byte_alt in self.data:
|
|
35
|
+
return byte_alt
|
|
36
|
+
except UnicodeEncodeError:
|
|
37
|
+
pass
|
|
70
38
|
elif isinstance(key, bytes):
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
39
|
+
try:
|
|
40
|
+
str_alt = key.decode(self._encoding)
|
|
41
|
+
if str_alt in self.data:
|
|
42
|
+
return str_alt
|
|
43
|
+
except UnicodeDecodeError:
|
|
44
|
+
pass
|
|
45
|
+
return key
|
|
46
|
+
|
|
47
|
+
def __getitem__(self, key: StringT) -> Any:
|
|
48
|
+
if key in self.data:
|
|
49
|
+
return self.data[key]
|
|
50
|
+
alt = self._alt_key(key)
|
|
51
|
+
if alt in self.data:
|
|
52
|
+
return self.data[alt]
|
|
53
|
+
raise KeyError(key)
|
|
54
|
+
|
|
55
|
+
def __setitem__(self, key: StringT, value: Any) -> None:
|
|
56
|
+
alt = self._alt_key(key)
|
|
57
|
+
self.data[alt] = value
|
|
58
|
+
|
|
59
|
+
def __delitem__(self, key: StringT) -> None:
|
|
60
|
+
alt = self._alt_key(key)
|
|
61
|
+
del self.data[alt]
|
|
62
|
+
|
|
63
|
+
def __contains__(self, key: Any) -> bool:
|
|
64
|
+
return key in self.data or self._alt_key(key) in self.data
|
|
65
|
+
|
|
66
|
+
def get(self, key: StringT, default: Any = None) -> Any:
|
|
67
|
+
return self.data.get(key, self.data.get(self._alt_key(key), default))
|
|
68
|
+
|
|
69
|
+
def pop(self, key: StringT, default: Any = None) -> Any:
|
|
70
|
+
if key in self.data:
|
|
71
|
+
return self.data.pop(key)
|
|
72
|
+
alt = self._alt_key(key)
|
|
73
|
+
return self.data.pop(alt, default)
|
|
76
74
|
|
|
77
75
|
|
|
78
76
|
@enum.unique
|
|
@@ -122,10 +120,6 @@ def b(x: ResponseType, encoding: str | None = None) -> bytes:
|
|
|
122
120
|
return _v.encode(encoding) if encoding else _v.encode()
|
|
123
121
|
|
|
124
122
|
|
|
125
|
-
def defaultvalue(value: U | None, default: T) -> U | T:
|
|
126
|
-
return default if value is None else value
|
|
127
|
-
|
|
128
|
-
|
|
129
123
|
def nativestr(x: ResponseType, encoding: str = "utf-8") -> str:
|
|
130
124
|
if isinstance(x, (str, bytes)):
|
|
131
125
|
return x if isinstance(x, str) else x.decode(encoding, "replace")
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-07-
|
|
11
|
+
"date": "2025-07-16T17:47:22-0700",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "
|
|
14
|
+
"full-revisionid": "ac290229e2b463e1643d9829542cb1a59083b600",
|
|
15
|
+
"version": "5.0.0"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|