dvt-core 0.52.2__cp310-cp310-macosx_10_9_x86_64.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.
Potentially problematic release.
This version of dvt-core might be problematic. Click here for more details.
- 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 +2039 -0
- dbt/cli/option_types.py +121 -0
- dbt/cli/options.py +80 -0
- dbt/cli/params.py +804 -0
- dbt/cli/requires.py +490 -0
- dbt/cli/resolvers.py +50 -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 +624 -0
- dbt/compute/federated_executor.py +837 -0
- dbt/compute/filter_pushdown.cpython-310-darwin.so +0 -0
- dbt/compute/filter_pushdown.py +273 -0
- dbt/compute/jar_provisioning.cpython-310-darwin.so +0 -0
- dbt/compute/jar_provisioning.py +255 -0
- dbt/compute/java_compat.cpython-310-darwin.so +0 -0
- dbt/compute/java_compat.py +689 -0
- dbt/compute/jdbc_utils.cpython-310-darwin.so +0 -0
- dbt/compute/jdbc_utils.py +678 -0
- dbt/compute/smart_selector.cpython-310-darwin.so +0 -0
- dbt/compute/smart_selector.py +311 -0
- dbt/compute/strategies/__init__.py +54 -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 +364 -0
- dbt/compute/strategies/standalone.py +262 -0
- dbt/config/__init__.py +4 -0
- dbt/config/catalogs.py +94 -0
- dbt/config/compute.cpython-310-darwin.so +0 -0
- dbt/config/compute.py +547 -0
- dbt/config/dvt_profile.cpython-310-darwin.so +0 -0
- dbt/config/dvt_profile.py +342 -0
- dbt/config/profile.py +422 -0
- dbt/config/project.py +873 -0
- dbt/config/project_utils.py +28 -0
- dbt/config/renderer.py +231 -0
- dbt/config/runtime.py +553 -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 +417 -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 +346 -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 +247 -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/starter_project/.gitignore +4 -0
- dbt/include/starter_project/README.md +15 -0
- dbt/include/starter_project/__init__.py +3 -0
- dbt/include/starter_project/analyses/.gitkeep +0 -0
- dbt/include/starter_project/dbt_project.yml +36 -0
- dbt/include/starter_project/macros/.gitkeep +0 -0
- dbt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
- dbt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
- dbt/include/starter_project/models/example/schema.yml +21 -0
- dbt/include/starter_project/seeds/.gitkeep +0 -0
- dbt/include/starter_project/snapshots/.gitkeep +0 -0
- dbt/include/starter_project/tests/.gitkeep +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 +118 -0
- dbt/parser/macros.py +137 -0
- dbt/parser/manifest.py +2204 -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.cpython-310-darwin.so +0 -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 +503 -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 +454 -0
- dbt/task/debug.py +505 -0
- dbt/task/deps.py +280 -0
- dbt/task/docs/__init__.py +3 -0
- dbt/task/docs/generate.py +660 -0
- dbt/task/docs/index.html +250 -0
- dbt/task/docs/serve.py +29 -0
- dbt/task/freshness.py +322 -0
- dbt/task/function.py +121 -0
- dbt/task/group_lookup.py +46 -0
- dbt/task/init.py +553 -0
- dbt/task/java.py +316 -0
- dbt/task/list.py +236 -0
- dbt/task/printer.py +175 -0
- dbt/task/retry.py +175 -0
- dbt/task/run.py +1306 -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 +759 -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 +268 -0
- dvt_cli/__init__.py +72 -0
- dvt_core-0.52.2.dist-info/METADATA +286 -0
- dvt_core-0.52.2.dist-info/RECORD +275 -0
- dvt_core-0.52.2.dist-info/WHEEL +5 -0
- dvt_core-0.52.2.dist-info/entry_points.txt +2 -0
- dvt_core-0.52.2.dist-info/top_level.txt +2 -0
dbt/task/printer.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from typing import Dict, Optional, Union
|
|
2
|
+
|
|
3
|
+
from dbt.artifacts.schemas.results import NodeStatus
|
|
4
|
+
from dbt.contracts.graph.nodes import Exposure
|
|
5
|
+
from dbt.events.types import (
|
|
6
|
+
CheckNodeTestFailure,
|
|
7
|
+
EndOfRunSummary,
|
|
8
|
+
RunResultError,
|
|
9
|
+
RunResultErrorNoMessage,
|
|
10
|
+
RunResultFailure,
|
|
11
|
+
RunResultWarning,
|
|
12
|
+
RunResultWarningMessage,
|
|
13
|
+
SQLCompiledPath,
|
|
14
|
+
StatsLine,
|
|
15
|
+
)
|
|
16
|
+
from dbt.node_types import NodeType
|
|
17
|
+
from dbt.task import group_lookup
|
|
18
|
+
from dbt_common.events.base_types import EventLevel
|
|
19
|
+
from dbt_common.events.format import pluralize
|
|
20
|
+
from dbt_common.events.functions import fire_event
|
|
21
|
+
from dbt_common.events.types import Formatting
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_counts(flat_nodes) -> str:
|
|
25
|
+
counts: Dict[str, int] = {}
|
|
26
|
+
|
|
27
|
+
for node in flat_nodes:
|
|
28
|
+
t = node.resource_type
|
|
29
|
+
|
|
30
|
+
if node.resource_type == NodeType.Model:
|
|
31
|
+
t = "{} {}".format(node.get_materialization(), t)
|
|
32
|
+
elif node.resource_type == NodeType.Operation:
|
|
33
|
+
t = "project hook"
|
|
34
|
+
|
|
35
|
+
counts[t] = counts.get(t, 0) + 1
|
|
36
|
+
|
|
37
|
+
sorted_items = sorted(counts.items(), key=lambda x: x[0])
|
|
38
|
+
stat_line = ", ".join([pluralize(v, k).replace("_", " ") for k, v in sorted_items])
|
|
39
|
+
|
|
40
|
+
return stat_line
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def interpret_run_result(result) -> str:
|
|
44
|
+
if result.status in (NodeStatus.Error, NodeStatus.Fail, NodeStatus.PartialSuccess):
|
|
45
|
+
return "error"
|
|
46
|
+
elif result.status == NodeStatus.Skipped:
|
|
47
|
+
return "skip"
|
|
48
|
+
elif result.status == NodeStatus.Warn:
|
|
49
|
+
return "warn"
|
|
50
|
+
elif result.status in (NodeStatus.Pass, NodeStatus.Success):
|
|
51
|
+
return "pass"
|
|
52
|
+
elif result.status == NodeStatus.NoOp:
|
|
53
|
+
return "noop"
|
|
54
|
+
else:
|
|
55
|
+
raise RuntimeError(f"unhandled result {result}")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def print_run_status_line(results) -> None:
|
|
59
|
+
stats = {
|
|
60
|
+
"error": 0,
|
|
61
|
+
"skip": 0,
|
|
62
|
+
"pass": 0,
|
|
63
|
+
"warn": 0,
|
|
64
|
+
"noop": 0,
|
|
65
|
+
"total": 0,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for r in results:
|
|
69
|
+
result_type = interpret_run_result(r)
|
|
70
|
+
stats[result_type] += 1
|
|
71
|
+
stats["total"] += 1
|
|
72
|
+
|
|
73
|
+
fire_event(Formatting(""))
|
|
74
|
+
fire_event(StatsLine(stats=stats))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def print_run_result_error(
|
|
78
|
+
result,
|
|
79
|
+
newline: bool = True,
|
|
80
|
+
is_warning: bool = False,
|
|
81
|
+
group: Optional[Dict[str, Union[str, Dict[str, str]]]] = None,
|
|
82
|
+
) -> None:
|
|
83
|
+
# set node_info for logging events
|
|
84
|
+
node_info = None
|
|
85
|
+
if hasattr(result, "node") and result.node:
|
|
86
|
+
node_info = result.node.node_info
|
|
87
|
+
if result.status in (NodeStatus.Fail, NodeStatus.Error) or (
|
|
88
|
+
is_warning and result.status == NodeStatus.Warn
|
|
89
|
+
):
|
|
90
|
+
if newline:
|
|
91
|
+
fire_event(Formatting(""))
|
|
92
|
+
if is_warning:
|
|
93
|
+
fire_event(
|
|
94
|
+
RunResultWarning(
|
|
95
|
+
resource_type=result.node.resource_type,
|
|
96
|
+
node_name=result.node.name,
|
|
97
|
+
path=result.node.original_file_path,
|
|
98
|
+
node_info=node_info,
|
|
99
|
+
group=group,
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
fire_event(
|
|
104
|
+
RunResultFailure(
|
|
105
|
+
resource_type=result.node.resource_type,
|
|
106
|
+
node_name=result.node.name,
|
|
107
|
+
path=result.node.original_file_path,
|
|
108
|
+
node_info=node_info,
|
|
109
|
+
group=group,
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if result.message:
|
|
114
|
+
if is_warning:
|
|
115
|
+
fire_event(RunResultWarningMessage(msg=result.message, node_info=node_info))
|
|
116
|
+
else:
|
|
117
|
+
fire_event(RunResultError(msg=result.message, node_info=node_info, group=group))
|
|
118
|
+
else:
|
|
119
|
+
fire_event(RunResultErrorNoMessage(status=result.status, node_info=node_info))
|
|
120
|
+
|
|
121
|
+
if getattr(result.node, "compiled_path", None):
|
|
122
|
+
fire_event(Formatting(""))
|
|
123
|
+
fire_event(SQLCompiledPath(path=result.node.compiled_path, node_info=node_info))
|
|
124
|
+
|
|
125
|
+
if getattr(result.node, "should_store_failures", None):
|
|
126
|
+
fire_event(Formatting(""))
|
|
127
|
+
fire_event(
|
|
128
|
+
CheckNodeTestFailure(relation_name=result.node.relation_name, node_info=node_info)
|
|
129
|
+
)
|
|
130
|
+
elif result.status == NodeStatus.Skipped and result.message is not None:
|
|
131
|
+
if newline:
|
|
132
|
+
fire_event(Formatting(""), level=EventLevel.DEBUG)
|
|
133
|
+
fire_event(RunResultError(msg=result.message), level=EventLevel.DEBUG)
|
|
134
|
+
elif result.message is not None:
|
|
135
|
+
if newline:
|
|
136
|
+
fire_event(Formatting(""))
|
|
137
|
+
fire_event(RunResultError(msg=result.message, node_info=node_info, group=group))
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def print_run_end_messages(results, keyboard_interrupt: bool = False) -> None:
|
|
141
|
+
errors, warnings, partial_successes = [], [], []
|
|
142
|
+
for r in results:
|
|
143
|
+
if r.status in (NodeStatus.RuntimeErr, NodeStatus.Error, NodeStatus.Fail):
|
|
144
|
+
errors.append(r)
|
|
145
|
+
elif r.status == NodeStatus.Skipped and r.message:
|
|
146
|
+
if isinstance(r.node, Exposure):
|
|
147
|
+
# Don't include exposure skips in errors list
|
|
148
|
+
continue
|
|
149
|
+
else:
|
|
150
|
+
# This means we skipped a node because of an issue upstream, so include it as an error
|
|
151
|
+
errors.append(r)
|
|
152
|
+
elif r.status == NodeStatus.Warn:
|
|
153
|
+
warnings.append(r)
|
|
154
|
+
elif r.status == NodeStatus.PartialSuccess:
|
|
155
|
+
partial_successes.append(r)
|
|
156
|
+
|
|
157
|
+
fire_event(Formatting(""))
|
|
158
|
+
fire_event(
|
|
159
|
+
EndOfRunSummary(
|
|
160
|
+
num_errors=len(errors),
|
|
161
|
+
num_warnings=len(warnings),
|
|
162
|
+
num_partial_success=len(partial_successes),
|
|
163
|
+
keyboard_interrupt=keyboard_interrupt,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
for error in errors:
|
|
168
|
+
group = group_lookup.get(error.node.unique_id) if hasattr(error, "node") else None
|
|
169
|
+
print_run_result_error(error, is_warning=False, group=group)
|
|
170
|
+
|
|
171
|
+
for warning in warnings:
|
|
172
|
+
group = group_lookup.get(warning.node.unique_id) if hasattr(warning, "node") else None
|
|
173
|
+
print_run_result_error(warning, is_warning=True, group=group)
|
|
174
|
+
|
|
175
|
+
print_run_status_line(results)
|
dbt/task/retry.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from click import get_current_context
|
|
4
|
+
from click.core import ParameterSource
|
|
5
|
+
|
|
6
|
+
from dbt.artifacts.schemas.results import NodeStatus
|
|
7
|
+
from dbt.cli.flags import Flags
|
|
8
|
+
from dbt.cli.types import Command as CliCommand
|
|
9
|
+
from dbt.config import RuntimeConfig
|
|
10
|
+
from dbt.constants import RUN_RESULTS_FILE_NAME
|
|
11
|
+
from dbt.contracts.state import load_result_state
|
|
12
|
+
from dbt.flags import get_flags, set_flags
|
|
13
|
+
from dbt.graph import GraphQueue
|
|
14
|
+
from dbt.parser.manifest import parse_manifest
|
|
15
|
+
from dbt.task.base import ConfiguredTask
|
|
16
|
+
from dbt.task.build import BuildTask
|
|
17
|
+
from dbt.task.clone import CloneTask
|
|
18
|
+
from dbt.task.compile import CompileTask
|
|
19
|
+
from dbt.task.docs.generate import GenerateTask
|
|
20
|
+
from dbt.task.run import RunTask
|
|
21
|
+
from dbt.task.run_operation import RunOperationTask
|
|
22
|
+
from dbt.task.seed import SeedTask
|
|
23
|
+
from dbt.task.snapshot import SnapshotTask
|
|
24
|
+
from dbt.task.test import TestTask
|
|
25
|
+
from dbt_common.exceptions import DbtRuntimeError
|
|
26
|
+
|
|
27
|
+
RETRYABLE_STATUSES = {
|
|
28
|
+
NodeStatus.Error,
|
|
29
|
+
NodeStatus.Fail,
|
|
30
|
+
NodeStatus.Skipped,
|
|
31
|
+
NodeStatus.RuntimeErr,
|
|
32
|
+
NodeStatus.PartialSuccess,
|
|
33
|
+
}
|
|
34
|
+
IGNORE_PARENT_FLAGS = {
|
|
35
|
+
"log_path",
|
|
36
|
+
"output_path",
|
|
37
|
+
"profiles_dir",
|
|
38
|
+
"profiles_dir_exists_false",
|
|
39
|
+
"project_dir",
|
|
40
|
+
"defer_state",
|
|
41
|
+
"deprecated_state",
|
|
42
|
+
"target_path",
|
|
43
|
+
"warn_error",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ALLOW_CLI_OVERRIDE_FLAGS = {"vars", "threads"}
|
|
47
|
+
|
|
48
|
+
TASK_DICT = {
|
|
49
|
+
"build": BuildTask,
|
|
50
|
+
"compile": CompileTask,
|
|
51
|
+
"clone": CloneTask,
|
|
52
|
+
"generate": GenerateTask,
|
|
53
|
+
"seed": SeedTask,
|
|
54
|
+
"snapshot": SnapshotTask,
|
|
55
|
+
"test": TestTask,
|
|
56
|
+
"run": RunTask,
|
|
57
|
+
"run-operation": RunOperationTask,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
CMD_DICT = {
|
|
61
|
+
"build": CliCommand.BUILD,
|
|
62
|
+
"compile": CliCommand.COMPILE,
|
|
63
|
+
"clone": CliCommand.CLONE,
|
|
64
|
+
"generate": CliCommand.DOCS_GENERATE,
|
|
65
|
+
"seed": CliCommand.SEED,
|
|
66
|
+
"snapshot": CliCommand.SNAPSHOT,
|
|
67
|
+
"test": CliCommand.TEST,
|
|
68
|
+
"run": CliCommand.RUN,
|
|
69
|
+
"run-operation": CliCommand.RUN_OPERATION,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class RetryTask(ConfiguredTask):
|
|
74
|
+
def __init__(self, args: Flags, config: RuntimeConfig) -> None:
|
|
75
|
+
# load previous run results
|
|
76
|
+
state_path = args.state or config.target_path
|
|
77
|
+
self.previous_results = load_result_state(
|
|
78
|
+
Path(config.project_root) / Path(state_path) / RUN_RESULTS_FILE_NAME
|
|
79
|
+
)
|
|
80
|
+
if not self.previous_results:
|
|
81
|
+
raise DbtRuntimeError(
|
|
82
|
+
f"Could not find previous run in '{state_path}' target directory"
|
|
83
|
+
)
|
|
84
|
+
self.previous_args = self.previous_results.args
|
|
85
|
+
self.previous_command_name = self.previous_args.get("which")
|
|
86
|
+
|
|
87
|
+
# Reslove flags and config
|
|
88
|
+
if args.warn_error:
|
|
89
|
+
RETRYABLE_STATUSES.add(NodeStatus.Warn)
|
|
90
|
+
|
|
91
|
+
cli_command = CMD_DICT.get(self.previous_command_name) # type: ignore
|
|
92
|
+
# Remove these args when their default values are present, otherwise they'll raise an exception
|
|
93
|
+
args_to_remove = {
|
|
94
|
+
"show": lambda x: True,
|
|
95
|
+
"resource_types": lambda x: x == [],
|
|
96
|
+
"warn_error_options": lambda x: x == {"warn": [], "error": [], "silence": []},
|
|
97
|
+
}
|
|
98
|
+
for k, v in args_to_remove.items():
|
|
99
|
+
if k in self.previous_args and v(self.previous_args[k]):
|
|
100
|
+
del self.previous_args[k]
|
|
101
|
+
previous_args = {
|
|
102
|
+
k: v for k, v in self.previous_args.items() if k not in IGNORE_PARENT_FLAGS
|
|
103
|
+
}
|
|
104
|
+
click_context = get_current_context()
|
|
105
|
+
current_args = {
|
|
106
|
+
k: v
|
|
107
|
+
for k, v in args.__dict__.items()
|
|
108
|
+
if k in IGNORE_PARENT_FLAGS
|
|
109
|
+
or (
|
|
110
|
+
click_context.get_parameter_source(k) == ParameterSource.COMMANDLINE
|
|
111
|
+
and k in ALLOW_CLI_OVERRIDE_FLAGS
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
combined_args = {**previous_args, **current_args}
|
|
115
|
+
retry_flags = Flags.from_dict(cli_command, combined_args) # type: ignore
|
|
116
|
+
set_flags(retry_flags)
|
|
117
|
+
retry_config = RuntimeConfig.from_args(args=retry_flags)
|
|
118
|
+
|
|
119
|
+
# Parse manifest using resolved config/flags
|
|
120
|
+
manifest = parse_manifest(retry_config, False, True, retry_flags.write_json, []) # type: ignore
|
|
121
|
+
super().__init__(args, retry_config, manifest)
|
|
122
|
+
self.task_class = TASK_DICT.get(self.previous_command_name) # type: ignore
|
|
123
|
+
|
|
124
|
+
def run(self):
|
|
125
|
+
unique_ids = {
|
|
126
|
+
result.unique_id
|
|
127
|
+
for result in self.previous_results.results
|
|
128
|
+
if result.status in RETRYABLE_STATUSES
|
|
129
|
+
and not (
|
|
130
|
+
self.previous_command_name != "run-operation"
|
|
131
|
+
and result.unique_id.startswith("operation.")
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# We need this so that re-running of a microbatch model will only rerun
|
|
136
|
+
# batches that previously failed. Note _explicitly_ do no pass the
|
|
137
|
+
# batch info if there were _no_ successful batches previously. This is
|
|
138
|
+
# because passing the batch info _forces_ the microbatch process into
|
|
139
|
+
# _incremental_ model, and it may be that we need to be in full refresh
|
|
140
|
+
# mode which is only handled if previous_batch_results _isn't_ passed for a node
|
|
141
|
+
batch_map = {
|
|
142
|
+
result.unique_id: result.batch_results
|
|
143
|
+
for result in self.previous_results.results
|
|
144
|
+
if result.batch_results is not None
|
|
145
|
+
and len(result.batch_results.successful) != 0
|
|
146
|
+
and len(result.batch_results.failed) > 0
|
|
147
|
+
and not (
|
|
148
|
+
self.previous_command_name != "run-operation"
|
|
149
|
+
and result.unique_id.startswith("operation.")
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
class TaskWrapper(self.task_class):
|
|
154
|
+
def get_graph_queue(self):
|
|
155
|
+
new_graph = self.graph.get_subset_graph(unique_ids)
|
|
156
|
+
return GraphQueue(
|
|
157
|
+
new_graph.graph,
|
|
158
|
+
self.manifest,
|
|
159
|
+
unique_ids,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
task = TaskWrapper(
|
|
163
|
+
get_flags(),
|
|
164
|
+
self.config,
|
|
165
|
+
self.manifest,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
if self.task_class == RunTask:
|
|
169
|
+
task.batch_map = batch_map
|
|
170
|
+
|
|
171
|
+
return_value = task.run()
|
|
172
|
+
return return_value
|
|
173
|
+
|
|
174
|
+
def interpret_results(self, *args, **kwargs):
|
|
175
|
+
return self.task_class.interpret_results(*args, **kwargs)
|