dagster-dbt 0.28.10__py3-none-any.whl → 0.28.12__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/asset_utils.py +55 -7
- dagster_dbt/cli/app.py +1 -1
- dagster_dbt/cloud/asset_defs.py +10 -1
- dagster_dbt/dagster_dbt_translator.py +9 -0
- dagster_dbt/utils.py +16 -1
- dagster_dbt/version.py +1 -1
- {dagster_dbt-0.28.10.dist-info → dagster_dbt-0.28.12.dist-info}/METADATA +2 -2
- {dagster_dbt-0.28.10.dist-info → dagster_dbt-0.28.12.dist-info}/RECORD +12 -12
- {dagster_dbt-0.28.10.dist-info → dagster_dbt-0.28.12.dist-info}/WHEEL +1 -1
- {dagster_dbt-0.28.10.dist-info → dagster_dbt-0.28.12.dist-info}/entry_points.txt +0 -0
- {dagster_dbt-0.28.10.dist-info → dagster_dbt-0.28.12.dist-info}/licenses/LICENSE +0 -0
- {dagster_dbt-0.28.10.dist-info → dagster_dbt-0.28.12.dist-info}/top_level.txt +0 -0
dagster_dbt/asset_utils.py
CHANGED
|
@@ -63,6 +63,42 @@ DBT_EMPTY_INDIRECT_SELECTION: Final[str] = "empty"
|
|
|
63
63
|
# https://github.com/dagster-io/dagster/issues/16997
|
|
64
64
|
_SELECTION_ARGS_THRESHOLD: Final[int] = 200
|
|
65
65
|
|
|
66
|
+
|
|
67
|
+
def _parse_selection_args(
|
|
68
|
+
selection_args: list[str],
|
|
69
|
+
) -> tuple[Optional[list[str]], Optional[list[str]]]:
|
|
70
|
+
"""Parse selection args into separate select and exclude resource lists.
|
|
71
|
+
|
|
72
|
+
This function is designed for dagster-dbt's internal argument format, where select/exclude
|
|
73
|
+
values are passed as a single space-separated string (e.g., ["--select", "model1 model2"]).
|
|
74
|
+
This matches how dagster-dbt constructs these arguments in get_subset_selection_for_context.
|
|
75
|
+
It does not handle the dbt CLI's alternative format of multiple --select flags.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
selection_args: CLI arguments in dagster-dbt's internal format,
|
|
79
|
+
e.g., ["--select", "model1 model2", "--exclude", "model3"]
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Tuple of (select_resources, exclude_resources) where each is a list of resource names
|
|
83
|
+
or None if not present.
|
|
84
|
+
"""
|
|
85
|
+
select_resources: Optional[list[str]] = None
|
|
86
|
+
exclude_resources: Optional[list[str]] = None
|
|
87
|
+
|
|
88
|
+
i = 0
|
|
89
|
+
while i < len(selection_args):
|
|
90
|
+
if selection_args[i] == "--select" and i + 1 < len(selection_args):
|
|
91
|
+
select_resources = selection_args[i + 1].split(" ")
|
|
92
|
+
i += 2
|
|
93
|
+
elif selection_args[i] == "--exclude" and i + 1 < len(selection_args):
|
|
94
|
+
exclude_resources = selection_args[i + 1].split(" ")
|
|
95
|
+
i += 2
|
|
96
|
+
else:
|
|
97
|
+
i += 1
|
|
98
|
+
|
|
99
|
+
return select_resources, exclude_resources
|
|
100
|
+
|
|
101
|
+
|
|
66
102
|
DUPLICATE_ASSET_KEY_ERROR_MESSAGE = (
|
|
67
103
|
"The following dbt resources are configured with identical Dagster asset keys."
|
|
68
104
|
" Please ensure that each dbt resource generates a unique Dagster asset key."
|
|
@@ -464,11 +500,11 @@ def get_updated_cli_invocation_params_for_context(
|
|
|
464
500
|
dagster_dbt_translator=dagster_dbt_translator,
|
|
465
501
|
current_dbt_indirect_selection_env=indirect_selection,
|
|
466
502
|
)
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
503
|
+
# Parse selection args to get select and exclude resources
|
|
504
|
+
select_resources, exclude_resources = _parse_selection_args(selection_args)
|
|
505
|
+
total_resources = len(select_resources or []) + len(exclude_resources or [])
|
|
506
|
+
|
|
507
|
+
if select_resources and project_dir and total_resources > _SELECTION_ARGS_THRESHOLD:
|
|
472
508
|
temp_project_dir = tempfile.mkdtemp()
|
|
473
509
|
shutil.copytree(project_dir, temp_project_dir, dirs_exist_ok=True)
|
|
474
510
|
selectors_path = Path(temp_project_dir) / "selectors.yml"
|
|
@@ -478,17 +514,25 @@ def get_updated_cli_invocation_params_for_context(
|
|
|
478
514
|
selectors_path.unlink()
|
|
479
515
|
|
|
480
516
|
selector_name = f"dagster_run_{context.run_id}"
|
|
517
|
+
# Build selector definition with union of selected resources
|
|
518
|
+
# and optional exclude section nested inside the union
|
|
519
|
+
# See: https://docs.getdbt.com/reference/node-selection/yaml-selectors
|
|
520
|
+
# Note: exclude must be nested inside the union array, not a sibling key
|
|
521
|
+
union_items: list[Any] = list(select_resources)
|
|
522
|
+
if exclude_resources:
|
|
523
|
+
union_items.append({"exclude": list(exclude_resources)})
|
|
524
|
+
|
|
481
525
|
temp_selectors = {
|
|
482
526
|
"selectors": [
|
|
483
527
|
{
|
|
484
528
|
"name": selector_name,
|
|
485
|
-
"definition": {"union":
|
|
529
|
+
"definition": {"union": union_items},
|
|
486
530
|
}
|
|
487
531
|
]
|
|
488
532
|
}
|
|
489
533
|
selectors_path.write_text(yaml.safe_dump(temp_selectors))
|
|
490
534
|
logger.info(
|
|
491
|
-
f"DBT selection of {
|
|
535
|
+
f"DBT selection of {total_resources} resources exceeds threshold of {_SELECTION_ARGS_THRESHOLD}. "
|
|
492
536
|
"This may exceed system argument length limits. "
|
|
493
537
|
f"Executing materialization against temporary copy of DBT project at {temp_project_dir} with ephemeral selector."
|
|
494
538
|
)
|
|
@@ -742,6 +786,7 @@ def is_non_asset_node(dbt_resource_props: Mapping[str, Any]):
|
|
|
742
786
|
resource_type == "metric",
|
|
743
787
|
resource_type == "semantic_model",
|
|
744
788
|
resource_type == "saved_query",
|
|
789
|
+
resource_type == "function",
|
|
745
790
|
resource_type == "model"
|
|
746
791
|
and dbt_resource_props.get("config", {}).get("materialized") == "ephemeral",
|
|
747
792
|
]
|
|
@@ -1219,4 +1264,7 @@ def get_node(manifest: Mapping[str, Any], unique_id: str) -> Mapping[str, Any]:
|
|
|
1219
1264
|
if unique_id in manifest.get("unit_tests", {}):
|
|
1220
1265
|
return manifest["unit_tests"][unique_id]
|
|
1221
1266
|
|
|
1267
|
+
if unique_id in manifest.get("functions", {}):
|
|
1268
|
+
return manifest["functions"][unique_id]
|
|
1269
|
+
|
|
1222
1270
|
check.failed(f"Could not find {unique_id} in dbt manifest")
|
dagster_dbt/cli/app.py
CHANGED
|
@@ -361,7 +361,7 @@ def project_prepare_and_package_command(
|
|
|
361
361
|
f"Running with dagster-dbt version: [bold green]{dagster_dbt_version}[/bold green]."
|
|
362
362
|
)
|
|
363
363
|
if file:
|
|
364
|
-
contents = load_python_file(file, working_directory=None)
|
|
364
|
+
contents = load_python_file(file, working_directory=None, add_uuid_suffix=True)
|
|
365
365
|
dbt_projects = find_objects_in_module_of_types(contents, types=DbtProject)
|
|
366
366
|
elif components:
|
|
367
367
|
from dagster_dbt.components.dbt_project.component import get_projects_from_dbt_component
|
dagster_dbt/cloud/asset_defs.py
CHANGED
|
@@ -72,8 +72,10 @@ class DbtCloudCacheableAssetsDefinition(CacheableAssetsDefinition):
|
|
|
72
72
|
else dbt_cloud_resource_def(build_init_resource_context())
|
|
73
73
|
)
|
|
74
74
|
self._job_id = job_id
|
|
75
|
+
self._account_id: int = self._dbt_cloud._account_id # noqa: SLF001
|
|
75
76
|
self._project_id: int
|
|
76
77
|
self._has_generate_docs: bool
|
|
78
|
+
self._environment_id: Optional[int] = None
|
|
77
79
|
self._job_commands: list[str]
|
|
78
80
|
self._job_materialization_command_step: int
|
|
79
81
|
self._node_info_to_asset_key = node_info_to_asset_key
|
|
@@ -240,6 +242,7 @@ class DbtCloudCacheableAssetsDefinition(CacheableAssetsDefinition):
|
|
|
240
242
|
job = self._dbt_cloud.get_job(job_id=self._job_id)
|
|
241
243
|
self._project_id = job["project_id"]
|
|
242
244
|
self._has_generate_docs = job["generate_docs"]
|
|
245
|
+
self._environment_id = job.get("environment_id")
|
|
243
246
|
|
|
244
247
|
# We constraint the kinds of dbt Cloud jobs that we support running.
|
|
245
248
|
#
|
|
@@ -380,7 +383,7 @@ class DbtCloudCacheableAssetsDefinition(CacheableAssetsDefinition):
|
|
|
380
383
|
def _build_dbt_cloud_assets_metadata(
|
|
381
384
|
self, resource_props: Mapping[str, Any]
|
|
382
385
|
) -> RawMetadataMapping:
|
|
383
|
-
metadata = {
|
|
386
|
+
metadata: dict[str, Any] = {
|
|
384
387
|
"dbt Cloud Job": MetadataValue.url(
|
|
385
388
|
self._dbt_cloud.build_url_for_job(
|
|
386
389
|
project_id=self._project_id,
|
|
@@ -398,6 +401,12 @@ class DbtCloudCacheableAssetsDefinition(CacheableAssetsDefinition):
|
|
|
398
401
|
)
|
|
399
402
|
)
|
|
400
403
|
|
|
404
|
+
# Add internal metadata for tracking/debugging
|
|
405
|
+
metadata["dagster_dbt/cloud_account_id"] = MetadataValue.int(self._account_id)
|
|
406
|
+
metadata["dagster_dbt/cloud_project_id"] = MetadataValue.int(self._project_id)
|
|
407
|
+
if self._environment_id is not None:
|
|
408
|
+
metadata["dagster_dbt/cloud_environment_id"] = MetadataValue.int(self._environment_id)
|
|
409
|
+
|
|
401
410
|
return metadata
|
|
402
411
|
|
|
403
412
|
def _rebuild_specs(self, cacheable_data: AssetsDefinitionCacheableData) -> Sequence[AssetSpec]:
|
|
@@ -12,6 +12,7 @@ from dagster import (
|
|
|
12
12
|
AutoMaterializePolicy,
|
|
13
13
|
AutomationCondition,
|
|
14
14
|
DagsterInvalidDefinitionError,
|
|
15
|
+
MetadataValue,
|
|
15
16
|
PartitionMapping,
|
|
16
17
|
)
|
|
17
18
|
from dagster._annotations import beta, public
|
|
@@ -210,6 +211,14 @@ class DagsterDbtTranslator:
|
|
|
210
211
|
**({DAGSTER_DBT_PROJECT_METADATA_KEY: project} if project else {}),
|
|
211
212
|
}
|
|
212
213
|
)
|
|
214
|
+
|
|
215
|
+
# Add dbt Core project_id for tracking/debugging
|
|
216
|
+
project_id = manifest.get("metadata", {}).get("project_id")
|
|
217
|
+
if project_id:
|
|
218
|
+
spec = spec.merge_attributes(
|
|
219
|
+
metadata={"dagster_dbt/project_id": MetadataValue.text(project_id)}
|
|
220
|
+
)
|
|
221
|
+
|
|
213
222
|
if self.settings.enable_code_references:
|
|
214
223
|
if not project:
|
|
215
224
|
raise DagsterInvalidDefinitionError(
|
dagster_dbt/utils.py
CHANGED
|
@@ -16,7 +16,6 @@ if TYPE_CHECKING:
|
|
|
16
16
|
# dbt resource types that may be considered assets
|
|
17
17
|
ASSET_RESOURCE_TYPES = ["model", "seed", "snapshot"]
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
clean_name = clean_name_lower
|
|
21
20
|
|
|
22
21
|
|
|
@@ -135,6 +134,21 @@ def _select_unique_ids_from_manifest(
|
|
|
135
134
|
else {}
|
|
136
135
|
)
|
|
137
136
|
|
|
137
|
+
functions = {}
|
|
138
|
+
if DBT_PYTHON_VERSION is not None and DBT_PYTHON_VERSION >= version.parse("1.11.0"):
|
|
139
|
+
from dbt.contracts.graph.nodes import FunctionNode # pyright: ignore
|
|
140
|
+
|
|
141
|
+
functions = (
|
|
142
|
+
{
|
|
143
|
+
"functions": {
|
|
144
|
+
unique_id: FunctionNode.from_dict(info)
|
|
145
|
+
for unique_id, info in manifest_json["functions"].items()
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if manifest_json.get("functions")
|
|
149
|
+
else {}
|
|
150
|
+
)
|
|
151
|
+
|
|
138
152
|
manifest = Manifest(
|
|
139
153
|
nodes={unique_id: _DictShim(info) for unique_id, info in manifest_json["nodes"].items()},
|
|
140
154
|
sources={
|
|
@@ -182,6 +196,7 @@ def _select_unique_ids_from_manifest(
|
|
|
182
196
|
else {}
|
|
183
197
|
),
|
|
184
198
|
**unit_tests,
|
|
199
|
+
**functions,
|
|
185
200
|
)
|
|
186
201
|
|
|
187
202
|
child_map = manifest_json["child_map"]
|
dagster_dbt/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.28.
|
|
1
|
+
__version__ = "0.28.12"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dagster-dbt
|
|
3
|
-
Version: 0.28.
|
|
3
|
+
Version: 0.28.12
|
|
4
4
|
Summary: A Dagster integration for dbt
|
|
5
5
|
Home-page: https://github.com/dagster-io/dagster/tree/master/python_modules/libraries/dagster-dbt
|
|
6
6
|
Author: Dagster Labs
|
|
@@ -15,7 +15,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Requires-Python: >=3.10,<3.14
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: dagster==1.12.
|
|
18
|
+
Requires-Dist: dagster==1.12.12
|
|
19
19
|
Requires-Dist: dbt-core<1.12,>=1.7
|
|
20
20
|
Requires-Dist: gitpython
|
|
21
21
|
Requires-Dist: Jinja2
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
dagster_dbt/__init__.py,sha256=rlPCxCzovXNDiqXBUEcgNVHjZrXQXwcX3kwUhe_69C4,4708
|
|
2
2
|
dagster_dbt/asset_decorator.py,sha256=OFFjhmDQO6dK8N3U7VQF7gergswkIS3eHnMRwAe2BZY,14892
|
|
3
3
|
dagster_dbt/asset_specs.py,sha256=2EdWIhY2QZhtGXM7N-kkkeK3ClnGgYX7ayRi_X11cLg,2741
|
|
4
|
-
dagster_dbt/asset_utils.py,sha256=
|
|
4
|
+
dagster_dbt/asset_utils.py,sha256=eTX8vvbKwxYqRLlGmTzbTsu4oOsNgNLU9d0vgFA7P6M,48962
|
|
5
5
|
dagster_dbt/compat.py,sha256=lqzGonzQE7Lb825yRqUaQPXeNQp8umAR4LqyD6COXdc,3609
|
|
6
|
-
dagster_dbt/dagster_dbt_translator.py,sha256=
|
|
6
|
+
dagster_dbt/dagster_dbt_translator.py,sha256=ZoDlIhHQk9ka8yyx8f2Z6XTTf2E7dvbrmHLuyMBBvus,31143
|
|
7
7
|
dagster_dbt/dbt_core_version.py,sha256=Xbygc8qrDnhUhicD0KRRry6YRi3W5ztB2VxKmcxPXeA,38
|
|
8
8
|
dagster_dbt/dbt_manifest.py,sha256=q10Qq1whh-dLfWtFbTYXYbqBVCf0oU8T1yRPyy9ASw0,1307
|
|
9
9
|
dagster_dbt/dbt_manifest_asset_selection.py,sha256=KSEHcVdtfFZaEqSQDUsAx8H8BQe62jZxAOE_CLtwVlI,5072
|
|
@@ -14,12 +14,12 @@ dagster_dbt/errors.py,sha256=a8xag0tjh8OQVkiL10_uwY4hkAgRCH6HtTGaZxIbXZI,1073
|
|
|
14
14
|
dagster_dbt/freshness_builder.py,sha256=DHAC3AGWAwIA7psDf72R0t5p8NjxDytGU9g5xnca1hc,6395
|
|
15
15
|
dagster_dbt/metadata_set.py,sha256=lqjASYoYeM_Ey6r8UsPUkRMwmuAIfFCFvkNm0xW5xTg,512
|
|
16
16
|
dagster_dbt/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
|
17
|
-
dagster_dbt/utils.py,sha256=
|
|
18
|
-
dagster_dbt/version.py,sha256=
|
|
17
|
+
dagster_dbt/utils.py,sha256=AMSksIptEBr6aMLv0DEj1pjMMl_BRTLqXvBnkgAeJhg,9034
|
|
18
|
+
dagster_dbt/version.py,sha256=1WEy1K1rD5aYOP4qevjehq-uhsiK733U8NKj3tvYXW4,24
|
|
19
19
|
dagster_dbt/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
dagster_dbt/cli/app.py,sha256=
|
|
20
|
+
dagster_dbt/cli/app.py,sha256=yQ4OqtUOIsAIzjU2QaI4lcWXWVhBW5_ajqsjQr8TBws,13538
|
|
21
21
|
dagster_dbt/cloud/__init__.py,sha256=8WKaLuPl_pUG9Cv78GW782vrWQfqK8QtAWegkTxA9r4,441
|
|
22
|
-
dagster_dbt/cloud/asset_defs.py,sha256=
|
|
22
|
+
dagster_dbt/cloud/asset_defs.py,sha256=CcEiNeOz8JO4tRzSxKHPYKLFzZgsnUvUH-NV6DLJ7UA,29885
|
|
23
23
|
dagster_dbt/cloud/cli.py,sha256=VnKzBjn-BPpjn4nPZm5xSrboAKpRhlCa-4IxsN1ROCo,4525
|
|
24
24
|
dagster_dbt/cloud/ops.py,sha256=rsU4qPCRUUzeHRInZph7YEz_iynwu_KidO5vMAYHX5E,4615
|
|
25
25
|
dagster_dbt/cloud/resources.py,sha256=AWW3VTBS6zrSKeDjMJovbnu54sKena93FoZle6ZSSq8,31747
|
|
@@ -51,9 +51,9 @@ dagster_dbt/include/scaffold/assets.py.jinja,sha256=JImqnDUP5ewy8RVti4IuXL70yJno
|
|
|
51
51
|
dagster_dbt/include/scaffold/definitions.py.jinja,sha256=Hou7emwkEeh5YXTdqjYFrAc2SK-Q6MgTNsQOKA_Vy3s,364
|
|
52
52
|
dagster_dbt/include/scaffold/project.py.jinja,sha256=YNtkT5Hq4VbGw-b7QcxdelhXsesIKORwVuBFGFdfeUs,432
|
|
53
53
|
dagster_dbt/include/scaffold/schedules.py.jinja,sha256=Xua_VtPjYFc498A5uaBGQ36GwV1gqciO4P3D8Yt9M-Y,413
|
|
54
|
-
dagster_dbt-0.28.
|
|
55
|
-
dagster_dbt-0.28.
|
|
56
|
-
dagster_dbt-0.28.
|
|
57
|
-
dagster_dbt-0.28.
|
|
58
|
-
dagster_dbt-0.28.
|
|
59
|
-
dagster_dbt-0.28.
|
|
54
|
+
dagster_dbt-0.28.12.dist-info/licenses/LICENSE,sha256=4lsMW-RCvfVD4_F57wrmpe3vX1xwUk_OAKKmV_XT7Z0,11348
|
|
55
|
+
dagster_dbt-0.28.12.dist-info/METADATA,sha256=CuD3sObsVXUPC9vKXzTSJgFwuNY822MJhppeo8XA_Bo,1632
|
|
56
|
+
dagster_dbt-0.28.12.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
57
|
+
dagster_dbt-0.28.12.dist-info/entry_points.txt,sha256=pbv0tVoTB7cByG-noE8rC6atvthh64qBaTo7PkQ9HbM,163
|
|
58
|
+
dagster_dbt-0.28.12.dist-info/top_level.txt,sha256=hoOwFvw9OpJUN1azE6UVHcxMKqhUwR_BTN0Ay-iKUDA,12
|
|
59
|
+
dagster_dbt-0.28.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|