mobius-error-py 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. mobius_error/__init__.py +60 -0
  2. mobius_error/config.py +13 -0
  3. mobius_error/errors/__init__.py +0 -0
  4. mobius_error/errors/common_errors.py +33 -0
  5. mobius_error/errors/error.py +17 -0
  6. mobius_error/errors/error_message.py +37 -0
  7. mobius_error/exceptions/__init__.py +0 -0
  8. mobius_error/exceptions/access_violation_exception.py +24 -0
  9. mobius_error/exceptions/api_exception.py +28 -0
  10. mobius_error/exceptions/application_exception.py +71 -0
  11. mobius_error/exceptions/data_type_mismatch_exception.py +11 -0
  12. mobius_error/exceptions/group_data_retrieval_exception.py +8 -0
  13. mobius_error/exceptions/invalid_name_exception.py +8 -0
  14. mobius_error/exceptions/invalid_tenant_exception.py +8 -0
  15. mobius_error/exceptions/kafka_consumption_exception.py +8 -0
  16. mobius_error/exceptions/kafka_exception.py +8 -0
  17. mobius_error/exceptions/object_mapping_exception.py +8 -0
  18. mobius_error/exceptions/rest_exception.py +11 -0
  19. mobius_error/exceptions/rest_get_exception.py +11 -0
  20. mobius_error/exceptions/rest_post_exception.py +11 -0
  21. mobius_error/exceptions/token_exception.py +26 -0
  22. mobius_error/exceptions/unsupported_operation_exception.py +8 -0
  23. mobius_error/exceptions/validation_exception.py +23 -0
  24. mobius_error/handlers/__init__.py +0 -0
  25. mobius_error/handlers/exception_handler.py +248 -0
  26. mobius_error/kafka/__init__.py +0 -0
  27. mobius_error/kafka/constants.py +5 -0
  28. mobius_error/kafka/producer.py +161 -0
  29. mobius_error/py.typed +0 -0
  30. mobius_error/responses/__init__.py +0 -0
  31. mobius_error/responses/api_error_response.py +117 -0
  32. mobius_error/responses/error_response.py +84 -0
  33. mobius_error_py-1.0.0.dist-info/METADATA +575 -0
  34. mobius_error_py-1.0.0.dist-info/RECORD +37 -0
  35. mobius_error_py-1.0.0.dist-info/WHEEL +5 -0
  36. mobius_error_py-1.0.0.dist-info/licenses/LICENSE +21 -0
  37. mobius_error_py-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,60 @@
