From 55f4962c061d86dfc66d07f23883535d19c9d825 Mon Sep 17 00:00:00 2001 From: Ruslan Sayfutdinov Date: Thu, 23 Dec 2021 19:14:47 +0000 Subject: [PATCH] Fix pylint plugin which checks relative imports (#62693) --- homeassistant/__main__.py | 10 ++--- homeassistant/async_timeout_backcompat.py | 2 +- homeassistant/auth/auth_store.py | 8 +++- homeassistant/block_async_io.py | 2 +- homeassistant/bootstrap.py | 27 +++++------ homeassistant/components/zha/core/typing.py | 15 +++---- homeassistant/config.py | 44 ++++++++---------- homeassistant/config_entries.py | 45 ++++++++----------- homeassistant/const.py | 2 +- homeassistant/core.py | 26 +++++------ homeassistant/helpers/aiohttp_client.py | 3 +- homeassistant/helpers/area_registry.py | 2 +- homeassistant/helpers/check_config.py | 3 +- homeassistant/helpers/collection.py | 9 ++-- homeassistant/helpers/condition.py | 8 ++-- homeassistant/helpers/config_entry_flow.py | 3 +- .../helpers/config_entry_oauth2_flow.py | 2 +- homeassistant/helpers/config_validation.py | 6 +-- homeassistant/helpers/data_entry_flow.py | 3 +- homeassistant/helpers/device_registry.py | 4 +- homeassistant/helpers/entity.py | 11 ++--- homeassistant/helpers/entity_component.py | 10 +---- homeassistant/helpers/entity_registry.py | 6 +-- homeassistant/helpers/entityfilter.py | 3 +- homeassistant/helpers/event.py | 11 ++--- homeassistant/helpers/httpx_client.py | 3 +- homeassistant/helpers/intent.py | 3 +- homeassistant/helpers/location.py | 2 +- homeassistant/helpers/reload.py | 7 +-- homeassistant/helpers/restore_state.py | 13 +++--- homeassistant/helpers/script.py | 25 ++++------- homeassistant/helpers/service.py | 21 ++++----- homeassistant/helpers/storage.py | 2 +- homeassistant/helpers/template.py | 24 +++------- homeassistant/helpers/trace.py | 3 +- homeassistant/helpers/trigger.py | 3 +- homeassistant/helpers/update_coordinator.py | 2 +- homeassistant/loader.py | 18 ++++---- homeassistant/requirements.py | 10 ++--- homeassistant/runner.py | 10 ++--- homeassistant/setup.py | 14 +++--- homeassistant/util/executor.py | 2 +- homeassistant/util/unit_system.py | 3 +- pylint/plugins/hass_imports.py | 16 ++++--- 44 files changed, 209 insertions(+), 237 deletions(-) diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py index c2802e1b9c4..1a129686a8f 100644 --- a/homeassistant/__main__.py +++ b/homeassistant/__main__.py @@ -9,7 +9,7 @@ import subprocess import sys import threading -from homeassistant.const import REQUIRED_PYTHON_VER, RESTART_EXIT_CODE, __version__ +from .const import REQUIRED_PYTHON_VER, RESTART_EXIT_CODE, __version__ FAULT_LOG_FILENAME = "home-assistant.log.fault" @@ -27,7 +27,7 @@ def validate_python() -> None: def ensure_config_path(config_dir: str) -> None: """Validate the configuration directory.""" # pylint: disable=import-outside-toplevel - import homeassistant.config as config_util + from . import config as config_util lib_dir = os.path.join(config_dir, "deps") @@ -61,7 +61,7 @@ def ensure_config_path(config_dir: str) -> None: def get_arguments() -> argparse.Namespace: """Get parsed passed in arguments.""" # pylint: disable=import-outside-toplevel - import homeassistant.config as config_util + from . import config as config_util parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate." @@ -282,7 +282,7 @@ def main() -> int: if args.script is not None: # pylint: disable=import-outside-toplevel - from homeassistant import scripts + from . import scripts return scripts.run(args.script) @@ -298,7 +298,7 @@ def main() -> int: write_pid(args.pid_file) # pylint: disable=import-outside-toplevel - from homeassistant import runner + from . import runner runtime_conf = runner.RuntimeConfig( config_dir=config_dir, diff --git a/homeassistant/async_timeout_backcompat.py b/homeassistant/async_timeout_backcompat.py index 189f64020bb..70b38c18708 100644 --- a/homeassistant/async_timeout_backcompat.py +++ b/homeassistant/async_timeout_backcompat.py @@ -6,7 +6,7 @@ from typing import Any import async_timeout -from homeassistant.helpers.frame import report +from .helpers.frame import report def timeout( diff --git a/homeassistant/auth/auth_store.py b/homeassistant/auth/auth_store.py index 8acb7c44398..8b8531b4aff 100644 --- a/homeassistant/auth/auth_store.py +++ b/homeassistant/auth/auth_store.py @@ -8,12 +8,16 @@ import hmac from logging import getLogger from typing import Any -from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION from homeassistant.core import HomeAssistant, callback from homeassistant.util import dt as dt_util from . import models -from .const import GROUP_ID_ADMIN, GROUP_ID_READ_ONLY, GROUP_ID_USER +from .const import ( + ACCESS_TOKEN_EXPIRATION, + GROUP_ID_ADMIN, + GROUP_ID_READ_ONLY, + GROUP_ID_USER, +) from .permissions import PermissionLookup, system_policies from .permissions.types import PolicyType diff --git a/homeassistant/block_async_io.py b/homeassistant/block_async_io.py index ec56b746706..0a1f4445c3e 100644 --- a/homeassistant/block_async_io.py +++ b/homeassistant/block_async_io.py @@ -1,7 +1,7 @@ """Block I/O being done in asyncio.""" from http.client import HTTPConnection -from homeassistant.util.async_ import protect_loop +from .util.async_ import protect_loop def enable() -> None: diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 64a6e98aa87..94dfb2bd1c8 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -15,27 +15,24 @@ from typing import TYPE_CHECKING, Any import voluptuous as vol import yarl -from homeassistant import config as conf_util, config_entries, core, loader -from homeassistant.components import http -from homeassistant.const import ( - REQUIRED_NEXT_PYTHON_HA_RELEASE, - REQUIRED_NEXT_PYTHON_VER, -) -from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import area_registry, device_registry, entity_registry -from homeassistant.helpers.dispatcher import async_dispatcher_send -from homeassistant.helpers.typing import ConfigType -from homeassistant.setup import ( +from . import config as conf_util, config_entries, core, loader +from .components import http +from .const import REQUIRED_NEXT_PYTHON_HA_RELEASE, REQUIRED_NEXT_PYTHON_VER +from .exceptions import HomeAssistantError +from .helpers import area_registry, device_registry, entity_registry +from .helpers.dispatcher import async_dispatcher_send +from .helpers.typing import ConfigType +from .setup import ( DATA_SETUP, DATA_SETUP_STARTED, DATA_SETUP_TIME, async_set_domains_to_be_loaded, async_setup_component, ) -from homeassistant.util.async_ import gather_with_concurrency -import homeassistant.util.dt as dt_util -from homeassistant.util.logging import async_activate_log_queue_handler -from homeassistant.util.package import async_get_user_site, is_virtual_env +from .util import dt as dt_util +from .util.async_ import gather_with_concurrency +from .util.logging import async_activate_log_queue_handler +from .util.package import async_get_user_site, is_virtual_env if TYPE_CHECKING: from .runner import RuntimeConfig diff --git a/homeassistant/components/zha/core/typing.py b/homeassistant/components/zha/core/typing.py index 62a797d9fd5..7e5cce8fec5 100644 --- a/homeassistant/components/zha/core/typing.py +++ b/homeassistant/components/zha/core/typing.py @@ -26,20 +26,17 @@ ZigpyGroupType = zigpy.group.Group ZigpyZdoType = zigpy.zdo.ZDO if TYPE_CHECKING: - from homeassistant.components.zha.core import channels - import homeassistant.components.zha.core.channels - import homeassistant.components.zha.core.channels.base as base_channels - import homeassistant.components.zha.core.device - import homeassistant.components.zha.core.gateway - import homeassistant.components.zha.core.group import homeassistant.components.zha.entity + from . import channels, device, gateway, group + from .channels import base as base_channels + ChannelType = base_channels.ZigbeeChannel ChannelsType = channels.Channels ChannelPoolType = channels.ChannelPool ClientChannelType = base_channels.ClientChannel ZDOChannelType = base_channels.ZDOChannel - ZhaDeviceType = homeassistant.components.zha.core.device.ZHADevice + ZhaDeviceType = device.ZHADevice ZhaEntityType = homeassistant.components.zha.entity.ZhaEntity - ZhaGatewayType = homeassistant.components.zha.core.gateway.ZHAGateway - ZhaGroupType = homeassistant.components.zha.core.group.ZHAGroup + ZhaGatewayType = gateway.ZHAGateway + ZhaGroupType = group.ZHAGroup diff --git a/homeassistant/config.py b/homeassistant/config.py index a2c613ebe69..ed9ffa7c47d 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -16,12 +16,9 @@ from awesomeversion import AwesomeVersion import voluptuous as vol from voluptuous.humanize import humanize_error -from homeassistant import auth -from homeassistant.auth import ( - mfa_modules as auth_mfa_modules, - providers as auth_providers, -) -from homeassistant.const import ( +from . import auth +from .auth import mfa_modules as auth_mfa_modules, providers as auth_providers +from .const import ( ATTR_ASSUMED_STATE, ATTR_FRIENDLY_NAME, ATTR_HIDDEN, @@ -52,25 +49,20 @@ from homeassistant.const import ( TEMP_CELSIUS, __version__, ) -from homeassistant.core import ( - DOMAIN as CONF_CORE, - ConfigSource, - HomeAssistant, - callback, +from .core import DOMAIN as CONF_CORE, ConfigSource, HomeAssistant, callback +from .exceptions import HomeAssistantError +from .helpers import ( + config_per_platform, + config_validation as cv, + extract_domain_configs, ) -from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import config_per_platform, extract_domain_configs -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.entity_values import EntityValues -from homeassistant.helpers.typing import ConfigType -from homeassistant.loader import Integration, IntegrationNotFound -from homeassistant.requirements import ( - RequirementsNotFound, - async_get_integration_with_requirements, -) -from homeassistant.util.package import is_docker_env -from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM -from homeassistant.util.yaml import SECRET_YAML, Secrets, load_yaml +from .helpers.entity_values import EntityValues +from .helpers.typing import ConfigType +from .loader import Integration, IntegrationNotFound +from .requirements import RequirementsNotFound, async_get_integration_with_requirements +from .util.package import is_docker_env +from .util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM +from .util.yaml import SECRET_YAML, Secrets, load_yaml _LOGGER = logging.getLogger(__name__) @@ -938,7 +930,7 @@ async def async_check_ha_config_file(hass: HomeAssistant) -> str | None: This method is a coroutine. """ # pylint: disable=import-outside-toplevel - from homeassistant.helpers import check_config + from .helpers import check_config res = await check_config.async_check_ha_config_file(hass) @@ -956,7 +948,7 @@ def async_notify_setup_error( This method must be run in the event loop. """ # pylint: disable=import-outside-toplevel - from homeassistant.components import persistent_notification + from .components import persistent_notification if (errors := hass.data.get(DATA_PERSISTENT_ERRORS)) is None: errors = hass.data[DATA_PERSISTENT_ERRORS] = {} diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index d1910364f4c..063040dc398 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -12,35 +12,26 @@ from types import MappingProxyType, MethodType from typing import TYPE_CHECKING, Any, Callable, Optional, cast import weakref -from homeassistant import data_entry_flow, loader -from homeassistant.backports.enum import StrEnum -from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP -from homeassistant.core import CALLBACK_TYPE, CoreState, HomeAssistant, callback -from homeassistant.exceptions import ( - ConfigEntryAuthFailed, - ConfigEntryNotReady, - HomeAssistantError, -) -from homeassistant.helpers import device_registry, entity_registry -from homeassistant.helpers.event import Event -from homeassistant.helpers.frame import report -from homeassistant.helpers.typing import ( - UNDEFINED, - ConfigType, - DiscoveryInfoType, - UndefinedType, -) -from homeassistant.setup import async_process_deps_reqs, async_setup_component -from homeassistant.util.decorator import Registry -import homeassistant.util.uuid as uuid_util +from . import data_entry_flow, loader +from .backports.enum import StrEnum +from .const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP +from .core import CALLBACK_TYPE, CoreState, HomeAssistant, callback +from .exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady, HomeAssistantError +from .helpers import device_registry, entity_registry +from .helpers.event import Event +from .helpers.frame import report +from .helpers.typing import UNDEFINED, ConfigType, DiscoveryInfoType, UndefinedType +from .setup import async_process_deps_reqs, async_setup_component +from .util import uuid as uuid_util +from .util.decorator import Registry if TYPE_CHECKING: - from homeassistant.components.dhcp import DhcpServiceInfo - from homeassistant.components.hassio import HassioServiceInfo - from homeassistant.components.mqtt import MqttServiceInfo - from homeassistant.components.ssdp import SsdpServiceInfo - from homeassistant.components.usb import UsbServiceInfo - from homeassistant.components.zeroconf import ZeroconfServiceInfo + from .components.dhcp import DhcpServiceInfo + from .components.hassio import HassioServiceInfo + from .components.mqtt import MqttServiceInfo + from .components.ssdp import SsdpServiceInfo + from .components.usb import UsbServiceInfo + from .components.zeroconf import ZeroconfServiceInfo _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/const.py b/homeassistant/const.py index ffe472acec9..6dcda3243b1 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Final -from homeassistant.backports.enum import StrEnum +from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 2 diff --git a/homeassistant/core.py b/homeassistant/core.py index 51317d17d48..9566ad6c596 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -25,9 +25,9 @@ import attr import voluptuous as vol import yarl -from homeassistant import async_timeout_backcompat, block_async_io, loader, util -from homeassistant.backports.enum import StrEnum -from homeassistant.const import ( +from . import async_timeout_backcompat, block_async_io, loader, util +from .backports.enum import StrEnum +from .const import ( ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, @@ -53,7 +53,7 @@ from homeassistant.const import ( MAX_LENGTH_STATE_STATE, __version__, ) -from homeassistant.exceptions import ( +from .exceptions import ( HomeAssistantError, InvalidEntityFormatError, InvalidStateError, @@ -61,22 +61,20 @@ from homeassistant.exceptions import ( ServiceNotFound, Unauthorized, ) -from homeassistant.util import location -from homeassistant.util.async_ import ( +from .util import dt as dt_util, location, uuid as uuid_util +from .util.async_ import ( fire_coroutine_threadsafe, run_callback_threadsafe, shutdown_run_callback_threadsafe, ) -import homeassistant.util.dt as dt_util -from homeassistant.util.timeout import TimeoutManager -from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem -import homeassistant.util.uuid as uuid_util +from .util.timeout import TimeoutManager +from .util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem # Typing imports that create a circular dependency if TYPE_CHECKING: - from homeassistant.auth import AuthManager - from homeassistant.components.http import HomeAssistantHTTP - from homeassistant.config_entries import ConfigEntries + from .auth import AuthManager + from .components.http import HomeAssistantHTTP + from .config_entries import ConfigEntries STAGE_1_SHUTDOWN_TIMEOUT = 100 @@ -286,7 +284,7 @@ class HomeAssistant: await self.async_start() if attach_signals: # pylint: disable=import-outside-toplevel - from homeassistant.helpers.signal import async_register_signal_handling + from .helpers.signal import async_register_signal_handling async_register_signal_handling(self) diff --git a/homeassistant/helpers/aiohttp_client.py b/homeassistant/helpers/aiohttp_client.py index 908a9d68ddf..65b1b657ef4 100644 --- a/homeassistant/helpers/aiohttp_client.py +++ b/homeassistant/helpers/aiohttp_client.py @@ -18,10 +18,11 @@ import async_timeout from homeassistant import config_entries from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE, __version__ from homeassistant.core import Event, HomeAssistant, callback -from homeassistant.helpers.frame import warn_use from homeassistant.loader import bind_hass from homeassistant.util import ssl as ssl_util +from .frame import warn_use + DATA_CONNECTOR = "aiohttp_connector" DATA_CONNECTOR_NOTVERIFY = "aiohttp_connector_notverify" DATA_CLIENTSESSION = "aiohttp_clientsession" diff --git a/homeassistant/helpers/area_registry.py b/homeassistant/helpers/area_registry.py index 11b7e5a78bd..8c4179dd940 100644 --- a/homeassistant/helpers/area_registry.py +++ b/homeassistant/helpers/area_registry.py @@ -8,10 +8,10 @@ from typing import cast import attr from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.loader import bind_hass from homeassistant.util import slugify +from . import device_registry as dr, entity_registry as er from .typing import UNDEFINED, UndefinedType # mypy: disallow-any-generics diff --git a/homeassistant/helpers/check_config.py b/homeassistant/helpers/check_config.py index 83505fc8356..6e0415b2a54 100644 --- a/homeassistant/helpers/check_config.py +++ b/homeassistant/helpers/check_config.py @@ -23,7 +23,6 @@ from homeassistant.config import ( ) from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers.typing import ConfigType from homeassistant.requirements import ( RequirementsNotFound, async_clear_install_history, @@ -31,6 +30,8 @@ from homeassistant.requirements import ( ) import homeassistant.util.yaml.loader as yaml_loader +from .typing import ConfigType + class CheckConfigError(NamedTuple): """Configuration check error.""" diff --git a/homeassistant/helpers/collection.py b/homeassistant/helpers/collection.py index f1ea4800c16..57e34a02d96 100644 --- a/homeassistant/helpers/collection.py +++ b/homeassistant/helpers/collection.py @@ -16,12 +16,13 @@ from homeassistant.components import websocket_api from homeassistant.const import CONF_ID from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import entity_registry -from homeassistant.helpers.entity import Entity -from homeassistant.helpers.entity_component import EntityComponent -from homeassistant.helpers.storage import Store from homeassistant.util import slugify +from . import entity_registry +from .entity import Entity +from .entity_component import EntityComponent +from .storage import Store + STORAGE_VERSION = 1 SAVE_DELAY = 10 diff --git a/homeassistant/helpers/condition.py b/homeassistant/helpers/condition.py index f52e1bb1595..404eea5ea4a 100644 --- a/homeassistant/helpers/condition.py +++ b/homeassistant/helpers/condition.py @@ -52,13 +52,12 @@ from homeassistant.exceptions import ( HomeAssistantError, TemplateError, ) -from homeassistant.helpers import config_validation as cv, entity_registry as er -from homeassistant.helpers.sun import get_astral_event_date -from homeassistant.helpers.template import Template -from homeassistant.helpers.typing import ConfigType, TemplateVarsType from homeassistant.util.async_ import run_callback_threadsafe import homeassistant.util.dt as dt_util +from . import config_validation as cv, entity_registry as er +from .sun import get_astral_event_date +from .template import Template from .trace import ( TraceElement, trace_append_element, @@ -69,6 +68,7 @@ from .trace import ( trace_stack_push, trace_stack_top, ) +from .typing import ConfigType, TemplateVarsType # mypy: disallow-any-generics diff --git a/homeassistant/helpers/config_entry_flow.py b/homeassistant/helpers/config_entry_flow.py index 0a565b3b9eb..a3e7ae4869d 100644 --- a/homeassistant/helpers/config_entry_flow.py +++ b/homeassistant/helpers/config_entry_flow.py @@ -8,7 +8,8 @@ from homeassistant import config_entries from homeassistant.components import dhcp, mqtt, ssdp, zeroconf from homeassistant.core import HomeAssistant from homeassistant.data_entry_flow import FlowResult -from homeassistant.helpers.typing import UNDEFINED, DiscoveryInfoType, UndefinedType + +from .typing import UNDEFINED, DiscoveryInfoType, UndefinedType DiscoveryFunctionType = Callable[[HomeAssistant], Union[Awaitable[bool], bool]] diff --git a/homeassistant/helpers/config_entry_oauth2_flow.py b/homeassistant/helpers/config_entry_oauth2_flow.py index 3c987b1ea9e..b3a569aa071 100644 --- a/homeassistant/helpers/config_entry_oauth2_flow.py +++ b/homeassistant/helpers/config_entry_oauth2_flow.py @@ -25,9 +25,9 @@ from homeassistant import config_entries from homeassistant.components import http from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult -from homeassistant.helpers.network import NoURLAvailableError from .aiohttp_client import async_get_clientsession +from .network import NoURLAvailableError _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index 08f232951ae..ffd1f7586c0 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -75,13 +75,11 @@ from homeassistant.const import ( ) from homeassistant.core import split_entity_id, valid_entity_id from homeassistant.exceptions import TemplateError -from homeassistant.helpers import ( - script_variables as script_variables_helper, - template as template_helper, -) from homeassistant.util import raise_if_invalid_path, slugify as util_slugify import homeassistant.util.dt as dt_util +from . import script_variables as script_variables_helper, template as template_helper + # pylint: disable=invalid-name TIME_PERIOD_ERROR = "offset {} should be format 'HH:MM', 'HH:MM:SS' or 'HH:MM:SS.F'" diff --git a/homeassistant/helpers/data_entry_flow.py b/homeassistant/helpers/data_entry_flow.py index 061233c0e1a..09345bf51bf 100644 --- a/homeassistant/helpers/data_entry_flow.py +++ b/homeassistant/helpers/data_entry_flow.py @@ -10,7 +10,8 @@ import voluptuous as vol from homeassistant import config_entries, data_entry_flow from homeassistant.components.http import HomeAssistantView from homeassistant.components.http.data_validator import RequestDataValidator -import homeassistant.helpers.config_validation as cv + +from . import config_validation as cv class _BaseFlowManagerView(HomeAssistantView): diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index 68af26160d8..bf8ef5fbd0e 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -12,12 +12,12 @@ from homeassistant.backports.enum import StrEnum from homeassistant.const import EVENT_HOMEASSISTANT_STARTED from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import RequiredParameterMissing -from homeassistant.helpers import storage -from homeassistant.helpers.frame import report from homeassistant.loader import bind_hass import homeassistant.util.uuid as uuid_util +from . import storage from .debounce import Debouncer +from .frame import report from .typing import UNDEFINED, UndefinedType # mypy: disallow_any_generics diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 87891c9f2a8..474d079edbc 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -37,14 +37,15 @@ from homeassistant.const import ( ) from homeassistant.core import CALLBACK_TYPE, Context, HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError, NoEntitySpecifiedError -from homeassistant.helpers import entity_registry as er -from homeassistant.helpers.device_registry import DeviceEntryType -from homeassistant.helpers.entity_platform import EntityPlatform -from homeassistant.helpers.event import Event, async_track_entity_registry_updated_event -from homeassistant.helpers.typing import StateType from homeassistant.loader import bind_hass from homeassistant.util import dt as dt_util, ensure_unique_string, slugify +from . import entity_registry as er +from .device_registry import DeviceEntryType +from .entity_platform import EntityPlatform +from .event import Event, async_track_entity_registry_updated_event +from .typing import StateType + _LOGGER = logging.getLogger(__name__) SLOW_UPDATE_WARNING = 10 DATA_ENTITY_SOURCE = "entity_info" diff --git a/homeassistant/helpers/entity_component.py b/homeassistant/helpers/entity_component.py index c190fd5fc35..66d733619d0 100644 --- a/homeassistant/helpers/entity_component.py +++ b/homeassistant/helpers/entity_component.py @@ -20,18 +20,12 @@ from homeassistant.const import ( ) from homeassistant.core import Event, HomeAssistant, ServiceCall, callback from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import ( - config_per_platform, - config_validation as cv, - discovery, - entity, - service, -) -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from homeassistant.loader import async_get_integration, bind_hass from homeassistant.setup import async_prepare_setup_platform +from . import config_per_platform, config_validation as cv, discovery, entity, service from .entity_platform import EntityPlatform +from .typing import ConfigType, DiscoveryInfoType DEFAULT_SCAN_INTERVAL = timedelta(seconds=15) DATA_INSTANCES = "entity_components" diff --git a/homeassistant/helpers/entity_registry.py b/homeassistant/helpers/entity_registry.py index b79e9af209e..7c49e884646 100644 --- a/homeassistant/helpers/entity_registry.py +++ b/homeassistant/helpers/entity_registry.py @@ -38,13 +38,13 @@ from homeassistant.core import ( valid_entity_id, ) from homeassistant.exceptions import MaxLengthExceeded -from homeassistant.helpers import device_registry as dr, storage -from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED -from homeassistant.helpers.frame import report from homeassistant.loader import bind_hass from homeassistant.util import slugify, uuid as uuid_util from homeassistant.util.yaml import load_yaml +from . import device_registry as dr, storage +from .device_registry import EVENT_DEVICE_REGISTRY_UPDATED +from .frame import report from .typing import UNDEFINED, UndefinedType if TYPE_CHECKING: diff --git a/homeassistant/helpers/entityfilter.py b/homeassistant/helpers/entityfilter.py index 522f789b163..3d119404ffd 100644 --- a/homeassistant/helpers/entityfilter.py +++ b/homeassistant/helpers/entityfilter.py @@ -9,7 +9,8 @@ import voluptuous as vol from homeassistant.const import CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, CONF_INCLUDE from homeassistant.core import split_entity_id -from homeassistant.helpers import config_validation as cv + +from . import config_validation as cv CONF_INCLUDE_DOMAINS = "include_domains" CONF_INCLUDE_ENTITY_GLOBS = "include_entity_globs" diff --git a/homeassistant/helpers/event.py b/homeassistant/helpers/event.py index 1404b3730f1..289d3321a41 100644 --- a/homeassistant/helpers/event.py +++ b/homeassistant/helpers/event.py @@ -33,15 +33,16 @@ from homeassistant.core import ( split_entity_id, ) from homeassistant.exceptions import TemplateError -from homeassistant.helpers.entity_registry import EVENT_ENTITY_REGISTRY_UPDATED -from homeassistant.helpers.ratelimit import KeyedRateLimit -from homeassistant.helpers.sun import get_astral_event_next -from homeassistant.helpers.template import RenderInfo, Template, result_as_boolean -from homeassistant.helpers.typing import TemplateVarsType from homeassistant.loader import bind_hass from homeassistant.util import dt as dt_util from homeassistant.util.async_ import run_callback_threadsafe +from .entity_registry import EVENT_ENTITY_REGISTRY_UPDATED +from .ratelimit import KeyedRateLimit +from .sun import get_astral_event_next +from .template import RenderInfo, Template, result_as_boolean +from .typing import TemplateVarsType + TRACK_STATE_CHANGE_CALLBACKS = "track_state_change_callbacks" TRACK_STATE_CHANGE_LISTENER = "track_state_change_listener" diff --git a/homeassistant/helpers/httpx_client.py b/homeassistant/helpers/httpx_client.py index ec5b0a5e7ca..d1dc11aae4d 100644 --- a/homeassistant/helpers/httpx_client.py +++ b/homeassistant/helpers/httpx_client.py @@ -9,9 +9,10 @@ import httpx from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE, __version__ from homeassistant.core import Event, HomeAssistant, callback -from homeassistant.helpers.frame import warn_use from homeassistant.loader import bind_hass +from .frame import warn_use + DATA_ASYNC_CLIENT = "httpx_async_client" DATA_ASYNC_CLIENT_NOVERIFY = "httpx_async_client_noverify" SERVER_SOFTWARE = "HomeAssistant/{0} httpx/{1} Python/{2[0]}.{2[1]}".format( diff --git a/homeassistant/helpers/intent.py b/homeassistant/helpers/intent.py index d3494c3f41b..0c111fd9afa 100644 --- a/homeassistant/helpers/intent.py +++ b/homeassistant/helpers/intent.py @@ -11,9 +11,10 @@ import voluptuous as vol from homeassistant.const import ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES from homeassistant.core import Context, HomeAssistant, State, T, callback from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import config_validation as cv from homeassistant.loader import bind_hass +from . import config_validation as cv + _LOGGER = logging.getLogger(__name__) _SlotsType = Dict[str, Any] diff --git a/homeassistant/helpers/location.py b/homeassistant/helpers/location.py index e9d3f34b970..a3f2dfb4c6f 100644 --- a/homeassistant/helpers/location.py +++ b/homeassistant/helpers/location.py @@ -86,7 +86,7 @@ def find_coordinates( # Check if state is valid coordinate set try: # Import here, not at top-level to avoid circular import - import homeassistant.helpers.config_validation as cv # pylint: disable=import-outside-toplevel + from . import config_validation as cv # pylint: disable=import-outside-toplevel cv.gps(entity_state.state.split(",")) except vol.Invalid: diff --git a/homeassistant/helpers/reload.py b/homeassistant/helpers/reload.py index 8f9ce48a59b..baa31bb41fc 100644 --- a/homeassistant/helpers/reload.py +++ b/homeassistant/helpers/reload.py @@ -10,12 +10,13 @@ from homeassistant import config as conf_util from homeassistant.const import SERVICE_RELOAD from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import config_per_platform -from homeassistant.helpers.entity_platform import EntityPlatform, async_get_platforms -from homeassistant.helpers.typing import ConfigType from homeassistant.loader import async_get_integration from homeassistant.setup import async_setup_component +from . import config_per_platform +from .entity_platform import EntityPlatform, async_get_platforms +from .typing import ConfigType + # mypy: disallow-any-generics _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/helpers/restore_state.py b/homeassistant/helpers/restore_state.py index f1e74e26908..56b5b106278 100644 --- a/homeassistant/helpers/restore_state.py +++ b/homeassistant/helpers/restore_state.py @@ -9,14 +9,15 @@ from typing import Any, cast from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.core import HomeAssistant, State, callback, valid_entity_id from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers import entity_registry, start -from homeassistant.helpers.entity import Entity -from homeassistant.helpers.event import async_track_time_interval -from homeassistant.helpers.json import JSONEncoder -from homeassistant.helpers.singleton import singleton -from homeassistant.helpers.storage import Store import homeassistant.util.dt as dt_util +from . import entity_registry, start +from .entity import Entity +from .event import async_track_time_interval +from .json import JSONEncoder +from .singleton import singleton +from .storage import Store + DATA_RESTORE_STATE_TASK = "restore_state_task" _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/helpers/script.py b/homeassistant/helpers/script.py index 1c199525d4d..77e4fd38508 100644 --- a/homeassistant/helpers/script.py +++ b/homeassistant/helpers/script.py @@ -56,29 +56,18 @@ from homeassistant.core import ( HomeAssistant, callback, ) -from homeassistant.helpers import condition, config_validation as cv, service, template -from homeassistant.helpers.condition import ( - ConditionCheckerType, - trace_condition_function, -) -from homeassistant.helpers.dispatcher import ( - async_dispatcher_connect, - async_dispatcher_send, -) -from homeassistant.helpers.event import async_call_later, async_track_template -from homeassistant.helpers.script_variables import ScriptVariables -from homeassistant.helpers.trace import script_execution_set -from homeassistant.helpers.trigger import ( - async_initialize_triggers, - async_validate_trigger_config, -) -from homeassistant.helpers.typing import ConfigType from homeassistant.util import slugify from homeassistant.util.dt import utcnow +from . import condition, config_validation as cv, service, template +from .condition import ConditionCheckerType, trace_condition_function +from .dispatcher import async_dispatcher_connect, async_dispatcher_send +from .event import async_call_later, async_track_template +from .script_variables import ScriptVariables from .trace import ( TraceElement, async_trace_path, + script_execution_set, trace_append_element, trace_id_get, trace_path, @@ -90,6 +79,8 @@ from .trace import ( trace_stack_top, trace_update_result, ) +from .trigger import async_initialize_triggers, async_validate_trigger_config +from .typing import ConfigType # mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index 00369d43536..13ec3cb5df5 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -31,14 +31,6 @@ from homeassistant.exceptions import ( Unauthorized, UnknownUser, ) -from homeassistant.helpers import ( - area_registry, - config_validation as cv, - device_registry, - entity_registry, - template, -) -from homeassistant.helpers.typing import ConfigType, TemplateVarsType from homeassistant.loader import ( MAX_LOAD_CONCURRENTLY, Integration, @@ -49,9 +41,18 @@ from homeassistant.util.async_ import gather_with_concurrency from homeassistant.util.yaml import load_yaml from homeassistant.util.yaml.loader import JSON_TYPE +from . import ( + area_registry, + config_validation as cv, + device_registry, + entity_registry, + template, +) +from .typing import ConfigType, TemplateVarsType + if TYPE_CHECKING: - from homeassistant.helpers.entity import Entity - from homeassistant.helpers.entity_platform import EntityPlatform + from .entity import Entity + from .entity_platform import EntityPlatform CONF_SERVICE_ENTITY_ID = "entity_id" diff --git a/homeassistant/helpers/storage.py b/homeassistant/helpers/storage.py index da9aa06ba4a..af0c50ec5fa 100644 --- a/homeassistant/helpers/storage.py +++ b/homeassistant/helpers/storage.py @@ -197,7 +197,7 @@ class Store: def async_delay_save(self, data_func: Callable[[], dict], delay: float = 0) -> None: """Save data with an optional delay.""" # pylint: disable-next=import-outside-toplevel - from homeassistant.helpers.event import async_call_later + from .event import async_call_later self._data = { "version": self.version, diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 6373f63c5a0..ce7984c03bb 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -45,13 +45,6 @@ from homeassistant.core import ( valid_entity_id, ) from homeassistant.exceptions import TemplateError -from homeassistant.helpers import ( - area_registry, - device_registry, - entity_registry, - location as loc_helper, -) -from homeassistant.helpers.typing import TemplateVarsType from homeassistant.loader import bind_hass from homeassistant.util import ( convert, @@ -62,6 +55,9 @@ from homeassistant.util import ( from homeassistant.util.async_ import run_callback_threadsafe from homeassistant.util.thread import ThreadWithException +from . import area_registry, device_registry, entity_registry, location as loc_helper +from .typing import TemplateVarsType + # mypy: allow-untyped-defs, no-check-untyped-defs _LOGGER = logging.getLogger(__name__) @@ -882,9 +878,7 @@ def result_as_boolean(template_result: Any | None) -> bool: try: # Import here, not at top-level to avoid circular import - from homeassistant.helpers import ( # pylint: disable=import-outside-toplevel - config_validation as cv, - ) + from . import config_validation as cv # pylint: disable=import-outside-toplevel return cv.boolean(template_result) except vol.Invalid: @@ -952,7 +946,7 @@ def integration_entities(hass: HomeAssistant, entry_name: str) -> Iterable[str]: # fallback to just returning all entities for a domain # pylint: disable=import-outside-toplevel - from homeassistant.helpers.entity import entity_sources + from .entity import entity_sources return [ entity_id @@ -1014,9 +1008,7 @@ def area_id(hass: HomeAssistant, lookup_value: str) -> str | None: ent_reg = entity_registry.async_get(hass) dev_reg = device_registry.async_get(hass) # Import here, not at top-level to avoid circular import - from homeassistant.helpers import ( # pylint: disable=import-outside-toplevel - config_validation as cv, - ) + from . import config_validation as cv # pylint: disable=import-outside-toplevel try: cv.entity_id(lookup_value) @@ -1054,9 +1046,7 @@ def area_name(hass: HomeAssistant, lookup_value: str) -> str | None: dev_reg = device_registry.async_get(hass) ent_reg = entity_registry.async_get(hass) # Import here, not at top-level to avoid circular import - from homeassistant.helpers import ( # pylint: disable=import-outside-toplevel - config_validation as cv, - ) + from . import config_validation as cv # pylint: disable=import-outside-toplevel try: cv.entity_id(lookup_value) diff --git a/homeassistant/helpers/trace.py b/homeassistant/helpers/trace.py index 4332f34107c..bc3e7ff3565 100644 --- a/homeassistant/helpers/trace.py +++ b/homeassistant/helpers/trace.py @@ -8,9 +8,10 @@ from contextvars import ContextVar from functools import wraps from typing import Any, cast -from homeassistant.helpers.typing import TemplateVarsType import homeassistant.util.dt as dt_util +from .typing import TemplateVarsType + class TraceElement: """Container for trace data.""" diff --git a/homeassistant/helpers/trigger.py b/homeassistant/helpers/trigger.py index c7ef6d31be4..175a29fcc5d 100644 --- a/homeassistant/helpers/trigger.py +++ b/homeassistant/helpers/trigger.py @@ -11,9 +11,10 @@ import voluptuous as vol from homeassistant.const import CONF_ID, CONF_PLATFORM from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers.typing import ConfigType, TemplateVarsType from homeassistant.loader import IntegrationNotFound, async_get_integration +from .typing import ConfigType, TemplateVarsType + _PLATFORM_ALIASES = { "device_automation": ("device",), "homeassistant": ("event", "numeric_state", "state", "time_pattern", "time"), diff --git a/homeassistant/helpers/update_coordinator.py b/homeassistant/helpers/update_coordinator.py index a48fca8a01f..d9ab337e84e 100644 --- a/homeassistant/helpers/update_coordinator.py +++ b/homeassistant/helpers/update_coordinator.py @@ -15,9 +15,9 @@ import requests from homeassistant import config_entries from homeassistant.core import CALLBACK_TYPE, Event, HassJob, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady -from homeassistant.helpers import entity, event from homeassistant.util.dt import utcnow +from . import entity, event from .debounce import Debouncer REQUEST_REFRESH_DEFAULT_COOLDOWN = 10 diff --git a/homeassistant/loader.py b/homeassistant/loader.py index af3f90ab356..6fd66dab2fa 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -23,16 +23,16 @@ from awesomeversion import ( AwesomeVersionStrategy, ) -from homeassistant.generated.dhcp import DHCP -from homeassistant.generated.mqtt import MQTT -from homeassistant.generated.ssdp import SSDP -from homeassistant.generated.usb import USB -from homeassistant.generated.zeroconf import HOMEKIT, ZEROCONF -from homeassistant.util.async_ import gather_with_concurrency +from .generated.dhcp import DHCP +from .generated.mqtt import MQTT +from .generated.ssdp import SSDP +from .generated.usb import USB +from .generated.zeroconf import HOMEKIT, ZEROCONF +from .util.async_ import gather_with_concurrency # Typing imports that create a circular dependency if TYPE_CHECKING: - from homeassistant.core import HomeAssistant + from .core import HomeAssistant # mypy: disallow-any-generics @@ -167,7 +167,7 @@ async def async_get_custom_components( async def async_get_config_flows(hass: HomeAssistant) -> set[str]: """Return cached list of config flows.""" # pylint: disable=import-outside-toplevel - from homeassistant.generated.config_flows import FLOWS + from .generated.config_flows import FLOWS flows: set[str] = set() flows.update(FLOWS) @@ -607,7 +607,7 @@ async def _async_get_integration(hass: HomeAssistant, domain: str) -> Integratio if integration := (await async_get_custom_components(hass)).get(domain): return integration - from homeassistant import components # pylint: disable=import-outside-toplevel + from . import components # pylint: disable=import-outside-toplevel if integration := await hass.async_add_executor_job( Integration.resolve_from_root, hass, components, domain diff --git a/homeassistant/requirements.py b/homeassistant/requirements.py index e98ba2afe68..6b9c0bd0661 100644 --- a/homeassistant/requirements.py +++ b/homeassistant/requirements.py @@ -7,11 +7,11 @@ import logging import os from typing import Any, cast -from homeassistant.core import HomeAssistant, callback -from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers.typing import UNDEFINED, UndefinedType -from homeassistant.loader import Integration, IntegrationNotFound, async_get_integration -import homeassistant.util.package as pkg_util +from .core import HomeAssistant, callback +from .exceptions import HomeAssistantError +from .helpers.typing import UNDEFINED, UndefinedType +from .loader import Integration, IntegrationNotFound, async_get_integration +from .util import package as pkg_util # mypy: disallow-any-generics diff --git a/homeassistant/runner.py b/homeassistant/runner.py index dcf39485531..7caf6be2c8f 100644 --- a/homeassistant/runner.py +++ b/homeassistant/runner.py @@ -8,11 +8,11 @@ import threading import traceback from typing import Any -from homeassistant import bootstrap -from homeassistant.core import callback -from homeassistant.helpers.frame import warn_use -from homeassistant.util.executor import InterruptibleThreadPoolExecutor -from homeassistant.util.thread import deadlock_safe_shutdown +from . import bootstrap +from .core import callback +from .helpers.frame import warn_use +from .util.executor import InterruptibleThreadPoolExecutor +from .util.thread import deadlock_safe_shutdown # mypy: disallow-any-generics diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 3e6db28a194..44dc6fe1014 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -8,18 +8,18 @@ import logging.handlers from timeit import default_timer as timer from types import ModuleType -from homeassistant import config as conf_util, core, loader, requirements -from homeassistant.config import async_notify_setup_error -from homeassistant.const import ( +from . import config as conf_util, core, loader, requirements +from .config import async_notify_setup_error +from .const import ( EVENT_COMPONENT_LOADED, EVENT_HOMEASSISTANT_START, PLATFORM_FORMAT, Platform, ) -from homeassistant.core import CALLBACK_TYPE -from homeassistant.exceptions import HomeAssistantError -from homeassistant.helpers.typing import ConfigType -from homeassistant.util import dt as dt_util, ensure_unique_string +from .core import CALLBACK_TYPE +from .exceptions import HomeAssistantError +from .helpers.typing import ConfigType +from .util import dt as dt_util, ensure_unique_string # mypy: disallow-any-generics diff --git a/homeassistant/util/executor.py b/homeassistant/util/executor.py index 9277e396bc4..8451e71e0ec 100644 --- a/homeassistant/util/executor.py +++ b/homeassistant/util/executor.py @@ -10,7 +10,7 @@ from threading import Thread import time import traceback -from homeassistant.util.thread import async_raise +from .thread import async_raise _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/util/unit_system.py b/homeassistant/util/unit_system.py index bdb637a9149..824e324095d 100644 --- a/homeassistant/util/unit_system.py +++ b/homeassistant/util/unit_system.py @@ -31,7 +31,8 @@ from homeassistant.const import ( VOLUME_LITERS, WIND_SPEED, ) -from homeassistant.util import ( + +from . import ( distance as distance_util, pressure as pressure_util, speed as speed_util, diff --git a/pylint/plugins/hass_imports.py b/pylint/plugins/hass_imports.py index 341abff202a..beb7f87616f 100644 --- a/pylint/plugins/hass_imports.py +++ b/pylint/plugins/hass_imports.py @@ -25,24 +25,28 @@ class HassImportsFormatChecker(BaseChecker): # type: ignore[misc] def __init__(self, linter: PyLinter | None = None) -> None: super().__init__(linter) - self.current_module: str | None = None + self.current_package: str | None = None def visit_module(self, node: Module) -> None: - """Called when a Import node is visited.""" - self.current_module = node.name + """Called when a Module node is visited.""" + if node.package: + self.current_package = node.name + else: + # Strip name of the current module + self.current_package = node.name[: node.name.rfind(".")] def visit_import(self, node: Import) -> None: """Called when a Import node is visited.""" for module, _alias in node.names: - if module.startswith(f"{self.current_module}."): + if module.startswith(f"{self.current_package}."): self.add_message("hass-relative-import", node=node) def visit_importfrom(self, node: ImportFrom) -> None: """Called when a ImportFrom node is visited.""" if node.level is not None: return - if node.modname == self.current_module or node.modname.startswith( - f"{self.current_module}." + if node.modname == self.current_package or node.modname.startswith( + f"{self.current_package}." ): self.add_message("hass-relative-import", node=node)