API reference

Functions

async picows.ws_connect(ws_listener_factory: ~collections.abc.Callable[[], ~picows.picows.WSListener], url: str, *, ssl_context: ~ssl.SSLContext | None = None, disconnect_on_exception: bool = True, websocket_handshake_timeout=5, logger_name: str = 'client', enable_auto_ping: bool = False, auto_ping_idle_timeout: float = 10.0, auto_ping_reply_timeout: float = 10.0, auto_ping_strategy=<WSAutoPingStrategy.PING_WHEN_IDLE: 1>, enable_auto_pong: bool = True, max_frame_size: int = 10485760, extra_headers: ~collections.abc.Mapping[str, str] | ~collections.abc.Iterable[tuple[str, str]] | None = None, **kwargs) tuple[WSTransport, WSListener]

Open a websocket connection to a given URL.

This function forwards its kwargs directly to asyncio.loop.create_connection

Parameters:
  • ws_listener_factory – A parameterless factory function that returns a user handler. User handler has to derive from WSListener.

  • url – Destination URL

  • ssl_context – optional SSLContext to override default one when wss scheme is used

  • disconnect_on_exception – Indicates whether the client should initiate disconnect on any exception thrown from WSListener.on_ws_frame callbacks

  • websocket_handshake_timeout – is the time in seconds to wait for the websocket client to receive websocket handshake response before aborting the connection.

  • logger_name – picows will use picows.<logger_name> logger to do all the logging.

  • enable_auto_ping

    Enable detection of a stale connection by periodically pinging remote peer.

    Note

    This does NOT enable automatic replies to incoming ping requests. enable_auto_pong argument controls it.

  • auto_ping_idle_timeout

    • when auto_ping_strategy == PING_WHEN_IDLE

      how long to wait before sending ping request when there is no incoming data.

    • when auto_ping_strategy == PING_PERIODICALLY

      how often to send ping

  • auto_ping_reply_timeout – how long to wait for a pong reply before shutting down connection.

  • auto_ping_strategy

    An WSAutoPingStrategy enum value:

    • PING_WHEN_IDLE - ping only if there is no new incoming data.

    • PING_PERIODICALLY - send ping at regular intervals regardless of incoming data.

  • enable_auto_pong – If enabled then picows will automatically reply to incoming PING frames.

  • max_frame_size

    • Maximum allowed frame size. Disconnect will be initiated if client receives a frame that is bigger than max size.

  • extra_headers – Arbitrary HTTP headers to add to the handshake request.

Returns:

WSTransport object and a user handler returned by ws_listener_factory()

async picows.ws_create_server(ws_listener_factory: ~collections.abc.Callable[[~picows.picows.WSUpgradeRequest], ~picows.picows.WSListener | ~picows.picows.WSUpgradeResponseWithListener | None], host=None, port=None, *, disconnect_on_exception: bool = True, websocket_handshake_timeout=5, logger_name: str = 'server', enable_auto_ping: bool = False, auto_ping_idle_timeout: float = 20.0, auto_ping_reply_timeout: float = 20.0, auto_ping_strategy=<WSAutoPingStrategy.PING_WHEN_IDLE: 1>, enable_auto_pong: bool = True, max_frame_size: int = 10485760, **kwargs) Server

Create a websocket server listening on TCP port of the host address. This function forwards its kwargs directly to asyncio.loop.create_server

It has a few extra parameters to control the behaviour of websocket

Parameters:
  • ws_listener_factory

    A factory function that accepts WSUpgradeRequest object and returns one of:

    • User handler object. A standard 101 response will be sent to the client.

    • WSUpgradeResponseWithListener object. This allows to send a custom response with extra headers and an optional body.

    • None. In such case 404 Not Found response will be sent and the client will be disconnected.

    The user handler must derive from WSListener and is responsible for processing incoming data.

    The factory function acts as a router. WSUpgradeRequest contains the requested path and headers. Different user listeners may be returned depending on the path and other conditions.

  • host

    The host parameter can be set to several types which determine where the server would be listening:

    • If host is a string, the TCP server is bound to a single network interface specified by host.

    • If host is a sequence of strings, the TCP server is bound to all network interfaces specified by the sequence.

    • If host is an empty string or None, all interfaces are assumed and a list of multiple sockets will be returned (most likely one for IPv4 and another one for IPv6).

  • port – specify which port the server should listen on. If 0 or None (the default), a random unused port will be selected (note that if host resolves to multiple network interfaces, a different random port will be selected for each interface).

  • disconnect_on_exception – Indicates whether the client should initiate disconnect on any exception thrown by WSListener.on_ws_frame callback

  • websocket_handshake_timeout – is the time in seconds to wait for the websocket server to receive websocket handshake request before aborting the connection.

  • logger_name – picows will use picows.<logger_name> logger to do all the logging.

  • enable_auto_ping

    Enable detection of a stale connection by periodically pinging remote peer.

    Note

    This does NOT enable automatic replies to incoming ping requests. enable_auto_pong argument controls it.

  • auto_ping_idle_timeout

    • when auto_ping_strategy == PING_WHEN_IDLE

      how long to wait before sending ping request when there is no incoming data.

    • when auto_ping_strategy == PING_PERIODICALLY

      how often to send ping

  • auto_ping_reply_timeout – how long to wait for a pong reply before shutting down connection.

  • auto_ping_strategy

    An WSAutoPingStrategy enum value:

    • PING_WHEN_IDLE - ping only if there is no new incoming data.

    • PING_PERIODICALLY - send ping at regular intervals regardless of incoming data.

  • enable_auto_pong – If enabled then picows will automatically reply to incoming PING frames.

  • max_frame_size

    • Maximum allowed frame size. Disconnect will be initiated if server side receives frame that is bigger than max size.

