diff --git a/.changes/unreleased/Features-20230623-114625.yaml b/.changes/unreleased/Features-20230623-114625.yaml new file mode 100644 index 00000000..c0ca3375 --- /dev/null +++ b/.changes/unreleased/Features-20230623-114625.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Add Configuration Object to Semantic Manifest +time: 2023-06-23T11:46:25.858497-07:00 +custom: + Author: plypaul + Issue: "94" diff --git a/dbt_semantic_interfaces/implementations/project_configuration.py b/dbt_semantic_interfaces/implementations/project_configuration.py new file mode 100644 index 00000000..3e52fd91 --- /dev/null +++ b/dbt_semantic_interfaces/implementations/project_configuration.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from typing import List, Optional + +from importlib_metadata import version +from pydantic import validator +from typing_extensions import override + +from dbt_semantic_interfaces.implementations.base import ( + HashableBaseModel, + ModelWithMetadataParsing, +) +from dbt_semantic_interfaces.implementations.metadata import PydanticMetadata +from dbt_semantic_interfaces.implementations.semantic_version import ( + UNKNOWN_VERSION_SENTINEL, + PydanticSemanticVersion, +) +from dbt_semantic_interfaces.implementations.time_spine_table_configuration import ( + PydanticTimeSpineTableConfiguration, +) +from dbt_semantic_interfaces.protocols import ProtocolHint +from dbt_semantic_interfaces.protocols.project_configuration import ProjectConfiguration + + +class PydanticProjectConfiguration(HashableBaseModel, ModelWithMetadataParsing, ProtocolHint[ProjectConfiguration]): + """Pydantic implementation of ProjectConfiguration.""" + + @override + def _implements_protocol(self) -> ProjectConfiguration: + return self + + time_spine_table_configurations: List[PydanticTimeSpineTableConfiguration] + metadata: Optional[PydanticMetadata] = None + dsi_package_version: PydanticSemanticVersion = UNKNOWN_VERSION_SENTINEL + + @validator("dsi_package_version", always=True) + @classmethod + def __create_default_dsi_package_version(cls, value: Optional[PydanticSemanticVersion]) -> PydanticSemanticVersion: + """Returns the version of the dbt_semantic_interfaces package that generated this manifest.""" + if value is not None and value != UNKNOWN_VERSION_SENTINEL: + return value + return PydanticSemanticVersion.create_from_string(version("dbt_semantic_interfaces")) diff --git a/dbt_semantic_interfaces/implementations/semantic_manifest.py b/dbt_semantic_interfaces/implementations/semantic_manifest.py index ab781be7..3556df62 100644 --- a/dbt_semantic_interfaces/implementations/semantic_manifest.py +++ b/dbt_semantic_interfaces/implementations/semantic_manifest.py @@ -1,11 +1,12 @@ from typing import List -from importlib_metadata import version -from pydantic import validator from typing_extensions import override from dbt_semantic_interfaces.implementations.base import HashableBaseModel from dbt_semantic_interfaces.implementations.metric import PydanticMetric +from dbt_semantic_interfaces.implementations.project_configuration import ( + PydanticProjectConfiguration, +) from dbt_semantic_interfaces.implementations.semantic_model import PydanticSemanticModel from dbt_semantic_interfaces.protocols import ProtocolHint, SemanticManifest @@ -14,17 +15,9 @@ class PydanticSemanticManifest(HashableBaseModel, ProtocolHint[SemanticManifest] """Model holds all the information the SemanticLayer needs to render a query.""" @override - def _implements_protocol(self) -> SemanticManifest: # noqa: D + def _implements_protocol(self) -> SemanticManifest: return self semantic_models: List[PydanticSemanticModel] metrics: List[PydanticMetric] - interfaces_version: str = "" - - @validator("interfaces_version", always=True) - @classmethod - def __create_default_interfaces_version(cls, value: str) -> str: # type: ignore[misc] - """Returns the version of the dbt_semantic_interfaces package that generated this manifest.""" - if value: - return value - return version("dbt_semantic_interfaces") + project_configuration: PydanticProjectConfiguration diff --git a/dbt_semantic_interfaces/implementations/semantic_version.py b/dbt_semantic_interfaces/implementations/semantic_version.py new file mode 100644 index 00000000..6f065a25 --- /dev/null +++ b/dbt_semantic_interfaces/implementations/semantic_version.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +from typing import Optional + +from typing_extensions import override + +from dbt_semantic_interfaces.implementations.base import ( + HashableBaseModel, + PydanticCustomInputParser, + PydanticParseableValueType, +) +from dbt_semantic_interfaces.protocols.semantic_version import SemanticVersion + + +class PydanticSemanticVersion(PydanticCustomInputParser, HashableBaseModel): + """Pydantic implementation of SemanticVersion.""" + + @override + def _implements_protocol(self) -> SemanticVersion: + return self + + major_version: str + minor_version: str + patch_version: Optional[str] + + @classmethod + @override + def _from_yaml_value(cls, input: PydanticParseableValueType) -> PydanticSemanticVersion: + if isinstance(input, str): + return PydanticSemanticVersion.create_from_string(input) + else: + raise ValueError( + f"{cls.__name__} inputs from YAML files are expected to be of either type string or " + f"object (key/value pairs), but got type {type(input)} with value: {input}" + ) + + @staticmethod + def create_from_string(version_str: str) -> PydanticSemanticVersion: # noqa: D + version_str_split = version_str.split(".") + if len(version_str_split) < 2: + raise ValueError(f"Expected version string to be of the form x.y or x.y.z, but got {version_str}") + return PydanticSemanticVersion( + major_version=version_str_split[0], + minor_version=version_str_split[1], + patch_version=".".join(version_str_split[2:]) if len(version_str_split) >= 3 else None, + ) + + +UNKNOWN_VERSION_SENTINEL = PydanticSemanticVersion(major_version="0", minor_version="0", patch_version="0") diff --git a/dbt_semantic_interfaces/implementations/time_spine_table_configuration.py b/dbt_semantic_interfaces/implementations/time_spine_table_configuration.py new file mode 100644 index 00000000..9bab71f8 --- /dev/null +++ b/dbt_semantic_interfaces/implementations/time_spine_table_configuration.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from typing_extensions import override + +from dbt_semantic_interfaces.implementations.base import ( + HashableBaseModel, + ModelWithMetadataParsing, +) +from dbt_semantic_interfaces.protocols import ProtocolHint +from dbt_semantic_interfaces.protocols.time_spine_configuration import ( + TimeSpineTableConfiguration, +) +from dbt_semantic_interfaces.type_enums import TimeGranularity + + +class PydanticTimeSpineTableConfiguration( + HashableBaseModel, ModelWithMetadataParsing, ProtocolHint[TimeSpineTableConfiguration] +): + """Pydantic implementation of SemanticVersion.""" + + @override + def _implements_protocol(self) -> TimeSpineTableConfiguration: + return self + + location: str + column_name: str + grain: TimeGranularity diff --git a/dbt_semantic_interfaces/parsing/dir_to_model.py b/dbt_semantic_interfaces/parsing/dir_to_model.py index 2461157c..17c1c10a 100644 --- a/dbt_semantic_interfaces/parsing/dir_to_model.py +++ b/dbt_semantic_interfaces/parsing/dir_to_model.py @@ -9,6 +9,9 @@ from dbt_semantic_interfaces.errors import ParsingException from dbt_semantic_interfaces.implementations.metric import PydanticMetric +from dbt_semantic_interfaces.implementations.project_configuration import ( + PydanticProjectConfiguration, +) from dbt_semantic_interfaces.implementations.semantic_manifest import ( PydanticSemanticManifest, ) @@ -16,6 +19,7 @@ from dbt_semantic_interfaces.parsing.objects import Version, YamlConfigFile from dbt_semantic_interfaces.parsing.schemas import ( metric_validator, + project_configuration_validator, semantic_model_validator, ) from dbt_semantic_interfaces.parsing.yaml_loader import ( @@ -39,7 +43,9 @@ VERSION_KEY = "mf_config_schema" METRIC_TYPE = "metric" SEMANTIC_MODEL_TYPE = "semantic_model" -DOCUMENT_TYPES = [METRIC_TYPE, SEMANTIC_MODEL_TYPE] +PROJECT_CONFIGURATION_TYPE = "project_configuration" + +DOCUMENT_TYPES = [METRIC_TYPE, SEMANTIC_MODEL_TYPE, PROJECT_CONFIGURATION_TYPE] @dataclass(frozen=True) @@ -58,7 +64,7 @@ class FileParsingResult: issues: Issues found when trying to parse the file """ - elements: List[Union[PydanticSemanticModel, PydanticMetric]] + elements: List[Union[PydanticSemanticModel, PydanticMetric, PydanticProjectConfiguration]] issues: List[ValidationIssue] @@ -183,6 +189,7 @@ def parse_yaml_files_to_semantic_manifest( files: List[YamlConfigFile], semantic_model_class: Type[PydanticSemanticModel] = PydanticSemanticModel, metric_class: Type[PydanticMetric] = PydanticMetric, + project_configuration_class: Type[PydanticProjectConfiguration] = PydanticProjectConfiguration, ) -> SemanticManifestBuildResult: """Builds SemanticManifest from list of config files (as strings). @@ -193,7 +200,8 @@ def parse_yaml_files_to_semantic_manifest( """ semantic_models = [] metrics = [] - valid_object_classes = [semantic_model_class.__name__, metric_class.__name__] + project_configurations = [] + valid_object_classes = [semantic_model_class.__name__, metric_class.__name__, project_configuration_class.__name__] issues: List[ValidationIssue] = [] for config_file in files: @@ -208,6 +216,8 @@ def parse_yaml_files_to_semantic_manifest( semantic_models.append(obj) elif isinstance(obj, metric_class): metrics.append(obj) + elif isinstance(obj, project_configuration_class): + project_configurations.append(obj) else: file_issues.append( ValidationError( @@ -218,10 +228,14 @@ def parse_yaml_files_to_semantic_manifest( issues += file_issues + if len(project_configurations) != 1: + raise ParsingException(f"Did not find exactly one project configuration. Got: {project_configurations}") + return SemanticManifestBuildResult( semantic_manifest=PydanticSemanticManifest( semantic_models=semantic_models, metrics=metrics, + project_configuration=project_configurations[0], ), issues=SemanticManifestValidationResults.from_issues_sequence(issues), ) @@ -231,9 +245,10 @@ def parse_config_yaml( config_yaml: YamlConfigFile, semantic_model_class: Type[PydanticSemanticModel] = PydanticSemanticModel, metric_class: Type[PydanticMetric] = PydanticMetric, + project_configuration_class: Type[PydanticProjectConfiguration] = PydanticProjectConfiguration, ) -> FileParsingResult: """Parses transform config file passed as string - Returns list of model objects.""" - results: List[Union[PydanticSemanticModel, PydanticMetric]] = [] + results: List[Union[PydanticSemanticModel, PydanticMetric, PydanticProjectConfiguration]] = [] ctx: Optional[ParsingContext] = None issues: List[ValidationIssue] = [] try: @@ -299,6 +314,9 @@ def parse_config_yaml( elif document_type == SEMANTIC_MODEL_TYPE: semantic_model_validator.validate(config_document[document_type]) results.append(semantic_model_class.parse_obj(object_cfg)) + elif document_type == PROJECT_CONFIGURATION_TYPE: + project_configuration_validator.validate(config_document[document_type]) + results.append(project_configuration_class.parse_obj(object_cfg)) else: issues.append( ValidationError( diff --git a/dbt_semantic_interfaces/parsing/explicit_schema.py b/dbt_semantic_interfaces/parsing/explicit_schema.py index d423ec23..d2c515f9 100644 --- a/dbt_semantic_interfaces/parsing/explicit_schema.py +++ b/dbt_semantic_interfaces/parsing/explicit_schema.py @@ -9,6 +9,7 @@ "metric": "metric", "semantic_model": "semantic_model", "derived_group_by_element_schema": "derived_identifier", + "project_configuration": "project_configuration", } BASE_SCHEMA = { diff --git a/dbt_semantic_interfaces/parsing/schemas.py b/dbt_semantic_interfaces/parsing/schemas.py index 9f8a5494..06f6a169 100644 --- a/dbt_semantic_interfaces/parsing/schemas.py +++ b/dbt_semantic_interfaces/parsing/schemas.py @@ -242,6 +242,33 @@ } +time_spine_table_configuration_schema = { + "$id": "time_spine_table_configuration", + "type": "object", + "properties": { + "location": {"type": "string"}, + "column_name": {"type": "string"}, + "grain": {"enum": time_granularity_values}, + }, + "additionalProperties": False, + "required": ["location", "column_name", "grain"], +} + + +project_configuration_schema = { + "$id": "project_configuration", + "type": "object", + "properties": { + "time_spine_table_configurations": { + "type": "array", + "items": {"$ref": "time_spine_table_configuration"}, + }, + }, + "additionalProperties": False, + "required": ["time_spine_table_configurations"], +} + + semantic_model_schema = { "$id": "semantic_model", "type": "object", @@ -284,6 +311,7 @@ metric_schema["$id"]: metric_schema, semantic_model_schema["$id"]: semantic_model_schema, derived_group_by_element_schema["$id"]: derived_group_by_element_schema, + project_configuration_schema["$id"]: project_configuration_schema, # Sub-object schemas metric_input_measure_schema["$id"]: metric_input_measure_schema, metric_type_params_schema["$id"]: metric_type_params_schema, @@ -297,6 +325,7 @@ metric_input_schema["$id"]: metric_input_schema, node_relation_schema["$id"]: node_relation_schema, semantic_model_defaults_schema["$id"]: semantic_model_defaults_schema, + time_spine_table_configuration_schema["$id"]: time_spine_table_configuration_schema, } @@ -304,3 +333,4 @@ semantic_model_validator = SchemaValidator(semantic_model_schema, resolver=resolver) derived_group_by_element_validator = SchemaValidator(derived_group_by_element_schema, resolver=resolver) metric_validator = SchemaValidator(metric_schema, resolver=resolver) +project_configuration_validator = SchemaValidator(project_configuration_schema, resolver=resolver) diff --git a/dbt_semantic_interfaces/parsing/schemas/default_explicit_schema.json b/dbt_semantic_interfaces/parsing/schemas/default_explicit_schema.json index e6f8f0a4..fb8a5f1b 100644 --- a/dbt_semantic_interfaces/parsing/schemas/default_explicit_schema.json +++ b/dbt_semantic_interfaces/parsing/schemas/default_explicit_schema.json @@ -404,6 +404,22 @@ ], "type": "object" }, + "project_configuration": { + "$id": "project_configuration", + "additionalProperties": false, + "properties": { + "time_spine_table_configurations": { + "items": { + "$ref": "#/definitions/time_spine_table_configuration" + }, + "type": "array" + } + }, + "required": [ + "time_spine_table_configurations" + ], + "type": "object" + }, "semantic_model": { "$id": "semantic_model", "additionalProperties": false, @@ -456,6 +472,38 @@ "required": [], "type": "object" }, + "time_spine_table_configuration": { + "$id": "time_spine_table_configuration", + "additionalProperties": false, + "properties": { + "column_name": { + "type": "string" + }, + "grain": { + "enum": [ + "DAY", + "WEEK", + "MONTH", + "QUARTER", + "YEAR", + "day", + "week", + "month", + "quarter", + "year" + ] + }, + "location": { + "type": "string" + } + }, + "required": [ + "location", + "column_name", + "grain" + ], + "type": "object" + }, "validity_params_schema": { "$id": "validity_params_schema", "additionalProperties": false, @@ -477,6 +525,9 @@ "metric": { "$ref": "#/definitions/metric" }, + "project_configuration": { + "$ref": "#/definitions/project_configuration" + }, "semantic_model": { "$ref": "#/definitions/semantic_model" } diff --git a/dbt_semantic_interfaces/protocols/project_configuration.py b/dbt_semantic_interfaces/protocols/project_configuration.py new file mode 100644 index 00000000..e2248bb3 --- /dev/null +++ b/dbt_semantic_interfaces/protocols/project_configuration.py @@ -0,0 +1,23 @@ +from abc import abstractmethod +from typing import Protocol, Sequence + +from dbt_semantic_interfaces.protocols.semantic_version import SemanticVersion +from dbt_semantic_interfaces.protocols.time_spine_configuration import ( + TimeSpineTableConfiguration, +) + + +class ProjectConfiguration(Protocol): + """Configuration options for the project associated with a semantic manifest.""" + + @property + @abstractmethod + def dsi_package_version(self) -> SemanticVersion: + """Version of the dbt-semantic-interfaces package used to define this manifest.""" + pass + + @property + @abstractmethod + def time_spine_table_configurations(self) -> Sequence[TimeSpineTableConfiguration]: + """The time spine table configurations. Multiple allowed for different time grains.""" + pass diff --git a/dbt_semantic_interfaces/protocols/semantic_manifest.py b/dbt_semantic_interfaces/protocols/semantic_manifest.py index e9e8826d..250b36ce 100644 --- a/dbt_semantic_interfaces/protocols/semantic_manifest.py +++ b/dbt_semantic_interfaces/protocols/semantic_manifest.py @@ -2,6 +2,7 @@ from typing import Protocol, Sequence, TypeVar from dbt_semantic_interfaces.protocols.metric import Metric +from dbt_semantic_interfaces.protocols.project_configuration import ProjectConfiguration from dbt_semantic_interfaces.protocols.semantic_model import SemanticModel @@ -20,7 +21,7 @@ def metrics(self) -> Sequence[Metric]: # noqa: D @property @abstractmethod - def interfaces_version(self) -> str: # noqa: D + def project_configuration(self) -> ProjectConfiguration: # noqa: D pass diff --git a/dbt_semantic_interfaces/protocols/semantic_version.py b/dbt_semantic_interfaces/protocols/semantic_version.py new file mode 100644 index 00000000..194274ae --- /dev/null +++ b/dbt_semantic_interfaces/protocols/semantic_version.py @@ -0,0 +1,21 @@ +from abc import abstractmethod +from typing import Optional, Protocol + + +class SemanticVersion(Protocol): + """Represents a semantic version in the MAJOR.MINOR.PATCH format.""" + + @property + @abstractmethod + def major_version(self) -> str: # noqa: D + pass + + @property + @abstractmethod + def minor_version(self) -> str: # noqa: D + pass + + @property + @abstractmethod + def patch_version(self) -> Optional[str]: # noqa: D + pass diff --git a/dbt_semantic_interfaces/protocols/time_spine_configuration.py b/dbt_semantic_interfaces/protocols/time_spine_configuration.py new file mode 100644 index 00000000..de0579a7 --- /dev/null +++ b/dbt_semantic_interfaces/protocols/time_spine_configuration.py @@ -0,0 +1,37 @@ +from abc import abstractmethod +from typing import Protocol + +from dbt_semantic_interfaces.type_enums import TimeGranularity + + +class TimeSpineTableConfiguration(Protocol): + """Describes the configuration for a time spine table. + + A time spine table is a table with a single column containing dates at a specific grain. + + e.g. with day granularity: + ... + 2020-01-01 + 2020-01-02 + 2020-01-03 + ... + + The time spine table is used to join to the measure source to compute cumulative metrics. + """ + + @property + @abstractmethod + def location(self) -> str: + """The location of the time spine table in schema_name.table_name format.""" + pass + + @property + @abstractmethod + def column_name(self) -> str: + """The name of the column in the time spine table that has the date values.""" + + @property + @abstractmethod + def grain(self) -> TimeGranularity: + """The grain of the dates in the time spine table.""" + pass diff --git a/tests/example_project_configuration.py b/tests/example_project_configuration.py new file mode 100644 index 00000000..b7cd99aa --- /dev/null +++ b/tests/example_project_configuration.py @@ -0,0 +1,33 @@ +import textwrap + +from dbt_semantic_interfaces.implementations.project_configuration import ( + PydanticProjectConfiguration, +) +from dbt_semantic_interfaces.implementations.time_spine_table_configuration import ( + PydanticTimeSpineTableConfiguration, +) +from dbt_semantic_interfaces.parsing.objects import YamlConfigFile +from dbt_semantic_interfaces.type_enums import TimeGranularity + +EXAMPLE_PROJECT_CONFIGURATION = PydanticProjectConfiguration( + time_spine_table_configurations=[ + PydanticTimeSpineTableConfiguration( + location="example_schema.example_table", + column_name="ds", + grain=TimeGranularity.DAY, + ) + ], +) + +EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE = YamlConfigFile( + filepath="projection_configuration_yaml_file_path", + contents=textwrap.dedent( + """\ + project_configuration: + time_spine_table_configurations: + - location: example_schema.example_table + column_name: ds + grain: day + """ + ), +) diff --git a/tests/fixtures/semantic_manifest_yamls/simple_semantic_manifest/project_configuration.yaml b/tests/fixtures/semantic_manifest_yamls/simple_semantic_manifest/project_configuration.yaml new file mode 100644 index 00000000..7840fe9f --- /dev/null +++ b/tests/fixtures/semantic_manifest_yamls/simple_semantic_manifest/project_configuration.yaml @@ -0,0 +1,6 @@ +--- +project_configuration: + time_spine_table_configurations: + - location: example_schema.example_table + column_name: ds + grain: day diff --git a/tests/implementations/test_semantic_manifest.py b/tests/implementations/test_semantic_manifest.py index aac40e36..b89e98c1 100644 --- a/tests/implementations/test_semantic_manifest.py +++ b/tests/implementations/test_semantic_manifest.py @@ -3,6 +3,10 @@ from dbt_semantic_interfaces.implementations.semantic_manifest import ( PydanticSemanticManifest, ) +from dbt_semantic_interfaces.implementations.semantic_version import ( + PydanticSemanticVersion, +) +from tests.example_project_configuration import EXAMPLE_PROJECT_CONFIGURATION def test_interfaces_version_matches() -> None: @@ -10,8 +14,11 @@ def test_interfaces_version_matches() -> None: semantic_manifest = PydanticSemanticManifest( semantic_models=[], metrics=[], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) # get the actual installed version installed_version = version("dbt_semantic_interfaces") - assert semantic_manifest.interfaces_version == installed_version + assert semantic_manifest.project_configuration.dsi_package_version == PydanticSemanticVersion.create_from_string( + installed_version + ) diff --git a/tests/parsing/test_metric_parsing.py b/tests/parsing/test_metric_parsing.py index 367eb1eb..71aec839 100644 --- a/tests/parsing/test_metric_parsing.py +++ b/tests/parsing/test_metric_parsing.py @@ -16,6 +16,9 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import ( + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, +) def test_legacy_measure_metric_parsing() -> None: @@ -31,7 +34,7 @@ def test_legacy_measure_metric_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -55,7 +58,7 @@ def test_legacy_metric_input_measure_object_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -79,7 +82,7 @@ def test_metric_metadata_parsing() -> None: ) file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -114,7 +117,7 @@ def test_ratio_metric_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -141,7 +144,7 @@ def test_ratio_metric_input_measure_object_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -169,7 +172,7 @@ def test_cumulative_window_metric_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -194,7 +197,7 @@ def test_grain_to_date_metric_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -223,7 +226,7 @@ def test_derived_metric_offset_window_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.issues.all_issues) == 0 assert len(build_result.semantic_manifest.metrics) == 1 @@ -257,7 +260,7 @@ def test_derive_metric_offset_to_grain_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.issues.all_issues) == 0 assert len(build_result.semantic_manifest.metrics) == 1 @@ -288,7 +291,7 @@ def test_constraint_metric_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -317,7 +320,7 @@ def test_derived_metric_input_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.metrics) == 1 metric = build_result.semantic_manifest.metrics[0] @@ -348,7 +351,7 @@ def test_invalid_metric_type_parsing_error() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert build_result.issues.has_blocking_issues assert "'this is not a valid type' is not one of" in str( SemanticManifestValidationException(build_result.issues.all_issues) @@ -370,7 +373,7 @@ def test_invalid_cumulative_metric_window_format_parsing_error() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert build_result.issues.has_blocking_issues assert "Invalid window" in str(SemanticManifestValidationException(build_result.issues.all_issues)) @@ -390,7 +393,7 @@ def test_invalid_cumulative_metric_window_granularity_parsing_error() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert build_result.issues.has_blocking_issues assert "Invalid time granularity" in str(SemanticManifestValidationException(build_result.issues.all_issues)) @@ -410,6 +413,6 @@ def test_invalid_cumulative_metric_window_count_parsing_error() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert build_result.issues.has_blocking_issues assert "Invalid count" in str(SemanticManifestValidationException(build_result.issues.all_issues)) diff --git a/tests/parsing/test_semantic_model_parsing.py b/tests/parsing/test_semantic_model_parsing.py index 8fd533c2..442e6444 100644 --- a/tests/parsing/test_semantic_model_parsing.py +++ b/tests/parsing/test_semantic_model_parsing.py @@ -10,6 +10,9 @@ EntityType, TimeGranularity, ) +from tests.example_project_configuration import ( + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, +) def test_semantic_model_metadata_parsing() -> None: @@ -25,7 +28,7 @@ def test_semantic_model_metadata_parsing() -> None: ) file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -56,7 +59,7 @@ def test_semantic_model_node_relation_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -81,7 +84,7 @@ def test_semantic_model_entity_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -110,7 +113,7 @@ def test_semantic_model_entity_metadata_parsing() -> None: ) file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -146,7 +149,7 @@ def test_semantic_model_measure_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -175,7 +178,7 @@ def test_semantic_model_measure_metadata_parsing() -> None: ) file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -211,7 +214,7 @@ def test_semantic_model_create_metric_measure_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -237,7 +240,7 @@ def test_semantic_model_categorical_dimension_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -265,7 +268,7 @@ def test_semantic_model_partition_dimension_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -292,7 +295,7 @@ def test_semantic_model_time_dimension_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -321,7 +324,7 @@ def test_semantic_model_primary_time_dimension_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -348,7 +351,7 @@ def test_semantic_model_dimension_metadata_parsing() -> None: ) file = YamlConfigFile(filepath="test_dir/inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] @@ -393,7 +396,7 @@ def test_semantic_model_dimension_validity_params_parsing() -> None: ) file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - build_result = parse_yaml_files_to_semantic_manifest(files=[file]) + build_result = parse_yaml_files_to_semantic_manifest(files=[file, EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE]) assert len(build_result.semantic_manifest.semantic_models) == 1 semantic_model = build_result.semantic_manifest.semantic_models[0] diff --git a/tests/test_implements_satisfy_protocols.py b/tests/test_implements_satisfy_protocols.py index 30f9b4c4..d618867d 100644 --- a/tests/test_implements_satisfy_protocols.py +++ b/tests/test_implements_satisfy_protocols.py @@ -39,6 +39,7 @@ MetricType, TimeGranularity, ) +from tests.example_project_configuration import EXAMPLE_PROJECT_CONFIGURATION @runtime_checkable @@ -67,6 +68,7 @@ def test_semantic_manifest_protocol() -> None: # noqa: D semantic_manifest = PydanticSemanticManifest( semantic_models=[semantic_model], metrics=[metric], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) assert isinstance(semantic_manifest, RuntimeCheckableSemanticManifest) diff --git a/tests/validations/test_dimension_const.py b/tests/validations/test_dimension_const.py index 0e7ea380..cde9147c 100644 --- a/tests/validations/test_dimension_const.py +++ b/tests/validations/test_dimension_const.py @@ -29,6 +29,7 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import EXAMPLE_PROJECT_CONFIGURATION def test_incompatible_dimension_type() -> None: # noqa:D @@ -64,6 +65,7 @@ def test_incompatible_dimension_type() -> None: # noqa:D type_params=PydanticMetricTypeParams(measure=PydanticMetricInputMeasure(name=measure_name)), ) ], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) @@ -111,5 +113,6 @@ def test_incompatible_dimension_is_partition() -> None: # noqa:D type_params=PydanticMetricTypeParams(measure=PydanticMetricInputMeasure(name=measure_name)), ) ], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) diff --git a/tests/validations/test_entities.py b/tests/validations/test_entities.py index 9851ad05..da4e2d97 100644 --- a/tests/validations/test_entities.py +++ b/tests/validations/test_entities.py @@ -27,6 +27,9 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import ( + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, +) def test_semantic_model_cant_have_more_than_one_primary_entity( @@ -96,7 +99,9 @@ def test_multiple_natural_entities() -> None: """ ) natural_entity_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - model = parse_yaml_files_to_validation_ready_semantic_manifest([base_semantic_manifest_file(), natural_entity_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), natural_entity_file] + ) with pytest.raises(SemanticManifestValidationException, match="can have at most one natural entity"): SemanticManifestValidator[PydanticSemanticManifest]([NaturalEntityConfigurationRule()]).checked_validations( @@ -122,7 +127,9 @@ def test_natural_entity_used_in_wrong_context() -> None: """ ) natural_entity_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - model = parse_yaml_files_to_validation_ready_semantic_manifest([base_semantic_manifest_file(), natural_entity_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), natural_entity_file] + ) with pytest.raises( SemanticManifestValidationException, match="use of `natural` entities is currently supported only in" diff --git a/tests/validations/test_measures.py b/tests/validations/test_measures.py index 29ac1d52..d01bf3fc 100644 --- a/tests/validations/test_measures.py +++ b/tests/validations/test_measures.py @@ -28,6 +28,9 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import ( + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, +) def test_metric_missing_measure() -> None: @@ -48,7 +51,9 @@ def test_metric_missing_measure() -> None: """ ) metric_missing_measure_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - model = parse_yaml_files_to_validation_ready_semantic_manifest([metric_missing_measure_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, metric_missing_measure_file] + ) with pytest.raises( SemanticManifestValidationException, @@ -85,7 +90,9 @@ def test_measures_only_exist_in_one_semantic_model() -> None: # noqa: D """ ) base_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents_1) - model = parse_yaml_files_to_validation_ready_semantic_manifest([base_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_file] + ) model_issues = SemanticManifestValidator[PydanticSemanticManifest]().validate_semantic_manifest( model.semantic_manifest ) @@ -124,7 +131,13 @@ def test_measures_only_exist_in_one_semantic_model() -> None: # noqa: D """ ) dup_measure_file = YamlConfigFile(filepath="inline_for_test_2", contents=yaml_contents_2) - dup_model = parse_yaml_files_to_validation_ready_semantic_manifest([base_file, dup_measure_file]) + dup_model = parse_yaml_files_to_validation_ready_semantic_manifest( + [ + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, + base_file, + dup_measure_file, + ] + ) model_issues = SemanticManifestValidator[PydanticSemanticManifest]( [SemanticModelMeasuresUniqueRule()] ).validate_semantic_manifest(dup_model.semantic_manifest) @@ -187,7 +200,9 @@ def test_invalid_non_additive_dimension_properties() -> None: ) invalid_dim_file = YamlConfigFile(filepath="inline_for_test_2", contents=yaml_contents) model_build_result = parse_yaml_files_to_validation_ready_semantic_manifest( - [invalid_dim_file], apply_transformations=False, raise_issues_as_exceptions=False + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, invalid_dim_file], + apply_transformations=False, + raise_issues_as_exceptions=False, ) transformed_model = PydanticSemanticManifestTransformer.transform( model=model_build_result.semantic_manifest, @@ -247,7 +262,7 @@ def test_count_measure_missing_expr() -> None: ) missing_expr_file = YamlConfigFile(filepath="inline_for_test_2", contents=yaml_contents) model_build_result = parse_yaml_files_to_validation_ready_semantic_manifest( - [missing_expr_file], apply_transformations=False + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, missing_expr_file], apply_transformations=False ) transformed_model = PydanticSemanticManifestTransformer.transform( model=model_build_result.semantic_manifest, @@ -301,7 +316,7 @@ def test_count_measure_with_distinct_expr() -> None: ) distinct_count_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model_build_result = parse_yaml_files_to_validation_ready_semantic_manifest( - [distinct_count_file], apply_transformations=False + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, distinct_count_file], apply_transformations=False ) transformed_model = PydanticSemanticManifestTransformer.transform( model=model_build_result.semantic_manifest, @@ -357,7 +372,12 @@ def test_percentile_measure_missing_agg_params() -> None: """ ) missing_agg_params_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - model = parse_yaml_files_to_validation_ready_semantic_manifest([missing_agg_params_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [ + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, + missing_agg_params_file, + ] + ) model_issues = SemanticManifestValidator[PydanticSemanticManifest]().validate_semantic_manifest( model.semantic_manifest @@ -419,7 +439,12 @@ def test_percentile_measure_bad_percentile_values() -> None: """ ) bad_percentile_values_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - model = parse_yaml_files_to_validation_ready_semantic_manifest([bad_percentile_values_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [ + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, + bad_percentile_values_file, + ] + ) model_issues = SemanticManifestValidator[PydanticSemanticManifest]().validate_semantic_manifest( model.semantic_manifest diff --git a/tests/validations/test_metrics.py b/tests/validations/test_metrics.py index 355765a2..6fe7d056 100644 --- a/tests/validations/test_metrics.py +++ b/tests/validations/test_metrics.py @@ -38,6 +38,7 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import EXAMPLE_PROJECT_CONFIGURATION def test_metric_no_time_dim_dim_only_source() -> None: # noqa:D @@ -81,6 +82,7 @@ def test_metric_no_time_dim_dim_only_source() -> None: # noqa:D type_params=PydanticMetricTypeParams(measure=PydanticMetricInputMeasure(name=measure_name)), ) ], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) @@ -111,6 +113,7 @@ def test_metric_no_time_dim() -> None: # noqa:D type_params=PydanticMetricTypeParams(measure=PydanticMetricInputMeasure(name=measure_name)), ) ], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) @@ -152,6 +155,7 @@ def test_metric_multiple_primary_time_dims() -> None: # noqa:D type_params=PydanticMetricTypeParams(measure=PydanticMetricInputMeasure(name=measure_name)), ) ], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) @@ -187,6 +191,7 @@ def test_generated_metrics_only() -> None: # noqa:D PydanticSemanticManifest( semantic_models=[semantic_model], metrics=[], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) @@ -276,6 +281,7 @@ def test_derived_metric() -> None: # noqa: D ), ), ], + project_configuration=EXAMPLE_PROJECT_CONFIGURATION, ) ) build_issues = validation_results.errors diff --git a/tests/validations/test_semantic_models.py b/tests/validations/test_semantic_models.py index 4cb5da69..5a7783e4 100644 --- a/tests/validations/test_semantic_models.py +++ b/tests/validations/test_semantic_models.py @@ -24,6 +24,9 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import ( + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, +) @pytest.mark.skip("TODO: Will convert to validation rule") @@ -61,7 +64,9 @@ def test_semantic_model_defaults_invalid() -> None: # noqa: D """ ) invalid_defaults_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) - model = parse_yaml_files_to_validation_ready_semantic_manifest([invalid_defaults_file]) + model = parse_yaml_files_to_validation_ready_semantic_manifest( + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, invalid_defaults_file] + ) with pytest.raises( SemanticManifestValidationException, match="'doesnotexist' which doesn't exist as a time dimension" diff --git a/tests/validations/test_validity_param_definitions.py b/tests/validations/test_validity_param_definitions.py index 84f6ab5f..8ce82e7b 100644 --- a/tests/validations/test_validity_param_definitions.py +++ b/tests/validations/test_validity_param_definitions.py @@ -19,6 +19,9 @@ from dbt_semantic_interfaces.validations.validator_helpers import ( SemanticManifestValidationException, ) +from tests.example_project_configuration import ( + EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, +) def test_validity_window_configuration() -> None: @@ -52,7 +55,7 @@ def test_validity_window_configuration() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) model_issues = SemanticManifestValidator[PydanticSemanticManifest]().validate_semantic_manifest( @@ -90,7 +93,7 @@ def test_validity_window_must_have_a_start() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="has 1 dimensions defined with validity params"): @@ -124,7 +127,7 @@ def test_validity_window_must_have_an_end() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="has 1 dimensions defined with validity params"): @@ -162,7 +165,7 @@ def test_validity_window_uses_two_dimensions() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises( @@ -205,7 +208,7 @@ def test_two_dimension_validity_windows_must_not_overload_start_and_end() -> Non ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="does not have exactly one each"): @@ -257,7 +260,7 @@ def test_multiple_validity_windows_are_invalid() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="has 4 dimensions defined with validity params"): @@ -297,7 +300,7 @@ def test_empty_validity_windows_are_invalid() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="does not have exactly one each"): @@ -346,7 +349,7 @@ def test_measures_are_prevented() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises( @@ -388,7 +391,7 @@ def test_validity_window_must_have_a_natural_key() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="does not have an entity with type `natural` set"): @@ -435,7 +438,7 @@ def test_validity_window_does_not_use_primary_key() -> None: ) validity_window_file = YamlConfigFile(filepath="inline_for_test", contents=yaml_contents) model = parse_yaml_files_to_validation_ready_semantic_manifest( - [base_semantic_manifest_file(), validity_window_file] + [EXAMPLE_PROJECT_CONFIGURATION_YAML_CONFIG_FILE, base_semantic_manifest_file(), validity_window_file] ) with pytest.raises(SemanticManifestValidationException, match="has one or more entities designated as `primary`"):