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.
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,232 @@
1
+ from typing import List, Optional, Set
2
+
3
+ from dbt import deprecations
4
+ from dbt.constants import (
5
+ LEGACY_TIME_SPINE_GRANULARITY,
6
+ LEGACY_TIME_SPINE_MODEL_NAME,
7
+ MINIMUM_REQUIRED_TIME_SPINE_GRANULARITY,
8
+ )
9
+ from dbt.contracts.graph.manifest import Manifest
10
+ from dbt.contracts.graph.nodes import ModelNode
11
+ from dbt.events.types import ArtifactWritten, SemanticValidationFailure
12
+ from dbt.exceptions import ParsingError
13
+ from dbt.flags import get_flags
14
+ from dbt_common.clients.system import write_file
15
+ from dbt_common.events.base_types import EventLevel
16
+ from dbt_common.events.functions import fire_event
17
+ from dbt_semantic_interfaces.implementations.metric import PydanticMetric
18
+ from dbt_semantic_interfaces.implementations.node_relation import PydanticNodeRelation
19
+ from dbt_semantic_interfaces.implementations.project_configuration import (
20
+ PydanticProjectConfiguration,
21
+ )
22
+ from dbt_semantic_interfaces.implementations.saved_query import PydanticSavedQuery
23
+ from dbt_semantic_interfaces.implementations.semantic_manifest import (
24
+ PydanticSemanticManifest,
25
+ )
26
+ from dbt_semantic_interfaces.implementations.semantic_model import PydanticSemanticModel
27
+ from dbt_semantic_interfaces.implementations.time_spine import (
28
+ PydanticTimeSpine,
29
+ PydanticTimeSpineCustomGranularityColumn,
30
+ PydanticTimeSpinePrimaryColumn,
31
+ )
32
+ from dbt_semantic_interfaces.implementations.time_spine_table_configuration import (
33
+ PydanticTimeSpineTableConfiguration as LegacyTimeSpine,
34
+ )
35
+ from dbt_semantic_interfaces.type_enums import TimeGranularity
36
+ from dbt_semantic_interfaces.validations.semantic_manifest_validator import (
37
+ SemanticManifestValidator,
38
+ )
39
+ from dbt_semantic_interfaces.validations.validator_helpers import (
40
+ FileContext,
41
+ ValidationError,
42
+ ValidationIssueContext,
43
+ )
44
+
45
+
46
+ class SemanticManifest:
47
+ def __init__(self, manifest: Manifest) -> None:
48
+ self.manifest = manifest
49
+
50
+ def validate(self) -> bool:
51
+
52
+ # TODO: Enforce this check.
53
+ # if self.manifest.metrics and not self.manifest.semantic_models:
54
+ # fire_event(
55
+ # SemanticValidationFailure(
56
+ # msg="Metrics require semantic models, but none were found."
57
+ # ),
58
+ # EventLevel.ERROR,
59
+ # )
60
+ # return False
61
+
62
+ if not self.manifest.metrics or not self.manifest.semantic_models:
63
+ return True
64
+
65
+ semantic_manifest = self._get_pydantic_semantic_manifest()
66
+ validator = SemanticManifestValidator[PydanticSemanticManifest]()
67
+ validation_results = validator.validate_semantic_manifest(semantic_manifest)
68
+ validation_result_errors = list(validation_results.errors)
69
+
70
+ metrics_using_old_params: Set[str] = set()
71
+ for metric in semantic_manifest.metrics or []:
72
+ for field in ("window", "grain_to_date"):
73
+ type_params_field_value = getattr(metric.type_params, field)
74
+ # Warn that the old type_params structure has been deprecated.
75
+ if type_params_field_value:
76
+ metrics_using_old_params.add(metric.name)
77
+ if metrics_using_old_params:
78
+ if get_flags().require_nested_cumulative_type_params is False:
79
+ deprecations.warn(
80
+ "mf-cumulative-type-params-deprecation",
81
+ )
82
+ else:
83
+ names = ", ".join(metrics_using_old_params)
84
+ validation_result_errors.append(
85
+ ValidationError(
86
+ context=ValidationIssueContext(
87
+ # We don't have the file context at this point.
88
+ file_context=FileContext(),
89
+ object_name=names,
90
+ object_type="metric",
91
+ ),
92
+ message=f"Cumulative fields `type_params.window` and `type_params.grain_to_date` should be nested under `type_params.cumulative_type_params.window` and `type_params.cumulative_type_params.grain_to_date`. Invalid metrics: {names}. See documentation on behavior changes: https://docs.getdbt.com/reference/global-configs/behavior-changes.",
93
+ )
94
+ )
95
+
96
+ time_spines = semantic_manifest.project_configuration.time_spines
97
+ legacy_time_spines = (
98
+ semantic_manifest.project_configuration.time_spine_table_configurations
99
+ )
100
+ # If the time spine contains a day grain then it is functionally equivalent to the legacy time spine.
101
+ time_spines_contain_day = any(
102
+ c for c in time_spines if c.primary_column.time_granularity == TimeGranularity.DAY
103
+ )
104
+ if (
105
+ get_flags().require_yaml_configuration_for_mf_time_spines is False
106
+ and legacy_time_spines
107
+ and not time_spines_contain_day
108
+ ):
109
+ deprecations.warn(
110
+ "mf-timespine-without-yaml-configuration",
111
+ )
112
+
113
+ for warning in validation_results.warnings:
114
+ fire_event(SemanticValidationFailure(msg=warning.message))
115
+
116
+ for error in validation_result_errors:
117
+ fire_event(SemanticValidationFailure(msg=error.message), EventLevel.ERROR)
118
+
119
+ return not validation_result_errors
120
+
121
+ def write_json_to_file(self, file_path: str):
122
+ semantic_manifest = self._get_pydantic_semantic_manifest()
123
+ json = semantic_manifest.json()
124
+ write_file(file_path, json)
125
+ fire_event(ArtifactWritten(artifact_type=self.__class__.__name__, artifact_path=file_path))
126
+
127
+ def _get_pydantic_semantic_manifest(self) -> PydanticSemanticManifest:
128
+ pydantic_time_spines: List[PydanticTimeSpine] = []
129
+ minimum_time_spine_granularity: Optional[TimeGranularity] = None
130
+ for node in self.manifest.nodes.values():
131
+ if not (isinstance(node, ModelNode) and node.time_spine):
132
+ continue
133
+ time_spine = node.time_spine
134
+ standard_granularity_column = None
135
+ for column in node.columns.values():
136
+ if column.name == time_spine.standard_granularity_column:
137
+ standard_granularity_column = column
138
+ break
139
+ # Assertions needed for type checking
140
+ if not standard_granularity_column:
141
+ raise ParsingError(
142
+ "Expected to find time spine standard granularity column in model columns, but did not. "
143
+ "This should have been caught in YAML parsing."
144
+ )
145
+ if not standard_granularity_column.granularity:
146
+ raise ParsingError(
147
+ "Expected to find granularity set for time spine standard granularity column, but did not. "
148
+ "This should have been caught in YAML parsing."
149
+ )
150
+ pydantic_time_spine = PydanticTimeSpine(
151
+ node_relation=PydanticNodeRelation(
152
+ alias=node.alias,
153
+ schema_name=node.schema,
154
+ database=node.database,
155
+ relation_name=node.relation_name,
156
+ ),
157
+ primary_column=PydanticTimeSpinePrimaryColumn(
158
+ name=time_spine.standard_granularity_column,
159
+ time_granularity=standard_granularity_column.granularity,
160
+ ),
161
+ custom_granularities=[
162
+ PydanticTimeSpineCustomGranularityColumn(
163
+ name=custom_granularity.name, column_name=custom_granularity.column_name
164
+ )
165
+ for custom_granularity in time_spine.custom_granularities
166
+ ],
167
+ )
168
+ pydantic_time_spines.append(pydantic_time_spine)
169
+ if (
170
+ not minimum_time_spine_granularity
171
+ or standard_granularity_column.granularity.to_int()
172
+ < minimum_time_spine_granularity.to_int()
173
+ ):
174
+ minimum_time_spine_granularity = standard_granularity_column.granularity
175
+
176
+ project_config = PydanticProjectConfiguration(
177
+ time_spine_table_configurations=[], time_spines=pydantic_time_spines
178
+ )
179
+ pydantic_semantic_manifest = PydanticSemanticManifest(
180
+ metrics=[], semantic_models=[], project_configuration=project_config
181
+ )
182
+
183
+ for semantic_model in self.manifest.semantic_models.values():
184
+ pydantic_semantic_manifest.semantic_models.append(
185
+ PydanticSemanticModel.parse_obj(semantic_model.to_dict())
186
+ )
187
+
188
+ for metric in self.manifest.metrics.values():
189
+ pydantic_semantic_manifest.metrics.append(PydanticMetric.parse_obj(metric.to_dict()))
190
+
191
+ for saved_query in self.manifest.saved_queries.values():
192
+ pydantic_semantic_manifest.saved_queries.append(
193
+ PydanticSavedQuery.parse_obj(saved_query.to_dict())
194
+ )
195
+
196
+ legacy_time_spine_model: Optional[ModelNode] = None
197
+ if self.manifest.semantic_models:
198
+ legacy_time_spine_model = self.manifest.ref_lookup.find(
199
+ LEGACY_TIME_SPINE_MODEL_NAME, None, None, self.manifest
200
+ )
201
+ if legacy_time_spine_model:
202
+ if (
203
+ not minimum_time_spine_granularity
204
+ or LEGACY_TIME_SPINE_GRANULARITY.to_int()
205
+ < minimum_time_spine_granularity.to_int()
206
+ ):
207
+ minimum_time_spine_granularity = LEGACY_TIME_SPINE_GRANULARITY
208
+
209
+ # If no time spines have been configured at DAY or smaller AND legacy time spine model does not exist, error.
210
+ if (
211
+ not minimum_time_spine_granularity
212
+ or minimum_time_spine_granularity.to_int()
213
+ > MINIMUM_REQUIRED_TIME_SPINE_GRANULARITY.to_int()
214
+ ):
215
+ raise ParsingError(
216
+ "The semantic layer requires a time spine model with granularity DAY or smaller in the project, "
217
+ "but none was found. Guidance on creating this model can be found on our docs site "
218
+ "(https://docs.getdbt.com/docs/build/metricflow-time-spine)."
219
+ )
220
+
221
+ # For backward compatibility: if legacy time spine exists without config, include it in the manifest.
222
+ if legacy_time_spine_model and legacy_time_spine_model.time_spine is None:
223
+ legacy_time_spine = LegacyTimeSpine(
224
+ location=legacy_time_spine_model.relation_name,
225
+ column_name="date_day",
226
+ grain=LEGACY_TIME_SPINE_GRANULARITY,
227
+ )
228
+ pydantic_semantic_manifest.project_configuration.time_spine_table_configurations = [
229
+ legacy_time_spine
230
+ ]
231
+
232
+ return pydantic_semantic_manifest