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,28 @@
1
+ """Utility functions for working with dbt project files."""
2
+
3
+ from pathlib import Path
4
+ from typing import Optional
5
+ import yaml
6
+
7
+
8
+ def get_project_profile_name(project_dir: Path) -> Optional[str]:
9
+ """
10
+ Read profile name from dbt_project.yml in the given directory.
11
+
12
+ Args:
13
+ project_dir: Path to the project directory
14
+
15
+ Returns:
16
+ Profile name if found, None otherwise
17
+ """
18
+ try:
19
+ project_yml_path = project_dir / "dbt_project.yml"
20
+ if not project_yml_path.exists():
21
+ return None
22
+
23
+ with open(project_yml_path) as f:
24
+ project = yaml.safe_load(f)
25
+ return project.get("profile")
26
+ except Exception:
27
+ # Silently handle any YAML parsing or file read errors
28
+ return None
dbt/config/renderer.py ADDED
@@ -0,0 +1,231 @@
1
+ import re
2
+ from datetime import date
3
+ from typing import Any, Callable, Dict, Optional, Tuple, Union
4
+
5
+ from dbt.adapters.contracts.connection import HasCredentials
6
+ from dbt.clients.jinja import get_rendered
7
+ from dbt.constants import DEPENDENCIES_FILE_NAME, SECRET_PLACEHOLDER
8
+ from dbt.context.base import BaseContext
9
+ from dbt.context.secret import SecretContext
10
+ from dbt.context.target import TargetContext
11
+ from dbt.exceptions import DbtProjectError
12
+ from dbt_common.clients.jinja import catch_jinja
13
+ from dbt_common.constants import SECRET_ENV_PREFIX
14
+ from dbt_common.context import get_invocation_context
15
+ from dbt_common.exceptions import CompilationError, RecursionError
16
+ from dbt_common.utils import deep_map_render
17
+
18
+ Keypath = Tuple[Union[str, int], ...]
19
+
20
+
21
+ class BaseRenderer:
22
+ def __init__(self, context: Dict[str, Any]) -> None:
23
+ self.context = context
24
+
25
+ @property
26
+ def name(self):
27
+ return "Rendering"
28
+
29
+ def should_render_keypath(self, keypath: Keypath) -> bool:
30
+ return True
31
+
32
+ def render_entry(self, value: Any, keypath: Keypath) -> Any:
33
+ if not self.should_render_keypath(keypath):
34
+ return value
35
+
36
+ return self.render_value(value, keypath)
37
+
38
+ def render_value(self, value: Any, keypath: Optional[Keypath] = None) -> Any:
39
+ # keypath is ignored (and someone who knows should explain why here)
40
+ if not isinstance(value, str):
41
+ return value if not isinstance(value, date) else value.isoformat()
42
+
43
+ try:
44
+ with catch_jinja():
45
+ return get_rendered(value, self.context, native=True)
46
+ except CompilationError as exc:
47
+ msg = f"Could not render {value}: {exc.msg}"
48
+ raise CompilationError(msg) from exc
49
+
50
+ def render_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
51
+ try:
52
+ return deep_map_render(self.render_entry, data)
53
+ except RecursionError:
54
+ raise DbtProjectError(
55
+ f"Cycle detected: {self.name} input has a reference to itself", project=data
56
+ )
57
+
58
+
59
+ def _list_if_none(value):
60
+ if value is None:
61
+ value = []
62
+ return value
63
+
64
+
65
+ def _dict_if_none(value):
66
+ if value is None:
67
+ value = {}
68
+ return value
69
+
70
+
71
+ def _list_if_none_or_string(value):
72
+ value = _list_if_none(value)
73
+ if isinstance(value, str):
74
+ return [value]
75
+ return value
76
+
77
+
78
+ class ProjectPostprocessor(Dict[Keypath, Callable[[Any], Any]]):
79
+ def __init__(self) -> None:
80
+ super().__init__()
81
+
82
+ self[("on-run-start",)] = _list_if_none_or_string
83
+ self[("on-run-end",)] = _list_if_none_or_string
84
+
85
+ for k in ("models", "seeds", "snapshots"):
86
+ self[(k,)] = _dict_if_none
87
+ self[(k, "vars")] = _dict_if_none
88
+ self[(k, "pre-hook")] = _list_if_none_or_string
89
+ self[(k, "post-hook")] = _list_if_none_or_string
90
+ self[("seeds", "column_types")] = _dict_if_none
91
+
92
+ def postprocess(self, value: Any, key: Keypath) -> Any:
93
+ if key in self:
94
+ handler = self[key]
95
+ return handler(value)
96
+
97
+ return value
98
+
99
+
100
+ class DbtProjectYamlRenderer(BaseRenderer):
101
+ _KEYPATH_HANDLERS = ProjectPostprocessor()
102
+
103
+ def __init__(
104
+ self, profile: Optional[HasCredentials] = None, cli_vars: Optional[Dict[str, Any]] = None
105
+ ) -> None:
106
+ # Generate contexts here because we want to save the context
107
+ # object in order to retrieve the env_vars. This is almost always
108
+ # a TargetContext, but in the debug task we want a project
109
+ # even when we don't have a profile.
110
+ if cli_vars is None:
111
+ cli_vars = {}
112
+ if profile:
113
+ self.ctx_obj = TargetContext(profile.to_target_dict(), cli_vars)
114
+ else:
115
+ self.ctx_obj = BaseContext(cli_vars) # type:ignore
116
+ context = self.ctx_obj.to_dict()
117
+ super().__init__(context)
118
+
119
+ @property
120
+ def name(self):
121
+ "Project config"
122
+
123
+ # Uses SecretRenderer
124
+ def get_package_renderer(self) -> BaseRenderer:
125
+ return PackageRenderer(self.ctx_obj.cli_vars)
126
+
127
+ def render_project(
128
+ self,
129
+ project: Dict[str, Any],
130
+ project_root: str,
131
+ ) -> Dict[str, Any]:
132
+ """Render the project and insert the project root after rendering."""
133
+ rendered_project = self.render_data(project)
134
+ rendered_project["project-root"] = project_root
135
+ return rendered_project
136
+
137
+ def render_packages(self, packages: Dict[str, Any], packages_specified_path: str):
138
+ """Render the given packages dict"""
139
+ packages = packages or {} # Sometimes this is none in tests
140
+ package_renderer = self.get_package_renderer()
141
+ if packages_specified_path == DEPENDENCIES_FILE_NAME:
142
+ # We don't want to render the "packages" dictionary that came from dependencies.yml
143
+ return packages
144
+ else:
145
+ return package_renderer.render_data(packages)
146
+
147
+ def render_selectors(self, selectors: Dict[str, Any]):
148
+ return self.render_data(selectors)
149
+
150
+ def render_entry(self, value: Any, keypath: Keypath) -> Any:
151
+ result = super().render_entry(value, keypath)
152
+ return self._KEYPATH_HANDLERS.postprocess(result, keypath)
153
+
154
+ def should_render_keypath(self, keypath: Keypath) -> bool:
155
+ if not keypath:
156
+ return True
157
+
158
+ first = keypath[0]
159
+ # run hooks are not rendered
160
+ if first in {"on-run-start", "on-run-end", "query-comment"}:
161
+ return False
162
+
163
+ # don't render vars blocks until runtime
164
+ if first == "vars":
165
+ return False
166
+
167
+ if first in {"seeds", "models", "snapshots", "tests", "data_tests"}:
168
+ keypath_parts = {(k.lstrip("+ ") if isinstance(k, str) else k) for k in keypath}
169
+ # model-level hooks
170
+ late_rendered_hooks = {"pre-hook", "post-hook", "pre_hook", "post_hook"}
171
+ if keypath_parts.intersection(late_rendered_hooks):
172
+ return False
173
+
174
+ return True
175
+
176
+
177
+ class SecretRenderer(BaseRenderer):
178
+ def __init__(self, cli_vars: Dict[str, Any] = {}) -> None:
179
+ # Generate contexts here because we want to save the context
180
+ # object in order to retrieve the env_vars.
181
+ self.ctx_obj = SecretContext(cli_vars)
182
+ context = self.ctx_obj.to_dict()
183
+ super().__init__(context)
184
+
185
+ @property
186
+ def name(self):
187
+ return "Secret"
188
+
189
+ def render_value(self, value: Any, keypath: Optional[Keypath] = None) -> Any:
190
+ # First, standard Jinja rendering, with special handling for 'secret' environment variables
191
+ # "{{ env_var('DBT_SECRET_ENV_VAR') }}" -> "$$$DBT_SECRET_START$$$DBT_SECRET_ENV_{VARIABLE_NAME}$$$DBT_SECRET_END$$$"
192
+ # This prevents Jinja manipulation of secrets via macros/filters that might leak partial/modified values in logs
193
+
194
+ try:
195
+ rendered = super().render_value(value, keypath)
196
+ except Exception as ex:
197
+ if keypath and "password" in keypath:
198
+ # Passwords sometimes contain jinja-esque characters, but we
199
+ # don't want to render them if they aren't valid jinja.
200
+ rendered = value
201
+ else:
202
+ raise ex
203
+
204
+ # Now, detect instances of the placeholder value ($$$DBT_SECRET_START...DBT_SECRET_END$$$)
205
+ # and replace them with the actual secret value
206
+ if SECRET_ENV_PREFIX in str(rendered):
207
+ search_group = f"({SECRET_ENV_PREFIX}(.*))"
208
+ pattern = SECRET_PLACEHOLDER.format(search_group).replace("$", r"\$")
209
+ m = re.search(
210
+ pattern,
211
+ rendered,
212
+ )
213
+ if m:
214
+ found = m.group(1)
215
+ value = get_invocation_context().env[found]
216
+ replace_this = SECRET_PLACEHOLDER.format(found)
217
+ return rendered.replace(replace_this, value)
218
+ else:
219
+ return rendered
220
+
221
+
222
+ class ProfileRenderer(SecretRenderer):
223
+ @property
224
+ def name(self):
225
+ return "Profile"
226
+
227
+
228
+ class PackageRenderer(SecretRenderer):
229
+ @property
230
+ def name(self):
231
+ return "Packages config"