diff --git a/pylint/plugins/hass_imports.py b/pylint/plugins/hass_imports.py index 57b71560b53..afe307dce42 100644 --- a/pylint/plugins/hass_imports.py +++ b/pylint/plugins/hass_imports.py @@ -460,6 +460,11 @@ class HassImportsFormatChecker(BaseChecker): "hass-helper-namespace-import", "Used when a helper should be used via the namespace", ), + "W7426": ( + "`%s` should be imported using an alias, such as `%s as %s`", + "hass-import-constant-alias", + "Used when a constant should be imported as an alias", + ), } options = () @@ -540,19 +545,30 @@ class HassImportsFormatChecker(BaseChecker): if node.modname.startswith(f"{root}.components.{current_component}."): self.add_message("hass-relative-import", node=node) return - if node.modname.startswith("homeassistant.components.") and ( - node.modname.endswith(".const") - or "const" in {names[0] for names in node.names} + + if node.modname.startswith("homeassistant.components.") and not ( + self.current_package.startswith("tests.components.") + and self.current_package.split(".")[2] == node.modname.split(".")[2] ): - if ( - self.current_package.startswith("tests.components.") - and self.current_package.split(".")[2] == node.modname.split(".")[2] - ): - # Ignore check if the component being tested matches - # the component being imported from + if node.modname.endswith(".const"): + self.add_message("hass-component-root-import", node=node) return - self.add_message("hass-component-root-import", node=node) - return + for name, alias in node.names: + if name == "const": + self.add_message("hass-component-root-import", node=node) + return + if name == "DOMAIN" and (alias is None or alias == "DOMAIN"): + self.add_message( + "hass-import-constant-alias", + node=node, + args=( + "DOMAIN", + "DOMAIN", + f"{node.modname.split(".")[2].upper()}_DOMAIN", + ), + ) + return + if obsolete_imports := _OBSOLETE_IMPORT.get(node.modname): for name_tuple in node.names: for obsolete_import in obsolete_imports: diff --git a/tests/pylint/test_imports.py b/tests/pylint/test_imports.py index e53b8206848..980b9ead74c 100644 --- a/tests/pylint/test_imports.py +++ b/tests/pylint/test_imports.py @@ -309,3 +309,54 @@ def test_bad_namespace_import( ), ): imports_checker.visit_importfrom(node) + + +@pytest.mark.parametrize( + ("module_name", "import_string", "end_col_offset"), + [ + ( + "homeassistant.components.pylint_test.sensor", + "from homeassistant.components.other import DOMAIN as OTHER_DOMAIN", + -1, + ), + ( + "homeassistant.components.pylint_test.sensor", + "from homeassistant.components.other import DOMAIN", + 49, + ), + ], +) +def test_domain_alias( + linter: UnittestLinter, + imports_checker: BaseChecker, + module_name: str, + import_string: str, + end_col_offset: int, +) -> None: + """Ensure good imports pass through ok.""" + + import_node = astroid.extract_node( + f"{import_string} #@", + module_name, + ) + imports_checker.visit_module(import_node.parent) + + expected_messages = [] + if end_col_offset > 0: + expected_messages.append( + pylint.testutils.MessageTest( + msg_id="hass-import-constant-alias", + node=import_node, + args=("DOMAIN", "DOMAIN", "OTHER_DOMAIN"), + line=1, + col_offset=0, + end_line=1, + end_col_offset=end_col_offset, + ) + ) + + with assert_adds_messages(linter, *expected_messages): + if import_string.startswith("import"): + imports_checker.visit_import(import_node) + else: + imports_checker.visit_importfrom(import_node)