CI / Build Pip package (push) Successful in 4m55s
Granian's RSGI transport raises RSGIProtocolClosed when the peer is gone without a close handshake, which escaped receive() and was logged as an application error, and sends to the dead transport raised the raw Granian exception as well. Treat a closed RSGI transport like the ASGI websocket.disconnect message: receive() reports a close message so async-for loops end normally, while writes (accept/send/close) raise a new kaya.core.WebSocketDisconnect carrying close code 1006. KayaApp.handle_websocket swallows that exception as normal termination, so after hooks still run and disconnects are no longer reported as errors. The ASGI adapter maps its server's OSError disconnect (e.g. uvicorn's ClientDisconnected) to the same exception for consistent semantics across backends.
kaya-core
Core package of the Kaya web framework.
Provides method-aware routing, path matching, HTTP/WebSocket abstractions, and an ASGI adapter.