Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/redis/_parsers/response_callbacks.py: 50%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

22 statements  

1"""Response-callback dictionaries and the protocol/legacy selector. 

2 

3This module is the single source of truth for the mapping between Redis 

4command names and the Python-side callbacks that post-process raw parser 

5output into user-facing values. 

6 

7Six dictionaries are defined: 

8 

9* ``_RedisCallbacks`` — entries that produce the same Python value 

10 regardless of wire protocol or legacy-response selection. 

11* ``_RedisCallbacksRESP2`` — RESP2 wire, legacy Python shapes. 

12* ``_RedisCallbacksRESP3`` — RESP3 wire, Python shapes from the previous 

13 RESP3 callbacks. 

14* ``_RedisCallbacksRESP2Unified`` — RESP2 wire, unified Python shapes 

15 (``legacy_responses=False``). 

16* ``_RedisCallbacksRESP3Unified`` — RESP3 wire, unified Python shapes 

17 (``legacy_responses=False``). 

18* ``_RedisCallbacksRESP3toRESP2Legacy`` — RESP3 wire converted back to the 

19 legacy RESP2 Python shapes for users who keep ``legacy_responses=True`` 

20 on a RESP3 connection. 

21 

22``get_response_callbacks`` merges ``_RedisCallbacks`` with the appropriate 

23protocol-specific overlay. Callers wrap the returned dict in 

24``CaseInsensitiveDict``. 

25""" 

26 

27from typing import Any, Callable, Optional 

28 

29from redis.utils import str_if_bytes 

30 

31from .helpers import ( 

32 bool_ok, 

33 bzpop_score_resp3_to_resp2_legacy, 

34 bzpop_score_unified, 

35 float_or_none, 

36 hrandfield_resp3_to_resp2_legacy, 

37 hrandfield_unified, 

38 pairs_to_dict, 

39 parse_acl_getuser, 

40 parse_acl_getuser_resp3_to_resp2_legacy, 

41 parse_acl_getuser_unified, 

42 parse_acl_log, 

43 parse_acl_log_resp3_to_resp2_legacy, 

44 parse_acl_log_resp3_unified, 

45 parse_arinfo, 

46 parse_client_info, 

47 parse_client_kill, 

48 parse_client_list, 

49 parse_client_trackinginfo_resp3_to_resp2_legacy, 

50 parse_client_trackinginfo_unified, 

51 parse_cluster_info, 

52 parse_cluster_links_resp3_to_resp2_legacy, 

53 parse_cluster_links_unified, 

54 parse_cluster_nodes, 

55 parse_command, 

56 parse_command_resp3, 

57 parse_command_unified, 

58 parse_config_get, 

59 parse_config_get_resp3_to_resp2_legacy, 

60 parse_debug_object, 

61 parse_function_list_resp3_to_resp2_legacy, 

62 parse_function_list_unified, 

63 parse_geopos_resp3_to_resp2_legacy, 

64 parse_geopos_unified, 

65 parse_geosearch_generic, 

66 parse_geosearch_generic_unified, 

67 parse_hscan, 

68 parse_info, 

69 parse_lcs_idx_resp3_to_resp2_legacy, 

70 parse_lcs_idx_unified, 

71 parse_list_of_dicts, 

72 parse_list_of_dicts_resp3, 

73 parse_memory_stats, 

74 parse_memory_stats_resp3, 

75 parse_memory_stats_unified, 

76 parse_pubsub_numsub, 

77 parse_scan, 

78 parse_sentinel_get_master, 

79 parse_sentinel_master, 

80 parse_sentinel_master_resp3_to_resp2_legacy, 

81 parse_sentinel_master_unified, 

82 parse_sentinel_master_unified_resp3, 

83 parse_sentinel_masters, 

84 parse_sentinel_masters_resp3, 

85 parse_sentinel_masters_resp3_to_resp2_legacy, 

86 parse_sentinel_masters_unified, 

87 parse_sentinel_masters_unified_resp3, 

88 parse_sentinel_slaves_and_sentinels, 

89 parse_sentinel_slaves_and_sentinels_resp3, 

90 parse_sentinel_slaves_and_sentinels_resp3_to_resp2_legacy, 

91 parse_sentinel_slaves_and_sentinels_unified, 

92 parse_sentinel_slaves_and_sentinels_unified_resp3, 

93 parse_sentinel_state_resp3, 

94 parse_set_result, 

95 parse_slowlog_get, 

96 parse_stralgo, 

97 parse_stralgo_resp3_unified, 

98 parse_stralgo_unified, 

99 parse_stream_list, 

100 parse_xautoclaim, 

101 parse_xclaim, 

102 parse_xinfo_stream, 

103 parse_xpending, 

104 parse_xread, 

105 parse_xread_resp3, 

106 parse_xread_resp3_to_resp2_legacy, 

107 parse_xread_unified, 

108 parse_zadd, 

109 parse_zmscore, 

110 parse_zscan, 

111 parse_zscan_unified, 

112 sort_return_tuples, 

113 string_keys_to_dict, 

114 timestamp_to_datetime, 

115 zmpop_resp3_to_resp2_legacy, 

116 zmpop_unified, 

117 zpop_score_pairs, 

118 zpop_score_pairs_resp3_to_resp2_legacy, 

119 zpop_score_pairs_resp3_unified, 

120 zpop_score_pairs_unified, 

121 zset_score_for_rank, 

122 zset_score_for_rank_resp3, 

123 zset_score_for_rank_resp3_to_resp2_legacy, 

124 zset_score_for_rank_unified, 

125 zset_score_pairs, 

126 zset_score_pairs_resp3, 

127 zset_score_pairs_resp3_to_resp2_legacy, 

128 zset_score_pairs_resp3_to_resp2_legacy_flat, 

129 zset_score_pairs_unified, 

130) 

