diff --git a/src/google/adk/utils/feature_decorator.py b/src/google/adk/utils/feature_decorator.py index eb4987249..ce4c3621d 100644 --- a/src/google/adk/utils/feature_decorator.py +++ b/src/google/adk/utils/feature_decorator.py @@ -70,10 +70,18 @@ def new_init(self, *args, **kwargs): bypass_env_var is not None and os.environ.get(bypass_env_var, "").lower() == "true" ) + # Suppress experimental warnings if env is set + suppress_experimental = ( + label.upper() == "EXPERIMENTAL" + and os.environ.get("ADK_DISABLE_EXPERIMENTAL_WARNING", "").lower() + in ("1", "true", "yes", "on") + ) if should_bypass: # Bypass completely - no warning, no error pass + elif suppress_experimental: + pass elif block_usage: raise RuntimeError(msg) else: @@ -92,10 +100,18 @@ def wrapper(*args, **kwargs): bypass_env_var is not None and os.environ.get(bypass_env_var, "").lower() == "true" ) + # Suppress experimental warnings if env is set + suppress_experimental = ( + label.upper() == "EXPERIMENTAL" + and os.environ.get("ADK_DISABLE_EXPERIMENTAL_WARNING", "").lower() + in ("1", "true", "yes", "on") + ) if should_bypass: # Bypass completely - no warning, no error pass + elif suppress_experimental: + pass elif block_usage: raise RuntimeError(msg) else: diff --git a/tests/unittests/utils/test_feature_decorator.py b/tests/unittests/utils/test_feature_decorator.py index e2f16446a..dc1050503 100644 --- a/tests/unittests/utils/test_feature_decorator.py +++ b/tests/unittests/utils/test_feature_decorator.py @@ -208,6 +208,9 @@ def test_working_in_progress_loads_from_dotenv_file(): def test_experimental_function_warns(): """Test that experimental function shows warnings (unchanged behavior).""" + # Ensure environment variable is not set + if "ADK_DISABLE_EXPERIMENTAL_WARNING" in os.environ: + del os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") @@ -222,6 +225,9 @@ def test_experimental_function_warns(): def test_experimental_class_warns(): """Test that experimental class shows warnings (unchanged behavior).""" + # Ensure environment variable is not set + if "ADK_DISABLE_EXPERIMENTAL_WARNING" in os.environ: + del os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") @@ -235,6 +241,67 @@ def test_experimental_class_warns(): assert "class may change" in str(w[0].message) +def test_experimental_function_warning_suppressed_with_env_var(): + """Test that experimental function warnings are suppressed when env var is set.""" + true_values = ["true", "True", "TRUE", "1", "yes", "YES", "on", "ON"] + for true_val in true_values: + os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] = true_val + try: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + result = experimental_fn() + assert result == "executing" + assert len(w) == 0, f"Warning not suppressed for env value {true_val}" + finally: + del os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] + + +def test_experimental_class_warning_suppressed_with_env_var(): + """Test that experimental class warnings are suppressed when env var is set.""" + true_values = ["true", "True", "TRUE", "1", "yes", "YES", "on", "ON"] + for true_val in true_values: + os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] = true_val + try: + 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"Warning not suppressed for env value {true_val}" + finally: + del os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] + + +def test_experimental_function_warning_not_suppressed_for_false_env_var(): + """Test that experimental function warnings are not suppressed for false-like env var values.""" + false_values = ["false", "False", "FALSE", "0", "", "no", "off"] + for false_val in false_values: + os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] = false_val + try: + 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) + finally: + del os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] + + +def test_experimental_class_warning_not_suppressed_for_false_env_var(): + """Test that experimental class warnings are not suppressed for false-like env var values.""" + false_values = ["false", "False", "FALSE", "0", "", "no", "off"] + for false_val in false_values: + os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] = false_val + try: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + ExperimentalClass() + assert len(w) == 1 + assert "[EXPERIMENTAL] ExperimentalClass:" in str(w[0].message) + finally: + del os.environ["ADK_DISABLE_EXPERIMENTAL_WARNING"] + + def test_experimental_class_no_parens_warns(): """Test that experimental class without parentheses shows default warning.""" with warnings.catch_warnings(record=True) as w: