diff --git a/homeassistant/components/harmony/switch.py b/homeassistant/components/harmony/switch.py index 16b83c80478..a45b43fce0f 100644 --- a/homeassistant/components/harmony/switch.py +++ b/homeassistant/components/harmony/switch.py @@ -30,7 +30,7 @@ async def async_setup_entry(hass, entry, async_add_entities): class HarmonyActivitySwitch(ConnectionStateMixin, SwitchEntity): """Switch representation of a Harmony activity.""" - def __init__(self, name: str, activity: dict, data: HarmonyData): + def __init__(self, name: str, activity: dict, data: HarmonyData) -> None: """Initialize HarmonyActivitySwitch class.""" super().__init__() self._name = name diff --git a/homeassistant/components/tesla/config_flow.py b/homeassistant/components/tesla/config_flow.py index 89dc8d2a2b4..af2fd7ae769 100644 --- a/homeassistant/components/tesla/config_flow.py +++ b/homeassistant/components/tesla/config_flow.py @@ -114,7 +114,7 @@ class TeslaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): class OptionsFlowHandler(config_entries.OptionsFlow): """Handle a option flow for Tesla.""" - def __init__(self, config_entry: config_entries.ConfigEntry): + def __init__(self, config_entry: config_entries.ConfigEntry) -> None: """Initialize options flow.""" self.config_entry = config_entry diff --git a/pylint/plugins/hass_constructor.py b/pylint/plugins/hass_constructor.py new file mode 100644 index 00000000000..3a3012b9f69 --- /dev/null +++ b/pylint/plugins/hass_constructor.py @@ -0,0 +1,52 @@ +"""Plugin for constructor definitions.""" +from astroid import ClassDef, Const, FunctionDef +from pylint.checkers import BaseChecker +from pylint.interfaces import IAstroidChecker +from pylint.lint import PyLinter + + +class HassConstructorFormatChecker(BaseChecker): # type: ignore[misc] + """Checker for __init__ definitions.""" + + __implements__ = IAstroidChecker + + name = "hass_constructor" + priority = -1 + msgs = { + "W0006": ( + '__init__ should have explicit return type "None"', + "hass-constructor-return", + "Used when __init__ has all arguments typed " + "but doesn't have return type declared", + ), + } + options = () + + def visit_functiondef(self, node: FunctionDef) -> None: + """Called when a FunctionDef node is visited.""" + if not node.is_method() or node.name != "__init__": + return + + # Check that all arguments are annotated. + # The first argument is "self". + args = node.args + annotations = ( + args.posonlyargs_annotations + + args.annotations + + args.kwonlyargs_annotations + )[1:] + if args.vararg is not None: + annotations.append(args.varargannotation) + if args.kwarg is not None: + annotations.append(args.kwargannotation) + if not annotations or None in annotations: + return + + # Check that return type is specified and it is "None". + if not isinstance(node.returns, Const) or node.returns.value != None: + self.add_message("hass-constructor-return", node=node) + + +def register(linter: PyLinter) -> None: + """Register the checker.""" + linter.register_checker(HassConstructorFormatChecker(linter)) diff --git a/pylint/plugins/hass_logger.py b/pylint/plugins/hass_logger.py index b771b07aa5e..0ca57b8da19 100644 --- a/pylint/plugins/hass_logger.py +++ b/pylint/plugins/hass_logger.py @@ -1,18 +1,18 @@ +"""Plugin for logger invocations.""" import astroid from pylint.checkers import BaseChecker from pylint.interfaces import IAstroidChecker +from pylint.lint import PyLinter LOGGER_NAMES = ("LOGGER", "_LOGGER") LOG_LEVEL_ALLOWED_LOWER_START = ("debug",) -# This is our checker class. -# Checkers should always inherit from `BaseChecker`. -class HassLoggerFormatChecker(BaseChecker): - """Add class member attributes to the class locals dictionary.""" + +class HassLoggerFormatChecker(BaseChecker): # type: ignore[misc] + """Checker for logger invocations.""" __implements__ = IAstroidChecker - # The name defines a custom section of the config for this checker. name = "hass_logger" priority = -1 msgs = { @@ -27,24 +27,10 @@ class HassLoggerFormatChecker(BaseChecker): "All logger messages must start with a capital letter", ), } - options = ( - ( - "hass-logger", - { - "default": "properties", - "help": ( - "Validate _LOGGER or LOGGER messages conform to Home Assistant standards." - ), - }, - ), - ) + options = () - def visit_call(self, node): - """Called when a :class:`.astroid.node_classes.Call` node is visited. - See :mod:`astroid` for the description of available nodes. - :param node: The node to check. - :type node: astroid.node_classes.Call - """ + def visit_call(self, node: astroid.Call) -> None: + """Called when a Call node is visited.""" if not isinstance(node.func, astroid.Attribute) or not isinstance( node.func.expr, astroid.Name ): @@ -67,19 +53,16 @@ class HassLoggerFormatChecker(BaseChecker): return if log_message[-1] == ".": - self.add_message("hass-logger-period", args=node.args, node=node) + self.add_message("hass-logger-period", node=node) if ( isinstance(node.func.attrname, str) and node.func.attrname not in LOG_LEVEL_ALLOWED_LOWER_START and log_message[0].upper() != log_message[0] ): - self.add_message("hass-logger-capital", args=node.args, node=node) + self.add_message("hass-logger-capital", node=node) -def register(linter): - """This required method auto registers the checker. - :param linter: The linter to register the checker to. - :type linter: pylint.lint.PyLinter - """ +def register(linter: PyLinter) -> None: + """Register the checker.""" linter.register_checker(HassLoggerFormatChecker(linter)) diff --git a/pyproject.toml b/pyproject.toml index 0e38a197319..33af823fae4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,8 @@ init-hook='from pylint.config.find_default_config_files import find_default_conf load-plugins = [ "pylint.extensions.typing", "pylint_strict_informational", - "hass_logger" + "hass_constructor", + "hass_logger", ] persistent = false extension-pkg-whitelist = [