131 

132_RedisCallbacks = { 

133 **string_keys_to_dict( 

134 "AUTH COPY EXPIRE EXPIREAT HEXISTS HMSET MOVE MSETNX PERSIST PSETEX " 

135 "PEXPIRE PEXPIREAT RENAMENX SETEX SETNX SMOVE", 

136 bool, 

137 ), 

138 **string_keys_to_dict("HINCRBYFLOAT INCRBYFLOAT", float), 

139 **string_keys_to_dict( 

140 "ASKING FLUSHALL FLUSHDB LSET LTRIM MSET PFMERGE READONLY READWRITE " 

141 "RENAME SAVE SELECT SHUTDOWN SLAVEOF SWAPDB WATCH UNWATCH", 

142 bool_ok, 

143 ), 

144 **string_keys_to_dict("XREAD XREADGROUP", parse_xread), 

145 **string_keys_to_dict( 

146 "GEORADIUS GEORADIUSBYMEMBER GEOSEARCH", 

147 parse_geosearch_generic, 

148 ), 

149 **string_keys_to_dict("XRANGE XREVRANGE", parse_stream_list), 

150 "ACL GETUSER": parse_acl_getuser, 

151 "ACL LOAD": bool_ok, 

152 "ACL LOG": parse_acl_log, 

153 "ACL SETUSER": bool_ok, 

154 "ACL SAVE": bool_ok, 

155 "CLIENT INFO": parse_client_info, 

156 "CLIENT KILL": parse_client_kill, 

157 "CLIENT LIST": parse_client_list, 

158 "CLIENT PAUSE": bool_ok, 

159 "CLIENT SETINFO": bool_ok, 

160 "CLIENT SETNAME": bool_ok, 

161 "CLIENT UNBLOCK": bool, 

162 "CLUSTER ADDSLOTS": bool_ok, 

163 "CLUSTER ADDSLOTSRANGE": bool_ok, 

164 "CLUSTER DELSLOTS": bool_ok, 

165 "CLUSTER DELSLOTSRANGE": bool_ok, 

166 "CLUSTER FAILOVER": bool_ok, 

167 "CLUSTER FORGET": bool_ok, 

168 "CLUSTER INFO": parse_cluster_info, 

169 "CLUSTER MEET": bool_ok, 

170 "CLUSTER NODES": parse_cluster_nodes, 

171 "CLUSTER REPLICAS": parse_cluster_nodes, 

172 "CLUSTER REPLICATE": bool_ok, 

173 "CLUSTER RESET": bool_ok, 

174 "CLUSTER SAVECONFIG": bool_ok, 

175 "CLUSTER SET-CONFIG-EPOCH": bool_ok, 

176 "CLUSTER SETSLOT": bool_ok, 

177 "CLUSTER SLAVES": parse_cluster_nodes, 

178 "COMMAND": parse_command, 

179 "CONFIG RESETSTAT": bool_ok, 

180 "CONFIG SET": bool_ok, 

181 "FUNCTION DELETE": bool_ok, 

182 "FUNCTION FLUSH": bool_ok, 

183 "FUNCTION RESTORE": bool_ok, 

184 "GEODIST": float_or_none, 

185 "HSCAN": parse_hscan, 

186 "INFO": parse_info, 

187 "LASTSAVE": timestamp_to_datetime, 

188 "MEMORY PURGE": bool_ok, 

189 "MODULE LOAD": bool, 

190 "MODULE UNLOAD": bool, 

191 "PING": lambda r: str_if_bytes(r) == "PONG", 

192 "PUBSUB NUMSUB": parse_pubsub_numsub, 

193 "PUBSUB SHARDNUMSUB": parse_pubsub_numsub, 

194 "QUIT": bool_ok, 

195 "SET": parse_set_result, 

196 "SCAN": parse_scan, 

197 "SCRIPT EXISTS": lambda r: list(map(bool, r)), 

198 "SCRIPT FLUSH": bool_ok, 

199 "SCRIPT KILL": bool_ok, 

200 "SCRIPT LOAD": str_if_bytes, 

201 "SENTINEL CKQUORUM": bool_ok, 

202 "SENTINEL FAILOVER": bool_ok, 

203 "SENTINEL FLUSHCONFIG": bool_ok, 

204 "SENTINEL GET-MASTER-ADDR-BY-NAME": parse_sentinel_get_master, 

205 "SENTINEL MONITOR": bool_ok, 

206 "SENTINEL RESET": bool_ok, 

207 "SENTINEL REMOVE": bool_ok, 

208 "SENTINEL SET": bool_ok, 

209 "SLOWLOG GET": parse_slowlog_get, 

210 "SLOWLOG RESET": bool_ok, 

211 "SORT": sort_return_tuples, 

212 "SSCAN": parse_scan, 

213 "TIME": lambda x: (int(x[0]), int(x[1])), 

214 "XAUTOCLAIM": parse_xautoclaim, 

215 "XCLAIM": parse_xclaim, 

216 "XGROUP CREATE": bool_ok, 

217 "XGROUP DESTROY": bool, 

218 "XGROUP SETID": bool_ok, 

219 "ARINFO": parse_arinfo, 

220 "XINFO STREAM": parse_xinfo_stream, 

221 "XPENDING": parse_xpending, 

222 "ZSCAN": parse_zscan, 

223} 

