Code styling tweaks to the ESPHome integration (#86146)

This commit is contained in:
Franck Nijhof 2023-01-18 11:10:16 +01:00 committed by GitHub
parent f17a829bd8
commit 382e1ac679
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 36 deletions

View File

@ -141,7 +141,8 @@ async def async_setup_entry( # noqa: C901
# Use async_listen instead of async_listen_once so that we don't deregister # Use async_listen instead of async_listen_once so that we don't deregister
# the callback twice when shutting down Home Assistant. # the callback twice when shutting down Home Assistant.
# "Unable to remove unknown listener <function EventBus.async_listen_once.<locals>.onetime_listener>" # "Unable to remove unknown listener
# <function EventBus.async_listen_once.<locals>.onetime_listener>"
entry_data.cleanup_callbacks.append( entry_data.cleanup_callbacks.append(
hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, on_stop) hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, on_stop)
) )
@ -651,7 +652,9 @@ class EsphomeEnumMapper(Generic[_EnumT, _ValT]):
def __init__(self, mapping: dict[_EnumT, _ValT]) -> None: def __init__(self, mapping: dict[_EnumT, _ValT]) -> None:
"""Construct a EsphomeEnumMapper.""" """Construct a EsphomeEnumMapper."""
# Add none mapping # Add none mapping
augmented_mapping: dict[_EnumT | None, _ValT | None] = mapping # type: ignore[assignment] augmented_mapping: dict[
_EnumT | None, _ValT | None
] = mapping # type: ignore[assignment]
augmented_mapping[None] = None augmented_mapping[None] = None
self._mapping = augmented_mapping self._mapping = augmented_mapping
@ -823,7 +826,10 @@ class EsphomeEntity(Entity, Generic[_InfoT, _StateT]):
@property @property
def entity_registry_enabled_default(self) -> bool: def entity_registry_enabled_default(self) -> bool:
"""Return if the entity should be enabled when first added to the entity registry.""" """Return if the entity should be enabled when first added.
This only applies when fist added to the entity registry.
"""
return not self._static_info.disabled_by_default return not self._static_info.disabled_by_default
@property @property

View File

