64 lines
1.2 KiB
Python
64 lines
1.2 KiB
Python
import re
|
|
import urllib.parse as urllib
|
|
|
|
OPERATORS = [
|
|
'!=',
|
|
'>=',
|
|
'<=',
|
|
'=',
|
|
'>',
|
|
'<',
|
|
'TO',
|
|
'EXISTS',
|
|
'IN',
|
|
'NOT IN',
|
|
]
|
|
|
|
|
|
def remove_quotes(value: str) -> str:
|
|
if (value.startswith('"') and value.endswith('"')) or (
|
|
value.startswith("'") and value.endswith("'")
|
|
):
|
|
return value[1:-1]
|
|
return value
|
|
|
|
|
|
def parse_condition(condition: str) -> dict[str, str] | None:
|
|
for op in OPERATORS:
|
|
parts = condition.split(op)
|
|
|
|
if len(parts) == 2:
|
|
attr, value = parts
|
|
attr = attr.strip()
|
|
value = remove_quotes(value.strip())
|
|
|
|
return {
|
|
'attr': attr,
|
|
'op': op,
|
|
'value': value,
|
|
}
|
|
|
|
return None
|
|
|
|
|
|
def parse(s: str) -> list[dict]:
|
|
filter_expr = re.sub(r'\s+', ' ', urllib.unquote(s)).strip()
|
|
|
|
if filter_expr == '':
|
|
return []
|
|
|
|
parts = re.split(r'\b(?:AND|OR)\b', filter_expr)
|
|
conditions = []
|
|
|
|
for part in parts:
|
|
condition = parse_condition(part.strip())
|
|
|
|
if condition:
|
|
conditions.append(condition)
|
|
|
|
return conditions
|
|
|
|
|
|
def encode(conditions: list[dict]):
|
|
return ' AND '.join(' '.join(c.values()).strip() for c in conditions if c)
|