Pylint plugin to check that relative imports are used (#50937)

* Pylint plugin to check that relative imports are used

* Fix existing sites

* Update description message

* Fix typo
This commit is contained in:
Ruslan Sayfutdinov 2021-05-22 09:15:30 +01:00 committed by GitHub
parent b704f0e729
commit 016abda12e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 89 additions and 44 deletions

View File

@ -9,13 +9,12 @@ from typing import Any, Dict, Mapping, Optional, Tuple, cast
import jwt import jwt
from homeassistant import data_entry_flow from homeassistant import data_entry_flow
from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult from homeassistant.data_entry_flow import FlowResult
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from . import auth_store, models from . import auth_store, models
from .const import GROUP_ID_ADMIN from .const import ACCESS_TOKEN_EXPIRATION, GROUP_ID_ADMIN
from .mfa_modules import MultiFactorAuthModule, auth_mfa_module_from_config from .mfa_modules import MultiFactorAuthModule, auth_mfa_module_from_config
from .providers import AuthProvider, LoginFlow, auth_provider_from_config from .providers import AuthProvider, LoginFlow, auth_provider_from_config

View File

@ -6,17 +6,6 @@ import logging
from adguardhome import AdGuardHome, AdGuardHomeConnectionError, AdGuardHomeError from adguardhome import AdGuardHome, AdGuardHomeConnectionError, AdGuardHomeError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.adguard.const import (
CONF_FORCE,
DATA_ADGUARD_CLIENT,
DATA_ADGUARD_VERSION,
DOMAIN,
SERVICE_ADD_URL,
SERVICE_DISABLE_URL,
SERVICE_ENABLE_URL,
SERVICE_REFRESH,
SERVICE_REMOVE_URL,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_HOST,
@ -34,6 +23,18 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import DeviceInfo, Entity from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import (
CONF_FORCE,
DATA_ADGUARD_CLIENT,
DATA_ADGUARD_VERSION,
DOMAIN,
SERVICE_ADD_URL,
SERVICE_DISABLE_URL,
SERVICE_ENABLE_URL,
SERVICE_REFRESH,
SERVICE_REMOVE_URL,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SERVICE_URL_SCHEMA = vol.Schema({vol.Required(CONF_URL): cv.url}) SERVICE_URL_SCHEMA = vol.Schema({vol.Required(CONF_URL): cv.url})

View File

@ -6,18 +6,13 @@ import logging
from aioazuredevops.client import DevOpsClient from aioazuredevops.client import DevOpsClient
import aiohttp import aiohttp
from homeassistant.components.azure_devops.const import (
CONF_ORG,
CONF_PAT,
CONF_PROJECT,
DATA_AZURE_DEVOPS_CLIENT,
DOMAIN,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.entity import DeviceInfo, Entity from homeassistant.helpers.entity import DeviceInfo, Entity
from .const import CONF_ORG, CONF_PAT, CONF_PROJECT, DATA_AZURE_DEVOPS_CLIENT, DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
PLATFORMS = ["sensor"] PLATFORMS = ["sensor"]

View File

@ -7,7 +7,13 @@ from blinkpy.blinkpy import Blink
import voluptuous as vol import voluptuous as vol
from homeassistant.components import persistent_notification from homeassistant.components import persistent_notification
from homeassistant.components.blink.const import ( from homeassistant.config_entries import SOURCE_REAUTH
from homeassistant.const import CONF_FILENAME, CONF_NAME, CONF_PIN, CONF_SCAN_INTERVAL
from homeassistant.core import callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
from .const import (
DEFAULT_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL,
DOMAIN, DOMAIN,
PLATFORMS, PLATFORMS,
@ -15,11 +21,6 @@ from homeassistant.components.blink.const import (
SERVICE_SAVE_VIDEO, SERVICE_SAVE_VIDEO,
SERVICE_SEND_PIN, SERVICE_SEND_PIN,
) )
from homeassistant.config_entries import SOURCE_REAUTH
from homeassistant.const import CONF_FILENAME, CONF_NAME, CONF_PIN, CONF_SCAN_INTERVAL
from homeassistant.core import callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@ -9,12 +9,6 @@ import async_timeout
from colorthief import ColorThief from colorthief import ColorThief
import voluptuous as vol import voluptuous as vol
from homeassistant.components.color_extractor.const import (
ATTR_PATH,
ATTR_URL,
DOMAIN,
SERVICE_TURN_ON,
)
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_RGB_COLOR, ATTR_RGB_COLOR,
DOMAIN as LIGHT_DOMAIN, DOMAIN as LIGHT_DOMAIN,
@ -24,6 +18,8 @@ from homeassistant.components.light import (
from homeassistant.helpers import aiohttp_client from homeassistant.helpers import aiohttp_client
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from .const import ATTR_PATH, ATTR_URL, DOMAIN, SERVICE_TURN_ON
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# Extend the existing light.turn_on service schema # Extend the existing light.turn_on service schema

View File

@ -6,7 +6,6 @@ import logging
from pymfy.api.devices.category import Category from pymfy.api.devices.category import Category
import voluptuous as vol import voluptuous as vol
from homeassistant.components.somfy import config_flow
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_OPTIMISTIC from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_OPTIMISTIC
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
@ -21,7 +20,7 @@ from homeassistant.helpers.update_coordinator import (
DataUpdateCoordinator, DataUpdateCoordinator,
) )
from . import api from . import api, config_flow
from .const import API, COORDINATOR, DOMAIN from .const import API, COORDINATOR, DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@ -5,7 +5,6 @@ from spotipy import Spotify, SpotifyException
import voluptuous as vol import voluptuous as vol
from homeassistant.components.media_player import DOMAIN as MEDIA_PLAYER_DOMAIN from homeassistant.components.media_player import DOMAIN as MEDIA_PLAYER_DOMAIN
from homeassistant.components.spotify import config_flow
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_CREDENTIALS, CONF_CLIENT_ID, CONF_CLIENT_SECRET from homeassistant.const import ATTR_CREDENTIALS, CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@ -17,6 +16,7 @@ from homeassistant.helpers.config_entry_oauth2_flow import (
) )
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from . import config_flow
from .const import ( from .const import (
DATA_SPOTIFY_CLIENT, DATA_SPOTIFY_CLIENT,
DATA_SPOTIFY_ME, DATA_SPOTIFY_ME,

View File

@ -7,13 +7,6 @@ from datetime import timedelta
from twentemilieu import TwenteMilieu from twentemilieu import TwenteMilieu
import voluptuous as vol import voluptuous as vol
from homeassistant.components.twentemilieu.const import (
CONF_HOUSE_LETTER,
CONF_HOUSE_NUMBER,
CONF_POST_CODE,
DATA_UPDATE,
DOMAIN,
)
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID from homeassistant.const import CONF_ID
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
@ -23,6 +16,14 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from .const import (
CONF_HOUSE_LETTER,
CONF_HOUSE_NUMBER,
CONF_POST_CODE,
DATA_UPDATE,
DOMAIN,
)
SCAN_INTERVAL = timedelta(seconds=3600) SCAN_INTERVAL = timedelta(seconds=3600)
SERVICE_UPDATE = "update" SERVICE_UPDATE = "update"

View File

@ -1,5 +1,5 @@
"""Plugin for constructor definitions.""" """Plugin for constructor definitions."""
from astroid import ClassDef, Const, FunctionDef from astroid import Const, FunctionDef
from pylint.checkers import BaseChecker from pylint.checkers import BaseChecker
from pylint.interfaces import IAstroidChecker from pylint.interfaces import IAstroidChecker
from pylint.lint import PyLinter from pylint.lint import PyLinter
@ -43,7 +43,7 @@ class HassConstructorFormatChecker(BaseChecker): # type: ignore[misc]
return return
# Check that return type is specified and it is "None". # Check that return type is specified and it is "None".
if not isinstance(node.returns, Const) or node.returns.value != None: if not isinstance(node.returns, Const) or node.returns.value is not None:
self.add_message("hass-constructor-return", node=node) self.add_message("hass-constructor-return", node=node)

View File

@ -0,0 +1,52 @@
"""Plugin for checking imports."""
from __future__ import annotations
from astroid import Import, ImportFrom, Module
from pylint.checkers import BaseChecker
from pylint.interfaces import IAstroidChecker
from pylint.lint import PyLinter
class HassImportsFormatChecker(BaseChecker): # type: ignore[misc]
"""Checker for imports."""
__implements__ = IAstroidChecker
name = "hass_imports"
priority = -1
msgs = {
"W0011": (
"Relative import should be used",
"hass-relative-import",
"Used when absolute import should be replaced with relative import",
),
}
options = ()
def __init__(self, linter: PyLinter | None = None) -> None:
super().__init__(linter)
self.current_module: str | None = None
def visit_module(self, node: Module) -> None:
"""Called when a Import node is visited."""
self.current_module = node.name
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}."):
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}."
):
self.add_message("hass-relative-import", node=node)
def register(linter: PyLinter) -> None:
"""Register the checker."""
linter.register_checker(HassImportsFormatChecker(linter))

View File

@ -28,6 +28,7 @@ load-plugins = [
"pylint.extensions.typing", "pylint.extensions.typing",
"pylint_strict_informational", "pylint_strict_informational",
"hass_constructor", "hass_constructor",
"hass_imports",
"hass_logger", "hass_logger",
] ]
persistent = false persistent = false