Compare commits

..

No commits in common. "836d812ef3f7ca91863d9477cb69a24885536d16" and "c380d37cf9963584937360dbdbf9a81b7caf7a8d" have entirely different histories.

8 changed files with 346 additions and 356 deletions

View File

@ -78,7 +78,7 @@ class NoteColours(dbtables.NoteColoursTable):
self.order = order self.order = order
session.add(self) session.add(self)
session.commit() session.flush()
@classmethod @classmethod
def get_all(cls, session: Session) -> Sequence["NoteColours"]: def get_all(cls, session: Session) -> Sequence["NoteColours"]:
@ -162,7 +162,7 @@ class Playlists(dbtables.PlaylistsTable):
def __init__(self, session: Session, name: str): def __init__(self, session: Session, name: str):
self.name = name self.name = name
session.add(self) session.add(self)
session.commit() session.flush()
@staticmethod @staticmethod
def clear_tabs(session: Session, playlist_ids: List[int]) -> None: def clear_tabs(session: Session, playlist_ids: List[int]) -> None:
@ -201,7 +201,7 @@ class Playlists(dbtables.PlaylistsTable):
""" """
self.deleted = True self.deleted = True
session.commit() session.flush()
@classmethod @classmethod
def get_all(cls, session: Session) -> Sequence["Playlists"]: def get_all(cls, session: Session) -> Sequence["Playlists"]:
@ -268,7 +268,7 @@ class Playlists(dbtables.PlaylistsTable):
""" """
self.name = new_name self.name = new_name
session.commit() session.flush()
@staticmethod @staticmethod
def save_as_template( def save_as_template(
@ -381,7 +381,7 @@ class PlaylistRows(dbtables.PlaylistRowsTable):
PlaylistRows.plr_rownum > maxrow, PlaylistRows.plr_rownum > maxrow,
) )
) )
session.commit() session.flush()
@staticmethod @staticmethod
def delete_row(session: Session, playlist_id: int, row_number: int) -> None: def delete_row(session: Session, playlist_id: int, row_number: int) -> None:
@ -575,7 +575,7 @@ class Settings(dbtables.SettingsTable):
def __init__(self, session: Session, name: str): def __init__(self, session: Session, name: str):
self.name = name self.name = name
session.add(self) session.add(self)
session.commit() session.flush()
@classmethod @classmethod
def all_as_dict(cls, session): def all_as_dict(cls, session):
@ -605,7 +605,7 @@ class Settings(dbtables.SettingsTable):
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.commit() session.flush()
class Tracks(dbtables.TracksTable): class Tracks(dbtables.TracksTable):

View File

@ -59,9 +59,10 @@ from classes import (
PlaylistTrack, PlaylistTrack,
) )
from config import Config from config import Config
from dbtables import db
from dialogs import TrackSelectDialog from dialogs import TrackSelectDialog
from log import log from log import log
from models import db, Carts, Playdates, PlaylistRows, Playlists, Settings, Tracks from models import Carts, Playdates, PlaylistRows, Playlists, Settings, Tracks
from playlistmodel import PlaylistModel, PlaylistProxyModel from playlistmodel import PlaylistModel, PlaylistProxyModel
from playlists import PlaylistTab from playlists import PlaylistTab
from ui import icons_rc # noqa F401 from ui import icons_rc # noqa F401
@ -1117,15 +1118,34 @@ class Window(QMainWindow, Ui_MainWindow):
# Restore volume if -3dB active # Restore volume if -3dB active
if self.btnDrop3db.isChecked(): if self.btnDrop3db.isChecked():
log.debug("Reset -3db button")
self.btnDrop3db.setChecked(False) self.btnDrop3db.setChecked(False)
# Show closing volume graph
if track_sequence.now.fade_graph:
track_sequence.now.fade_graph.plot()
else:
log.error("No fade_graph")
# Play (new) current track # Play (new) current track
if not track_sequence.now.path: if not track_sequence.now.path:
log.error("No path for next track") log.error("No path for next track")
return return
self.music.play(track_sequence.now.path, position) self.music.play(track_sequence.now.path, position)
# Note that track is playing
track_sequence.now.start()
self.playing = True
# Disable play next controls
self.catch_return_key = True
self.show_status_message("Play controls: Disabled", 0)
# Notify model
self.active_proxy_model().current_track_started()
# Update headers
self.update_headers()
# Ensure 100% volume # Ensure 100% volume
# For as-yet unknown reasons. sometimes the volume gets # For as-yet unknown reasons. sometimes the volume gets
# reset to zero within 200mS or so of starting play. This # reset to zero within 200mS or so of starting play. This
@ -1140,36 +1160,6 @@ class Window(QMainWindow, Ui_MainWindow):
break break
sleep(0.1) sleep(0.1)
# TODO: remove sleep() calls - used to try to isolate bug #223
# Show closing volume graph
sleep(1)
if track_sequence.now.fade_graph:
track_sequence.now.fade_graph.plot()
else:
log.error("No fade_graph")
# Note that track is playing
sleep(1)
log.error("set track_sequence")
track_sequence.now.start()
self.playing = True
# Disable play next controls
sleep(1)
log.error("catch return key")
self.catch_return_key = True
self.show_status_message("Play controls: Disabled", 0)
# Notify model
sleep(1)
log.error("active_proxy_model().current_track_started()")
self.active_proxy_model().current_track_started()
# Update headers
sleep(1)
log.error("update headers")
self.update_headers()
def preview(self) -> None: def preview(self) -> None:
""" """
Preview selected or next track. We use a different mechanism to Preview selected or next track. We use a different mechanism to

