Skip to content

Commit 7db5a7c

Browse files
refactor: restore old functionality for gradual refactor
1 parent f3bd0a8 commit 7db5a7c

19 files changed

Lines changed: 261 additions & 40 deletions

File tree

alembic/env.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
from __future__ import with_statement
22

3-
from logging.config import fileConfig
4-
5-
from sqlalchemy import engine_from_config
6-
from sqlalchemy import pool
3+
from alembic import context
4+
from sqlalchemy import engine_from_config, pool
75
from sqlalchemy.sql.schema import SchemaItem
6+
from logging.config import fileConfig
87

9-
from alembic import context
10-
from app.common.infrastructure.base_sqlalchemy_model import BaseSQLAlchemyModel
118
from app.core.config import get_settings
12-
from app.users.infrastructure.sqlalchemy_user_model import * # noqa
13-
14-
# from app.two_factor_authentication.models import * # noqa
9+
from app.common.models.base_class import Base
10+
from app.users.models import * # noqa
11+
from app.two_factor_authentication.models import * # noqa
1512

1613

1714
# this is the Alembic Config object, which provides
@@ -26,7 +23,7 @@
2623
# add your model's MetaData object here
2724
# for 'autogenerate' support
2825

29-
target_metadata = BaseSQLAlchemyModel.metadata
26+
target_metadata = Base.metadata
3027
# target_metadata = None
3128

3229

app/auth/services/auth_service.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
from pydantic import EmailStr
22
from sqlalchemy.orm import Session
33

