youtube-summarizer/venv311/lib/python3.11/site-packages/fakeredis/_command_args_parsing.py

143 lines
4.9 KiB
Python

from typing import Tuple, List, Dict, Any, Sequence, Optional
from . import _msgs as msgs
from ._commands import Int, Float
from ._helpers import SimpleError, null_terminate
def _count_params(s: str) -> int:
res = 0
while res < len(s) and s[res] in '.+*~':
res += 1
return res
def _encode_arg(s: str) -> bytes:
return s[_count_params(s):].encode()
def _default_value(s: str) -> Any:
if s[0] == '~':
return None
ind = _count_params(s)
if ind == 0:
return False
elif ind == 1:
return None
else:
return [None] * ind
def extract_args(
actual_args: Tuple[bytes, ...],
expected: Tuple[str, ...],
error_on_unexpected: bool = True,
left_from_first_unexpected: bool = True,
exception: Optional[str] = None
) -> Tuple[List[Any], Sequence[Any]]:
"""Parse argument values.
Extract from actual arguments which arguments exist and their value if relevant.
:param actual_args: The actual arguments to parse
:param expected: Arguments to look for, see below explanation.
:param error_on_unexpected: Should an error be raised when actual_args contain an unexpected argument?
:param left_from_first_unexpected: Once reaching an unexpected argument in actual_args, Should parsing stop?
:param exception: What exception msg to raise
:returns:
- List of values for expected arguments.
- List of remaining args.
An expected argument can have parameters:
- A numerical (Int) parameter is identified with '+'
- A float (Float) parameter is identified with '.'
- A non-numerical parameter is identified with a '*'
- An argument with potentially ~ or = between the
argument name and the value is identified with a '~'
- A numberical argument with potentially ~ or = between the
argument name and the value marked with a '~+'
E.g.
'++limit' will translate as an argument with 2 int parameters.
>>> extract_args((b'nx', b'ex', b'324', b'xx',), ('nx', 'xx', '+ex', 'keepttl'))
[True, True, 324, False], None
>>> extract_args(
(b'maxlen', b'10',b'nx', b'ex', b'324', b'xx',),
('~+maxlen', 'nx', 'xx', '+ex', 'keepttl'))
10, [True, True, 324, False], None
"""
args_info: Dict[bytes, Tuple[int, int]] = {
_encode_arg(k): (i, _count_params(k))
for (i, k) in enumerate(expected)
}
def _parse_params(key: bytes, ind: int, _actual_args: Tuple[bytes, ...]) -> Tuple[Any, int]:
"""Parse an argument from actual args.
:param key: Argument name to parse
:param ind: index of argument in actual_args
:param _actual_args: actual args
"""
pos, expected_following = args_info[key]
argument_name = expected[pos]
# Deal with parameters with optional ~/= before numerical value.
arg: Any
if argument_name[0] == '~':
if ind + 1 >= len(_actual_args):
raise SimpleError(msgs.SYNTAX_ERROR_MSG)
if _actual_args[ind + 1] != b'~' and _actual_args[ind + 1] != b'=':
arg, _parsed = _actual_args[ind + 1], 1
elif ind + 2 >= len(_actual_args):
raise SimpleError(msgs.SYNTAX_ERROR_MSG)
else:
arg, _parsed = _actual_args[ind + 2], 2
if argument_name[1] == '+':
arg = Int.decode(arg)
return arg, _parsed
# Boolean parameters
if expected_following == 0:
return True, 0
if ind + expected_following >= len(_actual_args):
raise SimpleError(msgs.SYNTAX_ERROR_MSG)
temp_res = []
for i in range(expected_following):
curr_arg: Any = _actual_args[ind + i + 1]
if argument_name[i] == '+':
curr_arg = Int.decode(curr_arg)
elif argument_name[i] == '.':
curr_arg = Float.decode(curr_arg)
temp_res.append(curr_arg)
if len(temp_res) == 1:
return temp_res[0], expected_following
else:
return temp_res, expected_following
results: List[Any] = [_default_value(key) for key in expected]
left_args = []
i = 0
while i < len(actual_args):
found = False
for key in args_info:
if null_terminate(actual_args[i]) == key:
arg_position, _ = args_info[key]
results[arg_position], parsed = _parse_params(key, i, actual_args)
i += parsed
found = True
break
if not found:
if error_on_unexpected:
raise (
SimpleError(msgs.SYNTAX_ERROR_MSG)
if exception is None
else SimpleError(exception.format(actual_args[i])))
if left_from_first_unexpected:
return results, actual_args[i:]
left_args.append(actual_args[i])
i += 1
return results, left_args