dvt-core 0.52.2__cp310-cp310-macosx_10_9_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (275) hide show
  1. dbt/__init__.py +7 -0
  2. dbt/_pydantic_shim.py +26 -0
  3. dbt/artifacts/__init__.py +0 -0
  4. dbt/artifacts/exceptions/__init__.py +1 -0
  5. dbt/artifacts/exceptions/schemas.py +31 -0
  6. dbt/artifacts/resources/__init__.py +116 -0
  7. dbt/artifacts/resources/base.py +67 -0
  8. dbt/artifacts/resources/types.py +93 -0
  9. dbt/artifacts/resources/v1/analysis.py +10 -0
  10. dbt/artifacts/resources/v1/catalog.py +23 -0
  11. dbt/artifacts/resources/v1/components.py +274 -0
  12. dbt/artifacts/resources/v1/config.py +277 -0
  13. dbt/artifacts/resources/v1/documentation.py +11 -0
  14. dbt/artifacts/resources/v1/exposure.py +51 -0
  15. dbt/artifacts/resources/v1/function.py +52 -0
  16. dbt/artifacts/resources/v1/generic_test.py +31 -0
  17. dbt/artifacts/resources/v1/group.py +21 -0
  18. dbt/artifacts/resources/v1/hook.py +11 -0
  19. dbt/artifacts/resources/v1/macro.py +29 -0
  20. dbt/artifacts/resources/v1/metric.py +172 -0
  21. dbt/artifacts/resources/v1/model.py +145 -0
  22. dbt/artifacts/resources/v1/owner.py +10 -0
  23. dbt/artifacts/resources/v1/saved_query.py +111 -0
  24. dbt/artifacts/resources/v1/seed.py +41 -0
  25. dbt/artifacts/resources/v1/semantic_layer_components.py +72 -0
  26. dbt/artifacts/resources/v1/semantic_model.py +314 -0
  27. dbt/artifacts/resources/v1/singular_test.py +14 -0
  28. dbt/artifacts/resources/v1/snapshot.py +91 -0
  29. dbt/artifacts/resources/v1/source_definition.py +84 -0
  30. dbt/artifacts/resources/v1/sql_operation.py +10 -0
  31. dbt/artifacts/resources/v1/unit_test_definition.py +77 -0
  32. dbt/artifacts/schemas/__init__.py +0 -0
  33. dbt/artifacts/schemas/base.py +191 -0
  34. dbt/artifacts/schemas/batch_results.py +24 -0
  35. dbt/artifacts/schemas/catalog/__init__.py +11 -0
  36. dbt/artifacts/schemas/catalog/v1/__init__.py +0 -0
  37. dbt/artifacts/schemas/catalog/v1/catalog.py +59 -0
  38. dbt/artifacts/schemas/freshness/__init__.py +1 -0
  39. dbt/artifacts/schemas/freshness/v3/__init__.py +0 -0
  40. dbt/artifacts/schemas/freshness/v3/freshness.py +158 -0
  41. dbt/artifacts/schemas/manifest/__init__.py +2 -0
  42. dbt/artifacts/schemas/manifest/v12/__init__.py +0 -0
  43. dbt/artifacts/schemas/manifest/v12/manifest.py +211 -0
  44. dbt/artifacts/schemas/results.py +147 -0
  45. dbt/artifacts/schemas/run/__init__.py +2 -0
  46. dbt/artifacts/schemas/run/v5/__init__.py +0 -0
  47. dbt/artifacts/schemas/run/v5/run.py +184 -0
  48. dbt/artifacts/schemas/upgrades/__init__.py +4 -0
  49. dbt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
  50. dbt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
  51. dbt/artifacts/utils/validation.py +153 -0
  52. dbt/cli/__init__.py +1 -0
  53. dbt/cli/context.py +17 -0
  54. dbt/cli/exceptions.py +57 -0
  55. dbt/cli/flags.py +560 -0
  56. dbt/cli/main.py +2039 -0
  57. dbt/cli/option_types.py +121 -0
  58. dbt/cli/options.py +80 -0
  59. dbt/cli/params.py +804 -0
  60. dbt/cli/requires.py +490 -0
  61. dbt/cli/resolvers.py +50 -0
  62. dbt/cli/types.py +40 -0
  63. dbt/clients/__init__.py +0 -0
  64. dbt/clients/checked_load.py +83 -0
  65. dbt/clients/git.py +164 -0
  66. dbt/clients/jinja.py +206 -0
  67. dbt/clients/jinja_static.py +245 -0
  68. dbt/clients/registry.py +192 -0
  69. dbt/clients/yaml_helper.py +68 -0
  70. dbt/compilation.py +876 -0
  71. dbt/compute/__init__.py +14 -0
  72. dbt/compute/engines/__init__.py +12 -0
  73. dbt/compute/engines/spark_engine.py +624 -0
  74. dbt/compute/federated_executor.py +837 -0
  75. dbt/compute/filter_pushdown.cpython-310-darwin.so +0 -0
  76. dbt/compute/filter_pushdown.py +273 -0
  77. dbt/compute/jar_provisioning.cpython-310-darwin.so +0 -0
  78. dbt/compute/jar_provisioning.py +255 -0
  79. dbt/compute/java_compat.cpython-310-darwin.so +0 -0
  80. dbt/compute/java_compat.py +689 -0
  81. dbt/compute/jdbc_utils.cpython-310-darwin.so +0 -0
  82. dbt/compute/jdbc_utils.py +678 -0
  83. dbt/compute/smart_selector.cpython-310-darwin.so +0 -0
  84. dbt/compute/smart_selector.py +311 -0
  85. dbt/compute/strategies/__init__.py +54 -0
  86. dbt/compute/strategies/base.py +165 -0
  87. dbt/compute/strategies/dataproc.py +207 -0
  88. dbt/compute/strategies/emr.py +203 -0
  89. dbt/compute/strategies/local.py +364 -0
  90. dbt/compute/strategies/standalone.py +262 -0
  91. dbt/config/__init__.py +4 -0
  92. dbt/config/catalogs.py +94 -0
  93. dbt/config/compute.cpython-310-darwin.so +0 -0
  94. dbt/config/compute.py +547 -0
  95. dbt/config/dvt_profile.cpython-310-darwin.so +0 -0
  96. dbt/config/dvt_profile.py +342 -0
  97. dbt/config/profile.py +422 -0
  98. dbt/config/project.py +873 -0
  99. dbt/config/project_utils.py +28 -0
  100. dbt/config/renderer.py +231 -0
  101. dbt/config/runtime.py +553 -0
  102. dbt/config/selectors.py +208 -0
  103. dbt/config/utils.py +77 -0
  104. dbt/constants.py +28 -0
  105. dbt/context/__init__.py +0 -0
  106. dbt/context/base.py +745 -0
  107. dbt/context/configured.py +135 -0
  108. dbt/context/context_config.py +382 -0
  109. dbt/context/docs.py +82 -0
  110. dbt/context/exceptions_jinja.py +178 -0
  111. dbt/context/macro_resolver.py +195 -0
  112. dbt/context/macros.py +171 -0
  113. dbt/context/manifest.py +72 -0
  114. dbt/context/providers.py +2249 -0
  115. dbt/context/query_header.py +13 -0
  116. dbt/context/secret.py +58 -0
  117. dbt/context/target.py +74 -0
  118. dbt/contracts/__init__.py +0 -0
  119. dbt/contracts/files.py +413 -0
  120. dbt/contracts/graph/__init__.py +0 -0
  121. dbt/contracts/graph/manifest.py +1904 -0
  122. dbt/contracts/graph/metrics.py +97 -0
  123. dbt/contracts/graph/model_config.py +70 -0
  124. dbt/contracts/graph/node_args.py +42 -0
  125. dbt/contracts/graph/nodes.py +1806 -0
  126. dbt/contracts/graph/semantic_manifest.py +232 -0
  127. dbt/contracts/graph/unparsed.py +811 -0
  128. dbt/contracts/project.py +417 -0
  129. dbt/contracts/results.py +53 -0
  130. dbt/contracts/selection.py +23 -0
  131. dbt/contracts/sql.py +85 -0
  132. dbt/contracts/state.py +68 -0
  133. dbt/contracts/util.py +46 -0
  134. dbt/deprecations.py +346 -0
  135. dbt/deps/__init__.py +0 -0
  136. dbt/deps/base.py +152 -0
  137. dbt/deps/git.py +195 -0
  138. dbt/deps/local.py +79 -0
  139. dbt/deps/registry.py +130 -0
  140. dbt/deps/resolver.py +149 -0
  141. dbt/deps/tarball.py +120 -0
  142. dbt/docs/source/_ext/dbt_click.py +119 -0
  143. dbt/docs/source/conf.py +32 -0
  144. dbt/env_vars.py +64 -0
  145. dbt/event_time/event_time.py +40 -0
  146. dbt/event_time/sample_window.py +60 -0
  147. dbt/events/__init__.py +15 -0
  148. dbt/events/base_types.py +36 -0
  149. dbt/events/core_types_pb2.py +2 -0
  150. dbt/events/logging.py +108 -0
  151. dbt/events/types.py +2516 -0
  152. dbt/exceptions.py +1486 -0
  153. dbt/flags.py +89 -0
  154. dbt/graph/__init__.py +11 -0
  155. dbt/graph/cli.py +247 -0
  156. dbt/graph/graph.py +172 -0
  157. dbt/graph/queue.py +214 -0
  158. dbt/graph/selector.py +374 -0
  159. dbt/graph/selector_methods.py +975 -0
  160. dbt/graph/selector_spec.py +222 -0
  161. dbt/graph/thread_pool.py +18 -0
  162. dbt/hooks.py +21 -0
  163. dbt/include/README.md +49 -0
  164. dbt/include/__init__.py +3 -0
  165. dbt/include/starter_project/.gitignore +4 -0
  166. dbt/include/starter_project/README.md +15 -0
  167. dbt/include/starter_project/__init__.py +3 -0
  168. dbt/include/starter_project/analyses/.gitkeep +0 -0
  169. dbt/include/starter_project/dbt_project.yml +36 -0
  170. dbt/include/starter_project/macros/.gitkeep +0 -0
  171. dbt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
  172. dbt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
  173. dbt/include/starter_project/models/example/schema.yml +21 -0
  174. dbt/include/starter_project/seeds/.gitkeep +0 -0
  175. dbt/include/starter_project/snapshots/.gitkeep +0 -0
  176. dbt/include/starter_project/tests/.gitkeep +0 -0
  177. dbt/internal_deprecations.py +26 -0
  178. dbt/jsonschemas/__init__.py +3 -0
  179. dbt/jsonschemas/jsonschemas.py +309 -0
  180. dbt/jsonschemas/project/0.0.110.json +4717 -0
  181. dbt/jsonschemas/project/0.0.85.json +2015 -0
  182. dbt/jsonschemas/resources/0.0.110.json +2636 -0
  183. dbt/jsonschemas/resources/0.0.85.json +2536 -0
  184. dbt/jsonschemas/resources/latest.json +6773 -0
  185. dbt/links.py +4 -0
  186. dbt/materializations/__init__.py +0 -0
  187. dbt/materializations/incremental/__init__.py +0 -0
  188. dbt/materializations/incremental/microbatch.py +236 -0
  189. dbt/mp_context.py +8 -0
  190. dbt/node_types.py +37 -0
  191. dbt/parser/__init__.py +23 -0
  192. dbt/parser/analysis.py +21 -0
  193. dbt/parser/base.py +548 -0
  194. dbt/parser/common.py +266 -0
  195. dbt/parser/docs.py +52 -0
  196. dbt/parser/fixtures.py +51 -0
  197. dbt/parser/functions.py +30 -0
  198. dbt/parser/generic_test.py +100 -0
  199. dbt/parser/generic_test_builders.py +333 -0
  200. dbt/parser/hooks.py +118 -0
  201. dbt/parser/macros.py +137 -0
  202. dbt/parser/manifest.py +2204 -0
  203. dbt/parser/models.py +573 -0
  204. dbt/parser/partial.py +1178 -0
  205. dbt/parser/read_files.py +445 -0
  206. dbt/parser/schema_generic_tests.py +422 -0
  207. dbt/parser/schema_renderer.py +111 -0
  208. dbt/parser/schema_yaml_readers.py +935 -0
  209. dbt/parser/schemas.py +1466 -0
  210. dbt/parser/search.py +149 -0
  211. dbt/parser/seeds.py +28 -0
  212. dbt/parser/singular_test.py +20 -0
  213. dbt/parser/snapshots.py +44 -0
  214. dbt/parser/sources.py +558 -0
  215. dbt/parser/sql.py +62 -0
  216. dbt/parser/unit_tests.py +621 -0
  217. dbt/plugins/__init__.py +20 -0
  218. dbt/plugins/contracts.py +9 -0
  219. dbt/plugins/exceptions.py +2 -0
  220. dbt/plugins/manager.py +163 -0
  221. dbt/plugins/manifest.py +21 -0
  222. dbt/profiler.py +20 -0
  223. dbt/py.typed +1 -0
  224. dbt/query_analyzer.cpython-310-darwin.so +0 -0
  225. dbt/query_analyzer.py +410 -0
  226. dbt/runners/__init__.py +2 -0
  227. dbt/runners/exposure_runner.py +7 -0
  228. dbt/runners/no_op_runner.py +45 -0
  229. dbt/runners/saved_query_runner.py +7 -0
  230. dbt/selected_resources.py +8 -0
  231. dbt/task/__init__.py +0 -0
  232. dbt/task/base.py +503 -0
  233. dbt/task/build.py +197 -0
  234. dbt/task/clean.py +56 -0
  235. dbt/task/clone.py +161 -0
  236. dbt/task/compile.py +150 -0
  237. dbt/task/compute.py +454 -0
  238. dbt/task/debug.py +505 -0
  239. dbt/task/deps.py +280 -0
  240. dbt/task/docs/__init__.py +3 -0
  241. dbt/task/docs/generate.py +660 -0
  242. dbt/task/docs/index.html +250 -0
  243. dbt/task/docs/serve.py +29 -0
  244. dbt/task/freshness.py +322 -0
  245. dbt/task/function.py +121 -0
  246. dbt/task/group_lookup.py +46 -0
  247. dbt/task/init.py +553 -0
  248. dbt/task/java.py +316 -0
  249. dbt/task/list.py +236 -0
  250. dbt/task/printer.py +175 -0
  251. dbt/task/retry.py +175 -0
  252. dbt/task/run.py +1306 -0
  253. dbt/task/run_operation.py +141 -0
  254. dbt/task/runnable.py +758 -0
  255. dbt/task/seed.py +103 -0
  256. dbt/task/show.py +149 -0
  257. dbt/task/snapshot.py +56 -0
  258. dbt/task/spark.py +414 -0
  259. dbt/task/sql.py +110 -0
  260. dbt/task/target_sync.py +759 -0
  261. dbt/task/test.py +464 -0
  262. dbt/tests/fixtures/__init__.py +1 -0
  263. dbt/tests/fixtures/project.py +620 -0
  264. dbt/tests/util.py +651 -0
  265. dbt/tracking.py +529 -0
  266. dbt/utils/__init__.py +3 -0
  267. dbt/utils/artifact_upload.py +151 -0
  268. dbt/utils/utils.py +408 -0
  269. dbt/version.py +268 -0
  270. dvt_cli/__init__.py +72 -0
  271. dvt_core-0.52.2.dist-info/METADATA +286 -0
  272. dvt_core-0.52.2.dist-info/RECORD +275 -0
  273. dvt_core-0.52.2.dist-info/WHEEL +5 -0
  274. dvt_core-0.52.2.dist-info/entry_points.txt +2 -0
  275. dvt_core-0.52.2.dist-info/top_level.txt +2 -0
