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

dabla 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 7839f4a2da0 Type the durable default of the common.compat 
ResumableJobMixin stand-in as bool | None (#75271)
7839f4a2da0 is described below

commit 7839f4a2da09c3dba27f52ce23707fa919b0b6a7
Author: David Blain <[email protected]>
AuthorDate: Wed Oct 28 14:11:16 2026 +0100

    Type the durable default of the common.compat ResumableJobMixin stand-in as 
bool | None (#75271)
    
    * Type the durable default of the common.compat ResumableJobMixin stand-in 
as bool | None
    
    Follow-up to #74673, addressing the post-merge review comment
    (https://github.com/apache/airflow/pull/74673#pullrequestreview-5596067358).
    
    The stand-in annotated `durable: bool` but defaulted it to an `object()` 
sentinel that was typed `Any`
    to keep mypy quiet. It now defaults to `None`, the value the operators 
already use for "not set"
    (they only forward `durable` when it is not `None`), so the annotation is 
accurate and mypy keeps
    checking the argument. No behaviour change: only an explicit 
`durable=True/False` warns below 3.3.
    
    * Test that an explicit durable=None does not warn in the ResumableJobMixin 
stand-in
    
    The no-warning test only covered durable left out, so a change back to 
warning on an explicit
    None would have passed. It now runs with durable left out and with 
durable=None.
---
 .../airflow/providers/common/compat/_resumable_job_mixin.py    | 10 ++++------
 .../tests/unit/common/compat/test__resumable_job_mixin.py      |  5 +++--
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git 
a/providers/common/compat/src/airflow/providers/common/compat/_resumable_job_mixin.py
 
b/providers/common/compat/src/airflow/providers/common/compat/_resumable_job_mixin.py
index aa2b9c2f4c3..d4b35ba0024 100644
--- 
a/providers/common/compat/src/airflow/providers/common/compat/_resumable_job_mixin.py
+++ 
b/providers/common/compat/src/airflow/providers/common/compat/_resumable_job_mixin.py
@@ -32,18 +32,16 @@ from typing import TYPE_CHECKING, Any
 if TYPE_CHECKING:
     from airflow.sdk.definitions.context import Context
 
-# Tells "durable left at its default" apart from an explicit 
durable=True/False, so only an explicit
-# value warns that it has no effect here.
-_DURABLE_UNSET: Any = object()
-
 
 class ResumableJobMixin:
     """Airflow < 3.3 stand-in: no ``task_state_store`` to resume from, so 
every try submits a new job."""
 
     external_id_key: str = "remote_job_id"
 
-    def __init__(self, *, durable: bool = _DURABLE_UNSET, **kwargs: Any) -> 
None:
-        if durable is not _DURABLE_UNSET:
+    def __init__(self, *, durable: bool | None = None, **kwargs: Any) -> None:
+        # None means "left at its default", so only an explicit 
durable=True/False warns that it has no
+        # effect here. The operators only forward durable when it is not None.
+        if durable is not None:
             warnings.warn(
                 "`durable` has no effect on Airflow versions below 3.3.",
                 UserWarning,
diff --git 
a/providers/common/compat/tests/unit/common/compat/test__resumable_job_mixin.py 
b/providers/common/compat/tests/unit/common/compat/test__resumable_job_mixin.py
index 31c0a861355..5dc9a967d4c 100644
--- 
a/providers/common/compat/tests/unit/common/compat/test__resumable_job_mixin.py
+++ 
b/providers/common/compat/tests/unit/common/compat/test__resumable_job_mixin.py
@@ -67,10 +67,11 @@ def test_stand_in_is_used_below_airflow_3_3():
 
 
 class TestStandIn:
-    def test_durable_left_at_default_does_not_warn(self):
+    @pytest.mark.parametrize("durable_kwargs", [{}, {"durable": None}], 
ids=["omitted", "none"])
+    def test_durable_left_at_default_does_not_warn(self, durable_kwargs):
         with warnings.catch_warnings():
             warnings.simplefilter("error")
-            operator = _JobOperator(task_id="t")
+            operator = _JobOperator(task_id="t", **durable_kwargs)
 
         assert operator.durable is False
         assert operator.base_kwargs == {"task_id": "t"}

Reply via email to