redis 5.2.1__py3-none-any.whl → 5.3.0__py3-none-any.whl
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/asyncio/client.py +49 -12
- redis/asyncio/cluster.py +101 -12
- redis/asyncio/connection.py +78 -11
- redis/auth/__init__.py +0 -0
- redis/auth/err.py +31 -0
- redis/auth/idp.py +28 -0
- redis/auth/token.py +126 -0
- redis/auth/token_manager.py +370 -0
- redis/backoff.py +15 -0
- redis/client.py +116 -56
- redis/cluster.py +157 -33
- redis/connection.py +103 -11
- redis/credentials.py +40 -1
- redis/event.py +394 -0
- redis/typing.py +1 -1
- redis/utils.py +65 -0
- {redis-5.2.1.dist-info → redis-5.3.0.dist-info}/METADATA +2 -1
- {redis-5.2.1.dist-info → redis-5.3.0.dist-info}/RECORD +21 -15
- {redis-5.2.1.dist-info → redis-5.3.0.dist-info}/LICENSE +0 -0
- {redis-5.2.1.dist-info → redis-5.3.0.dist-info}/WHEEL +0 -0
- {redis-5.2.1.dist-info → redis-5.3.0.dist-info}/top_level.txt +0 -0
redis/event.py
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import threading
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import List, Optional, Union
|
|
6
|
+
|
|
7
|
+
from redis.auth.token import TokenInterface
|
|
8
|
+
from redis.credentials import CredentialProvider, StreamingCredentialProvider
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EventListenerInterface(ABC):
|
|
12
|
+
"""
|
|
13
|
+
Represents a listener for given event object.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def listen(self, event: object):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AsyncEventListenerInterface(ABC):
|
|
22
|
+
"""
|
|
23
|
+
Represents an async listener for given event object.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
async def listen(self, event: object):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class EventDispatcherInterface(ABC):
|
|
32
|
+
"""
|
|
33
|
+
Represents a dispatcher that dispatches events to listeners
|
|
34
|
+
associated with given event.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def dispatch(self, event: object):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
async def dispatch_async(self, event: object):
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class EventException(Exception):
|
|
47
|
+
"""
|
|
48
|
+
Exception wrapper that adds an event object into exception context.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, exception: Exception, event: object):
|
|
52
|
+
self.exception = exception
|
|
53
|
+
self.event = event
|
|
54
|
+
super().__init__(exception)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class EventDispatcher(EventDispatcherInterface):
|
|
58
|
+
# TODO: Make dispatcher to accept external mappings.
|
|
59
|
+
def __init__(self):
|
|
60
|
+
"""
|
|
61
|
+
Mapping should be extended for any new events or listeners to be added.
|
|
62
|
+
"""
|
|
63
|
+
self._event_listeners_mapping = {
|
|
64
|
+
AfterConnectionReleasedEvent: [
|
|
65
|
+
ReAuthConnectionListener(),
|
|
66
|
+
],
|
|
67
|
+
AfterPooledConnectionsInstantiationEvent: [
|
|
68
|
+
RegisterReAuthForPooledConnections()
|
|
69
|
+
],
|
|
70
|
+
AfterSingleConnectionInstantiationEvent: [
|
|
71
|
+
RegisterReAuthForSingleConnection()
|
|
72
|
+
],
|
|
73
|
+
AfterPubSubConnectionInstantiationEvent: [RegisterReAuthForPubSub()],
|
|
74
|
+
AfterAsyncClusterInstantiationEvent: [RegisterReAuthForAsyncClusterNodes()],
|
|
75
|
+
AsyncAfterConnectionReleasedEvent: [
|
|
76
|
+
AsyncReAuthConnectionListener(),
|
|
77
|
+
],
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
def dispatch(self, event: object):
|
|
81
|
+
listeners = self._event_listeners_mapping.get(type(event))
|
|
82
|
+
|
|
83
|
+
for listener in listeners:
|
|
84
|
+
listener.listen(event)
|
|
85
|
+
|
|
86
|
+
async def dispatch_async(self, event: object):
|
|
87
|
+
listeners = self._event_listeners_mapping.get(type(event))
|
|
88
|
+
|
|
89
|
+
for listener in listeners:
|
|
90
|
+
await listener.listen(event)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class AfterConnectionReleasedEvent:
|
|
94
|
+
"""
|
|
95
|
+
Event that will be fired before each command execution.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(self, connection):
|
|
99
|
+
self._connection = connection
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def connection(self):
|
|
103
|
+
return self._connection
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class AsyncAfterConnectionReleasedEvent(AfterConnectionReleasedEvent):
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class ClientType(Enum):
|
|
111
|
+
SYNC = ("sync",)
|
|
112
|
+
ASYNC = ("async",)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class AfterPooledConnectionsInstantiationEvent:
|
|
116
|
+
"""
|
|
117
|
+
Event that will be fired after pooled connection instances was created.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
connection_pools: List,
|
|
123
|
+
client_type: ClientType,
|
|
124
|
+
credential_provider: Optional[CredentialProvider] = None,
|
|
125
|
+
):
|
|
126
|
+
self._connection_pools = connection_pools
|
|
127
|
+
self._client_type = client_type
|
|
128
|
+
self._credential_provider = credential_provider
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def connection_pools(self):
|
|
132
|
+
return self._connection_pools
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def client_type(self) -> ClientType:
|
|
136
|
+
return self._client_type
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def credential_provider(self) -> Union[CredentialProvider, None]:
|
|
140
|
+
return self._credential_provider
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class AfterSingleConnectionInstantiationEvent:
|
|
144
|
+
"""
|
|
145
|
+
Event that will be fired after single connection instances was created.
|
|
146
|
+
|
|
147
|
+
:param connection_lock: For sync client thread-lock should be provided,
|
|
148
|
+
for async asyncio.Lock
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
def __init__(
|
|
152
|
+
self,
|
|
153
|
+
connection,
|
|
154
|
+
client_type: ClientType,
|
|
155
|
+
connection_lock: Union[threading.Lock, asyncio.Lock],
|
|
156
|
+
):
|
|
157
|
+
self._connection = connection
|
|
158
|
+
self._client_type = client_type
|
|
159
|
+
self._connection_lock = connection_lock
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def connection(self):
|
|
163
|
+
return self._connection
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def client_type(self) -> ClientType:
|
|
167
|
+
return self._client_type
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def connection_lock(self) -> Union[threading.Lock, asyncio.Lock]:
|
|
171
|
+
return self._connection_lock
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class AfterPubSubConnectionInstantiationEvent:
|
|
175
|
+
def __init__(
|
|
176
|
+
self,
|
|
177
|
+
pubsub_connection,
|
|
178
|
+
connection_pool,
|
|
179
|
+
client_type: ClientType,
|
|
180
|
+
connection_lock: Union[threading.Lock, asyncio.Lock],
|
|
181
|
+
):
|
|
182
|
+
self._pubsub_connection = pubsub_connection
|
|
183
|
+
self._connection_pool = connection_pool
|
|
184
|
+
self._client_type = client_type
|
|
185
|
+
self._connection_lock = connection_lock
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def pubsub_connection(self):
|
|
189
|
+
return self._pubsub_connection
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def connection_pool(self):
|
|
193
|
+
return self._connection_pool
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def client_type(self) -> ClientType:
|
|
197
|
+
return self._client_type
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def connection_lock(self) -> Union[threading.Lock, asyncio.Lock]:
|
|
201
|
+
return self._connection_lock
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class AfterAsyncClusterInstantiationEvent:
|
|
205
|
+
"""
|
|
206
|
+
Event that will be fired after async cluster instance was created.
|
|
207
|
+
|
|
208
|
+
Async cluster doesn't use connection pools,
|
|
209
|
+
instead ClusterNode object manages connections.
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
def __init__(
|
|
213
|
+
self,
|
|
214
|
+
nodes: dict,
|
|
215
|
+
credential_provider: Optional[CredentialProvider] = None,
|
|
216
|
+
):
|
|
217
|
+
self._nodes = nodes
|
|
218
|
+
self._credential_provider = credential_provider
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def nodes(self) -> dict:
|
|
222
|
+
return self._nodes
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def credential_provider(self) -> Union[CredentialProvider, None]:
|
|
226
|
+
return self._credential_provider
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class ReAuthConnectionListener(EventListenerInterface):
|
|
230
|
+
"""
|
|
231
|
+
Listener that performs re-authentication of given connection.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
def listen(self, event: AfterConnectionReleasedEvent):
|
|
235
|
+
event.connection.re_auth()
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class AsyncReAuthConnectionListener(AsyncEventListenerInterface):
|
|
239
|
+
"""
|
|
240
|
+
Async listener that performs re-authentication of given connection.
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
async def listen(self, event: AsyncAfterConnectionReleasedEvent):
|
|
244
|
+
await event.connection.re_auth()
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class RegisterReAuthForPooledConnections(EventListenerInterface):
|
|
248
|
+
"""
|
|
249
|
+
Listener that registers a re-authentication callback for pooled connections.
|
|
250
|
+
Required by :class:`StreamingCredentialProvider`.
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
def __init__(self):
|
|
254
|
+
self._event = None
|
|
255
|
+
|
|
256
|
+
def listen(self, event: AfterPooledConnectionsInstantiationEvent):
|
|
257
|
+
if isinstance(event.credential_provider, StreamingCredentialProvider):
|
|
258
|
+
self._event = event
|
|
259
|
+
|
|
260
|
+
if event.client_type == ClientType.SYNC:
|
|
261
|
+
event.credential_provider.on_next(self._re_auth)
|
|
262
|
+
event.credential_provider.on_error(self._raise_on_error)
|
|
263
|
+
else:
|
|
264
|
+
event.credential_provider.on_next(self._re_auth_async)
|
|
265
|
+
event.credential_provider.on_error(self._raise_on_error_async)
|
|
266
|
+
|
|
267
|
+
def _re_auth(self, token):
|
|
268
|
+
for pool in self._event.connection_pools:
|
|
269
|
+
pool.re_auth_callback(token)
|
|
270
|
+
|
|
271
|
+
async def _re_auth_async(self, token):
|
|
272
|
+
for pool in self._event.connection_pools:
|
|
273
|
+
await pool.re_auth_callback(token)
|
|
274
|
+
|
|
275
|
+
def _raise_on_error(self, error: Exception):
|
|
276
|
+
raise EventException(error, self._event)
|
|
277
|
+
|
|
278
|
+
async def _raise_on_error_async(self, error: Exception):
|
|
279
|
+
raise EventException(error, self._event)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class RegisterReAuthForSingleConnection(EventListenerInterface):
|
|
283
|
+
"""
|
|
284
|
+
Listener that registers a re-authentication callback for single connection.
|
|
285
|
+
Required by :class:`StreamingCredentialProvider`.
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
def __init__(self):
|
|
289
|
+
self._event = None
|
|
290
|
+
|
|
291
|
+
def listen(self, event: AfterSingleConnectionInstantiationEvent):
|
|
292
|
+
if isinstance(
|
|
293
|
+
event.connection.credential_provider, StreamingCredentialProvider
|
|
294
|
+
):
|
|
295
|
+
self._event = event
|
|
296
|
+
|
|
297
|
+
if event.client_type == ClientType.SYNC:
|
|
298
|
+
event.connection.credential_provider.on_next(self._re_auth)
|
|
299
|
+
event.connection.credential_provider.on_error(self._raise_on_error)
|
|
300
|
+
else:
|
|
301
|
+
event.connection.credential_provider.on_next(self._re_auth_async)
|
|
302
|
+
event.connection.credential_provider.on_error(
|
|
303
|
+
self._raise_on_error_async
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
def _re_auth(self, token):
|
|
307
|
+
with self._event.connection_lock:
|
|
308
|
+
self._event.connection.send_command(
|
|
309
|
+
"AUTH", token.try_get("oid"), token.get_value()
|
|
310
|
+
)
|
|
311
|
+
self._event.connection.read_response()
|
|
312
|
+
|
|
313
|
+
async def _re_auth_async(self, token):
|
|
314
|
+
async with self._event.connection_lock:
|
|
315
|
+
await self._event.connection.send_command(
|
|
316
|
+
"AUTH", token.try_get("oid"), token.get_value()
|
|
317
|
+
)
|
|
318
|
+
await self._event.connection.read_response()
|
|
319
|
+
|
|
320
|
+
def _raise_on_error(self, error: Exception):
|
|
321
|
+
raise EventException(error, self._event)
|
|
322
|
+
|
|
323
|
+
async def _raise_on_error_async(self, error: Exception):
|
|
324
|
+
raise EventException(error, self._event)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class RegisterReAuthForAsyncClusterNodes(EventListenerInterface):
|
|
328
|
+
def __init__(self):
|
|
329
|
+
self._event = None
|
|
330
|
+
|
|
331
|
+
def listen(self, event: AfterAsyncClusterInstantiationEvent):
|
|
332
|
+
if isinstance(event.credential_provider, StreamingCredentialProvider):
|
|
333
|
+
self._event = event
|
|
334
|
+
event.credential_provider.on_next(self._re_auth)
|
|
335
|
+
event.credential_provider.on_error(self._raise_on_error)
|
|
336
|
+
|
|
337
|
+
async def _re_auth(self, token: TokenInterface):
|
|
338
|
+
for key in self._event.nodes:
|
|
339
|
+
await self._event.nodes[key].re_auth_callback(token)
|
|
340
|
+
|
|
341
|
+
async def _raise_on_error(self, error: Exception):
|
|
342
|
+
raise EventException(error, self._event)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class RegisterReAuthForPubSub(EventListenerInterface):
|
|
346
|
+
def __init__(self):
|
|
347
|
+
self._connection = None
|
|
348
|
+
self._connection_pool = None
|
|
349
|
+
self._client_type = None
|
|
350
|
+
self._connection_lock = None
|
|
351
|
+
self._event = None
|
|
352
|
+
|
|
353
|
+
def listen(self, event: AfterPubSubConnectionInstantiationEvent):
|
|
354
|
+
if isinstance(
|
|
355
|
+
event.pubsub_connection.credential_provider, StreamingCredentialProvider
|
|
356
|
+
) and event.pubsub_connection.get_protocol() in [3, "3"]:
|
|
357
|
+
self._event = event
|
|
358
|
+
self._connection = event.pubsub_connection
|
|
359
|
+
self._connection_pool = event.connection_pool
|
|
360
|
+
self._client_type = event.client_type
|
|
361
|
+
self._connection_lock = event.connection_lock
|
|
362
|
+
|
|
363
|
+
if self._client_type == ClientType.SYNC:
|
|
364
|
+
self._connection.credential_provider.on_next(self._re_auth)
|
|
365
|
+
self._connection.credential_provider.on_error(self._raise_on_error)
|
|
366
|
+
else:
|
|
367
|
+
self._connection.credential_provider.on_next(self._re_auth_async)
|
|
368
|
+
self._connection.credential_provider.on_error(
|
|
369
|
+
self._raise_on_error_async
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
def _re_auth(self, token: TokenInterface):
|
|
373
|
+
with self._connection_lock:
|
|
374
|
+
self._connection.send_command(
|
|
375
|
+
"AUTH", token.try_get("oid"), token.get_value()
|
|
376
|
+
)
|
|
377
|
+
self._connection.read_response()
|
|
378
|
+
|
|
379
|
+
self._connection_pool.re_auth_callback(token)
|
|
380
|
+
|
|
381
|
+
async def _re_auth_async(self, token: TokenInterface):
|
|
382
|
+
async with self._connection_lock:
|
|
383
|
+
await self._connection.send_command(
|
|
384
|
+
"AUTH", token.try_get("oid"), token.get_value()
|
|
385
|
+
)
|
|
386
|
+
await self._connection.read_response()
|
|
387
|
+
|
|
388
|
+
await self._connection_pool.re_auth_callback(token)
|
|
389
|
+
|
|
390
|
+
def _raise_on_error(self, error: Exception):
|
|
391
|
+
raise EventException(error, self._event)
|
|
392
|
+
|
|
393
|
+
async def _raise_on_error_async(self, error: Exception):
|
|
394
|
+
raise EventException(error, self._event)
|
redis/typing.py
CHANGED
redis/utils.py
CHANGED
|
@@ -122,6 +122,71 @@ def deprecated_function(reason="", version="", name=None):
|
|
|
122
122
|
return decorator
|
|
123
123
|
|
|
124
124
|
|
|
125
|
+
def warn_deprecated_arg_usage(
|
|
126
|
+
arg_name: Union[list, str],
|
|
127
|
+
function_name: str,
|
|
128
|
+
reason: str = "",
|
|
129
|
+
version: str = "",
|
|
130
|
+
stacklevel: int = 2,
|
|
131
|
+
):
|
|
132
|
+
import warnings
|
|
133
|
+
|
|
134
|
+
msg = (
|
|
135
|
+
f"Call to '{function_name}' function with deprecated"
|
|
136
|
+
f" usage of input argument/s '{arg_name}'."
|
|
137
|
+
)
|
|
138
|
+
if reason:
|
|
139
|
+
msg += f" ({reason})"
|
|
140
|
+
if version:
|
|
141
|
+
msg += f" -- Deprecated since version {version}."
|
|
142
|
+
warnings.warn(msg, category=DeprecationWarning, stacklevel=stacklevel)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def deprecated_args(
|
|
146
|
+
args_to_warn: list = ["*"],
|
|
147
|
+
allowed_args: list = [],
|
|
148
|
+
reason: str = "",
|
|
149
|
+
version: str = "",
|
|
150
|
+
):
|
|
151
|
+
"""
|
|
152
|
+
Decorator to mark specified args of a function as deprecated.
|
|
153
|
+
If '*' is in args_to_warn, all arguments will be marked as deprecated.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
def decorator(func):
|
|
157
|
+
@wraps(func)
|
|
158
|
+
def wrapper(*args, **kwargs):
|
|
159
|
+
# Get function argument names
|
|
160
|
+
arg_names = func.__code__.co_varnames[: func.__code__.co_argcount]
|
|
161
|
+
|
|
162
|
+
provided_args = dict(zip(arg_names, args))
|
|
163
|
+
provided_args.update(kwargs)
|
|
164
|
+
|
|
165
|
+
provided_args.pop("self", None)
|
|
166
|
+
for allowed_arg in allowed_args:
|
|
167
|
+
provided_args.pop(allowed_arg, None)
|
|
168
|
+
|
|
169
|
+
for arg in args_to_warn:
|
|
170
|
+
if arg == "*" and len(provided_args) > 0:
|
|
171
|
+
warn_deprecated_arg_usage(
|
|
172
|
+
list(provided_args.keys()),
|
|
173
|
+
func.__name__,
|
|
174
|
+
reason,
|
|
175
|
+
version,
|
|
176
|
+
stacklevel=3,
|
|
177
|
+
)
|
|
178
|
+
elif arg in provided_args:
|
|
179
|
+
warn_deprecated_arg_usage(
|
|
180
|
+
arg, func.__name__, reason, version, stacklevel=3
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
return func(*args, **kwargs)
|
|
184
|
+
|
|
185
|
+
return wrapper
|
|
186
|
+
|
|
187
|
+
return decorator
|
|
188
|
+
|
|
189
|
+
|
|
125
190
|
def _set_info_logger():
|
|
126
191
|
"""
|
|
127
192
|
Set up a logger that log info logs to stdout.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: redis
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.3.0
|
|
4
4
|
Summary: Python client for Redis database and key-value store
|
|
5
5
|
Home-page: https://github.com/redis/redis-py
|
|
6
6
|
Author: Redis Inc.
|
|
@@ -30,6 +30,7 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
|
30
30
|
Requires-Python: >=3.8
|
|
31
31
|
Description-Content-Type: text/markdown
|
|
32
32
|
License-File: LICENSE
|
|
33
|
+
Requires-Dist: PyJWT~=2.9.0
|
|
33
34
|
Requires-Dist: async-timeout>=4.0.3; python_full_version < "3.11.3"
|
|
34
35
|
Provides-Extra: hiredis
|
|
35
36
|
Requires-Dist: hiredis>=3.0.0; extra == "hiredis"
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
redis/__init__.py,sha256=WlARnwwst8oaEyjXV5XTcmSGyEKVCn3S9N1MrHyJ8U8,2015
|
|
2
|
-
redis/backoff.py,sha256=
|
|
2
|
+
redis/backoff.py,sha256=d22h74LEatJiFd_5o8HvFW3biFBotYOFZHddHt45ydc,3663
|
|
3
3
|
redis/cache.py,sha256=68rJDNogvNwgdgBel6zSX9QziL11qsKIMhmvQvHvznM,9549
|
|
4
|
-
redis/client.py,sha256=
|
|
5
|
-
redis/cluster.py,sha256=
|
|
6
|
-
redis/connection.py,sha256=
|
|
4
|
+
redis/client.py,sha256=5KynKSwVK7YPKWwOItEfNpJsVlu_oSchm2lNc_xJnVc,61733
|
|
5
|
+
redis/cluster.py,sha256=YzGkte85bSJOYeqs_WESFam_gtaWgEZ6CijPIdldVis,99287
|
|
6
|
+
redis/connection.py,sha256=sZiKny4EQ8BtReUYtB4zBQ5D3Tk0SOjbjD3j56jrb0g,65270
|
|
7
7
|
redis/crc.py,sha256=Z3kXFtkY2LdgefnQMud1xr4vG5UYvA9LCMqNMX1ywu4,729
|
|
8
|
-
redis/credentials.py,sha256=
|
|
8
|
+
redis/credentials.py,sha256=GOnO3-LSW34efHaIrUbS742Mw8l70mRzF6UrKiKZsMY,1828
|
|
9
|
+
redis/event.py,sha256=urOK241IdgmCQ3fq7GqXRstZ2vcXRV14bBBMdN3latk,12129
|
|
9
10
|
redis/exceptions.py,sha256=OmOGoS9EPInuTZPJT0BuDeIYuYrtRGEUT_Pu6NtEQNI,5211
|
|
10
11
|
redis/lock.py,sha256=3JOC3AmYJ10zbq0blOtV4uNwuEhw4K7xuJ6nM-qv5Ig,11976
|
|
11
12
|
redis/ocsp.py,sha256=4b1s43x-DJ859zRKtwGTIbNys_dyGv5YyOdWnOvigyM,11451
|
|
12
13
|
redis/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
14
|
redis/retry.py,sha256=JiIDxeD890vgi_me8pwypO1LixwhU0Fv3A5NEay8SAY,2206
|
|
14
15
|
redis/sentinel.py,sha256=ya1aPeAvUcY9qXMSpV_wA3081vUqkIqcyXG9SqAvU88,14661
|
|
15
|
-
redis/typing.py,sha256=
|
|
16
|
-
redis/utils.py,sha256=
|
|
16
|
+
redis/typing.py,sha256=k7F_3Vtsexeb7mUl6txlwrY1veGDLEhtcHe9FwIJOOo,2149
|
|
17
|
+
redis/utils.py,sha256=ErCe0V4nMTWTfeCI1Pg6X3WZeuxG0E-AirsI1AYaGF4,6664
|
|
17
18
|
redis/_parsers/__init__.py,sha256=qkfgV2X9iyvQAvbLdSelwgz0dCk9SGAosCvuZC9-qDc,550
|
|
18
19
|
redis/_parsers/base.py,sha256=0j3qIhLjQZOzYGc4n1IesNegckomVhvDsEZD6-yb3Ns,7475
|
|
19
20
|
redis/_parsers/commands.py,sha256=pmR4hl4u93UvCmeDgePHFc6pWDr4slrKEvCsdMmtj_M,11052
|
|
@@ -24,13 +25,18 @@ redis/_parsers/resp2.py,sha256=f22kH-_ZP2iNtOn6xOe65MSy_fJpu8OEn1u_hgeeojI,4813
|
|
|
24
25
|
redis/_parsers/resp3.py,sha256=jHtL1LYJegJ_LiNTsjzIvS-kZyNR58jZ_YV4cRfwuN0,11127
|
|
25
26
|
redis/_parsers/socket.py,sha256=CKD8QW_wFSNlIZzxlbNduaGpiv0I8wBcsGuAIojDfJg,5403
|
|
26
27
|
redis/asyncio/__init__.py,sha256=uoDD8XYVi0Kj6mcufYwLDUTQXmBRx7a0bhKF9stZr7I,1489
|
|
27
|
-
redis/asyncio/client.py,sha256=
|
|
28
|
-
redis/asyncio/cluster.py,sha256=
|
|
29
|
-
redis/asyncio/connection.py,sha256=
|
|
28
|
+
redis/asyncio/client.py,sha256=Ef2yknTMQrTJ0bvi3-4payHGsDqU0cRZLytHrPxHNuE,61016
|
|
29
|
+
redis/asyncio/cluster.py,sha256=4uV8uTRDFeAY25BbgagX1ykwnPLMuXzOtxzUH5SC8Q0,66922
|
|
30
|
+
redis/asyncio/connection.py,sha256=NKzj0LNn27ZR9A4sh3KtOiPuKkFwujc9dTegodHaHAo,47512
|
|
30
31
|
redis/asyncio/lock.py,sha256=lLasXEO2E1CskhX5ZZoaSGpmwZP1Q782R3HAUNG3wD4,11967
|
|
31
32
|
redis/asyncio/retry.py,sha256=SnPPOlo5gcyIFtkC4DY7HFvmDgUaILsJ3DeHioogdB8,2219
|
|
32
33
|
redis/asyncio/sentinel.py,sha256=QBpsrdlhZlFqENy_rK1IuasSicox55_xSvP_IywbhbQ,14293
|
|
33
34
|
redis/asyncio/utils.py,sha256=Yxc5YQumhLjtDDwCS4mgxI6yy2Z21AzLlFxVbxCohic,704
|
|
35
|
+
redis/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
36
|
+
redis/auth/err.py,sha256=WYkbuDIzwp1S-eAvsya6QMlO6g9QIXbzMITOsTWX0xk,694
|
|
37
|
+
redis/auth/idp.py,sha256=IMDIIb9q72vbIwtFN8vPdaAKZVTdh0HuC5uj5ufqmw4,631
|
|
38
|
+
redis/auth/token.py,sha256=DslJx_wN8yPcrmcF-Ui8E5emcamP6OUwi9PTGSvsXQw,3125
|
|
39
|
+
redis/auth/token_manager.py,sha256=ShBsYXiBZBJBOMB_Y-pXfLwEOAmc9s1okaCECinNZ7g,12018
|
|
34
40
|
redis/commands/__init__.py,sha256=cTUH-MGvaLYS0WuoytyqtN1wniw2A1KbkUXcpvOSY3I,576
|
|
35
41
|
redis/commands/cluster.py,sha256=BBHSyXfl3OETIJs4JC5DrcfzqgF2Kt4WMEcd0WMILOU,31598
|
|
36
42
|
redis/commands/core.py,sha256=YlCzD44YJnFzdEKIFDBloPh1ivgHKcFMZsxPzamE9JM,238528
|
|
@@ -69,8 +75,8 @@ redis/commands/timeseries/__init__.py,sha256=gkz6wshEzzQQryBOnrAqqQzttS-AHfXmuN_
|
|
|
69
75
|
redis/commands/timeseries/commands.py,sha256=8Z2BEyP23qTYCJR_e9zdG11yWmIDwGBMO2PJNLtK2BA,47147
|
|
70
76
|
redis/commands/timeseries/info.py,sha256=meZYdu7IV9KaUWMKZs9qW4vo3Q9MwhdY-EBtKQzls5o,3223
|
|
71
77
|
redis/commands/timeseries/utils.py,sha256=NLwSOS5Dz9N8dYQSzEyBIvrItOWwfQ0xgDj8un6x3dU,1319
|
|
72
|
-
redis-5.
|
|
73
|
-
redis-5.
|
|
74
|
-
redis-5.
|
|
75
|
-
redis-5.
|
|
76
|
-
redis-5.
|
|
78
|
+
redis-5.3.0.dist-info/LICENSE,sha256=pXslClvwPXr-VbdAYzE_Ktt7ANVGwKsUmok5gzP-PMg,1074
|
|
79
|
+
redis-5.3.0.dist-info/METADATA,sha256=ql3ziX3Hi71hXv26oLIMfFNqOCfAMtA8izDvb-NHQvI,9166
|
|
80
|
+
redis-5.3.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
81
|
+
redis-5.3.0.dist-info/top_level.txt,sha256=OMAefszlde6ZoOtlM35AWzpRIrwtcqAMHGlRit-w2-4,6
|
|
82
|
+
redis-5.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|