Returns:

asyncio.Server object

Classes

class picows.WSError

Thrown by ws_connect on any kind of handshake errors.

class picows.WSFrame

Received websocket frame.

Danger

Only use WSFrame object during WSListener.on_ws_frame callback. WSFrame objects are essentially just pointers to the underlying receiving buffer. After WSListener.on_ws_frame has completed the buffer will be reused for the new incoming data.

In order to actually copy payload use one of the get_* methods.

msg_type: WSMsgType

Message type

fin: bool

Indicates whether this is the last frame of the message. Websocket messages MAY consist of multiple frames.

Unfragmented message:

WSFrame(msg_type=WSMsgType.<actual message type>, fin=True)

Fragmented message:

WSFrame(msg_type=WSMsgType.<actual message type>, fin=False)
WSFrame(msg_type=WSMsgType.CONTINUATION, fin=False)
...
# the last frame of the message
WSFrame(msg_type=WSMsgType.CONTINUATION, fin=True)
rsv1: bool

Indicates whether rsv1 flag is set in the frame. Some protocol extensions use this flag to indicated that the frame data is compressed. For example in permessage_deflate extension

Note

Currently, picows forbids any protocol extensions during upgrade phase. You may still check that it is set to False to verify behaviour of the remote side.

last_in_buffer: bool

Indicates whether this is the last available frame in the receiving buffer. The receiving buffer may contain more available data, but not the full frame yet.

tail_size: int

Indicates how many bytes are in the receiving buffer after the current frame.

payload_ptr: char*

Available only from Cython.

Raw pointer to the beginning of the frame payload in the receiving buffer.

payload_size: size_t

Available only from Cython.

Size of the payload.

get_close_code()
Returns:

WSCloseCode

This method is only valid for WSMsgType.CLOSE frames.

get_close_message()
Returns:

a new bytes object with a close message. If there is no close message then returns None.

This method is only valid for WSMsgType.CLOSE frames.

get_payload_as_ascii_text()
Returns:

a new str object with a copy of frame payload.

This method will throw if payload does not contain valid ASCII 7 text.

This method does not cache results. Payload is copied and a new str object is created every time this method is called.

get_payload_as_bytes()
Returns:

a new bytes object with a copy of frame payload.

This method does not cache results. Payload is copied and a new bytes object is created every time this method is called.

get_payload_as_memoryview()
Returns:

continous memoryview to a parser buffer with payload.

Danger

Returned memoryview does NOT own the underlying memory. The content will be invalidated after WSListener.on_ws_frame has completed. Please process payload or copy it as soon as possible.

get_payload_as_utf8_text()
Returns:

a new str object with a copy of frame payload.

This method will throw if payload does not contain valid UTF8 text.

This method does not cache results. Payload is copied and a new str object is created every time this method is called.

class picows.WSUpgradeRequest
method: bytes

Request method. b”GET”, b”POST”, etc

path: bytes

Request path. For example b”/ws”

version: bytes

HTTP version. For example b”HTTP/1.1”

headers: CIMultiDict[str, str]

Request headers. Keys are case insensitive

class picows.WSUpgradeResponse
version: bytes

HTTP version. For example b”HTTP/1.1”

status: http.HTTPStatus

HTTP response status enum value. For example: HTTPStatus.SWITCHING_PROTOCOLS

headers: CIMultiDict[str, str]

Response headers. Keys are case insensitive

body: bytes

Optional response body. Can be non-empty in case of errors

