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

vatsrahul1001 pushed a commit to branch v3-2-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-2-test by this push:
     new 586df8da52b Fix ArgNotSet repr to use stable string instead of memory 
address (#65222) (#66897)
586df8da52b is described below

commit 586df8da52b9fd87624fc5032bf9f90e8fbe29c4
Author: Rahul Vats <[email protected]>
AuthorDate: Mon May 18 12:18:47 2026 +0530

    Fix ArgNotSet repr to use stable string instead of memory address (#65222) 
(#66897)
    
    * Add tests for ArgNotSet serialization and repr/str behavior
    
    * Add serialize, __repr__, __str__ to ArgNotSet for deterministic 
serialization
    
    * Flip ArgNotSet repr/str test to expect sentinel string and use top-level 
imports
    
    * Delegate ArgNotSet __repr__/__str__ to serialize() for polymorphic 
sentinel strings
    
    ---------
    
    
    (cherry picked from commit e0587fdc18baf28722b167b71eaf85068181a462)
    
    Co-authored-by: necmo <[email protected]>
    Co-authored-by: taeyong <[email protected]>
---
 airflow-core/src/airflow/models/__init__.py        |  1 +
 .../airflow/serialization/definitions/notset.py    | 10 +++++++++
 .../tests/unit/serialization/test_helpers.py       | 26 ++++++++++++++++++++--
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/airflow-core/src/airflow/models/__init__.py 
b/airflow-core/src/airflow/models/__init__.py
index 8e12325f568..7a58a17fdb0 100644
--- a/airflow-core/src/airflow/models/__init__.py
+++ b/airflow-core/src/airflow/models/__init__.py
@@ -66,6 +66,7 @@ def import_all_models():
     import airflow.models.dag_version
     import airflow.models.dagbag
     import airflow.models.dagbundle
+    import airflow.models.dagcode
     import airflow.models.dagwarning
     import airflow.models.deadline_alert
     import airflow.models.errors
diff --git a/airflow-core/src/airflow/serialization/definitions/notset.py 
b/airflow-core/src/airflow/serialization/definitions/notset.py
index a7731daed20..d7498243236 100644
--- a/airflow-core/src/airflow/serialization/definitions/notset.py
+++ b/airflow-core/src/airflow/serialization/definitions/notset.py
@@ -31,6 +31,16 @@ __all__ = ["NOTSET", "ArgNotSet", "is_arg_set"]
 class ArgNotSet:
     """Sentinel type for annotations, useful when None is not viable."""
 
+    @staticmethod
+    def serialize() -> str:
+        return "NOTSET"
+
+    def __repr__(self) -> str:
+        return self.serialize()
+
+    def __str__(self) -> str:
+        return self.serialize()
+
 
 NOTSET = ArgNotSet()
 """Sentinel value for argument default. See ``ArgNotSet``."""
diff --git a/airflow-core/tests/unit/serialization/test_helpers.py 
b/airflow-core/tests/unit/serialization/test_helpers.py
index 0ded4f64a86..94fb26525c7 100644
--- a/airflow-core/tests/unit/serialization/test_helpers.py
+++ b/airflow-core/tests/unit/serialization/test_helpers.py
@@ -16,16 +16,38 @@
 # under the License.
 from __future__ import annotations
 
+from airflow.sdk.definitions._internal.types import SET_DURING_EXECUTION
+from airflow.serialization.definitions.notset import NOTSET
+from airflow.serialization.helpers import serialize_template_field
+
 
 def test_serialize_template_field_with_very_small_max_length(monkeypatch):
     """Test that truncation message is prioritized even for very small 
max_length."""
     monkeypatch.setenv("AIRFLOW__CORE__MAX_TEMPLATED_FIELD_LENGTH", "1")
 
-    from airflow.serialization.helpers import serialize_template_field
-
     result = serialize_template_field("This is a long string", "test")
 
     # The truncation message should be shown even if it exceeds max_length
     # This ensures users always see why content is truncated
     assert result
     assert "Truncated. You can change this behaviour" in result
+
+
+def test_serialize_template_field_with_notset():
+    """NOTSET must serialize deterministically via serialize(), not str() 
fallback."""
+    result = serialize_template_field(NOTSET, "logical_date")
+    assert result == "NOTSET"
+
+
+def test_serialize_template_field_with_set_during_execution():
+    """SetDuringExecution must use its own serialize() override."""
+    result = serialize_template_field(SET_DURING_EXECUTION, "logical_date")
+    assert result == "DYNAMIC (set during execution)"
+
+
+def test_argnotset_repr_and_str():
+    """repr/str should return the stable serialized sentinel string."""
+    assert repr(NOTSET) == "NOTSET"
+    assert str(NOTSET) == "NOTSET"
+    assert repr(SET_DURING_EXECUTION) == "DYNAMIC (set during execution)"
+    assert str(SET_DURING_EXECUTION) == "DYNAMIC (set during execution)"

Reply via email to