Compare commits
No commits in common. "34fa0c92b2db5fca68947cd965d3bb30845072f8" and "4ce6c2e9b9a7043f7e31689c0d7aa46be2a2c865" have entirely different histories.
34fa0c92b2
...
4ce6c2e9b9
@ -1,38 +0,0 @@
|
|||||||
import os
|
|
||||||
import sqlalchemy
|
|
||||||
|
|
||||||
from config import Config
|
|
||||||
from sqlalchemy.orm import (sessionmaker, scoped_session)
|
|
||||||
|
|
||||||
MM_ENV = os.environ.get('MM_ENV', 'PRODUCTION')
|
|
||||||
testing = False
|
|
||||||
|
|
||||||
if MM_ENV == 'PRODUCTION':
|
|
||||||
dbname = os.environ.get('MM_PRODUCTION_DBNAME', 'musicmuster_prod')
|
|
||||||
dbuser = os.environ.get('MM_PRODUCTION_DBUSER', 'musicmuster')
|
|
||||||
dbpw = os.environ.get('MM_PRODUCTION_DBPW', 'musicmuster')
|
|
||||||
dbhost = os.environ.get('MM_PRODUCTION_DBHOST', 'localhost')
|
|
||||||
elif MM_ENV == 'TESTING':
|
|
||||||
dbname = os.environ.get('MM_TESTING_DBNAME', 'musicmuster_testing')
|
|
||||||
dbuser = os.environ.get('MM_TESTING_DBUSER', 'musicmuster_testing')
|
|
||||||
dbpw = os.environ.get('MM_TESTING_DBPW', 'musicmuster_testing')
|
|
||||||
dbhost = os.environ.get('MM_TESTING_DBHOST', 'localhost')
|
|
||||||
testing = True
|
|
||||||
elif MM_ENV == 'DEVELOPMENT':
|
|
||||||
dbname = os.environ.get('MM_DEVELOPMENT_DBNAME', 'musicmuster_dev')
|
|
||||||
dbuser = os.environ.get('MM_DEVELOPMENT_DBUSER', 'musicmuster')
|
|
||||||
dbpw = os.environ.get('MM_DEVELOPMENT_DBPW', 'musicmuster')
|
|
||||||
dbhost = os.environ.get('MM_DEVELOPMENT_DBHOST', 'localhost')
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unknown MusicMuster environment: {MM_ENV=}")
|
|
||||||
|
|
||||||
MYSQL_CONNECT = f"mysql+mysqldb://{dbuser}:{dbpw}@{dbhost}/{dbname}"
|
|
||||||
|
|
||||||
engine = sqlalchemy.create_engine(
|
|
||||||
MYSQL_CONNECT,
|
|
||||||
encoding='utf-8',
|
|
||||||
echo=Config.DISPLAY_SQL,
|
|
||||||
pool_pre_ping=True
|
|
||||||
)
|
|
||||||
|
|
||||||
session = scoped_session(sessionmaker(bind=engine))
|
|
||||||
156
app/models.py
156
app/models.py
@ -3,7 +3,7 @@
|
|||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from dbconfig import Session
|
import sqlalchemy
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
@ -25,7 +25,8 @@ from sqlalchemy.exc import IntegrityError
|
|||||||
from sqlalchemy.orm import (
|
from sqlalchemy.orm import (
|
||||||
backref,
|
backref,
|
||||||
relationship,
|
relationship,
|
||||||
RelationshipProperty
|
sessionmaker,
|
||||||
|
scoped_session, RelationshipProperty
|
||||||
)
|
)
|
||||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||||
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
||||||
@ -39,8 +40,28 @@ from helpers import (
|
|||||||
)
|
)
|
||||||
from log import DEBUG, ERROR
|
from log import DEBUG, ERROR
|
||||||
|
|
||||||
|
# Create session at the global level as per
|
||||||
|
# https://docs.sqlalchemy.org/en/13/orm/session_basics.html
|
||||||
|
# and make objects persistent
|
||||||
|
# https://docs.sqlalchemy.org/en/14/orm/session_state_management.html
|
||||||
|
|
||||||
|
engine = sqlalchemy.create_engine(
|
||||||
|
f"{Config.MYSQL_CONNECT}?charset=utf8",
|
||||||
|
encoding='utf-8',
|
||||||
|
echo=Config.DISPLAY_SQL,
|
||||||
|
pool_pre_ping=True)
|
||||||
|
|
||||||
|
# Create a Session factory
|
||||||
|
Session = scoped_session(sessionmaker(bind=engine))
|
||||||
|
# sm: sessionmaker = sessionmaker(bind=engine) # , expire_on_commit=False)
|
||||||
|
# Session = scoped_session(sm)
|
||||||
|
|
||||||
Base: DeclarativeMeta = declarative_base()
|
Base: DeclarativeMeta = declarative_base()
|
||||||
|
Base.metadata.create_all(engine)
|
||||||
|
|
||||||
|
|
||||||
|
def db_init():
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
# Database classes
|
# Database classes
|
||||||
@ -67,7 +88,7 @@ class NoteColours(Base):
|
|||||||
self.order = order
|
self.order = order
|
||||||
|
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (
|
return (
|
||||||
@ -139,7 +160,7 @@ class Notes(Base):
|
|||||||
self.row = row
|
self.row = row
|
||||||
self.note = text
|
self.note = text
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (
|
return (
|
||||||
@ -152,7 +173,7 @@ class Notes(Base):
|
|||||||
DEBUG(f"delete_note({self.id=}")
|
DEBUG(f"delete_note({self.id=}")
|
||||||
|
|
||||||
session.query(Notes).filter_by(id=self.id).delete()
|
session.query(Notes).filter_by(id=self.id).delete()
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_id(cls, session: Session, note_id: int) -> Optional["Notes"]:
|
def get_by_id(cls, session: Session, note_id: int) -> Optional["Notes"]:
|
||||||
@ -178,7 +199,7 @@ class Notes(Base):
|
|||||||
self.row = row
|
self.row = row
|
||||||
if text:
|
if text:
|
||||||
self.note = text
|
self.note = text
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
class Playdates(Base):
|
class Playdates(Base):
|
||||||
@ -199,7 +220,7 @@ class Playdates(Base):
|
|||||||
self.track_id = track.id
|
self.track_id = track.id
|
||||||
track.update_lastplayed(session)
|
track.update_lastplayed(session)
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def last_played(session: Session, track_id: int) -> Optional[datetime]:
|
def last_played(session: Session, track_id: int) -> Optional[datetime]:
|
||||||
@ -221,8 +242,9 @@ class Playdates(Base):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
session.query(Playdates).filter(
|
session.query(Playdates).filter(
|
||||||
Playdates.track_id == track_id).delete()
|
Playdates.track_id == track_id,
|
||||||
session.flush()
|
).delete()
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
class Playlists(Base):
|
class Playlists(Base):
|
||||||
@ -247,7 +269,7 @@ class Playlists(Base):
|
|||||||
def __init__(self, session: Session, name: str) -> None:
|
def __init__(self, session: Session, name: str) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"<Playlists(id={self.id}, name={self.name}>"
|
return f"<Playlists(id={self.id}, name={self.name}>"
|
||||||
@ -275,7 +297,7 @@ class Playlists(Base):
|
|||||||
|
|
||||||
self.loaded = False
|
self.loaded = False
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all(cls, session: Session) -> List["Playlists"]:
|
def get_all(cls, session: Session) -> List["Playlists"]:
|
||||||
@ -316,38 +338,25 @@ class Playlists(Base):
|
|||||||
|
|
||||||
self.loaded = True
|
self.loaded = True
|
||||||
self.last_used = datetime.now()
|
self.last_used = datetime.now()
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def move_track(self, session: Session, rows: List[int],
|
|
||||||
to_playlist: "Playlists") -> None:
|
|
||||||
"""Move tracks to another playlist"""
|
|
||||||
|
|
||||||
for row in rows:
|
|
||||||
track = self.tracks[row]
|
|
||||||
to_playlist.add_track(session, track.id)
|
|
||||||
del self.tracks[row]
|
|
||||||
|
|
||||||
session.flush()
|
|
||||||
|
|
||||||
def remove_all_tracks(self, session: Session) -> None:
|
def remove_all_tracks(self, session: Session) -> None:
|
||||||
"""
|
"""
|
||||||
Remove all tracks from this playlist
|
Remove all tracks from this playlist
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.tracks = {}
|
session.query(PlaylistTracks).filter(
|
||||||
session.flush()
|
PlaylistTracks.playlist_id == self.id,
|
||||||
|
).delete()
|
||||||
|
session.commit()
|
||||||
|
|
||||||
def remove_track(self, session: Session, row: int) -> None:
|
def remove_track(self, session: Session, row: int) -> None:
|
||||||
DEBUG(f"Playlist.remove_track({self.id=}, {row=})")
|
DEBUG(f"Playlist.remove_track({self.id=}, {row=})")
|
||||||
|
|
||||||
# Get tracks collection for this playlist
|
session.query(PlaylistTracks).filter(
|
||||||
tracks_collections = self.tracks
|
PlaylistTracks.playlist_id == self.id,
|
||||||
# Tracks are a dictionary of tracks keyed on row
|
PlaylistTracks.row == row
|
||||||
# number. Remove the relevant row.
|
).delete()
|
||||||
del tracks_collections[row]
|
|
||||||
# Save the new tracks collection
|
|
||||||
self.tracks = tracks_collections
|
|
||||||
session.flush()
|
|
||||||
|
|
||||||
|
|
||||||
class PlaylistTracks(Base):
|
class PlaylistTracks(Base):
|
||||||
@ -364,8 +373,7 @@ class PlaylistTracks(Base):
|
|||||||
backref=backref(
|
backref=backref(
|
||||||
"playlist_tracks",
|
"playlist_tracks",
|
||||||
collection_class=attribute_mapped_collection("row"),
|
collection_class=attribute_mapped_collection("row"),
|
||||||
lazy="joined",
|
lazy="joined"
|
||||||
cascade="all, delete-orphan"
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -378,7 +386,45 @@ class PlaylistTracks(Base):
|
|||||||
self.track_id = track_id
|
self.track_id = track_id
|
||||||
self.row = row
|
self.row = row
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def move_track(
|
||||||
|
session: Session, from_playlist_id: int, row: int,
|
||||||
|
to_playlist_id: int) -> None:
|
||||||
|
"""
|
||||||
|
Move track between playlists. This would be more efficient with
|
||||||
|
an ORM-enabled UPDATE statement, but this works just fine.
|
||||||
|
"""
|
||||||
|
DEBUG(
|
||||||
|
"PlaylistTracks.move_tracks("
|
||||||
|
f"{from_playlist_id=}, {row=}, {to_playlist_id=})"
|
||||||
|
)
|
||||||
|
|
||||||
|
new_row: int
|
||||||
|
max_row: Optional[int] = session.query(
|
||||||
|
func.max(PlaylistTracks.row)).filter(
|
||||||
|
PlaylistTracks.playlist_id == to_playlist_id).scalar()
|
||||||
|
if max_row is None:
|
||||||
|
# Destination playlist is empty; use row 0
|
||||||
|
new_row = 0
|
||||||
|
else:
|
||||||
|
# Destination playlist has tracks; add to end
|
||||||
|
new_row = max_row + 1
|
||||||
|
try:
|
||||||
|
record: PlaylistTracks = session.query(PlaylistTracks).filter(
|
||||||
|
PlaylistTracks.playlist_id == from_playlist_id,
|
||||||
|
PlaylistTracks.row == row).one()
|
||||||
|
except NoResultFound:
|
||||||
|
ERROR(
|
||||||
|
f"No rows matched in query: "
|
||||||
|
f"PlaylistTracks.playlist_id == {from_playlist_id}, "
|
||||||
|
f"PlaylistTracks.row == {row}"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
record.playlist_id = to_playlist_id
|
||||||
|
record.row = new_row
|
||||||
|
session.commit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def next_free_row(session: Session, playlist: Playlists) -> int:
|
def next_free_row(session: Session, playlist: Playlists) -> int:
|
||||||
@ -421,14 +467,14 @@ class Settings(Base):
|
|||||||
int_setting.name = name
|
int_setting.name = name
|
||||||
int_setting.f_int = None
|
int_setting.f_int = None
|
||||||
session.add(int_setting)
|
session.add(int_setting)
|
||||||
session.flush()
|
session.commit()
|
||||||
return int_setting
|
return int_setting
|
||||||
|
|
||||||
def update(self, session: Session, data):
|
def update(self, session: Session, data):
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
assert hasattr(self, key)
|
assert hasattr(self, key)
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
class Tracks(Base):
|
class Tracks(Base):
|
||||||
@ -451,30 +497,10 @@ class Tracks(Base):
|
|||||||
back_populates="tracks",
|
back_populates="tracks",
|
||||||
lazy="joined")
|
lazy="joined")
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self, session: Session, path: str) -> None:
|
||||||
session: Session,
|
|
||||||
path: str,
|
|
||||||
title: Optional[str] = None,
|
|
||||||
artist: Optional[str] = None,
|
|
||||||
duration: Optional[int] = None,
|
|
||||||
start_gap: Optional[int] = None,
|
|
||||||
fade_at: Optional[int] = None,
|
|
||||||
silence_at: Optional[int] = None,
|
|
||||||
mtime: Optional[float] = None,
|
|
||||||
lastplayed: Optional[datetime] = None,
|
|
||||||
) -> None:
|
|
||||||
self.path = path
|
self.path = path
|
||||||
self.title = title
|
|
||||||
self.artist = artist
|
|
||||||
self.duration = duration
|
|
||||||
self.start_gap = start_gap
|
|
||||||
self.fade_at = fade_at
|
|
||||||
self.silence_at = silence_at
|
|
||||||
self.mtime = mtime
|
|
||||||
self.lastplayed = lastplayed
|
|
||||||
|
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (
|
return (
|
||||||
@ -563,7 +589,7 @@ class Tracks(Base):
|
|||||||
Config.MILLISECOND_SIGFIGS) * 1000
|
Config.MILLISECOND_SIGFIGS) * 1000
|
||||||
self.start_gap = leading_silence(audio)
|
self.start_gap = leading_silence(audio)
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_by_path(session: Session, path: str) -> None:
|
def remove_by_path(session: Session, path: str) -> None:
|
||||||
@ -573,7 +599,7 @@ class Tracks(Base):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
session.query(Tracks).filter(Tracks.path == path).delete()
|
session.query(Tracks).filter(Tracks.path == path).delete()
|
||||||
session.flush()
|
session.commit()
|
||||||
except IntegrityError as exception:
|
except IntegrityError as exception:
|
||||||
ERROR(f"Can't remove track with {path=} ({exception=})")
|
ERROR(f"Can't remove track with {path=} ({exception=})")
|
||||||
|
|
||||||
@ -597,17 +623,17 @@ class Tracks(Base):
|
|||||||
def update_lastplayed(self, session: Session) -> None:
|
def update_lastplayed(self, session: Session) -> None:
|
||||||
self.lastplayed = datetime.now()
|
self.lastplayed = datetime.now()
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def update_artist(self, session: Session, artist: str) -> None:
|
def update_artist(self, session: Session, artist: str) -> None:
|
||||||
self.artist = artist
|
self.artist = artist
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def update_title(self, session: Session, title: str) -> None:
|
def update_title(self, session: Session, title: str) -> None:
|
||||||
self.title = title
|
self.title = title
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.commit()
|
||||||
|
|
||||||
def update_path(self, newpath: str) -> None:
|
def update_path(self, newpath: str) -> None:
|
||||||
self.path = newpath
|
self.path = newpath
|
||||||
|
|||||||
@ -23,12 +23,11 @@ from PyQt5.QtWidgets import (
|
|||||||
QMainWindow,
|
QMainWindow,
|
||||||
)
|
)
|
||||||
|
|
||||||
import dbconfig
|
|
||||||
import helpers
|
import helpers
|
||||||
import music
|
import music
|
||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
from models import (Playdates, Playlists, PlaylistTracks,
|
from models import (db_init, Playdates, Playlists, PlaylistTracks,
|
||||||
Session, Settings, Tracks)
|
Session, Settings, Tracks)
|
||||||
from playlists import PlaylistTab
|
from playlists import PlaylistTab
|
||||||
from utilities import create_track_from_file
|
from utilities import create_track_from_file
|
||||||
@ -102,12 +101,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
height = record.f_int or 981
|
height = record.f_int or 981
|
||||||
self.setGeometry(x, y, width, height)
|
self.setGeometry(x, y, width, height)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def kae():
|
|
||||||
with Session() as session:
|
|
||||||
db = session.bind.engine.url.database
|
|
||||||
print(f"kae(): {db=}")
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_audacity() -> None:
|
def check_audacity() -> None:
|
||||||
"""Offer to run Audacity if not running"""
|
"""Offer to run Audacity if not running"""
|
||||||
@ -980,13 +973,16 @@ class SelectPlaylistDialog(QDialog):
|
|||||||
self.accept()
|
self.accept()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def main():
|
||||||
try:
|
try:
|
||||||
Base.metadata.create_all(dbconfig.engine)
|
|
||||||
Session = dbconfig.Session
|
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
db_init()
|
||||||
win = Window()
|
win = Window()
|
||||||
win.show()
|
win.show()
|
||||||
sys.exit(app.exec())
|
sys.exit(app.exec())
|
||||||
except Exception:
|
except Exception:
|
||||||
EXCEPTION("Unhandled Exception caught by musicmuster.main()")
|
EXCEPTION("Unhandled Exception caught by musicmuster.main()")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
@ -27,11 +27,11 @@ from models import (
|
|||||||
Notes,
|
Notes,
|
||||||
Playdates,
|
Playdates,
|
||||||
Playlists,
|
Playlists,
|
||||||
|
Session,
|
||||||
Settings,
|
Settings,
|
||||||
Tracks,
|
Tracks,
|
||||||
NoteColours
|
NoteColours
|
||||||
)
|
)
|
||||||
from dbconfig import Session
|
|
||||||
|
|
||||||
|
|
||||||
class RowMeta:
|
class RowMeta:
|
||||||
@ -101,7 +101,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
self.setHorizontalHeaderItem(7, item)
|
self.setHorizontalHeaderItem(7, item)
|
||||||
self.horizontalHeader().setMinimumSectionSize(0)
|
self.horizontalHeader().setMinimumSectionSize(0)
|
||||||
|
|
||||||
self._set_column_widths(session)
|
self._set_column_widths()
|
||||||
self.setHorizontalHeaderLabels([
|
self.setHorizontalHeaderLabels([
|
||||||
Config.COLUMN_NAME_AUTOPLAY,
|
Config.COLUMN_NAME_AUTOPLAY,
|
||||||
Config.COLUMN_NAME_LEADING_SILENCE,
|
Config.COLUMN_NAME_LEADING_SILENCE,
|
||||||
@ -1368,7 +1368,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
ms: int = 0
|
ms: int = 0
|
||||||
with Session() as session:
|
with Session() as session:
|
||||||
for row in (sel_rows - notes_rows):
|
for row in (sel_rows - notes_rows):
|
||||||
ms += self._get_row_track_object(row, session).duration or 0
|
ms += self._get_row_track_object(row, session).duration
|
||||||
|
|
||||||
# Only paint message if there are selected track rows
|
# Only paint message if there are selected track rows
|
||||||
if ms > 0:
|
if ms > 0:
|
||||||
@ -1398,9 +1398,10 @@ class PlaylistTab(QTableWidget):
|
|||||||
# Reset extended selection
|
# Reset extended selection
|
||||||
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||||
|
|
||||||
def _set_column_widths(self, session: Session) -> None:
|
def _set_column_widths(self) -> None:
|
||||||
"""Column widths from settings"""
|
"""Column widths from settings"""
|
||||||
|
|
||||||
|
with Session() as session:
|
||||||
for column in range(self.columnCount()):
|
for column in range(self.columnCount()):
|
||||||
name: str = f"playlist_col_{str(column)}_width"
|
name: str = f"playlist_col_{str(column)}_width"
|
||||||
record: Settings = Settings.get_int_settings(session, name)
|
record: Settings = Settings.get_int_settings(session, name)
|
||||||
|
|||||||
@ -53,7 +53,7 @@ def main():
|
|||||||
DEBUG("Finished")
|
DEBUG("Finished")
|
||||||
|
|
||||||
|
|
||||||
def create_track_from_file(session, path, normalise=None, interactive=False):
|
def create_track_from_file(session, path, interactive=False):
|
||||||
"""
|
"""
|
||||||
Create track in database from passed path, or update database entry
|
Create track in database from passed path, or update database entry
|
||||||
if path already in database.
|
if path already in database.
|
||||||
@ -100,7 +100,7 @@ def create_track_from_file(session, path, normalise=None, interactive=False):
|
|||||||
track.mtime = os.path.getmtime(path)
|
track.mtime = os.path.getmtime(path)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
if normalise or normalise is None and Config.NORMALISE_ON_IMPORT:
|
if Config.NORMALISE_ON_IMPORT:
|
||||||
if interactive:
|
if interactive:
|
||||||
INFO("Normalise...")
|
INFO("Normalise...")
|
||||||
# Check type
|
# Check type
|
||||||
|
|||||||
22
conftest.py
22
conftest.py
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
sys.path.append("app")
|
|
||||||
import models
|
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||||
|
|
||||||
|
sys.path.append("app")
|
||||||
|
from app.models import Base # noqa E402
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
@ -19,9 +19,25 @@ def connection():
|
|||||||
return engine.connect()
|
return engine.connect()
|
||||||
|
|
||||||
|
|
||||||
|
def seed_database():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# users = [
|
||||||
|
# {
|
||||||
|
# "id": 1,
|
||||||
|
# "name": "John Doe",
|
||||||
|
# },
|
||||||
|
# # ...
|
||||||
|
# ]
|
||||||
|
|
||||||
|
# for user in users:
|
||||||
|
# db_user = User(**user)
|
||||||
|
# db_session.add(db_user)
|
||||||
|
# db_session.commit()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def setup_database(connection):
|
def setup_database(connection):
|
||||||
from app.models import Base # noqa E402
|
|
||||||
Base.metadata.bind = connection
|
Base.metadata.bind = connection
|
||||||
Base.metadata.create_all()
|
Base.metadata.create_all()
|
||||||
# seed_database()
|
# seed_database()
|
||||||
|
|||||||
20
poetry.lock
generated
20
poetry.lock
generated
@ -1,6 +1,6 @@
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "alembic"
|
name = "alembic"
|
||||||
version = "1.7.7"
|
version = "1.7.6"
|
||||||
description = "A database migration tool for SQLAlchemy."
|
description = "A database migration tool for SQLAlchemy."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
@ -439,11 +439,11 @@ python-versions = "*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "7.1.0"
|
version = "7.0.1"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
||||||
@ -551,14 +551,14 @@ tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinytag"
|
name = "tinytag"
|
||||||
version = "1.8.1"
|
version = "1.8.0"
|
||||||
description = "Read music meta data and length of MP3, OGG, OPUS, MP4, M4A, FLAC, WMA and Wave files"
|
description = "Read music meta data and length of MP3, OGG, OPUS, MP4, M4A, FLAC, WMA and Wave files"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7"
|
python-versions = ">=2.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
tests = ["pytest", "pytest-cov", "flake8"]
|
tests = ["pytest", "pytest-cov", "coveralls", "flake8"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
@ -610,8 +610,8 @@ content-hash = "08353ac7c54559da365ff26807f5179fefe388b62bc52884ee475a4a644e924a
|
|||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
alembic = [
|
alembic = [
|
||||||
{file = "alembic-1.7.7-py3-none-any.whl", hash = "sha256:29be0856ec7591c39f4e1cb10f198045d890e6e2274cf8da80cb5e721a09642b"},
|
{file = "alembic-1.7.6-py3-none-any.whl", hash = "sha256:ad842f2c3ab5c5d4861232730779c05e33db4ba880a08b85eb505e87c01095bc"},
|
||||||
{file = "alembic-1.7.7.tar.gz", hash = "sha256:4961248173ead7ce8a21efb3de378f13b8398e6630fab0eb258dc74a8af24c58"},
|
{file = "alembic-1.7.6.tar.gz", hash = "sha256:6c0c05e9768a896d804387e20b299880fe01bc56484246b0dffe8075d6d3d847"},
|
||||||
]
|
]
|
||||||
appnope = [
|
appnope = [
|
||||||
{file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
|
{file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
|
||||||
@ -940,8 +940,8 @@ pyqtwebengine-qt5 = [
|
|||||||
{file = "PyQtWebEngine_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:24231f19e1595018779977de6722b5c69f3d03f34a5f7574ff21cd1e764ef76d"},
|
{file = "PyQtWebEngine_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:24231f19e1595018779977de6722b5c69f3d03f34a5f7574ff21cd1e764ef76d"},
|
||||||
]
|
]
|
||||||
pytest = [
|
pytest = [
|
||||||
{file = "pytest-7.1.0-py3-none-any.whl", hash = "sha256:b555252a95bbb2a37a97b5ac2eb050c436f7989993565f5e0c9128fcaacadd0e"},
|
{file = "pytest-7.0.1-py3-none-any.whl", hash = "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db"},
|
||||||
{file = "pytest-7.1.0.tar.gz", hash = "sha256:f1089d218cfcc63a212c42896f1b7fbf096874d045e1988186861a1a87d27b47"},
|
{file = "pytest-7.0.1.tar.gz", hash = "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"},
|
||||||
]
|
]
|
||||||
pytest-qt = [
|
pytest-qt = [
|
||||||
{file = "pytest-qt-4.0.2.tar.gz", hash = "sha256:dfc5240dec7eb43b76bcb5f9a87eecae6ef83592af49f3af5f1d5d093acaa93e"},
|
{file = "pytest-qt-4.0.2.tar.gz", hash = "sha256:dfc5240dec7eb43b76bcb5f9a87eecae6ef83592af49f3af5f1d5d093acaa93e"},
|
||||||
@ -1001,7 +1001,7 @@ stack-data = [
|
|||||||
{file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"},
|
{file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"},
|
||||||
]
|
]
|
||||||
tinytag = [
|
tinytag = [
|
||||||
{file = "tinytag-1.8.1.tar.gz", hash = "sha256:363ab3107831a5598b68aaa061aba915fb1c7b4254d770232e65d5db8487636d"},
|
{file = "tinytag-1.8.0.tar.gz", hash = "sha256:e222d2fed7e2a26708963d907355ae242cf44908c1175d9d0d21c2ce51d47beb"},
|
||||||
]
|
]
|
||||||
toml = [
|
toml = [
|
||||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||||
|
|||||||
@ -126,7 +126,7 @@ def test_playdates_add_playdate(session):
|
|||||||
assert playdate
|
assert playdate
|
||||||
|
|
||||||
last_played = Playdates.last_played(session, track.id)
|
last_played = Playdates.last_played(session, track.id)
|
||||||
assert abs((playdate.lastplayed - last_played).total_seconds()) < 2
|
assert playdate.lastplayed == last_played
|
||||||
|
|
||||||
|
|
||||||
def test_playdates_remove_track(session):
|
def test_playdates_remove_track(session):
|
||||||
@ -274,9 +274,6 @@ def test_playlist_remove_tracks(session):
|
|||||||
|
|
||||||
playlist1.remove_track(session, 1)
|
playlist1.remove_track(session, 1)
|
||||||
assert len(playlist1.tracks) == 2
|
assert len(playlist1.tracks) == 2
|
||||||
# Check the track itself still exists
|
|
||||||
original_track = Tracks.get_by_id(session, track1.id)
|
|
||||||
assert original_track
|
|
||||||
|
|
||||||
playlist1.remove_all_tracks(session)
|
playlist1.remove_all_tracks(session)
|
||||||
assert len(playlist1.tracks) == 0
|
assert len(playlist1.tracks) == 0
|
||||||
@ -333,7 +330,8 @@ def test_playlisttracks_move_track(session):
|
|||||||
assert tracks[track2_row] == track2
|
assert tracks[track2_row] == track2
|
||||||
|
|
||||||
# Move track2 to playlist2 and check
|
# Move track2 to playlist2 and check
|
||||||
playlist1.move_track(session, [track2_row], playlist2)
|
PlaylistTracks.move_track(
|
||||||
|
session, playlist1.id, track2_row, playlist2.id)
|
||||||
|
|
||||||
tracks1 = playlist1.tracks
|
tracks1 = playlist1.tracks
|
||||||
tracks2 = playlist2.tracks
|
tracks2 = playlist2.tracks
|
||||||
|
|||||||
@ -1,47 +1,15 @@
|
|||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
from app import playlists
|
from app.playlists import Notes, PlaylistTab, Tracks
|
||||||
from app import models
|
from app.models import Playlists
|
||||||
from app import musicmuster
|
from musicmuster import Window
|
||||||
from app import dbconfig
|
|
||||||
|
|
||||||
|
|
||||||
def seed2tracks(session):
|
|
||||||
tracks = [
|
|
||||||
{
|
|
||||||
"path": "testdata/isa.mp3",
|
|
||||||
"title": "I'm so afraid",
|
|
||||||
"artist": "Fleetwood Mac",
|
|
||||||
"duration": 263000,
|
|
||||||
"start_gap": 60,
|
|
||||||
"fade_at": 236263,
|
|
||||||
"silence_at": 260343,
|
|
||||||
"mtime": 371900000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "testdata/mom.mp3",
|
|
||||||
"title": "Man of Mystery",
|
|
||||||
"artist": "The Shadows",
|
|
||||||
"duration": 120000,
|
|
||||||
"start_gap": 70,
|
|
||||||
"fade_at": 115000,
|
|
||||||
"silence_at": 118000,
|
|
||||||
"mtime": 1642760000,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
for track in tracks:
|
|
||||||
db_track = models.Tracks(session=session, **track)
|
|
||||||
session.add(db_track)
|
|
||||||
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def test_init(qtbot, session):
|
def test_init(qtbot, session):
|
||||||
"""Just check we can create a playlist_tab"""
|
"""Just check we can create a playlist_tab"""
|
||||||
|
|
||||||
playlist = models.Playlists(session, "my playlist")
|
playlist = Playlists(session, "my playlist")
|
||||||
playlist_tab = playlists.PlaylistTab(None, session, playlist.id)
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
assert playlist_tab
|
assert playlist_tab
|
||||||
|
|
||||||
|
|
||||||
@ -49,51 +17,46 @@ def test_save_and_restore(qtbot, session):
|
|||||||
"""Playlist with one track, one note, save and restore"""
|
"""Playlist with one track, one note, save and restore"""
|
||||||
|
|
||||||
# Create playlist
|
# Create playlist
|
||||||
playlist = models.Playlists(session, "my playlist")
|
playlist = Playlists(session, "my playlist")
|
||||||
playlist_tab = playlists.PlaylistTab(None, session, playlist.id)
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
|
|
||||||
# Insert a note
|
# Insert a note
|
||||||
note_text = "my note"
|
note_text = "my note"
|
||||||
note_row = 7
|
note_row = 7
|
||||||
note = models.Notes(session, playlist.id, note_row, note_text)
|
note = Notes(session, playlist.id, note_row, note_text)
|
||||||
playlist_tab._insert_note(session, note)
|
playlist_tab._insert_note(session, note)
|
||||||
|
|
||||||
# Add a track
|
# Add a track
|
||||||
track_path = "/a/b/c"
|
track_path = "/a/b/c"
|
||||||
track = models.Tracks(session, track_path)
|
track = Tracks(session, track_path)
|
||||||
playlist_tab.insert_track(session, track)
|
playlist_tab.insert_track(session, track)
|
||||||
|
|
||||||
# Save playlist
|
# Save playlist
|
||||||
playlist_tab.save_playlist(session)
|
playlist_tab.save_playlist(session)
|
||||||
|
|
||||||
# We need to commit the session before re-querying
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
# Retrieve playlist
|
# Retrieve playlist
|
||||||
all_playlists = playlists.Playlists.get_open(session)
|
playlists = Playlists.get_open(session)
|
||||||
assert len(all_playlists) == 1
|
assert len(playlists) == 1
|
||||||
retrieved_playlist = all_playlists[0]
|
retrieved_playlist = playlists[0]
|
||||||
paths = [a.path for a in retrieved_playlist.tracks.values()]
|
assert track_path in [a.path for a in retrieved_playlist.tracks.values()]
|
||||||
assert track_path in paths
|
assert note_text in [a.note for a in retrieved_playlist.notes]
|
||||||
notes = [a.note for a in retrieved_playlist.notes]
|
|
||||||
assert note_text in notes
|
|
||||||
|
|
||||||
|
|
||||||
def test_meta_all_clear(qtbot, session):
|
def test_meta_all_clear(qtbot, session):
|
||||||
|
|
||||||
# Create playlist
|
# Create playlist
|
||||||
playlist = models.Playlists(session, "my playlist")
|
playlist = Playlists(session, "my playlist")
|
||||||
playlist_tab = playlists.PlaylistTab(None, session, playlist.id)
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
|
|
||||||
# Add some tracks
|
# Add some tracks
|
||||||
track1_path = "/a/b/c"
|
track1_path = "/a/b/c"
|
||||||
track1 = models.Tracks(session, track1_path)
|
track1 = Tracks(session, track1_path)
|
||||||
playlist_tab.insert_track(session, track1)
|
playlist_tab.insert_track(session, track1)
|
||||||
track2_path = "/d/e/f"
|
track2_path = "/d/e/f"
|
||||||
track2 = models.Tracks(session, track2_path)
|
track2 = Tracks(session, track2_path)
|
||||||
playlist_tab.insert_track(session, track2)
|
playlist_tab.insert_track(session, track2)
|
||||||
track3_path = "/h/i/j"
|
track3_path = "/h/i/j"
|
||||||
track3 = models.Tracks(session, track3_path)
|
track3 = Tracks(session, track3_path)
|
||||||
playlist_tab.insert_track(session, track3)
|
playlist_tab.insert_track(session, track3)
|
||||||
|
|
||||||
assert playlist_tab._get_current_track_row() is None
|
assert playlist_tab._get_current_track_row() is None
|
||||||
@ -106,18 +69,18 @@ def test_meta_all_clear(qtbot, session):
|
|||||||
def test_meta(qtbot, session):
|
def test_meta(qtbot, session):
|
||||||
|
|
||||||
# Create playlist
|
# Create playlist
|
||||||
playlist = playlists.Playlists(session, "my playlist")
|
playlist = Playlists(session, "my playlist")
|
||||||
playlist_tab = playlists.PlaylistTab(None, session, playlist.id)
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
|
|
||||||
# Add some tracks
|
# Add some tracks
|
||||||
track1_path = "/a/b/c"
|
track1_path = "/a/b/c"
|
||||||
track1 = models.Tracks(session, track1_path)
|
track1 = Tracks(session, track1_path)
|
||||||
playlist_tab.insert_track(session, track1)
|
playlist_tab.insert_track(session, track1)
|
||||||
track2_path = "/d/e/f"
|
track2_path = "/d/e/f"
|
||||||
track2 = models.Tracks(session, track2_path)
|
track2 = Tracks(session, track2_path)
|
||||||
playlist_tab.insert_track(session, track2)
|
playlist_tab.insert_track(session, track2)
|
||||||
track3_path = "/h/i/j"
|
track3_path = "/h/i/j"
|
||||||
track3 = models.Tracks(session, track3_path)
|
track3 = Tracks(session, track3_path)
|
||||||
playlist_tab.insert_track(session, track3)
|
playlist_tab.insert_track(session, track3)
|
||||||
|
|
||||||
assert len(playlist_tab._get_unreadable_track_rows()) == 3
|
assert len(playlist_tab._get_unreadable_track_rows()) == 3
|
||||||
@ -136,7 +99,7 @@ def test_meta(qtbot, session):
|
|||||||
# Add a note
|
# Add a note
|
||||||
note_text = "my note"
|
note_text = "my note"
|
||||||
note_row = 7 # will be added as row 3
|
note_row = 7 # will be added as row 3
|
||||||
note = models.Notes(session, playlist.id, note_row, note_text)
|
note = Notes(session, playlist.id, note_row, note_text)
|
||||||
playlist_tab._insert_note(session, note)
|
playlist_tab._insert_note(session, note)
|
||||||
|
|
||||||
assert playlist_tab._get_played_track_rows() == [0]
|
assert playlist_tab._get_played_track_rows() == [0]
|
||||||
@ -184,15 +147,15 @@ def test_meta(qtbot, session):
|
|||||||
|
|
||||||
def test_clear_next(qtbot, session):
|
def test_clear_next(qtbot, session):
|
||||||
# Create playlist
|
# Create playlist
|
||||||
playlist = models.Playlists(session, "my playlist")
|
playlist = Playlists(session, "my playlist")
|
||||||
playlist_tab = playlists.PlaylistTab(None, session, playlist.id)
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
|
|
||||||
# Add some tracks
|
# Add some tracks
|
||||||
track1_path = "/a/b/c"
|
track1_path = "/a/b/c"
|
||||||
track1 = models.Tracks(session, track1_path)
|
track1 = Tracks(session, track1_path)
|
||||||
playlist_tab.insert_track(session, track1)
|
playlist_tab.insert_track(session, track1)
|
||||||
track2_path = "/d/e/f"
|
track2_path = "/d/e/f"
|
||||||
track2 = models.Tracks(session, track2_path)
|
track2 = Tracks(session, track2_path)
|
||||||
playlist_tab.insert_track(session, track2)
|
playlist_tab.insert_track(session, track2)
|
||||||
|
|
||||||
playlist_tab._set_next_track_row(1)
|
playlist_tab._set_next_track_row(1)
|
||||||
@ -202,24 +165,21 @@ def test_clear_next(qtbot, session):
|
|||||||
assert playlist_tab._get_next_track_row() is None
|
assert playlist_tab._get_next_track_row() is None
|
||||||
|
|
||||||
|
|
||||||
def test_get_selected_row(qtbot, monkeypatch, session):
|
def test_get_selected_row(qtbot, session):
|
||||||
|
|
||||||
monkeypatch.setattr(musicmuster, "Session", session)
|
# Create playlist
|
||||||
monkeypatch.setattr(playlists, "Session", session)
|
playlist = Playlists(session, "test playlist")
|
||||||
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
# Create playlist and playlist_tab
|
|
||||||
window = musicmuster.Window()
|
|
||||||
playlist = models.Playlists(session, "test playlist")
|
|
||||||
playlist_tab = playlists.PlaylistTab(window, session, playlist.id)
|
|
||||||
|
|
||||||
# Add some tracks
|
# Add some tracks
|
||||||
track1_path = "/a/b/c"
|
track1_path = "/a/b/c"
|
||||||
track1 = models.Tracks(session, track1_path)
|
track1 = Tracks(session, track1_path)
|
||||||
playlist_tab.insert_track(session, track1)
|
playlist_tab.insert_track(session, track1)
|
||||||
track2_path = "/d/e/f"
|
track2_path = "/d/e/f"
|
||||||
track2 = models.Tracks(session, track2_path)
|
track2 = Tracks(session, track2_path)
|
||||||
playlist_tab.insert_track(session, track2)
|
playlist_tab.insert_track(session, track2)
|
||||||
|
|
||||||
|
window = Window()
|
||||||
qtbot.addWidget(playlist_tab)
|
qtbot.addWidget(playlist_tab)
|
||||||
with qtbot.waitExposed(window):
|
with qtbot.waitExposed(window):
|
||||||
window.show()
|
window.show()
|
||||||
@ -231,50 +191,32 @@ def test_get_selected_row(qtbot, monkeypatch, session):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_set_next(qtbot, monkeypatch, session):
|
def test_set_next(qtbot, session):
|
||||||
|
|
||||||
monkeypatch.setattr(musicmuster, "Session", session)
|
|
||||||
monkeypatch.setattr(playlists, "Session", session)
|
|
||||||
seed2tracks(session)
|
|
||||||
|
|
||||||
playlist_name = "test playlist"
|
|
||||||
# Create testing playlist
|
# Create testing playlist
|
||||||
window = musicmuster.Window()
|
playlist = Playlists(session, "test playlist")
|
||||||
playlist = models.Playlists(session, playlist_name)
|
playlist_tab = PlaylistTab(None, session, playlist.id)
|
||||||
playlist_tab = playlists.PlaylistTab(window, session, playlist.id)
|
|
||||||
idx = window.tabPlaylist.addTab(playlist_tab, playlist_name)
|
|
||||||
window.tabPlaylist.setCurrentIndex(idx)
|
|
||||||
qtbot.addWidget(playlist_tab)
|
|
||||||
|
|
||||||
# Add some tracks
|
# Add some tracks
|
||||||
track1 = models.Tracks.get_from_filename(session, "isa.mp3")
|
track1_path = "testdata/isa.mp3"
|
||||||
|
track1 = Tracks(session, track1_path)
|
||||||
playlist_tab.insert_track(session, track1)
|
playlist_tab.insert_track(session, track1)
|
||||||
track2 = models.Tracks.get_from_filename(session, "mom.mp3")
|
track2_path = "mom.mp3"
|
||||||
|
track2 = Tracks(session, track2_path)
|
||||||
playlist_tab.insert_track(session, track2)
|
playlist_tab.insert_track(session, track2)
|
||||||
|
|
||||||
|
window = Window()
|
||||||
|
qtbot.addWidget(playlist_tab)
|
||||||
with qtbot.waitExposed(window):
|
with qtbot.waitExposed(window):
|
||||||
window.show()
|
window.show()
|
||||||
|
|
||||||
row0_item2 = playlist_tab.item(0, 2)
|
row0_item2 = playlist_tab.item(0, 2)
|
||||||
assert row0_item2 is not None
|
assert row0_item2 is not None
|
||||||
rect = playlist_tab.visualItemRect(row0_item2)
|
rect = playlist_tab.visualItemRect(row0_item2)
|
||||||
qtbot.mouseClick(
|
qtbot.mouseClick(
|
||||||
playlist_tab.viewport(), Qt.LeftButton, pos=rect.center()
|
playlist_tab.viewport(), Qt.LeftButton, pos=rect.center()
|
||||||
)
|
)
|
||||||
# qtbot.wait(10000)
|
qtbot.wait(10000)
|
||||||
qtbot.keyPress(playlist_tab.viewport(), "N",
|
qtbot.keyPress(playlist_tab.viewport(), "N",
|
||||||
modifier=Qt.ControlModifier)
|
modifier=Qt.ControlModifier)
|
||||||
qtbot.wait(2000)
|
qtbot.wait(2000)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def test_kae(monkeypatch, session):
|
|
||||||
# monkeypatch.setattr(dbconfig, "Session", session)
|
|
||||||
monkeypatch.setattr(musicmuster, "Session", session)
|
|
||||||
|
|
||||||
musicmuster.Window.kae()
|
|
||||||
# monkeypatch.setattr(musicmuster, "Session", session)
|
|
||||||
# monkeypatch.setattr(dbconfig, "Session", session)
|
|
||||||
# monkeypatch.setattr(models, "Session", session)
|
|
||||||
# monkeypatch.setattr(playlists, "Session", session)
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user