dbt/deps/local.py ADDED
@@ -0,0 +1,79 @@
1
+ import shutil
2
+ from typing import Dict
3
+
4
+ from dbt.config.project import PartialProject, Project
5
+ from dbt.config.renderer import PackageRenderer
6
+ from dbt.contracts.project import LocalPackage, ProjectPackageMetadata
7
+ from dbt.deps.base import PinnedPackage, UnpinnedPackage
8
+ from dbt.events.types import DepsCreatingLocalSymlink, DepsSymlinkNotAvailable
9
+ from dbt_common.clients import system
10
+ from dbt_common.events.functions import fire_event
11
+
12
+
13
+ class LocalPackageMixin:
14
+ def __init__(self, local: str) -> None:
15
+ super().__init__()
16
+ self.local = local
17
+
18
+ @property
19
+ def name(self):
20
+ return self.local
21
+
22
+ def source_type(self):
23
+ return "local"
24
+
25
+
26
+ class LocalPinnedPackage(LocalPackageMixin, PinnedPackage):
27
+ def __init__(self, local: str) -> None:
28
+ super().__init__(local)
29
+
30
+ def to_dict(self) -> Dict[str, str]:
31
+ return {
32
+ "local": self.local,
33
+ }
34
+
35
+ def get_version(self):
36
+ return None
37
+
38
+ def nice_version_name(self):
39
+ return "<local @ {}>".format(self.local)
40
+
41
+ def resolve_path(self, project):
42
+ return system.resolve_path_from_base(
43
+ self.local,
44
+ project.project_root,
45
+ )
46
+
47
+ def _fetch_metadata(
48
+ self, project: Project, renderer: PackageRenderer
49
+ ) -> ProjectPackageMetadata:
50
+ partial = PartialProject.from_project_root(self.resolve_path(project))
51
+ return partial.render_package_metadata(renderer)
52
+
53
+ def install(self, project, renderer):
54
+ src_path = self.resolve_path(project)
55
+ dest_path = self.get_installation_path(project, renderer)
56
+
57
+ if system.path_exists(dest_path):
58
+ if not system.path_is_symlink(dest_path):
59
+ system.rmdir(dest_path)
60
+ else:
61
+ system.remove_file(dest_path)
62
+ try:
63
+ fire_event(DepsCreatingLocalSymlink())
64
+ system.make_symlink(src_path, dest_path)
65
+ except OSError:
66
+ fire_event(DepsSymlinkNotAvailable())
67
+ shutil.copytree(src_path, dest_path)
68
+
69
+
70
+ class LocalUnpinnedPackage(LocalPackageMixin, UnpinnedPackage[LocalPinnedPackage]):
71
+ @classmethod
72
+ def from_contract(cls, contract: LocalPackage) -> "LocalUnpinnedPackage":
73
+ return cls(local=contract.local)
74
+
75
+ def incorporate(self, other: "LocalUnpinnedPackage") -> "LocalUnpinnedPackage":
76
+ return LocalUnpinnedPackage(local=self.local)
77
+
78
+ def resolved(self) -> LocalPinnedPackage:
79
+ return LocalPinnedPackage(local=self.local)
dbt/deps/registry.py ADDED
@@ -0,0 +1,130 @@
1
+ from typing import Dict, List
2
+
3
+ from dbt.clients import registry
4
+ from dbt.contracts.project import RegistryPackage, RegistryPackageMetadata
5
+ from dbt.deps.base import PinnedPackage, UnpinnedPackage
6
+ from dbt.exceptions import (
7
+ DependencyError,
8
+ PackageNotFoundError,
9
+ PackageVersionNotFoundError,
10
+ )
11
+ from dbt.flags import get_flags
12
+ from dbt.version import get_installed_version
13
+ from dbt_common import semver
14
+ from dbt_common.exceptions import VersionsNotCompatibleError
15
+
16
+
17
+ class RegistryPackageMixin:
18
+ def __init__(self, package: str) -> None:
19
+ super().__init__()
20
+ self.package = package
21
+
22
+ @property
23
+ def name(self):
24
+ return self.package
25
+
26
+ def source_type(self) -> str:
27
+ return "hub"
28
+
29
+
30
+ class RegistryPinnedPackage(RegistryPackageMixin, PinnedPackage):
31
+ def __init__(self, package: str, version: str, version_latest: str) -> None:
32
+ super().__init__(package)
33
+ self.version = version
34
+ self.version_latest = version_latest
35
+
36
+ @property
37
+ def name(self):
38
+ return self.package
39
+
40
+ def to_dict(self) -> Dict[str, str]:
41
+ return {
42
+ "package": self.package,
43
+ "version": self.version,
44
+ }
45
+
46
+ def source_type(self):
47
+ return "hub"
48
+
49
+ def get_version(self):
50
+ return self.version
51
+
52
+ def get_version_latest(self):
53
+ return self.version_latest
54
+
55
+ def nice_version_name(self):
56
+ return "version {}".format(self.version)
57
+
58
+ def _fetch_metadata(self, project, renderer) -> RegistryPackageMetadata:
59
+ dct = registry.package_version(self.package, self.version)
60
+ return RegistryPackageMetadata.from_dict(dct)
61
+
62
+ def install(self, project, renderer):
63
+ self._install(project, renderer)
64
+
65
+
66
+ class RegistryUnpinnedPackage(RegistryPackageMixin, UnpinnedPackage[RegistryPinnedPackage]):
67
+ def __init__(
68
+ self, package: str, versions: List[semver.VersionSpecifier], install_prerelease: bool
69
+ ) -> None:
70
+ super().__init__(package)
71
+ self.versions = versions
72
+ self.install_prerelease = install_prerelease
73
+
74
+ def _check_in_index(self):
75
+ index = registry.index_cached()
76
+ if self.package not in index:
77
+ raise PackageNotFoundError(self.package)
78
+
79
+ @classmethod
80
+ def from_contract(cls, contract: RegistryPackage) -> "RegistryUnpinnedPackage":
81
+ raw_version = contract.get_versions()
82
+
83
+ versions = [semver.VersionSpecifier.from_version_string(v) for v in raw_version]
84
+ return cls(
85
+ package=contract.package,
86
+ versions=versions,
87
+ install_prerelease=bool(contract.install_prerelease),
88
+ )
89
+
90
+ def incorporate(self, other: "RegistryUnpinnedPackage") -> "RegistryUnpinnedPackage":
91
+ return RegistryUnpinnedPackage(
92
+ package=self.package,
93
+ install_prerelease=self.install_prerelease,
94
+ versions=self.versions + other.versions,
95
+ )
96
+
97
+ def resolved(self) -> RegistryPinnedPackage:
98
+ self._check_in_index()
99
+ try:
100
+ range_ = semver.reduce_versions(*self.versions)
101
+ except VersionsNotCompatibleError as e:
102
+ new_msg = "Version error for package {}: {}".format(self.name, e)
103
+ raise DependencyError(new_msg) from e
104
+ flags = get_flags()
105
+ should_version_check = bool(flags.VERSION_CHECK)
106
+ dbt_version = get_installed_version()
107
+ compatible_versions = registry.get_compatible_versions(
108
+ self.package, dbt_version, should_version_check
109
+ )
110
+ prerelease_version_specified = any(bool(version.prerelease) for version in self.versions)
111
+ installable = semver.filter_installable(
112
+ compatible_versions, self.install_prerelease or prerelease_version_specified
113
+ )
114
+ if installable:
115
+ # for now, pick a version and then recurse. later on,
116
+ # we'll probably want to traverse multiple options
117
+ # so we can match packages. not going to make a difference
118
+ # right now.
119
+ target = semver.resolve_to_specific_version(range_, installable)
120
+ else:
121
+ target = None
122
+ if not target:
123
+ # raise an exception if no installable target version is found
124
+ raise PackageVersionNotFoundError(
125
+ self.package, range_, installable, should_version_check
126
+ )
127
+ latest_compatible = installable[-1]
128
+ return RegistryPinnedPackage(
129
+ package=self.package, version=target, version_latest=latest_compatible
130
+ )
dbt/deps/resolver.py ADDED
@@ -0,0 +1,149 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Dict, Iterator, List, NoReturn, Set, Type
3
+
4
+ from dbt.config import Project
5
+ from dbt.config.renderer import PackageRenderer
6
+ from dbt.contracts.project import (
7
+ GitPackage,
8
+ LocalPackage,
9
+ PackageSpec,
10
+ PrivatePackage,
11
+ RegistryPackage,
12
+ TarballPackage,
13
+ )
14
+ from dbt.deps.base import BasePackage, PinnedPackage, UnpinnedPackage
15
+ from dbt.deps.git import GitUnpinnedPackage
16
+ from dbt.deps.local import LocalUnpinnedPackage
17
+ from dbt.deps.registry import RegistryUnpinnedPackage
18
+ from dbt.deps.tarball import TarballUnpinnedPackage
19
+ from dbt.exceptions import (
20
+ DependencyError,
21
+ DuplicateDependencyToRootError,
22
+ DuplicateProjectDependencyError,
23
+ MismatchedDependencyTypeError,
24
+ )
25
+
26
+
27
+ @dataclass
28
+ class PackageListing:
29
+ packages: Dict[str, UnpinnedPackage] = field(default_factory=dict)
30
+
31
+ def __len__(self):
32
+ return len(self.packages)
33
+
34
+ def __bool__(self):
35
+ return bool(self.packages)
36
+
37
+ def _pick_key(self, key: BasePackage) -> str:
38
+ for name in key.all_names():
39
+ if name in self.packages:
40
+ return name
41
+ return key.name
42
+
43
+ def __contains__(self, key: BasePackage):
44
+ for name in key.all_names():
45
+ if name in self.packages:
46
+ return True
47
+
48
+ def __getitem__(self, key: BasePackage):
49
+ key_str: str = self._pick_key(key)
50
+ return self.packages[key_str]
51
+
52
+ def __setitem__(self, key: BasePackage, value):
53
+ key_str: str = self._pick_key(key)
54
+ self.packages[key_str] = value
55
+
56
+ def _mismatched_types(self, old: UnpinnedPackage, new: UnpinnedPackage) -> NoReturn:
57
+ raise MismatchedDependencyTypeError(new, old)
58
+
59
+ def incorporate(self, package: UnpinnedPackage):
60
+ key: str = self._pick_key(package)
61
+ if key in self.packages:
62
+ existing: UnpinnedPackage = self.packages[key]
63
+ if not isinstance(existing, type(package)):
64
+ self._mismatched_types(existing, package)
65
+ self.packages[key] = existing.incorporate(package)
66
+ else:
67
+ self.packages[key] = package
68
+
69
+ def update_from(self, src: List[PackageSpec]) -> None:
70
+ pkg: UnpinnedPackage
71
+ for contract in src:
72
+ if isinstance(contract, LocalPackage):
73
+ pkg = LocalUnpinnedPackage.from_contract(contract)
74
+ elif isinstance(contract, TarballPackage):
75
+ pkg = TarballUnpinnedPackage.from_contract(contract)
76
+ elif isinstance(contract, GitPackage):
77
+ pkg = GitUnpinnedPackage.from_contract(contract)
78
+ elif isinstance(contract, PrivatePackage):
79
+ raise DependencyError(
80
+ f'Cannot resolve private package {contract.private} because git provider integration is missing. Please use a "git" package instead.'
81
+ )
82
+ elif isinstance(contract, RegistryPackage):
83
+ pkg = RegistryUnpinnedPackage.from_contract(contract)
84
+ else:
85
+ raise DependencyError("Invalid package type {}".format(type(contract)))
86
+ self.incorporate(pkg)
87
+
88
+ @classmethod
89
+ def from_contracts(cls: Type["PackageListing"], src: List[PackageSpec]) -> "PackageListing":
90
+ self = cls({})
91
+ self.update_from(src)
92
+ return self
93
+
94
+ def resolved(self) -> List[PinnedPackage]:
95
+ return [p.resolved() for p in self.packages.values()]
96
+
97
+ def __iter__(self) -> Iterator[UnpinnedPackage]:
98
+ return iter(self.packages.values())
99
+
100
+
101
+ def _check_for_duplicate_project_names(
102
+ final_deps: List[PinnedPackage],
103
+ project: Project,
104
+ renderer: PackageRenderer,
105
+ ):
106
+ seen: Set[str] = set()
107
+ for package in final_deps:
108
+ project_name = package.get_project_name(project, renderer)
109
+ if project_name in seen:
110
+ raise DuplicateProjectDependencyError(project_name)
111
+ elif project_name == project.project_name:
112
+ raise DuplicateDependencyToRootError(project_name)
113
+ seen.add(project_name)
114
+
115
+
116
+ def resolve_packages(
117
+ packages: List[PackageSpec],
118
+ project: Project,
119
+ cli_vars: Dict[str, Any],
120
+ ) -> List[PinnedPackage]:
121
+ pending = PackageListing.from_contracts(packages)
122
+ final = PackageListing()
123
+
124
+ renderer = PackageRenderer(cli_vars)
125
+
126
+ while pending:
127
+ next_pending = PackageListing()
128
+ # resolve the dependency in question
129
+ for package in pending:
130
+ final.incorporate(package)
131
+ target = final[package].resolved().fetch_metadata(project, renderer)
132
+ next_pending.update_from(target.packages)
133
+ pending = next_pending
134
+
135
+ resolved = final.resolved()
136
+ _check_for_duplicate_project_names(resolved, project, renderer)
137
+ return resolved
138
+
139
+
140
+ def resolve_lock_packages(packages: List[PackageSpec]) -> List[PinnedPackage]:
141
+ lock_packages = PackageListing.from_contracts(packages)
142
+ final = PackageListing()
143
+
144
+ for package in lock_packages:
145
+ final.incorporate(package)
146
+
147
+ resolved = final.resolved()
148
+
149
+ return resolved
dbt/deps/tarball.py ADDED
@@ -0,0 +1,120 @@
1
+ import functools
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Dict
5
+
6
+ from dbt.config.project import PartialProject
7
+ from dbt.contracts.project import TarballPackage
8
+ from dbt.deps.base import PinnedPackage, UnpinnedPackage, get_downloads_path
9
+ from dbt.events.types import DepsScrubbedPackageName
10
+ from dbt.exceptions import DependencyError, env_secrets, scrub_secrets
11
+ from dbt_common.clients import system
12
+ from dbt_common.events.functions import warn_or_error
13
+ from dbt_common.utils.connection import connection_exception_retry
14
+
15
+
16
+ class TarballPackageMixin:
17
+ def __init__(self, tarball: str, tarball_unrendered: str) -> None:
18
+ super().__init__()
19
+ self.tarball = tarball
20
+ self.tarball_unrendered = tarball_unrendered
21
+
22
+ @property
23
+ def name(self):
24
+ return self.tarball
25
+
26
+ def source_type(self) -> str:
27
+ return "tarball"
28
+
29
+
30
+ class TarballPinnedPackage(TarballPackageMixin, PinnedPackage):
31
+ def __init__(self, tarball: str, tarball_unrendered: str, package: str) -> None:
32
+ super().__init__(tarball, tarball_unrendered)
33
+ self.package = package
34
+ self.version = "tarball"
35
+ self.tar_path = os.path.join(Path(get_downloads_path()), self.package)
36
+ self.untarred_path = f"{self.tar_path}_untarred"
37
+
38
+ @property
39
+ def name(self):
40
+ return self.package
41
+
42
+ def to_dict(self) -> Dict[str, str]:
43
+ tarball_scrubbed = scrub_secrets(self.tarball_unrendered, env_secrets())
44
+ if self.tarball_unrendered != tarball_scrubbed:
45
+ warn_or_error(DepsScrubbedPackageName(package_name=tarball_scrubbed))
46
+ return {
47
+ "tarball": tarball_scrubbed,
48
+ "name": self.package,
49
+ }
50
+
51
+ def get_version(self):
52
+ return self.version
53
+
54
+ def nice_version_name(self):
55
+ return f"tarball (url: {self.tarball})"
56
+
57
+ def _fetch_metadata(self, project, renderer):
58
+ """Download and untar the project and parse metadata from the project folder."""
59
+ download_untar_fn = functools.partial(
60
+ self.download_and_untar, self.tarball, self.tar_path, self.untarred_path, self.name
61
+ )
62
+ connection_exception_retry(download_untar_fn, 5)
63
+
64
+ tar_contents = os.listdir(self.untarred_path)
65
+ if len(tar_contents) != 1:
66
+ raise DependencyError(
67
+ f"Incorrect structure for package extracted from {self.tarball}."
68
+ f"The extracted package needs to follow the structure {self.name}/<package_contents>."
69
+ )
70
+ child_folder = os.listdir(self.untarred_path)[0]
71
+
72
+ self.untarred_path = os.path.join(self.untarred_path, child_folder)
73
+ partial = PartialProject.from_project_root(self.untarred_path)
74
+ metadata = partial.render_package_metadata(renderer)
75
+ metadata.name = self.package if self.package else metadata.name
76
+ return metadata
77
+
78
+ def install(self, project, renderer):
79
+ download_untar_fn = functools.partial(
80
+ self.download_and_untar, self.tarball, self.tar_path, self.untarred_path, self.name
81
+ )
82
+ connection_exception_retry(download_untar_fn, 5)
83
+ dest_path = self.get_installation_path(project, renderer)
84
+ if os.path.exists(dest_path):
85
+ if system.path_is_symlink(dest_path):
86
+ system.remove_file(dest_path)
87
+ else:
88
+ system.rmdir(dest_path)
89
+ system.move(self.untarred_path, dest_path)
90
+
91
+
92
+ class TarballUnpinnedPackage(TarballPackageMixin, UnpinnedPackage[TarballPinnedPackage]):
93
+ def __init__(
94
+ self,
95
+ tarball: str,
96
+ tarball_unrendered: str,
97
+ package: str,
98
+ ) -> None:
99
+ super().__init__(tarball, tarball_unrendered)
100
+ # setup to recycle RegistryPinnedPackage fns
101
+ self.package = package
102
+ self.version = "tarball"
103
+
104
+ @classmethod
105
+ def from_contract(cls, contract: TarballPackage) -> "TarballUnpinnedPackage":
106
+ return cls(
107
+ tarball=contract.tarball,
108
+ tarball_unrendered=(contract.unrendered.get("tarball") or contract.tarball),
109
+ package=contract.name,
110
+ )
111
+
112
+ def incorporate(self, other: "TarballUnpinnedPackage") -> "TarballUnpinnedPackage":
113
+ return TarballUnpinnedPackage(
114
+ tarball=self.tarball, tarball_unrendered=self.tarball_unrendered, package=self.package
115
+ )
116
+
117
+ def resolved(self) -> TarballPinnedPackage:
118
+ return TarballPinnedPackage(
119
+ tarball=self.tarball, tarball_unrendered=self.tarball_unrendered, package=self.package
120
+ )
@@ -0,0 +1,119 @@
1
+ import traceback
2
+ import typing as t
3
+
4
+ import click
5
+ import click.types as click_t
6
+ from docutils import nodes
7
+ from docutils.parsers.rst import Directive
8
+
9
+ import dbt.cli.option_types as dbt_t
10
+
11
+ PARAM_TYPE_MAP = {
12
+ click_t.BoolParamType: lambda _: "boolean",
13
+ click_t.Choice: lambda c: f"choice: {c.choices}",
14
+ click_t.IntParamType: lambda _: "int",
15
+ click_t.Path: lambda _: "path",
16
+ click_t.StringParamType: lambda _: "string",
17
+ dbt_t.YAML: lambda _: "YAML",
18
+ }
19
+
20
+
21
+ def format_command(cmd) -> nodes.section:
22
+ cmd_name = cmd.name.replace("-", "_")
23
+ section = nodes.section(
24
+ "",
25
+ nodes.title(text=f"Command: {cmd_name}"),
26
+ ids=[cmd_name],
27
+ names=[cmd_name],
28
+ )
29
+ section.extend(format_params(cmd))
30
+ return section
31
+
32
+
33
+ def format_params(cmd) -> t.List[nodes.section]:
34
+ lines = []
35
+ for param in cmd.params:
36
+ uid = f"{cmd.name}|{param.name}"
37
+ param_section = nodes.section(
38
+ "",
39
+ nodes.title(text=param.name),
40
+ ids=[uid],
41
+ names=[uid],
42
+ )
43
+
44
+ get_type_str = PARAM_TYPE_MAP.get(type(param.type), lambda _: "unknown")
45
+ type_str = get_type_str(param.type)
46
+
47
+ param_section.append(nodes.paragraph(text=f"Type: {type_str}"))
48
+ help_txt = getattr(param, "help", None)
49
+ if help_txt is not None:
50
+ param_section.append(nodes.paragraph(text=help_txt))
51
+ lines.append(param_section)
52
+ return lines
53
+
54
+
55
+ def load_module(module_path: str, error) -> t.Union[click.Command, click.Group]:
56
+ try:
57
+ module_name, attr_name = module_path.split(":", 1)
58
+ except ValueError: # noqa
59
+ raise error(f'"{module_path}" is not of format "module:parser"')
60
+
61
+ try:
62
+ mod = __import__(module_name, globals(), locals(), [attr_name])
63
+ except Exception: # noqa
64
+ raise error(
65
+ f'Failed to import "{attr_name}" from "{module_name}". '
66
+ f"The following exception was raised:\n{traceback.format_exc()}"
67
+ )
68
+
69
+ if not hasattr(mod, attr_name):
70
+ raise error(f'Module "{module_name}" has no attribute "{attr_name}"')
71
+
72
+ parser = getattr(mod, attr_name)
73
+
74
+ if not isinstance(parser, (click.Command, click.Group)):
75
+ raise error(
76
+ f'"{type(parser)}" of type "{module_path}" is not click.Command'
77
+ ' or click.Group."click.BaseCommand"'
78
+ )
79
+ return parser
80
+
81
+
82
+ class DBTClick(Directive):
83
+ has_content = False
84
+ required_arguments = 1
85
+
86
+ def run(self):
87
+ section = nodes.section(
88
+ "",
89
+ ids=["dbt-section"],
90
+ names=["dbt-section"],
91
+ )
92
+ cmds = self._get_commands(self.arguments[0])
93
+ for cmd in cmds:
94
+ command_section = format_command(cmd)
95
+ section.extend(command_section)
96
+ return [section]
97
+
98
+ def _get_commands(self, module: str) -> t.List[click.Command]:
99
+ click_group = load_module(module, self.error)
100
+ if type(click_group) is not click.Group:
101
+ raise self.error('Type "click.Group" not supported in dbt_click extension')
102
+ cmd_strs = [cmd for cmd in click_group.commands]
103
+ cmd_strs.sort()
104
+ cmds = []
105
+ for cmd_str in cmd_strs:
106
+ cmd = click_group.commands.get(cmd_str)
107
+ if cmd is not None:
108
+ cmds.append(cmd)
109
+ return cmds
110
+
111
+
112
+ def setup(app) -> t.Dict[str, t.Any]:
113
+ app.add_directive("dbt_click", DBTClick)
114
+
115
+ return {
116
+ "version": "0.1",
117
+ "parallel_read_safe": True,
118
+ "parallel_write_safe": True,
119
+ }
@@ -0,0 +1,32 @@
1
+ import os
2
+ import sys
3
+ import typing as t
4
+
5
+ # Configuration file for the Sphinx documentation builder.
6
+ #
7
+ # For the full list of built-in configuration values, see the documentation:
8
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html
9
+
10
+ sys.path.insert(0, os.path.abspath("../../.."))
11
+ sys.path.insert(0, os.path.abspath("./_ext"))
12
+
13
+ # -- Project information -----------------------------------------------------
14
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
15
+
16
+ project = "dbt-core"
17
+ copyright = "2022, dbt Labs"
18
+ author = "dbt Labs"
19
+
20
+ # -- General configuration ---------------------------------------------------
21
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
22
+
23
+ extensions = ["dbt_click"]
24
+
25
+ templates_path = ["_templates"]
26
+ exclude_patterns: t.List[str] = []
27
+
28
+ # -- Options for HTML output -------------------------------------------------
29
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
30
+
31
+ html_theme = "alabaster"
32
+ html_static_path = ["_static"]
dbt/env_vars.py ADDED
@@ -0,0 +1,64 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from dbt.cli import params
5
+ from dbt.deprecations import warn
6
+ from dbt.exceptions import DbtInternalError
7
+ from dbt_common.constants import ENGINE_ENV_PREFIX
8
+ from dbt_common.context import get_invocation_context
9
+
10
+ # These are env vars that are not in the params module, but are still allowed to be set.
11
+ # New additions to this list should use the new naming scheme, unless they are being added because
12
+ # they already existed, but we didn't know about them previously.
13
+ # TODO: Should at least some of these become (undocumented) cli param options?
14
+ _ADDITIONAL_ENGINE_ENV_VARS: List[str] = [
15
+ "DBT_INVOCATION_ENV",
16
+ "DBT_RECORDED_FILE_PATH",
17
+ "DBT_TEST_STATE_MODIFIED", # TODO: This is testing related, should we do this differently?
18
+ "DBT_PACKAGE_HUB_URL",
19
+ "DBT_DOWNLOAD_DIR",
20
+ "DBT_PP_FILE_DIFF_TEST", # TODO: This is testing related, should we do this differently?
21
+ "DBT_PP_TEST", # TODO: This is testing related, should we do this differently?
22
+ ]
23
+
24
+
25
+ @dataclass(frozen=True, init=False)
26
+ class EngineEnvVar:
27
+ name: str
28
+ old_name: Optional[str] = None
29
+
30
+ def __init__(self, envvar: str) -> None:
31
+ if envvar.startswith(ENGINE_ENV_PREFIX):
32
+ object.__setattr__(self, "name", envvar)
33
+ object.__setattr__(self, "old_name", None)
34
+ elif envvar.startswith("DBT") or envvar.startswith("DVT"):
35
+ # Allow both DBT_ and DVT_ prefixes for DVT-core
36
+ object.__setattr__(self, "name", envvar.replace("DBT", f"{ENGINE_ENV_PREFIX}").replace("DVT", f"{ENGINE_ENV_PREFIX}"))
37
+ object.__setattr__(self, "old_name", envvar)
38
+ else:
39
+ raise DbtInternalError(
40
+ f"Invalid environment variable: {envvar}, this will only happen if we add a new option to dbt that has an envvar that doesn't start with DBT_, DVT_, or {ENGINE_ENV_PREFIX}"
41
+ )
42
+
43
+
44
+ # Here we are creating a set of all known engine env vars. This is used in this moduleto create an allow list of dbt
45
+ # engine env vars. We also use it in the cli flags module to cross propagate engine env vars with their old non-engine prefixed names.
46
+ KNOWN_ENGINE_ENV_VARS: set[EngineEnvVar] = {
47
+ EngineEnvVar(envvar=envvar)
48
+ for envvar in [*params.KNOWN_ENV_VARS, *_ADDITIONAL_ENGINE_ENV_VARS]
49
+ }
50
+ _ALLOWED_ENV_VARS: set[str] = {envvar.name for envvar in KNOWN_ENGINE_ENV_VARS}
51
+
52
+
53
+ def validate_engine_env_vars() -> None:
54
+ """
55
+ Validate that any set environment variables that begin with the engine prefix are allowed.
56
+ """
57
+ env_vars = get_invocation_context()._env
58
+ for env_var in env_vars.keys():
59
+ if env_var.startswith(ENGINE_ENV_PREFIX) and env_var not in _ALLOWED_ENV_VARS:
60
+ warn(
61
+ "environment-variable-namespace-deprecation",
62
+ env_var=env_var,
63
+ reserved_prefix=ENGINE_ENV_PREFIX,
64
+ )