mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
feat: Add env var to suppress experimental warnings
Checked with local wheel and worked as intended. The harness shows suppression works: 0 warnings for all true-like values. This CL adds ADK_DISABLE_EXPERIMENTAL_WARNING to let the users to suppress warning messages from features decorated with @experimental. Previously, using experimental features would always trigger a UserWarning. This change creates a way to disable these warnings, which can be good to stop flooding logs. The warning is suppressed if ADK_DISABLE_EXPERIMENTAL_WARNING is set to a truthy value such as "true", "1", "yes", or "on" (case-insensitive). Added unit tests to make sure: Warning suppression for functions and classes when the env var is set. Case-insensitivity and various truthy values for the env var. Loading the env var from a .env file. PiperOrigin-RevId: 796649404
This commit is contained in:
committed by
Copybara-Service
parent
f8fd6a4f09
commit
4afc9b2f33
@@ -26,6 +26,13 @@ import warnings
|
|||||||
T = TypeVar("T", bound=Union[Callable, type])
|
T = TypeVar("T", bound=Union[Callable, type])
|
||||||
|
|
||||||
|
|
||||||
|
def _is_truthy_env(var_name: str) -> bool:
|
||||||
|
value = os.environ.get(var_name)
|
||||||
|
if value is None:
|
||||||
|
return False
|
||||||
|
return value.strip().lower() in ("1", "true", "yes", "on")
|
||||||
|
|
||||||
|
|
||||||
def _make_feature_decorator(
|
def _make_feature_decorator(
|
||||||
*,
|
*,
|
||||||
label: str,
|
label: str,
|
||||||
@@ -66,9 +73,8 @@ def _create_decorator(
|
|||||||
@functools.wraps(orig_init)
|
@functools.wraps(orig_init)
|
||||||
def new_init(self, *args, **kwargs):
|
def new_init(self, *args, **kwargs):
|
||||||
# Check if usage should be bypassed via environment variable at call time
|
# Check if usage should be bypassed via environment variable at call time
|
||||||
should_bypass = (
|
should_bypass = bypass_env_var is not None and _is_truthy_env(
|
||||||
bypass_env_var is not None
|
bypass_env_var
|
||||||
and os.environ.get(bypass_env_var, "").lower() == "true"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if should_bypass:
|
if should_bypass:
|
||||||
@@ -88,9 +94,8 @@ def _create_decorator(
|
|||||||
@functools.wraps(obj)
|
@functools.wraps(obj)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
# Check if usage should be bypassed via environment variable at call time
|
# Check if usage should be bypassed via environment variable at call time
|
||||||
should_bypass = (
|
should_bypass = bypass_env_var is not None and _is_truthy_env(
|
||||||
bypass_env_var is not None
|
bypass_env_var
|
||||||
and os.environ.get(bypass_env_var, "").lower() == "true"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if should_bypass:
|
if should_bypass:
|
||||||
@@ -143,6 +148,7 @@ experimental = _make_feature_decorator(
|
|||||||
" versions without notice. It may introduce breaking changes at any"
|
" versions without notice. It may introduce breaking changes at any"
|
||||||
" time."
|
" time."
|
||||||
),
|
),
|
||||||
|
bypass_env_var="ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS",
|
||||||
)
|
)
|
||||||
"""Mark a class or a function as an experimental feature.
|
"""Mark a class or a function as an experimental feature.
|
||||||
|
|
||||||
|
|||||||
@@ -206,8 +206,12 @@ def test_working_in_progress_loads_from_dotenv_file():
|
|||||||
del os.environ["ADK_ALLOW_WIP_FEATURES"]
|
del os.environ["ADK_ALLOW_WIP_FEATURES"]
|
||||||
|
|
||||||
|
|
||||||
def test_experimental_function_warns():
|
def test_experimental_function_warns(monkeypatch):
|
||||||
"""Test that experimental function shows warnings (unchanged behavior)."""
|
"""Test that experimental function shows warnings (unchanged behavior)."""
|
||||||
|
# Ensure environment variable is not set
|
||||||
|
monkeypatch.delenv(
|
||||||
|
"ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS", raising=False
|
||||||
|
)
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
warnings.simplefilter("always")
|
warnings.simplefilter("always")
|
||||||
|
|
||||||
@@ -220,8 +224,12 @@ def test_experimental_function_warns():
|
|||||||
assert "breaking change in the future" in str(w[0].message)
|
assert "breaking change in the future" in str(w[0].message)
|
||||||
|
|
||||||
|
|
||||||
def test_experimental_class_warns():
|
def test_experimental_class_warns(monkeypatch):
|
||||||
"""Test that experimental class shows warnings (unchanged behavior)."""
|
"""Test that experimental class shows warnings (unchanged behavior)."""
|
||||||
|
# Ensure environment variable is not set
|
||||||
|
monkeypatch.delenv(
|
||||||
|
"ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS", raising=False
|
||||||
|
)
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
warnings.simplefilter("always")
|
warnings.simplefilter("always")
|
||||||
|
|
||||||
@@ -235,6 +243,55 @@ def test_experimental_class_warns():
|
|||||||
assert "class may change" in str(w[0].message)
|
assert "class may change" in str(w[0].message)
|
||||||
|
|
||||||
|
|
||||||
|
def test_experimental_function_bypassed_with_env_var(monkeypatch):
|
||||||
|
"""Experimental function emits no warning when bypass env var is true."""
|
||||||
|
true_values = ["true", "True", "TRUE", "1", "yes", "YES", "on", "ON"]
|
||||||
|
for true_val in true_values:
|
||||||
|
monkeypatch.setenv("ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS", true_val)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter("always")
|
||||||
|
result = experimental_fn()
|
||||||
|
assert result == "executing"
|
||||||
|
assert len(w) == 0, f"Bypass failed for env value {true_val}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_experimental_class_bypassed_with_env_var(monkeypatch):
|
||||||
|
"""Experimental class emits no warning when bypass env var is true."""
|
||||||
|
true_values = ["true", "True", "TRUE", "1", "yes", "YES", "on", "ON"]
|
||||||
|
for true_val in true_values:
|
||||||
|
monkeypatch.setenv("ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS", true_val)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter("always")
|
||||||
|
exp_class = ExperimentalClass()
|
||||||
|
result = exp_class.run()
|
||||||
|
assert result == "running experimental"
|
||||||
|
assert len(w) == 0, f"Bypass failed for env value {true_val}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_experimental_function_not_bypassed_for_false_env_var(monkeypatch):
|
||||||
|
"""Experimental function still warns for non-true bypass env var values."""
|
||||||
|
false_values = ["false", "False", "FALSE", "0", "", "no", "off"]
|
||||||
|
for false_val in false_values:
|
||||||
|
monkeypatch.setenv("ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS", false_val)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter("always")
|
||||||
|
experimental_fn()
|
||||||
|
assert len(w) == 1
|
||||||
|
assert "[EXPERIMENTAL] experimental_fn:" in str(w[0].message)
|
||||||
|
|
||||||
|
|
||||||
|
def test_experimental_class_not_bypassed_for_false_env_var(monkeypatch):
|
||||||
|
"""Experimental class still warns for non-true bypass env var values."""
|
||||||
|
false_values = ["false", "False", "FALSE", "0", "", "no", "off"]
|
||||||
|
for false_val in false_values:
|
||||||
|
monkeypatch.setenv("ADK_SUPPRESS_EXPERIMENTAL_FEATURE_WARNINGS", false_val)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter("always")
|
||||||
|
ExperimentalClass()
|
||||||
|
assert len(w) == 1
|
||||||
|
assert "[EXPERIMENTAL] ExperimentalClass:" in str(w[0].message)
|
||||||
|
|
||||||
|
|
||||||
def test_experimental_class_no_parens_warns():
|
def test_experimental_class_no_parens_warns():
|
||||||
"""Test that experimental class without parentheses shows default warning."""
|
"""Test that experimental class without parentheses shows default warning."""
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
|||||||
Reference in New Issue
Block a user