dvt-core 0.59.0a51__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) 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 +2660 -0
  57. dbt/cli/option_types.py +121 -0
  58. dbt/cli/options.py +80 -0
  59. dbt/cli/params.py +844 -0
  60. dbt/cli/requires.py +490 -0
  61. dbt/cli/resolvers.py +60 -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 +642 -0
  74. dbt/compute/federated_executor.py +1080 -0
  75. dbt/compute/filter_pushdown.py +273 -0
  76. dbt/compute/jar_provisioning.py +273 -0
  77. dbt/compute/java_compat.py +689 -0
  78. dbt/compute/jdbc_utils.py +1252 -0
  79. dbt/compute/metadata/__init__.py +63 -0
  80. dbt/compute/metadata/adapters_registry.py +370 -0
  81. dbt/compute/metadata/catalog_store.py +1036 -0
  82. dbt/compute/metadata/registry.py +674 -0
  83. dbt/compute/metadata/store.py +1020 -0
  84. dbt/compute/smart_selector.py +377 -0
  85. dbt/compute/spark_logger.py +272 -0
  86. dbt/compute/strategies/__init__.py +55 -0
  87. dbt/compute/strategies/base.py +165 -0
  88. dbt/compute/strategies/dataproc.py +207 -0
  89. dbt/compute/strategies/emr.py +203 -0
  90. dbt/compute/strategies/local.py +472 -0
  91. dbt/compute/strategies/standalone.py +262 -0
  92. dbt/config/__init__.py +4 -0
  93. dbt/config/catalogs.py +94 -0
  94. dbt/config/compute.py +513 -0
  95. dbt/config/dvt_profile.py +408 -0
  96. dbt/config/profile.py +422 -0
  97. dbt/config/project.py +888 -0
  98. dbt/config/project_utils.py +48 -0
  99. dbt/config/renderer.py +231 -0
  100. dbt/config/runtime.py +564 -0
  101. dbt/config/selectors.py +208 -0
  102. dbt/config/utils.py +77 -0
  103. dbt/constants.py +28 -0
  104. dbt/context/__init__.py +0 -0
  105. dbt/context/base.py +745 -0
  106. dbt/context/configured.py +135 -0
  107. dbt/context/context_config.py +382 -0
  108. dbt/context/docs.py +82 -0
  109. dbt/context/exceptions_jinja.py +178 -0
  110. dbt/context/macro_resolver.py +195 -0
  111. dbt/context/macros.py +171 -0
  112. dbt/context/manifest.py +72 -0
  113. dbt/context/providers.py +2249 -0
  114. dbt/context/query_header.py +13 -0
  115. dbt/context/secret.py +58 -0
  116. dbt/context/target.py +74 -0
  117. dbt/contracts/__init__.py +0 -0
  118. dbt/contracts/files.py +413 -0
  119. dbt/contracts/graph/__init__.py +0 -0
  120. dbt/contracts/graph/manifest.py +1904 -0
  121. dbt/contracts/graph/metrics.py +97 -0
  122. dbt/contracts/graph/model_config.py +70 -0
  123. dbt/contracts/graph/node_args.py +42 -0
  124. dbt/contracts/graph/nodes.py +1806 -0
  125. dbt/contracts/graph/semantic_manifest.py +232 -0
  126. dbt/contracts/graph/unparsed.py +811 -0
  127. dbt/contracts/project.py +419 -0
  128. dbt/contracts/results.py +53 -0
  129. dbt/contracts/selection.py +23 -0
  130. dbt/contracts/sql.py +85 -0
  131. dbt/contracts/state.py +68 -0
  132. dbt/contracts/util.py +46 -0
  133. dbt/deprecations.py +348 -0
  134. dbt/deps/__init__.py +0 -0
  135. dbt/deps/base.py +152 -0
  136. dbt/deps/git.py +195 -0
  137. dbt/deps/local.py +79 -0
  138. dbt/deps/registry.py +130 -0
  139. dbt/deps/resolver.py +149 -0
  140. dbt/deps/tarball.py +120 -0
  141. dbt/docs/source/_ext/dbt_click.py +119 -0
  142. dbt/docs/source/conf.py +32 -0
  143. dbt/env_vars.py +64 -0
  144. dbt/event_time/event_time.py +40 -0
  145. dbt/event_time/sample_window.py +60 -0
  146. dbt/events/__init__.py +15 -0
  147. dbt/events/base_types.py +36 -0
  148. dbt/events/core_types_pb2.py +2 -0
  149. dbt/events/logging.py +108 -0
  150. dbt/events/types.py +2516 -0
  151. dbt/exceptions.py +1486 -0
  152. dbt/flags.py +89 -0
  153. dbt/graph/__init__.py +11 -0
  154. dbt/graph/cli.py +249 -0
  155. dbt/graph/graph.py +172 -0
  156. dbt/graph/queue.py +214 -0
  157. dbt/graph/selector.py +374 -0
  158. dbt/graph/selector_methods.py +975 -0
  159. dbt/graph/selector_spec.py +222 -0
  160. dbt/graph/thread_pool.py +18 -0
  161. dbt/hooks.py +21 -0
  162. dbt/include/README.md +49 -0
  163. dbt/include/__init__.py +3 -0
  164. dbt/include/data/adapters_registry.duckdb +0 -0
  165. dbt/include/data/build_comprehensive_registry.py +1254 -0
  166. dbt/include/data/build_registry.py +242 -0
  167. dbt/include/data/csv/adapter_queries.csv +33 -0
  168. dbt/include/data/csv/syntax_rules.csv +9 -0
  169. dbt/include/data/csv/type_mappings_bigquery.csv +28 -0
  170. dbt/include/data/csv/type_mappings_databricks.csv +30 -0
  171. dbt/include/data/csv/type_mappings_mysql.csv +40 -0
  172. dbt/include/data/csv/type_mappings_oracle.csv +30 -0
  173. dbt/include/data/csv/type_mappings_postgres.csv +56 -0
  174. dbt/include/data/csv/type_mappings_redshift.csv +33 -0
  175. dbt/include/data/csv/type_mappings_snowflake.csv +38 -0
  176. dbt/include/data/csv/type_mappings_sqlserver.csv +35 -0
  177. dbt/include/dvt_starter_project/README.md +15 -0
  178. dbt/include/dvt_starter_project/__init__.py +3 -0
  179. dbt/include/dvt_starter_project/analyses/PLACEHOLDER +0 -0
  180. dbt/include/dvt_starter_project/dvt_project.yml +39 -0
  181. dbt/include/dvt_starter_project/logs/PLACEHOLDER +0 -0
  182. dbt/include/dvt_starter_project/macros/PLACEHOLDER +0 -0
  183. dbt/include/dvt_starter_project/models/example/my_first_dbt_model.sql +27 -0
  184. dbt/include/dvt_starter_project/models/example/my_second_dbt_model.sql +6 -0
  185. dbt/include/dvt_starter_project/models/example/schema.yml +21 -0
  186. dbt/include/dvt_starter_project/seeds/PLACEHOLDER +0 -0
  187. dbt/include/dvt_starter_project/snapshots/PLACEHOLDER +0 -0
  188. dbt/include/dvt_starter_project/tests/PLACEHOLDER +0 -0
  189. dbt/internal_deprecations.py +26 -0
  190. dbt/jsonschemas/__init__.py +3 -0
  191. dbt/jsonschemas/jsonschemas.py +309 -0
  192. dbt/jsonschemas/project/0.0.110.json +4717 -0
  193. dbt/jsonschemas/project/0.0.85.json +2015 -0
  194. dbt/jsonschemas/resources/0.0.110.json +2636 -0
  195. dbt/jsonschemas/resources/0.0.85.json +2536 -0
  196. dbt/jsonschemas/resources/latest.json +6773 -0
  197. dbt/links.py +4 -0
  198. dbt/materializations/__init__.py +0 -0
  199. dbt/materializations/incremental/__init__.py +0 -0
  200. dbt/materializations/incremental/microbatch.py +236 -0
  201. dbt/mp_context.py +8 -0
  202. dbt/node_types.py +37 -0
  203. dbt/parser/__init__.py +23 -0
  204. dbt/parser/analysis.py +21 -0
  205. dbt/parser/base.py +548 -0
  206. dbt/parser/common.py +266 -0
  207. dbt/parser/docs.py +52 -0
  208. dbt/parser/fixtures.py +51 -0
  209. dbt/parser/functions.py +30 -0
  210. dbt/parser/generic_test.py +100 -0
  211. dbt/parser/generic_test_builders.py +333 -0
  212. dbt/parser/hooks.py +122 -0
  213. dbt/parser/macros.py +137 -0
  214. dbt/parser/manifest.py +2208 -0
  215. dbt/parser/models.py +573 -0
  216. dbt/parser/partial.py +1178 -0
  217. dbt/parser/read_files.py +445 -0
  218. dbt/parser/schema_generic_tests.py +422 -0
  219. dbt/parser/schema_renderer.py +111 -0
  220. dbt/parser/schema_yaml_readers.py +935 -0
  221. dbt/parser/schemas.py +1466 -0
  222. dbt/parser/search.py +149 -0
  223. dbt/parser/seeds.py +28 -0
  224. dbt/parser/singular_test.py +20 -0
  225. dbt/parser/snapshots.py +44 -0
  226. dbt/parser/sources.py +558 -0
  227. dbt/parser/sql.py +62 -0
  228. dbt/parser/unit_tests.py +621 -0
  229. dbt/plugins/__init__.py +20 -0
  230. dbt/plugins/contracts.py +9 -0
  231. dbt/plugins/exceptions.py +2 -0
  232. dbt/plugins/manager.py +163 -0
  233. dbt/plugins/manifest.py +21 -0
  234. dbt/profiler.py +20 -0
  235. dbt/py.typed +1 -0
  236. dbt/query_analyzer.py +410 -0
  237. dbt/runners/__init__.py +2 -0
  238. dbt/runners/exposure_runner.py +7 -0
  239. dbt/runners/no_op_runner.py +45 -0
  240. dbt/runners/saved_query_runner.py +7 -0
  241. dbt/selected_resources.py +8 -0
  242. dbt/task/__init__.py +0 -0
  243. dbt/task/base.py +506 -0
  244. dbt/task/build.py +197 -0
  245. dbt/task/clean.py +56 -0
  246. dbt/task/clone.py +161 -0
  247. dbt/task/compile.py +150 -0
  248. dbt/task/compute.py +458 -0
  249. dbt/task/debug.py +513 -0
  250. dbt/task/deps.py +280 -0
  251. dbt/task/docs/__init__.py +3 -0
  252. dbt/task/docs/api/__init__.py +23 -0
  253. dbt/task/docs/api/catalog.py +204 -0
  254. dbt/task/docs/api/lineage.py +234 -0
  255. dbt/task/docs/api/profile.py +204 -0
  256. dbt/task/docs/api/spark.py +186 -0
  257. dbt/task/docs/generate.py +1002 -0
  258. dbt/task/docs/index.html +250 -0
  259. dbt/task/docs/serve.py +174 -0
  260. dbt/task/dvt_output.py +509 -0
  261. dbt/task/dvt_run.py +282 -0
  262. dbt/task/dvt_seed.py +806 -0
  263. dbt/task/freshness.py +322 -0
  264. dbt/task/function.py +121 -0
  265. dbt/task/group_lookup.py +46 -0
  266. dbt/task/init.py +1022 -0
  267. dbt/task/java.py +316 -0
  268. dbt/task/list.py +236 -0
  269. dbt/task/metadata.py +804 -0
  270. dbt/task/migrate.py +714 -0
  271. dbt/task/printer.py +175 -0
  272. dbt/task/profile.py +1489 -0
  273. dbt/task/profile_serve.py +662 -0
  274. dbt/task/retract.py +441 -0
  275. dbt/task/retry.py +175 -0
  276. dbt/task/run.py +1647 -0
  277. dbt/task/run_operation.py +141 -0
  278. dbt/task/runnable.py +758 -0
  279. dbt/task/seed.py +103 -0
  280. dbt/task/show.py +149 -0
  281. dbt/task/snapshot.py +56 -0
  282. dbt/task/spark.py +414 -0
  283. dbt/task/sql.py +110 -0
  284. dbt/task/target_sync.py +814 -0
  285. dbt/task/test.py +464 -0
  286. dbt/tests/fixtures/__init__.py +1 -0
  287. dbt/tests/fixtures/project.py +620 -0
  288. dbt/tests/util.py +651 -0
  289. dbt/tracking.py +529 -0
  290. dbt/utils/__init__.py +3 -0
  291. dbt/utils/artifact_upload.py +151 -0
  292. dbt/utils/utils.py +408 -0
  293. dbt/version.py +271 -0
  294. dvt_cli/__init__.py +158 -0
  295. dvt_core-0.59.0a51.dist-info/METADATA +288 -0
  296. dvt_core-0.59.0a51.dist-info/RECORD +299 -0
  297. dvt_core-0.59.0a51.dist-info/WHEEL +5 -0
  298. dvt_core-0.59.0a51.dist-info/entry_points.txt +2 -0
  299. dvt_core-0.59.0a51.dist-info/top_level.txt +2 -0
