refactor: improve variable naming and add comments for clarity in models and services
Test / test (push) Successful in 15s Details

This commit is contained in:
Artem Kashaev 2025-12-01 16:24:23 +05:00
parent 1039fba571
commit dc0046c730
8 changed files with 16 additions and 15 deletions

View File

@ -11,7 +11,7 @@ from sqlalchemy import DateTime, ForeignKey, Integer, func, text
from sqlalchemy import Enum as SqlEnum from sqlalchemy import Enum as SqlEnum
from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.types import JSON as GenericJSON from sqlalchemy.types import JSON as SA_JSON
from sqlalchemy.types import TypeDecorator from sqlalchemy.types import TypeDecorator
from app.models.base import Base, enum_values from app.models.base import Base, enum_values
@ -33,9 +33,9 @@ class JSONBCompat(TypeDecorator):
def load_dialect_impl(self, dialect): # type: ignore[override] def load_dialect_impl(self, dialect): # type: ignore[override]
if dialect.name == "sqlite": if dialect.name == "sqlite":
from sqlalchemy.dialects.sqlite import JSON as SQLiteJSON # local import from sqlalchemy.dialects.sqlite import JSON as SQLITE_JSON # local import
return dialect.type_descriptor(SQLiteJSON()) return dialect.type_descriptor(SQLITE_JSON())
return dialect.type_descriptor(JSONB()) return dialect.type_descriptor(JSONB())
@ -55,7 +55,7 @@ class Activity(Base):
nullable=False, nullable=False,
) )
payload: Mapped[dict[str, Any]] = mapped_column( payload: Mapped[dict[str, Any]] = mapped_column(
JSONBCompat().with_variant(GenericJSON(), "sqlite"), JSONBCompat().with_variant(SA_JSON(), "sqlite"),
nullable=False, nullable=False,
server_default=text("'{}'"), server_default=text("'{}'"),
) )

View File

@ -14,7 +14,7 @@ class Base(DeclarativeBase):
"""Base class that configures naming conventions.""" """Base class that configures naming conventions."""
@declared_attr.directive @declared_attr.directive
def __tablename__(cls) -> str: # type: ignore[misc] def __tablename__(cls) -> str: # type: ignore[misc] # noqa: N805 - SQLAlchemy expects cls
return cls.__name__.lower() return cls.__name__.lower()

View File

@ -16,7 +16,7 @@ class TokenPayload(BaseModel):
class TokenResponse(BaseModel): class TokenResponse(BaseModel):
access_token: str access_token: str
refresh_token: str refresh_token: str
token_type: str = "bearer" token_type: str = "bearer" # noqa: S105 -- OAuth2 spec default value
expires_in: int expires_in: int
refresh_expires_in: int refresh_expires_in: int

View File

@ -187,5 +187,5 @@ class TaskService:
) )
try: try:
await self._activity_repository.create(data, organization_id=context.organization_id) await self._activity_repository.create(data, organization_id=context.organization_id)
except ActivityOrganizationMismatchError: # pragma: no cover - defensive except ActivityOrganizationMismatchError as exc: # pragma: no cover - defensive
raise TaskOrganizationError("Activity target does not belong to organization") raise TaskOrganizationError("Activity target does not belong to organization") from exc

View File

@ -77,7 +77,8 @@ select = [
ignore = ["E203", "E266", "E501", "S101"] ignore = ["E203", "E266", "E501", "S101"]
[tool.ruff.lint.per-file-ignores] [tool.ruff.lint.per-file-ignores]
"tests/**/*" = ["S311"] "app/api/**/*" = ["B008"]
"tests/**/*" = ["S105", "S106", "S311"]
"migrations/*" = ["B008", "DTZ001", "TID252"] "migrations/*" = ["B008", "DTZ001", "TID252"]
[tool.ruff.format] [tool.ruff.format]

View File

@ -30,9 +30,9 @@ async def session_factory() -> AsyncGenerator[async_sessionmaker[AsyncSession],
(User.__table__, Organization.__table__, OrganizationMember.__table__), (User.__table__, Organization.__table__, OrganizationMember.__table__),
) )
await conn.run_sync(Base.metadata.create_all, tables=tables) await conn.run_sync(Base.metadata.create_all, tables=tables)
SessionLocal = async_sessionmaker(engine, expire_on_commit=False) session_local = async_sessionmaker(engine, expire_on_commit=False)
yield SessionLocal yield session_local
await engine.dispose() await engine.dispose()

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
from datetime import date, datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
import pytest import pytest
from app.models.task import Task from app.models.task import Task
@ -23,7 +23,7 @@ async def test_create_task_endpoint_creates_task_and_activity(
) -> None: ) -> None:
scenario = await prepare_scenario(session_factory) scenario = await prepare_scenario(session_factory)
token = make_token(scenario.user_id, scenario.user_email) token = make_token(scenario.user_id, scenario.user_email)
due_date = (date.today() + timedelta(days=5)).isoformat() due_date = (datetime.now(timezone.utc).date() + timedelta(days=5)).isoformat()
response = await client.post( response = await client.post(
"/api/v1/tasks/", "/api/v1/tasks/",

View File

@ -30,8 +30,8 @@ async def session() -> AsyncGenerator[AsyncSession, None]:
) )
async with engine.begin() as conn: async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all) await conn.run_sync(Base.metadata.create_all)
Session = async_sessionmaker(engine, expire_on_commit=False) session_factory = async_sessionmaker(engine, expire_on_commit=False)
async with Session() as session: async with session_factory() as session:
yield session yield session
await engine.dispose() await engine.dispose()