fix(media_player,config_flow): close the batch review's O2 and O3 (t17)
Both observations from the t8-t12 batch review, settled by execution rather than
by argument.
O2 — WHICH STATES MAY CARRY A NOW-PLAYING ROW. The review read
`extra_state_attributes` and argued the row publishes the entity state verbatim,
so `now_playing_state: on` is reachable, while the README documents only
playing/paused/buffering/idle; t10's author had reported that `on` and `off`
publish no row at all. The probe settles both halves:
* the t10 account is true on the NATURAL ladder — `on` means no source reported a
power or playback fact, and every tier that can produce a reading sets
`reported = True` in the ladder, so the two cannot meet;
* the review is right about the RULE. It was "publish unless the state is off", an
assumption nothing enforced: forcing the ladder to `on` (and to `standby`, which
the README does not even mention) published `now_playing_state: on`/`standby`
beside a real title.
So the rule is now explicit — `NOW_PLAYING_STATE_VALUES = ("playing", "paused",
"buffering", "idle")` — and a reading is dropped whole when the entity state is
anything else, exactly as `off` always dropped it. Nothing legitimate is lost: a
tier only ever answers in one of those four (`idle` for "reported, nothing
playing", which is where the foreground tier's remembered-playback bridge lands).
The README says the same thing in the table row and in prose, and
tests/test_now_playing_publication.py walks EVERY `MediaPlayerState` member with a
reading present (the four publish themselves; on/off/standby publish nothing),
then reads the four values back OUT OF THE README and compares them to the
constant, so code and docs cannot drift again.
O3 — A REJECTED APP PASTE NAMES ITS BAD LINES. The bulk paste was all-or-nothing
and reported a generic `invalid_app_map`, so a 30-row paste with one typo had to
be bisected by hand. `_app_map_parse` now returns `(map | None, problems)` where
each problem carries the 1-based line NUMBER, the line as the user typed it, and
why (empty/space-bearing package, empty name, space in the icon), and the
rejection puts them in the form's `description_placeholders["invalid_lines"]`,
which the error copy interpolates — capped at 4 named lines with the remaining
count, so the message stays readable. The map is still None when anything is
wrong (never half-stored) and the detail is cleared as soon as a paste parses.
The single-row editor is untouched and keeps its own `invalid_app_row`; a test
asserts the new per-line report and `_valid_app_row` accept and refuse the same
rows, so a paste and a typed row cannot disagree.
Verify: 794 passed / 4 skipped, 795 passed / 3 skipped (with androidtvremote2),
ruff clean.
This commit is contained in:
1 parent
91d9fb3883
commit
2819ee5a49
7 files changed
+489
-33
No files matched your search
@@ -876,7 +876,7 @@ TOP-LEVEL attributes**, not one nested object — that object read badly in YAML
|
||||
| Attribute | What it holds |
|
||||
| --- | --- |
|
||||
| `now_playing_via` | which TIER produced the reading: `jellyfin`, `media_session` or `app` |
|
||||
| `now_playing_state` | the reading's own state: `playing` / `paused` / `buffering` / `idle` |
|
||||
| `now_playing_state` | the reading's own state — exactly one of `playing`, `paused`, `buffering`, `idle` |
|
||||
| `now_playing_title` | the title — or, in privacy mode, the app identity |
|
||||
| `now_playing_artist`, `now_playing_album` | the session's artist and album, when it has them |
|
||||
| `now_playing_media_type` | the content type the source reported |
|
||||
@@ -893,6 +893,13 @@ The rules that keep the set predictable:
|
||||
gone stale must not put a title beside a device that is off, and the state
|
||||
already says nothing is playing. `on` (no source reported a power or playback
|
||||
fact) publishes none either — there is no reading to publish.
|
||||
- **`now_playing_state` is one of FOUR values, and `on` is not one of them.** The
|
||||
full set is `playing`, `paused`, `buffering`, `idle` — the states a source can
|
||||
report when it has something to say. The row is published only while the entity
|
||||
state is one of those four, so `on` (nothing reported), `off` and any frontend-
|
||||
or app-side state can never appear beside a title. The list is code
|
||||
(`NOW_PLAYING_STATE_VALUES` in `media_player.py`) and a test compares THIS
|
||||
paragraph and the table above against it, so neither can drift.
|
||||
- **`now_playing_via` is deliberately not `source`.** On a media player, `source`
|
||||
and `source_list` mean the selected app input (`Netflix`, `TiviMate`, …) and they
|
||||
still do; naming the tier `source` is exactly what made the reading look like
|
||||
|
||||
Reference in new issue
Block a user