dvt-core 0.58.6__cp311-cp311-macosx_10_9_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) 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 +2403 -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 +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.cpython-311-darwin.so +0 -0
  74. dbt/compute/engines/spark_engine.py +642 -0
  75. dbt/compute/federated_executor.cpython-311-darwin.so +0 -0
  76. dbt/compute/federated_executor.py +1080 -0
  77. dbt/compute/filter_pushdown.cpython-311-darwin.so +0 -0
  78. dbt/compute/filter_pushdown.py +273 -0
  79. dbt/compute/jar_provisioning.cpython-311-darwin.so +0 -0
  80. dbt/compute/jar_provisioning.py +255 -0
  81. dbt/compute/java_compat.cpython-311-darwin.so +0 -0
  82. dbt/compute/java_compat.py +689 -0
  83. dbt/compute/jdbc_utils.cpython-311-darwin.so +0 -0
  84. dbt/compute/jdbc_utils.py +678 -0
  85. dbt/compute/metadata/__init__.py +40 -0
  86. dbt/compute/metadata/adapters_registry.cpython-311-darwin.so +0 -0
  87. dbt/compute/metadata/adapters_registry.py +370 -0
  88. dbt/compute/metadata/registry.cpython-311-darwin.so +0 -0
  89. dbt/compute/metadata/registry.py +674 -0
  90. dbt/compute/metadata/store.cpython-311-darwin.so +0 -0
  91. dbt/compute/metadata/store.py +1499 -0
  92. dbt/compute/smart_selector.cpython-311-darwin.so +0 -0
  93. dbt/compute/smart_selector.py +377 -0
  94. dbt/compute/strategies/__init__.py +55 -0
  95. dbt/compute/strategies/base.cpython-311-darwin.so +0 -0
  96. dbt/compute/strategies/base.py +165 -0
  97. dbt/compute/strategies/dataproc.cpython-311-darwin.so +0 -0
  98. dbt/compute/strategies/dataproc.py +207 -0
  99. dbt/compute/strategies/emr.cpython-311-darwin.so +0 -0
  100. dbt/compute/strategies/emr.py +203 -0
  101. dbt/compute/strategies/local.cpython-311-darwin.so +0 -0
  102. dbt/compute/strategies/local.py +443 -0
  103. dbt/compute/strategies/standalone.cpython-311-darwin.so +0 -0
  104. dbt/compute/strategies/standalone.py +262 -0
  105. dbt/config/__init__.py +4 -0
  106. dbt/config/catalogs.py +94 -0
  107. dbt/config/compute.cpython-311-darwin.so +0 -0
  108. dbt/config/compute.py +513 -0
  109. dbt/config/dvt_profile.cpython-311-darwin.so +0 -0
  110. dbt/config/dvt_profile.py +342 -0
  111. dbt/config/profile.py +422 -0
  112. dbt/config/project.py +873 -0
  113. dbt/config/project_utils.py +28 -0
  114. dbt/config/renderer.py +231 -0
  115. dbt/config/runtime.py +553 -0
  116. dbt/config/selectors.py +208 -0
  117. dbt/config/utils.py +77 -0
  118. dbt/constants.py +28 -0
  119. dbt/context/__init__.py +0 -0
  120. dbt/context/base.py +745 -0
  121. dbt/context/configured.py +135 -0
  122. dbt/context/context_config.py +382 -0
  123. dbt/context/docs.py +82 -0
  124. dbt/context/exceptions_jinja.py +178 -0
  125. dbt/context/macro_resolver.py +195 -0
  126. dbt/context/macros.py +171 -0
  127. dbt/context/manifest.py +72 -0
  128. dbt/context/providers.py +2249 -0
  129. dbt/context/query_header.py +13 -0
  130. dbt/context/secret.py +58 -0
  131. dbt/context/target.py +74 -0
  132. dbt/contracts/__init__.py +0 -0
  133. dbt/contracts/files.py +413 -0
  134. dbt/contracts/graph/__init__.py +0 -0
  135. dbt/contracts/graph/manifest.py +1904 -0
  136. dbt/contracts/graph/metrics.py +97 -0
  137. dbt/contracts/graph/model_config.py +70 -0
  138. dbt/contracts/graph/node_args.py +42 -0
  139. dbt/contracts/graph/nodes.py +1806 -0
  140. dbt/contracts/graph/semantic_manifest.py +232 -0
  141. dbt/contracts/graph/unparsed.py +811 -0
  142. dbt/contracts/project.py +417 -0
  143. dbt/contracts/results.py +53 -0
  144. dbt/contracts/selection.py +23 -0
  145. dbt/contracts/sql.py +85 -0
  146. dbt/contracts/state.py +68 -0
  147. dbt/contracts/util.py +46 -0
  148. dbt/deprecations.py +348 -0
  149. dbt/deps/__init__.py +0 -0
  150. dbt/deps/base.py +152 -0
  151. dbt/deps/git.py +195 -0
  152. dbt/deps/local.py +79 -0
  153. dbt/deps/registry.py +130 -0
  154. dbt/deps/resolver.py +149 -0
  155. dbt/deps/tarball.py +120 -0
  156. dbt/docs/source/_ext/dbt_click.py +119 -0
  157. dbt/docs/source/conf.py +32 -0
  158. dbt/env_vars.py +64 -0
  159. dbt/event_time/event_time.py +40 -0
  160. dbt/event_time/sample_window.py +60 -0
  161. dbt/events/__init__.py +15 -0
  162. dbt/events/base_types.py +36 -0
  163. dbt/events/core_types_pb2.py +2 -0
  164. dbt/events/logging.py +108 -0
  165. dbt/events/types.py +2516 -0
  166. dbt/exceptions.py +1486 -0
  167. dbt/flags.py +89 -0
  168. dbt/graph/__init__.py +11 -0
  169. dbt/graph/cli.py +249 -0
  170. dbt/graph/graph.py +172 -0
  171. dbt/graph/queue.py +214 -0
  172. dbt/graph/selector.py +374 -0
  173. dbt/graph/selector_methods.py +975 -0
  174. dbt/graph/selector_spec.py +222 -0
  175. dbt/graph/thread_pool.py +18 -0
  176. dbt/hooks.py +21 -0
  177. dbt/include/README.md +49 -0
  178. dbt/include/__init__.py +3 -0
  179. dbt/include/data/adapters_registry.duckdb +0 -0
  180. dbt/include/data/build_registry.py +242 -0
  181. dbt/include/data/csv/adapter_queries.csv +33 -0
  182. dbt/include/data/csv/syntax_rules.csv +9 -0
  183. dbt/include/data/csv/type_mappings_bigquery.csv +28 -0
  184. dbt/include/data/csv/type_mappings_databricks.csv +30 -0
  185. dbt/include/data/csv/type_mappings_mysql.csv +40 -0
  186. dbt/include/data/csv/type_mappings_oracle.csv +30 -0
  187. dbt/include/data/csv/type_mappings_postgres.csv +56 -0
  188. dbt/include/data/csv/type_mappings_redshift.csv +33 -0
  189. dbt/include/data/csv/type_mappings_snowflake.csv +38 -0
  190. dbt/include/data/csv/type_mappings_sqlserver.csv +35 -0
  191. dbt/include/starter_project/.gitignore +4 -0
  192. dbt/include/starter_project/README.md +15 -0
  193. dbt/include/starter_project/__init__.py +3 -0
  194. dbt/include/starter_project/analyses/.gitkeep +0 -0
  195. dbt/include/starter_project/dbt_project.yml +36 -0
  196. dbt/include/starter_project/macros/.gitkeep +0 -0
  197. dbt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
  198. dbt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
  199. dbt/include/starter_project/models/example/schema.yml +21 -0
  200. dbt/include/starter_project/seeds/.gitkeep +0 -0
  201. dbt/include/starter_project/snapshots/.gitkeep +0 -0
  202. dbt/include/starter_project/tests/.gitkeep +0 -0
  203. dbt/internal_deprecations.py +26 -0
  204. dbt/jsonschemas/__init__.py +3 -0
  205. dbt/jsonschemas/jsonschemas.py +309 -0
  206. dbt/jsonschemas/project/0.0.110.json +4717 -0
  207. dbt/jsonschemas/project/0.0.85.json +2015 -0
  208. dbt/jsonschemas/resources/0.0.110.json +2636 -0
  209. dbt/jsonschemas/resources/0.0.85.json +2536 -0
  210. dbt/jsonschemas/resources/latest.json +6773 -0
  211. dbt/links.py +4 -0
  212. dbt/materializations/__init__.py +0 -0
  213. dbt/materializations/incremental/__init__.py +0 -0
  214. dbt/materializations/incremental/microbatch.py +236 -0
  215. dbt/mp_context.py +8 -0
  216. dbt/node_types.py +37 -0
  217. dbt/parser/__init__.py +23 -0
  218. dbt/parser/analysis.py +21 -0
  219. dbt/parser/base.py +548 -0
  220. dbt/parser/common.py +266 -0
  221. dbt/parser/docs.py +52 -0
  222. dbt/parser/fixtures.py +51 -0
  223. dbt/parser/functions.py +30 -0
  224. dbt/parser/generic_test.py +100 -0
  225. dbt/parser/generic_test_builders.py +333 -0
  226. dbt/parser/hooks.py +118 -0
  227. dbt/parser/macros.py +137 -0
  228. dbt/parser/manifest.py +2204 -0
  229. dbt/parser/models.py +573 -0
  230. dbt/parser/partial.py +1178 -0
  231. dbt/parser/read_files.py +445 -0
  232. dbt/parser/schema_generic_tests.py +422 -0
  233. dbt/parser/schema_renderer.py +111 -0
  234. dbt/parser/schema_yaml_readers.py +935 -0
  235. dbt/parser/schemas.py +1466 -0
  236. dbt/parser/search.py +149 -0
  237. dbt/parser/seeds.py +28 -0
  238. dbt/parser/singular_test.py +20 -0
  239. dbt/parser/snapshots.py +44 -0
  240. dbt/parser/sources.py +558 -0
  241. dbt/parser/sql.py +62 -0
  242. dbt/parser/unit_tests.py +621 -0
  243. dbt/plugins/__init__.py +20 -0
  244. dbt/plugins/contracts.py +9 -0
  245. dbt/plugins/exceptions.py +2 -0
  246. dbt/plugins/manager.py +163 -0
  247. dbt/plugins/manifest.py +21 -0
  248. dbt/profiler.py +20 -0
  249. dbt/py.typed +1 -0
  250. dbt/query_analyzer.cpython-311-darwin.so +0 -0
  251. dbt/query_analyzer.py +410 -0
  252. dbt/runners/__init__.py +2 -0
  253. dbt/runners/exposure_runner.py +7 -0
  254. dbt/runners/no_op_runner.py +45 -0
  255. dbt/runners/saved_query_runner.py +7 -0
  256. dbt/selected_resources.py +8 -0
  257. dbt/task/__init__.py +0 -0
  258. dbt/task/base.py +503 -0
  259. dbt/task/build.py +197 -0
  260. dbt/task/clean.py +56 -0
  261. dbt/task/clone.py +161 -0
  262. dbt/task/compile.py +150 -0
  263. dbt/task/compute.cpython-311-darwin.so +0 -0
  264. dbt/task/compute.py +458 -0
  265. dbt/task/debug.py +505 -0
  266. dbt/task/deps.py +280 -0
  267. dbt/task/docs/__init__.py +3 -0
  268. dbt/task/docs/api/__init__.py +23 -0
  269. dbt/task/docs/api/catalog.cpython-311-darwin.so +0 -0
  270. dbt/task/docs/api/catalog.py +204 -0
  271. dbt/task/docs/api/lineage.cpython-311-darwin.so +0 -0
  272. dbt/task/docs/api/lineage.py +234 -0
  273. dbt/task/docs/api/profile.cpython-311-darwin.so +0 -0
  274. dbt/task/docs/api/profile.py +204 -0
  275. dbt/task/docs/api/spark.cpython-311-darwin.so +0 -0
  276. dbt/task/docs/api/spark.py +186 -0
  277. dbt/task/docs/generate.py +947 -0
  278. dbt/task/docs/index.html +250 -0
  279. dbt/task/docs/serve.cpython-311-darwin.so +0 -0
  280. dbt/task/docs/serve.py +174 -0
  281. dbt/task/dvt_output.py +362 -0
  282. dbt/task/dvt_run.py +204 -0
  283. dbt/task/freshness.py +322 -0
  284. dbt/task/function.py +121 -0
  285. dbt/task/group_lookup.py +46 -0
  286. dbt/task/init.cpython-311-darwin.so +0 -0
  287. dbt/task/init.py +604 -0
  288. dbt/task/java.cpython-311-darwin.so +0 -0
  289. dbt/task/java.py +316 -0
  290. dbt/task/list.py +236 -0
  291. dbt/task/metadata.cpython-311-darwin.so +0 -0
  292. dbt/task/metadata.py +804 -0
  293. dbt/task/printer.py +175 -0
  294. dbt/task/profile.cpython-311-darwin.so +0 -0
  295. dbt/task/profile.py +1307 -0
  296. dbt/task/profile_serve.py +615 -0
  297. dbt/task/retract.py +438 -0
  298. dbt/task/retry.py +175 -0
  299. dbt/task/run.py +1387 -0
  300. dbt/task/run_operation.py +141 -0
  301. dbt/task/runnable.py +758 -0
  302. dbt/task/seed.py +103 -0
  303. dbt/task/show.py +149 -0
  304. dbt/task/snapshot.py +56 -0
  305. dbt/task/spark.cpython-311-darwin.so +0 -0
  306. dbt/task/spark.py +414 -0
  307. dbt/task/sql.py +110 -0
  308. dbt/task/target_sync.cpython-311-darwin.so +0 -0
  309. dbt/task/target_sync.py +766 -0
  310. dbt/task/test.py +464 -0
  311. dbt/tests/fixtures/__init__.py +1 -0
  312. dbt/tests/fixtures/project.py +620 -0
  313. dbt/tests/util.py +651 -0
  314. dbt/tracking.py +529 -0
  315. dbt/utils/__init__.py +3 -0
  316. dbt/utils/artifact_upload.py +151 -0
  317. dbt/utils/utils.py +408 -0
  318. dbt/version.py +270 -0
  319. dvt_cli/__init__.py +72 -0
  320. dvt_core-0.58.6.dist-info/METADATA +288 -0
  321. dvt_core-0.58.6.dist-info/RECORD +324 -0
  322. dvt_core-0.58.6.dist-info/WHEEL +5 -0
  323. dvt_core-0.58.6.dist-info/entry_points.txt +2 -0
  324. dvt_core-0.58.6.dist-info/top_level.txt +2 -0
