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

Update behavior deprecation flags to be behavior change flags #193

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading