diff --git a/pygeoapi/api.py b/pygeoapi/api.py index 9686936..84c36d6 100644 --- a/pygeoapi/api.py +++ b/pygeoapi/api.py @@ -3381,10 +3381,9 @@ class API: headers['Location'] = f'{self.base_url}/jobs/{job_id}' except ProcessorExecuteError as err: LOGGER.error(err) - msg = 'Processing error' return self.get_exception( - HTTPStatus.INTERNAL_SERVER_ERROR, headers, - request.format, 'NoApplicableCode', msg) + err.http_status_code, headers, + request.format, err.ogc_exception_code, err.message) response = {} if status == JobStatus.failed: diff --git a/pygeoapi/error.py b/pygeoapi/error.py new file mode 100644 index 0000000..98f73f0 --- /dev/null +++ b/pygeoapi/error.py @@ -0,0 +1,53 @@ +# ================================================================= +# +# Authors: Bernhard Mallinger +# +# Copyright (c) 2024 Bernhard Mallinger +# +# 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 http import HTTPStatus + + +class GenericError(Exception): + """Exception class where error codes and messages + can be defined in custom error subclasses, so custom + providers and processes can raise appropriate errors. + """ + + ogc_exception_code = 'NoApplicableCode' + http_status_code = HTTPStatus.INTERNAL_SERVER_ERROR + default_msg = 'Unknown error' + + def __init__(self, msg=None, *args, user_msg=None) -> None: + # if only a user_msg is provided, use it as msg + if user_msg and not msg: + msg = user_msg + super().__init__(msg, *args) + self.user_msg = user_msg + + @property + def message(self): + return self.user_msg if self.user_msg else self.default_msg diff --git a/pygeoapi/process/base.py b/pygeoapi/process/base.py index 3d681f5..2403d17 100644 --- a/pygeoapi/process/base.py +++ b/pygeoapi/process/base.py @@ -30,6 +30,8 @@ import logging from typing import Any, Tuple +from pygeoapi.error import GenericError + LOGGER = logging.getLogger(__name__) @@ -64,14 +66,14 @@ class BaseProcessor: return f' {self.name}' -class ProcessorGenericError(Exception): +class ProcessorGenericError(GenericError): """processor generic error""" pass class ProcessorExecuteError(ProcessorGenericError): """query / backend error""" - pass + default_msg = "generic error (check logs)" class JobError(Exception): diff --git a/pygeoapi/provider/base.py b/pygeoapi/provider/base.py index 9eeeb55..4f8728d 100644 --- a/pygeoapi/provider/base.py +++ b/pygeoapi/provider/base.py @@ -32,6 +32,8 @@ import logging from enum import Enum from http import HTTPStatus +from pygeoapi.error import GenericError + LOGGER = logging.getLogger(__name__) @@ -272,23 +274,10 @@ class BaseProvider: return f' {self.type}' -class ProviderGenericError(Exception): +class ProviderGenericError(GenericError): """provider generic error""" - ogc_exception_code = 'NoApplicableCode' - http_status_code = HTTPStatus.INTERNAL_SERVER_ERROR default_msg = 'generic error (check logs)' - def __init__(self, msg=None, *args, user_msg=None) -> None: - # if only a user_msg is provided, use it as msg - if user_msg and not msg: - msg = user_msg - super().__init__(msg, *args) - self.user_msg = user_msg - - @property - def message(self): - return self.user_msg if self.user_msg else self.default_msg - class ProviderConnectionError(ProviderGenericError): """provider connection error"""