224 

225 

226_RedisCallbacksRESP2 = { 

227 **string_keys_to_dict( 

228 "SDIFF SINTER SMEMBERS SUNION", lambda r: r and set(r) or set() 

229 ), 

230 **string_keys_to_dict( 

231 "ZINTER ZRANGE ZRANGEBYSCORE ZREVRANGE ZREVRANGEBYSCORE ZUNION", 

232 zset_score_pairs, 

233 ), 

234 **string_keys_to_dict("ZPOPMAX ZPOPMIN", zpop_score_pairs), 

235 **string_keys_to_dict( 

236 "ZREVRANK ZRANK", 

237 zset_score_for_rank, 

238 ), 

239 **string_keys_to_dict("ZINCRBY ZSCORE", float_or_none), 

240 **string_keys_to_dict("BGREWRITEAOF BGSAVE", lambda r: True), 

241 **string_keys_to_dict("BLPOP BRPOP", lambda r: r and tuple(r) or None), 

242 **string_keys_to_dict( 

243 "BZPOPMAX BZPOPMIN", lambda r: r and (r[0], r[1], float(r[2])) or None 

244 ), 

245 "ACL CAT": lambda r: list(map(str_if_bytes, r)), 

246 "ACL GENPASS": str_if_bytes, 

247 "ACL HELP": lambda r: list(map(str_if_bytes, r)), 

248 "ACL LIST": lambda r: list(map(str_if_bytes, r)), 

249 "ACL USERS": lambda r: list(map(str_if_bytes, r)), 

250 "ACL WHOAMI": str_if_bytes, 

251 "CLIENT GETNAME": str_if_bytes, 

252 "CLIENT TRACKINGINFO": lambda r: list(map(str_if_bytes, r)), 

253 "CLUSTER GETKEYSINSLOT": lambda r: list(map(str_if_bytes, r)), 

254 "COMMAND GETKEYS": lambda r: list(map(str_if_bytes, r)), 

255 "CONFIG GET": parse_config_get, 

256 "DEBUG OBJECT": parse_debug_object, 

257 "GEOHASH": lambda r: list(map(str_if_bytes, r)), 

258 "GEOPOS": lambda r: list( 

259 map(lambda ll: (float(ll[0]), float(ll[1])) if ll is not None else None, r) 

260 ), 

261 "HGETALL": lambda r: r and pairs_to_dict(r) or {}, 

262 "HOTKEYS GET": lambda r: [pairs_to_dict(m) for m in r], 

263 "MEMORY STATS": parse_memory_stats, 

264 "MODULE LIST": lambda r: [pairs_to_dict(m) for m in r], 

265 "RESET": str_if_bytes, 

266 "SENTINEL MASTER": parse_sentinel_master, 

267 "SENTINEL MASTERS": parse_sentinel_masters, 

268 "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels, 

269 "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels, 

270 "STRALGO": parse_stralgo, 

271 "XINFO CONSUMERS": parse_list_of_dicts, 

272 "XINFO GROUPS": parse_list_of_dicts, 

273 "ZADD": parse_zadd, 

274 "ZMSCORE": parse_zmscore, 

275} 

