Source code for hs_py.ontology.reflect

"""Reflection engine for mapping entity dicts to ontology defs.

Reflection determines which defs apply to an entity based on its tag set.
This includes detecting simple marker matches, conjunct matches, and
computing the full effective def set.

See: https://project-haystack.org/doc/docHaystack/Reflection
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from hs_py.kinds import Symbol, sym_name

if TYPE_CHECKING:
    from hs_py.ontology.defs import Def
    from hs_py.ontology.namespace import Namespace

__all__ = [
    "fits",
    "reflect",
]


[docs] def reflect(ns: Namespace, tags: dict[str, Any]) -> list[Def]: """Return all defs that apply to an entity with the given tags. The algorithm: 1. Scan the entity's tags for marker tags (tags whose value is Marker). 2. For each marker, look up the matching def in the namespace. 3. Check for conjuncts (compound terms matching tag combinations). 4. Include all transitive supertypes. :param ns: Namespace to resolve defs in. :param tags: Entity tag dict. :returns: List of applicable defs (most-specific first). """ from hs_py.kinds import Marker # Step 1: Find directly matching marker defs direct: list[Def] = [] marker_names: set[str] = set() for key, val in tags.items(): if isinstance(val, Marker): marker_names.add(key) d = ns.get(key) if d is not None: direct.append(d) # Step 2: Check for conjuncts conjuncts = ns.find_conjuncts(marker_names) direct.extend(conjuncts) # Step 3: Collect all supertypes seen: set[str] = set() result: list[Def] = [] # Add direct matches first (most-specific) for d in direct: if d.symbol.val not in seen: seen.add(d.symbol.val) result.append(d) # Add all transitive supertypes for d in list(result): for sup in ns.all_supertypes(d.symbol.val): if sup.symbol.val not in seen: seen.add(sup.symbol.val) result.append(sup) return result
[docs] def fits(ns: Namespace, tags: dict[str, Any], def_symbol: str | Symbol) -> bool: """Check if an entity's tags fit a given def. An entity fits a def if the def (or one of its subtypes) appears in the entity's reflected def set. :param ns: Namespace to resolve defs in. :param tags: Entity tag dict. :param def_symbol: Def symbol to check against. :returns: ``True`` if the entity fits the def. """ target = sym_name(def_symbol) defs = reflect(ns, tags) return any(d.symbol.val == target or d.name == target for d in defs)