64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
from .shared import *
|
|
|
|
def _enum_value(value: Any) -> Any:
|
|
return value.value if hasattr(value, "value") else value
|
|
|
|
def _parse_role_values(raw: Any) -> list[str]:
|
|
if raw is None:
|
|
return []
|
|
if isinstance(raw, (list, tuple, set)):
|
|
values = [str(_enum_value(item)).strip().upper() for item in raw]
|
|
else:
|
|
values = [str(token).strip().upper() for token in str(_enum_value(raw)).split(",")]
|
|
deduped: list[str] = []
|
|
for value in values:
|
|
if value and value not in deduped:
|
|
deduped.append(value)
|
|
return deduped
|
|
|
|
def _normalize_role_input(raw: Any, *, allow_empty: bool = False) -> list[str]:
|
|
values = _parse_role_values(raw)
|
|
if not values and not allow_empty:
|
|
raise ValueError("role required")
|
|
invalid = [value for value in values if value not in VALID_ROLE_VALUES]
|
|
if invalid:
|
|
raise ValueError(f"Invalid role: {','.join(invalid)}")
|
|
return values
|
|
|
|
def _pack_roles(raw: Any) -> str:
|
|
return ",".join(_normalize_role_input(raw))
|
|
|
|
def _has_any_role(raw: Any, *roles: str) -> bool:
|
|
values = set(_parse_role_values(raw))
|
|
expected = {str(role).strip().upper() for role in roles}
|
|
return bool(values.intersection(expected))
|
|
|
|
def _build_role_filter(column: Any, roles: list[str]) -> Any:
|
|
filters = []
|
|
for role in roles:
|
|
filters.extend(
|
|
[
|
|
column == role,
|
|
column.like(f"{role},%"),
|
|
column.like(f"%,{role},%"),
|
|
column.like(f"%,{role}"),
|
|
]
|
|
)
|
|
return or_(*filters)
|
|
|
|
def _parse_int_list(raw: Optional[str]) -> list[int]:
|
|
if not raw:
|
|
return []
|
|
ids: list[int] = []
|
|
for part in raw.split(","):
|
|
token = part.strip()
|
|
if not token:
|
|
continue
|
|
try:
|
|
ids.append(int(token))
|
|
except ValueError:
|
|
continue
|
|
return ids
|