Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert contract to dict #7222

Merged
merged 15 commits into from
Mar 28, 2023
6 changes: 0 additions & 6 deletions .changes/1.5.0/Under the Hood-20230217-105223.yaml

This file was deleted.

6 changes: 6 additions & 0 deletions .changes/unreleased/Under the Hood-20230217-105223.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Under the Hood
body: Treat contract config as a python object
time: 2023-02-17T10:52:23.212474-05:00
custom:
Author: gshank emmyoop
Issue: 6748 7184
14 changes: 11 additions & 3 deletions core/dbt/contracts/graph/model_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ class Severity(str):
register_pattern(Severity, insensitive_patterns("warn", "error"))


@dataclass
class Contract(dbtClassMixin, Replaceable):
enforced: bool = False


@dataclass
class Hook(dbtClassMixin, Replaceable):
sql: str
Expand Down Expand Up @@ -286,7 +291,7 @@ def same_contents(cls, unrendered: Dict[str, Any], other: Dict[str, Any]) -> boo
# 'meta' moved here from node
mergebehavior = {
"append": ["pre-hook", "pre_hook", "post-hook", "post_hook", "tags"],
"update": ["quoting", "column_types", "meta", "docs"],
"update": ["quoting", "column_types", "meta", "docs", "contract"],
"dict_key_append": ["grants"],
}

Expand Down Expand Up @@ -451,7 +456,10 @@ class NodeConfig(NodeAndTestConfig):
default_factory=Docs,
metadata=MergeBehavior.Update.meta(),
)
contract: bool = False
contract: Contract = field(
default_factory=Contract,
metadata=MergeBehavior.Update.meta(),
)

def __post_init__(self):
# we validate that node_color has a suitable value to prevent dbt-docs from crashing
Expand All @@ -464,7 +472,7 @@ def __post_init__(self):
)

if (
self.contract
self.contract.enforced
and self.materialized == "incremental"
and self.on_schema_change != "append_new_columns"
):
Expand Down
20 changes: 10 additions & 10 deletions core/dbt/contracts/graph/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
from dbt.clients.system import write_file
from dbt.contracts.files import FileHash
from dbt.contracts.graph.unparsed import (
Quoting,
Docs,
FreshnessThreshold,
ExposureType,
ExternalTable,
FreshnessThreshold,
HasYamlMetadata,
MacroArgument,
UnparsedSourceDefinition,
UnparsedSourceTableDefinition,
UnparsedColumn,
TestDef,
Owner,
ExposureType,
MaturityType,
MetricFilter,
MetricTime,
Owner,
Quoting,
TestDef,
UnparsedSourceDefinition,
UnparsedSourceTableDefinition,
UnparsedColumn,
)
from dbt.contracts.util import Replaceable, AdditionalPropertiesMixin
from dbt.events.functions import warn_or_error
Expand All @@ -50,8 +50,8 @@
from dbt.flags import get_flags
from dbt.node_types import ModelLanguage, NodeType, AccessType


