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.
- dvt/__init__.py +7 -0
- dvt/_pydantic_shim.py +26 -0
- dvt/adapters/__init__.py +16 -0
- dvt/adapters/multi_adapter_manager.py +268 -0
- dvt/artifacts/__init__.py +0 -0
- dvt/artifacts/exceptions/__init__.py +1 -0
- dvt/artifacts/exceptions/schemas.py +31 -0
- dvt/artifacts/resources/__init__.py +116 -0
- dvt/artifacts/resources/base.py +68 -0
- dvt/artifacts/resources/types.py +93 -0
- dvt/artifacts/resources/v1/analysis.py +10 -0
- dvt/artifacts/resources/v1/catalog.py +23 -0
- dvt/artifacts/resources/v1/components.py +275 -0
- dvt/artifacts/resources/v1/config.py +282 -0
- dvt/artifacts/resources/v1/documentation.py +11 -0
- dvt/artifacts/resources/v1/exposure.py +52 -0
- dvt/artifacts/resources/v1/function.py +53 -0
- dvt/artifacts/resources/v1/generic_test.py +32 -0
- dvt/artifacts/resources/v1/group.py +22 -0
- dvt/artifacts/resources/v1/hook.py +11 -0
- dvt/artifacts/resources/v1/macro.py +30 -0
- dvt/artifacts/resources/v1/metric.py +173 -0
- dvt/artifacts/resources/v1/model.py +146 -0
- dvt/artifacts/resources/v1/owner.py +10 -0
- dvt/artifacts/resources/v1/saved_query.py +112 -0
- dvt/artifacts/resources/v1/seed.py +42 -0
- dvt/artifacts/resources/v1/semantic_layer_components.py +72 -0
- dvt/artifacts/resources/v1/semantic_model.py +315 -0
- dvt/artifacts/resources/v1/singular_test.py +14 -0
- dvt/artifacts/resources/v1/snapshot.py +92 -0
- dvt/artifacts/resources/v1/source_definition.py +85 -0
- dvt/artifacts/resources/v1/sql_operation.py +10 -0
- dvt/artifacts/resources/v1/unit_test_definition.py +78 -0
- dvt/artifacts/schemas/__init__.py +0 -0
- dvt/artifacts/schemas/base.py +191 -0
- dvt/artifacts/schemas/batch_results.py +24 -0
- dvt/artifacts/schemas/catalog/__init__.py +12 -0
- dvt/artifacts/schemas/catalog/v1/__init__.py +0 -0
- dvt/artifacts/schemas/catalog/v1/catalog.py +60 -0
- dvt/artifacts/schemas/freshness/__init__.py +1 -0
- dvt/artifacts/schemas/freshness/v3/__init__.py +0 -0
- dvt/artifacts/schemas/freshness/v3/freshness.py +159 -0
- dvt/artifacts/schemas/manifest/__init__.py +2 -0
- dvt/artifacts/schemas/manifest/v12/__init__.py +0 -0
- dvt/artifacts/schemas/manifest/v12/manifest.py +212 -0
- dvt/artifacts/schemas/results.py +148 -0
- dvt/artifacts/schemas/run/__init__.py +2 -0
- dvt/artifacts/schemas/run/v5/__init__.py +0 -0
- dvt/artifacts/schemas/run/v5/run.py +184 -0
- dvt/artifacts/schemas/upgrades/__init__.py +4 -0
- dvt/artifacts/schemas/upgrades/upgrade_manifest.py +174 -0
- dvt/artifacts/schemas/upgrades/upgrade_manifest_dbt_version.py +2 -0
- dvt/artifacts/utils/validation.py +153 -0
- dvt/cli/__init__.py +1 -0
- dvt/cli/context.py +16 -0
- dvt/cli/exceptions.py +56 -0
- dvt/cli/flags.py +558 -0
- dvt/cli/main.py +971 -0
- dvt/cli/option_types.py +121 -0
- dvt/cli/options.py +79 -0
- dvt/cli/params.py +803 -0
- dvt/cli/requires.py +478 -0
- dvt/cli/resolvers.py +32 -0
- dvt/cli/types.py +40 -0
- dvt/clients/__init__.py +0 -0
- dvt/clients/checked_load.py +82 -0
- dvt/clients/git.py +164 -0
- dvt/clients/jinja.py +206 -0
- dvt/clients/jinja_static.py +245 -0
- dvt/clients/registry.py +192 -0
- dvt/clients/yaml_helper.py +68 -0
- dvt/compilation.py +833 -0
- dvt/compute/__init__.py +26 -0
- dvt/compute/base.py +288 -0
- dvt/compute/engines/__init__.py +13 -0
- dvt/compute/engines/duckdb_engine.py +368 -0
- dvt/compute/engines/spark_engine.py +273 -0
- dvt/compute/query_analyzer.py +212 -0
- dvt/compute/router.py +483 -0
- dvt/config/__init__.py +4 -0
- dvt/config/catalogs.py +95 -0
- dvt/config/compute_config.py +406 -0
- dvt/config/profile.py +411 -0
- dvt/config/profiles_v2.py +464 -0
- dvt/config/project.py +893 -0
- dvt/config/renderer.py +232 -0
- dvt/config/runtime.py +491 -0
- dvt/config/selectors.py +209 -0
- dvt/config/utils.py +78 -0
- dvt/connectors/.gitignore +6 -0
- dvt/connectors/README.md +306 -0
- dvt/connectors/catalog.yml +217 -0
- dvt/connectors/download_connectors.py +300 -0
- dvt/constants.py +29 -0
- dvt/context/__init__.py +0 -0
- dvt/context/base.py +746 -0
- dvt/context/configured.py +136 -0
- dvt/context/context_config.py +350 -0
- dvt/context/docs.py +82 -0
- dvt/context/exceptions_jinja.py +179 -0
- dvt/context/macro_resolver.py +195 -0
- dvt/context/macros.py +171 -0
- dvt/context/manifest.py +73 -0
- dvt/context/providers.py +2198 -0
- dvt/context/query_header.py +14 -0
- dvt/context/secret.py +59 -0
- dvt/context/target.py +74 -0
- dvt/contracts/__init__.py +0 -0
- dvt/contracts/files.py +413 -0
- dvt/contracts/graph/__init__.py +0 -0
- dvt/contracts/graph/manifest.py +1904 -0
- dvt/contracts/graph/metrics.py +98 -0
- dvt/contracts/graph/model_config.py +71 -0
- dvt/contracts/graph/node_args.py +42 -0
- dvt/contracts/graph/nodes.py +1806 -0
- dvt/contracts/graph/semantic_manifest.py +233 -0
- dvt/contracts/graph/unparsed.py +812 -0
- dvt/contracts/project.py +417 -0
- dvt/contracts/results.py +53 -0
- dvt/contracts/selection.py +23 -0
- dvt/contracts/sql.py +86 -0
- dvt/contracts/state.py +69 -0
- dvt/contracts/util.py +46 -0
- dvt/deprecations.py +347 -0
- dvt/deps/__init__.py +0 -0
- dvt/deps/base.py +153 -0
- dvt/deps/git.py +196 -0
- dvt/deps/local.py +80 -0
- dvt/deps/registry.py +131 -0
- dvt/deps/resolver.py +149 -0
- dvt/deps/tarball.py +121 -0
- dvt/docs/source/_ext/dbt_click.py +118 -0
- dvt/docs/source/conf.py +32 -0
- dvt/env_vars.py +64 -0
- dvt/event_time/event_time.py +40 -0
- dvt/event_time/sample_window.py +60 -0
- dvt/events/__init__.py +16 -0
- dvt/events/base_types.py +37 -0
- dvt/events/core_types_pb2.py +2 -0
- dvt/events/logging.py +109 -0
- dvt/events/types.py +2534 -0
- dvt/exceptions.py +1487 -0
- dvt/flags.py +89 -0
- dvt/graph/__init__.py +11 -0
- dvt/graph/cli.py +248 -0
- dvt/graph/graph.py +172 -0
- dvt/graph/queue.py +213 -0
- dvt/graph/selector.py +375 -0
- dvt/graph/selector_methods.py +976 -0
- dvt/graph/selector_spec.py +223 -0
- dvt/graph/thread_pool.py +18 -0
- dvt/hooks.py +21 -0
- dvt/include/README.md +49 -0
- dvt/include/__init__.py +3 -0
- dvt/include/global_project.py +4 -0
- dvt/include/starter_project/.gitignore +4 -0
- dvt/include/starter_project/README.md +15 -0
- dvt/include/starter_project/__init__.py +3 -0
- dvt/include/starter_project/analyses/.gitkeep +0 -0
- dvt/include/starter_project/dvt_project.yml +36 -0
- dvt/include/starter_project/macros/.gitkeep +0 -0
- dvt/include/starter_project/models/example/my_first_dbt_model.sql +27 -0
- dvt/include/starter_project/models/example/my_second_dbt_model.sql +6 -0
- dvt/include/starter_project/models/example/schema.yml +21 -0
- dvt/include/starter_project/seeds/.gitkeep +0 -0
- dvt/include/starter_project/snapshots/.gitkeep +0 -0
- dvt/include/starter_project/tests/.gitkeep +0 -0
- dvt/internal_deprecations.py +27 -0
- dvt/jsonschemas/__init__.py +3 -0
- dvt/jsonschemas/jsonschemas.py +309 -0
- dvt/jsonschemas/project/0.0.110.json +4717 -0
- dvt/jsonschemas/project/0.0.85.json +2015 -0
- dvt/jsonschemas/resources/0.0.110.json +2636 -0
- dvt/jsonschemas/resources/0.0.85.json +2536 -0
- dvt/jsonschemas/resources/latest.json +6773 -0
- dvt/links.py +4 -0
- dvt/materializations/__init__.py +0 -0
- dvt/materializations/incremental/__init__.py +0 -0
- dvt/materializations/incremental/microbatch.py +235 -0
- dvt/mp_context.py +8 -0
- dvt/node_types.py +37 -0
- dvt/parser/__init__.py +23 -0
- dvt/parser/analysis.py +21 -0
- dvt/parser/base.py +549 -0
- dvt/parser/common.py +267 -0
- dvt/parser/docs.py +52 -0
- dvt/parser/fixtures.py +51 -0
- dvt/parser/functions.py +30 -0
- dvt/parser/generic_test.py +100 -0
- dvt/parser/generic_test_builders.py +334 -0
- dvt/parser/hooks.py +119 -0
- dvt/parser/macros.py +137 -0
- dvt/parser/manifest.py +2204 -0
- dvt/parser/models.py +574 -0
- dvt/parser/partial.py +1179 -0
- dvt/parser/read_files.py +445 -0
- dvt/parser/schema_generic_tests.py +423 -0
- dvt/parser/schema_renderer.py +111 -0
- dvt/parser/schema_yaml_readers.py +936 -0
- dvt/parser/schemas.py +1467 -0
- dvt/parser/search.py +149 -0
- dvt/parser/seeds.py +28 -0
- dvt/parser/singular_test.py +20 -0
- dvt/parser/snapshots.py +44 -0
- dvt/parser/sources.py +557 -0
- dvt/parser/sql.py +63 -0
- dvt/parser/unit_tests.py +622 -0
- dvt/plugins/__init__.py +20 -0
- dvt/plugins/contracts.py +10 -0
- dvt/plugins/exceptions.py +2 -0
- dvt/plugins/manager.py +164 -0
- dvt/plugins/manifest.py +21 -0
- dvt/profiler.py +20 -0
- dvt/py.typed +1 -0
- dvt/runners/__init__.py +2 -0
- dvt/runners/exposure_runner.py +7 -0
- dvt/runners/no_op_runner.py +46 -0
- dvt/runners/saved_query_runner.py +7 -0
- dvt/selected_resources.py +8 -0
- dvt/task/__init__.py +0 -0
- dvt/task/base.py +504 -0
- dvt/task/build.py +197 -0
- dvt/task/clean.py +57 -0
- dvt/task/clone.py +162 -0
- dvt/task/compile.py +151 -0
- dvt/task/compute.py +366 -0
- dvt/task/debug.py +650 -0
- dvt/task/deps.py +280 -0
- dvt/task/docs/__init__.py +3 -0
- dvt/task/docs/generate.py +408 -0
- dvt/task/docs/index.html +250 -0
- dvt/task/docs/serve.py +28 -0
- dvt/task/freshness.py +323 -0
- dvt/task/function.py +122 -0
- dvt/task/group_lookup.py +46 -0
- dvt/task/init.py +374 -0
- dvt/task/list.py +237 -0
- dvt/task/printer.py +176 -0
- dvt/task/profiles.py +256 -0
- dvt/task/retry.py +175 -0
- dvt/task/run.py +1146 -0
- dvt/task/run_operation.py +142 -0
- dvt/task/runnable.py +802 -0
- dvt/task/seed.py +104 -0
- dvt/task/show.py +150 -0
- dvt/task/snapshot.py +57 -0
- dvt/task/sql.py +111 -0
- dvt/task/test.py +464 -0
- dvt/tests/fixtures/__init__.py +1 -0
- dvt/tests/fixtures/project.py +620 -0
- dvt/tests/util.py +651 -0
- dvt/tracking.py +529 -0
- dvt/utils/__init__.py +3 -0
- dvt/utils/artifact_upload.py +151 -0
- dvt/utils/utils.py +408 -0
- dvt/version.py +249 -0
- dvt_core-1.11.0b4.dist-info/METADATA +252 -0
- dvt_core-1.11.0b4.dist-info/RECORD +261 -0
- dvt_core-1.11.0b4.dist-info/WHEEL +5 -0
- dvt_core-1.11.0b4.dist-info/entry_points.txt +2 -0
- 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]
|