cmboulanger's picture
Upload folder using huggingface_hub
9be5ad7 verified
Raw History Blame Contribute Delete
2.12 kB
from __future__ import annotations
import difflib
import re
from ..models.schema import TEISchema
from ..models.spans import ResolvedSpan
def validate_spans(
spans: list[ResolvedSpan],
schema: TEISchema,
source: str,
) -> list[ResolvedSpan]:
"""
Filter out spans that fail schema validation.
Rejected when:
- element is not in the schema
- an attribute name is not listed for that element
- an attribute value is not in the element's allowed_values (when constrained)
- span bounds are out of range
"""
valid: list[ResolvedSpan] = []
for span in spans:
# Bounds sanity check
if span.start < 0 or span.end > len(source) or span.start >= span.end:
continue
elem = schema.get(span.element)
if elem is None:
continue # element not in schema
allowed_names = {a.name for a in elem.attributes}
attr_ok = True
for attr_name, attr_value in span.attrs.items():
if attr_name not in allowed_names:
attr_ok = False
break
attr_def = next((a for a in elem.attributes if a.name == attr_name), None)
if attr_def and attr_def.allowed_values is not None:
if attr_value not in attr_def.allowed_values:
attr_ok = False
break
if not attr_ok:
continue
valid.append(span)
return valid
def validate_output(xml: str, source: str) -> None:
"""Raise ValueError if xml text content differs from source (tags stripped, whitespace normalised)."""
def _norm(t: str) -> str:
return re.sub(r'\s+', ' ', t).strip()
got = _norm(re.sub(r'<[^>]+>', '', xml))
expected = _norm(source)
if got != expected:
diff = '\n'.join(
difflib.unified_diff(
expected.split(), got.split(),
fromfile='source', tofile='injected',
)
)
raise ValueError(
f"inject_xml text content mismatch — annotated output differs from source.\n{diff}"
)