View File

@ -4,7 +4,6 @@ from __future__ import annotations
from enum import auto, Enum from enum import auto, Enum
from operator import attrgetter from operator import attrgetter
from time import sleep
from random import shuffle from random import shuffle
from typing import List, Optional from typing import List, Optional
import datetime as dt import datetime as dt
@ -124,7 +123,7 @@ class PlaylistModel(QAbstractTableModel):
*args, *args,
**kwargs, **kwargs,
): ):
log.debug(f"PlaylistModel.__init__({playlist_id=})") log.info(f"PlaylistModel.__init__({playlist_id=})")
self.playlist_id = playlist_id self.playlist_id = playlist_id
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -156,7 +155,7 @@ class PlaylistModel(QAbstractTableModel):
Add track to existing header row Add track to existing header row
""" """
log.debug(f"add_track_to_header({row_number=}, {track_id=}, {note=}") log.info(f"add_track_to_header({row_number=}, {track_id=}, {note=}")
# Get existing row # Get existing row
try: try:
@ -279,21 +278,14 @@ class PlaylistModel(QAbstractTableModel):
) )
return return
# TODO: remove sleep/log calls, used to debug #223
# Check for OBS scene change # Check for OBS scene change
sleep(1)
log.error("Call OBS scene change")
self.obs_scene_change(row_number) self.obs_scene_change(row_number)
with db.Session() as session: with db.Session() as session:
# Update Playdates in database # Update Playdates in database
sleep(1)
log.error("update playdates")
Playdates(session, track_sequence.now.track_id) Playdates(session, track_sequence.now.track_id)
# Mark track as played in playlist # Mark track as played in playlist
sleep(1)
log.error("Mark track as played")
plr = session.get(PlaylistRows, track_sequence.now.plr_id) plr = session.get(PlaylistRows, track_sequence.now.plr_id)
if plr: if plr:
plr.played = True plr.played = True
@ -302,8 +294,6 @@ class PlaylistModel(QAbstractTableModel):
log.error(f"Can't retrieve plr, {track_sequence.now.plr_id=}") log.error(f"Can't retrieve plr, {track_sequence.now.plr_id=}")
# Update track times # Update track times
sleep(1)
log.error("Update track times")
if prd: if prd:
prd.start_time = track_sequence.now.start_time prd.start_time = track_sequence.now.start_time
prd.end_time = track_sequence.now.end_time prd.end_time = track_sequence.now.end_time
@ -320,8 +310,6 @@ class PlaylistModel(QAbstractTableModel):
# Find next track # Find next track
# Get all unplayed track rows # Get all unplayed track rows
sleep(1)
log.error("Find next track")
next_row = None next_row = None
unplayed_rows = self.get_unplayed_rows() unplayed_rows = self.get_unplayed_rows()
if unplayed_rows: if unplayed_rows:
@ -555,7 +543,7 @@ class PlaylistModel(QAbstractTableModel):
If not given, return row number to add to end of model. If not given, return row number to add to end of model.
""" """
log.debug(f"_get_new_row_number({proposed_row_number=})") log.info(f"_get_new_row_number({proposed_row_number=})")
if proposed_row_number is None or proposed_row_number > len(self.playlist_rows): if proposed_row_number is None or proposed_row_number > len(self.playlist_rows):
# We are adding to the end of the list # We are adding to the end of the list
@ -852,7 +840,7 @@ class PlaylistModel(QAbstractTableModel):
Move the playlist rows given to to_row and below. Move the playlist rows given to to_row and below.
""" """
log.debug(f"move_rows({from_rows=}, {to_row_number=}") log.info(f"move_rows({from_rows=}, {to_row_number=}")
# Build a {current_row_number: new_row_number} dictionary # Build a {current_row_number: new_row_number} dictionary
row_map: dict[int, int] = {} row_map: dict[int, int] = {}
@ -916,7 +904,7 @@ class PlaylistModel(QAbstractTableModel):
Move the playlist rows given to to_row and below of to_playlist. Move the playlist rows given to to_row and below of to_playlist.
""" """
log.debug( log.info(
f"move_rows_between_playlists({from_rows=}, {to_row_number=}, {to_playlist_id=}" f"move_rows_between_playlists({from_rows=}, {to_row_number=}, {to_playlist_id=}"
) )
@ -1114,7 +1102,7 @@ class PlaylistModel(QAbstractTableModel):
Signal handler for when row ordering has changed Signal handler for when row ordering has changed
""" """
log.debug("reset_track_sequence_row_numbers()") log.info("reset_track_sequence_row_numbers()")
# Check the track_sequence next, now and previous plrs and # Check the track_sequence next, now and previous plrs and
# update the row number # update the row number
@ -1146,7 +1134,7 @@ class PlaylistModel(QAbstractTableModel):
return: [[20, 21], [17], [13], [9, 10], [7], [2, 3, 4, 5]] return: [[20, 21], [17], [13], [9, 10], [7], [2, 3, 4, 5]]
""" """
log.debug(f"_reversed_contiguous_row_groups({row_numbers=} called") log.info(f"_reversed_contiguous_row_groups({row_numbers=} called")
result: List[List[int]] = [] result: List[List[int]] = []
temp: List[int] = [] temp: List[int] = []
@ -1162,7 +1150,7 @@ class PlaylistModel(QAbstractTableModel):
result.append(temp) result.append(temp)
result.reverse() result.reverse()
log.debug(f"_reversed_contiguous_row_groups() returned: {result=}") log.info(f"_reversed_contiguous_row_groups() returned: {result=}")
return result return result
def rowCount(self, index: QModelIndex = QModelIndex()) -> int: def rowCount(self, index: QModelIndex = QModelIndex()) -> int:
@ -1175,7 +1163,7 @@ class PlaylistModel(QAbstractTableModel):
Signal handler for when row ordering has changed Signal handler for when row ordering has changed
""" """
log.debug(f"row_order_changed({playlist_id=}) {self.playlist_id=}") log.info(f"row_order_changed({playlist_id=}) {self.playlist_id=}")
# Only action if this is for us # Only action if this is for us
if playlist_id != self.playlist_id: if playlist_id != self.playlist_id:

