Python API

The Lakehouse Plumber (LHP) Python API exposes the same generation engine that powers the lhp command-line interface. Import it to build custom tooling: notebook integrations, CI/CD wrappers, programmatic validation in tests, or embedding LHP inside a larger orchestrator. For day-to-day pipeline authoring, prefer the CLI — the Python API trades convenience for control.

This page catalogs the public surface by stability tier and renders live docstrings via Sphinx autodoc. The tier table is the contract; the autodoc sections below it are the source-of-truth signatures pulled from the code at build time.

Stability tiers

LHP follows a four-tier stability model. The tier governs what level of change to expect between minor and major versions.

Tier

Change policy

Definition

Stable

Semantic versioning; breaking changes only at major releases.

Public API in active use by external integrations. Method signatures, return shapes, and observable behavior are versioned.

Beta

May change between minor versions with a deprecation cycle of at least one release.

Public API still settling. Suitable for production use if you pin LHP to a minor version.

Experimental

May change without notice at any release, including patch releases.

Public API exposed for evaluation. Do not depend on it from long-lived code.

Internal

May change at any time. Not part of the API contract.

Implementation detail. Importing it from outside lhp.* is unsupported even when the import path resolves.

If a symbol is not listed on this page, treat it as Internal regardless of its import path.

Public API by tier

Stable

No symbol is currently Stable. LHP is pre-1.0; the CLI is the stable contract. Python API consumers should treat the Beta tier as the recommended entry point and pin to a minor version of LHP.

Beta

These symbols are the recommended entry points for programmatic use.

Symbol

Summary

lhp.api.LakehousePlumberApplicationFacade

Public entry point; construct via .for_project(project_root). Drives discovery, validation, code generation, and bundle sync through its sub-facades.

lhp.parsers.yaml_parser.YAMLParser

Parses and validates LHP YAML files into Pydantic models. Use to load flowgroups, presets, and templates without invoking the full pipeline.

lhp.parsers.yaml_parser.CachingYAMLParser

Thread-safe caching wrapper around YAMLParser. Suitable when parsing the same files repeatedly within one process.

lhp.presets.preset_manager.PresetManager

Loads presets from a directory and resolves inheritance chains.

lhp.bundle.manager.BundleManager

Synchronizes Databricks bundle resource files with generated pipeline code.

lhp.models

Pydantic models for the on-disk YAML schema: FlowGroup, Action, Preset, Template, ProjectConfig, Blueprint, and the associated enumerations (ActionType, LoadSourceType, TransformType, WriteTargetType, TestActionType).

lhp.errors

Public exception hierarchy: LHPError, LHPConfigError, LHPValidationError, LHPFileError. Catch these to handle LHP failures programmatically.

Experimental

These symbols are exposed but may change without notice.

Symbol

Summary

lhp.utils.version.get_version

Returns the installed LHP package version string.

Internal

Everything else under lhp.* is Internal — including all of lhp.core.*, lhp.generators.*, lhp.cli.*, lhp.schemas.*, lhp.templates.*, lhp.resources.*, and any lhp.utils.* module not listed under Beta or Experimental above. Drive LHP through the facade, not these modules.

Important

Importing from an Internal namespace works today but provides no guarantees. Patch releases may move, rename, or remove these symbols without a deprecation notice.

Detailed reference

The sections below render docstrings, type hints, and signatures directly from the source code. Refer to the tier table above for stability guarantees on each symbol.

Package root: lhp

Lakehouse Plumber - YAML-driven framework for Databricks Lakeflow Spark Declarative Pipelines.

Application facade: 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 LakehousePlumberApplicationFacade.for_project(); the composition root lives in lhp.core.coordination.layers.

stability:

provisional

class lhp.api.LakehousePlumberApplicationFacade(orchestrator)[source]

Bases: object

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 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

Parameters:

orchestrator (_Orchestrator)

classmethod for_project(project_root, *, pipeline_config_path=None, enforce_version=True, max_workers=None, no_cache=False)[source]

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.LHPErrorLHP-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.

