52 lines
1.5 KiB
Python
52 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
import re
|
|
from typing import Iterable, Mapping, Optional
|
|
|
|
from publication_meta import clean, parse_meta
|
|
|
|
|
|
class MarkerError(ValueError):
|
|
pass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class PageMarker:
|
|
block_id: str
|
|
raw: str
|
|
meta: dict[str, str]
|
|
|
|
|
|
def find_marker(blocks: Iterable[Mapping[str, object]]) -> Optional[PageMarker]:
|
|
valid: list[PageMarker] = []
|
|
near_misses: list[str] = []
|
|
|
|
for block in blocks:
|
|
block_id = str(block.get("id", "unknown"))
|
|
raw_value = block.get("text", "")
|
|
raw = raw_value if isinstance(raw_value, str) else ""
|
|
normalized = clean(raw)
|
|
if re.search(r"anwarpy", normalized, re.IGNORECASE) is None:
|
|
continue
|
|
if not normalized.startswith("anwarpy:"):
|
|
near_misses.append(block_id)
|
|
continue
|
|
try:
|
|
meta = parse_meta(normalized)
|
|
except ValueError:
|
|
near_misses.append(block_id)
|
|
continue
|
|
valid.append(PageMarker(block_id=block_id, raw=raw, meta=meta))
|
|
|
|
if len(valid) > 1:
|
|
ids = ", ".join(marker.block_id for marker in valid)
|
|
raise MarkerError(f"multiple anwarpy markers found in blocks: {ids}")
|
|
if valid and near_misses:
|
|
ids = ", ".join(near_misses)
|
|
raise MarkerError(f"ambiguous anwarpy markers; near-miss blocks: {ids}")
|
|
if near_misses:
|
|
ids = ", ".join(near_misses)
|
|
raise MarkerError(f"near-miss anwarpy marker in blocks: {ids}")
|
|
return valid[0] if valid else None
|