Skip to content

Commit 9a3b447

Browse files
committed
fix: flake8
1 parent a69b521 commit 9a3b447

16 files changed

Lines changed: 151 additions & 16 deletions

File tree

‎.github/CODEOWNERS‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pyproject.toml @felipementel
2+
/.github/CODEOWNERS @felipementel
3+
/.github/ @felipementel
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
"""HTTP dependency injectors for FastAPI route handlers."""
2+
13
from fastapi import Request
24

35
from application.services.user_service import UserService
46

57

68
def get_user_service(request: Request) -> UserService:
9+
"""Retrieve the UserService from the application state."""
710
return request.app.state.user_service

‎src/adapters/inbound/http/routes/health.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1+
"""Liveness and readiness health check routes."""
2+
13
from fastapi import APIRouter, HTTPException, Request, status
24

35
router = APIRouter(prefix="/health", tags=["Health"])
46

57

68
@router.get("/live", status_code=status.HTTP_200_OK)
79
def liveness() -> dict[str, str]:
10+
"""Return 200 OK when the application process is running."""
811
return {"status": "alive"}
912

1013

1114
@router.get("/ready", status_code=status.HTTP_200_OK)
1215
def readiness(request: Request) -> dict[str, str]:
16+
"""Return 200 when dependencies are ready, 503 otherwise."""
1317
if getattr(request.app.state, "user_service", None) is None:
1418
raise HTTPException(
1519
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,

‎src/adapters/inbound/http/routes/root.py‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Root, documentation, and API explorer routes."""
2+
13
from fastapi import APIRouter, Request
24
from fastapi.openapi.docs import get_scalar_api_reference
35
from fastapi.responses import HTMLResponse
@@ -14,7 +16,8 @@
1416
<style>
1517
*, *::before, *::after {{ box-sizing: border-box; margin: 0; padding: 0; }}
1618
body {{
17-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
19+
font-family:
20+
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
1821
background: #f5f5f5;
1922
display: flex;
2023
justify-content: center;
@@ -68,9 +71,15 @@
6871
<div class="section">
6972
<div class="section-title">Documentação</div>
7073
<ul>
71-
<li><a href="/scalar">Scalar UI <span class="badge">interactive</span></a></li>
74+
<li>
75+
<a href="/scalar">Scalar UI
76+
<span class="badge">interactive</span></a>
77+
</li>
7278
<li><a href="/docs">Swagger UI</a></li>
73-
<li><a href="/openapi.json">OpenAPI Spec <span class="badge">JSON</span></a></li>
79+
<li>
80+
<a href="/openapi.json">OpenAPI Spec
81+
<span class="badge">JSON</span></a>
82+
</li>
7483
</ul>
7584
</div>
7685
@@ -88,12 +97,14 @@
8897

8998
@router.get("/", response_class=HTMLResponse)
9099
async def root(request: Request) -> HTMLResponse:
100+
"""Serve the API landing page with links to docs and health probes."""
91101
version = getattr(request.app, "version", "0.1.0")
92102
return HTMLResponse(content=_ROOT_HTML_TEMPLATE.format(version=version))
93103

94104

95105
@router.get("/scalar", response_class=HTMLResponse)
96106
async def scalar_ui(request: Request) -> HTMLResponse:
107+
"""Serve the Scalar interactive API explorer."""
97108
return get_scalar_api_reference(
98109
openapi_url=str(request.app.openapi_url),
99110
title=request.app.title,

‎src/adapters/inbound/http/routes/users.py‎

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""HTTP route handlers for the /usuarios resource."""
2+
13
from typing import Annotated
24

35
from fastapi import APIRouter, Depends, HTTPException, Response, status
@@ -12,28 +14,47 @@
1214
UserServiceDependency = Annotated[UserService, Depends(get_user_service)]
1315

1416

15-
@router.post("", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
16-
def create_user(payload: UserRequest, user_service: UserServiceDependency) -> UserResponse:
17+
@router.post(
18+
"",
19+
response_model=UserResponse,
20+
status_code=status.HTTP_201_CREATED,
21+
)
22+
def create_user(
23+
payload: UserRequest,
24+
user_service: UserServiceDependency,
25+
) -> UserResponse:
26+
"""Create a new user and return the created resource."""
1727
try:
1828
user = user_service.create_user(payload.to_command())
1929
except UserAlreadyExistsError as error:
20-
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=str(error)) from error
30+
raise HTTPException(
31+
status_code=status.HTTP_409_CONFLICT,
32+
detail=str(error),
33+
) from error
2134

2235
return UserResponse.from_domain(user)
2336

2437

2538
@router.get("", response_model=list[UserResponse])
2639
def list_users(user_service: UserServiceDependency) -> list[UserResponse]:
40+
"""Return all registered users."""
2741
users = user_service.list_users()
2842
return [UserResponse.from_domain(user) for user in users]
2943

3044

3145
@router.get("/{usuario_id}", response_model=UserResponse)
32-
def get_user(usuario_id: int, user_service: UserServiceDependency) -> UserResponse:
46+
def get_user(
47+
usuario_id: int,
48+
user_service: UserServiceDependency,
49+
) -> UserResponse:
50+
"""Return a user by ID or raise HTTP 404."""
3351
try:
3452
user = user_service.get_user(usuario_id)
3553
except UserNotFoundError as error:
36-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(error)) from error
54+
raise HTTPException(
55+
status_code=status.HTTP_404_NOT_FOUND,
56+
detail=str(error),
57+
) from error
3758

