1
0
mirror of https://github.com/ijaric/voice_assistant.git synced 2025-12-17 12:26:17 +00:00

Review fix

This commit is contained in:
2023-09-19 17:16:30 +03:00
parent cb98517f67
commit cf1a29d520
37 changed files with 55 additions and 70 deletions

View File

View File

View File

@@ -0,0 +1,25 @@
import uuid
import sqlalchemy
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.ext.declarative import declared_attr
class BaseMixin:
@declared_attr
def id(cls):
return sqlalchemy.Column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
unique=True,
nullable=False,
)
@declared_attr
def created_at(cls):
return sqlalchemy.Column(sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now())
@declared_attr
def updated_at(cls):
return sqlalchemy.Column(sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now())

View File

@@ -0,0 +1,8 @@
import uuid
import pydantic
class Token(pydantic.BaseModel):
sub: uuid.UUID
exp: int | None = None

View File

@@ -0,0 +1,27 @@
import fastapi
from jose import JWTError, jwt
from pydantic import ValidationError
from lib.api import schemas as app_schemas
from lib.app import settings as app_settings
app = fastapi.FastAPI()
settings = app_settings.get_settings()
security = fastapi.security.HTTPBearer()
def get_token_data(
authorization: fastapi.security.HTTPAuthorizationCredentials = fastapi.Security(security),
) -> app_schemas.entity.Token:
token = authorization.credentials
try:
secret_key = settings.jwt_secret_key
payload = jwt.decode(token, secret_key, algorithms=["HS256"])
return app_schemas.entity.Token(**payload)
except (JWTError, ValidationError):
raise fastapi.HTTPException(
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)

View File

View File

@@ -0,0 +1,41 @@
import logging
import logging.config as logging_config
import lib.api.handlers as admin_api_handlers
import fastapi
from .logger import LOGGING
from .settings import get_settings
logging_config.dictConfig(LOGGING)
logger = logging.getLogger(__name__)
class Application:
def __init__(self) -> None:
self.settings = get_settings()
self.logger = logging.getLogger(__name__)
self.producer = None
def create_app(self) -> fastapi.FastAPI:
app = fastapi.FastAPI(
title="FastAPI",
version="0.1.0",
docs_url="/api/openapi",
openapi_url="/api/openapi.json",
default_response_class=fastapi.responses.ORJSONResponse,
)
# app.include_router(admin_api_handlers.user_router, prefix="/api/v1/users", tags=["users"])
# app.include_router(admin_api_handlers.movie_router, prefix="/api/v1/movies", tags=["movies"])
@app.on_event("startup")
async def startup_event():
self.logger.info("Starting server")
@app.on_event("shutdown")
async def shutdown_event():
self.logger.info("Shutting down server")
return app

View File

@@ -0,0 +1,69 @@
import pydantic_settings
class LoggingSettings(pydantic_settings.BaseSettings):
log_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
log_default_handlers: list[str] = [
"console",
]
log_level_handlers: str = "DEBUG"
log_level_loggers: str = "INFO"
log_level_root: str = "INFO"
log_settings = LoggingSettings()
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"verbose": {"format": log_settings.log_format},
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(levelprefix)s %(message)s",
"use_colors": None,
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(levelprefix)s %(client_addr)s - '%(request_line)s' %(status_code)s",
},
},
"handlers": {
"console": {
"level": log_settings.log_level_handlers,
"class": "logging.StreamHandler",
"formatter": "verbose",
},
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout",
},
},
"loggers": {
"": {
"handlers": log_settings.log_default_handlers,
"level": log_settings.log_level_loggers,
},
"uvicorn.error": {
"level": log_settings.log_level_loggers,
},
"uvicorn.access": {
"handlers": ["access"],
"level": log_settings.log_level_loggers,
"propagate": False,
},
},
"root": {
"level": log_settings.log_level_root,
"formatter": "verbose",
"handlers": log_settings.log_default_handlers,
},
}

View File

@@ -0,0 +1,36 @@
import functools
import pydantic_settings
from dotenv import load_dotenv
from pydantic import Field
load_dotenv(".env.dev")
class DbSettings(pydantic_settings.BaseSettings):
model_config = pydantic_settings.SettingsConfigDict(env_prefix="db_")
host: str = "localhost"
port: int = 5432
user: str
password: str
name: str
class ApiSettings(pydantic_settings.BaseSettings):
model_config = pydantic_settings.SettingsConfigDict(env_prefix="server_")
host: str = "0.0.0.0"
port: int = 8000
class Settings(pydantic_settings.BaseSettings):
db: DbSettings = Field(default_factory=DbSettings)
api: ApiSettings = Field(default_factory=ApiSettings)
jwt_secret_key: str
@functools.lru_cache
def get_settings() -> Settings:
return Settings()

View File

View File

@@ -0,0 +1,3 @@
# from libs.api.models.movies import *
# from libs.api.models.notification_templates import *
# from libs.api.models.users import *

View File

@@ -0,0 +1,31 @@
import typing
from lib.app import settings as app_settings
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase
settings = app_settings.get_settings()
# Создаём базовый класс для будущих моделей
class Base(DeclarativeBase):
pass
# Создаём движок
# Настройки подключения к БД передаём из переменных окружения, которые заранее загружены в файл настроек
database_dsn = (
f"postgresql+asyncpg://{settings.db.user}:{settings.db.password}"
f"@{settings.db.host}:{settings.db.port}/{settings.db.name}"
)
engine = create_async_engine(database_dsn, echo=True, future=True)
async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_session() -> typing.AsyncGenerator[AsyncSession, typing.Any]:
async with async_session() as session:
yield session