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/deps.py ADDED
@@ -0,0 +1,280 @@
1
+ import json
2
+ from hashlib import sha1
3
+ from pathlib import Path
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import yaml
7
+
8
+ import dbt.deprecations
9
+ import dbt.exceptions
10
+ import dbt.utils
11
+ from dbt.config import Project
12
+ from dbt.config.project import load_yml_dict, package_config_from_data
13
+ from dbt.config.renderer import PackageRenderer
14
+ from dbt.constants import PACKAGE_LOCK_FILE_NAME, PACKAGE_LOCK_HASH_KEY
15
+ from dbt.contracts.project import PackageSpec
16
+ from dbt.deps.base import downloads_directory
17
+ from dbt.deps.registry import RegistryPinnedPackage
18
+ from dbt.deps.resolver import resolve_lock_packages, resolve_packages
19
+ from dbt.events.types import (
20
+ DepsAddPackage,
21
+ DepsFoundDuplicatePackage,
22
+ DepsInstallInfo,
23
+ DepsListSubdirectory,
24
+ DepsLockUpdating,
25
+ DepsNoPackagesFound,
26
+ DepsNotifyUpdatesAvailable,
27
+ DepsStartPackageInstall,
28
+ DepsUpdateAvailable,
29
+ DepsUpToDate,
30
+ )
31
+ from dbt.task.base import BaseTask, move_to_nearest_project_dir
32
+ from dbt_common.clients import system
33
+ from dbt_common.events.functions import fire_event
34
+ from dbt_common.events.types import Formatting
35
+
36
+
37
+ class dbtPackageDumper(yaml.Dumper):
38
+ def increase_indent(self, flow=False, indentless=False):
39
+ return super(dbtPackageDumper, self).increase_indent(flow, False)
40
+
41
+
42
+ def _create_sha1_hash(packages: List[PackageSpec]) -> str:
43
+ """Create a SHA1 hash of the packages list,
44
+ this is used to determine if the packages for current execution matches
45
+ the previous lock.
46
+
47
+ Args:
48
+ list[Packages]: list of packages specified that are already rendered
49
+
50
+ Returns:
51
+ str: SHA1 hash of the packages list
52
+ """
53
+ package_strs = [json.dumps(package.to_dict(), sort_keys=True) for package in packages]
54
+ package_strs = sorted(package_strs)
55
+
56
+ return sha1("\n".join(package_strs).encode("utf-8")).hexdigest()
57
+
58
+
59
+ def _create_packages_yml_entry(package: str, version: Optional[str], source: str) -> dict:
60
+ """Create a formatted entry to add to `packages.yml` or `package-lock.yml` file
61
+
62
+ Args:
63
+ package (str): Name of package to download
64
+ version (str): Version of package to download
65
+ source (str): Source of where to download package from
66
+
67
+ Returns:
68
+ dict: Formatted dict to write to `packages.yml` or `package-lock.yml` file
69
+ """
70
+ package_key = source
71
+ version_key = "version"
72
+
73
+ if source == "hub":
74
+ package_key = "package"
75
+
76
+ packages_yml_entry = {package_key: package}
77
+
78
+ if source == "git":
79
+ version_key = "revision"
80
+
81
+ if version:
82
+ if "," in version:
83
+ version = version.split(",") # type: ignore
84
+
85
+ packages_yml_entry[version_key] = version
86
+
87
+ return packages_yml_entry
88
+
89
+
90
+ class DepsTask(BaseTask):
91
+ def __init__(self, args: Any, project: Project) -> None:
92
+ super().__init__(args=args)
93
+ # N.B. This is a temporary fix for a bug when using relative paths via
94
+ # --project-dir with deps. A larger overhaul of our path handling methods
95
+ # is needed to fix this the "right" way.
96
+ # See GH-7615
97
+ project.project_root = str(Path(project.project_root).resolve())
98
+ self.project = project
99
+ self.cli_vars = args.vars
100
+
101
+ def track_package_install(
102
+ self, package_name: str, source_type: str, version: Optional[str]
103
+ ) -> None:
104
+ # Hub packages do not need to be hashed, as they are public
105
+ if source_type == "local":
106
+ package_name = dbt.utils.md5(package_name)
107
+ version = "local"
108
+ elif source_type == "tarball":
109
+ package_name = dbt.utils.md5(package_name)
110
+ version = "tarball"
111
+ elif source_type != "hub":
112
+ package_name = dbt.utils.md5(package_name)
113
+ version = dbt.utils.md5(version)
114
+
115
+ dbt.tracking.track_package_install(
116
+ "deps",
117
+ self.project.hashed_name(),
118
+ {"name": package_name, "source": source_type, "version": version},
119
+ )
120
+
121
+ def check_for_duplicate_packages(self, packages_yml):
122
+ """Loop through contents of `packages.yml` to ensure no duplicate package names + versions.
123
+
124
+ This duplicate check will take into consideration exact match of a package name, as well as
125
+ a check to see if a package name exists within a name (i.e. a package name inside a git URL).
126
+
127
+ Args:
128
+ packages_yml (dict): In-memory read of `packages.yml` contents
129
+
130
+ Returns:
131
+ dict: Updated or untouched packages_yml contents
132
+ """
133
+ for i, pkg_entry in enumerate(packages_yml["packages"]):
134
+ for val in pkg_entry.values():
135
+ if self.args.add_package["name"] in val:
136
+ del packages_yml["packages"][i]
137
+
138
+ fire_event(DepsFoundDuplicatePackage(removed_package=pkg_entry))
139
+
140
+ return packages_yml
141
+
142
+ def add(self):
143
+ packages_yml_filepath = (
144
+ f"{self.project.project_root}/{self.project.packages_specified_path}"
145
+ )
146
+ if not system.path_exists(packages_yml_filepath):
147
+ with open(packages_yml_filepath, "w") as package_yml:
148
+ yaml.safe_dump({"packages": []}, package_yml)
149
+ fire_event(Formatting("Created packages.yml"))
150
+
151
+ new_package_entry = _create_packages_yml_entry(
152
+ self.args.add_package["name"], self.args.add_package["version"], self.args.source
153
+ )
154
+
155
+ with open(packages_yml_filepath, "r") as user_yml_obj:
156
+ packages_yml = yaml.safe_load(user_yml_obj)
157
+ packages_yml = self.check_for_duplicate_packages(packages_yml)
158
+ packages_yml["packages"].append(new_package_entry)
159
+
160
+ self.project.packages.packages = package_config_from_data(packages_yml).packages
161
+
162
+ if packages_yml:
163
+ with open(packages_yml_filepath, "w") as pkg_obj:
164
+ pkg_obj.write(
165
+ yaml.dump(packages_yml, Dumper=dbtPackageDumper, default_flow_style=False)
166
+ )
167
+
168
+ fire_event(
169
+ DepsAddPackage(
170
+ package_name=self.args.add_package["name"],
171
+ version=self.args.add_package["version"],
172
+ packages_filepath=packages_yml_filepath,
173
+ )
174
+ )
175
+
176
+ def lock(self) -> None:
177
+ lock_filepath = f"{self.project.project_root}/{PACKAGE_LOCK_FILE_NAME}"
178
+
179
+ packages = self.project.packages.packages
180
+ packages_installed: Dict[str, Any] = {"packages": []}
181
+
182
+ if not packages:
183
+ fire_event(DepsNoPackagesFound())
184
+ return
185
+
186
+ with downloads_directory():
187
+ resolved_deps = resolve_packages(packages, self.project, self.cli_vars)
188
+
189
+ # this loop is to create the package-lock.yml in the same format as original packages.yml
190
+ # package-lock.yml includes both the stated packages in packages.yml along with dependent packages
191
+ renderer = PackageRenderer(self.cli_vars)
192
+ for package in resolved_deps:
193
+ package_dict = package.to_dict()
194
+ package_dict["name"] = package.get_project_name(self.project, renderer)
195
+ packages_installed["packages"].append(package_dict)
196
+
197
+ packages_installed[PACKAGE_LOCK_HASH_KEY] = _create_sha1_hash(
198
+ self.project.packages.packages
199
+ )
200
+
201
+ with open(lock_filepath, "w") as lock_obj:
202
+ yaml.dump(packages_installed, lock_obj, Dumper=dbtPackageDumper)
203
+
204
+ fire_event(DepsLockUpdating(lock_filepath=lock_filepath))
205
+
206
+ def run(self) -> None:
207
+ move_to_nearest_project_dir(self.args.project_dir)
208
+ if self.args.add_package:
209
+ self.add()
210
+
211
+ # Check lock file exist and generated by the same packages.yml
212
+ # or dependencies.yml.
213
+ lock_file_path = f"{self.project.project_root}/{PACKAGE_LOCK_FILE_NAME}"
214
+ if not system.path_exists(lock_file_path):
215
+ self.lock()
216
+ elif self.args.upgrade:
217
+ self.lock()
218
+ else:
219
+ # Check dependency definition is modified or not.
220
+ current_hash = _create_sha1_hash(self.project.packages.packages)
221
+ previous_hash = load_yml_dict(lock_file_path).get(PACKAGE_LOCK_HASH_KEY, None)
222
+ if previous_hash != current_hash:
223
+ self.lock()
224
+
225
+ # Early return when 'dbt deps --lock'
226
+ # Just resolve packages and write lock file, don't actually install packages
227
+ if self.args.lock:
228
+ return
229
+
230
+ if system.path_exists(self.project.packages_install_path):
231
+ system.rmtree(self.project.packages_install_path)
232
+
233
+ system.make_directory(self.project.packages_install_path)
234
+
235
+ packages_lock_dict = load_yml_dict(f"{self.project.project_root}/{PACKAGE_LOCK_FILE_NAME}")
236
+
237
+ renderer = PackageRenderer(self.cli_vars)
238
+ packages_lock_config = package_config_from_data(
239
+ renderer.render_data(packages_lock_dict), packages_lock_dict
240
+ ).packages
241
+
242
+ if not packages_lock_config:
243
+ fire_event(DepsNoPackagesFound())
244
+ return
245
+
246
+ with downloads_directory():
247
+ lock_defined_deps = resolve_lock_packages(packages_lock_config)
248
+ renderer = PackageRenderer(self.cli_vars)
249
+
250
+ packages_to_upgrade = []
251
+
252
+ for package in lock_defined_deps:
253
+ package_name = package.name
254
+ source_type = package.source_type()
255
+ version = package.get_version()
256
+
257
+ fire_event(DepsStartPackageInstall(package_name=package_name))
258
+ package.install(self.project, renderer)
259
+
260
+ fire_event(DepsInstallInfo(version_name=package.nice_version_name()))
261
+
262
+ if isinstance(package, RegistryPinnedPackage):
263
+ version_latest = package.get_version_latest()
264
+
265
+ if version_latest != version:
266
+ packages_to_upgrade.append(package_name)
267
+ fire_event(DepsUpdateAvailable(version_latest=version_latest))
268
+ else:
269
+ fire_event(DepsUpToDate())
270
+
271
+ if package.get_subdirectory():
272
+ fire_event(DepsListSubdirectory(subdirectory=package.get_subdirectory()))
273
+
274
+ self.track_package_install(
275
+ package_name=package_name, source_type=source_type, version=version
276
+ )
277
+
278
+ if packages_to_upgrade:
279
+ fire_event(Formatting(""))
280
+ fire_event(DepsNotifyUpdatesAvailable(packages=packages_to_upgrade))
@@ -0,0 +1,3 @@
1
+ import os
2
+
3
+ DOCS_INDEX_FILE_PATH = os.path.normpath(os.path.join(os.path.dirname(__file__), "index.html"))
@@ -0,0 +1,23 @@
1
+ """
2
+ DVT Docs Serve API
3
+
4
+ v0.56.0: FastAPI routers for enhanced docs serve with 3-tab web UI.
5
+
6
+ Endpoints:
7
+ - /api/catalog/* - Catalog nodes and search
8
+ - /api/profile/* - Profile results and alerts
9
+ - /api/lineage/* - Lineage graph and traversal
10
+ - /api/spark/* - Spark status (local only)
11
+ """
12
+
13
+ from dbt.task.docs.api.catalog import router as catalog_router
14
+ from dbt.task.docs.api.profile import router as profile_router
15
+ from dbt.task.docs.api.lineage import router as lineage_router
16
+ from dbt.task.docs.api.spark import router as spark_router
17
+
18
+ __all__ = [
19
+ "catalog_router",
20
+ "profile_router",
21
+ "lineage_router",
22
+ "spark_router",
23
+ ]
@@ -0,0 +1,204 @@
1
+ """
2
+ DVT Docs Serve - Catalog API
3
+
4
+ v0.56.0: Catalog nodes, search, and node details.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ try:
11
+ from fastapi import APIRouter, HTTPException, Query
12
+ except ImportError:
13
+ # Provide stub for when FastAPI is not installed
14
+ class APIRouter:
15
+ def __init__(self, *args, **kwargs):
16
+ pass
17
+ def get(self, *args, **kwargs):
18
+ def decorator(func):
19
+ return func
20
+ return decorator
21
+ class HTTPException(Exception):
22
+ def __init__(self, status_code, detail):
23
+ self.status_code = status_code
24
+ self.detail = detail
25
+ def Query(*args, **kwargs):
26
+ return None
27
+
28
+
29
+ router = APIRouter(prefix="/api/catalog", tags=["catalog"])
30
+
31
+ # Will be set by serve.py
32
+ _project_root: Optional[Path] = None
33
+ _store_initialized: bool = False
34
+
35
+
36
+ def set_project_root(project_root: Path) -> None:
37
+ """Set project root for API access."""
38
+ global _project_root, _store_initialized
39
+ _project_root = project_root
40
+ _store_initialized = True # Assume serve.py already initialized
41
+
42
+
43
+ def _get_store():
44
+ """Get metadata store instance (lazy initialization)."""
45
+ global _store_initialized
46
+
47
+ if _project_root is None:
48
+ raise HTTPException(status_code=500, detail="Project root not configured")
49
+
50
+ try:
51
+ from dbt.compute.metadata import ProjectMetadataStore
52
+ store = ProjectMetadataStore(_project_root)
53
+ # Only initialize if not already done by serve.py
54
+ if not _store_initialized:
55
+ store.initialize()
56
+ _store_initialized = True
57
+ return store
58
+ except Exception as e:
59
+ raise HTTPException(status_code=500, detail=f"Could not open metadata store: {e}")
60
+
61
+
62
+ @router.get("/nodes")
63
+ async def list_catalog_nodes(
64
+ resource_type: Optional[str] = Query(None, description="Filter by type: model, source, test, seed, snapshot"),
65
+ ) -> List[Dict[str, Any]]:
66
+ """
67
+ List all catalog nodes.
68
+
69
+ Returns all nodes from the catalog, optionally filtered by resource type.
70
+ """
71
+ store = _get_store()
72
+
73
+ try:
74
+ if resource_type:
75
+ nodes = store.get_catalog_nodes_by_type(resource_type)
76
+ else:
77
+ nodes = store.get_all_catalog_nodes()
78
+
79
+ return [
80
+ {
81
+ "unique_id": n.unique_id,
82
+ "resource_type": n.resource_type,
83
+ "name": n.name,
84
+ "schema": n.schema_name,
85
+ "database": n.database,
86
+ "connection": n.connection_name,
87
+ "adapter": n.adapter_type,
88
+ "description": n.description,
89
+ "icon": n.icon_type,
90
+ "color": n.color_hex,
91
+ "materialized": n.materialized,
92
+ "row_count": n.row_count,
93
+ }
94
+ for n in nodes
95
+ ]
96
+ finally:
97
+ store.close()
98
+
99
+
100
+ @router.get("/nodes/{unique_id}")
101
+ async def get_catalog_node(unique_id: str) -> Dict[str, Any]:
102
+ """
103
+ Get a specific catalog node by unique ID.
104
+
105
+ Returns full node details including columns.
106
+ """
107
+ import json
108
+
109
+ store = _get_store()
110
+
111
+ try:
112
+ node = store.get_catalog_node(unique_id)
113
+ if not node:
114
+ raise HTTPException(status_code=404, detail=f"Node not found: {unique_id}")
115
+
116
+ return {
117
+ "unique_id": node.unique_id,
118
+ "resource_type": node.resource_type,
119
+ "name": node.name,
120
+ "schema": node.schema_name,
121
+ "database": node.database,
122
+ "connection": node.connection_name,
123
+ "adapter": node.adapter_type,
124
+ "description": node.description,
125
+ "icon": node.icon_type,
126
+ "color": node.color_hex,
127
+ "materialized": node.materialized,
128
+ "tags": json.loads(node.tags) if node.tags else [],
129
+ "meta": json.loads(node.meta) if node.meta else {},
130
+ "columns": json.loads(node.columns) if node.columns else [],
131
+ "row_count": node.row_count,
132
+ "bytes_stored": node.bytes_stored,
133
+ "created_at": node.created_at.isoformat() if node.created_at else None,
134
+ "updated_at": node.updated_at.isoformat() if node.updated_at else None,
135
+ }
136
+ finally:
137
+ store.close()
138
+
139
+
140
+ @router.get("/search")
141
+ async def search_catalog(
142
+ q: str = Query(..., description="Search query"),
143
+ ) -> List[Dict[str, Any]]:
144
+ """
145
+ Search catalog nodes by name or description.
146
+
147
+ Returns matching nodes sorted by relevance.
148
+ """
149
+ if not q or len(q) < 2:
150
+ raise HTTPException(status_code=400, detail="Query must be at least 2 characters")
151
+
152
+ store = _get_store()
153
+
154
+ try:
155
+ nodes = store.search_catalog_nodes(q)
156
+ return [
157
+ {
158
+ "unique_id": n.unique_id,
159
+ "resource_type": n.resource_type,
160
+ "name": n.name,
161
+ "schema": n.schema_name,
162
+ "connection": n.connection_name,
163
+ "description": n.description,
164
+ "icon": n.icon_type,
165
+ "color": n.color_hex,
166
+ }
167
+ for n in nodes
168
+ ]
169
+ finally:
170
+ store.close()
171
+
172
+
173
+ @router.get("/stats")
174
+ async def get_catalog_stats() -> Dict[str, Any]:
175
+ """
176
+ Get catalog statistics.
177
+
178
+ Returns counts of nodes by type, connections, etc.
179
+ """
180
+ store = _get_store()
181
+
182
+ try:
183
+ all_nodes = store.get_all_catalog_nodes()
184
+
185
+ # Count by type
186
+ type_counts: Dict[str, int] = {}
187
+ connection_counts: Dict[str, int] = {}
188
+ adapter_counts: Dict[str, int] = {}
189
+
190
+ for node in all_nodes:
191
+ type_counts[node.resource_type] = type_counts.get(node.resource_type, 0) + 1
192
+ if node.connection_name:
193
+ connection_counts[node.connection_name] = connection_counts.get(node.connection_name, 0) + 1
194
+ if node.adapter_type:
195
+ adapter_counts[node.adapter_type] = adapter_counts.get(node.adapter_type, 0) + 1
196
+
197
+ return {
198
+ "total_nodes": len(all_nodes),
199
+ "by_type": type_counts,
200
+ "by_connection": connection_counts,
201
+ "by_adapter": adapter_counts,
202
+ }
203
+ finally:
204
+ store.close()