Parameters:
  • project_root (Path)

  • pipeline_config_path (str | None)

  • enforce_version (bool)

  • max_workers (int | None)

  • no_cache (bool)

Return type:

LakehousePlumberApplicationFacade

generate_pipelines(*, pipeline_filter=None, pipeline_fields=(), env, output_dir, specific_flowgroups=None, include_tests=False, apply_formatting=None, bundle_enabled=False, pre_discovered_all_flowgroups=None, max_workers=None, progress=None, sandbox=False)[source]

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 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).

  • lhp.errors.LHPError – same families as 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.

Parameters:
  • pipeline_filter (Optional[str])

  • pipeline_fields (Sequence[str])

  • env (str)

  • output_dir (Optional[Path])

  • specific_flowgroups (Optional[List[str]])

  • include_tests (bool)

  • apply_formatting (bool | None)

  • bundle_enabled (bool)

  • pre_discovered_all_flowgroups (Optional[Sequence['FlowGroup']])

  • max_workers (Optional[int])

  • progress (ProgressSink | None)

  • sandbox (bool)

Return type:

Iterator[LHPEvent]

validate_pipelines(*, pipeline_filter=None, pipeline_fields=(), env, max_workers=None, include_tests=True, bundle_enabled=False, pre_discovered_all_flowgroups=None, progress=None, sandbox=False)[source]

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 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).

  • lhp.errors.LHPError – same families as 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.

Parameters:
  • pipeline_filter (Optional[str])

  • pipeline_fields (Sequence[str])

  • env (str)

  • max_workers (Optional[int])

  • include_tests (bool)

  • bundle_enabled (bool)

  • pre_discovered_all_flowgroups (Optional[Sequence['FlowGroup']])

  • progress (ProgressSink | None)

  • sandbox (bool)

Return type:

Iterator[LHPEvent]

YAML parsing: lhp.parsers.yaml_parser

class lhp.parsers.yaml_parser.YAMLParser[source]

Bases: object

can_seed = False

True on parsers whose caches can be warmed/seeded from a persistent store (the caching wrapper overrides this).

Type:

Capability marker

reserve_capacity(n)[source]

No-op: a non-caching parser has no cache to size.

Present so callers can size any parser uniformly without a capability check. The caching subclass overrides this.

Parameters:

n (int)

Return type:

None

warm(path)[source]

No-op: nothing to warm (returns False). Mirrors reserve_capacity().

Parameters:

path (Path)

Return type:

bool

seed(path, documents, flowgroups)[source]

No-op: a non-caching parser has no cache to seed.

Parameters:
Return type:

None

sweep_parse_cache(live_paths)[source]

No-op: a non-caching parser has no persistent shards to sweep.

Parameters:

live_paths (Iterable[Path])

Return type:

None

parse_flowgroups_from_file(file_path)[source]

Supports both multi-document syntax (—) and flowgroups array syntax.

Parameters:

file_path (Path)

Return type:

List[FlowGroup]

parse_template_raw(file_path)[source]

Skip Action object creation so template syntax (e.g. {{ table_properties }}) is not validated until rendering when actual parameter values are available.

Parameters:

file_path (Path)

Return type:

Template

parse_preset(file_path)[source]

Parse a Preset YAML file.

Parameters:

file_path (Path)

Return type:

Preset

class lhp.parsers.yaml_parser.CachingYAMLParser(base_parser=None, max_cache_size=500, *, persistent_cache=None)[source]

Bases: object

Thread-safe caching wrapper for YAMLParser.

Uses file path + modification time as cache key to automatically invalidate cache when files change. With a persistent_cache attached, parse results also round-trip through on-disk shards (PersistentParseCache) so a later process can warm its in-memory sub-caches without re-reading unchanged files.

Parameters:
  • base_parser (YAMLParser | None)

  • max_cache_size (int)

  • persistent_cache (PersistentParseCache | None)

can_seed = True

Capability marker mirroring YAMLParser.can_seed.

reserve_capacity(n)[source]

