Source code for cadrumo.domain.calculations.registry.formula_text_inputs
"""Text-input validation for registry formula evaluation.Text casilla inputs are canonicalised into:class:`~core.casilla_id.CasillaId` keys before:func:`domain.calculations.registry.formula_runtime.calculate_registry_snapshot`checks that they target text-capable:class:`~domain.calculations.registry.schema_surfaces.CasillaDefinition` rows.See Also: :mod:`domain.calculations.registry.formula_runtime` Runtime caller that consumes the validated text input mapping. :mod:`domain.calculations.registry.formula_runtime_ops` Numeric input companion that validates decimal casilla inputs. :mod:`domain.calculations.registry.schema` Registry schema layer declaring casilla identifiers and data types."""from__future__importannotationsfromcollections.abcimportMappingfrom....core.casilla_idimportCasillaId,validated_casilla_idfrom.errorsimportRegistryValidationErrorfrom.schema_scalarsimportregistry_scalar_value_type,validate_registry_text_scalarfrom.schema_surfacesimportCasillaDefinitionfrom.tax_id_formatimportruntime_tax_id_format__all__=["validate_text_input_targets","validated_text_input_casilla_ids"]
[docs]defvalidated_text_input_casilla_ids[InputKey,InputValue](text_inputs:Mapping[InputKey,InputValue],)->dict[CasillaId,str]:"""Canonicalise raw text input keys and strip operator-supplied strings. Raw mapping keys become validated :class:`~core.casilla_id.CasillaId` values; values must be non-empty strings after whitespace trimming so text leaves enter the formula runtime in canonical form. """invalid=tuple(repr(key)forkeyintext_inputsifnotisinstance(key,str))ifinvalid:raiseRegistryValidationError(f"text_input keys must be canonical casilla.id strings: {sorted(invalid)!r}",translated_message="errors.calc.unknown_text_input_casillas",context={"casilla_ids":",".join(sorted(invalid))},)malformed:list[str]=[]canonical_text_inputs:dict[CasillaId,InputValue]={}forkeyintext_inputs:try:canonical_text_inputs[validated_casilla_id(key,surface="text_input casilla.id")]=text_inputs[key]exceptValueError:malformed.append(str(key))ifmalformed:raiseRegistryValidationError(f"text_input keys must be canonical casilla.id strings: {sorted(malformed)!r}",translated_message="errors.calc.unknown_text_input_casillas",context={"casilla_ids":",".join(sorted(malformed))},)resolved_text_inputs:dict[CasillaId,str]={}forkey,valueincanonical_text_inputs.items():ifnotisinstance(value,str):raiseRegistryValidationError(f"text_input {key!r} must be a non-empty string")stripped=value.strip()ifnotstripped:raiseRegistryValidationError(f"text_input {key!r} must be a non-empty string")resolved_text_inputs[key]=strippedreturnresolved_text_inputs
[docs]defvalidate_text_input_targets(text_inputs:Mapping[CasillaId,str],*,casillas_by_id:Mapping[CasillaId,CasillaDefinition],)->dict[CasillaId,str]:"""Validate and canonicalise text-family inputs against declared casillas. The runtime passes the revision's :class:`~domain.calculations.registry.schema_surfaces.CasillaDefinition` map so callers cannot supply unknown casillas or route text into numeric registry targets. """text_casilla_ids={casilla_idforcasilla_id,casillaincasillas_by_id.items()ifregistry_scalar_value_type(casilla.data_type)=="str"}unknown_text_inputs=sorted(set(text_inputs).difference(casillas_by_id))ifunknown_text_inputs:raiseRegistryValidationError(f"unknown text_input casilla ids: {unknown_text_inputs!r}",translated_message="errors.calc.unknown_text_input_casillas",context={"casilla_ids":",".join(unknown_text_inputs)},)mistyped_text_inputs=sorted(set(text_inputs).difference(text_casilla_ids))ifmistyped_text_inputs:raiseRegistryValidationError(f"text_input supplied for non-text casilla ids: {mistyped_text_inputs!r}",translated_message="errors.calc.text_input_non_text_casillas",context={"casilla_ids":",".join(mistyped_text_inputs)},)validated:dict[CasillaId,str]={}forcasilla_id,valueintext_inputs.items():casilla=casillas_by_id[casilla_id]canonical=validate_registry_text_scalar(casilla.data_type,value,tax_id_format=runtime_tax_id_format()ifcasilla.data_type=="nif"elseNone,)ifcasilla.constraintsisnotNone:reason=casilla.constraints.violates_text(canonical)ifreasonisnotNone:raiseRegistryValidationError(f"text_input {casilla_id!r}{reason}")validated[casilla_id]=canonicalreturnvalidated