Skip to content

Commit 4675b41

Browse files
committed
Extract remaining exceptions
1 parent 64dfda4 commit 4675b41

File tree

9 files changed

+45
-31
lines changed

9 files changed

+45
-31
lines changed

futuramaapi/apps/fastapi.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ def _setup_static(self) -> None:
101101
def _exception_handler(self, _: Request, exc) -> Response:
102102
from futuramaapi.routers.services import ( # noqa: PLC0415
103103
ConflictError,
104+
EmptyUpdateError,
104105
NotFoundError,
106+
RegistrationDisabledError,
105107
ServiceError,
106108
UnauthorizedError,
107109
)
@@ -119,6 +121,14 @@ def _exception_handler(self, _: Request, exc) -> Response:
119121
status_code=status.HTTP_404_NOT_FOUND,
120122
default_message="Not Found",
121123
),
124+
RegistrationDisabledError: _ExceptionValue(
125+
status_code=status.HTTP_403_FORBIDDEN,
126+
default_message="User registration is currently disabled.",
127+
),
128+
EmptyUpdateError: _ExceptionValue(
129+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
130+
default_message="No data to update.",
131+
),
122132
}
123133

124134
exc_value = exception_to_value[type(exc)]

futuramaapi/routers/rest/notifications/api.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from sse_starlette.sse import EventSourceResponse
55

66
from futuramaapi.repositories import INT32
7+
from futuramaapi.routers.exceptions import NotFoundResponse
78
from futuramaapi.routers.services.notifications.sse_character import (
89
CharacterNotificationResponse,
910
GetCharacterNotificationService,
@@ -21,7 +22,10 @@
2122
responses={
2223
status.HTTP_200_OK: {
2324
"model": CharacterNotificationResponse,
24-
}
25+
},
26+
status.HTTP_404_NOT_FOUND: {
27+
"model": NotFoundResponse,
28+
},
2529
},
2630
status_code=status.HTTP_200_OK,
2731
)