Grow-only size hint (max(current, n)): both discovery passes call this with their own glob size; a monotonic max ensures neither pass can shrink the ceiling mid-workload. FIFO eviction in _cached_load still guards against unbounded growth.

Parameters:

n (int)

Return type:

None

parse_flowgroups_from_file(path)[source]

On a _cache miss, documents are obtained via load_documents_all so the raw read populates _documents_cache too; the instance pass then hits that entry instead of re-reading the file.

With a persistent store attached, warm() first tries to seed both in-memory sub-caches from the on-disk shard, and a successful fresh parse writes the shard back. Files whose parse raises never get a shard — fatal errors re-raise identically on every run.

Parameters:

path (Path)

Return type:

List[FlowGroup]

load_documents_all(path, error_context=None)[source]

Mtime-keyed cached load; hit/miss counters shared with the flowgroup sub-cache.

Parameters:
  • path (Path)

  • error_context (str | None)

Return type:

List[Dict[str, Any]]

warm(path)[source]

Try to satisfy a future parse of path without reading the file.

Order: in-memory flowgroups sub-cache, then the persistent store. A full shard seeds both in-memory sub-caches; a doc-only shard (flowgroups is None) additionally builds the flowgroups from the cached documents and rewrites the shard as a full payload. Never raises; any failure returns False (fresh parse).

Parameters:

path (Path)

Return type:

bool

seed(path, documents, flowgroups)[source]

Insert an externally parsed result into both in-memory sub-caches and (when attached) the persistent store. One stat; never raises.

Parameters:
Return type:

None

sweep_parse_cache(live_paths)[source]

Delegate shard garbage collection to the persistent store (no-op when no store is attached).

Parameters:

live_paths (Iterable[Path])

Return type:

None

Presets: lhp.presets.preset_manager

Preset management with hierarchical inheritance.

class lhp.presets.preset_manager.PresetManager(presets_dir)[source]

Bases: object

Parameters:

presets_dir (Path)

Bundle integration: lhp.bundle.manager

class lhp.bundle.manager.BundleManager(project_root, pipeline_config_path=None, project_config=None, event_log_name_transform=None)[source]

Bases: object

Manages Databricks Asset Bundle resource files.

Wipe-and-regenerate contract: resources/lhp/ is fully wiped by the CLI before sync, and BundleManager re-renders one resource file per pipeline under generated/<env>/. databricks.yml is never read or mutated. Catalog and schema must come from pipeline_config.yaml (per-pipeline or via the top-level project_defaults block).

Parameters:
  • project_root (Path | str)

  • pipeline_config_path (str | None)

  • project_config (Any | None)

  • event_log_name_transform (Callable[[str], str] | None)

sync_resources_with_generated_files(output_dir, env)[source]

Wipe-and-regenerate contract: callers must clear resources/lhp/ before invoking this method. BundleManager only writes files for pipelines that exist under output_dir — it does not preserve, back up, or delete any pre-existing files.

Parameters:
Return type:

int

get_resource_file_path(pipeline_name)[source]

Return the path where this pipeline’s resource file is written.

Under the wipe-and-regenerate contract, resources/lhp/ is empty when sync starts and BundleManager always writes the canonical <pipeline>.pipeline.yml filename, so no existence probing is needed.

Parameters:

pipeline_name (str)

Return type:

Path

generate_resource_file_content(pipeline_name, output_dir, env)[source]

Generate content for a bundle resource file using Jinja2 template.

Applies LHP token substitution to ALL fields in pipeline_config.yaml, enabling environment-specific configuration for node types, policies, emails, and all other pipeline settings. Catalog and schema MUST be defined in pipeline_config.yaml (either per-pipeline or via the top-level project_defaults block); they are never read from databricks.yml.

Catalog/schema validation is performed upstream by bundle.preflight.validate_catalog_schema before any wipes occur. The guard here is a defense-in-depth assertion that fires only if a non-CLI caller invokes this method without running preflight first.

Parameters:
  • pipeline_name (str) – Name of the pipeline

  • output_dir (Path) – Output directory

  • env (str) – Environment name for token resolution (REQUIRED)

Returns:

