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)"