diff --git a/.changes/unreleased/Fixes-20240920-165607.yaml b/.changes/unreleased/Fixes-20240920-165607.yaml new file mode 100644 index 0000000..04e40c2 --- /dev/null +++ b/.changes/unreleased/Fixes-20240920-165607.yaml @@ -0,0 +1,7 @@ +kind: Fixes +body: Restrict behavior change warning to firing once per run to avoid noisy warnings + in logs +time: 2024-09-20T16:56:07.951544-04:00 +custom: + Author: mikealfare + Issue: "197" diff --git a/dbt_common/__about__.py b/dbt_common/__about__.py index 7aba640..bd1378f 100644 --- a/dbt_common/__about__.py +++ b/dbt_common/__about__.py @@ -1 +1 @@ -version = "1.9.0" +version = "1.10.0" diff --git a/dbt_common/behavior_flags.py b/dbt_common/behavior_flags.py index a2eb097..d4af386 100644 --- a/dbt_common/behavior_flags.py +++ b/dbt_common/behavior_flags.py @@ -46,6 +46,8 @@ class BehaviorFlagRendered: user_overrides: a set of user settings, one of which may be an override on this behavior flag """ + fired: bool = False + def __init__(self, flag: BehaviorFlag, user_overrides: Dict[str, Any]) -> None: self._validate(flag) @@ -72,8 +74,9 @@ def _validate(flag: BehaviorFlag) -> None: @property def setting(self) -> bool: - if self._setting is False: + if self._setting is False and not self.fired: fire_event(self._behavior_change_event) + self.fired = True return self._setting @setting.setter diff --git a/dbt_common/exceptions/base.py b/dbt_common/exceptions/base.py index 22cbb68..fdabd86 100644 --- a/dbt_common/exceptions/base.py +++ b/dbt_common/exceptions/base.py @@ -240,7 +240,7 @@ def process_stack(self) -> List[str]: lines = [] if hasattr(self.node, "build_path") and self.node.build_path: - lines.append(f"compiled Code at {self.node.build_path}") + lines.append(f"compiled code at {self.node.build_path}") return lines + DbtRuntimeError.process_stack(self) diff --git a/tests/unit/test_behavior_flags.py b/tests/unit/test_behavior_flags.py index 3c0ccce..5bf7db0 100644 --- a/tests/unit/test_behavior_flags.py +++ b/tests/unit/test_behavior_flags.py @@ -171,3 +171,35 @@ def test_behavior_flags_no_behavior_change_event_on_no_warn(event_catcher: Event def test_behavior_flag_requires_description_or_docs_url(event_catcher: EventCatcher) -> None: with pytest.raises(DbtInternalError): Behavior([{"name": "flag_false", "default": False}], {}) + + +def test_behavior_flags_fire_once_per_flag(event_catcher: EventCatcher) -> None: + behavior = Behavior( + [ + {"name": "flag_1", "default": False, "description": "This is flag 1."}, + {"name": "flag_2", "default": False, "description": "This is flag 2."}, + ], + {}, + ) + + assert len(event_catcher.caught_events) == 0 + + # trigger the evaluation for flag_1, an event should fire + if behavior.flag_1: + pass + assert len(event_catcher.caught_events) == 1 + + # trigger the evaluation for flag_1 again, no event should fire + if behavior.flag_1: + pass + assert len(event_catcher.caught_events) == 1 + + # trigger the evaluation for flag_2, an event should fire + if behavior.flag_2: + pass + assert len(event_catcher.caught_events) == 2 + + # trigger the evaluation for flag_1 again, no event should fire + if behavior.flag_1: + pass + assert len(event_catcher.caught_events) == 2