View File

@ -36,6 +36,7 @@ from PyQt6.QtWidgets import (
# App imports # App imports
from classes import MusicMusterSignals, track_sequence from classes import MusicMusterSignals, track_sequence
from config import Config from config import Config
from dbtables import db
from dialogs import TrackSelectDialog from dialogs import TrackSelectDialog
from helpers import ( from helpers import (
ask_yes_no, ask_yes_no,
@ -44,7 +45,7 @@ from helpers import (
show_warning, show_warning,
) )
from log import log from log import log
from models import db, Settings from models import Settings
from playlistmodel import PlaylistModel, PlaylistProxyModel from playlistmodel import PlaylistModel, PlaylistProxyModel
if TYPE_CHECKING: if TYPE_CHECKING:

View File

@ -1,7 +1,5 @@
# Standard library imports # Standard library imports
import datetime as dt import datetime as dt
import shutil
import tempfile
import unittest import unittest
# PyQt imports # PyQt imports
@ -16,7 +14,6 @@ from helpers import (
get_relative_date, get_relative_date,
leading_silence, leading_silence,
ms_to_mmss, ms_to_mmss,
normalise_track,
) )
@ -88,14 +85,3 @@ class TestMMHelpers(unittest.TestCase):
assert ms_to_mmss(None) == "-" assert ms_to_mmss(None) == "-"
assert ms_to_mmss(59600) == "0:59" assert ms_to_mmss(59600) == "0:59"
assert ms_to_mmss((5 * 60 * 1000) + 23000) == "5:23" assert ms_to_mmss((5 * 60 * 1000) + 23000) == "5:23"
def test_normalise(self):
"""Make copies to normalise to avoid corrupting source"""
_, mp3_temp_path = tempfile.mkstemp(suffix=".mp3")
shutil.copyfile("testdata/isa.mp3", mp3_temp_path)
normalise_track(mp3_temp_path)
_, flac_temp_path = tempfile.mkstemp(suffix=".flac")
shutil.copyfile("testdata/isa.flac", flac_temp_path)
normalise_track(flac_temp_path)

View File

@ -35,6 +35,8 @@ class TestMMModels(unittest.TestCase):
track1_path = "testdata/isa.mp3" track1_path = "testdata/isa.mp3"
metadata1 = helpers.get_file_metadata(track1_path) metadata1 = helpers.get_file_metadata(track1_path)
self.track1 = Tracks(session, **metadata1) self.track1 = Tracks(session, **metadata1)
# Test repr
_ = str(self.track1)
track2_path = "testdata/mom.mp3" track2_path = "testdata/mom.mp3"
metadata2 = helpers.get_file_metadata(track2_path) metadata2 = helpers.get_file_metadata(track2_path)
@ -43,11 +45,6 @@ class TestMMModels(unittest.TestCase):
def tearDown(self): def tearDown(self):
db.drop_all() db.drop_all()
def test_track_repr(self):
with db.Session() as session:
session.add(self.track1)
_ =str(self.track1)
def test_notecolours_get_colour(self): def test_notecolours_get_colour(self):
"""Create a colour record and retrieve all colours""" """Create a colour record and retrieve all colours"""

View File

@ -28,114 +28,61 @@ from app.models import ( # noqa: E402
) )
class TestMMMiscTracks(unittest.TestCase): # class TestMMMiscTracks(unittest.TestCase):
def setUp(self): # def setUp(self):
PLAYLIST_NAME = "tracks playlist" # PLAYLIST_NAME = "tracks playlist"
self.test_tracks = [ # self.test_tracks = [
"testdata/isa.mp3", # "testdata/isa.mp3",
"testdata/isa_with_gap.mp3", # "testdata/isa_with_gap.mp3",
"testdata/loser.mp3", # "testdata/loser.mp3",
"testdata/lovecats-10seconds.mp3", # "testdata/lovecats-10seconds.mp3",
"testdata/lovecats.mp3", # "testdata/lovecats.mp3",
"testdata/mom.mp3", # "testdata/mom.mp3",
"testdata/sitting.mp3", # "testdata/sitting.mp3",
"testdata/wrb.flac", # ]
]
db.create_all() # db.create_all()
# Create a playlist and model # # Create a playlist and model
with db.Session() as session: # with db.Session() as session:
self.playlist = Playlists(session, PLAYLIST_NAME) # self.playlist = Playlists(session, PLAYLIST_NAME)
self.model = playlistmodel.PlaylistModel(self.playlist.id) # self.model = playlistmodel.PlaylistModel(self.playlist.id)
for row in range(len(self.test_tracks)): # for row in range(len(self.test_tracks)):
track_path = self.test_tracks[row % len(self.test_tracks)] # track_path = self.test_tracks[row % len(self.test_tracks)]
metadata = get_file_metadata(track_path) # metadata = get_file_metadata(track_path)
track = Tracks(session, **metadata) # track = Tracks(session, **metadata)
self.model.insert_row( # self.model.insert_row(
proposed_row_number=row, track_id=track.id, note=f"{row=}" # proposed_row_number=row, track_id=track.id, note=f"{row=}"
) # )
session.commit() # session.commit()
def tearDown(self): # def tearDown(self):
db.drop_all() # db.drop_all()
def test_8_row_playlist(self): # def test_7_row_playlist(self):
# Test auto-created playlist # # Test auto-created playlist
assert self.model.rowCount() == 8 # assert self.model.rowCount() == 7
assert max(self.model.playlist_rows.keys()) == 7 # assert max(self.model.playlist_rows.keys()) == 6
for row in range(self.model.rowCount()): # for row in range(self.model.rowCount()):
assert row in self.model.playlist_rows # assert row in self.model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row # assert self.model.playlist_rows[row].plr_rownum == row
def test_timing_one_track(self):
START_ROW = 0
END_ROW = 2
self.model.insert_row(proposed_row_number=START_ROW, note="start+")
self.model.insert_row(proposed_row_number=END_ROW, note="-")
prd = self.model.playlist_rows[START_ROW]
qv_value = self.model.display_role(START_ROW, playlistmodel.HEADER_NOTES_COLUMN, prd)
assert qv_value.value() == "start [1 tracks, 4:23 unplayed]"
class TestMMMiscNoPlaylist(unittest.TestCase):
PLAYLIST_NAME = "tracks playlist"
test_tracks = [
"testdata/isa.mp3",
"testdata/isa_with_gap.mp3",
"testdata/loser.mp3",
"testdata/lovecats-10seconds.mp3",
"testdata/lovecats.mp3",
"testdata/mom.mp3",
"testdata/sitting.mp3",
]
def setUp(self):
db.create_all()
def tearDown(self):
db.drop_all()
def test_insert_track_new_playlist(self):
# insert a track into a new playlist
with db.Session() as session:
playlist = Playlists(session, self.PLAYLIST_NAME)
# Create a model
model = playlistmodel.PlaylistModel(playlist.id)
# test repr
_ = str(model)
track_path = self.test_tracks[0]
metadata = get_file_metadata(track_path)
track = Tracks(session, **metadata)
model.insert_row(proposed_row_number=0, track_id=track.id)
prd = model.playlist_rows[model.rowCount() - 1]
# test repr
_ = str(prd)
assert (
model.edit_role(model.rowCount() - 1, playlistmodel.Col.TITLE.value, prd)
== metadata["title"]
)
class TestMMMiscRowMove(unittest.TestCase): class TestMMMiscRowMove(unittest.TestCase):
def setUp(self):
PLAYLIST_NAME = "rowmove playlist" PLAYLIST_NAME = "rowmove playlist"
ROWS_TO_CREATE = 11 ROWS_TO_CREATE = 11
def setUp(self):
db.create_all() db.create_all()
with db.Session() as session: with db.Session() as session:
self.playlist = Playlists(session, self.PLAYLIST_NAME) self.playlist = Playlists(session, PLAYLIST_NAME)
self.model = playlistmodel.PlaylistModel(self.playlist.id) self.model = playlistmodel.PlaylistModel(self.playlist.id)
for row in range(self.ROWS_TO_CREATE): for row in range(ROWS_TO_CREATE):
print(f"{row=}")
self.model.insert_row(proposed_row_number=row, note=str(row)) self.model.insert_row(proposed_row_number=row, note=str(row))
session.commit() session.commit()
@ -159,230 +106,311 @@ class TestMMMiscRowMove(unittest.TestCase):
elif row == 5: elif row == 5:
assert self.model.playlist_rows[row].note == str(3) assert self.model.playlist_rows[row].note == str(3)
def test_move_rows_test3(self):
# move row 4 to row 3
self.model.move_rows([4], 3) # def test_move_rows_test3(monkeypatch, session):
# # move row 4 to row 3
# Check we have all rows and plr_rownums are correct # monkeypatch.setattr(playlistmodel, "Session", session)
for row in range(self.model.rowCount()):
assert row in self.model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row
if row not in [3, 4]:
assert self.model.playlist_rows[row].note == str(row)
elif row == 3:
assert self.model.playlist_rows[row].note == str(4)
elif row == 4:
assert self.model.playlist_rows[row].note == str(3)
def test_move_rows_test4(self): # model = create_model_with_playlist_rows(session, 11)
# move row 4 to row 2 # model.move_rows([4], 3)
self.model.move_rows([4], 2) # # Check we have all rows and plr_rownums are correct
# for row in range(model.rowCount()):
# assert row in model.playlist_rows
# assert model.playlist_rows[row].plr_rownum == row
# if row not in [3, 4]:
# assert model.playlist_rows[row].note == str(row)
# elif row == 3:
# assert model.playlist_rows[row].note == str(4)
# elif row == 4:
# assert model.playlist_rows[row].note == str(3)
# Check we have all rows and plr_rownums are correct
for row in range(self.model.rowCount()):
assert row in self.model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row
if row not in [2, 3, 4]:
assert self.model.playlist_rows[row].note == str(row)
elif row == 2:
assert self.model.playlist_rows[row].note == str(4)
elif row == 3:
assert self.model.playlist_rows[row].note == str(2)
elif row == 4:
assert self.model.playlist_rows[row].note == str(3)
def test_move_rows_test5(self): # def test_move_rows_test4(monkeypatch, session):
# move rows [1, 4, 5, 10] → 8 # # move row 4 to row 2
self.model.move_rows([1, 4, 5, 10], 8) # monkeypatch.setattr(playlistmodel, "Session", session)
# Check we have all rows and plr_rownums are correct # model = create_model_with_playlist_rows(session, 11)
new_order = [] # model.move_rows([4], 2)
for row in range(self.model.rowCount()):
assert row in self.model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row
new_order.append(int(self.model.playlist_rows[row].note))
assert new_order == [0, 2, 3, 6, 7, 8, 9, 1, 4, 5, 10]
def test_move_rows_test6(self): # # Check we have all rows and plr_rownums are correct
# move rows [3, 6] → 5 # for row in range(model.rowCount()):
# assert row in model.playlist_rows
# assert model.playlist_rows[row].plr_rownum == row
# if row not in [2, 3, 4]:
# assert model.playlist_rows[row].note == str(row)
# elif row == 2:
# assert model.playlist_rows[row].note == str(4)
# elif row == 3:
# assert model.playlist_rows[row].note == str(2)
# elif row == 4:
# assert model.playlist_rows[row].note == str(3)
self.model.move_rows([3, 6], 5)
# Check we have all rows and plr_rownums are correct # def test_move_rows_test5(monkeypatch, session):
new_order = [] # # move rows [1, 4, 5, 10] → 8
for row in range(self.model.rowCount()):
assert row in self.model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row
new_order.append(int(self.model.playlist_rows[row].note))
assert new_order == [0, 1, 2, 4, 5, 3, 6, 7, 8, 9, 10]
def test_move_rows_test7(self): # monkeypatch.setattr(playlistmodel, "Session", session)
# move rows [3, 5, 6] → 8
self.model.move_rows([3, 5, 6], 8) # model = create_model_with_playlist_rows(session, 11)
# model.move_rows([1, 4, 5, 10], 8)
# Check we have all rows and plr_rownums are correct # # Check we have all rows and plr_rownums are correct
new_order = [] # new_order = []
for row in range(self.model.rowCount()): # for row in range(model.rowCount()):
assert row in self.model.playlist_rows # assert row in model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row # assert model.playlist_rows[row].plr_rownum == row
new_order.append(int(self.model.playlist_rows[row].note)) # new_order.append(int(model.playlist_rows[row].note))
assert new_order == [0, 1, 2, 4, 7, 8, 9, 10, 3, 5, 6] # assert new_order == [0, 2, 3, 6, 7, 8, 9, 1, 4, 5, 10]
def test_move_rows_test8(self):
# move rows [7, 8, 10] → 5
self.model.move_rows([7, 8, 10], 5) # def test_move_rows_test6(monkeypatch, session):
# # move rows [3, 6] → 5
# Check we have all rows and plr_rownums are correct # monkeypatch.setattr(playlistmodel, "Session", session)
new_order = []
for row in range(self.model.rowCount()):
assert row in self.model.playlist_rows
assert self.model.playlist_rows[row].plr_rownum == row
new_order.append(int(self.model.playlist_rows[row].note))
assert new_order == [0, 1, 2, 3, 4, 7, 8, 10, 5, 6, 9]
def test_insert_header_row_end(self): # model = create_model_with_playlist_rows(session, 11)
# insert header row at end of playlist # model.move_rows([3, 6], 5)
note_text = "test text" # # Check we have all rows and plr_rownums are correct
# new_order = []
# for row in range(model.rowCount()):
# assert row in model.playlist_rows
# assert model.playlist_rows[row].plr_rownum == row
# new_order.append(int(model.playlist_rows[row].note))
# assert new_order == [0, 1, 2, 4, 5, 3, 6, 7, 8, 9, 10]
assert self.model.rowCount() == self.ROWS_TO_CREATE
self.model.insert_row(proposed_row_number=None, note=note_text)
assert self.model.rowCount() == self.ROWS_TO_CREATE + 1
prd = self.model.playlist_rows[self.model.rowCount() - 1]
# Test against edit_role because display_role for headers is
# handled differently (sets up row span)
assert (
self.model.edit_role(
self.model.rowCount() - 1, playlistmodel.Col.NOTE.value, prd
)
== note_text
)
def test_insert_header_row_middle(self): # def test_move_rows_test7(monkeypatch, session):
# insert header row in middle of playlist # # move rows [3, 5, 6] → 8
note_text = "test text" # monkeypatch.setattr(playlistmodel, "Session", session)
insert_row = 6
self.model.insert_row(proposed_row_number=insert_row, note=note_text) # model = create_model_with_playlist_rows(session, 11)
assert self.model.rowCount() == self.ROWS_TO_CREATE + 1 # model.move_rows([3, 5, 6], 8)
prd = self.model.playlist_rows[insert_row]
# Test against edit_role because display_role for headers is
# handled differently (sets up row span)
assert (
self.model.edit_role(
self.model.rowCount() - 1, playlistmodel.Col.NOTE.value, prd
)
== note_text
)
def test_add_track_to_header(self): # # Check we have all rows and plr_rownums are correct
note_text = "test text" # new_order = []
insert_row = 6 # for row in range(model.rowCount()):
# assert row in model.playlist_rows
# assert model.playlist_rows[row].plr_rownum == row
# new_order.append(int(model.playlist_rows[row].note))
# assert new_order == [0, 1, 2, 4, 7, 8, 9, 10, 3, 5, 6]
self.model.insert_row(proposed_row_number=insert_row, note=note_text)
assert self.model.rowCount() == self.ROWS_TO_CREATE + 1
prd = self.model.playlist_rows[1] # def test_move_rows_test8(monkeypatch, session):
self.model.add_track_to_header(insert_row, prd.track_id) # # move rows [7, 8, 10] → 5
def test_reverse_row_groups_one_row(self): # monkeypatch.setattr(playlistmodel, "Session", session)
rows_to_move = [3] # model = create_model_with_playlist_rows(session, 11)
# model.move_rows([7, 8, 10], 5)
result = self.model._reversed_contiguous_row_groups(rows_to_move) # # Check we have all rows and plr_rownums are correct
# new_order = []
# for row in range(model.rowCount()):
# assert row in model.playlist_rows
# assert model.playlist_rows[row].plr_rownum == row
# new_order.append(int(model.playlist_rows[row].note))
# assert new_order == [0, 1, 2, 3, 4, 7, 8, 10, 5, 6, 9]
assert len(result) == 1
assert result[0] == [3]
def test_reverse_row_groups_multiple_row(self): # def test_insert_header_row_end(monkeypatch, session):
# # insert header row at end of playlist
rows_to_move = [2, 3, 4, 5, 7, 9, 10, 13, 17, 20, 21] # monkeypatch.setattr(playlistmodel, "Session", session)
# note_text = "test text"
# initial_row_count = 11
result = self.model._reversed_contiguous_row_groups(rows_to_move) # model = create_model_with_playlist_rows(session, initial_row_count)
# model.insert_row(proposed_row_number=None, note=note_text)
# assert model.rowCount() == initial_row_count + 1
# prd = model.playlist_rows[model.rowCount() - 1]
# # Test against edit_role because display_role for headers is
# # handled differently (sets up row span)
# assert (
# model.edit_role(model.rowCount() - 1, playlistmodel.Col.NOTE.value, prd)
# == note_text
# )
assert result == [[20, 21], [17], [13], [9, 10], [7], [2, 3, 4, 5]]
def test_move_one_row_between_playlists_to_end(self): # def test_insert_header_row_middle(monkeypatch, session):
from_rows = [3] # # insert header row in middle of playlist
to_row = self.ROWS_TO_CREATE
destination_playlist = "destination"
model_src = self.model # monkeypatch.setattr(playlistmodel, "Session", session)
with db.Session() as session: # note_text = "test text"
playlist_dst = Playlists(session, destination_playlist) # initial_row_count = 11
model_dst = playlistmodel.PlaylistModel(playlist_dst.id) # insert_row = 6
for row in range(self.ROWS_TO_CREATE):
model_dst.insert_row(proposed_row_number=row, note=str(row))
model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id) # model = create_model_with_playlist_rows(session, initial_row_count)
model_dst.refresh_data(session) # model.insert_row(proposed_row_number=insert_row, note=note_text)
# assert model.rowCount() == initial_row_count + 1
# prd = model.playlist_rows[insert_row]
# # Test against edit_role because display_role for headers is
# # handled differently (sets up row span)
# assert (
# model.edit_role(model.rowCount() - 1, playlistmodel.Col.NOTE.value, prd)
# == note_text
# )
assert len(model_src.playlist_rows) == self.ROWS_TO_CREATE - len(from_rows)
assert len(model_dst.playlist_rows) == self.ROWS_TO_CREATE + len(from_rows)
assert sorted([a.plr_rownum for a in model_src.playlist_rows.values()]) == list(
range(len(model_src.playlist_rows))
)
def test_move_one_row_between_playlists_to_middle(self): # def test_add_track_to_header(monkeypatch, session):
from_rows = [3] # monkeypatch.setattr(playlistmodel, "Session", session)
to_row = 2 # note_text = "test text"
destination_playlist = "destination" # initial_row_count = 11
# insert_row = 6
model_src = self.model # model = create_model_with_playlist_rows(session, initial_row_count)
with db.Session() as session: # model.insert_row(proposed_row_number=insert_row, note=note_text)
playlist_dst = Playlists(session, destination_playlist) # assert model.rowCount() == initial_row_count + 1
model_dst = playlistmodel.PlaylistModel(playlist_dst.id)
for row in range(self.ROWS_TO_CREATE):
model_dst.insert_row(proposed_row_number=row, note=str(row))
model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id) # prd = model.playlist_rows[1]
model_dst.refresh_data(session) # model.add_track_to_header(insert_row, prd.track_id)
# Check the rows of the destination model
row_notes = []
for row_number in range(model_dst.rowCount()):
index = model_dst.index(
row_number, playlistmodel.Col.TITLE.value, QModelIndex()
)
row_notes.append(model_dst.data(index, Qt.ItemDataRole.EditRole).value())
assert len(model_src.playlist_rows) == self.ROWS_TO_CREATE - len(from_rows) # def test_create_model_with_tracks(monkeypatch, session):
assert len(model_dst.playlist_rows) == self.ROWS_TO_CREATE + len(from_rows) # monkeypatch.setattr(playlistmodel, "Session", session)
assert [int(a) for a in row_notes] == [0, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10] # model = create_model_with_tracks(session)
# assert len(model.playlist_rows) == len(self.test_tracks)
def test_move_multiple_rows_between_playlists_to_end(self):
from_rows = [1, 3, 4] # def test_timing_one_track(monkeypatch, session):
to_row = 2 # START_ROW = 0
destination_playlist = "destination" # END_ROW = 2
model_src = self.model # monkeypatch.setattr(playlistmodel, "Session", session)
with db.Session() as session: # model = create_model_with_tracks(session)
playlist_dst = Playlists(session, destination_playlist)
model_dst = playlistmodel.PlaylistModel(playlist_dst.id)
for row in range(self.ROWS_TO_CREATE):
model_dst.insert_row(proposed_row_number=row, note=str(row))
model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id) # model.insert_row(proposed_row_number=START_ROW, note="start+")
model_dst.refresh_data(session) # model.insert_row(proposed_row_number=END_ROW, note="-")
# Check the rows of the destination model # prd = model.playlist_rows[START_ROW]
row_notes = [] # qv_value = model.display_role(START_ROW, playlistmodel.HEADER_NOTES_COLUMN, prd)
for row_number in range(model_dst.rowCount()): # assert qv_value.value() == "start [1 tracks, 4:23 unplayed]"
index = model_dst.index(
row_number, playlistmodel.Col.TITLE.value, QModelIndex()
)
row_notes.append(model_dst.data(index, Qt.ItemDataRole.EditRole).value())
assert len(model_src.playlist_rows) == self.ROWS_TO_CREATE - len(from_rows)
assert len(model_dst.playlist_rows) == self.ROWS_TO_CREATE + len(from_rows) # def test_insert_track_new_playlist(monkeypatch, session):
assert [int(a) for a in row_notes] == [0, 1, 3, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # # insert a track into a new playlist
# monkeypatch.setattr(playlistmodel, "Session", session)
# playlist = Playlists(session, "test playlist")
# # Create a model
# model = playlistmodel.PlaylistModel(playlist.id)
# track_path = self.test_tracks[0]
# metadata = get_file_metadata(track_path)
# track = Tracks(session, **metadata)
# model.insert_row(proposed_row_number=0, track_id=track.id)
# prd = model.playlist_rows[model.rowCount() - 1]
# assert (
# model.edit_role(model.rowCount() - 1, playlistmodel.Col.TITLE.value, prd)
# == metadata["title"]
# )
# def test_reverse_row_groups_one_row(monkeypatch, session):
# monkeypatch.setattr(playlistmodel, "Session", session)
# rows_to_move = [3]
# model_src = create_model_with_playlist_rows(session, 5, name="source")
# result = model_src._reversed_contiguous_row_groups(rows_to_move)
# assert len(result) == 1
# assert result[0] == [3]
# def test_reverse_row_groups_multiple_row(monkeypatch, session):
# monkeypatch.setattr(playlistmodel, "Session", session)
# rows_to_move = [2, 3, 4, 5, 7, 9, 10, 13, 17, 20, 21]
# model_src = create_model_with_playlist_rows(session, 5, name="source")
# result = model_src._reversed_contiguous_row_groups(rows_to_move)
# assert result == [[20, 21], [17], [13], [9, 10], [7], [2, 3, 4, 5]]
# def test_move_one_row_between_playlists_to_end(monkeypatch, session):
# monkeypatch.setattr(playlistmodel, "Session", session)
# create_rowcount = 5
# from_rows = [3]
# to_row = create_rowcount
# model_src = create_model_with_playlist_rows(session, create_rowcount, name="source")
# model_dst = create_model_with_playlist_rows(
# session, create_rowcount, name="destination"
# )
# model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id)
# model_dst.refresh_data(session)
# assert len(model_src.playlist_rows) == create_rowcount - len(from_rows)
# assert len(model_dst.playlist_rows) == create_rowcount + len(from_rows)
# assert sorted([a.plr_rownum for a in model_src.playlist_rows.values()]) == list(
# range(len(model_src.playlist_rows))
# )
# def test_move_one_row_between_playlists_to_middle(monkeypatch, session):
# monkeypatch.setattr(playlistmodel, "Session", session)
# create_rowcount = 5
# from_rows = [3]
# to_row = 2
# model_src = create_model_with_playlist_rows(session, create_rowcount, name="source")
# model_dst = create_model_with_playlist_rows(
# session, create_rowcount, name="destination"
# )
# model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id)
# model_dst.refresh_data(session)
# # Check the rows of the destination model
# row_notes = []
# for row_number in range(model_dst.rowCount()):
# index = model_dst.index(
# row_number, playlistmodel.Col.TITLE.value, QModelIndex()
# )
# row_notes.append(model_dst.data(index, Qt.ItemDataRole.EditRole).value())
# assert len(model_src.playlist_rows) == create_rowcount - len(from_rows)
# assert len(model_dst.playlist_rows) == create_rowcount + len(from_rows)
# assert [int(a) for a in row_notes] == [0, 1, 3, 2, 3, 4]
# def test_move_multiple_rows_between_playlists_to_end(monkeypatch, session):
# monkeypatch.setattr(playlistmodel, "Session", session)
# create_rowcount = 5
# from_rows = [1, 3, 4]
# to_row = 2
# model_src = create_model_with_playlist_rows(session, create_rowcount, name="source")
# model_dst = create_model_with_playlist_rows(
# session, create_rowcount, name="destination"
# )
# model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id)
# model_dst.refresh_data(session)
# # Check the rows of the destination model
# row_notes = []
# for row_number in range(model_dst.rowCount()):
# index = model_dst.index(
# row_number, playlistmodel.Col.TITLE.value, QModelIndex()
# )
# row_notes.append(model_dst.data(index, Qt.ItemDataRole.EditRole).value())
# assert len(model_src.playlist_rows) == create_rowcount - len(from_rows)
# assert len(model_dst.playlist_rows) == create_rowcount + len(from_rows)
# assert [int(a) for a in row_notes] == [0, 1, 3, 4, 1, 2, 3, 4]
# # def test_edit_header(monkeypatch, session): # edit header row in middle of playlist # # def test_edit_header(monkeypatch, session): # edit header row in middle of playlist