From b60ca23dbaaade817836ddd7b4a4ba1b02f32a4d Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Sat, 19 Aug 2023 22:20:57 +0530 Subject: [PATCH 1/3] Add CommonsException, CommonsRuntimeException, ConcurrentException --- pycommons/base/concurrent/exception.py | 7 +++ pycommons/base/exception/__init__.py | 52 ++++++++++++++++++++-- tests/parametrized.py | 6 +-- tests/pycommons/base/test_exception.py | 60 ++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 pycommons/base/concurrent/exception.py create mode 100644 tests/pycommons/base/test_exception.py diff --git a/pycommons/base/concurrent/exception.py b/pycommons/base/concurrent/exception.py new file mode 100644 index 0000000..da16c3e --- /dev/null +++ b/pycommons/base/concurrent/exception.py @@ -0,0 +1,7 @@ +from ..exception import CommonsException + + +class ConcurrentException(CommonsException): + """ + Raised for Concurrent Operations + """ diff --git a/pycommons/base/exception/__init__.py b/pycommons/base/exception/__init__.py index f14a4ae..e6f13c1 100644 --- a/pycommons/base/exception/__init__.py +++ b/pycommons/base/exception/__init__.py @@ -1,15 +1,59 @@ -__all__ = ["NoSuchElementError", "IllegalStateException"] +__all__ = ["CommonsException", "CommonsRuntimeException", "NoSuchElementError", "IllegalStateException"] +import traceback +from typing import Optional -class NoSuchElementError(RuntimeError): + +class CommonsException(Exception): + + def __init__(self, message: Optional[str] = None, cause: Optional[Exception] = None, *args): + super().__init__(*args) + if cause is not None: + self.__cause__ = cause + self._message = message + + def get_cause(self) -> Optional[Exception]: + return self.__cause__ + + def get_traceback(self): + return self.__traceback__ + + def get_message(self) -> Optional[str]: + return self._message + + def print_traceback(self) -> None: + traceback.print_tb(self.get_traceback()) + + +class CommonsRuntimeException(RuntimeError): + def __init__(self, message: Optional[str] = None, cause: Optional[Exception] = None, *args): + super().__init__(*args) + if cause is not None: + self.__cause__ = cause + self._message = message + + def get_cause(self) -> Optional[Exception]: + return self.__cause__ + + def get_traceback(self): + return self.__traceback__ + + def get_message(self) -> Optional[str]: + return self._message + + def print_traceback(self) -> None: + traceback.print_tb(self.get_traceback()) + + +class NoSuchElementError(CommonsRuntimeException): """ Raised when an object is expected to be present but is not in real. Extends RuntimeError as this error happens during runtime. """ -class IllegalStateException(RuntimeError): +class IllegalStateException(CommonsRuntimeException): """ - Runtime Error raised when the program's state is not in a expected state or the code execution + Runtime Error raised when the program's state is not in an expected state or the code execution should never have reached this state """ diff --git a/tests/parametrized.py b/tests/parametrized.py index b59f57f..852175e 100644 --- a/tests/parametrized.py +++ b/tests/parametrized.py @@ -1,10 +1,10 @@ import dataclasses import functools -from typing import Any, Optional, List +from typing import Any, Optional @dataclasses.dataclass -class TestData: +class CommonsTestData: data: Any expected: Any @@ -17,7 +17,7 @@ def get_message(self): ) -def cases(testcases: List[TestData]): +def cases(*testcases: CommonsTestData): def decorator(f): @functools.wraps(f) def wrapped(self): diff --git a/tests/pycommons/base/test_exception.py b/tests/pycommons/base/test_exception.py new file mode 100644 index 0000000..d3008d5 --- /dev/null +++ b/tests/pycommons/base/test_exception.py @@ -0,0 +1,60 @@ +from unittest import TestCase + +from pycommons.base.exception import CommonsException, CommonsRuntimeException +from tests.parametrized import CommonsTestData, cases + + +class TestCommonsException(TestCase): + + @cases( + CommonsTestData(data=CommonsException, expected=None), + CommonsTestData(data=CommonsRuntimeException, expected=None) + ) + def test_initialize_without_params(self, test_data: CommonsTestData): + try: + raise test_data.data() + except test_data.data as exc: + self.assertEqual(test_data.expected, exc.get_message()) + self.assertIsNone(exc.get_cause()) + self.assertIsNotNone(exc.get_traceback()) + exc.print_traceback() + + @cases( + CommonsTestData(data=CommonsException, expected="Some error occurred"), + CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred") + ) + def test_initialize_with_message(self, test_data: CommonsTestData): + try: + raise test_data.data(message="Some error occurred") + except test_data.data as exc: + self.assertEqual(test_data.expected, exc.get_message()) + self.assertIsNone(exc.get_cause()) + self.assertIsNotNone(exc.get_traceback()) + + @cases( + CommonsTestData(data=CommonsException, expected="Some error occurred"), + CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred") + ) + def test_initialize_with_cause(self, test_data: CommonsTestData): + _cause = Exception("cause exception") + try: + raise test_data.data(message="Some error occurred", cause=_cause) + except test_data.data as exc: + self.assertEqual(test_data.expected, exc.get_message()) + self.assertEqual(_cause, exc.get_cause()) + self.assertEqual(_cause, exc.__cause__) + self.assertIsNotNone(exc.get_traceback()) + + @cases( + CommonsTestData(data=CommonsException, expected="Some error occurred"), + CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred") + ) + def test_initialize_with_cause2(self, test_data: CommonsTestData): + _cause = Exception("cause exception") + try: + raise test_data.data(message="Some error occurred") from _cause + except test_data.data as exc: + self.assertEqual(test_data.expected, exc.get_message()) + self.assertEqual(_cause, exc.get_cause()) + self.assertEqual(_cause, exc.__cause__) + self.assertIsNotNone(exc.get_traceback()) From ed3955d44538a1cd7c6141deee0fd4c8650042df Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Sat, 19 Aug 2023 22:26:29 +0530 Subject: [PATCH 2/3] Fix format issues --- pycommons/base/exception/__init__.py | 27 +++++++++++++++++--------- tests/pycommons/base/test_exception.py | 9 ++++----- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/pycommons/base/exception/__init__.py b/pycommons/base/exception/__init__.py index e6f13c1..bb640e5 100644 --- a/pycommons/base/exception/__init__.py +++ b/pycommons/base/exception/__init__.py @@ -1,21 +1,28 @@ -__all__ = ["CommonsException", "CommonsRuntimeException", "NoSuchElementError", "IllegalStateException"] +__all__ = [ + "CommonsException", + "CommonsRuntimeException", + "NoSuchElementError", + "IllegalStateException", +] import traceback -from typing import Optional +from types import TracebackType +from typing import Optional, Any class CommonsException(Exception): - - def __init__(self, message: Optional[str] = None, cause: Optional[Exception] = None, *args): + def __init__( + self, message: Optional[str] = None, cause: Optional[Exception] = None, *args: Any + ) -> None: # pylint: disable=W1113 super().__init__(*args) if cause is not None: self.__cause__ = cause self._message = message - def get_cause(self) -> Optional[Exception]: + def get_cause(self) -> Optional[BaseException]: return self.__cause__ - def get_traceback(self): + def get_traceback(self) -> Optional[TracebackType]: return self.__traceback__ def get_message(self) -> Optional[str]: @@ -26,16 +33,18 @@ def print_traceback(self) -> None: class CommonsRuntimeException(RuntimeError): - def __init__(self, message: Optional[str] = None, cause: Optional[Exception] = None, *args): + def __init__( + self, message: Optional[str] = None, cause: Optional[Exception] = None, *args: Any + ) -> None: # pylint: disable=W1113 super().__init__(*args) if cause is not None: self.__cause__ = cause self._message = message - def get_cause(self) -> Optional[Exception]: + def get_cause(self) -> Optional[BaseException]: return self.__cause__ - def get_traceback(self): + def get_traceback(self) -> Optional[TracebackType]: return self.__traceback__ def get_message(self) -> Optional[str]: diff --git a/tests/pycommons/base/test_exception.py b/tests/pycommons/base/test_exception.py index d3008d5..d8765c1 100644 --- a/tests/pycommons/base/test_exception.py +++ b/tests/pycommons/base/test_exception.py @@ -5,10 +5,9 @@ class TestCommonsException(TestCase): - @cases( CommonsTestData(data=CommonsException, expected=None), - CommonsTestData(data=CommonsRuntimeException, expected=None) + CommonsTestData(data=CommonsRuntimeException, expected=None), ) def test_initialize_without_params(self, test_data: CommonsTestData): try: @@ -21,7 +20,7 @@ def test_initialize_without_params(self, test_data: CommonsTestData): @cases( CommonsTestData(data=CommonsException, expected="Some error occurred"), - CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred") + CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred"), ) def test_initialize_with_message(self, test_data: CommonsTestData): try: @@ -33,7 +32,7 @@ def test_initialize_with_message(self, test_data: CommonsTestData): @cases( CommonsTestData(data=CommonsException, expected="Some error occurred"), - CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred") + CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred"), ) def test_initialize_with_cause(self, test_data: CommonsTestData): _cause = Exception("cause exception") @@ -47,7 +46,7 @@ def test_initialize_with_cause(self, test_data: CommonsTestData): @cases( CommonsTestData(data=CommonsException, expected="Some error occurred"), - CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred") + CommonsTestData(data=CommonsRuntimeException, expected="Some error occurred"), ) def test_initialize_with_cause2(self, test_data: CommonsTestData): _cause = Exception("cause exception") From a0c025078746b0a1c667a3f1143ba0f63db51bf4 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Sat, 19 Aug 2023 22:29:34 +0530 Subject: [PATCH 3/3] Fix lint --- pycommons/base/exception/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pycommons/base/exception/__init__.py b/pycommons/base/exception/__init__.py index bb640e5..5455d32 100644 --- a/pycommons/base/exception/__init__.py +++ b/pycommons/base/exception/__init__.py @@ -11,9 +11,9 @@ class CommonsException(Exception): - def __init__( + def __init__( # pylint: disable=W1113 self, message: Optional[str] = None, cause: Optional[Exception] = None, *args: Any - ) -> None: # pylint: disable=W1113 + ) -> None: super().__init__(*args) if cause is not None: self.__cause__ = cause @@ -33,9 +33,9 @@ def print_traceback(self) -> None: class CommonsRuntimeException(RuntimeError): - def __init__( + def __init__( # pylint: disable=W1113 self, message: Optional[str] = None, cause: Optional[Exception] = None, *args: Any - ) -> None: # pylint: disable=W1113 + ) -> None: super().__init__(*args) if cause is not None: self.__cause__ = cause