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.

Potentially problematic release.


This version of dvt-core might be problematic. Click here for more details.

Files changed (275) hide show
  1. dbt/__init__.py +7 -0
  2. dbt/_pydantic_shim.py +26 -0
  3. dbt/artifacts/__init__.py +0 -0
  4. dbt/artifacts/exceptions/__init__.py +1 -0
  5. dbt/artifacts/exceptions/schemas.py +31 -0
  6. dbt/artifacts/resources/__init__.py +116 -0
  7. dbt/artifacts/resources/base.py +67 -0
  8. dbt/artifacts/resources/types.py +93 -0
  9. dbt/artifacts/resources/v1/analysis.py +10 -0
  10. dbt/artifacts/resources/v1/catalog.py +23 -0
  11. dbt/artifacts/resources/v1/components.py +274 -0
  12. dbt/artifacts/resources/v1/config.py +277 -0
  13. dbt/artifacts/resources/v1/documentation.py +11 -0
  14. dbt/artifacts/resources/v1/exposure.py +51 -0
  15. dbt/artifacts/resources/v1/function.py +52 -0
  16. dbt/artifacts/resources/v1/generic_test.py +31 -0
  17. dbt/artifacts/resources/v1/group.py +21 -0
  18. dbt/artifacts/resources/v1/hook.py +11 -0
  19. dbt/artifacts/resources/v1/macro.py +29 -0
  20. dbt/artifacts/resources/v1/metric.py +172 -0
  21. dbt/artifacts/resources/v1/model.py +145 -0
  22. dbt/artifacts/resources/v1/owner.py +10 -0
  23. dbt/artifacts/resources/v1/saved_query.py +111 -0
  24. dbt/artifacts/resources/v1/seed.py +41 -0
  25. dbt/artifacts/resources/v1/semantic_layer_components.py +72 -0
  26. dbt/artifacts/resources/v1/semantic_model.py +314 -0
  27. dbt/artifacts/resources/v1/singular_test.py +14 -0
  28. dbt/artifacts/resources/v1/snapshot.py +91 -0
  29. dbt/artifacts/resources/v1/source_definition.py +84 -0
  30. dbt/artifacts/resources/v1/sql_operation.py +10 -0
  31. dbt/artifacts/resources/v1/unit_test_definition.py +77 -0
  32. dbt/artifacts/schemas/__init__.py +0 -0
  33. dbt/artifacts/schemas/base.py +191 -0
  34. dbt/artifacts/schemas/batch_results.py +24 -0
  35. dbt/artifacts/schemas/catalog/__init__.py +11 -0
  36. dbt/artifacts/schemas/catalog/v1/__init__.py +0 -0
  37. dbt/artifacts/schemas/catalog/v1/catalog.py +59 -0
  38. dbt/artifacts/schemas/freshness/__init__.py +1 -0
  39. dbt/artifacts/schemas/freshness/v3/__init__.py +0 -0
  40. dbt/artifacts/schemas/freshness/v3/freshness.py +158 -0
  41. dbt/artifacts/schemas/manifest/__init__.py +2 -0
  42. dbt/artifacts/schemas/manifest/v12/__init__.py +0 -0
  43. dbt/artifacts/schemas/manifest/v12/manifest.py +211 -0
  44. dbt/artifacts/schemas/results.py +147 -0
  45. dbt/artifacts/schemas/run/__init__.py +2 -0
  46. dbt/artifacts/schemas/run/v5/__init__.py +0 -0
  47. dbt/artifacts/schemas/run/v5/run.py +184 -0
  48. dbt/artifacts/schemas/upgrades/__init__.py +4 -0
  49. dbt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
  50. dbt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
  51. dbt/artifacts/utils/validation.py +153 -0
  52. dbt/cli/__init__.py +1 -0
  53. dbt/cli/context.py +17 -0
  54. dbt/cli/exceptions.py +57 -0
  55. dbt/cli/flags.py +560 -0
  56. dbt/cli/main.py +2039 -0
  57. dbt/cli/option_types.py +121 -0
  58. dbt/cli/options.py +80 -0
  59. dbt/cli/params.py +804 -0
  60. dbt/cli/requires.py +490 -0
  61. dbt/cli/resolvers.py +50 -0
  62. dbt/cli/types.py +40 -0
  63. dbt/clients/__init__.py +0 -0
  64. dbt/clients/checked_load.py +83 -0
  65. dbt/clients/git.py +164 -0
  66. dbt/clients/jinja.py +206 -0
  67. dbt/clients/jinja_static.py +245 -0
  68. dbt/clients/registry.py +192 -0
  69. dbt/clients/yaml_helper.py +68 -0
  70. dbt/compilation.py +876 -0
  71. dbt/compute/__init__.py +14 -0
  72. dbt/compute/engines/__init__.py +12 -0
  73. dbt/compute/engines/spark_engine.py +624 -0
  74. dbt/compute/federated_executor.py +837 -0
  75. dbt/compute/filter_pushdown.cpython-310-darwin.so +0 -0
  76. dbt/compute/filter_pushdown.py +273 -0
  77. dbt/compute/jar_provisioning.cpython-310-darwin.so +0 -0
  78. dbt/compute/jar_provisioning.py +255 -0
  79. dbt/compute/java_compat.cpython-310-darwin.so +0 -0
  80. dbt/compute/java_compat.py +689 -0
  81. dbt/compute/jdbc_utils.cpython-310-darwin.so +0 -0
  82. dbt/compute/jdbc_utils.py +678 -0
  83. dbt/compute/smart_selector.cpython-310-darwin.so +0 -0
  84. dbt/compute/smart_selector.py +311 -0
  85. dbt/compute/strategies/__init__.py +54 -0
  86. dbt/compute/strategies/base.py +165 -0
  87. dbt/compute/strategies/dataproc.py +207 -0
  88. dbt/compute/strategies/emr.py +203 -0
  89. dbt/compute/strategies/local.py +364 -0
  90. dbt/compute/strategies/standalone.py +262 -0
  91. dbt/config/__init__.py +4 -0
  92. dbt/config/catalogs.py +94 -0
  93. dbt/config/compute.cpython-310-darwin.so +0 -0
  94. dbt/config/compute.py +547 -0
  95. dbt/config/dvt_profile.cpython-310-darwin.so +0 -0
  96. dbt/config/dvt_profile.py +342 -0
  97. dbt/config/profile.py +422 -0
  98. dbt/config/project.py +873 -0
  99. dbt/config/project_utils.py +28 -0
  100. dbt/config/renderer.py +231 -0
  101. dbt/config/runtime.py +553 -0
  102. dbt/config/selectors.py +208 -0
  103. dbt/config/utils.py +77 -0
  104. dbt/constants.py +28 -0
  105. dbt/context/__init__.py +0 -0
  106. dbt/context/base.py +745 -0
  107. dbt/context/configured.py +135 -0
  108. dbt/context/context_config.py +382 -0
  109. dbt/context/docs.py +82 -0
  110. dbt/context/exceptions_jinja.py +178 -0
  111. dbt/context/macro_resolver.py +195 -0
  112. dbt/context/macros.py +171 -0
  113. dbt/context/manifest.py +72 -0
  114. dbt/context/providers.py +2249 -0
  115. dbt/context/query_header.py +13 -0
  116. dbt/context/secret.py +58 -0
  117. dbt/context/target.py +74 -0
  118. dbt/contracts/__init__.py +0 -0
  119. dbt/contracts/files.py +413 -0
  120. dbt/contracts/graph/__init__.py +0 -0
  121. dbt/contracts/graph/manifest.py +1904 -0
  122. dbt/contracts/graph/metrics.py +97 -0
  123. dbt/contracts/graph/model_config.py +70 -0
  124. dbt/contracts/graph/node_args.py +42 -0
  125. dbt/contracts/graph/nodes.py +1806 -0
  126. dbt/contracts/graph/semantic_manifest.py +232 -0
  127. dbt/contracts/graph/unparsed.py +811 -0
  128. dbt/contracts/project.py +417 -0
  129. dbt/contracts/results.py +53 -0
  130. dbt/contracts/selection.py +23 -0
  131. dbt/contracts/sql.py +85 -0
  132. dbt/contracts/state.py +68 -0
  133. dbt/contracts/util.py +46 -0
  134. dbt/deprecations.py +346 -0
  135. dbt/deps/__init__.py +0 -0
  136. dbt/deps/base.py +152 -0
  137. dbt/deps/git.py +195 -0
  138. dbt/deps/local.py +79 -0
  139. dbt/deps/registry.py +130 -0
  140. dbt/deps/resolver.py +149 -0
  141. dbt/deps/tarball.py +120 -0
  142. dbt/docs/source/_ext/dbt_click.py +119 -0
  143. dbt/docs/source/conf.py +32 -0
  144. dbt/env_vars.py +64 -0
  145. dbt/event_time/event_time.py +40 -0
  146. dbt/event_time/sample_window.py +60 -0
  147. dbt/events/__init__.py +15 -0
  148. dbt/events/base_types.py +36 -0
  149. dbt/events/core_types_pb2.py +2 -0
  150. dbt/events/logging.py +108 -0
  151. dbt/events/types.py +2516 -0
  152. dbt/exceptions.py +1486 -0
  153. dbt/flags.py +89 -0
  154. dbt/graph/__init__.py +11 -0
  155. dbt/graph/cli.py +247 -0
  156. dbt/graph/graph.py +172 -0
  157. dbt/graph/queue.py +214 -0
  158. dbt/graph/selector.py +374 -0
  159. dbt/graph/selector_methods.py +975 -0
  160. dbt/graph/selector_spec.py +222 -0
  161. dbt/graph/thread_pool.py +18 -0
  162. dbt/hooks.py +21 -0
  163. dbt/include/README.md +49 -0
  164. dbt/include/__init__.py +3 -0
  165. dbt/include/starter_project/.gitignore +4 -0
  166. dbt/include/starter_project/README.md +15 -0
  167. dbt/include/starter_project/__init__.py +3 -0
  168. dbt/include/starter_project/analyses/.gitkeep +0 -0
  169. dbt/include/starter_project/dbt_project.yml +36 -0
  170. dbt/include/starter_project/macros/.gitkeep +0 -0
  171. dbt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
  172. dbt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
  173. dbt/include/starter_project/models/example/schema.yml +21 -0
  174. dbt/include/starter_project/seeds/.gitkeep +0 -0
  175. dbt/include/starter_project/snapshots/.gitkeep +0 -0
  176. dbt/include/starter_project/tests/.gitkeep +0 -0
  177. dbt/internal_deprecations.py +26 -0
  178. dbt/jsonschemas/__init__.py +3 -0
  179. dbt/jsonschemas/jsonschemas.py +309 -0
  180. dbt/jsonschemas/project/0.0.110.json +4717 -0
  181. dbt/jsonschemas/project/0.0.85.json +2015 -0
  182. dbt/jsonschemas/resources/0.0.110.json +2636 -0
  183. dbt/jsonschemas/resources/0.0.85.json +2536 -0
  184. dbt/jsonschemas/resources/latest.json +6773 -0
  185. dbt/links.py +4 -0
  186. dbt/materializations/__init__.py +0 -0
  187. dbt/materializations/incremental/__init__.py +0 -0
  188. dbt/materializations/incremental/microbatch.py +236 -0
  189. dbt/mp_context.py +8 -0
  190. dbt/node_types.py +37 -0
  191. dbt/parser/__init__.py +23 -0
  192. dbt/parser/analysis.py +21 -0
  193. dbt/parser/base.py +548 -0
  194. dbt/parser/common.py +266 -0
  195. dbt/parser/docs.py +52 -0
  196. dbt/parser/fixtures.py +51 -0
  197. dbt/parser/functions.py +30 -0
  198. dbt/parser/generic_test.py +100 -0
  199. dbt/parser/generic_test_builders.py +333 -0
  200. dbt/parser/hooks.py +118 -0
  201. dbt/parser/macros.py +137 -0
  202. dbt/parser/manifest.py +2204 -0
  203. dbt/parser/models.py +573 -0
  204. dbt/parser/partial.py +1178 -0
  205. dbt/parser/read_files.py +445 -0
  206. dbt/parser/schema_generic_tests.py +422 -0
  207. dbt/parser/schema_renderer.py +111 -0
  208. dbt/parser/schema_yaml_readers.py +935 -0
  209. dbt/parser/schemas.py +1466 -0
  210. dbt/parser/search.py +149 -0
  211. dbt/parser/seeds.py +28 -0
  212. dbt/parser/singular_test.py +20 -0
  213. dbt/parser/snapshots.py +44 -0
  214. dbt/parser/sources.py +558 -0
  215. dbt/parser/sql.py +62 -0
  216. dbt/parser/unit_tests.py +621 -0
  217. dbt/plugins/__init__.py +20 -0
  218. dbt/plugins/contracts.py +9 -0
  219. dbt/plugins/exceptions.py +2 -0
  220. dbt/plugins/manager.py +163 -0
  221. dbt/plugins/manifest.py +21 -0
  222. dbt/profiler.py +20 -0
  223. dbt/py.typed +1 -0
  224. dbt/query_analyzer.cpython-310-darwin.so +0 -0
  225. dbt/query_analyzer.py +410 -0
  226. dbt/runners/__init__.py +2 -0
  227. dbt/runners/exposure_runner.py +7 -0
  228. dbt/runners/no_op_runner.py +45 -0
  229. dbt/runners/saved_query_runner.py +7 -0
  230. dbt/selected_resources.py +8 -0
  231. dbt/task/__init__.py +0 -0
  232. dbt/task/base.py +503 -0
  233. dbt/task/build.py +197 -0
  234. dbt/task/clean.py +56 -0
  235. dbt/task/clone.py +161 -0
  236. dbt/task/compile.py +150 -0
  237. dbt/task/compute.py +454 -0
  238. dbt/task/debug.py +505 -0
  239. dbt/task/deps.py +280 -0
  240. dbt/task/docs/__init__.py +3 -0
  241. dbt/task/docs/generate.py +660 -0
  242. dbt/task/docs/index.html +250 -0
  243. dbt/task/docs/serve.py +29 -0
  244. dbt/task/freshness.py +322 -0
  245. dbt/task/function.py +121 -0
  246. dbt/task/group_lookup.py +46 -0
  247. dbt/task/init.py +553 -0
  248. dbt/task/java.py +316 -0
  249. dbt/task/list.py +236 -0
  250. dbt/task/printer.py +175 -0
  251. dbt/task/retry.py +175 -0
  252. dbt/task/run.py +1306 -0
  253. dbt/task/run_operation.py +141 -0
  254. dbt/task/runnable.py +758 -0
  255. dbt/task/seed.py +103 -0
  256. dbt/task/show.py +149 -0
  257. dbt/task/snapshot.py +56 -0
  258. dbt/task/spark.py +414 -0
  259. dbt/task/sql.py +110 -0
  260. dbt/task/target_sync.py +759 -0
  261. dbt/task/test.py +464 -0
  262. dbt/tests/fixtures/__init__.py +1 -0
  263. dbt/tests/fixtures/project.py +620 -0
  264. dbt/tests/util.py +651 -0
  265. dbt/tracking.py +529 -0
  266. dbt/utils/__init__.py +3 -0
  267. dbt/utils/artifact_upload.py +151 -0
  268. dbt/utils/utils.py +408 -0
  269. dbt/version.py +268 -0
  270. dvt_cli/__init__.py +72 -0
  271. dvt_core-0.52.2.dist-info/METADATA +286 -0
  272. dvt_core-0.52.2.dist-info/RECORD +275 -0
  273. dvt_core-0.52.2.dist-info/WHEEL +5 -0
  274. dvt_core-0.52.2.dist-info/entry_points.txt +2 -0
  275. dvt_core-0.52.2.dist-info/top_level.txt +2 -0
