Skip to content

Commit

Permalink
Update behavior deprecation flags to be behavior change flags (#193)
Browse files Browse the repository at this point in the history
* update behavior deprecation flags to be behavior change flags

* update behavior deprecation flags to be behavior change flags

* update the default message for the behavior change event

* move defaults into the behavior flag to work with the eventing system

* move defaults into the behavior flag to work with the eventing system

* remove extra period
  • Loading branch information
mikealfare authored Sep 18, 2024
1 parent 9798ca7 commit e5dff92
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 118 deletions.
52 changes: 33 additions & 19 deletions dbt_common/behavior_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from typing import Optional as NotRequired

from dbt_common.events.functions import fire_event
from dbt_common.events.types import BehaviorDeprecationEvent
from dbt_common.exceptions import CompilationError
from dbt_common.events.types import BehaviorChangeEvent
from dbt_common.exceptions import CompilationError, DbtInternalError


class BehaviorFlag(TypedDict):
Expand All @@ -20,16 +20,20 @@ class BehaviorFlag(TypedDict):
Args:
name: the name of the behavior flag
default: default setting, starts as False, becomes True after a bake-in period
deprecation_version: the version when the default will change to True
deprecation_message: an additional message to send when the flag evaluates to False
description: an additional message to send when the flag evaluates to False
docs_url: the url to the relevant docs on docs.getdbt.com
*Note*:
While `description` and `docs_url` are both listed as `NotRequired`, at least one of them is required.
This is validated when the flag is rendered in `BehaviorFlagRendered` below.
The goal of this restriction is to provide the end user with context so they can make an informed decision
about if, and when, to enable the behavior flag.
"""

name: str
default: bool
source: NotRequired[str]
deprecation_version: NotRequired[str]
deprecation_message: NotRequired[str]
description: NotRequired[str]
docs_url: NotRequired[str]


Expand All @@ -43,14 +47,33 @@ class BehaviorFlagRendered:
"""

def __init__(self, flag: BehaviorFlag, user_overrides: Dict[str, Any]) -> None:
self._validate(flag)

self.name = flag["name"]
self.setting = user_overrides.get(flag["name"], flag["default"])
self.deprecation_event = self._deprecation_event(flag)

default_description = (
f"""The behavior controlled by `{flag["name"]}` is currently turned off.\n"""
)
default_docs_url = "https://docs.getdbt.com/reference/global-configs/behavior-changes"
self._behavior_change_event = BehaviorChangeEvent(
flag_name=flag["name"],
flag_source=flag.get("source", self._default_source()),
description=flag.get("description", default_description),
docs_url=flag.get("docs_url", default_docs_url),
)

@staticmethod
def _validate(flag: BehaviorFlag) -> None:
if flag.get("description") is None and flag.get("docs_url") is None:
raise DbtInternalError(
"Behavior change flags require at least one of `description` and `docs_url`."
)

@property
def setting(self) -> bool:
if self._setting is False:
fire_event(self.deprecation_event)
fire_event(self._behavior_change_event)
return self._setting

@setting.setter
Expand All @@ -61,15 +84,6 @@ def setting(self, value: bool) -> None:
def no_warn(self) -> bool:
return self._setting

def _deprecation_event(self, flag: BehaviorFlag) -> BehaviorDeprecationEvent:
return BehaviorDeprecationEvent(
flag_name=flag["name"],
flag_source=flag.get("source", self._default_source()),
deprecation_version=flag.get("deprecation_version"),
deprecation_message=flag.get("deprecation_message"),
docs_url=flag.get("docs_url"),
)

@staticmethod
def _default_source() -> str:
"""
Expand All @@ -95,15 +109,15 @@ class Behavior:
if adapter.behavior.my_flag:
...
if adapter.behavior.my_flag.no_warn: # this will not fire the deprecation event
if adapter.behavior.my_flag.no_warn: # this will not fire the behavior change event
...
```
```jinja
{% if adapter.behavior.my_flag %}
...
{% endif %}
{% if adapter.behavior.my_flag.no_warn %} {# this will not fire the deprecation event #}
{% if adapter.behavior.my_flag.no_warn %} {# this will not fire the behavior change event #}
...
{% endif %}
```
Expand Down
11 changes: 5 additions & 6 deletions dbt_common/events/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,16 @@ message GenericMessage {
// D - Deprecations

// D018
message BehaviorDeprecationEvent {
message BehaviorChangeEvent {
string flag_name = 1;
string flag_source = 2;
string deprecation_version = 3;
string deprecation_message = 4;
string docs_url = 5;
string description = 3;
string docs_url = 4;
}

message BehaviorDeprecationEventMsg {
message BehaviorChangeEventMsg {
EventInfo info = 1;
BehaviorDeprecationEvent data = 2;
BehaviorChangeEvent data = 2;
}

// M - Deps generation
Expand Down
31 changes: 6 additions & 25 deletions dbt_common/events/types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Optional

from dbt_common.events.base_types import (
DebugLevel,
InfoLevel,
Expand Down Expand Up @@ -38,33 +36,16 @@
# =======================================================


class BehaviorDeprecationEvent(WarnLevel):
flag_name: str
flag_source: str
deprecation_version: Optional[str]
deprecation_message: Optional[str]
docs_url: Optional[str]

class BehaviorChangeEvent(WarnLevel):
def code(self) -> str:
return "D018"

def message(self) -> str:
msg = f"The legacy behavior controlled by `{self.flag_name}` is deprecated.\n"

if self.deprecation_version:
msg = (
f"The legacy behavior is expected to be retired in `{self.deprecation_version}`.\n"
)

msg += f"The new behavior can be turned on by setting `flags.{self.flag_name}` to `True` in `dbt_project.yml`.\n"

if self.deprecation_message:
msg += f"{self.deprecation_message}.\n"

docs_url = self.docs_url or f"https://docs.getdbt.com/search?q={self.flag_name}"
msg += f"Visit {docs_url} for more information."

return warning_tag(msg)
return warning_tag(
f"{self.description}\n"
f"You may opt into the new behavior sooner by setting `flags.{self.flag_name}` to `True` in `dbt_project.yml`.\n"
f"Visit {self.docs_url} for more information."
)


# =======================================================
Expand Down
90 changes: 45 additions & 45 deletions dbt_common/events/types_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e5dff92

Please sign in to comment.