@ -77,8 +77,11 @@ def verify_connected(func: _WrapFuncType) -> _WrapFuncType:
task.cancel() task.cancel()
with contextlib.suppress(asyncio.CancelledError): with contextlib.suppress(asyncio.CancelledError):
await task await task
raise BleakError( raise BleakError(
f"{self._source_name}: {self._ble_device.name} - {self._ble_device.address}: " # pylint: disable=protected-access f"{self._source_name}: " # pylint: disable=protected-access
f"{self._ble_device.name} - " # pylint: disable=protected-access
f" {self._ble_device.address}: " # pylint: disable=protected-access
"Disconnected during operation" "Disconnected during operation"
) )
return next(iter(done)).result() return next(iter(done)).result()
@ -105,8 +108,8 @@ def api_error_as_bleak_error(func: _WrapFuncType) -> _WrapFuncType:
# that we find out about the disconnection during the operation # that we find out about the disconnection during the operation
# before the callback is delivered. # before the callback is delivered.
# pylint: disable=protected-access
if ex.error.error == -1: if ex.error.error == -1:
# pylint: disable=protected-access
_LOGGER.debug( _LOGGER.debug(
"%s: %s - %s: BLE device disconnected during %s operation", "%s: %s - %s: BLE device disconnected during %s operation",
self._source_name, self._source_name,
@ -228,7 +231,8 @@ class ESPHomeClient(BaseBleakClient):
"""Connect to a specified Peripheral. """Connect to a specified Peripheral.
Keyword Args: Keyword Args:
timeout (float): Timeout for required ``BleakScanner.find_device_by_address`` call. Defaults to 10.0. timeout (float): Timeout for required
``BleakScanner.find_device_by_address`` call. Defaults to 10.0.
Returns: Returns:
Boolean representing connection status. Boolean representing connection status.
""" """
@ -395,7 +399,8 @@ class ESPHomeClient(BaseBleakClient):
"""Get all services registered for this GATT server. """Get all services registered for this GATT server.
Returns: Returns:
A :py:class:`bleak.backends.service.BleakGATTServiceCollection` with this device's services tree. A :py:class:`bleak.backends.service.BleakGATTServiceCollection`
with this device's services tree.
""" """
address_as_int = self._address_as_int address_as_int = self._address_as_int
domain_data = self.domain_data domain_data = self.domain_data
@ -494,9 +499,10 @@ class ESPHomeClient(BaseBleakClient):
"""Perform read operation on the specified GATT characteristic. """Perform read operation on the specified GATT characteristic.
Args: Args:
char_specifier (BleakGATTCharacteristic, int, str or UUID): The characteristic to read from, char_specifier (BleakGATTCharacteristic, int, str or UUID):
specified by either integer handle, UUID or directly by the The characteristic to read from, specified by either integer
BleakGATTCharacteristic object representing it. handle, UUID or directly by the BleakGATTCharacteristic
object representing it.
Returns: Returns:
(bytearray) The read data. (bytearray) The read data.
""" """
@ -530,11 +536,13 @@ class ESPHomeClient(BaseBleakClient):
"""Perform a write operation of the specified GATT characteristic. """Perform a write operation of the specified GATT characteristic.
Args: Args:
char_specifier (BleakGATTCharacteristic, int, str or UUID): The characteristic to write char_specifier (BleakGATTCharacteristic, int, str or UUID):
to, specified by either integer handle, UUID or directly by the The characteristic to write to, specified by either integer
BleakGATTCharacteristic object representing it. handle, UUID or directly by the BleakGATTCharacteristic object
representing it.
data (bytes or bytearray): The data to send. data (bytes or bytearray): The data to send.
response (bool): If write-with-response operation should be done. Defaults to `False`. response (bool): If write-with-response operation should be done.
Defaults to `False`.
""" """
characteristic = self._resolve_characteristic(char_specifier) characteristic = self._resolve_characteristic(char_specifier)
await self._client.bluetooth_gatt_write( await self._client.bluetooth_gatt_write(
@ -566,16 +574,19 @@ class ESPHomeClient(BaseBleakClient):
) -> None: ) -> None:
"""Activate notifications/indications on a characteristic. """Activate notifications/indications on a characteristic.
Callbacks must accept two inputs. The first will be a integer handle of the characteristic generating the Callbacks must accept two inputs. The first will be a integer handle of the
data and the second will be a ``bytearray`` containing the data sent from the connected server. characteristic generating the data and the second will be a ``bytearray``
containing the data sent from the connected server.
.. code-block:: python .. code-block:: python
def callback(sender: int, data: bytearray): def callback(sender: int, data: bytearray):
print(f"{sender}: {data}") print(f"{sender}: {data}")
client.start_notify(char_uuid, callback) client.start_notify(char_uuid, callback)
Args: Args:
char_specifier (BleakGATTCharacteristic, int, str or UUID): The characteristic to activate char_specifier (BleakGATTCharacteristic, int, str or UUID):
notifications/indications on a characteristic, specified by either integer handle, The characteristic to activate notifications/indications on a
UUID or directly by the BleakGATTCharacteristic object representing it. characteristic, specified by either integer handle, UUID or
directly by the BleakGATTCharacteristic object representing it.
callback (function): The function to be called on notification. callback (function): The function to be called on notification.
""" """
ble_handle = characteristic.handle ble_handle = characteristic.handle
@ -645,9 +656,10 @@ class ESPHomeClient(BaseBleakClient):
"""Deactivate notification/indication on a specified characteristic. """Deactivate notification/indication on a specified characteristic.
Args: Args:
char_specifier (BleakGATTCharacteristic, int, str or UUID): The characteristic to deactivate char_specifier (BleakGATTCharacteristic, int, str or UUID):
notification/indication on, specified by either integer handle, UUID or The characteristic to deactivate notification/indication on,
directly by the BleakGATTCharacteristic object representing it. specified by either integer handle, UUID or directly by the
BleakGATTCharacteristic object representing it.
""" """
characteristic = self._resolve_characteristic(char_specifier) characteristic = self._resolve_characteristic(char_specifier)
# Do not raise KeyError if notifications are not enabled on this characteristic # Do not raise KeyError if notifications are not enabled on this characteristic

View File

@ -118,7 +118,10 @@ def _color_mode_to_ha(mode: int) -> str:
def _filter_color_modes( def _filter_color_modes(
supported: list[int], features: LightColorCapability supported: list[int], features: LightColorCapability
) -> list[int]: ) -> list[int]:
"""Filter the given supported color modes, excluding all values that don't have the requested features.""" """Filter the given supported color modes.
Excluding all values that don't have the requested features.
"""
return [mode for mode in supported if mode & features] return [mode for mode in supported if mode & features]
@ -161,7 +164,7 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
try_keep_current_mode = False try_keep_current_mode = False
if (rgbw_ha := kwargs.get(ATTR_RGBW_COLOR)) is not None: if (rgbw_ha := kwargs.get(ATTR_RGBW_COLOR)) is not None:
# pylint: disable=invalid-name # pylint: disable-next=invalid-name
*rgb, w = tuple(x / 255 for x in rgbw_ha) # type: ignore[assignment] *rgb, w = tuple(x / 255 for x in rgbw_ha) # type: ignore[assignment]
color_bri = max(rgb) color_bri = max(rgb)
# normalize rgb # normalize rgb
@ -174,7 +177,7 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
try_keep_current_mode = False try_keep_current_mode = False
if (rgbww_ha := kwargs.get(ATTR_RGBWW_COLOR)) is not None: if (rgbww_ha := kwargs.get(ATTR_RGBWW_COLOR)) is not None:
# pylint: disable=invalid-name # pylint: disable-next=invalid-name
*rgb, cw, ww = tuple(x / 255 for x in rgbww_ha) # type: ignore[assignment] *rgb, cw, ww = tuple(x / 255 for x in rgbww_ha) # type: ignore[assignment]
color_bri = max(rgb) color_bri = max(rgb)
# normalize rgb # normalize rgb
@ -226,7 +229,8 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
if (white_ha := kwargs.get(ATTR_WHITE)) is not None: if (white_ha := kwargs.get(ATTR_WHITE)) is not None:
# ESPHome multiplies brightness and white together for final brightness # ESPHome multiplies brightness and white together for final brightness
# HA only sends `white` in turn_on, and reads total brightness through brightness property # HA only sends `white` in turn_on, and reads total brightness
# through brightness property.
data["brightness"] = white_ha / 255 data["brightness"] = white_ha / 255
data["white"] = 1.0 data["white"] = 1.0
color_modes = _filter_color_modes( color_modes = _filter_color_modes(
@ -244,8 +248,10 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
# if possible, stay with the color mode that is already set # if possible, stay with the color mode that is already set
data["color_mode"] = self._state.color_mode data["color_mode"] = self._state.color_mode
else: else:
# otherwise try the color mode with the least complexity (fewest capabilities set) # otherwise try the color mode with the least complexity
# popcount with bin() function because it appears to be the best way: https://stackoverflow.com/a/9831671 # (fewest capabilities set)
# popcount with bin() function because it appears
# to be the best way: https://stackoverflow.com/a/9831671
color_modes.sort(key=lambda mode: bin(mode).count("1")) color_modes.sort(key=lambda mode: bin(mode).count("1"))
data["color_mode"] = color_modes[0] data["color_mode"] = color_modes[0]
@ -332,9 +338,9 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
@property @property
@esphome_state_property @esphome_state_property
def color_temp(self) -> float | None: # type: ignore[override] def color_temp(self) -> int:
"""Return the CT color value in mireds.""" """Return the CT color value in mireds."""
return self._state.color_temperature return round(self._state.color_temperature)
@property @property
@esphome_state_property @esphome_state_property
@ -377,11 +383,11 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
return self._static_info.effects return self._static_info.effects
@property @property
def min_mireds(self) -> float: # type: ignore[override] def min_mireds(self) -> int:
"""Return the coldest color_temp that this light supports.""" """Return the coldest color_temp that this light supports."""
return self._static_info.min_mireds return round(self._static_info.min_mireds)
@property @property
def max_mireds(self) -> float: # type: ignore[override] def max_mireds(self) -> int:
"""Return the warmest color_temp that this light supports.""" """Return the warmest color_temp that this light supports."""
return self._static_info.max_mireds return round(self._static_info.max_mireds)

View File

@ -17,6 +17,7 @@ from homeassistant.components.media_player import (
MediaPlayerEntity, MediaPlayerEntity,
MediaPlayerEntityFeature, MediaPlayerEntityFeature,
MediaPlayerState, MediaPlayerState,
MediaType,
async_process_play_media_url, async_process_play_media_url,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -97,7 +98,7 @@ class EsphomeMediaPlayer(
return flags return flags
async def async_play_media( async def async_play_media(
self, media_type: str, media_id: str, **kwargs: Any self, media_type: MediaType | str, media_id: str, **kwargs: Any
) -> None: ) -> None:
"""Send the play command with media url to the media player.""" """Send the play command with media url to the media player."""
if media_source.is_media_source_id(media_id): if media_source.is_media_source_id(media_id):

View File

@ -113,7 +113,8 @@ class EsphomeSensor(EsphomeEntity[SensorInfo, SensorState], SensorEntity):
state_class == EsphomeSensorStateClass.MEASUREMENT state_class == EsphomeSensorStateClass.MEASUREMENT
and reset_type == LastResetType.AUTO and reset_type == LastResetType.AUTO
): ):
# Legacy, last_reset_type auto was the equivalent to the TOTAL_INCREASING state class # Legacy, last_reset_type auto was the equivalent to the
# TOTAL_INCREASING state class
return SensorStateClass.TOTAL_INCREASING return SensorStateClass.TOTAL_INCREASING
return _STATE_CLASSES.from_esphome(self._static_info.state_class) return _STATE_CLASSES.from_esphome(self._static_info.state_class)