From ce70d287f54ecebe91a448ea286a0d09b0c6f347 Mon Sep 17 00:00:00 2001 From: Markus Zehnder Date: Mon, 26 Feb 2024 12:12:30 +0100 Subject: [PATCH] fixup! chore: yet another attempt fixing new linting issues --- .../runConfigurations/Format_Black_style.xml | 35 ++++ ucapi/api.py | 157 +++++++++++++----- ucapi/api_definitions.py | 4 +- ucapi/entity.py | 4 +- 4 files changed, 159 insertions(+), 41 deletions(-) create mode 100644 .idea/runConfigurations/Format_Black_style.xml diff --git a/.idea/runConfigurations/Format_Black_style.xml b/.idea/runConfigurations/Format_Black_style.xml new file mode 100644 index 0000000..5ebef65 --- /dev/null +++ b/.idea/runConfigurations/Format_Black_style.xml @@ -0,0 +1,35 @@ + + + + + \ No newline at end of file diff --git a/ucapi/api.py b/ucapi/api.py index 8cf447b..1762472 100644 --- a/ucapi/api.py +++ b/ucapi/api.py @@ -49,7 +49,9 @@ def __init__(self, loop: AbstractEventLoop): self._server_task = None self._clients = set() - self._config_dir_path: str = os.getenv("UC_CONFIG_HOME") or os.getenv("HOME") or "./" + self._config_dir_path: str = ( + os.getenv("UC_CONFIG_HOME") or os.getenv("HOME") or "./" + ) self._available_entities = Entities("available", self._loop) self._configured_entities = Entities("configured", self._loop) @@ -57,7 +59,9 @@ def __init__(self, loop: AbstractEventLoop): # Setup event loop asyncio.set_event_loop(self._loop) - async def init(self, driver_path: str, setup_handler: uc.SetupHandler | None = None): + async def init( + self, driver_path: str, setup_handler: uc.SetupHandler | None = None + ): """ Load driver configuration and start integration-API WebSocket server. @@ -68,7 +72,9 @@ async def init(self, driver_path: str, setup_handler: uc.SetupHandler | None = N self._driver_path = driver_path self._setup_handler = setup_handler - self._configured_entities.add_listener(uc.Events.ENTITY_ATTRIBUTES_UPDATED, self._on_entity_attributes_updated) + self._configured_entities.add_listener( + uc.Events.ENTITY_ATTRIBUTES_UPDATED, self._on_entity_attributes_updated + ) # Load driver config with open(self._driver_path, "r", encoding="utf-8") as file: @@ -83,13 +89,17 @@ async def init(self, driver_path: str, setup_handler: uc.SetupHandler | None = N _adjust_driver_url(self._driver_info, port) - disable_mdns_publish = os.getenv("UC_DISABLE_MDNS_PUBLISH", "false").lower() in ("true", "1") + disable_mdns_publish = os.getenv( + "UC_DISABLE_MDNS_PUBLISH", "false" + ).lower() in ("true", "1") if disable_mdns_publish is False: # Setup zeroconf service info name = f"{self._driver_info['driver_id']}._uc-integration._tcp.local." hostname = local_hostname() - driver_name = _get_default_language_string(self._driver_info["name"], "Unknown driver") + driver_name = _get_default_language_string( + self._driver_info["name"], "Unknown driver" + ) _LOG.debug("Publishing driver: name=%s, host=%s:%d", name, hostname, port) @@ -109,7 +119,9 @@ async def init(self, driver_path: str, setup_handler: uc.SetupHandler | None = N await zeroconf.async_register_service(info) host = interface if interface is not None else "0.0.0.0" - self._server_task = self._loop.create_task(self._start_web_socket_server(host, port)) + self._server_task = self._loop.create_task( + self._start_web_socket_server(host, port) + ) _LOG.info( "Driver is up: %s, version: %s, listening on: %s:%d", @@ -126,7 +138,9 @@ async def _on_entity_attributes_updated(self, entity_id, entity_type, attributes "attributes": attributes, } - await self._broadcast_ws_event(uc.WsMsgEvents.ENTITY_CHANGE, data, uc.EventCategory.ENTITY) + await self._broadcast_ws_event( + uc.WsMsgEvents.ENTITY_CHANGE, data, uc.EventCategory.ENTITY + ) async def _start_web_socket_server(self, host: str, port: int) -> None: async with serve(self._handle_ws, host, port): @@ -158,7 +172,9 @@ async def _handle_ws(self, websocket) -> None: _LOG.info("WS: Client removed") self._events.emit(uc.Events.DISCONNECT) - async def _send_ok_result(self, websocket, req_id: int, msg_data: dict[str, Any] | list | None = None) -> None: + async def _send_ok_result( + self, websocket, req_id: int, msg_data: dict[str, Any] | list | None = None + ) -> None: """ Send a WebSocket success message with status code OK. @@ -169,7 +185,9 @@ async def _send_ok_result(self, websocket, req_id: int, msg_data: dict[str, Any] Raises: websockets.ConnectionClosed: When the connection is closed. """ - await self._send_ws_response(websocket, req_id, "result", msg_data, uc.StatusCodes.OK) + await self._send_ws_response( + websocket, req_id, "result", msg_data, uc.StatusCodes.OK + ) async def _send_error_result( self, @@ -226,7 +244,9 @@ async def _send_ws_response( else: _LOG.error("Error sending response: connection no longer established") - async def _broadcast_ws_event(self, msg: str, msg_data: dict[str, Any], category: uc.EventCategory) -> None: + async def _broadcast_ws_event( + self, msg: str, msg_data: dict[str, Any], category: uc.EventCategory + ) -> None: """ Send the given event-message to all connected WebSocket clients. @@ -247,7 +267,9 @@ async def _broadcast_ws_event(self, msg: str, msg_data: dict[str, Any], category except websockets.exceptions.WebSocketException: pass - async def _send_ws_event(self, websocket, msg: str, msg_data: dict[str, Any], category: uc.EventCategory) -> None: + async def _send_ws_event( + self, websocket, msg: str, msg_data: dict[str, Any], category: uc.EventCategory + ) -> None: """ Send an event-message to the given WebSocket client. @@ -279,13 +301,17 @@ async def _process_ws_message(self, websocket, message) -> None: if kind == "req": if req_id is None: - _LOG.warning("Ignoring request message with missing 'req_id': %s", message) + _LOG.warning( + "Ignoring request message with missing 'req_id': %s", message + ) else: await self._handle_ws_request_msg(websocket, msg, req_id, msg_data) elif kind == "event": await self._handle_ws_event_msg(msg, msg_data) - async def _handle_ws_request_msg(self, websocket, msg: str, req_id: int, msg_data: dict[str, Any] | None) -> None: + async def _handle_ws_request_msg( + self, websocket, msg: str, req_id: int, msg_data: dict[str, Any] | None + ) -> None: if msg == uc.WsMessages.GET_DRIVER_VERSION: await self._send_ws_response( websocket, @@ -325,7 +351,9 @@ async def _handle_ws_request_msg(self, websocket, msg: str, req_id: int, msg_dat await self._unsubscribe_events(msg_data) await self._send_ok_result(websocket, req_id) elif msg == uc.WsMessages.GET_DRIVER_METADATA: - await self._send_ws_response(websocket, req_id, uc.WsMsgEvents.DRIVER_METADATA, self._driver_info) + await self._send_ws_response( + websocket, req_id, uc.WsMsgEvents.DRIVER_METADATA, self._driver_info + ) elif msg == uc.WsMessages.SETUP_DRIVER: if not await self._setup_driver(websocket, req_id, msg_data): # sleep for web-configurator quirks... @@ -336,7 +364,9 @@ async def _handle_ws_request_msg(self, websocket, msg: str, req_id: int, msg_dat await asyncio.sleep(0.5) await self.driver_setup_error(websocket) - async def _handle_ws_event_msg(self, msg: str, msg_data: dict[str, Any] | None) -> None: + async def _handle_ws_event_msg( + self, msg: str, msg_data: dict[str, Any] | None + ) -> None: if msg == uc.WsMsgEvents.CONNECT: self._events.emit(uc.Events.CONNECT) elif msg == uc.WsMsgEvents.DISCONNECT: @@ -347,7 +377,9 @@ async def _handle_ws_event_msg(self, msg: str, msg_data: dict[str, Any] | None) self._events.emit(uc.Events.EXIT_STANDBY) elif msg == uc.WsMsgEvents.ABORT_DRIVER_SETUP: if not self._setup_handler: - _LOG.warning("Received abort_driver_setup event, but no setup handler provided by the driver!") # noqa + _LOG.warning( + "Received abort_driver_setup event, but no setup handler provided by the driver!" + ) # noqa return if "error" in msg_data: @@ -357,7 +389,9 @@ async def _handle_ws_event_msg(self, msg: str, msg_data: dict[str, Any] | None) error = uc.IntegrationSetupError.OTHER await self._setup_handler(uc.AbortDriverSetup(error)) else: - _LOG.warning("Unsupported abort_driver_setup payload received: %s", msg_data) + _LOG.warning( + "Unsupported abort_driver_setup payload received: %s", msg_data + ) async def _authenticate(self, websocket, success: bool) -> None: await self._send_ws_response( @@ -424,17 +458,23 @@ async def _unsubscribe_events(self, msg_data: dict[str, Any] | None) -> bool: return res - async def _entity_command(self, websocket, req_id: int, msg_data: dict[str, Any] | None) -> None: + async def _entity_command( + self, websocket, req_id: int, msg_data: dict[str, Any] | None + ) -> None: if not msg_data: _LOG.warning("Ignoring _entity_command: called with empty msg_data") - await self.acknowledge_command(websocket, req_id, uc.StatusCodes.BAD_REQUEST) + await self.acknowledge_command( + websocket, req_id, uc.StatusCodes.BAD_REQUEST + ) return entity_id = msg_data["entity_id"] if "entity_id" in msg_data else None cmd_id = msg_data["cmd_id"] if "cmd_id" in msg_data else None if entity_id is None or cmd_id is None: _LOG.warning("Ignoring command: missing entity_id or cmd_id") - await self.acknowledge_command(websocket, req_id, uc.StatusCodes.BAD_REQUEST) + await self.acknowledge_command( + websocket, req_id, uc.StatusCodes.BAD_REQUEST + ) return entity = self.configured_entities.get(entity_id) @@ -447,10 +487,14 @@ async def _entity_command(self, websocket, req_id: int, msg_data: dict[str, Any] await self.acknowledge_command(websocket, req_id, uc.StatusCodes.NOT_FOUND) return - result = await entity.command(cmd_id, msg_data["params"] if "params" in msg_data else None) + result = await entity.command( + cmd_id, msg_data["params"] if "params" in msg_data else None + ) await self.acknowledge_command(websocket, req_id, result) - async def _setup_driver(self, websocket, req_id: int, msg_data: dict[str, Any] | None) -> bool: + async def _setup_driver( + self, websocket, req_id: int, msg_data: dict[str, Any] | None + ) -> bool: await self.acknowledge_command(websocket, req_id) if msg_data is None or "setup_data" not in msg_data: @@ -460,18 +504,24 @@ async def _setup_driver(self, websocket, req_id: int, msg_data: dict[str, Any] | # make sure integration driver installed a setup handler if not self._setup_handler: - _LOG.error("Received setup_driver request, but no setup handler provided by the driver!") # noqa + _LOG.error( + "Received setup_driver request, but no setup handler provided by the driver!" + ) # noqa return False result = False try: action = await self._setup_handler( - uc.DriverSetupRequest(msg_data.get("reconfigure") or False, msg_data["setup_data"]) + uc.DriverSetupRequest( + msg_data.get("reconfigure") or False, msg_data["setup_data"] + ) ) if isinstance(action, uc.RequestUserInput): await self.driver_setup_progress(websocket) - await self.request_driver_setup_user_input(websocket, action.title, action.settings) + await self.request_driver_setup_user_input( + websocket, action.title, action.settings + ) result = True elif isinstance(action, uc.RequestUserConfirmation): await self.driver_setup_progress(websocket) @@ -492,11 +542,15 @@ async def _setup_driver(self, websocket, req_id: int, msg_data: dict[str, Any] | return result - async def _set_driver_user_data(self, websocket, req_id: int, msg_data: dict[str, Any] | None) -> bool: + async def _set_driver_user_data( + self, websocket, req_id: int, msg_data: dict[str, Any] | None + ) -> bool: await self.acknowledge_command(websocket, req_id) if not self._setup_handler: - _LOG.error("Received set_driver_user_data request, but no setup handler provided by the driver!") # noqa + _LOG.error( + "Received set_driver_user_data request, but no setup handler provided by the driver!" + ) # noqa return False if "input_values" in msg_data or "confirm" in msg_data: @@ -504,19 +558,27 @@ async def _set_driver_user_data(self, websocket, req_id: int, msg_data: dict[str await asyncio.sleep(0.5) await self.driver_setup_progress(websocket) else: - _LOG.warning("Unsupported set_driver_user_data payload received: %s", msg_data) + _LOG.warning( + "Unsupported set_driver_user_data payload received: %s", msg_data + ) return False result = False try: action = uc.SetupError() if "input_values" in msg_data: - action = await self._setup_handler(uc.UserDataResponse(msg_data["input_values"])) + action = await self._setup_handler( + uc.UserDataResponse(msg_data["input_values"]) + ) elif "confirm" in msg_data: - action = await self._setup_handler(uc.UserConfirmationResponse(msg_data["confirm"])) + action = await self._setup_handler( + uc.UserConfirmationResponse(msg_data["confirm"]) + ) if isinstance(action, uc.RequestUserInput): - await self.request_driver_setup_user_input(websocket, action.title, action.settings) + await self.request_driver_setup_user_input( + websocket, action.title, action.settings + ) result = True elif isinstance(action, uc.RequestUserConfirmation): await self.request_driver_setup_user_confirmation( @@ -562,7 +624,9 @@ async def driver_setup_progress(self, websocket) -> None: """ data = {"event_type": "SETUP", "state": "SETUP"} - await self._send_ws_event(websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE) + await self._send_ws_event( + websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE + ) async def request_driver_setup_user_confirmation( self, @@ -597,7 +661,9 @@ async def request_driver_setup_user_confirmation( }, } - await self._send_ws_event(websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE) + await self._send_ws_event( + websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE + ) async def request_driver_setup_user_input( self, websocket, title: str | dict[str, str], settings: dict[str, Any] | list @@ -606,22 +672,30 @@ async def request_driver_setup_user_input( data = { "event_type": "SETUP", "state": "WAIT_USER_ACTION", - "require_user_action": {"input": {"title": _to_language_object(title), "settings": settings}}, + "require_user_action": { + "input": {"title": _to_language_object(title), "settings": settings} + }, } - await self._send_ws_event(websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE) + await self._send_ws_event( + websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE + ) async def driver_setup_complete(self, websocket) -> None: """Send a driver setup complete event to Remote Two.""" data = {"event_type": "STOP", "state": "OK"} - await self._send_ws_event(websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE) + await self._send_ws_event( + websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE + ) async def driver_setup_error(self, websocket, error="OTHER") -> None: """Send a driver setup error event to Remote Two.""" data = {"event_type": "STOP", "state": "ERROR", "error": error} - await self._send_ws_event(websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE) + await self._send_ws_event( + websocket, uc.WsMsgEvents.DRIVER_SETUP_CHANGE, data, uc.EventCategory.DEVICE + ) def add_listener(self, event: uc.Events, f: Callable) -> None: """ @@ -703,7 +777,9 @@ def _to_language_object(text: str | dict[str, str] | None) -> dict[str, str] | N return text -def _get_default_language_string(text: str | dict[str, str] | None, default_text="Undefined") -> str: +def _get_default_language_string( + text: str | dict[str, str] | None, default_text="Undefined" +) -> str: if text is None: return default_text @@ -763,4 +839,7 @@ def local_hostname() -> str: # local hostname keeps on changing with a increasing number suffix! # https://apple.stackexchange.com/questions/189350/my-macs-hostname-keeps-adding-a-2-to-the-end - return os.getenv("UC_MDNS_LOCAL_HOSTNAME") or f"{socket.gethostname().split('.', 1)[0]}.local." + return ( + os.getenv("UC_MDNS_LOCAL_HOSTNAME") + or f"{socket.gethostname().split('.', 1)[0]}.local." + ) diff --git a/ucapi/api_definitions.py b/ucapi/api_definitions.py index b354772..51ec80c 100644 --- a/ucapi/api_definitions.py +++ b/ucapi/api_definitions.py @@ -193,7 +193,9 @@ class SetupComplete(SetupAction): """Setup action to complete a successful setup process.""" -CommandHandler: TypeAlias = Callable[[Any, str, dict[str, Any] | None], Awaitable[StatusCodes]] +CommandHandler: TypeAlias = Callable[ + [Any, str, dict[str, Any] | None], Awaitable[StatusCodes] +] SetupHandler: TypeAlias = Callable[[SetupDriver], Awaitable[SetupAction]] diff --git a/ucapi/entity.py b/ucapi/entity.py index be30af0..67c9976 100644 --- a/ucapi/entity.py +++ b/ucapi/entity.py @@ -72,7 +72,9 @@ def __init__( _LOG.debug("Created %s entity: %s", self.entity_type.value, self.id) - async def command(self, cmd_id: str, params: dict[str, Any] | None = None) -> StatusCodes: + async def command( + self, cmd_id: str, params: dict[str, Any] | None = None + ) -> StatusCodes: """ Execute entity command with the installed command handler.