276 

277 

278_RedisCallbacksRESP3 = { 

279 **string_keys_to_dict( 

280 "SDIFF SINTER SMEMBERS SUNION", lambda r: r and set(r) or set() 

281 ), 

282 **string_keys_to_dict( 

283 "ZRANGE ZINTER ZPOPMAX ZPOPMIN HGETALL XREADGROUP", 

284 lambda r, **kwargs: r, 

285 ), 

286 **string_keys_to_dict( 

287 "ZRANGE ZRANGEBYSCORE ZREVRANGE ZREVRANGEBYSCORE ZUNION", 

288 zset_score_pairs_resp3, 

289 ), 

290 **string_keys_to_dict( 

291 "ZREVRANK ZRANK", 

292 zset_score_for_rank_resp3, 

293 ), 

294 **string_keys_to_dict("XREAD XREADGROUP", parse_xread_resp3), 

295 "ACL LOG": lambda r: ( 

296 [ 

297 {str_if_bytes(key): str_if_bytes(value) for key, value in x.items()} 

298 for x in r 

299 ] 

300 if isinstance(r, list) 

301 else bool_ok(r) 

302 ), 

303 "COMMAND": parse_command_resp3, 

304 "CONFIG GET": parse_config_get_resp3_to_resp2_legacy, 

305 "MEMORY STATS": parse_memory_stats_resp3, 

306 "SENTINEL MASTER": parse_sentinel_state_resp3, 

307 "SENTINEL MASTERS": parse_sentinel_masters_resp3, 

308 "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels_resp3, 

309 "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels_resp3, 

310 "STRALGO": lambda r, **options: ( 

311 {str_if_bytes(key): str_if_bytes(value) for key, value in r.items()} 

312 if isinstance(r, dict) 

313 else str_if_bytes(r) 

314 ), 

315 "XINFO CONSUMERS": parse_list_of_dicts_resp3, 

316 "XINFO GROUPS": parse_list_of_dicts_resp3, 

317} 