3859
return UserResponse.from_domain(user)
3960

@@ -44,19 +65,30 @@ def update_user(
4465
payload: UserRequest,
4566
user_service: UserServiceDependency,
4667
) -> UserResponse:
68+
"""Replace an existing user's data or raise HTTP 404."""
4769
try:
4870
user = user_service.update_user(usuario_id, payload.to_command())
4971
except UserNotFoundError as error:
50-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(error)) from error
72+
raise HTTPException(
73+
status_code=status.HTTP_404_NOT_FOUND,
74+
detail=str(error),
75+
) from error
5176

5277
return UserResponse.from_domain(user)
5378

5479

5580
@router.delete("/{usuario_id}", status_code=status.HTTP_204_NO_CONTENT)
56-
def delete_user(usuario_id: int, user_service: UserServiceDependency) -> Response:
81+
def delete_user(
82+
usuario_id: int,
83+
user_service: UserServiceDependency,
84+
) -> Response:
85+
"""Delete a user by ID or raise HTTP 404."""
5786
try:
5887
user_service.delete_user(usuario_id)
5988
except UserNotFoundError as error:
60-
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(error)) from error
89+
raise HTTPException(
90+
status_code=status.HTTP_404_NOT_FOUND,
91+
detail=str(error),
92+
) from error
6193

6294
return Response(status_code=status.HTTP_204_NO_CONTENT)

‎src/adapters/inbound/http/schemas.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Pydantic request and response schemas for the Usuarios API."""
2+
13
from datetime import date
24

35
from pydantic import BaseModel, ConfigDict, Field
@@ -7,6 +9,8 @@
79

810

911
class UserRequest(BaseModel):
12+
"""Schema for creating or updating a user."""
13+
1014
model_config = ConfigDict(populate_by_name=True, str_strip_whitespace=True)
1115

1216
id: int = Field(gt=0)
@@ -16,6 +20,7 @@ class UserRequest(BaseModel):
1620
telefones: list[str] = Field(default_factory=list)
1721

1822
def to_command(self) -> SaveUserCommand:
23+
"""Convert this request schema to a SaveUserCommand."""
1924
return SaveUserCommand(
2025
id=self.id,
2126
nome=self.nome,
@@ -26,6 +31,8 @@ def to_command(self) -> SaveUserCommand:
2631

2732

2833
class UserResponse(BaseModel):
34+
"""Schema for returning user data in API responses."""
35+
2936
model_config = ConfigDict(populate_by_name=True)
3037

3138
id: int
@@ -36,6 +43,7 @@ class UserResponse(BaseModel):
3643

3744
@classmethod
3845
def from_domain(cls, user: User) -> "UserResponse":
46+
"""Build a UserResponse from a domain User entity."""
3947
return cls(
4048
id=user.id,
4149
nome=user.nome,

‎src/adapters/outbound/repositories/in_memory_user_repository.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
1+
"""In-memory implementation of the UserRepository port."""
2+
13
from domain.user import User
24

35

46
class InMemoryUserRepository:
7+
"""Thread-unsafe in-memory store for User entities."""
8+
59
def __init__(self) -> None:
10+
"""Initialise an empty in-memory user store."""
611
self._storage: dict[int, User] = {}
712

813
def save(self, user: User) -> User:
14+
"""Persist a user and return the stored copy."""
915
stored_user = self._clone(user)
1016
self._storage[user.id] = stored_user
1117
return self._clone(stored_user)
1218

1319
def list_all(self) -> list[User]:
20+
"""Return copies of all stored users."""
1421
return [self._clone(user) for user in self._storage.values()]
1522

1623
def get_by_id(self, user_id: int) -> User | None:
24+
"""Return a user by ID, or None if not found."""
1725
user = self._storage.get(user_id)
1826
if user is None:
1927
return None
2028
return self._clone(user)
2129

2230
def delete(self, user_id: int) -> None:
31+
"""Remove a user by ID (no-op if not found)."""
2332
self._storage.pop(user_id, None)
2433

2534
@staticmethod

‎src/application/commands.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
"""Command objects for the application use-case layer."""
2+
13
from dataclasses import dataclass
24
from datetime import date
35

46

57
@dataclass(frozen=True, slots=True)
68
class SaveUserCommand:
9+
"""Immutable command carrying the data needed to save a user."""
10+
711
id: int
812
nome: str
913
dt_nascimento: date

‎src/application/services/user_service.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,45 @@
1+
"""Application service orchestrating user use-cases."""
2+
13
from application.commands import SaveUserCommand
24
from domain.errors import UserAlreadyExistsError, UserNotFoundError
35
from domain.ports.user_repository import UserRepository
46
from domain.user import User
57

68

79
class UserService:
10+
"""Coordinate domain logic and repository access for users."""
11+
812
def __init__(self, repository: UserRepository) -> None:
13+
"""Inject the UserRepository dependency."""
914
self._repository = repository
1015

1116
def create_user(self, command: SaveUserCommand) -> User:
17+
"""Create and persist a new user from the given command."""
1218
if self._repository.get_by_id(command.id) is not None:
1319
raise UserAlreadyExistsError(command.id)
1420

1521
user = self._to_user(command)
1622
return self._repository.save(user)
1723

1824
def list_users(self) -> list[User]:
25+
"""Return all persisted users."""
1926
return self._repository.list_all()
2027

2128
def get_user(self, user_id: int) -> User:
29+
"""Return a user by ID or raise UserNotFoundError."""
2230
user = self._repository.get_by_id(user_id)
2331
if user is None:
2432
raise UserNotFoundError(user_id)
2533
return user
2634

2735
def update_user(self, user_id: int, command: SaveUserCommand) -> User:
36+
"""Replace an existing user's data or raise UserNotFoundError."""
2837
self.get_user(user_id)
2938
user = self._to_user(command, user_id=user_id)
3039
return self._repository.save(user)
3140

3241
def delete_user(self, user_id: int) -> None:
42+
"""Delete a user by ID or raise UserNotFoundError."""
3343
self.get_user(user_id)
3444
self._repository.delete(user_id)
3545

‎src/domain/errors.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
"""Domain exceptions for the Usuarios bounded context."""
2+
3+
14
class UserAlreadyExistsError(Exception):
5+
"""Raised when attempting to create a user with a duplicate ID."""
6+
27
def __init__(self, user_id: int) -> None:
8+
"""Initialise with the duplicate user ID."""
39
super().__init__(f"Usuario com id {user_id} ja existe.")
410

511

612
class UserNotFoundError(Exception):
13+
"""Raised when a requested user does not exist."""
14+
715
def __init__(self, user_id: int) -> None:
16+
"""Initialise with the missing user ID."""
817
super().__init__(f"Usuario com id {user_id} nao foi encontrado.")

0 commit comments

Comments
 (0)