Voice et bot modif
This commit is contained in:
parent
189d56026b
commit
7333a22bcd
10774 changed files with 634644 additions and 933308 deletions
|
|
@ -0,0 +1,175 @@
|
|||
from ..helpers import nativestr
|
||||
|
||||
|
||||
def list_to_dict(aList):
|
||||
return {nativestr(aList[i][0]): nativestr(aList[i][1]) for i in range(len(aList))}
|
||||
|
||||
|
||||
def _pairs_to_dict(pairs):
|
||||
"""Convert a list of [key, value] pairs to a dict without forcing str."""
|
||||
return {pairs[i][0]: pairs[i][1] for i in range(len(pairs))}
|
||||
|
||||
|
||||
def _nativestr_dict(d):
|
||||
"""Apply ``nativestr`` to every key and string-typed value of ``d``.
|
||||
|
||||
Used by the RESP3-to-RESP2-legacy adapters so labels coming from a
|
||||
RESP3 native map match today's RESP2 ``list_to_dict`` semantics.
|
||||
"""
|
||||
return {
|
||||
nativestr(k): nativestr(v) if isinstance(v, (bytes, str)) else v
|
||||
for k, v in d.items()
|
||||
}
|
||||
|
||||
|
||||
def parse_range(response, **kwargs):
|
||||
"""Parse range response. Used by TS.RANGE and TS.REVRANGE (legacy shape)."""
|
||||
if not response:
|
||||
return []
|
||||
# Multi-aggregator: samples have >2 elements [timestamp, val1, val2, ...]
|
||||
if len(response[0]) > 2:
|
||||
return [tuple([r[0]] + [float(v) for v in r[1:]]) for r in response]
|
||||
return [tuple((r[0], float(r[1]))) for r in response]
|
||||
|
||||
|
||||
def parse_range_unified(response, **kwargs):
|
||||
"""Unified parser for TS.RANGE / TS.REVRANGE.
|
||||
|
||||
Returns ``list[list]`` rather than ``list[tuple]`` so the unified
|
||||
shape is symmetric with the RESP3 wire format.
|
||||
"""
|
||||
if not response:
|
||||
return []
|
||||
if len(response[0]) > 2:
|
||||
return [[r[0]] + [float(v) for v in r[1:]] for r in response]
|
||||
return [[r[0], float(r[1])] for r in response]
|
||||
|
||||
|
||||
def parse_get(response):
|
||||
"""Parse get response. Used by TS.GET (legacy shape)."""
|
||||
if not response:
|
||||
return None
|
||||
return int(response[0]), float(response[1])
|
||||
|
||||
|
||||
def parse_get_unified(response, **kwargs):
|
||||
"""Unified parser for TS.GET. Returns ``[int, float]``."""
|
||||
if not response:
|
||||
return None
|
||||
return [int(response[0]), float(response[1])]
|
||||
|
||||
|
||||
def parse_m_get(response):
|
||||
"""Parse multi get response (RESP2 wire)."""
|
||||
res = []
|
||||
for item in response:
|
||||
if not item[2]:
|
||||
res.append({nativestr(item[0]): [list_to_dict(item[1]), None, None]})
|
||||
else:
|
||||
res.append(
|
||||
{
|
||||
nativestr(item[0]): [
|
||||
list_to_dict(item[1]),
|
||||
int(item[2][0]),
|
||||
float(item[2][1]),
|
||||
]
|
||||
}
|
||||
)
|
||||
return sorted(res, key=lambda d: list(d.keys()))
|
||||
|
||||
|
||||
def parse_m_get_unified(response, **kwargs):
|
||||
"""Unified parser for TS.MGET.
|
||||
|
||||
Emits ``{key: [labels_dict, sample]}`` where ``sample`` is
|
||||
``[int, float]`` or ``[]`` when no sample exists. Handles both wire
|
||||
formats: the RESP2 wire arrives as a list of ``[key, label_pairs,
|
||||
sample]`` triples; the RESP3 wire is already keyed by name.
|
||||
"""
|
||||
if isinstance(response, dict):
|
||||
res = {}
|
||||
for key, item in response.items():
|
||||
sample = item[1] if len(item) > 1 else []
|
||||
if not sample:
|
||||
res[key] = [item[0], []]
|
||||
else:
|
||||
res[key] = [item[0], [int(sample[0]), float(sample[1])]]
|
||||
return res
|
||||
res = {}
|
||||
for item in response:
|
||||
if not item[2]:
|
||||
res[item[0]] = [_pairs_to_dict(item[1]), []]
|
||||
else:
|
||||
res[item[0]] = [
|
||||
_pairs_to_dict(item[1]),
|
||||
[int(item[2][0]), float(item[2][1])],
|
||||
]
|
||||
return res
|
||||
|
||||
|
||||
def parse_m_get_resp3_to_resp2_legacy(response, **kwargs):
|
||||
"""RESP3 wire → today's RESP2 legacy shape for TS.MGET."""
|
||||
res = []
|
||||
for key, item in response.items():
|
||||
labels = _nativestr_dict(item[0]) if item[0] else {}
|
||||
sample = item[1] if len(item) > 1 else []
|
||||
if not sample:
|
||||
res.append({nativestr(key): [labels, None, None]})
|
||||
else:
|
||||
res.append({nativestr(key): [labels, int(sample[0]), float(sample[1])]})
|
||||
return sorted(res, key=lambda d: list(d.keys()))
|
||||
|
||||
|
||||
def parse_m_range(response, **kwargs):
|
||||
"""Parse multi range response (RESP2 wire)."""
|
||||
res = []
|
||||
for item in response:
|
||||
res.append({nativestr(item[0]): [list_to_dict(item[1]), parse_range(item[2])]})
|
||||
return sorted(res, key=lambda d: list(d.keys()))
|
||||
|
||||
|
||||
def _m_range_metadata(aggregation_type=None):
|
||||
if aggregation_type is None:
|
||||
# Aggregators are empty when TS.MRANGE/TS.MREVRANGE is called without
|
||||
# AGGREGATION; this mirrors RESP3 metadata such as {"aggregators": []}.
|
||||
return {"aggregators": []}
|
||||
if isinstance(aggregation_type, list):
|
||||
aggregators = aggregation_type
|
||||
else:
|
||||
aggregators = [aggregation_type]
|
||||
return {"aggregators": [nativestr(agg).lower() for agg in aggregators]}
|
||||
|
||||
|
||||
def parse_m_range_unified(response, **kwargs):
|
||||
"""Unified parser for TS.MRANGE / TS.MREVRANGE.
|
||||
|
||||
Emits ``{key: [labels_dict, metadata, samples]}`` regardless of wire
|
||||
format. RESP2 has no metadata element on the wire, so the command options
|
||||
are used to synthesize the same ``{"aggregators": ...}`` structure that
|
||||
RESP3 returns.
|
||||
"""
|
||||
if isinstance(response, dict):
|
||||
res = {}
|
||||
for key, item in response.items():
|
||||
metadata = item[1] if len(item) > 2 else []
|
||||
res[key] = [item[0], metadata, parse_range_unified(item[-1])]
|
||||
return res
|
||||
res = {}
|
||||
metadata = _m_range_metadata(kwargs.get("aggregation_type"))
|
||||
for item in response:
|
||||
res[item[0]] = [
|
||||
_pairs_to_dict(item[1]),
|
||||
metadata,
|
||||
parse_range_unified(item[2]),
|
||||
]
|
||||
return res
|
||||
|
||||
|
||||
def parse_m_range_resp3_to_resp2_legacy(response, **kwargs):
|
||||
"""RESP3 wire → today's RESP2 legacy shape for TS.MRANGE / TS.MREVRANGE."""
|
||||
res = []
|
||||
for key, item in response.items():
|
||||
labels = _nativestr_dict(item[0]) if item[0] else {}
|
||||
samples = item[-1]
|
||||
res.append({nativestr(key): [labels, parse_range(samples)]})
|
||||
return sorted(res, key=lambda d: list(d.keys()))
|
||||
Loading…
Add table
Add a link
Reference in a new issue