Fix DateTimeSensor crash when target_time renders to a datetime#70320
Open
1fanwang wants to merge 4 commits into
Open
Fix DateTimeSensor crash when target_time renders to a datetime#703201fanwang wants to merge 4 commits into
1fanwang wants to merge 4 commits into
Conversation
1fanwang
requested review from
amoghrajesh,
ashb,
bugraoz93,
gopidesupavan,
jason810496,
jscheffl and
potiuk
as code owners
July 23, 2026 18:53
shahar1
previously requested changes
Jul 24, 2026
1fanwang
marked this pull request as draft
July 24, 2026 05:47
1fanwang
marked this pull request as ready for review
July 24, 2026 06:23
shahar1
reviewed
Jul 24, 2026
target_time is a template field, so it is only rendered after __init__ runs. DateTimeSensor validated and normalized it in the constructor (acting on the un-rendered Jinja expression), and poke() parsed self.target_time directly with timezone.parse(). With a templated target_time and render_template_as_native_obj enabled, the field renders to a datetime and poke() raised "TypeError: 'DateTime' object cannot be cast as 'str'". Store target_time verbatim in the constructor and defer normalization and validation to _moment, the accessor that already runs after rendering; poke() now goes through it. related: apache#70296 Signed-off-by: 1fanwang <1fannnw@gmail.com>
The earlier refactor removed the datetime-to-ISO-string normalization that the constructor used to apply to target_time, leaving a datetime stored in the template field. Relocate that normalization to poke (the post-render execute path) so a datetime target_time is again stored as an ISO string, while __init__ keeps only the plain assignment. Signed-off-by: 1fanwang <1fannnw@gmail.com>
poke() is not reached by DateTimeSensorAsync, which overrides execute(); moving the datetime normalization into _moment (the shared post-render accessor) localizes a naive datetime for both the sync and async sensors, and drops the explanatory comments. Signed-off-by: 1fanwang <1fannnw@gmail.com>
1fanwang
force-pushed
the
fix-datetime-sensor-init-template-field
branch
from
July 24, 2026 18:05
2d99c66 to
0e4bc6a
Compare
Drop exemption entries that sibling burn-down PRs already resolved on main, which a stale rebase base had re-introduced. Net change to this file is only the DateTimeSensor removal. Signed-off-by: 1fanwang <1fannnw@gmail.com>
1fanwang
force-pushed
the
fix-datetime-sensor-init-template-field
branch
from
July 25, 2026 09:22
1f67ce4 to
2ffad8d
Compare
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.
target_timeis a template field, so it is only rendered after__init__runs.DateTimeSensorvalidated and normalized it in the constructor — acting on the un-rendered Jinja expression — andpoke()parsedself.target_timedirectly withtimezone.parse(). Whentarget_timeis templated and the Dag usesrender_template_as_native_obj=True, the field renders to adatetime, andpoke()crashed:The deferrable path already read the value through
_moment, which handles bothstranddatetime, so only the synchronous sensor was affected. The constructor now storestarget_timeverbatim, and thedatetime→ISO-string normalization it used to do is relocated topoke()(the post-render execute path) rather than dropped, soself.target_timestays a string once the sensor runs._momentstill parses and validates the rendered value, and both sensors route through it.__init__only assigns the template field now, in line with the burn-down in #70296.related: #70296
Testing Done
Operator-level repro (real Dag, real render, real
poke) — before the fix:After the fix:
test_date_time.py: 13 passed. The two normalization guards —poke()turns a native-rendered and a constructor-passeddatetimeinto its ISO string — fail on the pre-fix source and pass after.Was generative AI tooling used to co-author this PR?
Generated-by: GitHub Copilot CLI following the guidelines