Skip to content

Commit

Permalink
Merge branch 'main' into dimension_dot_grain_support
Browse files Browse the repository at this point in the history
  • Loading branch information
DevonFulcher committed Sep 20, 2023
2 parents a374894 + 3d02807 commit 31a1bb0
Show file tree
Hide file tree
Showing 21 changed files with 491 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Features-20230913-172754.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Features
body: Add New SavedQuery Protocol
time: 2023-09-13T17:27:54.018355-07:00
custom:
Author: plypaul
Issue: "144"
6 changes: 6 additions & 0 deletions .changes/unreleased/Fixes-20230914-134708.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Fixes
body: Disallow dunders semantic object names
time: 2023-09-14T13:47:08.907492-07:00
custom:
Author: QMalcolm
Issue: "149"
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ repos:
- id: ruff
verbose: true
language: system
args: [--fix]

- repo: https://github.com/pre-commit/mirrors-mypy # configured via mypy.ini
rev: v1.3.0
Expand Down
32 changes: 32 additions & 0 deletions dbt_semantic_interfaces/implementations/saved_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from __future__ import annotations

from typing import List, Optional

from typing_extensions import override

from dbt_semantic_interfaces.implementations.base import (
HashableBaseModel,
ModelWithMetadataParsing,
)
from dbt_semantic_interfaces.implementations.filters.where_filter import (
PydanticWhereFilter,
)
from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata
from dbt_semantic_interfaces.protocols import ProtocolHint
from dbt_semantic_interfaces.protocols.saved_query import SavedQuery


class PydanticSavedQuery(HashableBaseModel, ModelWithMetadataParsing, ProtocolHint[SavedQuery]):
"""Pydantic implementation of SavedQuery."""

@override
def _implements_protocol(self) -> SavedQuery:
return self

name: str
metrics: List[str]
group_bys: List[str] = []
where: List[PydanticWhereFilter] = []

description: Optional[str] = None
metadata: Optional[PydanticMetadata] = None
2 changes: 2 additions & 0 deletions dbt_semantic_interfaces/implementations/semantic_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from dbt_semantic_interfaces.implementations.project_configuration import (
PydanticProjectConfiguration,
)
from dbt_semantic_interfaces.implementations.saved_query import PydanticSavedQuery
from dbt_semantic_interfaces.implementations.semantic_model import PydanticSemanticModel
from dbt_semantic_interfaces.protocols import ProtocolHint, SemanticManifest

