From 5f03ff995d3e2a1b0366bca33c4dc58dc58df59b Mon Sep 17 00:00:00 2001 From: Olezhich Date: Tue, 16 Sep 2025 20:10:19 +0300 Subject: [PATCH] added album status table and migrations --- audiostats/application/__init__.py | 1 + audiostats/application/dto_mappers.py | 13 ----- audiostats/application/models.py | 11 +++++ audiostats/db/models.py | 32 ++++++++----- audiostats/db/repositories.py | 4 +- .../a337b3f88bf1_added_album_status.py | 47 +++++++++++++++++++ 6 files changed, 81 insertions(+), 27 deletions(-) create mode 100644 audiostats/application/models.py create mode 100644 migrations/versions/a337b3f88bf1_added_album_status.py diff --git a/audiostats/application/__init__.py b/audiostats/application/__init__.py index e69de29..b2c762e 100644 --- a/audiostats/application/__init__.py +++ b/audiostats/application/__init__.py @@ -0,0 +1 @@ +from .models import Status, Success \ No newline at end of file diff --git a/audiostats/application/dto_mappers.py b/audiostats/application/dto_mappers.py index 4e448a1..c5bb593 100644 --- a/audiostats/application/dto_mappers.py +++ b/audiostats/application/dto_mappers.py @@ -2,19 +2,6 @@ from audiostats.handlers import AlbumDTO, TrackDTO - -# def create_album_f_dto(album : AlbumDTO) -> Album: -# return Album(title=album.title, -# performer=album.performer, -# year=album.year, -# path=album.path, -# cover=album.cover, -# tracks=[Track(title=track.title, -# number=track.number, -# path=track.path, -# offset=track.offset, -# duration=track.duration) for track in album.tracks]) - def update_track_orm_f_dto(old : Track, new : TrackDTO) -> None: old.title = new.title old.number = new.number diff --git a/audiostats/application/models.py b/audiostats/application/models.py new file mode 100644 index 0000000..3cb3d1b --- /dev/null +++ b/audiostats/application/models.py @@ -0,0 +1,11 @@ +from enum import StrEnum + +class Status(StrEnum): + ADDED = 'added' + MODIFIED = 'modified' + +class Success(StrEnum): + SUCCESS = 'success' + WARNING = 'warning' + ERROR = 'error' + diff --git a/audiostats/db/models.py b/audiostats/db/models.py index 4aaeec1..59d9f18 100644 --- a/audiostats/db/models.py +++ b/audiostats/db/models.py @@ -1,8 +1,10 @@ from datetime import datetime -from sqlalchemy import String, Integer, UniqueConstraint, ForeignKey, Float, DATETIME +from sqlalchemy import String, Integer, UniqueConstraint, ForeignKey, Float, Enum, DateTime from sqlalchemy.orm import declarative_base, Mapped, mapped_column, relationship +from audiostats.application import Status, Success + Base = declarative_base() MAX_PATH_FIELD_LEN = 200 @@ -34,7 +36,8 @@ class Album(Base): year : Mapped[int | None] = mapped_column(Integer, nullable=True) path : Mapped[str | None] = mapped_column(String(MAX_PATH_FIELD_LEN), nullable=True) cover : Mapped[str | None] = mapped_column(String(MAX_PATH_FIELD_LEN), nullable=True) - tracks : Mapped[list['Track']] = relationship('Track', back_populates='album') + tracks : Mapped[list['Track']] = relationship('Track', back_populates='album', lazy='noload') + album_statuses : Mapped[list['AlbumStatus']] = relationship('AlbumStatus', back_populates='album', lazy='noload') def __repr__(self): return f'' @@ -63,7 +66,7 @@ class Track(Base): path : Mapped[str] = mapped_column(String(MAX_PATH_FIELD_LEN), nullable=True) offset : Mapped[float | None] = mapped_column(Float, nullable=True) duration : Mapped[float | None] = mapped_column(Float, nullable=True) - album : Mapped["Album"]= relationship('Album', back_populates='tracks') + album : Mapped["Album"]= relationship('Album', back_populates='tracks', lazy='noload') def __repr__(self): return f'' @@ -72,15 +75,18 @@ def __str__(self): return f'{self.number} - {self.title}' -# class AlbumStatus(Base): -# """Represents **album_statuses** line as orm object""" -# -# __tablename__ = 'album_statuses' -# -# id : Mapped[int] = mapped_column(Integer, primary_key=True) -# album_id : Mapped[int] = mapped_column(Integer, ForeignKey('albums.id', ondelete='CASCADE'), index=True) -# time_stamp : Mapped[datetime] = mapped_column(DATETIME, nullable=False) -# status : Mapped[] -# success : Mapped[] +class AlbumStatus(Base): + """Represents **album_statuses** line as orm object""" + + __tablename__ = 'album_statuses' + + id : Mapped[int] = mapped_column(Integer, primary_key=True) + album_id : Mapped[int] = mapped_column(Integer, ForeignKey('albums.id', ondelete='CASCADE'), index=True) + time_stamp : Mapped[datetime] = mapped_column(DateTime, nullable=False) + status : Mapped[Status] = mapped_column(Enum(Status), nullable=False) + success : Mapped[Success] = mapped_column(Enum(Success), nullable=False) + album : Mapped["Album"] = relationship('Album', back_populates='album_statuses', lazy='noload') + + diff --git a/audiostats/db/repositories.py b/audiostats/db/repositories.py index db099f7..33f8f43 100644 --- a/audiostats/db/repositories.py +++ b/audiostats/db/repositories.py @@ -3,7 +3,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload -from .models import Album +from .models import Album, AlbumStatus from audiostats.handlers 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 @@ -17,10 +17,12 @@ def __init__(self, session : AsyncSession): async def upsert(self, album_data : AlbumDTO): album = await self.find_by_title_performer(album_data.title, album_data.performer) + # album_status = AlbumStatus() if not album: album = Album() self._session.add(album) + update_album_orm_meta_f_dto(album, album_data) old_tracks_by_title = {track.title: track for track in album.tracks} diff --git a/migrations/versions/a337b3f88bf1_added_album_status.py b/migrations/versions/a337b3f88bf1_added_album_status.py new file mode 100644 index 0000000..54026ac --- /dev/null +++ b/migrations/versions/a337b3f88bf1_added_album_status.py @@ -0,0 +1,47 @@ +"""added album status + +Revision ID: a337b3f88bf1 +Revises: bd8d699fa622 +Create Date: 2025-09-16 20:08:54.362324 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'a337b3f88bf1' +down_revision: Union[str, Sequence[str], None] = 'bd8d699fa622' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('album_statuses', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('album_id', sa.Integer(), nullable=False), + sa.Column('time_stamp', sa.DateTime(), nullable=False), + sa.Column('status', sa.Enum('ADDED', 'MODIFIED', name='status'), nullable=False), + sa.Column('success', sa.Enum('SUCCESS', 'WARNING', 'ERROR', name='success'), nullable=False), + sa.ForeignKeyConstraint(['album_id'], ['albums.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_album_statuses_album_id'), 'album_statuses', ['album_id'], unique=False) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index(op.f('ix_album_statuses_album_id'), table_name='album_statuses') + op.drop_table('album_statuses') + + status_enum = sa.Enum('ADDED', 'MODIFIED', name='status') + success_enum = sa.Enum('SUCCESS', 'WARNING', 'ERROR', name='success') + status_enum.drop(op.get_bind()) + success_enum.drop(op.get_bind()) + # ### end Alembic commands ###