dagster-dbt 0.23.3__py3-none-any.whl → 0.28.4__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.
- dagster_dbt/__init__.py +41 -140
- dagster_dbt/asset_decorator.py +49 -230
- dagster_dbt/asset_specs.py +65 -0
- dagster_dbt/asset_utils.py +655 -338
- dagster_dbt/cli/app.py +44 -43
- dagster_dbt/cloud/__init__.py +6 -4
- dagster_dbt/cloud/asset_defs.py +119 -177
- dagster_dbt/cloud/cli.py +3 -4
- dagster_dbt/cloud/ops.py +9 -6
- dagster_dbt/cloud/resources.py +9 -4
- dagster_dbt/cloud/types.py +12 -7
- dagster_dbt/cloud/utils.py +186 -0
- dagster_dbt/cloud_v2/__init__.py +10 -0
- dagster_dbt/cloud_v2/asset_decorator.py +81 -0
- dagster_dbt/cloud_v2/cli_invocation.py +67 -0
- dagster_dbt/cloud_v2/client.py +438 -0
- dagster_dbt/cloud_v2/resources.py +462 -0
- dagster_dbt/cloud_v2/run_handler.py +229 -0
- dagster_dbt/cloud_v2/sensor_builder.py +254 -0
- dagster_dbt/cloud_v2/types.py +143 -0
- dagster_dbt/compat.py +107 -0
- dagster_dbt/components/__init__.py +0 -0
- dagster_dbt/components/dbt_project/__init__.py +0 -0
- dagster_dbt/components/dbt_project/component.py +545 -0
- dagster_dbt/components/dbt_project/scaffolder.py +65 -0
- dagster_dbt/core/__init__.py +0 -10
- dagster_dbt/core/dbt_cli_event.py +612 -0
- dagster_dbt/core/dbt_cli_invocation.py +474 -0
- dagster_dbt/core/dbt_event_iterator.py +399 -0
- dagster_dbt/core/resource.py +733 -0
- dagster_dbt/core/utils.py +14 -279
- dagster_dbt/dagster_dbt_translator.py +317 -74
- dagster_dbt/dbt_core_version.py +1 -0
- dagster_dbt/dbt_manifest.py +6 -5
- dagster_dbt/dbt_manifest_asset_selection.py +62 -22
- dagster_dbt/dbt_project.py +179 -40
- dagster_dbt/dbt_project_manager.py +173 -0
- dagster_dbt/dbt_version.py +0 -0
- dagster_dbt/errors.py +9 -84
- dagster_dbt/freshness_builder.py +147 -0
- dagster_dbt/include/pyproject.toml.jinja +21 -0
- dagster_dbt/include/scaffold/assets.py.jinja +1 -8
- dagster_dbt/include/scaffold/definitions.py.jinja +0 -15
- dagster_dbt/include/scaffold/project.py.jinja +1 -0
- dagster_dbt/include/setup.py.jinja +2 -3
- dagster_dbt/metadata_set.py +18 -0
- dagster_dbt/utils.py +136 -234
- dagster_dbt/version.py +1 -1
- dagster_dbt-0.28.4.dist-info/METADATA +47 -0
- dagster_dbt-0.28.4.dist-info/RECORD +59 -0
- {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info}/WHEEL +1 -1
- {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info}/entry_points.txt +3 -0
- {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info/licenses}/LICENSE +1 -1
- dagster_dbt/asset_defs.py +0 -1049
- dagster_dbt/core/resources.py +0 -527
- dagster_dbt/core/resources_v2.py +0 -1542
- dagster_dbt/core/types.py +0 -63
- dagster_dbt/dbt_resource.py +0 -220
- dagster_dbt/include/scaffold/constants.py.jinja +0 -21
- dagster_dbt/ops.py +0 -134
- dagster_dbt/types.py +0 -22
- dagster_dbt-0.23.3.dist-info/METADATA +0 -31
- dagster_dbt-0.23.3.dist-info/RECORD +0 -43
- {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info}/top_level.txt +0 -0
|
@@ -1,33 +1,54 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from collections.abc import Mapping, Sequence
|
|
1
3
|
from dataclasses import dataclass
|
|
2
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
3
6
|
|
|
4
7
|
from dagster import (
|
|
8
|
+
AssetCheckSpec,
|
|
9
|
+
AssetDep,
|
|
5
10
|
AssetKey,
|
|
11
|
+
AssetSpec,
|
|
6
12
|
AutoMaterializePolicy,
|
|
7
|
-
|
|
13
|
+
AutomationCondition,
|
|
14
|
+
DagsterInvalidDefinitionError,
|
|
8
15
|
PartitionMapping,
|
|
9
|
-
_check as check,
|
|
10
16
|
)
|
|
11
|
-
from dagster._annotations import public
|
|
12
|
-
from dagster._core.definitions.
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
from dagster._annotations import beta, public
|
|
18
|
+
from dagster._core.definitions.metadata.source_code import (
|
|
19
|
+
CodeReferencesMetadataSet,
|
|
20
|
+
CodeReferencesMetadataValue,
|
|
21
|
+
LocalFileCodeReference,
|
|
15
22
|
)
|
|
16
|
-
from dagster._core.definitions.
|
|
17
|
-
|
|
18
|
-
from .
|
|
23
|
+
from dagster._core.definitions.partitions.definition import PartitionsDefinition
|
|
24
|
+
from dagster._utils.tags import is_valid_tag_key
|
|
25
|
+
from dagster.components.resolved.base import Resolvable
|
|
26
|
+
from dagster_shared import check
|
|
27
|
+
|
|
28
|
+
from dagster_dbt.asset_utils import (
|
|
29
|
+
DAGSTER_DBT_MANIFEST_METADATA_KEY,
|
|
30
|
+
DAGSTER_DBT_PROJECT_METADATA_KEY,
|
|
31
|
+
DAGSTER_DBT_TRANSLATOR_METADATA_KEY,
|
|
32
|
+
DAGSTER_DBT_UNIQUE_ID_METADATA_KEY,
|
|
33
|
+
default_asset_check_fn,
|
|
19
34
|
default_asset_key_fn,
|
|
20
35
|
default_auto_materialize_policy_fn,
|
|
36
|
+
default_code_version_fn,
|
|
21
37
|
default_description_fn,
|
|
22
|
-
default_freshness_policy_fn,
|
|
23
38
|
default_group_from_dbt_resource_props,
|
|
24
39
|
default_metadata_from_dbt_resource_props,
|
|
25
40
|
default_owners_from_dbt_resource_props,
|
|
41
|
+
get_node,
|
|
42
|
+
get_upstream_unique_ids,
|
|
43
|
+
has_self_dependency,
|
|
26
44
|
)
|
|
27
45
|
|
|
46
|
+
if TYPE_CHECKING:
|
|
47
|
+
from dagster_dbt.dbt_project import DbtProject
|
|
48
|
+
|
|
28
49
|
|
|
29
50
|
@dataclass(frozen=True)
|
|
30
|
-
class DagsterDbtTranslatorSettings:
|
|
51
|
+
class DagsterDbtTranslatorSettings(Resolvable):
|
|
31
52
|
"""Settings to enable Dagster features for your dbt project.
|
|
32
53
|
|
|
33
54
|
Args:
|
|
@@ -35,10 +56,19 @@ class DagsterDbtTranslatorSettings:
|
|
|
35
56
|
Defaults to True.
|
|
36
57
|
enable_duplicate_source_asset_keys (bool): Whether to allow dbt sources with duplicate
|
|
37
58
|
Dagster asset keys. Defaults to False.
|
|
59
|
+
enable_code_references (bool): Whether to enable Dagster code references for dbt resources.
|
|
60
|
+
Defaults to False.
|
|
61
|
+
enable_dbt_selection_by_name (bool): Whether to enable selecting dbt resources by name,
|
|
62
|
+
rather than fully qualified name. Defaults to False.
|
|
63
|
+
enable_source_tests_as_checks (bool): Whether to load dbt source tests as Dagster asset checks.
|
|
64
|
+
Defaults to False. If False, asset observations will be emitted for source tests.
|
|
38
65
|
"""
|
|
39
66
|
|
|
40
67
|
enable_asset_checks: bool = True
|
|
41
68
|
enable_duplicate_source_asset_keys: bool = False
|
|
69
|
+
enable_code_references: bool = False
|
|
70
|
+
enable_dbt_selection_by_name: bool = False
|
|
71
|
+
enable_source_tests_as_checks: bool = False
|
|
42
72
|
|
|
43
73
|
|
|
44
74
|
class DagsterDbtTranslator:
|
|
@@ -64,6 +94,145 @@ class DagsterDbtTranslator:
|
|
|
64
94
|
|
|
65
95
|
return self._settings
|
|
66
96
|
|
|
97
|
+
def get_resource_props(self, manifest: Mapping[str, Any], unique_id: str) -> Mapping[str, Any]:
|
|
98
|
+
"""Given a parsed manifest and a dbt unique_id, returns the dictionary of properties
|
|
99
|
+
for the corresponding dbt resource (e.g. model, seed, snapshot, source) as defined
|
|
100
|
+
in your dbt project. This can be used as a convenience method when overriding the
|
|
101
|
+
`get_asset_spec` method.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
manifest (Mapping[str, Any]): The parsed manifest of the dbt project.
|
|
105
|
+
unique_id (str): The unique_id of the dbt resource.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Mapping[str, Any]: The dictionary of properties for the corresponding dbt resource.
|
|
109
|
+
|
|
110
|
+
Examples:
|
|
111
|
+
.. code-block:: python
|
|
112
|
+
|
|
113
|
+
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
114
|
+
|
|
115
|
+
def get_asset_spec(self, manifest: Mapping[str, Any], unique_id: str, project: Optional[DbtProject]) -> dg.AssetSpec:
|
|
116
|
+
base_spec = super().get_asset_spec(manifest, unique_id, project)
|
|
117
|
+
resource_props = self.get_resource_props(manifest, unique_id)
|
|
118
|
+
if resource_props["meta"].get("use_custom_group"):
|
|
119
|
+
return base_spec.replace_attributes(group_name="custom_group")
|
|
120
|
+
else:
|
|
121
|
+
return base_spec
|
|
122
|
+
"""
|
|
123
|
+
return get_node(manifest, unique_id)
|
|
124
|
+
|
|
125
|
+
def get_asset_spec(
|
|
126
|
+
self,
|
|
127
|
+
manifest: Mapping[str, Any],
|
|
128
|
+
unique_id: str,
|
|
129
|
+
project: Optional["DbtProject"],
|
|
130
|
+
) -> AssetSpec:
|
|
131
|
+
"""Returns an AssetSpec representing a specific dbt resource."""
|
|
132
|
+
# memoize resolution for a given manifest & unique_id
|
|
133
|
+
# since we recursively call get_asset_spec for dependencies
|
|
134
|
+
memo_id = (id(manifest), unique_id, id(project))
|
|
135
|
+
|
|
136
|
+
# Don't initialize this in the constructor in case a subclass does not call __init__
|
|
137
|
+
if not hasattr(self, "_resolved_specs"):
|
|
138
|
+
self._resolved_specs = {}
|
|
139
|
+
|
|
140
|
+
if memo_id in self._resolved_specs:
|
|
141
|
+
return self._resolved_specs[memo_id]
|
|
142
|
+
|
|
143
|
+
group_props = {group["name"]: group for group in manifest.get("groups", {}).values()}
|
|
144
|
+
resource_props = self.get_resource_props(manifest, unique_id)
|
|
145
|
+
|
|
146
|
+
# calculate the dependencies for the asset
|
|
147
|
+
upstream_ids = get_upstream_unique_ids(manifest, resource_props)
|
|
148
|
+
deps = [
|
|
149
|
+
AssetDep(
|
|
150
|
+
asset=self.get_asset_spec(manifest, upstream_id, project).key,
|
|
151
|
+
partition_mapping=self.get_partition_mapping(
|
|
152
|
+
resource_props, self.get_resource_props(manifest, upstream_id)
|
|
153
|
+
),
|
|
154
|
+
)
|
|
155
|
+
for upstream_id in upstream_ids
|
|
156
|
+
]
|
|
157
|
+
self_partition_mapping = self.get_partition_mapping(resource_props, resource_props)
|
|
158
|
+
if self_partition_mapping and has_self_dependency(resource_props):
|
|
159
|
+
deps.append(
|
|
160
|
+
AssetDep(
|
|
161
|
+
asset=self.get_asset_key(resource_props),
|
|
162
|
+
partition_mapping=self_partition_mapping,
|
|
163
|
+
)
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
resource_group_props = group_props.get(resource_props.get("group") or "")
|
|
167
|
+
if resource_group_props:
|
|
168
|
+
owners_resource_props = {
|
|
169
|
+
**resource_props,
|
|
170
|
+
# this overrides the group key in resource_props, which is bad as
|
|
171
|
+
# this key is not always empty and this dictionary generally differs
|
|
172
|
+
# in structure from other inputs, but this is necessary for backcompat
|
|
173
|
+
**({"group": resource_group_props} if resource_group_props else {}),
|
|
174
|
+
}
|
|
175
|
+
else:
|
|
176
|
+
owners_resource_props = resource_props
|
|
177
|
+
|
|
178
|
+
spec = AssetSpec(
|
|
179
|
+
key=self.get_asset_key(resource_props),
|
|
180
|
+
deps=deps,
|
|
181
|
+
description=self.get_description(resource_props),
|
|
182
|
+
metadata=self.get_metadata(resource_props),
|
|
183
|
+
skippable=True,
|
|
184
|
+
group_name=self.get_group_name(resource_props),
|
|
185
|
+
code_version=self.get_code_version(resource_props),
|
|
186
|
+
automation_condition=self.get_automation_condition(resource_props),
|
|
187
|
+
owners=self.get_owners(owners_resource_props),
|
|
188
|
+
tags=self.get_tags(resource_props),
|
|
189
|
+
kinds={"dbt", manifest.get("metadata", {}).get("adapter_type", "dbt")},
|
|
190
|
+
partitions_def=self.get_partitions_def(resource_props),
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# add integration-specific metadata to the spec
|
|
194
|
+
spec = spec.merge_attributes(
|
|
195
|
+
metadata={
|
|
196
|
+
DAGSTER_DBT_MANIFEST_METADATA_KEY: DbtManifestWrapper(manifest=manifest),
|
|
197
|
+
DAGSTER_DBT_TRANSLATOR_METADATA_KEY: self,
|
|
198
|
+
DAGSTER_DBT_UNIQUE_ID_METADATA_KEY: resource_props["unique_id"],
|
|
199
|
+
**({DAGSTER_DBT_PROJECT_METADATA_KEY: project} if project else {}),
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
if self.settings.enable_code_references:
|
|
203
|
+
if not project:
|
|
204
|
+
raise DagsterInvalidDefinitionError(
|
|
205
|
+
"enable_code_references requires a DbtProject to be supplied"
|
|
206
|
+
" to the @dbt_assets decorator."
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
spec = spec.replace_attributes(
|
|
210
|
+
metadata=_attach_sql_model_code_reference(
|
|
211
|
+
existing_metadata=spec.metadata,
|
|
212
|
+
dbt_resource_props=resource_props,
|
|
213
|
+
project=project,
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
self._resolved_specs[memo_id] = spec
|
|
218
|
+
|
|
219
|
+
return self._resolved_specs[memo_id]
|
|
220
|
+
|
|
221
|
+
def get_asset_check_spec(
|
|
222
|
+
self,
|
|
223
|
+
asset_spec: AssetSpec,
|
|
224
|
+
manifest: Mapping[str, Any],
|
|
225
|
+
unique_id: str,
|
|
226
|
+
project: Optional["DbtProject"],
|
|
227
|
+
) -> Optional[AssetCheckSpec]:
|
|
228
|
+
return default_asset_check_fn(
|
|
229
|
+
manifest=manifest,
|
|
230
|
+
dagster_dbt_translator=self,
|
|
231
|
+
asset_key=asset_spec.key,
|
|
232
|
+
test_unique_id=unique_id,
|
|
233
|
+
project=project,
|
|
234
|
+
)
|
|
235
|
+
|
|
67
236
|
@public
|
|
68
237
|
def get_asset_key(self, dbt_resource_props: Mapping[str, Any]) -> AssetKey:
|
|
69
238
|
"""A function that takes a dictionary representing properties of a dbt resource, and
|
|
@@ -119,6 +288,7 @@ class DagsterDbtTranslator:
|
|
|
119
288
|
return default_asset_key_fn(dbt_resource_props)
|
|
120
289
|
|
|
121
290
|
@public
|
|
291
|
+
@beta(emit_runtime_warning=False)
|
|
122
292
|
def get_partition_mapping(
|
|
123
293
|
self,
|
|
124
294
|
dbt_resource_props: Mapping[str, Any],
|
|
@@ -223,8 +393,8 @@ class DagsterDbtTranslator:
|
|
|
223
393
|
https://docs.getdbt.com/reference/artifacts/manifest-json#resource-details
|
|
224
394
|
|
|
225
395
|
dbt tags are strings, but Dagster tags are key-value pairs. To bridge this divide, the dbt
|
|
226
|
-
tag string is used as the Dagster tag key, and the Dagster tag value is set to
|
|
227
|
-
|
|
396
|
+
tag string is used as the Dagster tag key, and the Dagster tag value is set to the empty
|
|
397
|
+
string, "".
|
|
228
398
|
|
|
229
399
|
Any dbt tags that don't match Dagster's supported tag key format (e.g. they contain
|
|
230
400
|
unsupported characters) will be ignored.
|
|
@@ -250,7 +420,7 @@ class DagsterDbtTranslator:
|
|
|
250
420
|
return {"custom": "tag"}
|
|
251
421
|
"""
|
|
252
422
|
tags = dbt_resource_props.get("tags", [])
|
|
253
|
-
return {tag: "" for tag in tags if
|
|
423
|
+
return {tag: "" for tag in tags if is_valid_tag_key(tag)}
|
|
254
424
|
|
|
255
425
|
@public
|
|
256
426
|
def get_group_name(self, dbt_resource_props: Mapping[str, Any]) -> Optional[str]:
|
|
@@ -284,6 +454,38 @@ class DagsterDbtTranslator:
|
|
|
284
454
|
"""
|
|
285
455
|
return default_group_from_dbt_resource_props(dbt_resource_props)
|
|
286
456
|
|
|
457
|
+
@public
|
|
458
|
+
def get_code_version(self, dbt_resource_props: Mapping[str, Any]) -> Optional[str]:
|
|
459
|
+
"""A function that takes a dictionary representing properties of a dbt resource, and
|
|
460
|
+
returns the Dagster code version for that resource.
|
|
461
|
+
|
|
462
|
+
Note that a dbt resource is unrelated to Dagster's resource concept, and simply represents
|
|
463
|
+
a model, seed, snapshot or source in a given dbt project. You can learn more about dbt
|
|
464
|
+
resources and the properties available in this dictionary here:
|
|
465
|
+
https://docs.getdbt.com/reference/artifacts/manifest-json#resource-details
|
|
466
|
+
|
|
467
|
+
This method can be overridden to provide a custom code version for a dbt resource.
|
|
468
|
+
|
|
469
|
+
Args:
|
|
470
|
+
dbt_resource_props (Mapping[str, Any]): A dictionary representing the dbt resource.
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
Optional[str]: A Dagster code version.
|
|
474
|
+
|
|
475
|
+
Examples:
|
|
476
|
+
.. code-block:: python
|
|
477
|
+
|
|
478
|
+
from typing import Any, Mapping
|
|
479
|
+
|
|
480
|
+
from dagster_dbt import DagsterDbtTranslator
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
484
|
+
def get_code_version(self, dbt_resource_props: Mapping[str, Any]) -> Optional[str]:
|
|
485
|
+
return dbt_resource_props["checksum"]["checksum"]
|
|
486
|
+
"""
|
|
487
|
+
return default_code_version_fn(dbt_resource_props)
|
|
488
|
+
|
|
287
489
|
@public
|
|
288
490
|
def get_owners(self, dbt_resource_props: Mapping[str, Any]) -> Optional[Sequence[str]]:
|
|
289
491
|
"""A function that takes a dictionary representing properties of a dbt resource, and
|
|
@@ -317,27 +519,28 @@ class DagsterDbtTranslator:
|
|
|
317
519
|
return default_owners_from_dbt_resource_props(dbt_resource_props)
|
|
318
520
|
|
|
319
521
|
@public
|
|
320
|
-
|
|
522
|
+
@beta(emit_runtime_warning=False)
|
|
523
|
+
def get_auto_materialize_policy(
|
|
321
524
|
self, dbt_resource_props: Mapping[str, Any]
|
|
322
|
-
) -> Optional[
|
|
525
|
+
) -> Optional[AutoMaterializePolicy]:
|
|
323
526
|
"""A function that takes a dictionary representing properties of a dbt resource, and
|
|
324
|
-
returns the Dagster :py:class:`dagster.
|
|
527
|
+
returns the Dagster :py:class:`dagster.AutoMaterializePolicy` for that resource.
|
|
325
528
|
|
|
326
529
|
Note that a dbt resource is unrelated to Dagster's resource concept, and simply represents
|
|
327
530
|
a model, seed, snapshot or source in a given dbt project. You can learn more about dbt
|
|
328
531
|
resources and the properties available in this dictionary here:
|
|
329
532
|
https://docs.getdbt.com/reference/artifacts/manifest-json#resource-details
|
|
330
533
|
|
|
331
|
-
This method can be overridden to provide a custom
|
|
534
|
+
This method can be overridden to provide a custom auto-materialize policy for a dbt resource.
|
|
332
535
|
|
|
333
536
|
Args:
|
|
334
537
|
dbt_resource_props (Mapping[str, Any]): A dictionary representing the dbt resource.
|
|
335
538
|
|
|
336
539
|
Returns:
|
|
337
|
-
Optional[
|
|
540
|
+
Optional[AutoMaterializePolicy]: A Dagster auto-materialize policy.
|
|
338
541
|
|
|
339
542
|
Examples:
|
|
340
|
-
Set a custom
|
|
543
|
+
Set a custom auto-materialize policy for all dbt resources:
|
|
341
544
|
|
|
342
545
|
.. code-block:: python
|
|
343
546
|
|
|
@@ -347,10 +550,10 @@ class DagsterDbtTranslator:
|
|
|
347
550
|
|
|
348
551
|
|
|
349
552
|
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
350
|
-
def
|
|
351
|
-
return
|
|
553
|
+
def get_auto_materialize_policy(self, dbt_resource_props: Mapping[str, Any]) -> Optional[AutoMaterializePolicy]:
|
|
554
|
+
return AutoMaterializePolicy.eager()
|
|
352
555
|
|
|
353
|
-
Set a custom
|
|
556
|
+
Set a custom auto-materialize policy for dbt resources with a specific tag:
|
|
354
557
|
|
|
355
558
|
.. code-block:: python
|
|
356
559
|
|
|
@@ -360,19 +563,21 @@ class DagsterDbtTranslator:
|
|
|
360
563
|
|
|
361
564
|
|
|
362
565
|
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
363
|
-
def
|
|
364
|
-
|
|
566
|
+
def get_auto_materialize_policy(self, dbt_resource_props: Mapping[str, Any]) -> Optional[AutoMaterializePolicy]:
|
|
567
|
+
auto_materialize_policy = None
|
|
365
568
|
if "my_custom_tag" in dbt_resource_props.get("tags", []):
|
|
366
|
-
|
|
569
|
+
auto_materialize_policy = AutoMaterializePolicy.eager()
|
|
570
|
+
|
|
571
|
+
return auto_materialize_policy
|
|
367
572
|
|
|
368
|
-
return freshness_policy
|
|
369
573
|
"""
|
|
370
|
-
return
|
|
574
|
+
return default_auto_materialize_policy_fn(dbt_resource_props)
|
|
371
575
|
|
|
372
576
|
@public
|
|
373
|
-
|
|
577
|
+
@beta(emit_runtime_warning=False)
|
|
578
|
+
def get_automation_condition(
|
|
374
579
|
self, dbt_resource_props: Mapping[str, Any]
|
|
375
|
-
) -> Optional[
|
|
580
|
+
) -> Optional[AutomationCondition]:
|
|
376
581
|
"""A function that takes a dictionary representing properties of a dbt resource, and
|
|
377
582
|
returns the Dagster :py:class:`dagster.AutoMaterializePolicy` for that resource.
|
|
378
583
|
|
|
@@ -381,7 +586,7 @@ class DagsterDbtTranslator:
|
|
|
381
586
|
resources and the properties available in this dictionary here:
|
|
382
587
|
https://docs.getdbt.com/reference/artifacts/manifest-json#resource-details
|
|
383
588
|
|
|
384
|
-
This method can be overridden to provide a custom
|
|
589
|
+
This method can be overridden to provide a custom AutomationCondition for a dbt resource.
|
|
385
590
|
|
|
386
591
|
Args:
|
|
387
592
|
dbt_resource_props (Mapping[str, Any]): A dictionary representing the dbt resource.
|
|
@@ -390,7 +595,7 @@ class DagsterDbtTranslator:
|
|
|
390
595
|
Optional[AutoMaterializePolicy]: A Dagster auto-materialize policy.
|
|
391
596
|
|
|
392
597
|
Examples:
|
|
393
|
-
Set a custom
|
|
598
|
+
Set a custom AutomationCondition for all dbt resources:
|
|
394
599
|
|
|
395
600
|
.. code-block:: python
|
|
396
601
|
|
|
@@ -400,10 +605,10 @@ class DagsterDbtTranslator:
|
|
|
400
605
|
|
|
401
606
|
|
|
402
607
|
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
403
|
-
def
|
|
404
|
-
return
|
|
608
|
+
def get_automation_condition(self, dbt_resource_props: Mapping[str, Any]) -> Optional[AutomationCondition]:
|
|
609
|
+
return AutomationCondition.eager()
|
|
405
610
|
|
|
406
|
-
Set a custom
|
|
611
|
+
Set a custom AutomationCondition for dbt resources with a specific tag:
|
|
407
612
|
|
|
408
613
|
.. code-block:: python
|
|
409
614
|
|
|
@@ -413,58 +618,58 @@ class DagsterDbtTranslator:
|
|
|
413
618
|
|
|
414
619
|
|
|
415
620
|
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
416
|
-
def
|
|
417
|
-
|
|
621
|
+
def get_automation_condition(self, dbt_resource_props: Mapping[str, Any]) -> Optional[AutomationCondition]:
|
|
622
|
+
automation_condition = None
|
|
418
623
|
if "my_custom_tag" in dbt_resource_props.get("tags", []):
|
|
419
|
-
|
|
624
|
+
automation_condition = AutomationCondition.eager()
|
|
420
625
|
|
|
421
|
-
return
|
|
626
|
+
return automation_condition
|
|
422
627
|
|
|
423
628
|
"""
|
|
424
|
-
|
|
629
|
+
auto_materialize_policy = self.get_auto_materialize_policy(dbt_resource_props)
|
|
630
|
+
return (
|
|
631
|
+
auto_materialize_policy.to_automation_condition() if auto_materialize_policy else None
|
|
632
|
+
)
|
|
425
633
|
|
|
634
|
+
def get_partitions_def(
|
|
635
|
+
self, dbt_resource_props: Mapping[str, Any]
|
|
636
|
+
) -> Optional[PartitionsDefinition]:
|
|
637
|
+
"""[INTERNAL] A function that takes a dictionary representing properties of a dbt resource, and
|
|
638
|
+
returns the Dagster :py:class:`dagster.PartitionsDefinition` for that resource.
|
|
426
639
|
|
|
427
|
-
|
|
428
|
-
"""A DagsterDbtTranslator that applies prefixes to the asset keys generated from dbt resources.
|
|
640
|
+
This method can be overridden to provide a custom PartitionsDefinition for a dbt resource.
|
|
429
641
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
seeds, snapshots, etc. This will *not* apply to dbt sources.
|
|
433
|
-
source_asset_key_prefix (Optional[Union[str, Sequence[str]]]): A prefix to apply to all dbt
|
|
434
|
-
sources.
|
|
435
|
-
"""
|
|
642
|
+
Args:
|
|
643
|
+
dbt_resource_props (Mapping[str, Any]): A dictionary representing the dbt resource.
|
|
436
644
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
asset_key_prefix: Optional[CoercibleToAssetKeyPrefix] = None,
|
|
440
|
-
source_asset_key_prefix: Optional[CoercibleToAssetKeyPrefix] = None,
|
|
441
|
-
*args,
|
|
442
|
-
**kwargs,
|
|
443
|
-
):
|
|
444
|
-
self._asset_key_prefix = (
|
|
445
|
-
check_opt_coercible_to_asset_key_prefix_param(asset_key_prefix, "asset_key_prefix")
|
|
446
|
-
or []
|
|
447
|
-
)
|
|
448
|
-
self._source_asset_key_prefix = (
|
|
449
|
-
check_opt_coercible_to_asset_key_prefix_param(
|
|
450
|
-
source_asset_key_prefix, "source_asset_key_prefix"
|
|
451
|
-
)
|
|
452
|
-
or []
|
|
453
|
-
)
|
|
645
|
+
Returns:
|
|
646
|
+
Optional[PartitionsDefinition]: A Dagster partitions definition.
|
|
454
647
|
|
|
455
|
-
|
|
648
|
+
Examples:
|
|
649
|
+
Set a custom AutomationCondition for dbt resources with a specific tag:
|
|
456
650
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
651
|
+
.. code-block:: python
|
|
652
|
+
|
|
653
|
+
from typing import Any, Mapping
|
|
654
|
+
|
|
655
|
+
from dagster import DailyPartitionsDefinition
|
|
656
|
+
from dagster_dbt import DagsterDbtTranslator
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
class CustomDagsterDbtTranslator(DagsterDbtTranslator):
|
|
660
|
+
def get_partitions_def(self, dbt_resource_props: Mapping[str, Any]) -> Optional[PartitionsDefinition]:
|
|
661
|
+
if "my_custom_tag" in dbt_resource_props.get("tags", []):
|
|
662
|
+
return DailyPartitionsDefinition(start_date="2022-01-01")
|
|
663
|
+
else:
|
|
664
|
+
return None
|
|
665
|
+
"""
|
|
666
|
+
return None
|
|
464
667
|
|
|
465
668
|
|
|
466
669
|
@dataclass
|
|
467
670
|
class DbtManifestWrapper:
|
|
671
|
+
"""Wrapper around parsed DBT manifest json to provide convenient and efficient access."""
|
|
672
|
+
|
|
468
673
|
manifest: Mapping[str, Any]
|
|
469
674
|
|
|
470
675
|
|
|
@@ -492,3 +697,41 @@ def validate_opt_translator(
|
|
|
492
697
|
" DagsterDbtTranslator."
|
|
493
698
|
),
|
|
494
699
|
)
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
def _attach_sql_model_code_reference(
|
|
703
|
+
existing_metadata: Mapping[str, Any],
|
|
704
|
+
dbt_resource_props: Mapping[str, Any],
|
|
705
|
+
project: "DbtProject",
|
|
706
|
+
) -> Mapping[str, Any]:
|
|
707
|
+
"""Pulls the SQL model location for a dbt resource and attaches it as a code reference to the
|
|
708
|
+
existing metadata.
|
|
709
|
+
"""
|
|
710
|
+
existing_references_meta = CodeReferencesMetadataSet.extract(existing_metadata)
|
|
711
|
+
references = (
|
|
712
|
+
existing_references_meta.code_references.code_references
|
|
713
|
+
if existing_references_meta.code_references
|
|
714
|
+
else []
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
if "original_file_path" not in dbt_resource_props:
|
|
718
|
+
raise DagsterInvalidDefinitionError(
|
|
719
|
+
"Cannot attach SQL model code reference because 'original_file_path' is not present"
|
|
720
|
+
" in the dbt resource properties."
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
# attempt to get root_path, which is removed from manifests in newer dbt versions
|
|
724
|
+
relative_path = Path(dbt_resource_props["original_file_path"])
|
|
725
|
+
abs_path = project.project_dir.joinpath(relative_path).resolve()
|
|
726
|
+
|
|
727
|
+
return {
|
|
728
|
+
**existing_metadata,
|
|
729
|
+
**CodeReferencesMetadataSet(
|
|
730
|
+
code_references=CodeReferencesMetadataValue(
|
|
731
|
+
code_references=[
|
|
732
|
+
*references,
|
|
733
|
+
LocalFileCodeReference(file_path=os.fspath(abs_path)),
|
|
734
|
+
],
|
|
735
|
+
)
|
|
736
|
+
),
|
|
737
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DBT_CORE_VERSION_UPPER_BOUND = "1.11"
|
dagster_dbt/dbt_manifest.py
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from functools import cache
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Union, cast
|
|
4
5
|
|
|
5
6
|
import dagster._check as check
|
|
6
7
|
import orjson
|
|
7
8
|
|
|
8
|
-
from .errors import DagsterDbtManifestNotFoundError
|
|
9
|
+
from dagster_dbt.errors import DagsterDbtManifestNotFoundError
|
|
9
10
|
|
|
10
11
|
DbtManifestParam = Union[Mapping[str, Any], str, Path]
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
@
|
|
14
|
+
@cache
|
|
14
15
|
def read_manifest_path(manifest_path: Path) -> Mapping[str, Any]:
|
|
15
16
|
"""Reads a dbt manifest path and returns the parsed JSON as a dict.
|
|
16
17
|
|
|
@@ -23,7 +24,7 @@ def read_manifest_path(manifest_path: Path) -> Mapping[str, Any]:
|
|
|
23
24
|
if not manifest_path.exists():
|
|
24
25
|
raise DagsterDbtManifestNotFoundError(f"{manifest_path} does not exist.")
|
|
25
26
|
|
|
26
|
-
return cast(Mapping[str, Any], orjson.loads(manifest_path.read_bytes()))
|
|
27
|
+
return cast("Mapping[str, Any]", orjson.loads(manifest_path.read_bytes()))
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def validate_manifest(manifest: DbtManifestParam) -> Mapping[str, Any]:
|