dbt/parser/common.py ADDED
@@ -0,0 +1,266 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Dict, Generic, List, Optional, TypeVar, Union
3
+
4
+ from dbt.artifacts.resources import ColumnConfig, ColumnInfo, NodeVersion
5
+ from dbt.contracts.graph.nodes import UnpatchedSourceDefinition
6
+ from dbt.contracts.graph.unparsed import (
7
+ HasColumnDocs,
8
+ HasColumnProps,
9
+ HasColumnTests,
10
+ UnparsedAnalysisUpdate,
11
+ UnparsedColumn,
12
+ UnparsedExposure,
13
+ UnparsedFunctionUpdate,
14
+ UnparsedMacroUpdate,
15
+ UnparsedModelUpdate,
16
+ UnparsedNodeUpdate,
17
+ UnparsedSingularTestUpdate,
18
+ )
19
+ from dbt.exceptions import ParsingError
20
+ from dbt.node_types import NodeType
21
+ from dbt.parser.search import FileBlock
22
+ from dbt_common.contracts.constraints import ColumnLevelConstraint, ConstraintType
23
+ from dbt_common.exceptions import DbtInternalError
24
+ from dbt_semantic_interfaces.type_enums import TimeGranularity
25
+
26
+ schema_file_keys_to_resource_types = {
27
+ "models": NodeType.Model,
28
+ "seeds": NodeType.Seed,
29
+ "snapshots": NodeType.Snapshot,
30
+ "sources": NodeType.Source,
31
+ "macros": NodeType.Macro,
32
+ "analyses": NodeType.Analysis,
33
+ "exposures": NodeType.Exposure,
34
+ "metrics": NodeType.Metric,
35
+ "semantic_models": NodeType.SemanticModel,
36
+ "saved_queries": NodeType.SavedQuery,
37
+ "functions": NodeType.Function,
38
+ }
39
+
40
+ resource_types_to_schema_file_keys = {
41
+ v: k for (k, v) in schema_file_keys_to_resource_types.items()
42
+ }
43
+
44
+ schema_file_keys = list(schema_file_keys_to_resource_types.keys())
45
+
46
+
47
+ def trimmed(inp: str) -> str:
48
+ if len(inp) < 50:
49
+ return inp
50
+ return inp[:44] + "..." + inp[-3:]
51
+
52
+
53
+ TestDef = Union[str, Dict[str, Any]]
54
+
55
+
56
+ Target = TypeVar(
57
+ "Target",
58
+ UnparsedNodeUpdate,
59
+ UnparsedMacroUpdate,
60
+ UnparsedAnalysisUpdate,
61
+ UnpatchedSourceDefinition,
62
+ UnparsedExposure,
63
+ UnparsedModelUpdate,
64
+ UnparsedFunctionUpdate,
65
+ UnparsedSingularTestUpdate,
66
+ )
67
+
68
+
69
+ ColumnTarget = TypeVar(
70
+ "ColumnTarget",
71
+ UnparsedModelUpdate,
72
+ UnparsedNodeUpdate,
73
+ UnparsedAnalysisUpdate,
74
+ UnpatchedSourceDefinition,
75
+ )
76
+
77
+ Versioned = TypeVar("Versioned", bound=UnparsedModelUpdate)
78
+
79
+ Testable = TypeVar("Testable", UnparsedNodeUpdate, UnpatchedSourceDefinition, UnparsedModelUpdate)
80
+
81
+
82
+ @dataclass
83
+ class YamlBlock(FileBlock):
84
+ data: Dict[str, Any]
85
+
86
+ @classmethod
87
+ def from_file_block(cls, src: FileBlock, data: Dict[str, Any]):
88
+ return cls(
89
+ file=src.file,
90
+ data=data,
91
+ )
92
+
93
+
94
+ @dataclass
95
+ class TargetBlock(YamlBlock, Generic[Target]):
96
+ target: Target
97
+
98
+ @property
99
+ def name(self):
100
+ return self.target.name
101
+
102
+ @property
103
+ def columns(self):
104
+ return []
105
+
106
+ @property
107
+ def data_tests(self) -> List[TestDef]:
108
+ return []
109
+
110
+ @property
111
+ def tests(self) -> List[TestDef]:
112
+ return []
113
+
114
+ @classmethod
115
+ def from_yaml_block(cls, src: YamlBlock, target: Target) -> "TargetBlock[Target]":
116
+ return cls(
117
+ file=src.file,
118
+ data=src.data,
119
+ target=target,
120
+ )
121
+
122
+
123
+ @dataclass
124
+ class TargetColumnsBlock(TargetBlock[ColumnTarget], Generic[ColumnTarget]):
125
+ @property
126
+ def columns(self):
127
+ if self.target.columns is None:
128
+ return []
129
+ else:
130
+ return self.target.columns
131
+
132
+
133
+ @dataclass
134
+ class TestBlock(TargetColumnsBlock[Testable], Generic[Testable]):
135
+ @property
136
+ def data_tests(self) -> List[TestDef]:
137
+ if self.target.data_tests is None:
138
+ return []
139
+ else:
140
+ return self.target.data_tests
141
+
142
+ @property
143
+ def quote_columns(self) -> Optional[bool]:
144
+ return self.target.quote_columns
145
+
146
+ @classmethod
147
+ def from_yaml_block(cls, src: YamlBlock, target: Testable) -> "TestBlock[Testable]":
148
+ return cls(
149
+ file=src.file,
150
+ data=src.data,
151
+ target=target,
152
+ )
153
+
154
+
155
+ @dataclass
156
+ class VersionedTestBlock(TestBlock, Generic[Versioned]):
157
+ @property
158
+ def columns(self):
159
+ if not self.target.versions:
160
+ return super().columns
161
+ else:
162
+ raise DbtInternalError(".columns for VersionedTestBlock with versions")
163
+
164
+ @property
165
+ def data_tests(self) -> List[TestDef]:
166
+ if not self.target.versions:
167
+ return super().data_tests
168
+ else:
169
+ raise DbtInternalError(".data_tests for VersionedTestBlock with versions")
170
+
171
+ @classmethod
172
+ def from_yaml_block(cls, src: YamlBlock, target: Versioned) -> "VersionedTestBlock[Versioned]":
173
+ return cls(
174
+ file=src.file,
175
+ data=src.data,
176
+ target=target,
177
+ )
178
+
179
+
180
+ @dataclass
181
+ class GenericTestBlock(TestBlock[Testable], Generic[Testable]):
182
+ data_test: Dict[str, Any]
183
+ column_name: Optional[str]
184
+ tags: List[str]
185
+ version: Optional[NodeVersion]
186
+
187
+ @classmethod
188
+ def from_test_block(
189
+ cls,
190
+ src: TestBlock,
191
+ data_test: Dict[str, Any],
192
+ column_name: Optional[str],
193
+ tags: List[str],
194
+ version: Optional[NodeVersion],
195
+ ) -> "GenericTestBlock":
196
+ return cls(
197
+ file=src.file,
198
+ data=src.data,
199
+ target=src.target,
200
+ data_test=data_test,
201
+ column_name=column_name,
202
+ tags=tags,
203
+ version=version,
204
+ )
205
+
206
+
207
+ class ParserRef:
208
+ """A helper object to hold parse-time references."""
209
+
210
+ def __init__(self) -> None:
211
+ self.column_info: Dict[str, ColumnInfo] = {}
212
+
213
+ def _add(self, column: HasColumnProps) -> None:
214
+ tags: List[str] = getattr(column, "tags", [])
215
+ quote: Optional[bool] = None
216
+ granularity: Optional[TimeGranularity] = None
217
+ if isinstance(column, UnparsedColumn):
218
+ quote = column.quote
219
+ granularity = TimeGranularity(column.granularity) if column.granularity else None
220
+
221
+ if any(
222
+ c
223
+ for c in column.constraints
224
+ if "type" not in c or not ConstraintType.is_valid(c["type"])
225
+ ):
226
+ raise ParsingError(f"Invalid constraint type on column {column.name}")
227
+
228
+ # Merge meta and tags from column and config
229
+ column_config_meta = (
230
+ column.config["meta"] if isinstance(column.config.get("meta"), dict) else {}
231
+ )
232
+ column_config_tags = []
233
+ if "tags" in column.config:
234
+ if isinstance(column.config["tags"], list):
235
+ column_config_tags = column.config["tags"]
236
+ elif isinstance(column.config["tags"], str):
237
+ column_config_tags = [column.config["tags"]]
238
+
239
+ column_meta = {**column.meta, **column_config_meta}
240
+ column_tags = list(set(tags + column_config_tags))
241
+ self.column_info[column.name] = ColumnInfo(
242
+ name=column.name,
243
+ description=column.description,
244
+ data_type=column.data_type,
245
+ constraints=[ColumnLevelConstraint.from_dict(c) for c in column.constraints],
246
+ meta=column_meta,
247
+ tags=column_tags,
248
+ quote=quote,
249
+ _extra=column.extra,
250
+ granularity=granularity,
251
+ config=ColumnConfig(meta=column_meta, tags=column_tags),
252
+ )
253
+
254
+ @classmethod
255
+ def from_target(cls, target: Union[HasColumnDocs, HasColumnTests]) -> "ParserRef":
256
+ refs = cls()
257
+ for column in target.columns:
258
+ refs._add(column)
259
+ return refs
260
+
261
+ @classmethod
262
+ def from_versioned_target(cls, target: Versioned, version: NodeVersion) -> "ParserRef":
263
+ refs = cls()
264
+ for base_column in target.get_columns_for_version(version):
265
+ refs._add(base_column)
266
+ return refs
dbt/parser/docs.py ADDED
@@ -0,0 +1,52 @@
1
+ import re
2
+ from typing import Iterable, Optional
3
+
4
+ from dbt.clients.jinja import get_rendered
5
+ from dbt.contracts.files import SourceFile
6
+ from dbt.contracts.graph.nodes import Documentation
7
+ from dbt.node_types import NodeType
8
+ from dbt.parser.base import Parser
9
+ from dbt.parser.search import BlockContents, BlockSearcher, FileBlock
10
+
11
+ SHOULD_PARSE_RE = re.compile(r"{[{%]")
12
+
13
+
14
+ class DocumentationParser(Parser[Documentation]):
15
+ @property
16
+ def resource_type(self) -> NodeType:
17
+ return NodeType.Documentation
18
+
19
+ @classmethod
20
+ def get_compiled_path(cls, block: FileBlock):
21
+ return block.path.relative_path
22
+
23
+ def generate_unique_id(self, resource_name: str, _: Optional[str] = None) -> str:
24
+ # For consistency, use the same format for doc unique_ids
25
+ return f"doc.{self.project.project_name}.{resource_name}"
26
+
27
+ def parse_block(self, block: BlockContents) -> Iterable[Documentation]:
28
+ unique_id = self.generate_unique_id(block.name)
29
+ contents = get_rendered(block.contents, {}).strip()
30
+
31
+ doc = Documentation(
32
+ path=block.file.path.relative_path,
33
+ original_file_path=block.path.original_file_path,
34
+ package_name=self.project.project_name,
35
+ unique_id=unique_id,
36
+ name=block.name,
37
+ block_contents=contents,
38
+ resource_type=NodeType.Documentation,
39
+ )
40
+ return [doc]
41
+
42
+ def parse_file(self, file_block: FileBlock):
43
+ assert isinstance(file_block.file, SourceFile)
44
+ searcher: Iterable[BlockContents] = BlockSearcher(
45
+ source=[file_block],
46
+ allowed_blocks={"docs"},
47
+ source_tag_factory=BlockContents,
48
+ check_jinja=False,
49
+ )
50
+ for block in searcher:
51
+ for parsed in self.parse_block(block):
52
+ self.manifest.add_doc(file_block.file, parsed)
dbt/parser/fixtures.py ADDED
@@ -0,0 +1,51 @@
1
+ import csv
2
+ from io import StringIO
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ from dbt.contracts.files import FixtureSourceFile
6
+ from dbt.contracts.graph.nodes import UnitTestFileFixture
7
+ from dbt.node_types import NodeType
8
+ from dbt.parser.base import Parser
9
+ from dbt.parser.search import FileBlock
10
+
11
+
12
+ class FixtureParser(Parser[UnitTestFileFixture]):
13
+ @property
14
+ def resource_type(self) -> NodeType:
15
+ return NodeType.Fixture
16
+
17
+ @classmethod
18
+ def get_compiled_path(cls, block: FileBlock):
19
+ # Is this necessary?
20
+ return block.path.relative_path
21
+
22
+ def generate_unique_id(self, resource_name: str, _: Optional[str] = None) -> str:
23
+ return f"fixture.{self.project.project_name}.{resource_name}"
24
+
25
+ def parse_file(self, file_block: FileBlock):
26
+ assert isinstance(file_block.file, FixtureSourceFile)
27
+ unique_id = self.generate_unique_id(file_block.name)
28
+
29
+ if file_block.file.path.relative_path.endswith(".sql"):
30
+ rows = file_block.file.contents # type: ignore
31
+ else: # endswith('.csv')
32
+ rows = self.get_rows(file_block.file.contents) # type: ignore
33
+
34
+ fixture = UnitTestFileFixture(
35
+ name=file_block.name,
36
+ path=file_block.file.path.relative_path,
37
+ original_file_path=file_block.path.original_file_path,
38
+ package_name=self.project.project_name,
39
+ unique_id=unique_id,
40
+ resource_type=NodeType.Fixture,
41
+ rows=rows,
42
+ )
43
+ self.manifest.add_fixture(file_block.file, fixture)
44
+
45
+ def get_rows(self, contents) -> List[Dict[str, Any]]:
46
+ rows = []
47
+ dummy_file = StringIO(contents)
48
+ reader = csv.DictReader(dummy_file)
49
+ for row in reader:
50
+ rows.append(row)
51
+ return rows
@@ -0,0 +1,30 @@
1
+ from dbt.artifacts.resources.types import NodeType
2
+ from dbt.contracts.graph.nodes import FunctionNode, ManifestNode
3
+ from dbt.parser.base import SimpleParser
4
+ from dbt.parser.search import FileBlock
5
+
6
+
7
+ class FunctionParser(SimpleParser[FileBlock, FunctionNode]):
8
+ def parse_from_dict(self, dct, validate=True) -> FunctionNode:
9
+ if validate:
10
+ FunctionNode.validate(dct)
11
+ return FunctionNode.from_dict(dct)
12
+
13
+ @property
14
+ def resource_type(self) -> NodeType:
15
+ return NodeType.Function
16
+
17
+ @classmethod
18
+ def get_compiled_path(cls, block: FileBlock):
19
+ return block.path.relative_path
20
+
21
+ # overrides SimpleSQLParser.add_result_node
22
+ def add_result_node(self, block: FileBlock, node: ManifestNode):
23
+ assert isinstance(node, FunctionNode), "Got non FunctionNode in FunctionParser"
24
+ if node.config.enabled:
25
+ self.manifest.add_function(node)
26
+ else:
27
+ self.manifest.add_disabled(block.file, node)
28
+
29
+ def parse_file(self, file_block: FileBlock) -> None:
30
+ self.parse_node(file_block)
@@ -0,0 +1,100 @@
1
+ from typing import Iterable, List
2
+
3
+ import jinja2
4
+
5
+ from dbt.contracts.files import SourceFile
6
+ from dbt.contracts.graph.nodes import GenericTestNode, Macro
7
+ from dbt.contracts.graph.unparsed import UnparsedMacro
8
+ from dbt.exceptions import ParsingError
9
+ from dbt.node_types import NodeType
10
+ from dbt.parser.base import BaseParser
11
+ from dbt.parser.search import FileBlock
12
+ from dbt_common.clients import jinja
13
+ from dbt_common.utils import MACRO_PREFIX
14
+
15
+
16
+ class GenericTestParser(BaseParser[GenericTestNode]):
17
+ @property
18
+ def resource_type(self) -> NodeType:
19
+ return NodeType.Macro
20
+
21
+ @classmethod
22
+ def get_compiled_path(cls, block: FileBlock):
23
+ return block.path.relative_path
24
+
25
+ def create_generic_test_macro(
26
+ self, block: jinja.BlockTag, base_node: UnparsedMacro, name: str
27
+ ) -> Macro:
28
+ unique_id = self.generate_unique_id(name)
29
+ macro_sql = block.full_block or ""
30
+
31
+ return Macro(
32
+ path=base_node.path,
33
+ macro_sql=macro_sql,
34
+ original_file_path=base_node.original_file_path,
35
+ package_name=base_node.package_name,
36
+ resource_type=base_node.resource_type,
37
+ name=name,
38
+ unique_id=unique_id,
39
+ )
40
+
41
+ def parse_unparsed_generic_test(self, base_node: UnparsedMacro) -> Iterable[Macro]:
42
+ try:
43
+ blocks: List[jinja.BlockTag] = [
44
+ t
45
+ for t in jinja.extract_toplevel_blocks(
46
+ base_node.raw_code,
47
+ allowed_blocks={"test", "data_test"},
48
+ collect_raw_data=False,
49
+ )
50
+ if isinstance(t, jinja.BlockTag)
51
+ ]
52
+ except ParsingError as exc:
53
+ exc.add_node(base_node)
54
+ raise
55
+
56
+ for block in blocks:
57
+ try:
58
+ ast = jinja.parse(block.full_block)
59
+ except ParsingError as e:
60
+ e.add_node(base_node)
61
+ raise
62
+
63
+ # generic tests are structured as macros so we want to count the number of macro blocks
64
+ generic_test_nodes = list(ast.find_all(jinja2.nodes.Macro))
65
+
66
+ if len(generic_test_nodes) != 1:
67
+ # things have gone disastrously wrong, we thought we only
68
+ # parsed one block!
69
+ raise ParsingError(
70
+ f"Found multiple generic tests in {block.full_block}, expected 1",
71
+ node=base_node,
72
+ )
73
+
74
+ generic_test_name = generic_test_nodes[0].name
75
+
76
+ if not generic_test_name.startswith(MACRO_PREFIX):
77
+ continue
78
+
79
+ name: str = generic_test_name.replace(MACRO_PREFIX, "")
80
+ node = self.create_generic_test_macro(block, base_node, name)
81
+ yield node
82
+
83
+ def parse_file(self, block: FileBlock):
84
+ assert isinstance(block.file, SourceFile)
85
+ source_file = block.file
86
+ assert isinstance(source_file.contents, str)
87
+ original_file_path = source_file.path.original_file_path
88
+
89
+ # this is really only used for error messages
90
+ base_node = UnparsedMacro(
91
+ path=original_file_path,
92
+ original_file_path=original_file_path,
93
+ package_name=self.project.project_name,
94
+ raw_code=source_file.contents,
95
+ resource_type=NodeType.Macro,
96
+ language="sql",
97
+ )
98
+
99
+ for node in self.parse_unparsed_generic_test(base_node):
100
+ self.manifest.add_macro(block.file, node)