from __future__ import annotations from typing import Callable, Dict, List, Union Extractor = Callable[[object, str], Dict[str, Union[str, float, int, list, dict, None]]] REGISTRY: List[Extractor] = [] def extractor(fn: Extractor) -> Extractor: """Decorator to register an extractor.""" REGISTRY.append(fn) return fn def merge_missing(dst: dict, src: dict) -> None: """ Merge src into dst. Only write keys that are missing or empty in dst. "Empty" means None, "", [], {}. """ for k, v in (src or {}).items(): if k not in dst or dst[k] in (None, "", [], {}): dst[k] = v