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.
- 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/build.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from typing import Dict, List, Optional, Set, Type
|
|
2
|
+
|
|
3
|
+
from dbt.artifacts.schemas.results import NodeStatus
|
|
4
|
+
from dbt.artifacts.schemas.run import RunResult
|
|
5
|
+
from dbt.cli.flags import Flags
|
|
6
|
+
from dbt.config.runtime import RuntimeConfig
|
|
7
|
+
from dbt.contracts.graph.manifest import Manifest
|
|
8
|
+
from dbt.exceptions import DbtInternalError
|
|
9
|
+
from dbt.graph import Graph, GraphQueue, ResourceTypeSelector
|
|
10
|
+
from dbt.node_types import NodeType
|
|
11
|
+
from dbt.runners import ExposureRunner as exposure_runner
|
|
12
|
+
from dbt.runners import SavedQueryRunner as saved_query_runner
|
|
13
|
+
from dbt.task.base import BaseRunner, resource_types_from_args
|
|
14
|
+
from dbt.task.run import MicrobatchModelRunner
|
|
15
|
+
|
|
16
|
+
from .function import FunctionRunner as function_runner
|
|
17
|
+
from .run import ModelRunner as run_model_runner
|
|
18
|
+
from .run import RunTask
|
|
19
|
+
from .seed import SeedRunner as seed_runner
|
|
20
|
+
from .snapshot import SnapshotRunner as snapshot_model_runner
|
|
21
|
+
from .test import TestRunner as test_runner
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class BuildTask(RunTask):
|
|
25
|
+
"""The Build task processes all assets of a given process and attempts to
|
|
26
|
+
'build' them in an opinionated fashion. Every resource type outlined in
|
|
27
|
+
RUNNER_MAP will be processed by the mapped runners class.
|
|
28
|
+
|
|
29
|
+
I.E. a resource of type Model is handled by the ModelRunner which is
|
|
30
|
+
imported as run_model_runner."""
|
|
31
|
+
|
|
32
|
+
MARK_DEPENDENT_ERRORS_STATUSES = [
|
|
33
|
+
NodeStatus.Error,
|
|
34
|
+
NodeStatus.Fail,
|
|
35
|
+
NodeStatus.Skipped,
|
|
36
|
+
NodeStatus.PartialSuccess,
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
RUNNER_MAP = {
|
|
40
|
+
NodeType.Model: run_model_runner,
|
|
41
|
+
NodeType.Snapshot: snapshot_model_runner,
|
|
42
|
+
NodeType.Seed: seed_runner,
|
|
43
|
+
NodeType.Test: test_runner,
|
|
44
|
+
NodeType.Unit: test_runner,
|
|
45
|
+
NodeType.SavedQuery: saved_query_runner,
|
|
46
|
+
NodeType.Exposure: exposure_runner,
|
|
47
|
+
NodeType.Function: function_runner,
|
|
48
|
+
}
|
|
49
|
+
ALL_RESOURCE_VALUES = frozenset({x for x in RUNNER_MAP.keys()})
|
|
50
|
+
|
|
51
|
+
def __init__(self, args: Flags, config: RuntimeConfig, manifest: Manifest) -> None:
|
|
52
|
+
super().__init__(args, config, manifest)
|
|
53
|
+
self.selected_unit_tests: Set = set()
|
|
54
|
+
self.model_to_unit_test_map: Dict[str, List] = {}
|
|
55
|
+
|
|
56
|
+
def resource_types(self, no_unit_tests: bool = False) -> List[NodeType]:
|
|
57
|
+
resource_types = resource_types_from_args(
|
|
58
|
+
self.args, set(self.ALL_RESOURCE_VALUES), set(self.ALL_RESOURCE_VALUES)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# First we get selected_nodes including unit tests, then without,
|
|
62
|
+
# and do a set difference.
|
|
63
|
+
if no_unit_tests is True and NodeType.Unit in resource_types:
|
|
64
|
+
resource_types.remove(NodeType.Unit)
|
|
65
|
+
return list(resource_types)
|
|
66
|
+
|
|
67
|
+
# overrides get_graph_queue in runnable.py
|
|
68
|
+
def get_graph_queue(self) -> GraphQueue:
|
|
69
|
+
# Following uses self.selection_arg and self.exclusion_arg
|
|
70
|
+
spec = self.get_selection_spec()
|
|
71
|
+
|
|
72
|
+
# selector including unit tests
|
|
73
|
+
full_selector = self.get_node_selector(no_unit_tests=False)
|
|
74
|
+
# selected node unique_ids with unit_tests
|
|
75
|
+
full_selected_nodes = full_selector.get_selected(spec)
|
|
76
|
+
|
|
77
|
+
# This selector removes the unit_tests from the selector
|
|
78
|
+
selector_wo_unit_tests = self.get_node_selector(no_unit_tests=True)
|
|
79
|
+
# selected node unique_ids without unit_tests
|
|
80
|
+
selected_nodes_wo_unit_tests = selector_wo_unit_tests.get_selected(spec)
|
|
81
|
+
|
|
82
|
+
# Get the difference in the sets of nodes with and without unit tests and
|
|
83
|
+
# save it
|
|
84
|
+
selected_unit_tests = full_selected_nodes - selected_nodes_wo_unit_tests
|
|
85
|
+
self.selected_unit_tests = selected_unit_tests
|
|
86
|
+
self.build_model_to_unit_test_map(selected_unit_tests)
|
|
87
|
+
|
|
88
|
+
# get_graph_queue in the selector will remove NodeTypes not specified
|
|
89
|
+
# in the node_selector (filter_selection).
|
|
90
|
+
return selector_wo_unit_tests.get_graph_queue(spec)
|
|
91
|
+
|
|
92
|
+
# overrides handle_job_queue in runnable.py
|
|
93
|
+
def handle_job_queue(self, pool, callback):
|
|
94
|
+
if self.run_count == 0:
|
|
95
|
+
self.num_nodes = self.num_nodes + len(self.selected_unit_tests)
|
|
96
|
+
node = self.job_queue.get()
|
|
97
|
+
if (
|
|
98
|
+
node.resource_type == NodeType.Model
|
|
99
|
+
and self.model_to_unit_test_map
|
|
100
|
+
and node.unique_id in self.model_to_unit_test_map
|
|
101
|
+
):
|
|
102
|
+
self.handle_model_with_unit_tests_node(node, pool, callback)
|
|
103
|
+
|
|
104
|
+
else:
|
|
105
|
+
self.handle_job_queue_node(node, pool, callback)
|
|
106
|
+
|
|
107
|
+
def handle_model_with_unit_tests_node(self, node, pool, callback):
|
|
108
|
+
self._raise_set_error()
|
|
109
|
+
args = [node, pool]
|
|
110
|
+
if self.config.args.single_threaded:
|
|
111
|
+
callback(self.call_model_and_unit_tests_runner(*args))
|
|
112
|
+
else:
|
|
113
|
+
pool.apply_async(self.call_model_and_unit_tests_runner, args=args, callback=callback)
|
|
114
|
+
|
|
115
|
+
def call_model_and_unit_tests_runner(self, node, pool) -> RunResult:
|
|
116
|
+
assert self.manifest
|
|
117
|
+
for unit_test_unique_id in self.model_to_unit_test_map[node.unique_id]:
|
|
118
|
+
unit_test_node = self.manifest.unit_tests[unit_test_unique_id]
|
|
119
|
+
unit_test_runner = self.get_runner(unit_test_node)
|
|
120
|
+
# If the model is marked skip, also skip the unit tests
|
|
121
|
+
if node.unique_id in self._skipped_children:
|
|
122
|
+
# cause is only for ephemeral nodes
|
|
123
|
+
unit_test_runner.do_skip(cause=None)
|
|
124
|
+
result = self.call_runner(unit_test_runner)
|
|
125
|
+
self._handle_result(result)
|
|
126
|
+
if result.status in self.MARK_DEPENDENT_ERRORS_STATUSES:
|
|
127
|
+
# The _skipped_children dictionary can contain a run_result for ephemeral nodes,
|
|
128
|
+
# but that should never be the case here.
|
|
129
|
+
self._skipped_children[node.unique_id] = None
|
|
130
|
+
runner = self.get_runner(node)
|
|
131
|
+
if runner.node.unique_id in self._skipped_children:
|
|
132
|
+
cause = self._skipped_children.pop(runner.node.unique_id)
|
|
133
|
+
runner.do_skip(cause=cause)
|
|
134
|
+
|
|
135
|
+
if isinstance(runner, MicrobatchModelRunner):
|
|
136
|
+
runner.set_parent_task(self)
|
|
137
|
+
runner.set_pool(pool)
|
|
138
|
+
|
|
139
|
+
return self.call_runner(runner)
|
|
140
|
+
|
|
141
|
+
# handle non-model-plus-unit-tests nodes
|
|
142
|
+
def handle_job_queue_node(self, node, pool, callback):
|
|
143
|
+
self._raise_set_error()
|
|
144
|
+
runner = self.get_runner(node)
|
|
145
|
+
# we finally know what we're running! Make sure we haven't decided
|
|
146
|
+
# to skip it due to upstream failures
|
|
147
|
+
if runner.node.unique_id in self._skipped_children:
|
|
148
|
+
cause = self._skipped_children.pop(runner.node.unique_id)
|
|
149
|
+
runner.do_skip(cause=cause)
|
|
150
|
+
|
|
151
|
+
if isinstance(runner, MicrobatchModelRunner):
|
|
152
|
+
runner.set_parent_task(self)
|
|
153
|
+
runner.set_pool(pool)
|
|
154
|
+
|
|
155
|
+
args = [runner]
|
|
156
|
+
self._submit(pool, args, callback)
|
|
157
|
+
|
|
158
|
+
# Make a map of model unique_ids to selected unit test unique_ids,
|
|
159
|
+
# for processing before the model.
|
|
160
|
+
def build_model_to_unit_test_map(self, selected_unit_tests):
|
|
161
|
+
dct = {}
|
|
162
|
+
for unit_test_unique_id in selected_unit_tests:
|
|
163
|
+
unit_test = self.manifest.unit_tests[unit_test_unique_id]
|
|
164
|
+
model_unique_id = unit_test.depends_on.nodes[0]
|
|
165
|
+
if model_unique_id not in dct:
|
|
166
|
+
dct[model_unique_id] = []
|
|
167
|
+
dct[model_unique_id].append(unit_test.unique_id)
|
|
168
|
+
self.model_to_unit_test_map = dct
|
|
169
|
+
|
|
170
|
+
# We return two different kinds of selectors, one with unit tests and one without
|
|
171
|
+
def get_node_selector(self, no_unit_tests=False) -> ResourceTypeSelector:
|
|
172
|
+
if self.manifest is None or self.graph is None:
|
|
173
|
+
raise DbtInternalError("manifest and graph must be set to get node selection")
|
|
174
|
+
|
|
175
|
+
resource_types = self.resource_types(no_unit_tests)
|
|
176
|
+
|
|
177
|
+
return ResourceTypeSelector(
|
|
178
|
+
graph=self.graph,
|
|
179
|
+
manifest=self.manifest,
|
|
180
|
+
previous_state=self.previous_state,
|
|
181
|
+
resource_types=resource_types,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def get_runner_type(self, node) -> Optional[Type[BaseRunner]]:
|
|
185
|
+
if (
|
|
186
|
+
node.resource_type == NodeType.Model
|
|
187
|
+
and super().get_runner_type(node) == MicrobatchModelRunner
|
|
188
|
+
):
|
|
189
|
+
return MicrobatchModelRunner
|
|
190
|
+
|
|
191
|
+
return self.RUNNER_MAP.get(node.resource_type)
|
|
192
|
+
|
|
193
|
+
# Special build compile_manifest method to pass add_test_edges to the compiler
|
|
194
|
+
def compile_manifest(self) -> None:
|
|
195
|
+
if self.manifest is None:
|
|
196
|
+
raise DbtInternalError("compile_manifest called before manifest was loaded")
|
|
197
|
+
self.graph: Graph = self.compiler.compile(self.manifest, add_test_edges=True)
|
dbt/task/clean.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from shutil import rmtree
|
|
3
|
+
|
|
4
|
+
from dbt import deprecations
|
|
5
|
+
from dbt.cli.flags import Flags
|
|
6
|
+
from dbt.config.project import Project
|
|
7
|
+
from dbt.events.types import CheckCleanPath, ConfirmCleanPath, FinishedCleanPaths
|
|
8
|
+
from dbt.task.base import BaseTask, move_to_nearest_project_dir
|
|
9
|
+
from dbt_common.events.functions import fire_event
|
|
10
|
+
from dbt_common.exceptions import DbtRuntimeError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CleanTask(BaseTask):
|
|
14
|
+
def __init__(self, args: Flags, config: Project):
|
|
15
|
+
super().__init__(args)
|
|
16
|
+
self.config = config
|
|
17
|
+
self.project = config
|
|
18
|
+
|
|
19
|
+
def run(self) -> None:
|
|
20
|
+
"""
|
|
21
|
+
This function takes all the paths in the target file
|
|
22
|
+
and cleans the project paths that are not protected.
|
|
23
|
+
"""
|
|
24
|
+
project_dir = move_to_nearest_project_dir(self.args.project_dir)
|
|
25
|
+
|
|
26
|
+
potential_clean_paths = set(Path(p).resolve() for p in self.project.clean_targets)
|
|
27
|
+
source_paths = set(
|
|
28
|
+
Path(p).resolve() for p in (*self.project.all_source_paths, *self.project.test_paths)
|
|
29
|
+
)
|
|
30
|
+
clean_paths = potential_clean_paths.difference(source_paths)
|
|
31
|
+
|
|
32
|
+
if potential_clean_paths != clean_paths:
|
|
33
|
+
raise DbtRuntimeError(
|
|
34
|
+
f"dbt will not clean the following source paths: {[str(s) for s in source_paths.intersection(potential_clean_paths)]}"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
paths_outside_project = set(
|
|
38
|
+
path for path in clean_paths if project_dir not in path.absolute().parents
|
|
39
|
+
)
|
|
40
|
+
if paths_outside_project and self.args.clean_project_files_only:
|
|
41
|
+
raise DbtRuntimeError(
|
|
42
|
+
f"dbt will not clean the following directories outside the project: {[str(p) for p in paths_outside_project]}"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
"dbt_modules" in self.project.clean_targets
|
|
47
|
+
and self.config.packages_install_path not in self.config.clean_targets
|
|
48
|
+
):
|
|
49
|
+
deprecations.warn("install-packages-path")
|
|
50
|
+
|
|
51
|
+
for path in clean_paths:
|
|
52
|
+
fire_event(CheckCleanPath(path=str(path)))
|
|
53
|
+
rmtree(path, True)
|
|
54
|
+
fire_event(ConfirmCleanPath(path=str(path)))
|
|
55
|
+
|
|
56
|
+
fire_event(FinishedCleanPaths())
|
dbt/task/clone.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from typing import AbstractSet, Any, Collection, Iterable, List, Optional, Set, Type
|
|
3
|
+
|
|
4
|
+
from dbt.adapters.base import BaseAdapter, BaseRelation
|
|
5
|
+
from dbt.artifacts.resources.types import NodeType
|
|
6
|
+
from dbt.artifacts.schemas.run import RunResult, RunStatus
|
|
7
|
+
from dbt.clients.jinja import MacroGenerator
|
|
8
|
+
from dbt.context.providers import generate_runtime_model_context
|
|
9
|
+
from dbt.contracts.graph.manifest import Manifest
|
|
10
|
+
from dbt.graph import ResourceTypeSelector
|
|
11
|
+
from dbt.node_types import REFABLE_NODE_TYPES
|
|
12
|
+
from dbt.task.base import BaseRunner, resource_types_from_args
|
|
13
|
+
from dbt.task.run import _validate_materialization_relations_dict
|
|
14
|
+
from dbt.task.runnable import GraphRunnableMode, GraphRunnableTask
|
|
15
|
+
from dbt_common.dataclass_schema import dbtClassMixin
|
|
16
|
+
from dbt_common.exceptions import CompilationError, DbtInternalError
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CloneRunner(BaseRunner):
|
|
20
|
+
def before_execute(self) -> None:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def after_execute(self, result) -> None:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
def _build_run_model_result(self, model, context):
|
|
27
|
+
result = context["load_result"]("main")
|
|
28
|
+
if result:
|
|
29
|
+
status = RunStatus.Success
|
|
30
|
+
message = str(result.response)
|
|
31
|
+
else:
|
|
32
|
+
status = RunStatus.Success
|
|
33
|
+
message = "No-op"
|
|
34
|
+
adapter_response = {}
|
|
35
|
+
if result and isinstance(result.response, dbtClassMixin):
|
|
36
|
+
adapter_response = result.response.to_dict(omit_none=True)
|
|
37
|
+
return RunResult(
|
|
38
|
+
node=model,
|
|
39
|
+
status=status,
|
|
40
|
+
timing=[],
|
|
41
|
+
thread_id=threading.current_thread().name,
|
|
42
|
+
execution_time=0,
|
|
43
|
+
message=message,
|
|
44
|
+
adapter_response=adapter_response,
|
|
45
|
+
failures=None,
|
|
46
|
+
batch_results=None,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def compile(self, manifest: Manifest):
|
|
50
|
+
# no-op
|
|
51
|
+
return self.node
|
|
52
|
+
|
|
53
|
+
def _materialization_relations(self, result: Any, model) -> List[BaseRelation]:
|
|
54
|
+
if isinstance(result, str):
|
|
55
|
+
msg = (
|
|
56
|
+
'The materialization ("{}") did not explicitly return a '
|
|
57
|
+
"list of relations to add to the cache.".format(str(model.get_materialization()))
|
|
58
|
+
)
|
|
59
|
+
raise CompilationError(msg, node=model)
|
|
60
|
+
|
|
61
|
+
if isinstance(result, dict):
|
|
62
|
+
return _validate_materialization_relations_dict(result, model)
|
|
63
|
+
|
|
64
|
+
msg = (
|
|
65
|
+
"Invalid return value from materialization, expected a dict "
|
|
66
|
+
'with key "relations", got: {}'.format(str(result))
|
|
67
|
+
)
|
|
68
|
+
raise CompilationError(msg, node=model)
|
|
69
|
+
|
|
70
|
+
def execute(self, model, manifest):
|
|
71
|
+
context = generate_runtime_model_context(model, self.config, manifest)
|
|
72
|
+
materialization_macro = manifest.find_materialization_macro_by_name(
|
|
73
|
+
self.config.project_name, "clone", self.adapter.type()
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if "config" not in context:
|
|
77
|
+
raise DbtInternalError(
|
|
78
|
+
"Invalid materialization context generated, missing config: {}".format(context)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
context_config = context["config"]
|
|
82
|
+
|
|
83
|
+
hook_ctx = self.adapter.pre_model_hook(context_config)
|
|
84
|
+
try:
|
|
85
|
+
result = MacroGenerator(materialization_macro, context)()
|
|
86
|
+
finally:
|
|
87
|
+
self.adapter.post_model_hook(context_config, hook_ctx)
|
|
88
|
+
|
|
89
|
+
for relation in self._materialization_relations(result, model):
|
|
90
|
+
self.adapter.cache_added(relation.incorporate(dbt_created=True))
|
|
91
|
+
|
|
92
|
+
return self._build_run_model_result(model, context)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class CloneTask(GraphRunnableTask):
|
|
96
|
+
def raise_on_first_error(self) -> bool:
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
def get_run_mode(self) -> GraphRunnableMode:
|
|
100
|
+
return GraphRunnableMode.Independent
|
|
101
|
+
|
|
102
|
+
def _get_deferred_manifest(self) -> Optional[Manifest]:
|
|
103
|
+
# Unlike other commands, 'clone' always requires a state manifest
|
|
104
|
+
# Load previous state, regardless of whether --defer flag has been set
|
|
105
|
+
return self._get_previous_state()
|
|
106
|
+
|
|
107
|
+
def get_model_schemas(self, adapter, selected_uids: Iterable[str]) -> Set[BaseRelation]:
|
|
108
|
+
if self.manifest is None:
|
|
109
|
+
raise DbtInternalError("manifest was None in get_model_schemas")
|
|
110
|
+
result: Set[BaseRelation] = set()
|
|
111
|
+
|
|
112
|
+
for node in self.manifest.nodes.values():
|
|
113
|
+
if node.unique_id not in selected_uids:
|
|
114
|
+
continue
|
|
115
|
+
if node.is_relational and not node.is_ephemeral:
|
|
116
|
+
relation = adapter.Relation.create_from(self.config, node)
|
|
117
|
+
result.add(relation.without_identifier())
|
|
118
|
+
|
|
119
|
+
# cache the 'other' schemas too!
|
|
120
|
+
if node.defer_relation: # type: ignore
|
|
121
|
+
other_relation = adapter.Relation.create_from(
|
|
122
|
+
self.config, node.defer_relation # type: ignore
|
|
123
|
+
)
|
|
124
|
+
result.add(other_relation.without_identifier())
|
|
125
|
+
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
def before_run(self, adapter: BaseAdapter, selected_uids: AbstractSet[str]) -> RunStatus:
|
|
129
|
+
with adapter.connection_named("master"):
|
|
130
|
+
self.defer_to_manifest()
|
|
131
|
+
# only create target schemas, but also cache defer_relation schemas
|
|
132
|
+
schemas_to_create = super().get_model_schemas(adapter, selected_uids)
|
|
133
|
+
self.create_schemas(adapter, schemas_to_create)
|
|
134
|
+
schemas_to_cache = self.get_model_schemas(adapter, selected_uids)
|
|
135
|
+
self.populate_adapter_cache(adapter, schemas_to_cache)
|
|
136
|
+
return RunStatus.Success
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def resource_types(self) -> List[NodeType]:
|
|
140
|
+
resource_types: Collection[NodeType] = resource_types_from_args(
|
|
141
|
+
self.args, set(REFABLE_NODE_TYPES), set(REFABLE_NODE_TYPES)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# filter out any non-refable node types
|
|
145
|
+
resource_types = [rt for rt in resource_types if rt in REFABLE_NODE_TYPES]
|
|
146
|
+
return list(resource_types)
|
|
147
|
+
|
|
148
|
+
def get_node_selector(self) -> ResourceTypeSelector:
|
|
149
|
+
resource_types = self.resource_types
|
|
150
|
+
|
|
151
|
+
if self.manifest is None or self.graph is None:
|
|
152
|
+
raise DbtInternalError("manifest and graph must be set to get perform node selection")
|
|
153
|
+
return ResourceTypeSelector(
|
|
154
|
+
graph=self.graph,
|
|
155
|
+
manifest=self.manifest,
|
|
156
|
+
previous_state=self.previous_state,
|
|
157
|
+
resource_types=resource_types,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def get_runner_type(self, _) -> Optional[Type[BaseRunner]]:
|
|
161
|
+
return CloneRunner
|
dbt/task/compile.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from typing import Optional, Type
|
|
3
|
+
|
|
4
|
+
from dbt.artifacts.schemas.run import RunResult, RunStatus
|
|
5
|
+
from dbt.contracts.graph.manifest import Manifest
|
|
6
|
+
from dbt.events.types import CompiledNode, ParseInlineNodeError
|
|
7
|
+
from dbt.flags import get_flags
|
|
8
|
+
from dbt.graph import ResourceTypeSelector
|
|
9
|
+
from dbt.node_types import EXECUTABLE_NODE_TYPES, NodeType
|
|
10
|
+
from dbt.parser.manifest import process_node
|
|
11
|
+
from dbt.parser.sql import SqlBlockParser
|
|
12
|
+
from dbt.task.base import BaseRunner
|
|
13
|
+
from dbt.task.runnable import GraphRunnableTask
|
|
14
|
+
from dbt_common.events.base_types import EventLevel
|
|
15
|
+
from dbt_common.events.functions import fire_event
|
|
16
|
+
from dbt_common.events.types import Note
|
|
17
|
+
from dbt_common.exceptions import CompilationError
|
|
18
|
+
from dbt_common.exceptions import DbtBaseException as DbtException
|
|
19
|
+
from dbt_common.exceptions import DbtInternalError
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CompileRunner(BaseRunner):
|
|
23
|
+
def before_execute(self) -> None:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
def after_execute(self, result) -> None:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def execute(self, compiled_node, manifest):
|
|
30
|
+
return RunResult(
|
|
31
|
+
node=compiled_node,
|
|
32
|
+
status=RunStatus.Success,
|
|
33
|
+
timing=[],
|
|
34
|
+
thread_id=threading.current_thread().name,
|
|
35
|
+
execution_time=0,
|
|
36
|
+
message=None,
|
|
37
|
+
adapter_response={},
|
|
38
|
+
failures=None,
|
|
39
|
+
batch_results=None,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def compile(self, manifest: Manifest):
|
|
43
|
+
return self.compiler.compile_node(self.node, manifest, {})
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CompileTask(GraphRunnableTask):
|
|
47
|
+
# We add a new inline node to the manifest during initialization
|
|
48
|
+
# it should be removed before the task is complete
|
|
49
|
+
_inline_node_id = None
|
|
50
|
+
|
|
51
|
+
def raise_on_first_error(self) -> bool:
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
def get_node_selector(self) -> ResourceTypeSelector:
|
|
55
|
+
if getattr(self.args, "inline", None):
|
|
56
|
+
resource_types = [NodeType.SqlOperation]
|
|
57
|
+
else:
|
|
58
|
+
resource_types = EXECUTABLE_NODE_TYPES
|
|
59
|
+
|
|
60
|
+
if self.manifest is None or self.graph is None:
|
|
61
|
+
raise DbtInternalError("manifest and graph must be set to get perform node selection")
|
|
62
|
+
return ResourceTypeSelector(
|
|
63
|
+
graph=self.graph,
|
|
64
|
+
manifest=self.manifest,
|
|
65
|
+
previous_state=self.previous_state,
|
|
66
|
+
resource_types=resource_types,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def get_runner_type(self, _) -> Optional[Type[BaseRunner]]:
|
|
70
|
+
return CompileRunner
|
|
71
|
+
|
|
72
|
+
def task_end_messages(self, results) -> None:
|
|
73
|
+
is_inline = bool(getattr(self.args, "inline", None))
|
|
74
|
+
output_format = getattr(self.args, "output", "text")
|
|
75
|
+
|
|
76
|
+
if is_inline:
|
|
77
|
+
matched_results = [result for result in results if result.node.name == "inline_query"]
|
|
78
|
+
elif self.selection_arg:
|
|
79
|
+
matched_results = []
|
|
80
|
+
for result in results:
|
|
81
|
+
if result.node.name in self.selection_arg[0]:
|
|
82
|
+
matched_results.append(result)
|
|
83
|
+
else:
|
|
84
|
+
fire_event(
|
|
85
|
+
Note(msg=f"Excluded node '{result.node.name}' from results"),
|
|
86
|
+
EventLevel.DEBUG,
|
|
87
|
+
)
|
|
88
|
+
# No selector passed, compiling all nodes
|
|
89
|
+
else:
|
|
90
|
+
matched_results = []
|
|
91
|
+
|
|
92
|
+
for result in matched_results:
|
|
93
|
+
fire_event(
|
|
94
|
+
CompiledNode(
|
|
95
|
+
node_name=result.node.name,
|
|
96
|
+
compiled=result.node.compiled_code,
|
|
97
|
+
is_inline=is_inline,
|
|
98
|
+
output_format=output_format,
|
|
99
|
+
unique_id=result.node.unique_id,
|
|
100
|
+
quiet=get_flags().QUIET,
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def _runtime_initialize(self):
|
|
105
|
+
if getattr(self.args, "inline", None):
|
|
106
|
+
try:
|
|
107
|
+
block_parser = SqlBlockParser(
|
|
108
|
+
project=self.config, manifest=self.manifest, root_project=self.config
|
|
109
|
+
)
|
|
110
|
+
sql_node = block_parser.parse_remote(self.args.inline, "inline_query")
|
|
111
|
+
process_node(self.config, self.manifest, sql_node)
|
|
112
|
+
# Special hack to remove disabled, if it's there. This would only happen
|
|
113
|
+
# if all models are disabled in dbt_project
|
|
114
|
+
if sql_node.config.enabled is False:
|
|
115
|
+
sql_node.config.enabled = True
|
|
116
|
+
self.manifest.disabled.pop(sql_node.unique_id)
|
|
117
|
+
self.manifest.nodes[sql_node.unique_id] = sql_node
|
|
118
|
+
# keep track of the node added to the manifest
|
|
119
|
+
self._inline_node_id = sql_node.unique_id
|
|
120
|
+
except CompilationError as exc:
|
|
121
|
+
fire_event(
|
|
122
|
+
ParseInlineNodeError(
|
|
123
|
+
exc=str(exc.msg),
|
|
124
|
+
node_info={
|
|
125
|
+
"node_path": "sql/inline_query",
|
|
126
|
+
"node_name": "inline_query",
|
|
127
|
+
"unique_id": "sqloperation.test.inline_query",
|
|
128
|
+
"node_status": "failed",
|
|
129
|
+
},
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
raise DbtException("Error parsing inline query")
|
|
133
|
+
super()._runtime_initialize()
|
|
134
|
+
|
|
135
|
+
def after_run(self, adapter, results) -> None:
|
|
136
|
+
# remove inline node from manifest
|
|
137
|
+
if self._inline_node_id:
|
|
138
|
+
self.manifest.nodes.pop(self._inline_node_id)
|
|
139
|
+
self._inline_node_id = None
|
|
140
|
+
super().after_run(adapter, results)
|
|
141
|
+
|
|
142
|
+
def _handle_result(self, result) -> None:
|
|
143
|
+
super()._handle_result(result)
|
|
144
|
+
|
|
145
|
+
if (
|
|
146
|
+
result.node.is_ephemeral_model
|
|
147
|
+
and type(self) is CompileTask
|
|
148
|
+
and (self.args.select or getattr(self.args, "inline", None))
|
|
149
|
+
):
|
|
150
|
+
self.node_results.append(result)
|