Sayd#
A performant asynchronous communication protocol in pure Python.
This library was developed with simplicity and performance in mind, with modern practices of Python development, currently in a test state.
Install#
Works on Python 3.7.4+.
pip install sayd
Development#
You need to have installed poetry for dependencies management (how to).
git clone https://github.com/lw016/sayd
cd sayd
poetry install
Run tests#
poetry run tox -e tests
Build docs#
poetry run tox -e docs
Features#
Client and server implementations
Reliable TCP persistent connection
Auto reconnection (client)
Multiple asynchronous connections (server)
Blacklist of clients (server)
TLS encryption
Proxy Protocol V2 support (server)
Data transmitted as dictionaries (json)
Broadcast (server)
Remote function callbacks
Built-in CLI utility to generate self-signed certificates
Roadmap#
Add support to Unix socket
Implement TLS certificate authentication
CLI#
The built-in CLI utility (sayd) can be used to generate self-signed certificates to encrypt the connection.
sayd --help
Usage example#
Server#
import logging
import asyncio
from sayd import SaydServer
logging.basicConfig(
format="[%(name)s][%(levelname)s] %(asctime)s - %(message)s",
datefmt="%Y/%m/%d %H:%M:%S"
)
logger = logging.getLogger("SERVER")
logger.setLevel(logging.INFO)
server = SaydServer(logger=logger)
@server.callback("message")
async def msg(address: tuple, instance: str, data: dict) -> dict:
return {"greetings": "Hello from server!"}
async def main() -> None:
await server.start()
while True:
result = await server.call("msg", {"greetings": "Hi!"}) # Broadcast call.
print(result)
await asyncio.sleep(1)
await server.stop()
if __name__ == "__main__":
asyncio.run(main())
Client#
import logging
import asyncio
from sayd import SaydClient
logging.basicConfig(
format="[%(name)s][%(levelname)s] %(asctime)s - %(message)s",
datefmt="%Y/%m/%d %H:%M:%S"
)
logger = logging.getLogger("CLIENT")
logger.setLevel(logging.INFO)
client = SaydClient(logger=logger)
@client.callback("msg")
async def msg(instance: str, data: dict) -> dict:
return {"greetings": "Hello from client!"}
async def main() -> None:
await client.start()
while True:
result = await client.call("message", {"greetings": "Hi!"})
print(result)
await asyncio.sleep(1)
await client.stop()
if __name__ == "__main__":
asyncio.run(main())