Move overlapping pylint rules to ruff, disable mypy overlap (#94359)

pull/95393/head
Franck Nijhof 2023-06-27 17:42:46 +02:00 committed by GitHub
parent 7c676c0a7d
commit 3e85a29b86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 537 additions and 357 deletions

View File

@ -296,7 +296,6 @@ class ADBDevice(MediaPlayerEntity):
self._process_config, self._process_config,
) )
) )
return
@property @property
def media_image_hash(self) -> str | None: def media_image_hash(self) -> str | None:

View File

@ -137,16 +137,15 @@ class VoiceCommandSegmenter:
self._reset_seconds_left -= self._seconds_per_chunk self._reset_seconds_left -= self._seconds_per_chunk
if self._reset_seconds_left <= 0: if self._reset_seconds_left <= 0:
self._speech_seconds_left = self.speech_seconds self._speech_seconds_left = self.speech_seconds
elif not is_speech:
self._reset_seconds_left = self.reset_seconds
self._silence_seconds_left -= self._seconds_per_chunk
if self._silence_seconds_left <= 0:
return False
else: else:
if not is_speech: # Reset if enough speech
self._reset_seconds_left = self.reset_seconds self._reset_seconds_left -= self._seconds_per_chunk
self._silence_seconds_left -= self._seconds_per_chunk if self._reset_seconds_left <= 0:
if self._silence_seconds_left <= 0: self._silence_seconds_left = self.silence_seconds
return False
else:
# Reset if enough speech
self._reset_seconds_left -= self._seconds_per_chunk
if self._reset_seconds_left <= 0:
self._silence_seconds_left = self.silence_seconds
return True return True

View File

@ -865,8 +865,6 @@ async def _async_process_config(
entities = await _create_automation_entities(hass, updated_automation_configs) entities = await _create_automation_entities(hass, updated_automation_configs)
await component.async_add_entities(entities) await component.async_add_entities(entities)
return
async def _async_process_if( async def _async_process_if(
hass: HomeAssistant, name: str, config: dict[str, Any] hass: HomeAssistant, name: str, config: dict[str, Any]

View File

@ -276,17 +276,16 @@ class DaikinClimate(ClimateEntity):
await self._api.device.set_advanced_mode( await self._api.device.set_advanced_mode(
HA_PRESET_TO_DAIKIN[PRESET_ECO], ATTR_STATE_ON HA_PRESET_TO_DAIKIN[PRESET_ECO], ATTR_STATE_ON
) )
else: elif self.preset_mode == PRESET_AWAY:
if self.preset_mode == PRESET_AWAY: await self._api.device.set_holiday(ATTR_STATE_OFF)
await self._api.device.set_holiday(ATTR_STATE_OFF) elif self.preset_mode == PRESET_BOOST:
elif self.preset_mode == PRESET_BOOST: await self._api.device.set_advanced_mode(
await self._api.device.set_advanced_mode( HA_PRESET_TO_DAIKIN[PRESET_BOOST], ATTR_STATE_OFF
HA_PRESET_TO_DAIKIN[PRESET_BOOST], ATTR_STATE_OFF )
) elif self.preset_mode == PRESET_ECO:
elif self.preset_mode == PRESET_ECO: await self._api.device.set_advanced_mode(
await self._api.device.set_advanced_mode( HA_PRESET_TO_DAIKIN[PRESET_ECO], ATTR_STATE_OFF
HA_PRESET_TO_DAIKIN[PRESET_ECO], ATTR_STATE_OFF )
)
@property @property
def preset_modes(self): def preset_modes(self):

View File

@ -71,13 +71,12 @@ class DevoloLightDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, LightEntity):
self._multi_level_switch_property.set( self._multi_level_switch_property.set(
round(kwargs[ATTR_BRIGHTNESS] / 255 * 100) round(kwargs[ATTR_BRIGHTNESS] / 255 * 100)
) )
elif self._binary_switch_property is not None:
# Turn on the light device to the latest known value. The value is known by the device itself.
self._binary_switch_property.set(True)
else: else:
if self._binary_switch_property is not None: # If there is no binary switch attached to the device, turn it on to 100 %.
# Turn on the light device to the latest known value. The value is known by the device itself. self._multi_level_switch_property.set(100)
self._binary_switch_property.set(True)
else:
# If there is no binary switch attached to the device, turn it on to 100 %.
self._multi_level_switch_property.set(100)
def turn_off(self, **kwargs: Any) -> None: def turn_off(self, **kwargs: Any) -> None:
"""Turn device off.""" """Turn device off."""

View File

@ -350,14 +350,13 @@ class Doods(ImageProcessingEntity):
or boxes[3] > self._area[3] or boxes[3] > self._area[3]
): ):
continue continue
else: elif (
if ( boxes[0] > self._area[2]
boxes[0] > self._area[2] or boxes[1] > self._area[3]
or boxes[1] > self._area[3] or boxes[2] < self._area[0]
or boxes[2] < self._area[0] or boxes[3] < self._area[1]
or boxes[3] < self._area[1] ):
): continue
continue
# Exclude matches outside label specific area definition # Exclude matches outside label specific area definition
if self._label_areas.get(label): if self._label_areas.get(label):
@ -369,14 +368,13 @@ class Doods(ImageProcessingEntity):
or boxes[3] > self._label_areas[label][3] or boxes[3] > self._label_areas[label][3]
): ):
continue continue
else: elif (
if ( boxes[0] > self._label_areas[label][2]
boxes[0] > self._label_areas[label][2] or boxes[1] > self._label_areas[label][3]
or boxes[1] > self._label_areas[label][3] or boxes[2] < self._label_areas[label][0]
or boxes[2] < self._label_areas[label][0] or boxes[3] < self._label_areas[label][1]
or boxes[3] < self._label_areas[label][1] ):
): continue
continue
if label not in matches: if label not in matches:
matches[label] = [] matches[label] = []

View File

