-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Relation/Materialization Prep Reformat #8128
Changes from 1 commit
488b5a8
1da1605
67d0238
e3570f4
3d719ce
c895a08
a02483d
1686186
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,3 +10,5 @@ ignore = | |
E741 | ||
E501 # long line checking is done in black | ||
exclude = test/ | ||
per-file-ignores = | ||
*/__init__.py: F401 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import abc | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjusted the import order and combined imports where we have multiple lines importing from the same module or package. |
||
from concurrent.futures import as_completed, Future | ||
from concurrent.futures import Future, as_completed | ||
from contextlib import contextmanager | ||
from datetime import datetime | ||
from enum import Enum | ||
|
@@ -20,11 +20,36 @@ | |
Union, | ||
) | ||
|
||
from dbt.contracts.graph.nodes import ColumnLevelConstraint, ConstraintType, ModelLevelConstraint | ||
|
||
import agate | ||
import pytz | ||
|
||
from dbt import deprecations | ||
from dbt.adapters.base import Column as BaseColumn, Credentials | ||
from dbt.adapters.base.connections import AdapterResponse, Connection | ||
from dbt.adapters.base.meta import AdapterMeta, available | ||
from dbt.adapters.base.relation import BaseRelation, InformationSchema, SchemaSearchMap | ||
from dbt.adapters.cache import RelationsCache, _make_ref_key_dict | ||
from dbt.adapters.protocol import AdapterConfig, ConnectionManagerProtocol | ||
from dbt.clients.agate_helper import empty_table, merge_tables, table_from_rows | ||
from dbt.clients.jinja import MacroGenerator | ||
from dbt.contracts.graph.manifest import Manifest, MacroManifest | ||
from dbt.contracts.graph.nodes import ( | ||
ColumnLevelConstraint, | ||
ConstraintType, | ||
ModelLevelConstraint, | ||
ResultNode, | ||
) | ||
from dbt.contracts.relation import ComponentName | ||
from dbt.events.functions import fire_event, warn_or_error | ||
from dbt.events.types import ( | ||
CacheMiss, | ||
CatalogGenerationError, | ||
CodeExecution, | ||
CodeExecutionStatus, | ||
ConstraintNotEnforced, | ||
ConstraintNotSupported, | ||
ListRelations, | ||
) | ||
from dbt.exceptions import ( | ||
DbtInternalError, | ||
DbtRuntimeError, | ||
|
@@ -42,36 +67,8 @@ | |
UnexpectedNonTimestampError, | ||
UnexpectedNullError, | ||
) | ||
|
||
from dbt.adapters.protocol import AdapterConfig, ConnectionManagerProtocol | ||
from dbt.clients.agate_helper import empty_table, merge_tables, table_from_rows | ||
from dbt.clients.jinja import MacroGenerator | ||
from dbt.contracts.graph.manifest import Manifest, MacroManifest | ||
from dbt.contracts.graph.nodes import ResultNode | ||
from dbt.events.functions import fire_event, warn_or_error | ||
from dbt.events.types import ( | ||
CacheMiss, | ||
ListRelations, | ||
CodeExecution, | ||
CodeExecutionStatus, | ||
CatalogGenerationError, | ||
ConstraintNotSupported, | ||
ConstraintNotEnforced, | ||
) | ||
from dbt.utils import filter_null_values, executor, cast_to_str, AttrDict | ||
|
||
from dbt.adapters.base.connections import Connection, AdapterResponse | ||
from dbt.adapters.base.meta import AdapterMeta, available | ||
from dbt.adapters.base.relation import ( | ||
ComponentName, | ||
BaseRelation, | ||
InformationSchema, | ||
SchemaSearchMap, | ||
) | ||
from dbt.adapters.base import Column as BaseColumn | ||
from dbt.adapters.base import Credentials | ||
from dbt.adapters.cache import RelationsCache, _make_ref_key_dict | ||
from dbt import deprecations | ||
|
||
GET_CATALOG_MACRO_NAME = "get_catalog" | ||
FRESHNESS_MACRO_NAME = "collect_freshness" | ||
|
@@ -848,16 +845,16 @@ def drop_schema(self, relation: BaseRelation): | |
"""Drop the given schema (and everything in it) if it exists.""" | ||
raise NotImplementedError("`drop_schema` is not implemented for this adapter!") | ||
|
||
@available | ||
@classmethod | ||
@available | ||
@abc.abstractmethod | ||
def quote(cls, identifier: str) -> str: | ||
"""Quote the given identifier, as appropriate for the database.""" | ||
raise NotImplementedError("`quote` is not implemented for this adapter!") | ||
|
||
@available | ||
def quote_as_configured(self, identifier: str, quote_key: str) -> str: | ||
"""Quote or do not quote the given identifer as configured in the | ||
"""Quote or do not quote the given identifier as configured in the | ||
project config for the quote key. | ||
|
||
The quote key should be one of 'database' (on bigquery, 'profile'), | ||
|
@@ -965,8 +962,8 @@ def convert_time_type(cls, agate_table: agate.Table, col_idx: int) -> str: | |
""" | ||
raise NotImplementedError("`convert_time_type` is not implemented for this adapter!") | ||
|
||
@available | ||
@classmethod | ||
@available | ||
def convert_type(cls, agate_table: agate.Table, col_idx: int) -> Optional[str]: | ||
return cls.convert_agate_type(agate_table, col_idx) | ||
|
||
|
@@ -1349,8 +1346,8 @@ def render_column_constraint(cls, constraint: ColumnLevelConstraint) -> Optional | |
|
||
return rendered_column_constraint | ||
|
||
@available | ||
@classmethod | ||
@available | ||
def render_raw_columns_constraints(cls, raw_columns: Dict[str, Dict[str, Any]]) -> List: | ||
rendered_column_constraints = [] | ||
|
||
|
@@ -1398,8 +1395,8 @@ def _parse_model_constraint(cls, raw_constraint: Dict[str, Any]) -> ModelLevelCo | |
except Exception: | ||
raise DbtValidationError(f"Could not parse constraint: {raw_constraint}") | ||
|
||
@available | ||
@classmethod | ||
@available | ||
def render_raw_model_constraints(cls, raw_constraints: List[Dict[str, Any]]) -> List[str]: | ||
return [c for c in map(cls.render_raw_model_constraint, raw_constraints) if c is not None] | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,24 @@ | ||
from collections.abc import Hashable | ||
from dataclasses import dataclass, field | ||
from typing import Optional, TypeVar, Any, Type, Dict, Iterator, Tuple, Set | ||
from typing import Any, Dict, Iterator, Optional, Set, Tuple, Type, TypeVar | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed import order |
||
|
||
from dbt.contracts.graph.nodes import SourceDefinition, ManifestNode, ResultNode, ParsedNode | ||
from dbt.contracts.graph.nodes import ManifestNode, ParsedNode, ResultNode, SourceDefinition | ||
from dbt.contracts.relation import ( | ||
RelationType, | ||
ComponentName, | ||
HasQuoting, | ||
FakeAPIObject, | ||
Policy, | ||
HasQuoting, | ||
Path, | ||
Policy, | ||
RelationType, | ||
) | ||
import dbt.exceptions | ||
from dbt.exceptions import ( | ||
ApproximateMatchError, | ||
DbtInternalError, | ||
MultipleDatabasesNotAllowedError, | ||
) | ||
from dbt.node_types import NodeType | ||
from dbt.utils import filter_null_values, deep_merge, classproperty | ||
|
||
import dbt.exceptions | ||
from dbt.utils import classproperty, deep_merge, filter_null_values | ||
|
||
|
||
Self = TypeVar("Self", bound="BaseRelation") | ||
|
@@ -31,7 +30,8 @@ class BaseRelation(FakeAPIObject, Hashable): | |
type: Optional[RelationType] = None | ||
quote_character: str = '"' | ||
# Python 3.11 requires that these use default_factory instead of simple default | ||
# ValueError: mutable default <class 'dbt.contracts.relation.Policy'> for field include_policy is not allowed: use default_factory | ||
# ValueError: mutable default <class 'dbt.contracts.relation.Policy'> for field include_policy is not allowed: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line exceeded max length |
||
# use default_factory | ||
include_policy: Policy = field(default_factory=lambda: Policy()) | ||
quote_policy: Policy = field(default_factory=lambda: Policy()) | ||
dbt_created: bool = False | ||
|
@@ -170,13 +170,14 @@ def without_identifier(self) -> "BaseRelation": | |
|
||
def _render_iterator(self) -> Iterator[Tuple[Optional[ComponentName], Optional[str]]]: | ||
|
||
for key in ComponentName: | ||
for member in ComponentName: | ||
path_part: Optional[str] = None | ||
if self.include_policy.get_part(key): | ||
path_part = self.path.get_part(key) | ||
if path_part is not None and self.quote_policy.get_part(key): | ||
component = ComponentName(member) | ||
if self.include_policy.get_part(component): | ||
path_part = self.path.get_part(component) | ||
if path_part is not None and self.quote_policy.get_part(component): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
path_part = self.quoted(path_part) | ||
yield key, path_part | ||
yield component, path_part | ||
|
||
def render(self) -> str: | ||
# if there is nothing set, this will return the empty string. | ||
|
@@ -259,7 +260,7 @@ def create_from( | |
return cls.create_from_source(node, **kwargs) | ||
else: | ||
# Can't use ManifestNode here because of parameterized generics | ||
if not isinstance(node, (ParsedNode)): | ||
if not isinstance(node, ParsedNode): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. redundant |
||
raise DbtInternalError( | ||
f"type mismatch, expected ManifestNode but got {type(node)}" | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from dbt.adapters.relation.models._relation import ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename |
||
DescribeRelationResults, | ||
RelationComponent, | ||
) | ||
from dbt.adapters.relation.models._change import ( | ||
RelationChangeAction, | ||
RelationChange, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,19 +2,19 @@ | |
from dataclasses import dataclass | ||
from typing import Hashable | ||
|
||
from dbt.adapters.relation_configs.config_base import RelationConfigBase | ||
from dbt.adapters.relation.models._relation import RelationComponent | ||
from dbt.dataclass_schema import StrEnum | ||
|
||
|
||
class RelationConfigChangeAction(StrEnum): | ||
class RelationChangeAction(StrEnum): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
alter = "alter" | ||
create = "create" | ||
drop = "drop" | ||
|
||
|
||
@dataclass(frozen=True, eq=True, unsafe_hash=True) | ||
class RelationConfigChange(RelationConfigBase, ABC): | ||
action: RelationConfigChangeAction | ||
class RelationChange(RelationComponent, ABC): | ||
action: RelationChangeAction | ||
context: Hashable # this is usually a RelationConfig, e.g. IndexConfig, but shouldn't be limited | ||
|
||
@property | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
from dataclasses import dataclass | ||
from typing import Union, Dict | ||
from typing import Any, Dict, Union | ||
|
||
import agate | ||
|
||
from dbt.utils import filter_null_values | ||
|
||
|
||
|
@@ -18,24 +19,24 @@ | |
]) | ||
} | ||
""" | ||
RelationResults = Dict[str, Union[agate.Row, agate.Table]] | ||
DescribeRelationResults = Dict[str, Union[agate.Row, agate.Table]] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the result of running a |
||
|
||
|
||
@dataclass(frozen=True) | ||
class RelationConfigBase: | ||
class RelationComponent: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The equivalent of |
||
@classmethod | ||
def from_dict(cls, kwargs_dict) -> "RelationConfigBase": | ||
def from_dict(cls, config_dict: Dict[str, Any]) -> "RelationComponent": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This varied between |
||
""" | ||
This assumes the subclass of `RelationConfigBase` is flat, in the sense that no attribute is | ||
itself another subclass of `RelationConfigBase`. If that's not the case, this should be overriden | ||
to manually manage that complexity. | ||
|
||
Args: | ||
kwargs_dict: the dict representation of this instance | ||
config_dict: the dict representation of this instance | ||
|
||
Returns: the `RelationConfigBase` representation associated with the provided dict | ||
""" | ||
return cls(**filter_null_values(kwargs_dict)) # type: ignore | ||
return cls(**filter_null_values(config_dict)) # type: ignore | ||
|
||
@classmethod | ||
def _not_implemented_error(cls) -> NotImplementedError: | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,16 @@ | ||
import agate | ||
from typing import Any, Optional, Tuple, Type, List | ||
from typing import Any, List, Optional, Tuple, Type | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Import order |
||
|
||
from dbt.contracts.connection import Connection, AdapterResponse | ||
from dbt.exceptions import RelationTypeNullError | ||
from dbt.adapters.base import BaseAdapter, available | ||
from dbt.adapters.base.relation import BaseRelation | ||
from dbt.adapters.cache import _make_ref_key_dict | ||
from dbt.adapters.sql import SQLConnectionManager | ||
from dbt.contracts.connection import AdapterResponse, Connection | ||
from dbt.events.functions import fire_event | ||
from dbt.events.types import ColTypeChange, SchemaCreation, SchemaDrop | ||
from dbt.exceptions import RelationTypeNullError | ||
|
||
|
||
from dbt.adapters.base.relation import BaseRelation | ||
|
||
LIST_RELATIONS_MACRO_NAME = "list_relations_without_caching" | ||
GET_COLUMNS_IN_RELATION_MACRO_NAME = "get_columns_in_relation" | ||
LIST_SCHEMAS_MACRO_NAME = "list_schemas" | ||
|
@@ -222,14 +221,14 @@ def check_schema_exists(self, database: str, schema: str) -> bool: | |
def validate_sql(self, sql: str) -> AdapterResponse: | ||
"""Submit the given SQL to the engine for validation, but not execution. | ||
|
||
By default we simply prefix the query with the explain keyword and allow the | ||
By default, we simply prefix the query with the explain keyword and allow the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Grammar |
||
exceptions thrown by the underlying engine on invalid SQL inputs to bubble up | ||
to the exception handler. For adjustments to the explain statement - such as | ||
for adapters that have different mechanisms for hinting at query validation | ||
or dry-run - callers may be able to override the validate_sql_query macro with | ||
the addition of an <adapter>__validate_sql implementation. | ||
|
||
:param sql str: The sql to validate | ||
:param sql: str The sql to validate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect docstring |
||
""" | ||
kwargs = { | ||
"sql": sql, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
|
||
|
||
@dataclass(frozen=True, eq=True, unsafe_hash=True) | ||
class RelationConfigValidationRule: | ||
class ValidationRule: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The validation framework does not contain anything that suggests it's specific to the relation framework. It would be more useful to make this available to other components instead of rebuild it within each component. |
||
validation_check: bool | ||
validation_error: Optional[DbtRuntimeError] | ||
|
||
|
@@ -18,12 +18,12 @@ def default_error(self): | |
|
||
|
||
@dataclass(frozen=True) | ||
class RelationConfigValidationMixin: | ||
class ValidationMixin: | ||
def __post_init__(self): | ||
self.run_validation_rules() | ||
|
||
@property | ||
def validation_rules(self) -> Set[RelationConfigValidationRule]: | ||
def validation_rules(self) -> Set[ValidationRule]: | ||
""" | ||
A set of validation rules to run against the object upon creation. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already throw
# type: ignore
ornoqa: F401
in all of our__init__.py
files. This makes it automatic.