From 64c2340fab33e659a90feec95fc6f682bdf5b9c3 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sun, 15 Jan 2023 23:00:51 +0100 Subject: [PATCH] Core code styling improvements (#85963) --- homeassistant/auth/auth_store.py | 4 ++- homeassistant/block_async_io.py | 4 ++- homeassistant/bootstrap.py | 16 +++++++-- homeassistant/config.py | 4 +-- homeassistant/config_entries.py | 39 +++++++++++++-------- homeassistant/core.py | 7 ++-- homeassistant/data_entry_flow.py | 5 ++- homeassistant/helpers/template.py | 4 +-- homeassistant/loader.py | 19 ++++++---- homeassistant/requirements.py | 11 ++++-- homeassistant/runner.py | 14 ++++++-- homeassistant/scripts/benchmark/__init__.py | 5 ++- homeassistant/setup.py | 27 +++++++------- 13 files changed, 106 insertions(+), 53 deletions(-) diff --git a/homeassistant/auth/auth_store.py b/homeassistant/auth/auth_store.py index 5a9fb469e0d..50d5d630429 100644 --- a/homeassistant/auth/auth_store.py +++ b/homeassistant/auth/auth_store.py @@ -555,7 +555,9 @@ class AuthStore: "client_icon": refresh_token.client_icon, "token_type": refresh_token.token_type, "created_at": refresh_token.created_at.isoformat(), - "access_token_expiration": refresh_token.access_token_expiration.total_seconds(), + "access_token_expiration": ( + refresh_token.access_token_expiration.total_seconds() + ), "token": refresh_token.token, "jwt_key": refresh_token.jwt_key, "last_used_at": refresh_token.last_used_at.isoformat() diff --git a/homeassistant/block_async_io.py b/homeassistant/block_async_io.py index 29e31ae4a88..753fda5ae9b 100644 --- a/homeassistant/block_async_io.py +++ b/homeassistant/block_async_io.py @@ -8,7 +8,9 @@ from .util.async_ import protect_loop def enable() -> None: """Enable the detection of blocking calls in the event loop.""" # Prevent urllib3 and requests doing I/O in event loop - HTTPConnection.putrequest = protect_loop(HTTPConnection.putrequest) # type: ignore[assignment] + HTTPConnection.putrequest = protect_loop( # type: ignore[assignment] + HTTPConnection.putrequest + ) # Prevent sleeping in event loop. Non-strict since 2022.02 time.sleep = protect_loop(time.sleep, strict=False) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index c8858293706..bda54021a4a 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -385,7 +385,11 @@ def async_enable_logging( ) threading.excepthook = lambda args: logging.getLogger(None).exception( "Uncaught thread exception", - exc_info=(args.exc_type, args.exc_value, args.exc_traceback), # type: ignore[arg-type] + exc_info=( # type: ignore[arg-type] + args.exc_type, + args.exc_value, + args.exc_traceback, + ), ) # Log errors to a file if we have write access to file or config dir @@ -403,7 +407,10 @@ def async_enable_logging( not err_path_exists and os.access(err_dir, os.W_OK) ): - err_handler: logging.handlers.RotatingFileHandler | logging.handlers.TimedRotatingFileHandler + err_handler: ( + logging.handlers.RotatingFileHandler + | logging.handlers.TimedRotatingFileHandler + ) if log_rotate_days: err_handler = logging.handlers.TimedRotatingFileHandler( err_log_path, when="midnight", backupCount=log_rotate_days @@ -462,7 +469,10 @@ def _get_domains(hass: core.HomeAssistant, config: dict[str, Any]) -> set[str]: async def _async_watch_pending_setups(hass: core.HomeAssistant) -> None: - """Periodic log of setups that are pending for longer than LOG_SLOW_STARTUP_INTERVAL.""" + """Periodic log of setups that are pending. + + Pending for longer than LOG_SLOW_STARTUP_INTERVAL. + """ loop_count = 0 setup_started: dict[str, datetime] = hass.data[DATA_SETUP_STARTED] previous_was_empty = True diff --git a/homeassistant/config.py b/homeassistant/config.py index a4205461b30..dab44c6ce52 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -864,8 +864,8 @@ async def async_process_component_config( # noqa: C901 config_validator, "async_validate_config" ): try: - return await config_validator.async_validate_config( # type: ignore[no-any-return] - hass, config + return ( # type: ignore[no-any-return] + await config_validator.async_validate_config(hass, config) ) except (vol.Invalid, HomeAssistantError) as ex: async_log_exception(ex, domain, config, hass, integration.documentation) diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index f2e2be97e42..252f01eceef 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -63,14 +63,14 @@ SOURCE_USB = "usb" SOURCE_USER = "user" SOURCE_ZEROCONF = "zeroconf" -# If a user wants to hide a discovery from the UI they can "Ignore" it. The config_entries/ignore_flow -# websocket command creates a config entry with this source and while it exists normal discoveries -# with the same unique id are ignored. +# If a user wants to hide a discovery from the UI they can "Ignore" it. The +# config_entries/ignore_flow websocket command creates a config entry with this +# source and while it exists normal discoveries with the same unique id are ignored. SOURCE_IGNORE = "ignore" # This is used when a user uses the "Stop Ignoring" button in the UI (the -# config_entries/ignore_flow websocket command). It's triggered after the "ignore" config entry has -# been removed and unloaded. +# config_entries/ignore_flow websocket command). It's triggered after the +# "ignore" config entry has been removed and unloaded. SOURCE_UNIGNORE = "unignore" # This is used to signal that re-authentication is required by the user. @@ -643,7 +643,8 @@ class ConfigEntry: Returns function to unlisten. """ weak_listener: Any - # weakref.ref is not applicable to a bound method, e.g. method of a class instance, as reference will die immediately + # weakref.ref is not applicable to a bound method, e.g., + # method of a class instance, as reference will die immediately. if hasattr(listener, "__self__"): weak_listener = weakref.WeakMethod(cast(MethodType, listener)) else: @@ -994,10 +995,10 @@ class ConfigEntries: ): self.hass.config_entries.flow.async_abort(progress_flow["flow_id"]) - # After we have fully removed an "ignore" config entry we can try and rediscover it so that a - # user is able to immediately start configuring it. We do this by starting a new flow with - # the 'unignore' step. If the integration doesn't implement async_step_unignore then - # this will be a no-op. + # After we have fully removed an "ignore" config entry we can try and rediscover + # it so that a user is able to immediately start configuring it. We do this by + # starting a new flow with the 'unignore' step. If the integration doesn't + # implement async_step_unignore then this will be a no-op. if entry.source == SOURCE_IGNORE: self.hass.async_create_task( self.hass.config_entries.flow.async_init( @@ -1040,7 +1041,8 @@ class ConfigEntries: for entry in config["entries"]: pref_disable_new_entities = entry.get("pref_disable_new_entities") - # Between 0.98 and 2021.6 we stored 'disable_new_entities' in a system options dictionary + # Between 0.98 and 2021.6 we stored 'disable_new_entities' in a + # system options dictionary. if pref_disable_new_entities is None and "system_options" in entry: pref_disable_new_entities = entry.get("system_options", {}).get( "disable_new_entities" @@ -1100,7 +1102,9 @@ class ConfigEntries: if not result: return result - return entry.state is ConfigEntryState.LOADED # type: ignore[comparison-overlap] # mypy bug? + return ( + entry.state is ConfigEntryState.LOADED # type: ignore[comparison-overlap] + ) async def async_unload(self, entry_id: str) -> bool: """Unload a config entry.""" @@ -1382,7 +1386,11 @@ class ConfigFlow(data_entry_flow.FlowHandler): match_dict = {} # Match any entry for entry in self._async_current_entries(include_ignore=False): if all( - item in ChainMap(entry.options, entry.data).items() # type: ignore[arg-type] + item + in ChainMap( + entry.options, # type: ignore[arg-type] + entry.data, # type: ignore[arg-type] + ).items() for item in match_dict.items() ): raise data_entry_flow.AbortFlow("already_configured") @@ -1474,7 +1482,8 @@ class ConfigFlow(data_entry_flow.FlowHandler): ) -> list[ConfigEntry]: """Return current entries. - If the flow is user initiated, filter out ignored entries unless include_ignore is True. + If the flow is user initiated, filter out ignored entries, + unless include_ignore is True. """ config_entries = self.hass.config_entries.async_entries(self.handler) @@ -1737,7 +1746,7 @@ class OptionsFlowWithConfigEntry(OptionsFlow): class EntityRegistryDisabledHandler: - """Handler to handle when entities related to config entries updating disabled_by.""" + """Handler when entities related to config entries updated disabled_by.""" def __init__(self, hass: HomeAssistant) -> None: """Initialize the handler.""" diff --git a/homeassistant/core.py b/homeassistant/core.py index c5f3fe65cfc..771943ba7ef 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -2041,8 +2041,8 @@ class Config: if not (data := await self._store.async_load()): return - # In 2021.9 we fixed validation to disallow a path (because that's never correct) - # but this data still lives in storage, so we print a warning. + # In 2021.9 we fixed validation to disallow a path (because that's never + # correct) but this data still lives in storage, so we print a warning. if data.get("external_url") and urlparse(data["external_url"]).path not in ( "", "/", @@ -2125,7 +2125,8 @@ class Config: if data["unit_system_v2"] == _CONF_UNIT_SYSTEM_IMPERIAL: data["unit_system_v2"] = _CONF_UNIT_SYSTEM_US_CUSTOMARY if old_major_version == 1 and old_minor_version < 3: - # In 1.3, we add the key "language", initialize it from the owner account + # In 1.3, we add the key "language", initialize it from the + # owner account. data["language"] = "en" try: owner = await self.hass.auth.async_get_owner() diff --git a/homeassistant/data_entry_flow.py b/homeassistant/data_entry_flow.py index 70c09020ca3..7072e52bdc0 100644 --- a/homeassistant/data_entry_flow.py +++ b/homeassistant/data_entry_flow.py @@ -175,7 +175,10 @@ class FlowManager(abc.ABC): def async_has_matching_flow( self, handler: str, context: dict[str, Any], data: Any ) -> bool: - """Check if an existing matching flow is in progress with the same handler, context, and data.""" + """Check if an existing matching flow is in progress. + + A flow with the same handler, context, and data. + """ return any( flow for flow in self._async_progress_by_handler(handler) diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 78ed392f5fb..5445d14c097 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -378,9 +378,9 @@ class Template: wanted_env = _ENVIRONMENT ret: TemplateEnvironment | None = self.hass.data.get(wanted_env) if ret is None: - ret = self.hass.data[wanted_env] = TemplateEnvironment( # type: ignore[no-untyped-call] + ret = self.hass.data[wanted_env] = TemplateEnvironment( self.hass, - self._limited, + self._limited, # type: ignore[no-untyped-call] self._strict, ) return ret diff --git a/homeassistant/loader.py b/homeassistant/loader.py index da3f2aaa6d3..a41fb582ee1 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -123,8 +123,9 @@ class Manifest(TypedDict, total=False): """ Integration manifest. - Note that none of the attributes are marked Optional here. However, some of them may be optional in manifest.json - in the sense that they can be omitted altogether. But when present, they should not have null values in it. + Note that none of the attributes are marked Optional here. However, some of + them may be optional in manifest.json in the sense that they can be omitted + altogether. But when present, they should not have null values in it. """ name: str @@ -338,7 +339,9 @@ async def async_get_zeroconf( hass: HomeAssistant, ) -> dict[str, list[dict[str, str | dict[str, str]]]]: """Return cached list of zeroconf types.""" - zeroconf: dict[str, list[dict[str, str | dict[str, str]]]] = ZEROCONF.copy() # type: ignore[assignment] + zeroconf: dict[ + str, list[dict[str, str | dict[str, str]]] + ] = ZEROCONF.copy() # type: ignore[assignment] integrations = await async_get_custom_components(hass) for integration in integrations.values(): @@ -496,7 +499,8 @@ class Integration: ( "The custom integration '%s' does not have a version key in the" " manifest file and was blocked from loading. See" - " https://developers.home-assistant.io/blog/2021/01/29/custom-integration-changes#versions" + " https://developers.home-assistant.io" + "/blog/2021/01/29/custom-integration-changes#versions" " for more details" ), integration.domain, @@ -518,7 +522,8 @@ class Integration: ( "The custom integration '%s' does not have a valid version key" " (%s) in the manifest file and was blocked from loading. See" - " https://developers.home-assistant.io/blog/2021/01/29/custom-integration-changes#versions" + " https://developers.home-assistant.io" + "/blog/2021/01/29/custom-integration-changes#versions" " for more details" ), integration.domain, @@ -895,7 +900,9 @@ def _load_file( Async friendly. """ with suppress(KeyError): - return hass.data[DATA_COMPONENTS][comp_or_platform] # type: ignore[no-any-return] + return hass.data[DATA_COMPONENTS][ # type: ignore[no-any-return] + comp_or_platform + ] if (cache := hass.data.get(DATA_COMPONENTS)) is None: if not _async_mount_config_dir(hass): diff --git a/homeassistant/requirements.py b/homeassistant/requirements.py index 5710c313903..30c5d0a2448 100644 --- a/homeassistant/requirements.py +++ b/homeassistant/requirements.py @@ -15,7 +15,8 @@ from .helpers.typing import UNDEFINED, UndefinedType from .loader import Integration, IntegrationNotFound, async_get_integration from .util import package as pkg_util -PIP_TIMEOUT = 60 # The default is too low when the internet connection is satellite or high latency +# The default is too low when the internet connection is satellite or high latency +PIP_TIMEOUT = 60 MAX_INSTALL_FAILURES = 3 DATA_REQUIREMENTS_MANAGER = "requirements_manager" CONSTRAINT_FILE = "package_constraints.txt" @@ -132,7 +133,7 @@ class RequirementsManager: async def async_get_integration_with_requirements( self, domain: str, done: set[str] | None = None ) -> Integration: - """Get an integration with all requirements installed, including the dependencies. + """Get an integration with all requirements installed, including dependencies. This can raise IntegrationNotFound if manifest or integration is invalid, RequirementNotFound if there was some type of @@ -257,7 +258,11 @@ class RequirementsManager: def _raise_for_failed_requirements( self, integration: str, missing: list[str] ) -> None: - """Raise RequirementsNotFound so we do not keep trying requirements that have already failed.""" + """Raise for failed installing integration requirements. + + Raise RequirementsNotFound so we do not keep trying requirements + that have already failed. + """ for req in missing: if req in self.install_failure_history: _LOGGER.info( diff --git a/homeassistant/runner.py b/homeassistant/runner.py index 51b47e0fe2d..c64e570280e 100644 --- a/homeassistant/runner.py +++ b/homeassistant/runner.py @@ -90,11 +90,18 @@ def _async_loop_exception_handler(_: Any, context: dict[str, Any]) -> None: if source_traceback := context.get("source_traceback"): stack_summary = "".join(traceback.format_list(source_traceback)) logger.error( - "Error doing job: %s: %s", context["message"], stack_summary, **kwargs # type: ignore[arg-type] + "Error doing job: %s: %s", + context["message"], + stack_summary, + **kwargs, # type: ignore[arg-type] ) return - logger.error("Error doing job: %s", context["message"], **kwargs) # type: ignore[arg-type] + logger.error( + "Error doing job: %s", + context["message"], + **kwargs, # type: ignore[arg-type] + ) async def setup_and_run_hass(runtime_config: RuntimeConfig) -> int: @@ -105,7 +112,8 @@ async def setup_and_run_hass(runtime_config: RuntimeConfig) -> int: return 1 # threading._shutdown can deadlock forever - threading._shutdown = deadlock_safe_shutdown # type: ignore[attr-defined] # pylint: disable=protected-access + # pylint: disable=protected-access + threading._shutdown = deadlock_safe_shutdown # type: ignore[attr-defined] return await hass.async_run() diff --git a/homeassistant/scripts/benchmark/__init__.py b/homeassistant/scripts/benchmark/__init__.py index d3165ad6cac..76af064f3b8 100644 --- a/homeassistant/scripts/benchmark/__init__.py +++ b/homeassistant/scripts/benchmark/__init__.py @@ -191,7 +191,10 @@ async def state_changed_event_helper(hass): @benchmark async def state_changed_event_filter_helper(hass): - """Run a million events through state changed event helper with 1000 entities that all get filtered.""" + """Run a million events through state changed event helper. + + With 1000 entities that all get filtered. + """ count = 0 entity_id = "light.kitchen" events_to_fire = 10**6 diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 13467713e2d..94aa3ab1b03 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -30,24 +30,27 @@ ATTR_COMPONENT = "component" BASE_PLATFORMS = {platform.value for platform in Platform} # DATA_SETUP is a dict[str, asyncio.Task[bool]], indicating domains which are currently -# being setup or which failed to setup -# - Tasks are added to DATA_SETUP by `async_setup_component`, the key is the domain being setup -# and the Task is the `_async_setup_component` helper. -# - Tasks are removed from DATA_SETUP if setup was successful, that is, the task returned True +# being setup or which failed to setup: +# - Tasks are added to DATA_SETUP by `async_setup_component`, the key is the domain +# being setup and the Task is the `_async_setup_component` helper. +# - Tasks are removed from DATA_SETUP if setup was successful, that is, +# the task returned True. DATA_SETUP = "setup_tasks" -# DATA_SETUP_DONE is a dict [str, asyncio.Event], indicating components which will be setup -# - Events are added to DATA_SETUP_DONE during bootstrap by async_set_domains_to_be_loaded, -# the key is the domain which will be loaded -# - Events are set and removed from DATA_SETUP_DONE when async_setup_component is finished, -# regardless of if the setup was successful or not. +# DATA_SETUP_DONE is a dict [str, asyncio.Event], indicating components which +# will be setup: +# - Events are added to DATA_SETUP_DONE during bootstrap by +# async_set_domains_to_be_loaded, the key is the domain which will be loaded. +# - Events are set and removed from DATA_SETUP_DONE when async_setup_component +# is finished, regardless of if the setup was successful or not. DATA_SETUP_DONE = "setup_done" -# DATA_SETUP_DONE is a dict [str, datetime], indicating when an attempt to setup a component -# started +# DATA_SETUP_DONE is a dict [str, datetime], indicating when an attempt +# to setup a component started. DATA_SETUP_STARTED = "setup_started" -# DATA_SETUP_TIME is a dict [str, timedelta], indicating how time was spent setting up a component +# DATA_SETUP_TIME is a dict [str, timedelta], indicating how time was spent +# setting up a component. DATA_SETUP_TIME = "setup_time" DATA_DEPS_REQS = "deps_reqs_processed"