@@ -0,0 +1,135 @@
1
+ from typing import Any, Dict, Optional
2
+
3
+ from dbt.adapters.contracts.connection import AdapterRequiredConfig
4
+ from dbt.constants import DEFAULT_ENV_PLACEHOLDER
5
+ from dbt.context.base import Var, contextmember, contextproperty
6
+ from dbt.context.target import TargetContext
7
+ from dbt.exceptions import EnvVarMissingError, SecretEnvVarLocationError
8
+ from dbt.node_types import NodeType
9
+ from dbt.utils import MultiDict
10
+ from dbt_common.constants import SECRET_ENV_PREFIX
11
+ from dbt_common.context import get_invocation_context
12
+
13
+
14
+ class ConfiguredContext(TargetContext):
15
+ # subclasses are SchemaYamlContext, MacroResolvingContext, ManifestContext
16
+ config: AdapterRequiredConfig
17
+
18
+ def __init__(self, config: AdapterRequiredConfig) -> None:
19
+ super().__init__(config.to_target_dict(), config.cli_vars)
20
+ self.config = config
21
+
22
+ @contextproperty()
23
+ def project_name(self) -> str:
24
+ return self.config.project_name
25
+
26
+
27
+ class FQNLookup:
28
+ def __init__(self, package_name: str):
29
+ self.package_name = package_name
30
+ self.fqn = [package_name]
31
+ self.resource_type = NodeType.Model
32
+
33
+
34
+ class ConfiguredVar(Var):
35
+ def __init__(
36
+ self,
37
+ context: Dict[str, Any],
38
+ config: AdapterRequiredConfig,
39
+ project_name: str,
40
+ ):
41
+ super().__init__(context, config.cli_vars)
42
+ self._config = config
43
+ self._project_name = project_name
44
+
45
+ def __call__(self, var_name, default=Var._VAR_NOTSET):
46
+ my_config = self._config.load_dependencies()[self._project_name]
47
+
48
+ # cli vars > active project > local project
49
+ if var_name in self._config.cli_vars:
50
+ return self._config.cli_vars[var_name]
51
+
52
+ adapter_type = self._config.credentials.type
53
+ lookup = FQNLookup(self._project_name)
54
+ active_vars = self._config.vars.vars_for(lookup, adapter_type)
55
+
56
+ all_vars = MultiDict()
57
+ if self._config.project_name != my_config.project_name:
58
+ all_vars.add(my_config.vars.vars_for(lookup, adapter_type))
59
+ all_vars.add(active_vars)
60
+
61
+ if var_name in all_vars:
62
+ return all_vars[var_name]
63
+
64
+ if default is not Var._VAR_NOTSET:
65
+ return default
66
+
67
+ return self.get_missing_var(var_name)
68
+
69
+
70
+ class SchemaYamlVars:
71
+ def __init__(self):
72
+ self.env_vars = {}
73
+ self.vars = {}
74
+
75
+
76
+ class SchemaYamlContext(ConfiguredContext):
77
+ # subclass is DocsRuntimeContext
78
+ def __init__(self, config, project_name: str, schema_yaml_vars: Optional[SchemaYamlVars]):
79
+ super().__init__(config)
80
+ self._project_name = project_name
81
+ self.schema_yaml_vars = schema_yaml_vars
82
+
83
+ @contextproperty()
84
+ def var(self) -> ConfiguredVar:
85
+ return ConfiguredVar(self._ctx, self.config, self._project_name)
86
+
87
+ @contextmember()
88
+ def env_var(self, var: str, default: Optional[str] = None) -> str:
89
+ return_value = None
90
+ if var.startswith(SECRET_ENV_PREFIX):
91
+ raise SecretEnvVarLocationError(var)
92
+ env = get_invocation_context().env
93
+ if var in env:
94
+ return_value = env[var]
95
+ elif default is not None:
96
+ return_value = default
97
+
98
+ if return_value is not None:
99
+ if self.schema_yaml_vars:
100
+ # If the environment variable is set from a default, store a string indicating
101
+ # that so we can skip partial parsing. Otherwise the file will be scheduled for
102
+ # reparsing. If the default changes, the file will have been updated and therefore
103
+ # will be scheduled for reparsing anyways.
104
+ self.schema_yaml_vars.env_vars[var] = (
105
+ return_value if var in env else DEFAULT_ENV_PLACEHOLDER
106
+ )
107
+
108
+ return return_value
109
+ else:
110
+ raise EnvVarMissingError(var)
111
+
112
+
113
+ class MacroResolvingContext(ConfiguredContext):
114
+ def __init__(self, config):
115
+ super().__init__(config)
116
+
117
+ @contextproperty()
118
+ def var(self) -> ConfiguredVar:
119
+ return ConfiguredVar(self._ctx, self.config, self.config.project_name)
120
+
121
+
122
+ def generate_schema_yml_context(
123
+ config: AdapterRequiredConfig,
124
+ project_name: str,
125
+ schema_yaml_vars: Optional[SchemaYamlVars] = None,
126
+ ) -> Dict[str, Any]:
127
+ ctx = SchemaYamlContext(config, project_name, schema_yaml_vars)
128
+ return ctx.to_dict()
129
+
130
+
131
+ def generate_macro_context(
132
+ config: AdapterRequiredConfig,
133
+ ) -> Dict[str, Any]:
134
+ ctx = MacroResolvingContext(config)
135
+ return ctx.to_dict()
@@ -0,0 +1,382 @@
1
+ from abc import abstractmethod
2
+ from copy import deepcopy
3
+ from dataclasses import dataclass
4
+ from typing import Any, Dict, Generic, Iterator, List, Optional, TypeVar
5
+
6
+ from dbt.adapters.factory import get_config_class_by_name
7
+ from dbt.config import IsFQNResource, Project, RuntimeConfig
8
+ from dbt.contracts.graph.model_config import get_config_for
9
+ from dbt.exceptions import SchemaConfigError
10
+ from dbt.flags import get_flags
11
+ from dbt.node_types import NodeType
12
+ from dbt.utils import fqn_search
13
+ from dbt_common.contracts.config.base import BaseConfig, merge_config_dicts
14
+ from dbt_common.dataclass_schema import ValidationError
15
+ from dbt_common.exceptions import DbtInternalError
16
+
17
+
18
+ @dataclass
19
+ class ModelParts(IsFQNResource):
20
+ fqn: List[str]
21
+ resource_type: NodeType
22
+ package_name: str
23
+
24
+
25
+ T = TypeVar("T") # any old type
26
+ C = TypeVar("C", bound=BaseConfig)
27
+
28
+
29
+ class ConfigSource:
30
+ def __init__(self, project):
31
+ self.project = project
32
+
33
+ def get_config_dict(self, resource_type: NodeType): ...
34
+
35
+
36
+ class UnrenderedConfig(ConfigSource):
37
+ def __init__(self, project: Project):
38
+ self.project = project
39
+
40
+ def get_config_dict(self, resource_type: NodeType) -> Dict[str, Any]:
41
+ unrendered = self.project.unrendered.project_dict
42
+ if resource_type == NodeType.Seed:
43
+ model_configs = unrendered.get("seeds")
44
+ elif resource_type == NodeType.Snapshot:
45
+ model_configs = unrendered.get("snapshots")
46
+ elif resource_type == NodeType.Source:
47
+ model_configs = unrendered.get("sources")
48
+ elif resource_type == NodeType.Test:
49
+ model_configs = unrendered.get("data_tests")
50
+ elif resource_type == NodeType.Metric:
51
+ model_configs = unrendered.get("metrics")
52
+ elif resource_type == NodeType.SemanticModel:
53
+ model_configs = unrendered.get("semantic_models")
54
+ elif resource_type == NodeType.SavedQuery:
55
+ model_configs = unrendered.get("saved_queries")
56
+ elif resource_type == NodeType.Exposure:
57
+ model_configs = unrendered.get("exposures")
58
+ elif resource_type == NodeType.Unit:
59
+ model_configs = unrendered.get("unit_tests")
60
+ else:
61
+ model_configs = unrendered.get("models")
62
+ if model_configs is None:
63
+ return {}
64
+ else:
65
+ return model_configs
66
+
67
+
68
+ class RenderedConfig(ConfigSource):
69
+ def __init__(self, project: Project):
70
+ self.project = project
71
+
72
+ def get_config_dict(self, resource_type: NodeType) -> Dict[str, Any]:
73
+ if resource_type == NodeType.Seed:
74
+ model_configs = self.project.seeds
75
+ elif resource_type == NodeType.Snapshot:
76
+ model_configs = self.project.snapshots
77
+ elif resource_type == NodeType.Source:
78
+ model_configs = self.project.sources
79
+ elif resource_type == NodeType.Test:
80
+ model_configs = self.project.data_tests
81
+ elif resource_type == NodeType.Metric:
82
+ model_configs = self.project.metrics
83
+ elif resource_type == NodeType.SemanticModel:
84
+ model_configs = self.project.semantic_models
85
+ elif resource_type == NodeType.SavedQuery:
86
+ model_configs = self.project.saved_queries
87
+ elif resource_type == NodeType.Exposure:
88
+ model_configs = self.project.exposures
89
+ elif resource_type == NodeType.Unit:
90
+ model_configs = self.project.unit_tests
91
+ elif resource_type == NodeType.Function:
92
+ model_configs = self.project.functions
93
+ else:
94
+ model_configs = self.project.models
95
+ return model_configs
96
+
97
+
98
+ class BaseContextConfigGenerator(Generic[T]):
99
+ def __init__(self, active_project: RuntimeConfig):
100
+ self._active_project = active_project
101
+
102
+ def get_config_source(self, project: Project) -> ConfigSource:
103
+ return RenderedConfig(project)
104
+
105
+ def get_node_project(self, project_name: str):
106
+ if project_name == self._active_project.project_name:
107
+ return self._active_project
108
+ dependencies = self._active_project.load_dependencies()
109
+ if project_name not in dependencies:
110
+ raise DbtInternalError(
111
+ f"Project name {project_name} not found in dependencies "
112
+ f"(found {list(dependencies)})"
113
+ )
114
+ return dependencies[project_name]
115
+
116
+ def _project_configs(
117
+ self, project: Project, fqn: List[str], resource_type: NodeType
118
+ ) -> Iterator[Dict[str, Any]]:
119
+ src = self.get_config_source(project)
120
+ model_configs = src.get_config_dict(resource_type)
121
+ for level_config in fqn_search(model_configs, fqn):
122
+ result = {}
123
+ for key, value in level_config.items():
124
+ if key.startswith("+"):
125
+ result[key[1:].strip()] = deepcopy(value)
126
+ elif not isinstance(value, dict):
127
+ result[key] = deepcopy(value)
128
+
129
+ yield result
130
+
131
+ def _active_project_configs(
132
+ self, fqn: List[str], resource_type: NodeType
133
+ ) -> Iterator[Dict[str, Any]]:
134
+ return self._project_configs(self._active_project, fqn, resource_type)
135
+
136
+ @abstractmethod
137
+ def _update_from_config(
138
+ self, result: T, partial: Dict[str, Any], validate: bool = False
139
+ ) -> T: ...
140
+
141
+ @abstractmethod
142
+ def initial_result(self, resource_type: NodeType, base: bool) -> T: ...
143
+
144
+ def calculate_node_config(
145
+ self,
146
+ # this is the config from the sql file
147
+ config_call_dict: Dict[str, Any],
148
+ fqn: List[str],
149
+ resource_type: NodeType,
150
+ project_name: str,
151
+ base: bool,
152
+ # this is the config from the schema file
153
+ patch_config_dict: Optional[Dict[str, Any]] = None,
154
+ ) -> BaseConfig:
155
+ own_config = self.get_node_project(project_name)
156
+
157
+ result = self.initial_result(resource_type=resource_type, base=base)
158
+
159
+ # builds the config from what was specified in the runtime_config, which generally
160
+ # comes from the project's dbt_project.yml file.
161
+ project_configs = self._project_configs(own_config, fqn, resource_type)
162
+ for fqn_config in project_configs:
163
+ result = self._update_from_config(result, fqn_config)
164
+
165
+ # When schema files patch config, it has lower precedence than
166
+ # config in the models (config_call_dict), so we add the patch_config_dict
167
+ # before the config_call_dict
168
+ if patch_config_dict:
169
+ result = self._update_from_config(result, patch_config_dict)
170
+
171
+ # config_calls are created in the 'experimental' model parser and
172
+ # the ParseConfigObject (via add_config_call)
173
+ result = self._update_from_config(result, config_call_dict)
174
+
175
+ if own_config.project_name != self._active_project.project_name:
176
+ for fqn_config in self._active_project_configs(fqn, resource_type):
177
+ result = self._update_from_config(result, fqn_config)
178
+
179
+ # this is mostly impactful in the snapshot config case
180
+ # TODO CT-211
181
+ return result # type: ignore[return-value]
182
+
183
+ @abstractmethod
184
+ def calculate_node_config_dict(
185
+ self,
186
+ config_call_dict: Dict[str, Any],
187
+ fqn: List[str],
188
+ resource_type: NodeType,
189
+ project_name: str,
190
+ base: bool,
191
+ patch_config_dict: Optional[Dict[str, Any]] = None,
192
+ ) -> Dict[str, Any]: ...
193
+
194
+
195
+ class ContextConfigGenerator(BaseContextConfigGenerator[C]):
196
+ def __init__(self, active_project: RuntimeConfig):
197
+ self._active_project = active_project
198
+
199
+ def get_config_source(self, project: Project) -> ConfigSource:
200
+ return RenderedConfig(project)
201
+
202
+ def initial_result(self, resource_type: NodeType, base: bool) -> C:
203
+ # defaults, own_config, config calls, active_config (if != own_config)
204
+ config_cls = get_config_for(resource_type, base=base)
205
+ # Calculate the defaults. We don't want to validate the defaults,
206
+ # because it might be invalid in the case of required config members
207
+ # (such as on snapshots!)
208
+ result = config_cls.from_dict({})
209
+ return result
210
+
211
+ def _get_target_adapter_type(self, config: Dict[str, Any]) -> str:
212
+ """
213
+ Determine which adapter type to use for config merging.
214
+
215
+ If model specifies 'target' override, use that target's adapter type.
216
+ Otherwise, use the default target's adapter type.
217
+
218
+ This enables adapter-specific configs (like Redshift dist/sort,
219
+ BigQuery partition_by, Snowflake transient) to work correctly
220
+ when materializing to non-default targets in federated mode.
221
+
222
+ Args:
223
+ config: Model configuration dictionary
224
+
225
+ Returns:
226
+ Adapter type name (e.g., 'postgres', 'snowflake', 'redshift')
227
+ """
228
+ target_name = config.get('target')
229
+
230
+ if target_name:
231
+ # Model has target override - use that adapter's type
232
+ if hasattr(self._active_project, 'outputs'):
233
+ # DVTProfile with multiple outputs
234
+ target_creds = self._active_project.outputs.get(target_name)
235
+ if target_creds:
236
+ return target_creds.type
237
+ # Target name not found in outputs - fall back to default
238
+ # This maintains backward compatibility
239
+
240
+ # No target override, or target not found - use default
241
+ return self._active_project.credentials.type
242
+
243
+ def _update_from_config(self, result: C, partial: Dict[str, Any], validate: bool = False) -> C:
244
+ translated = self._active_project.credentials.translate_aliases(partial)
245
+ translated = self.translate_hook_names(translated)
246
+
247
+ # ENHANCEMENT (v0.2.3): Use target adapter type if specified
248
+ adapter_type = self._get_target_adapter_type(partial)
249
+ adapter_config_cls = get_config_class_by_name(adapter_type)
250
+
251
+ updated = result.update_from(translated, adapter_config_cls, validate=validate)
252
+ return updated
253
+
254
+ def translate_hook_names(self, project_dict):
255
+ # This is a kind of kludge because the fix for #6411 specifically allowed misspelling
256
+ # the hook field names in dbt_project.yml, which only ever worked because we didn't
257
+ # run validate on the dbt_project configs.
258
+ if "pre_hook" in project_dict:
259
+ project_dict["pre-hook"] = project_dict.pop("pre_hook")
260
+ if "post_hook" in project_dict:
261
+ project_dict["post-hook"] = project_dict.pop("post_hook")
262
+ return project_dict
263
+
264
+ def calculate_node_config_dict(
265
+ self,
266
+ config_call_dict: Dict[str, Any],
267
+ fqn: List[str],
268
+ resource_type: NodeType,
269
+ project_name: str,
270
+ base: bool,
271
+ patch_config_dict: Optional[dict] = None,
272
+ ) -> Dict[str, Any]:
273
+ config = self.calculate_node_config(
274
+ config_call_dict=config_call_dict,
275
+ fqn=fqn,
276
+ resource_type=resource_type,
277
+ project_name=project_name,
278
+ base=base,
279
+ patch_config_dict=patch_config_dict,
280
+ )
281
+ try:
282
+ finalized = config.finalize_and_validate()
283
+ return finalized.to_dict(omit_none=True)
284
+ except ValidationError as exc:
285
+ # we got a ValidationError - probably bad types in config()
286
+ raise SchemaConfigError(exc, node=config) from exc
287
+
288
+
289
+ class UnrenderedConfigGenerator(BaseContextConfigGenerator[Dict[str, Any]]):
290
+ def get_config_source(self, project: Project) -> ConfigSource:
291
+ return UnrenderedConfig(project)
292
+
293
+ def calculate_node_config_dict(
294
+ self,
295
+ config_call_dict: Dict[str, Any],
296
+ fqn: List[str],
297
+ resource_type: NodeType,
298
+ project_name: str,
299
+ base: bool,
300
+ patch_config_dict: Optional[dict] = None,
301
+ ) -> Dict[str, Any]:
302
+ # TODO CT-211
303
+ return self.calculate_node_config(
304
+ config_call_dict=config_call_dict,
305
+ fqn=fqn,
306
+ resource_type=resource_type,
307
+ project_name=project_name,
308
+ base=base,
309
+ patch_config_dict=patch_config_dict,
310
+ ) # type: ignore[return-value]
311
+
312
+ def initial_result(self, resource_type: NodeType, base: bool) -> Dict[str, Any]:
313
+ return {}
314
+
315
+ def _update_from_config(
316
+ self,
317
+ result: Dict[str, Any],
318
+ partial: Dict[str, Any],
319
+ validate: bool = False,
320
+ ) -> Dict[str, Any]:
321
+ translated = self._active_project.credentials.translate_aliases(partial)
322
+ result.update(translated)
323
+ return result
324
+
325
+
326
+ class ContextConfig:
327
+ def __init__(
328
+ self,
329
+ active_project: RuntimeConfig,
330
+ fqn: List[str],
331
+ resource_type: NodeType,
332
+ project_name: str,
333
+ ) -> None:
334
+ self._config_call_dict: Dict[str, Any] = {}
335
+ self._unrendered_config_call_dict: Dict[str, Any] = {}
336
+ self._active_project = active_project
337
+ self._fqn = fqn
338
+ self._resource_type = resource_type
339
+ self._project_name = project_name
340
+
341
+ def add_config_call(self, opts: Dict[str, Any]) -> None:
342
+ dct = self._config_call_dict
343
+ merge_config_dicts(dct, opts)
344
+
345
+ def add_unrendered_config_call(self, opts: Dict[str, Any]) -> None:
346
+ # Cannot perform complex merge behaviours on unrendered configs as they may not be appropriate types.
347
+ self._unrendered_config_call_dict.update(opts)
348
+
349
+ def build_config_dict(
350
+ self,
351
+ base: bool = False,
352
+ *,
353
+ rendered: bool = True,
354
+ patch_config_dict: Optional[dict] = None,
355
+ ) -> Dict[str, Any]:
356
+ if rendered:
357
+ # TODO CT-211
358
+ src = ContextConfigGenerator(self._active_project) # type: ignore[var-annotated]
359
+ config_call_dict = self._config_call_dict
360
+ else:
361
+ # TODO CT-211
362
+ src = UnrenderedConfigGenerator(self._active_project) # type: ignore[assignment]
363
+
364
+ # preserve legacy behaviour - using unreliable (potentially rendered) _config_call_dict
365
+ if get_flags().state_modified_compare_more_unrendered_values is False:
366
+ config_call_dict = self._config_call_dict
367
+ else:
368
+ # Prefer _config_call_dict if it is available and _unrendered_config_call_dict is not,
369
+ # as _unrendered_config_call_dict is unreliable for non-sql nodes (e.g. no jinja config block rendered for python models, etc)
370
+ if self._config_call_dict and not self._unrendered_config_call_dict:
371
+ config_call_dict = self._config_call_dict
372
+ else:
373
+ config_call_dict = self._unrendered_config_call_dict
374
+
375
+ return src.calculate_node_config_dict(
376
+ config_call_dict=config_call_dict,
377
+ fqn=self._fqn,
378
+ resource_type=self._resource_type,
379
+ project_name=self._project_name,
380
+ base=base,
381
+ patch_config_dict=patch_config_dict,
382
+ )
dbt/context/docs.py ADDED
@@ -0,0 +1,82 @@
1
+ from typing import Any, Dict, Union
2
+
3
+ from dbt.config.runtime import RuntimeConfig
4
+ from dbt.context.base import contextmember
5
+ from dbt.context.configured import SchemaYamlContext
6
+ from dbt.contracts.graph.manifest import Manifest
7
+ from dbt.contracts.graph.nodes import Macro, ResultNode
8
+ from dbt.exceptions import DocArgsError, DocTargetNotFoundError
9
+
10
+
11
+ class DocsRuntimeContext(SchemaYamlContext):
12
+ def __init__(
13
+ self,
14
+ config: RuntimeConfig,
15
+ node: Union[Macro, ResultNode],
16
+ manifest: Manifest,
17
+ current_project: str,
18
+ ) -> None:
19
+ super().__init__(config, current_project, None)
20
+ self.node = node
21
+ self.manifest = manifest
22
+
23
+ @contextmember()
24
+ def doc(self, *args: str) -> str:
25
+ """The `doc` function is used to reference docs blocks in schema.yml
26
+ files. It is analogous to the `ref` function. For more information,
27
+ consult the Documentation guide.
28
+
29
+ > orders.md:
30
+
31
+ {% docs orders %}
32
+ # docs
33
+ - go
34
+ - here
35
+ {% enddocs %}
36
+
37
+ > schema.yml
38
+
39
+ version: 2
40
+ models:
41
+ - name: orders
42
+ description: "{{ doc('orders') }}"
43
+ """
44
+ # when you call doc(), this is what happens at runtime
45
+ if len(args) == 1:
46
+ doc_package_name = None
47
+ doc_name = args[0]
48
+ elif len(args) == 2:
49
+ doc_package_name, doc_name = args
50
+ else:
51
+ raise DocArgsError(self.node, args)
52
+
53
+ # Documentation
54
+ target_doc = self.manifest.resolve_doc(
55
+ doc_name,
56
+ doc_package_name,
57
+ self._project_name,
58
+ self.node.package_name,
59
+ )
60
+ if target_doc:
61
+ file_id = target_doc.file_id
62
+ if file_id in self.manifest.files:
63
+ source_file = self.manifest.files[file_id]
64
+ # TODO CT-211
65
+ source_file.add_node(self.node.unique_id) # type: ignore[union-attr]
66
+ else:
67
+ raise DocTargetNotFoundError(
68
+ node=self.node, target_doc_name=doc_name, target_doc_package=doc_package_name
69
+ )
70
+
71
+ return target_doc.block_contents
72
+
73
+
74
+ def generate_runtime_docs_context(
75
+ config: RuntimeConfig,
76
+ target: Any,
77
+ manifest: Manifest,
78
+ current_project: str,
79
+ ) -> Dict[str, Any]:
80
+ ctx = DocsRuntimeContext(config, target, manifest, current_project)
81
+ # This is not a Mashumaro to_dict call
82
+ return ctx.to_dict()