This is an automated email from the ASF dual-hosted git repository.

shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 8a4984e30d7 Mark Snowflake connection form `Proxy Port` field optional 
(#65444)
8a4984e30d7 is described below

commit 8a4984e30d71ea2fee099def7ed62749f58cfacc
Author: Nikhil Gupta <[email protected]>
AuthorDate: Wed Apr 22 20:40:43 2026 +0530

    Mark Snowflake connection form `Proxy Port` field optional (#65444)
---
 .../airflow/providers/snowflake/hooks/snowflake.py |  7 ++++-
 .../tests/unit/snowflake/hooks/test_snowflake.py   | 34 ++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git 
a/providers/snowflake/src/airflow/providers/snowflake/hooks/snowflake.py 
b/providers/snowflake/src/airflow/providers/snowflake/hooks/snowflake.py
index c69f2435581..1f9d1b0c5b9 100644
--- a/providers/snowflake/src/airflow/providers/snowflake/hooks/snowflake.py
+++ b/providers/snowflake/src/airflow/providers/snowflake/hooks/snowflake.py
@@ -138,6 +138,7 @@ class SnowflakeHook(DbApiHook):
         )
         from flask_babel import lazy_gettext
         from wtforms import BooleanField, IntegerField, PasswordField, 
StringField
+        from wtforms.validators import Optional
 
         return {
             "account": StringField(lazy_gettext("Account"), 
widget=BS3TextFieldWidget()),
@@ -153,7 +154,11 @@ class SnowflakeHook(DbApiHook):
                 label=lazy_gettext("Insecure mode"), description="Turns off 
OCSP certificate checks"
             ),
             "proxy_host": StringField(lazy_gettext("Proxy Host"), 
widget=BS3TextFieldWidget()),
-            "proxy_port": IntegerField(lazy_gettext("Proxy Port")),
+            "proxy_port": IntegerField(
+                lazy_gettext("Proxy Port"),
+                widget=BS3TextFieldWidget(),
+                validators=[Optional()],
+            ),
             "proxy_user": StringField(lazy_gettext("Proxy User"), 
widget=BS3TextFieldWidget()),
             "proxy_password": PasswordField(lazy_gettext("Proxy Password"), 
widget=BS3PasswordFieldWidget()),
         }
diff --git a/providers/snowflake/tests/unit/snowflake/hooks/test_snowflake.py 
b/providers/snowflake/tests/unit/snowflake/hooks/test_snowflake.py
index 5e59a282b37..111a79d7021 100644
--- a/providers/snowflake/tests/unit/snowflake/hooks/test_snowflake.py
+++ b/providers/snowflake/tests/unit/snowflake/hooks/test_snowflake.py
@@ -1787,3 +1787,37 @@ class TestPytestSnowflakeHook:
             # Check that the URI doesn't contain proxy params
             called_uri = mock_create_engine.call_args[0][0]
             assert "proxy_host" not in str(called_uri)
+
+    def test_get_connection_form_widgets_proxy_port_is_optional(self):
+        """Proxy Port is an IntegerField and must remain optional.
+
+        Regression test for the Snowflake connection form silently rejecting
+        save when `Proxy Port` is left blank. `IntegerField` fails WTForms
+        validation on empty input by default, so `Optional()` is required to
+        preserve the documented optional semantics.
+        """
+        pytest.importorskip("flask_appbuilder")
+        pytest.importorskip("flask_babel")
+        Form = pytest.importorskip("wtforms").Form
+        Optional = pytest.importorskip("wtforms.validators").Optional
+        MultiDict = pytest.importorskip("werkzeug.datastructures").MultiDict
+
+        widgets = SnowflakeHook.get_connection_form_widgets()
+        assert "proxy_port" in widgets
+
+        proxy_port_field = widgets["proxy_port"]
+        assert any(isinstance(v, Optional) for v in 
proxy_port_field.kwargs.get("validators", []))
+
+        form_cls = type("_SnowflakeConnForm", (Form,), dict(widgets))
+
+        empty_form = form_cls(MultiDict([("proxy_port", "")]))
+        assert empty_form.validate() is True, empty_form.errors
+        assert empty_form.proxy_port.data is None
+
+        populated_form = form_cls(MultiDict([("proxy_port", "8080")]))
+        assert populated_form.validate() is True, populated_form.errors
+        assert populated_form.proxy_port.data == 8080
+
+        invalid_form = form_cls(MultiDict([("proxy_port", "not-an-int")]))
+        assert invalid_form.validate() is False
+        assert "proxy_port" in invalid_form.errors

Reply via email to