futuramaapi/routers/rest/users_new/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
status.HTTP_403_FORBIDDEN: {
4747
"description": "User registration is currently disabled.",
4848
},
49-
status.HTTP_422_UNPROCESSABLE_CONTENT: {
49+
status.HTTP_409_CONFLICT: {
5050
"description": "User already exists.",
5151
},
5252
},
@@ -155,7 +155,7 @@ async def update_user(
155155
"/confirmations/resend",
156156
status_code=status.HTTP_202_ACCEPTED,
157157
responses={
158-
status.HTTP_400_BAD_REQUEST: {
158+
status.HTTP_409_CONFLICT: {
159159
"description": "User already activated.",
160160
},
161161
status.HTTP_401_UNAUTHORIZED: {

futuramaapi/routers/services/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
BaseSessionService,
44
BaseUserAuthenticatedService,
55
ConflictError,
6+
EmptyUpdateError,
67
NotFoundError,
8+
RegistrationDisabledError,
79
ServiceError,
810
UnauthorizedError,
11+
ValidationError,
912
)
1013
from ._base_template import BaseTemplateService
1114

@@ -15,7 +18,10 @@
1518
"BaseTemplateService",
1619
"BaseUserAuthenticatedService",
1720
"ConflictError",
21+
"EmptyUpdateError",
1822
"NotFoundError",
23+
"RegistrationDisabledError",
1924
"ServiceError",
2025
"UnauthorizedError",
26+
"ValidationError",
2127
]

futuramaapi/routers/services/_base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ class ConflictError(ServiceError):
3636
"""Conflict Error."""
3737

3838

39+
class RegistrationDisabledError(ServiceError):
40+
"""Registration Disabled Error."""
41+
42+
43+
class ValidationError(ServiceError):
44+
"""Validation Error."""
45+
46+
47+
class EmptyUpdateError(ValidationError):
48+
"""Empty Update Error."""
49+
50+
3951
class BaseService[TResponse](BaseModel, ABC):
4052
context: dict[str, Any] | None = None
4153

futuramaapi/routers/services/notifications/sse_character.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from random import randint
55
from typing import TYPE_CHECKING
66

7-
from fastapi import HTTPException, Request, status
7+
from fastapi import Request
88
from pydantic import Field
99
from sqlalchemy import Select, select
1010
from sqlalchemy.exc import NoResultFound
@@ -13,7 +13,7 @@
1313
from futuramaapi.helpers.pydantic import BaseModel
1414
from futuramaapi.repositories.models import CharacterModel
1515
from futuramaapi.repositories.session import session_manager
16-
from futuramaapi.routers.services import BaseService
16+
from futuramaapi.routers.services import BaseService, NotFoundError
1717
from futuramaapi.routers.services.characters.get_character import GetCharacterResponse
1818

1919
if TYPE_CHECKING:
@@ -75,9 +75,6 @@ async def __call__(self, request: Request, *args, **kwargs) -> EventSourceRespon
7575
try:
7676
character: CharacterModel = (await session.execute(self.statement)).scalars().one()
7777
except NoResultFound:
78-
raise HTTPException(
79-
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
80-
detail=f"Character with id={self.pk} not found",
81-
) from None
78+
raise NotFoundError(f"Character with id={self.pk} not found") from None
8279

8380
return EventSourceResponse(self.get_move(request, character))

futuramaapi/routers/services/users/create_user.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44

55
import jwt
66
from asyncpg import UniqueViolationError
7-
from fastapi import HTTPException, status
87
from pydantic import EmailStr, Field, HttpUrl, SecretStr, field_validator
98
from sqlalchemy import exc
109

1110
from futuramaapi.core import feature_flags, settings
1211
from futuramaapi.helpers.pydantic import BaseModel
1312
from futuramaapi.repositories.models import UserModel
14-
from futuramaapi.routers.services import BaseSessionService
13+
from futuramaapi.routers.services import BaseSessionService, ConflictError, RegistrationDisabledError
1514

1615
from .get_user_me import GetUserMeResponse
1716

@@ -119,10 +118,7 @@ def _get_user(self) -> UserModel:
119118

120119
async def process(self, *args, **kwargs) -> CreateUserResponse:
121120
if not feature_flags.user_signup:
122-
raise HTTPException(
123-
status_code=status.HTTP_403_FORBIDDEN,
124-
detail="User registration is currently disabled",
125-
)
121+
raise RegistrationDisabledError()
126122

127123
user: UserModel = self._get_user()
128124
self.session.add(user)
@@ -131,10 +127,7 @@ async def process(self, *args, **kwargs) -> CreateUserResponse:
131127
await self.session.commit()
132128
except exc.IntegrityError as err:
133129
if err.orig.sqlstate == UniqueViolationError.sqlstate:
134-
raise HTTPException(
135-
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
136-
detail="User already exists.",
137-
) from None
130+
raise ConflictError("User already exists.") from None
138131
raise
139132

140133
await self._send_confirmation_email(user)

futuramaapi/routers/services/users/resend_user_confirmation.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
from typing import Any, ClassVar
44

55
import jwt
6-
from fastapi import HTTPException, status
76
from pydantic import HttpUrl
87

98
from futuramaapi.core import feature_flags, settings
10-
from futuramaapi.routers.services import BaseUserAuthenticatedService
9+
from futuramaapi.routers.services import BaseUserAuthenticatedService, ConflictError
1110

1211

1312
class ResendUserConfirmationService(BaseUserAuthenticatedService[None]):
@@ -52,10 +51,7 @@ def _get_template_body(self) -> dict[str, Any]:
5251

5352
async def process(self, *args, **kwargs) -> None:
5453
if self.user.is_confirmed:
55-
raise HTTPException(
56-
status_code=status.HTTP_400_BAD_REQUEST,
57-
detail="User already activated.",
58-
) from None
54+
raise ConflictError("User already confirmed.") from None
5955

6056
if not feature_flags.activate_users:
6157
return

futuramaapi/routers/services/users/update_user.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
from fastapi import HTTPException, status
21
from pydantic import Field, SecretStr, field_validator
32

43
from futuramaapi.helpers.pydantic import BaseModel
5-
from futuramaapi.routers.services import BaseUserAuthenticatedService
4+
from futuramaapi.routers.services import BaseUserAuthenticatedService, EmptyUpdateError
65

76
from .get_user_me import GetUserMeResponse
87

@@ -48,10 +47,7 @@ class UpdateUserService(BaseUserAuthenticatedService[UpdateUserResponse]):
4847
async def process(self, *args, **kwargs) -> UpdateUserResponse:
4948
data: dict[str, str] = self.request_data.to_dict(by_alias=False, reveal_secrets=True, exclude_unset=True)
5049
if not data:
51-
raise HTTPException(
52-
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
53-
detail="No data to update.",
54-
)
50+
raise EmptyUpdateError()
5551

5652
for field, value in data.items():
5753
setattr(self.user, field, value)

0 commit comments

Comments
 (0)