From 05503855ae4fe9cceb2325091cc0d05857fad0f2 Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:22:50 +0100 Subject: [PATCH 1/4] Move content of pyleco.errors to json_utils.errors and json_utils.json_objects. --- pyleco/errors.py | 27 ++++++---- pyleco/json_utils/errors.py | 76 ++++++++++++++++++--------- pyleco/json_utils/json_objects.py | 4 ++ pyleco/utils/coordinator_utils.py | 12 ++++- tests/json_utils/test_errors.py | 33 ++++++++++++ tests/json_utils/test_json_objects.py | 8 +++ 6 files changed, 121 insertions(+), 39 deletions(-) create mode 100644 tests/json_utils/test_errors.py diff --git a/pyleco/errors.py b/pyleco/errors.py index 2c6d216f..0cb685dd 100644 --- a/pyleco/errors.py +++ b/pyleco/errors.py @@ -23,27 +23,32 @@ # from typing import Any +from warnings import warn from .json_utils.json_objects import Error, DataError, ErrorResponse -# JSON specification: -# -32000 to -32099 Server error reserved for implementation-defined server-errors +from .json_utils.errors import NOT_SIGNED_IN, DUPLICATE_NAME, NODE_UNKNOWN, RECEIVER_UNKNOWN # noqa -# TODO define valid error codes: Proposal: -# general error: -32000 -# Routing errors (Coordinator) between -32090 and -32099 -NOT_SIGNED_IN = Error(code=-32090, message="You did not sign in!") -DUPLICATE_NAME = Error(code=-32091, message="The name is already taken.") -NODE_UNKNOWN = Error(code=-32092, message="Node is not known.") -RECEIVER_UNKNOWN = Error(code=-32093, message="Receiver is not in addresses list.") + +warn("The `pyleco.errors` module is deprecated, use the objects from the `pyleco.json_utils` " + "subpackage instead.", FutureWarning) def generate_error_with_data(error: Error, data: Any) -> DataError: - return DataError(code=error.code, message=error.message, data=data) + """Generate a DataError from an Error. + + .. deprecated:: 0.3 + Use `DataError.from_error` instead. + """ + return DataError.from_error(error=error, data=data) class CommunicationError(ConnectionError): - """Something went wrong, send an `error_msg` to the recipient.""" + """Something went wrong, send an `error_msg` to the recipient. + + .. deprecated:: 0.3 + Use the definition in `communicator_utils` module instead. + """ def __init__(self, text: str, error_payload: ErrorResponse, *args: Any) -> None: super().__init__(text, *args) diff --git a/pyleco/json_utils/errors.py b/pyleco/json_utils/errors.py index a5161bd7..4f3080b0 100644 --- a/pyleco/json_utils/errors.py +++ b/pyleco/json_utils/errors.py @@ -1,40 +1,64 @@ -"""This module provides exceptions for each JSON-RPC 2.0 error. +# +# This file is part of the PyLECO package. +# +# Copyright (c) 2023-2024 PyLECO Developers +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +""" +Based on jsonrpc2-objects + +This module provides exceptions for each JSON-RPC 2.0 error. There is one Exception defined for each pre-defined JSON-RPC 2.0 error. Additionally, there is a ServerError for implementation-defined errors. Each exception extends a base exception JSONRPCError. - -Copied from jsonrpc2-objects """ -__all__ = ( - "INTERNAL_ERROR", - "INVALID_PARAMS", - "INVALID_REQUEST", - "InternalError", - "InvalidParams", - "InvalidRequest", - "JSONRPCError", - "METHOD_NOT_FOUND", - "MethodNotFound", - "PARSE_ERROR", - "ParseError", - "ServerError", - "get_exception_by_code", -) from typing import Optional, Type from .json_objects import DataError, Error, ErrorType -SERVER_ERROR = Error(code=-32000, message="Server error") +# JSONRPC 2.0 defined errors INVALID_REQUEST = Error(code=-32600, message="Invalid Request") METHOD_NOT_FOUND = Error(code=-32601, message="Method not found") INVALID_PARAMS = Error(code=-32602, message="Invalid params") INTERNAL_ERROR = Error(code=-32603, message="Internal error") PARSE_ERROR = Error(code=-32700, message="Parse error") +# -32000 to -32099 Server error reserved for implementation-defined server-errors +# general error: -32000 +SERVER_ERROR = Error(code=-32000, message="Server error") + +# LECO defined errors +# Routing errors (Coordinator) between -32090 and -32099 +NOT_SIGNED_IN = Error(code=-32090, message="You did not sign in!") +DUPLICATE_NAME = Error(code=-32091, message="The name is already taken.") +NODE_UNKNOWN = Error(code=-32092, message="Node is not known.") +RECEIVER_UNKNOWN = Error(code=-32093, message="Receiver is not in addresses list.") + +# Error during deserialization error of the server's response +INVALID_SERVER_RESPONSE = Error(code=-32000, message="Invalid response from server.") + class JSONRPCError(Exception): """Base error that all JSON RPC exceptions extend.""" @@ -44,49 +68,49 @@ def __init__(self, error: ErrorType) -> None: self.rpc_error = error if isinstance(error, DataError): msg += f"\nError Data: {error.data}" - super(JSONRPCError, self).__init__(msg) + super().__init__(msg) class ParseError(JSONRPCError): """Error raised when invalid JSON was received by the server.""" def __init__(self, error: Optional[ErrorType] = None) -> None: - super(ParseError, self).__init__(error or PARSE_ERROR) + super().__init__(error or PARSE_ERROR) class InvalidRequest(JSONRPCError): """Error raised when the JSON sent is not a valid Request object.""" def __init__(self, error: Optional[ErrorType] = None) -> None: - super(InvalidRequest, self).__init__(error or INVALID_REQUEST) + super().__init__(error or INVALID_REQUEST) class MethodNotFound(JSONRPCError): """Error raised when the method does not exist / is not available.""" def __init__(self, error: Optional[ErrorType] = None) -> None: - super(MethodNotFound, self).__init__(error or METHOD_NOT_FOUND) + super().__init__(error or METHOD_NOT_FOUND) class InvalidParams(JSONRPCError): """Error raised when invalid method parameter(s) are supplied.""" def __init__(self, error: Optional[ErrorType] = None) -> None: - super(InvalidParams, self).__init__(error or INVALID_PARAMS) + super().__init__(error or INVALID_PARAMS) class InternalError(JSONRPCError): """Error raised when there is an internal JSON-RPC error.""" def __init__(self, error: Optional[ErrorType] = None) -> None: - super(InternalError, self).__init__(error or INTERNAL_ERROR) + super().__init__(error or INTERNAL_ERROR) class ServerError(JSONRPCError): """Error raised when a server error occurs.""" def __init__(self, error: ErrorType) -> None: - super(ServerError, self).__init__(error) + super().__init__(error) def get_exception_by_code(code: int) -> Optional[Type[JSONRPCError]]: diff --git a/pyleco/json_utils/json_objects.py b/pyleco/json_utils/json_objects.py index bd02ea83..2488db04 100644 --- a/pyleco/json_utils/json_objects.py +++ b/pyleco/json_utils/json_objects.py @@ -113,6 +113,10 @@ class DataError(JsonObject): message: str data: Any + @classmethod + def from_error(cls, error: Error, data: Any) -> DataError: + return cls(code=error.code, message=error.message, data=data) + @dataclass class ErrorResponse(JsonObject): diff --git a/pyleco/utils/coordinator_utils.py b/pyleco/utils/coordinator_utils.py index 8bdfeb39..a064349b 100644 --- a/pyleco/utils/coordinator_utils.py +++ b/pyleco/utils/coordinator_utils.py @@ -27,14 +27,14 @@ from dataclasses import dataclass import logging from time import perf_counter -from typing import Protocol, Optional, Union +from typing import Any, Protocol, Optional, Union import zmq from ..core import COORDINATOR_PORT -from ..errors import CommunicationError, NOT_SIGNED_IN, DUPLICATE_NAME from ..core.message import Message, MessageTypes from ..core.serialization import deserialize_data +from ..json_utils.errors import NOT_SIGNED_IN, DUPLICATE_NAME from ..json_utils.rpc_generator import RPCGenerator from ..json_utils.json_objects import ErrorResponse, Request @@ -43,6 +43,14 @@ log.addHandler(logging.NullHandler()) +class CommunicationError(ConnectionError): + """Something went wrong, send an `error_msg` to the recipient.""" + + def __init__(self, text: str, error_payload: ErrorResponse, *args: Any) -> None: + super().__init__(text, *args) + self.error_payload = error_payload + + class MultiSocket(Protocol): """Represents a socket with multiple connections.""" diff --git a/tests/json_utils/test_errors.py b/tests/json_utils/test_errors.py new file mode 100644 index 00000000..e2815609 --- /dev/null +++ b/tests/json_utils/test_errors.py @@ -0,0 +1,33 @@ +# +# This file is part of the PyLECO package. +# +# Copyright (c) 2023-2024 PyLECO Developers +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +from pyleco.json_utils.json_objects import Error +from pyleco.json_utils.errors import JSONRPCError + + +def test_JsonRPCError(): + error = Error(5, "abc") + exc = JSONRPCError(error) + assert exc.rpc_error == error + assert exc.args[0] == "5: abc" diff --git a/tests/json_utils/test_json_objects.py b/tests/json_utils/test_json_objects.py index 5df37ca5..07191029 100644 --- a/tests/json_utils/test_json_objects.py +++ b/tests/json_utils/test_json_objects.py @@ -75,3 +75,11 @@ def test_error_with_data(): data_error = json_objects.DataError(code=5, message="whatever", data="abc") error_response = json_objects.ErrorResponse(id=7, error=data_error) assert error_response.model_dump_json() == '{"id":7,"error":{"code":5,"message":"whatever","data":"abc"},"jsonrpc":"2.0"}' # noqa + + +def test_generate_data_error_from_error(): + error = json_objects.Error(code=5, message="abc") + data_error = json_objects.DataError.from_error(error, "data") + assert data_error.code == error.code + assert data_error.message == error.message + assert data_error.data == "data" From da76c33e55a48cfb317a975c2de62ff275dc08f1 Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:24:51 +0100 Subject: [PATCH 2/4] Adjust codebase to new places. --- pyleco/coordinators/coordinator.py | 24 +++++++++++----------- pyleco/json_utils/rpc_generator.py | 7 ++----- pyleco/json_utils/rpc_server_definition.py | 7 +++---- pyleco/utils/base_communicator.py | 3 +-- pyleco/utils/communicator.py | 2 +- tests/coordinators/test_coordinator.py | 13 ++++++------ tests/json_utils/test_rpc_generator.py | 4 ++-- tests/utils/test_base_communicator.py | 3 ++- tests/utils/test_communicator.py | 3 +-- tests/utils/test_coordinator_utils.py | 5 +++-- tests/utils/test_message_handler.py | 4 ++-- 11 files changed, 35 insertions(+), 40 deletions(-) diff --git a/pyleco/coordinators/coordinator.py b/pyleco/coordinators/coordinator.py index 88aa9e9c..866bbed7 100644 --- a/pyleco/coordinators/coordinator.py +++ b/pyleco/coordinators/coordinator.py @@ -32,12 +32,12 @@ if __name__ != "__main__": from ..core import COORDINATOR_PORT - from ..utils.coordinator_utils import Directory, ZmqNode, ZmqMultiSocket, MultiSocket + from ..utils.coordinator_utils import CommunicationError, Directory, ZmqNode, ZmqMultiSocket,\ + MultiSocket from ..core.message import Message, MessageTypes from ..core.serialization import get_json_content_type, JsonContentTypes - from ..errors import CommunicationError - from ..errors import NODE_UNKNOWN, RECEIVER_UNKNOWN, generate_error_with_data - from ..json_utils.json_objects import ErrorResponse, Request, ParamsRequest + from ..json_utils.errors import NODE_UNKNOWN, RECEIVER_UNKNOWN + from ..json_utils.json_objects import ErrorResponse, Request, ParamsRequest, DataError from ..json_utils.rpc_server import RPCServer from ..utils.timers import RepeatingTimer from ..utils.zmq_log_handler import ZmqLogHandler @@ -45,12 +45,12 @@ from ..utils.log_levels import PythonLogLevels else: # pragma: no cover from pyleco.core import COORDINATOR_PORT - from pyleco.utils.coordinator_utils import Directory, ZmqNode, ZmqMultiSocket, MultiSocket + from pyleco.utils.coordinator_utils import CommunicationError, Directory, ZmqNode,\ + ZmqMultiSocket, MultiSocket from pyleco.core.message import Message, MessageTypes from pyleco.core.serialization import get_json_content_type, JsonContentTypes - from pyleco.errors import CommunicationError - from pyleco.errors import NODE_UNKNOWN, RECEIVER_UNKNOWN, generate_error_with_data - from pyleco.json_utils.json_objects import ErrorResponse, Request, ParamsRequest + from pyleco.json_utils.errors import NODE_UNKNOWN, RECEIVER_UNKNOWN + from pyleco.json_utils.json_objects import ErrorResponse, Request, ParamsRequest, DataError from pyleco.json_utils.rpc_server import RPCServer from pyleco.utils.timers import RepeatingTimer from pyleco.utils.zmq_log_handler import ZmqLogHandler @@ -288,12 +288,12 @@ def deliver_message(self, sender_identity: bytes, message: Message) -> None: else: self._deliver_remotely(message=message, receiver_namespace=receiver_namespace) - def _deliver_locally(self, message, receiver_name): + def _deliver_locally(self, message: Message, receiver_name: bytes) -> None: try: receiver_identity = self.directory.get_component_id(name=receiver_name) except ValueError: log.error(f"Receiver '{message.receiver}' is not in the addresses list.") - error = generate_error_with_data(RECEIVER_UNKNOWN, data=message.receiver.decode()) + error = DataError.from_error(RECEIVER_UNKNOWN, data=message.receiver.decode()) self.send_message( receiver=message.sender, conversation_id=message.conversation_id, @@ -303,11 +303,11 @@ def _deliver_locally(self, message, receiver_name): else: self.sock.send_message(receiver_identity, message) - def _deliver_remotely(self, message, receiver_namespace) -> None: + def _deliver_remotely(self, message: Message, receiver_namespace: bytes) -> None: try: self.directory.send_node_message(namespace=receiver_namespace, message=message) except ValueError: - error = generate_error_with_data(NODE_UNKNOWN, data=receiver_namespace.decode()) + error = DataError.from_error(NODE_UNKNOWN, data=receiver_namespace.decode()) self.send_message( receiver=message.sender, conversation_id=message.conversation_id, diff --git a/pyleco/json_utils/rpc_generator.py b/pyleco/json_utils/rpc_generator.py index 28f67111..377ab2e0 100644 --- a/pyleco/json_utils/rpc_generator.py +++ b/pyleco/json_utils/rpc_generator.py @@ -28,15 +28,12 @@ from typing import Any, Union from .json_objects import Request, ParamsRequest, DataError, Error, ResultResponse -from .errors import ServerError, get_exception_by_code, JSONRPCError +from .errors import ServerError, get_exception_by_code, JSONRPCError, INVALID_SERVER_RESPONSE log = logging.getLogger(__name__) log.addHandler(logging.NullHandler()) -INVALID_SERVER_RESPONSE = Error(code=-32000, message="Invalid response from server.") - - class RPCGenerator: """This class can generate a JSONRPC request string and interpret the result string.""" @@ -59,7 +56,7 @@ def build_request_str(self, method: str, *args, **kwargs) -> str: def get_result_from_response(self, data: Union[bytes, str, dict]) -> Any: """Get the result of that object or raise an error.""" - # copied and modified from jsonrpc2-pyclient + # copied from jsonrpc2-pyclient and modified try: # Parse string to JSON. if not isinstance(data, dict): diff --git a/pyleco/json_utils/rpc_server_definition.py b/pyleco/json_utils/rpc_server_definition.py index 8d2273f3..7a6b2c4f 100644 --- a/pyleco/json_utils/rpc_server_definition.py +++ b/pyleco/json_utils/rpc_server_definition.py @@ -28,8 +28,7 @@ from typing import Any, Callable, Optional, Union from .errors import INTERNAL_ERROR, SERVER_ERROR, INVALID_REQUEST -from .json_objects import ResultResponse, ErrorResponse -from ..errors import generate_error_with_data +from .json_objects import ResultResponse, ErrorResponse, DataError log = logging.getLogger(__name__) @@ -87,7 +86,7 @@ def process_request(self, data: Union[bytes, str]) -> Optional[str]: else: return ErrorResponse( id=None, - error=generate_error_with_data(INVALID_REQUEST, json_data), + error=DataError.from_error(INVALID_REQUEST, json_data), ).model_dump_json() except Exception as exc: log.exception(f"{type(exc).__name__}:", exc_info=exc) @@ -102,7 +101,7 @@ def _process_single_request( method_name = request.get("method") if method_name is None: return ErrorResponse( - id=id_, error=generate_error_with_data(INVALID_REQUEST, data=request) + id=id_, error=DataError.from_error(INVALID_REQUEST, data=request) ) params = request.get("params") method = self._rpc_methods[method_name] diff --git a/pyleco/utils/base_communicator.py b/pyleco/utils/base_communicator.py index 4e03680f..82c76705 100644 --- a/pyleco/utils/base_communicator.py +++ b/pyleco/utils/base_communicator.py @@ -31,8 +31,7 @@ from ..core.internal_protocols import CommunicatorProtocol from ..core.message import Message, MessageTypes -from ..errors import DUPLICATE_NAME, NOT_SIGNED_IN -from ..json_utils.errors import JSONRPCError +from ..json_utils.errors import JSONRPCError, DUPLICATE_NAME, NOT_SIGNED_IN NOT_SIGNED_IN_ERROR_CODE = str(NOT_SIGNED_IN.code).encode() diff --git a/pyleco/utils/communicator.py b/pyleco/utils/communicator.py index 0f78c0dc..fca2aed1 100644 --- a/pyleco/utils/communicator.py +++ b/pyleco/utils/communicator.py @@ -29,10 +29,10 @@ import zmq -from ..errors import NOT_SIGNED_IN from ..core import COORDINATOR_PORT from ..core.message import Message, MessageTypes from ..json_utils.rpc_generator import RPCGenerator +from ..json_utils.errors import NOT_SIGNED_IN from .base_communicator import BaseCommunicator diff --git a/tests/coordinators/test_coordinator.py b/tests/coordinators/test_coordinator.py index 66aff32e..2b390b70 100644 --- a/tests/coordinators/test_coordinator.py +++ b/tests/coordinators/test_coordinator.py @@ -27,9 +27,8 @@ import pytest -from pyleco.json_utils.json_objects import Request, ErrorResponse -from pyleco.errors import (NODE_UNKNOWN, NOT_SIGNED_IN, DUPLICATE_NAME, RECEIVER_UNKNOWN, - generate_error_with_data) +from pyleco.json_utils.json_objects import Request, ErrorResponse, DataError +from pyleco.json_utils.errors import NODE_UNKNOWN, NOT_SIGNED_IN, DUPLICATE_NAME, RECEIVER_UNKNOWN from pyleco.core import VERSION_B from pyleco.core.message import Message, MessageTypes from pyleco.core.leco_protocols import ExtendedComponentProtocol, Protocol, CoordinatorProtocol @@ -250,14 +249,14 @@ def read_message() -> tuple[bytes, Message]: ([b"321", VERSION_B, b"x", b"send", b"conversation_id;mid0", b""], [b"321", VERSION_B, b"send", b"N1.COORDINATOR", b"conversation_id;\x00\x00\x00\x01", ErrorResponse(id=None, - error=generate_error_with_data(RECEIVER_UNKNOWN, - "x")).model_dump_json().encode()]), + error=DataError.from_error(RECEIVER_UNKNOWN, + "x")).model_dump_json().encode()]), # unknown receiver node: ([b"321", VERSION_B, b"N3.CB", b"N1.send", b"conversation_id;mid0"], [b"321", VERSION_B, b"N1.send", b"N1.COORDINATOR", b"conversation_id;\x00\x00\x00\x01", ErrorResponse(id=None, - error=generate_error_with_data(NODE_UNKNOWN, - "N3")).model_dump_json().encode()]), + error=DataError.from_error(NODE_UNKNOWN, + "N3")).model_dump_json().encode()]), # sender (without namespace) did not sign in: ([b"1", VERSION_B, b"rec", b"unknownSender", b"conversation_id;mid0"], [b"1", VERSION_B, b"unknownSender", b"N1.COORDINATOR", b"conversation_id;\x00\x00\x00\x01", diff --git a/tests/json_utils/test_rpc_generator.py b/tests/json_utils/test_rpc_generator.py index fa9aff1a..45d63da5 100644 --- a/tests/json_utils/test_rpc_generator.py +++ b/tests/json_utils/test_rpc_generator.py @@ -27,9 +27,9 @@ import pytest from pyleco.json_utils.json_objects import ErrorResponse -from pyleco.json_utils.errors import JSONRPCError +from pyleco.json_utils.errors import (JSONRPCError, NODE_UNKNOWN, NOT_SIGNED_IN, DUPLICATE_NAME, + RECEIVER_UNKNOWN) -from pyleco.errors import NODE_UNKNOWN, NOT_SIGNED_IN, DUPLICATE_NAME, RECEIVER_UNKNOWN from pyleco.json_utils.rpc_generator import RPCGenerator, INVALID_SERVER_RESPONSE diff --git a/tests/utils/test_base_communicator.py b/tests/utils/test_base_communicator.py index 50779cc8..7ad1dd91 100644 --- a/tests/utils/test_base_communicator.py +++ b/tests/utils/test_base_communicator.py @@ -33,7 +33,8 @@ from pyleco.test import FakeSocket from pyleco.core.message import Message, MessageTypes from pyleco.json_utils.rpc_generator import RPCGenerator -from pyleco.errors import DUPLICATE_NAME, ErrorResponse +from pyleco.json_utils.errors import DUPLICATE_NAME +from pyleco.json_utils.json_objects import ErrorResponse from pyleco.utils.base_communicator import BaseCommunicator diff --git a/tests/utils/test_communicator.py b/tests/utils/test_communicator.py index 6643abde..e301aca1 100644 --- a/tests/utils/test_communicator.py +++ b/tests/utils/test_communicator.py @@ -28,9 +28,8 @@ from pyleco.core import VERSION_B from pyleco.core.message import Message, MessageTypes -from pyleco.errors import NOT_SIGNED_IN, NODE_UNKNOWN from pyleco.core.serialization import serialize_data -from pyleco.json_utils.errors import JSONRPCError +from pyleco.json_utils.errors import JSONRPCError, NOT_SIGNED_IN, NODE_UNKNOWN from pyleco.utils.communicator import Communicator from pyleco.test import FakeSocket, FakeContext diff --git a/tests/utils/test_coordinator_utils.py b/tests/utils/test_coordinator_utils.py index 1c6d8c15..91953ca8 100644 --- a/tests/utils/test_coordinator_utils.py +++ b/tests/utils/test_coordinator_utils.py @@ -26,9 +26,10 @@ from pyleco.test import FakeContext from pyleco.core.message import Message, MessageTypes -from pyleco.errors import CommunicationError, NOT_SIGNED_IN, DUPLICATE_NAME -from pyleco.utils.coordinator_utils import ZmqNode, ZmqMultiSocket, Node, Directory, FakeNode +from pyleco.json_utils.errors import NOT_SIGNED_IN, DUPLICATE_NAME from pyleco.json_utils.json_objects import Request, ResultResponse, ErrorResponse +from pyleco.utils.coordinator_utils import CommunicationError, ZmqNode, ZmqMultiSocket, Node,\ + Directory, FakeNode class TestZmqMultiSocket: diff --git a/tests/utils/test_message_handler.py b/tests/utils/test_message_handler.py index fc886e91..52e637f7 100644 --- a/tests/utils/test_message_handler.py +++ b/tests/utils/test_message_handler.py @@ -36,9 +36,9 @@ from pyleco.core.internal_protocols import CommunicatorProtocol from pyleco.core.serialization import serialize_data from pyleco.test import FakeContext, FakePoller -from pyleco.errors import NOT_SIGNED_IN, DUPLICATE_NAME, NODE_UNKNOWN, RECEIVER_UNKNOWN from pyleco.json_utils.json_objects import Request, ResultResponse, ErrorResponse -from pyleco.json_utils.errors import JSONRPCError, INVALID_REQUEST +from pyleco.json_utils.errors import JSONRPCError, INVALID_REQUEST, NOT_SIGNED_IN, DUPLICATE_NAME,\ + NODE_UNKNOWN, RECEIVER_UNKNOWN from pyleco.utils.message_handler import MessageHandler, SimpleEvent From a9dbfd88c1acd045f935d0e1f60b2334e7f63262 Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:25:02 +0100 Subject: [PATCH 3/4] Add changelog. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12aacdef..0d56f4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ _Use self defined objects instead of jsonrpc2-objects and jsonrpc2-pyclient._ - Rename `cls` parameter to `device_class` in `Actor` and `TransparentDirector`. - Substitute `jsonrpc2-objects` and `jsonrpc2-pyclient` by self written objects. +- Move error definitions from `pyleco.errors` to `pyleco.json_utils.errors`. +- Move `pyleco.errors.CommunicationError` to `pyleco.json_utils.errors`. +- Deprecate `generate_error_with_data` in favor of `DataError.from_error` class method. - Python requirement lowered to Python 3.8 ### Added @@ -15,6 +18,9 @@ _Use self defined objects instead of jsonrpc2-objects and jsonrpc2-pyclient._ - Add __future__.annotations to all files, which need it for annotations for Python 3.7/3.8. - Add self written `RPCServer` as alternative to openrpc package. +### Deprecated +- Deprecate `pyleco.errors` in favor of `json_utils.errors` and `json_utils.json_objects`. + ## [0.2.2] - 2024-02-14 From 5b3b193dad619c0d465112c09c5a588d27a2768b Mon Sep 17 00:00:00 2001 From: Benedikt Burger <67148916+BenediktBurger@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:32:05 +0100 Subject: [PATCH 4/4] Fix message creation. --- pyleco/coordinators/coordinator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyleco/coordinators/coordinator.py b/pyleco/coordinators/coordinator.py index 866bbed7..f2bb11d4 100644 --- a/pyleco/coordinators/coordinator.py +++ b/pyleco/coordinators/coordinator.py @@ -292,7 +292,7 @@ def _deliver_locally(self, message: Message, receiver_name: bytes) -> None: try: receiver_identity = self.directory.get_component_id(name=receiver_name) except ValueError: - log.error(f"Receiver '{message.receiver}' is not in the addresses list.") + log.error(f"Receiver '{message.receiver!r}' is not in the addresses list.") error = DataError.from_error(RECEIVER_UNKNOWN, data=message.receiver.decode()) self.send_message( receiver=message.sender,