Source code for lhp.api.facade

"""Application facade — single entry point for LHP runtime operations.

Composes seven sub-facades (generation, validation, inspection, bundle,
wheel, sandbox, dependency) that group related operations. Constructed exclusively via
:meth:`LakehousePlumberApplicationFacade.for_project`; the composition
root lives in :mod:`lhp.core.coordination.layers`.

:stability: provisional
"""

from __future__ import annotations

from pathlib import Path
from typing import (
    TYPE_CHECKING,
    Any,
    Iterator,
    List,
    Optional,
    Sequence,
)

from lhp.api._bundle_facade import BundleFacade as BundleFacade  # re-export (§1.10)
from lhp.api._dependency_facade import (
    DependencyFacade as DependencyFacade,  # re-export (§1.10)
)
from lhp.api._generation_facade import (
    GenerationFacade as GenerationFacade,  # re-export (§1.10)
)
from lhp.api._inspection_facade import (
    InspectionFacade as InspectionFacade,  # re-export (§1.10)
)
from lhp.api._progress import ProgressSink
from lhp.api._sandbox_facade import SandboxFacade as SandboxFacade  # re-export (§1.10)
from lhp.api._validation_facade import (
    ValidationFacade as ValidationFacade,  # re-export (§1.10)
)
from lhp.api._wheel_facade import WheelFacade as WheelFacade  # re-export (§1.10)
from lhp.api.events import LHPEvent

if TYPE_CHECKING:
    from lhp.models import FlowGroup

    # Internal orchestrator type, referenced only as a quoted annotation
    # below; never named directly in the public API surface (§1.10,
    # §9.13). Composition is delegated to ``core/coordination/layers``.
    _Orchestrator = Any


