Source code for veupath_chatbot.domain.parameters.normalize

"""Normalize parameter values into WDK wire format.

Delegates validation and decoding to the shared dispatch chain in
``_value_helpers._process_value()``, then applies WDK wire formatting:
compound types (multi-pick lists, ranges, filter dicts/lists) are
serialized as JSON strings.
"""

import json
from dataclasses import dataclass

from veupath_chatbot.domain.parameters._value_helpers import (
    ParameterValueMixin,
    ParamKind,
)
from veupath_chatbot.domain.parameters.specs import ParamSpecNormalized
from veupath_chatbot.platform.errors import ValidationError
from veupath_chatbot.platform.types import (
    JSONObject,
    JSONValue,
)

# WDK wire format wraps these compound kinds with json.dumps().
_WIRE_JSON_KINDS = frozenset({ParamKind.MULTI_PICK, ParamKind.RANGE, ParamKind.FILTER})


[docs] @dataclass(frozen=True) class ParameterNormalizer(ParameterValueMixin): """Normalize parameter values using canonical parameter specs. Produces WDK wire-safe values: multi-pick lists become JSON strings, ranges become JSON strings, filters become JSON strings. Does NOT expand selections to leaf terms -- even when WDK marks a vocabulary as ``countOnlyLeaves``, WDK handles that expansion itself. """ specs: dict[str, ParamSpecNormalized]
[docs] def normalize(self, parameters: JSONObject) -> JSONObject: normalized: JSONObject = {} for name, value in (parameters or {}).items(): spec = self.specs.get(name) if not spec: available = sorted(self.specs.keys()) raise ValidationError( title="Unknown parameter", detail=f"Parameter '{name}' does not exist for this search. Available parameters: {', '.join(available)}", errors=[{"param": name, "value": value}], ) if spec.param_type == "input-step": continue normalized[name] = self._normalize_value(spec, value) return normalized
def _normalize_value( self, spec: ParamSpecNormalized, value: JSONValue ) -> JSONValue: result = self._process_value(spec, value) # WDK wire format: compound types must be serialized as JSON strings. if result.kind in _WIRE_JSON_KINDS and isinstance(result.value, (list, dict)): return json.dumps(result.value) return result.value