dvt-core 1.11.0b4__py3-none-any.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 (261) hide show
  1. dvt/__init__.py +7 -0
  2. dvt/_pydantic_shim.py +26 -0
  3. dvt/adapters/__init__.py +16 -0
  4. dvt/adapters/multi_adapter_manager.py +268 -0
  5. dvt/artifacts/__init__.py +0 -0
  6. dvt/artifacts/exceptions/__init__.py +1 -0
  7. dvt/artifacts/exceptions/schemas.py +31 -0
  8. dvt/artifacts/resources/__init__.py +116 -0
  9. dvt/artifacts/resources/base.py +68 -0
  10. dvt/artifacts/resources/types.py +93 -0
  11. dvt/artifacts/resources/v1/analysis.py +10 -0
  12. dvt/artifacts/resources/v1/catalog.py +23 -0
  13. dvt/artifacts/resources/v1/components.py +275 -0
  14. dvt/artifacts/resources/v1/config.py +282 -0
  15. dvt/artifacts/resources/v1/documentation.py +11 -0
  16. dvt/artifacts/resources/v1/exposure.py +52 -0
  17. dvt/artifacts/resources/v1/function.py +53 -0
  18. dvt/artifacts/resources/v1/generic_test.py +32 -0
  19. dvt/artifacts/resources/v1/group.py +22 -0
  20. dvt/artifacts/resources/v1/hook.py +11 -0
  21. dvt/artifacts/resources/v1/macro.py +30 -0
  22. dvt/artifacts/resources/v1/metric.py +173 -0
  23. dvt/artifacts/resources/v1/model.py +146 -0
  24. dvt/artifacts/resources/v1/owner.py +10 -0
  25. dvt/artifacts/resources/v1/saved_query.py +112 -0
  26. dvt/artifacts/resources/v1/seed.py +42 -0
  27. dvt/artifacts/resources/v1/semantic_layer_components.py +72 -0
  28. dvt/artifacts/resources/v1/semantic_model.py +315 -0
  29. dvt/artifacts/resources/v1/singular_test.py +14 -0
  30. dvt/artifacts/resources/v1/snapshot.py +92 -0
  31. dvt/artifacts/resources/v1/source_definition.py +85 -0
  32. dvt/artifacts/resources/v1/sql_operation.py +10 -0
  33. dvt/artifacts/resources/v1/unit_test_definition.py +78 -0
  34. dvt/artifacts/schemas/__init__.py +0 -0
  35. dvt/artifacts/schemas/base.py +191 -0
  36. dvt/artifacts/schemas/batch_results.py +24 -0
  37. dvt/artifacts/schemas/catalog/__init__.py +12 -0
  38. dvt/artifacts/schemas/catalog/v1/__init__.py +0 -0
  39. dvt/artifacts/schemas/catalog/v1/catalog.py +60 -0
  40. dvt/artifacts/schemas/freshness/__init__.py +1 -0
  41. dvt/artifacts/schemas/freshness/v3/__init__.py +0 -0
  42. dvt/artifacts/schemas/freshness/v3/freshness.py +159 -0
  43. dvt/artifacts/schemas/manifest/__init__.py +2 -0
  44. dvt/artifacts/schemas/manifest/v12/__init__.py +0 -0
  45. dvt/artifacts/schemas/manifest/v12/manifest.py +212 -0
  46. dvt/artifacts/schemas/results.py +148 -0
  47. dvt/artifacts/schemas/run/__init__.py +2 -0
  48. dvt/artifacts/schemas/run/v5/__init__.py +0 -0
  49. dvt/artifacts/schemas/run/v5/run.py +184 -0
  50. dvt/artifacts/schemas/upgrades/__init__.py +4 -0
  51. dvt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
  52. dvt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
  53. dvt/artifacts/utils/validation.py +153 -0
  54. dvt/cli/__init__.py +1 -0
  55. dvt/cli/context.py +16 -0
  56. dvt/cli/exceptions.py +56 -0
  57. dvt/cli/flags.py +558 -0
  58. dvt/cli/main.py +971 -0
  59. dvt/cli/option_types.py +121 -0
  60. dvt/cli/options.py +79 -0
  61. dvt/cli/params.py +803 -0
  62. dvt/cli/requires.py +478 -0
  63. dvt/cli/resolvers.py +32 -0
  64. dvt/cli/types.py +40 -0
  65. dvt/clients/__init__.py +0 -0
  66. dvt/clients/checked_load.py +82 -0
  67. dvt/clients/git.py +164 -0
  68. dvt/clients/jinja.py +206 -0
  69. dvt/clients/jinja_static.py +245 -0
  70. dvt/clients/registry.py +192 -0
  71. dvt/clients/yaml_helper.py +68 -0
  72. dvt/compilation.py +833 -0
  73. dvt/compute/__init__.py +26 -0
  74. dvt/compute/base.py +288 -0
  75. dvt/compute/engines/__init__.py +13 -0
  76. dvt/compute/engines/duckdb_engine.py +368 -0
  77. dvt/compute/engines/spark_engine.py +273 -0
  78. dvt/compute/query_analyzer.py +212 -0
  79. dvt/compute/router.py +483 -0
  80. dvt/config/__init__.py +4 -0
  81. dvt/config/catalogs.py +95 -0
  82. dvt/config/compute_config.py +406 -0
  83. dvt/config/profile.py +411 -0
  84. dvt/config/profiles_v2.py +464 -0
  85. dvt/config/project.py +893 -0
  86. dvt/config/renderer.py +232 -0
  87. dvt/config/runtime.py +491 -0
  88. dvt/config/selectors.py +209 -0
  89. dvt/config/utils.py +78 -0
  90. dvt/connectors/.gitignore +6 -0
  91. dvt/connectors/README.md +306 -0
  92. dvt/connectors/catalog.yml +217 -0
  93. dvt/connectors/download_connectors.py +300 -0
  94. dvt/constants.py +29 -0
  95. dvt/context/__init__.py +0 -0
  96. dvt/context/base.py +746 -0
  97. dvt/context/configured.py +136 -0
  98. dvt/context/context_config.py +350 -0
  99. dvt/context/docs.py +82 -0
  100. dvt/context/exceptions_jinja.py +179 -0
  101. dvt/context/macro_resolver.py +195 -0
  102. dvt/context/macros.py +171 -0
  103. dvt/context/manifest.py +73 -0
  104. dvt/context/providers.py +2198 -0
  105. dvt/context/query_header.py +14 -0
  106. dvt/context/secret.py +59 -0
  107. dvt/context/target.py +74 -0
  108. dvt/contracts/__init__.py +0 -0
  109. dvt/contracts/files.py +413 -0
  110. dvt/contracts/graph/__init__.py +0 -0
  111. dvt/contracts/graph/manifest.py +1904 -0
  112. dvt/contracts/graph/metrics.py +98 -0
  113. dvt/contracts/graph/model_config.py +71 -0
  114. dvt/contracts/graph/node_args.py +42 -0
  115. dvt/contracts/graph/nodes.py +1806 -0
  116. dvt/contracts/graph/semantic_manifest.py +233 -0
  117. dvt/contracts/graph/unparsed.py +812 -0
  118. dvt/contracts/project.py +417 -0
  119. dvt/contracts/results.py +53 -0
  120. dvt/contracts/selection.py +23 -0
  121. dvt/contracts/sql.py +86 -0
  122. dvt/contracts/state.py +69 -0
  123. dvt/contracts/util.py +46 -0
  124. dvt/deprecations.py +347 -0
  125. dvt/deps/__init__.py +0 -0
  126. dvt/deps/base.py +153 -0
  127. dvt/deps/git.py +196 -0
  128. dvt/deps/local.py +80 -0
  129. dvt/deps/registry.py +131 -0
  130. dvt/deps/resolver.py +149 -0
  131. dvt/deps/tarball.py +121 -0
  132. dvt/docs/source/_ext/dbt_click.py +118 -0
  133. dvt/docs/source/conf.py +32 -0
  134. dvt/env_vars.py +64 -0
  135. dvt/event_time/event_time.py +40 -0
  136. dvt/event_time/sample_window.py +60 -0
  137. dvt/events/__init__.py +16 -0
  138. dvt/events/base_types.py +37 -0
  139. dvt/events/core_types_pb2.py +2 -0
  140. dvt/events/logging.py +109 -0
  141. dvt/events/types.py +2534 -0
  142. dvt/exceptions.py +1487 -0
  143. dvt/flags.py +89 -0
  144. dvt/graph/__init__.py +11 -0
  145. dvt/graph/cli.py +248 -0
  146. dvt/graph/graph.py +172 -0
  147. dvt/graph/queue.py +213 -0
  148. dvt/graph/selector.py +375 -0
  149. dvt/graph/selector_methods.py +976 -0
  150. dvt/graph/selector_spec.py +223 -0
  151. dvt/graph/thread_pool.py +18 -0
  152. dvt/hooks.py +21 -0
  153. dvt/include/README.md +49 -0
  154. dvt/include/__init__.py +3 -0
  155. dvt/include/global_project.py +4 -0
  156. dvt/include/starter_project/.gitignore +4 -0
  157. dvt/include/starter_project/README.md +15 -0
  158. dvt/include/starter_project/__init__.py +3 -0
  159. dvt/include/starter_project/analyses/.gitkeep +0 -0
  160. dvt/include/starter_project/dvt_project.yml +36 -0
  161. dvt/include/starter_project/macros/.gitkeep +0 -0
  162. dvt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
  163. dvt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
  164. dvt/include/starter_project/models/example/schema.yml +21 -0
  165. dvt/include/starter_project/seeds/.gitkeep +0 -0
  166. dvt/include/starter_project/snapshots/.gitkeep +0 -0
  167. dvt/include/starter_project/tests/.gitkeep +0 -0
  168. dvt/internal_deprecations.py +27 -0
  169. dvt/jsonschemas/__init__.py +3 -0
  170. dvt/jsonschemas/jsonschemas.py +309 -0
  171. dvt/jsonschemas/project/0.0.110.json +4717 -0
  172. dvt/jsonschemas/project/0.0.85.json +2015 -0
  173. dvt/jsonschemas/resources/0.0.110.json +2636 -0
  174. dvt/jsonschemas/resources/0.0.85.json +2536 -0
  175. dvt/jsonschemas/resources/latest.json +6773 -0
  176. dvt/links.py +4 -0
  177. dvt/materializations/__init__.py +0 -0
  178. dvt/materializations/incremental/__init__.py +0 -0
  179. dvt/materializations/incremental/microbatch.py +235 -0
  180. dvt/mp_context.py +8 -0
  181. dvt/node_types.py +37 -0
  182. dvt/parser/__init__.py +23 -0
  183. dvt/parser/analysis.py +21 -0
  184. dvt/parser/base.py +549 -0
  185. dvt/parser/common.py +267 -0
  186. dvt/parser/docs.py +52 -0
  187. dvt/parser/fixtures.py +51 -0
  188. dvt/parser/functions.py +30 -0
  189. dvt/parser/generic_test.py +100 -0
  190. dvt/parser/generic_test_builders.py +334 -0
  191. dvt/parser/hooks.py +119 -0
  192. dvt/parser/macros.py +137 -0
  193. dvt/parser/manifest.py +2204 -0
  194. dvt/parser/models.py +574 -0
  195. dvt/parser/partial.py +1179 -0
  196. dvt/parser/read_files.py +445 -0
  197. dvt/parser/schema_generic_tests.py +423 -0
  198. dvt/parser/schema_renderer.py +111 -0
  199. dvt/parser/schema_yaml_readers.py +936 -0
  200. dvt/parser/schemas.py +1467 -0
  201. dvt/parser/search.py +149 -0
  202. dvt/parser/seeds.py +28 -0
  203. dvt/parser/singular_test.py +20 -0
  204. dvt/parser/snapshots.py +44 -0
  205. dvt/parser/sources.py +557 -0
  206. dvt/parser/sql.py +63 -0
  207. dvt/parser/unit_tests.py +622 -0
  208. dvt/plugins/__init__.py +20 -0
  209. dvt/plugins/contracts.py +10 -0
  210. dvt/plugins/exceptions.py +2 -0
  211. dvt/plugins/manager.py +164 -0
  212. dvt/plugins/manifest.py +21 -0
  213. dvt/profiler.py +20 -0
  214. dvt/py.typed +1 -0
  215. dvt/runners/__init__.py +2 -0
  216. dvt/runners/exposure_runner.py +7 -0
  217. dvt/runners/no_op_runner.py +46 -0
  218. dvt/runners/saved_query_runner.py +7 -0
  219. dvt/selected_resources.py +8 -0
  220. dvt/task/__init__.py +0 -0
  221. dvt/task/base.py +504 -0
  222. dvt/task/build.py +197 -0
  223. dvt/task/clean.py +57 -0
  224. dvt/task/clone.py +162 -0
  225. dvt/task/compile.py +151 -0
  226. dvt/task/compute.py +366 -0
  227. dvt/task/debug.py +650 -0
  228. dvt/task/deps.py +280 -0
  229. dvt/task/docs/__init__.py +3 -0
  230. dvt/task/docs/generate.py +408 -0
  231. dvt/task/docs/index.html +250 -0
  232. dvt/task/docs/serve.py +28 -0
  233. dvt/task/freshness.py +323 -0
  234. dvt/task/function.py +122 -0
  235. dvt/task/group_lookup.py +46 -0
  236. dvt/task/init.py +374 -0
  237. dvt/task/list.py +237 -0
  238. dvt/task/printer.py +176 -0
  239. dvt/task/profiles.py +256 -0
  240. dvt/task/retry.py +175 -0
  241. dvt/task/run.py +1146 -0
  242. dvt/task/run_operation.py +142 -0
  243. dvt/task/runnable.py +802 -0
  244. dvt/task/seed.py +104 -0
  245. dvt/task/show.py +150 -0
  246. dvt/task/snapshot.py +57 -0
  247. dvt/task/sql.py +111 -0
  248. dvt/task/test.py +464 -0
  249. dvt/tests/fixtures/__init__.py +1 -0
  250. dvt/tests/fixtures/project.py +620 -0
  251. dvt/tests/util.py +651 -0
  252. dvt/tracking.py +529 -0
  253. dvt/utils/__init__.py +3 -0
  254. dvt/utils/artifact_upload.py +151 -0
  255. dvt/utils/utils.py +408 -0
  256. dvt/version.py +249 -0
  257. dvt_core-1.11.0b4.dist-info/METADATA +252 -0
  258. dvt_core-1.11.0b4.dist-info/RECORD +261 -0
  259. dvt_core-1.11.0b4.dist-info/WHEEL +5 -0
  260. dvt_core-1.11.0b4.dist-info/entry_points.txt +2 -0
  261. dvt_core-1.11.0b4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,32 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Dict, Literal, Optional
