Improve test coverage
This commit is contained in:
parent
ebf62fe161
commit
6890e0d0c2
@ -1,5 +1,5 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timedelta
|
import datetime as dt
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtSignal, QObject, QThread
|
from PyQt6.QtCore import pyqtSignal, QObject, QThread
|
||||||
@ -108,7 +108,7 @@ class PlaylistTrack:
|
|||||||
|
|
||||||
self.artist: Optional[str] = None
|
self.artist: Optional[str] = None
|
||||||
self.duration: Optional[int] = None
|
self.duration: Optional[int] = None
|
||||||
self.end_time: Optional[datetime] = None
|
self.end_time: Optional[dt.datetime] = None
|
||||||
self.fade_at: Optional[int] = None
|
self.fade_at: Optional[int] = None
|
||||||
self.fade_graph: Optional[FadeCurve] = None
|
self.fade_graph: Optional[FadeCurve] = None
|
||||||
self.fade_graph_start_updates: Optional[datetime] = None
|
self.fade_graph_start_updates: Optional[datetime] = None
|
||||||
@ -120,7 +120,7 @@ class PlaylistTrack:
|
|||||||
self.resume_marker: Optional[float] = None
|
self.resume_marker: Optional[float] = None
|
||||||
self.silence_at: Optional[int] = None
|
self.silence_at: Optional[int] = None
|
||||||
self.start_gap: Optional[int] = None
|
self.start_gap: Optional[int] = None
|
||||||
self.start_time: Optional[datetime] = None
|
self.start_time: Optional[dt.datetime] = None
|
||||||
self.title: Optional[str] = None
|
self.title: Optional[str] = None
|
||||||
self.track_id: Optional[int] = None
|
self.track_id: Optional[int] = None
|
||||||
|
|
||||||
@ -178,10 +178,9 @@ class PlaylistTrack:
|
|||||||
Called when track starts playing
|
Called when track starts playing
|
||||||
"""
|
"""
|
||||||
|
|
||||||
now = datetime.now()
|
self.start_time = dt.datetime.now()
|
||||||
self.start_time = now
|
|
||||||
if self.duration:
|
if self.duration:
|
||||||
self.end_time = self.start_time + timedelta(milliseconds=self.duration)
|
self.end_time = self.start_time + dt.timedelta(milliseconds=self.duration)
|
||||||
|
|
||||||
# Calculate time fade_graph should start updating
|
# Calculate time fade_graph should start updating
|
||||||
if self.fade_at:
|
if self.fade_at:
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import datetime
|
import datetime as dt
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
@ -38,7 +38,7 @@ class Config(object):
|
|||||||
DEBUG_MODULES: List[Optional[str]] = ["dbconfig"]
|
DEBUG_MODULES: List[Optional[str]] = ["dbconfig"]
|
||||||
DEFAULT_COLUMN_WIDTH = 200
|
DEFAULT_COLUMN_WIDTH = 200
|
||||||
DISPLAY_SQL = False
|
DISPLAY_SQL = False
|
||||||
EPOCH = datetime.datetime(1970, 1, 1)
|
EPOCH = dt.datetime(1970, 1, 1)
|
||||||
ERRORS_FROM = ["noreply@midnighthax.com"]
|
ERRORS_FROM = ["noreply@midnighthax.com"]
|
||||||
ERRORS_TO = ["kae@midnighthax.com"]
|
ERRORS_TO = ["kae@midnighthax.com"]
|
||||||
FADE_CURVE_BACKGROUND = "lightyellow"
|
FADE_CURVE_BACKGROUND = "lightyellow"
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime
|
import datetime as dt
|
||||||
from email.message import EmailMessage
|
from email.message import EmailMessage
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
import functools
|
import functools
|
||||||
@ -99,7 +99,7 @@ def get_audio_segment(path: str) -> Optional[AudioSegment]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_embedded_time(text: str) -> Optional[datetime]:
|
def get_embedded_time(text: str) -> Optional[dt.datetime]:
|
||||||
"""Return datetime specified as @hh:mm in text"""
|
"""Return datetime specified as @hh:mm in text"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -110,7 +110,7 @@ def get_embedded_time(text: str) -> Optional[datetime]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return datetime.strptime(match.group(0)[1:], Config.NOTE_TIME_FORMAT)
|
return dt.datetime.strptime(match.group(0)[1:], Config.NOTE_TIME_FORMAT)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ def get_file_metadata(filepath: str) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def get_relative_date(
|
def get_relative_date(
|
||||||
past_date: Optional[datetime], reference_date: Optional[datetime] = None
|
past_date: Optional[dt.datetime], reference_date: Optional[dt.datetime] = None
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Return how long before reference_date past_date is as string.
|
Return how long before reference_date past_date is as string.
|
||||||
@ -158,7 +158,7 @@ def get_relative_date(
|
|||||||
if not past_date or past_date == Config.EPOCH:
|
if not past_date or past_date == Config.EPOCH:
|
||||||
return "Never"
|
return "Never"
|
||||||
if not reference_date:
|
if not reference_date:
|
||||||
reference_date = datetime.now()
|
reference_date = dt.datetime.now()
|
||||||
|
|
||||||
# Check parameters
|
# Check parameters
|
||||||
if past_date > reference_date:
|
if past_date > reference_date:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from datetime import datetime
|
import datetime as dt
|
||||||
from slugify import slugify # type: ignore
|
from slugify import slugify # type: ignore
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from PyQt6.QtCore import QUrl # type: ignore
|
from PyQt6.QtCore import QUrl # type: ignore
|
||||||
@ -24,14 +24,14 @@ class InfoTabs(QTabWidget):
|
|||||||
self.signals.search_songfacts_signal.connect(self.open_in_songfacts)
|
self.signals.search_songfacts_signal.connect(self.open_in_songfacts)
|
||||||
self.signals.search_wikipedia_signal.connect(self.open_in_wikipedia)
|
self.signals.search_wikipedia_signal.connect(self.open_in_wikipedia)
|
||||||
# re-use the oldest one later)
|
# re-use the oldest one later)
|
||||||
self.last_update: Dict[QWebEngineView, datetime] = {}
|
self.last_update: Dict[QWebEngineView, dt.datetime] = {}
|
||||||
self.tabtitles: Dict[int, str] = {}
|
self.tabtitles: Dict[int, str] = {}
|
||||||
|
|
||||||
# Create one tab which (for some reason) creates flickering if
|
# Create one tab which (for some reason) creates flickering if
|
||||||
# done later
|
# done later
|
||||||
widget = QWebEngineView()
|
widget = QWebEngineView()
|
||||||
widget.setZoomFactor(Config.WEB_ZOOM_FACTOR)
|
widget.setZoomFactor(Config.WEB_ZOOM_FACTOR)
|
||||||
self.last_update[widget] = datetime.now()
|
self.last_update[widget] = dt.datetime.now()
|
||||||
_ = self.addTab(widget, "")
|
_ = self.addTab(widget, "")
|
||||||
|
|
||||||
def open_in_songfacts(self, title):
|
def open_in_songfacts(self, title):
|
||||||
@ -80,7 +80,7 @@ class InfoTabs(QTabWidget):
|
|||||||
self.setTabText(tab_index, short_title)
|
self.setTabText(tab_index, short_title)
|
||||||
|
|
||||||
widget.setUrl(QUrl(url))
|
widget.setUrl(QUrl(url))
|
||||||
self.last_update[widget] = datetime.now()
|
self.last_update[widget] = dt.datetime.now()
|
||||||
self.tabtitles[tab_index] = url
|
self.tabtitles[tab_index] = url
|
||||||
|
|
||||||
# Show newly updated tab
|
# Show newly updated tab
|
||||||
|
|||||||
@ -5,8 +5,7 @@ import re
|
|||||||
from config import Config
|
from config import Config
|
||||||
from dbconfig import scoped_session
|
from dbconfig import scoped_session
|
||||||
|
|
||||||
from datetime import datetime
|
import datetime as dt
|
||||||
from pprint import pprint
|
|
||||||
from typing import List, Optional, Sequence
|
from typing import List, Optional, Sequence
|
||||||
|
|
||||||
from sqlalchemy.ext.associationproxy import association_proxy
|
from sqlalchemy.ext.associationproxy import association_proxy
|
||||||
@ -162,7 +161,7 @@ class Playdates(Base):
|
|||||||
__tablename__ = "playdates"
|
__tablename__ = "playdates"
|
||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||||
lastplayed: Mapped[datetime] = mapped_column(index=True)
|
lastplayed: Mapped[dt.datetime] = mapped_column(index=True)
|
||||||
track_id: Mapped[int] = mapped_column(ForeignKey("tracks.id"))
|
track_id: Mapped[int] = mapped_column(ForeignKey("tracks.id"))
|
||||||
track: Mapped["Tracks"] = relationship("Tracks", back_populates="playdates")
|
track: Mapped["Tracks"] = relationship("Tracks", back_populates="playdates")
|
||||||
|
|
||||||
@ -175,13 +174,13 @@ class Playdates(Base):
|
|||||||
def __init__(self, session: scoped_session, track_id: int) -> None:
|
def __init__(self, session: scoped_session, track_id: int) -> None:
|
||||||
"""Record that track was played"""
|
"""Record that track was played"""
|
||||||
|
|
||||||
self.lastplayed = datetime.now()
|
self.lastplayed = dt.datetime.now()
|
||||||
self.track_id = track_id
|
self.track_id = track_id
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def last_played(session: scoped_session, track_id: int) -> datetime:
|
def last_played(session: scoped_session, track_id: int) -> dt.datetime:
|
||||||
"""Return datetime track last played or None"""
|
"""Return datetime track last played or None"""
|
||||||
|
|
||||||
last_played = session.execute(
|
last_played = session.execute(
|
||||||
@ -194,10 +193,12 @@ class Playdates(Base):
|
|||||||
if last_played:
|
if last_played:
|
||||||
return last_played[0]
|
return last_played[0]
|
||||||
else:
|
else:
|
||||||
return Config.EPOCH
|
# Should never be reached as we create record with a
|
||||||
|
# last_played value
|
||||||
|
return Config.EPOCH # pragma: no cover
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def played_after(session: scoped_session, since: datetime) -> Sequence["Playdates"]:
|
def played_after(session: scoped_session, since: dt.datetime) -> Sequence["Playdates"]:
|
||||||
"""Return a list of Playdates objects since passed time"""
|
"""Return a list of Playdates objects since passed time"""
|
||||||
|
|
||||||
return session.scalars(
|
return session.scalars(
|
||||||
@ -216,7 +217,7 @@ class Playlists(Base):
|
|||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||||
name: Mapped[str] = mapped_column(String(32), unique=True)
|
name: Mapped[str] = mapped_column(String(32), unique=True)
|
||||||
last_used: Mapped[Optional[datetime]] = mapped_column(DateTime, default=None)
|
last_used: Mapped[Optional[dt.datetime]] = mapped_column(DateTime, default=None)
|
||||||
tab: Mapped[Optional[int]] = mapped_column(default=None)
|
tab: Mapped[Optional[int]] = mapped_column(default=None)
|
||||||
open: Mapped[bool] = mapped_column(default=False)
|
open: Mapped[bool] = mapped_column(default=False)
|
||||||
is_template: Mapped[bool] = mapped_column(default=False)
|
is_template: Mapped[bool] = mapped_column(default=False)
|
||||||
@ -328,7 +329,7 @@ class Playlists(Base):
|
|||||||
"""Mark playlist as loaded and used now"""
|
"""Mark playlist as loaded and used now"""
|
||||||
|
|
||||||
self.open = True
|
self.open = True
|
||||||
self.last_used = datetime.now()
|
self.last_used = dt.datetime.now()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def name_is_available(session: scoped_session, name: str) -> bool:
|
def name_is_available(session: scoped_session, name: str) -> bool:
|
||||||
@ -586,8 +587,6 @@ class PlaylistRows(Base):
|
|||||||
cls,
|
cls,
|
||||||
session: scoped_session,
|
session: scoped_session,
|
||||||
playlist_id: int,
|
playlist_id: int,
|
||||||
from_row: Optional[int] = None,
|
|
||||||
to_row: Optional[int] = None,
|
|
||||||
) -> Sequence["PlaylistRows"]:
|
) -> Sequence["PlaylistRows"]:
|
||||||
"""
|
"""
|
||||||
For passed playlist, return a list of rows that
|
For passed playlist, return a list of rows that
|
||||||
@ -597,11 +596,6 @@ class PlaylistRows(Base):
|
|||||||
query = select(cls).where(
|
query = select(cls).where(
|
||||||
cls.playlist_id == playlist_id, cls.track_id.is_not(None)
|
cls.playlist_id == playlist_id, cls.track_id.is_not(None)
|
||||||
)
|
)
|
||||||
if from_row is not None:
|
|
||||||
query = query.where(cls.plr_rownum >= from_row)
|
|
||||||
if to_row is not None:
|
|
||||||
query = query.where(cls.plr_rownum <= to_row)
|
|
||||||
|
|
||||||
plrs = session.scalars((query).order_by(cls.plr_rownum)).all()
|
plrs = session.scalars((query).order_by(cls.plr_rownum)).all()
|
||||||
|
|
||||||
return plrs
|
return plrs
|
||||||
@ -682,7 +676,7 @@ class Settings(Base):
|
|||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||||
name: Mapped[str] = mapped_column(String(64), unique=True)
|
name: Mapped[str] = mapped_column(String(64), unique=True)
|
||||||
f_datetime: Mapped[Optional[datetime]] = mapped_column(default=None)
|
f_datetime: Mapped[Optional[dt.datetime]] = mapped_column(default=None)
|
||||||
f_int: Mapped[Optional[int]] = mapped_column(default=None)
|
f_int: Mapped[Optional[int]] = mapped_column(default=None)
|
||||||
f_string: Mapped[Optional[str]] = mapped_column(String(128), default=None)
|
f_string: Mapped[Optional[str]] = mapped_column(String(128), default=None)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
import datetime as dt
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from typing import (
|
from typing import (
|
||||||
cast,
|
cast,
|
||||||
@ -208,14 +208,12 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
self.music: music.Music = music.Music()
|
self.music: music.Music = music.Music()
|
||||||
self.playing: bool = False
|
self.playing: bool = False
|
||||||
|
|
||||||
self.selected_plrs: Optional[List[PlaylistRows]] = None
|
|
||||||
|
|
||||||
self.set_main_window_size()
|
self.set_main_window_size()
|
||||||
self.lblSumPlaytime = QLabel("")
|
self.lblSumPlaytime = QLabel("")
|
||||||
self.statusbar.addPermanentWidget(self.lblSumPlaytime)
|
self.statusbar.addPermanentWidget(self.lblSumPlaytime)
|
||||||
self.txtSearch = QLineEdit()
|
self.txtSearch = QLineEdit()
|
||||||
self.statusbar.addWidget(self.txtSearch)
|
|
||||||
self.txtSearch.setHidden(True)
|
self.txtSearch.setHidden(True)
|
||||||
|
self.statusbar.addWidget(self.txtSearch)
|
||||||
self.hide_played_tracks = False
|
self.hide_played_tracks = False
|
||||||
mixer.init()
|
mixer.init()
|
||||||
self.widgetFadeVolume.hideAxis("bottom")
|
self.widgetFadeVolume.hideAxis("bottom")
|
||||||
@ -755,7 +753,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if track_sequence.now.track_id is None or track_sequence.now.start_time is None:
|
if track_sequence.now.track_id is None or track_sequence.now.start_time is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
now = datetime.now()
|
now = dt.datetime.now()
|
||||||
track_start = track_sequence.now.start_time
|
track_start = track_sequence.now.start_time
|
||||||
elapsed_seconds = (now - track_start).total_seconds()
|
elapsed_seconds = (now - track_start).total_seconds()
|
||||||
return int(elapsed_seconds * 1000)
|
return int(elapsed_seconds * 1000)
|
||||||
@ -902,7 +900,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
if playlist:
|
if playlist:
|
||||||
_ = self.create_playlist_tab(playlist)
|
_ = self.create_playlist_tab(playlist)
|
||||||
playlist_ids.append(playlist.id)
|
playlist_ids.append(playlist.id)
|
||||||
log.info(f"load_last_playlists() loaded {playlist=}")
|
log.debug(f"load_last_playlists() loaded {playlist=}")
|
||||||
# Set active tab
|
# Set active tab
|
||||||
record = Settings.get_int_settings(session, "active_tab")
|
record = Settings.get_int_settings(session, "active_tab")
|
||||||
if record.f_int is not None and record.f_int >= 0:
|
if record.f_int is not None and record.f_int >= 0:
|
||||||
@ -1239,7 +1237,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
and track_sequence.now.resume_marker
|
and track_sequence.now.resume_marker
|
||||||
):
|
):
|
||||||
elapsed_ms = track_sequence.now.duration * track_sequence.now.resume_marker
|
elapsed_ms = track_sequence.now.duration * track_sequence.now.resume_marker
|
||||||
track_sequence.now.start_time -= timedelta(milliseconds=elapsed_ms)
|
track_sequence.now.start_time -= dt.timedelta(milliseconds=elapsed_ms)
|
||||||
|
|
||||||
def save_as_template(self) -> None:
|
def save_as_template(self) -> None:
|
||||||
"""Save current playlist as template"""
|
"""Save current playlist as template"""
|
||||||
@ -1506,7 +1504,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
and track_sequence.now.start_time
|
and track_sequence.now.start_time
|
||||||
):
|
):
|
||||||
play_time = (
|
play_time = (
|
||||||
datetime.now() - track_sequence.now.start_time
|
dt.datetime.now() - track_sequence.now.start_time
|
||||||
).total_seconds() * 1000
|
).total_seconds() * 1000
|
||||||
track_sequence.now.fade_graph.tick(play_time)
|
track_sequence.now.fade_graph.tick(play_time)
|
||||||
|
|
||||||
@ -1515,7 +1513,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
Called every 500ms
|
Called every 500ms
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.lblTOD.setText(datetime.now().strftime(Config.TOD_TIME_FORMAT))
|
self.lblTOD.setText(dt.datetime.now().strftime(Config.TOD_TIME_FORMAT))
|
||||||
# Update carts
|
# Update carts
|
||||||
# self.cart_tick()
|
# self.cart_tick()
|
||||||
|
|
||||||
@ -1543,8 +1541,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
and track_sequence.now.start_time
|
and track_sequence.now.start_time
|
||||||
and (
|
and (
|
||||||
self.music.player.is_playing()
|
self.music.player.is_playing()
|
||||||
or (datetime.now() - track_sequence.now.start_time)
|
or (dt.datetime.now() - track_sequence.now.start_time)
|
||||||
< timedelta(microseconds=Config.PLAY_SETTLE)
|
< dt.timedelta(microseconds=Config.PLAY_SETTLE)
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
playtime = self.get_playtime()
|
playtime = self.get_playtime()
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import obsws_python as obs # type: ignore
|
import obsws_python as obs # type: ignore
|
||||||
import re
|
import re
|
||||||
from datetime import datetime, timedelta
|
import datetime as dt
|
||||||
from enum import auto, Enum
|
from enum import auto, Enum
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from random import shuffle
|
from random import shuffle
|
||||||
@ -62,13 +62,13 @@ class PlaylistRowData:
|
|||||||
self.artist: str = ""
|
self.artist: str = ""
|
||||||
self.bitrate = 0
|
self.bitrate = 0
|
||||||
self.duration: int = 0
|
self.duration: int = 0
|
||||||
self.lastplayed: datetime = Config.EPOCH
|
self.lastplayed: dt.datetime = Config.EPOCH
|
||||||
self.path = ""
|
self.path = ""
|
||||||
self.played = False
|
self.played = False
|
||||||
self.start_gap: Optional[int] = None
|
self.start_gap: Optional[int] = None
|
||||||
self.title: str = ""
|
self.title: str = ""
|
||||||
self.start_time: Optional[datetime] = None
|
self.start_time: Optional[dt.datetime] = None
|
||||||
self.end_time: Optional[datetime] = None
|
self.end_time: Optional[dt.datetime] = None
|
||||||
|
|
||||||
self.plrid: int = plr.id
|
self.plrid: int = plr.id
|
||||||
self.plr_rownum: int = plr.plr_rownum
|
self.plr_rownum: int = plr.plr_rownum
|
||||||
@ -688,7 +688,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
< prd.plr_rownum
|
< prd.plr_rownum
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
section_end_time = track_sequence.now.end_time + timedelta(
|
section_end_time = track_sequence.now.end_time + dt.timedelta(
|
||||||
milliseconds=duration
|
milliseconds=duration
|
||||||
)
|
)
|
||||||
end_time_str = (
|
end_time_str = (
|
||||||
@ -1344,7 +1344,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
|
|
||||||
log.info("update_track_times()")
|
log.info("update_track_times()")
|
||||||
|
|
||||||
next_start_time: Optional[datetime] = None
|
next_start_time: Optional[dt.datetime] = None
|
||||||
update_rows: List[int] = []
|
update_rows: List[int] = []
|
||||||
|
|
||||||
for row_number in range(len(self.playlist_rows)):
|
for row_number in range(len(self.playlist_rows)):
|
||||||
@ -1365,7 +1365,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
and track_sequence.now.end_time
|
and track_sequence.now.end_time
|
||||||
):
|
):
|
||||||
prd.start_time = track_sequence.now.end_time
|
prd.start_time = track_sequence.now.end_time
|
||||||
prd.end_time = prd.start_time + timedelta(milliseconds=prd.duration)
|
prd.end_time = prd.start_time + dt.timedelta(milliseconds=prd.duration)
|
||||||
next_start_time = prd.end_time
|
next_start_time = prd.end_time
|
||||||
update_rows.append(row_number)
|
update_rows.append(row_number)
|
||||||
continue
|
continue
|
||||||
@ -1410,7 +1410,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
update_rows.append(row_number)
|
update_rows.append(row_number)
|
||||||
|
|
||||||
# Calculate next start time
|
# Calculate next start time
|
||||||
next_start_time += timedelta(milliseconds=prd.duration)
|
next_start_time += dt.timedelta(milliseconds=prd.duration)
|
||||||
|
|
||||||
# Update end time of this row if it's incorrect
|
# Update end time of this row if it's incorrect
|
||||||
if prd.end_time != next_start_time:
|
if prd.end_time != next_start_time:
|
||||||
@ -1486,9 +1486,9 @@ class PlaylistProxyModel(QSortFilterProxyModel):
|
|||||||
== self.source_model.playlist_id
|
== self.source_model.playlist_id
|
||||||
):
|
):
|
||||||
if track_sequence.now.start_time:
|
if track_sequence.now.start_time:
|
||||||
if datetime.now() > (
|
if dt.datetime.now() > (
|
||||||
track_sequence.now.start_time
|
track_sequence.now.start_time
|
||||||
+ timedelta(
|
+ dt.timedelta(
|
||||||
milliseconds=Config.HIDE_AFTER_PLAYING_OFFSET
|
milliseconds=Config.HIDE_AFTER_PLAYING_OFFSET
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
import datetime as dt
|
||||||
from threading import Timer
|
from threading import Timer
|
||||||
from pydub import AudioSegment
|
from pydub import AudioSegment
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from timeloop import Timeloop
|
from timeloop import Timeloop # type: ignore
|
||||||
import vlc
|
import vlc # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class RepeatedTimer(object):
|
class RepeatedTimer(object):
|
||||||
@ -124,7 +124,7 @@ def update_progress(player, talk_at, silent_at):
|
|||||||
remaining_time = total_time - elapsed_time
|
remaining_time = total_time - elapsed_time
|
||||||
talk_time = remaining_time - (total_time - talk_at)
|
talk_time = remaining_time - (total_time - talk_at)
|
||||||
silent_time = remaining_time - (total_time - silent_at)
|
silent_time = remaining_time - (total_time - silent_at)
|
||||||
end_time = (datetime.now() + timedelta(
|
end_time = (dt.datetime.now() + timedelta(
|
||||||
milliseconds=remaining_time)).strftime("%H:%M:%S")
|
milliseconds=remaining_time)).strftime("%H:%M:%S")
|
||||||
print(
|
print(
|
||||||
f"\t{ms_to_mmss(elapsed_time)}/"
|
f"\t{ms_to_mmss(elapsed_time)}/"
|
||||||
|
|||||||
89
poetry.lock
generated
89
poetry.lock
generated
@ -292,6 +292,74 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
development = ["black", "flake8", "mypy", "pytest", "types-colorama"]
|
development = ["black", "flake8", "mypy", "pytest", "types-colorama"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coverage"
|
||||||
|
version = "7.4.4"
|
||||||
|
description = "Code coverage measurement for Python"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-win32.whl", hash = "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d"},
|
||||||
|
{file = "coverage-7.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-win32.whl", hash = "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286"},
|
||||||
|
{file = "coverage-7.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-win32.whl", hash = "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0"},
|
||||||
|
{file = "coverage-7.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-win32.whl", hash = "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e"},
|
||||||
|
{file = "coverage-7.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-win32.whl", hash = "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57"},
|
||||||
|
{file = "coverage-7.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c"},
|
||||||
|
{file = "coverage-7.4.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677"},
|
||||||
|
{file = "coverage-7.4.4.tar.gz", hash = "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
toml = ["tomli"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "decorator"
|
name = "decorator"
|
||||||
version = "5.1.1"
|
version = "5.1.1"
|
||||||
@ -1524,6 +1592,25 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest-cov"
|
||||||
|
version = "5.0.0"
|
||||||
|
description = "Pytest plugin for measuring coverage."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"},
|
||||||
|
{file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||||
|
pytest = ">=4.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-qt"
|
name = "pytest-qt"
|
||||||
version = "4.4.0"
|
version = "4.4.0"
|
||||||
@ -2186,4 +2273,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "9fc13f4695a3be773cbbdcc175495650e638f31d786f6e35724b57f70bcb5f78"
|
content-hash = "500cefc31e30cba9ae917cc51b7407961d69825d1fcae53515ed1fa12f4ab171"
|
||||||
|
|||||||
@ -44,6 +44,7 @@ black = "^24.2.0"
|
|||||||
flakehell = "^0.9.0"
|
flakehell = "^0.9.0"
|
||||||
mypy = "^1.7.0"
|
mypy = "^1.7.0"
|
||||||
pdbp = "^1.5.0"
|
pdbp = "^1.5.0"
|
||||||
|
pytest-cov = "^5.0.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime, timedelta
|
import datetime as dt
|
||||||
from helpers import (
|
from helpers import (
|
||||||
fade_point,
|
fade_point,
|
||||||
get_audio_segment,
|
get_audio_segment,
|
||||||
@ -43,12 +43,12 @@ def test_get_tags():
|
|||||||
|
|
||||||
def test_get_relative_date():
|
def test_get_relative_date():
|
||||||
assert get_relative_date(None) == "Never"
|
assert get_relative_date(None) == "Never"
|
||||||
today_at_10 = datetime.now().replace(hour=10, minute=0)
|
today_at_10 = dt.datetime.now().replace(hour=10, minute=0)
|
||||||
today_at_11 = datetime.now().replace(hour=11, minute=0)
|
today_at_11 = dt.datetime.now().replace(hour=11, minute=0)
|
||||||
assert get_relative_date(today_at_10, today_at_11) == "Today 10:00"
|
assert get_relative_date(today_at_10, today_at_11) == "Today 10:00"
|
||||||
eight_days_ago = today_at_10 - timedelta(days=8)
|
eight_days_ago = today_at_10 - dt.timedelta(days=8)
|
||||||
assert get_relative_date(eight_days_ago, today_at_11) == "1 week, 1 day ago"
|
assert get_relative_date(eight_days_ago, today_at_11) == "1 week, 1 day ago"
|
||||||
sixteen_days_ago = today_at_10 - timedelta(days=16)
|
sixteen_days_ago = today_at_10 - dt.timedelta(days=16)
|
||||||
assert get_relative_date(sixteen_days_ago, today_at_11) == "2 weeks, 2 days ago"
|
assert get_relative_date(sixteen_days_ago, today_at_11) == "2 weeks, 2 days ago"
|
||||||
|
|
||||||
|
|
||||||
25
tests/test_misc.py
Normal file
25
tests/test_misc.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import pytest
|
||||||
|
from models import NoteColours, Settings
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_exception():
|
||||||
|
"""Test deliberate exception"""
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
1 / 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_settings(session):
|
||||||
|
SETTING_NAME = "wombat"
|
||||||
|
NO_SUCH_SETTING = "abc"
|
||||||
|
VALUE = 3
|
||||||
|
|
||||||
|
setting = Settings(session, SETTING_NAME)
|
||||||
|
setting.update(session, dict(f_int=VALUE))
|
||||||
|
print(setting)
|
||||||
|
_ = Settings.all_as_dict(session)
|
||||||
|
test = Settings.get_int_settings(session, SETTING_NAME)
|
||||||
|
assert test.name == SETTING_NAME
|
||||||
|
assert test.f_int == VALUE
|
||||||
|
test_new = Settings.get_int_settings(session, NO_SUCH_SETTING)
|
||||||
|
assert test_new.name == NO_SUCH_SETTING
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import os.path
|
import datetime as dt
|
||||||
|
|
||||||
import helpers
|
|
||||||
|
|
||||||
from app.models import (
|
from app.models import (
|
||||||
|
Carts,
|
||||||
NoteColours,
|
NoteColours,
|
||||||
Playdates,
|
Playdates,
|
||||||
Playlists,
|
Playlists,
|
||||||
|
PlaylistRows,
|
||||||
Tracks,
|
Tracks,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -60,68 +60,44 @@ def test_playdates_add_playdate(session, track1):
|
|||||||
|
|
||||||
playdate = Playdates(session, track1.id)
|
playdate = Playdates(session, track1.id)
|
||||||
assert playdate
|
assert playdate
|
||||||
|
print(playdate)
|
||||||
|
|
||||||
last_played = Playdates.last_played(session, track1.id)
|
last_played = Playdates.last_played(session, track1.id)
|
||||||
assert abs((playdate.lastplayed - last_played).total_seconds()) < 2
|
assert abs((playdate.lastplayed - last_played).total_seconds()) < 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_playdates_played_after(session, track1):
|
||||||
|
playdate = Playdates(session, track1.id)
|
||||||
|
yesterday = dt.datetime.now() - dt.timedelta(days=1)
|
||||||
|
played = Playdates.played_after(session, yesterday)
|
||||||
|
|
||||||
|
assert len(played) == 1
|
||||||
|
assert played[0] == playdate
|
||||||
|
|
||||||
|
|
||||||
def test_playlist_create(session):
|
def test_playlist_create(session):
|
||||||
|
TEMPLATE_NAME = "my template"
|
||||||
|
|
||||||
playlist = Playlists(session, "my playlist")
|
playlist = Playlists(session, "my playlist")
|
||||||
assert playlist
|
assert playlist
|
||||||
|
print(playlist)
|
||||||
|
|
||||||
|
# test clear tabs
|
||||||
|
Playlists.clear_tabs(session, [playlist.id])
|
||||||
|
|
||||||
# def test_playlist_add_track(session, track):
|
# create template
|
||||||
# # We need a playlist
|
Playlists.save_as_template(session, playlist.id, TEMPLATE_NAME)
|
||||||
# playlist = Playlists(session, "my playlist")
|
|
||||||
|
|
||||||
# row = 17
|
# test create template
|
||||||
|
_ = Playlists.create_playlist_from_template(session, playlist, "my new name")
|
||||||
|
|
||||||
# playlist.add_track(session, track.id, row)
|
# get all templates
|
||||||
|
all_templates = Playlists.get_all_templates(session)
|
||||||
# assert len(playlist.tracks) == 1
|
assert len(all_templates) == 1
|
||||||
# playlist_track = playlist.tracks[row]
|
# Save as template creates new playlist
|
||||||
# assert playlist_track.path == track_path
|
assert all_templates[0] != playlist
|
||||||
|
# test delete playlist
|
||||||
|
playlist.delete(session)
|
||||||
# def test_playlist_tracks(session):
|
|
||||||
# # We need a playlist
|
|
||||||
# playlist = Playlists(session, "my playlist")
|
|
||||||
|
|
||||||
# # We need two tracks
|
|
||||||
# track1_path = "/a/b/c"
|
|
||||||
# track1_row = 17
|
|
||||||
# track1 = Tracks(session, track1_path)
|
|
||||||
|
|
||||||
# track2_path = "/x/y/z"
|
|
||||||
# track2_row = 29
|
|
||||||
# track2 = Tracks(session, track2_path)
|
|
||||||
|
|
||||||
# playlist.add_track(session, track1.id, track1_row)
|
|
||||||
# playlist.add_track(session, track2.id, track2_row)
|
|
||||||
|
|
||||||
# tracks = playlist.tracks
|
|
||||||
# assert tracks[track1_row] == track1
|
|
||||||
# assert tracks[track2_row] == track2
|
|
||||||
|
|
||||||
|
|
||||||
# def test_playlist_notes(session):
|
|
||||||
# # We need a playlist
|
|
||||||
# playlist = Playlists(session, "my playlist")
|
|
||||||
|
|
||||||
# # We need two notes
|
|
||||||
# note1_text = "note1 text"
|
|
||||||
# note1_row = 11
|
|
||||||
# _ = Notes(session, playlist.id, note1_row, note1_text)
|
|
||||||
|
|
||||||
# note2_text = "note2 text"
|
|
||||||
# note2_row = 19
|
|
||||||
# _ = Notes(session, playlist.id, note2_row, note2_text)
|
|
||||||
|
|
||||||
# notes = playlist.notes
|
|
||||||
# assert note1_text in [n.note for n in notes]
|
|
||||||
# assert note1_row in [n.row for n in notes]
|
|
||||||
# assert note2_text in [n.note for n in notes]
|
|
||||||
# assert note2_row in [n.row for n in notes]
|
|
||||||
|
|
||||||
|
|
||||||
def test_playlist_open_and_close(session):
|
def test_playlist_open_and_close(session):
|
||||||
@ -184,3 +160,91 @@ def test_tracks_search_titles(session, track1):
|
|||||||
track1_title = "I'm So Afraid"
|
track1_title = "I'm So Afraid"
|
||||||
|
|
||||||
assert len(Tracks.search_titles(session, track1_title)) == 1
|
assert len(Tracks.search_titles(session, track1_title)) == 1
|
||||||
|
|
||||||
|
def test_repr(session):
|
||||||
|
"""Just check for error retrieving reprs"""
|
||||||
|
|
||||||
|
nc = NoteColours(session, substring="x", colour="x")
|
||||||
|
print(nc)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_colour(session):
|
||||||
|
"""Test for errors in execution"""
|
||||||
|
|
||||||
|
GOOD_STRING = "cantelope"
|
||||||
|
BAD_STRING = "ericTheBee"
|
||||||
|
SUBSTR = "ant"
|
||||||
|
COLOUR = "blue"
|
||||||
|
|
||||||
|
nc1 = NoteColours(session, substring=SUBSTR, colour=COLOUR, is_casesensitive=True)
|
||||||
|
|
||||||
|
_ = nc1.get_colour(session, "")
|
||||||
|
colour = nc1.get_colour(session, GOOD_STRING)
|
||||||
|
assert colour == COLOUR
|
||||||
|
|
||||||
|
colour = nc1.get_colour(session, BAD_STRING)
|
||||||
|
assert colour is None
|
||||||
|
|
||||||
|
nc2 = NoteColours(session, substring=".*" + SUBSTR, colour=COLOUR, is_regex=True)
|
||||||
|
colour = nc2.get_colour(session, GOOD_STRING)
|
||||||
|
assert colour == COLOUR
|
||||||
|
|
||||||
|
colour = nc2.get_colour(session, BAD_STRING)
|
||||||
|
assert colour is None
|
||||||
|
|
||||||
|
nc3 = NoteColours(
|
||||||
|
session, substring=".*" + SUBSTR, colour=COLOUR, is_regex=True, is_casesensitive=True
|
||||||
|
)
|
||||||
|
|
||||||
|
colour = nc3.get_colour(session, GOOD_STRING)
|
||||||
|
assert colour == COLOUR
|
||||||
|
|
||||||
|
colour = nc3.get_colour(session, BAD_STRING)
|
||||||
|
assert colour is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_cart(session):
|
||||||
|
cart = Carts(session, 1, "name")
|
||||||
|
assert cart
|
||||||
|
print(cart)
|
||||||
|
|
||||||
|
|
||||||
|
def test_name_available(session):
|
||||||
|
PLAYLIST_NAME = "a name"
|
||||||
|
RENAME = "new name"
|
||||||
|
|
||||||
|
if Playlists.name_is_available(session, PLAYLIST_NAME):
|
||||||
|
playlist = Playlists(session, PLAYLIST_NAME)
|
||||||
|
assert playlist
|
||||||
|
|
||||||
|
assert Playlists.name_is_available(session, PLAYLIST_NAME) is False
|
||||||
|
|
||||||
|
playlist.rename(session, RENAME)
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_playlist_row(session):
|
||||||
|
PLAYLIST_NAME = "a name"
|
||||||
|
|
||||||
|
if Playlists.name_is_available(session, PLAYLIST_NAME):
|
||||||
|
playlist = Playlists(session, PLAYLIST_NAME)
|
||||||
|
|
||||||
|
plr = PlaylistRows(session, playlist.id, 1)
|
||||||
|
assert plr
|
||||||
|
print(plr)
|
||||||
|
plr.append_note("a note")
|
||||||
|
plr.append_note("another note")
|
||||||
|
|
||||||
|
|
||||||
|
def test_delete_plr(session):
|
||||||
|
PLAYLIST_NAME = "a name"
|
||||||
|
|
||||||
|
if Playlists.name_is_available(session, PLAYLIST_NAME):
|
||||||
|
playlist = Playlists(session, PLAYLIST_NAME)
|
||||||
|
|
||||||
|
plr = PlaylistRows(session, playlist.id, 1)
|
||||||
|
assert plr
|
||||||
|
PlaylistRows.delete_higher_rows(session, plr.playlist_id, 10)
|
||||||
|
|
||||||
|
assert PlaylistRows.get_track_plr(session, 12, plr.playlist_id) is None
|
||||||
|
|
||||||
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
from pprint import pprint
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from app.models import (
|
from app.models import (
|
||||||
@ -228,6 +227,20 @@ def test_insert_header_row_middle(monkeypatch, session):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_track_to_header(monkeypatch, session):
|
||||||
|
monkeypatch.setattr(playlistmodel, "Session", session)
|
||||||
|
note_text = "test text"
|
||||||
|
initial_row_count = 11
|
||||||
|
insert_row = 6
|
||||||
|
|
||||||
|
model = create_model_with_playlist_rows(session, initial_row_count)
|
||||||
|
model.insert_row(proposed_row_number=insert_row, note=note_text)
|
||||||
|
assert model.rowCount() == initial_row_count + 1
|
||||||
|
|
||||||
|
prd = model.playlist_rows[1]
|
||||||
|
model.add_track_to_header(insert_row, prd.track_id)
|
||||||
|
|
||||||
|
|
||||||
def test_create_model_with_tracks(monkeypatch, session):
|
def test_create_model_with_tracks(monkeypatch, session):
|
||||||
monkeypatch.setattr(playlistmodel, "Session", session)
|
monkeypatch.setattr(playlistmodel, "Session", session)
|
||||||
model = create_model_with_tracks(session)
|
model = create_model_with_tracks(session)
|
||||||
@ -303,7 +316,7 @@ def test_move_one_row_between_playlists_to_end(monkeypatch, session):
|
|||||||
model_src = create_model_with_playlist_rows(session, create_rowcount, name="source")
|
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_dst = create_model_with_playlist_rows(session, create_rowcount, name="destination")
|
||||||
|
|
||||||
model_src.move_rows_between_playlists(from_rows, to_row, model_dst)
|
model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id)
|
||||||
model_dst.refresh_data(session)
|
model_dst.refresh_data(session)
|
||||||
|
|
||||||
assert len(model_src.playlist_rows) == create_rowcount - len(from_rows)
|
assert len(model_src.playlist_rows) == create_rowcount - len(from_rows)
|
||||||
@ -323,7 +336,7 @@ def test_move_one_row_between_playlists_to_middle(monkeypatch, session):
|
|||||||
model_src = create_model_with_playlist_rows(session, create_rowcount, name="source")
|
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_dst = create_model_with_playlist_rows(session, create_rowcount, name="destination")
|
||||||
|
|
||||||
model_src.move_rows_between_playlists(from_rows, to_row, model_dst)
|
model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id)
|
||||||
model_dst.refresh_data(session)
|
model_dst.refresh_data(session)
|
||||||
|
|
||||||
# Check the rows of the destination model
|
# Check the rows of the destination model
|
||||||
@ -347,7 +360,7 @@ def test_move_multiple_rows_between_playlists_to_end(monkeypatch, session):
|
|||||||
model_src = create_model_with_playlist_rows(session, create_rowcount, name="source")
|
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_dst = create_model_with_playlist_rows(session, create_rowcount, name="destination")
|
||||||
|
|
||||||
model_src.move_rows_between_playlists(from_rows, to_row, model_dst)
|
model_src.move_rows_between_playlists(from_rows, to_row, model_dst.playlist_id)
|
||||||
model_dst.refresh_data(session)
|
model_dst.refresh_data(session)
|
||||||
|
|
||||||
# Check the rows of the destination model
|
# Check the rows of the destination model
|
||||||
Loading…
Reference in New Issue
Block a user