diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index aabe188..491acb1 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -27,7 +27,7 @@ jobs:
- name: Run tests
run: docker compose build
- - name: Docker Compose remove old containers and volumes
+ - name: Docker Compose remove old containers and volumes
run: docker compose down -v --remove-orphans
- name: Docker Compose up
run: docker compose up -d
diff --git a/src/backend/app/alembic/README b/src/backend/app/alembic/README
index 98e4f9c..2500aa1 100755
--- a/src/backend/app/alembic/README
+++ b/src/backend/app/alembic/README
@@ -1 +1 @@
-Generic single-database configuration.
\ No newline at end of file
+Generic single-database configuration.
diff --git a/src/backend/app/alembic/env.py b/src/backend/app/alembic/env.py
index 3e002a2..c146cf6 100755
--- a/src/backend/app/alembic/env.py
+++ b/src/backend/app/alembic/env.py
@@ -1,10 +1,8 @@
-from __future__ import with_statement
-
import os
+from logging.config import fileConfig
from alembic import context
from sqlalchemy import engine_from_config, pool
-from logging.config import fileConfig
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
@@ -69,7 +67,9 @@ def run_migrations_online():
configuration = config.get_section(config.config_ini_section)
configuration["sqlalchemy.url"] = get_url()
connectable = engine_from_config(
- configuration, prefix="sqlalchemy.", poolclass=pool.NullPool,
+ configuration,
+ prefix="sqlalchemy.",
+ poolclass=pool.NullPool,
)
with connectable.connect() as connection:
diff --git a/src/backend/app/alembic/versions/e2412789c190_initialize_models.py b/src/backend/app/alembic/versions/e2412789c190_initialize_models.py
index 7232ed4..7529ea9 100644
--- a/src/backend/app/alembic/versions/e2412789c190_initialize_models.py
+++ b/src/backend/app/alembic/versions/e2412789c190_initialize_models.py
@@ -1,17 +1,16 @@
"""Initialize models
Revision ID: e2412789c190
-Revises:
+Revises:
Create Date: 2023-11-24 22:55:43.195942
"""
-from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
-
+from alembic import op
# revision identifiers, used by Alembic.
-revision = 'e2412789c190'
+revision = "e2412789c190"
down_revision = None
branch_labels = None
depends_on = None
@@ -19,30 +18,37 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
- op.create_table('user',
- sa.Column('email', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
- sa.Column('is_active', sa.Boolean(), nullable=False),
- sa.Column('is_superuser', sa.Boolean(), nullable=False),
- sa.Column('full_name', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('hashed_password', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
- sa.PrimaryKeyConstraint('id')
+ op.create_table(
+ "user",
+ sa.Column("email", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
+ sa.Column("is_active", sa.Boolean(), nullable=False),
+ sa.Column("is_superuser", sa.Boolean(), nullable=False),
+ sa.Column("full_name", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
+ sa.Column("id", sa.Integer(), nullable=False),
+ sa.Column(
+ "hashed_password", sqlmodel.sql.sqltypes.AutoString(), nullable=False
+ ),
+ sa.PrimaryKeyConstraint("id"),
)
- op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=True)
- op.create_table('item',
- sa.Column('description', sqlmodel.sql.sqltypes.AutoString(), nullable=True),
- sa.Column('id', sa.Integer(), nullable=False),
- sa.Column('title', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
- sa.Column('owner_id', sa.Integer(), nullable=False),
- sa.ForeignKeyConstraint(['owner_id'], ['user.id'], ),
- sa.PrimaryKeyConstraint('id')
+ op.create_index(op.f("ix_user_email"), "user", ["email"], unique=True)
+ op.create_table(
+ "item",
+ sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
+ sa.Column("id", sa.Integer(), nullable=False),
+ sa.Column("title", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
+ sa.Column("owner_id", sa.Integer(), nullable=False),
+ sa.ForeignKeyConstraint(
+ ["owner_id"],
+ ["user.id"],
+ ),
+ sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
- op.drop_table('item')
- op.drop_index(op.f('ix_user_email'), table_name='user')
- op.drop_table('user')
+ op.drop_table("item")
+ op.drop_index(op.f("ix_user_email"), table_name="user")
+ op.drop_table("user")
# ### end Alembic commands ###
diff --git a/src/backend/app/api/api_v1/endpoints/items.py b/src/backend/app/api/api_v1/endpoints/items.py
index 9878c09..ddbe93e 100644
--- a/src/backend/app/api/api_v1/endpoints/items.py
+++ b/src/backend/app/api/api_v1/endpoints/items.py
@@ -1,10 +1,10 @@
from typing import Any
from fastapi import APIRouter, HTTPException
-from sqlmodel import select, func
+from sqlmodel import func, select
from app.api.deps import CurrentUser, SessionDep
-from app.models import Item, ItemCreate, ItemOut, ItemUpdate, Message, ItemsOut
+from app.models import Item, ItemCreate, ItemOut, ItemsOut, ItemUpdate, Message
router = APIRouter()
@@ -22,7 +22,7 @@ def read_items(
if current_user.is_superuser:
statement = select(Item).offset(skip).limit(limit)
- items = session.exec(statement).all()
+ items = session.exec(statement).all()
else:
statement = (
select(Item)
diff --git a/src/backend/app/api/api_v1/endpoints/users.py b/src/backend/app/api/api_v1/endpoints/users.py
index 0e71f1f..0b9a511 100644
--- a/src/backend/app/api/api_v1/endpoints/users.py
+++ b/src/backend/app/api/api_v1/endpoints/users.py
@@ -1,7 +1,7 @@
-from typing import Any, List
+from typing import Any
from fastapi import APIRouter, Depends, HTTPException
-from sqlmodel import select, func
+from sqlmodel import func, select
from app import crud
from app.api.deps import (
@@ -28,9 +28,7 @@ router = APIRouter()
@router.get(
- "/",
- dependencies=[Depends(get_current_active_superuser)],
- response_model=UsersOut
+ "/", dependencies=[Depends(get_current_active_superuser)], response_model=UsersOut
)
def read_users(session: SessionDep, skip: int = 0, limit: int = 100) -> Any:
"""
diff --git a/src/backend/app/api/deps.py b/src/backend/app/api/deps.py
index abe067b..1810ce0 100644
--- a/src/backend/app/api/deps.py
+++ b/src/backend/app/api/deps.py
@@ -1,4 +1,5 @@
-from typing import Annotated, Generator
+from collections.abc import Generator
+from typing import Annotated
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
diff --git a/src/backend/app/core/config.py b/src/backend/app/core/config.py
index 5aa0f83..abc96e5 100644
--- a/src/backend/app/core/config.py
+++ b/src/backend/app/core/config.py
@@ -1,5 +1,5 @@
import secrets
-from typing import Any, Dict, List, Optional, Union
+from typing import Any
from pydantic import AnyHttpUrl, BaseSettings, EmailStr, HttpUrl, PostgresDsn, validator
@@ -14,21 +14,21 @@ class Settings(BaseSettings):
# BACKEND_CORS_ORIGINS is a JSON-formatted list of origins
# e.g: '["http://localhost", "http://localhost:4200", "http://localhost:3000", \
# "http://localhost:8080", "http://local.dockertoolbox.tiangolo.com"]'
- BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = []
+ BACKEND_CORS_ORIGINS: list[AnyHttpUrl] = []
@validator("BACKEND_CORS_ORIGINS", pre=True)
- def assemble_cors_origins(cls, v: Union[str, List[str]]) -> Union[List[str], str]:
+ def assemble_cors_origins(cls, v: str | list[str]) -> list[str] | str:
if isinstance(v, str) and not v.startswith("["):
return [i.strip() for i in v.split(",")]
- elif isinstance(v, (list, str)):
+ elif isinstance(v, list | str):
return v
raise ValueError(v)
PROJECT_NAME: str
- SENTRY_DSN: Optional[HttpUrl] = None
+ SENTRY_DSN: HttpUrl | None = None
@validator("SENTRY_DSN", pre=True)
- def sentry_dsn_can_be_blank(cls, v: str) -> Optional[str]:
+ def sentry_dsn_can_be_blank(cls, v: str) -> str | None:
if len(v) == 0:
return None
return v
@@ -37,10 +37,10 @@ class Settings(BaseSettings):
POSTGRES_USER: str
POSTGRES_PASSWORD: str
POSTGRES_DB: str
- SQLALCHEMY_DATABASE_URI: Optional[PostgresDsn] = None
+ SQLALCHEMY_DATABASE_URI: PostgresDsn | None = None
@validator("SQLALCHEMY_DATABASE_URI", pre=True)
- def assemble_db_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
+ def assemble_db_connection(cls, v: str | None, values: dict[str, Any]) -> Any:
if isinstance(v, str):
return v
return PostgresDsn.build(
@@ -52,15 +52,15 @@ class Settings(BaseSettings):
)
SMTP_TLS: bool = True
- SMTP_PORT: Optional[int] = None
- SMTP_HOST: Optional[str] = None
- SMTP_USER: Optional[str] = None
- SMTP_PASSWORD: Optional[str] = None
- EMAILS_FROM_EMAIL: Optional[EmailStr] = None
- EMAILS_FROM_NAME: Optional[str] = None
+ SMTP_PORT: int | None = None
+ SMTP_HOST: str | None = None
+ SMTP_USER: str | None = None
+ SMTP_PASSWORD: str | None = None
+ EMAILS_FROM_EMAIL: EmailStr | None = None
+ EMAILS_FROM_NAME: str | None = None
@validator("EMAILS_FROM_NAME")
- def get_project_name(cls, v: Optional[str], values: Dict[str, Any]) -> str:
+ def get_project_name(cls, v: str | None, values: dict[str, Any]) -> str:
if not v:
return values["PROJECT_NAME"]
return v
@@ -70,7 +70,7 @@ class Settings(BaseSettings):
EMAILS_ENABLED: bool = False
@validator("EMAILS_ENABLED", pre=True)
- def get_emails_enabled(cls, v: bool, values: Dict[str, Any]) -> bool:
+ def get_emails_enabled(cls, v: bool, values: dict[str, Any]) -> bool:
return bool(
values.get("SMTP_HOST")
and values.get("SMTP_PORT")
diff --git a/src/backend/app/core/security.py b/src/backend/app/core/security.py
index 6c6ee8b..c9e5085 100644
--- a/src/backend/app/core/security.py
+++ b/src/backend/app/core/security.py
@@ -1,5 +1,5 @@
from datetime import datetime, timedelta
-from typing import Any, Union
+from typing import Any
from jose import jwt
from passlib.context import CryptContext
@@ -12,9 +12,7 @@ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
ALGORITHM = "HS256"
-def create_access_token(
- subject: Union[str, Any], expires_delta: timedelta = None
-) -> str:
+def create_access_token(subject: str | Any, expires_delta: timedelta = None) -> str:
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
diff --git a/src/backend/app/crud/__init__.py b/src/backend/app/crud/__init__.py
index d452138..ee949e5 100644
--- a/src/backend/app/crud/__init__.py
+++ b/src/backend/app/crud/__init__.py
@@ -1,16 +1,15 @@
-from .crud_item import item
-from .crud_user import user
-
# For a new basic set of CRUD operations you could just do
-
# from .base import CRUDBase
# from app.models.item import Item
# from app.schemas.item import ItemCreate, ItemUpdate
-
# item = CRUDBase[Item, ItemCreate, ItemUpdate](Item)
from sqlmodel import Session, select
+
from app.core.security import get_password_hash, verify_password
-from app.models import UserCreate, User
+from app.models import User, UserCreate
+
+from .crud_item import item as item
+from .crud_user import user as user
def create_user(*, session: Session, user_create: UserCreate) -> User:
@@ -30,9 +29,9 @@ def get_user_by_email(*, session: Session, email: str) -> User | None:
def authenticate(*, session: Session, email: str, password: str) -> User | None:
- user = get_user_by_email(session=session, email=email)
- if not user:
+ db_user = get_user_by_email(session=session, email=email)
+ if not db_user:
return None
- if not verify_password(password, user.hashed_password):
+ if not verify_password(password, db_user.hashed_password):
return None
- return user
+ return db_user
diff --git a/src/backend/app/crud/base.py b/src/backend/app/crud/base.py
index da93c49..6556e3c 100644
--- a/src/backend/app/crud/base.py
+++ b/src/backend/app/crud/base.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
+from typing import Any, Generic, TypeVar
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
@@ -10,7 +10,7 @@ UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
- def __init__(self, model: Type[ModelType]):
+ def __init__(self, model: type[ModelType]):
"""
CRUD object with default methods to Create, Read, Update, Delete (CRUD).
@@ -21,7 +21,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
"""
self.model = model
- def get(self, db: Session, id: Any) -> Optional[ModelType]:
+ def get(self, db: Session, id: Any) -> ModelType | None:
return db.query(self.model).filter(self.model.id == id).first()
def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:
@@ -37,7 +37,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
db: Session,
*,
db_obj: ModelType,
- obj_in: Union[UpdateSchemaType, Dict[str, Any]]
+ obj_in: UpdateSchemaType | dict[str, Any],
) -> ModelType:
obj_data = jsonable_encoder(db_obj)
if isinstance(obj_in, dict):
diff --git a/src/backend/app/crud/crud_item.py b/src/backend/app/crud/crud_item.py
index c62d80e..02c5060 100644
--- a/src/backend/app/crud/crud_item.py
+++ b/src/backend/app/crud/crud_item.py
@@ -1,5 +1,3 @@
-from typing import List
-
from fastapi.encoders import jsonable_encoder
from sqlalchemy.orm import Session
@@ -21,7 +19,7 @@ class CRUDItem(CRUDBase[Item, ItemCreate, ItemUpdate]):
def get_multi_by_owner(
self, db: Session, *, owner_id: int, skip: int = 0, limit: int = 100
- ) -> List[Item]:
+ ) -> list[Item]:
return (
db.query(self.model)
.filter(Item.owner_id == owner_id)
diff --git a/src/backend/app/crud/crud_user.py b/src/backend/app/crud/crud_user.py
index 1f2509b..b444502 100644
--- a/src/backend/app/crud/crud_user.py
+++ b/src/backend/app/crud/crud_user.py
@@ -1,4 +1,4 @@
-from typing import Any, Dict, Optional, Union
+from typing import Any
from sqlalchemy.orm import Session
@@ -9,7 +9,7 @@ from app.schemas.user import UserCreate, UserUpdate
class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
- def get_by_email(self, db: Session, *, email: str) -> Optional[User]:
+ def get_by_email(self, db: Session, *, email: str) -> User | None:
return db.query(User).filter(User.email == email).first()
def create(self, db: Session, *, obj_in: UserCreate) -> User:
@@ -25,7 +25,7 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
return db_obj
def update(
- self, db: Session, *, db_obj: User, obj_in: Union[UserUpdate, Dict[str, Any]]
+ self, db: Session, *, db_obj: User, obj_in: UserUpdate | dict[str, Any]
) -> User:
if isinstance(obj_in, dict):
update_data = obj_in
@@ -37,7 +37,7 @@ class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
update_data["hashed_password"] = hashed_password
return super().update(db, db_obj=db_obj, obj_in=update_data)
- def authenticate(self, db: Session, *, email: str, password: str) -> Optional[User]:
+ def authenticate(self, db: Session, *, email: str, password: str) -> User | None:
user = self.get_by_email(db, email=email)
if not user:
return None
diff --git a/src/backend/app/email-templates/build/new_account.html b/src/backend/app/email-templates/build/new_account.html
index 395c7bd..9d82b56 100644
--- a/src/backend/app/email-templates/build/new_account.html
+++ b/src/backend/app/email-templates/build/new_account.html
@@ -23,4 +23,4 @@
.mj-column-per-100 { width:100% !important; max-width: 100%; }
}
| {{ project_name }} - New Account | You have a new account: | Username: {{ username }} | Password: {{ password }} | | |
|