mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-22 21:21:28 +00:00
Compare commits
3 Commits
enable-pos
...
qmalcolm--
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7c2e83253 | ||
|
|
6d89d103f0 | ||
|
|
d6aeb313f5 |
@@ -1,14 +1,17 @@
|
|||||||
import abc
|
import abc
|
||||||
|
from dataclasses import dataclass
|
||||||
from typing import Callable, ClassVar, Dict, List, Optional, Set
|
from typing import Callable, ClassVar, Dict, List, Optional, Set
|
||||||
|
|
||||||
import dbt.tracking
|
import dbt.tracking
|
||||||
from dbt.events import types as core_types
|
from dbt.events import types as core_types
|
||||||
from dbt_common.events.functions import warn_or_error
|
from dbt_common.events.base_types import EventLevel
|
||||||
|
from dbt_common.events.functions import fire_event, warn_or_error
|
||||||
|
|
||||||
|
|
||||||
class DBTDeprecation:
|
class DBTDeprecation:
|
||||||
_name: ClassVar[Optional[str]] = None
|
_name: ClassVar[Optional[str]] = None
|
||||||
_event: ClassVar[Optional[str]] = None
|
_event: ClassVar[Optional[str]] = None
|
||||||
|
_summary_event: ClassVar[Optional[str]] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
@@ -33,6 +36,21 @@ class DBTDeprecation:
|
|||||||
raise NameError(msg)
|
raise NameError(msg)
|
||||||
raise NotImplementedError("event not implemented for {}".format(self._event))
|
raise NotImplementedError("event not implemented for {}".format(self._event))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def summary_event(self) -> abc.ABCMeta:
|
||||||
|
if self._summary_event is not None:
|
||||||
|
module_path = core_types
|
||||||
|
class_name = self._summary_event
|
||||||
|
try:
|
||||||
|
return getattr(module_path, class_name)
|
||||||
|
except AttributeError:
|
||||||
|
msg = f"Event Class `{class_name}` is not defined in `{module_path}`"
|
||||||
|
raise NameError(msg)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(
|
||||||
|
"summary_event not implemented for {}".format(self._summary_event)
|
||||||
|
)
|
||||||
|
|
||||||
def show(self, *args, **kwargs) -> None:
|
def show(self, *args, **kwargs) -> None:
|
||||||
if self.name not in active_deprecations:
|
if self.name not in active_deprecations:
|
||||||
event = self.event(**kwargs)
|
event = self.event(**kwargs)
|
||||||
@@ -110,7 +128,8 @@ class PackageMaterializationOverrideDeprecation(DBTDeprecation):
|
|||||||
|
|
||||||
class ResourceNamesWithSpacesDeprecation(DBTDeprecation):
|
class ResourceNamesWithSpacesDeprecation(DBTDeprecation):
|
||||||
_name = "resource-names-with-spaces"
|
_name = "resource-names-with-spaces"
|
||||||
_event = "ResourceNamesWithSpacesDeprecation"
|
_event = "SpacesInResourceNameDeprecation"
|
||||||
|
_summary_event = "ResourceNamesWithSpacesDeprecation"
|
||||||
|
|
||||||
|
|
||||||
class SourceFreshnessProjectHooksNotRun(DBTDeprecation):
|
class SourceFreshnessProjectHooksNotRun(DBTDeprecation):
|
||||||
@@ -198,3 +217,41 @@ def reset_deprecations():
|
|||||||
def fire_buffered_deprecations():
|
def fire_buffered_deprecations():
|
||||||
[dep_fn() for dep_fn in buffered_deprecations]
|
[dep_fn() for dep_fn in buffered_deprecations]
|
||||||
buffered_deprecations.clear()
|
buffered_deprecations.clear()
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ManagedDeprecationWarning:
|
||||||
|
deprecation_warning: DBTDeprecation
|
||||||
|
occurances: int = 0
|
||||||
|
only_show_once: bool = True
|
||||||
|
|
||||||
|
def show(self, fire_as_error: bool = False, *args, **kwargs) -> None:
|
||||||
|
# We don't use the `show` built into the DBTDeprecation class,
|
||||||
|
# because we want to handle gating whether the warning should is
|
||||||
|
# fired or not, and we want to track the number of times the warning
|
||||||
|
# has been shown.
|
||||||
|
if not self.only_show_once or self.occurances == 0:
|
||||||
|
event = self.deprecation_warning.event(*args, **kwargs)
|
||||||
|
|
||||||
|
# This is for maintaining current functionality wherein certain deprecations
|
||||||
|
# allow for force firing as an error outside of warn_or_error.
|
||||||
|
if fire_as_error:
|
||||||
|
fire_event(event, level=EventLevel.ERROR)
|
||||||
|
else:
|
||||||
|
warn_or_error(event)
|
||||||
|
|
||||||
|
self.deprecation_warning.track_deprecation_warn()
|
||||||
|
|
||||||
|
self.occurances += 1
|
||||||
|
|
||||||
|
def show_summary(self) -> None:
|
||||||
|
event = self.deprecation_warning.summary_event(
|
||||||
|
occurances=self.occurances,
|
||||||
|
show_debug_hint=(self.only_show_once),
|
||||||
|
)
|
||||||
|
warn_or_error(event)
|
||||||
|
|
||||||
|
if dbt.tracking.active_user is not None:
|
||||||
|
dbt.tracking.track_deprecation_warn_summary(
|
||||||
|
{"deprecation_name": self.deprecation_warning.name, "occurances": self.occurances}
|
||||||
|
)
|
||||||
|
|||||||
@@ -417,9 +417,10 @@ message SpacesInResourceNameDeprecationMsg {
|
|||||||
|
|
||||||
// D015
|
// D015
|
||||||
message ResourceNamesWithSpacesDeprecation {
|
message ResourceNamesWithSpacesDeprecation {
|
||||||
int32 count_invalid_names = 1;
|
int32 count_invalid_names = 1; // Field no longer used, but kept for backwards compatibility
|
||||||
bool show_debug_hint = 2;
|
bool show_debug_hint = 2;
|
||||||
string level = 3;
|
string level = 3;
|
||||||
|
int32 occurances = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ResourceNamesWithSpacesDeprecationMsg {
|
message ResourceNamesWithSpacesDeprecationMsg {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -436,7 +436,9 @@ class ResourceNamesWithSpacesDeprecation(WarnLevel):
|
|||||||
return "D015"
|
return "D015"
|
||||||
|
|
||||||
def message(self) -> str:
|
def message(self) -> str:
|
||||||
description = f"Spaces found in {self.count_invalid_names} resource name(s). This is deprecated, and may lead to errors when using dbt."
|
# set the count_invalid_names field to the occurances field for
|
||||||
|
self.count_invalid_names = self.occurances
|
||||||
|
description = f"Spaces found in {self.occurances} resource name(s). This is deprecated, and may lead to errors when using dbt."
|
||||||
|
|
||||||
if self.show_debug_hint:
|
if self.show_debug_hint:
|
||||||
description += " Run again with `--debug` to see them all."
|
description += " Run again with `--debug` to see them all."
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ from dbt.contracts.graph.nodes import (
|
|||||||
SourceDefinition,
|
SourceDefinition,
|
||||||
)
|
)
|
||||||
from dbt.contracts.graph.semantic_manifest import SemanticManifest
|
from dbt.contracts.graph.semantic_manifest import SemanticManifest
|
||||||
|
from dbt.deprecations import (
|
||||||
|
ManagedDeprecationWarning,
|
||||||
|
ResourceNamesWithSpacesDeprecation,
|
||||||
|
)
|
||||||
from dbt.events.types import (
|
from dbt.events.types import (
|
||||||
ArtifactWritten,
|
ArtifactWritten,
|
||||||
DeprecatedModel,
|
DeprecatedModel,
|
||||||
@@ -78,7 +82,6 @@ from dbt.events.types import (
|
|||||||
PartialParsingErrorProcessingFile,
|
PartialParsingErrorProcessingFile,
|
||||||
PartialParsingNotEnabled,
|
PartialParsingNotEnabled,
|
||||||
PartialParsingSkipParsing,
|
PartialParsingSkipParsing,
|
||||||
SpacesInResourceNameDeprecation,
|
|
||||||
StateCheckVarsHash,
|
StateCheckVarsHash,
|
||||||
UnableToPartialParse,
|
UnableToPartialParse,
|
||||||
UpcomingReferenceDeprecation,
|
UpcomingReferenceDeprecation,
|
||||||
@@ -618,7 +621,7 @@ class ManifestLoader:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_for_spaces_in_resource_names(self):
|
def check_for_spaces_in_resource_names(self) -> None:
|
||||||
"""Validates that resource names do not contain spaces
|
"""Validates that resource names do not contain spaces
|
||||||
|
|
||||||
If `DEBUG` flag is `False`, logs only first bad model name
|
If `DEBUG` flag is `False`, logs only first bad model name
|
||||||
@@ -626,7 +629,6 @@ class ManifestLoader:
|
|||||||
If `REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES` is `True`, logs are `ERROR` level and an exception is raised if any names are bad
|
If `REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES` is `True`, logs are `ERROR` level and an exception is raised if any names are bad
|
||||||
If `REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES` is `False`, logs are `WARN` level
|
If `REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES` is `False`, logs are `WARN` level
|
||||||
"""
|
"""
|
||||||
improper_resource_names = 0
|
|
||||||
level = (
|
level = (
|
||||||
EventLevel.ERROR
|
EventLevel.ERROR
|
||||||
if self.root_project.args.REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES
|
if self.root_project.args.REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES
|
||||||
@@ -634,26 +636,22 @@ class ManifestLoader:
|
|||||||
)
|
)
|
||||||
|
|
||||||
flags = get_flags()
|
flags = get_flags()
|
||||||
|
deprecation_manager = ManagedDeprecationWarning(
|
||||||
|
deprecation_warning=ResourceNamesWithSpacesDeprecation(),
|
||||||
|
only_show_once=(not flags.DEBUG),
|
||||||
|
)
|
||||||
|
|
||||||
for node in self.manifest.nodes.values():
|
for node in self.manifest.nodes.values():
|
||||||
if " " in node.name:
|
if " " in node.name:
|
||||||
if improper_resource_names == 0 or flags.DEBUG:
|
deprecation_manager.show(
|
||||||
fire_event(
|
fire_as_error=(level == EventLevel.ERROR),
|
||||||
SpacesInResourceNameDeprecation(
|
unique_id=node.unique_id,
|
||||||
unique_id=node.unique_id,
|
level=level.value,
|
||||||
level=level.value,
|
|
||||||
),
|
|
||||||
level=level,
|
|
||||||
)
|
|
||||||
improper_resource_names += 1
|
|
||||||
|
|
||||||
if improper_resource_names > 0:
|
|
||||||
if level == EventLevel.WARN:
|
|
||||||
dbt.deprecations.warn(
|
|
||||||
"resource-names-with-spaces",
|
|
||||||
count_invalid_names=improper_resource_names,
|
|
||||||
show_debug_hint=(not flags.DEBUG),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if deprecation_manager.occurances > 0:
|
||||||
|
if level == EventLevel.WARN:
|
||||||
|
deprecation_manager.show_summary()
|
||||||
else: # ERROR level
|
else: # ERROR level
|
||||||
raise DbtValidationError("Resource names cannot contain spaces")
|
raise DbtValidationError("Resource names cannot contain spaces")
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ DBT_INVOCATION_ENV = "DBT_INVOCATION_ENV"
|
|||||||
|
|
||||||
ADAPTER_INFO_SPEC = "iglu:com.dbt/adapter_info/jsonschema/1-0-1"
|
ADAPTER_INFO_SPEC = "iglu:com.dbt/adapter_info/jsonschema/1-0-1"
|
||||||
DEPRECATION_WARN_SPEC = "iglu:com.dbt/deprecation_warn/jsonschema/1-0-0"
|
DEPRECATION_WARN_SPEC = "iglu:com.dbt/deprecation_warn/jsonschema/1-0-0"
|
||||||
|
DEPRECATION_WARN_SUMMARY_SPEC = "iglu:com.dbt/deprecation_warn_summary/jsonschema/1-0-0"
|
||||||
BEHAVIOR_CHANGE_WARN_SPEC = "iglu:com.dbt/behavior_change_warn/jsonschema/1-0-0"
|
BEHAVIOR_CHANGE_WARN_SPEC = "iglu:com.dbt/behavior_change_warn/jsonschema/1-0-0"
|
||||||
EXPERIMENTAL_PARSER = "iglu:com.dbt/experimental_parser/jsonschema/1-0-0"
|
EXPERIMENTAL_PARSER = "iglu:com.dbt/experimental_parser/jsonschema/1-0-0"
|
||||||
INVOCATION_ENV_SPEC = "iglu:com.dbt/invocation_env/jsonschema/1-0-0"
|
INVOCATION_ENV_SPEC = "iglu:com.dbt/invocation_env/jsonschema/1-0-0"
|
||||||
@@ -368,6 +369,24 @@ def track_deprecation_warn(options):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def track_deprecation_warn_summary(options):
|
||||||
|
|
||||||
|
assert (
|
||||||
|
active_user is not None
|
||||||
|
), "Cannot track deprecation warnings summary when active user is None"
|
||||||
|
|
||||||
|
context = [SelfDescribingJson(DEPRECATION_WARN_SUMMARY_SPEC, options)]
|
||||||
|
|
||||||
|
track(
|
||||||
|
active_user,
|
||||||
|
category="dbt",
|
||||||
|
action="deprecation_summary",
|
||||||
|
label=get_invocation_id(),
|
||||||
|
property_="warn",
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def track_behavior_change_warn(msg: EventMsg) -> None:
|
def track_behavior_change_warn(msg: EventMsg) -> None:
|
||||||
if msg.info.name != "BehaviorChangeEvent" or active_user is None:
|
if msg.info.name != "BehaviorChangeEvent" or active_user is None:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -149,9 +149,7 @@ sample_values = [
|
|||||||
core_types.TestsConfigDeprecation(deprecated_path="", exp_path=""),
|
core_types.TestsConfigDeprecation(deprecated_path="", exp_path=""),
|
||||||
core_types.ProjectFlagsMovedDeprecation(),
|
core_types.ProjectFlagsMovedDeprecation(),
|
||||||
core_types.SpacesInResourceNameDeprecation(unique_id="", level=""),
|
core_types.SpacesInResourceNameDeprecation(unique_id="", level=""),
|
||||||
core_types.ResourceNamesWithSpacesDeprecation(
|
core_types.ResourceNamesWithSpacesDeprecation(occurances=1, show_debug_hint=True, level=""),
|
||||||
count_invalid_names=1, show_debug_hint=True, level=""
|
|
||||||
),
|
|
||||||
core_types.PackageMaterializationOverrideDeprecation(
|
core_types.PackageMaterializationOverrideDeprecation(
|
||||||
package_name="my_package", materialization_name="view"
|
package_name="my_package", materialization_name="view"
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user