318 

319 

320# RESP2 wire, unified response shapes (``legacy_responses=False``). 

321_RedisCallbacksRESP2Unified: dict[str, Callable[..., Any]] = { 

322 **_RedisCallbacksRESP2, 

323 **string_keys_to_dict( 

324 "ZDIFF ZINTER ZRANGE ZRANGEBYSCORE ZREVRANGE ZREVRANGEBYSCORE ZUNION", 

325 zset_score_pairs_unified, 

326 ), 

327 **string_keys_to_dict( 

328 "ZPOPMAX ZPOPMIN", 

329 zpop_score_pairs_unified, 

330 ), 

331 **string_keys_to_dict( 

332 "ZREVRANK ZRANK", 

333 zset_score_for_rank_unified, 

334 ), 

335 **string_keys_to_dict( 

336 "BZPOPMAX BZPOPMIN", 

337 bzpop_score_unified, 

338 ), 

339 **string_keys_to_dict("XREAD XREADGROUP", parse_xread_unified), 

340 **string_keys_to_dict( 

341 "GEORADIUS GEORADIUSBYMEMBER GEOSEARCH", 

342 parse_geosearch_generic_unified, 

343 ), 

344 **string_keys_to_dict("BLPOP BRPOP", lambda r: r or None), 

345 **string_keys_to_dict("ZMPOP BZMPOP", zmpop_unified), 

346 "ZSCAN": parse_zscan_unified, 

347 "ZRANDMEMBER": zset_score_pairs_unified, 

348 "HRANDFIELD": hrandfield_unified, 

349 "ACL GETUSER": parse_acl_getuser_unified, 

350 "CLIENT TRACKINGINFO": parse_client_trackinginfo_unified, 

351 "CLUSTER GETKEYSINSLOT": lambda r, **kwargs: r, 

352 "CLUSTER LINKS": parse_cluster_links_unified, 

353 "COMMAND": parse_command_unified, 

354 "COMMAND GETKEYS": lambda r, **kwargs: r, 

355 "FUNCTION LIST": parse_function_list_unified, 

356 "GEOPOS": parse_geopos_unified, 

357 "LCS": parse_lcs_idx_unified, 

358 "MEMORY STATS": parse_memory_stats_unified, 

359 "SENTINEL MASTER": parse_sentinel_master_unified, 

360 "SENTINEL MASTERS": parse_sentinel_masters_unified, 

361 "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels_unified, 

362 "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels_unified, 

363 "STRALGO": parse_stralgo_unified, 

364} 

365 

366 

367# RESP3 wire, unified response shapes (``legacy_responses=False``). 

