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.
@@ -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
- if (
468
- selection_args[0] == "--select"
469
- and project_dir
470
- and len(resources := selection_args[1].split(" ")) > _SELECTION_ARGS_THRESHOLD
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": list(resources)},
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 {len(resources)} resources exceeds threshold of {_SELECTION_ARGS_THRESHOLD}. "
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
@@ -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.10"
1
+ __version__ = "0.28.12"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dagster-dbt
3
- Version: 0.28.10
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.10
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=xS2gAWRdVlHnYkc5iu-ppf6dpdz_OHspeg9g_gc14fs,46790
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=HnXtw9UgUMrrPDUrJ8__kMtOrYDHVz4jCBVXl_VbdHM,30834
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=gT6xO7buRolkhc2fa5ySUPfD1eXo3e6RJWZAKkM6yFo,8513
18
- dagster_dbt/version.py,sha256=110BPTEyn13PDWnHpj0D7VMBpjnNxJ6-MM3ZHvQwyQ0,24
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=9oBx85uzAkMtBdV39vNm5rxuAGPVYzzDUs6Ek-KL0XY,13516
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=4mdXd3tiGd9OPBBF6xvH81DZhcyGL9pAw3WH8dB7Qu8,29311
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.10.dist-info/licenses/LICENSE,sha256=4lsMW-RCvfVD4_F57wrmpe3vX1xwUk_OAKKmV_XT7Z0,11348
55
- dagster_dbt-0.28.10.dist-info/METADATA,sha256=dsDUeemD81OMLqjg0MlSA7Asy0JLjhdoJVPHxLwHNJ8,1632
56
- dagster_dbt-0.28.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
57
- dagster_dbt-0.28.10.dist-info/entry_points.txt,sha256=pbv0tVoTB7cByG-noE8rC6atvthh64qBaTo7PkQ9HbM,163
58
- dagster_dbt-0.28.10.dist-info/top_level.txt,sha256=hoOwFvw9OpJUN1azE6UVHcxMKqhUwR_BTN0Ay-iKUDA,12
59
- dagster_dbt-0.28.10.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5