Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion audiostats/application/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from .models import Status, Success
22 changes: 19 additions & 3 deletions audiostats/application/dto_mappers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from audiostats.db import Album, Track
from audiostats.db.models import Album, Track

from audiostats.handlers import AlbumDTO, TrackDTO
from audiostats.handlers import AlbumDTO, TrackDTO, StatusDTO

def update_track_orm_f_dto(old : Track, new : TrackDTO) -> None:
old.title = new.title
Expand Down Expand Up @@ -31,4 +31,20 @@ def create_album_dto_f_orm(album : Album):
number=track.number,
path=track.path,
offset=track.offset,
duration=track.duration) for track in album.tracks])
duration=track.duration) for track in album.tracks],
statuses=[StatusDTO(status=status.status,
success=status.success) for status in album.album_statuses])

def diff_album_meta(old : Album, new : AlbumDTO) -> bool:
return any([old.title != new.title,
old.performer != new.performer,
old.year != new.year,
old.path != new.path,
old.cover != new.cover])

def diff_track(old : Track, new : TrackDTO) -> bool:
return any([old.title != new.title,
old.number != new.number,
old.path != new.path,
old.offset != new.offset,
old.duration != new.duration])
6 changes: 3 additions & 3 deletions audiostats/db/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from datetime import datetime

from sqlalchemy import String, Integer, UniqueConstraint, ForeignKey, Float, Enum, DateTime
from sqlalchemy import String, Integer, UniqueConstraint, ForeignKey, Float, Enum, DateTime, func
from sqlalchemy.orm import declarative_base, Mapped, mapped_column, relationship

from audiostats.application import Status, Success
from audiostats.domain import Status, Success

Base = declarative_base()

Expand Down Expand Up @@ -82,7 +82,7 @@ class AlbumStatus(Base):

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)
time_stamp : Mapped[datetime] = mapped_column(DateTime, nullable=False, server_default=func.now(), default=func.now())
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')
Expand Down
26 changes: 23 additions & 3 deletions audiostats/db/repositories.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import logging

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from audiostats.domain import Status, Success
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
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


logger = logging.getLogger(__name__)
Expand All @@ -17,27 +19,39 @@ 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()
album_status = None

if not album:
if not album: #if new album
album = Album()
album_status = Status.ADDED
self._session.add(album)
elif diff_album_meta(album, album_data): #if album meta modified
album_status = Status.MODIFIED

update_album_orm_meta_f_dto(album, album_data)

old_tracks_by_title = {track.title: track for track in album.tracks}
for dto in album_data.tracks:
if dto.title in old_tracks_by_title:
old_track = old_tracks_by_title.pop(dto.title)
if diff_track(old_track, dto):
album_status = Status.MODIFIED
update_track_orm_f_dto(old_track, dto)
else:
if not album_status:
album_status = Status.MODIFIED
track = create_track_orm_f_dto(dto)
track.album = album
album.tracks.append(track)

for track in old_tracks_by_title.values():
album_status = Status.MODIFIED
await self._session.delete(track)

if album_status:
status = AlbumStatus(album=album, status=album_status, success=Success.SUCCESS)
self._session.add(status)

logger.info(f'Album upserted: {album_data}')

async def find_by_title_performer(self, title : str, performer : str | None) -> Album | None:
Expand All @@ -53,3 +67,9 @@ async def all(self) -> list[Album]:
selectinload(Album.tracks)
))
return [create_album_dto_f_orm(album) for album in result.all()]

async def all_w_status(self) -> list[Album]:
result = await self._session.scalars(select(Album).options(
selectinload(Album.tracks)
).options(selectinload(Album.album_statuses)))
return [create_album_dto_f_orm(album) for album in result.all()]
1 change: 1 addition & 0 deletions audiostats/domain/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .enums import Status, Success
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ class Success(StrEnum):
SUCCESS = 'success'
WARNING = 'warning'
ERROR = 'error'

2 changes: 1 addition & 1 deletion audiostats/handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .plst_handler import PlayListHandler
from .models import AlbumDTO, TrackDTO
from .models import AlbumDTO, TrackDTO, StatusDTO
13 changes: 12 additions & 1 deletion audiostats/handlers/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
from dataclasses import dataclass
from dataclasses import dataclass, field

from audiostats.domain import Status, Success

@dataclass(slots=True)
class StatusDTO:
status : Status
success : Success

def __repr__(self):
return f'<StatusDTO(status={self.status}, success={self.success})>'

@dataclass(slots=True)
class TrackDTO:
Expand All @@ -20,10 +29,12 @@ class AlbumDTO:
path : str | None
cover : str | None
tracks : list[TrackDTO]
statuses : list[StatusDTO] = field(default_factory=list)

def __repr__(self):
return f'''\n<AlbumDTO(title={self.title}, performer={self.performer}, year={self.year}, path={self.path}, cover={self.cover},
{'\n'.join(['\t' + repr(i) for i in self.tracks])}
{'\n'.join(['\t' + repr(i) for i in self.statuses])}
)>'''


Loading