Skip to content

Commit

Permalink
Improve exception for humans (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
kasium authored Jan 31, 2024
1 parent d77f2f9 commit 0fe3577
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 0 deletions.
8 changes: 8 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

1.3.0
-----

Features
~~~~~~~~
- Support ``InvalidObjectNameError`` in ``sqlalchemy_hana.errors``
- Add ``convert_dbapi_error`` to ``sqlalchemy_hana.errors``

1.2.0
-----

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ disable = [
"too-many-public-methods",
"too-many-function-args",
"too-many-lines",
"too-many-branches",
]

[tool.pylint.basic]
Expand Down
21 changes: 21 additions & 0 deletions sqlalchemy_hana/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ class TransactionCancelledError(HANAError):
"""Error raised when a transaction is cancelled."""


class InvalidObjectNameError(HANAError):
"""Error when an invalid object name is referenced."""


def wrap_dbapi_error(error: DBAPIError) -> None:
"""Takes a :py:exc:`sqlalchemy.exc.DBAPIError` and raises a more specific exception if possible.
Expand All @@ -77,6 +81,19 @@ def wrap_dbapi_error(error: DBAPIError) -> None:
wrap_hdbcli_error(error.orig)


def convert_dbapi_error(error: DBAPIError) -> DBAPIError | HANAError:
"""Takes a :py:exc:`sqlalchemy.exc.DBAPIError` and converts it to a more specific exception.
Similar to :py:func:`~wrap_dbapi_error`, but instead of throwing the error, it returns it as
an object.
"""
try:
wrap_dbapi_error(error)
except HANAError as thrown:
return thrown
return error


def wrap_hdbcli_error(error: HdbcliError) -> None:
"""Wraps the given :py:exc:`hdbcli.dbapi.Error` and raises specific exception if possible.
Expand Down Expand Up @@ -151,6 +168,8 @@ def wrap_hdbcli_error(error: HdbcliError) -> None:
and "An error occurred while opening the channel" in error.errortext
):
raise StatementExecutionError from error
if error.errorcode == 397:
raise InvalidObjectNameError from error


__all__ = (
Expand All @@ -166,4 +185,6 @@ def wrap_hdbcli_error(error: HdbcliError) -> None:
"DeadlockError",
"DatabaseOverloadedError",
"StatementExecutionError",
"InvalidObjectNameError",
"convert_dbapi_error",
)
26 changes: 26 additions & 0 deletions test/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
DatabaseOutOfMemoryError,
DatabaseOverloadedError,
DeadlockError,
InvalidObjectNameError,
LockAcquisitionError,
LockWaitTimeoutError,
SequenceCacheTimeoutError,
StatementExecutionError,
StatementTimeoutError,
TransactionCancelledError,
convert_dbapi_error,
wrap_dbapi_error,
wrap_hdbcli_error,
)
Expand Down Expand Up @@ -96,6 +98,7 @@ def test_wrap_hdbcli_error_txsavepoint_not_found(self) -> None:
TransactionCancelledError,
),
(613, "", StatementTimeoutError),
(397, "", InvalidObjectNameError),
],
)
def test_wrap_hdbcli_error(
Expand All @@ -120,3 +123,26 @@ def test_wrap_hdbcli_error(
def test_wrap_hdbcli_error_no_wrap(self, errorcode: int, errortext: str) -> None:
error = HdbcliError(errorcode, errortext)
wrap_hdbcli_error(error)


class TestConvertDbapiError(TestBase):
def test_calls_wrap_dbapi_error_throw(self) -> None:
error = DBAPIError("", None, orig=HdbcliError())

with mock.patch(
"sqlalchemy_hana.errors.wrap_dbapi_error", side_effect=StatementTimeoutError
) as mocked:
new_error = convert_dbapi_error(error)
assert isinstance(new_error, StatementTimeoutError)

mocked.assert_called_once_with(error)

def test_calls_not_wrap_hdbcli_error_no_throw(self) -> None:
error = DBAPIError("", None, orig=ValueError())

with mock.patch(
"sqlalchemy_hana.errors.wrap_dbapi_error", return_value=None
) as mocked:
assert convert_dbapi_error(error) == error

mocked.assert_called_once_with(error)

0 comments on commit 0fe3577

Please sign in to comment.