static create_101_response(extra_headers: Mapping[str, str] | Iterable[tuple[str, str]] | None = None) WSUpgradeResponse

Create 101 Switching Protocols response.

Parameters:

extra_headers – optional additional headers

Returns:

a new WSUpgradeResponse object

static create_error_response(status: int | HTTPStatus, body=None, extra_headers: Mapping[str, str] | Iterable[tuple[str, str]] | None = None) WSUpgradeResponse

Create upgrade response with error.

Parameters:
  • status – int status code or http.HTTPStatus enum value

  • body – optional bytes-like response body

  • extra_headers – optional additional headers

Returns:

a new WSUpgradeResponse object

class picows.WSUpgradeResponseWithListener
__init__(response: WSUpgradeResponse, listener: WSListener | None)
class picows.WSListener

Base class for user handlers.

All on_ws_* methods receive transport as a first argument for convenience. It is guaranteed that passed transport object is always the same for the same connection.

is_user_specific_pong(frame)

Called before WSListener.on_ws_frame if auto ping is enabled and pong is expected.

User can override this method to indicate that the received frame is a valid response to a previously sent user specific ping message.

The default implementation just do:

def is_user_specific_pong(self, frame: picows.WSFrame)
    return frame.msg_type == WSMsgType.PONG
Returns:

Returns True if the frame is a response to a previously send ping. In such case the frame will be consumed by the protocol, i.e WSListener.on_ws_frame will not be called for this frame.

on_ws_connected(transport)

Called after websocket handshake is complete and websocket is ready to send and receive frames. Initiate disconnect if exception is thrown by user handler.

  • client side: the exception will be transferred to and reraised by wait_disconnected.

  • server side: the exception will be ‘swallowed’ by the library and logged at the ERROR level.

Parameters:

transportWSTransport object

on_ws_disconnected(transport)

Called when websocket has been disconnected.

Parameters:

transportWSTransport

on_ws_frame(transport, frame)

Called when a new frame is received.

Initiate disconnect if exception is thrown by user handler and disconnect_on_exception was set to True in ws_connect or ws_create_server. In such case:

  • client side: the exception will be transferred to and reraised by wait_disconnected.

  • server side: the exception will be ‘swallowed’ by the library and logged at the ERROR level.

Danger

WSFrame is essentially just a pointer to a chunk of memory in the receiving buffer. It does not own the memory. Do NOT cache or store WSFrame object for later processing because the data may be invalidated after WSListener.on_ws_frame is complete. Process the payload immediately or just copy it with one of WSFrame.get_* methods.

Parameters:
pause_writing()

Called when the underlying transport’s buffer goes over the high watermark.

resume_writing()

Called when the underlying transport’s buffer drains below the low watermark.

send_user_specific_ping(transport)

Called when the auto-ping logic wants to send a ping to a remote peer.

User can override this method to send something else instead of the standard PING frame.

Default implementation:

def send_user_specific_ping(self, transport: picows.WSTransport)
    return transport.send_ping()
Parameters:

transportWSTransport

class picows.WSTransport

Note

All send methods never block. The data is buffered and arranged to be sent out asynchronously in case if it can’t be sent immediately. This behaviour is derived from the underlying asyncio.WriteTransport.write

underlying_transport: asyncio.Transport

Underlying TCP or SSL transport. Can be used to set buffer limits, check connection state, etc.

Note

Please don’t use it to send data. Use only WSTransport.send methods to send frames.

request: WSUpgradeRequest

Opening handshake request.

response: WSUpgradeResponse

Opening handshake response.

send_reuse_external_buffer(WSMsgType msg_type, char* msg_ptr, size_t msg_size, bint fin=True, bint rsv1=False)

Available only from Cython.

Send a frame over websocket with a message as its payload. This function does not copy message to prepare websocket frames. It reuses message’s memory and append websocket header at the front.

Attention

Message’s buffer should have at least 14 bytes in front of the message pointer available for writing.

Parameters:
  • msg_type – Message type

  • msg_ptr – Pointer to a message payload

  • msg_size – Size of the message payload

  • fin – fin bit in websocket frame. Indicate that the frame is the last one in the message.

  • rsv1 – first reserved bit in websocket frame. Some protocol extensions use it to indicate that payload is compressed.

disconnect(graceful=True)

Close the underlying transport.

It is safe to call this method multiple times. It does nothing if the transport is already closed.

Parameters:

graceful – If True then send any remaining outgoing data in the buffer before closing the socket. This may potentially significantly delay on_ws_disconnected event since OS may wait for TCP_ACK for the data that was previously sent and until OS ack timeout fires up the socket will remain in connected state.

async measure_roundtrip_time(rounds) list[float]

