From acc7bc3d0180f5e069e81434d4e229674582e7a3 Mon Sep 17 00:00:00 2001 From: James Mackay Date: Sun, 11 Oct 2026 06:02:08 +0100 Subject: [PATCH] =?UTF-8?q?fix(media=5Fplayer):=20F1=20=E2=80=94=20extra?= =?UTF-8?q?=5Fstate=5Fattributes=20must=20be=20a=20property=20(t40=20block?= =?UTF-8?q?er)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported from a live install: the entity never rendered, and every state write raised ``TypeError: 'method' object is not iterable``. Root cause, from HA's own code (homeassistant/helpers/entity.py, ``__async_calculate_state``): if extra_state_attributes := self.extra_state_attributes: attr |= extra_state_attributes ``attr`` is a dict, so ``|=`` needs a mapping — and this was declared as a plain method while the sensors' were properties. Reproduced against the pre-fix tree with real HA: instantiating the entity and calling ``async_write_ha_state()`` prints ``REPRODUCED TypeError: 'method' object is not iterable``; with the fix the same call writes the state and the extra attributes through. The stub suites could never see it: their harness replaces ``async_write_ha_state``, so the method was simply called and returned a dict. tests/test_ha_api_drift.py now drives HA's real state calculation for every entity, and the drift sweep grew an entity-contract pass (next commit). --- custom_components/nvidia_shield/media_player.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/custom_components/nvidia_shield/media_player.py b/custom_components/nvidia_shield/media_player.py index 83c5dec..480602f 100644 --- a/custom_components/nvidia_shield/media_player.py +++ b/custom_components/nvidia_shield/media_player.py @@ -825,7 +825,16 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity): } ) + @property def extra_state_attributes(self) -> dict: + """Extra state attributes — a PROPERTY, as HA requires (t40 blocker). + + ``Entity.__async_calculate_state`` merges them with + ``attr |= self.extra_state_attributes``; declaring this as a plain + method made every state write raise + ``TypeError: 'method' object is not iterable``, so the entity could + never render on a live install. + """ # Now playing: prefer Jellyfin, fall back to ADB media session, # then the foreground tier (P3-3a). now_playing = self._get_now_playing()