Reduce magic in Sonos error handling fixture (#67401)

pull/67412/head
jjlawren 2022-02-28 18:38:08 -06:00 committed by GitHub
parent e963ad96d4
commit aea1209d0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 22 additions and 10 deletions

View File

@ -3,7 +3,7 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
import logging import logging
from typing import TYPE_CHECKING, TypeVar from typing import TYPE_CHECKING, Any, TypeVar
from soco import SoCo from soco import SoCo
from soco.exceptions import SoCoException, SoCoUPnPException from soco.exceptions import SoCoException, SoCoUPnPException
@ -55,15 +55,9 @@ def soco_error(
) )
return None return None
# In order of preference: if (target := _find_target_identifier(self, args_soco)) is None:
# * SonosSpeaker instance raise RuntimeError("Unexpected use of soco_error") from err
# * SoCo instance passed as an arg
# * SoCo instance (as self)
speaker_or_soco = getattr(self, "speaker", args_soco or self)
zone_name = speaker_or_soco.zone_name
# Prefer the entity_id if available, zone name as a fallback
# Needed as SonosSpeaker instances are not entities
target = getattr(self, "entity_id", zone_name)
message = f"Error calling {function} on {target}: {err}" message = f"Error calling {function} on {target}: {err}"
raise SonosUpdateError(message) from err raise SonosUpdateError(message) from err
@ -80,6 +74,24 @@ def soco_error(
return decorator return decorator
def _find_target_identifier(instance: Any, fallback_soco: SoCo | None) -> str | None:
"""Extract the the best available target identifier from the provided instance object."""
if entity_id := getattr(instance, "entity_id", None):
# SonosEntity instance
return entity_id
if zone_name := getattr(instance, "zone_name", None):
# SonosSpeaker instance
return zone_name
if speaker := getattr(instance, "speaker", None):
# Holds a SonosSpeaker instance attribute
return speaker.zone_name
if soco := getattr(instance, "soco", fallback_soco):
# Holds a SoCo instance attribute
# Only use attributes with no I/O
return soco._player_name or soco.ip_address # pylint: disable=protected-access
return None
def hostname_to_uid(hostname: str) -> str: def hostname_to_uid(hostname: str) -> str:
"""Convert a Sonos hostname to a uid.""" """Convert a Sonos hostname to a uid."""
if hostname.startswith("Sonos-"): if hostname.startswith("Sonos-"):