From dee4aff41d87e01b641896a486fb85ec99530edc Mon Sep 17 00:00:00 2001 From: G Johansson Date: Wed, 29 Jul 2026 13:39:09 +0200 Subject: [PATCH] Add async_will_remove_from_hass to pylint super call checker (#175986) --- .../checkers/super_call.py | 1 + tests/pylint/test_super_call.py | 186 ++++++++++++++++-- 2 files changed, 173 insertions(+), 14 deletions(-) diff --git a/pylint/plugins/pylint_home_assistant/checkers/super_call.py b/pylint/plugins/pylint_home_assistant/checkers/super_call.py index e767b5d23eec..fa6bbf9b98a7 100644 --- a/pylint/plugins/pylint_home_assistant/checkers/super_call.py +++ b/pylint/plugins/pylint_home_assistant/checkers/super_call.py @@ -7,6 +7,7 @@ from pylint.lint import PyLinter METHODS = { "async_added_to_hass", + "async_will_remove_from_hass", } diff --git a/tests/pylint/test_super_call.py b/tests/pylint/test_super_call.py index b6f406068ff0..651988294e2d 100644 --- a/tests/pylint/test_super_call.py +++ b/tests/pylint/test_super_call.py @@ -21,7 +21,15 @@ from . import assert_adds_messages, assert_no_messages, walk_checker async def async_added_to_hass(self) -> None: pass """, - id="no_parent", + id="added_to_no_parent", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + pass + """, + id="will_remove_from_no_parent", ), pytest.param( """ @@ -33,7 +41,19 @@ from . import assert_adds_messages, assert_no_messages, walk_checker async def async_added_to_hass(self) -> None: x = 2 """, - id="empty_parent_implementation", + id="added_to_empty_parent_implementation", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + \"\"\"Some docstring.\"\"\" + + class Child(Entity): + async def async_will_remove_from_hass(self) -> None: + x = 2 + """, + id="will_remove_from_empty_parent_implementation", ), pytest.param( """ @@ -46,7 +66,20 @@ from . import assert_adds_messages, assert_no_messages, walk_checker async def async_added_to_hass(self) -> None: x = 2 """, - id="empty_parent_implementation2", + id="added_to_empty_parent_implementation2", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + \"\"\"Some docstring.\"\"\" + pass + + class Child(Entity): + async def async_will_remove_from_hass(self) -> None: + x = 2 + """, + id="will_remove_from_empty_parent_implementation2", ), pytest.param( """ @@ -58,7 +91,19 @@ from . import assert_adds_messages, assert_no_messages, walk_checker async def async_added_to_hass(self) -> None: await super().async_added_to_hass() """, - id="correct_super_call", + id="added_to_correct_super_call", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity): + async def async_will_remove_from_hass(self) -> None: + await super().async_will_remove_from_hass() + """, + id="will_remove_from_correct_super_call", ), pytest.param( """ @@ -70,7 +115,19 @@ from . import assert_adds_messages, assert_no_messages, walk_checker async def async_added_to_hass(self) -> None: return await super().async_added_to_hass() """, - id="super_call_in_return", + id="added_to_super_call_in_return", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity): + async def async_will_remove_from_hass(self) -> None: + return await super().async_will_remove_from_hass() + """, + id="will_remove_from_super_call_in_return", ), pytest.param( """ @@ -82,7 +139,19 @@ from . import assert_adds_messages, assert_no_messages, walk_checker def added_to_hass(self) -> None: super().added_to_hass() """, - id="super_call_not_async", + id="added_to_super_call_not_async", + ), + pytest.param( + """ + class Entity: + def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity): + def async_will_remove_from_hass(self) -> None: + super().async_will_remove_from_hass() + """, + id="will_remove_from_super_call_not_async", ), pytest.param( """ @@ -98,14 +167,37 @@ from . import assert_adds_messages, assert_no_messages, walk_checker async def async_added_to_hass(self) -> None: await super().async_added_to_hass() """, - id="multiple_inheritance", + id="added_to_multiple_inheritance", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + \"\"\"\"\"\" + + class Coordinator: + async def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity, Coordinator): + async def async_will_remove_from_hass(self) -> None: + await super().async_will_remove_from_hass() + """, + id="will_remove_from_multiple_inheritance", ), pytest.param( """ async def async_added_to_hass() -> None: x = 2 """, - id="not_a_method", + id="added_to_not_a_method", + ), + pytest.param( + """ + async def async_will_remove_from_hass() -> None: + x = 2 + """, + id="will_remove_from_not_a_method", ), ], ) @@ -120,7 +212,12 @@ def test_enforce_super_call( with ( patch( "pylint_home_assistant.checkers.super_call.METHODS", - new={"added_to_hass", "async_added_to_hass"}, + new={ + "added_to_hass", + "async_added_to_hass", + "will_remove_from_hass", + "async_will_remove_from_hass", + }, ), assert_no_messages(linter), ): @@ -141,7 +238,20 @@ def test_enforce_super_call( x = 3 """, 1, - id="no_super_call", + id="added_to_no_super_call", + ), + pytest.param( + """ + class Entity: + def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity): + def async_will_remove_from_hass(self) -> None: + x = 3 + """, + 1, + id="will_remove_from_no_super_call", ), pytest.param( """ @@ -154,7 +264,20 @@ def test_enforce_super_call( x = 3 """, 1, - id="no_super_call_async", + id="async_added_to_no_super_call", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity): + async def async_will_remove_from_hass(self) -> None: + x = 3 + """, + 1, + id="async_will_remove_from_no_super_call", ), pytest.param( """ @@ -167,7 +290,20 @@ def test_enforce_super_call( await Entity.async_added_to_hass() """, 1, - id="explicit_call_to_base_implementation", + id="added_to_explicit_call_to_base_implementation", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity): + async def async_will_remove_from_hass(self) -> None: + await Entity.async_will_remove_from_hass() + """, + 1, + id="will_remove_from_explicit_call_to_base_implementation", ), pytest.param( """ @@ -184,7 +320,24 @@ def test_enforce_super_call( x = 3 """, 2, - id="multiple_inheritance", + id="added_to_multiple_inheritance", + ), + pytest.param( + """ + class Entity: + async def async_will_remove_from_hass(self) -> None: + \"\"\"\"\"\" + + class Coordinator: + async def async_will_remove_from_hass(self) -> None: + x = 2 + + class Child(Entity, Coordinator): + async def async_will_remove_from_hass(self) -> None: + x = 3 + """, + 2, + id="will_remove_from_multiple_inheritance", ), ], ) @@ -201,7 +354,12 @@ def test_enforce_super_call_bad( with ( patch( "pylint_home_assistant.checkers.super_call.METHODS", - new={"added_to_hass", "async_added_to_hass"}, + new={ + "added_to_hass", + "async_added_to_hass", + "will_remove_from_hass", + "async_will_remove_from_hass", + }, ), assert_adds_messages( linter,