From ff633ed16bb284e2fa309e38c7775b5848f2d1a3 Mon Sep 17 00:00:00 2001 From: John Pettitt Date: Sun, 11 Oct 2026 12:11:18 -0700 Subject: [PATCH] Clear the vendored library's ruff findings so the Lint workflow can pass Docstring wording and typing only, plus one bare except narrowed to Exception and an import moved above the function in const.py. No behaviour change. Co-Authored-By: Claude Fable 5.1 Reviewed-by: John Pettitt @jpettitt --- custom_components/securityspy/const.py | 9 ++-- .../securityspy/pysecspy/secspy_data.py | 1 - .../securityspy/pysecspy/secspy_server.py | 48 ++++++++----------- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/custom_components/securityspy/const.py b/custom_components/securityspy/const.py index cfa0e8c..f07349e 100644 --- a/custom_components/securityspy/const.py +++ b/custom_components/securityspy/const.py @@ -8,16 +8,17 @@ CONF_FILENAME, ) - -def slugify_camera_name(name: str) -> str: - """Create a stable slug from a camera name.""" - return re.sub(r"[^a-z0-9]+", "_", name.lower()).strip("_") from .pysecspy.const import ( RECORDING_TYPE_ACTION, RECORDING_TYPE_MOTION, RECORDING_TYPE_CONTINUOUS, ) + +def slugify_camera_name(name: str) -> str: + """Create a stable slug from a camera name.""" + return re.sub(r"[^a-z0-9]+", "_", name.lower()).strip("_") + DOMAIN = "securityspy" UNIQUE_ID = "unique_id" diff --git a/custom_components/securityspy/pysecspy/secspy_data.py b/custom_components/securityspy/pysecspy/secspy_data.py index e174af0..b840404 100644 --- a/custom_components/securityspy/pysecspy/secspy_data.py +++ b/custom_components/securityspy/pysecspy/secspy_data.py @@ -1,6 +1,5 @@ """SecuritySpy Data.""" import datetime -import json import logging import time from collections import OrderedDict diff --git a/custom_components/securityspy/pysecspy/secspy_server.py b/custom_components/securityspy/pysecspy/secspy_server.py index ed65d35..0818e1c 100644 --- a/custom_components/securityspy/pysecspy/secspy_server.py +++ b/custom_components/securityspy/pysecspy/secspy_server.py @@ -4,7 +4,6 @@ import logging import time from base64 import b64encode -from typing import Optional import aiohttp import xmltodict @@ -90,6 +89,7 @@ def __init__( use_ssl: bool = False, verify_ssl: bool = False, ): + """Initialize the SecuritySpy client.""" self._host = host self._port = port self._username = username @@ -134,11 +134,11 @@ def __init__( @property def devices(self): - """ Returns a JSON formatted list of Devices. """ + """Return the processed device data.""" return self._processed_data async def update(self, force_camera_update=False) -> dict: - """Updates the status of devices.""" + """Update the status of devices.""" current_time = time.time() device_update = False @@ -255,17 +255,17 @@ async def get_unique_id(self) -> None: return await self._get_server_information()[SERVER_ID] async def get_server_information(self): - """Returns a Server Information for this NVR.""" + """Return server information for this NVR.""" return await self._get_server_information() async def get_snapshot_image( self, camera_id: str, - width: Optional[int] = None, - height: Optional[int] = None, + width: int | None = None, + height: int | None = None, fit: bool = False, ) -> bytes: - """ Returns a Snapshot image from the specified Camera. """ + """Return a snapshot image from the specified camera.""" if not fit: # Default: byte-for-byte the request every release before this one # sent. SecuritySpy renders ++image at exactly the size asked for, @@ -301,7 +301,7 @@ async def get_snapshot_image( return await response.read() async def get_latest_motion_recording(self, camera_id: str) -> bytes: - """ Returns the latest motion recording file. """ + """Return the latest motion recording file.""" # Get the latest file name file_uri = f"{self._base_url}/download?cameraNum={camera_id}&mcFilesCheck=1&ageText=1&results=1&format=xml&auth={self._token}" @@ -334,8 +334,9 @@ async def get_latest_motion_recording(self, camera_id: str) -> bytes: return await response.read() async def set_arm_mode(self, camera_id: str, mode: str, enabled: bool) -> bool: - """Sets the camera arming mode . - Valid inputs for mode: action, on_motion, continuous. Valid input for value is True or False + """Set the camera arming mode. + + Valid inputs for mode: action, on_motion, continuous. Valid input for value is True or False. """ schedule = 1 if enabled else 0 @@ -368,9 +369,9 @@ async def set_arm_mode(self, camera_id: str, mode: str, enabled: bool) -> bool: return True async def enable_schedule_preset(self, schedule_id: str) -> bool: - """Enables a schedule preset. - Valid inputs for schedule_id is a valid preset id - Format: setPreset?id=X + """Enable a schedule preset. + + Valid input for schedule_id is a preset id. Format: setPreset?id=X """ cam_uri = f"{self._base_url}/setPreset?id={schedule_id}&auth={self._token}" @@ -439,8 +440,9 @@ async def set_camera_setting(self, camera_id: str, setting: str, value) -> bool: return True async def enable_camera(self, camera_id: str, enabled: bool) -> bool: - """Enables or disables the camera. - Valid input for enabled is True or False + """Enable or disable the camera. + + Valid input for enabled is True or False. """ _enable = 1 if enabled else 0 @@ -466,15 +468,7 @@ async def enable_camera(self, camera_id: str, enabled: bool) -> bool: def _process_cameras_json(self, json_response, server_id, include_events): items = json_response["system"]["cameralist"]["camera"] cameras = [] - if not isinstance( - items, - ( - frozenset, - list, - set, - tuple, - ), - ): + if not isinstance(items, frozenset | list | set | tuple): cameras.append(items) else: cameras = items @@ -506,7 +500,7 @@ def _reset_device_events(self) -> None: self._update_device(device_id, PROCESSED_EVENT_EMPTY) async def _setup_streamreader(self): - """Setup the Event Websocket.""" + """Set up the event stream reader.""" url = f"{self._base_url}/eventStream?version=3&format=multipart&auth={self._token}" timeout = aiohttp.ClientTimeout( total=None, connect=None, sock_connect=None, sock_read=None @@ -704,7 +698,7 @@ def _process_ws_message(self, msg): self.global_event_score_vehicle = action_array[7] self.global_event_score_animal = action_array[9] self.global_event_object = None - except: + except Exception: self.global_event_score_animal = 0 finally: # Set the Event Object to the highest score @@ -807,7 +801,7 @@ def _process_event_ws_message(self, action_json, data_json): self.fire_event(device_id, processed_event) def fire_event(self, device_id, processed_event): - """Callback and event to the subscribers and update data.""" + """Update device data and notify subscribers of the event.""" self._update_device(device_id, processed_event) for subscriber in self._ws_subscriptions: