Skip to content

Commit d8ba953

Browse files
refactor custom exceptions
1 parent 8f21183 commit d8ba953

23 files changed

Lines changed: 509 additions & 281 deletions

archipy/adapters/email/email_adapter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
from archipy.configs.base_config import BaseConfig
2121
from archipy.configs.config_template import EmailConfig
2222
from archipy.helpers.utils.base_utils import BaseUtils
23-
from archipy.models.dtos import EmailAttachmentDTO
23+
from archipy.models.dtos.email_dtos import EmailAttachmentDTO
2424
from archipy.models.exceptions import InvalidArgumentException
25-
from archipy.models.types import EmailAttachmentDispositionType, EmailAttachmentType
25+
from archipy.models.types.email_types import EmailAttachmentDispositionType, EmailAttachmentType
2626

2727

2828
class EmailConnectionManager:

archipy/adapters/email/email_port.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from pydantic import EmailStr
44

5-
from archipy.models.dtos import EmailAttachmentDTO
5+
from archipy.models.dtos.email_dtos import EmailAttachmentDTO
66

77

88
class EmailPort:

archipy/adapters/orm/sqlalchemy/sqlalchemy_adapters.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
from archipy.adapters.orm.sqlalchemy.sqlalchemy_ports import AnyExecuteParams, AsyncSqlAlchemyPort, SqlAlchemyPort
1212
from archipy.configs.base_config import BaseConfig
1313
from archipy.configs.config_template import SqlAlchemyConfig
14-
from archipy.models.dtos import PaginationDTO, SortDTO
14+
from archipy.models.dtos.pagination_dto import PaginationDTO
15+
from archipy.models.dtos.sort_dto import SortDTO
1516
from archipy.models.entities import BaseEntity
1617
from archipy.models.exceptions import InvalidEntityTypeException
17-
from archipy.models.types import FilterOperationType, SortOrderType
18+
from archipy.models.types.base_types import FilterOperationType
19+
from archipy.models.types.sort_order_type import SortOrderType
1820

1921

2022
class SqlAlchemyFilterMixin:

archipy/adapters/orm/sqlalchemy/sqlalchemy_ports.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from sqlalchemy.ext.asyncio import AsyncSession
88
from sqlalchemy.orm import Session
99

10-
from archipy.models.dtos import PaginationDTO, SortDTO
10+
from archipy.models.dtos.pagination_dto import PaginationDTO
11+
from archipy.models.dtos.sort_dto import SortDTO
1112
from archipy.models.entities import BaseEntity
1213

1314
_CoreSingleExecuteParams = Mapping[str, Any]

archipy/helpers/interceptors/fastapi/rate_limit/fastapi_rest_rate_limit_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pydantic import StrictInt
55
from starlette.status import HTTP_429_TOO_MANY_REQUESTS
66

7-
from archipy.adapters.redis import AsyncRedisAdapter
7+
from archipy.adapters.redis.redis_adapters import AsyncRedisAdapter
88

99

1010
class FastAPIRestRateLimitHandler:

archipy/helpers/interceptors/grpc/base/base_grpc_server_interceptor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import grpc
66

7-
from archipy.models.dtos import BaseDTO
7+
from archipy.models.dtos.base_dtos import BaseDTO
88

99

