Compare commits
No commits in common. "0391eed88eaa7bc920ba96a905d8f8dc7f111091" and "642e8523a2ba9ac38d37e4ad2f2d1a8bef1c01c3" have entirely different histories.
0391eed88e
...
642e8523a2
2
.envrc
2
.envrc
@ -13,8 +13,6 @@ branch=$(git branch --show-current)
|
|||||||
if [ $(pwd) == /home/kae/mm ]; then
|
if [ $(pwd) == /home/kae/mm ]; then
|
||||||
export MM_ENV="PRODUCTION"
|
export MM_ENV="PRODUCTION"
|
||||||
export DATABASE_URL="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod"
|
export DATABASE_URL="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod"
|
||||||
# on_git_branch is a direnv directive
|
|
||||||
# See https://github.com/direnv/direnv/blob/master/man/direnv-stdlib.1.md
|
|
||||||
elif on_git_branch master; then
|
elif on_git_branch master; then
|
||||||
export MM_ENV="PRODUCTION"
|
export MM_ENV="PRODUCTION"
|
||||||
export DATABASE_URL="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod"
|
export DATABASE_URL="mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod"
|
||||||
|
|||||||
@ -107,11 +107,7 @@ class AudacityController:
|
|||||||
f"and pipes exist at {self.pipe_to} and {self.pipe_from}."
|
f"and pipes exist at {self.pipe_to} and {self.pipe_from}."
|
||||||
)
|
)
|
||||||
|
|
||||||
def _test_connectivity(self) -> None:
|
# Send test command to Audacity
|
||||||
"""
|
|
||||||
Send test command to Audacity
|
|
||||||
"""
|
|
||||||
|
|
||||||
response = self._send_command(Config.AUDACITY_TEST_COMMAND)
|
response = self._send_command(Config.AUDACITY_TEST_COMMAND)
|
||||||
if response != Config.AUDACITY_TEST_RESPONSE:
|
if response != Config.AUDACITY_TEST_RESPONSE:
|
||||||
raise ApplicationError(
|
raise ApplicationError(
|
||||||
|
|||||||
@ -95,8 +95,6 @@ class Config(object):
|
|||||||
ROOT = os.environ.get("ROOT") or "/home/kae/music"
|
ROOT = os.environ.get("ROOT") or "/home/kae/music"
|
||||||
ROWS_FROM_ZERO = True
|
ROWS_FROM_ZERO = True
|
||||||
SCROLL_TOP_MARGIN = 3
|
SCROLL_TOP_MARGIN = 3
|
||||||
SECTION_ENDINGS = ("-", "+-", "-+")
|
|
||||||
SECTION_STARTS = ("+", "+-", "-+")
|
|
||||||
SONGFACTS_ON_NEXT = False
|
SONGFACTS_ON_NEXT = False
|
||||||
START_GAP_WARNING_THRESHOLD = 300
|
START_GAP_WARNING_THRESHOLD = 300
|
||||||
TEXT_NO_TRACK_NO_NOTE = "[Section header]"
|
TEXT_NO_TRACK_NO_NOTE = "[Section header]"
|
||||||
|
|||||||
@ -30,11 +30,9 @@ class NoteColoursTable(Model):
|
|||||||
substring: Mapped[str] = mapped_column(String(256), index=False)
|
substring: Mapped[str] = mapped_column(String(256), index=False)
|
||||||
colour: Mapped[str] = mapped_column(String(21), index=False)
|
colour: Mapped[str] = mapped_column(String(21), index=False)
|
||||||
enabled: Mapped[bool] = mapped_column(default=True, index=True)
|
enabled: Mapped[bool] = mapped_column(default=True, index=True)
|
||||||
foreground: Mapped[Optional[str]] = mapped_column(String(21), index=False)
|
|
||||||
is_regex: Mapped[bool] = mapped_column(default=False, index=False)
|
is_regex: Mapped[bool] = mapped_column(default=False, index=False)
|
||||||
is_casesensitive: Mapped[bool] = mapped_column(default=False, index=False)
|
is_casesensitive: Mapped[bool] = mapped_column(default=False, index=False)
|
||||||
order: Mapped[Optional[int]] = mapped_column(index=True)
|
order: Mapped[Optional[int]] = mapped_column(index=True)
|
||||||
strip_substring: Mapped[bool] = mapped_column(default=True, index=False)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -333,32 +333,6 @@ def normalise_track(path: str) -> None:
|
|||||||
os.remove(temp_path)
|
os.remove(temp_path)
|
||||||
|
|
||||||
|
|
||||||
def remove_substring_case_insensitive(parent_string: str, substring: str) -> str:
|
|
||||||
"""
|
|
||||||
Remove all instances of substring from parent string, case insensitively
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Convert both strings to lowercase for case-insensitive comparison
|
|
||||||
lower_parent = parent_string.lower()
|
|
||||||
lower_substring = substring.lower()
|
|
||||||
|
|
||||||
# Initialize the result string
|
|
||||||
result = parent_string
|
|
||||||
|
|
||||||
# Continue removing the substring until it's no longer found
|
|
||||||
while lower_substring in lower_parent:
|
|
||||||
# Find the index of the substring
|
|
||||||
index = lower_parent.find(lower_substring)
|
|
||||||
|
|
||||||
# Remove the substring
|
|
||||||
result = result[:index] + result[index + len(substring):]
|
|
||||||
|
|
||||||
# Update the lowercase versions
|
|
||||||
lower_parent = result.lower()
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def send_mail(to_addr: str, from_addr: str, subj: str, body: str) -> None:
|
def send_mail(to_addr: str, from_addr: str, subj: str, body: str) -> None:
|
||||||
# From https://docs.python.org/3/library/email.examples.html
|
# From https://docs.python.org/3/library/email.examples.html
|
||||||
|
|
||||||
|
|||||||
@ -22,9 +22,9 @@ from sqlalchemy.orm import joinedload
|
|||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
# App imports
|
# App imports
|
||||||
from config import Config
|
|
||||||
from dbmanager import DatabaseManager
|
from dbmanager import DatabaseManager
|
||||||
import dbtables
|
import dbtables
|
||||||
|
from config import Config
|
||||||
from log import log
|
from log import log
|
||||||
|
|
||||||
|
|
||||||
@ -70,22 +70,17 @@ class NoteColours(dbtables.NoteColoursTable):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_colour(session: Session, text: str, foreground: bool = False) -> Optional[str]:
|
def get_colour(session: Session, text: str) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Parse text and return background (foreground if foreground==True) colour
|
Parse text and return colour string if matched, else empty string
|
||||||
string if matched, else None
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not text:
|
if not text:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
match = False
|
|
||||||
for rec in session.scalars(
|
for rec in session.scalars(
|
||||||
select(NoteColours)
|
select(NoteColours)
|
||||||
.where(
|
.filter(NoteColours.enabled.is_(True))
|
||||||
NoteColours.enabled.is_(True),
|
|
||||||
)
|
|
||||||
.order_by(NoteColours.order)
|
.order_by(NoteColours.order)
|
||||||
).all():
|
).all():
|
||||||
if rec.is_regex:
|
if rec.is_regex:
|
||||||
@ -94,20 +89,15 @@ class NoteColours(dbtables.NoteColoursTable):
|
|||||||
flags |= re.IGNORECASE
|
flags |= re.IGNORECASE
|
||||||
p = re.compile(rec.substring, flags)
|
p = re.compile(rec.substring, flags)
|
||||||
if p.match(text):
|
if p.match(text):
|
||||||
match = True
|
return rec.colour
|
||||||
else:
|
else:
|
||||||
if rec.is_casesensitive:
|
if rec.is_casesensitive:
|
||||||
if rec.substring in text:
|
if rec.substring in text:
|
||||||
match = True
|
return rec.colour
|
||||||
else:
|
else:
|
||||||
if rec.substring.lower() in text.lower():
|
if rec.substring.lower() in text.lower():
|
||||||
match = True
|
|
||||||
|
|
||||||
if match:
|
|
||||||
if foreground:
|
|
||||||
return rec.foreground
|
|
||||||
else:
|
|
||||||
return rec.colour
|
return rec.colour
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,6 @@ from helpers import (
|
|||||||
get_embedded_time,
|
get_embedded_time,
|
||||||
get_relative_date,
|
get_relative_date,
|
||||||
ms_to_mmss,
|
ms_to_mmss,
|
||||||
remove_substring_case_insensitive,
|
|
||||||
set_track_metadata,
|
set_track_metadata,
|
||||||
)
|
)
|
||||||
from log import log
|
from log import log
|
||||||
@ -148,9 +147,9 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
if self.is_header_row(row):
|
if self.is_header_row(row):
|
||||||
# Check for specific header colouring
|
# Check for specific header colouring
|
||||||
with db.Session() as session:
|
with db.Session() as session:
|
||||||
note_background = NoteColours.get_colour(session, rat.note)
|
note_colour = NoteColours.get_colour(session, rat.note)
|
||||||
if note_background:
|
if note_colour:
|
||||||
return QBrush(QColor(note_background))
|
return QBrush(QColor(note_colour))
|
||||||
else:
|
else:
|
||||||
return QBrush(QColor(Config.COLOUR_NOTES_PLAYLIST))
|
return QBrush(QColor(Config.COLOUR_NOTES_PLAYLIST))
|
||||||
# Unreadable track file
|
# Unreadable track file
|
||||||
@ -185,9 +184,9 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
if column == Col.NOTE.value:
|
if column == Col.NOTE.value:
|
||||||
if rat.note:
|
if rat.note:
|
||||||
with db.Session() as session:
|
with db.Session() as session:
|
||||||
note_background = NoteColours.get_colour(session, rat.note)
|
note_colour = NoteColours.get_colour(session, rat.note)
|
||||||
if note_background:
|
if note_colour:
|
||||||
return QBrush(QColor(note_background))
|
return QBrush(QColor(note_colour))
|
||||||
|
|
||||||
return QBrush()
|
return QBrush()
|
||||||
|
|
||||||
@ -304,7 +303,6 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
int(Qt.ItemDataRole.DisplayRole): self.display_role,
|
int(Qt.ItemDataRole.DisplayRole): self.display_role,
|
||||||
int(Qt.ItemDataRole.EditRole): self.edit_role,
|
int(Qt.ItemDataRole.EditRole): self.edit_role,
|
||||||
int(Qt.ItemDataRole.FontRole): self.font_role,
|
int(Qt.ItemDataRole.FontRole): self.font_role,
|
||||||
int(Qt.ItemDataRole.ForegroundRole): self.foreground_role,
|
|
||||||
int(Qt.ItemDataRole.ToolTipRole): self.tooltip_role,
|
int(Qt.ItemDataRole.ToolTipRole): self.tooltip_role,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +316,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
Qt.ItemDataRole.WhatsThisRole,
|
Qt.ItemDataRole.WhatsThisRole,
|
||||||
Qt.ItemDataRole.SizeHintRole,
|
Qt.ItemDataRole.SizeHintRole,
|
||||||
Qt.ItemDataRole.TextAlignmentRole,
|
Qt.ItemDataRole.TextAlignmentRole,
|
||||||
|
Qt.ItemDataRole.ForegroundRole,
|
||||||
Qt.ItemDataRole.CheckStateRole,
|
Qt.ItemDataRole.CheckStateRole,
|
||||||
Qt.ItemDataRole.InitialSortOrderRole,
|
Qt.ItemDataRole.InitialSortOrderRole,
|
||||||
]:
|
]:
|
||||||
@ -378,7 +377,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return QVariant(self.header_text(rat))
|
return QVariant(self.header_text(rat))
|
||||||
else:
|
else:
|
||||||
return QVariant("")
|
return QVariant()
|
||||||
|
|
||||||
if column == Col.START_TIME.value:
|
if column == Col.START_TIME.value:
|
||||||
start_time = rat.forecast_start_time
|
start_time = rat.forecast_start_time
|
||||||
@ -448,19 +447,6 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
|
|
||||||
return QVariant()
|
return QVariant()
|
||||||
|
|
||||||
def foreground_role(self, row: int, column: int, rat: RowAndTrack) -> QBrush:
|
|
||||||
"""Return header foreground colour or QBrush() if none"""
|
|
||||||
|
|
||||||
if self.is_header_row(row):
|
|
||||||
with db.Session() as session:
|
|
||||||
note_foreground = NoteColours.get_colour(
|
|
||||||
session, rat.note, foreground=True
|
|
||||||
)
|
|
||||||
if note_foreground:
|
|
||||||
return QBrush(QColor(note_foreground))
|
|
||||||
|
|
||||||
return QBrush()
|
|
||||||
|
|
||||||
def flags(self, index: QModelIndex) -> Qt.ItemFlag:
|
def flags(self, index: QModelIndex) -> Qt.ItemFlag:
|
||||||
"""
|
"""
|
||||||
Standard model flags
|
Standard model flags
|
||||||
@ -632,7 +618,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
Process possible section timing directives embeded in header
|
Process possible section timing directives embeded in header
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if rat.note.endswith(Config.SECTION_STARTS):
|
if rat.note.endswith("+"):
|
||||||
return self.start_of_timed_section_header(rat)
|
return self.start_of_timed_section_header(rat)
|
||||||
|
|
||||||
elif rat.note.endswith("="):
|
elif rat.note.endswith("="):
|
||||||
@ -741,36 +727,6 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def load_data(
|
|
||||||
self, session: db.session, dummy_for_profiling: Optional[int] = None
|
|
||||||
) -> None:
|
|
||||||
"""
|
|
||||||
Same as refresh data, but only used when creating playslit.
|
|
||||||
Distinguishes profile time between initial load and other
|
|
||||||
refreshes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# We used to clear self.playlist_rows each time but that's
|
|
||||||
# expensive and slow on big playlists
|
|
||||||
|
|
||||||
# Note where each playlist_id is
|
|
||||||
plid_to_row: dict[int, int] = {}
|
|
||||||
for oldrow in self.playlist_rows:
|
|
||||||
plrdata = self.playlist_rows[oldrow]
|
|
||||||
plid_to_row[plrdata.playlistrow_id] = plrdata.row_number
|
|
||||||
|
|
||||||
# build a new playlist_rows
|
|
||||||
new_playlist_rows: dict[int, RowAndTrack] = {}
|
|
||||||
for p in PlaylistRows.get_playlist_rows(session, self.playlist_id):
|
|
||||||
if p.id not in plid_to_row:
|
|
||||||
new_playlist_rows[p.row_number] = RowAndTrack(p)
|
|
||||||
else:
|
|
||||||
new_playlist_rows[p.row_number] = self.playlist_rows[plid_to_row[p.id]]
|
|
||||||
new_playlist_rows[p.row_number].row_number = p.row_number
|
|
||||||
|
|
||||||
# Copy to self.playlist_rows
|
|
||||||
self.playlist_rows = new_playlist_rows
|
|
||||||
|
|
||||||
def mark_unplayed(self, row_numbers: list[int]) -> None:
|
def mark_unplayed(self, row_numbers: list[int]) -> None:
|
||||||
"""
|
"""
|
||||||
Mark row as unplayed
|
Mark row as unplayed
|
||||||
@ -1040,9 +996,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
self.invalidate_row(track_sequence.previous.row_number)
|
self.invalidate_row(track_sequence.previous.row_number)
|
||||||
|
|
||||||
@line_profiler.profile
|
@line_profiler.profile
|
||||||
def refresh_data(
|
def refresh_data(self, session: db.session, dummy_for_profiling=None) -> None:
|
||||||
self, session: db.session, dummy_for_profiling: Optional[int] = None
|
|
||||||
) -> None:
|
|
||||||
"""
|
"""
|
||||||
Populate self.playlist_rows with playlist data
|
Populate self.playlist_rows with playlist data
|
||||||
|
|
||||||
@ -1072,6 +1026,39 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
# Copy to self.playlist_rows
|
# Copy to self.playlist_rows
|
||||||
self.playlist_rows = new_playlist_rows
|
self.playlist_rows = new_playlist_rows
|
||||||
|
|
||||||
|
# Same as refresh data, but only used when creating playslit.
|
||||||
|
# Distinguishes profile time between initial load and other
|
||||||
|
# refreshes.
|
||||||
|
def load_data(
|
||||||
|
self, session: db.session, dummy_for_profiling: Optional[int] = None
|
||||||
|
) -> None:
|
||||||
|
"""Populate self.playlist_rows with playlist data"""
|
||||||
|
|
||||||
|
# Same as refresh data, but only used when creating playslit.
|
||||||
|
# Distinguishes profile time between initial load and other
|
||||||
|
# refreshes.
|
||||||
|
|
||||||
|
# We used to clear self.playlist_rows each time but that's
|
||||||
|
# expensive and slow on big playlists
|
||||||
|
|
||||||
|
# Note where each playlist_id is
|
||||||
|
plid_to_row: dict[int, int] = {}
|
||||||
|
for oldrow in self.playlist_rows:
|
||||||
|
plrdata = self.playlist_rows[oldrow]
|
||||||
|
plid_to_row[plrdata.playlistrow_id] = plrdata.row_number
|
||||||
|
|
||||||
|
# build a new playlist_rows
|
||||||
|
new_playlist_rows: dict[int, RowAndTrack] = {}
|
||||||
|
for p in PlaylistRows.get_playlist_rows(session, self.playlist_id):
|
||||||
|
if p.id not in plid_to_row:
|
||||||
|
new_playlist_rows[p.row_number] = RowAndTrack(p)
|
||||||
|
else:
|
||||||
|
new_playlist_rows[p.row_number] = self.playlist_rows[plid_to_row[p.id]]
|
||||||
|
new_playlist_rows[p.row_number].row_number = p.row_number
|
||||||
|
|
||||||
|
# Copy to self.playlist_rows
|
||||||
|
self.playlist_rows = new_playlist_rows
|
||||||
|
|
||||||
def refresh_row(self, session, row_number):
|
def refresh_row(self, session, row_number):
|
||||||
"""Populate dict for one row from database"""
|
"""Populate dict for one row from database"""
|
||||||
|
|
||||||
@ -1147,7 +1134,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
# Safety check
|
# Safety check
|
||||||
if not ask_yes_no(
|
if not ask_yes_no(
|
||||||
title="Remove comments",
|
title="Remove comments",
|
||||||
question=f"Remove comments from {len(row_numbers)} rows?",
|
question=f"Remove comments from {len(row_numbers)} rows?"
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -1199,49 +1186,6 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
log.debug(f"{self}: _reversed_contiguous_row_groups() returned: {result=}")
|
log.debug(f"{self}: _reversed_contiguous_row_groups() returned: {result=}")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def remove_section_timer_markers(self, header_text: str) -> str:
|
|
||||||
"""
|
|
||||||
Remove characters used to mark section timeings from
|
|
||||||
passed header text.
|
|
||||||
|
|
||||||
Remove text using to signal header colours if colour entry
|
|
||||||
is so marked.
|
|
||||||
|
|
||||||
Return header text witout markers
|
|
||||||
"""
|
|
||||||
|
|
||||||
while header_text.endswith(Config.SECTION_STARTS):
|
|
||||||
header_text = header_text[0:-1]
|
|
||||||
while header_text.endswith(Config.SECTION_ENDINGS):
|
|
||||||
header_text = header_text[0:-1]
|
|
||||||
|
|
||||||
# Parse passed header text and remove the first colour match string
|
|
||||||
with db.Session() as session:
|
|
||||||
for rec in NoteColours.get_all(session):
|
|
||||||
if not rec.strip_substring:
|
|
||||||
continue
|
|
||||||
if rec.is_regex:
|
|
||||||
flags = re.UNICODE
|
|
||||||
if not rec.is_casesensitive:
|
|
||||||
flags |= re.IGNORECASE
|
|
||||||
p = re.compile(rec.substring, flags)
|
|
||||||
if p.match(header_text):
|
|
||||||
header_text = re.sub(p, "", header_text)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if rec.is_casesensitive:
|
|
||||||
if rec.substring.lower() in header_text.lower():
|
|
||||||
header_text = remove_substring_case_insensitive(
|
|
||||||
header_text, rec.substring
|
|
||||||
)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if rec.substring in header_text:
|
|
||||||
header_text = header_text.replace(rec.substring, "")
|
|
||||||
break
|
|
||||||
|
|
||||||
return header_text
|
|
||||||
|
|
||||||
def rowCount(self, index: QModelIndex = QModelIndex()) -> int:
|
def rowCount(self, index: QModelIndex = QModelIndex()) -> int:
|
||||||
"""Standard function for view"""
|
"""Standard function for view"""
|
||||||
|
|
||||||
@ -1285,10 +1229,10 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
", section end time "
|
", section end time "
|
||||||
+ section_end_time.strftime(Config.TRACK_TIME_FORMAT)
|
+ section_end_time.strftime(Config.TRACK_TIME_FORMAT)
|
||||||
)
|
)
|
||||||
clean_header = self.remove_section_timer_markers(rat.note)
|
stripped_note = rat.note[:-1].strip()
|
||||||
if clean_header:
|
if stripped_note:
|
||||||
return (
|
return (
|
||||||
f"{clean_header} ["
|
f"{stripped_note} ["
|
||||||
f"{unplayed_count}/{count} track{'s' if count > 1 else ''} "
|
f"{unplayed_count}/{count} track{'s' if count > 1 else ''} "
|
||||||
f"({ms_to_mmss(duration)}) unplayed{end_time_str}]"
|
f"({ms_to_mmss(duration)}) unplayed{end_time_str}]"
|
||||||
)
|
)
|
||||||
@ -1498,14 +1442,12 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
unplayed_count: int = 0
|
unplayed_count: int = 0
|
||||||
duration: int = 0
|
duration: int = 0
|
||||||
|
|
||||||
clean_header = self.remove_section_timer_markers(rat.note)
|
|
||||||
|
|
||||||
for row_number in range(rat.row_number + 1, len(self.playlist_rows)):
|
for row_number in range(rat.row_number + 1, len(self.playlist_rows)):
|
||||||
row_rat = self.playlist_rows[row_number]
|
row_rat = self.playlist_rows[row_number]
|
||||||
if self.is_header_row(row_number):
|
if self.is_header_row(row_number):
|
||||||
if row_rat.note.endswith(Config.SECTION_ENDINGS):
|
if row_rat.note.endswith("-"):
|
||||||
return (
|
return (
|
||||||
f"{clean_header} "
|
f"{rat.note[:-1].strip()} "
|
||||||
f"[{count} tracks, {ms_to_mmss(duration)} unplayed]"
|
f"[{count} tracks, {ms_to_mmss(duration)} unplayed]"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -1516,7 +1458,7 @@ class PlaylistModel(QAbstractTableModel):
|
|||||||
unplayed_count += 1
|
unplayed_count += 1
|
||||||
duration += row_rat.duration
|
duration += row_rat.duration
|
||||||
return (
|
return (
|
||||||
f"{clean_header} "
|
f"{rat.note[:-1].strip()} "
|
||||||
f"[{count} tracks, {ms_to_mmss(duration, none='none')} "
|
f"[{count} tracks, {ms_to_mmss(duration, none='none')} "
|
||||||
"unplayed (to end of playlist)]"
|
"unplayed (to end of playlist)]"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -214,24 +214,6 @@ class PlaylistDelegate(QStyledItemDelegate):
|
|||||||
doc.setDefaultFont(option.font)
|
doc.setDefaultFont(option.font)
|
||||||
doc.setDocumentMargin(0)
|
doc.setDocumentMargin(0)
|
||||||
doc.setHtml(option.text)
|
doc.setHtml(option.text)
|
||||||
|
|
||||||
# For debugging +++
|
|
||||||
# Calculate sizes
|
|
||||||
# document_size = doc.documentLayout().documentSize()
|
|
||||||
# ideal_width = doc.idealWidth()
|
|
||||||
# height = document_size.height()
|
|
||||||
# rect_width = option.rect.width()
|
|
||||||
# text = option.text
|
|
||||||
|
|
||||||
# # Debug output
|
|
||||||
# print(f"Index: {index.row()}, {index.column()}")
|
|
||||||
# print(f"Text: {text}")
|
|
||||||
# print(f"Option.rect width: {rect_width}")
|
|
||||||
# print(f"Document idealWidth: {ideal_width}")
|
|
||||||
# print(f"Document height: {height}")
|
|
||||||
# print(f"---")
|
|
||||||
# --- For debugging
|
|
||||||
|
|
||||||
return QSize(int(doc.idealWidth()), int(doc.size().height()))
|
return QSize(int(doc.idealWidth()), int(doc.size().height()))
|
||||||
|
|
||||||
def setEditorData(self, editor, index):
|
def setEditorData(self, editor, index):
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
<%!
|
"""${message}
|
||||||
import re
|
|
||||||
|
|
||||||
%>"""${message}
|
|
||||||
|
|
||||||
Revision ID: ${up_revision}
|
Revision ID: ${up_revision}
|
||||||
Revises: ${down_revision | comma,n}
|
Revises: ${down_revision | comma,n}
|
||||||
@ -19,27 +16,9 @@ branch_labels = ${repr(branch_labels)}
|
|||||||
depends_on = ${repr(depends_on)}
|
depends_on = ${repr(depends_on)}
|
||||||
|
|
||||||
|
|
||||||
def upgrade(engine_name: str) -> None:
|
def upgrade():
|
||||||
globals()["upgrade_%s" % engine_name]()
|
${upgrades if upgrades else "pass"}
|
||||||
|
|
||||||
|
|
||||||
def downgrade(engine_name: str) -> None:
|
def downgrade():
|
||||||
globals()["downgrade_%s" % engine_name]()
|
${downgrades if downgrades else "pass"}
|
||||||
|
|
||||||
<%
|
|
||||||
db_names = config.get_main_option("databases")
|
|
||||||
%>
|
|
||||||
|
|
||||||
## generate an "upgrade_<xyz>() / downgrade_<xyz>()" function
|
|
||||||
## for each database name in the ini file.
|
|
||||||
|
|
||||||
% for db_name in re.split(r',\s*', db_names):
|
|
||||||
|
|
||||||
def upgrade_${db_name}() -> None:
|
|
||||||
${context.get("%s_upgrades" % db_name, "pass")}
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade_${db_name}() -> None:
|
|
||||||
${context.get("%s_downgrades" % db_name, "pass")}
|
|
||||||
|
|
||||||
% endfor
|
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
"""Add sort_column, deleted and query to playlists table
|
||||||
|
|
||||||
|
Revision ID: 07dcbe6c4f0e
|
||||||
|
Revises: 4a7b4ab3354f
|
||||||
|
Create Date: 2022-12-25 10:26:38.200941
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '07dcbe6c4f0e'
|
||||||
|
down_revision = '4a7b4ab3354f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playlists', sa.Column('sort_column', sa.Integer(), nullable=True))
|
||||||
|
op.add_column('playlists', sa.Column('query', sa.String(length=256), nullable=True))
|
||||||
|
op.add_column('playlists', sa.Column('deleted', sa.Boolean(), nullable=False))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('playlists', 'deleted')
|
||||||
|
op.drop_column('playlists', 'query')
|
||||||
|
op.drop_column('playlists', 'sort_column')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
"""Add 'played' column to playlist_rows
|
||||||
|
|
||||||
|
Revision ID: 0c604bf490f8
|
||||||
|
Revises: 29c0d7ffc741
|
||||||
|
Create Date: 2022-08-12 14:12:38.419845
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "0c604bf490f8"
|
||||||
|
down_revision = "29c0d7ffc741"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column("playlist_rows", sa.Column("played", sa.Boolean(), nullable=False))
|
||||||
|
op.drop_index("ix_tracks_lastplayed", table_name="tracks")
|
||||||
|
op.drop_column("tracks", "lastplayed")
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column("tracks", sa.Column("lastplayed", mysql.DATETIME(), nullable=True))
|
||||||
|
op.create_index("ix_tracks_lastplayed", "tracks", ["lastplayed"], unique=False)
|
||||||
|
op.drop_column("playlist_rows", "played")
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
"""Add columns to track table
|
||||||
|
|
||||||
|
Revision ID: 1bc727e5e87f
|
||||||
|
Revises: 52d82712d218
|
||||||
|
Create Date: 2021-03-22 22:43:40.458197
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '1bc727e5e87f'
|
||||||
|
down_revision = '52d82712d218'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('tracks', sa.Column('duration', sa.Integer(), nullable=True))
|
||||||
|
op.add_column('tracks', sa.Column('fade_at', sa.Integer(), nullable=True))
|
||||||
|
op.add_column('tracks', sa.Column('silence_at', sa.Integer(), nullable=True))
|
||||||
|
op.add_column('tracks', sa.Column('start_gap', sa.Integer(), nullable=True))
|
||||||
|
op.drop_index('ix_tracks_length', table_name='tracks')
|
||||||
|
op.create_index(op.f('ix_tracks_duration'), 'tracks', ['duration'], unique=False)
|
||||||
|
op.drop_column('tracks', 'length')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('tracks', sa.Column('length', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
|
||||||
|
op.drop_index(op.f('ix_tracks_duration'), table_name='tracks')
|
||||||
|
op.create_index('ix_tracks_length', 'tracks', ['length'], unique=False)
|
||||||
|
op.drop_column('tracks', 'start_gap')
|
||||||
|
op.drop_column('tracks', 'silence_at')
|
||||||
|
op.drop_column('tracks', 'fade_at')
|
||||||
|
op.drop_column('tracks', 'duration')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
"""Add constraint to playlist_tracks
|
||||||
|
|
||||||
|
Revision ID: 1c4048efee96
|
||||||
|
Revises: 52cbded98e7c
|
||||||
|
Create Date: 2022-03-29 19:26:27.378185
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '1c4048efee96'
|
||||||
|
down_revision = '52cbded98e7c'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_unique_constraint('uniquerow', 'playlist_tracks', ['row', 'playlist_id'])
|
||||||
|
op.alter_column('playlists', 'loaded',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('playlists', 'loaded',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=True)
|
||||||
|
op.drop_constraint('uniquerow', 'playlist_tracks', type_='unique')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
"""Fixup playdates relationship
|
||||||
|
|
||||||
|
Revision ID: 269a002f989d
|
||||||
|
Revises: 9bf80ba3635f
|
||||||
|
Create Date: 2021-03-28 14:36:59.103846
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '269a002f989d'
|
||||||
|
down_revision = '9bf80ba3635f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playdates', sa.Column('track_id', sa.Integer(), nullable=True))
|
||||||
|
op.create_foreign_key(None, 'playdates', 'tracks', ['track_id'], ['id'])
|
||||||
|
op.drop_constraint('tracks_ibfk_1', 'tracks', type_='foreignkey')
|
||||||
|
op.drop_column('tracks', 'playdates_id')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('tracks', sa.Column('playdates_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
|
||||||
|
op.create_foreign_key('tracks_ibfk_1', 'tracks', 'playdates', ['playdates_id'], ['id'])
|
||||||
|
op.drop_constraint(None, 'playdates', type_='foreignkey')
|
||||||
|
op.drop_column('playdates', 'track_id')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
"""Drop uniquerow index on playlist_rows
|
||||||
|
|
||||||
|
Revision ID: 29c0d7ffc741
|
||||||
|
Revises: 3b063011ed67
|
||||||
|
Create Date: 2022-08-06 22:21:46.881378
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '29c0d7ffc741'
|
||||||
|
down_revision = '3b063011ed67'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.drop_index('uniquerow', table_name='playlist_rows')
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.create_index('uniquerow', 'playlist_rows', ['row_number', 'playlist_id'], unique=True)
|
||||||
110
migrations/versions/2caa3d37f211_add_tracks_intro_column.py
Normal file
110
migrations/versions/2caa3d37f211_add_tracks_intro_column.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
"""add Tracks.intro column
|
||||||
|
|
||||||
|
Revision ID: 2caa3d37f211
|
||||||
|
Revises: 5bb2c572e1e5
|
||||||
|
Create Date: 2024-05-07 20:06:00.845979
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '2caa3d37f211'
|
||||||
|
down_revision = '5bb2c572e1e5'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(engine_name: str) -> None:
|
||||||
|
globals()["upgrade_%s" % engine_name]()
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade(engine_name: str) -> None:
|
||||||
|
globals()["downgrade_%s" % engine_name]()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade_() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('carts', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('name',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=False)
|
||||||
|
|
||||||
|
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('substring',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('colour',
|
||||||
|
existing_type=mysql.VARCHAR(length=21),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('enabled',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('is_regex',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('is_casesensitive',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=False)
|
||||||
|
|
||||||
|
with op.batch_alter_table('playdates', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('lastplayed',
|
||||||
|
existing_type=mysql.DATETIME(),
|
||||||
|
nullable=False)
|
||||||
|
batch_op.alter_column('track_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
|
||||||
|
with op.batch_alter_table('playlists', schema=None) as batch_op:
|
||||||
|
batch_op.drop_index('tab')
|
||||||
|
|
||||||
|
with op.batch_alter_table('tracks', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('intro', sa.Integer(), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade_() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('tracks', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('intro')
|
||||||
|
|
||||||
|
with op.batch_alter_table('playlists', schema=None) as batch_op:
|
||||||
|
batch_op.create_index('tab', ['tab'], unique=True)
|
||||||
|
|
||||||
|
with op.batch_alter_table('playdates', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('track_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
batch_op.alter_column('lastplayed',
|
||||||
|
existing_type=mysql.DATETIME(),
|
||||||
|
nullable=True)
|
||||||
|
|
||||||
|
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('is_casesensitive',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=True)
|
||||||
|
batch_op.alter_column('is_regex',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=True)
|
||||||
|
batch_op.alter_column('enabled',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=True)
|
||||||
|
batch_op.alter_column('colour',
|
||||||
|
existing_type=mysql.VARCHAR(length=21),
|
||||||
|
nullable=True)
|
||||||
|
batch_op.alter_column('substring',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=True)
|
||||||
|
|
||||||
|
with op.batch_alter_table('carts', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('name',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=True)
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
"""Add playlist dates and loaded
|
||||||
|
|
||||||
|
Revision ID: 2cc37d3cf07f
|
||||||
|
Revises: e3b04db5506f
|
||||||
|
Create Date: 2021-04-27 21:55:50.639406
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "2cc37d3cf07f"
|
||||||
|
down_revision = "e3b04db5506f"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column("playlists", sa.Column("last_used", sa.DateTime(), nullable=True))
|
||||||
|
op.add_column("playlists", sa.Column("loaded", sa.Boolean(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column("playlists", "loaded")
|
||||||
|
op.drop_column("playlists", "last_used")
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
"""Migrate SQLA 2 and remove redundant columns
|
||||||
|
|
||||||
|
Revision ID: 3a53a9fb26ab
|
||||||
|
Revises: 07dcbe6c4f0e
|
||||||
|
Create Date: 2023-10-15 09:39:16.449419
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '3a53a9fb26ab'
|
||||||
|
down_revision = '07dcbe6c4f0e'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('playlists', 'query')
|
||||||
|
op.drop_column('playlists', 'sort_column')
|
||||||
|
op.alter_column('tracks', 'title',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('tracks', 'artist',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('tracks', 'duration',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('tracks', 'start_gap',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('tracks', 'fade_at',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('tracks', 'silence_at',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('tracks', 'mtime',
|
||||||
|
existing_type=mysql.FLOAT(),
|
||||||
|
nullable=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('tracks', 'mtime',
|
||||||
|
existing_type=mysql.FLOAT(),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('tracks', 'silence_at',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('tracks', 'fade_at',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('tracks', 'start_gap',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('tracks', 'duration',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('tracks', 'artist',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('tracks', 'title',
|
||||||
|
existing_type=mysql.VARCHAR(length=256),
|
||||||
|
nullable=True)
|
||||||
|
op.add_column('playlists', sa.Column('sort_column', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
|
||||||
|
op.add_column('playlists', sa.Column('query', mysql.VARCHAR(length=256), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
"""schema changes for row notes
|
||||||
|
|
||||||
|
Revision ID: 3b063011ed67
|
||||||
|
Revises: 51f61433256f
|
||||||
|
Create Date: 2022-07-06 19:48:23.960471
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '3b063011ed67'
|
||||||
|
down_revision = '51f61433256f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('notes')
|
||||||
|
op.add_column('playlist_rows', sa.Column('note', sa.String(length=2048), nullable=True))
|
||||||
|
op.alter_column('playlist_rows', 'track_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.drop_index('uniquerow', table_name='playlist_rows')
|
||||||
|
op.drop_column('playlist_rows', 'text')
|
||||||
|
op.alter_column('playlist_rows', 'row', new_column_name='row_number',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.create_index('uniquerow', 'playlist_rows', ['row_number', 'playlist_id'], unique=True)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('playlist_rows', 'row_number', new_column_name='row',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.add_column('playlist_rows', sa.Column('text', mysql.VARCHAR(length=2048), nullable=True))
|
||||||
|
op.drop_index('uniquerow', table_name='playlist_rows')
|
||||||
|
op.create_index('uniquerow', 'playlist_rows', ['row', 'playlist_id'], unique=False)
|
||||||
|
op.drop_column('playlist_rows', 'note')
|
||||||
|
op.create_table('notes',
|
||||||
|
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('playlist_id', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True),
|
||||||
|
sa.Column('row', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False),
|
||||||
|
sa.Column('note', mysql.VARCHAR(length=256), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['playlist_id'], ['playlists.id'], name='notes_ibfk_1'),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_default_charset='utf8mb4',
|
||||||
|
mysql_engine='InnoDB'
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
"""Rename playlist_tracks to playlist_rows
|
||||||
|
|
||||||
|
Revision ID: 3f55ac7d80ad
|
||||||
|
Revises: 1c4048efee96
|
||||||
|
Create Date: 2022-07-04 20:51:59.874004
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '3f55ac7d80ad'
|
||||||
|
down_revision = '1c4048efee96'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# Rename so as not to lose content
|
||||||
|
op.rename_table('playlist_tracks', 'playlist_rows')
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# Rename so as not to lose content
|
||||||
|
op.rename_table('playlist_rows', 'playlist_tracks')
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
"""Record tab number for open playlists
|
||||||
|
|
||||||
|
Revision ID: 4a7b4ab3354f
|
||||||
|
Revises: 6730f03317df
|
||||||
|
Create Date: 2022-12-20 15:38:28.318280
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '4a7b4ab3354f'
|
||||||
|
down_revision = '6730f03317df'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playlists', sa.Column('tab', sa.Integer(), nullable=True))
|
||||||
|
op.create_unique_constraint(None, 'playlists', ['tab'])
|
||||||
|
op.drop_column('playlists', 'loaded')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playlists', sa.Column('loaded', mysql.TINYINT(display_width=1), autoincrement=False, nullable=False))
|
||||||
|
op.drop_constraint(None, 'playlists', type_='unique')
|
||||||
|
op.drop_column('playlists', 'tab')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
"""Increase settings.name len and add playlist_rows.notes
|
||||||
|
|
||||||
|
Revision ID: 51f61433256f
|
||||||
|
Revises: 3f55ac7d80ad
|
||||||
|
Create Date: 2022-07-04 21:21:39.830406
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '51f61433256f'
|
||||||
|
down_revision = '3f55ac7d80ad'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playlist_rows', sa.Column('text', sa.String(length=2048), nullable=True))
|
||||||
|
op.alter_column('playlists', 'loaded',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('playlists', 'loaded',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=True)
|
||||||
|
op.drop_column('playlist_rows', 'text')
|
||||||
|
# ### end Alembic commands ###
|
||||||
30
migrations/versions/52cbded98e7c_update_notecolours_table.py
Normal file
30
migrations/versions/52cbded98e7c_update_notecolours_table.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
"""Update notecolours table
|
||||||
|
|
||||||
|
Revision ID: 52cbded98e7c
|
||||||
|
Revises: c55992d1fe5f
|
||||||
|
Create Date: 2022-02-06 12:34:30.099417
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '52cbded98e7c'
|
||||||
|
down_revision = 'c55992d1fe5f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('notecolours', sa.Column('colour', sa.String(length=21), nullable=True))
|
||||||
|
op.drop_column('notecolours', 'hexcolour')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('notecolours', sa.Column('hexcolour', mysql.VARCHAR(length=6), nullable=True))
|
||||||
|
op.drop_column('notecolours', 'colour')
|
||||||
|
# ### end Alembic commands ###
|
||||||
24
migrations/versions/52d82712d218_initial.py
Normal file
24
migrations/versions/52d82712d218_initial.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"""Initial
|
||||||
|
|
||||||
|
Revision ID: 52d82712d218
|
||||||
|
Revises:
|
||||||
|
Create Date: 2021-03-22 22:16:03.272827
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '52d82712d218'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
pass
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
"""Add 'open' field to Playlists
|
||||||
|
|
||||||
|
Revision ID: 5bb2c572e1e5
|
||||||
|
Revises: 3a53a9fb26ab
|
||||||
|
Create Date: 2023-11-18 14:19:02.643914
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '5bb2c572e1e5'
|
||||||
|
down_revision = '3a53a9fb26ab'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('carts', 'duration',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('carts', 'path',
|
||||||
|
existing_type=mysql.VARCHAR(length=2048),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('carts', 'enabled',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('playlist_rows', 'note',
|
||||||
|
existing_type=mysql.VARCHAR(length=2048),
|
||||||
|
nullable=False)
|
||||||
|
op.add_column('playlists', sa.Column('open', sa.Boolean(), nullable=False))
|
||||||
|
op.alter_column('settings', 'name',
|
||||||
|
existing_type=mysql.VARCHAR(length=32),
|
||||||
|
type_=sa.String(length=64),
|
||||||
|
existing_nullable=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.alter_column('settings', 'name',
|
||||||
|
existing_type=sa.String(length=64),
|
||||||
|
type_=mysql.VARCHAR(length=32),
|
||||||
|
existing_nullable=False)
|
||||||
|
op.drop_column('playlists', 'open')
|
||||||
|
op.alter_column('playlist_rows', 'note',
|
||||||
|
existing_type=mysql.VARCHAR(length=2048),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('carts', 'enabled',
|
||||||
|
existing_type=mysql.TINYINT(display_width=1),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('carts', 'path',
|
||||||
|
existing_type=mysql.VARCHAR(length=2048),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('carts', 'duration',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
41
migrations/versions/6730f03317df_add_carts.py
Normal file
41
migrations/versions/6730f03317df_add_carts.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
"""Add carts
|
||||||
|
|
||||||
|
Revision ID: 6730f03317df
|
||||||
|
Revises: b4f524e2140c
|
||||||
|
Create Date: 2022-09-13 19:41:33.181752
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '6730f03317df'
|
||||||
|
down_revision = 'b4f524e2140c'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('carts',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('cart_number', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=256), nullable=True),
|
||||||
|
sa.Column('duration', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('path', sa.String(length=2048), nullable=True),
|
||||||
|
sa.Column('enabled', sa.Boolean(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
sa.UniqueConstraint('cart_number')
|
||||||
|
)
|
||||||
|
op.create_index(op.f('ix_carts_duration'), 'carts', ['duration'], unique=False)
|
||||||
|
op.create_index(op.f('ix_carts_name'), 'carts', ['name'], unique=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_index(op.f('ix_carts_name'), table_name='carts')
|
||||||
|
op.drop_index(op.f('ix_carts_duration'), table_name='carts')
|
||||||
|
op.drop_table('carts')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -1,75 +0,0 @@
|
|||||||
"""Initial migration
|
|
||||||
|
|
||||||
Revision ID: 708a21f5c271
|
|
||||||
Revises:
|
|
||||||
Create Date: 2024-12-14 11:16:09.067598
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
from sqlalchemy.dialects import mysql
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = '708a21f5c271'
|
|
||||||
down_revision = None
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(engine_name: str) -> None:
|
|
||||||
globals()["upgrade_%s" % engine_name]()
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade(engine_name: str) -> None:
|
|
||||||
globals()["downgrade_%s" % engine_name]()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade_() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
with op.batch_alter_table('carts', schema=None) as batch_op:
|
|
||||||
batch_op.drop_index('cart_number')
|
|
||||||
batch_op.drop_index('ix_carts_duration')
|
|
||||||
batch_op.drop_index('ix_carts_name')
|
|
||||||
|
|
||||||
op.drop_table('carts')
|
|
||||||
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
|
||||||
batch_op.add_column(sa.Column('foreground', sa.String(length=21), nullable=True))
|
|
||||||
|
|
||||||
with op.batch_alter_table('playlist_rows', schema=None) as batch_op:
|
|
||||||
batch_op.create_index(batch_op.f('ix_playlist_rows_playlist_id'), ['playlist_id'], unique=False)
|
|
||||||
batch_op.create_index(batch_op.f('ix_playlist_rows_row_number'), ['row_number'], unique=False)
|
|
||||||
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade_() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
with op.batch_alter_table('playlist_rows', schema=None) as batch_op:
|
|
||||||
batch_op.drop_index(batch_op.f('ix_playlist_rows_row_number'))
|
|
||||||
batch_op.drop_index(batch_op.f('ix_playlist_rows_playlist_id'))
|
|
||||||
|
|
||||||
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
|
||||||
batch_op.drop_column('foreground')
|
|
||||||
|
|
||||||
op.create_table('carts',
|
|
||||||
sa.Column('id', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False),
|
|
||||||
sa.Column('cart_number', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False),
|
|
||||||
sa.Column('name', mysql.VARCHAR(length=256), nullable=False),
|
|
||||||
sa.Column('duration', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True),
|
|
||||||
sa.Column('path', mysql.VARCHAR(length=2048), nullable=True),
|
|
||||||
sa.Column('enabled', mysql.TINYINT(display_width=1), autoincrement=False, nullable=True),
|
|
||||||
sa.PrimaryKeyConstraint('id'),
|
|
||||||
mysql_collate='utf8mb4_general_ci',
|
|
||||||
mysql_default_charset='utf8mb4',
|
|
||||||
mysql_engine='InnoDB'
|
|
||||||
)
|
|
||||||
with op.batch_alter_table('carts', schema=None) as batch_op:
|
|
||||||
batch_op.create_index('ix_carts_name', ['name'], unique=False)
|
|
||||||
batch_op.create_index('ix_carts_duration', ['duration'], unique=False)
|
|
||||||
batch_op.create_index('cart_number', ['cart_number'], unique=True)
|
|
||||||
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
"""Add id to playlist association table
|
||||||
|
|
||||||
|
Revision ID: 9bf80ba3635f
|
||||||
|
Revises: f071129cbd93
|
||||||
|
Create Date: 2021-03-28 12:16:14.631579
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '9bf80ba3635f'
|
||||||
|
down_revision = 'f071129cbd93'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
conn = op.get_bind()
|
||||||
|
conn.execute(
|
||||||
|
"ALTER TABLE playlistracks ADD id INT PRIMARY KEY AUTO_INCREMENT FIRST"
|
||||||
|
)
|
||||||
|
conn.execute("RENAME TABLE playlistracks TO playlisttracks")
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
conn = op.get_bind()
|
||||||
|
conn.execute("ALTER TABLE playlistracks DROP id")
|
||||||
|
conn.execute("RENAME TABLE playlisttracks TO playlistracks")
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -1,44 +0,0 @@
|
|||||||
"""Add strip_substring to NoteColoursTable
|
|
||||||
|
|
||||||
Revision ID: a524796269fa
|
|
||||||
Revises: 708a21f5c271
|
|
||||||
Create Date: 2024-12-14 12:42:45.214707
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = 'a524796269fa'
|
|
||||||
down_revision = '708a21f5c271'
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(engine_name: str) -> None:
|
|
||||||
globals()["upgrade_%s" % engine_name]()
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade(engine_name: str) -> None:
|
|
||||||
globals()["downgrade_%s" % engine_name]()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade_() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
|
||||||
batch_op.add_column(sa.Column('strip_substring', sa.Boolean(), nullable=False))
|
|
||||||
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade_() -> None:
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
|
||||||
batch_op.drop_column('strip_substring')
|
|
||||||
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
36
migrations/versions/a5aada49f2fc_add_notecolours_table.py
Normal file
36
migrations/versions/a5aada49f2fc_add_notecolours_table.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""Add NoteColours table
|
||||||
|
|
||||||
|
Revision ID: a5aada49f2fc
|
||||||
|
Revises: 2cc37d3cf07f
|
||||||
|
Create Date: 2022-02-05 17:34:54.880473
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'a5aada49f2fc'
|
||||||
|
down_revision = '2cc37d3cf07f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('notecolours',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('substring', sa.String(length=256), nullable=True),
|
||||||
|
sa.Column('hexcolour', sa.String(length=6), nullable=True),
|
||||||
|
sa.Column('enabled', sa.Boolean(), nullable=True),
|
||||||
|
sa.Column('is_regex', sa.Boolean(), nullable=True),
|
||||||
|
sa.Column('is_casesensitive', sa.Boolean(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('notecolours')
|
||||||
|
# ### end Alembic commands ###
|
||||||
37
migrations/versions/b0983648595e_add_settings_table.py
Normal file
37
migrations/versions/b0983648595e_add_settings_table.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
"""Add settings table
|
||||||
|
|
||||||
|
Revision ID: b0983648595e
|
||||||
|
Revises: 1bc727e5e87f
|
||||||
|
Create Date: 2021-03-26 13:33:41.994508
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "b0983648595e"
|
||||||
|
down_revision = "1bc727e5e87f"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table(
|
||||||
|
"settings",
|
||||||
|
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column("name", sa.String(length=32), nullable=False),
|
||||||
|
sa.Column("f_datetime", sa.DateTime(), nullable=True),
|
||||||
|
sa.Column("f_int", sa.Integer(), nullable=True),
|
||||||
|
sa.Column("f_string", sa.String(length=128), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
|
sa.UniqueConstraint("name"),
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table("settings")
|
||||||
|
# ### end Alembic commands ###
|
||||||
32
migrations/versions/b4f524e2140c_add_templates.py
Normal file
32
migrations/versions/b4f524e2140c_add_templates.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""Add templates
|
||||||
|
|
||||||
|
Revision ID: b4f524e2140c
|
||||||
|
Revises: ed3100326c38
|
||||||
|
Create Date: 2022-10-01 13:30:21.663287
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'b4f524e2140c'
|
||||||
|
down_revision = 'ed3100326c38'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_foreign_key(None, 'playlist_rows', 'tracks', ['track_id'], ['id'])
|
||||||
|
op.create_foreign_key(None, 'playlist_rows', 'playlists', ['playlist_id'], ['id'])
|
||||||
|
op.add_column('playlists', sa.Column('is_template', sa.Boolean(), nullable=False))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('playlists', 'is_template')
|
||||||
|
op.drop_constraint(None, 'playlist_rows', type_='foreignkey')
|
||||||
|
op.drop_constraint(None, 'playlist_rows', type_='foreignkey')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
"""Add order to colours table
|
||||||
|
|
||||||
|
Revision ID: c55992d1fe5f
|
||||||
|
Revises: a5aada49f2fc
|
||||||
|
Create Date: 2022-02-05 21:28:36.391312
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'c55992d1fe5f'
|
||||||
|
down_revision = 'a5aada49f2fc'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('notecolours', sa.Column('order', sa.Integer(), nullable=True))
|
||||||
|
op.create_index(op.f('ix_notecolours_enabled'), 'notecolours', ['enabled'], unique=False)
|
||||||
|
op.create_index(op.f('ix_notecolours_order'), 'notecolours', ['order'], unique=False)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_index(op.f('ix_notecolours_order'), table_name='notecolours')
|
||||||
|
op.drop_index(op.f('ix_notecolours_enabled'), table_name='notecolours')
|
||||||
|
op.drop_column('notecolours', 'order')
|
||||||
|
# ### end Alembic commands ###
|
||||||
51
migrations/versions/e3b04db5506f_add_structure_for_notes.py
Normal file
51
migrations/versions/e3b04db5506f_add_structure_for_notes.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
"""Add structure for notes
|
||||||
|
|
||||||
|
Revision ID: e3b04db5506f
|
||||||
|
Revises: 269a002f989d
|
||||||
|
Create Date: 2021-04-05 16:33:50.117747
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy.dialects import mysql
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'e3b04db5506f'
|
||||||
|
down_revision = '269a002f989d'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('notes',
|
||||||
|
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column('playlist_id', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('row', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('note', sa.String(length=256), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['playlist_id'], ['playlists.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
op.add_column('playlisttracks', sa.Column('row', sa.Integer(), nullable=False))
|
||||||
|
op.alter_column('playlisttracks', 'playlist_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.alter_column('playlisttracks', 'track_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=False)
|
||||||
|
op.drop_column('playlisttracks', 'sort')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playlisttracks', sa.Column('sort', mysql.INTEGER(display_width=11), autoincrement=False, nullable=False))
|
||||||
|
op.alter_column('playlisttracks', 'track_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.alter_column('playlisttracks', 'playlist_id',
|
||||||
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
|
nullable=True)
|
||||||
|
op.drop_column('playlisttracks', 'row')
|
||||||
|
op.drop_table('notes')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
"""Add column for bitrate in Tracks
|
||||||
|
|
||||||
|
Revision ID: ed3100326c38
|
||||||
|
Revises: fe2e127b3332
|
||||||
|
Create Date: 2022-08-22 16:16:42.181848
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'ed3100326c38'
|
||||||
|
down_revision = 'fe2e127b3332'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('tracks', sa.Column('bitrate', sa.Integer(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('tracks', 'bitrate')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
"""Add sort to playlist association table
|
||||||
|
|
||||||
|
Revision ID: f071129cbd93
|
||||||
|
Revises: f07b96a5e60f
|
||||||
|
Create Date: 2021-03-28 11:19:31.944110
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'f071129cbd93'
|
||||||
|
down_revision = 'f07b96a5e60f'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('playlistracks', sa.Column('sort', sa.Integer(), nullable=False))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('playlistracks', 'sort')
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
"""Add playlist and playtimes
|
||||||
|
|
||||||
|
Revision ID: f07b96a5e60f
|
||||||
|
Revises: b0983648595e
|
||||||
|
Create Date: 2021-03-27 19:53:09.524989
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "f07b96a5e60f"
|
||||||
|
down_revision = "b0983648595e"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table(
|
||||||
|
"playdates",
|
||||||
|
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column("lastplayed", sa.DateTime(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
|
)
|
||||||
|
op.create_index(
|
||||||
|
op.f("ix_playdates_lastplayed"), "playdates", ["lastplayed"], unique=False
|
||||||
|
)
|
||||||
|
op.create_table(
|
||||||
|
"playlists",
|
||||||
|
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column("name", sa.String(length=32), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
|
sa.UniqueConstraint("name"),
|
||||||
|
)
|
||||||
|
op.create_table(
|
||||||
|
"playlistracks",
|
||||||
|
sa.Column("playlist_id", sa.Integer(), nullable=True),
|
||||||
|
sa.Column("track_id", sa.Integer(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["playlist_id"],
|
||||||
|
["playlists.id"],
|
||||||
|
),
|
||||||
|
sa.ForeignKeyConstraint(
|
||||||
|
["track_id"],
|
||||||
|
["tracks.id"],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
op.add_column("tracks", sa.Column("playdates_id", sa.Integer(), nullable=True))
|
||||||
|
op.create_foreign_key(None, "tracks", "playdates", ["playdates_id"], ["id"])
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, "tracks", type_="foreignkey")
|
||||||
|
op.drop_column("tracks", "playdates_id")
|
||||||
|
op.drop_table("playlistracks")
|
||||||
|
op.drop_table("playlists")
|
||||||
|
op.drop_index(op.f("ix_playdates_lastplayed"), table_name="playdates")
|
||||||
|
op.drop_table("playdates")
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
"""Don't allow duplicate track paths
|
||||||
|
|
||||||
|
Revision ID: fe2e127b3332
|
||||||
|
Revises: 0c604bf490f8
|
||||||
|
Create Date: 2022-08-21 19:46:35.768659
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'fe2e127b3332'
|
||||||
|
down_revision = '0c604bf490f8'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_unique_constraint(None, 'tracks', ['path'])
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, 'tracks', type_='unique')
|
||||||
|
# ### end Alembic commands ###
|
||||||
Loading…
Reference in New Issue
Block a user