YAML content for the resource file with fully substituted pipeline config

Raises:

LHPConfigErrorLHP-GEN-001 if preflight was bypassed and catalog/schema is still missing/empty at the bundle-write phase.

Return type:

str

emit_wheels_bundle_file(output_dir, env)[source]

Write the LHP-owned resources/lhp/_wheels.bundle.yml for env.

Self-derives the wheel-mode pipeline list from output_dir (symmetric with _inject_wheel_dependency — the API layer passes nothing extra): every generated pipeline directory whose resolved packaging mode is "wheel". The emitted fragment sets targets.<env>.workspace.artifact_path to the resolved UC volume (so DAB uploads the wheels referenced by environment.dependencies there) and excludes the _wheels/ staging dir from the bundle file sync. It declares NO artifacts: block: each wheel reaches Databricks as a prebuilt local library reference that DAB uploads and rewrites itself (R2).

No-op when there are zero wheel pipelines: nothing is written and the method returns early, so source-only projects gain no bundle file.

${bundle.target} in the sync-exclude is a Databricks bundle runtime variable, emitted literally — it is NOT an LHP token and is never substituted here.

Raises:

LHPErrorLHP-CFG-061 (via _resolve_artifact_volume) if a wheel pipeline exists but the resolved wheel.artifact_volume is absent/empty or not a /Volumes/... path.

Parameters:
Return type:

None

Configuration models: lhp.models

Pydantic models that mirror the on-disk YAML schema. Import these to type your own loaders or to construct configurations programmatically.

Configuration models for LHP (project, action, flowgroup, blueprint, monitoring, test).

Each model is defined in an underscore-prefixed sub-module so the public surface is explicit and the package contract is auditable. Import every public class from lhp.models directly; sub-module paths are internal and may change.

class lhp.models.Action(*, name, type, source=None, target=None, description=None, readMode=None, write_target=None, transform_type=None, sql=None, sql_path=None, operational_metadata=None, expectations_file=None, mode=None, quarantine=None, schema_inline=None, schema_file=None, enforcement=None, module_path=None, depends_on=None, function_name=None, parameters=None, custom_datasource_class=None, once=None, test_type=None, on_violation=None, tolerance=None, columns=None, filter=None, reference=None, source_columns=None, reference_columns=None, required_columns=None, column=None, min_value=None, max_value=None, lookup_table=None, lookup_columns=None, lookup_result_columns=None, expectations=None, test_id=None)[source]

Bases: BaseModel

Parameters:
property resolved_test_target: str

explicit target or tmp_test_{name}.

Type:

Canonical target name for test actions

model_post_init(_Action__context)[source]

Normalize path fields for cross-platform compatibility.

Parameters:

_Action__context (Any)

Return type:

None

class lhp.models.ActionType(*values)[source]

Bases: str, Enum

class lhp.models.Blueprint(*, name, version='1.0', description=None, parameters=[], flowgroups)[source]

Bases: BaseModel

A reusable collection of flowgroups instantiated once per BlueprintInstance.

Distinguishing fields from a regular flowgroup file are parameters and flowgroups (the array of BlueprintFlowgroupSpec). looks_like_blueprint() keys on the presence of both fields together with the absence of actions.

Parameters:
class lhp.models.BlueprintFlowgroupSpec(*, pipeline, flowgroup, job_name=None, variables=None, presets=[], use_template=None, template_parameters=None, actions=[], operational_metadata=None)[source]

Bases: BaseModel

A flowgroup template inside a blueprint.

Same shape as FlowGroup, but pipeline and flowgroup are templates that contain %{var} placeholders resolved at expansion time against instance parameter values.

Parameters:
class lhp.models.BlueprintInstance(*, use_blueprint=None, parameters=None, overrides=None, blueprint=None)[source]

Bases: BaseModel

An instance of a blueprint with concrete parameter values.

Two input shapes are accepted:

  • New (preferred): use_blueprint: references the blueprint and a nested parameters: block holds parameter values; an optional overrides: block is reserved for future use. This shape mirrors the use_template: / template_parameters: pattern operators already know.

  • Legacy (deprecated, removed in V0.9): blueprint: plus flat top-level parameter keys. A deprecation warning is emitted once per file when this form is encountered.