from .model_config import (
Contract,
NodeConfig,
SeedConfig,
TestConfig,
Expand Down Expand Up @@ -451,7 +451,7 @@ class CompiledNode(ParsedNode):
extra_ctes_injected: bool = False
extra_ctes: List[InjectedCTE] = field(default_factory=list)
_pre_injected_sql: Optional[str] = None
contract: bool = False
contract: Contract = field(default_factory=Contract)

@property
def empty(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@

create {% if temporary: -%}temporary{%- endif %} table
{{ relation.include(database=(not temporary), schema=(not temporary)) }}
{% if config.get('contract', False) %}
{% set contract_config = config.get('contract') %}
{% if contract_config.enforced %}
{{ get_assert_columns_equivalent(sql) }}
{{ get_columns_spec_ddl() }}
{%- set sql = get_select_subquery(sql) %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

{{ sql_header if sql_header is not none }}
create view {{ relation }}
{%- if config.get('contract', False) %}
{% set contract_config = config.get('contract') %}
{% if contract_config.enforced %}
{{ get_assert_columns_equivalent(sql) }}
{%- endif %}
as (
Expand Down
12 changes: 6 additions & 6 deletions core/dbt/parser/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from dbt.config import Project, RuntimeConfig
from dbt.context.context_config import ContextConfig
from dbt.contracts.graph.manifest import Manifest
from dbt.contracts.graph.nodes import ManifestNode, BaseNode
from dbt.contracts.graph.unparsed import UnparsedNode, Docs
from dbt.contracts.graph.nodes import Contract, BaseNode, ManifestNode
from dbt.contracts.graph.unparsed import Docs, UnparsedNode
from dbt.exceptions import DbtInternalError, ConfigUpdateError, DictParseError
from dbt import hooks
from dbt.node_types import NodeType, ModelLanguage
Expand Down Expand Up @@ -297,7 +297,7 @@ def update_parsed_node_config(
# If we have docs in the config, merge with the node level, for backwards
# compatibility with earlier node-only config.
if "docs" in config_dict and config_dict["docs"]:
# we set show at the value of the config if it is set, otherwize, inherit the value
# we set show at the value of the config if it is set, otherwise, inherit the value
docs_show = (
config_dict["docs"]["show"]
if "show" in config_dict["docs"]
Expand All @@ -310,10 +310,10 @@ def update_parsed_node_config(
else:
parsed_node.docs = Docs(show=docs_show)

# If we have "contract" in the config, copy to node level, for backwards
# If we have contract in the config, copy to node level, for backwards
# compatibility with earlier node-only config.
if config_dict.get("contract", False):
parsed_node.contract = True
if "contract" in config_dict and config_dict["contract"]:
parsed_node.contract = Contract(enforced=config_dict["contract"]["enforced"])

# unrendered_config is used to compare the original database/schema/alias
# values and to handle 'same_config' and 'same_contents' calls
Expand Down
7 changes: 6 additions & 1 deletion core/dbt/parser/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ def get_unparsed_target(self) -> Iterable[NonSourceTarget]:
self.normalize_meta_attribute(data, path)
self.normalize_docs_attribute(data, path)
self.normalize_group_attribute(data, path)
self.normalize_contract_attribute(data, path)
node = self._target_type().from_dict(data)
except (ValidationError, JSONValidationError) as exc:
raise YamlParseDictError(path, self.key, data, exc)
Expand Down Expand Up @@ -828,6 +829,9 @@ def normalize_docs_attribute(self, data, path):
def normalize_group_attribute(self, data, path):
return self.normalize_attribute(data, path, "group")

def normalize_contract_attribute(self, data, path):
return self.normalize_attribute(data, path, "contract")

def patch_node_config(self, node, patch):
# Get the ContextConfig that's used in calculating the config
# This must match the model resource_type that's being patched
Expand Down Expand Up @@ -940,7 +944,8 @@ def parse_patch(self, block: TargetBlock[NodeTarget], refs: ParserRef) -> None:

def validate_constraints(self, patched_node):
error_messages = []
if patched_node.resource_type == "model" and patched_node.config.contract is True:
contract_config = patched_node.config.get("contract")
if patched_node.resource_type == "model" and contract_config.enforced is True:
validators = [
self.constraints_schema_validator(patched_node),
self.constraints_materialization_validator(patched_node),
Expand Down
3 changes: 2 additions & 1 deletion plugins/postgres/dbt/include/postgres/macros/adapters.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
{%- elif unlogged -%}
unlogged
{%- endif %} table {{ relation }}
{% if config.get('contract', False) %}
{% set contract_config = config.get('contract') %}
{% if contract_config.enforced %}
{{ get_assert_columns_equivalent(sql) }}
{{ get_columns_spec_ddl() }} ;
insert into {{ relation }} {{ get_column_names() }}
Expand Down
Loading