Loading README.md +2 −2 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ is raised during the processing of the data. If this command is not defined the The client can be used to exchange data with the server. ```py def start_cb(args : list): def start_cb(args : dict): print(args) if __name__ == "__main__": Loading @@ -101,7 +101,7 @@ client.send_command(cmd_name: str, args: list[svpBaseType], function = None) The function take the command name as a string, a list containing the arguments as RsvpBaseType and an optional callback function that will be called when the server answer. If the callback is not defined the function will return received data as a list. function will return received data as a dict. ### RsvpType classes Loading examples/tcpclient.py +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ from pyrsvp.rsvpclient import RsvpClientTcp, RsvpClientNotAck from pyrsvp.rsvptypes import * def start_cb(args : list): def start_cb(args : dict): print(args) if __name__ == "__main__": Loading poetry.lock +202 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,51 @@ category = "dev" optional = false python-versions = "*" [[package]] name = "astroid" version = "3.0.2" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.8.0" [package.dependencies] typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "black" version = "23.12.1" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.8" [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "click" version = "8.1.7" description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" version = "0.4.6" Loading @@ -14,6 +59,17 @@ category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "dill" version = "0.3.7" description = "serialize all of Python" category = "dev" optional = false python-versions = ">=3.7" [package.extras] graph = ["objgraph (>=1.7.2)"] [[package]] name = "exceptiongroup" version = "1.2.0" Loading @@ -33,6 +89,17 @@ category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "isort" version = "5.13.2" description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.8.0" [package.extras] colors = ["colorama (>=0.4.6)"] [[package]] name = "macholib" version = "1.16.3" Loading @@ -44,6 +111,22 @@ python-versions = "*" [package.dependencies] altgraph = ">=0.17" [[package]] name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = ">=3.6" [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false python-versions = ">=3.5" [[package]] name = "packaging" version = "23.2" Loading @@ -52,6 +135,14 @@ category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "pathspec" version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.8" [[package]] name = "pefile" version = "2023.2.7" Loading @@ -60,6 +151,18 @@ category = "dev" optional = false python-versions = ">=3.6.0" [[package]] name = "platformdirs" version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.8" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" version = "1.3.0" Loading Loading @@ -105,6 +208,32 @@ python-versions = ">=3.7" packaging = ">=22.0" setuptools = ">=42.0.0" [[package]] name = "pylint" version = "3.0.3" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.8.0" [package.dependencies] astroid = ">=3.0.1,<=3.1.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, ] isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] [[package]] name = "pyserial" version = "3.5" Loading Loading @@ -164,6 +293,14 @@ category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "tomlkit" version = "0.12.3" description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "typeguard" version = "4.1.5" Loading @@ -190,17 +327,53 @@ python-versions = ">=3.8" [metadata] lock-version = "1.1" python-versions = ">=3.10,<3.13" content-hash = "eb5574af099481673174dc0ff232f98027db90bc29bb3e7642fe52da84696f04" content-hash = "8a349c65a85dc3f6cbf92263ad83ae4dfaceac8ac07680bc6d6016face7c8f80" [metadata.files] altgraph = [ {file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"}, {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, ] astroid = [ {file = "astroid-3.0.2-py3-none-any.whl", hash = "sha256:d6e62862355f60e716164082d6b4b041d38e2a8cf1c7cd953ded5108bac8ff5c"}, {file = "astroid-3.0.2.tar.gz", hash = "sha256:4a61cf0a59097c7bb52689b0fd63717cd2a8a14dc9f1eee97b82d814881c8c91"}, ] black = [ {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] click = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] colorama = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] dill = [ {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] exceptiongroup = [ {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, Loading @@ -209,18 +382,38 @@ iniconfig = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] isort = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] macholib = [ {file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"}, {file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"}, ] mccabe = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] mypy-extensions = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] packaging = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] pathspec = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] pefile = [ {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, ] platformdirs = [ {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] pluggy = [ {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, Loading @@ -243,6 +436,10 @@ pyinstaller-hooks-contrib = [ {file = "pyinstaller-hooks-contrib-2023.12.tar.gz", hash = "sha256:11a9d59d903723dd693e8c10b054f3ea1ecad390623c9fa527c731d715fc5b3f"}, {file = "pyinstaller_hooks_contrib-2023.12-py2.py3-none-any.whl", hash = "sha256:6a601a0d783fa725327fc6ac712779475dc8979f639419c7fcd460dd8d0a6d2a"}, ] pylint = [ {file = "pylint-3.0.3-py3-none-any.whl", hash = "sha256:7a1585285aefc5165db81083c3e06363a27448f6b467b3b0f30dbd0ac1f73810"}, {file = "pylint-3.0.3.tar.gz", hash = "sha256:58c2398b0301e049609a8429789ec6edf3aabe9b6c5fec916acd18639c16de8b"}, ] pyserial = [ {file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"}, {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, Loading @@ -263,6 +460,10 @@ tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [ {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, ] typeguard = [ {file = "typeguard-4.1.5-py3-none-any.whl", hash = "sha256:8923e55f8873caec136c892c3bed1f676eae7be57cdb94819281b3d3bc9c0953"}, {file = "typeguard-4.1.5.tar.gz", hash = "sha256:ea0a113bbc111bcffc90789ebb215625c963411f7096a7e9062d4e4630c155fd"}, Loading pyproject.toml +6 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,12 @@ pytest = "^7.4.4" [tool.poetry.group.dev.dependencies] pyinstaller = "^6.3.0" [tool.poetry.group.lint.dependencies] pylint = "^3.0.3" black = "^23.12.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" pyrsvp/rsvpclient.py +51 −36 Original line number Diff line number Diff line Loading @@ -3,24 +3,28 @@ This file contains the client definition """ import socket from pyrsvp.rsvptypes import RsvpBaseType, process_data_types from typeguard import typechecked from pyrsvp.rsvptypes import RsvpBaseType, process_data_types class RsvpClientConnectionFailed(Exception): pass """Exception for client connection""" class RsvpClientNotAck(Exception): pass """Exception when server doesn't acknowledge""" class RsvpTimeoutExpired(Exception): pass """Received or send timeout""" class RsvpClientInvalidCallback(Exception): pass """Invalid callback function""" class RsvpClient: """Base RsvpClient class """ """Base RsvpClient class""" def __init__(self): pass Loading Loading @@ -61,6 +65,7 @@ class RsvpClient: Raises ------ RsvpClientNotAck: If something is wrong RsvpWrongTypeException: If it fails to parse the args """ tokens = resp.split(";") Loading @@ -73,21 +78,30 @@ class RsvpClient: # You expect to have a REPLY-{cmd_name} if cmd_name in cmd: if status == "NACK": match status: case "NACK": _, err_str = tokens[1].split("=") raise RsvpClientNotAck(err_str) elif status == "ACK": case "ACK": tokens = tokens[1:] return process_data_types(tokens) case _: raise RsvpClientNotAck(f"Unknown reply {cmd_name}={status}") else: raise RsvpClientNotAck(f"Command {cmd_name} not included in reply: {cmd}. Server reply is malformed") raise RsvpClientNotAck( f"Command {cmd_name} not included in reply: {cmd}. Server reply is malformed" ) class RsvpClientTcp(RsvpClient): """RsvpClient using TCP as transport layer """ def __init__(self, srv_ip_address : str = "localhost", srv_port : int = 8080, timeout : float = 5.0): class RsvpClientTcp(RsvpClient): """RsvpClient using TCP as transport layer""" def __init__( self, srv_ip_address: str = "localhost", srv_port: int = 8080, timeout: float = 5.0, ): """RsvpClientTcp constructor Params Loading @@ -105,26 +119,27 @@ class RsvpClientTcp(RsvpClient): self._timeout = timeout def __connect(self): """Connect to the server """ """Connect to the server""" try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except Exception as ex: raise RsvpClientConnectionFailed(f"Failed to create socket: {ex}") raise RsvpClientConnectionFailed(f"Failed to create socket: {ex}") from ex try: self.sock.settimeout(self._timeout) except Exception as ex: raise RsvpClientConnectionFailed(f"Failed to set timeout: {ex}") raise RsvpClientConnectionFailed(f"Failed to set timeout: {ex}") from ex try: self.sock.connect((self._srv_ip, self._port)) except Exception as ex: raise RsvpClientConnectionFailed(f"Failed to connect: {ex}") raise RsvpClientConnectionFailed(f"Failed to connect: {ex}") from ex @typechecked def send_command(self, cmd_name : str, args : list[RsvpBaseType] = None, callback = None) -> list: def send_command( self, cmd_name: str, args: list[RsvpBaseType] = None, callback=None ) -> list: """Send a command to the RSVP server and wait for a reply. Params Loading Loading @@ -155,12 +170,12 @@ class RsvpClientTcp(RsvpClient): try: self.sock.sendall(cmd.encode()) except socket.timeout as ex: raise RsvpTimeoutExpired(f"Failed to send data: {ex}") raise RsvpTimeoutExpired(f"Failed to send data: {ex}") from ex try: buf = self.sock.recv(1024).strip() except socket.timeout as ex: raise RsvpTimeoutExpired(f"Failed to receive data: {ex}") raise RsvpTimeoutExpired(f"Failed to receive data: {ex}") from ex # Process the response data = self.check_response(cmd_name, buf.decode()) Loading @@ -169,8 +184,8 @@ class RsvpClientTcp(RsvpClient): if callback: try: callback(data) return None except Exception as ex: raise RsvpClientInvalidCallback(ex) raise RsvpClientInvalidCallback(ex) from ex else: return data Loading
README.md +2 −2 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ is raised during the processing of the data. If this command is not defined the The client can be used to exchange data with the server. ```py def start_cb(args : list): def start_cb(args : dict): print(args) if __name__ == "__main__": Loading @@ -101,7 +101,7 @@ client.send_command(cmd_name: str, args: list[svpBaseType], function = None) The function take the command name as a string, a list containing the arguments as RsvpBaseType and an optional callback function that will be called when the server answer. If the callback is not defined the function will return received data as a list. function will return received data as a dict. ### RsvpType classes Loading
examples/tcpclient.py +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ from pyrsvp.rsvpclient import RsvpClientTcp, RsvpClientNotAck from pyrsvp.rsvptypes import * def start_cb(args : list): def start_cb(args : dict): print(args) if __name__ == "__main__": Loading
poetry.lock +202 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,51 @@ category = "dev" optional = false python-versions = "*" [[package]] name = "astroid" version = "3.0.2" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.8.0" [package.dependencies] typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} [[package]] name = "black" version = "23.12.1" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.8" [package.dependencies] click = ">=8.0.0" mypy-extensions = ">=0.4.3" packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "click" version = "8.1.7" description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" version = "0.4.6" Loading @@ -14,6 +59,17 @@ category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "dill" version = "0.3.7" description = "serialize all of Python" category = "dev" optional = false python-versions = ">=3.7" [package.extras] graph = ["objgraph (>=1.7.2)"] [[package]] name = "exceptiongroup" version = "1.2.0" Loading @@ -33,6 +89,17 @@ category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "isort" version = "5.13.2" description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.8.0" [package.extras] colors = ["colorama (>=0.4.6)"] [[package]] name = "macholib" version = "1.16.3" Loading @@ -44,6 +111,22 @@ python-versions = "*" [package.dependencies] altgraph = ">=0.17" [[package]] name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = ">=3.6" [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false python-versions = ">=3.5" [[package]] name = "packaging" version = "23.2" Loading @@ -52,6 +135,14 @@ category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "pathspec" version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = ">=3.8" [[package]] name = "pefile" version = "2023.2.7" Loading @@ -60,6 +151,18 @@ category = "dev" optional = false python-versions = ">=3.6.0" [[package]] name = "platformdirs" version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.8" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] [[package]] name = "pluggy" version = "1.3.0" Loading Loading @@ -105,6 +208,32 @@ python-versions = ">=3.7" packaging = ">=22.0" setuptools = ">=42.0.0" [[package]] name = "pylint" version = "3.0.3" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.8.0" [package.dependencies] astroid = ">=3.0.1,<=3.1.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, ] isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] testutils = ["gitpython (>3)"] [[package]] name = "pyserial" version = "3.5" Loading Loading @@ -164,6 +293,14 @@ category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "tomlkit" version = "0.12.3" description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=3.7" [[package]] name = "typeguard" version = "4.1.5" Loading @@ -190,17 +327,53 @@ python-versions = ">=3.8" [metadata] lock-version = "1.1" python-versions = ">=3.10,<3.13" content-hash = "eb5574af099481673174dc0ff232f98027db90bc29bb3e7642fe52da84696f04" content-hash = "8a349c65a85dc3f6cbf92263ad83ae4dfaceac8ac07680bc6d6016face7c8f80" [metadata.files] altgraph = [ {file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"}, {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, ] astroid = [ {file = "astroid-3.0.2-py3-none-any.whl", hash = "sha256:d6e62862355f60e716164082d6b4b041d38e2a8cf1c7cd953ded5108bac8ff5c"}, {file = "astroid-3.0.2.tar.gz", hash = "sha256:4a61cf0a59097c7bb52689b0fd63717cd2a8a14dc9f1eee97b82d814881c8c91"}, ] black = [ {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] click = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] colorama = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] dill = [ {file = "dill-0.3.7-py3-none-any.whl", hash = "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e"}, {file = "dill-0.3.7.tar.gz", hash = "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03"}, ] exceptiongroup = [ {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, Loading @@ -209,18 +382,38 @@ iniconfig = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] isort = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] macholib = [ {file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"}, {file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"}, ] mccabe = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] mypy-extensions = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] packaging = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] pathspec = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] pefile = [ {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, ] platformdirs = [ {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] pluggy = [ {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, Loading @@ -243,6 +436,10 @@ pyinstaller-hooks-contrib = [ {file = "pyinstaller-hooks-contrib-2023.12.tar.gz", hash = "sha256:11a9d59d903723dd693e8c10b054f3ea1ecad390623c9fa527c731d715fc5b3f"}, {file = "pyinstaller_hooks_contrib-2023.12-py2.py3-none-any.whl", hash = "sha256:6a601a0d783fa725327fc6ac712779475dc8979f639419c7fcd460dd8d0a6d2a"}, ] pylint = [ {file = "pylint-3.0.3-py3-none-any.whl", hash = "sha256:7a1585285aefc5165db81083c3e06363a27448f6b467b3b0f30dbd0ac1f73810"}, {file = "pylint-3.0.3.tar.gz", hash = "sha256:58c2398b0301e049609a8429789ec6edf3aabe9b6c5fec916acd18639c16de8b"}, ] pyserial = [ {file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"}, {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, Loading @@ -263,6 +460,10 @@ tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [ {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, ] typeguard = [ {file = "typeguard-4.1.5-py3-none-any.whl", hash = "sha256:8923e55f8873caec136c892c3bed1f676eae7be57cdb94819281b3d3bc9c0953"}, {file = "typeguard-4.1.5.tar.gz", hash = "sha256:ea0a113bbc111bcffc90789ebb215625c963411f7096a7e9062d4e4630c155fd"}, Loading
pyproject.toml +6 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,12 @@ pytest = "^7.4.4" [tool.poetry.group.dev.dependencies] pyinstaller = "^6.3.0" [tool.poetry.group.lint.dependencies] pylint = "^3.0.3" black = "^23.12.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api"
pyrsvp/rsvpclient.py +51 −36 Original line number Diff line number Diff line Loading @@ -3,24 +3,28 @@ This file contains the client definition """ import socket from pyrsvp.rsvptypes import RsvpBaseType, process_data_types from typeguard import typechecked from pyrsvp.rsvptypes import RsvpBaseType, process_data_types class RsvpClientConnectionFailed(Exception): pass """Exception for client connection""" class RsvpClientNotAck(Exception): pass """Exception when server doesn't acknowledge""" class RsvpTimeoutExpired(Exception): pass """Received or send timeout""" class RsvpClientInvalidCallback(Exception): pass """Invalid callback function""" class RsvpClient: """Base RsvpClient class """ """Base RsvpClient class""" def __init__(self): pass Loading Loading @@ -61,6 +65,7 @@ class RsvpClient: Raises ------ RsvpClientNotAck: If something is wrong RsvpWrongTypeException: If it fails to parse the args """ tokens = resp.split(";") Loading @@ -73,21 +78,30 @@ class RsvpClient: # You expect to have a REPLY-{cmd_name} if cmd_name in cmd: if status == "NACK": match status: case "NACK": _, err_str = tokens[1].split("=") raise RsvpClientNotAck(err_str) elif status == "ACK": case "ACK": tokens = tokens[1:] return process_data_types(tokens) case _: raise RsvpClientNotAck(f"Unknown reply {cmd_name}={status}") else: raise RsvpClientNotAck(f"Command {cmd_name} not included in reply: {cmd}. Server reply is malformed") raise RsvpClientNotAck( f"Command {cmd_name} not included in reply: {cmd}. Server reply is malformed" ) class RsvpClientTcp(RsvpClient): """RsvpClient using TCP as transport layer """ def __init__(self, srv_ip_address : str = "localhost", srv_port : int = 8080, timeout : float = 5.0): class RsvpClientTcp(RsvpClient): """RsvpClient using TCP as transport layer""" def __init__( self, srv_ip_address: str = "localhost", srv_port: int = 8080, timeout: float = 5.0, ): """RsvpClientTcp constructor Params Loading @@ -105,26 +119,27 @@ class RsvpClientTcp(RsvpClient): self._timeout = timeout def __connect(self): """Connect to the server """ """Connect to the server""" try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except Exception as ex: raise RsvpClientConnectionFailed(f"Failed to create socket: {ex}") raise RsvpClientConnectionFailed(f"Failed to create socket: {ex}") from ex try: self.sock.settimeout(self._timeout) except Exception as ex: raise RsvpClientConnectionFailed(f"Failed to set timeout: {ex}") raise RsvpClientConnectionFailed(f"Failed to set timeout: {ex}") from ex try: self.sock.connect((self._srv_ip, self._port)) except Exception as ex: raise RsvpClientConnectionFailed(f"Failed to connect: {ex}") raise RsvpClientConnectionFailed(f"Failed to connect: {ex}") from ex @typechecked def send_command(self, cmd_name : str, args : list[RsvpBaseType] = None, callback = None) -> list: def send_command( self, cmd_name: str, args: list[RsvpBaseType] = None, callback=None ) -> list: """Send a command to the RSVP server and wait for a reply. Params Loading Loading @@ -155,12 +170,12 @@ class RsvpClientTcp(RsvpClient): try: self.sock.sendall(cmd.encode()) except socket.timeout as ex: raise RsvpTimeoutExpired(f"Failed to send data: {ex}") raise RsvpTimeoutExpired(f"Failed to send data: {ex}") from ex try: buf = self.sock.recv(1024).strip() except socket.timeout as ex: raise RsvpTimeoutExpired(f"Failed to receive data: {ex}") raise RsvpTimeoutExpired(f"Failed to receive data: {ex}") from ex # Process the response data = self.check_response(cmd_name, buf.decode()) Loading @@ -169,8 +184,8 @@ class RsvpClientTcp(RsvpClient): if callback: try: callback(data) return None except Exception as ex: raise RsvpClientInvalidCallback(ex) raise RsvpClientInvalidCallback(ex) from ex else: return data