You've already forked hotpocket
BTHLABS-61: Service layer refactoring
A journey to fix `ValidationError` in Pocket imports turned service layer refactoring :D
This commit is contained in:
89
services/packages/soa/hotpocket_soa/exceptions/backend.py
Normal file
89
services/packages/soa/hotpocket_soa/exceptions/backend.py
Normal file
@@ -0,0 +1,89 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from hotpocket_soa.constants import BackendServiceErrorCode
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
VALIDATION_CODE_INVALID = 'invalid'
|
||||
|
||||
|
||||
def get_validation_error_data(validation_error: typing.Any) -> typing.Any: # Heh
|
||||
if hasattr(validation_error, 'error_dict') is True:
|
||||
return {
|
||||
field: [
|
||||
get_validation_error_data(inner_error)
|
||||
for inner_error
|
||||
in inner_errors
|
||||
]
|
||||
for field, inner_errors in validation_error.error_dict.items()
|
||||
}
|
||||
elif hasattr(validation_error, 'error_list') is True and len(validation_error.error_list) > 1:
|
||||
return [
|
||||
get_validation_error_data(inner_error)
|
||||
for inner_error
|
||||
in validation_error.error_list
|
||||
]
|
||||
elif hasattr(validation_error, 'code') is True:
|
||||
return validation_error.code
|
||||
elif isinstance(validation_error, (tuple, list)) is True:
|
||||
return [
|
||||
get_validation_error_data(inner_error)
|
||||
for inner_error
|
||||
in validation_error
|
||||
]
|
||||
elif isinstance(validation_error, dict) is True:
|
||||
return {
|
||||
field: [
|
||||
get_validation_error_data(inner_error)
|
||||
for inner_error
|
||||
in inner_errors
|
||||
]
|
||||
for field, inner_errors in validation_error.items()
|
||||
}
|
||||
else:
|
||||
return VALIDATION_CODE_INVALID
|
||||
|
||||
|
||||
class BackendServiceError(Exception):
|
||||
CODE = BackendServiceErrorCode.INTERNAL
|
||||
|
||||
def __init__(self, message: str, *args):
|
||||
super().__init__(message, *args)
|
||||
self.message = message
|
||||
|
||||
self.data: typing.Any = None
|
||||
if len(args) > 0:
|
||||
self.data = args[0]
|
||||
|
||||
|
||||
class InternalError(BackendServiceError):
|
||||
pass
|
||||
|
||||
|
||||
class NotFound(BackendServiceError):
|
||||
CODE = BackendServiceErrorCode.NOT_FOUND
|
||||
|
||||
|
||||
class AccessDenied(BackendServiceError):
|
||||
CODE = BackendServiceErrorCode.ACCESS_DENIED
|
||||
|
||||
|
||||
class Invalid(BackendServiceError):
|
||||
CODE = BackendServiceErrorCode.INVALID
|
||||
|
||||
@classmethod
|
||||
def from_django_validation_error(cls: type[typing.Self],
|
||||
exception: ValidationError,
|
||||
message: str | None = None,
|
||||
) -> typing.Self:
|
||||
data = get_validation_error_data(exception)
|
||||
|
||||
result = cls(message or 'Invalid', data)
|
||||
result.__cause__ = exception
|
||||
|
||||
return result
|
||||
28
services/packages/soa/hotpocket_soa/exceptions/frontend.py
Normal file
28
services/packages/soa/hotpocket_soa/exceptions/frontend.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import annotations
|
||||
|
||||
import typing
|
||||
|
||||
from .backend import BackendServiceError
|
||||
|
||||
|
||||
class SOAError(Exception):
|
||||
def __init__(self, code: int, message: str, *args):
|
||||
super().__init__(code, message, *args)
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
self.data: typing.Any = None
|
||||
if len(args) > 0:
|
||||
self.data = args[0]
|
||||
|
||||
@classmethod
|
||||
def from_backend_error(cls: type[typing.Self], exception: BackendServiceError) -> typing.Self:
|
||||
result = cls(
|
||||
exception.CODE.value,
|
||||
exception.message,
|
||||
exception.data,
|
||||
)
|
||||
result.__cause__ = exception
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user