dvt-core 0.59.0a51__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbt/__init__.py +7 -0
- dbt/_pydantic_shim.py +26 -0
- dbt/artifacts/__init__.py +0 -0
- dbt/artifacts/exceptions/__init__.py +1 -0
- dbt/artifacts/exceptions/schemas.py +31 -0
- dbt/artifacts/resources/__init__.py +116 -0
- dbt/artifacts/resources/base.py +67 -0
- dbt/artifacts/resources/types.py +93 -0
- dbt/artifacts/resources/v1/analysis.py +10 -0
- dbt/artifacts/resources/v1/catalog.py +23 -0
- dbt/artifacts/resources/v1/components.py +274 -0
- dbt/artifacts/resources/v1/config.py +277 -0
- dbt/artifacts/resources/v1/documentation.py +11 -0
- dbt/artifacts/resources/v1/exposure.py +51 -0
- dbt/artifacts/resources/v1/function.py +52 -0
- dbt/artifacts/resources/v1/generic_test.py +31 -0
- dbt/artifacts/resources/v1/group.py +21 -0
- dbt/artifacts/resources/v1/hook.py +11 -0
- dbt/artifacts/resources/v1/macro.py +29 -0
- dbt/artifacts/resources/v1/metric.py +172 -0
- dbt/artifacts/resources/v1/model.py +145 -0
- dbt/artifacts/resources/v1/owner.py +10 -0
- dbt/artifacts/resources/v1/saved_query.py +111 -0
- dbt/artifacts/resources/v1/seed.py +41 -0
- dbt/artifacts/resources/v1/semantic_layer_components.py +72 -0
- dbt/artifacts/resources/v1/semantic_model.py +314 -0
- dbt/artifacts/resources/v1/singular_test.py +14 -0
- dbt/artifacts/resources/v1/snapshot.py +91 -0
- dbt/artifacts/resources/v1/source_definition.py +84 -0
- dbt/artifacts/resources/v1/sql_operation.py +10 -0
- dbt/artifacts/resources/v1/unit_test_definition.py +77 -0
- dbt/artifacts/schemas/__init__.py +0 -0
- dbt/artifacts/schemas/base.py +191 -0
- dbt/artifacts/schemas/batch_results.py +24 -0
- dbt/artifacts/schemas/catalog/__init__.py +11 -0
- dbt/artifacts/schemas/catalog/v1/__init__.py +0 -0
- dbt/artifacts/schemas/catalog/v1/catalog.py +59 -0
- dbt/artifacts/schemas/freshness/__init__.py +1 -0
- dbt/artifacts/schemas/freshness/v3/__init__.py +0 -0
- dbt/artifacts/schemas/freshness/v3/freshness.py +158 -0
- dbt/artifacts/schemas/manifest/__init__.py +2 -0
- dbt/artifacts/schemas/manifest/v12/__init__.py +0 -0
- dbt/artifacts/schemas/manifest/v12/manifest.py +211 -0
- dbt/artifacts/schemas/results.py +147 -0
- dbt/artifacts/schemas/run/__init__.py +2 -0
- dbt/artifacts/schemas/run/v5/__init__.py +0 -0
- dbt/artifacts/schemas/run/v5/run.py +184 -0
- dbt/artifacts/schemas/upgrades/__init__.py +4 -0
- dbt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
- dbt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
- dbt/artifacts/utils/validation.py +153 -0
- dbt/cli/__init__.py +1 -0
- dbt/cli/context.py +17 -0
- dbt/cli/exceptions.py +57 -0
- dbt/cli/flags.py +560 -0
- dbt/cli/main.py +2660 -0
- dbt/cli/option_types.py +121 -0
- dbt/cli/options.py +80 -0
- dbt/cli/params.py +844 -0
- dbt/cli/requires.py +490 -0
- dbt/cli/resolvers.py +60 -0
- dbt/cli/types.py +40 -0
- dbt/clients/__init__.py +0 -0
- dbt/clients/checked_load.py +83 -0
- dbt/clients/git.py +164 -0
- dbt/clients/jinja.py +206 -0
- dbt/clients/jinja_static.py +245 -0
- dbt/clients/registry.py +192 -0
- dbt/clients/yaml_helper.py +68 -0
- dbt/compilation.py +876 -0
- dbt/compute/__init__.py +14 -0
- dbt/compute/engines/__init__.py +12 -0
- dbt/compute/engines/spark_engine.py +642 -0
- dbt/compute/federated_executor.py +1080 -0
- dbt/compute/filter_pushdown.py +273 -0
- dbt/compute/jar_provisioning.py +273 -0
- dbt/compute/java_compat.py +689 -0
- dbt/compute/jdbc_utils.py +1252 -0
- dbt/compute/metadata/__init__.py +63 -0
- dbt/compute/metadata/adapters_registry.py +370 -0
- dbt/compute/metadata/catalog_store.py +1036 -0
- dbt/compute/metadata/registry.py +674 -0
- dbt/compute/metadata/store.py +1020 -0
- dbt/compute/smart_selector.py +377 -0
- dbt/compute/spark_logger.py +272 -0
- dbt/compute/strategies/__init__.py +55 -0
- dbt/compute/strategies/base.py +165 -0
- dbt/compute/strategies/dataproc.py +207 -0
- dbt/compute/strategies/emr.py +203 -0
- dbt/compute/strategies/local.py +472 -0
- dbt/compute/strategies/standalone.py +262 -0
- dbt/config/__init__.py +4 -0
- dbt/config/catalogs.py +94 -0
- dbt/config/compute.py +513 -0
- dbt/config/dvt_profile.py +408 -0
- dbt/config/profile.py +422 -0
- dbt/config/project.py +888 -0
- dbt/config/project_utils.py +48 -0
- dbt/config/renderer.py +231 -0
- dbt/config/runtime.py +564 -0
- dbt/config/selectors.py +208 -0
- dbt/config/utils.py +77 -0
- dbt/constants.py +28 -0
- dbt/context/__init__.py +0 -0
- dbt/context/base.py +745 -0
- dbt/context/configured.py +135 -0
- dbt/context/context_config.py +382 -0
- dbt/context/docs.py +82 -0
- dbt/context/exceptions_jinja.py +178 -0
- dbt/context/macro_resolver.py +195 -0
- dbt/context/macros.py +171 -0
- dbt/context/manifest.py +72 -0
- dbt/context/providers.py +2249 -0
- dbt/context/query_header.py +13 -0
- dbt/context/secret.py +58 -0
- dbt/context/target.py +74 -0
- dbt/contracts/__init__.py +0 -0
- dbt/contracts/files.py +413 -0
- dbt/contracts/graph/__init__.py +0 -0
- dbt/contracts/graph/manifest.py +1904 -0
- dbt/contracts/graph/metrics.py +97 -0
- dbt/contracts/graph/model_config.py +70 -0
- dbt/contracts/graph/node_args.py +42 -0
- dbt/contracts/graph/nodes.py +1806 -0
- dbt/contracts/graph/semantic_manifest.py +232 -0
- dbt/contracts/graph/unparsed.py +811 -0
- dbt/contracts/project.py +419 -0
- dbt/contracts/results.py +53 -0
- dbt/contracts/selection.py +23 -0
- dbt/contracts/sql.py +85 -0
- dbt/contracts/state.py +68 -0
- dbt/contracts/util.py +46 -0
- dbt/deprecations.py +348 -0
- dbt/deps/__init__.py +0 -0
- dbt/deps/base.py +152 -0
- dbt/deps/git.py +195 -0
- dbt/deps/local.py +79 -0
- dbt/deps/registry.py +130 -0
- dbt/deps/resolver.py +149 -0
- dbt/deps/tarball.py +120 -0
- dbt/docs/source/_ext/dbt_click.py +119 -0
- dbt/docs/source/conf.py +32 -0
- dbt/env_vars.py +64 -0
- dbt/event_time/event_time.py +40 -0
- dbt/event_time/sample_window.py +60 -0
- dbt/events/__init__.py +15 -0
- dbt/events/base_types.py +36 -0
- dbt/events/core_types_pb2.py +2 -0
- dbt/events/logging.py +108 -0
- dbt/events/types.py +2516 -0
- dbt/exceptions.py +1486 -0
- dbt/flags.py +89 -0
- dbt/graph/__init__.py +11 -0
- dbt/graph/cli.py +249 -0
- dbt/graph/graph.py +172 -0
- dbt/graph/queue.py +214 -0
- dbt/graph/selector.py +374 -0
- dbt/graph/selector_methods.py +975 -0
- dbt/graph/selector_spec.py +222 -0
- dbt/graph/thread_pool.py +18 -0
- dbt/hooks.py +21 -0
- dbt/include/README.md +49 -0
- dbt/include/__init__.py +3 -0
- dbt/include/data/adapters_registry.duckdb +0 -0
- dbt/include/data/build_comprehensive_registry.py +1254 -0
- dbt/include/data/build_registry.py +242 -0
- dbt/include/data/csv/adapter_queries.csv +33 -0
- dbt/include/data/csv/syntax_rules.csv +9 -0
- dbt/include/data/csv/type_mappings_bigquery.csv +28 -0
- dbt/include/data/csv/type_mappings_databricks.csv +30 -0
- dbt/include/data/csv/type_mappings_mysql.csv +40 -0
- dbt/include/data/csv/type_mappings_oracle.csv +30 -0
- dbt/include/data/csv/type_mappings_postgres.csv +56 -0
- dbt/include/data/csv/type_mappings_redshift.csv +33 -0
- dbt/include/data/csv/type_mappings_snowflake.csv +38 -0
- dbt/include/data/csv/type_mappings_sqlserver.csv +35 -0
- dbt/include/dvt_starter_project/README.md +15 -0
- dbt/include/dvt_starter_project/__init__.py +3 -0
- dbt/include/dvt_starter_project/analyses/PLACEHOLDER +0 -0
- dbt/include/dvt_starter_project/dvt_project.yml +39 -0
- dbt/include/dvt_starter_project/logs/PLACEHOLDER +0 -0
- dbt/include/dvt_starter_project/macros/PLACEHOLDER +0 -0
- dbt/include/dvt_starter_project/models/example/my_first_dbt_model.sql +27 -0
- dbt/include/dvt_starter_project/models/example/my_second_dbt_model.sql +6 -0
- dbt/include/dvt_starter_project/models/example/schema.yml +21 -0
- dbt/include/dvt_starter_project/seeds/PLACEHOLDER +0 -0
- dbt/include/dvt_starter_project/snapshots/PLACEHOLDER +0 -0
- dbt/include/dvt_starter_project/tests/PLACEHOLDER +0 -0
- dbt/internal_deprecations.py +26 -0
- dbt/jsonschemas/__init__.py +3 -0
- dbt/jsonschemas/jsonschemas.py +309 -0
- dbt/jsonschemas/project/0.0.110.json +4717 -0
- dbt/jsonschemas/project/0.0.85.json +2015 -0
- dbt/jsonschemas/resources/0.0.110.json +2636 -0
- dbt/jsonschemas/resources/0.0.85.json +2536 -0
- dbt/jsonschemas/resources/latest.json +6773 -0
- dbt/links.py +4 -0
- dbt/materializations/__init__.py +0 -0
- dbt/materializations/incremental/__init__.py +0 -0
- dbt/materializations/incremental/microbatch.py +236 -0
- dbt/mp_context.py +8 -0
- dbt/node_types.py +37 -0
- dbt/parser/__init__.py +23 -0
- dbt/parser/analysis.py +21 -0
- dbt/parser/base.py +548 -0
- dbt/parser/common.py +266 -0
- dbt/parser/docs.py +52 -0
- dbt/parser/fixtures.py +51 -0
- dbt/parser/functions.py +30 -0
- dbt/parser/generic_test.py +100 -0
- dbt/parser/generic_test_builders.py +333 -0
- dbt/parser/hooks.py +122 -0
- dbt/parser/macros.py +137 -0
- dbt/parser/manifest.py +2208 -0
- dbt/parser/models.py +573 -0
- dbt/parser/partial.py +1178 -0
- dbt/parser/read_files.py +445 -0
- dbt/parser/schema_generic_tests.py +422 -0
- dbt/parser/schema_renderer.py +111 -0
- dbt/parser/schema_yaml_readers.py +935 -0
- dbt/parser/schemas.py +1466 -0
- dbt/parser/search.py +149 -0
- dbt/parser/seeds.py +28 -0
- dbt/parser/singular_test.py +20 -0
- dbt/parser/snapshots.py +44 -0
- dbt/parser/sources.py +558 -0
- dbt/parser/sql.py +62 -0
- dbt/parser/unit_tests.py +621 -0
- dbt/plugins/__init__.py +20 -0
- dbt/plugins/contracts.py +9 -0
- dbt/plugins/exceptions.py +2 -0
- dbt/plugins/manager.py +163 -0
- dbt/plugins/manifest.py +21 -0
- dbt/profiler.py +20 -0
- dbt/py.typed +1 -0
- dbt/query_analyzer.py +410 -0
- dbt/runners/__init__.py +2 -0
- dbt/runners/exposure_runner.py +7 -0
- dbt/runners/no_op_runner.py +45 -0
- dbt/runners/saved_query_runner.py +7 -0
- dbt/selected_resources.py +8 -0
- dbt/task/__init__.py +0 -0
- dbt/task/base.py +506 -0
- dbt/task/build.py +197 -0
- dbt/task/clean.py +56 -0
- dbt/task/clone.py +161 -0
- dbt/task/compile.py +150 -0
- dbt/task/compute.py +458 -0
- dbt/task/debug.py +513 -0
- dbt/task/deps.py +280 -0
- dbt/task/docs/__init__.py +3 -0
- dbt/task/docs/api/__init__.py +23 -0
- dbt/task/docs/api/catalog.py +204 -0
- dbt/task/docs/api/lineage.py +234 -0
- dbt/task/docs/api/profile.py +204 -0
- dbt/task/docs/api/spark.py +186 -0
- dbt/task/docs/generate.py +1002 -0
- dbt/task/docs/index.html +250 -0
- dbt/task/docs/serve.py +174 -0
- dbt/task/dvt_output.py +509 -0
- dbt/task/dvt_run.py +282 -0
- dbt/task/dvt_seed.py +806 -0
- dbt/task/freshness.py +322 -0
- dbt/task/function.py +121 -0
- dbt/task/group_lookup.py +46 -0
- dbt/task/init.py +1022 -0
- dbt/task/java.py +316 -0
- dbt/task/list.py +236 -0
- dbt/task/metadata.py +804 -0
- dbt/task/migrate.py +714 -0
- dbt/task/printer.py +175 -0
- dbt/task/profile.py +1489 -0
- dbt/task/profile_serve.py +662 -0
- dbt/task/retract.py +441 -0
- dbt/task/retry.py +175 -0
- dbt/task/run.py +1647 -0
- dbt/task/run_operation.py +141 -0
- dbt/task/runnable.py +758 -0
- dbt/task/seed.py +103 -0
- dbt/task/show.py +149 -0
- dbt/task/snapshot.py +56 -0
- dbt/task/spark.py +414 -0
- dbt/task/sql.py +110 -0
- dbt/task/target_sync.py +814 -0
- dbt/task/test.py +464 -0
- dbt/tests/fixtures/__init__.py +1 -0
- dbt/tests/fixtures/project.py +620 -0
- dbt/tests/util.py +651 -0
- dbt/tracking.py +529 -0
- dbt/utils/__init__.py +3 -0
- dbt/utils/artifact_upload.py +151 -0
- dbt/utils/utils.py +408 -0
- dbt/version.py +271 -0
- dvt_cli/__init__.py +158 -0
- dvt_core-0.59.0a51.dist-info/METADATA +288 -0
- dvt_core-0.59.0a51.dist-info/RECORD +299 -0
- dvt_core-0.59.0a51.dist-info/WHEEL +5 -0
- dvt_core-0.59.0a51.dist-info/entry_points.txt +2 -0
- dvt_core-0.59.0a51.dist-info/top_level.txt +2 -0
dbt/task/dvt_run.py
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# DVT Run Task with Rich UI Enhancement
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# Wrapper around standard RunTask that adds beautiful Rich UI output.
|
|
5
|
+
#
|
|
6
|
+
# DVT v0.58.0: Enhanced CLI output with Rich library
|
|
7
|
+
# DVT v0.59.0a36: Header + Summary panels (works with dbt's event system)
|
|
8
|
+
#
|
|
9
|
+
# IMPORTANT: This wrapper does NOT modify core dbt execution logic.
|
|
10
|
+
# All DVT compute rules are enforced in run.py's ModelRunner.execute().
|
|
11
|
+
#
|
|
12
|
+
# DVT Compute Rules (implemented in run.py):
|
|
13
|
+
# 1. Pushdown Preference: Same-target -> Adapter pushdown (no Spark)
|
|
14
|
+
# 2. Federation Path: Cross-target -> Spark execution
|
|
15
|
+
# 3. Compute Hierarchy: default < model config < CLI --target-compute
|
|
16
|
+
# 4. Target Hierarchy: default < model config < CLI --target
|
|
17
|
+
#
|
|
18
|
+
# NOTE: Rich's Live context conflicts with dbt's fire_event logging system.
|
|
19
|
+
# We use a header+summary approach instead of live-updating progress bars.
|
|
20
|
+
# =============================================================================
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import os
|
|
25
|
+
import time
|
|
26
|
+
import threading
|
|
27
|
+
from typing import Any, Dict, Optional, AbstractSet
|
|
28
|
+
|
|
29
|
+
from dbt.artifacts.schemas.results import NodeStatus
|
|
30
|
+
from dbt.cli.flags import Flags
|
|
31
|
+
from dbt.config import RuntimeConfig
|
|
32
|
+
from dbt.contracts.graph.manifest import Manifest
|
|
33
|
+
from dbt.task.run import RunTask, ModelRunner
|
|
34
|
+
from dbt.task.dvt_output import DVTMultiBarDisplay, HAS_RICH
|
|
35
|
+
|
|
36
|
+
# Lock for thread-safe Rich console updates
|
|
37
|
+
_console_lock = threading.Lock()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DVTRunTask(RunTask):
|
|
41
|
+
"""
|
|
42
|
+
DVT Run Task with Rich UI enhancement.
|
|
43
|
+
|
|
44
|
+
This class wraps the standard RunTask to add beautiful CLI output
|
|
45
|
+
while preserving all dbt-core and DVT compute logic.
|
|
46
|
+
|
|
47
|
+
DVT v0.59.0a36 Features:
|
|
48
|
+
- Header panel: Shows operation, target, and compute info
|
|
49
|
+
- dbt output: Normal dbt event logging flows during execution
|
|
50
|
+
- Summary panel: Errors grouped by execution path (pushdown vs federation)
|
|
51
|
+
- Warning tracking: Materialization coercions (e.g., view→table)
|
|
52
|
+
- Spark logging: Output captured to target/{compute}_log.txt
|
|
53
|
+
|
|
54
|
+
Note: Does NOT use Rich's Live context (conflicts with dbt's fire_event).
|
|
55
|
+
Instead, prints a header before execution and summary after.
|
|
56
|
+
|
|
57
|
+
Usage:
|
|
58
|
+
task = DVTRunTask(args, config, manifest)
|
|
59
|
+
results = task.run()
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
args: Flags,
|
|
65
|
+
config: RuntimeConfig,
|
|
66
|
+
manifest: Manifest,
|
|
67
|
+
batch_map: Optional[Dict[str, Any]] = None,
|
|
68
|
+
) -> None:
|
|
69
|
+
super().__init__(args, config, manifest, batch_map)
|
|
70
|
+
self._display: Optional[DVTMultiBarDisplay] = None
|
|
71
|
+
self._use_rich_output = HAS_RICH and not getattr(args, 'QUIET', False)
|
|
72
|
+
self._execution_paths: Dict[str, str] = {} # Track pushdown vs federation
|
|
73
|
+
self._spark_logger = None
|
|
74
|
+
|
|
75
|
+
def _get_target_info(self) -> str:
|
|
76
|
+
"""Get the current target name for display."""
|
|
77
|
+
cli_target = getattr(self.config.args, 'TARGET', None)
|
|
78
|
+
return cli_target or self.config.target_name or "default"
|
|
79
|
+
|
|
80
|
+
def _get_compute_info(self) -> str:
|
|
81
|
+
"""Get the current compute engine for display."""
|
|
82
|
+
cli_compute = getattr(self.config.args, 'TARGET_COMPUTE', None)
|
|
83
|
+
return cli_compute or "auto"
|
|
84
|
+
|
|
85
|
+
def _start_spark_logger(self) -> None:
|
|
86
|
+
"""Start Spark output logging to target directory.
|
|
87
|
+
|
|
88
|
+
Note: suppress_console=False so dbt's event output flows normally.
|
|
89
|
+
Spark output is tee'd to the log file for later reference.
|
|
90
|
+
"""
|
|
91
|
+
try:
|
|
92
|
+
from dbt.compute.spark_logger import get_spark_logger
|
|
93
|
+
|
|
94
|
+
# Get target directory
|
|
95
|
+
target_dir = os.path.join(os.getcwd(), "target")
|
|
96
|
+
compute_name = self._get_compute_info().replace("-", "_")
|
|
97
|
+
if compute_name == "auto":
|
|
98
|
+
compute_name = "spark"
|
|
99
|
+
|
|
100
|
+
self._spark_logger = get_spark_logger(target_dir, compute_name)
|
|
101
|
+
# Don't suppress console - let dbt events flow normally
|
|
102
|
+
# Spark output is tee'd to file for debugging
|
|
103
|
+
self._spark_logger.start_session(suppress_console=False)
|
|
104
|
+
except Exception:
|
|
105
|
+
# Don't fail if logging setup fails
|
|
106
|
+
self._spark_logger = None
|
|
107
|
+
|
|
108
|
+
def _stop_spark_logger(self) -> None:
|
|
109
|
+
"""Stop Spark output logging."""
|
|
110
|
+
if self._spark_logger:
|
|
111
|
+
try:
|
|
112
|
+
self._spark_logger.end_session()
|
|
113
|
+
except Exception:
|
|
114
|
+
pass
|
|
115
|
+
self._spark_logger = None
|
|
116
|
+
|
|
117
|
+
def _determine_execution_path(self, result) -> str:
|
|
118
|
+
"""Determine if model was executed via pushdown or federation."""
|
|
119
|
+
# Check if already tracked
|
|
120
|
+
if result.node and result.node.unique_id in self._execution_paths:
|
|
121
|
+
return self._execution_paths[result.node.unique_id]
|
|
122
|
+
|
|
123
|
+
# Check error message for federation hints
|
|
124
|
+
error_msg = result.message or ""
|
|
125
|
+
if "Federated" in error_msg or "JDBC" in error_msg or "Spark" in error_msg:
|
|
126
|
+
return "FEDERATION"
|
|
127
|
+
|
|
128
|
+
# Default to pushdown for all other cases (success or non-federation errors)
|
|
129
|
+
return "PUSHDOWN"
|
|
130
|
+
|
|
131
|
+
def _check_materialization_warning(self, result) -> Optional[str]:
|
|
132
|
+
"""Check if model has materialization coercion warning."""
|
|
133
|
+
if not result.node:
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
# Get model's intended materialization
|
|
137
|
+
config = getattr(result.node, 'config', None)
|
|
138
|
+
if not config:
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
materialized = getattr(config, 'materialized', 'table')
|
|
142
|
+
|
|
143
|
+
# Check if it's a cross-target view (coerced to table)
|
|
144
|
+
exec_path = self._determine_execution_path(result)
|
|
145
|
+
if exec_path == "FEDERATION" and materialized == "view":
|
|
146
|
+
return "view -> table (cross-target requires table)"
|
|
147
|
+
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
def before_run(self, adapter, selected_uids: AbstractSet[str]):
|
|
151
|
+
"""Called before running models - initialize multi-bar display."""
|
|
152
|
+
# Call parent first (handles schemas, cache, hooks, metadata)
|
|
153
|
+
result = super().before_run(adapter, selected_uids)
|
|
154
|
+
|
|
155
|
+
# Initialize multi-bar Rich display if available (BEFORE Spark logger)
|
|
156
|
+
if self._use_rich_output and hasattr(self, '_flattened_nodes') and self._flattened_nodes:
|
|
157
|
+
try:
|
|
158
|
+
self._display = DVTMultiBarDisplay(
|
|
159
|
+
title="DVT Run",
|
|
160
|
+
operation="run",
|
|
161
|
+
target=self._get_target_info(),
|
|
162
|
+
compute=self._get_compute_info(),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Initialize ALL model tracking upfront from _flattened_nodes
|
|
166
|
+
self._display.initialize_models(self._flattened_nodes)
|
|
167
|
+
|
|
168
|
+
# Print header before dbt output starts
|
|
169
|
+
self._display.start_display()
|
|
170
|
+
|
|
171
|
+
except Exception:
|
|
172
|
+
# Fall back to standard output on any Rich error
|
|
173
|
+
self._display = None
|
|
174
|
+
self._use_rich_output = False
|
|
175
|
+
|
|
176
|
+
# Start Spark output logging AFTER display header is shown
|
|
177
|
+
self._start_spark_logger()
|
|
178
|
+
|
|
179
|
+
return result
|
|
180
|
+
|
|
181
|
+
def _handle_result(self, result) -> None:
|
|
182
|
+
"""Handle a single model result - update the specific model's progress bar."""
|
|
183
|
+
# Call parent handler first (fires standard dbt events for logging)
|
|
184
|
+
super()._handle_result(result)
|
|
185
|
+
|
|
186
|
+
# Update the specific model's bar in multi-bar display
|
|
187
|
+
if self._display and result.node:
|
|
188
|
+
try:
|
|
189
|
+
# Determine execution path
|
|
190
|
+
exec_path = self._determine_execution_path(result)
|
|
191
|
+
self._execution_paths[result.node.unique_id] = exec_path
|
|
192
|
+
|
|
193
|
+
# Get error message
|
|
194
|
+
error_msg = result.message if result.status in (
|
|
195
|
+
NodeStatus.Error, NodeStatus.Fail
|
|
196
|
+
) else None
|
|
197
|
+
|
|
198
|
+
# Check for materialization warning
|
|
199
|
+
warning = self._check_materialization_warning(result)
|
|
200
|
+
|
|
201
|
+
# Map status
|
|
202
|
+
if result.status in (NodeStatus.Error, NodeStatus.Fail):
|
|
203
|
+
status = "error"
|
|
204
|
+
elif result.status == NodeStatus.Skipped:
|
|
205
|
+
status = "skip"
|
|
206
|
+
elif result.status == NodeStatus.Warn:
|
|
207
|
+
status = "warn"
|
|
208
|
+
else:
|
|
209
|
+
status = "pass"
|
|
210
|
+
|
|
211
|
+
# Calculate duration in milliseconds
|
|
212
|
+
duration_ms = (result.execution_time or 0) * 1000
|
|
213
|
+
|
|
214
|
+
# Thread-safe update to the model's progress bar
|
|
215
|
+
with _console_lock:
|
|
216
|
+
self._display.update_model_complete(
|
|
217
|
+
unique_id=result.node.unique_id,
|
|
218
|
+
status=status,
|
|
219
|
+
duration_ms=duration_ms,
|
|
220
|
+
execution_path=exec_path,
|
|
221
|
+
error_message=error_msg,
|
|
222
|
+
warning=warning,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
except Exception:
|
|
226
|
+
# Silently ignore Rich display errors
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
def after_run(self, adapter, results) -> None:
|
|
230
|
+
"""Called after all models complete - show summary."""
|
|
231
|
+
# Stop Spark logging FIRST so we can print to console
|
|
232
|
+
self._stop_spark_logger()
|
|
233
|
+
|
|
234
|
+
# Stop multi-bar display and show summary
|
|
235
|
+
if self._display:
|
|
236
|
+
try:
|
|
237
|
+
self._display.stop_display()
|
|
238
|
+
self._display.print_summary()
|
|
239
|
+
except Exception:
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
# Call parent (handles end hooks)
|
|
243
|
+
super().after_run(adapter, results)
|
|
244
|
+
|
|
245
|
+
def task_end_messages(self, results) -> None:
|
|
246
|
+
"""Override to prevent duplicate output when using Rich."""
|
|
247
|
+
if self._display:
|
|
248
|
+
# Rich display handles summary, skip default messages
|
|
249
|
+
return
|
|
250
|
+
|
|
251
|
+
# Fall back to standard dbt output
|
|
252
|
+
super().task_end_messages(results)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def create_dvt_run_task(
|
|
256
|
+
args: Flags,
|
|
257
|
+
config: RuntimeConfig,
|
|
258
|
+
manifest: Manifest,
|
|
259
|
+
batch_map: Optional[Dict[str, Any]] = None,
|
|
260
|
+
) -> RunTask:
|
|
261
|
+
"""
|
|
262
|
+
Factory function to create appropriate run task.
|
|
263
|
+
|
|
264
|
+
Returns DVTRunTask with Rich UI if available and not in quiet mode,
|
|
265
|
+
otherwise returns standard RunTask.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
args: CLI flags
|
|
269
|
+
config: Runtime configuration
|
|
270
|
+
manifest: Project manifest
|
|
271
|
+
batch_map: Optional batch map for retry
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
RunTask instance (DVTRunTask or standard RunTask)
|
|
275
|
+
"""
|
|
276
|
+
# Check if we should use Rich output
|
|
277
|
+
use_rich = HAS_RICH and not getattr(args, 'QUIET', False)
|
|
278
|
+
|
|
279
|
+
if use_rich:
|
|
280
|
+
return DVTRunTask(args, config, manifest, batch_map)
|
|
281
|
+
else:
|
|
282
|
+
return RunTask(args, config, manifest, batch_map)
|