mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-19 20:11:28 +00:00
Compare commits
3 Commits
enable-pos
...
qmalcolm--
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7c2e83253 | ||
|
|
6d89d103f0 | ||
|
|
d6aeb313f5 |
@@ -1,14 +1,17 @@
|
||||
import abc
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, ClassVar, Dict, List, Optional, Set
|
||||
|
||||
import dbt.tracking
|
||||
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:
|
||||
_name: ClassVar[Optional[str]] = None
|
||||
_event: ClassVar[Optional[str]] = None
|
||||
_summary_event: ClassVar[Optional[str]] = None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
@@ -33,6 +36,21 @@ class DBTDeprecation:
|
||||
raise NameError(msg)
|
||||
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:
|
||||
if self.name not in active_deprecations:
|
||||
event = self.event(**kwargs)
|
||||
@@ -110,7 +128,8 @@ class PackageMaterializationOverrideDeprecation(DBTDeprecation):
|
||||
|
||||
class ResourceNamesWithSpacesDeprecation(DBTDeprecation):
|
||||
_name = "resource-names-with-spaces"
|
||||
_event = "ResourceNamesWithSpacesDeprecation"
|
||||
_event = "SpacesInResourceNameDeprecation"
|
||||
_summary_event = "ResourceNamesWithSpacesDeprecation"
|
||||
|
||||
|
||||
class SourceFreshnessProjectHooksNotRun(DBTDeprecation):
|
||||
@@ -198,3 +217,41 @@ def reset_deprecations():
|
||||
def fire_buffered_deprecations():
|
||||
[dep_fn() for dep_fn in buffered_deprecations]
|
||||
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
|
||||
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;
|
||||
string level = 3;
|
||||
int32 occurances = 4;
|
||||
}
|
||||
|
||||
message ResourceNamesWithSpacesDeprecationMsg {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -436,7 +436,9 @@ class ResourceNamesWithSpacesDeprecation(WarnLevel):
|
||||
return "D015"
|
||||
|
||||
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:
|
||||
description += " Run again with `--debug` to see them all."
|
||||
|
||||
@@ -64,6 +64,10 @@ from dbt.contracts.graph.nodes import (
|
||||
SourceDefinition,
|
||||
)
|
||||
from dbt.contracts.graph.semantic_manifest import SemanticManifest
|
||||
from dbt.deprecations import (
|
||||
ManagedDeprecationWarning,
|
||||
ResourceNamesWithSpacesDeprecation,
|
||||
)
|
||||
from dbt.events.types import (
|
||||
ArtifactWritten,
|
||||
DeprecatedModel,
|
||||
@@ -78,7 +82,6 @@ from dbt.events.types import (
|
||||
PartialParsingErrorProcessingFile,
|
||||
PartialParsingNotEnabled,
|
||||
PartialParsingSkipParsing,
|
||||
SpacesInResourceNameDeprecation,
|
||||
StateCheckVarsHash,
|
||||
UnableToPartialParse,
|
||||
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
|
||||
|
||||
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 `False`, logs are `WARN` level
|
||||
"""
|
||||
improper_resource_names = 0
|
||||
level = (
|
||||
EventLevel.ERROR
|
||||
if self.root_project.args.REQUIRE_RESOURCE_NAMES_WITHOUT_SPACES
|
||||
@@ -634,26 +636,22 @@ class ManifestLoader:
|
||||
)
|
||||
|
||||
flags = get_flags()
|
||||
deprecation_manager = ManagedDeprecationWarning(
|
||||
deprecation_warning=ResourceNamesWithSpacesDeprecation(),
|
||||
only_show_once=(not flags.DEBUG),
|
||||
)
|
||||
|
||||
for node in self.manifest.nodes.values():
|
||||
if " " in node.name:
|
||||
if improper_resource_names == 0 or flags.DEBUG:
|
||||
fire_event(
|
||||
SpacesInResourceNameDeprecation(
|
||||
unique_id=node.unique_id,
|
||||
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),
|
||||
deprecation_manager.show(
|
||||
fire_as_error=(level == EventLevel.ERROR),
|
||||
unique_id=node.unique_id,
|
||||
level=level.value,
|
||||
)
|
||||
|
||||
if deprecation_manager.occurances > 0:
|
||||
if level == EventLevel.WARN:
|
||||
deprecation_manager.show_summary()
|
||||
else: # ERROR level
|
||||
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"
|
||||
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"
|
||||
EXPERIMENTAL_PARSER = "iglu:com.dbt/experimental_parser/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:
|
||||
if msg.info.name != "BehaviorChangeEvent" or active_user is None:
|
||||
return
|
||||
|
||||
@@ -149,9 +149,7 @@ sample_values = [
|
||||
core_types.TestsConfigDeprecation(deprecated_path="", exp_path=""),
|
||||
core_types.ProjectFlagsMovedDeprecation(),
|
||||
core_types.SpacesInResourceNameDeprecation(unique_id="", level=""),
|
||||
core_types.ResourceNamesWithSpacesDeprecation(
|
||||
count_invalid_names=1, show_debug_hint=True, level=""
|
||||
),
|
||||
core_types.ResourceNamesWithSpacesDeprecation(occurances=1, show_debug_hint=True, level=""),
|
||||
core_types.PackageMaterializationOverrideDeprecation(
|
||||
package_name="my_package", materialization_name="view"
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user