Pass native datetime and UUID literals to stub tasks - #71536
Open
jason810496 wants to merge 2 commits into
Open
Conversation
jason810496
force-pushed
the
feature/lang-sdk/stub-arg-native-values
branch
from
August 14, 2026 06:38
da71819 to
a517a7f
Compare
jason810496
marked this pull request as ready for review
August 14, 2026 06:47
jason810496
requested review from
amoghrajesh,
ashb,
bolkedebruin and
kaxil
as code owners
August 14, 2026 06:47
uranusjr
reviewed
Aug 17, 2026
uranusjr
reviewed
Aug 17, 2026
uranusjr
reviewed
Aug 17, 2026
jason810496
marked this pull request as draft
August 17, 2026 13:41
A @task.stub TaskFlow call could only carry values json.dumps already knew, so a datetime, date, timedelta or UUID argument was rejected outright and Dag authors had to hand-write the JSON spelling their lang SDK expected -- with nothing keeping that spelling consistent between authors, or in step with the value_schema the same parameter advertises. Rendering the value through the adapter that produced its schema means the two cannot disagree, and every language runtime sees one spelling per format. Timestamps are pinned to an explicit offset first: an offset-less timestamp is a different instant to each runtime -- UTC in Go, worker-local in JavaScript, unparsable in Java -- so leaving it naive on the wire would make a task's behaviour depend on the language that happens to run it.
1 task
jason810496
force-pushed
the
feature/lang-sdk/stub-arg-native-values
branch
from
August 19, 2026 02:48
a517a7f to
c8812b3
Compare
jason810496
force-pushed
the
feature/lang-sdk/stub-arg-native-values
branch
from
August 19, 2026 03:25
c8812b3 to
31e01bc
Compare
Pydantic JSON mode accepts a much broader set of Python objects than the temporal and UUID contract, which could silently change previously rejected values. Nested timestamps also need the same timezone normalization as top-level arguments.
jason810496
force-pushed
the
feature/lang-sdk/stub-arg-native-values
branch
from
August 19, 2026 04:32
31e01bc to
108dbf5
Compare
jason810496
marked this pull request as ready for review
August 19, 2026 06:05
jason810496
commented
Aug 19, 2026
jason810496
left a comment
Member
Author
There was a problem hiding this comment.
Thanks TP for the review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@task.stubTaskFlow arg-binding contract; this fills in the value half of it.Why
A
@task.stubTaskFlow call may only carry valuesjson.dumpsalready knows, so the most natural arguments to pass a foreign-language task were rejected outright:The parameter's
value_schemaalready told the runtime this was{"type": "string", "format": "date-time"}but the value could not travel.What
Temporal and UUID literals are now rendered through the same Pydantic adapter that produced their
value_schema, so the value and schema cannot disagree by construction. The conversion recurses through typed lists, sequences, tuples, mapping values, sets, and unions, so supported values use the same wire spelling at every depth. Sets containing supported leaves become deterministically sorted JSON arrays whileuniqueItems: truetells the runtime it may reconstruct set semantics.value_schemadatetime(2024, 1, 2, 3, 4, 5)"2024-01-02T03:04:05Z"{"type": "string", "format": "date-time"}date(2024, 1, 2)"2024-01-02"{"type": "string", "format": "date"}time(3, 4, 5)"03:04:05"{"type": "string", "format": "time"}timedelta(days=1, hours=2)"P1DT2H"{"type": "string", "format": "duration"}UUID("6BA7B810-...")"6ba7b810-..."{"type": "string", "format": "uuid"}[datetime(2024, 1, 2, 3, 4, 5)]["2024-01-02T03:04:05Z"]{"type": "array", "items": {"type": "string", "format": "date-time"}}{datetime(2024, 1, 2), datetime(2024, 1, 3)}["2024-01-02T00:00:00Z", "2024-01-03T00:00:00Z"]{"type": "array", "items": {"type": "string", "format": "date-time"}, "uniqueItems": true}Status.READYfor plainEnum{"type": "string", "enum": ["ready"], "title": "Status"}Status.READYforstr-backed Enum"ready"{"type": "string", "enum": ["ready"], "title": "Status"}Priority.HIGHforint-backed Enum1{"type": "integer", "enum": [1], "title": "Priority"}Decimal("1.20")Path("/tmp/example"){"type": "string", "format": "path"}Only temporal and UUID leaves opt into Pydantic serialization. Plain Enum members,
Decimal, andPathretain their previous rejection behavior; string- and integer-backed Enums retain their existing JSON-native behavior, and bytes remain unsupported. Schema generation and literal conversion are deliberately separate: Pydantic may describe a type even when its Python object cannot be emitted as JSON.Timezone-naive timestamps
A naive
datetimeis pinned to an explicit offset before serializing, via the samecoerce_datetimethe rest of Airflow uses. An offset-less timestamp is a different instant to each language runtime, so leaving it naive would make a task's behaviour depend on which language happens to run it.Instant.parsenew Date2024-01-02T03:04:05Z03:04:05Z03:04:05Z03:04:05Z2024-01-02T03:04:0503:04:05Z08:04:05Z(worker-local)Was generative AI tooling used to co-author this PR?