Expand All @@ -21,3 +22,4 @@ def _implements_protocol(self) -> SemanticManifest:
semantic_models: List[PydanticSemanticModel]
metrics: List[PydanticMetric]
project_configuration: PydanticProjectConfiguration
saved_queries: List[PydanticSavedQuery] = []
27 changes: 23 additions & 4 deletions dbt_semantic_interfaces/parsing/dir_to_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dbt_semantic_interfaces.implementations.project_configuration import (
PydanticProjectConfiguration,
)
from dbt_semantic_interfaces.implementations.saved_query import PydanticSavedQuery
from dbt_semantic_interfaces.implementations.semantic_manifest import (
PydanticSemanticManifest,
)
Expand All @@ -20,6 +21,7 @@
from dbt_semantic_interfaces.parsing.schemas import (
metric_validator,
project_configuration_validator,
saved_query_validator,
semantic_model_validator,
)
from dbt_semantic_interfaces.parsing.yaml_loader import (
Expand All @@ -45,8 +47,9 @@
METRIC_TYPE = "metric"
SEMANTIC_MODEL_TYPE = "semantic_model"
PROJECT_CONFIGURATION_TYPE = "project_configuration"
SAVED_QUERY_TYPE = "saved_query"

DOCUMENT_TYPES = [METRIC_TYPE, SEMANTIC_MODEL_TYPE, PROJECT_CONFIGURATION_TYPE]
DOCUMENT_TYPES = [METRIC_TYPE, SEMANTIC_MODEL_TYPE, PROJECT_CONFIGURATION_TYPE, SAVED_QUERY_TYPE]


@dataclass(frozen=True)
Expand All @@ -65,7 +68,7 @@ class FileParsingResult:
issues: Issues found when trying to parse the file
"""

elements: List[Union[PydanticSemanticModel, PydanticMetric, PydanticProjectConfiguration]]
elements: List[Union[PydanticSemanticModel, PydanticMetric, PydanticProjectConfiguration, PydanticSavedQuery]]
issues: List[ValidationIssue]


Expand Down Expand Up @@ -191,6 +194,7 @@ def parse_yaml_files_to_semantic_manifest(
semantic_model_class: Type[PydanticSemanticModel] = PydanticSemanticModel,
metric_class: Type[PydanticMetric] = PydanticMetric,
project_configuration_class: Type[PydanticProjectConfiguration] = PydanticProjectConfiguration,
saved_query_class: Type[PydanticSavedQuery] = PydanticSavedQuery,
) -> SemanticManifestBuildResult:
"""Builds SemanticManifest from list of config files (as strings).
Expand All @@ -202,7 +206,14 @@ def parse_yaml_files_to_semantic_manifest(
semantic_models = []
metrics = []
project_configurations = []
valid_object_classes = [semantic_model_class.__name__, metric_class.__name__, project_configuration_class.__name__]
saved_queries = []

valid_object_classes = [
semantic_model_class.__name__,
metric_class.__name__,
project_configuration_class.__name__,
saved_query_class.__name__,
]
issues: List[ValidationIssue] = []

for config_file in files:
Expand All @@ -211,6 +222,7 @@ def parse_yaml_files_to_semantic_manifest(
semantic_model_class=semantic_model_class,
metric_class=metric_class,
project_configuration_class=project_configuration_class,
saved_query_class=saved_query_class,
)
file_issues = parsing_result.issues
for obj in parsing_result.elements:
Expand All @@ -220,6 +232,8 @@ def parse_yaml_files_to_semantic_manifest(
metrics.append(obj)
elif isinstance(obj, project_configuration_class):
project_configurations.append(obj)
elif isinstance(obj, saved_query_class):
saved_queries.append(obj)
else:
file_issues.append(
ValidationError(
Expand All @@ -241,6 +255,7 @@ def parse_yaml_files_to_semantic_manifest(
semantic_models=semantic_models,
metrics=metrics,
project_configuration=project_configurations[0],
saved_queries=saved_queries,
),
issues=SemanticManifestValidationResults.from_issues_sequence(issues),
)
Expand All @@ -251,9 +266,10 @@ def parse_config_yaml(
semantic_model_class: Type[PydanticSemanticModel] = PydanticSemanticModel,
metric_class: Type[PydanticMetric] = PydanticMetric,
project_configuration_class: Type[PydanticProjectConfiguration] = PydanticProjectConfiguration,
saved_query_class: Type[PydanticSavedQuery] = PydanticSavedQuery,
) -> FileParsingResult:
"""Parses transform config file passed as string - Returns list of model objects."""
results: List[Union[PydanticSemanticModel, PydanticMetric, PydanticProjectConfiguration]] = []
results: List[Union[PydanticSemanticModel, PydanticMetric, PydanticProjectConfiguration, PydanticSavedQuery]] = []
ctx: Optional[ParsingContext] = None
issues: List[ValidationIssue] = []
try:
Expand Down Expand Up @@ -322,6 +338,9 @@ def parse_config_yaml(
elif document_type == PROJECT_CONFIGURATION_TYPE:
project_configuration_validator.validate(config_document[document_type])
results.append(project_configuration_class.parse_obj(object_cfg))
elif document_type == SAVED_QUERY_TYPE:
saved_query_validator.validate(config_document[document_type])
results.append(saved_query_class.parse_obj(object_cfg))
else:
issues.append(
ValidationError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,41 @@
],
"type": "object"
},
"saved_query_schema": {
"$id": "saved_query_schema",
"additionalProperties": false,
"properties": {
"description": {
"type": "string"
},
"group_bys": {
"items": {
"type": "string"
},
"type": "array"
},
"metrics": {
"items": {
"type": "string"
},
"type": "array"
},
"name": {
"type": "string"
},
"where": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"name",
"metrics"
],
"type": "object"
},
"semantic_model_defaults_schema": {
"$id": "semantic_model_defaults_schema",
"additionalProperties": false,
Expand Down
25 changes: 25 additions & 0 deletions dbt_semantic_interfaces/parsing/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,29 @@
}


saved_query_schema = {
"$id": "saved_query_schema",
"type": "object",
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"metrics": {
"type": "array",
"items": {"type": "string"},
},
"group_bys": {
"type": "array",
"items": {"type": "string"},
},
"where": {
"type": "array",
"items": {"type": "string"},
},
},
"required": ["name", "metrics"],
"additionalProperties": False,
}

semantic_model_schema = {
"$id": "semantic_model_schema",
"type": "object",
Expand Down Expand Up @@ -297,6 +320,7 @@
metric_schema["$id"]: metric_schema,
semantic_model_schema["$id"]: semantic_model_schema,
project_configuration_schema["$id"]: project_configuration_schema,
saved_query_schema["$id"]: saved_query_schema,
# Sub-object schemas
metric_input_measure_schema["$id"]: metric_input_measure_schema,
metric_type_params_schema["$id"]: metric_type_params_schema,
Expand All @@ -318,3 +342,4 @@
semantic_model_validator = SchemaValidator(semantic_model_schema, resolver=resolver)
metric_validator = SchemaValidator(metric_schema, resolver=resolver)
project_configuration_validator = SchemaValidator(project_configuration_schema, resolver=resolver)
saved_query_validator = SchemaValidator(saved_query_schema, resolver=resolver)
1 change: 1 addition & 0 deletions dbt_semantic_interfaces/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
MetricTypeParams,
)
from dbt_semantic_interfaces.protocols.protocol_hint import ProtocolHint # noqa:F401
from dbt_semantic_interfaces.protocols.saved_query import SavedQuery # noqa:F401
from dbt_semantic_interfaces.protocols.semantic_manifest import ( # noqa:F401
SemanticManifest,
SemanticManifestT,
Expand Down
39 changes: 39 additions & 0 deletions dbt_semantic_interfaces/protocols/saved_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from abc import abstractmethod
from typing import Optional, Protocol, Sequence

from dbt_semantic_interfaces.protocols.metadata import Metadata
from dbt_semantic_interfaces.protocols.where_filter import WhereFilter


class SavedQuery(Protocol):
"""Represents a query that the user wants to run repeatedly."""

@property
@abstractmethod
def metadata(self) -> Optional[Metadata]: # noqa: D
pass

@property
@abstractmethod
def name(self) -> str: # noqa: D
pass

@property
@abstractmethod
def description(self) -> Optional[str]: # noqa: D
pass

@property
@abstractmethod
def metrics(self) -> Sequence[str]: # noqa: D
pass

@property
@abstractmethod
def group_bys(self) -> Sequence[str]: # noqa: D
pass

@property
@abstractmethod
def where(self) -> Sequence[WhereFilter]: # noqa: D
pass
5 changes: 5 additions & 0 deletions dbt_semantic_interfaces/protocols/semantic_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from dbt_semantic_interfaces.protocols.metric import Metric
from dbt_semantic_interfaces.protocols.project_configuration import ProjectConfiguration
from dbt_semantic_interfaces.protocols.saved_query import SavedQuery
from dbt_semantic_interfaces.protocols.semantic_model import SemanticModel


Expand All @@ -24,5 +25,9 @@ def metrics(self) -> Sequence[Metric]: # noqa: D
def project_configuration(self) -> ProjectConfiguration: # noqa: D
pass

@property
def saved_queries(self) -> Sequence[SavedQuery]: # noqa: D
pass


SemanticManifestT = TypeVar("SemanticManifestT", bound=SemanticManifest)
5 changes: 1 addition & 4 deletions dbt_semantic_interfaces/validations/primary_entity.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import logging
from typing import Generic, List, Sequence

from dbt_semantic_interfaces.implementations.semantic_manifest import (
PydanticSemanticManifest,
)
from dbt_semantic_interfaces.protocols import SemanticManifestT, SemanticModel
from dbt_semantic_interfaces.references import SemanticModelReference
from dbt_semantic_interfaces.type_enums import EntityType
Expand Down Expand Up @@ -95,7 +92,7 @@ def _check_model(semantic_model: SemanticModel) -> Sequence[ValidationIssue]:

@staticmethod
@validate_safely("Check that semantic models in the manifest have properly configured primary entities.")
def validate_manifest(semantic_manifest: PydanticSemanticManifest) -> Sequence[ValidationIssue]: # noqa: D
def validate_manifest(semantic_manifest: SemanticManifestT) -> Sequence[ValidationIssue]: # noqa: D
issues: List[ValidationIssue] = []
for semantic_model in semantic_manifest.semantic_models:
issues += PrimaryEntityRule._check_model(semantic_model)
Expand Down
Loading

0 comments on commit 31a1bb0

Please sign in to comment.