diff --git a/.vscode/settings.json b/.vscode/settings.json index d99f2f3..6b50668 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter" - }, - "python.formatting.provider": "none" -} \ No newline at end of file + "editor.formatOnSave": true, + "editor.defaultFormatter": "charliermarsh.ruff" + } +} diff --git a/src/api/v2/highscore.py b/src/api/v2/highscore.py new file mode 100644 index 0000000..b308369 --- /dev/null +++ b/src/api/v2/highscore.py @@ -0,0 +1,36 @@ +from fastapi import APIRouter, Query +from src.app.repositories.highscore import HighscoreLatest + +router = APIRouter() + + +@router.get("/highscore/latest") +async def get_highscore_latest( + player_id: int, + many: bool = False, + limit: int = Query(default=10, ge=0, le=10_000), +): + repo = HighscoreLatest() + if many: + data = await repo.get_many(start=player_id, limit=limit) + else: + data = await repo.get(id=player_id) + return data + + +# @router.get("/highscore") +# async def get_highscore( +# player_id: str = None, +# greater_than: bool = None, +# limit: int = Query(default=1_000, ge=0, le=10_000), +# ): +# return {} + + +# @router.get("/highscore/xp") +# async def get_highscore_xp( +# player_id: str = None, +# greater_than: bool = None, +# limit: int = Query(default=1_000, ge=0, le=10_000), +# ): +# return {} diff --git a/src/api/v2/player.py b/src/api/v2/player.py index bd49d85..36cb34a 100644 --- a/src/api/v2/player.py +++ b/src/api/v2/player.py @@ -1,5 +1,5 @@ from fastapi import APIRouter, Query -from src.app.models.player import Player +from src.app.repositories.player import Player router = APIRouter() @@ -11,8 +11,10 @@ async def get_player( greater_than: bool = None, limit: int = Query(default=1_000, ge=0, le=100_000), ): - player_model = Player() - data = await player_model.get_player( + # TODO: make use of abstract base class + repo = Player() + + data = await repo.get_player( player_id=player_id, player_name=player_name, greater_than=greater_than, diff --git a/src/app/models/.gitkeep b/src/app/repositories/.gitkeep similarity index 100% rename from src/app/models/.gitkeep rename to src/app/repositories/.gitkeep diff --git a/src/app/models/__init__.py b/src/app/repositories/__init__.py similarity index 100% rename from src/app/models/__init__.py rename to src/app/repositories/__init__.py diff --git a/src/app/repositories/abstract_repo.py b/src/app/repositories/abstract_repo.py new file mode 100644 index 0000000..fe94af2 --- /dev/null +++ b/src/app/repositories/abstract_repo.py @@ -0,0 +1,18 @@ +from abc import ABC, abstractmethod + +class AbstractAPI(ABC): + @abstractmethod + def get(self, id): + raise NotImplementedError + + @abstractmethod + def get_many(self, start, limit): + raise NotImplementedError + + @abstractmethod + def update(self, id, data): + raise NotImplementedError + + @abstractmethod + def delete(self, id): + raise NotImplementedError diff --git a/src/app/repositories/highscore.py b/src/app/repositories/highscore.py new file mode 100644 index 0000000..abe380a --- /dev/null +++ b/src/app/repositories/highscore.py @@ -0,0 +1,37 @@ +from src.core.database.models.highscore import ( + # playerHiscoreData, + PlayerHiscoreDataLatest, + # PlayerHiscoreDataXPChange, +) +from src.core.database.database import SessionFactory +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncResult, AsyncSession +from sqlalchemy.sql.expression import Select +from fastapi.encoders import jsonable_encoder +from src.app.repositories.abstract_repo import AbstractAPI + + +class HighscoreLatest(AbstractAPI): + def __init__(self) -> None: + super().__init__() + self.table = PlayerHiscoreDataLatest + + async def _simple_execute(self, sql) -> dict: + async with SessionFactory() as session: + session: AsyncSession + + result: AsyncResult = await session.execute(sql) + result = result.scalars().all() + return jsonable_encoder(result) + + async def get(self, id: int): + sql: Select = select(self.table) + sql = sql.where(self.table.Player_id == id) + return await self._simple_execute(sql) + + async def get_many(self, start: int, limit: int = 5000): + sql: Select = select(self.table) + sql = sql.where(self.table.Player_id > start) + sql = sql.limit(limit) + return await self._simple_execute(sql) diff --git a/src/app/models/player.py b/src/app/repositories/player.py similarity index 97% rename from src/app/models/player.py rename to src/app/repositories/player.py index 13d7d9b..dbbb6d6 100644 --- a/src/app/models/player.py +++ b/src/app/repositories/player.py @@ -1,34 +1,34 @@ -from src.core.database.models.player import Player as dbPlayer -from src.core.database.database import SessionFactory -from sqlalchemy.ext.asyncio import AsyncSession -from sqlalchemy import delete, insert, select, update -from sqlalchemy.ext.asyncio import AsyncResult, AsyncSession -from sqlalchemy.sql.expression import Delete, Insert, Select, Update, and_ -from fastapi.encoders import jsonable_encoder - - -class Player: - def __init__(self) -> None: - pass - - async def get_player( - self, player_id: int, player_name: str, greater_than: bool, limit: int = 1_000 - ): - table = dbPlayer - sql_select: Select = select(table) - sql_select = sql_select.limit(limit) - - if player_name: - sql_select = sql_select.where(dbPlayer.name >= player_name) - - if greater_than: - sql_select = sql_select.where(dbPlayer.id >= player_id) - elif player_id: - sql_select = sql_select.where(dbPlayer.id == player_id) - - async with SessionFactory() as session: - session: AsyncSession - - result: AsyncResult = await session.execute(sql_select) - result = result.scalars().all() - return jsonable_encoder(result) +from src.core.database.models.player import Player as dbPlayer +from src.core.database.database import SessionFactory +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import delete, insert, select, update +from sqlalchemy.ext.asyncio import AsyncResult, AsyncSession +from sqlalchemy.sql.expression import Delete, Insert, Select, Update, and_ +from fastapi.encoders import jsonable_encoder + + +class Player: + def __init__(self) -> None: + pass + + async def get_player( + self, player_id: int, player_name: str, greater_than: bool, limit: int = 1_000 + ): + table = dbPlayer + sql_select: Select = select(table) + sql_select = sql_select.limit(limit) + + if player_name: + sql_select = sql_select.where(dbPlayer.name >= player_name) + + if greater_than: + sql_select = sql_select.where(dbPlayer.id >= player_id) + elif player_id: + sql_select = sql_select.where(dbPlayer.id == player_id) + + async with SessionFactory() as session: + session: AsyncSession + + result: AsyncResult = await session.execute(sql_select) + result = result.scalars().all() + return jsonable_encoder(result) diff --git a/src/app/views/response/highscore.py b/src/app/views/response/highscore.py new file mode 100644 index 0000000..b5ad6bc --- /dev/null +++ b/src/app/views/response/highscore.py @@ -0,0 +1,106 @@ +from pydantic import BaseModel, ConfigDict +from datetime import datetime, date +from typing import Optional + +class PlayerHiscoreData(BaseModel): + model_config = ConfigDict(from_attributes=True) + + id: Optional[int] = None + timestamp: datetime = datetime.utcnow() + ts_date: Optional[date] = None + Player_id: int + total: int + attack: int + defence: int + strength: int + hitpoints: int + ranged: int + prayer: int + magic: int + cooking: int + woodcutting: int + fletching: int + fishing: int + firemaking: int + crafting: int + smithing: int + mining: int + herblore: int + agility: int + thieving: int + slayer: int + farming: int + runecraft: int + hunter: int + construction: int + league: int + bounty_hunter_hunter: int + bounty_hunter_rogue: int + cs_all: int + cs_beginner: int + cs_easy: int + cs_medium: int + cs_hard: int + cs_elite: int + cs_master: int + lms_rank: int + soul_wars_zeal: int + abyssal_sire: int + alchemical_hydra: int + barrows_chests: int + bryophyta: int + callisto: int + cerberus: int + chambers_of_xeric: int + chambers_of_xeric_challenge_mode: int + chaos_elemental: int + chaos_fanatic: int + commander_zilyana: int + corporeal_beast: int + crazy_archaeologist: int + dagannoth_prime: int + dagannoth_rex: int + dagannoth_supreme: int + deranged_archaeologist: int + general_graardor: int + giant_mole: int + grotesque_guardians: int + hespori: int + kalphite_queen: int + king_black_dragon: int + kraken: int + kreearra: int + kril_tsutsaroth: int + mimic: int + nightmare: int + nex: int = 0 + phosanis_nightmare: int + obor: int + phantom_muspah: int = 0 + sarachnis: int + scorpia: int + skotizo: int + tempoross: int = 0 + the_gauntlet: int + the_corrupted_gauntlet: int + theatre_of_blood: int + theatre_of_blood_hard: int = 0 + thermonuclear_smoke_devil: int + tombs_of_amascut: int = 0 + tombs_of_amascut_expert: int = 0 + tzkal_zuk: int + tztok_jad: int + venenatis: int + vetion: int + vorkath: int + wintertodt: int + zalcano: int + zulrah: int + rifts_closed: int = 0 + artio: int = 0 + calvarion: int = 0 + duke_sucellus: int = 0 + spindel: int = 0 + the_leviathan: int = 0 + the_whisperer: int = 0 + vardorvis: int = 0 diff --git a/src/core/__init__.py b/src/core/__init__.py new file mode 100644 index 0000000..e1bf776 --- /dev/null +++ b/src/core/__init__.py @@ -0,0 +1,2 @@ +from . import logging +# needed for log formatting \ No newline at end of file diff --git a/src/core/database/models/highscore.py b/src/core/database/models/highscore.py new file mode 100644 index 0000000..b5e33f4 --- /dev/null +++ b/src/core/database/models/highscore.py @@ -0,0 +1,351 @@ +from sqlalchemy import ( + BigInteger, + Column, + Date, + DateTime, + ForeignKey, + Index, + Integer, + text, +) + +from sqlalchemy.ext.declarative import declarative_base + + +Base = declarative_base() +metadata = Base.metadata + +class playerHiscoreData(Base): + __tablename__ = "playerHiscoreData" + __table_args__ = ( + Index("Unique_player_time", "Player_id", "timestamp", unique=True), + Index("Unique_player_date", "Player_id", "ts_date", unique=True), + ) + + id = Column(Integer, primary_key=True, autoincrement=True) + timestamp = Column( + DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP") + ) + ts_date = Column(Date) + Player_id = Column( + ForeignKey("Players.id", ondelete="RESTRICT", onupdate="RESTRICT"), + nullable=False, + ) + total = Column(BigInteger) + attack = Column(Integer) + defence = Column(Integer) + strength = Column(Integer) + hitpoints = Column(Integer) + ranged = Column(Integer) + prayer = Column(Integer) + magic = Column(Integer) + cooking = Column(Integer) + woodcutting = Column(Integer) + fletching = Column(Integer) + fishing = Column(Integer) + firemaking = Column(Integer) + crafting = Column(Integer) + smithing = Column(Integer) + mining = Column(Integer) + herblore = Column(Integer) + agility = Column(Integer) + thieving = Column(Integer) + slayer = Column(Integer) + farming = Column(Integer) + runecraft = Column(Integer) + hunter = Column(Integer) + construction = Column(Integer) + league = Column(Integer) + bounty_hunter_hunter = Column(Integer) + bounty_hunter_rogue = Column(Integer) + cs_all = Column(Integer) + cs_beginner = Column(Integer) + cs_easy = Column(Integer) + cs_medium = Column(Integer) + cs_hard = Column(Integer) + cs_elite = Column(Integer) + cs_master = Column(Integer) + lms_rank = Column(Integer) + soul_wars_zeal = Column(Integer) + abyssal_sire = Column(Integer) + alchemical_hydra = Column(Integer) + barrows_chests = Column(Integer) + bryophyta = Column(Integer) + callisto = Column(Integer) + cerberus = Column(Integer) + chambers_of_xeric = Column(Integer) + chambers_of_xeric_challenge_mode = Column(Integer) + chaos_elemental = Column(Integer) + chaos_fanatic = Column(Integer) + commander_zilyana = Column(Integer) + corporeal_beast = Column(Integer) + crazy_archaeologist = Column(Integer) + dagannoth_prime = Column(Integer) + dagannoth_rex = Column(Integer) + dagannoth_supreme = Column(Integer) + deranged_archaeologist = Column(Integer) + general_graardor = Column(Integer) + giant_mole = Column(Integer) + grotesque_guardians = Column(Integer) + hespori = Column(Integer) + kalphite_queen = Column(Integer) + king_black_dragon = Column(Integer) + kraken = Column(Integer) + kreearra = Column(Integer) + kril_tsutsaroth = Column(Integer) + mimic = Column(Integer) + nightmare = Column(Integer) + nex = Column(Integer) + phosanis_nightmare = Column(Integer) + obor = Column(Integer) + phantom_muspah = Column(Integer) + sarachnis = Column(Integer) + scorpia = Column(Integer) + skotizo = Column(Integer) + tempoross = Column(Integer) + the_gauntlet = Column(Integer) + the_corrupted_gauntlet = Column(Integer) + theatre_of_blood = Column(Integer) + theatre_of_blood_hard = Column(Integer) + thermonuclear_smoke_devil = Column(Integer) + tombs_of_amascut = Column(Integer) + tombs_of_amascut_expert = Column(Integer) + tzkal_zuk = Column(Integer) + tztok_jad = Column(Integer) + venenatis = Column(Integer) + vetion = Column(Integer) + vorkath = Column(Integer) + wintertodt = Column(Integer) + zalcano = Column(Integer) + zulrah = Column(Integer) + + # New columns added + rifts_closed = Column(Integer, default=0) + artio = Column(Integer, default=0) + calvarion = Column(Integer, default=0) + duke_sucellus = Column(Integer, default=0) + spindel = Column(Integer, default=0) + the_leviathan = Column(Integer, default=0) + the_whisperer = Column(Integer, default=0) + vardorvis = Column(Integer, default=0) + + +class PlayerHiscoreDataLatest(Base): + __tablename__ = "playerHiscoreDataLatest" + + id = Column(Integer, primary_key=True) + timestamp = Column( + DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP") + ) + ts_date = Column(Date) + Player_id = Column( + ForeignKey("Players.id", ondelete="RESTRICT", onupdate="RESTRICT"), + nullable=False, + unique=True, + ) + total = Column(BigInteger) + attack = Column(Integer) + defence = Column(Integer) + strength = Column(Integer) + hitpoints = Column(Integer) + ranged = Column(Integer) + prayer = Column(Integer) + magic = Column(Integer) + cooking = Column(Integer) + woodcutting = Column(Integer) + fletching = Column(Integer) + fishing = Column(Integer) + firemaking = Column(Integer) + crafting = Column(Integer) + smithing = Column(Integer) + mining = Column(Integer) + herblore = Column(Integer) + agility = Column(Integer) + thieving = Column(Integer) + slayer = Column(Integer) + farming = Column(Integer) + runecraft = Column(Integer) + hunter = Column(Integer) + construction = Column(Integer) + league = Column(Integer) + bounty_hunter_hunter = Column(Integer) + bounty_hunter_rogue = Column(Integer) + cs_all = Column(Integer) + cs_beginner = Column(Integer) + cs_easy = Column(Integer) + cs_medium = Column(Integer) + cs_hard = Column(Integer) + cs_elite = Column(Integer) + cs_master = Column(Integer) + lms_rank = Column(Integer) + soul_wars_zeal = Column(Integer) + abyssal_sire = Column(Integer) + alchemical_hydra = Column(Integer) + barrows_chests = Column(Integer) + bryophyta = Column(Integer) + callisto = Column(Integer) + cerberus = Column(Integer) + chambers_of_xeric = Column(Integer) + chambers_of_xeric_challenge_mode = Column(Integer) + chaos_elemental = Column(Integer) + chaos_fanatic = Column(Integer) + commander_zilyana = Column(Integer) + corporeal_beast = Column(Integer) + crazy_archaeologist = Column(Integer) + dagannoth_prime = Column(Integer) + dagannoth_rex = Column(Integer) + dagannoth_supreme = Column(Integer) + deranged_archaeologist = Column(Integer) + general_graardor = Column(Integer) + giant_mole = Column(Integer) + grotesque_guardians = Column(Integer) + hespori = Column(Integer) + kalphite_queen = Column(Integer) + king_black_dragon = Column(Integer) + kraken = Column(Integer) + kreearra = Column(Integer) + kril_tsutsaroth = Column(Integer) + mimic = Column(Integer) + nightmare = Column(Integer) + nex = Column(Integer) + phosanis_nightmare = Column(Integer) + obor = Column(Integer) + phantom_muspah = Column(Integer) + sarachnis = Column(Integer) + scorpia = Column(Integer) + skotizo = Column(Integer) + Tempoross = Column(Integer, nullable=False) + the_gauntlet = Column(Integer) + the_corrupted_gauntlet = Column(Integer) + theatre_of_blood = Column(Integer) + theatre_of_blood_hard = Column(Integer) + thermonuclear_smoke_devil = Column(Integer) + tombs_of_amascut = Column(Integer) + tombs_of_amascut_expert = Column(Integer) + tzkal_zuk = Column(Integer) + tztok_jad = Column(Integer) + venenatis = Column(Integer) + vetion = Column(Integer) + vorkath = Column(Integer) + wintertodt = Column(Integer) + zalcano = Column(Integer) + zulrah = Column(Integer) + + # New columns added + rifts_closed = Column(Integer, default=0) + artio = Column(Integer, default=0) + calvarion = Column(Integer, default=0) + duke_sucellus = Column(Integer, default=0) + spindel = Column(Integer, default=0) + the_leviathan = Column(Integer, default=0) + the_whisperer = Column(Integer, default=0) + vardorvis = Column(Integer, default=0) +class PlayerHiscoreDataXPChange(Base): + __tablename__ = "playerHiscoreDataXPChange" + + id = Column(Integer, primary_key=True) + timestamp = Column( + DateTime, nullable=False, server_default=text("CURRENT_TIMESTAMP") + ) + ts_date = Column(Date) + Player_id = Column( + ForeignKey("Players.id", ondelete="RESTRICT", onupdate="RESTRICT"), + nullable=False, + index=True, + ) + total = Column(BigInteger) + attack = Column(Integer) + defence = Column(Integer) + strength = Column(Integer) + hitpoints = Column(Integer) + ranged = Column(Integer) + prayer = Column(Integer) + magic = Column(Integer) + cooking = Column(Integer) + woodcutting = Column(Integer) + fletching = Column(Integer) + fishing = Column(Integer) + firemaking = Column(Integer) + crafting = Column(Integer) + smithing = Column(Integer) + mining = Column(Integer) + herblore = Column(Integer) + agility = Column(Integer) + thieving = Column(Integer) + slayer = Column(Integer) + farming = Column(Integer) + runecraft = Column(Integer) + hunter = Column(Integer) + construction = Column(Integer) + league = Column(Integer) + bounty_hunter_hunter = Column(Integer) + bounty_hunter_rogue = Column(Integer) + cs_all = Column(Integer) + cs_beginner = Column(Integer) + cs_easy = Column(Integer) + cs_medium = Column(Integer) + cs_hard = Column(Integer) + cs_elite = Column(Integer) + cs_master = Column(Integer) + lms_rank = Column(Integer) + soul_wars_zeal = Column(Integer) + abyssal_sire = Column(Integer) + alchemical_hydra = Column(Integer) + barrows_chests = Column(Integer) + bryophyta = Column(Integer) + callisto = Column(Integer) + cerberus = Column(Integer) + chambers_of_xeric = Column(Integer) + chambers_of_xeric_challenge_mode = Column(Integer) + chaos_elemental = Column(Integer) + chaos_fanatic = Column(Integer) + commander_zilyana = Column(Integer) + corporeal_beast = Column(Integer) + crazy_archaeologist = Column(Integer) + dagannoth_prime = Column(Integer) + dagannoth_rex = Column(Integer) + dagannoth_supreme = Column(Integer) + deranged_archaeologist = Column(Integer) + general_graardor = Column(Integer) + giant_mole = Column(Integer) + grotesque_guardians = Column(Integer) + hespori = Column(Integer) + kalphite_queen = Column(Integer) + king_black_dragon = Column(Integer) + kraken = Column(Integer) + kreearra = Column(Integer) + kril_tsutsaroth = Column(Integer) + mimic = Column(Integer) + nightmare = Column(Integer) + nex = Column(Integer) + obor = Column(Integer) + phantom_muspah = Column(Integer) + phosanis_nightmare = Column(Integer) + sarachnis = Column(Integer) + scorpia = Column(Integer) + skotizo = Column(Integer) + Tempoross = Column(Integer, nullable=False) + the_gauntlet = Column(Integer) + the_corrupted_gauntlet = Column(Integer) + theatre_of_blood = Column(Integer) + theatre_of_blood_hard = Column(Integer) + thermonuclear_smoke_devil = Column(Integer) + tombs_of_amascut = Column(Integer) + tombs_of_amascut_expert = Column(Integer) + tzkal_zuk = Column(Integer) + tztok_jad = Column(Integer) + venenatis = Column(Integer) + vetion = Column(Integer) + vorkath = Column(Integer) + wintertodt = Column(Integer) + zalcano = Column(Integer) + zulrah = Column(Integer) + # New columns added + rifts_closed = Column(Integer, default=0) + artio = Column(Integer, default=0) + calvarion = Column(Integer, default=0) + duke_sucellus = Column(Integer, default=0) + spindel = Column(Integer, default=0) + the_leviathan = Column(Integer, default=0) + the_whisperer = Column(Integer, default=0) + vardorvis = Column(Integer, default=0) \ No newline at end of file diff --git a/src/core/logging_config.py b/src/core/logging.py similarity index 96% rename from src/core/logging_config.py rename to src/core/logging.py index d9918b7..a681659 100644 --- a/src/core/logging_config.py +++ b/src/core/logging.py @@ -1,43 +1,43 @@ -import json -import logging -import sys -import warnings - -from .config import settings - -# # log formatting -formatter = logging.Formatter( - json.dumps( - { - "ts": "%(asctime)s", - "name": "%(name)s", - "function": "%(funcName)s", - "level": "%(levelname)s", - "msg": json.dumps("%(message)s"), - } - ) -) - -stream_handler = logging.StreamHandler(sys.stdout) - -stream_handler.setFormatter(formatter) - -handlers = [stream_handler] - -logging.basicConfig(level=logging.DEBUG, handlers=handlers) - -# set imported loggers to warning -logging.getLogger("urllib3").setLevel(logging.DEBUG) -logging.getLogger("uvicorn").setLevel(logging.DEBUG) -logging.getLogger("aiomysql").setLevel(logging.ERROR) -logging.getLogger("aiokafka").setLevel(logging.WARNING) - -# if settings.ENV == "PRD": -# uvicorn_error = logging.getLogger("uvicorn.error") -# uvicorn_error.disabled = True -# uvicorn_access = logging.getLogger("uvicorn.access") -# uvicorn_access.disabled = True - -# # https://github.com/aio-libs/aiomysql/issues/103 -# # https://github.com/coleifer/peewee/issues/2229 -# warnings.filterwarnings("ignore", ".*Duplicate entry.*") +import json +import logging +import sys +import warnings + +from .config import settings + +# # log formatting +formatter = logging.Formatter( + json.dumps( + { + "ts": "%(asctime)s", + "name": "%(name)s", + "function": "%(funcName)s", + "level": "%(levelname)s", + "msg": json.dumps("%(message)s"), + } + ) +) + +stream_handler = logging.StreamHandler(sys.stdout) + +stream_handler.setFormatter(formatter) + +handlers = [stream_handler] + +logging.basicConfig(level=logging.DEBUG, handlers=handlers) + +# set imported loggers to warning +logging.getLogger("urllib3").setLevel(logging.DEBUG) +logging.getLogger("uvicorn").setLevel(logging.DEBUG) +logging.getLogger("aiomysql").setLevel(logging.ERROR) +logging.getLogger("aiokafka").setLevel(logging.WARNING) + +# if settings.ENV == "PRD": +# uvicorn_error = logging.getLogger("uvicorn.error") +# uvicorn_error.disabled = True +# uvicorn_access = logging.getLogger("uvicorn.access") +# uvicorn_access.disabled = True + +# # https://github.com/aio-libs/aiomysql/issues/103 +# # https://github.com/coleifer/peewee/issues/2229 +# warnings.filterwarnings("ignore", ".*Duplicate entry.*") diff --git a/src/core/server.py b/src/core/server.py index ed83ec3..8abe404 100644 --- a/src/core/server.py +++ b/src/core/server.py @@ -1,4 +1,3 @@ -import asyncio import logging from fastapi import FastAPI @@ -8,7 +7,7 @@ from src import api from src.core.fastapi.middleware.logging import LoggingMiddleware -from . import logging_config # needed for log formatting + logger = logging.getLogger(__name__)