dvt-core 1.11.0b4__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.

Potentially problematic release.


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

Files changed (261) hide show
  1. dvt/__init__.py +7 -0
  2. dvt/_pydantic_shim.py +26 -0
  3. dvt/adapters/__init__.py +16 -0
  4. dvt/adapters/multi_adapter_manager.py +268 -0
  5. dvt/artifacts/__init__.py +0 -0
  6. dvt/artifacts/exceptions/__init__.py +1 -0
  7. dvt/artifacts/exceptions/schemas.py +31 -0
  8. dvt/artifacts/resources/__init__.py +116 -0
  9. dvt/artifacts/resources/base.py +68 -0
  10. dvt/artifacts/resources/types.py +93 -0
  11. dvt/artifacts/resources/v1/analysis.py +10 -0
  12. dvt/artifacts/resources/v1/catalog.py +23 -0
  13. dvt/artifacts/resources/v1/components.py +275 -0
  14. dvt/artifacts/resources/v1/config.py +282 -0
  15. dvt/artifacts/resources/v1/documentation.py +11 -0
  16. dvt/artifacts/resources/v1/exposure.py +52 -0
  17. dvt/artifacts/resources/v1/function.py +53 -0
  18. dvt/artifacts/resources/v1/generic_test.py +32 -0
  19. dvt/artifacts/resources/v1/group.py +22 -0
  20. dvt/artifacts/resources/v1/hook.py +11 -0
  21. dvt/artifacts/resources/v1/macro.py +30 -0
  22. dvt/artifacts/resources/v1/metric.py +173 -0
  23. dvt/artifacts/resources/v1/model.py +146 -0
  24. dvt/artifacts/resources/v1/owner.py +10 -0
  25. dvt/artifacts/resources/v1/saved_query.py +112 -0
  26. dvt/artifacts/resources/v1/seed.py +42 -0
  27. dvt/artifacts/resources/v1/semantic_layer_components.py +72 -0
  28. dvt/artifacts/resources/v1/semantic_model.py +315 -0
  29. dvt/artifacts/resources/v1/singular_test.py +14 -0
  30. dvt/artifacts/resources/v1/snapshot.py +92 -0
  31. dvt/artifacts/resources/v1/source_definition.py +85 -0
  32. dvt/artifacts/resources/v1/sql_operation.py +10 -0
  33. dvt/artifacts/resources/v1/unit_test_definition.py +78 -0
  34. dvt/artifacts/schemas/__init__.py +0 -0
  35. dvt/artifacts/schemas/base.py +191 -0
  36. dvt/artifacts/schemas/batch_results.py +24 -0
  37. dvt/artifacts/schemas/catalog/__init__.py +12 -0
  38. dvt/artifacts/schemas/catalog/v1/__init__.py +0 -0
  39. dvt/artifacts/schemas/catalog/v1/catalog.py +60 -0
  40. dvt/artifacts/schemas/freshness/__init__.py +1 -0
  41. dvt/artifacts/schemas/freshness/v3/__init__.py +0 -0
  42. dvt/artifacts/schemas/freshness/v3/freshness.py +159 -0
  43. dvt/artifacts/schemas/manifest/__init__.py +2 -0
  44. dvt/artifacts/schemas/manifest/v12/__init__.py +0 -0
  45. dvt/artifacts/schemas/manifest/v12/manifest.py +212 -0
  46. dvt/artifacts/schemas/results.py +148 -0
  47. dvt/artifacts/schemas/run/__init__.py +2 -0
  48. dvt/artifacts/schemas/run/v5/__init__.py +0 -0
  49. dvt/artifacts/schemas/run/v5/run.py +184 -0
  50. dvt/artifacts/schemas/upgrades/__init__.py +4 -0
  51. dvt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
  52. dvt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
  53. dvt/artifacts/utils/validation.py +153 -0
  54. dvt/cli/__init__.py +1 -0
  55. dvt/cli/context.py +16 -0
  56. dvt/cli/exceptions.py +56 -0
  57. dvt/cli/flags.py +558 -0
  58. dvt/cli/main.py +971 -0
  59. dvt/cli/option_types.py +121 -0
  60. dvt/cli/options.py +79 -0
  61. dvt/cli/params.py +803 -0
  62. dvt/cli/requires.py +478 -0
  63. dvt/cli/resolvers.py +32 -0
  64. dvt/cli/types.py +40 -0
  65. dvt/clients/__init__.py +0 -0
  66. dvt/clients/checked_load.py +82 -0
  67. dvt/clients/git.py +164 -0
  68. dvt/clients/jinja.py +206 -0
  69. dvt/clients/jinja_static.py +245 -0
  70. dvt/clients/registry.py +192 -0
  71. dvt/clients/yaml_helper.py +68 -0
  72. dvt/compilation.py +833 -0
  73. dvt/compute/__init__.py +26 -0
  74. dvt/compute/base.py +288 -0
  75. dvt/compute/engines/__init__.py +13 -0
  76. dvt/compute/engines/duckdb_engine.py +368 -0
  77. dvt/compute/engines/spark_engine.py +273 -0
  78. dvt/compute/query_analyzer.py +212 -0
  79. dvt/compute/router.py +483 -0
  80. dvt/config/__init__.py +4 -0
  81. dvt/config/catalogs.py +95 -0
  82. dvt/config/compute_config.py +406 -0
  83. dvt/config/profile.py +411 -0
  84. dvt/config/profiles_v2.py +464 -0
  85. dvt/config/project.py +893 -0
  86. dvt/config/renderer.py +232 -0
  87. dvt/config/runtime.py +491 -0
  88. dvt/config/selectors.py +209 -0
  89. dvt/config/utils.py +78 -0
  90. dvt/connectors/.gitignore +6 -0
  91. dvt/connectors/README.md +306 -0
  92. dvt/connectors/catalog.yml +217 -0
  93. dvt/connectors/download_connectors.py +300 -0
  94. dvt/constants.py +29 -0
  95. dvt/context/__init__.py +0 -0
  96. dvt/context/base.py +746 -0
  97. dvt/context/configured.py +136 -0
  98. dvt/context/context_config.py +350 -0
  99. dvt/context/docs.py +82 -0
  100. dvt/context/exceptions_jinja.py +179 -0
  101. dvt/context/macro_resolver.py +195 -0
  102. dvt/context/macros.py +171 -0
  103. dvt/context/manifest.py +73 -0
  104. dvt/context/providers.py +2198 -0
  105. dvt/context/query_header.py +14 -0
  106. dvt/context/secret.py +59 -0
  107. dvt/context/target.py +74 -0
  108. dvt/contracts/__init__.py +0 -0
  109. dvt/contracts/files.py +413 -0
  110. dvt/contracts/graph/__init__.py +0 -0
  111. dvt/contracts/graph/manifest.py +1904 -0
  112. dvt/contracts/graph/metrics.py +98 -0
  113. dvt/contracts/graph/model_config.py +71 -0
  114. dvt/contracts/graph/node_args.py +42 -0
  115. dvt/contracts/graph/nodes.py +1806 -0
  116. dvt/contracts/graph/semantic_manifest.py +233 -0
  117. dvt/contracts/graph/unparsed.py +812 -0
  118. dvt/contracts/project.py +417 -0
  119. dvt/contracts/results.py +53 -0
  120. dvt/contracts/selection.py +23 -0
  121. dvt/contracts/sql.py +86 -0
  122. dvt/contracts/state.py +69 -0
  123. dvt/contracts/util.py +46 -0
  124. dvt/deprecations.py +347 -0
  125. dvt/deps/__init__.py +0 -0
  126. dvt/deps/base.py +153 -0
  127. dvt/deps/git.py +196 -0
  128. dvt/deps/local.py +80 -0
  129. dvt/deps/registry.py +131 -0
  130. dvt/deps/resolver.py +149 -0
  131. dvt/deps/tarball.py +121 -0
  132. dvt/docs/source/_ext/dbt_click.py +118 -0
  133. dvt/docs/source/conf.py +32 -0
  134. dvt/env_vars.py +64 -0
  135. dvt/event_time/event_time.py +40 -0
  136. dvt/event_time/sample_window.py +60 -0
  137. dvt/events/__init__.py +16 -0
  138. dvt/events/base_types.py +37 -0
  139. dvt/events/core_types_pb2.py +2 -0
  140. dvt/events/logging.py +109 -0
  141. dvt/events/types.py +2534 -0
  142. dvt/exceptions.py +1487 -0
  143. dvt/flags.py +89 -0
  144. dvt/graph/__init__.py +11 -0
  145. dvt/graph/cli.py +248 -0
  146. dvt/graph/graph.py +172 -0
  147. dvt/graph/queue.py +213 -0
  148. dvt/graph/selector.py +375 -0
  149. dvt/graph/selector_methods.py +976 -0
  150. dvt/graph/selector_spec.py +223 -0
  151. dvt/graph/thread_pool.py +18 -0
  152. dvt/hooks.py +21 -0
  153. dvt/include/README.md +49 -0
  154. dvt/include/__init__.py +3 -0
  155. dvt/include/global_project.py +4 -0
  156. dvt/include/starter_project/.gitignore +4 -0
  157. dvt/include/starter_project/README.md +15 -0
  158. dvt/include/starter_project/__init__.py +3 -0
  159. dvt/include/starter_project/analyses/.gitkeep +0 -0
  160. dvt/include/starter_project/dvt_project.yml +36 -0
  161. dvt/include/starter_project/macros/.gitkeep +0 -0
  162. dvt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
  163. dvt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
  164. dvt/include/starter_project/models/example/schema.yml +21 -0
  165. dvt/include/starter_project/seeds/.gitkeep +0 -0
  166. dvt/include/starter_project/snapshots/.gitkeep +0 -0
  167. dvt/include/starter_project/tests/.gitkeep +0 -0
  168. dvt/internal_deprecations.py +27 -0
  169. dvt/jsonschemas/__init__.py +3 -0
  170. dvt/jsonschemas/jsonschemas.py +309 -0
  171. dvt/jsonschemas/project/0.0.110.json +4717 -0
  172. dvt/jsonschemas/project/0.0.85.json +2015 -0
  173. dvt/jsonschemas/resources/0.0.110.json +2636 -0
  174. dvt/jsonschemas/resources/0.0.85.json +2536 -0
  175. dvt/jsonschemas/resources/latest.json +6773 -0
  176. dvt/links.py +4 -0
  177. dvt/materializations/__init__.py +0 -0
  178. dvt/materializations/incremental/__init__.py +0 -0
  179. dvt/materializations/incremental/microbatch.py +235 -0
  180. dvt/mp_context.py +8 -0
  181. dvt/node_types.py +37 -0
  182. dvt/parser/__init__.py +23 -0
  183. dvt/parser/analysis.py +21 -0
  184. dvt/parser/base.py +549 -0
  185. dvt/parser/common.py +267 -0
  186. dvt/parser/docs.py +52 -0
  187. dvt/parser/fixtures.py +51 -0
  188. dvt/parser/functions.py +30 -0
  189. dvt/parser/generic_test.py +100 -0
  190. dvt/parser/generic_test_builders.py +334 -0
  191. dvt/parser/hooks.py +119 -0
  192. dvt/parser/macros.py +137 -0
  193. dvt/parser/manifest.py +2204 -0
  194. dvt/parser/models.py +574 -0
  195. dvt/parser/partial.py +1179 -0
  196. dvt/parser/read_files.py +445 -0
  197. dvt/parser/schema_generic_tests.py +423 -0
  198. dvt/parser/schema_renderer.py +111 -0
  199. dvt/parser/schema_yaml_readers.py +936 -0
  200. dvt/parser/schemas.py +1467 -0
  201. dvt/parser/search.py +149 -0
  202. dvt/parser/seeds.py +28 -0
  203. dvt/parser/singular_test.py +20 -0
  204. dvt/parser/snapshots.py +44 -0
  205. dvt/parser/sources.py +557 -0
  206. dvt/parser/sql.py +63 -0
  207. dvt/parser/unit_tests.py +622 -0
  208. dvt/plugins/__init__.py +20 -0
  209. dvt/plugins/contracts.py +10 -0
  210. dvt/plugins/exceptions.py +2 -0
  211. dvt/plugins/manager.py +164 -0
  212. dvt/plugins/manifest.py +21 -0
  213. dvt/profiler.py +20 -0
  214. dvt/py.typed +1 -0
  215. dvt/runners/__init__.py +2 -0
  216. dvt/runners/exposure_runner.py +7 -0
  217. dvt/runners/no_op_runner.py +46 -0
  218. dvt/runners/saved_query_runner.py +7 -0
  219. dvt/selected_resources.py +8 -0
  220. dvt/task/__init__.py +0 -0
  221. dvt/task/base.py +504 -0
  222. dvt/task/build.py +197 -0
  223. dvt/task/clean.py +57 -0
  224. dvt/task/clone.py +162 -0
  225. dvt/task/compile.py +151 -0
  226. dvt/task/compute.py +366 -0
  227. dvt/task/debug.py +650 -0
  228. dvt/task/deps.py +280 -0
  229. dvt/task/docs/__init__.py +3 -0
  230. dvt/task/docs/generate.py +408 -0
  231. dvt/task/docs/index.html +250 -0
  232. dvt/task/docs/serve.py +28 -0
  233. dvt/task/freshness.py +323 -0
  234. dvt/task/function.py +122 -0
  235. dvt/task/group_lookup.py +46 -0
  236. dvt/task/init.py +374 -0
  237. dvt/task/list.py +237 -0
  238. dvt/task/printer.py +176 -0
  239. dvt/task/profiles.py +256 -0
  240. dvt/task/retry.py +175 -0
  241. dvt/task/run.py +1146 -0
  242. dvt/task/run_operation.py +142 -0
  243. dvt/task/runnable.py +802 -0
  244. dvt/task/seed.py +104 -0
  245. dvt/task/show.py +150 -0
  246. dvt/task/snapshot.py +57 -0
  247. dvt/task/sql.py +111 -0
  248. dvt/task/test.py +464 -0
  249. dvt/tests/fixtures/__init__.py +1 -0
  250. dvt/tests/fixtures/project.py +620 -0
  251. dvt/tests/util.py +651 -0
  252. dvt/tracking.py +529 -0
  253. dvt/utils/__init__.py +3 -0
  254. dvt/utils/artifact_upload.py +151 -0
  255. dvt/utils/utils.py +408 -0
  256. dvt/version.py +249 -0
  257. dvt_core-1.11.0b4.dist-info/METADATA +252 -0
  258. dvt_core-1.11.0b4.dist-info/RECORD +261 -0
  259. dvt_core-1.11.0b4.dist-info/WHEEL +5 -0
  260. dvt_core-1.11.0b4.dist-info/entry_points.txt +2 -0
  261. dvt_core-1.11.0b4.dist-info/top_level.txt +1 -0
