From 69f077bf8c284c227730fa8b96df9be6608abc58 Mon Sep 17 00:00:00 2001 From: Courtney Holcomb Date: Tue, 24 Oct 2023 16:39:15 -0700 Subject: [PATCH] Add exports config to YAML spec for saved queries --- .../unreleased/Features-20231024-162842.yaml | 6 +++ .../implementations/export.py | 29 ++++++++++++++ .../implementations/saved_query.py | 2 + dbt_semantic_interfaces/protocols/export.py | 40 +++++++++++++++++++ .../protocols/saved_query.py | 9 ++++- .../type_enums/export_destination_type.py | 8 ++++ 6 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 .changes/unreleased/Features-20231024-162842.yaml create mode 100644 dbt_semantic_interfaces/implementations/export.py create mode 100644 dbt_semantic_interfaces/protocols/export.py create mode 100644 dbt_semantic_interfaces/type_enums/export_destination_type.py diff --git a/.changes/unreleased/Features-20231024-162842.yaml b/.changes/unreleased/Features-20231024-162842.yaml new file mode 100644 index 00000000..d567e0e3 --- /dev/null +++ b/.changes/unreleased/Features-20231024-162842.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Add exports configuration to YAML spec. +time: 2023-10-24T16:28:42.013032-07:00 +custom: + Author: courtneyholcomb + Issue: "189" diff --git a/dbt_semantic_interfaces/implementations/export.py b/dbt_semantic_interfaces/implementations/export.py new file mode 100644 index 00000000..d3626ef9 --- /dev/null +++ b/dbt_semantic_interfaces/implementations/export.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from typing import Optional + +from typing_extensions import override + +from dbt_semantic_interfaces.implementations.base import HashableBaseModel +from dbt_semantic_interfaces.protocols import ProtocolHint +from dbt_semantic_interfaces.protocols.export import Export, ExportConfig +from dbt_semantic_interfaces.type_enums.export_destination_type import ExportDestinationType + + +class PydanticExport(HashableBaseModel, ProtocolHint[Export]): + """Pydantic implementation of Export.""" + + @override + def _implements_protocol(self) -> Export: + return self + + name: str + config: PydanticExportConfig + + +class PydanticExportConfig(HashableBaseModel, ProtocolHint[ExportConfig]): + """Pydantic implementation of ExportConfig.""" + + export_as: ExportDestinationType + schema: Optional[str] = None + alias: Optional[str] = None diff --git a/dbt_semantic_interfaces/implementations/saved_query.py b/dbt_semantic_interfaces/implementations/saved_query.py index 53de5038..1258b1be 100644 --- a/dbt_semantic_interfaces/implementations/saved_query.py +++ b/dbt_semantic_interfaces/implementations/saved_query.py @@ -12,6 +12,7 @@ PydanticWhereFilterIntersection, ) from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata +from dbt_semantic_interfaces.implementations.export import PydanticExport from dbt_semantic_interfaces.protocols import ProtocolHint from dbt_semantic_interfaces.protocols.saved_query import SavedQuery @@ -31,3 +32,4 @@ def _implements_protocol(self) -> SavedQuery: description: Optional[str] = None metadata: Optional[PydanticMetadata] = None label: Optional[str] = None + exports: Optional[List[PydanticExport]] = None diff --git a/dbt_semantic_interfaces/protocols/export.py b/dbt_semantic_interfaces/protocols/export.py new file mode 100644 index 00000000..4bf163a9 --- /dev/null +++ b/dbt_semantic_interfaces/protocols/export.py @@ -0,0 +1,40 @@ +from __future__ import annotations +from typing import Protocol, Optional +from abc import abstractmethod +from dbt_semantic_interfaces.type_enums.export_destination_type import ExportDestinationType + + +class Export(Protocol): + """Configuration for writing query results to a table.""" + + @property + @abstractmethod + def name(self) -> str: # noqa: D + pass + + @property + @abstractmethod + def config(self) -> ExportConfig: # noqa: D + pass + + +class ExportConfig(Protocol): + """Nested configuration attributes for exports.""" + + @property + @abstractmethod + def export_as(self) -> ExportDestinationType: + """Type of destination to write export to.""" + pass + + @property + @abstractmethod + def schema(self) -> Optional[str]: + """Schema to write export to. Defaults to deployment schema.""" + pass + + @property + @abstractmethod + def alias(self) -> Optional[str]: + """Name for table/filte export is written to. Defaults to export name.""" + pass diff --git a/dbt_semantic_interfaces/protocols/saved_query.py b/dbt_semantic_interfaces/protocols/saved_query.py index 3bd739d9..916bcf01 100644 --- a/dbt_semantic_interfaces/protocols/saved_query.py +++ b/dbt_semantic_interfaces/protocols/saved_query.py @@ -1,7 +1,8 @@ from abc import abstractmethod -from typing import Optional, Protocol, Sequence +from typing import Optional, Protocol, Sequence, List from dbt_semantic_interfaces.protocols.metadata import Metadata +from dbt_semantic_interfaces.protocols.export import Export from dbt_semantic_interfaces.protocols.where_filter import WhereFilterIntersection @@ -44,3 +45,9 @@ def where(self) -> Optional[WhereFilterIntersection]: def label(self) -> Optional[str]: """Returns a string representing a human readable label for the saved query.""" pass + + @property + @abstractmethod + def exports(self) -> Optional[List[Export]]: + """Exports that can run using this saved query.""" + pass diff --git a/dbt_semantic_interfaces/type_enums/export_destination_type.py b/dbt_semantic_interfaces/type_enums/export_destination_type.py new file mode 100644 index 00000000..2db47b7f --- /dev/null +++ b/dbt_semantic_interfaces/type_enums/export_destination_type.py @@ -0,0 +1,8 @@ +from dbt_semantic_interfaces.enum_extension import ExtendedEnum + + +class ExportDestinationType(ExtendedEnum): + """Types of destinations that exports can be written to.""" + + TABLE = "table" + VIEW = "view"