dbt/task/debug.py ADDED
@@ -0,0 +1,505 @@
1
+ # coding=utf-8
2
+ import importlib
3
+ import os
4
+ import platform
5
+ import sys
6
+ from collections import namedtuple
7
+ from enum import Flag
8
+ from pathlib import Path
9
+ from typing import Any, Dict, List, Optional, Tuple
10
+
11
+ import dbt.exceptions
12
+ import dbt_common.clients.system
13
+ import dbt_common.exceptions
14
+ from dbt.adapters.factory import get_adapter, register_adapter
15
+ from dbt.artifacts.schemas.results import RunStatus
16
+ from dbt.cli.flags import Flags
17
+
18
+ from dbt.config import PartialProject, Profile, Project
19
+ from dbt.config.dvt_profile import DVTProfile
20
+ from dbt.config.renderer import DbtProjectYamlRenderer, ProfileRenderer
21
+ from dbt.events.types import DebugCmdOut, DebugCmdResult, OpenCommand
22
+ from dbt.links import ProfileConfigDocs
23
+ from dbt.mp_context import get_mp_context
24
+ from dbt.task.base import BaseTask, get_nearest_project_dir
25
+ from dbt.version import get_installed_version
26
+ from dbt_common.events.format import pluralize
27
+ from dbt_common.events.functions import fire_event
28
+ from dbt_common.ui import green, red
29
+
30
+ ONLY_PROFILE_MESSAGE = """
31
+ A `dbt_project.yml` file was not found in this directory.
32
+ Using the only profile `{}`.
33
+ """.lstrip()
34
+
35
+ MULTIPLE_PROFILE_MESSAGE = """
36
+ A `dbt_project.yml` file was not found in this directory.
37
+ dbt found the following profiles:
38
+ {}
39
+
40
+ To debug one of these profiles, run:
41
+ dbt debug --profile [profile-name]
42
+ """.lstrip()
43
+
44
+ COULD_NOT_CONNECT_MESSAGE = """
45
+ dbt was unable to connect to the specified database.
46
+ The database returned the following error:
47
+
48
+ >{err}
49
+
50
+ Check your database credentials and try again. For more information, visit:
51
+ {url}
52
+ """.lstrip()
53
+
54
+ MISSING_PROFILE_MESSAGE = """
55
+ dbt looked for a profiles.yml file in {path}, but did
56
+ not find one. For more information on configuring your profile, consult the
57
+ documentation:
58
+
59
+ {url}
60
+ """.lstrip()
61
+
62
+ FILE_NOT_FOUND = "file not found"
63
+
64
+
65
+ SubtaskStatus = namedtuple(
66
+ "SubtaskStatus", ["log_msg", "run_status", "details", "summary_message"]
67
+ )
68
+
69
+
70
+ class DebugRunStatus(Flag):
71
+ SUCCESS = True
72
+ FAIL = False
73
+
74
+
75
+ class DebugTask(BaseTask):
76
+ def __init__(self, args: Flags) -> None:
77
+ super().__init__(args)
78
+ self.profiles_dir = args.PROFILES_DIR
79
+ self.profile_path = os.path.join(self.profiles_dir, "profiles.yml")
80
+ try:
81
+ self.project_dir = get_nearest_project_dir(self.args.project_dir)
82
+ except dbt_common.exceptions.DbtBaseException:
83
+ # we probably couldn't find a project directory. Set project dir
84
+ # to whatever was given, or default to the current directory.
85
+ if args.project_dir:
86
+ self.project_dir = args.project_dir
87
+ else:
88
+ self.project_dir = Path.cwd()
89
+ self.project_path = os.path.join(self.project_dir, "dbt_project.yml")
90
+ self.cli_vars: Dict[str, Any] = args.vars
91
+
92
+ # set by _load_*
93
+ self.profile: Optional[Profile] = None
94
+ self.raw_profile_data: Optional[Dict[str, Any]] = None
95
+ self.profile_name: Optional[str] = None
96
+
97
+ def run(self) -> bool:
98
+ # WARN: this is a legacy workflow that is not compatible with other runtime flags
99
+ if self.args.config_dir:
100
+ fire_event(
101
+ OpenCommand(
102
+ open_cmd=dbt_common.clients.system.open_dir_cmd(),
103
+ profiles_dir=str(self.profiles_dir),
104
+ )
105
+ )
106
+ return DebugRunStatus.SUCCESS.value
107
+
108
+ version: str = get_installed_version().to_version_string(skip_matcher=True)
109
+ fire_event(DebugCmdOut(msg="dbt version: {}".format(version)))
110
+ fire_event(DebugCmdOut(msg="python version: {}".format(sys.version.split()[0])))
111
+ fire_event(DebugCmdOut(msg="python path: {}".format(sys.executable)))
112
+ fire_event(DebugCmdOut(msg="os info: {}".format(platform.platform())))
113
+
114
+ # Load profile if possible, then load adapter info (which requires the profile)
115
+ load_profile_status: SubtaskStatus = self._load_profile()
116
+ fire_event(DebugCmdOut(msg="Using profiles dir at {}".format(self.profiles_dir)))
117
+ fire_event(DebugCmdOut(msg="Using profiles.yml file at {}".format(self.profile_path)))
118
+ fire_event(DebugCmdOut(msg="Using dbt_project.yml file at {}".format(self.project_path)))
119
+ if load_profile_status.run_status == RunStatus.Success:
120
+ if self.profile is None:
121
+ raise dbt_common.exceptions.DbtInternalError(
122
+ "Profile should not be None if loading profile completed"
123
+ )
124
+ else:
125
+ adapter_type: str = self.profile.credentials.type
126
+
127
+ adapter_version: str = self._read_adapter_version(
128
+ f"dbt.adapters.{adapter_type}.__version__"
129
+ )
130
+ fire_event(DebugCmdOut(msg="adapter type: {}".format(adapter_type)))
131
+ fire_event(DebugCmdOut(msg="adapter version: {}".format(adapter_version)))
132
+
133
+ # Get project loaded to do additional checks
134
+ load_project_status: SubtaskStatus = self._load_project()
135
+
136
+ dependencies_statuses: List[SubtaskStatus] = []
137
+ if self.args.connection:
138
+ fire_event(DebugCmdOut(msg="Skipping steps before connection verification"))
139
+ else:
140
+ # this job's status not logged since already accounted for in _load_* commands
141
+ self.test_configuration(load_profile_status.log_msg, load_project_status.log_msg)
142
+ dependencies_statuses = self.test_dependencies()
143
+
144
+ # Test connection
145
+ connection_status = self.test_connection()
146
+
147
+ # Log messages from any fails
148
+ all_statuses: List[SubtaskStatus] = [
149
+ load_profile_status,
150
+ load_project_status,
151
+ *dependencies_statuses,
152
+ connection_status,
153
+ ]
154
+ all_failing_statuses: List[SubtaskStatus] = list(
155
+ filter(lambda status: status.run_status == RunStatus.Error, all_statuses)
156
+ )
157
+
158
+ failure_count: int = len(all_failing_statuses)
159
+ if failure_count > 0:
160
+ fire_event(DebugCmdResult(msg=red(f"{(pluralize(failure_count, 'check'))} failed:")))
161
+ for status in all_failing_statuses:
162
+ fire_event(DebugCmdResult(msg=f"{status.summary_message}\n"))
163
+ return DebugRunStatus.FAIL.value
164
+ else:
165
+ fire_event(DebugCmdResult(msg=green("All checks passed!")))
166
+ return DebugRunStatus.SUCCESS.value
167
+
168
+ # ==============================
169
+ # Override for elsewhere in core
170
+ # ==============================
171
+
172
+ def interpret_results(self, results):
173
+ return results
174
+
175
+ # ===============
176
+ # Loading profile
177
+ # ===============
178
+
179
+ def _load_profile(self) -> SubtaskStatus:
180
+ """
181
+ Side effects: load self.profile
182
+ load self.target_name
183
+ load self.raw_profile_data
184
+ """
185
+ if not os.path.exists(self.profile_path):
186
+ return SubtaskStatus(
187
+ log_msg=red("ERROR not found"),
188
+ run_status=RunStatus.Error,
189
+ details=FILE_NOT_FOUND,
190
+ summary_message=MISSING_PROFILE_MESSAGE.format(
191
+ path=self.profile_path, url=ProfileConfigDocs
192
+ ),
193
+ )
194
+
195
+ # DVT: Use read_profile() to get automatic connections → outputs conversion
196
+ from dbt.config.profile import read_profile
197
+ raw_profile_data = read_profile(os.path.dirname(self.profile_path))
198
+ if isinstance(raw_profile_data, dict):
199
+ self.raw_profile_data = raw_profile_data
200
+
201
+ profile_errors = []
202
+ profile_names, summary_message = self._choose_profile_names()
203
+ renderer = ProfileRenderer(self.cli_vars)
204
+ for profile_name in profile_names:
205
+ try:
206
+ # DVT: Use DVTProfile.render instead of Profile.render
207
+ profile: Profile = DVTProfile.render(
208
+ renderer,
209
+ profile_name,
210
+ self.args.profile,
211
+ self.args.target,
212
+ # TODO: Generalize safe access to flags.THREADS:
213
+ # https://github.com/dbt-labs/dbt-core/issues/6259
214
+ getattr(self.args, "threads", None),
215
+ )
216
+ except dbt_common.exceptions.DbtConfigError as exc:
217
+ profile_errors.append(str(exc))
218
+ else:
219
+ if len(profile_names) == 1:
220
+ # if a profile was specified, set it on the task
221
+ self.target_name = self._choose_target_name(profile_name)
222
+ self.profile = profile
223
+
224
+ if profile_errors:
225
+ details = "\n\n".join(profile_errors)
226
+ return SubtaskStatus(
227
+ log_msg=red("ERROR invalid"),
228
+ run_status=RunStatus.Error,
229
+ details=details,
230
+ summary_message=(
231
+ summary_message + f"Profile loading failed for the following reason:"
232
+ f"\n{details}"
233
+ f"\n"
234
+ ),
235
+ )
236
+ else:
237
+ return SubtaskStatus(
238
+ log_msg=green("OK found and valid"),
239
+ run_status=RunStatus.Success,
240
+ details="",
241
+ summary_message="Profile is valid",
242
+ )
243
+
244
+ def _choose_profile_names(self) -> Tuple[List[str], str]:
245
+ project_profile: Optional[str] = None
246
+ if os.path.exists(self.project_path):
247
+ try:
248
+ partial = PartialProject.from_project_root(
249
+ os.path.dirname(self.project_path),
250
+ verify_version=bool(self.args.VERSION_CHECK),
251
+ )
252
+ renderer = DbtProjectYamlRenderer(None, self.cli_vars)
253
+ project_profile = partial.render_profile_name(renderer)
254
+ except dbt.exceptions.DbtProjectError:
255
+ pass
256
+
257
+ args_profile: Optional[str] = getattr(self.args, "profile", None)
258
+
259
+ try:
260
+ return [Profile.pick_profile_name(args_profile, project_profile)], ""
261
+ except dbt_common.exceptions.DbtConfigError:
262
+ pass
263
+ # try to guess
264
+
265
+ profiles = []
266
+ if self.raw_profile_data:
267
+ profiles = [k for k in self.raw_profile_data if k != "config"]
268
+ if project_profile is None:
269
+ summary_message = "Could not load dbt_project.yml\n"
270
+ elif len(profiles) == 0:
271
+ summary_message = "The profiles.yml has no profiles\n"
272
+ elif len(profiles) == 1:
273
+ summary_message = ONLY_PROFILE_MESSAGE.format(profiles[0])
274
+ else:
275
+ summary_message = MULTIPLE_PROFILE_MESSAGE.format(
276
+ "\n".join(" - {}".format(o) for o in profiles)
277
+ )
278
+ return profiles, summary_message
279
+
280
+ def _read_adapter_version(self, module) -> str:
281
+ """read the version out of a standard adapter file"""
282
+ try:
283
+ version = importlib.import_module(module).version
284
+ except ModuleNotFoundError:
285
+ version = red("ERROR not found")
286
+ except Exception as exc:
287
+ version = red("ERROR {}".format(exc))
288
+ raise dbt.exceptions.DbtInternalError(
289
+ f"Error when reading adapter version from {module}: {exc}"
290
+ )
291
+
292
+ return version
293
+
294
+ def _choose_target_name(self, profile_name: str):
295
+ has_raw_profile = (
296
+ self.raw_profile_data is not None and profile_name in self.raw_profile_data
297
+ )
298
+
299
+ if not has_raw_profile:
300
+ return None
301
+
302
+ # mypy appeasement, we checked just above
303
+ assert self.raw_profile_data is not None
304
+ raw_profile = self.raw_profile_data[profile_name]
305
+
306
+ renderer = ProfileRenderer(self.cli_vars)
307
+
308
+ # DVT: Use DVTProfile.render_profile instead of Profile.render_profile
309
+ target_name, _ = DVTProfile.render_profile(
310
+ raw_profile=raw_profile,
311
+ profile_name=profile_name,
312
+ target_override=getattr(self.args, "target", None),
313
+ renderer=renderer,
314
+ )
315
+ return target_name
316
+
317
+ # ===============
318
+ # Loading project
319
+ # ===============
320
+
321
+ def _load_project(self) -> SubtaskStatus:
322
+ """
323
+ Side effect: load self.project
324
+ """
325
+ if not os.path.exists(self.project_path):
326
+ return SubtaskStatus(
327
+ log_msg=red("ERROR not found"),
328
+ run_status=RunStatus.Error,
329
+ details=FILE_NOT_FOUND,
330
+ summary_message=(
331
+ f"Project loading failed for the following reason:"
332
+ f"\n project path <{self.project_path}> not found"
333
+ ),
334
+ )
335
+
336
+ renderer = DbtProjectYamlRenderer(self.profile, self.cli_vars)
337
+
338
+ try:
339
+ self.project = Project.from_project_root(
340
+ str(self.project_dir),
341
+ renderer,
342
+ verify_version=self.args.VERSION_CHECK,
343
+ )
344
+ except dbt_common.exceptions.DbtConfigError as exc:
345
+ return SubtaskStatus(
346
+ log_msg=red("ERROR invalid"),
347
+ run_status=RunStatus.Error,
348
+ details=str(exc),
349
+ summary_message=(
350
+ f"Project loading failed for the following reason:" f"\n{str(exc)}" f"\n"
351
+ ),
352
+ )
353
+ else:
354
+ return SubtaskStatus(
355
+ log_msg=green("OK found and valid"),
356
+ run_status=RunStatus.Success,
357
+ details="",
358
+ summary_message="Project is valid",
359
+ )
360
+
361
+ def _profile_found(self) -> str:
362
+ if not self.raw_profile_data:
363
+ return red("ERROR not found")
364
+ assert self.raw_profile_data is not None
365
+ if self.profile_name in self.raw_profile_data:
366
+ return green("OK found")
367
+ else:
368
+ return red("ERROR not found")
369
+
370
+ def _target_found(self) -> str:
371
+ requirements = self.raw_profile_data and self.profile_name and self.target_name
372
+ if not requirements:
373
+ return red("ERROR not found")
374
+ # mypy appeasement, we checked just above
375
+ assert self.raw_profile_data is not None
376
+ assert self.profile_name is not None
377
+ assert self.target_name is not None
378
+ if self.profile_name not in self.raw_profile_data:
379
+ return red("ERROR not found")
380
+ profiles = self.raw_profile_data[self.profile_name]["outputs"]
381
+ if self.target_name not in profiles:
382
+ return red("ERROR not found")
383
+ else:
384
+ return green("OK found")
385
+
386
+ # ============
387
+ # Config tests
388
+ # ============
389
+
390
+ def test_git(self) -> SubtaskStatus:
391
+ try:
392
+ dbt_common.clients.system.run_cmd(os.getcwd(), ["git", "--help"])
393
+ except dbt_common.exceptions.ExecutableError as exc:
394
+ return SubtaskStatus(
395
+ log_msg=red("ERROR"),
396
+ run_status=RunStatus.Error,
397
+ details="git error",
398
+ summary_message="Error from git --help: {!s}".format(exc),
399
+ )
400
+ else:
401
+ return SubtaskStatus(
402
+ log_msg=green("OK found"),
403
+ run_status=RunStatus.Success,
404
+ details="",
405
+ summary_message="git is installed and on the path",
406
+ )
407
+
408
+ def test_dependencies(self) -> List[SubtaskStatus]:
409
+ fire_event(DebugCmdOut(msg="Required dependencies:"))
410
+
411
+ git_test_status = self.test_git()
412
+ fire_event(DebugCmdResult(msg=f" - git [{git_test_status.log_msg}]\n"))
413
+
414
+ return [git_test_status]
415
+
416
+ def test_configuration(self, profile_status_msg, project_status_msg):
417
+ fire_event(DebugCmdOut(msg="Configuration:"))
418
+ fire_event(DebugCmdOut(msg=f" profiles.yml file [{profile_status_msg}]"))
419
+ fire_event(DebugCmdOut(msg=f" dbt_project.yml file [{project_status_msg}]"))
420
+
421
+ # skip profile stuff if we can't find a profile name
422
+ if self.profile_name is not None:
423
+ fire_event(
424
+ DebugCmdOut(
425
+ msg=" profile: {} [{}]\n".format(self.profile_name, self._profile_found())
426
+ )
427
+ )
428
+ fire_event(
429
+ DebugCmdOut(
430
+ msg=" target: {} [{}]\n".format(self.target_name, self._target_found())
431
+ )
432
+ )
433
+
434
+ # ===============
435
+ # Connection test
436
+ # ===============
437
+
438
+ @staticmethod
439
+ def attempt_connection(profile) -> Optional[str]:
440
+ """Return a string containing the error message, or None if there was no error."""
441
+ register_adapter(profile, get_mp_context())
442
+ adapter = get_adapter(profile)
443
+ try:
444
+ with adapter.connection_named("debug"):
445
+ # is defined in adapter class
446
+ adapter.debug_query()
447
+ except Exception as exc:
448
+ return COULD_NOT_CONNECT_MESSAGE.format(
449
+ err=str(exc),
450
+ url=ProfileConfigDocs,
451
+ )
452
+ return None
453
+
454
+ def test_connection(self) -> SubtaskStatus:
455
+ if self.profile is None:
456
+ fire_event(DebugCmdOut(msg="Connection test skipped since no profile was found"))
457
+ return SubtaskStatus(
458
+ log_msg=red("SKIPPED"),
459
+ run_status=RunStatus.Skipped,
460
+ details="No profile found",
461
+ summary_message="Connection test skipped since no profile was found",
462
+ )
463
+
464
+ fire_event(DebugCmdOut(msg="Connection:"))
465
+ for k, v in self.profile.credentials.connection_info():
466
+ fire_event(DebugCmdOut(msg=f" {k}: {v}"))
467
+
468
+ connection_result = self.attempt_connection(self.profile)
469
+ if connection_result is None:
470
+ status = SubtaskStatus(
471
+ log_msg=green("OK connection ok"),
472
+ run_status=RunStatus.Success,
473
+ details="",
474
+ summary_message="Connection test passed",
475
+ )
476
+ else:
477
+ status = SubtaskStatus(
478
+ log_msg=red("ERROR"),
479
+ run_status=RunStatus.Error,
480
+ details="Failure in connecting to db",
481
+ summary_message=connection_result,
482
+ )
483
+ fire_event(DebugCmdOut(msg=f" Connection test: [{status.log_msg}]\n"))
484
+ return status
485
+
486
+ @classmethod
487
+ def validate_connection(cls, target_dict) -> None:
488
+ """Validate a connection dictionary. On error, raises a DbtConfigError."""
489
+ target_name = "test"
490
+ # make a fake profile that we can parse
491
+ profile_data = {
492
+ "outputs": {
493
+ target_name: target_dict,
494
+ },
495
+ }
496
+ # this will raise a DbtConfigError on failure
497
+ profile = Profile.from_raw_profile_info(
498
+ raw_profile=profile_data,
499
+ profile_name="",
500
+ target_override=target_name,
501
+ renderer=ProfileRenderer({}),
502
+ )
503
+ result = cls.attempt_connection(profile)
504
+ if result is not None:
505
+ raise dbt.exceptions.DbtProfileError(result, result_type="connection_failure")