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.
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,277 @@
1
+ import re
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, Dict, List, Optional, Union
4
+
5
+ from mashumaro.jsonschema.annotations import Pattern
6
+ from typing_extensions import Annotated
7
+
8
+ from dbt import hooks
9
+ from dbt.artifacts.resources.base import Docs
10
+ from dbt.artifacts.resources.types import ModelHookType
11
+ from dbt.artifacts.utils.validation import validate_color
12
+ from dbt_common.contracts.config.base import BaseConfig, CompareBehavior, MergeBehavior
13
+ from dbt_common.contracts.config.materialization import OnConfigurationChangeOption
14
+ from dbt_common.contracts.config.metadata import Metadata, ShowBehavior
15
+ from dbt_common.dataclass_schema import ValidationError, dbtClassMixin
16
+
17
+
18
+ def list_str() -> List[str]:
19
+ return []
20
+
21
+
22
+ class Severity(str):
23
+ pass
24
+
25
+
26
+ def metas(*metas: Metadata) -> Dict[str, Any]:
27
+ existing: Dict[str, Any] = {}
28
+ for m in metas:
29
+ existing = m.meta(existing)
30
+ return existing
31
+
32
+
33
+ @dataclass
34
+ class ContractConfig(dbtClassMixin):
35
+ enforced: bool = False
36
+ alias_types: bool = True
37
+
38
+
39
+ @dataclass
40
+ class Hook(dbtClassMixin):
41
+ sql: str
42
+ transaction: bool = True
43
+ index: Optional[int] = None
44
+
45
+
46
+ @dataclass
47
+ class NodeAndTestConfig(BaseConfig):
48
+ enabled: bool = True
49
+ # these fields are included in serialized output, but are not part of
50
+ # config comparison (they are part of database_representation)
51
+ alias: Optional[str] = field(
52
+ default=None,
53
+ metadata=CompareBehavior.Exclude.meta(),
54
+ )
55
+ schema: Optional[str] = field(
56
+ default=None,
57
+ metadata=CompareBehavior.Exclude.meta(),
58
+ )
59
+ database: Optional[str] = field(
60
+ default=None,
61
+ metadata=CompareBehavior.Exclude.meta(),
62
+ )
63
+ tags: Union[List[str], str] = field(
64
+ default_factory=list_str,
65
+ metadata=metas(ShowBehavior.Hide, MergeBehavior.Append, CompareBehavior.Exclude),
66
+ )
67
+ meta: Dict[str, Any] = field(
68
+ default_factory=dict,
69
+ metadata=MergeBehavior.Update.meta(),
70
+ )
71
+ group: Optional[str] = field(
72
+ default=None,
73
+ metadata=CompareBehavior.Exclude.meta(),
74
+ )
75
+
76
+
77
+ @dataclass
78
+ class NodeConfig(NodeAndTestConfig):
79
+ # Note: if any new fields are added with MergeBehavior, also update the
80
+ # 'mergebehavior' dictionary
81
+ materialized: str = "view"
82
+ incremental_strategy: Optional[str] = None
83
+ batch_size: Any = None
84
+ lookback: Any = 1
85
+ begin: Any = None
86
+ persist_docs: Dict[str, Any] = field(default_factory=dict)
87
+ post_hook: List[Hook] = field(
88
+ default_factory=list,
89
+ metadata={"merge": MergeBehavior.Append, "alias": "post-hook"},
90
+ )
91
+ pre_hook: List[Hook] = field(
92
+ default_factory=list,
93
+ metadata={"merge": MergeBehavior.Append, "alias": "pre-hook"},
94
+ )
95
+ quoting: Dict[str, Any] = field(
96
+ default_factory=dict,
97
+ metadata=MergeBehavior.Update.meta(),
98
+ )
99
+ # This is actually only used by seeds. Should it be available to others?
100
+ # That would be a breaking change!
101
+ column_types: Dict[str, Any] = field(
102
+ default_factory=dict,
103
+ metadata=MergeBehavior.Update.meta(),
104
+ )
105
+ full_refresh: Optional[bool] = None
106
+ # 'unique_key' doesn't use 'Optional' because typing.get_type_hints was
107
+ # sometimes getting the Union order wrong, causing serialization failures.
108
+ unique_key: Union[str, List[str], None] = None
109
+ on_schema_change: Optional[str] = "ignore"
110
+ on_configuration_change: OnConfigurationChangeOption = field(
111
+ default_factory=OnConfigurationChangeOption.default
112
+ )
113
+ grants: Dict[str, Any] = field(
114
+ default_factory=dict, metadata=MergeBehavior.DictKeyAppend.meta()
115
+ )
116
+ packages: List[str] = field(
117
+ default_factory=list,
118
+ metadata=MergeBehavior.Append.meta(),
119
+ )
120
+ docs: Docs = field(
121
+ default_factory=Docs,
122
+ metadata=MergeBehavior.Update.meta(),
123
+ )
124
+ contract: ContractConfig = field(
125
+ default_factory=ContractConfig,
126
+ metadata=MergeBehavior.Update.meta(),
127
+ )
128
+ event_time: Any = None
129
+ concurrent_batches: Any = None
130
+ # DVT-specific configuration fields
131
+ target: Optional[str] = field(
132
+ default=None,
133
+ metadata=CompareBehavior.Exclude.meta(),
134
+ ) # Target connection for materialization
135
+ compute: Optional[str] = field(
136
+ default=None,
137
+ metadata=CompareBehavior.Exclude.meta(),
138
+ ) # Compute engine override (duckdb/spark/cluster_name)
139
+
140
+ def __post_init__(self):
141
+ # we validate that node_color has a suitable value to prevent dbt-docs from crashing
142
+ if self.docs.node_color:
143
+ node_color = self.docs.node_color
144
+ if not validate_color(node_color):
145
+ raise ValidationError(
146
+ f"Invalid color name for docs.node_color: {node_color}. "
147
+ "It is neither a valid HTML color name nor a valid HEX code."
148
+ )
149
+
150
+ if (
151
+ self.contract.enforced
152
+ and self.materialized == "incremental"
153
+ and self.on_schema_change not in ("append_new_columns", "fail")
154
+ ):
155
+ raise ValidationError(
156
+ f"Invalid value for on_schema_change: {self.on_schema_change}. Models "
157
+ "materialized as incremental with contracts enabled must set "
158
+ "on_schema_change to 'append_new_columns' or 'fail'"
159
+ )
160
+
161
+ @classmethod
162
+ def __pre_deserialize__(cls, data):
163
+ data = super().__pre_deserialize__(data)
164
+ for key in ModelHookType:
165
+ if key in data:
166
+ data[key] = [hooks.get_hook_dict(h) for h in data[key]]
167
+ return data
168
+
169
+
170
+ SEVERITY_PATTERN = r"^([Ww][Aa][Rr][Nn]|[Ee][Rr][Rr][Oo][Rr])$"
171
+
172
+
173
+ @dataclass
174
+ class TestConfig(NodeAndTestConfig):
175
+ __test__ = False
176
+
177
+ # this is repeated because of a different default
178
+ schema: Optional[str] = field(
179
+ default="dbt_test__audit",
180
+ metadata=CompareBehavior.Exclude.meta(),
181
+ )
182
+ materialized: str = "test"
183
+ # Annotated is used by mashumaro for jsonschema generation
184
+ severity: Annotated[Severity, Pattern(SEVERITY_PATTERN)] = Severity("ERROR")
185
+ store_failures: Optional[bool] = None
186
+ store_failures_as: Optional[str] = None
187
+ where: Optional[str] = None
188
+ limit: Optional[int] = None
189
+ fail_calc: str = "count(*)"
190
+ warn_if: str = "!= 0"
191
+ error_if: str = "!= 0"
192
+
193
+ def finalize_and_validate(self):
194
+ """
195
+ The presence of a setting for `store_failures_as` overrides any existing setting for `store_failures`,
196
+ regardless of level of granularity. If `store_failures_as` is not set, then `store_failures` takes effect.
197
+ At the time of implementation, `store_failures = True` would always create a table; the user could not
198
+ configure this. Hence, if `store_failures = True` and `store_failures_as` is not specified, then it
199
+ should be set to "table" to mimic the existing functionality.
200
+
201
+ A side effect of this overriding functionality is that `store_failures_as="view"` at the project
202
+ level cannot be turned off at the model level without setting both `store_failures_as` and
203
+ `store_failures`. The former would cascade down and override `store_failures=False`. The proposal
204
+ is to include "ephemeral" as a value for `store_failures_as`, which effectively sets
205
+ `store_failures=False`.
206
+
207
+ The exception handling for this is tricky. If we raise an exception here, the entire run fails at
208
+ parse time. We would rather well-formed models run successfully, leaving only exceptions to be rerun
209
+ if necessary. Hence, the exception needs to be raised in the test materialization. In order to do so,
210
+ we need to make sure that we go down the `store_failures = True` route with the invalid setting for
211
+ `store_failures_as`. This results in the `.get()` defaulted to `True` below, instead of a normal
212
+ dictionary lookup as is done in the `if` block. Refer to the test materialization for the
213
+ exception that is raise as a result of an invalid value.
214
+
215
+ The intention of this block is to behave as if `store_failures_as` is the only setting,
216
+ but still allow for backwards compatibility for `store_failures`.
217
+ See https://github.com/dbt-labs/dbt-core/issues/6914 for more information.
218
+ """
219
+ super().finalize_and_validate()
220
+
221
+ # if `store_failures_as` is not set, it gets set by `store_failures`
222
+ # the settings below mimic existing behavior prior to `store_failures_as`
223
+ get_store_failures_as_map = {
224
+ True: "table",
225
+ False: "ephemeral",
226
+ None: None,
227
+ }
228
+
229
+ # if `store_failures_as` is set, it dictates what `store_failures` gets set to
230
+ # the settings below overrides whatever `store_failures` is set to by the user
231
+ get_store_failures_map = {
232
+ "ephemeral": False,
233
+ "table": True,
234
+ "view": True,
235
+ }
236
+
237
+ if self.store_failures_as is None:
238
+ self.store_failures_as = get_store_failures_as_map[self.store_failures]
239
+ else:
240
+ self.store_failures = get_store_failures_map.get(self.store_failures_as, True)
241
+
242
+ return self
243
+
244
+ @classmethod
245
+ def same_contents(cls, unrendered: Dict[str, Any], other: Dict[str, Any]) -> bool:
246
+ """This is like __eq__, except it explicitly checks certain fields."""
247
+ modifiers = [
248
+ "severity",
249
+ "where",
250
+ "limit",
251
+ "fail_calc",
252
+ "warn_if",
253
+ "error_if",
254
+ "store_failures",
255
+ "store_failures_as",
256
+ ]
257
+
258
+ seen = set()
259
+ for _, target_name in cls._get_fields():
260
+ key = target_name
261
+ seen.add(key)
262
+ if key in modifiers:
263
+ if not cls.compare_key(unrendered, other, key):
264
+ return False
265
+ return True
266
+
267
+ @classmethod
268
+ def validate(cls, data):
269
+ if data.get("severity") and not re.match(SEVERITY_PATTERN, data.get("severity")):
270
+ raise ValidationError(
271
+ f"Severity must be either 'warn' or 'error'. Got '{data.get('severity')}'"
272
+ )
273
+
274
+ super().validate(data)
275
+
276
+ if data.get("materialized") and data.get("materialized") != "test":
277
+ raise ValidationError("A test must have a materialized value of 'test'")
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Literal
3
+
4
+ from dbt.artifacts.resources.base import BaseResource
5
+ from dbt.artifacts.resources.types import NodeType
6
+
7
+
8
+ @dataclass
9
+ class Documentation(BaseResource):
10
+ resource_type: Literal[NodeType.Documentation]
11
+ block_contents: str
@@ -0,0 +1,51 @@
1
+ import time
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, Dict, List, Literal, Optional
4
+
5
+ from dbt.artifacts.resources.base import GraphResource
6
+ from dbt.artifacts.resources.types import NodeType
7
+ from dbt.artifacts.resources.v1.components import DependsOn, RefArgs
8
+ from dbt.artifacts.resources.v1.owner import Owner
9
+ from dbt_common.contracts.config.base import BaseConfig
10
+ from dbt_common.dataclass_schema import StrEnum
11
+
12
+
13
+ class ExposureType(StrEnum):
14
+ Dashboard = "dashboard"
15
+ Notebook = "notebook"
16
+ Analysis = "analysis"
17
+ ML = "ml"
18
+ Application = "application"
19
+
20
+
21
+ class MaturityType(StrEnum):
22
+ Low = "low"
23
+ Medium = "medium"
24
+ High = "high"
25
+
26
+
27
+ @dataclass
28
+ class ExposureConfig(BaseConfig):
29
+ enabled: bool = True
30
+ tags: List[str] = field(default_factory=list)
31
+ meta: Dict[str, Any] = field(default_factory=dict)
32
+
33
+
34
+ @dataclass
35
+ class Exposure(GraphResource):
36
+ type: ExposureType
37
+ owner: Owner
38
+ resource_type: Literal[NodeType.Exposure]
39
+ description: str = ""
40
+ label: Optional[str] = None
41
+ maturity: Optional[MaturityType] = None
42
+ meta: Dict[str, Any] = field(default_factory=dict)
43
+ tags: List[str] = field(default_factory=list)
44
+ config: ExposureConfig = field(default_factory=ExposureConfig)
45
+ unrendered_config: Dict[str, Any] = field(default_factory=dict)
46
+ url: Optional[str] = None
47
+ depends_on: DependsOn = field(default_factory=DependsOn)
48
+ refs: List[RefArgs] = field(default_factory=list)
49
+ sources: List[List[str]] = field(default_factory=list)
50
+ metrics: List[List[str]] = field(default_factory=list)
51
+ created_at: float = field(default_factory=lambda: time.time())
@@ -0,0 +1,52 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import List, Literal, Optional
3
+
4
+ from dbt.artifacts.resources.types import FunctionType, FunctionVolatility, NodeType
5
+ from dbt.artifacts.resources.v1.components import CompiledResource
6
+ from dbt.artifacts.resources.v1.config import NodeConfig
7
+ from dbt_common.dataclass_schema import dbtClassMixin
8
+
9
+ # =============
10
+ # Function config, and supporting classes
11
+ # =============
12
+
13
+
14
+ @dataclass
15
+ class FunctionConfig(NodeConfig):
16
+ # The fact that this is a property, that can be changed, seems wrong.
17
+ # A function's materialization should never be changed, so why allow for it?
18
+ materialized: str = "function"
19
+ type: FunctionType = FunctionType.Scalar
20
+ volatility: Optional[FunctionVolatility] = None
21
+ runtime_version: Optional[str] = None
22
+ entry_point: Optional[str] = None
23
+
24
+
25
+ # =============
26
+ # Function resource, and supporting classes
27
+ # =============
28
+
29
+
30
+ @dataclass
31
+ class FunctionArgument(dbtClassMixin):
32
+ name: str
33
+ data_type: str
34
+ description: Optional[str] = None
35
+
36
+
37
+ @dataclass
38
+ class FunctionReturns(dbtClassMixin):
39
+ data_type: str
40
+ description: Optional[str] = None
41
+
42
+
43
+ @dataclass
44
+ class FunctionMandatory(dbtClassMixin):
45
+ returns: FunctionReturns
46
+
47
+
48
+ @dataclass
49
+ class Function(CompiledResource, FunctionMandatory):
50
+ resource_type: Literal[NodeType.Function]
51
+ config: FunctionConfig
52
+ arguments: List[FunctionArgument] = field(default_factory=list)
@@ -0,0 +1,31 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Dict, Literal, Optional
3
+
4
+ from dbt.artifacts.resources.types import NodeType
5
+ from dbt.artifacts.resources.v1.components import CompiledResource
6
+ from dbt.artifacts.resources.v1.config import TestConfig
7
+ from dbt_common.dataclass_schema import dbtClassMixin
8
+
9
+
10
+ @dataclass
11
+ class TestMetadata(dbtClassMixin):
12
+ __test__ = False
13
+
14
+ name: str = "test" # dummy default to allow default in GenericTestNode. Should always be set.
15
+ # kwargs are the args that are left in the test builder after
16
+ # removing configs. They are set from the test builder when
17
+ # the test node is created.
18
+ kwargs: Dict[str, Any] = field(default_factory=dict)
19
+ namespace: Optional[str] = None
20
+
21
+
22
+ @dataclass
23
+ class GenericTest(CompiledResource):
24
+ resource_type: Literal[NodeType.Test]
25
+ column_name: Optional[str] = None
26
+ file_key_name: Optional[str] = None
27
+ # Was not able to make mypy happy and keep the code working. We need to
28
+ # refactor the various configs.
29
+ config: TestConfig = field(default_factory=TestConfig) # type: ignore
30
+ attached_node: Optional[str] = None
31
+ test_metadata: TestMetadata = field(default_factory=TestMetadata)
@@ -0,0 +1,21 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Dict, Literal, Optional
3
+
4
+ from dbt.artifacts.resources.base import BaseResource
5
+ from dbt.artifacts.resources.types import NodeType
6
+ from dbt.artifacts.resources.v1.owner import Owner
7
+ from dbt_common.contracts.config.base import BaseConfig, MergeBehavior
8
+
9
+
10
+ @dataclass
11
+ class GroupConfig(BaseConfig):
12
+ meta: Dict[str, Any] = field(default_factory=dict, metadata=MergeBehavior.Update.meta())
13
+
14
+
15
+ @dataclass
16
+ class Group(BaseResource):
17
+ name: str
18
+ owner: Owner
19
+ resource_type: Literal[NodeType.Group]
20
+ description: Optional[str] = None
21
+ config: GroupConfig = field(default_factory=GroupConfig)
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Literal, Optional
3
+
4
+ from dbt.artifacts.resources.types import NodeType
5
+ from dbt.artifacts.resources.v1.components import CompiledResource
6
+
7
+
8
+ @dataclass
9
+ class HookNode(CompiledResource):
10
+ resource_type: Literal[NodeType.Operation]
11
+ index: Optional[int] = None
@@ -0,0 +1,29 @@
1
+ import time
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, Dict, List, Literal, Optional
4
+
5
+ from dbt.artifacts.resources.base import BaseResource, Docs
6
+ from dbt.artifacts.resources.types import ModelLanguage, NodeType
7
+ from dbt.artifacts.resources.v1.components import MacroDependsOn
8
+ from dbt_common.dataclass_schema import dbtClassMixin
9
+
10
+
11
+ @dataclass
12
+ class MacroArgument(dbtClassMixin):
13
+ name: str
14
+ type: Optional[str] = None
15
+ description: str = ""
16
+
17
+
18
+ @dataclass
19
+ class Macro(BaseResource):
20
+ macro_sql: str
21
+ resource_type: Literal[NodeType.Macro]
22
+ depends_on: MacroDependsOn = field(default_factory=MacroDependsOn)
23
+ description: str = ""
24
+ meta: Dict[str, Any] = field(default_factory=dict)
25
+ docs: Docs = field(default_factory=Docs)
26
+ patch_path: Optional[str] = None
27
+ arguments: List[MacroArgument] = field(default_factory=list)
28
+ created_at: float = field(default_factory=lambda: time.time())
29
+ supported_languages: Optional[List[ModelLanguage]] = None
@@ -0,0 +1,172 @@
1
+ import time
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, Dict, List, Literal, Optional
4
+
5
+ from dbt.artifacts.resources.base import GraphResource
6
+ from dbt.artifacts.resources.types import NodeType
7
+ from dbt.artifacts.resources.v1.components import DependsOn, RefArgs
8
+ from dbt.artifacts.resources.v1.semantic_layer_components import (
9
+ MeasureAggregationParameters,
10
+ NonAdditiveDimension,
11
+ SourceFileMetadata,
12
+ WhereFilterIntersection,
13
+ )
14
+ from dbt_common.contracts.config.base import BaseConfig, CompareBehavior, MergeBehavior
15
+ from dbt_common.dataclass_schema import dbtClassMixin
16
+ from dbt_semantic_interfaces.references import MeasureReference, MetricReference
17
+ from dbt_semantic_interfaces.type_enums import (
18
+ AggregationType,
19
+ ConversionCalculationType,
20
+ MetricType,
21
+ PeriodAggregation,
22
+ TimeGranularity,
23
+ )
24
+
25
+ """
26
+ The following classes are dataclasses which are used to construct the Metric
27
+ node in dbt-core. Additionally, these classes need to at a minimum support
28
+ what is specified in their protocol definitions in dbt-semantic-interfaces.
29
+ Their protocol definitions can be found here:
30
+ https://github.com/dbt-labs/dbt-semantic-interfaces/blob/main/dbt_semantic_interfaces/protocols/metric.py
31
+ """
32
+
33
+
34
+ @dataclass
35
+ class MetricInputMeasure(dbtClassMixin):
36
+ name: str
37
+ filter: Optional[WhereFilterIntersection] = None
38
+ alias: Optional[str] = None
39
+ join_to_timespine: bool = False
40
+ fill_nulls_with: Optional[int] = None
41
+
42
+ def measure_reference(self) -> MeasureReference:
43
+ return MeasureReference(element_name=self.name)
44
+
45
+ def post_aggregation_measure_reference(self) -> MeasureReference:
46
+ return MeasureReference(element_name=self.alias or self.name)
47
+
48
+
49
+ @dataclass
50
+ class MetricTimeWindow(dbtClassMixin):
51
+ count: int
52
+ granularity: str
53
+
54
+ @property
55
+ def window_string(self) -> str: # noqa: D
56
+ return f"{self.count} {self.granularity}"
57
+
58
+ @property
59
+ def is_standard_granularity(self) -> bool: # noqa: D
60
+ return self.granularity.casefold() in {item.value.casefold() for item in TimeGranularity}
61
+
62
+
63
+ @dataclass
64
+ class MetricInput(dbtClassMixin):
65
+ name: str
66
+ filter: Optional[WhereFilterIntersection] = None
67
+ alias: Optional[str] = None
68
+ offset_window: Optional[MetricTimeWindow] = None
69
+ offset_to_grain: Optional[str] = None
70
+
71
+ def as_reference(self) -> MetricReference:
72
+ return MetricReference(element_name=self.name)
73
+
74
+ def post_aggregation_reference(self) -> MetricReference:
75
+ return MetricReference(element_name=self.alias or self.name)
76
+
77
+
78
+ @dataclass
79
+ class ConstantPropertyInput(dbtClassMixin):
80
+ base_property: str
81
+ conversion_property: str
82
+
83
+
84
+ @dataclass
85
+ class ConversionTypeParams(dbtClassMixin):
86
+ base_measure: MetricInputMeasure
87
+ conversion_measure: MetricInputMeasure
88
+ entity: str
89
+ calculation: ConversionCalculationType = ConversionCalculationType.CONVERSION_RATE
90
+ window: Optional[MetricTimeWindow] = None
91
+ constant_properties: Optional[List[ConstantPropertyInput]] = None
92
+
93
+
94
+ @dataclass
95
+ class CumulativeTypeParams(dbtClassMixin):
96
+ window: Optional[MetricTimeWindow] = None
97
+ grain_to_date: Optional[str] = None
98
+ period_agg: PeriodAggregation = PeriodAggregation.FIRST
99
+ metric: Optional[MetricInput] = None
100
+
101
+
102
+ @dataclass
103
+ class MetricAggregationParams(dbtClassMixin):
104
+ semantic_model: str
105
+ agg: AggregationType
106
+ agg_params: Optional[MeasureAggregationParameters] = None
107
+ agg_time_dimension: Optional[str] = None
108
+ non_additive_dimension: Optional[NonAdditiveDimension] = None
109
+ expr: Optional[str] = None
110
+
111
+
112
+ @dataclass
113
+ class MetricTypeParams(dbtClassMixin):
114
+ measure: Optional[MetricInputMeasure] = None
115
+ input_measures: List[MetricInputMeasure] = field(default_factory=list)
116
+ numerator: Optional[MetricInput] = None
117
+ denominator: Optional[MetricInput] = None
118
+ expr: Optional[str] = None
119
+ window: Optional[MetricTimeWindow] = None
120
+ grain_to_date: Optional[TimeGranularity] = (
121
+ None # legacy, use cumulative_type_params.grain_to_date
122
+ )
123
+ metrics: Optional[List[MetricInput]] = None
124
+ conversion_type_params: Optional[ConversionTypeParams] = None
125
+ cumulative_type_params: Optional[CumulativeTypeParams] = None
126
+ metric_aggregation_params: Optional[MetricAggregationParams] = None
127
+
128
+
129
+ @dataclass
130
+ class MetricConfig(BaseConfig):
131
+ enabled: bool = True
132
+ group: Optional[str] = field(
133
+ default=None,
134
+ metadata=CompareBehavior.Exclude.meta(),
135
+ )
136
+
137
+ meta: Dict[str, Any] = field(default_factory=dict, metadata=MergeBehavior.Update.meta())
138
+
139
+
140
+ @dataclass
141
+ class Metric(GraphResource):
142
+ name: str
143
+ description: str
144
+ label: str
145
+ type: MetricType
146
+ type_params: MetricTypeParams
147
+ filter: Optional[WhereFilterIntersection] = None
148
+ metadata: Optional[SourceFileMetadata] = None
149
+ time_granularity: Optional[str] = None
150
+ resource_type: Literal[NodeType.Metric]
151
+ meta: Dict[str, Any] = field(default_factory=dict, metadata=MergeBehavior.Update.meta())
152
+ tags: List[str] = field(default_factory=list)
153
+ config: MetricConfig = field(default_factory=MetricConfig)
154
+ unrendered_config: Dict[str, Any] = field(default_factory=dict)
155
+ sources: List[List[str]] = field(default_factory=list)
156
+ depends_on: DependsOn = field(default_factory=DependsOn)
157
+ refs: List[RefArgs] = field(default_factory=list)
158
+ metrics: List[List[str]] = field(default_factory=list)
159
+ created_at: float = field(default_factory=lambda: time.time())
160
+ group: Optional[str] = None
161
+
162
+ @property
163
+ def input_measures(self) -> List[MetricInputMeasure]:
164
+ return self.type_params.input_measures
165
+
166
+ @property
167
+ def measure_references(self) -> List[MeasureReference]:
168
+ return [x.measure_reference() for x in self.input_measures]
169
+
170
+ @property
171
+ def input_metrics(self) -> List[MetricInput]:
172
+ return self.type_params.metrics or []