From 761598de54d9c0a34a2fcd91a1d8954e8c06c513 Mon Sep 17 00:00:00 2001 From: Albert Suralinski Date: Thu, 14 Oct 2021 09:25:20 +0000 Subject: [PATCH] PLINT-1175 Allow specifying error message --- src/galaxy/api/errors.py | 85 +++++++++++++++++------------ src/galaxy/api/jsonrpc.py | 39 ++++++++------ tests/test_errors.py | 103 ++++++++++++++++++++++++++++++++++++ tests/test_local_size.py | 2 +- tests/test_subscriptions.py | 2 +- 5 files changed, 180 insertions(+), 51 deletions(-) create mode 100644 tests/test_errors.py diff --git a/src/galaxy/api/errors.py b/src/galaxy/api/errors.py index a66a206..d5411d6 100644 --- a/src/galaxy/api/errors.py +++ b/src/galaxy/api/errors.py @@ -2,70 +2,87 @@ from galaxy.api.jsonrpc import ApplicationError, UnknownError assert UnknownError + class AuthenticationRequired(ApplicationError): - def __init__(self, data=None): - super().__init__(1, "Authentication required", data) + def __init__(self, message="Authentication required", data=None): + super().__init__(1, message, data) + class BackendNotAvailable(ApplicationError): - def __init__(self, data=None): - super().__init__(2, "Backend not available", data) + def __init__(self, message="Backend not available", data=None): + super().__init__(2, message, data) + class BackendTimeout(ApplicationError): - def __init__(self, data=None): - super().__init__(3, "Backend timed out", data) + def __init__(self, message="Backend timed out", data=None): + super().__init__(3, message, data) + class BackendError(ApplicationError): - def __init__(self, data=None): - super().__init__(4, "Backend error", data) + def __init__(self, message="Backend error", data=None): + super().__init__(4, message, data) + class UnknownBackendResponse(ApplicationError): - def __init__(self, data=None): - super().__init__(4, "Backend responded in unknown way", data) + def __init__(self, message="Backend responded in unknown way", data=None): + super().__init__(4, message, data) + class TooManyRequests(ApplicationError): - def __init__(self, data=None): - super().__init__(5, "Too many requests. Try again later", data) + def __init__(self, message="Too many requests. Try again later", data=None): + super().__init__(5, message, data) + class InvalidCredentials(ApplicationError): - def __init__(self, data=None): - super().__init__(100, "Invalid credentials", data) + def __init__(self, message="Invalid credentials", data=None): + super().__init__(100, message, data) + class NetworkError(ApplicationError): - def __init__(self, data=None): - super().__init__(101, "Network error", data) + def __init__(self, message="Network error", data=None): + super().__init__(101, message, data) + class ProtocolError(ApplicationError): - def __init__(self, data=None): - super().__init__(103, "Protocol error", data) + def __init__(self, message="Protocol error", data=None): + super().__init__(103, message, data) + class TemporaryBlocked(ApplicationError): - def __init__(self, data=None): - super().__init__(104, "Temporary blocked", data) + def __init__(self, message="Temporary blocked", data=None): + super().__init__(104, message, data) + class Banned(ApplicationError): - def __init__(self, data=None): - super().__init__(105, "Banned", data) + def __init__(self, message="Banned", data=None): + super().__init__(105, message, data) + class AccessDenied(ApplicationError): - def __init__(self, data=None): - super().__init__(106, "Access denied", data) + def __init__(self, message="Access denied", data=None): + super().__init__(106, message, data) + class FailedParsingManifest(ApplicationError): - def __init__(self, data=None): - super().__init__(200, "Failed parsing manifest", data) + def __init__(self, message="Failed parsing manifest", data=None): + super().__init__(200, message, data) + class TooManyMessagesSent(ApplicationError): - def __init__(self, data=None): - super().__init__(300, "Too many messages sent", data) + def __init__(self, message="Too many messages sent", data=None): + super().__init__(300, message, data) + class IncoherentLastMessage(ApplicationError): - def __init__(self, data=None): - super().__init__(400, "Different last message id on backend", data) + def __init__(self, message="Different last message id on backend", data=None): + super().__init__(400, message, data) + class MessageNotFound(ApplicationError): - def __init__(self, data=None): - super().__init__(500, "Message not found", data) + def __init__(self, message="Message not found", data=None): + super().__init__(500, message, data) + class ImportInProgress(ApplicationError): - def __init__(self, data=None): - super().__init__(600, "Import already in progress", data) + def __init__(self, message="Import already in progress", data=None): + super().__init__(600, message, data) diff --git a/src/galaxy/api/jsonrpc.py b/src/galaxy/api/jsonrpc.py index 97bc668..3b1ada5 100644 --- a/src/galaxy/api/jsonrpc.py +++ b/src/galaxy/api/jsonrpc.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) class JsonRpcError(Exception): def __init__(self, code, message, data=None): self.code = code - self.message = message + self.message = str(message) self.data = data super().__init__() @@ -33,29 +33,36 @@ class JsonRpcError(Exception): return obj + class ParseError(JsonRpcError): - def __init__(self): - super().__init__(-32700, "Parse error") + def __init__(self, message="Parse error"): + super().__init__(-32700, message) + class InvalidRequest(JsonRpcError): - def __init__(self): - super().__init__(-32600, "Invalid Request") + def __init__(self, message="Invalid Request"): + super().__init__(-32600, message) + class MethodNotFound(JsonRpcError): - def __init__(self): - super().__init__(-32601, "Method not found") + def __init__(self, message="Method not found"): + super().__init__(-32601, message) + class InvalidParams(JsonRpcError): - def __init__(self): - super().__init__(-32602, "Invalid params") + def __init__(self, message="Invalid params"): + super().__init__(-32602, message) + class Timeout(JsonRpcError): - def __init__(self): - super().__init__(-32000, "Method timed out") + def __init__(self, message="Method timed out"): + super().__init__(-32000, message) + class Aborted(JsonRpcError): - def __init__(self): - super().__init__(-32001, "Method aborted") + def __init__(self, message="Method aborted"): + super().__init__(-32001, message) + class ApplicationError(JsonRpcError): def __init__(self, code, message, data): @@ -63,9 +70,11 @@ class ApplicationError(JsonRpcError): raise ValueError("The error code in reserved range") super().__init__(code, message, data) + class UnknownError(ApplicationError): - def __init__(self, data=None): - super().__init__(0, "Unknown error", data) + def __init__(self, message="Unknown error", data=None): + super().__init__(0, message, data) + Request = namedtuple("Request", ["method", "params", "id"], defaults=[{}, None]) Response = namedtuple("Response", ["id", "result", "error"], defaults=[None, {}, {}]) diff --git a/tests/test_errors.py b/tests/test_errors.py new file mode 100644 index 0000000..264ee1c --- /dev/null +++ b/tests/test_errors.py @@ -0,0 +1,103 @@ +import pytest +import galaxy.api.errors as errors +import galaxy.api.jsonrpc as jsonrpc + + +@pytest.mark.parametrize("error, expected_error_msg", [ + (errors.AuthenticationRequired, "Authentication required"), + (errors.BackendNotAvailable, "Backend not available"), + (errors.BackendTimeout, "Backend timed out"), + (errors.BackendError, "Backend error"), + (errors.UnknownBackendResponse, "Backend responded in unknown way"), + (errors.TooManyRequests, "Too many requests. Try again later"), + (errors.InvalidCredentials, "Invalid credentials"), + (errors.NetworkError, "Network error"), + (errors.ProtocolError, "Protocol error"), + (errors.TemporaryBlocked, "Temporary blocked"), + (errors.Banned, "Banned"), + (errors.AccessDenied, "Access denied"), + (errors.FailedParsingManifest, "Failed parsing manifest"), + (errors.TooManyMessagesSent, "Too many messages sent"), + (errors.IncoherentLastMessage, "Different last message id on backend"), + (errors.MessageNotFound, "Message not found"), + (errors.ImportInProgress, "Import already in progress"), + (jsonrpc.UnknownError, "Unknown error"), + (jsonrpc.ParseError, "Parse error"), + (jsonrpc.InvalidRequest, "Invalid Request"), + (jsonrpc.MethodNotFound, "Method not found"), + (jsonrpc.InvalidParams, "Invalid params"), + (jsonrpc.Timeout, "Method timed out"), + (jsonrpc.Aborted, "Method aborted"), +]) +def test_error_default_message(error, expected_error_msg): + error_json = error().json() + + assert error_json["message"] == expected_error_msg + + +@pytest.mark.parametrize("error", [ + errors.AuthenticationRequired, + errors.BackendNotAvailable, + errors.BackendTimeout, + errors.BackendError, + errors.UnknownBackendResponse, + errors.TooManyRequests, + errors.InvalidCredentials, + errors.NetworkError, + errors.ProtocolError, + errors.TemporaryBlocked, + errors.Banned, + errors.AccessDenied, + errors.FailedParsingManifest, + errors.TooManyMessagesSent, + errors.IncoherentLastMessage, + errors.MessageNotFound, + errors.ImportInProgress, + jsonrpc.UnknownError, + jsonrpc.ParseError, + jsonrpc.InvalidRequest, + jsonrpc.MethodNotFound, + jsonrpc.InvalidParams, + jsonrpc.Timeout, + jsonrpc.Aborted, +]) +def test_set_error_custom_message(error): + custom_message = "test message" + + error_json = error(custom_message).json() + + assert error_json["message"] == custom_message + + +@pytest.mark.parametrize("error", [ + errors.AuthenticationRequired, + errors.BackendNotAvailable, + errors.BackendTimeout, + errors.BackendError, + errors.UnknownBackendResponse, + errors.TooManyRequests, + errors.InvalidCredentials, + errors.NetworkError, + errors.ProtocolError, + errors.TemporaryBlocked, + errors.Banned, + errors.AccessDenied, + errors.FailedParsingManifest, + errors.TooManyMessagesSent, + errors.IncoherentLastMessage, + errors.MessageNotFound, + errors.ImportInProgress, + jsonrpc.UnknownError, + jsonrpc.ParseError, + jsonrpc.InvalidRequest, + jsonrpc.MethodNotFound, + jsonrpc.InvalidParams, + jsonrpc.Timeout, + jsonrpc.Aborted, +]) +def test_set_arbitrary_error_message(error): + arbitrary_messages = [[], {}, (), 1, None] + + for msg in arbitrary_messages: + error_json = error(msg).json() + assert error_json["message"] == str(msg) diff --git a/tests/test_local_size.py b/tests/test_local_size.py index 2d03079..c40dfd1 100644 --- a/tests/test_local_size.py +++ b/tests/test_local_size.py @@ -122,7 +122,7 @@ async def test_prepare_get_local_size_context_error(plugin, read, write): request_id = "31415" error_details = "Unexpected syntax" error_message, error_code = FailedParsingManifest().message, FailedParsingManifest().code - plugin.prepare_local_size_context.side_effect = FailedParsingManifest(error_details) + plugin.prepare_local_size_context.side_effect = FailedParsingManifest(data=error_details) request = { "jsonrpc": "2.0", "id": request_id, diff --git a/tests/test_subscriptions.py b/tests/test_subscriptions.py index 474c722..643c24d 100644 --- a/tests/test_subscriptions.py +++ b/tests/test_subscriptions.py @@ -271,7 +271,7 @@ async def test_prepare_get_subscription_games_context_error(plugin, read, write) request_id = "31415" error_details = "Unexpected backend error" error_message, error_code = BackendError().message, BackendError().code - plugin.prepare_subscription_games_context.side_effect = BackendError(error_details) + plugin.prepare_subscription_games_context.side_effect = BackendError(data=error_details) request = { "jsonrpc": "2.0", "id": request_id,