Fix line length violations in components c-e (#170540)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: frenck <195327+frenck@users.noreply.github.com>
This commit is contained in:
Franck Nijhof
2026-05-14 16:30:32 -04:00
committed by GitHub
co-authored by copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> frenck
parent 2ec51ef113
commit bb964ccd95
158 changed files with 663 additions and 314 deletions
@@ -102,7 +102,8 @@ class CalDavUpdateCoordinator(DataUpdateCoordinator[CalendarEvent | None]):
)
# Create new events for each recurrence of an event that happens today.
# For recurring events, some servers return the original event with recurrence rules
# For recurring events, some servers return the original
# event with recurrence rules
# and they would not be properly parsed using their original start/end dates.
new_events = []
for event in results:
@@ -150,7 +150,8 @@ def _has_min_duration(
duration = end - start
if duration < min_duration:
raise vol.Invalid(
f"Expected minimum event duration of {min_duration} ({start}, {end})"
"Expected minimum event duration"
f" of {min_duration} ({start}, {end})"
)
return obj
@@ -1056,11 +1057,14 @@ async def handle_calendar_event_subscribe(
def _validate_timespan(
values: dict[str, Any],
) -> tuple[datetime.datetime | datetime.date, datetime.datetime | datetime.date]:
"""Parse a create event service call and convert the args ofr a create event entity call.
"""Parse a create event service call.
This converts the input service arguments into a `start` and `end` date or date time. This
exists because service calls use `start_date` and `start_date_time` whereas the
normal entity methods can take either a `datetime` or `date` as a single `start` argument.
Convert the args for a create event entity call.
This converts the input service arguments into a
`start` and `end` date or date time. This exists because
service calls use `start_date` and `start_date_time`
whereas the normal entity methods can take either a
`datetime` or `date` as a single `start` argument.
It also handles the other service call variations like "in days" as well.
"""
+1 -1
View File
@@ -327,7 +327,7 @@ class TargetCalendarEventListener(TargetEntityChangeTracker):
@callback
def _handle_entities_update(self, tracked_entities: set[str]) -> None:
"""Restart the listeners when the list of entities of the tracked targets is updated."""
"""Restart listeners when tracked target entities update."""
if self._pending_listener_task:
self._pending_listener_task.cancel()
self._pending_listener_task = self._hass.async_create_task(
+14 -6
View File
@@ -545,10 +545,13 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
) -> None:
"""Handle the async WebRTC offer.
Async means that it could take some time to process the offer and responses/message
will be sent with the send_message callback.
This method is used by cameras with CameraEntityFeature.STREAM.
An integration overriding this method must also implement async_on_webrtc_candidate.
Async means that it could take some time to process
the offer and responses/message will be sent with the
send_message callback.
This method is used by cameras with
CameraEntityFeature.STREAM.
An integration overriding this method must also
implement async_on_webrtc_candidate.
Integrations can override with a native WebRTC implementation.
"""
@@ -707,7 +710,10 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
@final
@callback
def async_get_webrtc_client_configuration(self) -> WebRTCClientConfiguration:
"""Return the WebRTC client configuration and extend it with the registered ice servers."""
"""Return the WebRTC client configuration.
Extend it with the registered ice servers.
"""
config = self._async_get_webrtc_client_configuration()
ice_servers = async_get_ice_servers(self.hass)
@@ -999,7 +1005,9 @@ async def async_handle_snapshot_service(
# check if we allow to access to that file
if not hass.config.is_allowed_path(snapshot_file):
raise HomeAssistantError(
f"Cannot write `{snapshot_file}`, no access to path; `allowlist_external_dirs` may need to be adjusted in `configuration.yaml`"
f"Cannot write `{snapshot_file}`, no access to path;"
" `allowlist_external_dirs` may need to be adjusted"
" in `configuration.yaml`"
)
try:
+2 -1
View File
@@ -91,7 +91,8 @@ class TurboJPEGSingleton:
TurboJPEGSingleton.__instance = TurboJPEG()
except Exception:
_LOGGER.exception(
"Error loading libturbojpeg; Camera snapshot performance will be sub-optimal"
"Error loading libturbojpeg;"
" Camera snapshot performance will be sub-optimal"
)
TurboJPEGSingleton.__instance = False
@@ -203,7 +203,8 @@ class CastDevice:
self.hass, SIGNAL_CAST_REMOVED, self._async_cast_removed
)
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self._async_stop)
# async_create_background_task is used to avoid delaying startup wrapup if the device
# async_create_background_task is used to avoid delaying
# startup wrapup if the device
# is discovered already during startup but then fails to respond
self.hass.async_create_background_task(
async_create_catching_coro(self._async_connect_to_chromecast()),
@@ -21,8 +21,10 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
COORDINATOR_NAME = f"{DOMAIN} Coordinator"
# Maximum update frequency is every 6 hours. The API will return 429 Too Many Requests if polled frequently.
# The device updates its data every 8-12 hours, so there's no need to poll more frequently.
# Maximum update frequency is every 6 hours. The API will
# return 429 Too Many Requests if polled frequently.
# The device updates its data every 8-12 hours, so there's
# no need to poll more frequently.
UPDATE_INTERVAL = timedelta(hours=6)
type CentriConnectConfigEntry = ConfigEntry[CentriConnectCoordinator]
+7 -4
View File
@@ -50,7 +50,7 @@ class ChaconDioCover(ChaconDioEntity, CoverEntity):
)
def _update_attr(self, data: dict[str, Any]) -> None:
"""Recomputes the attributes values either at init or when the device state changes."""
"""Recompute the attribute values on init or state change."""
self._attr_available = data["connected"]
self._attr_current_cover_position = data["openlevel"]
self._attr_is_closing = data["movement"] == ShutterMoveEnum.DOWN.value
@@ -60,7 +60,8 @@ class ChaconDioCover(ChaconDioEntity, CoverEntity):
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close the cover.
Closed status is effective after the server callback that triggers callback_device_state.
Closed status is effective after the server callback
that triggers callback_device_state.
"""
_LOGGER.debug(
@@ -82,7 +83,8 @@ class ChaconDioCover(ChaconDioEntity, CoverEntity):
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover.
Opened status is effective after the server callback that triggers callback_device_state.
Opened status is effective after the server callback
that triggers callback_device_state.
"""
_LOGGER.debug(
@@ -113,7 +115,8 @@ class ChaconDioCover(ChaconDioEntity, CoverEntity):
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Set the cover open position in percentage.
Closing or opening status is effective after the server callback that triggers callback_device_state.
Closing or opening status is effective after the server
callback that triggers callback_device_state.
"""
position: int = kwargs[ATTR_POSITION]
@@ -39,14 +39,15 @@ class ChaconDioSwitch(ChaconDioEntity, SwitchEntity):
_attr_name = None
def _update_attr(self, data: dict[str, Any]) -> None:
"""Recomputes the attributes values either at init or when the device state changes."""
"""Recompute the attribute values on init or state change."""
self._attr_available = data["connected"]
self._attr_is_on = data["is_on"]
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the switch.
Turned on status is effective after the server callback that triggers callback_device_state.
Turned on status is effective after the server callback
that triggers callback_device_state.
"""
_LOGGER.debug(
@@ -61,7 +62,8 @@ class ChaconDioSwitch(ChaconDioEntity, SwitchEntity):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the switch.
Turned on status is effective after the server callback that triggers callback_device_state.
Turned on status is effective after the server callback
that triggers callback_device_state.
"""
_LOGGER.debug(
@@ -111,7 +111,8 @@ class CieloClimate(CieloDeviceEntity, ClimateEntity):
def temperature_unit(self) -> str:
"""Return the unit of temperature in Home Assistant format.
It can change over time based on the device settings, so we fetch it dynamically from the client.
It can change over time based on the device settings,
so we fetch it dynamically from the client.
"""
unit = self.client.temperature_unit()
@@ -51,7 +51,9 @@ class CieloDataUpdateCoordinator(DataUpdateCoordinator[CieloData]):
name=DOMAIN,
config_entry=entry,
update_interval=timedelta(seconds=DEFAULT_SCAN_INTERVAL),
# The debouncer prevents multiple rapid refresh requests from triggering repeated full data fetches from the backend.
# The debouncer prevents multiple rapid refresh
# requests from triggering repeated full data
# fetches from the backend.
request_refresh_debouncer=Debouncer(
hass, LOGGER, cooldown=REQUEST_REFRESH_DELAY, immediate=False
),
+3 -1
View File
@@ -120,7 +120,9 @@ TRIGGERS: dict[str, type[Trigger]] = {
"target_humidity_changed": ClimateTargetHumidityChangedTrigger,
"target_humidity_crossed_threshold": ClimateTargetHumidityCrossedThresholdTrigger,
"target_temperature_changed": ClimateTargetTemperatureChangedTrigger,
"target_temperature_crossed_threshold": ClimateTargetTemperatureCrossedThresholdTrigger,
"target_temperature_crossed_threshold": (
ClimateTargetTemperatureCrossedThresholdTrigger
),
"turned_off": make_entity_target_state_trigger(DOMAIN, HVACMode.OFF),
"turned_on": make_entity_transition_trigger(
DOMAIN,
+4 -1
View File
@@ -253,7 +253,10 @@ def async_listen_cloudhook_change(
webhook_id: str,
on_change: Callable[[dict[str, Any] | None], None],
) -> Callable[[], None]:
"""Listen for cloudhook changes for the given webhook and notify when modified or deleted."""
"""Listen for cloudhook changes for the given webhook.
Notify when modified or deleted.
"""
@callback
def _handle_cloudhooks_updated(cloudhooks: dict[str, Any]) -> None:
@@ -128,8 +128,10 @@ class CloudOAuth2Implementation(config_entry_oauth2_flow.AbstractOAuth2Implement
flow_id=flow_id, user_input=tokens
)
# It's a background task because it should be cancelled on shutdown and there's nothing else
# we can do in such case. There's also no need to wait for this during setup.
# It's a background task because it should be cancelled
# on shutdown and there's nothing else we can do in
# such case. There's also no need to wait for this
# during setup.
self.hass.async_create_background_task(
await_tokens(), name="Awaiting OAuth tokens"
)
@@ -230,7 +230,8 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
ALEXA_SETTINGS_VERSION,
)
if self._prefs.alexa_settings_version < 2 or (
# Recover from a bug we had in 2023.5.0 where entities didn't get exposed
# Recover from a bug we had in 2023.5.0
# where entities didn't get exposed
self._prefs.alexa_settings_version < 3
and not any(
settings.get("should_expose", False)
+5 -1
View File
@@ -372,7 +372,11 @@ class CloudClient(Interface):
method=payload["method"],
query_string=payload["query"],
mock_source=DOMAIN,
remote=None, # Remote will be used for the local_only check, but since this is from the cloud we want it to be None to mark it as non-local and bypass the ip parsing and remote checks
# Remote will be used for the local_only check, but
# since this is from the cloud we want it to be None
# to mark it as non-local and bypass the ip parsing
# and remote checks
remote=None,
)
response = await webhook.async_handle_webhook(
+9 -7
View File
@@ -596,13 +596,15 @@ class BaseCloudLLMEntity(Entity):
_convert_content_to_param(
[
content
async for content in chat_log.async_add_delta_content_stream(
self.entity_id,
_transform_stream(
chat_log,
raw_stream,
True,
),
async for content in (
chat_log.async_add_delta_content_stream(
self.entity_id,
_transform_stream(
chat_log,
raw_stream,
True,
),
)
)
]
)
@@ -171,7 +171,7 @@ class CloudGoogleConfig(AbstractConfig):
return self.enabled and self._prefs.google_report_state
def get_local_webhook_id(self, agent_user_id: Any) -> str:
"""Return the webhook ID to be used for actions for a given agent user id via the local SDK."""
"""Return the webhook ID for actions for an agent user id via the local SDK."""
return self._prefs.google_local_webhook_id
def get_local_user_id(self, webhook_id: Any) -> str:
@@ -226,7 +226,8 @@ class CloudGoogleConfig(AbstractConfig):
GOOGLE_SETTINGS_VERSION,
)
if self._prefs.google_settings_version < 2 or (
# Recover from a bug we had in 2023.5.0 where entities didn't get exposed
# Recover from a bug we had in 2023.5.0
# where entities didn't get exposed
self._prefs.google_settings_version < 3
and not any(
settings.get("should_expose", False)
+8 -2
View File
@@ -138,7 +138,8 @@ def async_setup(hass: HomeAssistant) -> None:
),
MFAExpiredOrNotStarted: (
HTTPStatus.BAD_REQUEST,
"Multi-factor authentication expired, or not started. Please try again.",
"Multi-factor authentication expired,"
" or not started. Please try again.",
),
AlreadyConnectedError: (
HTTPStatus.CONFLICT,
@@ -561,7 +562,12 @@ class DownloadSupportPackageView(HomeAssistantView):
markdown += "--- | --- | --- | ---\n"
for integration in integration_info["custom_integrations"]:
doc_url = integration.get("documentation") or "N/A"
markdown += f"{integration['domain']} | {integration['name']} | {integration['version']} | {doc_url}\n"
markdown += (
f"{integration['domain']} | "
f"{integration['name']} | "
f"{integration['version']} | "
f"{doc_url}\n"
)
markdown += "\n</details>\n\n"
for domain, domain_info in domains_info.items():
+4 -2
View File
@@ -284,7 +284,8 @@ class CloudPreferences:
def alexa_default_expose(self) -> list[str] | None:
"""Return array of entity domains that are exposed by default to Alexa.
Can return None, in which case for backwards should be interpreted as allow all domains.
Can return None, in which case for backwards
should be interpreted as allow all domains.
"""
return self._prefs.get(PREF_ALEXA_DEFAULT_EXPOSE)
@@ -342,7 +343,8 @@ class CloudPreferences:
def google_default_expose(self) -> list[str] | None:
"""Return array of entity domains that are exposed by default to Google.
Can return None, in which case for backwards should be interpreted as allow all domains.
Can return None, in which case for backwards
should be interpreted as allow all domains.
"""
return self._prefs.get(PREF_GOOGLE_DEFAULT_EXPOSE)
@@ -25,7 +25,8 @@ async def async_subscription_info(cloud: Cloud[CloudClient]) -> SubscriptionInfo
_LOGGER.error("Failed to fetch subscription information - %s", exception)
except TimeoutError:
_LOGGER.error(
"A timeout of %s was reached while trying to fetch subscription information",
"A timeout of %s was reached while trying to"
" fetch subscription information",
REQUEST_TIMEOUT,
)
return None
@@ -1,4 +1,4 @@
"""Contains the Coordinator for updating the IP addresses of your Cloudflare DNS records."""
"""Coordinator for updating IP addresses of Cloudflare DNS records."""
import asyncio
from datetime import timedelta
@@ -240,8 +240,10 @@ class R2BackupAgent(BackupAgent):
finally:
view.release()
# Compact the buffer if the consumed offset has grown large enough. This
# avoids unnecessary memory copies when compacting after every part upload.
# Compact the buffer if the consumed offset
# has grown large enough. This avoids
# unnecessary memory copies when compacting
# after every part upload.
if offset and offset >= MULTIPART_MIN_PART_SIZE_BYTES:
buffer = bytearray(buffer[offset:])
offset = 0
@@ -63,7 +63,8 @@ def create_and_update_instance(entry: CoinbaseConfigEntry) -> CoinbaseData:
raise ConfigEntryAuthFailed(
"Your Coinbase API key appears to be for the deprecated v2 API. "
"Please reconfigure with a new API key created for the v3 API. "
"Visit https://www.coinbase.com/developer-platform to create new credentials."
"Visit https://www.coinbase.com/developer-platform"
" to create new credentials."
)
client = RESTClient(
@@ -300,4 +300,4 @@ class CurrencyUnavailable(HomeAssistantError):
class ExchangeRateUnavailable(HomeAssistantError):
"""Error to indicate the requested exchange rate resource is not provided by the API."""
"""Error to indicate the requested exchange rate is not provided by the API."""
+3 -1
View File
@@ -157,7 +157,9 @@ class AccountSensor(SensorEntity):
def extra_state_attributes(self) -> dict[str, str]:
"""Return the state attributes of the sensor."""
return {
ATTR_NATIVE_BALANCE: f"{self._native_balance} {self._coinbase_data.exchange_base}",
ATTR_NATIVE_BALANCE: (
f"{self._native_balance} {self._coinbase_data.exchange_base}"
),
}
def update(self) -> None:
@@ -125,7 +125,8 @@ class CommandBinarySensor(ManualTriggerEntity, BinarySensorEntity):
self._process_updates = asyncio.Lock()
if self._process_updates.locked():
LOGGER.warning(
"Updating Command Line Binary Sensor %s took longer than the scheduled update interval %s",
"Updating Command Line Binary Sensor %s took longer"
" than the scheduled update interval %s",
self.name,
self._scan_interval,
)
@@ -157,7 +157,8 @@ class CommandCover(ManualTriggerEntity, CoverEntity):
self._process_updates = asyncio.Lock()
if self._process_updates.locked():
LOGGER.warning(
"Updating Command Line Cover %s took longer than the scheduled update interval %s",
"Updating Command Line Cover %s took longer than"
" the scheduled update interval %s",
self.name,
self._scan_interval,
)
@@ -134,7 +134,8 @@ class CommandSensor(ManualTriggerSensorEntity):
if self._process_updates.locked():
LOGGER.warning(
"Updating Command Line Sensor %s took longer than the scheduled update interval %s",
"Updating Command Line Sensor %s took longer than"
" the scheduled update interval %s",
self.name,
self._scan_interval,
)
@@ -163,7 +163,8 @@ class CommandSwitch(ManualTriggerEntity, SwitchEntity):
self._process_updates = asyncio.Lock()
if self._process_updates.locked():
LOGGER.warning(
"Updating Command Line Switch %s took longer than the scheduled update interval %s",
"Updating Command Line Switch %s took longer than"
" the scheduled update interval %s",
self.name,
self._scan_interval,
)
@@ -155,7 +155,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: Control4ConfigEntry) ->
config[CONF_HOST],
)
raise ConfigEntryNotReady(
f"Timeout getting UI configuration from Control4 controller at {config[CONF_HOST]}"
"Timeout getting UI configuration from"
f" Control4 controller at {config[CONF_HOST]}"
) from err
ui_configuration = json.loads(ui_config_raw)
+2 -1
View File
@@ -202,7 +202,8 @@ class Control4Climate(Control4Entity, ClimateEntity):
def _create_api_object(self) -> C4Climate:
"""Create a pyControl4 device object.
This exists so the director token used is always the latest one, without needing to re-init the entire entity.
This exists so the director token used is always the
latest one, without needing to re-init the entire entity.
"""
return C4Climate(self.runtime_data.director, self._idx)
+2 -1
View File
@@ -182,7 +182,8 @@ class Control4Light(Control4Entity, LightEntity):
def _create_api_object(self):
"""Create a pyControl4 device object.
This exists so the director token used is always the latest one, without needing to re-init the entire entity.
This exists so the director token used is always the
latest one, without needing to re-init the entire entity.
"""
return C4Light(self.runtime_data.director, self._idx)
@@ -222,7 +222,8 @@ class Control4Room(Control4Entity, MediaPlayerEntity):
def _create_api_object(self) -> C4Room:
"""Create a pyControl4 device object.
This exists so the director token used is always the latest one, without needing to re-init the entire entity.
This exists so the director token used is always the
latest one, without needing to re-init the entire entity.
"""
return C4Room(self.runtime_data.director, self._idx)
@@ -421,9 +421,11 @@ class ChatLog:
) -> AsyncGenerator[ToolResultContent]:
"""Add assistant content and execute tool calls.
tool_call_tasks can contains tasks for tool calls that are already in progress.
tool_call_tasks can contain tasks for tool calls
that are already in progress.
This method is an async generator and will yield the tool results as they come in.
This method is an async generator and will yield
the tool results as they come in.
"""
LOGGER.debug("Adding assistant content: %s", content)
self.content.append(content)
@@ -487,14 +489,17 @@ class ChatLog:
) -> AsyncGenerator[AssistantContent | ToolResultContent]:
"""Stream content into the chat log.
Returns a generator with all content that was added to the chat log.
Returns a generator with all content that was added
to the chat log.
stream iterates over dictionaries with optional keys role, content and tool_calls.
stream iterates over dictionaries with optional keys
role, content and tool_calls.
When a delta contains a role key, the current message is considered complete and
a new message is started.
When a delta contains a role key, the current message
is considered complete and a new message is started.
The keys content and tool_calls will be concatenated if they appear multiple times.
The keys content and tool_calls will be concatenated
if they appear multiple times.
"""
current_content = ""
current_thinking_content = ""
@@ -730,7 +735,8 @@ class ChatLog:
if llm_api:
prompt_parts.append(llm_api.api_prompt)
# Append current date and time to the prompt if the corresponding tool is not provided
# Append current date and time to the prompt if the
# corresponding tool is not provided
llm_tools: list[llm.Tool] = llm_api.tools if llm_api else []
if not any(tool.name.endswith("GetDateTime") for tool in llm_tools):
prompt_parts.append(
@@ -171,7 +171,7 @@ class IntentCache:
return self.cache[key]
def put(self, key: IntentCacheKey, value: IntentCacheValue) -> None:
"""Put a value in the cache, evicting the least recently used item if necessary."""
"""Put a value in the cache, evicting the LRU item if necessary."""
if key in self.cache:
# Update value and mark as recently used
self.cache.move_to_end(key)
@@ -1072,7 +1072,8 @@ class DefaultAgent(ConversationEntity):
dict,
):
_LOGGER.warning(
"Custom sentences file does not match expected format path=%s",
"Custom sentences file does not match"
" expected format path=%s",
custom_sentences_file.name,
)
continue
@@ -1474,7 +1475,7 @@ def _make_error_result(
def _get_unmatched_response(result: RecognizeResult) -> tuple[ErrorKey, dict[str, Any]]:
"""Get key and template arguments for error when there are unmatched intent entities/slots."""
"""Get key and template args for unmatched intent entities/slots error."""
# Filter out non-text and missing context entities
unmatched_text: dict[str, str] = {
@@ -182,7 +182,7 @@ async def websocket_list_sentences(
async def websocket_hass_agent_debug(
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
) -> None:
"""Return intents that would be matched by the default agent for a list of sentences."""
"""Return intents matched by the default agent for a list of sentences."""
agent = get_agent_manager(hass).default_agent
assert agent is not None
@@ -31,7 +31,8 @@ def async_get_result_from_chat_log(
if not isinstance((last_content := chat_log.content[-1]), AssistantContent):
_LOGGER.error(
"Last content in chat log is not an AssistantContent: %s. This could be due to the model not returning a valid response",
"Last content in chat log is not an AssistantContent: %s."
" This could be due to the model not returning a valid response",
last_content,
)
raise HomeAssistantError("Unable to get response")
@@ -94,7 +94,8 @@ class CookidooDataUpdateCoordinator(DataUpdateCoordinator[CookidooData]):
},
) from exc
_LOGGER.debug(
"Authentication failed but re-authentication was successful, trying again later"
"Authentication failed but re-authentication"
" was successful, trying again later"
)
return self.data
except CookidooException as e:
+5 -2
View File
@@ -73,7 +73,10 @@ class CookidooIngredientsTodoListEntity(CookidooBaseEntity, TodoListEntity):
async def async_update_todo_item(self, item: TodoItem) -> None:
"""Update an ingredient to the To-do list.
Cookidoo ingredients can be changed in state, but not in summary or description. This is currently not possible to distinguish in home assistant and just fails silently.
Cookidoo ingredients can be changed in state, but not
in summary or description. This is currently not
possible to distinguish in Home Assistant and just
fails silently.
"""
try:
if TYPE_CHECKING:
@@ -99,7 +102,7 @@ class CookidooIngredientsTodoListEntity(CookidooBaseEntity, TodoListEntity):
class CookidooAdditionalItemTodoListEntity(CookidooBaseEntity, TodoListEntity):
"""A To-do List representation of the additional items in the Cookidoo Shopping List."""
"""A To-do List representation of additional Cookidoo Shopping List items."""
_attr_translation_key = "additional_item_list"
_attr_supported_features = (
@@ -68,7 +68,8 @@ class CoolmasterClimate(CoolmasterEntity, ClimateEntity):
_attr_name = None
# TODO(2026.7.0): When support for unknown fan speeds is removed, delete this variable.
# TODO(2026.7.0): When support for unknown fan speeds is
# removed, delete this variable.
# Holds unknown fan speeds we have already warned about.
warned_unknown_fan_speeds: set[str] = set()
@@ -54,7 +54,9 @@ class CoolmasterDataUpdateCoordinator(
except OSError as error:
if retries_left == 0:
raise UpdateFailed(
f"Error communicating with Coolmaster (aborting after {MAX_RETRIES} retries): {error}"
"Error communicating with Coolmaster"
f" (aborting after {MAX_RETRIES}"
f" retries): {error}"
) from error
_LOGGER.debug(
"Error communicating with coolmaster (%d retries left): %s",
@@ -66,7 +68,8 @@ class CoolmasterDataUpdateCoordinator(
return status
_LOGGER.debug(
"Error communicating with coolmaster: empty status received (%d retries left)",
"Error communicating with coolmaster:"
" empty status received (%d retries left)",
retries_left,
)
@@ -74,5 +77,7 @@ class CoolmasterDataUpdateCoordinator(
await asyncio.sleep(backoff)
raise UpdateFailed(
f"Error communicating with Coolmaster (aborting after {MAX_RETRIES} retries): empty status received"
"Error communicating with Coolmaster"
f" (aborting after {MAX_RETRIES} retries):"
" empty status received"
)
+6 -3
View File
@@ -254,17 +254,20 @@ class Counter(collection.CollectionEntity, RestoreEntity):
"""Set counter to value."""
if (maximum := self._config.get(CONF_MAXIMUM)) is not None and value > maximum:
raise ValueError(
f"Value {value} for {self.entity_id} exceeding the maximum value of {maximum}"
f"Value {value} for {self.entity_id}"
f" exceeding the maximum value of {maximum}"
)
if (minimum := self._config.get(CONF_MINIMUM)) is not None and value < minimum:
raise ValueError(
f"Value {value} for {self.entity_id} exceeding the minimum value of {minimum}"
f"Value {value} for {self.entity_id}"
f" exceeding the minimum value of {minimum}"
)
if (step := self._config.get(CONF_STEP)) is not None and value % step != 0:
raise ValueError(
f"Value {value} for {self.entity_id} is not a multiple of the step size {step}"
f"Value {value} for {self.entity_id}"
f" is not a multiple of the step size {step}"
)
self._state = value
+7 -3
View File
@@ -428,9 +428,13 @@ class CoverEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
# * fully open but do not report `current_cover_position`
# * stopped partially open
# * either opening or closing, but do not report them
# If we previously reported opening/closing, we should move in the opposite direction.
# Otherwise, we must assume we are (partially) open and should always close.
# Note: _cover_is_last_toggle_direction_open will always remain True if we never report opening/closing.
# If we previously reported opening/closing, we should
# move in the opposite direction.
# Otherwise, we must assume we are (partially) open
# and should always close.
# Note: _cover_is_last_toggle_direction_open will
# always remain True if we never report
# opening/closing.
return (
fns["close"] if self._cover_is_last_toggle_direction_open else fns["open"]
)
@@ -79,7 +79,8 @@ class CrownstoneEntryManager:
_LOGGER.error("Unknown error during login")
raise ConfigEntryNotReady from unknown_err
# A new clientsession is created because the default one does not cleanup on unload
# A new clientsession is created because the default
# one does not cleanup on unload
self.sse = CrownstoneSSEAsync(
email=email,
password=password,
@@ -98,7 +99,8 @@ class CrownstoneEntryManager:
await self.async_setup_usb()
# Save the sphere where the USB is located
# Makes HA aware of the Crownstone environment HA is placed in, a user can have multiple
# Makes HA aware of the Crownstone environment HA is
# placed in, a user can have multiple
self.usb_sphere_id = self.config_entry.options[CONF_USB_SPHERE]
return True
@@ -1,7 +1,9 @@
"""Listeners for updating data in the Crownstone integration.
For data updates, Cloud Push is used in form of an SSE server that sends out events.
For fast device switching Local Push is used in form of a USB dongle that hooks into a BLE mesh.
For data updates, Cloud Push is used in form of an SSE server
that sends out events.
For fast device switching Local Push is used in form of a USB
dongle that hooks into a BLE mesh.
"""
from functools import partial
+1 -1
View File
@@ -88,7 +88,7 @@ class CyncConfigFlow(ConfigFlow, domain=DOMAIN):
async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Dialog that informs the user that reauth is required and prompts for their Cync credentials."""
"""Inform the user that reauth is required and prompt for Cync credentials."""
errors: dict[str, str] = {}
reauth_entry = self._get_reauth_entry()
+1 -1
View File
@@ -51,7 +51,7 @@ class CyncCoordinator(DataUpdateCoordinator[dict[int, CyncDevice]]):
await self._update_config_cync_credentials(logged_in_user)
async def _async_update_data(self) -> dict[int, CyncDevice]:
"""First, refresh the user's auth token if it is set to expire in less than one hour.
"""Refresh the user's auth token if it expires within one hour.
Then, fetch all current device states.
"""
+4 -1
View File
@@ -173,7 +173,10 @@ async def async_setup_entry(
def format_target_temperature(target_temperature: float) -> str:
"""Format target temperature to be sent to the Daikin unit, rounding to nearest half degree."""
"""Format target temperature to be sent to the Daikin unit.
Rounds to nearest half degree.
"""
return str(round(float(target_temperature) * 2, 0) / 2).rstrip("0").rstrip(".")
+2 -1
View File
@@ -32,7 +32,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: DeakoConfigEntry) -> boo
await connection.disconnect()
raise ConfigEntryNotReady(exc) from exc
# If deako devices are advertising on mdns, we should be able to get at least one device
# If deako devices are advertising on mdns, we should be
# able to get at least one device
devices = connection.get_devices()
if len(devices) == 0:
await connection.disconnect()
+14 -8
View File
@@ -13,14 +13,19 @@ LOGGER = logging.getLogger(__package__)
class DelugeGetSessionStatusKeys(enum.Enum):
"""Enum representing the keys that get passed into the Deluge RPC `core.get_session_status` xml rpc method.
"""Keys passed into the Deluge RPC `core.get_session_status`.
You can call `core.get_session_status` with no keys (so an empty list in deluge-client.DelugeRPCClient.call)
to get the full list of possible keys, but it seems to basically be a all of the session statistics
listed on this page: https://www.rasterbar.com/products/libtorrent/manual-ref.html#session-statistics
You can call `core.get_session_status` with no keys
(so an empty list in
deluge-client.DelugeRPCClient.call)
to get the full list of possible keys, but it seems to
basically be all of the session statistics listed on
this page:
https://www.rasterbar.com/products/libtorrent/manual-ref.html#session-statistics
and a few others
there is also a list of deprecated keys that deluge will translate for you and issue a warning in the log:
there is also a list of deprecated keys that deluge
will translate for you and issue a warning in the log:
https://github.com/deluge-torrent/deluge/blob/7f3f7f69ee78610e95bea07d99f699e9310c4e08/deluge/core/core.py#L58
"""
@@ -32,10 +37,11 @@ class DelugeGetSessionStatusKeys(enum.Enum):
class DelugeSensorType(enum.StrEnum):
"""Enum that distinguishes the different sensor types that the Deluge integration has.
"""Sensor types for the Deluge integration.
This is mainly used to avoid passing strings around and to distinguish between similarly
named strings in `DelugeGetSessionStatusKeys`.
This is mainly used to avoid passing strings around
and to distinguish between similarly named strings
in `DelugeGetSessionStatusKeys`.
"""
CURRENT_STATUS_SENSOR = "current_status"
+2 -1
View File
@@ -27,7 +27,8 @@ def get_state(data: dict[str, float], key: str) -> str | float:
protocol_upload = data[DelugeGetSessionStatusKeys.DHT_UPLOAD_RATE.value]
protocol_download = data[DelugeGetSessionStatusKeys.DHT_DOWNLOAD_RATE.value]
# if key is CURRENT_STATUS, we just return whether we are uploading / downloading / idle
# if key is CURRENT_STATUS, we just return whether
# we are uploading / downloading / idle
if key == DelugeSensorType.CURRENT_STATUS_SENSOR:
if upload > 0 and download > 0:
return "seeding_and_downloading"
@@ -252,13 +252,15 @@ class DenonDevice(MediaPlayerEntity):
def _telnet_callback(self, zone: str, event: str, parameter: str) -> None:
"""Process a telnet command callback."""
# There are multiple checks implemented which reduce unnecessary updates of the ha state machine
# There are multiple checks implemented which reduce
# unnecessary updates of the ha state machine
if zone not in (self._receiver.zone, ALL_ZONES):
return
if event not in TELNET_EVENTS:
return
# Some updates trigger multiple events like one for artist and one for title for one change
# We skip every event except the last one
# Some updates trigger multiple events like one for
# artist and one for title for one change.
# We skip every event except the last one.
if event == "NSE" and not parameter.startswith("4"):
return
if event == "TA" and not parameter.startswith("ANNAME"):
@@ -63,7 +63,8 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
new_options = {**config_entry.options}
if new_options.get("unit_prefix") == "none":
# Before we had support for optional selectors, "none" was used for selecting nothing
# Before we had support for optional selectors,
# "none" was used for selecting nothing
del new_options["unit_prefix"]
hass.config_entries.async_update_entry(
+23 -12
View File
@@ -275,7 +275,8 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
if original_unit != self._attr_native_unit_of_measurement:
_LOGGER.debug(
"%s: Derivative sensor switched UoM from %s to %s, resetting state to 0",
"%s: Derivative sensor switched UoM from"
" %s to %s, resetting state to 0",
self.entity_id,
original_unit,
self._attr_native_unit_of_measurement,
@@ -327,7 +328,8 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
)
def _handle_invalid_source_state(self, state: State | None) -> bool:
# Check the source state for unknown/unavailable condition. If unusable, write unknown/unavailable state and return false.
# Check the source state for unknown/unavailable condition.
# If unusable, write unknown/unavailable state and return false.
if not state or state.state == STATE_UNAVAILABLE:
self._attr_available = False
self.async_write_ha_state()
@@ -376,10 +378,12 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
def schedule_max_sub_interval_exceeded(source_state: State | None) -> None:
"""Schedule calculation using the source state and max_sub_interval.
The callback reference is stored for possible cancellation if the source state
reports a change before max_sub_interval has passed.
If the callback is executed, meaning there was no state change reported, the
source_state is assumed constant and calculation is done using its value.
The callback reference is stored for possible
cancellation if the source state reports a change
before max_sub_interval has passed.
If the callback is executed, meaning there was no
state change reported, the source_state is assumed
constant and calculation is done using its value.
"""
if (
self._max_sub_interval is not None
@@ -394,14 +398,17 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
"""Calculate derivative based on time and reschedule."""
_LOGGER.debug(
"%s: Recalculating derivative due to max_sub_interval time elapsed",
"%s: Recalculating derivative due to"
" max_sub_interval time elapsed",
self.entity_id,
)
self._prune_state_list(now)
derivative = self._calc_derivative_from_state_list(now)
self._write_native_value(derivative)
# If derivative is now zero, don't schedule another timeout callback, as it will have no effect
# If derivative is now zero, don't schedule
# another timeout callback, as it will have
# no effect
if derivative != 0:
schedule_max_sub_interval_exceeded(source_state)
@@ -483,7 +490,8 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
old_value = self._last_valid_state_time[0]
old_timestamp = self._last_valid_state_time[1]
else:
# Sensor becomes valid for the first time, just keep the restored value
# Sensor becomes valid for the first time,
# just keep the restored value
self.async_write_ha_state()
return
@@ -525,7 +533,8 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
"%s: Could not calculate derivative: %s", self.entity_id, err
)
# For total inreasing sensors, the value is expected to continuously increase.
# For total increasing sensors, the value is
# expected to continuously increase.
# A negative derivative for a total increasing sensor likely indicates the
# sensor has been reset. To prevent inaccurate data, discard this sample.
if (
@@ -546,8 +555,10 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
new_timestamp,
)
# If outside of time window just report derivative (is the same as modeling it in the window),
# otherwise take the weighted average with the previous derivatives
# If outside of time window just report derivative
# (is the same as modeling it in the window),
# otherwise take the weighted average with the
# previous derivatives
if elapsed_time > self._time_window:
derivative = new_derivative
else:
@@ -162,7 +162,8 @@ async def async_get_device_automation_platform(
) -> DeviceAutomationPlatformType:
"""Load device automation platform for integration.
Throws InvalidDeviceAutomationConfig if the integration is not found or does not support device automation.
Throws InvalidDeviceAutomationConfig if the integration is not found
or does not support device automation.
"""
platform_name = automation_type.value.section
try:
@@ -106,7 +106,10 @@ def configure_mydevolo(conf: Mapping[str, Any]) -> Mydevolo:
def check_mydevolo_and_get_gateway_ids(mydevolo: Mydevolo) -> list[str]:
"""Check if the credentials are valid and return user's gateway IDs as long as mydevolo is not in maintenance mode."""
"""Check credentials and return user's gateway IDs.
Raises if mydevolo is in maintenance mode.
"""
if not mydevolo.credentials_valid():
raise ConfigEntryAuthFailed(
translation_domain=DOMAIN,
@@ -29,7 +29,7 @@ async def async_setup_entry(
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Get all binary sensor and multi level sensor devices and setup them via config entry."""
"""Get all binary sensor and multi level sensor devices."""
entities: list[BinarySensorEntity] = []
for gateway in entry.runtime_data:
@@ -75,7 +75,9 @@ class DevoloClimateDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, ClimateEntit
return next(
(
multi_level_sensor.value
for multi_level_sensor in self._device_instance.multi_level_sensor_property.values()
for multi_level_sensor in (
self._device_instance.multi_level_sensor_property.values()
)
if multi_level_sensor.sensor_type == "temperature"
),
None,
@@ -117,7 +117,9 @@ class DevoloHomeControlFlowHandler(ConfigFlow, domain=DOMAIN):
)
if self.unique_id != uuid:
# The old user and the new user are not the same. This could mess-up everything as all unique IDs might change.
# The old user and the new user are not the same.
# This could mess-up everything as all
# unique IDs might change.
raise UuidChanged
reauth_entry = self._get_reauth_entry()
@@ -115,7 +115,10 @@ class DevoloDeviceEntity(Entity):
class DevoloMultiLevelSwitchDeviceEntity(DevoloDeviceEntity):
"""Representation of a multi level switch device within devolo Home Control. Something like a dimmer or a thermostat."""
"""Representation of a multi level switch device within devolo Home Control.
Something like a dimmer or a thermostat.
"""
_attr_name = None
@@ -70,7 +70,8 @@ class DevoloLightDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, LightEntity):
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.
# 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:
# If there is no binary switch attached to the device, turn it on to 100 %.
@@ -18,7 +18,7 @@ async def async_setup_entry(
entry: DevoloHomeControlConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Get all binary sensor and multi level sensor devices and setup them via config entry."""
"""Get all binary sensor and multi level sensor devices."""
async_add_entities(
DevoloSirenDeviceEntity(
@@ -40,9 +40,11 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,
await device.async_connect(session_instance=async_client)
# Try a password protected, non-writing device API call that raises, if the password is wrong.
# If only the plcnet API is available, we can continue without trying a password as the plcnet
# API does not require a password.
# Try a password protected, non-writing device API
# call that raises, if the password is wrong.
# If only the plcnet API is available, we can continue
# without trying a password as the plcnet API does not
# require a password.
if device.device:
await device.device.async_uptime()
@@ -82,7 +82,7 @@ class DevoloDataUpdateCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
@callback
def update_sw_version(self) -> None:
"""Update device registry with new firmware version, if it changed at runtime."""
"""Update device registry with new firmware version."""
device_registry = dr.async_get(self.hass)
if (
device_entry := device_registry.async_get_device(
@@ -35,7 +35,11 @@ PARALLEL_UPDATES = 0
def _last_restart(runtime: int) -> datetime:
"""Calculate uptime. As fetching the data might also take some time, let's floor to the nearest 5 seconds."""
"""Calculate uptime.
As fetching the data might also take some time,
let's floor to the nearest 5 seconds.
"""
now = utcnow()
return (
now
+2 -1
View File
@@ -130,7 +130,8 @@ class DiscogsSensor(SensorEntity):
"cat_no": self._attrs["labels"][0]["catno"],
"cover_image": self._attrs["cover_image"],
"format": (
f"{self._attrs['formats'][0]['name']} ({self._attrs['formats'][0]['descriptions'][0]})"
f"{self._attrs['formats'][0]['name']}"
f" ({self._attrs['formats'][0]['descriptions'][0]})"
),
"label": self._attrs["labels"][0]["name"],
"released": self._attrs["year"],
@@ -25,7 +25,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: DiscovergyConfigEntry) -
)
try:
# try to get meters from api to check if credentials are still valid and for later use
# try to get meters from api to check if credentials
# are still valid and for later use;
# if no exception is raised everything is fine to go
meters = await client.meters()
except discovergyError.InvalidLogin as err:
@@ -173,7 +173,8 @@ async def async_setup_entry(
for coordinator in entry.runtime_data:
sensors: tuple[DiscovergySensorEntityDescription, ...] = ()
# select sensor descriptions based on meter type and combine with additional sensors
# select sensor descriptions based on meter type
# and combine with additional sensors
if coordinator.meter.measurement_type == "ELECTRICITY":
sensors = ELECTRICITY_SENSORS + ADDITIONAL_SENSORS
elif coordinator.meter.measurement_type == "GAS":
@@ -213,7 +214,11 @@ class DiscovergySensor(CoordinatorEntity[DiscovergyUpdateCoordinator], SensorEnt
self._attr_unique_id = f"{meter.full_serial_number}-{data_key}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, meter.meter_id)},
name=f"{meter.measurement_type.capitalize()} {meter.location.street} {meter.location.street_number}",
name=(
f"{meter.measurement_type.capitalize()}"
f" {meter.location.street}"
f" {meter.location.street_number}"
),
model=meter.meter_type,
manufacturer=MANUFACTURER,
serial_number=meter.full_serial_number,
@@ -116,7 +116,8 @@ class DoorBirdConfigFlow(ConfigFlow, domain=DOMAIN):
This method performs the following verification steps:
1. Ensures that the stored credentials work before updating the entry.
2. Verifies that the device at the discovered IP address has the expected MAC address.
2. Verifies that the device at the discovered IP
address has the expected MAC address.
"""
info, errors = await self._async_validate_or_error(
{
@@ -19,7 +19,10 @@ async def async_setup_entry(
config_entry: DremelConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up a MJPEG IP Camera for the 3D45 Model. The 3D20 and 3D40 models don't have built in cameras."""
"""Set up a MJPEG IP Camera for the 3D45 Model.
The 3D20 and 3D40 models don't have built in cameras.
"""
async_add_entities([Dremel3D45Camera(config_entry.runtime_data, CAMERA_TYPE)])
@@ -54,8 +54,9 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
f"{self._drop_discovery.hub_id}_{self._drop_discovery.device_id}"
)
if existing_entry is not None:
# Note: returning "invalid_discovery_info" here instead of "already_configured"
# allows discovery of additional device types.
# Note: returning "invalid_discovery_info" here
# instead of "already_configured" allows discovery
# of additional device types.
return self.async_abort(reason="invalid_discovery_info")
self.context.update({"title_placeholders": {"name": self._drop_discovery.name}})
@@ -25,7 +25,10 @@ async def async_get_auth_implementation(
class DropboxOAuth2Implementation(LocalOAuth2ImplementationWithPkce):
"""Custom Dropbox OAuth2 implementation to add the necessary authorize url parameters."""
"""Custom Dropbox OAuth2 implementation.
Adds the necessary authorize url parameters.
"""
@property
def extra_authorize_data(self) -> dict:
+3 -1
View File
@@ -126,7 +126,9 @@ class DSMRConnection:
async with asyncio.timeout(30):
await protocol.wait_closed()
except TimeoutError:
# Timeout (no data received), close transport and return True (if telegram is empty, will result in CannotCommunicate error)
# Timeout (no data received), close transport
# and return True (if telegram is empty, will
# result in CannotCommunicate error)
transport.close()
await protocol.wait_closed()
return True
@@ -16,7 +16,10 @@ async def _async_has_devices(_: HomeAssistant) -> bool:
class DsmrReaderFlowHandler(DiscoveryFlowHandler[Awaitable[bool]], domain=DOMAIN):
"""Handle DSMR Reader config flow. The MQTT step is inherited from the parent class."""
"""Handle DSMR Reader config flow.
The MQTT step is inherited from the parent class.
"""
VERSION = 1
+2 -1
View File
@@ -34,7 +34,8 @@ async def async_get_config_entry_diagnostics(
coordinator = entry.runtime_data
board = asdict(coordinator.board_info)
# `time` is a Unix epoch timestamp of the last board info fetch; not useful for support triage.
# `time` is a Unix epoch timestamp of the last board
# info fetch; not useful for support triage.
board.pop("time")
if board["public_api_version"] is None:
board.pop("public_api_version")
+2 -1
View File
@@ -62,7 +62,8 @@ async def async_setup_entry(
"""Set up Duco fan entities."""
coordinator = entry.runtime_data
# BOX is always node 1 and is never dynamically added or removed, so no listener needed.
# BOX is always node 1 and is never dynamically added
# or removed, so no listener needed.
async_add_entities(
DucoVentilationFanEntity(coordinator, node)
for node in coordinator.data.nodes.values()
@@ -30,7 +30,8 @@ def get_position_data(
longitude = entity.attributes.get(ATTR_LONGITUDE)
if not longitude:
raise AttributeError(
f"Failed to find attribute '{ATTR_LONGITUDE}' in {registry_entry.entity_id}",
f"Failed to find attribute '{ATTR_LONGITUDE}'"
f" in {registry_entry.entity_id}",
ATTR_LONGITUDE,
)
+7 -2
View File
@@ -64,7 +64,9 @@ class DynaliteBridge:
def update_device(self, device: DynaliteBaseDevice | None = None) -> None:
"""Call when a device or all devices should be updated."""
if not device:
# This is used to signal connection or disconnection, so all devices may become available or not.
# This is used to signal connection or
# disconnection, so all devices may become
# available or not.
log_string = (
"Connected" if self.dynalite_devices.connected else "Disconnected"
)
@@ -102,7 +104,10 @@ class DynaliteBridge:
self.async_add_devices[platform](self.waiting_devices[platform])
def add_devices_when_registered(self, devices: list[DynaliteBaseDevice]) -> None:
"""Add the devices to HA if the add devices callback was registered, otherwise queue until it is."""
"""Add the devices to HA if the add devices callback was registered.
Otherwise queue until it is.
"""
for platform in PLATFORMS:
platform_devices = [
device for device in devices if device.category == platform
+2 -2
View File
@@ -20,7 +20,7 @@ async def async_setup_entry(
config_entry: DynaliteConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Record the async_add_entities function to add them later when received from Dynalite."""
"""Record the async_add_entities function to add them later."""
@callback
def cover_from_device(device: Any, bridge: DynaliteBridge) -> CoverEntity:
@@ -86,7 +86,7 @@ class DynaliteCover(DynaliteBase, CoverEntity):
class DynaliteCoverWithTilt(DynaliteCover):
"""Representation of a Dynalite Channel as a Home Assistant Cover that uses up and down for tilt."""
"""Representation of a Dynalite Channel as a Cover with tilt."""
@property
def current_cover_tilt_position(self) -> int:
+1 -1
View File
@@ -21,7 +21,7 @@ def async_setup_entry_base(
platform: str,
entity_from_device: Callable,
) -> None:
"""Record the async_add_entities function to add them later when received from Dynalite."""
"""Record the async_add_entities function to add them later."""
LOGGER.debug("Setting up %s entry = %s", platform, config_entry.data)
bridge = config_entry.runtime_data
+1 -1
View File
@@ -15,7 +15,7 @@ async def async_setup_entry(
config_entry: DynaliteConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Record the async_add_entities function to add them later when received from Dynalite."""
"""Record the async_add_entities function to add them later."""
async_setup_entry_base(
hass, config_entry, async_add_entities, "light", DynaliteLight
)
+1 -1
View File
@@ -90,7 +90,7 @@ TEMPLATE_SCHEMA = vol.Schema({str: TEMPLATE_DATA_SCHEMA})
def validate_area(config: dict[str, Any]) -> dict[str, Any]:
"""Validate that template parameters are only used if area is using the relevant template."""
"""Validate template params are only used with relevant template."""
conf_set = set()
for configs in DEFAULT_TEMPLATES.values():
for conf in configs:
+1 -1
View File
@@ -16,7 +16,7 @@ async def async_setup_entry(
config_entry: DynaliteConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Record the async_add_entities function to add them later when received from Dynalite."""
"""Record the async_add_entities function to add them later."""
async_setup_entry_base(
hass, config_entry, async_add_entities, "switch", DynaliteSwitch
)
+2 -1
View File
@@ -114,7 +114,8 @@ class Measurement(CoordinatorEntity, SensorEntity):
if "latestReading" not in self.coordinator.data["measures"][self.key]:
return False
# Sometimes lastestReading key is present but actually a URL rather than a piece of data
# Sometimes lastestReading key is present but actually
# a URL rather than a piece of data.
# This is usually because the sensor has been archived
if not isinstance(
self.coordinator.data["measures"][self.key]["latestReading"], dict
@@ -244,7 +244,10 @@ class EasyEnergySensorEntity(
self.entity_id = (
f"{SENSOR_DOMAIN}.{DOMAIN}_{description.service_type}_{description.key}"
)
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.service_type}_{description.key}"
self._attr_unique_id = (
f"{coordinator.config_entry.entry_id}"
f"_{description.service_type}_{description.key}"
)
self._attr_device_info = DeviceInfo(
entry_type=DeviceEntryType.SERVICE,
identifiers={
+3 -2
View File
@@ -463,7 +463,7 @@ class Thermostat(ClimateEntity):
@property
def has_humidifier_control(self) -> bool:
"""Return true if humidifier connected to thermostat and set to manual/on mode."""
"""Return true if humidifier connected to thermostat and manual/on."""
return (
bool(self.settings.get("hasHumidifier"))
and self.settings.get("humidifierMode") == HUMIDIFIER_MANUAL_MODE
@@ -888,7 +888,8 @@ class Thermostat(ClimateEntity):
current_sensors_in_climate = self._sensors_in_preset_mode(preset_mode)
if set(sensor_names) == set(current_sensors_in_climate):
_LOGGER.debug(
"This action would not be an update, current sensors on climate (%s) are: %s",
"This action would not be an update, current sensors"
" on climate (%s) are: %s",
preset_mode,
", ".join(current_sensors_in_climate),
)
@@ -71,7 +71,7 @@ class EcobeeFlowHandler(ConfigFlow, domain=DOMAIN):
async def async_step_authorize(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Present the user with the PIN so that the app can be authorized on ecobee.com."""
"""Present the user with the PIN to authorize on ecobee.com."""
errors = {}
if user_input is not None:
+1 -1
View File
@@ -78,7 +78,7 @@ async def async_setup_entry(
class EcobeeVentilatorMinTime(EcobeeBaseEntity, NumberEntity):
"""A number class, representing min time for an ecobee thermostat with ventilator attached."""
"""Represent min time for an ecobee thermostat with ventilator."""
entity_description: EcobeeNumberEntityDescription
+1 -1
View File
@@ -51,7 +51,7 @@ async def async_setup_entry(
class EcobeeVentilator20MinSwitch(EcobeeBaseEntity, SwitchEntity):
"""A Switch class, representing 20 min timer for an ecobee thermostat with ventilator attached."""
"""Represent 20 min timer for an ecobee thermostat with ventilator."""
_attr_has_entity_name = True
_attr_name = "Ventilator 20m Timer"
+3 -2
View File
@@ -26,9 +26,10 @@ def ecobee_time(time_string):
def is_indefinite_hold(start_date_string: str, end_date_string: str) -> bool:
"""Determine if the given start and end dates from the ecobee API represent an indefinite hold.
"""Determine if the ecobee API dates represent an indefinite hold.
This is not documented in the API, so a rough heuristic is used where a hold over 1 year is considered indefinite.
This is not documented in the API, so a rough heuristic is
used where a hold over 1 year is considered indefinite.
"""
return date.fromisoformat(end_date_string) - date.fromisoformat(
start_date_string
+2 -1
View File
@@ -174,7 +174,8 @@ class EcovacsActiveMapSelectEntity(
if self._attr_current_option not in self._option_to_id:
self._attr_current_option = None
# Sort named maps first, then numeric IDs (unnamed maps during building) in ascending order.
# Sort named maps first, then numeric IDs
# (unnamed maps during building) in ascending order.
self._attr_options = sorted(
self._option_to_id.keys(), key=lambda x: (x.isdigit(), x.lower())
)
+10 -6
View File
@@ -413,9 +413,11 @@ class EcovacsVacuum(
"""Get the segments that can be cleaned."""
last_seen = self.last_seen_segments or []
if self._room_event is None or not self._maps:
# If we don't have the necessary information to determine segments, return the last
# seen segments to avoid temporarily losing all segments until we get the necessary
# information, which could cause unnecessary issues to be created
# If we don't have the necessary information to
# determine segments, return the last seen segments to
# avoid temporarily losing all segments until we get
# the necessary information, which could cause
# unnecessary issues to be created
return last_seen
map_id = self._room_event.map_id
@@ -429,8 +431,9 @@ class EcovacsVacuum(
for map_obj in self._maps.values()
if map_obj.id != self._room_event.map_id
}
# Include segments from the current map and any segments from other maps that were
# previously seen, as we want to continue showing segments from other maps for
# Include segments from the current map and any segments
# from other maps that were previously seen, as we want
# to continue showing segments from other maps for
# mapping purposes
segments = [
seg for seg in last_seen if _split_composite_id(seg.id)[0] in other_map_ids
@@ -486,7 +489,8 @@ class EcovacsVacuum(
if not valid_room_ids:
_LOGGER.warning(
"No valid segments to clean after validation, skipping clean segments command"
"No valid segments to clean after validation,"
" skipping clean segments command"
)
return
@@ -76,7 +76,9 @@ class EgaugeDataCoordinator(DataUpdateCoordinator[EgaugeData]):
EgaugePermissionError,
EgaugeException,
) as err:
# EgaugeAuthenticationError and EgaugePermissionError will raise ConfigEntryAuthFailed once reauth is implemented
# EgaugeAuthenticationError and
# EgaugePermissionError will raise
# ConfigEntryAuthFailed once reauth is implemented
raise ConfigEntryError from err
except ConnectError as err:
raise UpdateFailed(f"Error fetching device info: {err}") from err
+2 -2
View File
@@ -60,7 +60,7 @@ SENSORS: tuple[EgaugeSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
native_value_fn=lambda data, register: data.measurements[register],
available_fn=lambda data, register: register in data.measurements,
supported_fn=lambda register_info: register_info.type == RegisterType.VOLTAGE,
supported_fn=(lambda register_info: register_info.type == RegisterType.VOLTAGE),
),
EgaugeSensorEntityDescription(
key="current",
@@ -69,7 +69,7 @@ SENSORS: tuple[EgaugeSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
native_value_fn=lambda data, register: data.measurements[register],
available_fn=lambda data, register: register in data.measurements,
supported_fn=lambda register_info: register_info.type == RegisterType.CURRENT,
supported_fn=(lambda register_info: register_info.type == RegisterType.CURRENT),
),
)
@@ -56,7 +56,7 @@ async def async_setup_entry(
entry: EheimDigitalConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the callbacks for the coordinator so binary sensors can be added as devices are found."""
"""Set up callbacks to add binary sensors as devices are found."""
coordinator = entry.runtime_data
def async_setup_device_entities(
@@ -35,7 +35,7 @@ async def async_setup_entry(
entry: EheimDigitalConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the callbacks for the coordinator so climate entities can be added as devices are found."""
"""Set up callbacks to add climate entities as devices are found."""
coordinator = entry.runtime_data
def async_setup_device_entities(
@@ -30,7 +30,8 @@ class EheimDigitalEntity[_DeviceT: EheimDigitalDevice](
"""Initialize a EHEIM Digital entity."""
super().__init__(coordinator)
if TYPE_CHECKING:
# At this point at least one device is found and so there is always a main device set
# At this point at least one device is found
# and so there is always a main device set
assert isinstance(coordinator.hub.main, EheimDigitalDevice)
self._attr_device_info = DeviceInfo(
configuration_url=f"http://{coordinator.config_entry.data[CONF_HOST]}",
@@ -33,7 +33,7 @@ async def async_setup_entry(
entry: EheimDigitalConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the callbacks for the coordinator so lights can be added as devices are found."""
"""Set up callbacks for the coordinator to add lights as devices are found."""
coordinator = entry.runtime_data
def async_setup_device_entities(
@@ -201,7 +201,7 @@ async def async_setup_entry(
entry: EheimDigitalConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the callbacks for the coordinator so numbers can be added as devices are found."""
"""Set up callbacks for the coordinator to add numbers as devices are found."""
coordinator = entry.runtime_data
def async_setup_device_entities(

Some files were not shown because too many files have changed in this diff Show More