Repository navigation
fix: accept colon-less +0100 last_updated in is_running() on Python 3.9/3.10 - #5477
Open
headbouyJB wants to merge 2 commits into
Open
headbouyJB wants to merge 2 commits into
headbouyJB wants to merge 2 commits into
Conversation
….9/3.10
record_status() writes last_updated with TIME_FORMAT (%Y-%m-%dT%H:%M:%S%z);
strftime('%z') never emits a colon, and datetime.fromisoformat() only
accepts the colon-less form from Python 3.11, so is_running() parsed the
attribute as invalid on 3.9/3.10 and reported a false unhealthy status.
Parse with utils.str2time() first (its strptime fallback handles +0100 on
all versions), falling back to datetime.fromisoformat() on ValueError so
legacy naive last_updated values still reach the existing naive-now
branch (springfall2008#5181 review: keep the naive tolerance added in b8cb035).
load_plan() is left untouched: its timestamp is written via .isoformat()
(colon form), so it is not affected.
Adds fresh-timestamp coverage for +0100, +01:00 and naive last_updated to
the existing is_running() tests.
headbouyJB
force-pushed
the
fix-5181-str2time
branch
from
October 10, 2026 18:07
24ff33a to
29c651c
Compare
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The regression test does not distinguish the fixed implementation on the Python version used by CI.
1 open finding
What changed in this PR
Fixes Python 3.9/3.10 health checks by parsing status timestamps with the cross-version helper while preserving legacy naive timestamps.
Changes:
- Uses
str2time()with a naive-timestamp fallback. - Adds coverage for supported timestamp formats.
| File | Description |
|---|---|
apps/predbat/predbat.py |
Makes status timestamp parsing cross-version compatible. |
apps/predbat/tests/test_web_functions.py |
Adds timestamp-format regression cases. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+230
to
+246
| now_local = datetime.now(timezone.utc).astimezone() | ||
| fresh_formats = { | ||
| "colon-less offset (record_status writer format)": now_local.strftime("%Y-%m-%dT%H:%M:%S%z"), | ||
| "colon offset": now_local.isoformat(), | ||
| "naive legacy": str(datetime.now()), | ||
| } | ||
| for label, stamp in fresh_formats.items(): | ||
| set_entity(my_predbat, status_entity, state="Idle", error=False, last_updated=stamp) | ||
| try: | ||
| result = my_predbat.is_running() | ||
| except (TypeError, ValueError) as e: | ||
| print(f" ERROR: is_running() raised on a fresh {label} ({stamp}): {e}") | ||
| failed += 1 | ||
| else: | ||
| if result is not True: | ||
| print(f" ERROR: expected is_running() True for a fresh {label} ({stamp}), got: {result}") | ||
| failed += 1 |
The Python that CI runs accepts +0100, +01:00 and naive strings through datetime.fromisoformat() alone, so the fresh-timestamp cases passed with or without the fix. Spy on predbat.str2time and require each value to be handed to it, so reverting the fix fails the test on every Python version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.

Problem
record_status()writes the status entity'slast_updatedattribute withTIME_FORMAT(%Y-%m-%dT%H:%M:%S%z,const.py), andstrftime('%z')never emits a colon in the UTC offset.datetime.fromisoformat()only accepts the colon-less form from Python 3.11, so on 3.9/3.10is_running()fails to parse Predbat's own timestamp and returnsFalse— the web dashboard shows a false "(unhealthy)" status and the API ping endpoint 500s. Installs on 3.11+ never see it, which is why this was not caught internally.Change
Following the first of the two options in the automated triage on #5181 (keep the naive tolerance at the reader, rather than changing the writer): changing
record_status()to emit.isoformat()would alter the format of an attribute other consumers read —web.pyalready parses this same attribute withstr2time()— while the reader-side change leaves what is stored untouched and simply accepts what has always been written.In
is_running(): parse withutils.str2time()first (itsstrptimefallback handles+0100on all Python versions); onValueError, fall back todatetime.fromisoformat()so a legacy naivelast_updated— still persisted on installs upgraded from beforerecord_status()wrote a timezone-aware value — reaches the existing naive-now comparison branch instead of being rejected as unparseable (preserving the tolerance added inb8cb0350). The outerexcept (ValueError, TypeError)still returnsFalse.load_plan()is left unchanged: itsplan_last_updatedis written via.isoformat()(always the colon form), so that call site is not affected by this bug — and swapping it tostr2time()would have regressed its naive-timestamp fallback to UTC.Tests
Extended the existing
is_running()coverage inapps/predbat/tests/test_web_functions.py: a freshlast_updatedmust report running in all three formats the attribute can hold —+0100(the writer's format),+01:00, and the legacy naive form. Each case also spies onpredbat.str2timeand requires the value to be handed to it, so reverting the fix fails the test on every Python version, not only 3.9/3.10.CI runs Python 3.11+, where
fromisoformat()accepts+0100, so the format cases alone would pass there without the fix; thestr2time()spy is what makes the test fail on CI if the fix is reverted. The underlying bug was reproduced on Python 3.9.6 against the repo's real helpers:pre-commit(ruff, black, cspell) passes on the changed files.Closes #5181
AI assistance
Drafted with AI assistance (Warden, an OpenClaw agent running local Qwen models); reviewed and submitted by me.