From c07a4264d27a4b83c4af6e1e59b978c017aeccb8 Mon Sep 17 00:00:00 2001 From: Olezhich Date: Thu, 23 Oct 2025 12:11:09 +0300 Subject: [PATCH 1/2] dev side work is integrated with ruff --- audiostats/application/dto_mappers.py | 2 +- audiostats/db/__init__.py | 2 -- audiostats/db/api.py | 2 +- audiostats/db/models.py | 2 +- audiostats/db/repositories.py | 4 +-- audiostats/db/uow.py | 17 +-------- audiostats/domain/__init__.py | 1 - audiostats/handlers/__init__.py | 2 -- audiostats/handlers/models.py | 2 +- audiostats/handlers/plst_handler.py | 2 +- tests/conftest.py | 14 ++++---- tests/db_fixture.py | 51 --------------------------- tests/test_db_api.py | 4 +-- 13 files changed, 17 insertions(+), 88 deletions(-) delete mode 100644 tests/db_fixture.py diff --git a/audiostats/application/dto_mappers.py b/audiostats/application/dto_mappers.py index d980637..4a04504 100644 --- a/audiostats/application/dto_mappers.py +++ b/audiostats/application/dto_mappers.py @@ -1,6 +1,6 @@ from audiostats.db.models import Album, Track -from audiostats.handlers import AlbumDTO, TrackDTO, StatusDTO +from audiostats.handlers.models import AlbumDTO, TrackDTO, StatusDTO def update_track_orm_f_dto(old : Track, new : TrackDTO) -> None: old.title = new.title diff --git a/audiostats/db/__init__.py b/audiostats/db/__init__.py index 7bd12af..e69de29 100644 --- a/audiostats/db/__init__.py +++ b/audiostats/db/__init__.py @@ -1,2 +0,0 @@ -from .models import Album, Track -from .api import DBApi \ No newline at end of file diff --git a/audiostats/db/api.py b/audiostats/db/api.py index 72b35f0..54f3442 100644 --- a/audiostats/db/api.py +++ b/audiostats/db/api.py @@ -4,7 +4,7 @@ from .uow import UnitOfWork -from audiostats.handlers import AlbumDTO +from audiostats.handlers.models import AlbumDTO from audiostats.db.session import SessionFactory diff --git a/audiostats/db/models.py b/audiostats/db/models.py index eed9e8d..3136992 100644 --- a/audiostats/db/models.py +++ b/audiostats/db/models.py @@ -3,7 +3,7 @@ from sqlalchemy import String, Integer, UniqueConstraint, ForeignKey, Float, Enum, DateTime, func from sqlalchemy.orm import Mapped, mapped_column, relationship, DeclarativeBase -from audiostats.domain import Status, Success +from audiostats.domain.enums import Status, Success MAX_PATH_FIELD_LEN = 200 MAX_STR_FIELD_LEN = 50 diff --git a/audiostats/db/repositories.py b/audiostats/db/repositories.py index 30a9f57..6567a44 100644 --- a/audiostats/db/repositories.py +++ b/audiostats/db/repositories.py @@ -4,9 +4,9 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload -from audiostats.domain import Status, Success +from audiostats.domain.enums import Status, Success from .models import Album, AlbumStatus -from audiostats.handlers import AlbumDTO +from audiostats.handlers.models import AlbumDTO from audiostats.application.dto_mappers import create_album_dto_f_orm, update_album_orm_meta_f_dto, update_track_orm_f_dto, create_track_orm_f_dto, diff_track, diff_album_meta diff --git a/audiostats/db/uow.py b/audiostats/db/uow.py index 1d5c2e0..580a53d 100644 --- a/audiostats/db/uow.py +++ b/audiostats/db/uow.py @@ -1,6 +1,6 @@ from contextlib import asynccontextmanager -from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker +from sqlalchemy.ext.asyncio import AsyncSession import logging from .repositories import AlbumRepository @@ -28,18 +28,3 @@ async def __call__(self): await self._session.rollback() raise - # async def __aenter__(self): - # async with self._session_factory as sf: - # await self._session = sf.get_session() - # self.albums = AlbumRepository(self._session) - # logger.debug(f'AlbumRepo initialised: {self.albums}, Current Session: {self._session}') - # return self - # - # async def __aexit__(self, exc_type, exc_val, exc_tb): - # if exc_type is not None: - # await self._session.rollback() - # else: - # await self._session.commit() - # await self._session.close() - # logger.debug(f'Session closed') - diff --git a/audiostats/domain/__init__.py b/audiostats/domain/__init__.py index e21cd6c..e69de29 100644 --- a/audiostats/domain/__init__.py +++ b/audiostats/domain/__init__.py @@ -1 +0,0 @@ -from .enums import Status, Success \ No newline at end of file diff --git a/audiostats/handlers/__init__.py b/audiostats/handlers/__init__.py index a9557c7..e69de29 100644 --- a/audiostats/handlers/__init__.py +++ b/audiostats/handlers/__init__.py @@ -1,2 +0,0 @@ -from .plst_handler import PlayListHandler -from .models import AlbumDTO, TrackDTO, StatusDTO \ No newline at end of file diff --git a/audiostats/handlers/models.py b/audiostats/handlers/models.py index ef324b8..6adc408 100644 --- a/audiostats/handlers/models.py +++ b/audiostats/handlers/models.py @@ -1,7 +1,7 @@ from collections import Counter from dataclasses import dataclass, field -from audiostats.domain import Status, Success +from audiostats.domain.enums import Status, Success @dataclass(slots=True, frozen=True) class StatusDTO: diff --git a/audiostats/handlers/plst_handler.py b/audiostats/handlers/plst_handler.py index 307bf35..c5b216c 100644 --- a/audiostats/handlers/plst_handler.py +++ b/audiostats/handlers/plst_handler.py @@ -4,7 +4,7 @@ import subprocess import logging -from typing import Any, TYPE_CHECKING +from typing import Any from collections.abc import Iterator from cuetools import TrackData from types import ModuleType diff --git a/tests/conftest.py b/tests/conftest.py index 8073f44..317a678 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,9 +5,9 @@ from cuetools import TrackData -from audiostats.handlers import PlayListHandler,AlbumDTO, TrackDTO, StatusDTO -from audiostats.handlers.plst_handler import LIBROSA_AVAILABLE -from audiostats.domain import Status, Success +from audiostats.handlers.plst_handler import PlayListHandler, LIBROSA_AVAILABLE +from audiostats.handlers.models import AlbumDTO, TrackDTO, StatusDTO +from audiostats.domain.enums import Status, Success @pytest.fixture def plst_handler_instance(): @@ -42,15 +42,15 @@ def read(self): if filename == '/music/Album1/Album1.cue': return '' if filename == '/music/Album2/Album2.cue': - tracks = [TrackData(index={f'01' : f'{i//2}{(i%2)*5}:00:00'}, track=f'0{i+1}', title=f'Track 0{i+1}', link='Album.flac') for i in range(5)] + tracks = [TrackData(index={'01' : f'{i//2}{(i%2)*5}:00:00'}, track=f'0{i+1}', title=f'Track 0{i+1}', link='Album.flac') for i in range(5)] cue_sheet = cuetools.AlbumData(performer='The Performer',title='The Title Of Album2', rem=cuetools.RemData(genre='Rock', date='1969'), tracks=tracks) return cuetools.dumps(cue_sheet) if filename == '/music/Album3/Album3.cue': - tracks = [TrackData(index={f'01' : f'00:00:00'}, track=f'0{i+1}', title=f'Track 0{i+1}', link=f'Track0{i+1}.flac') for i in range(5)] + tracks = [TrackData(index={'01' : '00:00:00'}, track=f'0{i+1}', title=f'Track 0{i+1}', link=f'Track0{i+1}.flac') for i in range(5)] cue_sheet = cuetools.AlbumData(performer='The Performer',title='The Title Of Album3', rem=cuetools.RemData(genre='Rock', date='1969'), tracks=tracks) return cuetools.dumps(cue_sheet) if filename == '/music/Album4/Album4.cue': - tracks = [TrackData(index={f'01' : f'{(i%3)//2}{((i%3)%2)*5}:00:00'}, track=f'0{i+1}', title=f'Track 0{i+1}', link=f'Side{'A' if i < 3 else 'B'}.flac') for i in range(6)] + tracks = [TrackData(index={'01' : f'{(i%3)//2}{((i%3)%2)*5}:00:00'}, track=f'0{i+1}', title=f'Track 0{i+1}', link=f'Side{'A' if i < 3 else 'B'}.flac') for i in range(6)] cue_sheet = cuetools.AlbumData(performer='The Performer',title='The Title Of Album4', rem=cuetools.RemData(genre='Rock', date='1970'), tracks=tracks) return cuetools.dumps(cue_sheet) else: @@ -96,7 +96,7 @@ def mock_get_duration(monkeypatch): def mock_duration(self, path_to_file: str) -> float: return duration_map.get(path_to_file) - from audiostats.handlers import PlayListHandler + from audiostats.handlers.plst_handler import PlayListHandler monkeypatch.setattr(PlayListHandler, '_get_audiofile_duration', mock_duration) @pytest.fixture() diff --git a/tests/db_fixture.py b/tests/db_fixture.py deleted file mode 100644 index 2f97e48..0000000 --- a/tests/db_fixture.py +++ /dev/null @@ -1,51 +0,0 @@ -# import logging -# -# import pytest -# from sqlalchemy.ext.asyncio import create_async_engine, AsyncEngine -# from sqlalchemy.ext.asyncio import async_sessionmaker -# -# from testcontainers.postgres import PostgresContainer -# -# from audiostats.db.models import Base -# -# logger = logging.getLogger(__name__) -# -# POSTGRES_CONTAINER = None -# TEST_ENGINE = None -# -# @pytest.fixture(scope="session") -# def event_loop(): -# import asyncio -# loop = asyncio.new_event_loop() -# yield loop -# loop.close() -# -# @pytest.fixture(scope="session") -# async def test_engine(): -# global POSTGRES_CONTAINER, TEST_ENGINE -# POSTGRES_CONTAINER = PostgresContainer("postgres:15") -# POSTGRES_CONTAINER.start() -# DATABASE_URL = POSTGRES_CONTAINER.get_connection_url() \ -# .replace("postgresql://", "postgresql+asyncpg://")\ -# .replace("postgresql+psycopg2://", "postgresql+asyncpg://") -# engine = create_async_engine(DATABASE_URL, echo=False) -# -# async with engine.begin() as conn: -# await conn.run_sync(Base.metadata.create_all) -# TEST_ENGINE = engine -# return engine -# -# @pytest.fixture(scope="session") -# async def test_session_factory(test_engine): -# engine = test_engine -# return async_sessionmaker(bind=await engine, expire_on_commit=False) -# -# @pytest.fixture(scope="session", autouse=True) -# async def cleanup_test_resources(): -# yield -# global TEST_ENGINE, POSTGRES_CONTAINER -# if TEST_ENGINE: -# await TEST_ENGINE.dispose() -# if POSTGRES_CONTAINER: -# POSTGRES_CONTAINER.stop() - diff --git a/tests/test_db_api.py b/tests/test_db_api.py index abae18f..bc0457d 100644 --- a/tests/test_db_api.py +++ b/tests/test_db_api.py @@ -6,8 +6,8 @@ import copy from audiostats.db.api import DBApi -from audiostats.handlers import TrackDTO, StatusDTO -from audiostats.domain import Status, Success +from audiostats.handlers.models import TrackDTO, StatusDTO +from audiostats.domain.enums import Status, Success logger = logging.getLogger(__name__) From a04c6f6594b2325f9175708def71f6246debe272 Mon Sep 17 00:00:00 2001 From: Olezhich Date: Thu, 23 Oct 2025 12:21:23 +0300 Subject: [PATCH 2/2] added ruff check into ci --- .github/workflows/run_tests.yml | 4 ++++ pyproject.toml | 3 +++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 8f646af..5ba3896 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -48,6 +48,10 @@ jobs: run: | poetry run alembic upgrade head + - name: Run Ruff linter check + run: | + poetry run ruff check . + - name: Run Mypy check run: | poetry run mypy . diff --git a/pyproject.toml b/pyproject.toml index bcce167..fe1cba3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,9 @@ dotenv = "^0.9.9" mypy = "^1.18.2" ruff = "^0.14.1" +[tool.ruff] +target-version = "py312" + [tool.mypy] python_version = "3.12" ignore_missing_imports = true