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/deprecations.py ADDED
@@ -0,0 +1,347 @@
1
+ import abc
2
+ from collections import defaultdict
3
+ from dataclasses import dataclass
4
+ from typing import Any, Callable, ClassVar, DefaultDict, Dict, List, Optional
5
+
6
+ import dvt.tracking
7
+ from dvt.events import types as core_types
8
+ from dvt.flags import get_flags
9
+
10
+ from dbt_common.dataclass_schema import dbtClassMixin
11
+ from dbt_common.events.functions import fire_event, warn_or_error
12
+ from dbt_common.events.types import Note
13
+
14
+
15
+ class DBTDeprecation:
16
+ _name: ClassVar[Optional[str]] = None
17
+ _event: ClassVar[Optional[str]] = None
18
+ _is_preview: ClassVar[bool] = False
19
+
20
+ @property
21
+ def name(self) -> str:
22
+ if self._name is not None:
23
+ return self._name
24
+ raise NotImplementedError("name not implemented for {}".format(self))
25
+
26
+ def track_deprecation_warn(self) -> None:
27
+ if dbt.tracking.active_user is not None:
28
+ dbt.tracking.track_deprecation_warn({"deprecation_name": self.name})
29
+
30
+ @property
31
+ def event(self) -> abc.ABCMeta:
32
+ if self._event is not None:
33
+ module_path = core_types
34
+ class_name = self._event
35
+
36
+ try:
37
+ return getattr(module_path, class_name)
38
+ except AttributeError:
39
+ msg = f"Event Class `{class_name}` is not defined in `{module_path}`"
40
+ raise NameError(msg)
41
+ raise NotImplementedError("event not implemented for {}".format(self._event))
42
+
43
+ def preview(self, base_event: abc.ABCMeta) -> None:
44
+ note_event = Note(msg=base_event.message()) # type: ignore
45
+ fire_event(note_event)
46
+
47
+ def show(self, *args, **kwargs) -> None:
48
+ if self._is_preview:
49
+ base_event = self.event(**kwargs)
50
+ self.preview(base_event)
51
+ else:
52
+ flags = get_flags()
53
+ if self.name not in active_deprecations or flags.show_all_deprecations:
54
+ event = self.event(**kwargs)
55
+ warn_or_error(event)
56
+ self.track_deprecation_warn()
57
+
58
+ active_deprecations[self.name] += 1
59
+
60
+
61
+ class PackageRedirectDeprecation(DBTDeprecation):
62
+ _name = "package-redirect"
63
+ _event = "PackageRedirectDeprecation"
64
+
65
+
66
+ class PackageInstallPathDeprecation(DBTDeprecation):
67
+ _name = "install-packages-path"
68
+ _event = "PackageInstallPathDeprecation"
69
+
70
+
71
+ # deprecations with a pattern of `project-config-*` for the name are not hardcoded
72
+ # they are called programatically via the pattern below
73
+ class ConfigSourcePathDeprecation(DBTDeprecation):
74
+ _name = "project-config-source-paths"
75
+ _event = "ConfigSourcePathDeprecation"
76
+
77
+
78
+ class ConfigDataPathDeprecation(DBTDeprecation):
79
+ _name = "project-config-data-paths"
80
+ _event = "ConfigDataPathDeprecation"
81
+
82
+
83
+ class ConfigLogPathDeprecation(DBTDeprecation):
84
+ _name = "project-config-log-path"
85
+ _event = "ConfigLogPathDeprecation"
86
+
87
+
88
+ class ConfigTargetPathDeprecation(DBTDeprecation):
89
+ _name = "project-config-target-path"
90
+ _event = "ConfigTargetPathDeprecation"
91
+
92
+
93
+ def renamed_method(old_name: str, new_name: str):
94
+ class AdapterDeprecationWarning(DBTDeprecation):
95
+ _name = "adapter:{}".format(old_name)
96
+ _event = "AdapterDeprecationWarning"
97
+
98
+ dep = AdapterDeprecationWarning()
99
+ deprecations_list.append(dep)
100
+ deprecations[dep.name] = dep
101
+
102
+
103
+ class MetricAttributesRenamed(DBTDeprecation):
104
+ _name = "metric-attr-renamed"
105
+ _event = "MetricAttributesRenamed"
106
+
107
+
108
+ class ExposureNameDeprecation(DBTDeprecation):
109
+ _name = "exposure-name"
110
+ _event = "ExposureNameDeprecation"
111
+
112
+
113
+ class CollectFreshnessReturnSignature(DBTDeprecation):
114
+ _name = "collect-freshness-return-signature"
115
+ _event = "CollectFreshnessReturnSignature"
116
+
117
+
118
+ class ProjectFlagsMovedDeprecation(DBTDeprecation):
119
+ _name = "project-flags-moved"
120
+ _event = "ProjectFlagsMovedDeprecation"
121
+
122
+
123
+ class PackageMaterializationOverrideDeprecation(DBTDeprecation):
124
+ _name = "package-materialization-override"
125
+ _event = "PackageMaterializationOverrideDeprecation"
126
+
127
+
128
+ class ResourceNamesWithSpacesDeprecation(DBTDeprecation):
129
+ _name = "resource-names-with-spaces"
130
+ _event = "ResourceNamesWithSpacesDeprecation"
131
+
132
+
133
+ class SourceFreshnessProjectHooksNotRun(DBTDeprecation):
134
+ _name = "source-freshness-project-hooks"
135
+ _event = "SourceFreshnessProjectHooksNotRun"
136
+
137
+
138
+ class MFTimespineWithoutYamlConfigurationDeprecation(DBTDeprecation):
139
+ _name = "mf-timespine-without-yaml-configuration"
140
+ _event = "MFTimespineWithoutYamlConfigurationDeprecation"
141
+
142
+
143
+ class MFCumulativeTypeParamsDeprecation(DBTDeprecation):
144
+ _name = "mf-cumulative-type-params-deprecation"
145
+ _event = "MFCumulativeTypeParamsDeprecation"
146
+
147
+
148
+ class MicrobatchMacroOutsideOfBatchesDeprecation(DBTDeprecation):
149
+ _name = "microbatch-macro-outside-of-batches-deprecation"
150
+ _event = "MicrobatchMacroOutsideOfBatchesDeprecation"
151
+
152
+
153
+ class GenericJSONSchemaValidationDeprecation(DBTDeprecation):
154
+ _name = "generic-json-schema-validation-deprecation"
155
+ _event = "GenericJSONSchemaValidationDeprecation"
156
+ _is_preview = True
157
+
158
+
159
+ class UnexpectedJinjaBlockDeprecation(DBTDeprecation):
160
+ _name = "unexpected-jinja-block-deprecation"
161
+ _event = "UnexpectedJinjaBlockDeprecation"
162
+
163
+
164
+ class DuplicateYAMLKeysDeprecation(DBTDeprecation):
165
+ _name = "duplicate-yaml-keys-deprecation"
166
+ _event = "DuplicateYAMLKeysDeprecation"
167
+
168
+
169
+ class CustomTopLevelKeyDeprecation(DBTDeprecation):
170
+ _name = "custom-top-level-key-deprecation"
171
+ _event = "CustomTopLevelKeyDeprecation"
172
+
173
+
174
+ class CustomKeyInConfigDeprecation(DBTDeprecation):
175
+ _name = "custom-key-in-config-deprecation"
176
+ _event = "CustomKeyInConfigDeprecation"
177
+
178
+
179
+ class CustomKeyInObjectDeprecation(DBTDeprecation):
180
+ _name = "custom-key-in-object-deprecation"
181
+ _event = "CustomKeyInObjectDeprecation"
182
+
183
+
184
+ class WEOInlcudeExcludeDeprecation(DBTDeprecation):
185
+ _name = "weo-include-exclude-deprecation"
186
+ _event = "WEOIncludeExcludeDeprecation"
187
+
188
+
189
+ class CustomOutputPathInSourceFreshnessDeprecation(DBTDeprecation):
190
+ _name = "custom-output-path-in-source-freshness-deprecation"
191
+ _event = "CustomOutputPathInSourceFreshnessDeprecation"
192
+
193
+
194
+ class SourceOverrideDeprecation(DBTDeprecation):
195
+ _name = "source-override-deprecation"
196
+ _event = "SourceOverrideDeprecation"
197
+
198
+
199
+ class PropertyMovedToConfigDeprecation(DBTDeprecation):
200
+ _name = "property-moved-to-config-deprecation"
201
+ _event = "PropertyMovedToConfigDeprecation"
202
+
203
+
204
+ class ModelParamUsageDeprecation(DBTDeprecation):
205
+ _name = "model-param-usage-deprecation"
206
+ _event = "ModelParamUsageDeprecation"
207
+
208
+
209
+ class EnvironmentVariableNamespaceDeprecation(DBTDeprecation):
210
+ _name = "environment-variable-namespace-deprecation"
211
+ _event = "EnvironmentVariableNamespaceDeprecation"
212
+
213
+
214
+ class MissingPlusPrefixDeprecation(DBTDeprecation):
215
+ _name = "missing-plus-prefix-in-config-deprecation"
216
+ _event = "MissingPlusPrefixDeprecation"
217
+
218
+
219
+ class ArgumentsPropertyInGenericTestDeprecation(DBTDeprecation):
220
+ _name = "arguments-property-in-generic-test-deprecation"
221
+ _event = "ArgumentsPropertyInGenericTestDeprecation"
222
+
223
+
224
+ class MissingArgumentsPropertyInGenericTestDeprecation(DBTDeprecation):
225
+ _name = "missing-arguments-property-in-generic-test-deprecation"
226
+ _event = "MissingArgumentsPropertyInGenericTestDeprecation"
227
+
228
+
229
+ class ModulesItertoolsUsageDeprecation(DBTDeprecation):
230
+ _name = "modules-itertools-usage-deprecation"
231
+ _event = "ModulesItertoolsUsageDeprecation"
232
+
233
+
234
+ def renamed_env_var(old_name: str, new_name: str):
235
+ class EnvironmentVariableRenamed(DBTDeprecation):
236
+ _name = f"environment-variable-renamed:{old_name}"
237
+ _event = "EnvironmentVariableRenamed"
238
+
239
+ dep = EnvironmentVariableRenamed()
240
+ deprecations_list.append(dep)
241
+ deprecations[dep.name] = dep
242
+
243
+ def cb():
244
+ dep.show(old_name=old_name, new_name=new_name)
245
+
246
+ return cb
247
+
248
+
249
+ def warn(name: str, *args, **kwargs) -> None:
250
+ if name not in deprecations:
251
+ # this should (hopefully) never happen
252
+ raise RuntimeError("Error showing deprecation warning: {}".format(name))
253
+
254
+ deprecations[name].show(*args, **kwargs)
255
+
256
+
257
+ def buffer(name: str, *args, **kwargs):
258
+ def show_callback():
259
+ deprecations[name].show(*args, **kwargs)
260
+
261
+ buffered_deprecations.append(show_callback)
262
+
263
+
264
+ def show_deprecations_summary() -> None:
265
+ summaries: List[Dict[str, Any]] = []
266
+ for deprecation, occurrences in active_deprecations.items():
267
+ deprecation_event = deprecations[deprecation].event()
268
+ summaries.append(
269
+ DeprecationSummary(
270
+ event_name=deprecation_event.__name__,
271
+ event_code=deprecation_event.code(),
272
+ occurrences=occurrences,
273
+ ).to_msg_dict()
274
+ )
275
+
276
+ if len(summaries) > 0:
277
+ show_all_hint = not get_flags().show_all_deprecations
278
+ warn_or_error(
279
+ core_types.DeprecationsSummary(summaries=summaries, show_all_hint=show_all_hint)
280
+ )
281
+
282
+
283
+ # these are globally available
284
+ # since modules are only imported once, active_deprecations is a singleton
285
+
286
+ active_deprecations: DefaultDict[str, int] = defaultdict(int)
287
+
288
+ deprecations_list: List[DBTDeprecation] = [
289
+ PackageRedirectDeprecation(),
290
+ PackageInstallPathDeprecation(),
291
+ ConfigSourcePathDeprecation(),
292
+ ConfigDataPathDeprecation(),
293
+ ExposureNameDeprecation(),
294
+ ConfigLogPathDeprecation(),
295
+ ConfigTargetPathDeprecation(),
296
+ CollectFreshnessReturnSignature(),
297
+ ProjectFlagsMovedDeprecation(),
298
+ PackageMaterializationOverrideDeprecation(),
299
+ ResourceNamesWithSpacesDeprecation(),
300
+ SourceFreshnessProjectHooksNotRun(),
301
+ MFTimespineWithoutYamlConfigurationDeprecation(),
302
+ MFCumulativeTypeParamsDeprecation(),
303
+ MicrobatchMacroOutsideOfBatchesDeprecation(),
304
+ GenericJSONSchemaValidationDeprecation(),
305
+ UnexpectedJinjaBlockDeprecation(),
306
+ DuplicateYAMLKeysDeprecation(),
307
+ CustomTopLevelKeyDeprecation(),
308
+ CustomKeyInConfigDeprecation(),
309
+ CustomKeyInObjectDeprecation(),
310
+ CustomOutputPathInSourceFreshnessDeprecation(),
311
+ PropertyMovedToConfigDeprecation(),
312
+ ModelParamUsageDeprecation(),
313
+ WEOInlcudeExcludeDeprecation(),
314
+ SourceOverrideDeprecation(),
315
+ EnvironmentVariableNamespaceDeprecation(),
316
+ MissingPlusPrefixDeprecation(),
317
+ ArgumentsPropertyInGenericTestDeprecation(),
318
+ MissingArgumentsPropertyInGenericTestDeprecation(),
319
+ ModulesItertoolsUsageDeprecation(),
320
+ ]
321
+
322
+ deprecations: Dict[str, DBTDeprecation] = {d.name: d for d in deprecations_list}
323
+
324
+ buffered_deprecations: List[Callable] = []
325
+
326
+
327
+ def reset_deprecations():
328
+ active_deprecations.clear()
329
+
330
+
331
+ def fire_buffered_deprecations():
332
+ [dep_fn() for dep_fn in buffered_deprecations]
333
+ buffered_deprecations.clear()
334
+
335
+
336
+ @dataclass
337
+ class DeprecationSummary(dbtClassMixin):
338
+ event_name: str
339
+ event_code: str
340
+ occurrences: int
341
+
342
+ def to_msg_dict(self) -> Dict[str, Any]:
343
+ return {
344
+ "event_name": self.event_name,
345
+ "event_code": self.event_code,
346
+ "occurrences": self.occurrences,
347
+ }
dvt/deps/__init__.py ADDED
File without changes
dvt/deps/base.py ADDED
@@ -0,0 +1,153 @@
1
+ import abc
2
+ import functools
3
+ import os
4
+ import tempfile
5
+ from contextlib import contextmanager
6
+ from pathlib import Path
7
+ from typing import Dict, Generic, List, Optional, TypeVar
8
+
9
+ from dvt.contracts.project import ProjectPackageMetadata
10
+ from dvt.events.types import DepsSetDownloadDirectory
11
+
12
+ from dbt_common.clients import system
13
+ from dbt_common.events.functions import fire_event
14
+ from dbt_common.utils.connection import connection_exception_retry
15
+
16
+ DOWNLOADS_PATH = None
17
+
18
+
19
+ def get_downloads_path():
20
+ return DOWNLOADS_PATH
21
+
22
+
23
+ @contextmanager
24
+ def downloads_directory():
25
+ global DOWNLOADS_PATH
26
+ remove_downloads = False
27
+ # the user might have set an environment variable. Set it to that, and do
28
+ # not remove it when finished.
29
+ if DOWNLOADS_PATH is None:
30
+ DOWNLOADS_PATH = os.getenv("DBT_DOWNLOADS_DIR")
31
+ remove_downloads = False
32
+ # if we are making a per-run temp directory, remove it at the end of
33
+ # successful runs
34
+ if DOWNLOADS_PATH is None:
35
+ DOWNLOADS_PATH = tempfile.mkdtemp(prefix="dbt-downloads-")
36
+ remove_downloads = True
37
+
38
+ system.make_directory(DOWNLOADS_PATH)
39
+ fire_event(DepsSetDownloadDirectory(path=DOWNLOADS_PATH))
40
+
41
+ yield DOWNLOADS_PATH
42
+
43
+ if remove_downloads:
44
+ system.rmtree(DOWNLOADS_PATH)
45
+ DOWNLOADS_PATH = None
46
+
47
+
48
+ class BasePackage(metaclass=abc.ABCMeta):
49
+ @abc.abstractproperty
50
+ def name(self) -> str:
51
+ raise NotImplementedError
52
+
53
+ def all_names(self) -> List[str]:
54
+ return [self.name]
55
+
56
+ @abc.abstractmethod
57
+ def source_type(self) -> str:
58
+ raise NotImplementedError
59
+
60
+
61
+ class PinnedPackage(BasePackage):
62
+ def __init__(self) -> None:
63
+ self._cached_metadata: Optional[ProjectPackageMetadata] = None
64
+
65
+ def __str__(self) -> str:
66
+ version = self.get_version()
67
+ if not version:
68
+ return self.name
69
+
70
+ return "{}@{}".format(self.name, version)
71
+
72
+ @abc.abstractmethod
73
+ def get_version(self) -> Optional[str]:
74
+ raise NotImplementedError
75
+
76
+ @abc.abstractmethod
77
+ def _fetch_metadata(self, project, renderer):
78
+ raise NotImplementedError
79
+
80
+ @abc.abstractmethod
81
+ def install(self, project, renderer):
82
+ raise NotImplementedError
83
+
84
+ @abc.abstractmethod
85
+ def nice_version_name(self):
86
+ raise NotImplementedError
87
+
88
+ @abc.abstractmethod
89
+ def to_dict(self) -> Dict[str, str]:
90
+ raise NotImplementedError
91
+
92
+ def fetch_metadata(self, project, renderer):
93
+ if not self._cached_metadata:
94
+ self._cached_metadata = self._fetch_metadata(project, renderer)
95
+ return self._cached_metadata
96
+
97
+ def get_project_name(self, project, renderer):
98
+ metadata = self.fetch_metadata(project, renderer)
99
+ return metadata.name
100
+
101
+ def get_installation_path(self, project, renderer):
102
+ dest_dirname = self.get_project_name(project, renderer)
103
+ return os.path.join(project.packages_install_path, dest_dirname)
104
+
105
+ def get_subdirectory(self):
106
+ return None
107
+
108
+ def _install(self, project, renderer):
109
+ metadata = self.fetch_metadata(project, renderer)
110
+
111
+ tar_name = f"{self.package}.{self.version}.tar.gz"
112
+ tar_path = (Path(get_downloads_path()) / tar_name).resolve(strict=False)
113
+ system.make_directory(str(tar_path.parent))
114
+
115
+ download_url = metadata.downloads.tarball
116
+ deps_path = project.packages_install_path
117
+ package_name = self.get_project_name(project, renderer)
118
+
119
+ download_untar_fn = functools.partial(
120
+ self.download_and_untar, download_url, str(tar_path), deps_path, package_name
121
+ )
122
+ connection_exception_retry(download_untar_fn, 5)
123
+
124
+ def download_and_untar(self, download_url, tar_path, deps_path, package_name):
125
+ """
126
+ Sometimes the download of the files fails and we want to retry. Sometimes the
127
+ download appears successful but the file did not make it through as expected
128
+ (generally due to a github incident). Either way we want to retry downloading
129
+ and untarring to see if we can get a success. Call this within
130
+ `connection_exception_retry`
131
+ """
132
+
133
+ system.download(download_url, tar_path)
134
+ system.untar_package(tar_path, deps_path, package_name)
135
+
136
+
137
+ SomePinned = TypeVar("SomePinned", bound=PinnedPackage)
138
+ SomeUnpinned = TypeVar("SomeUnpinned", bound="UnpinnedPackage")
139
+
140
+
141
+ class UnpinnedPackage(Generic[SomePinned], BasePackage):
142
+ @classmethod
143
+ @abc.abstractmethod
144
+ def from_contract(cls, contract):
145
+ raise NotImplementedError
146
+
147
+ @abc.abstractmethod
148
+ def incorporate(self: SomeUnpinned, other: SomeUnpinned) -> SomeUnpinned:
149
+ raise NotImplementedError
150
+
151
+ @abc.abstractmethod
152
+ def resolved(self) -> SomePinned:
153
+ raise NotImplementedError
dvt/deps/git.py ADDED
@@ -0,0 +1,196 @@
1
+ import os
2
+ from typing import Dict, List, Optional
3
+
4
+ from dvt.clients import git
5
+ from dvt.config.project import PartialProject, Project
6
+ from dvt.config.renderer import PackageRenderer
7
+ from dvt.contracts.project import GitPackage, ProjectPackageMetadata
8
+ from dvt.deps.base import PinnedPackage, UnpinnedPackage, get_downloads_path
9
+ from dvt.events.types import DepsScrubbedPackageName, DepsUnpinned, EnsureGitInstalled
10
+ from dvt.exceptions import MultipleVersionGitDepsError
11
+ from dvt.utils import md5
12
+
13
+ from dbt_common.clients import system
14
+ from dbt_common.events.functions import (
15
+ env_secrets,
16
+ fire_event,
17
+ scrub_secrets,
18
+ warn_or_error,
19
+ )
20
+ from dbt_common.exceptions import ExecutableError
21
+
22
+
23
+ def md5sum(s: str):
24
+ return md5(s, "latin-1")
25
+
26
+
27
+ class GitPackageMixin:
28
+ def __init__(
29
+ self,
30
+ git: str,
31
+ git_unrendered: str,
32
+ subdirectory: Optional[str] = None,
33
+ ) -> None:
34
+ super().__init__()
35
+ self.git = git
36
+ self.git_unrendered = git_unrendered
37
+ self.subdirectory = subdirectory
38
+
39
+ @property
40
+ def name(self):
41
+ return f"{self.git}/{self.subdirectory}" if self.subdirectory else self.git
42
+
43
+ def source_type(self) -> str:
44
+ return "git"
45
+
46
+
47
+ class GitPinnedPackage(GitPackageMixin, PinnedPackage):
48
+ def __init__(
49
+ self,
50
+ git: str,
51
+ git_unrendered: str,
52
+ revision: str,
53
+ warn_unpinned: bool = True,
54
+ subdirectory: Optional[str] = None,
55
+ ) -> None:
56
+ super().__init__(git, git_unrendered, subdirectory)
57
+ self.revision = revision
58
+ self.warn_unpinned = warn_unpinned
59
+ self.subdirectory = subdirectory
60
+ self._checkout_name = md5sum(self.name)
61
+
62
+ def to_dict(self) -> Dict[str, str]:
63
+ git_scrubbed = scrub_secrets(self.git_unrendered, env_secrets())
64
+ if self.git_unrendered != git_scrubbed:
65
+ warn_or_error(DepsScrubbedPackageName(package_name=git_scrubbed))
66
+ ret = {
67
+ "git": git_scrubbed,
68
+ "revision": self.revision,
69
+ }
70
+ if self.subdirectory:
71
+ ret["subdirectory"] = self.subdirectory
72
+ return ret
73
+
74
+ def get_version(self):
75
+ return self.revision
76
+
77
+ def get_subdirectory(self):
78
+ return self.subdirectory
79
+
80
+ def nice_version_name(self):
81
+ if self.revision == "HEAD":
82
+ return "HEAD (default revision)"
83
+ else:
84
+ return "revision {}".format(self.revision)
85
+
86
+ def _checkout(self):
87
+ """Performs a shallow clone of the repository into the downloads
88
+ directory. This function can be called repeatedly. If the project has
89
+ already been checked out at this version, it will be a no-op. Returns
90
+ the path to the checked out directory."""
91
+ try:
92
+ dir_ = git.clone_and_checkout(
93
+ self.git,
94
+ get_downloads_path(),
95
+ revision=self.revision,
96
+ dirname=self._checkout_name,
97
+ subdirectory=self.subdirectory,
98
+ )
99
+ except ExecutableError as exc:
100
+ if exc.cmd and exc.cmd[0] == "git":
101
+ fire_event(EnsureGitInstalled())
102
+ raise
103
+ return os.path.join(get_downloads_path(), dir_)
104
+
105
+ def _fetch_metadata(
106
+ self, project: Project, renderer: PackageRenderer
107
+ ) -> ProjectPackageMetadata:
108
+ path = self._checkout()
109
+
110
+ # raise warning (or error) if this package is not pinned
111
+ if (self.revision == "HEAD" or self.revision in ("main", "master")) and self.warn_unpinned:
112
+ warn_or_error(DepsUnpinned(revision=self.revision, git=self.git))
113
+
114
+ # now overwrite 'revision' with actual commit SHA
115
+ self.revision = git.get_current_sha(path)
116
+
117
+ partial = PartialProject.from_project_root(path)
118
+ return partial.render_package_metadata(renderer)
119
+
120
+ def install(self, project, renderer):
121
+ dest_path = self.get_installation_path(project, renderer)
122
+ if os.path.exists(dest_path):
123
+ if system.path_is_symlink(dest_path):
124
+ system.remove_file(dest_path)
125
+ else:
126
+ system.rmdir(dest_path)
127
+
128
+ system.move(self._checkout(), dest_path)
129
+
130
+
131
+ class GitUnpinnedPackage(GitPackageMixin, UnpinnedPackage[GitPinnedPackage]):
132
+ def __init__(
133
+ self,
134
+ git: str,
135
+ git_unrendered: str,
136
+ revisions: List[str],
137
+ warn_unpinned: bool = True,
138
+ subdirectory: Optional[str] = None,
139
+ ) -> None:
140
+ super().__init__(git, git_unrendered, subdirectory)
141
+ self.revisions = revisions
142
+ self.warn_unpinned = warn_unpinned
143
+ self.subdirectory = subdirectory
144
+
145
+ @classmethod
146
+ def from_contract(cls, contract: GitPackage) -> "GitUnpinnedPackage":
147
+ revisions = contract.get_revisions()
148
+
149
+ # we want to map None -> True
150
+ warn_unpinned = contract.warn_unpinned is not False
151
+ return cls(
152
+ git=contract.git,
153
+ git_unrendered=(contract.unrendered.get("git") or contract.git),
154
+ revisions=revisions,
155
+ warn_unpinned=warn_unpinned,
156
+ subdirectory=contract.subdirectory,
157
+ )
158
+
159
+ def all_names(self) -> List[str]:
160
+ if self.git.endswith(".git"):
161
+ other = self.git[:-4]
162
+ else:
163
+ other = self.git + ".git"
164
+
165
+ if self.subdirectory:
166
+ git_name = f"{self.git}/{self.subdirectory}"
167
+ other = f"{other}/{self.subdirectory}"
168
+ else:
169
+ git_name = self.git
170
+
171
+ return [git_name, other]
172
+
173
+ def incorporate(self, other: "GitUnpinnedPackage") -> "GitUnpinnedPackage":
174
+ warn_unpinned = self.warn_unpinned and other.warn_unpinned
175
+
176
+ return GitUnpinnedPackage(
177
+ git=self.git,
178
+ git_unrendered=self.git_unrendered,
179
+ revisions=self.revisions + other.revisions,
180
+ warn_unpinned=warn_unpinned,
181
+ subdirectory=self.subdirectory,
182
+ )
183
+
184
+ def resolved(self) -> GitPinnedPackage:
185
+ requested = set(self.revisions)
186
+ if len(requested) == 0:
187
+ requested = {"HEAD"}
188
+ elif len(requested) > 1:
189
+ raise MultipleVersionGitDepsError(self.name, requested)
190
+ return GitPinnedPackage(
191
+ git=self.git,
192
+ git_unrendered=self.git_unrendered,
193
+ revision=requested.pop(),
194
+ warn_unpinned=self.warn_unpinned,
195
+ subdirectory=self.subdirectory,
196
+ )