368_RedisCallbacksRESP3Unified: dict[str, Callable[..., Any]] = { 

369 **_RedisCallbacksRESP3, 

370 **string_keys_to_dict( 

371 "ZDIFF ZINTER ZRANGE ZRANGEBYSCORE ZREVRANGE ZREVRANGEBYSCORE ZUNION", 

372 zset_score_pairs_resp3, 

373 ), 

374 **string_keys_to_dict( 

375 "ZPOPMAX ZPOPMIN", 

376 zpop_score_pairs_resp3_unified, 

377 ), 

378 **string_keys_to_dict( 

379 "BZPOPMAX BZPOPMIN", 

380 bzpop_score_unified, 

381 ), 

382 **string_keys_to_dict("XREAD XREADGROUP", parse_xread_unified), 

383 **string_keys_to_dict( 

384 "GEORADIUS GEORADIUSBYMEMBER GEOSEARCH", 

385 parse_geosearch_generic_unified, 

386 ), 

387 "ZSCAN": parse_zscan_unified, 

388 "ZRANDMEMBER": zset_score_pairs_resp3, 

389 "ACL CAT": lambda r: list(map(str_if_bytes, r)), 

390 "ACL GENPASS": str_if_bytes, 

391 "ACL HELP": lambda r: list(map(str_if_bytes, r)), 

392 "ACL LIST": lambda r: list(map(str_if_bytes, r)), 

393 "ACL LOG": parse_acl_log_resp3_unified, 

394 "ACL USERS": lambda r: list(map(str_if_bytes, r)), 

395 "ACL WHOAMI": str_if_bytes, 

396 "CLIENT GETNAME": str_if_bytes, 

397 "CLIENT TRACKINGINFO": parse_client_trackinginfo_unified, 

398 "CLUSTER LINKS": parse_cluster_links_unified, 

399 "COMMAND": parse_command_unified, 

400 "FUNCTION LIST": parse_function_list_unified, 

401 "GEOHASH": lambda r: list(map(str_if_bytes, r)), 

402 "LCS": parse_lcs_idx_unified, 

403 "RESET": str_if_bytes, 

404 "SENTINEL MASTER": parse_sentinel_master_unified_resp3, 

405 "SENTINEL MASTERS": parse_sentinel_masters_unified_resp3, 

406 "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels_unified_resp3, 

407 "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels_unified_resp3, 

408 "STRALGO": parse_stralgo_resp3_unified, 

409} 

410 

411 

412# RESP3 wire converted back to the legacy RESP2 Python shapes. Only the 

413# entries needed to undo RESP3-side differences are listed; everything 

414# else falls through to ``_RedisCallbacks``. Scores are re-encoded to bytes 

415# before being passed to ``score_cast_func`` so the callable observes the 

416# same input type it would on a RESP2 connection. 

