redis 6.0.0b2__tar.gz → 6.2.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.
- {redis-6.0.0b2 → redis-6.2.0}/.gitignore +1 -0
- {redis-6.0.0b2 → redis-6.2.0}/PKG-INFO +16 -12
- {redis-6.0.0b2 → redis-6.2.0}/README.md +12 -7
- {redis-6.0.0b2 → redis-6.2.0}/dev_requirements.txt +1 -1
- {redis-6.0.0b2 → redis-6.2.0}/pyproject.toml +4 -5
- {redis-6.0.0b2 → redis-6.2.0}/redis/__init__.py +8 -1
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/__init__.py +8 -1
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/base.py +53 -1
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/hiredis.py +72 -5
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/resp3.py +12 -37
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/client.py +76 -70
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/cluster.py +796 -104
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/connection.py +8 -10
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/retry.py +12 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/backoff.py +54 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/client.py +101 -89
- {redis-6.0.0b2 → redis-6.2.0}/redis/cluster.py +1088 -365
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/core.py +104 -104
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/helpers.py +19 -6
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/json/__init__.py +1 -1
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/json/commands.py +8 -8
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/redismodules.py +20 -10
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/commands.py +2 -2
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/timeseries/__init__.py +1 -1
- {redis-6.0.0b2 → redis-6.2.0}/redis/connection.py +19 -9
- {redis-6.0.0b2 → redis-6.2.0}/redis/exceptions.py +18 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/retry.py +25 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/typing.py +0 -4
- {redis-6.0.0b2 → redis-6.2.0}/redis/utils.py +5 -2
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_bloom.py +28 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_cluster.py +84 -42
- redis-6.2.0/tests/test_asyncio/test_cluster_transaction.py +399 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_connect.py +12 -1
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_connection_pool.py +3 -3
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_lock.py +2 -2
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_pubsub.py +5 -5
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_search.py +17 -6
- redis-6.2.0/tests/test_asyncio/test_ssl.py +56 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_timeseries.py +39 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_vsets.py +19 -8
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_bloom.py +28 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_cache.py +6 -5
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_cluster.py +120 -45
- redis-6.2.0/tests/test_cluster_transaction.py +398 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_connect.py +10 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_connection_pool.py +4 -5
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_pubsub.py +5 -6
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_retry.py +62 -3
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_search.py +8 -1
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_ssl.py +30 -1
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_timeseries.py +38 -1
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_vsets.py +21 -10
- {redis-6.0.0b2 → redis-6.2.0}/LICENSE +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/commands.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/encoders.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/helpers.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/resp2.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/_parsers/socket.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/lock.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/sentinel.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/asyncio/utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/auth/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/auth/err.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/auth/idp.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/auth/token.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/auth/token_manager.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/cache.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/bf/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/bf/commands.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/bf/info.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/cluster.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/json/_util.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/json/decoders.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/json/path.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/_util.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/aggregation.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/dialect.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/document.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/field.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/index_definition.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/profile_information.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/query.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/querystring.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/reducers.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/result.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/search/suggestion.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/sentinel.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/timeseries/commands.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/timeseries/info.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/timeseries/utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/vectorset/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/vectorset/commands.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/commands/vectorset/utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/crc.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/credentials.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/event.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/lock.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/ocsp.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/py.typed +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/redis/sentinel.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/conftest.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/entraid_utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/mocks.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/ssl_utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/compat.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/conftest.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/mocks.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_commands.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_connection.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_credentials.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_cwe_404.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_encoding.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_hash.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_json.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_monitor.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_pipeline.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_retry.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_scripting.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_sentinel.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_sentinel_managed_connection.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/test_utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/testdata/jsontestdata.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/testdata/titles.csv +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_asyncio/testdata/will_play_text.csv.bz2 +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_auth/__init__.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_auth/test_token.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_auth/test_token_manager.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_backoff.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_command_parser.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_commands.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_connection.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_credentials.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_encoding.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_function.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_hash.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_helpers.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_json.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_lock.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_monitor.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_multiprocessing.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_parsers/test_helpers.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_pipeline.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_scripting.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_sentinel.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/test_utils.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/testdata/jsontestdata.py +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/testdata/titles.csv +0 -0
- {redis-6.0.0b2 → redis-6.2.0}/tests/testdata/will_play_text.csv.bz2 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redis
|
|
3
|
-
Version: 6.0
|
|
3
|
+
Version: 6.2.0
|
|
4
4
|
Summary: Python client for Redis database and key-value store
|
|
5
5
|
Project-URL: Changes, https://github.com/redis/redis-py/releases
|
|
6
6
|
Project-URL: Code, https://github.com/redis/redis-py
|
|
@@ -19,7 +19,6 @@ Classifier: Operating System :: OS Independent
|
|
|
19
19
|
Classifier: Programming Language :: Python
|
|
20
20
|
Classifier: Programming Language :: Python :: 3
|
|
21
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.9
|
|
24
23
|
Classifier: Programming Language :: Python :: 3.10
|
|
25
24
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -27,12 +26,12 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
27
26
|
Classifier: Programming Language :: Python :: 3.13
|
|
28
27
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
29
28
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
30
|
-
Requires-Python: >=3.
|
|
29
|
+
Requires-Python: >=3.9
|
|
31
30
|
Requires-Dist: async-timeout>=4.0.3; python_full_version < '3.11.3'
|
|
32
31
|
Provides-Extra: hiredis
|
|
33
|
-
Requires-Dist: hiredis>=3.
|
|
32
|
+
Requires-Dist: hiredis>=3.2.0; extra == 'hiredis'
|
|
34
33
|
Provides-Extra: jwt
|
|
35
|
-
Requires-Dist: pyjwt
|
|
34
|
+
Requires-Dist: pyjwt>=2.9.0; extra == 'jwt'
|
|
36
35
|
Provides-Extra: ocsp
|
|
37
36
|
Requires-Dist: cryptography>=36.0.1; extra == 'ocsp'
|
|
38
37
|
Requires-Dist: pyopenssl>=20.0.1; extra == 'ocsp'
|
|
@@ -55,7 +54,7 @@ The Python interface to the Redis key-value store.
|
|
|
55
54
|
---------------------------------------------
|
|
56
55
|
|
|
57
56
|
**Note:** redis-py 5.0 will be the last version of redis-py to support Python 3.7, as it has reached [end of life](https://devguide.python.org/versions/). redis-py 5.1 will support Python 3.8+.
|
|
58
|
-
|
|
57
|
+
**Note:** redis-py 6.1.0 will be the last version of redis-py to support Python 3.8, as it has reached [end of life](https://devguide.python.org/versions/). redis-py 6.2.0 will support Python 3.9+.
|
|
59
58
|
---------------------------------------------
|
|
60
59
|
|
|
61
60
|
## How do I Redis?
|
|
@@ -72,12 +71,17 @@ The Python interface to the Redis key-value store.
|
|
|
72
71
|
|
|
73
72
|
## Installation
|
|
74
73
|
|
|
75
|
-
Start a redis via docker:
|
|
74
|
+
Start a redis via docker (for Redis versions >= 8.0):
|
|
76
75
|
|
|
77
76
|
``` bash
|
|
78
|
-
docker run -p 6379:6379 -it redis
|
|
77
|
+
docker run -p 6379:6379 -it redis:latest
|
|
79
78
|
```
|
|
80
79
|
|
|
80
|
+
Start a redis via docker (for Redis versions < 8.0):
|
|
81
|
+
|
|
82
|
+
``` bash
|
|
83
|
+
docker run -p 6379:6379 -it redis/redis-stack:latest
|
|
84
|
+
|
|
81
85
|
To install redis-py, simply:
|
|
82
86
|
|
|
83
87
|
``` bash
|
|
@@ -95,7 +99,7 @@ Looking for a high-level library to handle object mapping? See [redis-om-python]
|
|
|
95
99
|
|
|
96
100
|
## Supported Redis Versions
|
|
97
101
|
|
|
98
|
-
The most recent version of this library supports
|
|
102
|
+
The most recent version of this library supports Redis version [7.2](https://github.com/redis/redis/blob/7.2/00-RELEASENOTES), [7.4](https://github.com/redis/redis/blob/7.4/00-RELEASENOTES) and [8.0](https://github.com/redis/redis/blob/8.0/00-RELEASENOTES).
|
|
99
103
|
|
|
100
104
|
The table below highlights version compatibility of the most-recent library versions and redis versions.
|
|
101
105
|
|
|
@@ -196,8 +200,8 @@ The following example shows how to utilize [Redis Pub/Sub](https://redis.io/docs
|
|
|
196
200
|
|
|
197
201
|
### Redis’ search and query capabilities default dialect
|
|
198
202
|
|
|
199
|
-
Release 6.0.0 introduces a client-side default dialect for Redis’ search and query capabilities.
|
|
200
|
-
By default, the client now overrides the server-side dialect with version 2, automatically appending *DIALECT 2* to commands like *FT.AGGREGATE* and *FT.SEARCH*.
|
|
203
|
+
Release 6.0.0 introduces a client-side default dialect for Redis’ search and query capabilities.
|
|
204
|
+
By default, the client now overrides the server-side dialect with version 2, automatically appending *DIALECT 2* to commands like *FT.AGGREGATE* and *FT.SEARCH*.
|
|
201
205
|
|
|
202
206
|
**Important**: Be aware that the query dialect may impact the results returned. If needed, you can revert to a different dialect version by configuring the client accordingly.
|
|
203
207
|
|
|
@@ -245,4 +249,4 @@ Special thanks to:
|
|
|
245
249
|
system.
|
|
246
250
|
- Paul Hubbard for initial packaging support.
|
|
247
251
|
|
|
248
|
-
[](https://redis.io)
|
|
252
|
+
[](https://redis.io)
|
|
@@ -14,7 +14,7 @@ The Python interface to the Redis key-value store.
|
|
|
14
14
|
---------------------------------------------
|
|
15
15
|
|
|
16
16
|
**Note:** redis-py 5.0 will be the last version of redis-py to support Python 3.7, as it has reached [end of life](https://devguide.python.org/versions/). redis-py 5.1 will support Python 3.8+.
|
|
17
|
-
|
|
17
|
+
**Note:** redis-py 6.1.0 will be the last version of redis-py to support Python 3.8, as it has reached [end of life](https://devguide.python.org/versions/). redis-py 6.2.0 will support Python 3.9+.
|
|
18
18
|
---------------------------------------------
|
|
19
19
|
|
|
20
20
|
## How do I Redis?
|
|
@@ -31,12 +31,17 @@ The Python interface to the Redis key-value store.
|
|
|
31
31
|
|
|
32
32
|
## Installation
|
|
33
33
|
|
|
34
|
-
Start a redis via docker:
|
|
34
|
+
Start a redis via docker (for Redis versions >= 8.0):
|
|
35
35
|
|
|
36
36
|
``` bash
|
|
37
|
-
docker run -p 6379:6379 -it redis
|
|
37
|
+
docker run -p 6379:6379 -it redis:latest
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
Start a redis via docker (for Redis versions < 8.0):
|
|
41
|
+
|
|
42
|
+
``` bash
|
|
43
|
+
docker run -p 6379:6379 -it redis/redis-stack:latest
|
|
44
|
+
|
|
40
45
|
To install redis-py, simply:
|
|
41
46
|
|
|
42
47
|
``` bash
|
|
@@ -54,7 +59,7 @@ Looking for a high-level library to handle object mapping? See [redis-om-python]
|
|
|
54
59
|
|
|
55
60
|
## Supported Redis Versions
|
|
56
61
|
|
|
57
|
-
The most recent version of this library supports
|
|
62
|
+
The most recent version of this library supports Redis version [7.2](https://github.com/redis/redis/blob/7.2/00-RELEASENOTES), [7.4](https://github.com/redis/redis/blob/7.4/00-RELEASENOTES) and [8.0](https://github.com/redis/redis/blob/8.0/00-RELEASENOTES).
|
|
58
63
|
|
|
59
64
|
The table below highlights version compatibility of the most-recent library versions and redis versions.
|
|
60
65
|
|
|
@@ -155,8 +160,8 @@ The following example shows how to utilize [Redis Pub/Sub](https://redis.io/docs
|
|
|
155
160
|
|
|
156
161
|
### Redis’ search and query capabilities default dialect
|
|
157
162
|
|
|
158
|
-
Release 6.0.0 introduces a client-side default dialect for Redis’ search and query capabilities.
|
|
159
|
-
By default, the client now overrides the server-side dialect with version 2, automatically appending *DIALECT 2* to commands like *FT.AGGREGATE* and *FT.SEARCH*.
|
|
163
|
+
Release 6.0.0 introduces a client-side default dialect for Redis’ search and query capabilities.
|
|
164
|
+
By default, the client now overrides the server-side dialect with version 2, automatically appending *DIALECT 2* to commands like *FT.AGGREGATE* and *FT.SEARCH*.
|
|
160
165
|
|
|
161
166
|
**Important**: Be aware that the query dialect may impact the results returned. If needed, you can revert to a different dialect version by configuring the client accordingly.
|
|
162
167
|
|
|
@@ -204,4 +209,4 @@ Special thanks to:
|
|
|
204
209
|
system.
|
|
205
210
|
- Paul Hubbard for initial packaging support.
|
|
206
211
|
|
|
207
|
-
[](https://redis.io)
|
|
212
|
+
[](https://redis.io)
|
|
@@ -8,7 +8,7 @@ dynamic = ["version"]
|
|
|
8
8
|
description = "Python client for Redis database and key-value store"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
|
-
requires-python = ">=3.
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
12
|
authors = [{ name = "Redis Inc.", email = "oss@redis.com" }]
|
|
13
13
|
keywords = ["Redis", "database", "key-value-store"]
|
|
14
14
|
classifiers = [
|
|
@@ -20,7 +20,6 @@ classifiers = [
|
|
|
20
20
|
"Programming Language :: Python",
|
|
21
21
|
"Programming Language :: Python :: 3",
|
|
22
22
|
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
-
"Programming Language :: Python :: 3.8",
|
|
24
23
|
"Programming Language :: Python :: 3.9",
|
|
25
24
|
"Programming Language :: Python :: 3.10",
|
|
26
25
|
"Programming Language :: Python :: 3.11",
|
|
@@ -33,7 +32,7 @@ dependencies = ['async-timeout>=4.0.3; python_full_version<"3.11.3"']
|
|
|
33
32
|
|
|
34
33
|
[project.optional-dependencies]
|
|
35
34
|
hiredis = [
|
|
36
|
-
"hiredis>=3.
|
|
35
|
+
"hiredis>=3.2.0",
|
|
37
36
|
]
|
|
38
37
|
ocsp = [
|
|
39
38
|
"cryptography>=36.0.1",
|
|
@@ -41,7 +40,7 @@ ocsp = [
|
|
|
41
40
|
"requests>=2.31.0",
|
|
42
41
|
]
|
|
43
42
|
jwt = [
|
|
44
|
-
"PyJWT
|
|
43
|
+
"PyJWT>=2.9.0",
|
|
45
44
|
]
|
|
46
45
|
|
|
47
46
|
[project.urls]
|
|
@@ -83,7 +82,7 @@ filterwarnings = [
|
|
|
83
82
|
]
|
|
84
83
|
|
|
85
84
|
[tool.ruff]
|
|
86
|
-
target-version = "
|
|
85
|
+
target-version = "py39"
|
|
87
86
|
line-length = 88
|
|
88
87
|
exclude = [
|
|
89
88
|
"*.egg-info",
|
|
@@ -16,11 +16,14 @@ from redis.exceptions import (
|
|
|
16
16
|
BusyLoadingError,
|
|
17
17
|
ChildDeadlockedError,
|
|
18
18
|
ConnectionError,
|
|
19
|
+
CrossSlotTransactionError,
|
|
19
20
|
DataError,
|
|
21
|
+
InvalidPipelineStack,
|
|
20
22
|
InvalidResponse,
|
|
21
23
|
OutOfMemoryError,
|
|
22
24
|
PubSubError,
|
|
23
25
|
ReadOnlyError,
|
|
26
|
+
RedisClusterException,
|
|
24
27
|
RedisError,
|
|
25
28
|
ResponseError,
|
|
26
29
|
TimeoutError,
|
|
@@ -42,7 +45,8 @@ def int_or_str(value):
|
|
|
42
45
|
return value
|
|
43
46
|
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
# This version is used when building the package for publishing
|
|
49
|
+
__version__ = "6.2.0"
|
|
46
50
|
VERSION = tuple(map(int_or_str, __version__.split(".")))
|
|
47
51
|
|
|
48
52
|
|
|
@@ -56,15 +60,18 @@ __all__ = [
|
|
|
56
60
|
"ConnectionError",
|
|
57
61
|
"ConnectionPool",
|
|
58
62
|
"CredentialProvider",
|
|
63
|
+
"CrossSlotTransactionError",
|
|
59
64
|
"DataError",
|
|
60
65
|
"from_url",
|
|
61
66
|
"default_backoff",
|
|
67
|
+
"InvalidPipelineStack",
|
|
62
68
|
"InvalidResponse",
|
|
63
69
|
"OutOfMemoryError",
|
|
64
70
|
"PubSubError",
|
|
65
71
|
"ReadOnlyError",
|
|
66
72
|
"Redis",
|
|
67
73
|
"RedisCluster",
|
|
74
|
+
"RedisClusterException",
|
|
68
75
|
"RedisError",
|
|
69
76
|
"ResponseError",
|
|
70
77
|
"Sentinel",
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
from .base import
|
|
1
|
+
from .base import (
|
|
2
|
+
AsyncPushNotificationsParser,
|
|
3
|
+
BaseParser,
|
|
4
|
+
PushNotificationsParser,
|
|
5
|
+
_AsyncRESPBase,
|
|
6
|
+
)
|
|
2
7
|
from .commands import AsyncCommandsParser, CommandsParser
|
|
3
8
|
from .encoders import Encoder
|
|
4
9
|
from .hiredis import _AsyncHiredisParser, _HiredisParser
|
|
@@ -11,10 +16,12 @@ __all__ = [
|
|
|
11
16
|
"_AsyncRESPBase",
|
|
12
17
|
"_AsyncRESP2Parser",
|
|
13
18
|
"_AsyncRESP3Parser",
|
|
19
|
+
"AsyncPushNotificationsParser",
|
|
14
20
|
"CommandsParser",
|
|
15
21
|
"Encoder",
|
|
16
22
|
"BaseParser",
|
|
17
23
|
"_HiredisParser",
|
|
18
24
|
"_RESP2Parser",
|
|
19
25
|
"_RESP3Parser",
|
|
26
|
+
"PushNotificationsParser",
|
|
20
27
|
]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from abc import ABC
|
|
3
3
|
from asyncio import IncompleteReadError, StreamReader, TimeoutError
|
|
4
|
-
from typing import List, Optional, Union
|
|
4
|
+
from typing import Callable, List, Optional, Protocol, Union
|
|
5
5
|
|
|
6
6
|
if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
|
|
7
7
|
from asyncio import timeout as async_timeout
|
|
@@ -158,6 +158,58 @@ class AsyncBaseParser(BaseParser):
|
|
|
158
158
|
raise NotImplementedError()
|
|
159
159
|
|
|
160
160
|
|
|
161
|
+
_INVALIDATION_MESSAGE = [b"invalidate", "invalidate"]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class PushNotificationsParser(Protocol):
|
|
165
|
+
"""Protocol defining RESP3-specific parsing functionality"""
|
|
166
|
+
|
|
167
|
+
pubsub_push_handler_func: Callable
|
|
168
|
+
invalidation_push_handler_func: Optional[Callable] = None
|
|
169
|
+
|
|
170
|
+
def handle_pubsub_push_response(self, response):
|
|
171
|
+
"""Handle pubsub push responses"""
|
|
172
|
+
raise NotImplementedError()
|
|
173
|
+
|
|
174
|
+
def handle_push_response(self, response, **kwargs):
|
|
175
|
+
if response[0] not in _INVALIDATION_MESSAGE:
|
|
176
|
+
return self.pubsub_push_handler_func(response)
|
|
177
|
+
if self.invalidation_push_handler_func:
|
|
178
|
+
return self.invalidation_push_handler_func(response)
|
|
179
|
+
|
|
180
|
+
def set_pubsub_push_handler(self, pubsub_push_handler_func):
|
|
181
|
+
self.pubsub_push_handler_func = pubsub_push_handler_func
|
|
182
|
+
|
|
183
|
+
def set_invalidation_push_handler(self, invalidation_push_handler_func):
|
|
184
|
+
self.invalidation_push_handler_func = invalidation_push_handler_func
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class AsyncPushNotificationsParser(Protocol):
|
|
188
|
+
"""Protocol defining async RESP3-specific parsing functionality"""
|
|
189
|
+
|
|
190
|
+
pubsub_push_handler_func: Callable
|
|
191
|
+
invalidation_push_handler_func: Optional[Callable] = None
|
|
192
|
+
|
|
193
|
+
async def handle_pubsub_push_response(self, response):
|
|
194
|
+
"""Handle pubsub push responses asynchronously"""
|
|
195
|
+
raise NotImplementedError()
|
|
196
|
+
|
|
197
|
+
async def handle_push_response(self, response, **kwargs):
|
|
198
|
+
"""Handle push responses asynchronously"""
|
|
199
|
+
if response[0] not in _INVALIDATION_MESSAGE:
|
|
200
|
+
return await self.pubsub_push_handler_func(response)
|
|
201
|
+
if self.invalidation_push_handler_func:
|
|
202
|
+
return await self.invalidation_push_handler_func(response)
|
|
203
|
+
|
|
204
|
+
def set_pubsub_push_handler(self, pubsub_push_handler_func):
|
|
205
|
+
"""Set the pubsub push handler function"""
|
|
206
|
+
self.pubsub_push_handler_func = pubsub_push_handler_func
|
|
207
|
+
|
|
208
|
+
def set_invalidation_push_handler(self, invalidation_push_handler_func):
|
|
209
|
+
"""Set the invalidation push handler function"""
|
|
210
|
+
self.invalidation_push_handler_func = invalidation_push_handler_func
|
|
211
|
+
|
|
212
|
+
|
|
161
213
|
class _AsyncRESPBase(AsyncBaseParser):
|
|
162
214
|
"""Base class for async resp parsing"""
|
|
163
215
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import socket
|
|
3
3
|
import sys
|
|
4
|
+
from logging import getLogger
|
|
4
5
|
from typing import Callable, List, Optional, TypedDict, Union
|
|
5
6
|
|
|
6
7
|
if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
|
|
@@ -11,7 +12,12 @@ else:
|
|
|
11
12
|
from ..exceptions import ConnectionError, InvalidResponse, RedisError
|
|
12
13
|
from ..typing import EncodableT
|
|
13
14
|
from ..utils import HIREDIS_AVAILABLE
|
|
14
|
-
from .base import
|
|
15
|
+
from .base import (
|
|
16
|
+
AsyncBaseParser,
|
|
17
|
+
AsyncPushNotificationsParser,
|
|
18
|
+
BaseParser,
|
|
19
|
+
PushNotificationsParser,
|
|
20
|
+
)
|
|
15
21
|
from .socket import (
|
|
16
22
|
NONBLOCKING_EXCEPTION_ERROR_NUMBERS,
|
|
17
23
|
NONBLOCKING_EXCEPTIONS,
|
|
@@ -32,7 +38,7 @@ class _HiredisReaderArgs(TypedDict, total=False):
|
|
|
32
38
|
errors: Optional[str]
|
|
33
39
|
|
|
34
40
|
|
|
35
|
-
class _HiredisParser(BaseParser):
|
|
41
|
+
class _HiredisParser(BaseParser, PushNotificationsParser):
|
|
36
42
|
"Parser class for connections using Hiredis"
|
|
37
43
|
|
|
38
44
|
def __init__(self, socket_read_size):
|
|
@@ -40,6 +46,9 @@ class _HiredisParser(BaseParser):
|
|
|
40
46
|
raise RedisError("Hiredis is not installed")
|
|
41
47
|
self.socket_read_size = socket_read_size
|
|
42
48
|
self._buffer = bytearray(socket_read_size)
|
|
49
|
+
self.pubsub_push_handler_func = self.handle_pubsub_push_response
|
|
50
|
+
self.invalidation_push_handler_func = None
|
|
51
|
+
self._hiredis_PushNotificationType = None
|
|
43
52
|
|
|
44
53
|
def __del__(self):
|
|
45
54
|
try:
|
|
@@ -47,6 +56,11 @@ class _HiredisParser(BaseParser):
|
|
|
47
56
|
except Exception:
|
|
48
57
|
pass
|
|
49
58
|
|
|
59
|
+
def handle_pubsub_push_response(self, response):
|
|
60
|
+
logger = getLogger("push_response")
|
|
61
|
+
logger.debug("Push response: " + str(response))
|
|
62
|
+
return response
|
|
63
|
+
|
|
50
64
|
def on_connect(self, connection, **kwargs):
|
|
51
65
|
import hiredis
|
|
52
66
|
|
|
@@ -64,6 +78,12 @@ class _HiredisParser(BaseParser):
|
|
|
64
78
|
self._reader = hiredis.Reader(**kwargs)
|
|
65
79
|
self._next_response = NOT_ENOUGH_DATA
|
|
66
80
|
|
|
81
|
+
try:
|
|
82
|
+
self._hiredis_PushNotificationType = hiredis.PushNotification
|
|
83
|
+
except AttributeError:
|
|
84
|
+
# hiredis < 3.2
|
|
85
|
+
self._hiredis_PushNotificationType = None
|
|
86
|
+
|
|
67
87
|
def on_disconnect(self):
|
|
68
88
|
self._sock = None
|
|
69
89
|
self._reader = None
|
|
@@ -109,7 +129,7 @@ class _HiredisParser(BaseParser):
|
|
|
109
129
|
if custom_timeout:
|
|
110
130
|
sock.settimeout(self._socket_timeout)
|
|
111
131
|
|
|
112
|
-
def read_response(self, disable_decoding=False):
|
|
132
|
+
def read_response(self, disable_decoding=False, push_request=False):
|
|
113
133
|
if not self._reader:
|
|
114
134
|
raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR)
|
|
115
135
|
|
|
@@ -117,6 +137,16 @@ class _HiredisParser(BaseParser):
|
|
|
117
137
|
if self._next_response is not NOT_ENOUGH_DATA:
|
|
118
138
|
response = self._next_response
|
|
119
139
|
self._next_response = NOT_ENOUGH_DATA
|
|
140
|
+
if self._hiredis_PushNotificationType is not None and isinstance(
|
|
141
|
+
response, self._hiredis_PushNotificationType
|
|
142
|
+
):
|
|
143
|
+
response = self.handle_push_response(response)
|
|
144
|
+
if not push_request:
|
|
145
|
+
return self.read_response(
|
|
146
|
+
disable_decoding=disable_decoding, push_request=push_request
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
return response
|
|
120
150
|
return response
|
|
121
151
|
|
|
122
152
|
if disable_decoding:
|
|
@@ -135,6 +165,16 @@ class _HiredisParser(BaseParser):
|
|
|
135
165
|
# happened
|
|
136
166
|
if isinstance(response, ConnectionError):
|
|
137
167
|
raise response
|
|
168
|
+
elif self._hiredis_PushNotificationType is not None and isinstance(
|
|
169
|
+
response, self._hiredis_PushNotificationType
|
|
170
|
+
):
|
|
171
|
+
response = self.handle_push_response(response)
|
|
172
|
+
if not push_request:
|
|
173
|
+
return self.read_response(
|
|
174
|
+
disable_decoding=disable_decoding, push_request=push_request
|
|
175
|
+
)
|
|
176
|
+
else:
|
|
177
|
+
return response
|
|
138
178
|
elif (
|
|
139
179
|
isinstance(response, list)
|
|
140
180
|
and response
|
|
@@ -144,7 +184,7 @@ class _HiredisParser(BaseParser):
|
|
|
144
184
|
return response
|
|
145
185
|
|
|
146
186
|
|
|
147
|
-
class _AsyncHiredisParser(AsyncBaseParser):
|
|
187
|
+
class _AsyncHiredisParser(AsyncBaseParser, AsyncPushNotificationsParser):
|
|
148
188
|
"""Async implementation of parser class for connections using Hiredis"""
|
|
149
189
|
|
|
150
190
|
__slots__ = ("_reader",)
|
|
@@ -154,6 +194,14 @@ class _AsyncHiredisParser(AsyncBaseParser):
|
|
|
154
194
|
raise RedisError("Hiredis is not available.")
|
|
155
195
|
super().__init__(socket_read_size=socket_read_size)
|
|
156
196
|
self._reader = None
|
|
197
|
+
self.pubsub_push_handler_func = self.handle_pubsub_push_response
|
|
198
|
+
self.invalidation_push_handler_func = None
|
|
199
|
+
self._hiredis_PushNotificationType = None
|
|
200
|
+
|
|
201
|
+
async def handle_pubsub_push_response(self, response):
|
|
202
|
+
logger = getLogger("push_response")
|
|
203
|
+
logger.debug("Push response: " + str(response))
|
|
204
|
+
return response
|
|
157
205
|
|
|
158
206
|
def on_connect(self, connection):
|
|
159
207
|
import hiredis
|
|
@@ -171,6 +219,14 @@ class _AsyncHiredisParser(AsyncBaseParser):
|
|
|
171
219
|
self._reader = hiredis.Reader(**kwargs)
|
|
172
220
|
self._connected = True
|
|
173
221
|
|
|
222
|
+
try:
|
|
223
|
+
self._hiredis_PushNotificationType = getattr(
|
|
224
|
+
hiredis, "PushNotification", None
|
|
225
|
+
)
|
|
226
|
+
except AttributeError:
|
|
227
|
+
# hiredis < 3.2
|
|
228
|
+
self._hiredis_PushNotificationType = None
|
|
229
|
+
|
|
174
230
|
def on_disconnect(self):
|
|
175
231
|
self._connected = False
|
|
176
232
|
|
|
@@ -195,7 +251,7 @@ class _AsyncHiredisParser(AsyncBaseParser):
|
|
|
195
251
|
return True
|
|
196
252
|
|
|
197
253
|
async def read_response(
|
|
198
|
-
self, disable_decoding: bool = False
|
|
254
|
+
self, disable_decoding: bool = False, push_request: bool = False
|
|
199
255
|
) -> Union[EncodableT, List[EncodableT]]:
|
|
200
256
|
# If `on_disconnect()` has been called, prohibit any more reads
|
|
201
257
|
# even if they could happen because data might be present.
|
|
@@ -207,6 +263,7 @@ class _AsyncHiredisParser(AsyncBaseParser):
|
|
|
207
263
|
response = self._reader.gets(False)
|
|
208
264
|
else:
|
|
209
265
|
response = self._reader.gets()
|
|
266
|
+
|
|
210
267
|
while response is NOT_ENOUGH_DATA:
|
|
211
268
|
await self.read_from_socket()
|
|
212
269
|
if disable_decoding:
|
|
@@ -219,6 +276,16 @@ class _AsyncHiredisParser(AsyncBaseParser):
|
|
|
219
276
|
# happened
|
|
220
277
|
if isinstance(response, ConnectionError):
|
|
221
278
|
raise response
|
|
279
|
+
elif self._hiredis_PushNotificationType is not None and isinstance(
|
|
280
|
+
response, self._hiredis_PushNotificationType
|
|
281
|
+
):
|
|
282
|
+
response = await self.handle_push_response(response)
|
|
283
|
+
if not push_request:
|
|
284
|
+
return await self.read_response(
|
|
285
|
+
disable_decoding=disable_decoding, push_request=push_request
|
|
286
|
+
)
|
|
287
|
+
else:
|
|
288
|
+
return response
|
|
222
289
|
elif (
|
|
223
290
|
isinstance(response, list)
|
|
224
291
|
and response
|
|
@@ -3,13 +3,16 @@ from typing import Any, Union
|
|
|
3
3
|
|
|
4
4
|
from ..exceptions import ConnectionError, InvalidResponse, ResponseError
|
|
5
5
|
from ..typing import EncodableT
|
|
6
|
-
from .base import
|
|
6
|
+
from .base import (
|
|
7
|
+
AsyncPushNotificationsParser,
|
|
8
|
+
PushNotificationsParser,
|
|
9
|
+
_AsyncRESPBase,
|
|
10
|
+
_RESPBase,
|
|
11
|
+
)
|
|
7
12
|
from .socket import SERVER_CLOSED_CONNECTION_ERROR
|
|
8
13
|
|
|
9
|
-
_INVALIDATION_MESSAGE = [b"invalidate", "invalidate"]
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
class _RESP3Parser(_RESPBase):
|
|
15
|
+
class _RESP3Parser(_RESPBase, PushNotificationsParser):
|
|
13
16
|
"""RESP3 protocol implementation"""
|
|
14
17
|
|
|
15
18
|
def __init__(self, socket_read_size):
|
|
@@ -19,7 +22,7 @@ class _RESP3Parser(_RESPBase):
|
|
|
19
22
|
|
|
20
23
|
def handle_pubsub_push_response(self, response):
|
|
21
24
|
logger = getLogger("push_response")
|
|
22
|
-
logger.
|
|
25
|
+
logger.debug("Push response: " + str(response))
|
|
23
26
|
return response
|
|
24
27
|
|
|
25
28
|
def read_response(self, disable_decoding=False, push_request=False):
|
|
@@ -113,9 +116,7 @@ class _RESP3Parser(_RESPBase):
|
|
|
113
116
|
)
|
|
114
117
|
for _ in range(int(response))
|
|
115
118
|
]
|
|
116
|
-
response = self.handle_push_response(
|
|
117
|
-
response, disable_decoding, push_request
|
|
118
|
-
)
|
|
119
|
+
response = self.handle_push_response(response)
|
|
119
120
|
if not push_request:
|
|
120
121
|
return self._read_response(
|
|
121
122
|
disable_decoding=disable_decoding, push_request=push_request
|
|
@@ -129,20 +130,8 @@ class _RESP3Parser(_RESPBase):
|
|
|
129
130
|
response = self.encoder.decode(response)
|
|
130
131
|
return response
|
|
131
132
|
|
|
132
|
-
def handle_push_response(self, response, disable_decoding, push_request):
|
|
133
|
-
if response[0] not in _INVALIDATION_MESSAGE:
|
|
134
|
-
return self.pubsub_push_handler_func(response)
|
|
135
|
-
if self.invalidation_push_handler_func:
|
|
136
|
-
return self.invalidation_push_handler_func(response)
|
|
137
|
-
|
|
138
|
-
def set_pubsub_push_handler(self, pubsub_push_handler_func):
|
|
139
|
-
self.pubsub_push_handler_func = pubsub_push_handler_func
|
|
140
|
-
|
|
141
|
-
def set_invalidation_push_handler(self, invalidation_push_handler_func):
|
|
142
|
-
self.invalidation_push_handler_func = invalidation_push_handler_func
|
|
143
|
-
|
|
144
133
|
|
|
145
|
-
class _AsyncRESP3Parser(_AsyncRESPBase):
|
|
134
|
+
class _AsyncRESP3Parser(_AsyncRESPBase, AsyncPushNotificationsParser):
|
|
146
135
|
def __init__(self, socket_read_size):
|
|
147
136
|
super().__init__(socket_read_size)
|
|
148
137
|
self.pubsub_push_handler_func = self.handle_pubsub_push_response
|
|
@@ -150,7 +139,7 @@ class _AsyncRESP3Parser(_AsyncRESPBase):
|
|
|
150
139
|
|
|
151
140
|
async def handle_pubsub_push_response(self, response):
|
|
152
141
|
logger = getLogger("push_response")
|
|
153
|
-
logger.
|
|
142
|
+
logger.debug("Push response: " + str(response))
|
|
154
143
|
return response
|
|
155
144
|
|
|
156
145
|
async def read_response(
|
|
@@ -253,9 +242,7 @@ class _AsyncRESP3Parser(_AsyncRESPBase):
|
|
|
253
242
|
)
|
|
254
243
|
for _ in range(int(response))
|
|
255
244
|
]
|
|
256
|
-
response = await self.handle_push_response(
|
|
257
|
-
response, disable_decoding, push_request
|
|
258
|
-
)
|
|
245
|
+
response = await self.handle_push_response(response)
|
|
259
246
|
if not push_request:
|
|
260
247
|
return await self._read_response(
|
|
261
248
|
disable_decoding=disable_decoding, push_request=push_request
|
|
@@ -268,15 +255,3 @@ class _AsyncRESP3Parser(_AsyncRESPBase):
|
|
|
268
255
|
if isinstance(response, bytes) and disable_decoding is False:
|
|
269
256
|
response = self.encoder.decode(response)
|
|
270
257
|
return response
|
|
271
|
-
|
|
272
|
-
async def handle_push_response(self, response, disable_decoding, push_request):
|
|
273
|
-
if response[0] not in _INVALIDATION_MESSAGE:
|
|
274
|
-
return await self.pubsub_push_handler_func(response)
|
|
275
|
-
if self.invalidation_push_handler_func:
|
|
276
|
-
return await self.invalidation_push_handler_func(response)
|
|
277
|
-
|
|
278
|
-
def set_pubsub_push_handler(self, pubsub_push_handler_func):
|
|
279
|
-
self.pubsub_push_handler_func = pubsub_push_handler_func
|
|
280
|
-
|
|
281
|
-
def set_invalidation_push_handler(self, invalidation_push_handler_func):
|
|
282
|
-
self.invalidation_push_handler_func = invalidation_push_handler_func
|