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.
Files changed (64) hide show
  1. dagster_dbt/__init__.py +41 -140
  2. dagster_dbt/asset_decorator.py +49 -230
  3. dagster_dbt/asset_specs.py +65 -0
  4. dagster_dbt/asset_utils.py +655 -338
  5. dagster_dbt/cli/app.py +44 -43
  6. dagster_dbt/cloud/__init__.py +6 -4
  7. dagster_dbt/cloud/asset_defs.py +119 -177
  8. dagster_dbt/cloud/cli.py +3 -4
  9. dagster_dbt/cloud/ops.py +9 -6
  10. dagster_dbt/cloud/resources.py +9 -4
  11. dagster_dbt/cloud/types.py +12 -7
  12. dagster_dbt/cloud/utils.py +186 -0
  13. dagster_dbt/cloud_v2/__init__.py +10 -0
  14. dagster_dbt/cloud_v2/asset_decorator.py +81 -0
  15. dagster_dbt/cloud_v2/cli_invocation.py +67 -0
  16. dagster_dbt/cloud_v2/client.py +438 -0
  17. dagster_dbt/cloud_v2/resources.py +462 -0
  18. dagster_dbt/cloud_v2/run_handler.py +229 -0
  19. dagster_dbt/cloud_v2/sensor_builder.py +254 -0
  20. dagster_dbt/cloud_v2/types.py +143 -0
  21. dagster_dbt/compat.py +107 -0
  22. dagster_dbt/components/__init__.py +0 -0
  23. dagster_dbt/components/dbt_project/__init__.py +0 -0
  24. dagster_dbt/components/dbt_project/component.py +545 -0
  25. dagster_dbt/components/dbt_project/scaffolder.py +65 -0
  26. dagster_dbt/core/__init__.py +0 -10
  27. dagster_dbt/core/dbt_cli_event.py +612 -0
  28. dagster_dbt/core/dbt_cli_invocation.py +474 -0
  29. dagster_dbt/core/dbt_event_iterator.py +399 -0
  30. dagster_dbt/core/resource.py +733 -0
  31. dagster_dbt/core/utils.py +14 -279
  32. dagster_dbt/dagster_dbt_translator.py +317 -74
  33. dagster_dbt/dbt_core_version.py +1 -0
  34. dagster_dbt/dbt_manifest.py +6 -5
  35. dagster_dbt/dbt_manifest_asset_selection.py +62 -22
  36. dagster_dbt/dbt_project.py +179 -40
  37. dagster_dbt/dbt_project_manager.py +173 -0
  38. dagster_dbt/dbt_version.py +0 -0
  39. dagster_dbt/errors.py +9 -84
  40. dagster_dbt/freshness_builder.py +147 -0
  41. dagster_dbt/include/pyproject.toml.jinja +21 -0
  42. dagster_dbt/include/scaffold/assets.py.jinja +1 -8
  43. dagster_dbt/include/scaffold/definitions.py.jinja +0 -15
  44. dagster_dbt/include/scaffold/project.py.jinja +1 -0
  45. dagster_dbt/include/setup.py.jinja +2 -3
  46. dagster_dbt/metadata_set.py +18 -0
  47. dagster_dbt/utils.py +136 -234
  48. dagster_dbt/version.py +1 -1
  49. dagster_dbt-0.28.4.dist-info/METADATA +47 -0
  50. dagster_dbt-0.28.4.dist-info/RECORD +59 -0
  51. {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info}/WHEEL +1 -1
  52. {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info}/entry_points.txt +3 -0
  53. {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info/licenses}/LICENSE +1 -1
  54. dagster_dbt/asset_defs.py +0 -1049
  55. dagster_dbt/core/resources.py +0 -527
  56. dagster_dbt/core/resources_v2.py +0 -1542
  57. dagster_dbt/core/types.py +0 -63
  58. dagster_dbt/dbt_resource.py +0 -220
  59. dagster_dbt/include/scaffold/constants.py.jinja +0 -21
  60. dagster_dbt/ops.py +0 -134
  61. dagster_dbt/types.py +0 -22
  62. dagster_dbt-0.23.3.dist-info/METADATA +0 -31
  63. dagster_dbt-0.23.3.dist-info/RECORD +0 -43
  64. {dagster_dbt-0.23.3.dist-info → dagster_dbt-0.28.4.dist-info}/top_level.txt +0 -0
