coredis 5.2.0__cp314-cp314t-macosx_10_13_x86_64.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.
Potentially problematic release.
This version of coredis might be problematic. Click here for more details.
- 22fe76227e35f92ab5c3__mypyc.cpython-314t-darwin.so +0 -0
- coredis/__init__.py +42 -0
- coredis/_enum.py +42 -0
- coredis/_json.py +11 -0
- coredis/_packer.cpython-314t-darwin.so +0 -0
- coredis/_packer.py +71 -0
- coredis/_protocols.py +50 -0
- coredis/_py_311_typing.py +20 -0
- coredis/_py_312_typing.py +17 -0
- coredis/_sidecar.py +114 -0
- coredis/_utils.cpython-314t-darwin.so +0 -0
- coredis/_utils.py +440 -0
- coredis/_version.py +34 -0
- coredis/_version.pyi +1 -0
- coredis/cache.py +801 -0
- coredis/client/__init__.py +6 -0
- coredis/client/basic.py +1238 -0
- coredis/client/cluster.py +1264 -0
- coredis/commands/__init__.py +64 -0
- coredis/commands/_key_spec.py +517 -0
- coredis/commands/_utils.py +108 -0
- coredis/commands/_validators.py +159 -0
- coredis/commands/_wrappers.py +175 -0
- coredis/commands/bitfield.py +110 -0
- coredis/commands/constants.py +662 -0
- coredis/commands/core.py +8484 -0
- coredis/commands/function.py +408 -0
- coredis/commands/monitor.py +168 -0
- coredis/commands/pubsub.py +905 -0
- coredis/commands/request.py +108 -0
- coredis/commands/script.py +296 -0
- coredis/commands/sentinel.py +246 -0
- coredis/config.py +50 -0
- coredis/connection.py +906 -0
- coredis/constants.cpython-314t-darwin.so +0 -0
- coredis/constants.py +37 -0
- coredis/credentials.py +45 -0
- coredis/exceptions.py +360 -0
- coredis/experimental/__init__.py +1 -0
- coredis/globals.py +23 -0
- coredis/modules/__init__.py +117 -0
- coredis/modules/autocomplete.py +138 -0
- coredis/modules/base.py +262 -0
- coredis/modules/filters.py +1319 -0
- coredis/modules/graph.py +362 -0
- coredis/modules/json.py +691 -0
- coredis/modules/response/__init__.py +0 -0
- coredis/modules/response/_callbacks/__init__.py +0 -0
- coredis/modules/response/_callbacks/autocomplete.py +42 -0
- coredis/modules/response/_callbacks/graph.py +237 -0
- coredis/modules/response/_callbacks/json.py +21 -0
- coredis/modules/response/_callbacks/search.py +221 -0
- coredis/modules/response/_callbacks/timeseries.py +158 -0
- coredis/modules/response/types.py +179 -0
- coredis/modules/search.py +1089 -0
- coredis/modules/timeseries.py +1139 -0
- coredis/parser.cpython-314t-darwin.so +0 -0
- coredis/parser.py +344 -0
- coredis/pipeline.py +1225 -0
- coredis/pool/__init__.py +11 -0
- coredis/pool/basic.py +453 -0
- coredis/pool/cluster.py +517 -0
- coredis/pool/nodemanager.py +340 -0
- coredis/py.typed +0 -0
- coredis/recipes/__init__.py +0 -0
- coredis/recipes/credentials/__init__.py +5 -0
- coredis/recipes/credentials/iam_provider.py +63 -0
- coredis/recipes/locks/__init__.py +5 -0
- coredis/recipes/locks/extend.lua +17 -0
- coredis/recipes/locks/lua_lock.py +281 -0
- coredis/recipes/locks/release.lua +10 -0
- coredis/response/__init__.py +5 -0
- coredis/response/_callbacks/__init__.py +538 -0
- coredis/response/_callbacks/acl.py +32 -0
- coredis/response/_callbacks/cluster.py +183 -0
- coredis/response/_callbacks/command.py +86 -0
- coredis/response/_callbacks/connection.py +31 -0
- coredis/response/_callbacks/geo.py +58 -0
- coredis/response/_callbacks/hash.py +85 -0
- coredis/response/_callbacks/keys.py +59 -0
- coredis/response/_callbacks/module.py +33 -0
- coredis/response/_callbacks/script.py +85 -0
- coredis/response/_callbacks/sentinel.py +179 -0
- coredis/response/_callbacks/server.py +241 -0
- coredis/response/_callbacks/sets.py +44 -0
- coredis/response/_callbacks/sorted_set.py +204 -0
- coredis/response/_callbacks/streams.py +185 -0
- coredis/response/_callbacks/strings.py +70 -0
- coredis/response/_callbacks/vector_sets.py +159 -0
- coredis/response/_utils.py +33 -0
- coredis/response/types.py +416 -0
- coredis/retry.py +233 -0
- coredis/sentinel.py +477 -0
- coredis/stream.py +369 -0
- coredis/tokens.py +2286 -0
- coredis/typing.py +580 -0
- coredis-5.2.0.dist-info/METADATA +211 -0
- coredis-5.2.0.dist-info/RECORD +100 -0
- coredis-5.2.0.dist-info/WHEEL +6 -0
- coredis-5.2.0.dist-info/licenses/LICENSE +23 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import cast
|
|
4
|
+
|
|
5
|
+
from coredis._utils import EncodingInsensitiveDict, nativestr
|
|
6
|
+
from coredis.response._callbacks import ResponseCallback
|
|
7
|
+
from coredis.response._callbacks.server import InfoCallback
|
|
8
|
+
from coredis.typing import (
|
|
9
|
+
AnyStr,
|
|
10
|
+
ResponsePrimitive,
|
|
11
|
+
ResponseType,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
SENTINEL_STATE_INT_FIELDS = {
|
|
15
|
+
"can-failover-its-master",
|
|
16
|
+
"config-epoch",
|
|
17
|
+
"down-after-milliseconds",
|
|
18
|
+
"failover-timeout",
|
|
19
|
+
"info-refresh",
|
|
20
|
+
"last-hello-message",
|
|
21
|
+
"last-ok-ping-reply",
|
|
22
|
+
"last-ping-reply",
|
|
23
|
+
"last-ping-sent",
|
|
24
|
+
"master-link-down-time",
|
|
25
|
+
"master-port",
|
|
26
|
+
"num-other-sentinels",
|
|
27
|
+
"num-slaves",
|
|
28
|
+
"o-down-time",
|
|
29
|
+
"pending-commands",
|
|
30
|
+
"parallel-syncs",
|
|
31
|
+
"port",
|
|
32
|
+
"quorum",
|
|
33
|
+
"role-reported-time",
|
|
34
|
+
"s-down-time",
|
|
35
|
+
"slave-priority",
|
|
36
|
+
"slave-repl-offset",
|
|
37
|
+
"voted-leader-epoch",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def sentinel_state_typed(
|
|
42
|
+
response: list[str],
|
|
43
|
+
) -> EncodingInsensitiveDict[str, str | int | bool]:
|
|
44
|
+
it = iter(response)
|
|
45
|
+
result: EncodingInsensitiveDict[str, str | int | bool] = EncodingInsensitiveDict()
|
|
46
|
+
|
|
47
|
+
for key, value in zip(it, it):
|
|
48
|
+
if key in SENTINEL_STATE_INT_FIELDS:
|
|
49
|
+
value = int(value)
|
|
50
|
+
result[key] = value
|
|
51
|
+
|
|
52
|
+
return result
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def add_flags(
|
|
56
|
+
result: EncodingInsensitiveDict[str, int | str | bool],
|
|
57
|
+
) -> EncodingInsensitiveDict[str, int | str | bool]:
|
|
58
|
+
flags = set(nativestr(result["flags"]).split(","))
|
|
59
|
+
for name, flag in (
|
|
60
|
+
("is_master", "master"),
|
|
61
|
+
("is_slave", "slave"),
|
|
62
|
+
("is_sdown", "s_down"),
|
|
63
|
+
("is_odown", "o_down"),
|
|
64
|
+
("is_sentinel", "sentinel"),
|
|
65
|
+
("is_disconnected", "disconnected"),
|
|
66
|
+
("is_master_down", "master_down"),
|
|
67
|
+
):
|
|
68
|
+
result[name] = flag in flags
|
|
69
|
+
return result
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def parse_sentinel_state(
|
|
73
|
+
item: list[ResponsePrimitive],
|
|
74
|
+
) -> EncodingInsensitiveDict[str, int | str | bool]:
|
|
75
|
+
result = sentinel_state_typed([nativestr(k) for k in item])
|
|
76
|
+
result = add_flags(result)
|
|
77
|
+
return result
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class PrimaryCallback(
|
|
81
|
+
ResponseCallback[
|
|
82
|
+
ResponseType,
|
|
83
|
+
dict[ResponsePrimitive, ResponsePrimitive],
|
|
84
|
+
dict[str, ResponsePrimitive],
|
|
85
|
+
]
|
|
86
|
+
):
|
|
87
|
+
def transform(
|
|
88
|
+
self,
|
|
89
|
+
response: ResponseType,
|
|
90
|
+
) -> dict[str, ResponsePrimitive]:
|
|
91
|
+
return parse_sentinel_state(cast(list[ResponsePrimitive], response)).stringify_keys()
|
|
92
|
+
|
|
93
|
+
def transform_3(
|
|
94
|
+
self,
|
|
95
|
+
response: dict[ResponsePrimitive, ResponsePrimitive],
|
|
96
|
+
) -> dict[str, ResponsePrimitive]:
|
|
97
|
+
return add_flags(EncodingInsensitiveDict(response)).stringify_keys()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class PrimariesCallback(
|
|
101
|
+
ResponseCallback[
|
|
102
|
+
list[ResponseType],
|
|
103
|
+
list[ResponseType],
|
|
104
|
+
dict[str, dict[str, ResponsePrimitive]],
|
|
105
|
+
]
|
|
106
|
+
):
|
|
107
|
+
def transform(
|
|
108
|
+
self,
|
|
109
|
+
response: list[ResponseType] | dict[ResponsePrimitive, ResponsePrimitive],
|
|
110
|
+
) -> dict[str, dict[str, ResponsePrimitive]]:
|
|
111
|
+
result: dict[str, dict[str, ResponseType]] = {}
|
|
112
|
+
|
|
113
|
+
for item in response:
|
|
114
|
+
state = PrimaryCallback()(item)
|
|
115
|
+
result[str(state["name"])] = state
|
|
116
|
+
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
def transform_3(
|
|
120
|
+
self,
|
|
121
|
+
response: list[ResponseType],
|
|
122
|
+
) -> dict[str, dict[str, ResponsePrimitive]]:
|
|
123
|
+
states: dict[str, dict[str, ResponsePrimitive]] = {}
|
|
124
|
+
for state in response:
|
|
125
|
+
state = add_flags(EncodingInsensitiveDict(state)).stringify_keys()
|
|
126
|
+
states[nativestr(state["name"])] = state
|
|
127
|
+
return states
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class SentinelsStateCallback(
|
|
131
|
+
ResponseCallback[
|
|
132
|
+
list[ResponseType],
|
|
133
|
+
list[ResponseType],
|
|
134
|
+
tuple[dict[str, ResponsePrimitive], ...],
|
|
135
|
+
]
|
|
136
|
+
):
|
|
137
|
+
def transform(
|
|
138
|
+
self,
|
|
139
|
+
response: list[ResponseType],
|
|
140
|
+
) -> tuple[dict[str, ResponsePrimitive], ...]:
|
|
141
|
+
return tuple(
|
|
142
|
+
parse_sentinel_state([nativestr(i) for i in item]).stringify_keys() for item in response
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def transform_3(
|
|
146
|
+
self,
|
|
147
|
+
response: list[ResponseType],
|
|
148
|
+
) -> tuple[dict[str, ResponsePrimitive], ...]:
|
|
149
|
+
return tuple(
|
|
150
|
+
add_flags(EncodingInsensitiveDict(state)).stringify_keys() for state in response
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class GetPrimaryCallback(
|
|
155
|
+
ResponseCallback[
|
|
156
|
+
list[ResponsePrimitive],
|
|
157
|
+
list[ResponsePrimitive],
|
|
158
|
+
tuple[str, int] | None,
|
|
159
|
+
]
|
|
160
|
+
):
|
|
161
|
+
def transform(
|
|
162
|
+
self,
|
|
163
|
+
response: list[ResponsePrimitive],
|
|
164
|
+
) -> tuple[str, int] | None:
|
|
165
|
+
return nativestr(response[0]), int(response[1]) if response else None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class SentinelInfoCallback(
|
|
169
|
+
ResponseCallback[
|
|
170
|
+
list[ResponseType],
|
|
171
|
+
list[ResponseType],
|
|
172
|
+
dict[AnyStr, dict[int, dict[str, ResponsePrimitive]]],
|
|
173
|
+
]
|
|
174
|
+
):
|
|
175
|
+
def transform(
|
|
176
|
+
self,
|
|
177
|
+
response: list[ResponseType],
|
|
178
|
+
) -> dict[AnyStr, dict[int, dict[str, ResponsePrimitive]]]:
|
|
179
|
+
return {response[0]: {r[0]: InfoCallback()(r[1]) for r in response[1]}}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from coredis._utils import EncodingInsensitiveDict, nativestr
|
|
7
|
+
from coredis.response._callbacks import ResponseCallback
|
|
8
|
+
from coredis.response._utils import flat_pairs_to_dict
|
|
9
|
+
from coredis.response.types import ClientInfo, RoleInfo, SlowLogInfo
|
|
10
|
+
from coredis.typing import (
|
|
11
|
+
AnyStr,
|
|
12
|
+
ClassVar,
|
|
13
|
+
RedisValueT,
|
|
14
|
+
ResponsePrimitive,
|
|
15
|
+
ResponseType,
|
|
16
|
+
StringT,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TimeCallback(ResponseCallback[list[AnyStr], list[AnyStr], datetime.datetime]):
|
|
21
|
+
def transform(
|
|
22
|
+
self,
|
|
23
|
+
response: list[AnyStr],
|
|
24
|
+
) -> datetime.datetime:
|
|
25
|
+
return datetime.datetime.fromtimestamp(int(response[0])) + datetime.timedelta(
|
|
26
|
+
microseconds=int(response[1]) / 1000.0
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SlowlogCallback(ResponseCallback[ResponseType, ResponseType, tuple[SlowLogInfo, ...]]):
|
|
31
|
+
def transform(
|
|
32
|
+
self,
|
|
33
|
+
response: ResponseType,
|
|
34
|
+
) -> tuple[SlowLogInfo, ...]:
|
|
35
|
+
return tuple(
|
|
36
|
+
SlowLogInfo(
|
|
37
|
+
id=item[0],
|
|
38
|
+
start_time=int(item[1]),
|
|
39
|
+
duration=int(item[2]),
|
|
40
|
+
command=item[3],
|
|
41
|
+
client_addr=item[4],
|
|
42
|
+
client_name=item[5],
|
|
43
|
+
)
|
|
44
|
+
for item in response
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ClientInfoCallback(ResponseCallback[ResponseType, ResponseType, ClientInfo]):
|
|
49
|
+
INT_FIELDS: ClassVar = {
|
|
50
|
+
"id",
|
|
51
|
+
"fd",
|
|
52
|
+
"age",
|
|
53
|
+
"idle",
|
|
54
|
+
"db",
|
|
55
|
+
"sub",
|
|
56
|
+
"psub",
|
|
57
|
+
"multi",
|
|
58
|
+
"qbuf-free",
|
|
59
|
+
"argv-mem",
|
|
60
|
+
"multi-mem",
|
|
61
|
+
"obl",
|
|
62
|
+
"oll",
|
|
63
|
+
"omem",
|
|
64
|
+
"tot-mem",
|
|
65
|
+
"redir",
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def transform(
|
|
69
|
+
self,
|
|
70
|
+
response: ResponseType,
|
|
71
|
+
) -> ClientInfo:
|
|
72
|
+
decoded_response = nativestr(response)
|
|
73
|
+
pairs = [pair.split("=", 1) for pair in decoded_response.strip().split(" ")]
|
|
74
|
+
|
|
75
|
+
info: ClientInfo = {} # type: ignore
|
|
76
|
+
for k, v in pairs:
|
|
77
|
+
if k in ClientInfoCallback.INT_FIELDS:
|
|
78
|
+
info[k] = int(v) # type: ignore
|
|
79
|
+
else:
|
|
80
|
+
info[k] = v # type: ignore
|
|
81
|
+
return info
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class ClientListCallback(ResponseCallback[ResponseType, ResponseType, tuple[ClientInfo, ...]]):
|
|
85
|
+
def transform(
|
|
86
|
+
self,
|
|
87
|
+
response: ResponseType,
|
|
88
|
+
) -> tuple[ClientInfo, ...]:
|
|
89
|
+
return tuple(ClientInfoCallback()(c) for c in response.splitlines())
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class DebugCallback(ResponseCallback[ResponseType, ResponseType, dict[str, str | int]]):
|
|
93
|
+
INT_FIELDS: ClassVar = {"refcount", "serializedlength", "lru", "lru_seconds_idle"}
|
|
94
|
+
|
|
95
|
+
def transform(
|
|
96
|
+
self,
|
|
97
|
+
response: ResponseType,
|
|
98
|
+
) -> dict[str, str | int]:
|
|
99
|
+
# The 'type' of the object is the first item in the response, but isn't
|
|
100
|
+
# prefixed with a name
|
|
101
|
+
|
|
102
|
+
response = nativestr(response)
|
|
103
|
+
response = "type:" + response
|
|
104
|
+
parsed: dict[str, str | int] = {}
|
|
105
|
+
parsed.update(dict([kv.split(":") for kv in response.split()]))
|
|
106
|
+
|
|
107
|
+
# parse some expected int values from the string response
|
|
108
|
+
# note: this cmd isn't spec'd so these may not appear in all redis versions
|
|
109
|
+
|
|
110
|
+
for field in DebugCallback.INT_FIELDS:
|
|
111
|
+
if field in parsed:
|
|
112
|
+
parsed[field] = int(parsed[field])
|
|
113
|
+
|
|
114
|
+
return parsed
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class InfoCallback(
|
|
118
|
+
ResponseCallback[
|
|
119
|
+
StringT,
|
|
120
|
+
StringT,
|
|
121
|
+
dict[str, ResponseType],
|
|
122
|
+
]
|
|
123
|
+
):
|
|
124
|
+
def transform(
|
|
125
|
+
self,
|
|
126
|
+
response: StringT,
|
|
127
|
+
) -> dict[str, ResponseType]:
|
|
128
|
+
"""Parses the result of Redis's INFO command into a Python dict"""
|
|
129
|
+
|
|
130
|
+
info: dict[str, Any] = {}
|
|
131
|
+
response = nativestr(response)
|
|
132
|
+
|
|
133
|
+
def get_value(value: str) -> ResponseType:
|
|
134
|
+
if "," not in value or "=" not in value:
|
|
135
|
+
try:
|
|
136
|
+
if "." in value:
|
|
137
|
+
return float(value)
|
|
138
|
+
else:
|
|
139
|
+
return int(value)
|
|
140
|
+
except ValueError:
|
|
141
|
+
return value
|
|
142
|
+
else:
|
|
143
|
+
sub_dict: dict[ResponsePrimitive, ResponseType] = {}
|
|
144
|
+
|
|
145
|
+
for item in value.split(","):
|
|
146
|
+
k, v = item.rsplit("=", 1)
|
|
147
|
+
sub_dict[k] = get_value(v)
|
|
148
|
+
|
|
149
|
+
return sub_dict
|
|
150
|
+
|
|
151
|
+
cur_info = {}
|
|
152
|
+
header = None
|
|
153
|
+
for line in response.splitlines():
|
|
154
|
+
if line and not line.startswith("#"):
|
|
155
|
+
if line.find(":") != -1:
|
|
156
|
+
key, value = line.split(":", 1)
|
|
157
|
+
if key in cur_info:
|
|
158
|
+
if not isinstance(cur_info[key], list):
|
|
159
|
+
cur_info[key] = [cur_info[key]]
|
|
160
|
+
cur_info[key].append(get_value(value))
|
|
161
|
+
else:
|
|
162
|
+
cur_info[key] = get_value(value)
|
|
163
|
+
else:
|
|
164
|
+
# if the line isn't splittable, append it to the "__raw__" key
|
|
165
|
+
cur_info.setdefault("__raw__", []).append(line)
|
|
166
|
+
elif line:
|
|
167
|
+
if cur_info and header:
|
|
168
|
+
if self.options.get("nested"):
|
|
169
|
+
info[header] = cur_info
|
|
170
|
+
else:
|
|
171
|
+
info.update(cur_info)
|
|
172
|
+
cur_info = {}
|
|
173
|
+
header = line.lstrip("#").strip().lower()
|
|
174
|
+
if header and header not in info:
|
|
175
|
+
if self.options.get("nested"):
|
|
176
|
+
info[header] = cur_info
|
|
177
|
+
else:
|
|
178
|
+
info.update(cur_info)
|
|
179
|
+
return info
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class RoleCallback(ResponseCallback[ResponseType, ResponseType, RoleInfo]):
|
|
183
|
+
def transform(
|
|
184
|
+
self,
|
|
185
|
+
response: ResponseType,
|
|
186
|
+
) -> RoleInfo:
|
|
187
|
+
role = nativestr(response[0])
|
|
188
|
+
|
|
189
|
+
def _parse_master(response: Any) -> Any:
|
|
190
|
+
offset, replicas = response[1:]
|
|
191
|
+
res: dict[str, Any] = {"role": role, "offset": offset, "slaves": []}
|
|
192
|
+
|
|
193
|
+
for replica in replicas:
|
|
194
|
+
host, port, offset = replica
|
|
195
|
+
res["slaves"].append({"host": host, "port": int(port), "offset": int(offset)})
|
|
196
|
+
|
|
197
|
+
return res
|
|
198
|
+
|
|
199
|
+
def _parse_replica(response: Any) -> Any:
|
|
200
|
+
host, port, status, offset = response[1:]
|
|
201
|
+
|
|
202
|
+
return dict(
|
|
203
|
+
role=role,
|
|
204
|
+
status=status,
|
|
205
|
+
offset=offset,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
def _parse_sentinel(response: Any) -> Any:
|
|
209
|
+
return {"role": role, "masters": response[1]}
|
|
210
|
+
|
|
211
|
+
parser = {
|
|
212
|
+
"master": _parse_master,
|
|
213
|
+
"slave": _parse_replica,
|
|
214
|
+
"sentinel": _parse_sentinel,
|
|
215
|
+
}[role]
|
|
216
|
+
return RoleInfo(**parser(response)) # type: ignore
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class LatencyHistogramCallback(
|
|
220
|
+
ResponseCallback[ResponseType, ResponseType, dict[AnyStr, dict[AnyStr, RedisValueT]]]
|
|
221
|
+
):
|
|
222
|
+
def transform(
|
|
223
|
+
self,
|
|
224
|
+
response: ResponseType,
|
|
225
|
+
) -> dict[AnyStr, dict[AnyStr, RedisValueT]]:
|
|
226
|
+
histogram = flat_pairs_to_dict(response)
|
|
227
|
+
for key, value in histogram.items():
|
|
228
|
+
histogram[key] = EncodingInsensitiveDict(flat_pairs_to_dict(value))
|
|
229
|
+
histogram[key]["histogram_usec"] = flat_pairs_to_dict(histogram[key]["histogram_usec"])
|
|
230
|
+
histogram[key] = dict(histogram[key])
|
|
231
|
+
return histogram
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class LatencyCallback(
|
|
235
|
+
ResponseCallback[ResponseType, ResponseType, dict[AnyStr, tuple[int, int, int]]]
|
|
236
|
+
):
|
|
237
|
+
def transform(
|
|
238
|
+
self,
|
|
239
|
+
response: ResponseType,
|
|
240
|
+
) -> dict[AnyStr, tuple[int, int, int]]:
|
|
241
|
+
return {k[0]: (k[1], k[2], k[3]) for k in response}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import cast
|
|
4
|
+
|
|
5
|
+
from coredis.response._callbacks import ResponseCallback
|
|
6
|
+
from coredis.typing import (
|
|
7
|
+
AnyStr,
|
|
8
|
+
Iterable,
|
|
9
|
+
ResponsePrimitive,
|
|
10
|
+
ResponseType,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SScanCallback(
|
|
15
|
+
ResponseCallback[list[ResponseType], list[ResponseType], tuple[int, set[AnyStr]]]
|
|
16
|
+
):
|
|
17
|
+
def transform(
|
|
18
|
+
self,
|
|
19
|
+
response: list[ResponseType],
|
|
20
|
+
) -> tuple[int, set[AnyStr]]:
|
|
21
|
+
cursor, r = response
|
|
22
|
+
assert isinstance(cursor, (bytes, str)) and isinstance(r, Iterable)
|
|
23
|
+
return int(cursor), set(cast(Iterable[AnyStr], r))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ItemOrSetCallback(
|
|
27
|
+
ResponseCallback[
|
|
28
|
+
AnyStr | list[ResponsePrimitive] | set[ResponsePrimitive],
|
|
29
|
+
AnyStr | set[ResponsePrimitive],
|
|
30
|
+
AnyStr | set[AnyStr],
|
|
31
|
+
]
|
|
32
|
+
):
|
|
33
|
+
def transform(
|
|
34
|
+
self,
|
|
35
|
+
response: AnyStr | list[ResponsePrimitive] | set[ResponsePrimitive],
|
|
36
|
+
) -> AnyStr | set[AnyStr]:
|
|
37
|
+
if self.options.get("count"):
|
|
38
|
+
if isinstance(response, set):
|
|
39
|
+
return cast(set[AnyStr], response)
|
|
40
|
+
if isinstance(response, list):
|
|
41
|
+
return cast(set[AnyStr], set(response) if response else set())
|
|
42
|
+
raise ValueError(f"Unable to map {response!r} to set")
|
|
43
|
+
else:
|
|
44
|
+
return cast(AnyStr, response)
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import SupportsFloat, cast
|
|
4
|
+
|
|
5
|
+
from coredis.response._callbacks import ResponseCallback
|
|
6
|
+
from coredis.response.types import ScoredMember, ScoredMembers
|
|
7
|
+
from coredis.typing import (
|
|
8
|
+
AnyStr,
|
|
9
|
+
Generic,
|
|
10
|
+
ResponsePrimitive,
|
|
11
|
+
ResponseType,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ZRankCallback(
|
|
16
|
+
ResponseCallback[
|
|
17
|
+
int | list[ResponsePrimitive] | None,
|
|
18
|
+
int | list[ResponsePrimitive] | None,
|
|
19
|
+
int | tuple[int, float] | None,
|
|
20
|
+
],
|
|
21
|
+
):
|
|
22
|
+
def transform(
|
|
23
|
+
self,
|
|
24
|
+
response: int | list[ResponsePrimitive] | None,
|
|
25
|
+
) -> int | tuple[int, float] | None:
|
|
26
|
+
if self.options.get("withscore"):
|
|
27
|
+
return (response[0], float(response[1])) if response else None
|
|
28
|
+
else:
|
|
29
|
+
return cast(int | None, response)
|
|
30
|
+
|
|
31
|
+
def transform_3(
|
|
32
|
+
self,
|
|
33
|
+
response: int | list[ResponsePrimitive] | None,
|
|
34
|
+
) -> int | tuple[int, float] | None:
|
|
35
|
+
if self.options.get("withscore"):
|
|
36
|
+
return (response[0], response[1]) if response else None
|
|
37
|
+
else:
|
|
38
|
+
return cast(int | None, response)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ZMembersOrScoredMembers(
|
|
42
|
+
ResponseCallback[
|
|
43
|
+
list[AnyStr | list[ResponsePrimitive]],
|
|
44
|
+
list[AnyStr | list[ResponsePrimitive]],
|
|
45
|
+
tuple[AnyStr | ScoredMember, ...],
|
|
46
|
+
],
|
|
47
|
+
):
|
|
48
|
+
def transform(
|
|
49
|
+
self,
|
|
50
|
+
response: list[AnyStr | list[ResponsePrimitive]],
|
|
51
|
+
) -> tuple[AnyStr | ScoredMember, ...]:
|
|
52
|
+
if not response:
|
|
53
|
+
return ()
|
|
54
|
+
elif self.options.get("withscores"):
|
|
55
|
+
it = iter(cast(list[AnyStr], response))
|
|
56
|
+
return tuple(ScoredMember(*v) for v in zip(it, map(float, it)))
|
|
57
|
+
else:
|
|
58
|
+
return cast(tuple[AnyStr, ...], tuple(response))
|
|
59
|
+
|
|
60
|
+
def transform_3(
|
|
61
|
+
self,
|
|
62
|
+
response: list[AnyStr | list[ResponsePrimitive]],
|
|
63
|
+
) -> tuple[AnyStr | ScoredMember, ...]:
|
|
64
|
+
if self.options.get("withscores"):
|
|
65
|
+
return tuple(ScoredMember(*v) for v in cast(list[tuple[AnyStr, float]], response))
|
|
66
|
+
else:
|
|
67
|
+
return cast(tuple[AnyStr, ...], tuple(response))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ZSetScorePairCallback(
|
|
71
|
+
ResponseCallback[
|
|
72
|
+
list[ResponsePrimitive] | None,
|
|
73
|
+
list[ResponsePrimitive | list[ResponsePrimitive]] | None,
|
|
74
|
+
ScoredMember | ScoredMembers | None,
|
|
75
|
+
],
|
|
76
|
+
Generic[AnyStr],
|
|
77
|
+
):
|
|
78
|
+
def transform(
|
|
79
|
+
self,
|
|
80
|
+
response: list[ResponsePrimitive] | None,
|
|
81
|
+
) -> ScoredMember | ScoredMembers | None:
|
|
82
|
+
if not response:
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
if not (self.options.get("withscores") or self.options.get("count")):
|
|
86
|
+
return ScoredMember(cast(AnyStr, response[0]), float(cast(SupportsFloat, response[1])))
|
|
87
|
+
|
|
88
|
+
it = iter(response)
|
|
89
|
+
return tuple(ScoredMember(*v) for v in zip(it, map(float, it)))
|
|
90
|
+
|
|
91
|
+
def transform_3(
|
|
92
|
+
self,
|
|
93
|
+
response: list[ResponsePrimitive | list[ResponsePrimitive]] | None,
|
|
94
|
+
) -> ScoredMember | ScoredMembers | None:
|
|
95
|
+
if not response:
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
if not (self.options.get("withscores") or self.options.get("count")):
|
|
99
|
+
return ScoredMember(*cast(tuple[AnyStr, float], response))
|
|
100
|
+
|
|
101
|
+
return tuple(ScoredMember(*v) for v in cast(list[tuple[AnyStr, float]], response))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class ZMPopCallback(
|
|
105
|
+
ResponseCallback[
|
|
106
|
+
list[ResponseType] | None,
|
|
107
|
+
list[ResponseType] | None,
|
|
108
|
+
tuple[AnyStr, ScoredMembers] | None,
|
|
109
|
+
],
|
|
110
|
+
Generic[AnyStr],
|
|
111
|
+
):
|
|
112
|
+
def transform(
|
|
113
|
+
self,
|
|
114
|
+
response: list[ResponseType] | None,
|
|
115
|
+
) -> tuple[AnyStr, ScoredMembers] | None:
|
|
116
|
+
r = cast(tuple[AnyStr, list[tuple[AnyStr, int]]], response)
|
|
117
|
+
if r:
|
|
118
|
+
return r[0], tuple(ScoredMember(v[0], float(v[1])) for v in r[1])
|
|
119
|
+
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ZMScoreCallback(
|
|
124
|
+
ResponseCallback[list[ResponsePrimitive], list[ResponsePrimitive], tuple[float | None, ...]]
|
|
125
|
+
):
|
|
126
|
+
def transform(
|
|
127
|
+
self,
|
|
128
|
+
response: list[ResponsePrimitive],
|
|
129
|
+
) -> tuple[float | None, ...]:
|
|
130
|
+
return tuple(score if score is None else float(score) for score in response)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class ZScanCallback(
|
|
134
|
+
ResponseCallback[list[ResponseType], list[ResponseType], tuple[int, ScoredMembers]],
|
|
135
|
+
Generic[AnyStr],
|
|
136
|
+
):
|
|
137
|
+
def transform(
|
|
138
|
+
self,
|
|
139
|
+
response: list[ResponseType],
|
|
140
|
+
) -> tuple[int, ScoredMembers]:
|
|
141
|
+
cursor, r = cast(tuple[int, list[AnyStr]], response)
|
|
142
|
+
it = iter(r)
|
|
143
|
+
return int(cursor), tuple(
|
|
144
|
+
ScoredMember(*cast(tuple[AnyStr, float], v)) for v in zip(it, map(float, it))
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class ZRandMemberCallback(
|
|
149
|
+
ResponseCallback[
|
|
150
|
+
AnyStr | list[ResponsePrimitive] | None,
|
|
151
|
+
AnyStr | list[list[ResponsePrimitive]] | list[ResponsePrimitive] | None,
|
|
152
|
+
AnyStr | tuple[AnyStr, ...] | ScoredMembers | None,
|
|
153
|
+
]
|
|
154
|
+
):
|
|
155
|
+
def transform(
|
|
156
|
+
self,
|
|
157
|
+
response: AnyStr | list[ResponsePrimitive] | None,
|
|
158
|
+
) -> AnyStr | tuple[AnyStr, ...] | ScoredMembers | None:
|
|
159
|
+
if not (response and self.options.get("withscores")):
|
|
160
|
+
return tuple(response) if isinstance(response, list) else response
|
|
161
|
+
|
|
162
|
+
it = iter(response)
|
|
163
|
+
return tuple(ScoredMember(*v) for v in zip(it, map(float, it)))
|
|
164
|
+
|
|
165
|
+
def transform_3(
|
|
166
|
+
self,
|
|
167
|
+
response: AnyStr | list[list[ResponsePrimitive]] | list[ResponsePrimitive] | None,
|
|
168
|
+
) -> AnyStr | tuple[AnyStr, ...] | ScoredMembers | None:
|
|
169
|
+
if not (response and self.options.get("withscores")):
|
|
170
|
+
return tuple(response) if isinstance(response, list) else response
|
|
171
|
+
|
|
172
|
+
return tuple(ScoredMember(*v) for v in response)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class BZPopCallback(
|
|
176
|
+
ResponseCallback[
|
|
177
|
+
list[ResponsePrimitive] | None,
|
|
178
|
+
list[ResponsePrimitive] | None,
|
|
179
|
+
tuple[AnyStr, AnyStr, float] | None,
|
|
180
|
+
]
|
|
181
|
+
):
|
|
182
|
+
def transform(
|
|
183
|
+
self,
|
|
184
|
+
response: list[ResponsePrimitive] | None,
|
|
185
|
+
) -> tuple[AnyStr, AnyStr, float] | None:
|
|
186
|
+
if response:
|
|
187
|
+
return response[0], response[1], float(response[2])
|
|
188
|
+
return None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class ZAddCallback(ResponseCallback[ResponsePrimitive, int | float, int | float]):
|
|
192
|
+
def transform(
|
|
193
|
+
self,
|
|
194
|
+
response: ResponsePrimitive,
|
|
195
|
+
) -> int | float:
|
|
196
|
+
if self.options.get("condition"):
|
|
197
|
+
return float(response)
|
|
198
|
+
return int(response)
|
|
199
|
+
|
|
200
|
+
def transform_3(
|
|
201
|
+
self,
|
|
202
|
+
response: int | float,
|
|
203
|
+
) -> int | float:
|
|
204
|
+
return response
|