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

vincbeck 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 05011bdc714 Fix BaseBranchOperator import on Airflow 2 without 
standard provider (#73140)
05011bdc714 is described below

commit 05011bdc714b2508b420c2f6575e62dad2fd6f36
Author: Vincent <[email protected]>
AuthorDate: Mon Sep 14 14:53:02 2026 -0400

    Fix BaseBranchOperator import on Airflow 2 without standard provider 
(#73140)
    
    The standard provider is only an optional extra of the providers that use
    these classes, so a deployment on Airflow 2 can legitimately not have it
    installed. Falling back to the Airflow 2 core module keeps the compat layer
    resolvable with just the `apache-airflow` dependency it already declares,
    matching how every other standard-provider entry in this layer behaves.
---
 .../src/airflow/providers/common/compat/sdk.py     | 12 ++++++++++--
 .../compat/tests/unit/common/compat/test_sdk.py    | 22 ++++++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/providers/common/compat/src/airflow/providers/common/compat/sdk.py 
b/providers/common/compat/src/airflow/providers/common/compat/sdk.py
index 93174df7b2a..f8c7ef049cc 100644
--- a/providers/common/compat/src/airflow/providers/common/compat/sdk.py
+++ b/providers/common/compat/src/airflow/providers/common/compat/sdk.py
@@ -153,8 +153,16 @@ _IMPORT_MAP: dict[str, str | tuple[str, ...]] = {
     # 
============================================================================
     # Branching
     # 
============================================================================
-    "BaseBranchOperator": ("airflow.sdk.bases.branch", 
"airflow.providers.standard.operators.branch"),
-    "BranchMixIn": ("airflow.sdk.bases.branch", 
"airflow.providers.standard.operators.branch"),
+    "BaseBranchOperator": (
+        "airflow.sdk.bases.branch",
+        "airflow.operators.branch",
+        "airflow.providers.standard.operators.branch",
+    ),
+    "BranchMixIn": (
+        "airflow.sdk.bases.branch",
+        "airflow.operators.branch",
+        "airflow.providers.standard.operators.branch",
+    ),
     "SkipMixin": (
         "airflow.sdk.bases.skipmixin",
         "airflow.models.skipmixin",
diff --git a/providers/common/compat/tests/unit/common/compat/test_sdk.py 
b/providers/common/compat/tests/unit/common/compat/test_sdk.py
index 08b5107e493..d6f819ec9e5 100644
--- a/providers/common/compat/tests/unit/common/compat/test_sdk.py
+++ b/providers/common/compat/tests/unit/common/compat/test_sdk.py
@@ -18,8 +18,12 @@
 
 from __future__ import annotations
 
+import builtins
+
 import pytest
 
+from tests_common.test_utils.version_compat import AIRFLOW_V_3_0_PLUS
+
 
 def test_all_compat_imports_work():
     """
@@ -46,6 +50,24 @@ def test_all_compat_imports_work():
         pytest.fail(error_msg)
 
 
[email protected](AIRFLOW_V_3_0_PLUS, reason="Test requires Airflow < 3.0")
[email protected]("name", ["BaseBranchOperator", "BranchMixIn"])
+def test_branching_imports_work_without_standard_provider(name, monkeypatch):
+    """On Airflow 2 the standard provider is optional, so core paths must be 
used as fallback."""
+    from airflow.providers.common.compat import sdk
+
+    real_import = builtins.__import__
+
+    def fake_import(module_name, *args, **kwargs):
+        if module_name.startswith("airflow.providers.standard"):
+            raise ModuleNotFoundError(f"No module named {module_name!r}")
+        return real_import(module_name, *args, **kwargs)
+
+    monkeypatch.setattr(builtins, "__import__", fake_import)
+
+    assert getattr(sdk, name) is not None
+
+
 def test_invalid_import_raises_attribute_error():
     """Test that importing non-existent attribute raises AttributeError."""
     from airflow.providers.common.compat import sdk

Reply via email to