dvt/config/renderer.py ADDED
@@ -0,0 +1,232 @@
1
+ import re
2
+ from datetime import date
3
+ from typing import Any, Callable, Dict, Optional, Tuple, Union
4
+
5
+ from dvt.clients.jinja import get_rendered
6
+ from dvt.constants import DEPENDENCIES_FILE_NAME, SECRET_PLACEHOLDER
7
+ from dvt.context.base import BaseContext
8
+ from dvt.context.secret import SecretContext
9
+ from dvt.context.target import TargetContext
10
+ from dvt.exceptions import DbtProjectError
11
+
12
+ from dbt.adapters.contracts.connection import HasCredentials
13
+ from dbt_common.clients.jinja import catch_jinja
14
+ from dbt_common.constants import SECRET_ENV_PREFIX
15
+ from dbt_common.context import get_invocation_context
16
+ from dbt_common.exceptions import CompilationError, RecursionError
17
+ from dbt_common.utils import deep_map_render
18
+
19
+ Keypath = Tuple[Union[str, int], ...]
20
+
21
+
22
+ class BaseRenderer:
23
+ def __init__(self, context: Dict[str, Any]) -> None:
24
+ self.context = context
25
+
26
+ @property
27
+ def name(self):
28
+ return "Rendering"
29
+
30
+ def should_render_keypath(self, keypath: Keypath) -> bool:
31
+ return True
32
+
33
+ def render_entry(self, value: Any, keypath: Keypath) -> Any:
34
+ if not self.should_render_keypath(keypath):
35
+ return value
36
+
37
+ return self.render_value(value, keypath)
38
+
39
+ def render_value(self, value: Any, keypath: Optional[Keypath] = None) -> Any:
40
+ # keypath is ignored (and someone who knows should explain why here)
41
+ if not isinstance(value, str):
42
+ return value if not isinstance(value, date) else value.isoformat()
43
+
44
+ try:
45
+ with catch_jinja():
46
+ return get_rendered(value, self.context, native=True)
47
+ except CompilationError as exc:
48
+ msg = f"Could not render {value}: {exc.msg}"
49
+ raise CompilationError(msg) from exc
50
+
51
+ def render_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
52
+ try:
53
+ return deep_map_render(self.render_entry, data)
54
+ except RecursionError:
55
+ raise DbtProjectError(
56
+ f"Cycle detected: {self.name} input has a reference to itself", project=data
57
+ )
58
+
59
+
60
+ def _list_if_none(value):
61
+ if value is None:
62
+ value = []
63
+ return value
64
+
65
+
66
+ def _dict_if_none(value):
67
+ if value is None:
68
+ value = {}
69
+ return value
70
+
71
+
72
+ def _list_if_none_or_string(value):
73
+ value = _list_if_none(value)
74
+ if isinstance(value, str):
75
+ return [value]
76
+ return value
77
+
78
+
79
+ class ProjectPostprocessor(Dict[Keypath, Callable[[Any], Any]]):
80
+ def __init__(self) -> None:
81
+ super().__init__()
82
+
83
+ self[("on-run-start",)] = _list_if_none_or_string
84
+ self[("on-run-end",)] = _list_if_none_or_string
85
+
86
+ for k in ("models", "seeds", "snapshots"):
87
+ self[(k,)] = _dict_if_none
88
+ self[(k, "vars")] = _dict_if_none
89
+ self[(k, "pre-hook")] = _list_if_none_or_string
90
+ self[(k, "post-hook")] = _list_if_none_or_string
91
+ self[("seeds", "column_types")] = _dict_if_none
92
+
93
+ def postprocess(self, value: Any, key: Keypath) -> Any:
94
+ if key in self:
95
+ handler = self[key]
96
+ return handler(value)
97
+
98
+ return value
99
+
100
+
101
+ class DbtProjectYamlRenderer(BaseRenderer):
102
+ _KEYPATH_HANDLERS = ProjectPostprocessor()
103
+
104
+ def __init__(
105
+ self, profile: Optional[HasCredentials] = None, cli_vars: Optional[Dict[str, Any]] = None
106
+ ) -> None:
107
+ # Generate contexts here because we want to save the context
108
+ # object in order to retrieve the env_vars. This is almost always
109
+ # a TargetContext, but in the debug task we want a project
110
+ # even when we don't have a profile.
111
+ if cli_vars is None:
112
+ cli_vars = {}
113
+ if profile:
114
+ self.ctx_obj = TargetContext(profile.to_target_dict(), cli_vars)
115
+ else:
116
+ self.ctx_obj = BaseContext(cli_vars) # type:ignore
117
+ context = self.ctx_obj.to_dict()
118
+ super().__init__(context)
119
+
120
+ @property
121
+ def name(self):
122
+ "Project config"
123
+
124
+ # Uses SecretRenderer
125
+ def get_package_renderer(self) -> BaseRenderer:
126
+ return PackageRenderer(self.ctx_obj.cli_vars)
127
+
128
+ def render_project(
129
+ self,
130
+ project: Dict[str, Any],
131
+ project_root: str,
132
+ ) -> Dict[str, Any]:
133
+ """Render the project and insert the project root after rendering."""
134
+ rendered_project = self.render_data(project)
135
+ rendered_project["project-root"] = project_root
136
+ return rendered_project
137
+
138
+ def render_packages(self, packages: Dict[str, Any], packages_specified_path: str):
139
+ """Render the given packages dict"""
140
+ packages = packages or {} # Sometimes this is none in tests
141
+ package_renderer = self.get_package_renderer()
142
+ if packages_specified_path == DEPENDENCIES_FILE_NAME:
143
+ # We don't want to render the "packages" dictionary that came from dependencies.yml
144
+ return packages
145
+ else:
146
+ return package_renderer.render_data(packages)
147
+
148
+ def render_selectors(self, selectors: Dict[str, Any]):
149
+ return self.render_data(selectors)
150
+
151
+ def render_entry(self, value: Any, keypath: Keypath) -> Any:
152
+ result = super().render_entry(value, keypath)
153
+ return self._KEYPATH_HANDLERS.postprocess(result, keypath)
154
+
155
+ def should_render_keypath(self, keypath: Keypath) -> bool:
156
+ if not keypath:
157
+ return True
158
+
159
+ first = keypath[0]
160
+ # run hooks are not rendered
161
+ if first in {"on-run-start", "on-run-end", "query-comment"}:
162
+ return False
163
+
164
+ # don't render vars blocks until runtime
165
+ if first == "vars":
166
+ return False
167
+
168
+ if first in {"seeds", "models", "snapshots", "tests", "data_tests"}:
169
+ keypath_parts = {(k.lstrip("+ ") if isinstance(k, str) else k) for k in keypath}
170
+ # model-level hooks
171
+ late_rendered_hooks = {"pre-hook", "post-hook", "pre_hook", "post_hook"}
172
+ if keypath_parts.intersection(late_rendered_hooks):
173
+ return False
174
+
175
+ return True
176
+
177
+
178
+ class SecretRenderer(BaseRenderer):
179
+ def __init__(self, cli_vars: Dict[str, Any] = {}) -> None:
180
+ # Generate contexts here because we want to save the context
181
+ # object in order to retrieve the env_vars.
182
+ self.ctx_obj = SecretContext(cli_vars)
183
+ context = self.ctx_obj.to_dict()
184
+ super().__init__(context)
185
+
186
+ @property
187
+ def name(self):
188
+ return "Secret"
189
+
190
+ def render_value(self, value: Any, keypath: Optional[Keypath] = None) -> Any:
191
+ # First, standard Jinja rendering, with special handling for 'secret' environment variables
192
+ # "{{ env_var('DBT_SECRET_ENV_VAR') }}" -> "$$$DBT_SECRET_START$$$DBT_SECRET_ENV_{VARIABLE_NAME}$$$DBT_SECRET_END$$$"
193
+ # This prevents Jinja manipulation of secrets via macros/filters that might leak partial/modified values in logs
194
+
195
+ try:
196
+ rendered = super().render_value(value, keypath)
197
+ except Exception as ex:
198
+ if keypath and "password" in keypath:
199
+ # Passwords sometimes contain jinja-esque characters, but we
200
+ # don't want to render them if they aren't valid jinja.
201
+ rendered = value
202
+ else:
203
+ raise ex
204
+
205
+ # Now, detect instances of the placeholder value ($$$DBT_SECRET_START...DBT_SECRET_END$$$)
206
+ # and replace them with the actual secret value
207
+ if SECRET_ENV_PREFIX in str(rendered):
208
+ search_group = f"({SECRET_ENV_PREFIX}(.*))"
209
+ pattern = SECRET_PLACEHOLDER.format(search_group).replace("$", r"\$")
210
+ m = re.search(
211
+ pattern,
212
+ rendered,
213
+ )
214
+ if m:
215
+ found = m.group(1)
216
+ value = get_invocation_context().env[found]
217
+ replace_this = SECRET_PLACEHOLDER.format(found)
218
+ return rendered.replace(replace_this, value)
219
+ else:
220
+ return rendered
221
+
222
+
223
+ class ProfileRenderer(SecretRenderer):
224
+ @property
225
+ def name(self):
226
+ return "Profile"
227
+
228
+
229
+ class PackageRenderer(SecretRenderer):
230
+ @property
231
+ def name(self):
232
+ return "Packages config"