Metadata-Version: 2.1
Name: sayd
Version: 1.2.4
Summary: A performant asynchronous communication protocol in pure Python.
Home-page: https://github.com/lw016/sayd
License: Apache-2.0
Keywords: network,protocol,communication
Author: LW016
Requires-Python: >=3.7.4,<4.0.0
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: Android
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Unix
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries
Requires-Dist: pyOpenSSL (>=22.0.0)
Requires-Dist: rich (>=12.5.1)
Requires-Dist: typer (>=0.4.1)
Requires-Dist: ujson (>=5.4.0)
Requires-Dist: uvloop (>=0.16.0); sys_platform != "win32"
Project-URL: Repository, https://github.com/lw016/sayd
Description-Content-Type: text/x-rst

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.

`Documentation Reference <https://sayd.readthedocs.io>`_


Install
-------
Works on Python 3.7.4+.

.. code-block:: bash

    pip install sayd


Development
-----------
You need to have installed `poetry <https://github.com/python-poetry/poetry>`_ for dependencies management (`how to <https://python-poetry.org/docs/#installation>`_).

.. code-block:: bash

    git clone https://github.com/lw016/sayd
    cd sayd
    poetry install


Run tests
^^^^^^^^^
.. code-block:: bash

    poetry run tox -e tests

Build docs
^^^^^^^^^^
.. code-block:: bash

    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.

.. code-block:: bash

    sayd --help


Usage example
-------------
Server
^^^^^^
.. code-block:: python

    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
^^^^^^
.. code-block:: python

    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())

