From 66eb458dfe0bd2c12a64abd9d94bfd88590343f0 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 27 Jun 2025 20:13:35 +0200 Subject: [PATCH 1/9] Remove unneeded async function designation --- tests/test_init.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_init.py b/tests/test_init.py index ed6be9ece..8c67da028 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -89,7 +89,7 @@ async def load_testdata( content = await testdata_file.read() return json.loads(content) - async def setup_app( + def setup_app( self, broken=False, timeout=False, @@ -132,7 +132,7 @@ async def setup_app( return app - async def setup_legacy_app( + def setup_legacy_app( self, broken=False, timeout=False, @@ -290,7 +290,7 @@ async def connect( ) # Happy flow - app = await self.setup_app(broken, timeout, raise_timeout, fail_auth, stretch) + app = self.setup_app(broken, timeout, raise_timeout, fail_auth, stretch) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" @@ -374,7 +374,7 @@ async def connect_legacy( ) # Happy flow - app = await self.setup_legacy_app( + app = self.setup_legacy_app( broken, timeout, raise_timeout, fail_auth, stretch ) From 4a2f7509e60810cc77b7f4a54b34e7cbb74418bd Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 27 Jun 2025 20:14:50 +0200 Subject: [PATCH 2/9] Ruff fix --- tests/test_init.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_init.py b/tests/test_init.py index 8c67da028..d2384add6 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -374,9 +374,7 @@ async def connect_legacy( ) # Happy flow - app = self.setup_legacy_app( - broken, timeout, raise_timeout, fail_auth, stretch - ) + app = self.setup_legacy_app(broken, timeout, raise_timeout, fail_auth, stretch) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" From e99725bd693afaa05e4cdc7b1b4877ed6e202ea8 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 27 Jun 2025 20:16:29 +0200 Subject: [PATCH 3/9] Remove unneeded list(dict()) constructs --- plugwise/data.py | 2 +- plugwise/helper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 97ec5b51a..45cbe38db 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -86,7 +86,7 @@ def _detect_low_batteries(self) -> list[str]: mac_pattern = re.compile(r"(?:[0-9A-F]{2}){8}") matches = ["Battery", "below"] if self._notifications: - for msg_id, notification in list(self._notifications.items()): + for msg_id, notification in self._notifications.items(): mac_address: str | None = None message: str | None = notification.get("message") warning: str | None = notification.get("warning") diff --git a/plugwise/helper.py b/plugwise/helper.py index 87c4e986e..edd680747 100644 --- a/plugwise/helper.py +++ b/plugwise/helper.py @@ -723,7 +723,7 @@ def _scan_thermostats(self) -> None: for entity_id, entity in self.gw_entities.items(): self._rank_thermostat(thermo_matching, loc_id, entity_id, entity) - for loc_id, loc_data in list(self._thermo_locs.items()): + for loc_id, loc_data in self._thermo_locs.items(): if loc_data["primary_prio"] != 0: self._zones[loc_id] = { "dev_class": "climate", From af46088f10c3f96a67b012f4e24048f8da7ebf0e Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 27 Jun 2025 20:18:27 +0200 Subject: [PATCH 4/9] Use dict.copy() instead of list(dict) --- plugwise/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugwise/data.py b/plugwise/data.py index 45cbe38db..29b8e0922 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -86,7 +86,7 @@ def _detect_low_batteries(self) -> list[str]: mac_pattern = re.compile(r"(?:[0-9A-F]{2}){8}") matches = ["Battery", "below"] if self._notifications: - for msg_id, notification in self._notifications.items(): + for msg_id, notification in self._notifications.copy().items(): mac_address: str | None = None message: str | None = notification.get("message") warning: str | None = notification.get("warning") From 548d445abf0aa57f3ced2a5cb0aae26026ec41c1 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Fri, 27 Jun 2025 20:23:16 +0200 Subject: [PATCH 5/9] Combine if's --- plugwise/data.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugwise/data.py b/plugwise/data.py index 29b8e0922..cd36c9c4c 100644 --- a/plugwise/data.py +++ b/plugwise/data.py @@ -232,12 +232,12 @@ def _get_adam_data(self, entity: GwEntityData, data: GwEntityData) -> None: if self._on_off_device and isinstance(self._heating_valves(), int): data["binary_sensors"]["heating_state"] = self._heating_valves() != 0 # Add cooling_enabled binary_sensor - if "binary_sensors" in data: - if ( - "cooling_enabled" not in data["binary_sensors"] - and self._cooling_present - ): - data["binary_sensors"]["cooling_enabled"] = self._cooling_enabled + if ( + "binary_sensors" in data + and "cooling_enabled" not in data["binary_sensors"] + and self._cooling_present + ): + data["binary_sensors"]["cooling_enabled"] = self._cooling_enabled # Show the allowed regulation_modes and gateway_modes if entity["dev_class"] == "gateway": From 92ef5a6ca2e1b6da52675a8781cde6e2c9f3b3d4 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 28 Jun 2025 09:08:29 +0200 Subject: [PATCH 6/9] Change boolean name to timeout_happened --- tests/test_init.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/test_init.py b/tests/test_init.py index d2384add6..cacd86d4f 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -92,7 +92,7 @@ async def load_testdata( def setup_app( self, broken=False, - timeout=False, + timeout_happened=False, raise_timeout=False, fail_auth=False, stretch=False, @@ -108,7 +108,7 @@ def setup_app( if broken: app.router.add_get(CORE_DOMAIN_OBJECTS, self.smile_broken) - elif timeout: + elif timeout_happened: app.router.add_get(CORE_DOMAIN_OBJECTS, self.smile_timeout) else: app.router.add_get(CORE_DOMAIN_OBJECTS, self.smile_domain_objects) @@ -135,7 +135,7 @@ def setup_app( def setup_legacy_app( self, broken=False, - timeout=False, + timeout_happened=False, raise_timeout=False, fail_auth=False, stretch=False, @@ -151,7 +151,7 @@ def setup_legacy_app( if broken: app.router.add_get(CORE_LOCATIONS, self.smile_broken) - elif timeout: + elif timeout_happened: app.router.add_get(CORE_LOCATIONS, self.smile_timeout) else: app.router.add_get(CORE_LOCATIONS, self.smile_locations) @@ -264,12 +264,12 @@ async def smile_fail_auth(cls, request): raise aiohttp.web.HTTPUnauthorized() @staticmethod - def connect_status(broken, timeout, fail_auth): + def connect_status(broken, timeout_happened, fail_auth): """Determine assumed status from settings.""" assumed_status = 200 if broken: assumed_status = 500 - if timeout: + if timeout_happened: assumed_status = 504 if fail_auth: assumed_status = 401 @@ -278,7 +278,7 @@ def connect_status(broken, timeout, fail_auth): async def connect( self, broken=False, - timeout=False, + timeout_happened=False, raise_timeout=False, fail_auth=False, stretch=False, @@ -290,7 +290,7 @@ async def connect( ) # Happy flow - app = self.setup_app(broken, timeout, raise_timeout, fail_auth, stretch) + app = self.setup_app(broken, timeout_happened, raise_timeout, fail_auth, stretch) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" @@ -313,7 +313,7 @@ async def connect( timeoutpass_result = True assert timeoutpass_result - if not broken and not timeout and not fail_auth: + if not broken and not timeout_happened and not fail_auth: text = await resp.text() assert "xml" in text @@ -340,7 +340,7 @@ async def connect( websession=websession, ) - if not timeout: + if not timeout_happened: assert smile._timeout == 30 # Connect to the smile @@ -362,7 +362,7 @@ async def connect( async def connect_legacy( self, broken=False, - timeout=False, + timeout_happened=False, raise_timeout=False, fail_auth=False, stretch=False, @@ -374,7 +374,7 @@ async def connect_legacy( ) # Happy flow - app = self.setup_legacy_app(broken, timeout, raise_timeout, fail_auth, stretch) + app = self.setup_legacy_app(broken, timeout_happened, raise_timeout, fail_auth, stretch) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" @@ -389,7 +389,7 @@ async def connect_legacy( # Try/exceptpass to accommodate for Timeout of aoihttp try: resp = await websession.get(url) - assumed_status = self.connect_status(broken, timeout, fail_auth) + assumed_status = self.connect_status(broken, timeout_happened, fail_auth) assert resp.status == assumed_status timeoutpass_result = False assert timeoutpass_result @@ -397,7 +397,7 @@ async def connect_legacy( timeoutpass_result = True assert timeoutpass_result - if not broken and not timeout and not fail_auth: + if not broken and not timeout_happened and not fail_auth: text = await resp.text() assert "xml" in text @@ -424,7 +424,7 @@ async def connect_legacy( websession=websession, ) - if not timeout: + if not timeout_happened: assert smile._timeout == 30 # Connect to the smile @@ -464,7 +464,7 @@ async def connect_wrapper( try: _LOGGER.warning("Connecting to device exceeding timeout in response:") - await self.connect(timeout=True) + await self.connect(timeout_happened=True) _LOGGER.error(" - timeout not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.ConnectionFailedError: @@ -491,7 +491,7 @@ async def connect_legacy_wrapper( try: _LOGGER.warning("Connecting to device exceeding timeout in response:") - await self.connect_legacy(timeout=True) + await self.connect_legacy(timeout_happened=True) _LOGGER.error(" - timeout not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.ConnectionFailedError: From 25918eeb55798b562f8231d042b5b7c5002612d7 Mon Sep 17 00:00:00 2001 From: autoruff Date: Sat, 28 Jun 2025 07:09:27 +0000 Subject: [PATCH 7/9] fixup: sc-fixes-2 Python code fixed using ruff --- tests/test_init.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_init.py b/tests/test_init.py index cacd86d4f..d1e30fb98 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -290,7 +290,9 @@ async def connect( ) # Happy flow - app = self.setup_app(broken, timeout_happened, raise_timeout, fail_auth, stretch) + app = self.setup_app( + broken, timeout_happened, raise_timeout, fail_auth, stretch + ) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" @@ -374,7 +376,9 @@ async def connect_legacy( ) # Happy flow - app = self.setup_legacy_app(broken, timeout_happened, raise_timeout, fail_auth, stretch) + app = self.setup_legacy_app( + broken, timeout_happened, raise_timeout, fail_auth, stretch + ) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" From 71cd4203dba6d28a86e1102cf1f40207fb766670 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 28 Jun 2025 09:11:53 +0200 Subject: [PATCH 8/9] Fix missed --- tests/test_init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_init.py b/tests/test_init.py index d1e30fb98..aae4f9adc 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -307,7 +307,7 @@ async def connect( # Try/exceptpass to accommodate for Timeout of aoihttp try: resp = await websession.get(url) - assumed_status = self.connect_status(broken, timeout, fail_auth) + assumed_status = self.connect_status(broken, timeout_happened, fail_auth) assert resp.status == assumed_status timeoutpass_result = False assert timeoutpass_result From d70f24396a29661cd56d3c9702758429b3ff40f3 Mon Sep 17 00:00:00 2001 From: Bouwe Westerdijk Date: Sat, 28 Jun 2025 09:23:33 +0200 Subject: [PATCH 9/9] Test: combine connect-functions --- tests/test_init.py | 135 ++++++++++++--------------------------------- 1 file changed, 35 insertions(+), 100 deletions(-) diff --git a/tests/test_init.py b/tests/test_init.py index aae4f9adc..edfcbfac0 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -277,11 +277,14 @@ def connect_status(broken, timeout_happened, fail_auth): async def connect( self, + function, broken=False, timeout_happened=False, raise_timeout=False, + real_timeout_value=10, fail_auth=False, stretch=False, + url_part=CORE_DOMAIN_OBJECTS, ): """Connect to a smile environment and perform basic asserts.""" port = aiohttp.test_utils.unused_port() @@ -290,9 +293,7 @@ async def connect( ) # Happy flow - app = self.setup_app( - broken, timeout_happened, raise_timeout, fail_auth, stretch - ) + app = function(broken, timeout_happened, raise_timeout, fail_auth, stretch) server = aiohttp.test_utils.TestServer( app, port=port, scheme="http", host="127.0.0.1" @@ -302,7 +303,7 @@ async def connect( client = aiohttp.test_utils.TestClient(server) websession = client.session - url = f"{server.scheme}://{server.host}:{server.port}{CORE_DOMAIN_OBJECTS}" + url = f"{server.scheme}://{server.host}:{server.port}{url_part}" # Try/exceptpass to accommodate for Timeout of aoihttp try: @@ -350,93 +351,7 @@ async def connect( try: smile_version = await smile.connect() assert smile_version is not None - assert smile._timeout == 10 - return server, smile, client - except ( - pw_exceptions.ConnectionFailedError, - pw_exceptions.InvalidXMLError, - pw_exceptions.InvalidAuthentication, - ) as exception: - assert smile_version is None - await self.disconnect(server, client) - raise exception - - async def connect_legacy( - self, - broken=False, - timeout_happened=False, - raise_timeout=False, - fail_auth=False, - stretch=False, - ): - """Connect to a smile environment and perform basic asserts.""" - port = aiohttp.test_utils.unused_port() - test_password = "".join( - secrets.choice(string.ascii_lowercase) for _ in range(8) - ) - - # Happy flow - app = self.setup_legacy_app( - broken, timeout_happened, raise_timeout, fail_auth, stretch - ) - - server = aiohttp.test_utils.TestServer( - app, port=port, scheme="http", host="127.0.0.1" - ) - await server.start_server() - - client = aiohttp.test_utils.TestClient(server) - websession = client.session - - url = f"{server.scheme}://{server.host}:{server.port}{CORE_LOCATIONS}" - - # Try/exceptpass to accommodate for Timeout of aoihttp - try: - resp = await websession.get(url) - assumed_status = self.connect_status(broken, timeout_happened, fail_auth) - assert resp.status == assumed_status - timeoutpass_result = False - assert timeoutpass_result - except Exception: # pylint: disable=broad-except - timeoutpass_result = True - assert timeoutpass_result - - if not broken and not timeout_happened and not fail_auth: - text = await resp.text() - assert "xml" in text - - # Test lack of websession - try: - smile = pw_smile.Smile( - host=server.host, - username=pw_constants.DEFAULT_USERNAME, - password=test_password, - port=server.port, - websession=None, - ) - lack_of_websession = False - assert lack_of_websession - except Exception: # pylint: disable=broad-except - lack_of_websession = True - assert lack_of_websession - - smile = pw_smile.Smile( - host=server.host, - username=pw_constants.DEFAULT_USERNAME, - password=test_password, - port=server.port, - websession=websession, - ) - - if not timeout_happened: - assert smile._timeout == 30 - - # Connect to the smile - smile_version = None - try: - smile_version = await smile.connect() - assert smile_version is not None - assert smile._timeout == 30 + assert smile._timeout == real_timeout_value return server, smile, client except ( pw_exceptions.ConnectionFailedError, @@ -455,7 +370,7 @@ async def connect_wrapper( if fail_auth: try: _LOGGER.warning("Connecting to device with invalid credentials:") - await self.connect(fail_auth=fail_auth) + await self.connect(self.setup_app, fail_auth=fail_auth) _LOGGER.error(" - invalid credentials not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.InvalidAuthentication as exc: @@ -464,11 +379,11 @@ async def connect_wrapper( if raise_timeout: _LOGGER.warning("Connecting to device exceeding timeout in handling:") - return await self.connect(raise_timeout=True) + return await self.connect(self.setup_app, raise_timeout=True) try: _LOGGER.warning("Connecting to device exceeding timeout in response:") - await self.connect(timeout_happened=True) + await self.connect(self.setup_app, timeout_happened=True) _LOGGER.error(" - timeout not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.ConnectionFailedError: @@ -476,14 +391,14 @@ async def connect_wrapper( try: _LOGGER.warning("Connecting to device with missing data:") - await self.connect(broken=True) + await self.connect(self.setup_app, broken=True) _LOGGER.error(" - broken information not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.InvalidXMLError: _LOGGER.info(" + successfully passed XML issue handling.") _LOGGER.info("Connecting to functioning device:") - return await self.connect(stretch=stretch) + return await self.connect(self.setup_app, stretch=stretch) async def connect_legacy_wrapper( self, raise_timeout=False, fail_auth=False, stretch=False @@ -491,11 +406,21 @@ async def connect_legacy_wrapper( """Wrap connect to try negative testing before positive testing.""" if raise_timeout: _LOGGER.warning("Connecting to device exceeding timeout in handling:") - return await self.connect_legacy(raise_timeout=True) + return await self.connect( + self.setup_legacy_app, + raise_timeout=True, + real_timeout_value=30, + url_part=CORE_LOCATIONS, + ) try: _LOGGER.warning("Connecting to device exceeding timeout in response:") - await self.connect_legacy(timeout_happened=True) + await self.connect( + self.setup_legacy_app, + real_timeout_value=30, + timeout_happened=True, + url_part=CORE_LOCATIONS, + ) _LOGGER.error(" - timeout not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.ConnectionFailedError: @@ -503,14 +428,24 @@ async def connect_legacy_wrapper( try: _LOGGER.warning("Connecting to device with missing data:") - await self.connect_legacy(broken=True) + await self.connect( + self.setup_legacy_app, + broken=True, + real_timeout_value=30, + url_part=CORE_LOCATIONS, + ) _LOGGER.error(" - broken information not handled") # pragma: no cover raise self.ConnectError # pragma: no cover except pw_exceptions.InvalidXMLError: _LOGGER.info(" + successfully passed XML issue handling.") _LOGGER.info("Connecting to functioning device:") - return await self.connect_legacy(stretch=stretch) + return await self.connect( + self.setup_legacy_app, + real_timeout_value=30, + stretch=stretch, + url_part=CORE_LOCATIONS, + ) # Generic disconnect @classmethod