Coroutine that measures roundtrip time by running ping-pong.

Parameters:

rounds – how many ping-pong rounds to do

Returns:

list of measured roundtrip times

notify_user_specific_pong_received()

Notify the auto-ping loop that a user-specific pong message has been received.

This method is useful when determining whether a frame contains a user-specific pong is too expensive for is_user_specific_pong (for example, it may require full JSON parsing). In such cases, WSListener.is_user_specific_pong should always return False, and the logic in WSListener.on_ws_frame should call WSTransport.notify_user_specific_pong_received.

It is safe to call this method even if auto-ping is disabled or the auto-ping loop doesn’t expect pong messages. In such cases, the method simply does nothing.

send(msg_type, message, fin=True, rsv1=False)

Send a frame over websocket with a message as its payload.

Parameters:
  • msg_typeWSMsgType enum value

  • message – an optional bytes-like object

  • fin – fin bit in websocket frame. Indicate that the frame is the last one in the message.

  • rsv1 – first reserved bit in websocket frame. Some protocol extensions use it to indicate that payload is compressed.

send_close(close_code=<WSCloseCode.NO_INFO: 0>, close_message=None)

Send a CLOSE control frame with an optional message. This method doesn’t disconnect the underlying transport. Does nothing if the underlying transport is already disconnected.

Parameters:
  • close_codeWSCloseCode value

  • close_message – an optional bytes-like object

send_ping(message=None)

Send a PING control frame with an optional message.

Parameters:

message – an optional bytes-like object

send_pong(message=None)

Send a PONG control frame with an optional message.

Parameters:

message – an optional bytes-like object

send_reuse_external_bytearray(msg_type, buffer, msg_offset, fin=True, rsv1=False)

Send a frame over websocket with a message as its payload. This function does not copy message to prepare websocket frames. It reuses bytearray’s memory to append websocket frame header at the front.

Parameters:
  • msg_typeWSMsgType enum value

  • msg_offset – specifies where message begins in the bytearray. Must be at least 14 to let picows to insert websocket frame header in front of the message.

  • buffer – bytearray that contains message and some extra space (at least 14 bytes) in the beginning. The len of the message is determined as len(buffer) - msg_offset

  • fin – fin bit in websocket frame. Indicate that the frame is the last one in the message.

  • rsv1 – first reserved bit in websocket frame. Some protocol extensions use it to indicate that payload is compressed.

async wait_disconnected()

Coroutine that conveniently allows to wait until websocket is completely disconnected. (underlying transport is closed, on_ws_disconnected has been called)

Enums

enum picows.WSMsgType(value)
Member Type:

int

Valid values are as follows:

CONTINUATION = <WSMsgType.CONTINUATION: 0>
TEXT = <WSMsgType.TEXT: 1>
BINARY = <WSMsgType.BINARY: 2>
PING = <WSMsgType.PING: 9>
PONG = <WSMsgType.PONG: 10>
CLOSE = <WSMsgType.CLOSE: 8>
enum picows.WSCloseCode(value)
Member Type:

int

Valid values are as follows:

NO_INFO = <WSCloseCode.NO_INFO: 0>
OK = <WSCloseCode.OK: 1000>
GOING_AWAY = <WSCloseCode.GOING_AWAY: 1001>
PROTOCOL_ERROR = <WSCloseCode.PROTOCOL_ERROR: 1002>
UNSUPPORTED_DATA = <WSCloseCode.UNSUPPORTED_DATA: 1003>
ABNORMAL_CLOSURE = <WSCloseCode.ABNORMAL_CLOSURE: 1006>
INVALID_TEXT = <WSCloseCode.INVALID_TEXT: 1007>
POLICY_VIOLATION = <WSCloseCode.POLICY_VIOLATION: 1008>
MESSAGE_TOO_BIG = <WSCloseCode.MESSAGE_TOO_BIG: 1009>
MANDATORY_EXTENSION = <WSCloseCode.MANDATORY_EXTENSION: 1010>
INTERNAL_ERROR = <WSCloseCode.INTERNAL_ERROR: 1011>
SERVICE_RESTART = <WSCloseCode.SERVICE_RESTART: 1012>
TRY_AGAIN_LATER = <WSCloseCode.TRY_AGAIN_LATER: 1013>
BAD_GATEWAY = <WSCloseCode.BAD_GATEWAY: 1014>
enum picows.WSAutoPingStrategy(value)
Member Type:

int

Valid values are as follows:

PING_WHEN_IDLE = <WSAutoPingStrategy.PING_WHEN_IDLE: 1>
PING_PERIODICALLY = <WSAutoPingStrategy.PING_PERIODICALLY: 2>