diff --git a/.changes/unreleased/Under the Hood-20240130-161637.yaml b/.changes/unreleased/Under the Hood-20240130-161637.yaml new file mode 100644 index 00000000000..17d274a8595 --- /dev/null +++ b/.changes/unreleased/Under the Hood-20240130-161637.yaml @@ -0,0 +1,6 @@ +kind: Under the Hood +body: Move data parts of `Exposure` class to dbt/artifacts +time: 2024-01-30T16:16:37.176038-08:00 +custom: + Author: QMalcolm + Issue: "9380" diff --git a/core/dbt/artifacts/resources/__init__.py b/core/dbt/artifacts/resources/__init__.py index 80727abb4aa..fba7c9730c4 100644 --- a/core/dbt/artifacts/resources/__init__.py +++ b/core/dbt/artifacts/resources/__init__.py @@ -3,6 +3,12 @@ # alias to latest resource definitions from dbt.artifacts.resources.v1.components import DependsOn, NodeVersion, RefArgs from dbt.artifacts.resources.v1.documentation import Documentation +from dbt.artifacts.resources.v1.exposure import ( + Exposure, + ExposureConfig, + ExposureType, + MaturityType, +) from dbt.artifacts.resources.v1.macro import Macro, MacroDependsOn, MacroArgument from dbt.artifacts.resources.v1.docs import Docs from dbt.artifacts.resources.v1.group import Group diff --git a/core/dbt/artifacts/resources/v1/exposure.py b/core/dbt/artifacts/resources/v1/exposure.py new file mode 100644 index 00000000000..1460c110d43 --- /dev/null +++ b/core/dbt/artifacts/resources/v1/exposure.py @@ -0,0 +1,48 @@ +from dataclasses import dataclass, field +from dbt.artifacts.resources.base import GraphResource +from dbt.artifacts.resources.types import NodeType +from dbt.artifacts.resources.v1.components import DependsOn, RefArgs +from dbt.artifacts.resources.v1.owner import Owner +from dbt_common.contracts.config.base import BaseConfig +from dbt_common.dataclass_schema import StrEnum +import time +from typing import Any, Dict, List, Literal, Optional + + +class ExposureType(StrEnum): + Dashboard = "dashboard" + Notebook = "notebook" + Analysis = "analysis" + ML = "ml" + Application = "application" + + +class MaturityType(StrEnum): + Low = "low" + Medium = "medium" + High = "high" + + +@dataclass +class ExposureConfig(BaseConfig): + enabled: bool = True + + +@dataclass +class Exposure(GraphResource): + type: ExposureType + owner: Owner + resource_type: Literal[NodeType.Exposure] + description: str = "" + label: Optional[str] = None + maturity: Optional[MaturityType] = None + meta: Dict[str, Any] = field(default_factory=dict) + tags: List[str] = field(default_factory=list) + config: ExposureConfig = field(default_factory=ExposureConfig) + unrendered_config: Dict[str, Any] = field(default_factory=dict) + url: Optional[str] = None + depends_on: DependsOn = field(default_factory=DependsOn) + refs: List[RefArgs] = field(default_factory=list) + sources: List[List[str]] = field(default_factory=list) + metrics: List[List[str]] = field(default_factory=list) + created_at: float = field(default_factory=lambda: time.time()) diff --git a/core/dbt/artifacts/schemas/manifest/v12/manifest.py b/core/dbt/artifacts/schemas/manifest/v12/manifest.py index d4fbccbacbd..5f39f76e73d 100644 --- a/core/dbt/artifacts/schemas/manifest/v12/manifest.py +++ b/core/dbt/artifacts/schemas/manifest/v12/manifest.py @@ -11,6 +11,7 @@ from dbt.artifacts.schemas.upgrades import upgrade_manifest_json from dbt.artifacts.resources import ( Documentation, + Exposure, Group, Macro, Metric, @@ -22,7 +23,6 @@ from dbt import tracking from dbt.flags import get_flags from dbt.contracts.graph.nodes import ( - Exposure, GraphMemberNode, ManifestNode, SourceDefinition, diff --git a/core/dbt/contracts/graph/model_config.py b/core/dbt/contracts/graph/model_config.py index a2fc7801d8d..b266c52c395 100644 --- a/core/dbt/contracts/graph/model_config.py +++ b/core/dbt/contracts/graph/model_config.py @@ -3,6 +3,7 @@ from typing_extensions import Annotated from dbt.artifacts.resources import ( + ExposureConfig, MetricConfig, SavedQueryConfig, SemanticModelConfig, @@ -53,11 +54,6 @@ class Hook(dbtClassMixin, Replaceable): index: Optional[int] = None -@dataclass -class ExposureConfig(BaseConfig): - enabled: bool = True - - @dataclass class SourceConfig(BaseConfig): enabled: bool = True diff --git a/core/dbt/contracts/graph/nodes.py b/core/dbt/contracts/graph/nodes.py index 28d8bd34142..3561ba146da 100644 --- a/core/dbt/contracts/graph/nodes.py +++ b/core/dbt/contracts/graph/nodes.py @@ -31,12 +31,9 @@ from dbt_common.clients.system import write_file from dbt.contracts.files import FileHash from dbt.contracts.graph.unparsed import ( - ExposureType, ExternalTable, FreshnessThreshold, HasYamlMetadata, - MaturityType, - Owner, Quoting, TestDef, UnparsedSourceDefinition, @@ -74,7 +71,6 @@ SeedConfig, TestConfig, SourceConfig, - ExposureConfig, EmptySnapshotConfig, SnapshotConfig, UnitTestConfig, @@ -85,6 +81,7 @@ BaseResource, DependsOn, Docs, + Exposure as ExposureResource, MacroDependsOn, MacroArgument, Documentation as DocumentationResource, @@ -1378,24 +1375,7 @@ def group(self): @dataclass -class Exposure(GraphNode[GraphResource]): - type: ExposureType - owner: Owner - resource_type: Literal[NodeType.Exposure] - description: str = "" - label: Optional[str] = None - maturity: Optional[MaturityType] = None - meta: Dict[str, Any] = field(default_factory=dict) - tags: List[str] = field(default_factory=list) - config: ExposureConfig = field(default_factory=ExposureConfig) - unrendered_config: Dict[str, Any] = field(default_factory=dict) - url: Optional[str] = None - depends_on: DependsOn = field(default_factory=DependsOn) - refs: List[RefArgsResource] = field(default_factory=list) - sources: List[List[str]] = field(default_factory=list) - metrics: List[List[str]] = field(default_factory=list) - created_at: float = field(default_factory=lambda: time.time()) - +class Exposure(GraphNode[ExposureResource], ExposureResource): @property def depends_on_nodes(self): return self.depends_on.nodes diff --git a/core/dbt/contracts/graph/unparsed.py b/core/dbt/contracts/graph/unparsed.py index 852c747dedc..a5ddf70560b 100644 --- a/core/dbt/contracts/graph/unparsed.py +++ b/core/dbt/contracts/graph/unparsed.py @@ -18,6 +18,8 @@ from dbt.artifacts.resources import ( Defaults, DimensionValidityParams, + ExposureType, + MaturityType, MeasureAggregationParameters, ) from dbt.contracts.util import ( @@ -506,20 +508,6 @@ def __le__(self, other): return self == other or self < other -class ExposureType(StrEnum): - Dashboard = "dashboard" - Notebook = "notebook" - Analysis = "analysis" - ML = "ml" - Application = "application" - - -class MaturityType(StrEnum): - Low = "low" - Medium = "medium" - High = "high" - - @dataclass class UnparsedExposure(dbtClassMixin, Replaceable): name: str diff --git a/core/dbt/graph/selector_methods.py b/core/dbt/graph/selector_methods.py index cd2c3af934f..10403ba04fc 100644 --- a/core/dbt/graph/selector_methods.py +++ b/core/dbt/graph/selector_methods.py @@ -735,7 +735,7 @@ def search(self, included_nodes: Set[UniqueId], selector: str) -> Iterator[Uniqu elif unique_id in manifest.sources: previous_node = manifest.sources[unique_id] elif unique_id in manifest.exposures: - previous_node = manifest.exposures[unique_id] + previous_node = Exposure.from_resource(manifest.exposures[unique_id]) elif unique_id in manifest.metrics: previous_node = Metric.from_resource(manifest.metrics[unique_id]) elif unique_id in manifest.semantic_models: diff --git a/core/dbt/parser/schema_yaml_readers.py b/core/dbt/parser/schema_yaml_readers.py index 2b64312bf87..6d73913f8c4 100644 --- a/core/dbt/parser/schema_yaml_readers.py +++ b/core/dbt/parser/schema_yaml_readers.py @@ -33,6 +33,7 @@ Entity, Export, ExportConfig, + ExposureConfig, Measure, MetricConfig, MetricInput, @@ -49,7 +50,6 @@ from dbt.exceptions import YamlParseDictError, JSONValidationError from dbt.context.providers import generate_parse_exposure, generate_parse_semantic_models -from dbt.contracts.graph.model_config import ExposureConfig from dbt.context.context_config import ( BaseContextConfigGenerator, ContextConfigGenerator, diff --git a/tests/functional/exposures/test_exposure_configs.py b/tests/functional/exposures/test_exposure_configs.py index f01147e276e..8f60778e058 100644 --- a/tests/functional/exposures/test_exposure_configs.py +++ b/tests/functional/exposures/test_exposure_configs.py @@ -1,7 +1,7 @@ import pytest -from dbt_common.dataclass_schema import ValidationError -from dbt.contracts.graph.model_config import ExposureConfig +from dbt.artifacts.resources import ExposureConfig +from dbt_common.dataclass_schema import ValidationError from dbt.tests.util import run_dbt, update_config_file, get_manifest from tests.functional.exposures.fixtures import ( diff --git a/tests/unit/test_contracts_graph_parsed.py b/tests/unit/test_contracts_graph_parsed.py index f3cf839731f..0dfc74e8909 100644 --- a/tests/unit/test_contracts_graph_parsed.py +++ b/tests/unit/test_contracts_graph_parsed.py @@ -7,9 +7,13 @@ from dbt.artifacts.resources import ( Dimension, Entity, + ExposureConfig, + ExposureType, + MaturityType, Measure, MetricInputMeasure, MetricTypeParams, + Owner, RefArgs, ) from dbt.node_types import NodeType, AccessType @@ -21,7 +25,6 @@ TestConfig, SnapshotConfig, SourceConfig, - ExposureConfig, EmptySnapshotConfig, Hook, ) @@ -41,14 +44,11 @@ SourceDefinition, Documentation, HookNode, - Owner, TestMetadata, SemanticModel, ) from dbt.contracts.graph.unparsed import ( - ExposureType, FreshnessThreshold, - MaturityType, Quoting, Time, TimePeriod, diff --git a/tests/unit/test_contracts_graph_unparsed.py b/tests/unit/test_contracts_graph_unparsed.py index 2a6d55a20c7..d6f86466fe0 100644 --- a/tests/unit/test_contracts_graph_unparsed.py +++ b/tests/unit/test_contracts_graph_unparsed.py @@ -18,14 +18,12 @@ UnparsedModelUpdate, Docs, UnparsedExposure, - MaturityType, - Owner, - ExposureType, UnparsedMetric, UnparsedMetricTypeParams, UnparsedMetricInputMeasure, UnparsedVersion, ) +from dbt.artifacts.resources import ExposureType, MaturityType, Owner from dbt.artifacts.schemas.results import FreshnessStatus from dbt.node_types import NodeType from .utils import ContractTestCase diff --git a/tests/unit/test_graph_selector_methods.py b/tests/unit/test_graph_selector_methods.py index 2b06a1dbdb8..e1aaacc810b 100644 --- a/tests/unit/test_graph_selector_methods.py +++ b/tests/unit/test_graph_selector_methods.py @@ -29,14 +29,14 @@ ) from dbt.contracts.graph.manifest import Manifest, ManifestMetadata from dbt.artifacts.resources import ( + ExposureType, MetricInputMeasure, MetricTypeParams, NodeRelation, + Owner, QueryParams, ) from dbt.contracts.graph.unparsed import ( - ExposureType, - Owner, UnitTestInputFixture, UnitTestOutputFixture, ) diff --git a/tests/unit/test_manifest.py b/tests/unit/test_manifest.py index 94f1f94a91b..36232576e3a 100644 --- a/tests/unit/test_manifest.py +++ b/tests/unit/test_manifest.py @@ -27,17 +27,15 @@ Group, ) from dbt.artifacts.resources import ( + ExposureType, + MaturityType, MetricInputMeasure, MetricTypeParams, + Owner, RefArgs, WhereFilter, WhereFilterIntersection, ) -from dbt.contracts.graph.unparsed import ( - ExposureType, - Owner, - MaturityType, -) import dbt_common.invocation from dbt_common.events.functions import reset_metadata_vars from dbt.exceptions import AmbiguousResourceNameRefError