3
+
4
+ from dvt.artifacts.resources.types import NodeType
5
+ from dvt.artifacts.resources.v1.components import CompiledResource
6
+ from dvt.artifacts.resources.v1.config import TestConfig
7
+
8
+ from dbt_common.dataclass_schema import dbtClassMixin
9
+
10
+
11
+ @dataclass
12
+ class TestMetadata(dbtClassMixin):
13
+ __test__ = False
14
+
15
+ name: str = "test" # dummy default to allow default in GenericTestNode. Should always be set.
16
+ # kwargs are the args that are left in the test builder after
17
+ # removing configs. They are set from the test builder when
18
+ # the test node is created.
19
+ kwargs: Dict[str, Any] = field(default_factory=dict)
20
+ namespace: Optional[str] = None
21
+
22
+
23
+ @dataclass
24
+ class GenericTest(CompiledResource):
25
+ resource_type: Literal[NodeType.Test]
26
+ column_name: Optional[str] = None
27
+ file_key_name: Optional[str] = None
28
+ # Was not able to make mypy happy and keep the code working. We need to
29
+ # refactor the various configs.
30
+ config: TestConfig = field(default_factory=TestConfig) # type: ignore
31
+ attached_node: Optional[str] = None
32
+ test_metadata: TestMetadata = field(default_factory=TestMetadata)
@@ -0,0 +1,22 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Dict, Literal, Optional
3
+
4
+ from dvt.artifacts.resources.base import BaseResource
5
+ from dvt.artifacts.resources.types import NodeType
6
+ from dvt.artifacts.resources.v1.owner import Owner
7
+
8
+ from dbt_common.contracts.config.base import BaseConfig, MergeBehavior
9
+
10
+
11
+ @dataclass
12
+ class GroupConfig(BaseConfig):
13
+ meta: Dict[str, Any] = field(default_factory=dict, metadata=MergeBehavior.Update.meta())
14
+
15
+
16
+ @dataclass
17
+ class Group(BaseResource):
18
+ name: str
19
+ owner: Owner
20
+ resource_type: Literal[NodeType.Group]
21
+ description: Optional[str] = None
22
+ config: GroupConfig = field(default_factory=GroupConfig)
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Literal, Optional
3
+
4
+ from dvt.artifacts.resources.types import NodeType
5
+ from dvt.artifacts.resources.v1.components import CompiledResource
6
+
7
+
8
+ @dataclass
9
+ class HookNode(CompiledResource):
10
+ resource_type: Literal[NodeType.Operation]
11
+ index: Optional[int] = None
@@ -0,0 +1,30 @@
1
+ import time
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, Dict, List, Literal, Optional
4
+
5
+ from dvt.artifacts.resources.base import BaseResource, Docs
6
+ from dvt.artifacts.resources.types import ModelLanguage, NodeType
7
+ from dvt.artifacts.resources.v1.components import MacroDependsOn
8
+
9
+ from dbt_common.dataclass_schema import dbtClassMixin
10
+
11
+
12
+ @dataclass
13
+ class MacroArgument(dbtClassMixin):
14
+ name: str
15
+ type: Optional[str] = None
16
+ description: str = ""
17
+
18
+
19
+ @dataclass
20
+ class Macro(BaseResource):
21
+ macro_sql: str
22
+ resource_type: Literal[NodeType.Macro]
23
+ depends_on: MacroDependsOn = field(default_factory=MacroDependsOn)
24
+ description: str = ""
25
+ meta: Dict[str, Any] = field(default_factory=dict)
26
+ docs: Docs = field(default_factory=Docs)
27
+ patch_path: Optional[str] = None
28
+ arguments: List[MacroArgument] = field(default_factory=list)
29
+ created_at: float = field(default_factory=lambda: time.time())
30
+ supported_languages: Optional[List[ModelLanguage]] = None
@@ -0,0 +1,173 @@
1
+ import time
2
+ from dataclasses import dataclass, field
3
+ from typing import Any, Dict, List, Literal, Optional
4
+
5
+ from dvt.artifacts.resources.base import GraphResource
6
+ from dvt.artifacts.resources.types import NodeType
7
+ from dvt.artifacts.resources.v1.components import DependsOn, RefArgs
8
+ from dvt.artifacts.resources.v1.semantic_layer_components import (
9
+ MeasureAggregationParameters,
10
+ NonAdditiveDimension,
11
+ SourceFileMetadata,
12
+ WhereFilterIntersection,
13
+ )
14
+
15
+ from dbt_common.contracts.config.base import BaseConfig, CompareBehavior, MergeBehavior
16
+ from dbt_common.dataclass_schema import dbtClassMixin
17
+ from dbt_semantic_interfaces.references import MeasureReference, MetricReference
18
+ from dbt_semantic_interfaces.type_enums import (
19
+ AggregationType,
20
+ ConversionCalculationType,
21
+ MetricType,
22
+ PeriodAggregation,
23
+ TimeGranularity,
24
+ )
25
+
26
+ """
27
+ The following classes are dataclasses which are used to construct the Metric
28
+ node in dbt-core. Additionally, these classes need to at a minimum support
29
+ what is specified in their protocol definitions in dbt-semantic-interfaces.
30
+ Their protocol definitions can be found here:
31
+ https://github.com/dbt-labs/dbt-semantic-interfaces/blob/main/dbt_semantic_interfaces/protocols/metric.py
32
+ """
33
+
34
+
35
+ @dataclass
36
+ class MetricInputMeasure(dbtClassMixin):
37
+ name: str
38
+ filter: Optional[WhereFilterIntersection] = None
39
+ alias: Optional[str] = None
40
+ join_to_timespine: bool = False
41
+ fill_nulls_with: Optional[int] = None
42
+
43
+ def measure_reference(self) -> MeasureReference:
44
+ return MeasureReference(element_name=self.name)
45
+
46
+ def post_aggregation_measure_reference(self) -> MeasureReference:
47
+ return MeasureReference(element_name=self.alias or self.name)
48
+
49
+
50
+ @dataclass
51
+ class MetricTimeWindow(dbtClassMixin):
52
+ count: int
53
+ granularity: str
54
+
55
+ @property
56
+ def window_string(self) -> str: # noqa: D
57
+ return f"{self.count} {self.granularity}"
58
+
59
+ @property
60
+ def is_standard_granularity(self) -> bool: # noqa: D
61
+ return self.granularity.casefold() in {item.value.casefold() for item in TimeGranularity}
62
+
63
+
64
+ @dataclass
65
+ class MetricInput(dbtClassMixin):
66
+ name: str
67
+ filter: Optional[WhereFilterIntersection] = None
68
+ alias: Optional[str] = None
69
+ offset_window: Optional[MetricTimeWindow] = None
70
+ offset_to_grain: Optional[str] = None
71
+
72
+ def as_reference(self) -> MetricReference:
73
+ return MetricReference(element_name=self.name)
74
+
75
+ def post_aggregation_reference(self) -> MetricReference:
76
+ return MetricReference(element_name=self.alias or self.name)
77
+
78
+
79
+ @dataclass
80
+ class ConstantPropertyInput(dbtClassMixin):
81
+ base_property: str
82
+ conversion_property: str
83
+
84
+
85
+ @dataclass
86
+ class ConversionTypeParams(dbtClassMixin):
87
+ base_measure: MetricInputMeasure
88
+ conversion_measure: MetricInputMeasure
89
+ entity: str
90
+ calculation: ConversionCalculationType = ConversionCalculationType.CONVERSION_RATE
91
+ window: Optional[MetricTimeWindow] = None
92
+ constant_properties: Optional[List[ConstantPropertyInput]] = None
93
+
94
+
95
+ @dataclass
96
+ class CumulativeTypeParams(dbtClassMixin):
97
+ window: Optional[MetricTimeWindow] = None
98
+ grain_to_date: Optional[str] = None
99
+ period_agg: PeriodAggregation = PeriodAggregation.FIRST
100
+ metric: Optional[MetricInput] = None
101
+
102
+
103
+ @dataclass
104
+ class MetricAggregationParams(dbtClassMixin):
105
+ semantic_model: str
106
+ agg: AggregationType
107
+ agg_params: Optional[MeasureAggregationParameters] = None
108
+ agg_time_dimension: Optional[str] = None
109
+ non_additive_dimension: Optional[NonAdditiveDimension] = None
110
+ expr: Optional[str] = None
111
+
112
+
113
+ @dataclass
114
+ class MetricTypeParams(dbtClassMixin):
115
+ measure: Optional[MetricInputMeasure] = None
116
+ input_measures: List[MetricInputMeasure] = field(default_factory=list)
117
+ numerator: Optional[MetricInput] = None
118
+ denominator: Optional[MetricInput] = None
119
+ expr: Optional[str] = None
120
+ window: Optional[MetricTimeWindow] = None
121
+ grain_to_date: Optional[TimeGranularity] = (
122
+ None # legacy, use cumulative_type_params.grain_to_date
123
+ )
124
+ metrics: Optional[List[MetricInput]] = None
125
+ conversion_type_params: Optional[ConversionTypeParams] = None
126
+ cumulative_type_params: Optional[CumulativeTypeParams] = None
127
+ metric_aggregation_params: Optional[MetricAggregationParams] = None
128
+
129
+
130
+ @dataclass
131
+ class MetricConfig(BaseConfig):
132
+ enabled: bool = True
133
+ group: Optional[str] = field(
134
+ default=None,
135
+ metadata=CompareBehavior.Exclude.meta(),
136
+ )
137
+
138
+ meta: Dict[str, Any] = field(default_factory=dict, metadata=MergeBehavior.Update.meta())
139
+
140
+
141
+ @dataclass
142
+ class Metric(GraphResource):
143
+ name: str
144
+ description: str
145
+ label: str
146
+ type: MetricType
147
+ type_params: MetricTypeParams
148
+ filter: Optional[WhereFilterIntersection] = None
149
+ metadata: Optional[SourceFileMetadata] = None
150
+ time_granularity: Optional[str] = None
151
+ resource_type: Literal[NodeType.Metric]
152
+ meta: Dict[str, Any] = field(default_factory=dict, metadata=MergeBehavior.Update.meta())
153
+ tags: List[str] = field(default_factory=list)
154
+ config: MetricConfig = field(default_factory=MetricConfig)
155
+ unrendered_config: Dict[str, Any] = field(default_factory=dict)
156
+ sources: List[List[str]] = field(default_factory=list)
157
+ depends_on: DependsOn = field(default_factory=DependsOn)
158
+ refs: List[RefArgs] = field(default_factory=list)
159
+ metrics: List[List[str]] = field(default_factory=list)
160
+ created_at: float = field(default_factory=lambda: time.time())
161
+ group: Optional[str] = None
162
+
163
+ @property
164
+ def input_measures(self) -> List[MetricInputMeasure]:
165
+ return self.type_params.input_measures
166
+
167
+ @property
168
+ def measure_references(self) -> List[MeasureReference]:
169
+ return [x.measure_reference() for x in self.input_measures]
170
+
171
+ @property
172
+ def input_metrics(self) -> List[MetricInput]:
173
+ return self.type_params.metrics or []
@@ -0,0 +1,146 @@
1
+ import enum
2
+ from dataclasses import dataclass, field
3
+ from datetime import datetime
4
+ from typing import Dict, List, Literal, Optional
5
+
6
+ from dvt.artifacts.resources.types import AccessType, NodeType, TimePeriod
7
+ from dvt.artifacts.resources.v1.components import (
8
+ CompiledResource,
9
+ DeferRelation,
10
+ NodeVersion,
11
+ )
12
+ from dvt.artifacts.resources.v1.config import NodeConfig
13
+
14
+ from dbt_common.contracts.config.base import MergeBehavior
15
+ from dbt_common.contracts.constraints import ModelLevelConstraint
16
+ from dbt_common.contracts.util import Mergeable
17
+ from dbt_common.dataclass_schema import (
18
+ ExtensibleDbtClassMixin,
19
+ ValidationError,
20
+ dbtClassMixin,
21
+ )
22
+
23
+
24
+ class ModelFreshnessUpdatesOnOptions(enum.Enum):
25
+ all = "all"
26
+ any = "any"
27
+
28
+
29
+ @dataclass
30
+ class ModelBuildAfter(ExtensibleDbtClassMixin):
31
+ count: Optional[int] = None
32
+ period: Optional[TimePeriod] = None
33
+ updates_on: ModelFreshnessUpdatesOnOptions = ModelFreshnessUpdatesOnOptions.any
34
+
35
+
36
+ @dataclass
37
+ class ModelFreshness(ExtensibleDbtClassMixin, Mergeable):
38
+ build_after: ModelBuildAfter
39
+
40
+
41
+ def merge_model_freshness(*thresholds: Optional[ModelFreshness]) -> Optional[ModelFreshness]:
42
+ if not thresholds:
43
+ return None
44
+
45
+ current_merged_value: Optional[ModelFreshness] = thresholds[0]
46
+
47
+ for i in range(1, len(thresholds)):
48
+ base = current_merged_value
49
+ update = thresholds[i]
50
+
51
+ if base is not None and update is not None:
52
+ # When both base and update freshness are defined,
53
+ # create a new ModelFreshness instance using the build_after from the 'update'.
54
+ # This effectively means 'update's build_after configuration takes precedence.
55
+ merged_freshness_obj = base.merged(update)
56
+ if (
57
+ base.build_after.updates_on == ModelFreshnessUpdatesOnOptions.all
58
+ or update.build_after.updates_on == ModelFreshnessUpdatesOnOptions.all
59
+ ):
60
+ merged_freshness_obj.build_after.updates_on = ModelFreshnessUpdatesOnOptions.all
61
+ current_merged_value = merged_freshness_obj
62
+ elif base is None and update is not None:
63
+ # If the current merged value is None but the new update is defined,
64
+ # take the update.
65
+ current_merged_value = update
66
+ else:
67
+ # This covers cases where 'update' is None (regardless of 'base'),
68
+ # or both 'base' and 'update' are None.
69
+ # The result of the pair-merge is None.
70
+ current_merged_value = base
71
+
72
+ return current_merged_value
73
+
74
+
75
+ @dataclass
76
+ class ModelConfig(NodeConfig):
77
+ access: AccessType = field(
78
+ default=AccessType.Protected,
79
+ metadata=MergeBehavior.Clobber.meta(),
80
+ )
81
+ freshness: Optional[ModelFreshness] = None
82
+
83
+ def __post_init__(self):
84
+ super().__post_init__()
85
+ if (
86
+ self.freshness
87
+ and self.freshness.build_after.period
88
+ and self.freshness.build_after.count is None
89
+ ):
90
+ raise ValidationError(
91
+ "`freshness.build_after` must have a value for `count` if a `period` is provided"
92
+ )
93
+ elif (
94
+ self.freshness
95
+ and self.freshness.build_after.count is not None
96
+ and not self.freshness.build_after.period
97
+ ):
98
+ raise ValidationError(
99
+ "`freshness.build_after` must have a value for `period` if a `count` is provided"
100
+ )
101
+
102
+ @classmethod
103
+ def __pre_deserialize__(cls, data):
104
+ data = super().__pre_deserialize__(data)
105
+ # scrub out model configs where "build_after" is not defined
106
+ if (
107
+ "freshness" in data
108
+ and isinstance(data["freshness"], dict)
109
+ and "build_after" in data["freshness"]
110
+ ):
111
+ data["freshness"] = ModelFreshness.from_dict(data["freshness"]).to_dict()
112
+ else:
113
+ data.pop("freshness", None)
114
+ return data
115
+
116
+
117
+ @dataclass
118
+ class CustomGranularity(dbtClassMixin):
119
+ name: str
120
+ column_name: Optional[str] = None
121
+
122
+
123
+ @dataclass
124
+ class TimeSpine(dbtClassMixin):
125
+ standard_granularity_column: str
126
+ custom_granularities: List[CustomGranularity] = field(default_factory=list)
127
+
128
+
129
+ @dataclass
130
+ class Model(CompiledResource):
131
+ resource_type: Literal[NodeType.Model]
132
+ access: AccessType = AccessType.Protected
133
+ config: ModelConfig = field(default_factory=ModelConfig)
134
+ constraints: List[ModelLevelConstraint] = field(default_factory=list)
135
+ version: Optional[NodeVersion] = None
136
+ latest_version: Optional[NodeVersion] = None
137
+ deprecation_date: Optional[datetime] = None
138
+ defer_relation: Optional[DeferRelation] = None
139
+ primary_key: List[str] = field(default_factory=list)
140
+ time_spine: Optional[TimeSpine] = None
141
+
142
+ def __post_serialize__(self, dct: Dict, context: Optional[Dict] = None):
143
+ dct = super().__post_serialize__(dct, context)
144
+ if context and context.get("artifact") and "defer_relation" in dct:
145
+ del dct["defer_relation"]
146
+ return dct
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional, Union
3
+
4
+ from dbt_common.contracts.config.properties import AdditionalPropertiesAllowed
5
+
6
+
7
+ @dataclass
8
+ class Owner(AdditionalPropertiesAllowed):
9
+ email: Union[str, List[str], None] = None
10
+ name: Optional[str] = None
@@ -0,0 +1,112 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from dataclasses import dataclass, field
5
+ from typing import Any, Dict, List, Literal, Optional, Union
6
+
7
+ from dvt.artifacts.resources.base import GraphResource
8
+ from dvt.artifacts.resources.types import NodeType
9
+ from dvt.artifacts.resources.v1.components import DependsOn, RefArgs
10
+ from dvt.artifacts.resources.v1.config import list_str, metas
11
+ from dvt.artifacts.resources.v1.semantic_layer_components import (
12
+ SourceFileMetadata,
13
+ WhereFilterIntersection,
14
+ )
15
+
16
+ from dbt_common.contracts.config.base import BaseConfig, CompareBehavior, MergeBehavior
17
+ from dbt_common.contracts.config.metadata import ShowBehavior
18
+ from dbt_common.dataclass_schema import dbtClassMixin
19
+ from dbt_semantic_interfaces.type_enums.export_destination_type import (
20
+ ExportDestinationType,
21
+ )
22
+
23
+
24
+ @dataclass
25
+ class ExportConfig(dbtClassMixin):
26
+ """Nested configuration attributes for exports."""
27
+
28
+ export_as: ExportDestinationType
29
+ schema_name: Optional[str] = None
30
+ alias: Optional[str] = None
31
+ database: Optional[str] = None
32
+
33
+
34
+ @dataclass
35
+ class Export(dbtClassMixin):
36
+ """Configuration for writing query results to a table."""
37
+
38
+ name: str
39
+ config: ExportConfig
40
+ unrendered_config: Dict[str, str] = field(default_factory=dict)
41
+
42
+
43
+ @dataclass
44
+ class QueryParams(dbtClassMixin):
45
+ """The query parameters for the saved query"""
46
+
47
+ metrics: List[str]
48
+ group_by: List[str]
49
+ where: Optional[WhereFilterIntersection]
50
+ order_by: List[str] = field(default_factory=list)
51
+ limit: Optional[int] = None
52
+
53
+
54
+ @dataclass
55
+ class SavedQueryCache(dbtClassMixin):
56
+ enabled: bool = False
57
+
58
+
59
+ @dataclass
60
+ class SavedQueryConfig(BaseConfig):
61
+ """Where config options for SavedQueries are stored.
62
+
63
+ This class is much like many other node config classes. It's likely that
64
+ this class will expand in the direction of what's in the `NodeAndTestConfig`
65
+ class. It might make sense to clean the various *Config classes into one at
66
+ some point.
67
+ """
68
+
69
+ enabled: bool = True
70
+ group: Optional[str] = field(
71
+ default=None,
72
+ metadata=CompareBehavior.Exclude.meta(),
73
+ )
74
+ meta: Dict[str, Any] = field(
75
+ default_factory=dict,
76
+ metadata=MergeBehavior.Update.meta(),
77
+ )
78
+ export_as: Optional[ExportDestinationType] = None
79
+ schema: Optional[str] = None
80
+ cache: SavedQueryCache = field(default_factory=SavedQueryCache)
81
+
82
+
83
+ @dataclass
84
+ class SavedQueryMandatory(GraphResource):
85
+ query_params: QueryParams
86
+ exports: List[Export]
87
+
88
+
89
+ @dataclass
90
+ class SavedQuery(SavedQueryMandatory):
91
+ resource_type: Literal[NodeType.SavedQuery]
92
+ description: Optional[str] = None
93
+ label: Optional[str] = None
94
+ metadata: Optional[SourceFileMetadata] = None
95
+ config: SavedQueryConfig = field(default_factory=SavedQueryConfig)
96
+ unrendered_config: Dict[str, Any] = field(default_factory=dict)
97
+ group: Optional[str] = None
98
+ depends_on: DependsOn = field(default_factory=DependsOn)
99
+ created_at: float = field(default_factory=lambda: time.time())
100
+ refs: List[RefArgs] = field(default_factory=list)
101
+ tags: Union[List[str], str] = field(
102
+ default_factory=list_str,
103
+ metadata=metas(ShowBehavior.Hide, MergeBehavior.Append, CompareBehavior.Exclude),
104
+ )
105
+
106
+ @property
107
+ def metrics(self) -> List[str]:
108
+ return self.query_params.metrics
109
+
110
+ @property
111
+ def depends_on_nodes(self):
112
+ return self.depends_on.nodes
@@ -0,0 +1,42 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Dict, Literal, Optional
3
+
4
+ from dvt.artifacts.resources.types import NodeType
5
+ from dvt.artifacts.resources.v1.components import (
6
+ DeferRelation,
7
+ MacroDependsOn,
8
+ ParsedResource,
9
+ )
10
+ from dvt.artifacts.resources.v1.config import NodeConfig
11
+
12
+ from dbt_common.dataclass_schema import ValidationError
13
+
14
+
15
+ @dataclass
16
+ class SeedConfig(NodeConfig):
17
+ materialized: str = "seed"
18
+ delimiter: str = ","
19
+ quote_columns: Optional[bool] = None
20
+
21
+ @classmethod
22
+ def validate(cls, data):
23
+ super().validate(data)
24
+ if data.get("materialized") and data.get("materialized") != "seed":
25
+ raise ValidationError("A seed must have a materialized value of 'seed'")
26
+
27
+
28
+ @dataclass
29
+ class Seed(ParsedResource): # No SQLDefaults!
30
+ resource_type: Literal[NodeType.Seed]
31
+ config: SeedConfig = field(default_factory=SeedConfig)
32
+ # seeds need the root_path because the contents are not loaded initially
33
+ # and we need the root_path to load the seed later
34
+ root_path: Optional[str] = None
35
+ depends_on: MacroDependsOn = field(default_factory=MacroDependsOn)
36
+ defer_relation: Optional[DeferRelation] = None
37
+
38
+ def __post_serialize__(self, dct: Dict, context: Optional[Dict] = None):
39
+ dct = super().__post_serialize__(dct, context)
40
+ if context and context.get("artifact") and "defer_relation" in dct:
41
+ del dct["defer_relation"]
42
+ return dct
@@ -0,0 +1,72 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional, Sequence, Tuple
3
+
4
+ from dbt_common.dataclass_schema import dbtClassMixin
5
+ from dbt_semantic_interfaces.call_parameter_sets import JinjaCallParameterSets
6
+ from dbt_semantic_interfaces.parsing.where_filter.jinja_object_parser import (
7
+ JinjaObjectParser,
8
+ QueryItemLocation,
9
+ )
10
+ from dbt_semantic_interfaces.type_enums import AggregationType
11
+
12
+
13
+ @dataclass
14
+ class WhereFilter(dbtClassMixin):
15
+ where_sql_template: str
16
+
17
+ def call_parameter_sets(
18
+ self, custom_granularity_names: Sequence[str]
19
+ ) -> JinjaCallParameterSets:
20
+ return JinjaObjectParser.parse_call_parameter_sets(
21
+ self.where_sql_template,
22
+ custom_granularity_names=custom_granularity_names,
23
+ query_item_location=QueryItemLocation.NON_ORDER_BY,
24
+ )
25
+
26
+
27
+ @dataclass
28
+ class WhereFilterIntersection(dbtClassMixin):
29
+ where_filters: List[WhereFilter]
30
+
31
+ def filter_expression_parameter_sets(
32
+ self, custom_granularity_names: Sequence[str]
33
+ ) -> Sequence[Tuple[str, JinjaCallParameterSets]]:
34
+ raise NotImplementedError
35
+
36
+
37
+ @dataclass
38
+ class FileSlice(dbtClassMixin):
39
+ """Provides file slice level context about what something was created from.
40
+
41
+ Implementation of the dbt-semantic-interfaces `FileSlice` protocol
42
+ """
43
+
44
+ filename: str
45
+ content: str
46
+ start_line_number: int
47
+ end_line_number: int
48
+
49
+
50
+ @dataclass
51
+ class SourceFileMetadata(dbtClassMixin):
52
+ """Provides file context about what something was created from.
53
+
54
+ Implementation of the dbt-semantic-interfaces `Metadata` protocol
55
+ """
56
+
57
+ repo_file_path: str
58
+ file_slice: FileSlice
59
+
60
+
61
+ @dataclass
62
+ class MeasureAggregationParameters(dbtClassMixin):
63
+ percentile: Optional[float] = None
64
+ use_discrete_percentile: bool = False
65
+ use_approximate_percentile: bool = False
66
+
67
+
68
+ @dataclass
69
+ class NonAdditiveDimension(dbtClassMixin):
70
+ name: str
71
+ window_choice: AggregationType
72
+ window_groupings: List[str]