Coverage for src/lumen/fhir/binding_validator.py: 96%
24 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-31 18:46 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-08-31 18:46 +0000
1"""
2This file validates required value-set bindings for primitive code elements.
3It matches code values against the HL7 binding table to enforce conformance on writes.
4"""
6from __future__ import annotations
8import json
9from functools import lru_cache
10from pathlib import Path
12from .path import evaluate_path
14_TABLE_PATH = Path(__file__).parent / "data" / "r4b" / "r4b-code-bindings.json"
17@lru_cache(maxsize=1)
18def _bindings_by_type() -> dict[str, list[tuple[str, frozenset[str]]]]:
19 table: dict[str, list[str]] = json.loads(_TABLE_PATH.read_text())
20 index: dict[str, list[tuple[str, frozenset[str]]]] = {}
21 for path, codes in table.items():
22 resource_type = path.split(".", 1)[0]
23 index.setdefault(resource_type, []).append((path, frozenset(codes)))
24 return index
27def validate_code_bindings(resource: dict[str, object]) -> list[str]:
28 """Return messages for code values violating a required binding (empty if valid)."""
29 resource_type = resource.get("resourceType")
30 if not isinstance(resource_type, str):
31 return []
33 errors: list[str] = []
34 for path, allowed in _bindings_by_type().get(resource_type, []):
35 for value in evaluate_path(path, resource):
36 if isinstance(value, str) and value not in allowed:
37 errors.append(
38 f"{path}: {value!r} is not in the required value set "
39 f"({', '.join(sorted(allowed))})"
40 )
41 return errors