4-
from app.auth.exceptions.invalid_credentials_exception import (
5-
InvalidCredentialsException,
6-
)
74
from app.auth.schemas.auth_schema import UserLogin
8-
from app.auth.utils.security import verify_password
95
from app.common.exceptions.model_not_found_exception import (
106
ModelNotFoundException,
117
)
12-
from app.users.domain.user_dtos import UserAuth
13-
from app.users.domain.user_dtos import UserUpdate
14-
from app.users.infrastructure.sqlalchemy_user_repository import (
15-
SQLAlchemyUserRepository,
8+
from app.auth.utils.security import verify_password
9+
from app.auth.exceptions.invalid_credentials_exception import (
10+
InvalidCredentialsException,
1611
)
17-
from app.users.infrastructure.sqlalchemy_user_repository import (
12+
from app.users.repositories.users_repository import (
13+
UsersRepository,
1814
users_repository,
1915
)
16+
from app.users.schemas.user_schema import UserAuth, UserUpdate
2017

2118

2219
class AuthService:
2320
def __init__(
24-
self,
25-
session: Session,
26-
repository: SQLAlchemyUserRepository = users_repository,
21+
self, session: Session, repository: UsersRepository = users_repository
2722
):
2823
self.session = session
2924
self.repository = repository

app/celery/tasks/emails.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from uuid import UUID
2-
3-
from app.common.schemas.pagination_schema import ListFilter
4-
from app.core.config import get_settings
5-
from app.db.session import SessionLocal
62
from app.emails.exceptions.email_client_exception import EmailClientException
3+
from app.common.schemas.pagination_schema import ListFilter
74
from app.emails.services.emails_service import EmailService
5+
from app.db.session import SessionLocal
86
from app.main import celery
9-
from app.users.domain.user_dtos import UserInDB
7+
8+
9+
from app.core.config import get_settings
10+
from app.users.schemas.user_schema import UserInDB
1011
from app.users.services.users_service import UsersService
1112

1213
settings = get_settings()

app/common/domain/__init__.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
__all__ = (
2-
"Criteria",
3-
"Entity",
4-
"Repository",
5-
)
6-
7-
from .entities import Entity
8-
from .criteria import Criteria
9-
from .repository import Repository
1+
from .entities import *
2+
from .criteria import *
3+
from .paginator_criteria import *
4+
from .repository import *

app/common/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .base_class import Base # noqa

app/common/models/base_class.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from uuid import UUID, uuid4
2+
from datetime import datetime
3+
4+
from sqlalchemy import MetaData, func, UUID as SQLA_UUID, DateTime
5+
from sqlalchemy.orm import (
6+
DeclarativeBase,
7+
Mapped,
8+
mapped_column,
9+
)
10+
11+
12+
class Base(DeclarativeBase):
13+
__abstract__ = True
14+
15+
metadata = MetaData(
16+
naming_convention={
17+
"ix": "ix_%(column_0_label)s",
18+
"uq": "uq_%(table_name)s_%(column_0_name)s",
19+
"ck": "ck_%(table_name)s_%(constraint_name)s",
20+
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
21+
"pk": "pk_%(table_name)s",
22+
}
23+
)
24+
25+
type_annotation_map = {
26+
UUID: SQLA_UUID,
27+
datetime: DateTime(timezone=True),
28+
}
29+
30+
id: Mapped[UUID] = mapped_column(
31+
default=uuid4,
32+
primary_key=True,
33+
)
34+
created_at: Mapped[datetime] = mapped_column(
35+
server_default=func.now(),
36+
)
37+
updated_at: Mapped[datetime] = mapped_column(
38+
server_default=func.now(),
39+
server_onupdate=func.now(),
40+
)

app/common/repositories/__init__.py

Whitespace-only changes.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from math import ceil
2+
from typing import Any, Generic, Optional, Type, TypeVar
3+
from uuid import UUID
4+
5+
from fastapi.encoders import jsonable_encoder
6+
from pydantic import BaseModel
7+
from sqlalchemy import asc, desc
8+
from sqlalchemy.orm import Session
9+
from sqlalchemy.orm.query import Query
10+
11+
from app.common.schemas.pagination_schema import ListFilter, ListResponse
12+
13+
14+
ModelType = TypeVar("ModelType", bound=Any)
15+
CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
16+
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
17+
18+
19+
class BaseRepository(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
20+
def __init__(self, model: Type[ModelType]):
21+
"""
22+
CRUD object with default methods to Create, Read, Update, Delete (CRUD).
23+
24+
**Parameters**
25+
26+
* `model`: A SQLAlchemy model class
27+
* `schema`: A Pydantic model (schema) class
28+
"""
29+
self.model = model
30+
31+
def get(self, db: Session, model_id: UUID) -> Optional[ModelType]:
32+
return db.query(self.model).filter(self.model.id == model_id).first()
33+
34+
def list(
35+
self, db: Session, list_options: ListFilter, query: Query | None = None
36+
) -> ListResponse:
37+
if not query:
38+
query = db.query(self.model)
39+
40+
total = query.count()
41+
42+
if list_options.order_by:
43+
column = list_options.order_by
44+
direction = list_options.order
45+
by = desc if direction == "desc" else asc
46+
47+
query = query.order_by(by(column))
48+
49+
query = query.offset(list_options.page_size * (list_options.page - 1))
50+
51+
query = query.limit(list_options.page_size)
52+
return ListResponse(
53+
data=query.all(),
54+
page=list_options.page,
55+
page_size=list_options.page_size,
56+
total=total,
57+
total_pages=ceil(total / list_options.page_size),
58+
)
59+
60+
def create(self, db: Session, obj_in: CreateSchemaType) -> ModelType:
61+
obj_in_data = jsonable_encoder(obj_in)
62+
db_obj = self.model(**obj_in_data) # type: ignore
63+
db.add(db_obj)
64+
db.flush()
65+
return db_obj
66+
67+
def update(
68+
self, db: Session, db_obj: ModelType, obj_in: UpdateSchemaType
69+
) -> ModelType:
70+
obj_data = jsonable_encoder(db_obj)
71+
update_data = obj_in.dict(exclude_unset=True)
72+
for field in obj_data:
73+
if field in update_data:
74+
setattr(db_obj, field, update_data[field])
75+
db.add(db_obj)
76+
db.flush()
77+
return db_obj
78+
79+
def delete(self, db: Session, model_id: UUID) -> ModelType | None:
80+
obj = db.query(self.model).get(model_id)
81+
db.delete(obj)
82+
db.flush()
83+
return obj
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
USER_EMAIL_MAX_LENGTH = 100

app/users/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .user import User # noqa

0 commit comments

Comments
 (0)