1
+ """
2
+ Mobius Error Services - FastAPI Port
3
+ A comprehensive error handling library ported from the Spring Boot Java library.
4
+ """
5
+
6
+ from mobius_error.config import App
7
+ from mobius_error.errors.error import Error
8
+ from mobius_error.errors.common_errors import CommonErrors
9
+ from mobius_error.errors.error_message import ErrorMessage
10
+ from mobius_error.exceptions.application_exception import ApplicationException
11
+ from mobius_error.exceptions.api_exception import ApiException
12
+ from mobius_error.exceptions.validation_exception import ValidationException
13
+ from mobius_error.exceptions.access_violation_exception import AccessViolationException
14
+ from mobius_error.exceptions.token_exception import TokenException
15
+ from mobius_error.exceptions.rest_exception import RestException
16
+ from mobius_error.exceptions.rest_get_exception import RestGetException
17
+ from mobius_error.exceptions.rest_post_exception import RestPostException
18
+ from mobius_error.exceptions.kafka_exception import KafkaException
19
+ from mobius_error.exceptions.kafka_consumption_exception import KafkaConsumptionException
20
+ from mobius_error.exceptions.object_mapping_exception import ObjectMappingException
21
+ from mobius_error.exceptions.invalid_name_exception import InvalidNameException
22
+ from mobius_error.exceptions.invalid_tenant_exception import InvalidTenantException
23
+ from mobius_error.exceptions.unsupported_operation_exception import UnsupportedOperationException
24
+ from mobius_error.exceptions.data_type_mismatch_exception import DataTypeMismatchException
25
+ from mobius_error.exceptions.group_data_retrieval_exception import GroupDataRetrievalException
26
+ from mobius_error.responses.error_response import ErrorResponse
27
+ from mobius_error.responses.api_error_response import ApiErrorResponse
28
+ from mobius_error.handlers.exception_handler import register_exception_handlers
29
+ from mobius_error.kafka.producer import KafkaErrorProducer, LogEventSender, PyKafkaProducerClientSender, set_error_producer, get_error_producer
30
+
31
+ __all__ = [
32
+ "App",
33
+ "Error",
34
+ "CommonErrors",
35
+ "ErrorMessage",
36
+ "ApplicationException",
37
+ "ApiException",
38
+ "ValidationException",
39
+ "AccessViolationException",
40
+ "TokenException",
41
+ "RestException",
42
+ "RestGetException",
43
+ "RestPostException",
44
+ "KafkaException",
45
+ "KafkaConsumptionException",
46
+ "ObjectMappingException",
47
+ "InvalidNameException",
48
+ "InvalidTenantException",
49
+ "UnsupportedOperationException",
50
+ "DataTypeMismatchException",
51
+ "GroupDataRetrievalException",
52
+ "ErrorResponse",
53
+ "ApiErrorResponse",
54
+ "register_exception_handlers",
55
+ "KafkaErrorProducer",
56
+ "LogEventSender",
57
+ "PyKafkaProducerClientSender",
58
+ "set_error_producer",
59
+ "get_error_producer",
60
+ ]
mobius_error/config.py ADDED
@@ -0,0 +1,13 @@
1
+ """Application configuration — mirrors com.aidtaas.mobius.error.services.config.App"""
2
+
3
+
4
+ class App:
5
+ _app_name: str = ""
6
+
7
+ @classmethod
8
+ def get_app_name(cls) -> str:
9
+ return cls._app_name
10
+
11
+ @classmethod
12
+ def set_app_name(cls, name: str) -> None:
13
+ cls._app_name = name
File without changes
@@ -0,0 +1,33 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.error.CommonErrors"""
2
+
3
+ from mobius_error.errors.error import Error
4
+
5
+ _VERIFY_REQUEST = "Kindly verify your request or contact the support team"
6
+ _TRY_AGAIN = "Kindly try again after some time or contact the support team"
7
+
8
+
9
+ class CommonErrors:
10
+ # 403 Forbidden
11
+ INVALID_TENANT_ID = Error(
12
+ 403, 403002,
13
+ "You're not registered as a tenant yet",
14
+ "Kindly get yourself registered first",
15
+ )
16
+
17
+ # 500 Internal Server Error
18
+ UNEXPECTED_ERROR = Error(500, 500000, "Encountered an unexpected error", _TRY_AGAIN)
19
+ SERVICE_UNAVAILABLE = Error(500, 500001, "One or more service(s) are not up and running", _TRY_AGAIN)
20
+ OBJECT_MAPPING_FAILURE = Error(500, 500002, "Failed to convert json to object/map or vice versa", _VERIFY_REQUEST)
21
+ GROUP_DATA_RETRIEVAL_FAILURE = Error(500, 500003, "Failed to get group data from data lake", "Kindly verify if the group contains data")
22
+ GET_API_FAILURE = Error(500, 500004, "Failed to GET data from the URL", "Kindly verify if the URL is working")
23
+ POST_API_FAILURE = Error(500, 500005, "Failed to make POST call to an api", "Kindly verify if the POST API service is up and running")
24
+ REST_API_FAILURE = Error(500, 500006, "Failed to make REST call to an api", "Kindly verify if the POST API service is up and running")
25
+
26
+ # 401 Unauthorized
27
+ TENANT_NOT_AUTHORIZED = Error(401, 401000, "You're not authorized to access the resource", "Kindly request appropriate access required for your needs to its owner")
28
+
29
+ # 400 Bad Request
30
+ KAFKA_ERROR = Error(400, 400000, "An error occurred in kafka", "Kindly contact the support team")
31
+ KAFKA_CONSUMPTION_ERROR = Error(400, 400001, "An error occurred while consuming a message from kafka", "Kindly contact the support team")
32
+ INVALID_NAME = Error(400, 400002, "The name provided is invalid", "Kindly try with another name")
33
+ UNSUPPORTED_OPERATION = Error(400, 400003, "This operation is not yet supported", "Kindly try another operation")
@@ -0,0 +1,17 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.error.Error"""
2
+
3
+ from __future__ import annotations
4
+ from dataclasses import dataclass, field
5
+ from typing import TYPE_CHECKING, Optional
6
+
7
+ if TYPE_CHECKING:
8
+ from mobius_error.errors.error_message import ErrorMessage
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class Error:
13
+ http_status_code: int
14
+ error_code: int
15
+ error_message: str
16
+ action_required: str
17
+ error_message_description: Optional["ErrorMessage"] = field(default=None)
@@ -0,0 +1,37 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.error.ErrorMessage"""
2
+
3
+ from __future__ import annotations
4
+ import time
5
+ from dataclasses import dataclass, field
6
+ from typing import Any, Optional
7
+
8
+
9
+ @dataclass
10
+ class ErrorMessage:
11
+ message: Optional[str] = None
12
+ root_origin: Optional[str] = None
13
+ root_message: Optional[str] = None
14
+ action_required: Optional[str] = None
15
+ cause: Optional["ErrorMessage"] = None
16
+ origin: Optional[str] = None
17
+ http_status_code: Optional[int] = None
18
+ timestamp: int = field(default_factory=lambda: int(time.time()))
19
+
20
+ def to_dict(self) -> dict[str, Any]:
21
+ result: dict[str, Any] = {}
22
+ if self.root_origin is not None:
23
+ result["rootOrigin"] = self.root_origin
24
+ if self.root_message is not None:
25
+ result["rootMessage"] = self.root_message
26
+ if self.message is not None:
27
+ result["message"] = self.message
28
+ if self.action_required is not None:
29
+ result["actionRequired"] = self.action_required
30
+ if self.cause is not None:
31
+ result["cause"] = self.cause.to_dict()
32
+ if self.origin is not None:
33
+ result["origin"] = self.origin
34
+ if self.http_status_code is not None:
35
+ result["httpStatusCode"] = self.http_status_code
36
+ result["timestamp"] = self.timestamp
37
+ return result
File without changes
@@ -0,0 +1,24 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.exception.AccessViolationException"""
2
+
3
+ from __future__ import annotations
4
+ from typing import Any, Optional
5
+ from mobius_error.errors.error import Error
6
+ from mobius_error.exceptions.validation_exception import ValidationException
7
+
8
+
9
+ class AccessViolationException(ValidationException):
10
+
11
+ def __init__(
12
+ self,
13
+ error: Error,
14
+ detailed_error_message: Optional[str] = None,
15
+ error_object: Any = None,
16
+ cause: Optional[Exception] = None,
17
+ ) -> None:
18
+ super().__init__(
19
+ error=error,
20
+ detailed_error_message=detailed_error_message,
21
+ error_object=error_object,
22
+ cause=cause,
23
+ )
24
+ self.http_status_code = 403
@@ -0,0 +1,28 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.exception.ApiException"""
2
+
3
+ from __future__ import annotations
4
+ from typing import Any, Optional
5
+
6
+ from mobius_error.errors.error import Error
7
+ from mobius_error.errors.error_message import ErrorMessage
8
+ from mobius_error.exceptions.application_exception import ApplicationException
9
+
10
+
11
+ class ApiException(ApplicationException):
12
+
13
+ def __init__(
14
+ self,
15
+ error: Error,
16
+ detailed_error_message: Optional[str] = None,
17
+ error_object: Any = None,
18
+ nested_error_message: Optional[ErrorMessage] = None,
19
+ cause: Optional[Exception] = None,
20
+ ) -> None:
21
+ super().__init__(
22
+ error=error,
23
+ detailed_error_message=detailed_error_message,
24
+ error_object=error_object,
25
+ nested_error_message=nested_error_message,
26
+ cause=cause,
27
+ )
28
+ self.http_status_code: int = error.http_status_code if error else 500
@@ -0,0 +1,71 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.exception.ApplicationException"""
2
+
3
+ from __future__ import annotations
4
+ from typing import Any, Optional
5
+
6
+ from mobius_error.config import App
7
+ from mobius_error.errors.common_errors import CommonErrors
8
+ from mobius_error.errors.error import Error
9
+ from mobius_error.errors.error_message import ErrorMessage
10
+ import time
11
+
12
+
13
+ class ApplicationException(Exception):
14
+
15
+ def __init__(
16
+ self,
17
+ error: Optional[Error] = None,
18
+ detailed_error_message: Optional[str] = None,
19
+ error_object: Any = None,
20
+ nested_error_message: Optional[ErrorMessage] = None,
21
+ cause: Optional[Exception] = None,
22
+ sub_errors: Optional[list[ErrorMessage]] = None,
23
+ actions_required: Optional[list[str]] = None,
24
+ ) -> None:
25
+ self.error: Error = error or CommonErrors.UNEXPECTED_ERROR
26
+ self.detailed_error_message = detailed_error_message
27
+ self.error_object = error_object
28
+ self.origin: str = App.get_app_name()
29
+ self.sub_errors: list[ErrorMessage] = list(sub_errors) if sub_errors else []
30
+ self.actions_required: list[str] = list(actions_required) if actions_required else []
31
+ self.__cause__ = cause
32
+
33
+ # Build nested error message
34
+ if nested_error_message is not None:
35
+ self.nested_error_message = nested_error_message
36
+ elif detailed_error_message and cause is None:
37
+ self.nested_error_message = ErrorMessage(
38
+ root_origin=App.get_app_name(),
39
+ root_message=detailed_error_message,
40
+ )
41
+ elif cause is not None:
42
+ self.nested_error_message = ErrorMessage(
43
+ message=str(cause),
44
+ origin=App.get_app_name(),
45
+ http_status_code=500,
46
+ timestamp=int(time.time()),
47
+ )
48
+ else:
49
+ self.nested_error_message = None
50
+
51
+ msg = detailed_error_message or self.error.error_message
52
+ super().__init__(msg)
53
+
54
+ # ---- fluent helpers (mirror the Java builder pattern) ----
55
+
56
+ def add_action_required(self, action: str) -> "ApplicationException":
57
+ if action:
58
+ self.actions_required.append(action)
59
+ return self
60
+
61
+ def add_sub_error(self, message: str) -> "ApplicationException":
62
+ if message:
63
+ self.sub_errors.append(ErrorMessage(message=message))
64
+ return self
65
+
66
+ def add_nested_error_message(self, message: str) -> "ApplicationException":
67
+ if message:
68
+ new_msg = ErrorMessage(message=message)
69
+ new_msg.cause = self.nested_error_message
70
+ self.nested_error_message = new_msg
71
+ return self
@@ -0,0 +1,11 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.exception.DataTypeMismatchException"""
2
+
3
+ from typing import Any
4
+ from mobius_error.errors.error import Error
5
+ from mobius_error.exceptions.api_exception import ApiException
6
+
7
+
8
+ class DataTypeMismatchException(ApiException):
9
+
10
+ def __init__(self, error: Error, detailed_error_message: str, error_object: Any = None) -> None:
11
+ super().__init__(error=error, detailed_error_message=detailed_error_message, error_object=error_object)
@@ -0,0 +1,8 @@
1
+ """Mirrors GroupDataRetrievalException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+ class GroupDataRetrievalException(ApplicationException):
7
+ def __init__(self, error_message: str, cause: Optional[Exception] = None) -> None:
8
+ super().__init__(error=CommonErrors.GROUP_DATA_RETRIEVAL_FAILURE, detailed_error_message=error_message, cause=cause)
@@ -0,0 +1,8 @@
1
+ """Mirrors InvalidNameException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.validation_exception import ValidationException
5
+
6
+ class InvalidNameException(ValidationException):
7
+ def __init__(self, error_message: str, cause: Optional[Exception] = None) -> None:
8
+ super().__init__(error=CommonErrors.INVALID_NAME, detailed_error_message=error_message, cause=cause)
@@ -0,0 +1,8 @@
1
+ """Mirrors InvalidTenantException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.validation_exception import ValidationException
5
+
6
+ class InvalidTenantException(ValidationException):
7
+ def __init__(self, error_message: Optional[str] = None) -> None:
8
+ super().__init__(error=CommonErrors.INVALID_TENANT_ID, detailed_error_message=error_message)
@@ -0,0 +1,8 @@
1
+ """Mirrors KafkaConsumptionException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+ class KafkaConsumptionException(ApplicationException):
7
+ def __init__(self, error_message: str, cause: Optional[Exception] = None) -> None:
8
+ super().__init__(error=CommonErrors.KAFKA_CONSUMPTION_ERROR, detailed_error_message=error_message, cause=cause)
@@ -0,0 +1,8 @@
1
+ """Mirrors KafkaException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+ class KafkaException(ApplicationException):
7
+ def __init__(self, error_message: str, cause: Optional[Exception] = None) -> None:
8
+ super().__init__(error=CommonErrors.KAFKA_ERROR, detailed_error_message=error_message, cause=cause)
@@ -0,0 +1,8 @@
1
+ """Mirrors ObjectMappingException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+ class ObjectMappingException(ApplicationException):
7
+ def __init__(self, error_message: str, cause: Optional[Exception] = None) -> None:
8
+ super().__init__(error=CommonErrors.OBJECT_MAPPING_FAILURE, detailed_error_message=error_message, cause=cause)
@@ -0,0 +1,11 @@
1
+ """Mirrors RestException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+
7
+ class RestException(ApplicationException):
8
+ def __init__(self, error_message: str, cause: Optional[Exception] = None, detailed: Optional[str] = None) -> None:
9
+ super().__init__(error=CommonErrors.REST_API_FAILURE, detailed_error_message=error_message, cause=cause)
10
+ if detailed:
11
+ self.detailed_error_message = detailed
@@ -0,0 +1,11 @@
1
+ """Mirrors RestGetException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+
7
+ class RestGetException(ApplicationException):
8
+ def __init__(self, error_message: str, cause: Optional[Exception] = None, url: Optional[str] = None, status_code: Optional[int] = None, response_body: Optional[str] = None) -> None:
9
+ super().__init__(error=CommonErrors.GET_API_FAILURE, detailed_error_message=error_message, cause=cause)
10
+ if url and status_code is not None:
11
+ self.detailed_error_message = f"Error on GET {url} : {status_code} - {response_body or ''}"
@@ -0,0 +1,11 @@
1
+ """Mirrors RestPostException"""
2
+ from typing import Any, Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+
7
+ class RestPostException(ApplicationException):
8
+ def __init__(self, error_message: str, cause: Optional[Exception] = None, url: Optional[str] = None, payload: Any = None, status_code: Optional[int] = None, response_body: Optional[str] = None) -> None:
9
+ super().__init__(error=CommonErrors.POST_API_FAILURE, detailed_error_message=error_message, cause=cause)
10
+ if url and status_code is not None:
11
+ self.detailed_error_message = f"Error on POST {url} with payload {payload} : {status_code} - {response_body or ''}"
@@ -0,0 +1,26 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.exception.TokenException"""
2
+
3
+ from __future__ import annotations
4
+ from typing import Any, Optional
5
+ from mobius_error.errors.error import Error
6
+ from mobius_error.errors.error_message import ErrorMessage
7
+ from mobius_error.exceptions.api_exception import ApiException
8
+
9
+
10
+ class TokenException(ApiException):
11
+
12
+ def __init__(
13
+ self,
14
+ error: Error,
15
+ detailed_error_message: Optional[str] = None,
16
+ error_object: Any = None,
17
+ nested_error_message: Optional[ErrorMessage] = None,
18
+ cause: Optional[Exception] = None,
19
+ ) -> None:
20
+ super().__init__(
21
+ error=error,
22
+ detailed_error_message=detailed_error_message,
23
+ error_object=error_object,
24
+ nested_error_message=nested_error_message,
25
+ cause=cause,
26
+ )
@@ -0,0 +1,8 @@
1
+ """Mirrors UnsupportedOperationException"""
2
+ from typing import Optional
3
+ from mobius_error.errors.common_errors import CommonErrors
4
+ from mobius_error.exceptions.application_exception import ApplicationException
5
+
6
+ class UnsupportedOperationException(ApplicationException):
7
+ def __init__(self, error_message: str, cause: Optional[Exception] = None) -> None:
8
+ super().__init__(error=CommonErrors.UNSUPPORTED_OPERATION, detailed_error_message=error_message, cause=cause)
@@ -0,0 +1,23 @@
1
+ """Mirrors com.aidtaas.mobius.error.services.exception.ValidationException"""
2
+
3
+ from __future__ import annotations
4
+ from typing import Any, Optional
5
+ from mobius_error.errors.error import Error
6
+ from mobius_error.exceptions.api_exception import ApiException
7
+
8
+
9
+ class ValidationException(ApiException):
10
+
11
+ def __init__(
12
+ self,
13
+ error: Error,
14
+ detailed_error_message: Optional[str] = None,
15
+ error_object: Any = None,
16
+ cause: Optional[Exception] = None,
17
+ ) -> None:
18
+ super().__init__(
19
+ error=error,
20
+ detailed_error_message=detailed_error_message,
21
+ error_object=error_object,
22
+ cause=cause,
23
+ )
File without changes