A model_validator(mode=’before’) is the single normalization point: it converts both shapes into the canonical (use_blueprint, parameters) form so all downstream code reads from one place. Mixing the two forms in the same file raises LHP-CFG-061.

Parameters:
property blueprint_name: str

Normalized blueprint name (works for both input shapes).

class lhp.models.BlueprintParameter(*, name, required=False, default=None, description=None)[source]

Bases: BaseModel

Parameters:
  • name (str)

  • required (bool)

  • default (Any | None)

  • description (str | None)

class lhp.models.DQMode(*values)[source]

Bases: str, Enum

Data quality enforcement modes.

class lhp.models.EventLogConfig(*, enabled=True, catalog=None, schema=None, name_prefix='', name_suffix='')[source]

Bases: BaseModel

Project-level event log configuration for pipeline resource generation.

Parameters:
  • enabled (bool)

  • catalog (str | None)

  • schema (str | None)

  • name_prefix (str)

  • name_suffix (str)

class lhp.models.FlowGroup(*, pipeline, flowgroup, job_name=None, variables=None, presets=[], use_template=None, template_parameters=None, actions=[], operational_metadata=None)[source]

Bases: BaseModel

Parameters:
class lhp.models.FlowGroupContext(flowgroup, source_yaml, synthetic=False, auxiliary_files=<factory>)[source]

Bases: object

Envelope carrying per-flowgroup provenance across the worker boundary.

Parameters:
class lhp.models.LoadSourceType(*values)[source]

Bases: str, Enum

class lhp.models.MetadataColumnConfig(*, expression, description=None, applies_to=['streaming_table', 'materialized_view'], additional_imports=None, enabled=True)[source]

Bases: BaseModel

Parameters:
class lhp.models.MetadataPresetConfig(*, columns, description=None)[source]

Bases: BaseModel

Parameters:
class lhp.models.MonitoringConfig(*, enabled=True, pipeline_name=None, catalog=None, schema=None, streaming_table='all_pipelines_event_log', checkpoint_path='', job_config_path=None, max_concurrent_streams=10, materialized_views=None, enable_job_monitoring=False)[source]

Bases: BaseModel

Project-level monitoring pipeline configuration.

Generates two artifacts:

  1. A standalone notebook that runs N independent streaming queries (one per pipeline event log) appending into a user-created Delta table.

  2. A DLT pipeline with materialized views only, reading from that Delta table.

A Databricks Workflow job chains: notebook_task (union) → pipeline_task (MVs).

Parameters:
class lhp.models.MonitoringMaterializedViewConfig(*, name, sql=None, sql_path=None)[source]

Bases: BaseModel

Configuration for a single monitoring materialized view.

Parameters:
  • name (str)

  • sql (str | None)

  • sql_path (str | None)

class lhp.models.OperationalMetadataSelection(*, enabled=True, preset=None, columns=None, include_columns=None, exclude_columns=None)[source]

Bases: BaseModel

Parameters:
class lhp.models.Preset(*, name, version='1.0', extends=None, description=None, defaults=None)[source]

Bases: BaseModel

Parameters:
class lhp.models.ProjectConfig(*, name, version='1.0', description=None, author=None, created_date=None, include=None, blueprint_include=None, instance_include=None, operational_metadata=None, event_log=None, monitoring=None, required_lhp_version=None, test_reporting=None, uc_tagging=None, wheel=None, sandbox=None, apply_formatting=True)[source]

Bases: BaseModel

Project-level configuration loaded from lhp.yaml.

Parameters:
class lhp.models.ProjectOperationalMetadataConfig(*, columns, presets=None, defaults=None)[source]

Bases: BaseModel

Parameters:
class lhp.models.QuarantineConfig(*, dlq_table, source_table)[source]

Bases: BaseModel

Configuration for quarantine mode in data quality transforms.

Parameters:
  • dlq_table (str)

  • source_table (str)

class lhp.models.SandboxConfig(*, strategy='table', table_pattern='{namespace}_{table}', allowed_envs=None)[source]

Bases: BaseModel

Team-level sandbox policy from the sandbox: block in lhp.yaml.

Parameters:
class lhp.models.SandboxProfile(*, namespace, pipelines)[source]

Bases: BaseModel

Personal sandbox profile from gitignored .lhp/profile.yaml.

Explicit opt-in only: the namespace and pipeline scope are always stated by the developer — never auto-detected.

Parameters:
class lhp.models.Template(*, name, version='1.0', description=None, presets=[], parameters=[], actions=[])[source]

Bases: BaseModel

Parameters:
model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class lhp.models.TestActionType(*values)[source]

Bases: str, Enum

Types of test actions available.

class lhp.models.TestReportingConfig(*, module_path, function_name, config_file=None)[source]

Bases: BaseModel

Parameters:
  • module_path (str)

  • function_name (str)

  • config_file (str | None)

class lhp.models.TransformType(*values)[source]

Bases: str, Enum

class lhp.models.UCTaggingConfig(*, enabled=True, remove_undeclared_tags=False, tag_update_concurrency=16)[source]

Bases: BaseModel

Project-level uc_tagging configuration from lhp.yaml.

The feature is on by default: an absent uc_tagging block behaves as these defaults (enabled). Users opt IN simply by declaring tags on a table or column — the hook is emitted only when some write action or schema column declares tags (auto-detection). To disable the feature, set uc_tagging.enabled: false in lhp.yaml.

remove_undeclared_tags selects the reconcile behavior: when False (default) tag setting is purely additive (create/update only); when True the hook also deletes any existing tag whose key is not in the declared set for a managed entity (reconcile to the declared state).

tag_update_concurrency is the max concurrent tag operations (the hook’s ThreadPoolExecutor max_workers for the one-shot pass over all tables/columns); defaults to 16.

Parameters:
  • enabled (bool)

  • remove_undeclared_tags (bool)

  • tag_update_concurrency (int)

class lhp.models.ViolationAction(*values)[source]

Bases: str, Enum

Actions to take when test expectations are violated.

class lhp.models.WheelConfig(*, artifact_volume=None)[source]

Bases: BaseModel

Per-project wheel packaging configuration.

Parameters:

artifact_volume (str | None)

class lhp.models.WriteTarget(*, type, catalog=None, schema=None, database=None, table=None, create_table=True, comment=None, table_properties=None, tags=None, tags_file=None, partition_columns=None, cluster_columns=None, cluster_by_auto=None, spark_conf=None, table_schema=None, row_filter=None, temporary=False, path=None, refresh_schedule=None, refresh_policy=None, sql=None, sql_path=None, sink_type=None, sink_name=None, bootstrap_servers=None, topic=None, module_path=None, custom_sink_class=None, batch_handler=None, options=None)[source]

Bases: BaseModel

Write target configuration for streaming tables, materialized views, and sinks.

Parameters:
  • type (WriteTargetType)

  • catalog (str | None)

  • schema (str | None)

  • database (str | None)

  • table (str | None)

  • create_table (bool)

  • comment (str | None)

  • table_properties (Dict[str, Any] | None)

  • tags (Dict[str, str | None] | None)

  • tags_file (str | None)

  • partition_columns (List[str] | None)

  • cluster_columns (List[str] | None)

  • cluster_by_auto (bool | None)

  • spark_conf (Dict[str, Any] | None)

  • table_schema (str | None)

  • row_filter (str | None)

  • temporary (bool)

  • path (str | None)

  • refresh_schedule (str | None)

  • refresh_policy (str | None)

  • sql (str | None)

  • sql_path (str | None)

  • sink_type (str | None)

  • sink_name (str | None)

  • bootstrap_servers (str | None)

  • topic (str | None)

  • module_path (str | None)

  • custom_sink_class (str | None)

  • batch_handler (str | None)

  • options (Dict[str, Any] | None)

class lhp.models.WriteTargetType(*values)[source]

Bases: str, Enum

Errors and exceptions: lhp.errors

Catch LHPError for any LHP-originated failure. The concrete subclasses disambiguate configuration, validation, and I/O failures and carry an error code that maps to an entry in the error reference.

Domain error types and text formatting for LHP.

No Rich/colorama/click dependencies — Rich rendering lives in lhp.cli.error_panel.render_error_panel.

class lhp.errors.ErrorCategory(*values)[source]

Bases: Enum

Error categories with prefixes.

exception lhp.errors.LHPConfigError(category, code_number, title, details, suggestions=None, example=None, context=None, doc_link=None)[source]

Bases: LHPError, ValueError

LHPError subclass for configuration errors.

Also a ValueError for backward compatibility with existing except ValueError handlers.

Parameters:
  • category (ErrorCategory)

  • code_number (str)

  • title (str)

  • details (str)

  • suggestions (Optional[List[str]])

  • example (Optional[str])

  • context (Optional[Dict[str, Any]])

  • doc_link (Optional[str])

exception lhp.errors.LHPError(category, code_number, title, details, suggestions=None, example=None, context=None, doc_link=None)[source]

Bases: Exception

User-friendly error with formatting support.

Base class for all LHP-specific exceptions. Subclasses use dual inheritance (e.g. LHPValidationError(LHPError, ValueError)) so that existing except ValueError handlers still catch them.

Parameters:
  • category (ErrorCategory)

  • code_number (str)

  • title (str)

  • details (str)

  • suggestions (Optional[List[str]])

  • example (Optional[str])

  • context (Optional[Dict[str, Any]])

  • doc_link (Optional[str])

classmethod from_unexpected_exception(exc, operation)[source]

Wrap a non-LHP, non-Bundle exception as an LHPError for CLI rendering.

Used by cli_error_boundary() to surface generic fallback failures through the project’s unified Rich panel UX rather than as plain stderr lines. The full Python traceback is intentionally NOT carried on the returned LHPError; callers are expected to logger.exception(...) so the traceback lands in the log file only.

Parameters:
Return type:

LHPError

exception lhp.errors.LHPFileError(category, code_number, title, details, suggestions=None, example=None, context=None, doc_link=None)[source]

Bases: LHPError, FileNotFoundError

LHPError subclass that is also a FileNotFoundError.

Use when replacing a bare FileNotFoundError so that existing except FileNotFoundError handlers continue to catch it.

Parameters:
  • category (ErrorCategory)

  • code_number (str)

  • title (str)

  • details (str)

  • suggestions (Optional[List[str]])

  • example (Optional[str])

  • context (Optional[Dict[str, Any]])

  • doc_link (Optional[str])

exception lhp.errors.LHPValidationError(category, code_number, title, details, suggestions=None, example=None, context=None, doc_link=None)[source]

Bases: LHPError, ValueError

LHPError subclass that is also a ValueError.

Use when replacing a bare ValueError so that existing except ValueError handlers continue to catch it.

Parameters:
  • category (ErrorCategory)

  • code_number (str)

  • title (str)

  • details (str)

  • suggestions (Optional[List[str]])

  • example (Optional[str])

  • context (Optional[Dict[str, Any]])

  • doc_link (Optional[str])

Version (Experimental): lhp.utils.version

Version utilities for LakehousePlumber.

lhp.utils.version.get_version()[source]

Get the package version dynamically from package metadata.

Return type:

str

Notes on usage

  • All public classes log through logging.getLogger("lhp.<module>"). Configure the lhp logger to control LHP output independently of your application’s logging.

  • LHP raises LHPError (or a subclass) for every recoverable failure. Unexpected exceptions indicate a bug; file an issue with the traceback.

  • Pydantic v2 powers lhp.models. Treat the models as immutable once constructed; use model_copy(update=...) for derived instances.

  • Construct one LakehousePlumberApplicationFacade per run; it is not thread-safe. CachingYAMLParser is thread-safe and shared internally.

Most users should drive LHP through the CLI reference rather than the Python API. For the design rationale behind the engine, see the How Lakehouse Plumber works concept page.