[docs] class LakehousePlumberApplicationFacade: """Top-level application facade. Composes seven sub-facades that group related operations: - ``generation`` — batch generation runs. - ``validation`` — config validation. - ``inspection`` — read-only project introspection. - ``bundle`` — Asset Bundle operations. - ``wheel`` — built-wheel inspection / extraction. - ``sandbox`` — developer-sandbox scope inspection. - ``dependency`` — dependency-graph analysis and output generation. Constructed exclusively via :meth:`for_project`. The bare ``__init__(...)`` form is internal — external callers must route through the classmethod so the composition-root logic (single ``ConfigValidator``, threaded collaborators) is enforced (§4.5). The public ``orchestrator`` attribute is intentionally absent (§1.10, §9.23); callers must use the sub-facade methods. :stability: stable """ def __init__(self, orchestrator: "_Orchestrator") -> None: self._orchestrator = orchestrator self.generation = GenerationFacade(orchestrator) self.validation = ValidationFacade(orchestrator) self.inspection = InspectionFacade(orchestrator) self.bundle = BundleFacade(orchestrator) self.wheel = WheelFacade(orchestrator) self.sandbox = SandboxFacade(orchestrator) self.dependency = DependencyFacade(orchestrator)
[docs] @classmethod def for_project( cls, project_root: Path, *, pipeline_config_path: Optional[str] = None, enforce_version: bool = True, max_workers: Optional[int] = None, no_cache: bool = False, ) -> "LakehousePlumberApplicationFacade": """Construct a fully-wired facade from a project root. Centralises service-graph construction so no service reaches into another's private attributes; builds the single ``ConfigValidator`` that threads through validation and flowgroup-resolution (closes the §9.24 leak). ``no_cache`` disables the persistent on-disk parse cache (``<project_root>/.lhp/cache/parse``) for this facade; the cache is also disabled when the ``LHP_NO_CACHE`` environment variable is truthy (``"1"``, ``"true"``, ``"yes"``). The cache is delete-safe: results are identical with or without it. :stability: provisional :raises lhp.errors.LHPError: ``LHP-CFG-*`` if ``lhp.yaml`` is absent, malformed, or fails project-config validation; ``LHP-VAL-*`` if ``enforce_version`` is set and the ``lhp_version`` constraint rejects the installed package; ``LHP-FILE-*`` for missing-path conditions discovered during composition. """ # Composition is delegated to an internal helper so the # orchestrator class name never appears in :mod:`lhp.api` # source (§1.10, §9.13). Lazy import. from lhp.core.coordination.layers import build_facade_orchestrator # Wire the per-action generators into the core ``ActionRegistry`` # at this single composition point. ``core`` must not import # ``generators`` (layering), so registration is pushed from # ``api`` (the legal downward ``api -> generators`` edge). Lazy so # bare ``import lhp`` stays light; idempotent (later calls update). from lhp.generators.registration import register_all register_all() orchestrator = build_facade_orchestrator( project_root, pipeline_config_path=pipeline_config_path, enforce_version=enforce_version, max_workers=max_workers, no_cache=no_cache, ) return cls(orchestrator)
[docs] def generate_pipelines( self, *, pipeline_filter: Optional[str] = None, pipeline_fields: Sequence[str] = (), env: str, output_dir: Optional[Path], specific_flowgroups: Optional[List[str]] = None, include_tests: bool = False, apply_formatting: bool | None = None, bundle_enabled: bool = False, pre_discovered_all_flowgroups: Optional[Sequence["FlowGroup"]] = None, max_workers: Optional[int] = None, progress: ProgressSink | None = None, sandbox: bool = False, ) -> Iterator[LHPEvent]: """Shortcut for ``self.generation.generate_pipelines(...)``. Restates the canonical signature (§4.2) and forwards every parameter unchanged via ``yield from`` (§1.4, §5.7). ``apply_formatting`` is the tri-state formatting override (``None`` = use the project's ``lhp.yaml`` ``apply_formatting`` setting; ``True`` / ``False`` override it), resolved downstream in the orchestrator. ``progress`` is an optional :class:`~lhp.api.ProgressSink` the run advances as flowgroups complete; read its ``total`` / ``done`` fields while iterating the stream to observe live progress. ``sandbox`` switches the run to developer-sandbox mode: scope and namespace come from the personal ``.lhp/profile.yaml`` plus the team ``sandbox:`` policy in ``lhp.yaml``. CANNOT be combined with ``pipeline_filter`` / ``pipeline_fields``. :stability: provisional :raises ValueError: if ``sandbox=True`` is combined with ``pipeline_filter`` or ``pipeline_fields`` (API misuse). :raises lhp.errors.LHPError: same families as :meth:`GenerationFacade.generate_pipelines` — ``LHP-VAL-*``, ``LHP-CFG-*``, ``LHP-FILE-*``, ``LHP-MULT-*``, ``LHP-TPL-*``; plus the sandbox preflight errors on a ``sandbox=True`` run — ``LHP-IO-025``, ``LHP-CFG-064``, ``LHP-CFG-065``, ``LHP-VAL-064``. """ yield from self.generation.generate_pipelines( pipeline_filter=pipeline_filter, pipeline_fields=pipeline_fields, env=env, output_dir=output_dir, specific_flowgroups=specific_flowgroups, include_tests=include_tests, apply_formatting=apply_formatting, bundle_enabled=bundle_enabled, pre_discovered_all_flowgroups=pre_discovered_all_flowgroups, max_workers=max_workers, progress=progress, sandbox=sandbox, )
[docs] def validate_pipelines( self, *, pipeline_filter: Optional[str] = None, pipeline_fields: Sequence[str] = (), env: str, max_workers: Optional[int] = None, include_tests: bool = True, bundle_enabled: bool = False, pre_discovered_all_flowgroups: Optional[Sequence["FlowGroup"]] = None, progress: ProgressSink | None = None, sandbox: bool = False, ) -> Iterator[LHPEvent]: """Shortcut for ``self.validation.validate_pipelines(...)``. Restates the canonical signature (§4.2) and forwards every parameter unchanged via ``yield from`` (§1.4, §5.7). ``progress`` is an optional :class:`~lhp.api.ProgressSink` the run advances as flowgroups complete; read its ``total`` / ``done`` fields while iterating the stream to observe live progress. ``sandbox`` switches the run to developer-sandbox mode: scope and namespace come from the personal ``.lhp/profile.yaml`` plus the team ``sandbox:`` policy in ``lhp.yaml``. CANNOT be combined with ``pipeline_filter`` / ``pipeline_fields``. :stability: provisional :raises ValueError: if ``sandbox=True`` is combined with ``pipeline_filter`` or ``pipeline_fields`` (API misuse). :raises lhp.errors.LHPError: same families as :meth:`ValidationFacade.validate_pipelines` — ``LHP-VAL-*``, ``LHP-CFG-*``, ``LHP-FILE-*``, ``LHP-MULT-*``, ``LHP-TPL-*``; plus the sandbox preflight errors on a ``sandbox=True`` run — ``LHP-IO-025``, ``LHP-CFG-064``, ``LHP-CFG-065``, ``LHP-VAL-064``. """ yield from self.validation.validate_pipelines( pipeline_filter=pipeline_filter, pipeline_fields=pipeline_fields, env=env, max_workers=max_workers, include_tests=include_tests, bundle_enabled=bundle_enabled, pre_discovered_all_flowgroups=pre_discovered_all_flowgroups, progress=progress, sandbox=sandbox, )