1
0
mirror of https://github.com/home-assistant/core.git synced 2025-09-02 09:01:05 +00:00
Files
.devcontainer
.github
.vscode
homeassistant
machine
pylint
plugins
hass_decorator.py
hass_enforce_class_module.py
hass_enforce_sorted_platforms.py
hass_enforce_super_call.py
hass_enforce_type_hints.py
hass_imports.py
hass_inheritance.py
hass_logger.py
ruff.toml
rootfs
script
tests
.core_files.yaml
.dockerignore
.git-blame-ignore-revs
.gitattributes
.gitignore
.hadolint.yaml
.pre-commit-config.yaml
.prettierignore
.strict-typing
.yamllint
CLA.md
CODEOWNERS
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Dockerfile
Dockerfile.dev
LICENSE.md
MANIFEST.in
README.rst
build.yaml
codecov.yml
mypy.ini
pyproject.toml
requirements.txt
requirements_all.txt
requirements_test.txt
requirements_test_all.txt
requirements_test_pre_commit.txt
core/pylint/plugins/hass_inheritance.py

78 lines
2.4 KiB
Python

"""Plugin to enforce type hints on specific functions."""
from __future__ import annotations
import re
from astroid import nodes
from pylint.checkers import BaseChecker
from pylint.lint import PyLinter
_MODULE_REGEX: re.Pattern[str] = re.compile(r"^homeassistant\.components\.\w+(\.\w+)?$")
def _get_module_platform(module_name: str) -> str | None:
"""Return the platform for the module name."""
if not (module_match := _MODULE_REGEX.match(module_name)):
# Ensure `homeassistant.components.<component>`
# Or `homeassistant.components.<component>.<platform>`
return None
platform = module_match.groups()[0]
return platform.lstrip(".") if platform else "__init__"
class HassInheritanceChecker(BaseChecker):
"""Checker for invalid inheritance."""
name = "hass_inheritance"
priority = -1
msgs = {
"W7411": (
"Invalid inheritance: %s",
"hass-invalid-inheritance",
"Used when a class has inheritance has issues",
),
}
options = ()
_module_name: str
_module_platform: str | None
def visit_module(self, node: nodes.Module) -> None:
"""Populate matchers for a Module node."""
self._module_name = node.name
self._module_platform = _get_module_platform(node.name)
def visit_classdef(self, node: nodes.ClassDef) -> None:
"""Apply relevant type hint checks on a ClassDef node."""
if self._module_platform not in {"number", "sensor"}:
return
ancestors = [a.name for a in node.ancestors()]
if (
"RestoreEntity" in ancestors
and "SensorEntity" in ancestors
and "RestoreSensor" not in ancestors
):
self.add_message(
"hass-invalid-inheritance",
node=node,
args="SensorEntity and RestoreEntity should not be combined, please use RestoreSensor",
)
elif (
"RestoreEntity" in ancestors
and "NumberEntity" in ancestors
and "RestoreNumber" not in ancestors
):
self.add_message(
"hass-invalid-inheritance",
node=node,
args="NumberEntity and RestoreEntity should not be combined, please use RestoreNumber",
)
def register(linter: PyLinter) -> None:
"""Register the checker."""
linter.register_checker(HassInheritanceChecker(linter))