pysignalr
pysignalr is a modern, reliable, and async-ready client for the SignalR protocol. This project started as an asyncio fork of mandrewcito's signalrcore library and ended up as a complete rewrite.
Table of Contents
Installation
To install pysignalr, simply use pip:
pip install pysignalr
Basic Usage
Let's connect to TzKT, an API and block explorer of Tezos blockchain, and subscribe to all operations:
from __future__ import annotations
import asyncio
from contextlib import suppress
from typing import TYPE_CHECKING
from typing import Any
from pysignalr.client import SignalRClient
if TYPE_CHECKING:
from pysignalr.messages import CompletionMessage
async def on_open() -> None:
print('Connected to the server')
async def on_close() -> None:
print('Disconnected from the server')
async def on_message(message: list[dict[str, Any]]) -> None:
print(f'Received message: {message}')
async def on_client_result(message: list[dict[str, Any]]) -> str:
"""The server can request a result from a client.
Requires the server to use ISingleClientProxy.InvokeAsync and the client
to return a result from its .On handler.
See: https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-9.0#client-results
"""
print(f'Received message: {message}')
return 'reply'
async def on_error(message: CompletionMessage) -> None:
print(f'Received error: {message.error}')
async def main() -> None:
client = SignalRClient('https://api.tzkt.io/v1/ws')
client.on_open(on_open)
client.on_close(on_close)
client.on_error(on_error)
client.on('operations', on_message)
client.on('client_result', on_client_result)
await asyncio.gather(
client.run(),
client.send('SubscribeToOperations', [{}]),
)
with suppress(KeyboardInterrupt, asyncio.CancelledError):
asyncio.run(main())
Usage with Token Authentication
To connect to the SignalR server using token authentication:
from __future__ import annotations
import asyncio
from contextlib import suppress
from typing import TYPE_CHECKING
from typing import Any
from pysignalr.client import SignalRClient
if TYPE_CHECKING:
from pysignalr.messages import CompletionMessage
async def on_open() -> None:
print('Connected to the server')
async def on_close() -> None:
print('Disconnected from the server')
async def on_message(message: list[dict[str, Any]]) -> None:
print(f'Received message: {message}')
async def on_client_result(message: list[dict[str, Any]]) -> str:
"""The server can request a result from a client.
Requires the server to use ISingleClientProxy.InvokeAsync and the client
to return a result from its .On handler.
See: https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-9.0#client-results
"""
print(f'Received message: {message}')
return 'reply'
async def on_error(message: CompletionMessage) -> None:
print(f'Received error: {message.error}')
def token_factory() -> str:
# Replace with logic to fetch or generate the token
return 'your_access_token_here'
async def main() -> None:
client = SignalRClient(
url='https://api.tzkt.io/v1/ws',
access_token_factory=token_factory,
headers={'mycustomheader': 'mycustomheadervalue'},
)
client.on_open(on_open)
client.on_close(on_close)
client.on_error(on_error)
client.on('operations', on_message)
client.on('client_result', on_client_result)
await asyncio.gather(
client.run(),
client.send('SubscribeToOperations', [{}]),
)
with suppress(KeyboardInterrupt, asyncio.CancelledError):
asyncio.run(main())
API Reference
SignalRClient
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
url |
str |
required | The SignalR server URL |
protocol |
Protocol | None |
JSONProtocol() |
Protocol for message encoding/decoding |
headers |
dict[str, str] | None |
None |
Additional headers for the WebSocket handshake |
ping_interval |
int |
10 |
Keepalive ping interval in seconds |
connection_timeout |
int |
10 |
Connection timeout in seconds |
max_size |
int | None |
1048576 |
Maximum WebSocket message size (1 MB) |
retry_sleep |
float |
1 |
Initial retry delay in seconds |
retry_multiplier |
float |
1.1 |
Exponential backoff multiplier |
retry_count |
int |
10 |
Maximum number of retries |
access_token_factory |
Callable[[], str] | None |
None |
Function that returns an access token |
ssl |
ssl.SSLContext | None |
None |
Custom SSL context |
Methods
run(): Run the client, managing the connection lifecycle.on(event, callback): Register a callback for a specific event. If the callback returns a value, it is sent back as aCompletionMessage(client results).on_open(callback): Register a callback for connection open events.on_close(callback): Register a callback for connection close events.on_error(callback): Register a callback for error events.send(method, arguments, on_invocation=None): Send a message to the server. Withouton_invocation, sends a non-blocking (fire-and-forget) invocation. With a callback, tracks the invocation and routes the server's completion response to it.stream(event, event_params, on_next=None, on_complete=None, on_error=None): Start a server-to-client streaming invocation.client_stream(target): Async context manager for client-to-server streaming. Useawait stream.send(item)inside the context.
CompletionMessage
A message received from the server upon completion of a method invocation.
Attributes
invocation_id(str | None): The ID of the invocation.result(Any | None): The result of the invocation, if any.error(str | None): The error message, if the invocation failed.
Contributors
- Lev Gorodetskii
- Ola Lidholm
- ciaranby
- MichaelMKKelly
- Wizard1209
- Antonino Bonanno
- Caio Barbieri
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for pysignalr 1.3.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pysignalr-1.3.3.tar.gz | 239.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pysignalr-1.3.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 262.0 kB
Release files / pysignalr-1.3.3.tar.gz
| Download URL | pysignalr-1.3.3.tar.gz |
|---|---|
| Size | 239.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5bb0676f087a06e0ae8177b5791bf060f0f6546658707bb7de290c92da3052b
|
|
BLAKE2b-256 checksum How to use checksums |
6190991c2069ea98b6328a87a2380dea6c957cbe81b7954eddbcbf0bff5d62d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pysignalr-1.3.3-py3-none-any.whl
| Download URL | pysignalr-1.3.3-py3-none-any.whl |
|---|---|
| Size | 23.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5012af69a812eb0b8d725b1b8ca075ec1cc8633706da4239012ab7a76b83b23b
|
|
BLAKE2b-256 checksum How to use checksums |
59eadc88c56f80c0dfc3649948b1a768592a6e61b27623e88cce655da4ffc609
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for pysignalr 1.3.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.