
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