dagster_dbt/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
- from .asset_decorator import dbt_assets as dbt_assets
2
- from .asset_utils import (
1
+ from dagster_dbt.asset_decorator import dbt_assets as dbt_assets
2
+ from dagster_dbt.asset_specs import build_dbt_asset_specs as build_dbt_asset_specs
3
+ from dagster_dbt.asset_utils import (
3
4
  build_dbt_asset_selection as build_dbt_asset_selection,
4
5
  build_schedule_from_dbt_selection as build_schedule_from_dbt_selection,
5
6
  default_group_from_dbt_resource_props as default_group_from_dbt_resource_props,
@@ -9,7 +10,7 @@ from .asset_utils import (
9
10
  get_asset_keys_by_output_name_for_source as get_asset_keys_by_output_name_for_source,
10
11
  group_from_dbt_resource_props_fallback_to_directory as group_from_dbt_resource_props_fallback_to_directory,
11
12
  )
12
- from .cloud import (
13
+ from dagster_dbt.cloud import (
13
14
  DbtCloudClientResource as DbtCloudClientResource,
14
15
  DbtCloudOutput as DbtCloudOutput,
15
16
  DbtCloudResource as DbtCloudResource,
@@ -17,25 +18,39 @@ from .cloud import (
17
18
  dbt_cloud_run_op as dbt_cloud_run_op,
18
19
  load_assets_from_dbt_cloud_job as load_assets_from_dbt_cloud_job,
19
20
  )
20
- from .core import (
21
- DbtCliEventMessage as DbtCliEventMessage,
22
- DbtCliInvocation as DbtCliInvocation,
23
- DbtCliResource as DbtCliResource,
21
+ from dagster_dbt.cloud_v2 import (
22
+ DbtCloudCredentials as DbtCloudCredentials,
23
+ DbtCloudWorkspace as DbtCloudWorkspace,
24
+ build_dbt_cloud_polling_sensor as build_dbt_cloud_polling_sensor,
25
+ dbt_cloud_assets as dbt_cloud_assets,
26
+ load_dbt_cloud_asset_specs as load_dbt_cloud_asset_specs,
27
+ load_dbt_cloud_check_specs as load_dbt_cloud_check_specs,
24
28
  )
25
- from .dagster_dbt_translator import (
29
+ from dagster_dbt.components.dbt_project.component import DbtProjectComponent as DbtProjectComponent
30
+ from dagster_dbt.core.dbt_cli_event import DbtCliEventMessage as DbtCliEventMessage
31
+ from dagster_dbt.core.dbt_cli_invocation import DbtCliInvocation as DbtCliInvocation
32
+ from dagster_dbt.core.resource import DbtCliResource as DbtCliResource
33
+ from dagster_dbt.dagster_dbt_translator import (
26
34
  DagsterDbtTranslator as DagsterDbtTranslator,
27
35
  DagsterDbtTranslatorSettings as DagsterDbtTranslatorSettings,
28
- KeyPrefixDagsterDbtTranslator as KeyPrefixDagsterDbtTranslator,
29
36
  )
30
- from .dbt_manifest_asset_selection import DbtManifestAssetSelection as DbtManifestAssetSelection
31
- from .dbt_project import DbtProject as DbtProject
32
- from .errors import (
37
+ from dagster_dbt.dbt_manifest_asset_selection import (
38
+ DbtManifestAssetSelection as DbtManifestAssetSelection,
39
+ )
40
+ from dagster_dbt.dbt_project import (
41
+ DagsterDbtProjectPreparer as DagsterDbtProjectPreparer,
42
+ DbtProject as DbtProject,
43
+ DbtProjectPreparer as DbtProjectPreparer,
44
+ )
45
+ from dagster_dbt.errors import (
33
46
  DagsterDbtCliRuntimeError as DagsterDbtCliRuntimeError,
34
- DagsterDbtCliUnexpectedOutputError as DagsterDbtCliUnexpectedOutputError,
35
47
  DagsterDbtCloudJobInvariantViolationError as DagsterDbtCloudJobInvariantViolationError,
36
48
  DagsterDbtError as DagsterDbtError,
37
49
  )
38
- from .version import __version__ as __version__
50
+ from dagster_dbt.freshness_builder import (
51
+ build_freshness_checks_from_dbt_assets as build_freshness_checks_from_dbt_assets,
52
+ )
53
+ from dagster_dbt.version import __version__ as __version__
39
54
 
40
55
  # isort: split
41
56
 
@@ -43,155 +58,41 @@ from .version import __version__ as __version__
43
58
  # ##### DYNAMIC IMPORTS
44
59
  # ########################
45
60
  import importlib
46
- from typing import TYPE_CHECKING, Any, Mapping, Sequence, Tuple
61
+ from collections.abc import Mapping, Sequence
62
+ from typing import Any, Final, Tuple # noqa: F401, UP035
47
63
 
48
64
  from dagster._annotations import deprecated
49
- from dagster._core.libraries import DagsterLibraryRegistry
50
65
  from dagster._utils.warnings import deprecation_warning
51
- from typing_extensions import Final
66
+ from dagster_shared.libraries import DagsterLibraryRegistry
67
+
68
+ from dagster_dbt.compat import DBT_PYTHON_VERSION
52
69
 
53
70
  DagsterLibraryRegistry.register("dagster-dbt", __version__)
54
71
 
55
- if TYPE_CHECKING:
56
- ##### EXAMPLE
57
- # from dagster.some.module import (
58
- # Foo as Foo,
59
- # )
60
-
61
- # isort: split
62
- ##### Deprecating DbtCliClientResource
63
- from .core import (
64
- DbtCliClientResource as DbtCliClientResource,
65
- DbtCliOutput as DbtCliOutput,
66
- dbt_cli_resource as dbt_cli_resource,
67
- )
68
- from .dbt_resource import DbtResource as DbtResource
69
- from .errors import (
70
- DagsterDbtCliFatalRuntimeError as DagsterDbtCliFatalRuntimeError,
71
- DagsterDbtCliHandledRuntimeError as DagsterDbtCliHandledRuntimeError,
72
- DagsterDbtCliOutputsNotFoundError as DagsterDbtCliOutputsNotFoundError,
73
- )
74
- from .types import DbtOutput as DbtOutput
75
-
76
- ##### Deprecating dbt ops
77
- # isort: split
78
- from .ops import (
79
- dbt_build_op as dbt_build_op,
80
- dbt_compile_op as dbt_compile_op,
81
- dbt_docs_generate_op as dbt_docs_generate_op,
82
- dbt_ls_op as dbt_ls_op,
83
- dbt_run_op as dbt_run_op,
84
- dbt_seed_op as dbt_seed_op,
85
- dbt_snapshot_op as dbt_snapshot_op,
86
- dbt_test_op as dbt_test_op,
72
+ if DBT_PYTHON_VERSION is not None:
73
+ DagsterLibraryRegistry.register(
74
+ "dbt-core", DBT_PYTHON_VERSION.base_version, is_dagster_package=False
87
75
  )
76
+ else:
77
+ DagsterLibraryRegistry.register("dbt-fusion", "unknown", is_dagster_package=False)
88
78
 
89
- ##### Deprecating load_assets_from_XXX
90
- # isort: split
91
- from .asset_defs import (
92
- load_assets_from_dbt_manifest as load_assets_from_dbt_manifest,
93
- load_assets_from_dbt_project as load_assets_from_dbt_project,
94
- )
95
79
 
96
- _DEPRECATED: Final[Mapping[str, Tuple[str, str, str]]] = {
80
+ _DEPRECATED: Final[Mapping[str, tuple[str, str, str]]] = {
97
81
  ##### EXAMPLE
98
82
  # "Foo": (
99
83
  # "dagster.some.module",
100
84
  # "1.1.0", # breaking version
101
85
  # "Use Bar instead.",
102
86
  # ),
103
- **{
104
- value: (
105
- module,
106
- "0.24.0",
107
- additional_warn_text,
108
- )
109
- for value, module, additional_warn_text in [
110
- (
111
- "DbtCliClientResource",
112
- "dagster_dbt.core",
113
- "Use DbtCliResource instead",
114
- ),
115
- ("DbtCliOutput", "dagster_dbt.core", None),
116
- (
117
- "dbt_cli_resource",
118
- "dagster_dbt.core",
119
- "Use DbtCliResource instead",
120
- ),
121
- (
122
- "DbtResource",
123
- "dagster_dbt.dbt_resource",
124
- "Use DbtCliResource instead",
125
- ),
126
- ("DagsterDbtCliFatalRuntimeError", "dagster_dbt.errors", None),
127
- ("DagsterDbtCliHandledRuntimeError", "dagster_dbt.errors", None),
128
- ("DagsterDbtCliOutputsNotFoundError", "dagster_dbt.errors", None),
129
- ("DbtOutput", "dagster_dbt.types", None),
130
- ]
131
- },
132
- **{
133
- value: (
134
- module,
135
- "0.24.0",
136
- (
137
- "Use the @dbt_assets decorator, DbtCliResource, and DagsterDbtTranslator instead.\n\n"
138
- "For examples on how to use @dbt_assets and DbtCliResource to execute commands like"
139
- " `dbt run` or `dbt build` on your dbt project, see our API docs:"
140
- " https://docs.dagster.io/_apidocs/libraries/dagster-dbt#dagster_dbt.dbt_assets.\n\n"
141
- "For examples on how to customize your dbt assets using DagsterDbtTranslator"
142
- " see the reference:"
143
- " https://docs.dagster.io/integrations/dbt/reference#understanding-asset-definition-attributes"
144
- f"{additional_text}"
145
- ),
146
- )
147
- for value, module, additional_text in [
148
- (
149
- "load_assets_from_dbt_manifest",
150
- "dagster_dbt.asset_defs",
151
- "",
152
- ),
153
- (
154
- "load_assets_from_dbt_project",
155
- "dagster_dbt.asset_defs",
156
- (
157
- ".\n\nTo generate a dbt manifest for @dbt_assets at run time using `dbt parse`,"
158
- " see the reference:"
159
- " https://docs.dagster.io/integrations/dbt/reference#loading-dbt-models-from-a-dbt-project"
160
- ),
161
- ),
162
- ]
163
- },
164
87
  }
165
88
 
166
- _DEPRECATED_WARNING: Final[Mapping[str, Tuple[str, str, str]]] = {
89
+ _DEPRECATED_WARNING: Final[Mapping[str, tuple[str, str, str]]] = {
167
90
  ##### EXAMPLE
168
91
  # "Foo": (
169
92
  # "dagster.some.module",
170
93
  # "1.1.0", # breaking version
171
94
  # "Use Bar instead.",
172
95
  # ),
173
- **{
174
- value: (
175
- module,
176
- "0.24.0",
177
- (
178
- "Use the @op decorator and DbtCliResource instead.\n\n"
179
- "For examples on how to use @op and DbtCliResource to execute commands like"
180
- " `dbt run` or `dbt build`, see our API docs:"
181
- " https://docs.dagster.io/_apidocs/libraries/dagster-dbt#dagster_dbt.DbtCliResource.cli"
182
- ),
183
- )
184
- for value, module in [
185
- ("dbt_build_op", "dagster_dbt.ops"),
186
- ("dbt_compile_op", "dagster_dbt.ops"),
187
- ("dbt_docs_generate_op", "dagster_dbt.ops"),
188
- ("dbt_ls_op", "dagster_dbt.ops"),
189
- ("dbt_run_op", "dagster_dbt.ops"),
190
- ("dbt_seed_op", "dagster_dbt.ops"),
191
- ("dbt_snapshot_op", "dagster_dbt.ops"),
192
- ("dbt_test_op", "dagster_dbt.ops"),
193
- ]
194
- },
195
96
  }
196
97
 
197
98
 
@@ -1,72 +1,48 @@
1
- from typing import (
2
- Any,
3
- Callable,
4
- Dict,
5
- FrozenSet,
6
- Mapping,
7
- Optional,
8
- Sequence,
9
- Set,
10
- Tuple,
11
- )
1
+ from collections.abc import Callable, Mapping
2
+ from typing import Any, Optional
12
3
 
13
4
  from dagster import (
14
- AssetCheckKey,
15
- AssetCheckSpec,
16
- AssetDep,
17
- AssetKey,
18
- AssetOut,
19
5
  AssetsDefinition,
20
6
  BackfillPolicy,
21
7
  DagsterInvalidDefinitionError,
22
- Nothing,
23
8
  PartitionsDefinition,
9
+ RetryPolicy,
24
10
  TimeWindowPartitionsDefinition,
25
11
  multi_asset,
26
12
  )
27
- from dagster._utils.warnings import (
28
- experimental_warning,
29
- )
13
+ from dagster._utils.warnings import suppress_dagster_warnings
30
14
 
31
- from .asset_utils import (
15
+ from dagster_dbt.asset_utils import (
32
16
  DAGSTER_DBT_EXCLUDE_METADATA_KEY,
33
- DAGSTER_DBT_MANIFEST_METADATA_KEY,
34
17
  DAGSTER_DBT_SELECT_METADATA_KEY,
35
- DAGSTER_DBT_TRANSLATOR_METADATA_KEY,
36
- default_asset_check_fn,
37
- default_code_version_fn,
38
- get_deps,
39
- has_self_dependency,
40
- )
41
- from .dagster_dbt_translator import DagsterDbtTranslator, DbtManifestWrapper, validate_translator
42
- from .dbt_manifest import DbtManifestParam, validate_manifest
43
- from .utils import (
44
- ASSET_RESOURCE_TYPES,
45
- dagster_name_fn,
46
- get_dbt_resource_props_by_dbt_unique_id_from_manifest,
47
- select_unique_ids_from_manifest,
48
- )
49
-
50
- DUPLICATE_ASSET_KEY_ERROR_MESSAGE = (
51
- "The following dbt resources are configured with identical Dagster asset keys."
52
- " Please ensure that each dbt resource generates a unique Dagster asset key."
53
- " See the reference for configuring Dagster asset keys for your dbt project:"
54
- " https://docs.dagster.io/integrations/dbt/reference#customizing-asset-keys."
18
+ DAGSTER_DBT_SELECTOR_METADATA_KEY,
19
+ DBT_DEFAULT_EXCLUDE,
20
+ DBT_DEFAULT_SELECT,
21
+ DBT_DEFAULT_SELECTOR,
22
+ build_dbt_specs,
55
23
  )
24
+ from dagster_dbt.dagster_dbt_translator import DagsterDbtTranslator, validate_translator
25
+ from dagster_dbt.dbt_manifest import DbtManifestParam, validate_manifest
26
+ from dagster_dbt.dbt_project import DbtProject
56
27
 
57
28
 
29
+ @suppress_dagster_warnings
58
30
  def dbt_assets(
59
31
  *,
60
32
  manifest: DbtManifestParam,
61
- select: str = "fqn:*",
62
- exclude: Optional[str] = None,
33
+ select: str = DBT_DEFAULT_SELECT,
34
+ exclude: Optional[str] = DBT_DEFAULT_EXCLUDE,
35
+ selector: Optional[str] = DBT_DEFAULT_SELECTOR,
63
36
  name: Optional[str] = None,
64
37
  io_manager_key: Optional[str] = None,
65
38
  partitions_def: Optional[PartitionsDefinition] = None,
66
39
  dagster_dbt_translator: Optional[DagsterDbtTranslator] = None,
67
40
  backfill_policy: Optional[BackfillPolicy] = None,
68
41
  op_tags: Optional[Mapping[str, Any]] = None,
69
- required_resource_keys: Optional[Set[str]] = None,
42
+ required_resource_keys: Optional[set[str]] = None,
43
+ project: Optional[DbtProject] = None,
44
+ retry_policy: Optional[RetryPolicy] = None,
45
+ pool: Optional[str] = None,
70
46
  ) -> Callable[[Callable[..., Any]], AssetsDefinition]:
71
47
  """Create a definition for how to compute a set of dbt resources, described by a manifest.json.
72
48
  When invoking dbt commands using :py:class:`~dagster_dbt.DbtCliResource`'s
@@ -82,6 +58,8 @@ def dbt_assets(
82
58
  to include. Defaults to ``fqn:*``.
83
59
  exclude (Optional[str]): A dbt selection string for the models in a project that you want
84
60
  to exclude. Defaults to "".
61
+ selector (Optional[str]): A dbt selector for the models in a project that you want to
62
+ include. Cannot be combined with select or exclude. Defaults to None.
85
63
  name (Optional[str]): The name of the op.
86
64
  io_manager_key (Optional[str]): The IO manager key that will be set on each of the returned
87
65
  assets. When other ops are downstream of the loaded assets, the IOManager specified
@@ -98,6 +76,12 @@ def dbt_assets(
98
76
  are not strings will be json encoded and must meet the criteria that
99
77
  `json.loads(json.dumps(value)) == value`.
100
78
  required_resource_keys (Optional[Set[str]]): Set of required resource handles.
79
+ project (Optional[DbtProject]): A DbtProject instance which provides a pointer to the dbt
80
+ project location and manifest. Not required, but needed to attach code references from
81
+ model code to Dagster assets.
82
+ retry_policy (Optional[RetryPolicy]): The retry policy for the op that computes the asset.
83
+ pool (Optional[str]): A string that identifies the concurrency pool that governs the dbt
84
+ assets' execution.
101
85
 
102
86
  Examples:
103
87
  Running ``dbt build`` for a dbt project:
@@ -329,26 +313,14 @@ def dbt_assets(
329
313
  dagster_dbt_translator = validate_translator(dagster_dbt_translator or DagsterDbtTranslator())
330
314
  manifest = validate_manifest(manifest)
331
315
 
332
- unique_ids = select_unique_ids_from_manifest(
333
- select=select, exclude=exclude or "", manifest_json=manifest
334
- )
335
- node_info_by_dbt_unique_id = get_dbt_resource_props_by_dbt_unique_id_from_manifest(manifest)
336
- dbt_unique_id_deps = get_deps(
337
- dbt_nodes=node_info_by_dbt_unique_id,
338
- selected_unique_ids=unique_ids,
339
- asset_resource_types=ASSET_RESOURCE_TYPES,
340
- )
341
- (
342
- deps,
343
- outs,
344
- internal_asset_deps,
345
- check_specs,
346
- ) = get_dbt_multi_asset_args(
347
- dbt_nodes=node_info_by_dbt_unique_id,
348
- dbt_unique_id_deps=dbt_unique_id_deps,
349
- io_manager_key=io_manager_key,
316
+ specs, check_specs = build_dbt_specs(
317
+ translator=dagster_dbt_translator,
350
318
  manifest=manifest,
351
- dagster_dbt_translator=dagster_dbt_translator,
319
+ select=select,
320
+ exclude=exclude or DBT_DEFAULT_EXCLUDE,
321
+ selector=selector or DBT_DEFAULT_SELECTOR,
322
+ io_manager_key=io_manager_key,
323
+ project=project,
352
324
  )
353
325
 
354
326
  if op_tags and DAGSTER_DBT_SELECT_METADATA_KEY in op_tags:
@@ -363,9 +335,16 @@ def dbt_assets(
363
335
  " with op_tags"
364
336
  )
365
337
 
338
+ if op_tags and DAGSTER_DBT_SELECTOR_METADATA_KEY in op_tags:
339
+ raise DagsterInvalidDefinitionError(
340
+ f"To specify a dbt selector, use the 'selector' argument, not '{DAGSTER_DBT_SELECTOR_METADATA_KEY}'"
341
+ " with op_tags"
342
+ )
343
+
366
344
  resolved_op_tags = {
367
345
  **({DAGSTER_DBT_SELECT_METADATA_KEY: select} if select else {}),
368
346
  **({DAGSTER_DBT_EXCLUDE_METADATA_KEY: exclude} if exclude else {}),
347
+ **({DAGSTER_DBT_SELECTOR_METADATA_KEY: selector} if selector else {}),
369
348
  **(op_tags if op_tags else {}),
370
349
  }
371
350
 
@@ -377,175 +356,15 @@ def dbt_assets(
377
356
  backfill_policy = BackfillPolicy.single_run()
378
357
 
379
358
  return multi_asset(
380
- outs=outs,
381
359
  name=name,
382
- internal_asset_deps=internal_asset_deps,
383
- deps=deps,
360
+ specs=specs,
361
+ check_specs=check_specs,
362
+ can_subset=True,
384
363
  required_resource_keys=required_resource_keys,
385
- compute_kind="dbt",
386
364
  partitions_def=partitions_def,
387
- can_subset=True,
388
365
  op_tags=resolved_op_tags,
389
- check_specs=check_specs,
390
366
  backfill_policy=backfill_policy,
367
+ retry_policy=retry_policy,
368
+ pool=pool,
369
+ allow_arbitrary_check_specs=True,
391
370
  )
392
-
393
-
394
- def get_dbt_multi_asset_args(
395
- dbt_nodes: Mapping[str, Any],
396
- dbt_unique_id_deps: Mapping[str, FrozenSet[str]],
397
- io_manager_key: Optional[str],
398
- manifest: Mapping[str, Any],
399
- dagster_dbt_translator: DagsterDbtTranslator,
400
- ) -> Tuple[
401
- Sequence[AssetDep],
402
- Dict[str, AssetOut],
403
- Dict[str, Set[AssetKey]],
404
- Sequence[AssetCheckSpec],
405
- ]:
406
- deps: Set[AssetDep] = set()
407
- outs: Dict[str, AssetOut] = {}
408
- internal_asset_deps: Dict[str, Set[AssetKey]] = {}
409
- check_specs_by_key: Dict[AssetCheckKey, AssetCheckSpec] = {}
410
-
411
- dbt_unique_id_and_resource_types_by_asset_key: Dict[AssetKey, Tuple[Set[str], Set[str]]] = {}
412
- dbt_group_resource_props_by_group_name: Dict[str, Dict[str, Any]] = {
413
- dbt_group_resource_props["name"]: dbt_group_resource_props
414
- for dbt_group_resource_props in manifest["groups"].values()
415
- }
416
-
417
- for unique_id, parent_unique_ids in dbt_unique_id_deps.items():
418
- dbt_resource_props = dbt_nodes[unique_id]
419
- dbt_group_resource_props = dbt_group_resource_props_by_group_name.get(
420
- dbt_resource_props.get("group")
421
- )
422
-
423
- output_name = dagster_name_fn(dbt_resource_props)
424
- asset_key = dagster_dbt_translator.get_asset_key(dbt_resource_props)
425
-
426
- unique_ids_for_asset_key, resource_types_for_asset_key = (
427
- dbt_unique_id_and_resource_types_by_asset_key.setdefault(asset_key, (set(), set()))
428
- )
429
- unique_ids_for_asset_key.add(unique_id)
430
- resource_types_for_asset_key.add(dbt_resource_props["resource_type"])
431
-
432
- outs[output_name] = AssetOut(
433
- key=asset_key,
434
- dagster_type=Nothing,
435
- io_manager_key=io_manager_key,
436
- description=dagster_dbt_translator.get_description(dbt_resource_props),
437
- is_required=False,
438
- metadata={
439
- **dagster_dbt_translator.get_metadata(dbt_resource_props),
440
- DAGSTER_DBT_MANIFEST_METADATA_KEY: DbtManifestWrapper(manifest=manifest),
441
- DAGSTER_DBT_TRANSLATOR_METADATA_KEY: dagster_dbt_translator,
442
- },
443
- owners=dagster_dbt_translator.get_owners(
444
- {
445
- **dbt_resource_props,
446
- **({"group": dbt_group_resource_props} if dbt_group_resource_props else {}),
447
- }
448
- ),
449
- tags=dagster_dbt_translator.get_tags(dbt_resource_props),
450
- group_name=dagster_dbt_translator.get_group_name(dbt_resource_props),
451
- code_version=default_code_version_fn(dbt_resource_props),
452
- freshness_policy=dagster_dbt_translator.get_freshness_policy(dbt_resource_props),
453
- auto_materialize_policy=dagster_dbt_translator.get_auto_materialize_policy(
454
- dbt_resource_props
455
- ),
456
- )
457
-
458
- test_unique_ids = [
459
- child_unique_id
460
- for child_unique_id in manifest["child_map"][unique_id]
461
- if child_unique_id.startswith("test")
462
- ]
463
- for test_unique_id in test_unique_ids:
464
- check_spec = default_asset_check_fn(
465
- manifest, dbt_nodes, dagster_dbt_translator, asset_key, test_unique_id
466
- )
467
- if check_spec:
468
- check_specs_by_key[check_spec.key] = check_spec
469
-
470
- # Translate parent unique ids to dependencies
471
- output_internal_deps = internal_asset_deps.setdefault(output_name, set())
472
- for parent_unique_id in parent_unique_ids:
473
- dbt_parent_resource_props = dbt_nodes[parent_unique_id]
474
- parent_asset_key = dagster_dbt_translator.get_asset_key(dbt_parent_resource_props)
475
- parent_partition_mapping = dagster_dbt_translator.get_partition_mapping(
476
- dbt_resource_props,
477
- dbt_parent_resource_props=dbt_parent_resource_props,
478
- )
479
-
480
- parent_unique_ids_for_asset_key, parent_resource_types_for_asset_key = (
481
- dbt_unique_id_and_resource_types_by_asset_key.setdefault(
482
- parent_asset_key, (set(), set())
483
- )
484
- )
485
- parent_unique_ids_for_asset_key.add(parent_unique_id)
486
- parent_resource_types_for_asset_key.add(dbt_parent_resource_props["resource_type"])
487
-
488
- if parent_partition_mapping:
489
- experimental_warning("DagsterDbtTranslator.get_partition_mapping")
490
-
491
- # Add this parent as an internal dependency
492
- output_internal_deps.add(parent_asset_key)
493
-
494
- # Mark this parent as an input if it has no dependencies
495
- if parent_unique_id not in dbt_unique_id_deps:
496
- deps.add(
497
- AssetDep(
498
- asset=parent_asset_key,
499
- partition_mapping=parent_partition_mapping,
500
- )
501
- )
502
-
503
- self_partition_mapping = dagster_dbt_translator.get_partition_mapping(
504
- dbt_resource_props,
505
- dbt_parent_resource_props=dbt_resource_props,
506
- )
507
- if self_partition_mapping and has_self_dependency(dbt_resource_props):
508
- experimental_warning("+meta.dagster.has_self_dependency")
509
-
510
- deps.add(
511
- AssetDep(
512
- asset=asset_key,
513
- partition_mapping=self_partition_mapping,
514
- )
515
- )
516
- output_internal_deps.add(asset_key)
517
-
518
- dbt_unique_ids_by_duplicate_asset_key = {
519
- asset_key: sorted(unique_ids)
520
- for asset_key, (
521
- unique_ids,
522
- resource_types,
523
- ) in dbt_unique_id_and_resource_types_by_asset_key.items()
524
- if len(unique_ids) != 1
525
- and not (
526
- resource_types == set(["source"])
527
- and dagster_dbt_translator.settings.enable_duplicate_source_asset_keys
528
- )
529
- }
530
- if dbt_unique_ids_by_duplicate_asset_key:
531
- error_messages = []
532
- for asset_key, unique_ids in dbt_unique_ids_by_duplicate_asset_key.items():
533
- formatted_ids = []
534
- for id in unique_ids:
535
- unique_id_file_path = dbt_nodes[id]["original_file_path"]
536
- formatted_ids.append(f" - `{id}` ({unique_id_file_path})")
537
-
538
- error_messages.append(
539
- "\n".join(
540
- [
541
- f"The following dbt resources have the asset key `{asset_key.path}`:",
542
- *formatted_ids,
543
- ]
544
- )
545
- )
546
-
547
- raise DagsterInvalidDefinitionError(
548
- "\n\n".join([DUPLICATE_ASSET_KEY_ERROR_MESSAGE, *error_messages])
549
- )
550
-
551
- return list(deps), outs, internal_asset_deps, list(check_specs_by_key.values())
@@ -0,0 +1,65 @@
1
+ from collections.abc import Sequence
2
+ from typing import Optional
3
+
4
+ from dagster import AssetSpec
5
+
6
+ from dagster_dbt.asset_utils import (
7
+ DBT_DEFAULT_EXCLUDE,
8
+ DBT_DEFAULT_SELECT,
9
+ DBT_DEFAULT_SELECTOR,
10
+ build_dbt_specs,
11
+ )
12
+ from dagster_dbt.dagster_dbt_translator import DagsterDbtTranslator, validate_translator
13
+ from dagster_dbt.dbt_manifest import DbtManifestParam, validate_manifest
14
+ from dagster_dbt.dbt_project import DbtProject
15
+
16
+
17
+ def build_dbt_asset_specs(
18
+ *,
19
+ manifest: DbtManifestParam,
20
+ dagster_dbt_translator: Optional[DagsterDbtTranslator] = None,
21
+ select: str = DBT_DEFAULT_SELECT,
22
+ exclude: Optional[str] = DBT_DEFAULT_EXCLUDE,
23
+ selector: Optional[str] = DBT_DEFAULT_SELECTOR,
24
+ project: Optional[DbtProject] = None,
25
+ ) -> Sequence[AssetSpec]:
26
+ """Build a list of asset specs from a set of dbt resources selected from a dbt manifest.
27
+
28
+ Args:
29
+ manifest (Union[Mapping[str, Any], str, Path]): The contents of a manifest.json file
30
+ or the path to a manifest.json file. A manifest.json contains a representation of a
31
+ dbt project (models, tests, macros, etc). We use this representation to create
32
+ corresponding Dagster asset specs.
33
+ dagster_dbt_translator (Optional[DagsterDbtTranslator]): Allows customizing how to map
34
+ dbt models, seeds, etc. to asset keys and asset metadata.
35
+ select (str): A dbt selection string for the models in a project that you want
36
+ to include. Defaults to ``fqn:*``.
37
+ exclude (Optional[str]): A dbt selection string for the models in a project that you want
38
+ to exclude. Defaults to "".
39
+ selector (Optional[str]): A dbt selector for the models in a project that you want
40
+ to include. Defaults to None.
41
+ project (Optional[DbtProject]): A DbtProject instance which provides a pointer to the dbt
42
+ project location and manifest. Not required, but needed to attach code references from
43
+ model code to Dagster assets.
44
+
45
+ Returns:
46
+ Sequence[AssetSpec]: A list of asset specs.
47
+ """
48
+ manifest = validate_manifest(manifest)
49
+ dagster_dbt_translator = validate_translator(dagster_dbt_translator or DagsterDbtTranslator())
50
+
51
+ specs, _ = build_dbt_specs(
52
+ manifest=manifest,
53
+ translator=dagster_dbt_translator,
54
+ select=select,
55
+ exclude=exclude or DBT_DEFAULT_EXCLUDE,
56
+ selector=selector or DBT_DEFAULT_SELECTOR,
57
+ io_manager_key=None,
58
+ project=project,
59
+ )
60
+
61
+ return [
62
+ # Allow specs to be represented as external assets by adhering to external asset invariants.
63
+ spec.replace_attributes(skippable=False, code_version=None)
64
+ for spec in specs
65
+ ]