417_RedisCallbacksRESP3toRESP2Legacy: dict[str, Callable[..., Any]] = { 

418 **string_keys_to_dict( 

419 "SDIFF SINTER SMEMBERS SUNION", lambda r: r and set(r) or set() 

420 ), 

421 **string_keys_to_dict( 

422 "ZINTER ZRANGE ZRANGEBYSCORE ZREVRANGE ZREVRANGEBYSCORE ZUNION", 

423 zset_score_pairs_resp3_to_resp2_legacy, 

424 ), 

425 "ZDIFF": zset_score_pairs_resp3_to_resp2_legacy_flat, 

426 "ZRANDMEMBER": zset_score_pairs_resp3_to_resp2_legacy_flat, 

427 **string_keys_to_dict( 

428 "ZPOPMAX ZPOPMIN", 

429 zpop_score_pairs_resp3_to_resp2_legacy, 

430 ), 

431 **string_keys_to_dict( 

432 "BZPOPMAX BZPOPMIN", 

433 bzpop_score_resp3_to_resp2_legacy, 

434 ), 

435 **string_keys_to_dict( 

436 "ZREVRANK ZRANK", 

437 zset_score_for_rank_resp3_to_resp2_legacy, 

438 ), 

439 **string_keys_to_dict("BGREWRITEAOF BGSAVE", lambda r: True), 

440 **string_keys_to_dict("XREAD XREADGROUP", parse_xread_resp3_to_resp2_legacy), 

441 **string_keys_to_dict("BLPOP BRPOP", lambda r: r and tuple(r) or None), 

442 **string_keys_to_dict("ZMPOP BZMPOP", zmpop_resp3_to_resp2_legacy), 

443 "HRANDFIELD": hrandfield_resp3_to_resp2_legacy, 

444 "ACL CAT": lambda r: list(map(str_if_bytes, r)), 

445 "ACL GENPASS": str_if_bytes, 

446 "ACL GETUSER": parse_acl_getuser_resp3_to_resp2_legacy, 

447 "ACL HELP": lambda r: list(map(str_if_bytes, r)), 

448 "ACL LIST": lambda r: list(map(str_if_bytes, r)), 

449 "ACL LOG": parse_acl_log_resp3_to_resp2_legacy, 

450 "ACL USERS": lambda r: list(map(str_if_bytes, r)), 

451 "ACL WHOAMI": str_if_bytes, 

452 "CLIENT GETNAME": str_if_bytes, 

453 "CLIENT TRACKINGINFO": parse_client_trackinginfo_resp3_to_resp2_legacy, 

454 "CLUSTER GETKEYSINSLOT": lambda r: list(map(str_if_bytes, r)), 

455 "CLUSTER LINKS": parse_cluster_links_resp3_to_resp2_legacy, 

456 "COMMAND GETKEYS": lambda r: list(map(str_if_bytes, r)), 

457 "CONFIG GET": parse_config_get_resp3_to_resp2_legacy, 

458 "DEBUG OBJECT": parse_debug_object, 

459 "FUNCTION LIST": parse_function_list_resp3_to_resp2_legacy, 

460 "GEOHASH": lambda r: list(map(str_if_bytes, r)), 

461 "GEOPOS": parse_geopos_resp3_to_resp2_legacy, 

462 "LCS": parse_lcs_idx_resp3_to_resp2_legacy, 

463 "MEMORY STATS": parse_memory_stats_resp3, 

464 "RESET": str_if_bytes, 

465 "SENTINEL MASTER": parse_sentinel_master_resp3_to_resp2_legacy, 

466 "SENTINEL MASTERS": parse_sentinel_masters_resp3_to_resp2_legacy, 

467 "SENTINEL SENTINELS": parse_sentinel_slaves_and_sentinels_resp3_to_resp2_legacy, 

468 "SENTINEL SLAVES": parse_sentinel_slaves_and_sentinels_resp3_to_resp2_legacy, 

469 "XINFO CONSUMERS": parse_list_of_dicts_resp3, 

470 "XINFO GROUPS": parse_list_of_dicts_resp3, 

471} 

472 

473 

474def get_response_callbacks( 

475 user_protocol: Optional[int], 

476 legacy_responses: bool, 

477) -> dict[str, Callable[..., Any]]: 

478 """Return the merged callback dict for the given (protocol, legacy) 

479 combination. 

480 

481 ``user_protocol`` is the value the user supplied to the client 

482 constructor (``None`` means "not specified"). ``legacy_responses`` 

483 defaults to ``True`` and selects today's RESP2-style Python shapes 

484 even when the wire protocol is RESP3. 

485 

486 Callers wrap the returned dict in ``CaseInsensitiveDict``. 

487 """ 

488 callbacks: dict[str, Callable[..., Any]] = dict(_RedisCallbacks) 

489 if legacy_responses: 

490 if user_protocol is None: 

491 callbacks.update(_RedisCallbacksRESP3toRESP2Legacy) 

492 elif user_protocol in (3, "3"): 

493 callbacks.update(_RedisCallbacksRESP3) 

494 else: 

495 callbacks.update(_RedisCallbacksRESP2) 

496 else: 

497 if user_protocol is None or user_protocol in (3, "3"): 

498 callbacks.update(_RedisCallbacksRESP3Unified) 

499 else: 

500 callbacks.update(_RedisCallbacksRESP2Unified) 

501 return callbacks