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
@@ -0,0 +1,342 @@
1
+ """
2
+ DVT (Data Virtualization Tool) Profile Extensions
3
+
4
+ This module extends the dbt Profile class to support multiple named connections
5
+ per profile, enabling multi-source data federation.
6
+ """
7
+
8
+
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, Dict, Optional, Tuple
11
+
12
+ from dbt.adapters.contracts.connection import Credentials
13
+ from dbt.config.profile import Profile
14
+ from dbt.exceptions import DbtProfileError, DbtRuntimeError
15
+ from dbt_common.dataclass_schema import ValidationError
16
+
17
+
18
+ @dataclass
19
+ class DVTProfile(Profile):
20
+ """
21
+ Extended Profile class that supports multiple named connections.
22
+
23
+ In addition to the standard dbt Profile fields (profile_name, target_name, threads, credentials),
24
+ DVTProfile adds:
25
+ - connections: Dict of named connections (each with its own Credentials)
26
+ - default_target: The connection name to use for materialization by default
27
+
28
+ The 'credentials' field is maintained for backward compatibility and points to the default_target credentials.
29
+ """
30
+
31
+ # Additional DVT-specific fields
32
+ outputs: Dict[str, Credentials] = field(default_factory=dict)
33
+ default_target: Optional[str] = None
34
+
35
+ def __init__(
36
+ self,
37
+ profile_name: str,
38
+ target_name: str,
39
+ threads: int,
40
+ credentials: Credentials,
41
+ connections: Optional[Dict[str, Credentials]] = None,
42
+ default_target: Optional[str] = None,
43
+ ) -> None:
44
+ """
45
+ Initialize DVT Profile with multi-connection support.
46
+
47
+ :param profile_name: Name of the profile
48
+ :param target_name: Name of the target (for backward compatibility)
49
+ :param threads: Number of threads for parallel execution
50
+ :param credentials: Default credentials (for backward compatibility)
51
+ :param connections: Dictionary of named outputs (same as dbt)
52
+ :param default_target: Default output name for materialization
53
+ """
54
+ super().__init__(
55
+ profile_name=profile_name,
56
+ target_name=target_name,
57
+ threads=threads,
58
+ credentials=credentials,
59
+ )
60
+
61
+ self.outputs = connections or {}
62
+ self.default_target = default_target
63
+
64
+ # If outputs dict is provided but default_target is not, use target_name
65
+ if self.outputs and not self.default_target:
66
+ self.default_target = target_name
67
+
68
+ # Ensure backward compatibility: if outputs is empty, populate with single credentials
69
+ if not self.outputs and credentials:
70
+ self.outputs[target_name] = credentials
71
+ self.default_target = target_name
72
+
73
+ def get_connection(self, connection_name: Optional[str] = None) -> Credentials:
74
+ """
75
+ Get credentials for a specific output.
76
+
77
+ :param connection_name: Name of the output. If None, returns default_target credentials.
78
+ :returns: Credentials for the specified output
79
+ :raises DbtProfileError: If connection_name not found
80
+ """
81
+ name = connection_name or self.default_target
82
+
83
+ if not name:
84
+ raise DbtProfileError("No output name specified and no default_target configured")
85
+
86
+ if name not in self.outputs:
87
+ available = ", ".join(self.outputs.keys())
88
+ raise DbtProfileError(
89
+ f"Output '{name}' not found in profile '{self.profile_name}'. "
90
+ f"Available outputs: {available}"
91
+ )
92
+
93
+ return self.outputs[name]
94
+
95
+ def to_profile_info(self, serialize_credentials: bool = False) -> Dict[str, Any]:
96
+ """
97
+ Serialize DVT profile to dict.
98
+
99
+ :param serialize_credentials: If True, serialize all credentials to dicts
100
+ :returns: Serialized profile dict
101
+ """
102
+ result = super().to_profile_info(serialize_credentials=serialize_credentials)
103
+
104
+ # DVT uses standard dbt format - no need to serialize outputs separately
105
+ # since multi-output support is just for convenience, validation uses single target
106
+
107
+ return result
108
+
109
+ @staticmethod
110
+ def _parse_connections_from_profile(
111
+ profile: Dict[str, Any], profile_name: str
112
+ ) -> Tuple[Dict[str, Credentials], Optional[str]]:
113
+ """
114
+ Parse multiple outputs from profile configuration.
115
+
116
+ DVT uses standard dbt format with 'outputs' key and optional multi-output support:
117
+ outputs:
118
+ postgres_prod:
119
+ type: postgres
120
+ host: prod.example.com
121
+ ...
122
+ snowflake_warehouse:
123
+ type: snowflake
124
+ account: abc123
125
+ ...
126
+ target: postgres_prod
127
+
128
+ :param profile: Raw profile dict from YAML
129
+ :param profile_name: Name of the profile
130
+ :returns: Tuple of (outputs dict, default_target name)
131
+ :raises DbtProfileError: If profile format is invalid
132
+ """
133
+ # avoid an import cycle
134
+ from dbt.adapters.factory import load_plugin
135
+
136
+ outputs = {}
137
+ default_target = None
138
+
139
+ # Check for 'outputs' key (standard dbt format)
140
+ if "outputs" in profile:
141
+ raw_outputs = profile["outputs"]
142
+
143
+ if not isinstance(raw_outputs, dict):
144
+ raise DbtProfileError(
145
+ f"'outputs' in profile '{profile_name}' must be a dictionary"
146
+ )
147
+
148
+ # Parse each output
149
+ for output_name, output_data in raw_outputs.items():
150
+ if not isinstance(output_data, dict):
151
+ raise DbtProfileError(
152
+ f"Output '{output_name}' in profile '{profile_name}' must be a dictionary"
153
+ )
154
+
155
+ if "type" not in output_data:
156
+ raise DbtProfileError(
157
+ f"Output '{output_name}' in profile '{profile_name}' missing required 'type' field"
158
+ )
159
+
160
+ # Parse credentials for this output
161
+ output_data_copy = output_data.copy()
162
+ typename = output_data_copy.pop("type")
163
+
164
+ try:
165
+ cls = load_plugin(typename)
166
+ data = cls.translate_aliases(output_data_copy)
167
+ cls.validate(data)
168
+ credentials = cls.from_dict(data)
169
+ outputs[output_name] = credentials
170
+ except (DbtRuntimeError, ValidationError) as e:
171
+ msg = str(e) if isinstance(e, DbtRuntimeError) else e.message
172
+ raise DbtProfileError(
173
+ f"Credentials for output '{output_name}' in profile '{profile_name}' invalid: {msg}"
174
+ ) from e
175
+
176
+ # Get default target - use 'target' field (standard dbt)
177
+ # Also support 'default_target' for backward compatibility
178
+ default_target = profile.get("target") or profile.get("default_target")
179
+ if not default_target and outputs:
180
+ # If not specified, use first output as default
181
+ default_target = list(outputs.keys())[0]
182
+
183
+ if default_target and default_target not in outputs:
184
+ raise DbtProfileError(
185
+ f"target '{default_target}' not found in outputs of profile '{profile_name}'"
186
+ )
187
+
188
+ return outputs, default_target
189
+
190
+ @classmethod
191
+ def from_raw_profile_info(
192
+ cls,
193
+ raw_profile: Dict[str, Any],
194
+ profile_name: str,
195
+ renderer: Any, # ProfileRenderer
196
+ target_override: Optional[str] = None,
197
+ threads_override: Optional[int] = None,
198
+ ) -> "DVTProfile":
199
+ """
200
+ Create a DVTProfile from raw profile information.
201
+
202
+ This method supports both DVT multi-connection format and legacy dbt format.
203
+
204
+ :param raw_profile: The profile data for a single profile
205
+ :param profile_name: The profile name used
206
+ :param renderer: The config renderer
207
+ :param target_override: The target to use, if provided on the command line
208
+ :param threads_override: The thread count to use, if provided
209
+ :returns: The new DVTProfile object
210
+ :raises DbtProfileError: If the profile is invalid
211
+ """
212
+ # Check if this is a DVT multi-output profile
213
+ if "outputs" in raw_profile and len(raw_profile.get("outputs", {})) > 0:
214
+ # Parse outputs
215
+ outputs, default_target = cls._parse_connections_from_profile(
216
+ raw_profile, profile_name
217
+ )
218
+
219
+ if not outputs:
220
+ raise DbtProfileError(
221
+ f"Profile '{profile_name}' has 'outputs' key but no valid outputs defined"
222
+ )
223
+
224
+ # Get threads
225
+ threads = raw_profile.get("threads", 1)
226
+ if threads_override is not None:
227
+ threads = threads_override
228
+
229
+ # Determine target name
230
+ if target_override:
231
+ target_name = target_override
232
+ if target_name not in outputs:
233
+ raise DbtProfileError(
234
+ f"Target override '{target_name}' not found in outputs of profile '{profile_name}'"
235
+ )
236
+ default_target = target_name
237
+ else:
238
+ target_name = default_target or list(outputs.keys())[0]
239
+
240
+ # Get default credentials for backward compatibility
241
+ credentials = outputs[target_name]
242
+
243
+ profile = cls(
244
+ profile_name=profile_name,
245
+ target_name=target_name,
246
+ threads=threads,
247
+ credentials=credentials,
248
+ connections=outputs,
249
+ default_target=default_target,
250
+ )
251
+ profile.validate()
252
+ return profile
253
+
254
+ else:
255
+ # Fall back to legacy dbt format - use parent class implementation
256
+ legacy_profile = Profile.from_raw_profile_info(
257
+ raw_profile=raw_profile,
258
+ profile_name=profile_name,
259
+ renderer=renderer,
260
+ target_override=target_override,
261
+ threads_override=threads_override,
262
+ )
263
+
264
+ # Convert to DVTProfile for consistency
265
+ return cls(
266
+ profile_name=legacy_profile.profile_name,
267
+ target_name=legacy_profile.target_name,
268
+ threads=legacy_profile.threads,
269
+ credentials=legacy_profile.credentials,
270
+ connections={legacy_profile.target_name: legacy_profile.credentials},
271
+ default_target=legacy_profile.target_name,
272
+ )
273
+
274
+ @classmethod
275
+ def from_raw_profiles(
276
+ cls,
277
+ raw_profiles: Dict[str, Any],
278
+ profile_name: str,
279
+ renderer: Any, # ProfileRenderer
280
+ target_override: Optional[str] = None,
281
+ threads_override: Optional[int] = None,
282
+ ) -> "DVTProfile":
283
+ """
284
+ Create DVTProfile from raw profiles dict.
285
+
286
+ :param raw_profiles: The profile data, from disk as yaml
287
+ :param profile_name: The profile name to use
288
+ :param renderer: The config renderer
289
+ :param target_override: The target to use, if provided
290
+ :param threads_override: The thread count to use, if provided
291
+ :returns: The new DVTProfile object
292
+ """
293
+ from dbt.exceptions import DbtProjectError
294
+
295
+ if profile_name not in raw_profiles:
296
+ raise DbtProjectError(f"Could not find profile named '{profile_name}'")
297
+
298
+ raw_profile = raw_profiles[profile_name]
299
+ if not raw_profile:
300
+ raise DbtProfileError(f"Profile {profile_name} in profiles.yml is empty")
301
+
302
+ return cls.from_raw_profile_info(
303
+ raw_profile=raw_profile,
304
+ profile_name=profile_name,
305
+ renderer=renderer,
306
+ target_override=target_override,
307
+ threads_override=threads_override,
308
+ )
309
+
310
+ @classmethod
311
+ def render(
312
+ cls,
313
+ renderer: Any, # ProfileRenderer
314
+ project_profile_name: Optional[str],
315
+ profile_name_override: Optional[str] = None,
316
+ target_override: Optional[str] = None,
317
+ threads_override: Optional[int] = None,
318
+ ) -> "DVTProfile":
319
+ """
320
+ Render a DVTProfile from disk.
321
+
322
+ :param renderer: The config renderer
323
+ :param project_profile_name: The profile name from project
324
+ :param profile_name_override: Profile name override from CLI
325
+ :param target_override: Target override from CLI
326
+ :param threads_override: Threads override from CLI
327
+ :returns: The new DVTProfile object
328
+ """
329
+ from dbt.config.profile import read_profile
330
+ from dbt.flags import get_flags
331
+
332
+ flags = get_flags()
333
+ raw_profiles = read_profile(flags.PROFILES_DIR)
334
+ profile_name = cls.pick_profile_name(profile_name_override, project_profile_name)
335
+
336
+ return cls.from_raw_profiles(
337
+ raw_profiles=raw_profiles,
338
+ profile_name=profile_name,
339
+ renderer=renderer,
340
+ target_override=target_override,
341
+ threads_override=threads_override,
342
+ )