1010
def _get_factory_and_method(

archipy/helpers/utils/exception_utils.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from typing import Any
33

44
from archipy.configs.base_config import BaseConfig
5-
from archipy.models.dtos.exception_dto import ExceptionDetailDTO
65
from archipy.models.dtos.fastapi_exception_response_dto import (
76
FastAPIExceptionResponseDTO,
87
ValidationExceptionResponseDTO,
@@ -65,36 +64,6 @@ def capture_exception(exception: BaseException) -> None:
6564
except ImportError:
6665
logging.error("elasticapm is not installed, cannot capture exception in Elastic APM.")
6766

68-
@staticmethod
69-
def create_exception_detail(
70-
code: str,
71-
message_en: str,
72-
message_fa: str,
73-
http_status: int | HTTPStatus | None = None,
74-
grpc_status: int | StatusCode | None = None,
75-
) -> ExceptionDetailDTO:
76-
"""Creates an `ExceptionDetailDTO` with appropriate status codes.
77-
78-
Args:
79-
code (str): A unique error code.
80-
message_en (str): The error message in English.
81-
message_fa (str): The error message in Persian.
82-
http_status (int | HTTPStatus | None): The HTTP status code associated with the error.
83-
grpc_status (int | StatusCode | None): The gRPC status code associated with the error.
84-
85-
Returns:
86-
ExceptionDetailDTO: The created exception detail object.
87-
"""
88-
status_kwargs = {}
89-
90-
if HTTP_AVAILABLE and http_status is not None:
91-
status_kwargs['http_status'] = http_status.value if isinstance(http_status, HTTPStatus) else http_status
92-
93-
if GRPC_AVAILABLE and grpc_status is not None:
94-
status_kwargs['grpc_status'] = grpc_status.value[0] if isinstance(grpc_status, StatusCode) else grpc_status
95-
96-
return ExceptionDetailDTO(code=code, message_en=message_en, message_fa=message_fa, **status_kwargs)
97-
9867
@staticmethod
9968
async def async_handle_fastapi_exception(request: Request, exception: CommonsBaseException) -> JSONResponse:
10069
"""Handles a FastAPI exception and returns a JSON response.

archipy/models/dtos/__init__.py

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +0,0 @@
1-
from archipy.models.dtos.base_dtos import (
2-
BaseDTO,
3-
DateRangeDTO,
4-
DatetimeRangeDTO,
5-
IntegerRangeDTO,
6-
PaginationDTO,
7-
RangeDTO,
8-
SearchInputDTO,
9-
SortDTO,
10-
)
11-
from archipy.models.dtos.email_dtos import EmailAttachmentDTO
12-
13-
__all__ = [
14-
"BaseDTO",
15-
"SortDTO",
16-
"SearchInputDTO",
17-
"PaginationDTO",
18-
"RangeDTO",
19-
"IntegerRangeDTO",
20-
"DateRangeDTO",
21-
"DatetimeRangeDTO",
22-
"EmailAttachmentDTO",
23-
]

archipy/models/dtos/base_dtos.py

Lines changed: 2 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
from datetime import date, datetime
2-
from decimal import Decimal
31
from enum import Enum
4-
from typing import ClassVar, Generic, Self, TypeVar
2+
from typing import TypeVar
53

6-
from pydantic import BaseModel, ConfigDict, Field, PositiveInt, StrictInt, field_validator, model_validator
7-
8-
from archipy.models.types import SortOrderType
4+
from pydantic import BaseModel, ConfigDict
95

106
# Generic types
117
T = TypeVar('T', bound=Enum)
@@ -20,87 +16,3 @@ class BaseDTO(BaseModel):
2016
str_strip_whitespace=True,
2117
arbitrary_types_allowed=True,
2218
)
23-
24-
25-
class SortDTO(BaseModel, Generic[T]):
26-
column: T | str
27-
order: SortOrderType = SortOrderType.DESCENDING
28-
29-
@classmethod
30-
def default(cls) -> Self:
31-
return cls(column="created_at", order=SortOrderType.DESCENDING)
32-
33-
34-
class PaginationDTO(BaseDTO):
35-
page: PositiveInt = Field(default=1, ge=1)
36-
page_size: PositiveInt = Field(default=10, le=100)
37-
38-
MAX_ITEMS: ClassVar = 10000
39-
40-
@model_validator(mode="after")
41-
def validate_pagination(cls, model: Self) -> Self:
42-
total_items = model.page * model.page_size
43-
if total_items > cls.MAX_ITEMS:
44-
raise ValueError(
45-
f"Pagination limit exceeded. "
46-
f"Requested {total_items} items, but the maximum is {cls.MAX_ITEMS}. "
47-
f"Try reducing page size or requesting a lower page number.",
48-
)
49-
return model
50-
51-
52-
class SearchInputDTO(BaseModel, Generic[T]):
53-
pagination: PaginationDTO | None = None
54-
sort_info: SortDTO[T] | None = None
55-
56-
57-
class RangeDTO(BaseDTO):
58-
from_: Decimal | None = None
59-
to: Decimal | None = None
60-
61-
@field_validator("from_", "to", mode="before")
62-
def convert_to(cls, value: Decimal | str | None) -> Decimal | None:
63-
if value is None:
64-
return value
65-
if not (isinstance(value, Decimal | str)):
66-
raise ValueError("Decimal input should be str or decimal.")
67-
return Decimal(value)
68-
69-
@model_validator(mode="after")
70-
def validate_range(cls, model: Self) -> Self:
71-
if model.from_ and model.to and model.from_ >= model.to:
72-
raise ValueError("from_ can`t be bigger than to")
73-
return model
74-
75-
76-
class IntegerRangeDTO(BaseDTO):
77-
from_: StrictInt | None = None
78-
to: StrictInt | None = None
79-
80-
@model_validator(mode="after")
81-
def validate_range(cls, model: Self) -> Self:
82-
if model.from_ and model.to and model.from_ > model.to:
83-
raise ValueError("from_ can`t be bigger than to")
84-
return model
85-
86-
87-
class DateRangeDTO(BaseDTO):
88-
from_: date | None = None
89-
to: date | None = None
90-
91-
@model_validator(mode="after")
92-
def validate_range(cls, model: Self) -> Self:
93-
if model.from_ and model.to and model.from_ > model.to:
94-
raise ValueError("from_ can`t be bigger than to")
95-
return model
96-
97-
98-
class DatetimeRangeDTO(BaseDTO):
99-
from_: datetime | None = None
100-
to: datetime | None = None
101-
102-
@model_validator(mode="after")
103-
def validate_range(cls, model: Self) -> Self:
104-
if model.from_ and model.to and model.from_ > model.to:
105-
raise ValueError("from_ can`t be bigger than to")
106-
return model

archipy/models/dtos/email_dtos.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from pydantic import Field, field_validator, model_validator
55

6-
from archipy.models.dtos import BaseDTO
6+
from archipy.models.dtos.base_dtos import BaseDTO
77
from archipy.models.types.email_types import EmailAttachmentDispositionType, EmailAttachmentType
88

99

0 commit comments

Comments
 (0)