Uh oh!
There was an error while loading. Please reload this page.
refactor: remove prefer_typed - the server always streams typed values now - #33
Conversation
…s now The Teslemetry API maintainer confirms prefer_typed is always true server-side, so the per-vehicle opt-in and its untyped (string-encoded) wire-format handling no longer have a reason to exist. - Drop TeslemetryStreamVehicle.prefer_typed()/preferTyped, and the prefer_typed key from get_config/_on_config_event/_flush/config. - Drop the isinstance(data, str) coercion in make_int/make_float/ make_bool - listen_* callbacks now receive whatever the server sends straight through. - Delete tests/test_field_type_coercion.py (its subject, string-to- native coercion, no longer exists); adapt the remaining config/field tests to drop prefer_typed fixtures and assertions.
💡 Codex Reviewpython-teslemetry-stream/teslemetry_stream/vehicle.py Lines 135 to 139 in 8cf7c65 When a vehicle retains fields from before a disconnect and its configuration is deleted elsewhere, the reconnect-window REST fetch returns 404 but leaves those stale fields intact. Because this branch marks the vehicle populated, AGENTS.md reference: AGENTS.md:L21-L21 When an existing connection-state callback calls AGENTS.md reference: AGENTS.md:L20-L20 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
| data = event["data"][signal] | ||
| if isinstance(data, str): | ||
| # Handle invalid and None? | ||
| data = int(data) | ||
| callback(data) |
There was a problem hiding this comment.
These protections should stay, while prefer_typed is enabled by default, there are some vehicles that still don't use it so we should still catch those.
There was a problem hiding this comment.
Confirmed - restored the string coercion in make_int/make_float/make_bool and tests/test_field_type_coercion.py in 767c019. prefer_typed removal (the method/attribute/config-sync surface) stays; only the wire-format fallback was reinstated.
get_config()'s 404 branch marked the vehicle populated without clearing self.fields. A vehicle carrying fields from before a disconnect whose config was then deleted server-side would keep those stale fields forever, causing add_field() to permanently skip the PATCH for a field the server no longer has configured. Reported by Codex review on #33.
💡 Codex Reviewpython-teslemetry-stream/uv.lock Line 615 in 673130c The changed lock entry still declares version 0.10.1, matching the unchanged AGENTS.md reference: AGENTS.md:L17-L17 When an unpopulated vehicle's config GET raises a transport/timeout error or returns a non-200/404 status, this await aborts the fire-and-forget task created by AGENTS.md reference: AGENTS.md:L21-L21 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Matches the minor bump this PR's body already describes for the breaking removal of prefer_typed()/preferTyped - pyproject.toml and uv.lock still said 0.10.1. Reported by Codex review on #33.
_ensure_populated() let a failed populating GET (non-200/404 status, or a transport/timeout error) propagate out of add_field(). Called directly that's a normal exception a caller can handle, but every listen_* method reaches add_field() through _enable_field()'s fire-and-forget asyncio.create_task() - nobody awaits it, so the exception just became an unretrieved-task-exception log line and the requested field was never configured, silently. A failed fetch isn't authoritative like a 404: catch it, log a warning, and stay unpopulated so add_field() proceeds against whatever fields it currently knows and sends the PATCH, rather than abandoning the request. Reported by Codex review on #33.
…_bool prefer_typed is only a default now, not a guarantee: some vehicles haven't picked it up and still stream string-encoded numeric/boolean values. Dropping the isinstance(data, str) coercion in make_int/make_float/make_bool would silently hand those vehicles' consumers raw strings instead of int/float/bool. Restores tests/test_field_type_coercion.py, which regression-tests this coercion against real observed telemetry. The prefer_typed preference surface itself (prefer_typed()/preferTyped, the config-sync handling) stays removed - only the wire-format coercion is back. Per maintainer review on #33.
💡 Codex Reviewpython-teslemetry-stream/teslemetry_stream/vehicle.py Lines 160 to 161 in 767c019 When a stream uses an exact topic allowlist that omits AGENTS.md reference: AGENTS.md:L18-L21 When a connection-state callback calls AGENTS.md reference: AGENTS.md:L23-L23 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Uh oh!
There was an error while loading. Please reload this page.
#34) A connection listener that calls get_vehicle() for an uncached VIN (e.g. an integration discovering a vehicle on reconnect) registers that vehicle's own connection listener from inside TeslemetryStreamVehicle __init__, mutating _connection_listeners while _update_connection_listeners() is iterating it. That raised RuntimeError: dictionary changed size during iteration, interrupting connect()/disconnect notification delivery. listen() already dispatches over a snapshot of _listeners for the same reason; _update_connection_listeners() now does the same for _connection_listeners. Reported by Codex review on #33.
Intent
prefer_typedis enabled by default server-side now, so the per-vehicle opt-in itself has no reason to exist - but it's a default, not a guarantee: some vehicles haven't picked it up and still stream string-encoded numeric/boolean values, so the wire-format coercion inmake_int/make_float/make_boolstays (see below).TeslemetryStreamVehicle:prefer_typed(bool)method andpreferTypedattribute are gone.configproperty no longer carries aprefer_typedkey;get_config()/_on_config_event()/_flush()no longer read or write it from REST/SSE config bodies -fieldsis the only tracked piece now.make_int/make_float/make_boolkeep theirisinstance(data, str)coercion - per maintainer review, some vehicles still stream string-encoded values even withprefer_typedon by default, sotests/test_field_type_coercion.py(regression-tests this against real production telemetry) stays too.prefer_typed(),preferTyped, theprefer_typedkey inconfig) - user-facing breaking - but this repo's 0.x line uses the minor slot for changes of that scale (e.g. chore: bump version to 0.10.0 #18) rather than reserving a major bump.teslemetryintegration, HACS beta channel) - anything referencing these needs a mechanical update on the next bump:TeslemetryStreamVehicle.prefer_typed(...)- method removed.TeslemetryStreamVehicle.preferTyped- attribute removed.TeslemetryStreamVehicle.config["prefer_typed"]- key removed from theconfigproperty's return dict.listen_*callbacks are unaffected otherwise - numeric/boolean coercion behavior is unchanged.get_config()'s 404 branch marked the vehicle populated without clearingfields, so a config deleted server-side while offline could leaveadd_field()no-op'ing forever against a stale record - now the 404 branch clearsfieldstoo._ensure_populated(), which everylisten_*reaches through_enable_field()'s fire-and-forget task - the exception just became an unretrieved-task-exception log line and the field was never configured. Failed fetches aren't authoritative like a 404: now caught, logged, and the vehicle stays unpopulated soadd_field()proceeds to the PATCH instead of stranding the request._populated/lazy-fetch fix this branch coordinates with) was already merged tomainbefore this branch was created, so this sits directly on top of it with no rebase needed - it keeps fix: gate config no-op skip on a populated flag, not connection state #32'sadd_fieldmachinery intact and only removes theprefer_typedportions layered on top.tests/test_config_events.py,tests/test_config_listener_lifecycle.py,tests/test_config_update.py,tests/test_reconnect_config_window.py,tests/test_stream_lifecycle.pyadapted to dropprefer_typedfixtures/assertions while keeping theirfields/typed-behavior coverage;tests/test_field_type_coercion.pyunchanged.