From b4f4b06f29acba9643b8a84ff2fd203a644c1213 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Fri, 17 Jan 2025 10:20:45 +0100 Subject: [PATCH] Enable RUF021 (#135832) --- homeassistant/components/alexa/entities.py | 33 +++++++++++-------- .../components/alexa/state_report.py | 5 ++- homeassistant/components/bond/entity.py | 7 ++-- homeassistant/components/bthome/logbook.py | 2 +- .../components/caldav/coordinator.py | 12 +++---- homeassistant/components/coinbase/__init__.py | 3 +- .../components/config/entity_registry.py | 5 ++- homeassistant/components/energy/sensor.py | 11 +++---- .../components/geo_location/trigger.py | 9 ++--- homeassistant/components/glances/sensor.py | 6 ++-- homeassistant/components/google_mail/api.py | 6 ++-- homeassistant/components/group/entity.py | 6 ++-- homeassistant/components/history/__init__.py | 10 +++--- .../components/history/websocket_api.py | 10 +++--- .../components/homekit/type_covers.py | 7 ++-- homeassistant/components/homekit/util.py | 3 +- homeassistant/components/lidarr/sensor.py | 6 ++-- .../components/melcloud/config_flow.py | 8 ++--- homeassistant/components/mqtt/config_flow.py | 29 ++++++++-------- homeassistant/components/myuplink/helpers.py | 6 ++-- homeassistant/components/netatmo/__init__.py | 3 +- .../components/octoprint/coordinator.py | 2 +- homeassistant/components/overkiz/sensor.py | 3 +- .../domestic_hot_water_production.py | 6 ++-- .../components/python_script/__init__.py | 21 ++++-------- homeassistant/components/rfxtrx/switch.py | 3 +- .../components/rmvtransport/sensor.py | 8 ++--- homeassistant/components/shelly/switch.py | 5 ++- homeassistant/components/siren/__init__.py | 6 ++-- .../components/snmp/device_tracker.py | 2 +- homeassistant/components/snmp/switch.py | 2 +- .../components/squeezebox/__init__.py | 5 ++- homeassistant/components/ssdp/__init__.py | 2 +- homeassistant/components/tts/__init__.py | 6 ++-- homeassistant/components/tuya/vacuum.py | 5 ++- homeassistant/components/unifi/services.py | 9 ++--- homeassistant/components/whirlpool/sensor.py | 5 ++- homeassistant/components/zone/trigger.py | 16 +++------ homeassistant/components/zwave_js/light.py | 2 +- homeassistant/helpers/condition.py | 6 ++-- homeassistant/helpers/event.py | 3 +- homeassistant/helpers/script.py | 6 ++-- homeassistant/helpers/template.py | 11 ++++--- homeassistant/helpers/update_coordinator.py | 2 +- pylint/plugins/hass_enforce_type_hints.py | 16 +++++---- pylint/plugins/hass_imports.py | 5 ++- pyproject.toml | 1 + script/translations/deduplicate.py | 6 ++-- .../google_assistant/test_helpers.py | 2 +- tests/components/imap/test_init.py | 14 +++----- tests/components/matrix/test_commands.py | 5 ++- tests/components/onewire/__init__.py | 12 +++---- 52 files changed, 166 insertions(+), 218 deletions(-) diff --git a/homeassistant/components/alexa/entities.py b/homeassistant/components/alexa/entities.py index 8c139d66369..6a0b1830b7e 100644 --- a/homeassistant/components/alexa/entities.py +++ b/homeassistant/components/alexa/entities.py @@ -474,25 +474,30 @@ class ClimateCapabilities(AlexaEntity): # If we support two modes, one being off, we allow turning on too. supported_features = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) if ( - self.entity.domain == climate.DOMAIN - and climate.HVACMode.OFF - in (self.entity.attributes.get(climate.ATTR_HVAC_MODES) or []) - or self.entity.domain == climate.DOMAIN - and ( - supported_features - & ( - climate.ClimateEntityFeature.TURN_ON - | climate.ClimateEntityFeature.TURN_OFF + ( + self.entity.domain == climate.DOMAIN + and climate.HVACMode.OFF + in (self.entity.attributes.get(climate.ATTR_HVAC_MODES) or []) + ) + or ( + self.entity.domain == climate.DOMAIN + and ( + supported_features + & ( + climate.ClimateEntityFeature.TURN_ON + | climate.ClimateEntityFeature.TURN_OFF + ) ) ) - or self.entity.domain == water_heater.DOMAIN - and (supported_features & water_heater.WaterHeaterEntityFeature.ON_OFF) + or ( + self.entity.domain == water_heater.DOMAIN + and (supported_features & water_heater.WaterHeaterEntityFeature.ON_OFF) + ) ): yield AlexaPowerController(self.entity) - if ( - self.entity.domain == climate.DOMAIN - or self.entity.domain == water_heater.DOMAIN + if self.entity.domain == climate.DOMAIN or ( + self.entity.domain == water_heater.DOMAIN and ( supported_features & water_heater.WaterHeaterEntityFeature.OPERATION_MODE diff --git a/homeassistant/components/alexa/state_report.py b/homeassistant/components/alexa/state_report.py index 3eb761dacde..03b6a22007c 100644 --- a/homeassistant/components/alexa/state_report.py +++ b/homeassistant/components/alexa/state_report.py @@ -317,9 +317,8 @@ async def async_enable_proactive_mode( if should_doorbell: old_state = data["old_state"] - if ( - new_state.domain == event.DOMAIN - or new_state.state == STATE_ON + if new_state.domain == event.DOMAIN or ( + new_state.state == STATE_ON and (old_state is None or old_state.state != STATE_ON) ): await async_send_doorbell_event_message( diff --git a/homeassistant/components/bond/entity.py b/homeassistant/components/bond/entity.py index 81f96b1772c..2ae1df5fd68 100644 --- a/homeassistant/components/bond/entity.py +++ b/homeassistant/components/bond/entity.py @@ -115,11 +115,8 @@ class BondEntity(Entity): def _async_update_if_bpup_not_alive(self, now: datetime) -> None: """Fetch via the API if BPUP is not alive.""" self._async_schedule_bpup_alive_or_poll() - if ( - self.hass.is_stopping - or self._bpup_subs.alive - and self._initialized - and self.available + if self.hass.is_stopping or ( + self._bpup_subs.alive and self._initialized and self.available ): return if self._update_lock.locked(): diff --git a/homeassistant/components/bthome/logbook.py b/homeassistant/components/bthome/logbook.py index 32e90118dea..1c41d5553da 100644 --- a/homeassistant/components/bthome/logbook.py +++ b/homeassistant/components/bthome/logbook.py @@ -26,7 +26,7 @@ def async_describe_events( """Describe bthome logbook event.""" data = event.data device = dev_reg.async_get(data["device_id"]) - name = device and device.name or f"BTHome {data['address']}" + name = (device and device.name) or f"BTHome {data['address']}" if properties := data["event_properties"]: message = f"{data['event_class']} {data['event_type']}: {properties}" else: diff --git a/homeassistant/components/caldav/coordinator.py b/homeassistant/components/caldav/coordinator.py index eb09e3f5452..c6bbd15bdff 100644 --- a/homeassistant/components/caldav/coordinator.py +++ b/homeassistant/components/caldav/coordinator.py @@ -186,12 +186,12 @@ class CalDavUpdateCoordinator(DataUpdateCoordinator[CalendarEvent | None]): pattern = re.compile(search) return ( - hasattr(vevent, "summary") - and pattern.match(vevent.summary.value) - or hasattr(vevent, "location") - and pattern.match(vevent.location.value) - or hasattr(vevent, "description") - and pattern.match(vevent.description.value) + (hasattr(vevent, "summary") and pattern.match(vevent.summary.value)) + or (hasattr(vevent, "location") and pattern.match(vevent.location.value)) + or ( + hasattr(vevent, "description") + and pattern.match(vevent.description.value) + ) ) @staticmethod diff --git a/homeassistant/components/coinbase/__init__.py b/homeassistant/components/coinbase/__init__.py index f5fd8fa1dc3..6aa33a7c14d 100644 --- a/homeassistant/components/coinbase/__init__.py +++ b/homeassistant/components/coinbase/__init__.py @@ -101,7 +101,8 @@ async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> Non if ( "xe" in entity.unique_id and currency not in config_entry.options.get(CONF_EXCHANGE_RATES, []) - or "wallet" in entity.unique_id + ) or ( + "wallet" in entity.unique_id and currency not in config_entry.options.get(CONF_CURRENCIES, []) ): registry.async_remove(entity.entity_id) diff --git a/homeassistant/components/config/entity_registry.py b/homeassistant/components/config/entity_registry.py index aed04943975..b987f249a33 100644 --- a/homeassistant/components/config/entity_registry.py +++ b/homeassistant/components/config/entity_registry.py @@ -279,9 +279,8 @@ def websocket_update_entity( result: dict[str, Any] = {"entity_entry": entity_entry.extended_dict} if "disabled_by" in changes and changes["disabled_by"] is None: # Enabling an entity requires a config entry reload, or HA restart - if ( - not (config_entry_id := entity_entry.config_entry_id) - or (config_entry := hass.config_entries.async_get_entry(config_entry_id)) + if not (config_entry_id := entity_entry.config_entry_id) or ( + (config_entry := hass.config_entries.async_get_entry(config_entry_id)) and not config_entry.supports_unload ): result["require_restart"] = True diff --git a/homeassistant/components/energy/sensor.py b/homeassistant/components/energy/sensor.py index 147d8f3e26a..199d18d6b07 100644 --- a/homeassistant/components/energy/sensor.py +++ b/homeassistant/components/energy/sensor.py @@ -362,12 +362,11 @@ class EnergyCostSensor(SensorEntity): return if ( - ( - state_class != SensorStateClass.TOTAL_INCREASING - and energy_state.attributes.get(ATTR_LAST_RESET) - != self._last_energy_sensor_state.attributes.get(ATTR_LAST_RESET) - ) - or state_class == SensorStateClass.TOTAL_INCREASING + state_class != SensorStateClass.TOTAL_INCREASING + and energy_state.attributes.get(ATTR_LAST_RESET) + != self._last_energy_sensor_state.attributes.get(ATTR_LAST_RESET) + ) or ( + state_class == SensorStateClass.TOTAL_INCREASING and reset_detected( self.hass, cast(str, self._config[self._adapter.stat_energy_key]), diff --git a/homeassistant/components/geo_location/trigger.py b/homeassistant/components/geo_location/trigger.py index 96244e08d1b..5f0d6e92ee1 100644 --- a/homeassistant/components/geo_location/trigger.py +++ b/homeassistant/components/geo_location/trigger.py @@ -83,13 +83,8 @@ async def async_attach_trigger( ) to_match = condition.zone(hass, zone_state, to_state) if to_state else False - if ( - trigger_event == EVENT_ENTER - and not from_match - and to_match - or trigger_event == EVENT_LEAVE - and from_match - and not to_match + if (trigger_event == EVENT_ENTER and not from_match and to_match) or ( + trigger_event == EVENT_LEAVE and from_match and not to_match ): hass.async_run_hass_job( job, diff --git a/homeassistant/components/glances/sensor.py b/homeassistant/components/glances/sensor.py index 59eba69d60a..0741926296e 100644 --- a/homeassistant/components/glances/sensor.py +++ b/homeassistant/components/glances/sensor.py @@ -375,6 +375,8 @@ class GlancesSensor(CoordinatorEntity[GlancesDataUpdateCoordinator], SensorEntit self._data_valid = self._attr_native_value is not None and ( not self._numeric_state_expected or isinstance(self._attr_native_value, (int, float)) - or isinstance(self._attr_native_value, str) - and self._attr_native_value.isnumeric() + or ( + isinstance(self._attr_native_value, str) + and self._attr_native_value.isnumeric() + ) ) diff --git a/homeassistant/components/google_mail/api.py b/homeassistant/components/google_mail/api.py index 485d640a04d..3e455f645ad 100644 --- a/homeassistant/components/google_mail/api.py +++ b/homeassistant/components/google_mail/api.py @@ -49,10 +49,8 @@ class AsyncConfigEntryAuth: "OAuth session is not valid, reauth required" ) from ex raise ConfigEntryNotReady from ex - if ( - isinstance(ex, RefreshError) - or hasattr(ex, "status") - and ex.status == 400 + if isinstance(ex, RefreshError) or ( + hasattr(ex, "status") and ex.status == 400 ): self.oauth_session.config_entry.async_start_reauth( self.oauth_session.hass diff --git a/homeassistant/components/group/entity.py b/homeassistant/components/group/entity.py index 03a8be4bed5..40db70a2eb3 100644 --- a/homeassistant/components/group/entity.py +++ b/homeassistant/components/group/entity.py @@ -440,10 +440,8 @@ class Group(Entity): if not self._on_off: return - if ( - tr_state is None - or self._assumed_state - and not tr_state.attributes.get(ATTR_ASSUMED_STATE) + if tr_state is None or ( + self._assumed_state and not tr_state.attributes.get(ATTR_ASSUMED_STATE) ): self._assumed_state = self.mode(self._assumed.values()) diff --git a/homeassistant/components/history/__init__.py b/homeassistant/components/history/__init__.py index 7241e1fac9a..ba4614bbc35 100644 --- a/homeassistant/components/history/__init__.py +++ b/homeassistant/components/history/__init__.py @@ -111,10 +111,12 @@ class HistoryPeriodView(HomeAssistantView): # end_time. If it's false, we know there are no states in the # database up until end_time. (end_time and not has_states_before(hass, end_time)) - or not include_start_time_state - and entity_ids - and not entities_may_have_state_changes_after( - hass, entity_ids, start_time, no_attributes + or ( + not include_start_time_state + and entity_ids + and not entities_may_have_state_changes_after( + hass, entity_ids, start_time, no_attributes + ) ) ): return self.json([]) diff --git a/homeassistant/components/history/websocket_api.py b/homeassistant/components/history/websocket_api.py index 35f8ed5f1ac..e6c91453213 100644 --- a/homeassistant/components/history/websocket_api.py +++ b/homeassistant/components/history/websocket_api.py @@ -146,10 +146,12 @@ async def ws_get_history_during_period( # end_time. If it's false, we know there are no states in the # database up until end_time. (end_time and not has_states_before(hass, end_time)) - or not include_start_time_state - and entity_ids - and not entities_may_have_state_changes_after( - hass, entity_ids, start_time, no_attributes + or ( + not include_start_time_state + and entity_ids + and not entities_may_have_state_changes_after( + hass, entity_ids, start_time, no_attributes + ) ) ): connection.send_result(msg["id"], {}) diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index 6752633f3d2..651033682cf 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -409,11 +409,8 @@ class WindowCoveringBasic(OpeningDeviceBase, HomeAccessory): """Move cover to value if call came from HomeKit.""" _LOGGER.debug("%s: Set position to %d", self.entity_id, value) - if ( - self._supports_stop - and value > 70 - or not self._supports_stop - and value >= 50 + if (self._supports_stop and value > 70) or ( + not self._supports_stop and value >= 50 ): service, position = (SERVICE_OPEN_COVER, 100) elif value < 30 or not self._supports_stop: diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index d339aa6aded..cd659654617 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -643,7 +643,8 @@ def state_needs_accessory_mode(state: State) -> bool: state.domain == MEDIA_PLAYER_DOMAIN and state.attributes.get(ATTR_DEVICE_CLASS) in (MediaPlayerDeviceClass.TV, MediaPlayerDeviceClass.RECEIVER) - or state.domain == REMOTE_DOMAIN + ) or ( + state.domain == REMOTE_DOMAIN and state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) & RemoteEntityFeature.ACTIVITY ) diff --git a/homeassistant/components/lidarr/sensor.py b/homeassistant/components/lidarr/sensor.py index b02361e65ca..805fcce53ad 100644 --- a/homeassistant/components/lidarr/sensor.py +++ b/homeassistant/components/lidarr/sensor.py @@ -160,10 +160,8 @@ class LidarrSensor(LidarrEntity[T], SensorEntity): def queue_str(item: LidarrQueueItem) -> str: """Return string description of queue item.""" - if ( - item.sizeleft > 0 - and item.timeleft == "00:00:00" - or not hasattr(item, "trackedDownloadState") + if (item.sizeleft > 0 and item.timeleft == "00:00:00") or not hasattr( + item, "trackedDownloadState" ): return "stopped" return item.trackedDownloadState diff --git a/homeassistant/components/melcloud/config_flow.py b/homeassistant/components/melcloud/config_flow.py index b604ee5016e..d2c9d67f29a 100644 --- a/homeassistant/components/melcloud/config_flow.py +++ b/homeassistant/components/melcloud/config_flow.py @@ -126,9 +126,7 @@ class FlowHandler(ConfigFlow, domain=DOMAIN): HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN, ) - or isinstance(err, AttributeError) - and err.name == "get" - ): + ) or (isinstance(err, AttributeError) and err.name == "get"): errors["base"] = "invalid_auth" else: errors["base"] = "cannot_connect" @@ -165,9 +163,7 @@ class FlowHandler(ConfigFlow, domain=DOMAIN): HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN, ) - or isinstance(err, AttributeError) - and err.name == "get" - ): + ) or (isinstance(err, AttributeError) and err.name == "get"): errors["base"] = "invalid_auth" else: errors["base"] = "cannot_connect" diff --git a/homeassistant/components/mqtt/config_flow.py b/homeassistant/components/mqtt/config_flow.py index f07777742ee..a4d400dfea2 100644 --- a/homeassistant/components/mqtt/config_flow.py +++ b/homeassistant/components/mqtt/config_flow.py @@ -768,11 +768,8 @@ async def async_get_broker_settings( validated_user_input.update(user_input) client_certificate_id: str | None = user_input.get(CONF_CLIENT_CERT) client_key_id: str | None = user_input.get(CONF_CLIENT_KEY) - if ( - client_certificate_id - and not client_key_id - or not client_certificate_id - and client_key_id + if (client_certificate_id and not client_key_id) or ( + not client_certificate_id and client_key_id ): errors["base"] = "invalid_inclusion" return False @@ -782,14 +779,20 @@ async def async_get_broker_settings( # Return to form for file upload CA cert or client cert and key if ( - not client_certificate - and user_input.get(SET_CLIENT_CERT) - and not client_certificate_id - or not certificate - and user_input.get(SET_CA_CERT, "off") == "custom" - and not certificate_id - or user_input.get(CONF_TRANSPORT) == TRANSPORT_WEBSOCKETS - and CONF_WS_PATH not in user_input + ( + not client_certificate + and user_input.get(SET_CLIENT_CERT) + and not client_certificate_id + ) + or ( + not certificate + and user_input.get(SET_CA_CERT, "off") == "custom" + and not certificate_id + ) + or ( + user_input.get(CONF_TRANSPORT) == TRANSPORT_WEBSOCKETS + and CONF_WS_PATH not in user_input + ) ): return False diff --git a/homeassistant/components/myuplink/helpers.py b/homeassistant/components/myuplink/helpers.py index bd875d8a872..5751d574e04 100644 --- a/homeassistant/components/myuplink/helpers.py +++ b/homeassistant/components/myuplink/helpers.py @@ -26,10 +26,8 @@ def find_matching_platform( if len(device_point.enum_values) > 0 and device_point.writable: return Platform.SELECT - if ( - description - and description.native_unit_of_measurement == "DM" - or (device_point.raw["maxValue"] and device_point.raw["minValue"]) + if (description and description.native_unit_of_measurement == "DM") or ( + device_point.raw["maxValue"] and device_point.raw["minValue"] ): if device_point.writable: return Platform.NUMBER diff --git a/homeassistant/components/netatmo/__init__.py b/homeassistant/components/netatmo/__init__.py index 6f14c9c76bb..9c92724c543 100644 --- a/homeassistant/components/netatmo/__init__.py +++ b/homeassistant/components/netatmo/__init__.py @@ -257,7 +257,6 @@ async def async_remove_config_entry_device( return not any( identifier for identifier in device_entry.identifiers - if identifier[0] == DOMAIN - and identifier[1] in modules + if (identifier[0] == DOMAIN and identifier[1] in modules) or identifier[1] in rooms ) diff --git a/homeassistant/components/octoprint/coordinator.py b/homeassistant/components/octoprint/coordinator.py index ff00b6c3420..c6d7373a002 100644 --- a/homeassistant/components/octoprint/coordinator.py +++ b/homeassistant/components/octoprint/coordinator.py @@ -80,7 +80,7 @@ class OctoprintDataUpdateCoordinator(DataUpdateCoordinator): """Device info.""" unique_id = cast(str, self.config_entry.unique_id) configuration_url = URL.build( - scheme=self.config_entry.data[CONF_SSL] and "https" or "http", + scheme=(self.config_entry.data[CONF_SSL] and "https") or "http", host=self.config_entry.data[CONF_HOST], port=self.config_entry.data[CONF_PORT], path=self.config_entry.data[CONF_PATH], diff --git a/homeassistant/components/overkiz/sensor.py b/homeassistant/components/overkiz/sensor.py index 84d25b01d24..81a9ab41d2d 100644 --- a/homeassistant/components/overkiz/sensor.py +++ b/homeassistant/components/overkiz/sensor.py @@ -534,8 +534,7 @@ class OverkizStateSensor(OverkizDescriptiveEntity, SensorEntity): # This is probably incorrect and should be fixed in a follow up PR. # To ensure measurement sensors do not get an `unknown` state on # a falsy value (e.g. 0 or 0.0) we also check the state_class. - or self.state_class != SensorStateClass.MEASUREMENT - and not state.value + or (self.state_class != SensorStateClass.MEASUREMENT and not state.value) ): return None diff --git a/homeassistant/components/overkiz/water_heater/domestic_hot_water_production.py b/homeassistant/components/overkiz/water_heater/domestic_hot_water_production.py index abd3f40adc2..f5a9e3d4a7e 100644 --- a/homeassistant/components/overkiz/water_heater/domestic_hot_water_production.py +++ b/homeassistant/components/overkiz/water_heater/domestic_hot_water_production.py @@ -64,10 +64,8 @@ class DomesticHotWaterProduction(OverkizEntity, WaterHeaterEntity): for param, mode in OVERKIZ_TO_OPERATION_MODE.items(): # Filter only for mode allowed by this device # or allow all if no mode definition found - if ( - not state_mode_definition - or state_mode_definition.values - and param in state_mode_definition.values + if not state_mode_definition or ( + state_mode_definition.values and param in state_mode_definition.values ): self.operation_mode_to_overkiz[mode] = param self._attr_operation_list.append(param) diff --git a/homeassistant/components/python_script/__init__.py b/homeassistant/components/python_script/__init__.py index f9e6a994406..dbd1a5dce4b 100644 --- a/homeassistant/components/python_script/__init__.py +++ b/homeassistant/components/python_script/__init__.py @@ -239,20 +239,13 @@ def execute( if name.startswith("async_"): raise ScriptError("Not allowed to access async methods") if ( - obj is hass - and name not in ALLOWED_HASS - or obj is hass.bus - and name not in ALLOWED_EVENTBUS - or obj is hass.states - and name not in ALLOWED_STATEMACHINE - or obj is hass.services - and name not in ALLOWED_SERVICEREGISTRY - or obj is dt_util - and name not in ALLOWED_DT_UTIL - or obj is datetime - and name not in ALLOWED_DATETIME - or isinstance(obj, TimeWrapper) - and name not in ALLOWED_TIME + (obj is hass and name not in ALLOWED_HASS) + or (obj is hass.bus and name not in ALLOWED_EVENTBUS) + or (obj is hass.states and name not in ALLOWED_STATEMACHINE) + or (obj is hass.services and name not in ALLOWED_SERVICEREGISTRY) + or (obj is dt_util and name not in ALLOWED_DT_UTIL) + or (obj is datetime and name not in ALLOWED_DATETIME) + or (isinstance(obj, TimeWrapper) and name not in ALLOWED_TIME) ): raise ScriptError(f"Not allowed to access {obj.__class__.__name__}.{name}") diff --git a/homeassistant/components/rfxtrx/switch.py b/homeassistant/components/rfxtrx/switch.py index 1464cccb5c4..cd17e71f4f0 100644 --- a/homeassistant/components/rfxtrx/switch.py +++ b/homeassistant/components/rfxtrx/switch.py @@ -35,8 +35,7 @@ def supported(event: rfxtrxmod.RFXtrxEvent) -> bool: isinstance(event.device, rfxtrxmod.LightingDevice) and not event.device.known_to_be_dimmable and not event.device.known_to_be_rollershutter - or isinstance(event.device, rfxtrxmod.RfyDevice) - ) + ) or isinstance(event.device, rfxtrxmod.RfyDevice) async def async_setup_entry( diff --git a/homeassistant/components/rmvtransport/sensor.py b/homeassistant/components/rmvtransport/sensor.py index 8fd437e7e1d..ac6c66bb6d2 100644 --- a/homeassistant/components/rmvtransport/sensor.py +++ b/homeassistant/components/rmvtransport/sensor.py @@ -271,11 +271,9 @@ class RMVDepartureData: if not dest_found: continue - if ( - self._lines - and journey["number"] not in self._lines - or journey["minutes"] < self._time_offset - ): + if (self._lines and journey["number"] not in self._lines) or journey[ + "minutes" + ] < self._time_offset: continue for attr in ("direction", "departure_time", "product", "minutes"): diff --git a/homeassistant/components/shelly/switch.py b/homeassistant/components/shelly/switch.py index 134704cb0ff..8a33dae0938 100644 --- a/homeassistant/components/shelly/switch.py +++ b/homeassistant/components/shelly/switch.py @@ -120,9 +120,8 @@ def async_setup_block_entry( relay_blocks = [] assert coordinator.device.blocks for block in coordinator.device.blocks: - if ( - block.type != "relay" - or block.channel is not None + if block.type != "relay" or ( + block.channel is not None and is_block_channel_type_light( coordinator.device.settings, int(block.channel) ) diff --git a/homeassistant/components/siren/__init__.py b/homeassistant/components/siren/__init__.py index 9ce6898fd93..02b49f5732e 100644 --- a/homeassistant/components/siren/__init__.py +++ b/homeassistant/components/siren/__init__.py @@ -68,10 +68,8 @@ def process_turn_on_params( isinstance(siren.available_tones, dict) and tone in siren.available_tones.values() ) - if ( - not siren.available_tones - or tone not in siren.available_tones - and not is_tone_dict_value + if not siren.available_tones or ( + tone not in siren.available_tones and not is_tone_dict_value ): raise ValueError( f"Invalid tone specified for entity {siren.entity_id}: {tone}, " diff --git a/homeassistant/components/snmp/device_tracker.py b/homeassistant/components/snmp/device_tracker.py index 3c4a0a0725c..4c2b2b25ad8 100644 --- a/homeassistant/components/snmp/device_tracker.py +++ b/homeassistant/components/snmp/device_tracker.py @@ -172,7 +172,7 @@ class SnmpScanner(DeviceScanner): _LOGGER.error( "SNMP error: %s at %s", errstatus.prettyPrint(), - errindex and res[int(errindex) - 1][0] or "?", + (errindex and res[int(errindex) - 1][0]) or "?", ) return None diff --git a/homeassistant/components/snmp/switch.py b/homeassistant/components/snmp/switch.py index 92e27daed6c..2f9f8b0bfb7 100644 --- a/homeassistant/components/snmp/switch.py +++ b/homeassistant/components/snmp/switch.py @@ -264,7 +264,7 @@ class SnmpSwitch(SwitchEntity): _LOGGER.error( "SNMP error: %s at %s", errstatus.prettyPrint(), - errindex and restable[-1][int(errindex) - 1] or "?", + (errindex and restable[-1][int(errindex) - 1]) or "?", ) else: for resrow in restable: diff --git a/homeassistant/components/squeezebox/__init__.py b/homeassistant/components/squeezebox/__init__.py index f466f3bcb62..f94ea118c6a 100644 --- a/homeassistant/components/squeezebox/__init__.py +++ b/homeassistant/components/squeezebox/__init__.py @@ -105,9 +105,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: SqueezeboxConfigEntry) - lms.name = ( (STATUS_QUERY_LIBRARYNAME in status and status[STATUS_QUERY_LIBRARYNAME]) and status[STATUS_QUERY_LIBRARYNAME] - or host - ) - version = STATUS_QUERY_VERSION in status and status[STATUS_QUERY_VERSION] or None + ) or host + version = (STATUS_QUERY_VERSION in status and status[STATUS_QUERY_VERSION]) or None # mac can be missing mac_connect = ( {(CONNECTION_NETWORK_MAC, format_mac(status[STATUS_QUERY_MAC]))} diff --git a/homeassistant/components/ssdp/__init__.py b/homeassistant/components/ssdp/__init__.py index 637974853f6..c5fb349ddbb 100644 --- a/homeassistant/components/ssdp/__init__.py +++ b/homeassistant/components/ssdp/__init__.py @@ -273,7 +273,7 @@ async def async_build_source_set(hass: HomeAssistant) -> set[IPv4Address | IPv6A for source_ip in await network.async_get_enabled_source_ips(hass) if not source_ip.is_loopback and not source_ip.is_global - and (source_ip.version == 6 and source_ip.scope_id or source_ip.version == 4) + and ((source_ip.version == 6 and source_ip.scope_id) or source_ip.version == 4) } diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index 80c175ccfe4..0213fd17864 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -1052,10 +1052,8 @@ class TextToSpeechUrlView(HomeAssistantView): data = await request.json() except ValueError: return self.json_message("Invalid JSON specified", HTTPStatus.BAD_REQUEST) - if ( - not data.get("engine_id") - and not data.get(ATTR_PLATFORM) - or not data.get(ATTR_MESSAGE) + if (not data.get("engine_id") and not data.get(ATTR_PLATFORM)) or not data.get( + ATTR_MESSAGE ): return self.json_message( "Must specify platform and message", HTTPStatus.BAD_REQUEST diff --git a/homeassistant/components/tuya/vacuum.py b/homeassistant/components/tuya/vacuum.py index 738492102a1..bab9ac309ec 100644 --- a/homeassistant/components/tuya/vacuum.py +++ b/homeassistant/components/tuya/vacuum.py @@ -89,9 +89,8 @@ class TuyaVacuumEntity(TuyaEntity, StateVacuumEntity): if self.find_dpcode(DPCode.PAUSE, prefer_function=True): self._attr_supported_features |= VacuumEntityFeature.PAUSE - if ( - self.find_dpcode(DPCode.SWITCH_CHARGE, prefer_function=True) - or ( + if self.find_dpcode(DPCode.SWITCH_CHARGE, prefer_function=True) or ( + ( enum_type := self.find_dpcode( DPCode.MODE, dptype=DPType.ENUM, prefer_function=True ) diff --git a/homeassistant/components/unifi/services.py b/homeassistant/components/unifi/services.py index ce726a0f5d0..fc63c092d56 100644 --- a/homeassistant/components/unifi/services.py +++ b/homeassistant/components/unifi/services.py @@ -69,8 +69,7 @@ async def async_reconnect_client(hass: HomeAssistant, data: Mapping[str, Any]) - for config_entry in hass.config_entries.async_entries(UNIFI_DOMAIN): if config_entry.state is not ConfigEntryState.LOADED or ( - (hub := config_entry.runtime_data) - and not hub.available + ((hub := config_entry.runtime_data) and not hub.available) or (client := hub.api.clients.get(mac)) is None or client.is_wired ): @@ -87,10 +86,8 @@ async def async_remove_clients(hass: HomeAssistant, data: Mapping[str, Any]) -> - Neither IP, hostname nor name is configured. """ for config_entry in hass.config_entries.async_entries(UNIFI_DOMAIN): - if ( - config_entry.state is not ConfigEntryState.LOADED - or (hub := config_entry.runtime_data) - and not hub.available + if config_entry.state is not ConfigEntryState.LOADED or ( + (hub := config_entry.runtime_data) and not hub.available ): continue diff --git a/homeassistant/components/whirlpool/sensor.py b/homeassistant/components/whirlpool/sensor.py index b84518cedf1..9180164c272 100644 --- a/homeassistant/components/whirlpool/sensor.py +++ b/homeassistant/components/whirlpool/sensor.py @@ -291,9 +291,8 @@ class WasherDryerTimeClass(RestoreSensor): seconds=int(self._wd.get_attribute("Cavity_TimeStatusEstTimeRemaining")) ) - if ( - self._attr_native_value is None - or isinstance(self._attr_native_value, datetime) + if self._attr_native_value is None or ( + isinstance(self._attr_native_value, datetime) and abs(new_timestamp - self._attr_native_value) > timedelta(seconds=60) ): self._attr_native_value = new_timestamp diff --git a/homeassistant/components/zone/trigger.py b/homeassistant/components/zone/trigger.py index aa4aefe6d95..af4999e5438 100644 --- a/homeassistant/components/zone/trigger.py +++ b/homeassistant/components/zone/trigger.py @@ -85,11 +85,8 @@ async def async_attach_trigger( from_s = zone_event.data["old_state"] to_s = zone_event.data["new_state"] - if ( - from_s - and not location.has_location(from_s) - or to_s - and not location.has_location(to_s) + if (from_s and not location.has_location(from_s)) or ( + to_s and not location.has_location(to_s) ): return @@ -107,13 +104,8 @@ async def async_attach_trigger( from_match = condition.zone(hass, zone_state, from_s) if from_s else False to_match = condition.zone(hass, zone_state, to_s) if to_s else False - if ( - event == EVENT_ENTER - and not from_match - and to_match - or event == EVENT_LEAVE - and from_match - and not to_match + if (event == EVENT_ENTER and not from_match and to_match) or ( + event == EVENT_LEAVE and from_match and not to_match ): description = f"{entity} {_EVENT_DESCRIPTION[event]} {zone_state.attributes[ATTR_FRIENDLY_NAME]}" hass.async_run_hass_job( diff --git a/homeassistant/components/zwave_js/light.py b/homeassistant/components/zwave_js/light.py index e6cfc6c8b29..639d2fbcd7a 100644 --- a/homeassistant/components/zwave_js/light.py +++ b/homeassistant/components/zwave_js/light.py @@ -458,7 +458,7 @@ class ZwaveLight(ZWaveBaseEntity, LightEntity): if warm_white and cool_white: self._supports_color_temp = True # only one white channel (warm white or cool white) = rgbw support - elif red and green and blue and warm_white or cool_white: + elif (red and green and blue and warm_white) or cool_white: self._supports_rgbw = True @callback diff --git a/homeassistant/helpers/condition.py b/homeassistant/helpers/condition.py index 5952e28a1eb..695af80bc1c 100644 --- a/homeassistant/helpers/condition.py +++ b/homeassistant/helpers/condition.py @@ -884,10 +884,8 @@ def time( condition_trace_update_result(weekday=weekday, now_weekday=now_weekday) if ( - isinstance(weekday, str) - and weekday != now_weekday - or now_weekday not in weekday - ): + isinstance(weekday, str) and weekday != now_weekday + ) or now_weekday not in weekday: return False return True diff --git a/homeassistant/helpers/event.py b/homeassistant/helpers/event.py index 72a4ef3c050..b363bc21e86 100644 --- a/homeassistant/helpers/event.py +++ b/homeassistant/helpers/event.py @@ -951,8 +951,7 @@ def async_track_template( if ( not isinstance(last_result, TemplateError) and result_as_boolean(last_result) - or not result_as_boolean(result) - ): + ) or not result_as_boolean(result): return hass.async_run_hass_job( diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index f3f798e1d6b..1fd0e08988c 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -756,10 +756,8 @@ class _ScriptRun: ) running_script = ( - params[CONF_DOMAIN] == "automation" - and params[CONF_SERVICE] == "trigger" - or params[CONF_DOMAIN] in ("python_script", "script") - ) + params[CONF_DOMAIN] == "automation" and params[CONF_SERVICE] == "trigger" + ) or params[CONF_DOMAIN] in ("python_script", "script") trace_set_result(params=params, running_script=running_script) response_data = await self._async_run_long_action( self._hass.async_create_task_internal( diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index e8c169e92d8..4625c3000ba 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -601,7 +601,7 @@ class Template: or filter depending on hass or the state machine. """ if self.is_static: - if not parse_result or self.hass and self.hass.config.legacy_templates: + if not parse_result or (self.hass and self.hass.config.legacy_templates): return self.template return self._parse_result(self.template) assert self.hass is not None, "hass variable not set on template" @@ -630,7 +630,7 @@ class Template: self._renders += 1 if self.is_static: - if not parse_result or self.hass and self.hass.config.legacy_templates: + if not parse_result or (self.hass and self.hass.config.legacy_templates): return self.template return self._parse_result(self.template) @@ -651,7 +651,7 @@ class Template: render_result = render_result.strip() - if not parse_result or self.hass and self.hass.config.legacy_templates: + if not parse_result or (self.hass and self.hass.config.legacy_templates): return render_result return self._parse_result(render_result) @@ -826,7 +826,7 @@ class Template: ) return value if error_value is _SENTINEL else error_value - if not parse_result or self.hass and self.hass.config.legacy_templates: + if not parse_result or (self.hass and self.hass.config.legacy_templates): return render_result return self._parse_result(render_result) @@ -1873,7 +1873,8 @@ def is_state(hass: HomeAssistant, entity_id: str, state: str | list[str]) -> boo """Test if a state is a specific value.""" state_obj = _get_state(hass, entity_id) return state_obj is not None and ( - state_obj.state == state or isinstance(state, list) and state_obj.state in state + state_obj.state == state + or (isinstance(state, list) and state_obj.state in state) ) diff --git a/homeassistant/helpers/update_coordinator.py b/homeassistant/helpers/update_coordinator.py index 8acd43970f9..62dcb2622e7 100644 --- a/homeassistant/helpers/update_coordinator.py +++ b/homeassistant/helpers/update_coordinator.py @@ -359,7 +359,7 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_DataT]): self._async_unsub_refresh() self._debounced_refresh.async_cancel() - if self._shutdown_requested or scheduled and self.hass.is_stopping: + if self._shutdown_requested or (scheduled and self.hass.is_stopping): return if log_timing := self.logger.isEnabledFor(logging.DEBUG): diff --git a/pylint/plugins/hass_enforce_type_hints.py b/pylint/plugins/hass_enforce_type_hints.py index d66845583d1..d06d078ae8b 100644 --- a/pylint/plugins/hass_enforce_type_hints.py +++ b/pylint/plugins/hass_enforce_type_hints.py @@ -55,10 +55,14 @@ class TypeHintMatch: """Confirm if function should be checked.""" return ( self.function_name == node.name - or self.has_async_counterpart - and node.name == f"async_{self.function_name}" - or self.function_name.endswith("*") - and node.name.startswith(self.function_name[:-1]) + or ( + self.has_async_counterpart + and node.name == f"async_{self.function_name}" + ) + or ( + self.function_name.endswith("*") + and node.name.startswith(self.function_name[:-1]) + ) ) @@ -2998,8 +3002,8 @@ def _is_valid_type( isinstance(node, nodes.Subscript) and isinstance(node.value, nodes.Name) and node.value.name in _KNOWN_GENERIC_TYPES - or isinstance(node, nodes.Name) - and node.name.endswith(_KNOWN_GENERIC_TYPES_TUPLE) + ) or ( + isinstance(node, nodes.Name) and node.name.endswith(_KNOWN_GENERIC_TYPES_TUPLE) ): return True diff --git a/pylint/plugins/hass_imports.py b/pylint/plugins/hass_imports.py index 194f99ae700..2fe70fad10d 100644 --- a/pylint/plugins/hass_imports.py +++ b/pylint/plugins/hass_imports.py @@ -268,9 +268,8 @@ class HassImportsFormatChecker(BaseChecker): self, current_package: str, node: nodes.ImportFrom ) -> None: """Check for improper 'from ._ import _' invocations.""" - if ( - node.level <= 1 - or not current_package.startswith("homeassistant.components.") + if node.level <= 1 or ( + not current_package.startswith("homeassistant.components.") and not current_package.startswith("tests.components.") ): return diff --git a/pyproject.toml b/pyproject.toml index 8cd777c3c67..0623d681df7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -763,6 +763,7 @@ select = [ "RUF018", # Avoid assignment expressions in assert statements "RUF019", # Unnecessary key check before dictionary access "RUF020", # {never_like} | T is equivalent to T + "RUF021", # Parenthesize a and b expressions when chaining and and or together, to make the precedence clear "RUF022", # Sort __all__ "RUF024", # Do not pass mutable objects as values to dict.fromkeys "RUF026", # default_factory is a positional-only argument to defaultdict diff --git a/script/translations/deduplicate.py b/script/translations/deduplicate.py index f92f90115ce..ac608a1aa0e 100644 --- a/script/translations/deduplicate.py +++ b/script/translations/deduplicate.py @@ -70,8 +70,10 @@ def run(): # If we want to only add references to own integrations # but not include entity integrations if ( - args.limit_reference - and (key_integration != key_to_reference_integration and not is_common) + ( + args.limit_reference + and (key_integration != key_to_reference_integration and not is_common) + ) # Do not create self-references in entity integrations or key_integration in Platform.__members__.values() ): diff --git a/tests/components/google_assistant/test_helpers.py b/tests/components/google_assistant/test_helpers.py index 0e6876cc901..a5451e5332d 100644 --- a/tests/components/google_assistant/test_helpers.py +++ b/tests/components/google_assistant/test_helpers.py @@ -316,7 +316,7 @@ async def test_sync_notifications(agents) -> None: config, "async_sync_notification", return_value=HTTPStatus.NO_CONTENT ) as mock: await config.async_sync_notification_all("1234", {}) - assert not agents or bool(mock.mock_calls) and agents + assert not agents or (bool(mock.mock_calls) and agents) @pytest.mark.parametrize( diff --git a/tests/components/imap/test_init.py b/tests/components/imap/test_init.py index d4281b9e513..b86855bd78f 100644 --- a/tests/components/imap/test_init.py +++ b/tests/components/imap/test_init.py @@ -171,11 +171,8 @@ async def test_receiving_message_successfully( assert data["subject"] == "Test subject" assert data["uid"] == "1" assert "Test body" in data["text"] - assert ( - valid_date - and isinstance(data["date"], datetime) - or not valid_date - and data["date"] is None + assert (valid_date and isinstance(data["date"], datetime)) or ( + not valid_date and data["date"] is None ) @@ -581,11 +578,8 @@ async def test_reset_last_message( assert data["subject"] == "Test subject" assert data["text"] assert data["initial"] - assert ( - valid_date - and isinstance(data["date"], datetime) - or not valid_date - and data["date"] is None + assert (valid_date and isinstance(data["date"], datetime)) or ( + not valid_date and data["date"] is None ) # Simulate an update where no messages are found (needed for pushed coordinator) diff --git a/tests/components/matrix/test_commands.py b/tests/components/matrix/test_commands.py index dabee74fdc3..ea0805b920a 100644 --- a/tests/components/matrix/test_commands.py +++ b/tests/components/matrix/test_commands.py @@ -42,9 +42,8 @@ class CommandTestParameters: Commands that are named with 'Subset' are expected not to be read from Room A. """ - if ( - self.expected_event_data_extra is None - or "Subset" in self.expected_event_data_extra["command"] + if self.expected_event_data_extra is None or ( + "Subset" in self.expected_event_data_extra["command"] and self.room_id not in SUBSET_ROOMS ): return None diff --git a/tests/components/onewire/__init__.py b/tests/components/onewire/__init__.py index ac7e917d10a..9c025fe33af 100644 --- a/tests/components/onewire/__init__.py +++ b/tests/components/onewire/__init__.py @@ -25,10 +25,8 @@ def setup_owproxy_mock_devices(owproxy: MagicMock, device_ids: list[str]) -> Non if (side_effect := dir_side_effect.get(path)) is None: raise NotImplementedError(f"Unexpected _dir call: {path}") result = side_effect.pop(0) - if ( - isinstance(result, Exception) - or isinstance(result, type) - and issubclass(result, Exception) + if isinstance(result, Exception) or ( + isinstance(result, type) and issubclass(result, Exception) ): raise result return result @@ -39,10 +37,8 @@ def setup_owproxy_mock_devices(owproxy: MagicMock, device_ids: list[str]) -> Non if len(side_effect) == 0: raise ProtocolError(f"Missing injected value for: {path}") result = side_effect.pop(0) - if ( - isinstance(result, Exception) - or isinstance(result, type) - and issubclass(result, Exception) + if isinstance(result, Exception) or ( + isinstance(result, type) and issubclass(result, Exception) ): raise result return result