@ -459,9 +459,9 @@ async def async_setup_entry(
@callback @callback
def close_transport(_event: EventType) -> None: def close_transport(_event: EventType) -> None:
"""Close the transport on HA shutdown.""" """Close the transport on HA shutdown."""
if not transport: if not transport: # noqa: B023
return return
transport.close() transport.close() # noqa: B023
stop_listener = hass.bus.async_listen_once( stop_listener = hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STOP, close_transport EVENT_HOMEASSISTANT_STOP, close_transport

View File

@ -235,11 +235,10 @@ class FidoSensor(SensorEntity):
if (sensor_type := self.entity_description.key) == "balance": if (sensor_type := self.entity_description.key) == "balance":
if self.fido_data.data.get(sensor_type) is not None: if self.fido_data.data.get(sensor_type) is not None:
self._attr_native_value = round(self.fido_data.data[sensor_type], 2) self._attr_native_value = round(self.fido_data.data[sensor_type], 2)
else: elif self.fido_data.data.get(self._number, {}).get(sensor_type) is not None:
if self.fido_data.data.get(self._number, {}).get(sensor_type) is not None: self._attr_native_value = round(
self._attr_native_value = round( self.fido_data.data[self._number][sensor_type], 2
self.fido_data.data[self._number][sensor_type], 2 )
)
class FidoData: class FidoData:

View File

@ -442,14 +442,13 @@ class FitbitSensor(SensorEntity):
self._attr_native_value = f"{hours}:{minutes:02d} {setting}" self._attr_native_value = f"{hours}:{minutes:02d} {setting}"
else: else:
self._attr_native_value = raw_state self._attr_native_value = raw_state
elif self.is_metric:
self._attr_native_value = raw_state
else: else:
if self.is_metric: try:
self._attr_native_value = int(raw_state)
except TypeError:
self._attr_native_value = raw_state self._attr_native_value = raw_state
else:
try:
self._attr_native_value = int(raw_state)
except TypeError:
self._attr_native_value = raw_state
if resource_type == "activities/heart": if resource_type == "activities/heart":
self._attr_native_value = ( self._attr_native_value = (

View File

@ -51,9 +51,8 @@ class Light(CoordinatorEntity[Coordinator], LightEntity):
async with self.coordinator.async_connect_and_update() as device: async with self.coordinator.async_connect_and_update() as device:
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
await device.send_dim(int(kwargs[ATTR_BRIGHTNESS] * (100.0 / 255.0))) await device.send_dim(int(kwargs[ATTR_BRIGHTNESS] * (100.0 / 255.0)))
else: elif not self.is_on:
if not self.is_on: await device.send_command(COMMAND_LIGHT_ON_OFF)
await device.send_command(COMMAND_LIGHT_ON_OFF)
async def async_turn_off(self, **kwargs: Any) -> None: async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off.""" """Turn the entity off."""

View File

@ -435,17 +435,14 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
elif time is not None: elif time is not None:
# The time argument is passed only in keep-alive case # The time argument is passed only in keep-alive case
await self._async_device_turn_on() await self._async_device_turn_on()
else: elif (
if ( self._device_class == HumidifierDeviceClass.HUMIDIFIER and too_dry
self._device_class == HumidifierDeviceClass.HUMIDIFIER and too_dry ) or (self._device_class == HumidifierDeviceClass.DEHUMIDIFIER and too_wet):
) or ( _LOGGER.info("Turning on humidifier %s", self._switch_entity_id)
self._device_class == HumidifierDeviceClass.DEHUMIDIFIER and too_wet await self._async_device_turn_on()
): elif time is not None:
_LOGGER.info("Turning on humidifier %s", self._switch_entity_id) # The time argument is passed only in keep-alive case
await self._async_device_turn_on() await self._async_device_turn_off()
elif time is not None:
# The time argument is passed only in keep-alive case
await self._async_device_turn_off()
@property @property
def _is_device_active(self): def _is_device_active(self):

View File

@ -494,16 +494,15 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
self.heater_entity_id, self.heater_entity_id,
) )
await self._async_heater_turn_on() await self._async_heater_turn_on()
else: elif (self.ac_mode and too_hot) or (not self.ac_mode and too_cold):
if (self.ac_mode and too_hot) or (not self.ac_mode and too_cold): _LOGGER.info("Turning on heater %s", self.heater_entity_id)
_LOGGER.info("Turning on heater %s", self.heater_entity_id) await self._async_heater_turn_on()
await self._async_heater_turn_on() elif time is not None:
elif time is not None: # The time argument is passed only in keep-alive case
# The time argument is passed only in keep-alive case _LOGGER.info(
_LOGGER.info( "Keep-alive - Turning off heater %s", self.heater_entity_id
"Keep-alive - Turning off heater %s", self.heater_entity_id )
) await self._async_heater_turn_off()
await self._async_heater_turn_off()
@property @property
def _is_device_active(self): def _is_device_active(self):

View File

@ -278,7 +278,6 @@ async def async_devices_disconnect(
""" """
assert data.context.user_id is not None assert data.context.user_id is not None
await data.config.async_disconnect_agent_user(data.context.user_id) await data.config.async_disconnect_agent_user(data.context.user_id)
return None
@HANDLERS.register("action.devices.IDENTIFY") @HANDLERS.register("action.devices.IDENTIFY")

View File

@ -1008,24 +1008,22 @@ class TemperatureSettingTrait(_Trait):
), ),
1, 1,
) )
else: elif (target_temp := attrs.get(ATTR_TEMPERATURE)) is not None:
if (target_temp := attrs.get(ATTR_TEMPERATURE)) is not None: target_temp = round(
target_temp = round(
TemperatureConverter.convert(
target_temp, unit, UnitOfTemperature.CELSIUS
),
1,
)
response["thermostatTemperatureSetpointHigh"] = target_temp
response["thermostatTemperatureSetpointLow"] = target_temp
else:
if (target_temp := attrs.get(ATTR_TEMPERATURE)) is not None:
response["thermostatTemperatureSetpoint"] = round(
TemperatureConverter.convert( TemperatureConverter.convert(
target_temp, unit, UnitOfTemperature.CELSIUS target_temp, unit, UnitOfTemperature.CELSIUS
), ),
1, 1,
) )
response["thermostatTemperatureSetpointHigh"] = target_temp
response["thermostatTemperatureSetpointLow"] = target_temp
elif (target_temp := attrs.get(ATTR_TEMPERATURE)) is not None:
response["thermostatTemperatureSetpoint"] = round(
TemperatureConverter.convert(
target_temp, unit, UnitOfTemperature.CELSIUS
),
1,
)
return response return response

View File

@ -196,9 +196,8 @@ def expand_entity_ids(hass: HomeAssistant, entity_ids: Iterable[Any]) -> list[st
if ent_id not in found_ids if ent_id not in found_ids
) )
else: elif entity_id not in found_ids:
if entity_id not in found_ids: found_ids.append(entity_id)
found_ids.append(entity_id)
except AttributeError: except AttributeError:
# Raised by split_entity_id if entity_id is not a string # Raised by split_entity_id if entity_id is not a string

View File

@ -643,15 +643,14 @@ class GTFSDepartureSensor(SensorEntity):
# Define the state as a UTC timestamp with ISO 8601 format # Define the state as a UTC timestamp with ISO 8601 format
if not self._departure: if not self._departure:
self._state = None self._state = None
elif self._agency:
self._state = self._departure["departure_time"].replace(
tzinfo=dt_util.get_time_zone(self._agency.agency_timezone)
)
else: else:
if self._agency: self._state = self._departure["departure_time"].replace(
self._state = self._departure["departure_time"].replace( tzinfo=dt_util.UTC
tzinfo=dt_util.get_time_zone(self._agency.agency_timezone) )
)
else:
self._state = self._departure["departure_time"].replace(
tzinfo=dt_util.UTC
)
# Assign attributes, icon and name # Assign attributes, icon and name
self.update_attributes() self.update_attributes()

View File

@ -216,9 +216,8 @@ class HarmonyRemote(HarmonyEntity, RemoteEntity, RestoreEntity):
if not activity or activity == PREVIOUS_ACTIVE_ACTIVITY: if not activity or activity == PREVIOUS_ACTIVE_ACTIVITY:
if self._last_activity: if self._last_activity:
activity = self._last_activity activity = self._last_activity
else: elif all_activities := self._data.activity_names:
if all_activities := self._data.activity_names: activity = all_activities[0]
activity = all_activities[0]
if activity: if activity:
await self._data.async_start_activity(activity) await self._data.async_start_activity(activity)

View File

@ -41,9 +41,14 @@ SCHEMA_WEBSOCKET_EVENT = vol.Schema(
# Endpoints needed for ingress can't require admin because addons can set `panel_admin: false` # Endpoints needed for ingress can't require admin because addons can set `panel_admin: false`
# pylint: disable=implicit-str-concat # pylint: disable=implicit-str-concat
# fmt: off
WS_NO_ADMIN_ENDPOINTS = re.compile( WS_NO_ADMIN_ENDPOINTS = re.compile(
r"^(?:" r"|/ingress/(session|validate_session)" r"|/addons/[^/]+/info" r")$" r"^(?:"
r"|/ingress/(session|validate_session)"
r"|/addons/[^/]+/info"
r")$" # noqa: ISC001
) )
# fmt: on
# pylint: enable=implicit-str-concat # pylint: enable=implicit-str-concat
_LOGGER: logging.Logger = logging.getLogger(__package__) _LOGGER: logging.Logger = logging.getLogger(__package__)

View File

@ -62,28 +62,27 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
status = self.device.appliance.status status = self.device.appliance.status
if self._key not in status: if self._key not in status:
self._state = None self._state = None
else: elif self.device_class == SensorDeviceClass.TIMESTAMP:
if self.device_class == SensorDeviceClass.TIMESTAMP: if ATTR_VALUE not in status[self._key]:
if ATTR_VALUE not in status[self._key]: self._state = None
self._state = None elif (
elif ( self._state is not None
self._state is not None and self._sign == 1
and self._sign == 1 and self._state < dt_util.utcnow()
and self._state < dt_util.utcnow() ):
): # if the date is supposed to be in the future but we're
# if the date is supposed to be in the future but we're # already past it, set state to None.
# already past it, set state to None. self._state = None
self._state = None
else:
seconds = self._sign * float(status[self._key][ATTR_VALUE])
self._state = dt_util.utcnow() + timedelta(seconds=seconds)
else: else:
self._state = status[self._key].get(ATTR_VALUE) seconds = self._sign * float(status[self._key][ATTR_VALUE])
if self._key == BSH_OPERATION_STATE: self._state = dt_util.utcnow() + timedelta(seconds=seconds)
# Value comes back as an enum, we only really care about the else:
# last part, so split it off self._state = status[self._key].get(ATTR_VALUE)
# https://developer.home-connect.com/docs/status/operation_state if self._key == BSH_OPERATION_STATE:
self._state = self._state.split(".")[-1] # Value comes back as an enum, we only really care about the
# last part, so split it off
# https://developer.home-connect.com/docs/status/operation_state
self._state = self._state.split(".")[-1]
_LOGGER.debug("Updated, new state: %s", self._state) _LOGGER.debug("Updated, new state: %s", self._state)
@property @property

View File

@ -281,7 +281,7 @@ class HomeAccessory(Accessory): # type: ignore[misc]
display_name=cleanup_name_for_homekit(name), display_name=cleanup_name_for_homekit(name),
aid=aid, aid=aid,
iid_manager=HomeIIDManager(driver.iid_storage), iid_manager=HomeIIDManager(driver.iid_storage),
*args, *args, # noqa: B026
**kwargs, **kwargs,
) )
self.config = config or {} self.config = config or {}

View File

@ -164,7 +164,7 @@ class HomematicipGenericEntity(Entity):
else: else:
# Remove from entity registry. # Remove from entity registry.
# Only relevant for entities that do not belong to a device. # Only relevant for entities that do not belong to a device.
if entity_id := self.registry_entry.entity_id: if entity_id := self.registry_entry.entity_id: # noqa: PLR5501
entity_registry = er.async_get(self.hass) entity_registry = er.async_get(self.hass)
if entity_id in entity_registry.entities: if entity_id in entity_registry.entities:
entity_registry.async_remove(entity_id) entity_registry.async_remove(entity_id)
@ -185,9 +185,8 @@ class HomematicipGenericEntity(Entity):
if hasattr(self._device, "functionalChannels"): if hasattr(self._device, "functionalChannels"):
if self._is_multi_channel: if self._is_multi_channel:
name = self._device.functionalChannels[self._channel].label name = self._device.functionalChannels[self._channel].label
else: elif len(self._device.functionalChannels) > 1:
if len(self._device.functionalChannels) > 1: name = self._device.functionalChannels[1].label
name = self._device.functionalChannels[1].label
# Use device label, if name is not defined by channel label. # Use device label, if name is not defined by channel label.
if not name: if not name:

View File

@ -337,15 +337,14 @@ class HyperionBaseLight(LightEntity):
): ):
return return
# == Set a color # == Set a color
else: elif not await self._client.async_send_set_color(
if not await self._client.async_send_set_color( **{
**{ const.KEY_PRIORITY: self._get_option(CONF_PRIORITY),
const.KEY_PRIORITY: self._get_option(CONF_PRIORITY), const.KEY_COLOR: rgb_color,
const.KEY_COLOR: rgb_color, const.KEY_ORIGIN: DEFAULT_ORIGIN,
const.KEY_ORIGIN: DEFAULT_ORIGIN, }
} ):
): return
return
def _set_internal_state( def _set_internal_state(
self, self,

View File

@ -263,13 +263,12 @@ class IcloudFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
self.api.validate_2fa_code, self._verification_code self.api.validate_2fa_code, self._verification_code
): ):
raise PyiCloudException("The code you entered is not valid.") raise PyiCloudException("The code you entered is not valid.")
else: elif not await self.hass.async_add_executor_job(
if not await self.hass.async_add_executor_job( self.api.validate_verification_code,
self.api.validate_verification_code, self._trusted_device,
self._trusted_device, self._verification_code,
self._verification_code, ):
): raise PyiCloudException("The code you entered is not valid.")
raise PyiCloudException("The code you entered is not valid.")
except PyiCloudException as error: except PyiCloudException as error:
# Reset to the initial 2FA state to allow the user to retry # Reset to the initial 2FA state to allow the user to retry
_LOGGER.error("Failed to verify verification code: %s", error) _LOGGER.error("Failed to verify verification code: %s", error)

View File

@ -96,29 +96,26 @@ class IhcLight(IHCDevice, LightEntity):
"""Turn the light on.""" """Turn the light on."""
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs[ATTR_BRIGHTNESS] brightness = kwargs[ATTR_BRIGHTNESS]
else: elif (brightness := self._brightness) == 0:
if (brightness := self._brightness) == 0: brightness = 255
brightness = 255
if self._dimmable: if self._dimmable:
await async_set_int( await async_set_int(
self.hass, self.ihc_controller, self.ihc_id, int(brightness * 100 / 255) self.hass, self.ihc_controller, self.ihc_id, int(brightness * 100 / 255)
) )
elif self._ihc_on_id:
await async_pulse(self.hass, self.ihc_controller, self._ihc_on_id)
else: else:
if self._ihc_on_id: await async_set_bool(self.hass, self.ihc_controller, self.ihc_id, True)
await async_pulse(self.hass, self.ihc_controller, self._ihc_on_id)
else:
await async_set_bool(self.hass, self.ihc_controller, self.ihc_id, True)
async def async_turn_off(self, **kwargs: Any) -> None: async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off.""" """Turn the light off."""
if self._dimmable: if self._dimmable:
await async_set_int(self.hass, self.ihc_controller, self.ihc_id, 0) await async_set_int(self.hass, self.ihc_controller, self.ihc_id, 0)
elif self._ihc_off_id:
await async_pulse(self.hass, self.ihc_controller, self._ihc_off_id)
else: else:
if self._ihc_off_id: await async_set_bool(self.hass, self.ihc_controller, self.ihc_id, False)
await async_pulse(self.hass, self.ihc_controller, self._ihc_off_id)
else:
await async_set_bool(self.hass, self.ihc_controller, self.ihc_id, False)
def on_ihc_change(self, ihc_id, value): def on_ihc_change(self, ihc_id, value):
"""Handle IHC notifications.""" """Handle IHC notifications."""

View File

@ -145,12 +145,11 @@ def validate_version_specific_config(conf: dict) -> dict:
f" {CONF_API_VERSION} is {DEFAULT_API_VERSION}" f" {CONF_API_VERSION} is {DEFAULT_API_VERSION}"
) )
else: elif CONF_TOKEN in conf:
if CONF_TOKEN in conf: raise vol.Invalid(
raise vol.Invalid( f"{CONF_TOKEN} and {CONF_BUCKET} are only allowed when"
f"{CONF_TOKEN} and {CONF_BUCKET} are only allowed when" f" {CONF_API_VERSION} is {API_VERSION_2}"
f" {CONF_API_VERSION} is {API_VERSION_2}" )
)
return conf return conf

View File

@ -292,13 +292,12 @@ class InputDatetime(collection.CollectionEntity, RestoreEntity):
else: else:
current_datetime = py_datetime.datetime.combine(date, DEFAULT_TIME) current_datetime = py_datetime.datetime.combine(date, DEFAULT_TIME)
elif (time := dt_util.parse_time(old_state.state)) is None:
current_datetime = dt_util.parse_datetime(default_value)
else: else:
if (time := dt_util.parse_time(old_state.state)) is None: current_datetime = py_datetime.datetime.combine(
current_datetime = dt_util.parse_datetime(default_value) py_datetime.date.today(), time
else: )
current_datetime = py_datetime.datetime.combine(
py_datetime.date.today(), time
)
self._current_datetime = current_datetime.replace( self._current_datetime = current_datetime.replace(
tzinfo=dt_util.DEFAULT_TIME_ZONE tzinfo=dt_util.DEFAULT_TIME_ZONE

View File

@ -76,10 +76,9 @@ async def async_setup_entry(
options = RAMP_RATE_OPTIONS options = RAMP_RATE_OPTIONS
elif control == CMD_BACKLIGHT: elif control == CMD_BACKLIGHT:
options = BACKLIGHT_INDEX options = BACKLIGHT_INDEX
else: elif uom := node.aux_properties[control].uom == UOM_INDEX:
if uom := node.aux_properties[control].uom == UOM_INDEX: if options_dict := UOM_TO_STATES.get(uom):
if options_dict := UOM_TO_STATES.get(uom): options = list(options_dict.values())
options = list(options_dict.values())
description = SelectEntityDescription( description = SelectEntityDescription(
key=f"{node.address}_{control}", key=f"{node.address}_{control}",

View File

@ -116,18 +116,18 @@ class DoorLockFeature(IntFlag):
Should be replaced by the library provided one once that is released. Should be replaced by the library provided one once that is released.
""" """
kPinCredential = 0x1 kPinCredential = 0x1 # noqa: N815
kRfidCredential = 0x2 kRfidCredential = 0x2 # noqa: N815
kFingerCredentials = 0x4 kFingerCredentials = 0x4 # noqa: N815
kLogging = 0x8 kLogging = 0x8 # noqa: N815
kWeekDayAccessSchedules = 0x10 kWeekDayAccessSchedules = 0x10 # noqa: N815
kDoorPositionSensor = 0x20 kDoorPositionSensor = 0x20 # noqa: N815
kFaceCredentials = 0x40 kFaceCredentials = 0x40 # noqa: N815
kCredentialsOverTheAirAccess = 0x80 kCredentialsOverTheAirAccess = 0x80 # noqa: N815
kUser = 0x100 kUser = 0x100 # noqa: N815
kNotification = 0x200 kNotification = 0x200 # noqa: N815
kYearDayAccessSchedules = 0x400 kYearDayAccessSchedules = 0x400 # noqa: N815
kHolidaySchedules = 0x800 kHolidaySchedules = 0x800 # noqa: N815
DISCOVERY_SCHEMAS = [ DISCOVERY_SCHEMAS = [

View File

@ -42,9 +42,8 @@ def async_process_play_media_url(
if parsed.is_absolute(): if parsed.is_absolute():
if not is_hass_url(hass, media_content_id): if not is_hass_url(hass, media_content_id):
return media_content_id return media_content_id
else: elif media_content_id[0] != "/":
if media_content_id[0] != "/": return media_content_id
return media_content_id
if parsed.query: if parsed.query:
logging.getLogger(__name__).debug( logging.getLogger(__name__).debug(

View File

@ -271,11 +271,10 @@ class MeteoFranceSensor(CoordinatorEntity[DataUpdateCoordinator[_DataT]], Sensor
value = data[0][path[1]] value = data[0][path[1]]
# General case # General case
elif len(path) == 3:
value = data[path[1]][path[2]]
else: else:
if len(path) == 3: value = data[path[1]]
value = data[path[1]][path[2]]
else:
value = data[path[1]]
if self.entity_description.key in ("wind_speed", "wind_gust"): if self.entity_description.key in ("wind_speed", "wind_gust"):
# convert API wind speed from m/s to km/h # convert API wind speed from m/s to km/h

View File

@ -234,11 +234,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await register_webhook(None) await register_webhook(None)
cloud.async_listen_connection_change(hass, manage_cloudhook) cloud.async_listen_connection_change(hass, manage_cloudhook)
elif hass.state == CoreState.running:
await register_webhook(None)
else: else:
if hass.state == CoreState.running: hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, register_webhook)
await register_webhook(None)
else:
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, register_webhook)
hass.services.async_register(DOMAIN, "register_webhook", register_webhook) hass.services.async_register(DOMAIN, "register_webhook", register_webhook)
hass.services.async_register(DOMAIN, "unregister_webhook", unregister_webhook) hass.services.async_register(DOMAIN, "unregister_webhook", unregister_webhook)

View File

@ -199,7 +199,8 @@ class PlexServer:
if _update_plexdirect_hostname(): if _update_plexdirect_hostname():
config_entry_update_needed = True config_entry_update_needed = True
else: else:
raise Unauthorized( # pylint: disable=raise-missing-from # pylint: disable-next=raise-missing-from
raise Unauthorized( # noqa: TRY200
"New certificate cannot be validated" "New certificate cannot be validated"
" with provided token" " with provided token"
) )

View File

@ -145,7 +145,7 @@ def process_plex_payload(
plex_server = get_plex_server(hass, plex_server_id=server_id) plex_server = get_plex_server(hass, plex_server_id=server_id)
else: else:
# Handle legacy payloads without server_id in URL host position # Handle legacy payloads without server_id in URL host position
if plex_url.host == "search": if plex_url.host == "search": # noqa: PLR5501
content = {} content = {}
else: else:
content = int(plex_url.host) # type: ignore[arg-type] content = int(plex_url.host) # type: ignore[arg-type]

View File

@ -192,12 +192,10 @@ class PS4Device(MediaPlayerEntity):
self.async_get_title_data(title_id, name), self.async_get_title_data(title_id, name),
"ps4.media_player-get_title_data", "ps4.media_player-get_title_data",
) )
else: elif self.state != MediaPlayerState.IDLE:
if self.state != MediaPlayerState.IDLE: self.idle()
self.idle() elif self.state != MediaPlayerState.STANDBY:
else: self.state_standby()
if self.state != MediaPlayerState.STANDBY:
self.state_standby()
elif self._retry > DEFAULT_RETRIES: elif self._retry > DEFAULT_RETRIES:
self.state_unknown() self.state_unknown()

View File

@ -221,7 +221,7 @@ def execute(hass, filename, source, data=None):
try: try:
_LOGGER.info("Executing %s: %s", filename, data) _LOGGER.info("Executing %s: %s", filename, data)
# pylint: disable-next=exec-used # pylint: disable-next=exec-used
exec(compiled.code, restricted_globals) exec(compiled.code, restricted_globals) # noqa: S102
except ScriptError as err: except ScriptError as err:
logger.error("Error executing script: %s", err) logger.error("Error executing script: %s", err)
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except

View File

@ -434,11 +434,11 @@ def _state_changed_during_period_stmt(
) )
else: else:
stmt += lambda q: q.order_by(States.entity_id, States.last_updated.desc()) stmt += lambda q: q.order_by(States.entity_id, States.last_updated.desc())
elif schema_version >= 31:
stmt += lambda q: q.order_by(States.entity_id, States.last_updated_ts)
else: else:
if schema_version >= 31: stmt += lambda q: q.order_by(States.entity_id, States.last_updated)
stmt += lambda q: q.order_by(States.entity_id, States.last_updated_ts)
else:
stmt += lambda q: q.order_by(States.entity_id, States.last_updated)
if limit: if limit:
stmt += lambda q: q.limit(limit) stmt += lambda q: q.limit(limit)
return stmt return stmt

View File

@ -530,11 +530,10 @@ def setup_connection_for_dialect(
version, version,
) )
else: elif not version or version < MIN_VERSION_MYSQL:
if not version or version < MIN_VERSION_MYSQL: _fail_unsupported_version(
_fail_unsupported_version( version or version_string, "MySQL", MIN_VERSION_MYSQL
version or version_string, "MySQL", MIN_VERSION_MYSQL )
)
slow_range_in_select = bool( slow_range_in_select = bool(
not version not version

View File

@ -232,12 +232,11 @@ class RestSwitch(TemplateEntity, SwitchEntity):
self._attr_is_on = False self._attr_is_on = False
else: else:
self._attr_is_on = None self._attr_is_on = None
elif text == self._body_on.template:
self._attr_is_on = True
elif text == self._body_off.template:
self._attr_is_on = False
else: else:
if text == self._body_on.template: self._attr_is_on = None
self._attr_is_on = True
elif text == self._body_off.template:
self._attr_is_on = False
else:
self._attr_is_on = None
return req return req

View File

@ -549,7 +549,7 @@ class SamsungTVWSBridge(
except (ConnectionFailure, OSError, AsyncioTimeoutError) as err: except (ConnectionFailure, OSError, AsyncioTimeoutError) as err:
LOGGER.debug("Failing config: %s, %s error: %s", config, type(err), err) LOGGER.debug("Failing config: %s, %s error: %s", config, type(err), err)
# pylint: disable-next=useless-else-on-loop # pylint: disable-next=useless-else-on-loop
else: else: # noqa: PLW0120
if result: if result:
return result return result

View File

@ -184,7 +184,6 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
raise AbortFlow(result) raise AbortFlow(result)
assert method is not None assert method is not None
self._bridge = SamsungTVBridge.get_bridge(self.hass, method, self._host) self._bridge = SamsungTVBridge.get_bridge(self.hass, method, self._host)
return
async def _async_get_device_info_and_method( async def _async_get_device_info_and_method(
self, self,

View File

@ -80,11 +80,10 @@ class SatelIntegraBinarySensor(BinarySensorEntity):
self._state = 1 self._state = 1
else: else:
self._state = 0 self._state = 0
elif self._device_number in self._satel.violated_zones:
self._state = 1
else: else:
if self._device_number in self._satel.violated_zones: self._state = 0
self._state = 1
else:
self._state = 0
self.async_on_remove( self.async_on_remove(
async_dispatcher_connect( async_dispatcher_connect(
self.hass, self._react_to_signal, self._devices_updated self.hass, self._react_to_signal, self._devices_updated

View File

@ -168,4 +168,3 @@ class ScreenlogicDataUpdateCoordinator(DataUpdateCoordinator[None]):
if self.gateway.is_connected: if self.gateway.is_connected:
await self.gateway.async_disconnect() await self.gateway.async_disconnect()
raise UpdateFailed(ex.msg) from ex raise UpdateFailed(ex.msg) from ex
return None

View File

@ -74,7 +74,7 @@ class SCSGate:
def handle_message(self, message): def handle_message(self, message):
"""Handle a messages seen on the bus.""" """Handle a messages seen on the bus."""
self._logger.debug(f"Received message {message}") self._logger.debug("Received message %s", message)
if not isinstance(message, StateMessage) and not isinstance( if not isinstance(message, StateMessage) and not isinstance(
message, ScenarioTriggeredMessage message, ScenarioTriggeredMessage
): ):
@ -98,9 +98,7 @@ class SCSGate:
self._logger.error(msg) self._logger.error(msg)
else: else:
self._logger.info( self._logger.info(
"Ignoring state message for device {} because unknown".format( "Ignoring state message for device %s because unknown", message.entity
message.entity
)
) )
@property @property

View File

@ -200,18 +200,13 @@ def async_setup_rpc_attribute_entities(
domain = sensor_class.__module__.split(".")[-1] domain = sensor_class.__module__.split(".")[-1]
unique_id = f"{coordinator.mac}-{key}-{sensor_id}" unique_id = f"{coordinator.mac}-{key}-{sensor_id}"
async_remove_shelly_entity(hass, domain, unique_id) async_remove_shelly_entity(hass, domain, unique_id)
else: elif description.use_polling_coordinator:
if description.use_polling_coordinator: if not sleep_period:
if not sleep_period:
entities.append(
sensor_class(
polling_coordinator, key, sensor_id, description
)
)
else:
entities.append( entities.append(
sensor_class(coordinator, key, sensor_id, description) sensor_class(polling_coordinator, key, sensor_id, description)
) )
else:
entities.append(sensor_class(coordinator, key, sensor_id, description))
if not entities: if not entities:
return return

View File

@ -176,7 +176,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
await mqtt.async_publish( await mqtt.async_publish(
hass, "hermes/dialogueManager/startSession", json.dumps(notification) hass, "hermes/dialogueManager/startSession", json.dumps(notification)
) )
return
async def snips_say_action(call: ServiceCall) -> None: async def snips_say_action(call: ServiceCall) -> None:
"""Send a Snips action message.""" """Send a Snips action message."""
@ -193,7 +192,6 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
await mqtt.async_publish( await mqtt.async_publish(
hass, "hermes/dialogueManager/startSession", json.dumps(notification) hass, "hermes/dialogueManager/startSession", json.dumps(notification)
) )
return
async def feedback_on(call: ServiceCall) -> None: async def feedback_on(call: ServiceCall) -> None:
"""Turn feedback sounds on.""" """Turn feedback sounds on."""

View File

@ -56,7 +56,7 @@ class SolarlogData(update_coordinator.DataUpdateCoordinator):
try: try:
data = await self.hass.async_add_executor_job(SolarLog, self.host) data = await self.hass.async_add_executor_job(SolarLog, self.host)
except (OSError, Timeout, HTTPError) as err: except (OSError, Timeout, HTTPError) as err:
raise update_coordinator.UpdateFailed(err) raise update_coordinator.UpdateFailed(err) from err
if data.time.year == 1999: if data.time.year == 1999:
raise update_coordinator.UpdateFailed( raise update_coordinator.UpdateFailed(

View File

@ -68,9 +68,8 @@ class SolarLogConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
if self._host_in_configuration_exists(host): if self._host_in_configuration_exists(host):
self._errors[CONF_HOST] = "already_configured" self._errors[CONF_HOST] = "already_configured"
else: elif await self._test_connection(host):
if await self._test_connection(host): return self.async_create_entry(title=name, data={CONF_HOST: host})
return self.async_create_entry(title=name, data={CONF_HOST: host})
else: else:
user_input = {} user_input = {}
user_input[CONF_NAME] = DEFAULT_NAME user_input[CONF_NAME] = DEFAULT_NAME

View File

@ -82,9 +82,8 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
stat = "{}.{}".format(state.entity_id, key.replace(" ", "_")) stat = "{}.{}".format(state.entity_id, key.replace(" ", "_"))
statsd_client.gauge(stat, value, sample_rate) statsd_client.gauge(stat, value, sample_rate)
else: elif isinstance(_state, (float, int)):
if isinstance(_state, (float, int)): statsd_client.gauge(state.entity_id, _state, sample_rate)
statsd_client.gauge(state.entity_id, _state, sample_rate)
# Increment the count # Increment the count
statsd_client.incr(state.entity_id, rate=sample_rate) statsd_client.incr(state.entity_id, rate=sample_rate)

View File

@ -102,7 +102,8 @@ async def discover_devices(hass, hass_config):
async with async_timeout.timeout(SCAN_INTERVAL.total_seconds()): async with async_timeout.timeout(SCAN_INTERVAL.total_seconds()):
channels = { channels = {
channel["id"]: channel channel["id"]: channel
for channel in await server.get_channels( # pylint: disable=cell-var-from-loop # pylint: disable-next=cell-var-from-loop
for channel in await server.get_channels( # noqa: B023
include=["iodevice", "state", "connected"] include=["iodevice", "state", "connected"]
) )
} }

View File

@ -99,7 +99,6 @@ class SynologyDSMCentralUpdateCoordinator(SynologyDSMUpdateCoordinator[None]):
await self.api.async_update() await self.api.async_update()
except SYNOLOGY_CONNECTION_EXCEPTIONS as err: except SYNOLOGY_CONNECTION_EXCEPTIONS as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err raise UpdateFailed(f"Error communicating with API: {err}") from err
return None
class SynologyDSMCameraUpdateCoordinator( class SynologyDSMCameraUpdateCoordinator(

View File

@ -123,8 +123,6 @@ class VenstarDataUpdateCoordinator(update_coordinator.DataUpdateCoordinator[None
f"Exception during Venstar runtime update: {ex}" f"Exception during Venstar runtime update: {ex}"
) from ex ) from ex
return None
class VenstarEntity(CoordinatorEntity[VenstarDataUpdateCoordinator]): class VenstarEntity(CoordinatorEntity[VenstarDataUpdateCoordinator]):
"""Representation of a Venstar entity.""" """Representation of a Venstar entity."""

View File

@ -178,7 +178,7 @@ class ActiveConnection:
return return
if not (handler_schema := self.handlers.get(type_)): if not (handler_schema := self.handlers.get(type_)):
self.logger.info(f"Received unknown command: {type_}") self.logger.info("Received unknown command: %s", type_)
self.send_message( self.send_message(
messages.error_message( messages.error_message(
cur_id, const.ERR_UNKNOWN_COMMAND, "Unknown command." cur_id, const.ERR_UNKNOWN_COMMAND, "Unknown command."

View File

@ -129,9 +129,8 @@ class WorxLandroidSensor(SensorEntity):
elif self.sensor == "state": elif self.sensor == "state":
self._state = self.get_state(data) self._state = self.get_state(data)
else: elif self.sensor == "error":
if self.sensor == "error": self._state = "no"
self._state = "no"
@staticmethod @staticmethod
def get_error(obj): def get_error(obj):

View File

@ -74,17 +74,16 @@ class SunflowerBulb(LightEntity):
# when no arguments, just turn light on (full brightness) # when no arguments, just turn light on (full brightness)
if not kwargs: if not kwargs:
self._light.turn_on() self._light.turn_on()
else: elif ATTR_HS_COLOR in kwargs and ATTR_BRIGHTNESS in kwargs:
if ATTR_HS_COLOR in kwargs and ATTR_BRIGHTNESS in kwargs: rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100)
bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100) self._light.set_all(rgb[0], rgb[1], rgb[2], bright)
self._light.set_all(rgb[0], rgb[1], rgb[2], bright) elif ATTR_HS_COLOR in kwargs:
elif ATTR_HS_COLOR in kwargs: rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR])
rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) self._light.set_rgb_color(rgb[0], rgb[1], rgb[2])
self._light.set_rgb_color(rgb[0], rgb[1], rgb[2]) elif ATTR_BRIGHTNESS in kwargs:
elif ATTR_BRIGHTNESS in kwargs: bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100)
bright = int(kwargs[ATTR_BRIGHTNESS] / 255 * 100) self._light.set_brightness(bright)
self._light.set_brightness(bright)
def turn_off(self, **kwargs: Any) -> None: def turn_off(self, **kwargs: Any) -> None:
"""Instruct the light to turn off.""" """Instruct the light to turn off."""

View File

@ -67,17 +67,14 @@ def setup_platform(
for hostid in hostids: for hostid in hostids:
_LOGGER.debug("Creating Zabbix Sensor: %s", str(hostid)) _LOGGER.debug("Creating Zabbix Sensor: %s", str(hostid))
sensors.append(ZabbixSingleHostTriggerCountSensor(zapi, [hostid], name)) sensors.append(ZabbixSingleHostTriggerCountSensor(zapi, [hostid], name))
elif not hostids:
# Single sensor that provides the total count of triggers.
_LOGGER.debug("Creating Zabbix Sensor")
sensors.append(ZabbixTriggerCountSensor(zapi, name))
else: else:
if not hostids: # Single sensor that sums total issues for all hosts
# Single sensor that provides the total count of triggers. _LOGGER.debug("Creating Zabbix Sensor group: %s", str(hostids))
_LOGGER.debug("Creating Zabbix Sensor") sensors.append(ZabbixMultipleHostTriggerCountSensor(zapi, hostids, name))
sensors.append(ZabbixTriggerCountSensor(zapi, name))
else:
# Single sensor that sums total issues for all hosts
_LOGGER.debug("Creating Zabbix Sensor group: %s", str(hostids))
sensors.append(
ZabbixMultipleHostTriggerCountSensor(zapi, hostids, name)
)
else: else:
# Single sensor that provides the total count of triggers. # Single sensor that provides the total count of triggers.

View File

@ -62,11 +62,10 @@ def setup_platform(
# Check if a connection can be established to the device. # Check if a connection can be established to the device.
if mediabox.test_connection(): if mediabox.test_connection():
connection_successful = True connection_successful = True
elif manual_config:
_LOGGER.info("Can't connect to %s", host)
else: else:
if manual_config: _LOGGER.error("Can't connect to %s", host)
_LOGGER.info("Can't connect to %s", host)
else:
_LOGGER.error("Can't connect to %s", host)
# When the device is in eco mode it's not connected to the network # When the device is in eco mode it's not connected to the network
# so it needs to be added anyway if it's configured manually. # so it needs to be added anyway if it's configured manually.
if manual_config or connection_successful: if manual_config or connection_successful:

View File

@ -724,7 +724,7 @@ def socket_timeout(value: Any | None) -> object:
return float_value return float_value
raise vol.Invalid("Invalid socket timeout value. float > 0.0 required.") raise vol.Invalid("Invalid socket timeout value. float > 0.0 required.")
except Exception as err: except Exception as err:
raise vol.Invalid(f"Invalid socket timeout: {err}") raise vol.Invalid(f"Invalid socket timeout: {err}") from err
# pylint: disable=no-value-for-parameter # pylint: disable=no-value-for-parameter
@ -761,7 +761,7 @@ def uuid4_hex(value: Any) -> str:
try: try:
result = UUID(value, version=4) result = UUID(value, version=4)
except (ValueError, AttributeError, TypeError) as error: except (ValueError, AttributeError, TypeError) as error:
raise vol.Invalid("Invalid Version4 UUID", error_message=str(error)) raise vol.Invalid("Invalid Version4 UUID", error_message=str(error)) from error
if result.hex != value.lower(): if result.hex != value.lower():
# UUID() will create a uuid4 if input is invalid # UUID() will create a uuid4 if input is invalid
@ -1226,7 +1226,7 @@ def script_action(value: Any) -> dict:
try: try:
action = determine_script_action(value) action = determine_script_action(value)
except ValueError as err: except ValueError as err:
raise vol.Invalid(str(err)) raise vol.Invalid(str(err)) from err
return ACTION_TYPE_SCHEMAS[action](value) return ACTION_TYPE_SCHEMAS[action](value)

View File

@ -753,7 +753,7 @@ class EntityPlatform:
if already_exists: if already_exists:
self.logger.error( self.logger.error(
f"Entity id already exists - ignoring: {entity.entity_id}" "Entity id already exists - ignoring: %s", entity.entity_id
) )
entity.add_to_platform_abort() entity.add_to_platform_abort()
return return

View File

@ -1527,11 +1527,10 @@ class Script:
variables = {} variables = {}
variables["context"] = context variables["context"] = context
elif self._copy_variables_on_run:
variables = cast(dict, copy(run_variables))
else: else:
if self._copy_variables_on_run: variables = cast(dict, run_variables)
variables = cast(dict, copy(run_variables))
else:
variables = cast(dict, run_variables)
# Prevent non-allowed recursive calls which will cause deadlocks when we try to # Prevent non-allowed recursive calls which will cause deadlocks when we try to
# stop (restart) or wait for (queued) our own script run. # stop (restart) or wait for (queued) our own script run.

View File

@ -81,7 +81,8 @@ def set_default_time_zone(time_zone: dt.tzinfo) -> None:
Async friendly. Async friendly.
""" """
global DEFAULT_TIME_ZONE # pylint: disable=global-statement # pylint: disable-next=global-statement
global DEFAULT_TIME_ZONE # noqa: PLW0603
assert isinstance(time_zone, dt.tzinfo) assert isinstance(time_zone, dt.tzinfo)

View File

@ -163,19 +163,223 @@ disable = [
"too-few-public-methods", "too-few-public-methods",
"too-many-ancestors", "too-many-ancestors",
"too-many-arguments", "too-many-arguments",
"too-many-branches",
"too-many-instance-attributes", "too-many-instance-attributes",
"too-many-lines", "too-many-lines",
"too-many-locals", "too-many-locals",
"too-many-public-methods", "too-many-public-methods",
"too-many-return-statements",
"too-many-statements",
"too-many-boolean-expressions", "too-many-boolean-expressions",
"unused-argument",
"wrong-import-order", "wrong-import-order",
"consider-using-f-string", "consider-using-f-string",
"consider-using-namedtuple-or-dataclass", "consider-using-namedtuple-or-dataclass",
"consider-using-assignment-expr", "consider-using-assignment-expr",
# Handled by ruff
# Ref: <https://github.com/astral-sh/ruff/issues/970>
"await-outside-async", # PLE1142
"bad-str-strip-call", # PLE1310
"bad-string-format-type", # PLE1307
"bidirectional-unicode", # PLE2502
"continue-in-finally", # PLE0116
"duplicate-bases", # PLE0241
"format-needs-mapping", # F502
"function-redefined", # F811
"invalid-all-format", # PLE0605
"invalid-all-object", # PLE0604
"invalid-character-backspace", # PLE2510
"invalid-character-esc", # PLE2513
"invalid-character-nul", # PLE2514
"invalid-character-sub", # PLE2512
"invalid-character-zero-width-space", # PLE2515
"logging-too-few-args", # PLE1206
"logging-too-many-args", # PLE1205
"missing-format-string-key", # F524
"mixed-format-string", # F506
"no-method-argument", # N805
"no-self-argument", # N805
"nonexistent-operator", # B002
"nonlocal-without-binding", # PLE0117
"not-in-loop", # F701, F702
"notimplemented-raised", # F901
"return-in-init", # PLE0101
"return-outside-function", # F706
"syntax-error", # E999
"too-few-format-args", # F524
"too-many-format-args", # F522
"too-many-star-expressions", # F622
"truncated-format-string", # F501
"undefined-all-variable", # F822
"undefined-variable", # F821
"used-prior-global-declaration", # PLE0118
"yield-inside-async-function", # PLE1700
"yield-outside-function", # F704
"anomalous-backslash-in-string", # W605
"assert-on-string-literal", # PLW0129
"assert-on-tuple", # F631
"bad-format-string", # W1302, F
"bad-format-string-key", # W1300, F
"bare-except", # E722
"binary-op-exception", # PLW0711
"cell-var-from-loop", # B023
# "dangerous-default-value", # B006, ruff catches new occurrences, needs more work
"duplicate-except", # B014
"duplicate-key", # F601
"duplicate-string-formatting-argument", # F
"duplicate-value", # F
"eval-used", # PGH001
"exec-used", # S102
# "expression-not-assigned", # B018, ruff catches new occurrences, needs more work
"f-string-without-interpolation", # F541
"forgotten-debug-statement", # T100
"format-string-without-interpolation", # F
# "global-statement", # PLW0603, ruff catches new occurrences, needs more work
"global-variable-not-assigned", # PLW0602
"implicit-str-concat", # ISC001
"import-self", # PLW0406
"inconsistent-quotes", # Q000
"invalid-envvar-default", # PLW1508
"keyword-arg-before-vararg", # B026
"logging-format-interpolation", # G
"logging-fstring-interpolation", # G
"logging-not-lazy", # G
"misplaced-future", # F404
"named-expr-without-context", # PLW0131
"nested-min-max", # PLW3301
# "pointless-statement", # B018, ruff catches new occurrences, needs more work
"raise-missing-from", # TRY200
# "redefined-builtin", # A001, ruff is way more stricter, needs work
"try-except-raise", # TRY302
"unused-argument", # ARG001, we don't use it
"unused-format-string-argument", #F507
"unused-format-string-key", # F504
"unused-import", # F401
"unused-variable", # F841
"useless-else-on-loop", # PLW0120
"wildcard-import", # F403
"bad-classmethod-argument", # N804
"consider-iterating-dictionary", # SIM118
"empty-docstring", # D419
"invalid-name", # N815
"line-too-long", # E501, disabled globally
"missing-class-docstring", # D101
"missing-final-newline", # W292
"missing-function-docstring", # D103
"missing-module-docstring", # D100
"multiple-imports", #E401
"singleton-comparison", # E711, E712
"superfluous-parens", # UP034
"ungrouped-imports", # I001
"unidiomatic-typecheck", # E721
"unnecessary-direct-lambda-call", # PLC3002
"unnecessary-lambda-assignment", # PLC3001
"unneeded-not", # SIM208
"useless-import-alias", # PLC0414
"wrong-import-order", # I001
"wrong-import-position", # E402
"comparison-of-constants", # PLR0133
"comparison-with-itself", # PLR0124
"consider-alternative-union-syntax", # UP007
"consider-merging-isinstance", # PLR1701
"consider-using-alias", # UP006
"consider-using-dict-comprehension", # C402
"consider-using-generator", # C417
"consider-using-get", # SIM401
"consider-using-set-comprehension", # C401
"consider-using-sys-exit", # PLR1722
"consider-using-ternary", # SIM108
"literal-comparison", # F632
"property-with-parameters", # PLR0206
"super-with-arguments", # UP008
"too-many-branches", # PLR0912
"too-many-return-statements", # PLR0911
"too-many-statements", # PLR0915
"trailing-comma-tuple", # COM818
"unnecessary-comprehension", # C416
"use-a-generator", # C417
"use-dict-literal", # C406
"use-list-literal", # C405
"useless-object-inheritance", # UP004
"useless-return", # PLR1711
# Handled by mypy
# Ref: <https://github.com/antonagestam/pylint-mypy-overlap>
"abstract-class-instantiated",
"arguments-differ",
"assigning-non-slot",
"assignment-from-no-return",
"assignment-from-none",
"bad-exception-cause",
"bad-format-character",
"bad-reversed-sequence",
"bad-super-call",
"bad-thread-instantiation",
"catching-non-exception",
"comparison-with-callable",
"deprecated-class",
"dict-iter-missing-items",
"format-combined-specification",
"global-variable-undefined",
"import-error",
"inconsistent-mro",
"inherit-non-class",
"init-is-generator",
"invalid-class-object",
"invalid-enum-extension",
"invalid-envvar-value",
"invalid-format-returned",
"invalid-hash-returned",
"invalid-metaclass",
"invalid-overridden-method",
"invalid-repr-returned",
"invalid-sequence-index",
"invalid-slice-index",
"invalid-slots-object",
"invalid-slots",
"invalid-star-assignment-target",
"invalid-str-returned",
"invalid-unary-operand-type",
"invalid-unicode-codec",
"isinstance-second-argument-not-valid-type",
"method-hidden",
"misplaced-format-function",
"missing-format-argument-key",
"missing-format-attribute",
"missing-kwoa",
"no-member",
"no-value-for-parameter",
"non-iterator-returned",
"non-str-assignment-to-dunder-name",
"nonlocal-and-global",
"not-a-mapping",
"not-an-iterable",
"not-async-context-manager",
"not-callable",
"not-context-manager",
"overridden-final-method",
"raising-bad-type",
"raising-non-exception",
"redundant-keyword-arg",
"relative-beyond-top-level",
"self-cls-assignment",
"signature-differs",
"star-needs-assignment-target",
"subclassed-final-class",
"super-without-brackets",
"too-many-function-args",
"typevar-double-variance",
"typevar-name-mismatch",
"unbalanced-dict-unpacking",
"unbalanced-tuple-unpacking",
"unexpected-keyword-arg",
"unhashable-member",
"unpacking-non-sequence",
"unsubscriptable-object",
"unsupported-assignment-operation",
"unsupported-binary-operation",
"unsupported-delete-operation",
"unsupported-membership-test",
"used-before-assignment",
"using-final-decorator-in-unsupported-version",
"wrong-exception-operation",
] ]
enable = [ enable = [
#"useless-suppression", # temporarily every now and then to clean them up #"useless-suppression", # temporarily every now and then to clean them up
@ -230,16 +434,33 @@ filterwarnings = ["error::sqlalchemy.exc.SAWarning"]
target-version = "py310" target-version = "py310"
select = [ select = [
"B002", # Python does not support the unary prefix increment
"B007", # Loop control variable {name} not used within loop body "B007", # Loop control variable {name} not used within loop body
"B014", # Exception handler with duplicate exception "B014", # Exception handler with duplicate exception
"B023", # Function definition does not bind loop variable {name}
"B026", # Star-arg unpacking after a keyword argument is strongly discouraged
"C", # complexity "C", # complexity
"COM818", # Trailing comma on bare tuple prohibited
"D", # docstrings "D", # docstrings
"E", # pycodestyle "E", # pycodestyle
"F", # pyflakes/autoflake "F", # pyflakes/autoflake
"G", # flake8-logging-format
"I", # isort "I", # isort
"ICN001", # import concentions; {name} should be imported as {asname} "ICN001", # import concentions; {name} should be imported as {asname}
"ISC001", # Implicitly concatenated string literals on one line
"N804", # First argument of a class method should be named cls
"N805", # First argument of a method should be named self
"N815", # Variable {name} in class scope should not be mixedCase
"PGH001", # No builtin eval() allowed
"PGH004", # Use specific rule codes when using noqa "PGH004", # Use specific rule codes when using noqa
"PLC0414", # Useless import alias. Import alias does not rename original package. "PLC0414", # Useless import alias. Import alias does not rename original package.
"PLC", # pylint
"PLE", # pylint
"PLR", # pylint
"PLW", # pylint
"Q000", # Double quotes found but single quotes preferred
"RUF006", # Store a reference to the return value of asyncio.create_task
"S102", # Use of exec detected
"S103", # bad-file-permissions "S103", # bad-file-permissions
"S108", # hardcoded-temp-file "S108", # hardcoded-temp-file
"S306", # suspicious-mktemp-usage "S306", # suspicious-mktemp-usage
@ -261,12 +482,15 @@ select = [
"SIM117", # Merge with-statements that use the same scope "SIM117", # Merge with-statements that use the same scope
"SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys() "SIM118", # Use {key} in {dict} instead of {key} in {dict}.keys()
"SIM201", # Use {left} != {right} instead of not {left} == {right} "SIM201", # Use {left} != {right} instead of not {left} == {right}
"SIM208", # Use {expr} instead of not (not {expr})
"SIM212", # Use {a} if {a} else {b} instead of {b} if not {a} else {a} "SIM212", # Use {a} if {a} else {b} instead of {b} if not {a} else {a}
"SIM300", # Yoda conditions. Use 'age == 42' instead of '42 == age'. "SIM300", # Yoda conditions. Use 'age == 42' instead of '42 == age'.
"SIM401", # Use get from dict with default instead of an if block "SIM401", # Use get from dict with default instead of an if block
"T100", # Trace found: {name} used
"T20", # flake8-print "T20", # flake8-print
"TRY004", # Prefer TypeError exception for invalid type "TRY004", # Prefer TypeError exception for invalid type
"RUF006", # Store a reference to the return value of asyncio.create_task "TRY200", # Use raise from to specify exception cause
"TRY302", # Remove exception handler; error is immediately re-raised
"UP", # pyupgrade "UP", # pyupgrade
"W", # pycodestyle "W", # pycodestyle
] ]
@ -279,10 +503,20 @@ ignore = [
"D407", # Section name underlining "D407", # Section name underlining
"E501", # line too long "E501", # line too long
"E731", # do not assign a lambda expression, use a def "E731", # do not assign a lambda expression, use a def
"PLC1901", # Lots of false positives
# False positives https://github.com/astral-sh/ruff/issues/5386
"PLC0208", # Use a sequence type instead of a `set` when iterating over values
"PLR0911", # Too many return statements ({returns} > {max_returns})
"PLR0912", # Too many branches ({branches} > {max_branches})
"PLR0913", # Too many arguments to function call ({c_args} > {max_args})
"PLR0915", # Too many statements ({statements} > {max_statements})
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
"UP006", # keep type annotation style as is "UP006", # keep type annotation style as is
"UP007", # keep type annotation style as is "UP007", # keep type annotation style as is
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923 # Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)` "UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
] ]
[tool.ruff.flake8-import-conventions.extend-aliases] [tool.ruff.flake8-import-conventions.extend-aliases]

View File

@ -161,8 +161,8 @@ def verify_version(value: str) -> str:
AwesomeVersionStrategy.PEP440, AwesomeVersionStrategy.PEP440,
], ],
) )
except AwesomeVersionException: except AwesomeVersionException as err:
raise vol.Invalid(f"'{value}' is not a valid version.") raise vol.Invalid(f"'{value}' is not a valid version.") from err
return value return value

View File

@ -91,7 +91,7 @@ def format_python_namespace(
return f": {annotation}" if annotation else "" return f": {annotation}" if annotation else ""
code = "\n\n".join( code = "\n\n".join(
f"{key}{_get_annotation(key)}" f" = {to_string(value)}" f"{key}{_get_annotation(key)} = {to_string(value)}"
for key, value in sorted(content.items()) for key, value in sorted(content.items())
) )
if annotations: if annotations:

View File

@ -162,8 +162,8 @@ def _gather_info(fields) -> dict:
if "default" in info: if "default" in info:
msg += f" [{info['default']}]" msg += f" [{info['default']}]"
value = input(f"{msg}\n> ") value = input(f"{msg}\n> ")
except (KeyboardInterrupt, EOFError): except (KeyboardInterrupt, EOFError) as err:
raise ExitApp("Interrupted!", 1) raise ExitApp("Interrupted!", 1) from err
value = value.strip() value = value.strip()

View File

@ -120,7 +120,7 @@ async def _async_setup_emulated_hue(hass: HomeAssistant, conf: ConfigType) -> No
hass, hass,
emulated_hue.DOMAIN, emulated_hue.DOMAIN,
{emulated_hue.DOMAIN: conf}, {emulated_hue.DOMAIN: conf},
), )
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -680,7 +680,7 @@ async def test_execute_times_out(
async def slow_turn_on(*args, **kwargs): async def slow_turn_on(*args, **kwargs):
# Make DemoLigt.async_turn_on hang waiting for the turn_on_wait event # Make DemoLigt.async_turn_on hang waiting for the turn_on_wait event
await turn_on_wait.wait(), await turn_on_wait.wait()
with patch.object( with patch.object(
hass.services, "async_call", wraps=hass.services.async_call hass.services, "async_call", wraps=hass.services.async_call

View File

@ -30,7 +30,7 @@ MOCK_DATA_NEXT = (
'"ipAddress":false}}' '"ipAddress":false}}'
) )
MOCK_DATA_MISSING = '{"software": {},' '"system": {},' '"wan": {}}' MOCK_DATA_MISSING = '{"software": {},"system": {},"wan": {}}'
async def test_setup_minimum( async def test_setup_minimum(

View File

@ -190,7 +190,7 @@ async def test_config_entry_accessory(
"iid": 3, "iid": 3,
"perms": ["pr"], "perms": ["pr"],
"type": "20", "type": "20",
"value": "Home Assistant " "Light", "value": "Home Assistant Light",
}, },
{ {
"format": "string", "format": "string",
@ -475,7 +475,7 @@ async def test_config_entry_with_trigger_accessory(
"iid": 10, "iid": 10,
"perms": ["pr"], "perms": ["pr"],
"type": "23", "type": "23",
"value": "Ceiling Lights " "Changed States", "value": "Ceiling Lights Changed States",
}, },
{ {
"format": "uint8", "format": "uint8",
@ -521,7 +521,7 @@ async def test_config_entry_with_trigger_accessory(
"iid": 16, "iid": 16,
"perms": ["pr"], "perms": ["pr"],
"type": "23", "type": "23",
"value": "Ceiling Lights " "Turned Off", "value": "Ceiling Lights Turned Off",
}, },
{ {
"format": "uint8", "format": "uint8",
@ -567,7 +567,7 @@ async def test_config_entry_with_trigger_accessory(
"iid": 22, "iid": 22,
"perms": ["pr"], "perms": ["pr"],
"type": "23", "type": "23",
"value": "Ceiling Lights " "Turned On", "value": "Ceiling Lights Turned On",
}, },
{ {
"format": "uint8", "format": "uint8",

View File

@ -519,9 +519,7 @@ async def test_device(
"original_icon": None, "original_icon": None,
"original_name": "Koogeek-LS1-20833F Identify", "original_name": "Koogeek-LS1-20833F Identify",
"state": { "state": {
"attributes": { "attributes": {"friendly_name": "Koogeek-LS1-20833F Identify"},
"friendly_name": "Koogeek-LS1-20833F " "Identify"
},
"entity_id": "button.koogeek_ls1_20833f_identify", "entity_id": "button.koogeek_ls1_20833f_identify",
"last_changed": ANY, "last_changed": ANY,
"last_updated": ANY, "last_updated": ANY,

View File

@ -41,7 +41,7 @@ TEST_INVALID_DATE3 = (
TEST_MESSAGE_HEADERS1 + DATE_HEADER_INVALID3 + TEST_MESSAGE_HEADERS2 TEST_MESSAGE_HEADERS1 + DATE_HEADER_INVALID3 + TEST_MESSAGE_HEADERS2
) )
TEST_CONTENT_TEXT_BARE = b"\r\n" b"Test body\r\n" b"\r\n" TEST_CONTENT_TEXT_BARE = b"\r\nTest body\r\n\r\n"
TEST_CONTENT_BINARY = ( TEST_CONTENT_BINARY = (
b"Content-Type: application/binary\r\n" b"Content-Type: application/binary\r\n"

View File

@ -140,11 +140,11 @@ class KNXTestKit:
await self.hass.async_block_till_done() await self.hass.async_block_till_done()
try: try:
telegram = self._outgoing_telegrams.get_nowait() telegram = self._outgoing_telegrams.get_nowait()
except asyncio.QueueEmpty: except asyncio.QueueEmpty as err:
raise AssertionError( raise AssertionError(
f"No Telegram found. Expected: {apci_type.__name__} -" f"No Telegram found. Expected: {apci_type.__name__} -"
f" {group_address} - {payload}" f" {group_address} - {payload}"
) ) from err
assert isinstance( assert isinstance(
telegram.payload, apci_type telegram.payload, apci_type

View File

@ -2639,7 +2639,7 @@ async def test_get_events_with_device_ids(
@ha.callback @ha.callback
def async_describe_events( def async_describe_events(
hass: HomeAssistant, hass: HomeAssistant, # noqa: N805
async_describe_event: Callable[ async_describe_event: Callable[
[str, str, Callable[[Event], dict[str, str]]], None [str, str, Callable[[Event], dict[str, str]]], None
], ],

View File

@ -68,7 +68,7 @@ async def _async_mock_logbook_platform_with_broken_describe(
@core.callback @core.callback
def async_describe_events( def async_describe_events(
hass: HomeAssistant, hass: HomeAssistant, # noqa: N805
async_describe_event: Callable[ async_describe_event: Callable[
[str, str, Callable[[Event], dict[str, str]]], None [str, str, Callable[[Event], dict[str, str]]], None
], ],
@ -91,7 +91,7 @@ async def _async_mock_logbook_platform(hass: HomeAssistant) -> None:
@core.callback @core.callback
def async_describe_events( def async_describe_events(
hass: HomeAssistant, hass: HomeAssistant, # noqa: N805
async_describe_event: Callable[ async_describe_event: Callable[
[str, str, Callable[[Event], dict[str, str]]], None [str, str, Callable[[Event], dict[str, str]]], None
], ],

View File

@ -19,7 +19,7 @@ MOAT_S2_SERVICE_INFO = BluetoothServiceInfo(
service_data={ service_data={
"00005000-0000-1000-8000-00805f9b34fb": b"\xdfy\xe3\xa6\x12\xb3\xf5\x0b", "00005000-0000-1000-8000-00805f9b34fb": b"\xdfy\xe3\xa6\x12\xb3\xf5\x0b",
"00001000-0000-1000-8000-00805f9b34fb": ( "00001000-0000-1000-8000-00805f9b34fb": (
b"\xdfy\xe3\xa6\x12\xb3\x11S\xdbb\xfcbpq" b"\xf5\x0b\xff\xff" b"\xdfy\xe3\xa6\x12\xb3\x11S\xdbb\xfcbpq\xf5\x0b\xff\xff"
), ),
}, },
service_uuids=[ service_uuids=[

View File

@ -358,7 +358,7 @@ async def test_camera_option_stream_url_template(
}, },
options={ options={
CONF_STREAM_URL_TEMPLATE: ( CONF_STREAM_URL_TEMPLATE: (
f"http://127.0.0.1:{stream_server.port}/" "{{ name }}/{{ id }}" f"http://127.0.0.1:{stream_server.port}/{{{{ name }}}}/{{{{ id }}}}"
) )
}, },
) )

View File

@ -984,8 +984,8 @@ async def test_discovery_broken(
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
data1 = '{ "name": "Beer",' ' "off_delay": -1 }' data1 = '{ "name": "Beer", "off_delay": -1 }'
data2 = '{ "name": "Milk",' ' "state_topic": "test_topic" }' data2 = '{ "name": "Milk", "state_topic": "test_topic" }'
await help_test_discovery_broken( await help_test_discovery_broken(
hass, hass,
mqtt_mock_entry, mqtt_mock_entry,

View File

@ -769,8 +769,8 @@ async def test_discovery_broken(
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic#" }' data1 = '{ "name": "Beer", "command_topic": "test_topic#" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' data2 = '{ "name": "Milk", "command_topic": "test_topic" }'
await help_test_discovery_broken( await help_test_discovery_broken(
hass, mqtt_mock_entry, caplog, vacuum.DOMAIN, data1, data2 hass, mqtt_mock_entry, caplog, vacuum.DOMAIN, data1, data2
) )

View File

@ -2416,9 +2416,7 @@ async def test_discovery_ignores_extra_keys(
"""Test discovery ignores extra keys that are not blocked.""" """Test discovery ignores extra keys that are not blocked."""
await mqtt_mock_entry() await mqtt_mock_entry()
# inserted `platform` key should be ignored # inserted `platform` key should be ignored
data = ( data = '{ "name": "Beer", "platform": "mqtt", "command_topic": "test_topic"}'
'{ "name": "Beer",' ' "platform": "mqtt",' ' "command_topic": "test_topic"}'
)
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data) async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
await hass.async_block_till_done() await hass.async_block_till_done()
state = hass.states.get("light.beer") state = hass.states.get("light.beer")

View File

@ -161,9 +161,9 @@ async def test_setup_fails(
"command_topic": "test_light_rgb/set", "command_topic": "test_light_rgb/set",
"command_on_template": "on", "command_on_template": "on",
"command_off_template": "off", "command_off_template": "off",
"red_template": '{{ value.split(",")[4].' 'split("-")[0] }}', "red_template": '{{ value.split(",")[4].split("-")[0] }}',
"green_template": '{{ value.split(",")[4].' 'split("-")[1] }}', "green_template": '{{ value.split(",")[4].split("-")[1] }}',
"blue_template": '{{ value.split(",")[4].' 'split("-")[2] }}', "blue_template": '{{ value.split(",")[4].split("-")[2] }}',
} }
} }
} }
@ -416,9 +416,9 @@ async def test_state_brightness_color_effect_temp_change_via_topic(
"optimistic": True, "optimistic": True,
"state_template": '{{ value.split(",")[0] }}', "state_template": '{{ value.split(",")[0] }}',
"color_temp_template": '{{ value.split(",")[2] }}', "color_temp_template": '{{ value.split(",")[2] }}',
"red_template": '{{ value.split(",")[3].' 'split("-")[0] }}', "red_template": '{{ value.split(",")[3].split("-")[0] }}',
"green_template": '{{ value.split(",")[3].' 'split("-")[1] }}', "green_template": '{{ value.split(",")[3].split("-")[1] }}',
"blue_template": '{{ value.split(",")[3].' 'split("-")[2] }}', "blue_template": '{{ value.split(",")[3].split("-")[2] }}',
"effect_template": '{{ value.split(",")[4] }}', "effect_template": '{{ value.split(",")[4] }}',
"qos": 2, "qos": 2,
} }

View File

@ -796,7 +796,7 @@ async def test_discovery_removal_lock(
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test removal of discovered lock.""" """Test removal of discovered lock."""
data = '{ "name": "test",' ' "command_topic": "test_topic" }' data = '{ "name": "test", "command_topic": "test_topic" }'
await help_test_discovery_removal(hass, mqtt_mock_entry, caplog, lock.DOMAIN, data) await help_test_discovery_removal(hass, mqtt_mock_entry, caplog, lock.DOMAIN, data)
@ -855,7 +855,7 @@ async def test_discovery_broken(
) -> None: ) -> None:
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' data2 = '{ "name": "Milk", "command_topic": "test_topic" }'
await help_test_discovery_broken( await help_test_discovery_broken(
hass, mqtt_mock_entry, caplog, lock.DOMAIN, data1, data2 hass, mqtt_mock_entry, caplog, lock.DOMAIN, data1, data2
) )

View File

@ -180,7 +180,7 @@ async def test_discovery_removal_scene(
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test removal of discovered scene.""" """Test removal of discovered scene."""
data = '{ "name": "test",' ' "command_topic": "test_topic" }' data = '{ "name": "test", "command_topic": "test_topic" }'
await help_test_discovery_removal(hass, mqtt_mock_entry, caplog, scene.DOMAIN, data) await help_test_discovery_removal(hass, mqtt_mock_entry, caplog, scene.DOMAIN, data)
@ -213,7 +213,7 @@ async def test_discovery_update_unchanged_scene(
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test update of discovered scene.""" """Test update of discovered scene."""
data1 = '{ "name": "Beer",' ' "command_topic": "test_topic" }' data1 = '{ "name": "Beer", "command_topic": "test_topic" }'
with patch( with patch(
"homeassistant.components.mqtt.scene.MqttScene.discovery_update" "homeassistant.components.mqtt.scene.MqttScene.discovery_update"
) as discovery_update: ) as discovery_update:
@ -235,7 +235,7 @@ async def test_discovery_broken(
) -> None: ) -> None:
"""Test handling of bad discovery message.""" """Test handling of bad discovery message."""
data1 = '{ "name": "Beer" }' data1 = '{ "name": "Beer" }'
data2 = '{ "name": "Milk",' ' "command_topic": "test_topic" }' data2 = '{ "name": "Milk", "command_topic": "test_topic" }'
await help_test_discovery_broken( await help_test_discovery_broken(
hass, mqtt_mock_entry, caplog, scene.DOMAIN, data1, data2 hass, mqtt_mock_entry, caplog, scene.DOMAIN, data1, data2
) )

View File

@ -82,12 +82,12 @@ async def test_diagnostics(
}, },
"events": { "events": {
"pullpoint_manager_state": { "pullpoint_manager_state": {
"__type": "<enum " "'PullPointManagerState'>", "__type": "<enum 'PullPointManagerState'>",
"repr": "<PullPointManagerState.PAUSED: " "2>", "repr": "<PullPointManagerState.PAUSED: 2>",
}, },
"webhook_manager_state": { "webhook_manager_state": {
"__type": "<enum 'WebHookManagerState'>", "__type": "<enum 'WebHookManagerState'>",
"repr": "<WebHookManagerState.STARTED: " "1>", "repr": "<WebHookManagerState.STARTED: 1>",
}, },
}, },
} }

View File

@ -381,7 +381,7 @@ def test_bad_connection(hass: HomeAssistant, mock_exception_logger) -> None:
"POST", "POST",
"http://tomato-router:80/update.cgi", "http://tomato-router:80/update.cgi",
exc=requests.exceptions.ConnectionError, exc=requests.exceptions.ConnectionError,
), )
tomato.get_scanner(hass, config) tomato.get_scanner(hass, config)
assert mock_exception_logger.call_count == 1 assert mock_exception_logger.call_count == 1
assert mock_exception_logger.mock_calls[0] == mock.call( assert mock_exception_logger.mock_calls[0] == mock.call(
@ -409,7 +409,7 @@ def test_router_timeout(hass: HomeAssistant, mock_exception_logger) -> None:
"POST", "POST",
"http://tomato-router:80/update.cgi", "http://tomato-router:80/update.cgi",
exc=requests.exceptions.Timeout, exc=requests.exceptions.Timeout,
), )
tomato.get_scanner(hass, config) tomato.get_scanner(hass, config)
assert mock_exception_logger.call_count == 1 assert mock_exception_logger.call_count == 1
assert mock_exception_logger.mock_calls[0] == mock.call( assert mock_exception_logger.mock_calls[0] == mock.call(

View File

@ -247,7 +247,7 @@ async def test_smoke(hass: HomeAssistant) -> None:
hass, hass,
make_advertisement( make_advertisement(
"54:EF:44:E3:9C:BC", "54:EF:44:E3:9C:BC",
b"XY\x97\tf\xbc\x9c\xe3D\xefT\x01" b"\x08\x12\x05\x00\x00\x00q^\xbe\x90", b"XY\x97\tf\xbc\x9c\xe3D\xefT\x01\x08\x12\x05\x00\x00\x00q^\xbe\x90",
), ),
) )
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -116,7 +116,6 @@ def core_rs(hass_storage):
} }
], ],
} }
return
return _storage return _storage

View File

@ -1388,7 +1388,7 @@ def test_whitespace() -> None:
for value in ( for value in (
None, None,
"" "T", "T",
"negative", "negative",
"lock", "lock",
"tr ue", "tr ue",

View File

@ -16,7 +16,6 @@ async def test_hit(hass: HomeAssistant) -> None:
def _refresh(): def _refresh():
nonlocal refresh_called nonlocal refresh_called
refresh_called = True refresh_called = True
return
rate_limiter = ratelimit.KeyedRateLimit(hass) rate_limiter = ratelimit.KeyedRateLimit(hass)
rate_limiter.async_triggered("key1", dt_util.utcnow()) rate_limiter.async_triggered("key1", dt_util.utcnow())
@ -53,7 +52,6 @@ async def test_miss(hass: HomeAssistant) -> None:
def _refresh(): def _refresh():
nonlocal refresh_called nonlocal refresh_called
refresh_called = True refresh_called = True
return
rate_limiter = ratelimit.KeyedRateLimit(hass) rate_limiter = ratelimit.KeyedRateLimit(hass)
assert ( assert (
@ -85,7 +83,6 @@ async def test_no_limit(hass: HomeAssistant) -> None:
def _refresh(): def _refresh():
nonlocal refresh_called nonlocal refresh_called
refresh_called = True refresh_called = True
return
rate_limiter = ratelimit.KeyedRateLimit(hass) rate_limiter = ratelimit.KeyedRateLimit(hass)
rate_limiter.async_triggered("key1", dt_util.utcnow()) rate_limiter.async_triggered("key1", dt_util.utcnow())

View File

@ -12,6 +12,14 @@ extend-select = [
"PT022", # No teardown in fixture, replace useless yield with return "PT022", # No teardown in fixture, replace useless yield with return
] ]
extend-ignore = [
"PLC", # pylint
"PLE", # pylint
"PLR", # pylint
"PLW", # pylint
"N815", # Variable {name} in class scope should not be mixedCase
]
[isort] [isort]
known-first-party = [ known-first-party = [
"homeassistant", "homeassistant",