-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d5ed719
commit f31375c
Showing
232 changed files
with
12,141 additions
and
2,304 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,6 @@ exclude_dirs: ['tests'] | |
skips: [ | ||
'B403', # Imports of "pickle" | ||
] | ||
|
||
assert_used: | ||
skips: ['docs/**/*.py'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,5 @@ values = | |
first_value = 1 | ||
|
||
[bumpversion:file:src/easynetwork/__init__.py] | ||
|
||
[bumpversion:file:docs/source/conf.py] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,175 @@ | ||
# EasyNetwork | ||
The easiest way to use sockets in Python | ||
|
||
The easiest way to use sockets in Python! | ||
|
||
[![PyPI](https://img.shields.io/pypi/v/easynetwork)](https://pypi.org/project/easynetwork/) | ||
[![PyPI - License](https://img.shields.io/pypi/l/easynetwork)](https://github.com/francis-clairicia/EasyNetwork/blob/main/LICENSE) | ||
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/easynetwork) | ||
|
||
[![Test](https://github.com/francis-clairicia/EasyNetwork/actions/workflows/test.yml/badge.svg)](https://github.com/francis-clairicia/EasyNetwork/actions/workflows/test.yml) | ||
[![Codecov](https://img.shields.io/codecov/c/github/francis-clairicia/EasyNetwork)](https://codecov.io/gh/francis-clairicia/EasyNetwork) | ||
[![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/francis-clairicia/EasyNetwork)](https://www.codefactor.io/repository/github/francis-clairicia/easynetwork) | ||
|
||
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) | ||
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/francis-clairicia/EasyNetwork/main.svg)](https://results.pre-commit.ci/latest/github/francis-clairicia/EasyNetwork/main) | ||
|
||
[![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/) | ||
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) | ||
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/) | ||
[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) | ||
|
||
[![Hatch project](https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg)](https://github.com/pypa/hatch) | ||
[![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm.fming.dev) | ||
|
||
## Installation | ||
### From PyPI repository | ||
```sh | ||
pip install --user easynetwork | ||
``` | ||
|
||
### From source | ||
```sh | ||
git clone https://github.com/francis-clairicia/EasyNetwork.git | ||
cd EasyNetwork | ||
pip install --user . | ||
``` | ||
|
||
## Overview | ||
EasyNetwork completely encapsulates the socket handling, providing you with a higher level interface | ||
that allows an application/software to completely handle the logic part with Python objects, | ||
without worrying about how to process, send or receive data over the network. | ||
|
||
The communication protocol can be whatever you want, be it JSON, Pickle, ASCII, structure, base64 encoded, | ||
compressed, encrypted, or any other format that is not part of the standard library. | ||
You choose the data format and the library takes care of the rest. | ||
|
||
Works with TCP and UDP. | ||
|
||
### Documentation | ||
Coming soon. | ||
|
||
## Usage | ||
### TCP Echo server with JSON data | ||
```py | ||
import logging | ||
from collections.abc import AsyncGenerator | ||
from typing import Any, TypeAlias | ||
|
||
from easynetwork.api_async.server import AsyncStreamClient, AsyncStreamRequestHandler | ||
from easynetwork.api_sync.server import StandaloneTCPNetworkServer | ||
from easynetwork.exceptions import StreamProtocolParseError | ||
from easynetwork.protocol import StreamProtocol | ||
from easynetwork.serializers import JSONSerializer | ||
|
||
# These TypeAliases are there to help you understand | ||
# where requests and responses are used in the code | ||
RequestType: TypeAlias = Any | ||
ResponseType: TypeAlias = Any | ||
|
||
|
||
class JSONProtocol(StreamProtocol[ResponseType, RequestType]): | ||
def __init__(self) -> None: | ||
super().__init__(JSONSerializer()) | ||
|
||
|
||
class EchoRequestHandler(AsyncStreamRequestHandler[RequestType, ResponseType]): | ||
def __init__(self) -> None: | ||
self.logger: logging.Logger = logging.getLogger(self.__class__.__name__) | ||
|
||
async def handle( | ||
self, | ||
client: AsyncStreamClient[ResponseType], | ||
) -> AsyncGenerator[None, RequestType]: | ||
try: | ||
request: RequestType = yield # A JSON request has been sent by this client | ||
except StreamProtocolParseError: | ||
# Invalid JSON data sent | ||
# This is an example of how you can answer to an invalid request | ||
await client.send_packet({"error": "Invalid JSON", "code": "parse_error"}) | ||
return | ||
|
||
self.logger.info(f"{client.address} sent {request!r}") | ||
|
||
# As a good echo handler, the request is sent back to the client | ||
response: ResponseType = request | ||
await client.send_packet(response) | ||
|
||
# Leaving the generator will NOT close the connection, | ||
# a new generator will be created afterwards. | ||
# You may manually close the connection if you want to: | ||
# await client.aclose() | ||
|
||
|
||
def main() -> None: | ||
host = None # Bind on all interfaces | ||
port = 9000 | ||
|
||
logging.basicConfig(level=logging.INFO, format="[ %(levelname)s ] [ %(name)s ] %(message)s") | ||
with StandaloneTCPNetworkServer(host, port, JSONProtocol(), EchoRequestHandler()) as server: | ||
try: | ||
server.serve_forever() | ||
except KeyboardInterrupt: | ||
pass | ||
|
||
|
||
if __name__ == "__main__": | ||
main() | ||
``` | ||
|
||
### TCP Echo client with JSON data | ||
```py | ||
from typing import Any | ||
|
||
from easynetwork.api_sync.client import TCPNetworkClient | ||
from easynetwork.protocol import StreamProtocol | ||
from easynetwork.serializers import JSONSerializer | ||
|
||
|
||
class JSONProtocol(StreamProtocol[Any, Any]): | ||
def __init__(self) -> None: | ||
super().__init__(JSONSerializer()) | ||
|
||
|
||
def main() -> None: | ||
with TCPNetworkClient(("localhost", 9000), JSONProtocol()) as client: | ||
client.send_packet({"data": {"my_body": ["as json"]}}) | ||
response = client.recv_packet() # response should be the sent dictionary | ||
print(response) # prints {'data': {'my_body': ['as json']}} | ||
|
||
|
||
if __name__ == "__main__": | ||
main() | ||
``` | ||
|
||
<details markdown="1"> | ||
<summary>Asynchronous version ( with <code>async def</code> )</summary> | ||
|
||
```py | ||
import asyncio | ||
from typing import Any | ||
|
||
from easynetwork.api_async.client import AsyncTCPNetworkClient | ||
from easynetwork.protocol import StreamProtocol | ||
from easynetwork.serializers import JSONSerializer | ||
|
||
|
||
class JSONProtocol(StreamProtocol[Any, Any]): | ||
def __init__(self) -> None: | ||
super().__init__(JSONSerializer()) | ||
|
||
|
||
async def main() -> None: | ||
async with AsyncTCPNetworkClient(("localhost", 9000), JSONProtocol()) as client: | ||
await client.send_packet({"data": {"my_body": ["as json"]}}) | ||
response = await client.recv_packet() # response should be the sent dictionary | ||
print(response) # prints {'data': {'my_body': ['as json']}} | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) | ||
``` | ||
|
||
</details> | ||
|
||
## License | ||
This project is licensed under the terms of the [Apache Software License 2.0](https://github.com/francis-clairicia/EasyNetwork/blob/main/LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Intersphinx inventory dump. | ||
*-inv.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Minimal makefile for Sphinx documentation | ||
# | ||
|
||
# You can set these variables from the command line, and also | ||
# from the environment for the first two. | ||
SPHINXOPTS ?= | ||
SPHINXBUILD ?= sphinx-build | ||
SOURCEDIR = source | ||
BUILDDIR = build | ||
|
||
# Put it first so that "make" without argument is like "make help". | ||
help: | ||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) | ||
|
||
.PHONY: help Makefile | ||
|
||
# Catch-all target: route all unknown targets to Sphinx using the new | ||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). | ||
%: Makefile | ||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
@ECHO OFF | ||
|
||
pushd %~dp0 | ||
|
||
REM Command file for Sphinx documentation | ||
|
||
if "%SPHINXBUILD%" == "" ( | ||
set SPHINXBUILD=sphinx-build | ||
) | ||
set SOURCEDIR=source | ||
set BUILDDIR=build | ||
|
||
%SPHINXBUILD% >NUL 2>NUL | ||
if errorlevel 9009 ( | ||
echo. | ||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx | ||
echo.installed, then set the SPHINXBUILD environment variable to point | ||
echo.to the full path of the 'sphinx-build' executable. Alternatively you | ||
echo.may add the Sphinx directory to PATH. | ||
echo. | ||
echo.If you don't have Sphinx installed, grab it from | ||
echo.https://www.sphinx-doc.org/ | ||
exit /b 1 | ||
) | ||
|
||
if "%1" == "" goto help | ||
|
||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% | ||
goto end | ||
|
||
:help | ||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% | ||
|
||
:end | ||
popd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING, Any | ||
|
||
if TYPE_CHECKING: | ||
from sphinx.application import Sphinx | ||
|
||
from easynetwork.api_sync.server import AbstractNetworkServer | ||
from easynetwork.api_sync.server._base import BaseStandaloneNetworkServerImpl | ||
|
||
|
||
def _replace_base_in_place(klass: type, bases: list[type], base_to_replace: type, base_to_set_instead: type) -> None: | ||
if issubclass(klass, base_to_replace): | ||
for index, base in enumerate(bases): | ||
if base is base_to_replace: | ||
bases[index] = base_to_set_instead | ||
|
||
|
||
def autodoc_process_bases(app: Sphinx, name: str, obj: type, options: dict[str, Any], bases: list[type]) -> None: | ||
_replace_base_in_place(obj, bases, BaseStandaloneNetworkServerImpl, AbstractNetworkServer) | ||
|
||
|
||
def setup(app: Sphinx) -> dict[str, Any]: | ||
app.setup_extension("sphinx.ext.autodoc") | ||
app.connect("autodoc-process-bases", autodoc_process_bases) | ||
|
||
return { | ||
"version": "0.1", | ||
"parallel_read_safe": True, | ||
"parallel_write_safe": True, | ||
} |
Empty file.
Empty file.
11 changes: 11 additions & 0 deletions
11
docs/source/_include/examples/howto/protocols/basics/datagram_protocol_instance.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Any, TypeAlias | ||
|
||
from easynetwork.protocol import DatagramProtocol | ||
from easynetwork.serializers import JSONSerializer | ||
|
||
SentPacket: TypeAlias = Any | ||
ReceivedPacket: TypeAlias = Any | ||
|
||
json_protocol: DatagramProtocol[SentPacket, ReceivedPacket] = DatagramProtocol(JSONSerializer()) |
Oops, something went wrong.