CaptainAni187 opened a new pull request, #72710:
URL: https://github.com/apache/airflow/pull/72710
Closes: #72319
A `datetime.timedelta` payload whose seconds arrive as an `int` fails to
deserialize:
```python
deserialize({"__classname__": "datetime.timedelta", "__version__": 2,
"__data__": 2700})
# TypeError: unknown date/time format datetime.timedelta
```
`2700.0` and `"2700"` both work. The exception is unhandled during scheduler
DAG-run creation, so it takes the scheduler process down.
### Cause
The deserializer accepts only `str | float` for `timedelta`:
```python
if cls is datetime.timedelta and isinstance(data, str | float):
return datetime.timedelta(seconds=float(data))
```
`isinstance(2700, float)` is `False`, so an integral payload falls through
to the `TypeError` at the end of the function.
### Change
Widen the check to `str | int | float`.
Two things make this the natural fix rather than a special case:
- The `datetime` branch a few lines above already accepts `int | float`,
with a comment explaining it exists so payloads written by a different producer
can be read back through serde. This is the same situation one type down.
- The value goes through `float(data)` either way, so an int is handled
losslessly. Rejecting it was arbitrary rather than protective.
### On where the int comes from
I could not reproduce a producer inside this repo that emits the bare int —
`serialize()` writes `total_seconds()` as a float, `BaseSerialization` does the
same, and a plain JSON round-trip preserves `2700.0`. So I am not claiming to
have found the exact path from the reported traceback.
What is clear is that the value is *reachable*: any producer that drops a
trailing `.0` (common across JSON encoders and other languages) yields `2700`,
and the deadline-interval code this was reported from deals in integer seconds
by design — `VariableInterval` documents its variable as "interpreted as
seconds" and builds the timedelta via `int(value)`.
Given a one-character-class widening against an unhandled scheduler crash,
accepting the int seems clearly right regardless of which producer emitted it.
Happy to dig further if you would rather fix this at the producer instead.
### Tests
Adds `test_deserialize_timedelta_seconds`, parametrised over `int`, `float`
and `str`. On main the `int` case fails with the reported `TypeError` while
`float` and `str` pass, so the test pins the specific broken path rather than
the whole branch.
`tests/task_sdk/serde/` goes from 144 to 147 passed. Nine tests in that
directory fail identically before and after this change in my environment, from
missing optional dependencies (`pyarrow`, `deltalake`,
`airflow.providers.cncf`); they are unrelated to this change.
`ruff check` and `ruff format` are clean at the pinned 0.16.4.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]