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

potiuk 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 06c75db1ec7 fix(connection-model): RFC3896 `conn_type` warning (#63167)
06c75db1ec7 is described below

commit 06c75db1ec759abb6c3417eb05f84bcc323d0695
Author: Michael Trossbach <[email protected]>
AuthorDate: Sun Mar 29 11:24:26 2026 -0700

    fix(connection-model): RFC3896 `conn_type` warning (#63167)
    
    * fix(connection): check pre-normalized conn_type when warning about 
presence of underscores in conn_type
    
    * feat(connection): added test_get_uri_conn_type_warning method to 
TestConnection
    
    * fix(connection): use conn_type attr as default value when checking 
conn_type for presence of underscores in get_uri
    
    * fix(connection): generalized test cases used by 
test_get_uri_conn_type_warning test to include connections instantiated using a 
URI and connections instantiated not using a URI
    
    * fix(connection): coalesce conn_type value to an empty string before 
checking for presence of underscores in conn_type in get_uri
    
    * refactor(connection): updated assertion messages in 
test_get_uri_conn_type_warning method
    
    * style(connection): formatting changes according to prek static checks
---
 airflow-core/src/airflow/models/connection.py     | 13 +++---
 airflow-core/tests/unit/models/test_connection.py | 50 +++++++++++++++++++++++
 2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/airflow-core/src/airflow/models/connection.py 
b/airflow-core/src/airflow/models/connection.py
index d58f2b3202d..3032636f1b1 100644
--- a/airflow-core/src/airflow/models/connection.py
+++ b/airflow-core/src/airflow/models/connection.py
@@ -228,9 +228,11 @@ class Connection(Base, LoggingMixin):
             raise AirflowException("Invalid connection string.")
         host_with_protocol = schemes_count_in_uri == 2
         uri_parts = urlsplit(uri)
-        conn_type = uri_parts.scheme
-        self.conn_type = self._normalize_conn_type(conn_type)
-        rest_of_the_url = uri.replace(f"{conn_type}://", ("" if 
host_with_protocol else "//"))
+        self._prenormalized_conn_type = uri_parts.scheme
+        self.conn_type = 
self._normalize_conn_type(self._prenormalized_conn_type)
+        rest_of_the_url = uri.replace(
+            f"{self._prenormalized_conn_type}://", ("" if host_with_protocol 
else "//")
+        )
         if host_with_protocol:
             uri_splits = rest_of_the_url.split("://", 1)
             if "@" in uri_splits[0] or ":" in uri_splits[0]:
@@ -273,10 +275,11 @@ class Connection(Base, LoggingMixin):
 
         Note that the URI returned by this method is **not** 
SQLAlchemy-compatible, if you need a SQLAlchemy-compatible URI, use the 
:attr:`~airflow.providers.common.sql.hooks.sql.DbApiHook.sqlalchemy_url`
         """
-        if self.conn_type and "_" in self.conn_type:
+        conn_type = getattr(self, "_prenormalized_conn_type", self.conn_type) 
or ""
+        if "_" in conn_type:
             self.log.warning(
                 "Connection schemes (type: %s) shall not contain '_' according 
to RFC3986.",
-                self.conn_type,
+                conn_type,
             )
 
         if self.conn_type:
diff --git a/airflow-core/tests/unit/models/test_connection.py 
b/airflow-core/tests/unit/models/test_connection.py
index 6e0f9efbcd3..94cabe5e4da 100644
--- a/airflow-core/tests/unit/models/test_connection.py
+++ b/airflow-core/tests/unit/models/test_connection.py
@@ -23,6 +23,7 @@ from typing import TYPE_CHECKING
 from unittest import mock
 
 import pytest
+from structlog.testing import capture_logs
 
 from airflow.exceptions import AirflowException, AirflowNotFoundException
 from airflow.models import Connection
@@ -270,6 +271,55 @@ class TestConnection:
     def test_get_uri(self, connection, expected_uri):
         assert connection.get_uri() == expected_uri
 
+    @pytest.mark.parametrize(
+        ("connection", "expected_warned"),
+        [
+            (Connection(conn_id="test-uri-1", 
uri="google-cloud-platform://testlogin:testpassword@"), False),
+            (Connection(conn_id="test-uri-2", uri="amazon://test:test@"), 
False),
+            (
+                Connection(
+                    conn_id="test-non-uri-1",
+                    conn_type="google-cloud-platform",
+                    login="testlogin",
+                    password="testpassword",
+                ),
+                False,
+            ),
+            (
+                Connection(
+                    conn_id="test-non-uri-2",
+                    conn_type="google_cloud_platform",
+                    login="testlogin",
+                    password="testpassword",
+                ),
+                True,
+            ),
+            (
+                Connection(
+                    conn_id="test-non-uri-3", conn_type="amazon", 
login="testlogin", password="testpassword"
+                ),
+                False,
+            ),
+        ],
+    )
+    def test_get_uri_conn_type_warning(self, connection: Connection, 
expected_warned: bool):
+        with capture_logs() as captured_logs:
+            connection.get_uri()
+        conn_type_warnings = list(
+            filter(
+                lambda captured_log: (
+                    captured_log["log_level"] == "warning" and "RFC3986" in 
captured_log["event"]
+                ),
+                captured_logs,
+            )
+        )
+        if expected_warned:
+            assert conn_type_warnings, f"RFC3986 warning expected for 
connection '{connection.conn_id}'."
+        else:
+            assert not conn_type_warnings, (
+                f"RFC3986 warning not expected for connection 
'{connection.conn_id}'."
+            )
+
     @pytest.mark.parametrize(
         ("connection", "expected_conn_id"),
         [

Reply via email to