Compare commits
No commits in common. "caed7fd079b0bdbc72ccd81f6eddf61301130a4f" and "64799ccc6159951b7ed9c1da89535f5ad288c04c" have entirely different histories.
caed7fd079
...
64799ccc61
@ -137,31 +137,31 @@
|
|||||||
# return min(trim_ms, len(audio_segment))
|
# return min(trim_ms, len(audio_segment))
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
def ms_to_mmss(ms: int, decimals: int = 0, negative: bool = False) -> str:
|
# def ms_to_mmss(ms: int, decimals: int = 0, negative: bool = False) -> str:
|
||||||
"""Convert milliseconds to mm:ss"""
|
# """Convert milliseconds to mm:ss"""
|
||||||
|
#
|
||||||
minutes: int
|
# minutes: int
|
||||||
remainder: int
|
# remainder: int
|
||||||
seconds: float
|
# seconds: float
|
||||||
|
#
|
||||||
if not ms:
|
# if not ms:
|
||||||
return "-"
|
# return "-"
|
||||||
sign = ""
|
# sign = ""
|
||||||
if ms < 0:
|
# if ms < 0:
|
||||||
if negative:
|
# if negative:
|
||||||
sign = "-"
|
# sign = "-"
|
||||||
else:
|
# else:
|
||||||
ms = 0
|
# ms = 0
|
||||||
|
#
|
||||||
minutes, remainder = divmod(ms, 60 * 1000)
|
# minutes, remainder = divmod(ms, 60 * 1000)
|
||||||
seconds = remainder / 1000
|
# seconds = remainder / 1000
|
||||||
|
#
|
||||||
# if seconds >= 59.5, it will be represented as 60, which looks odd.
|
# # if seconds >= 59.5, it will be represented as 60, which looks odd.
|
||||||
# So, fake it under those circumstances
|
# # So, fake it under those circumstances
|
||||||
if seconds >= 59.5:
|
# if seconds >= 59.5:
|
||||||
seconds = 59.0
|
# seconds = 59.0
|
||||||
|
#
|
||||||
return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}"
|
# return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# def open_in_audacity(path: str) -> Optional[bool]:
|
# def open_in_audacity(path: str) -> Optional[bool]:
|
||||||
|
|||||||
@ -275,12 +275,8 @@ class Playlists(Base):
|
|||||||
name: str = Column(String(32), nullable=False, unique=True)
|
name: str = Column(String(32), nullable=False, unique=True)
|
||||||
last_used = Column(DateTime, default=None, nullable=True)
|
last_used = Column(DateTime, default=None, nullable=True)
|
||||||
loaded: bool = Column(Boolean, default=True, nullable=False)
|
loaded: bool = Column(Boolean, default=True, nullable=False)
|
||||||
rows = relationship(
|
rows = relationship("PlaylistRows", back_populates="playlist",
|
||||||
"PlaylistRows",
|
cascade="all, delete-orphan")
|
||||||
back_populates="playlist",
|
|
||||||
cascade="all, delete-orphan",
|
|
||||||
order_by="PlaylistRows.row_number"
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"<Playlists(id={self.id}, name={self.name}>"
|
return f"<Playlists(id={self.id}, name={self.name}>"
|
||||||
@ -317,11 +313,14 @@ class Playlists(Base):
|
|||||||
# """Returns a list of all playlists ordered by last use"""
|
# """Returns a list of all playlists ordered by last use"""
|
||||||
#
|
#
|
||||||
# return (
|
# return (
|
||||||
# session.query(cls).order_by(
|
# session.query(cls).order_by(cls.last_used.desc())
|
||||||
# cls.loaded.desc(), cls.last_used.desc())
|
|
||||||
# ).all()
|
# ).all()
|
||||||
#
|
#
|
||||||
# @classmethod
|
# @classmethod
|
||||||
|
# def get_by_id(cls, session: Session, playlist_id: int) -> "Playlists":
|
||||||
|
# return (session.query(cls).filter(cls.id == playlist_id)).one()
|
||||||
|
#
|
||||||
|
# @classmethod
|
||||||
# def get_closed(cls, session: Session) -> List["Playlists"]:
|
# def get_closed(cls, session: Session) -> List["Playlists"]:
|
||||||
# """Returns a list of all closed playlists ordered by last use"""
|
# """Returns a list of all closed playlists ordered by last use"""
|
||||||
#
|
#
|
||||||
@ -530,7 +529,7 @@ class Tracks(Base):
|
|||||||
silence_at = Column(Integer, index=False)
|
silence_at = Column(Integer, index=False)
|
||||||
path = Column(String(2048), index=False, nullable=False)
|
path = Column(String(2048), index=False, nullable=False)
|
||||||
mtime = Column(Float, index=True)
|
mtime = Column(Float, index=True)
|
||||||
# lastplayed = Column(DateTime, index=True, default=None)
|
lastplayed = Column(DateTime, index=True, default=None)
|
||||||
playlistrows = relationship("PlaylistRows", back_populates="track")
|
playlistrows = relationship("PlaylistRows", back_populates="track")
|
||||||
playlists = association_proxy("playlistrows", "playlist")
|
playlists = association_proxy("playlistrows", "playlist")
|
||||||
playdates = relationship("Playdates", back_populates="track")
|
playdates = relationship("Playdates", back_populates="track")
|
||||||
|
|||||||
@ -153,16 +153,14 @@
|
|||||||
# with lock:
|
# with lock:
|
||||||
# return self.player.set_time(ms)
|
# return self.player.set_time(ms)
|
||||||
#
|
#
|
||||||
# def set_volume(self, volume, set_default=True):
|
# def set_volume(self, volume):
|
||||||
# """Set maximum volume used for player"""
|
# """Set maximum volume used for player"""
|
||||||
#
|
#
|
||||||
# with lock:
|
# with lock:
|
||||||
# if not self.player:
|
# if not self.player:
|
||||||
# return
|
# return
|
||||||
#
|
#
|
||||||
# if set_default:
|
# self.max_volume = volume
|
||||||
# self.max_volume = volume
|
|
||||||
#
|
|
||||||
# self.player.audio_set_volume(volume)
|
# self.player.audio_set_volume(volume)
|
||||||
#
|
#
|
||||||
# def stop(self):
|
# def stop(self):
|
||||||
|
|||||||
@ -321,9 +321,9 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
# """Drop music level by 3db if button checked"""
|
# """Drop music level by 3db if button checked"""
|
||||||
#
|
#
|
||||||
# if self.btnDrop3db.isChecked():
|
# if self.btnDrop3db.isChecked():
|
||||||
# self.music.set_volume(Config.VOLUME_VLC_DROP3db, set_default=False)
|
# self.music.set_volume(Config.VOLUME_VLC_DROP3db)
|
||||||
# else:
|
# else:
|
||||||
# self.music.set_volume(Config.VOLUME_VLC_DEFAULT, set_default=False)
|
# self.music.set_volume(Config.VOLUME_VLC_DEFAULT)
|
||||||
#
|
#
|
||||||
# def enable_play_next_controls(self) -> None:
|
# def enable_play_next_controls(self) -> None:
|
||||||
# """
|
# """
|
||||||
|
|||||||
206
app/playlists.py
206
app/playlists.py
@ -4,7 +4,7 @@ from collections import namedtuple
|
|||||||
# from typing import Dict, List, Optional, Set, Tuple, Union
|
# from typing import Dict, List, Optional, Set, Tuple, Union
|
||||||
#
|
#
|
||||||
# from PyQt5 import QtCore
|
# from PyQt5 import QtCore
|
||||||
from PyQt5.QtCore import Qt
|
# from PyQt5.QtCore import Qt
|
||||||
# from PyQt5.Qt import QFont
|
# from PyQt5.Qt import QFont
|
||||||
# from PyQt5.QtGui import QColor, QDropEvent
|
# from PyQt5.QtGui import QColor, QDropEvent
|
||||||
# from PyQt5 import QtWidgets
|
# from PyQt5 import QtWidgets
|
||||||
@ -21,7 +21,7 @@ from PyQt5.QtWidgets import (
|
|||||||
QTableWidgetItem,
|
QTableWidgetItem,
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
import helpers
|
# import helpers
|
||||||
# import os
|
# import os
|
||||||
# import re
|
# import re
|
||||||
# import subprocess
|
# import subprocess
|
||||||
@ -34,8 +34,8 @@ from config import Config
|
|||||||
from models import (
|
from models import (
|
||||||
# Notes,
|
# Notes,
|
||||||
# Playdates,
|
# Playdates,
|
||||||
Playlists,
|
# Playlists,
|
||||||
PlaylistRows,
|
# PlaylistTracks,
|
||||||
Settings,
|
Settings,
|
||||||
# Tracks,
|
# Tracks,
|
||||||
# NoteColours
|
# NoteColours
|
||||||
@ -55,18 +55,16 @@ from dbconfig import Session
|
|||||||
# Columns
|
# Columns
|
||||||
Column = namedtuple("Column", ['idx', 'heading'])
|
Column = namedtuple("Column", ['idx', 'heading'])
|
||||||
columns = {}
|
columns = {}
|
||||||
columns["userdata"] = Column(idx=0, heading=Config.COLUMN_NAME_AUTOPLAY)
|
columns["userdata"] = Column(idx=0, heading=Config.COLUMN_NAME_AUTOPLAY),
|
||||||
columns["start_gap"] = Column(
|
columns["mss"] = Column(idx=1, heading=Config.COLUMN_NAME_LEADING_SILENCE),
|
||||||
idx=1, heading=Config.COLUMN_NAME_LEADING_SILENCE)
|
columns["title"] = Column(idx=2, heading=Config.COLUMN_NAME_TITLE),
|
||||||
columns["title"] = Column(idx=2, heading=Config.COLUMN_NAME_TITLE)
|
columns["artist"] = Column(idx=3, heading=Config.COLUMN_NAME_ARTIST),
|
||||||
columns["artist"] = Column(idx=3, heading=Config.COLUMN_NAME_ARTIST)
|
columns["duration"] = Column(idx=4, heading=Config.COLUMN_NAME_LENGTH),
|
||||||
columns["duration"] = Column(idx=4, heading=Config.COLUMN_NAME_LENGTH)
|
columns["start_time"] = Column(idx=5, heading=Config.COLUMN_NAME_START_TIME),
|
||||||
columns["start_time"] = Column(idx=5, heading=Config.COLUMN_NAME_START_TIME)
|
columns["end_time"] = Column(idx=6, heading=Config.COLUMN_NAME_END_TIME),
|
||||||
columns["end_time"] = Column(idx=6, heading=Config.COLUMN_NAME_END_TIME)
|
columns["last_played"] = Column(idx=7, heading=Config.COLUMN_NAME_LAST_PLAYED),
|
||||||
columns["lastplayed"] = Column(idx=7, heading=Config.COLUMN_NAME_LAST_PLAYED)
|
columns["row_notes"] = Column(idx=8, heading=Config.COLUMN_NAME_NOTES),
|
||||||
columns["row_notes"] = Column(idx=8, heading=Config.COLUMN_NAME_NOTES)
|
#
|
||||||
|
|
||||||
|
|
||||||
# class NoSelectDelegate(QStyledItemDelegate):
|
# class NoSelectDelegate(QStyledItemDelegate):
|
||||||
# """https://stackoverflow.com/questions/72790705/dont-select-text-in-qtablewidget-cell-when-editing/72792962#72792962"""
|
# """https://stackoverflow.com/questions/72790705/dont-select-text-in-qtablewidget-cell-when-editing/72792962#72792962"""
|
||||||
#
|
#
|
||||||
@ -87,10 +85,10 @@ class PlaylistTab(QTableWidget):
|
|||||||
# cellEditingStarted = QtCore.pyqtSignal(int, int)
|
# cellEditingStarted = QtCore.pyqtSignal(int, int)
|
||||||
# cellEditingEnded = QtCore.pyqtSignal()
|
# cellEditingEnded = QtCore.pyqtSignal()
|
||||||
|
|
||||||
# Qt.UserRoles
|
# # Qt.UserRoles
|
||||||
ROW_METADATA = Qt.UserRole
|
# ROW_METADATA = Qt.UserRole
|
||||||
# CONTENT_OBJECT = Qt.UserRole + 1
|
# CONTENT_OBJECT = Qt.UserRole + 1
|
||||||
ROW_DURATION = Qt.UserRole + 2
|
# ROW_DURATION = Qt.UserRole + 2
|
||||||
|
|
||||||
def __init__(self, musicmuster: QMainWindow, session: Session,
|
def __init__(self, musicmuster: QMainWindow, session: Session,
|
||||||
playlist_id: int, *args, **kwargs):
|
playlist_id: int, *args, **kwargs):
|
||||||
@ -121,8 +119,8 @@ class PlaylistTab(QTableWidget):
|
|||||||
self._set_column_widths(session)
|
self._set_column_widths(session)
|
||||||
# Set column headings sorted by idx
|
# Set column headings sorted by idx
|
||||||
self.setHorizontalHeaderLabels(
|
self.setHorizontalHeaderLabels(
|
||||||
[a.heading for a in list(sorted(columns.values(),
|
[a[0].heading for a in list(sorted(columns.values(),
|
||||||
key=lambda item: item.idx))]
|
key=lambda item: item[0][0]))]
|
||||||
)
|
)
|
||||||
|
|
||||||
# self.setDragEnabled(True)
|
# self.setDragEnabled(True)
|
||||||
@ -155,8 +153,8 @@ class PlaylistTab(QTableWidget):
|
|||||||
# self.doubleClicked.connect(self._edit_cell)
|
# self.doubleClicked.connect(self._edit_cell)
|
||||||
self.horizontalHeader().sectionResized.connect(self._column_resize)
|
self.horizontalHeader().sectionResized.connect(self._column_resize)
|
||||||
#
|
#
|
||||||
# Now load our tracks and notes
|
# # Now load our tracks and notes
|
||||||
self.populate(session, self.playlist_id)
|
# self.populate(session, self.playlist_id)
|
||||||
|
|
||||||
def _column_resize(self, idx, old, new):
|
def _column_resize(self, idx, old, new):
|
||||||
"""
|
"""
|
||||||
@ -167,7 +165,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
|
|
||||||
with Session() as session:
|
with Session() as session:
|
||||||
for column_name, data in columns.items():
|
for column_name, data in columns.items():
|
||||||
idx = data.idx
|
idx = data[0].idx
|
||||||
width = self.columnWidth(idx)
|
width = self.columnWidth(idx)
|
||||||
attribute_name = f"playlist_{column_name}_col_width"
|
attribute_name = f"playlist_{column_name}_col_width"
|
||||||
record = Settings.get_int_settings(session, attribute_name)
|
record = Settings.get_int_settings(session, attribute_name)
|
||||||
@ -352,87 +350,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
# return self.item(row, self.COL_TITLE).text()
|
# return self.item(row, self.COL_TITLE).text()
|
||||||
# else:
|
# else:
|
||||||
# return None
|
# return None
|
||||||
|
|
||||||
def insert_row(self, session: Session, row_data: PlaylistRows,
|
|
||||||
repaint: bool = True) -> None:
|
|
||||||
"""
|
|
||||||
Insert a row into playlist tab.
|
|
||||||
|
|
||||||
If playlist has a row selected, add new row above. Otherwise,
|
|
||||||
add to end of playlist.
|
|
||||||
|
|
||||||
Note: we ignore the row number in the PlaylistRows record. That is
|
|
||||||
used only to order the query that generates the records.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if self.selectionModel().hasSelection():
|
|
||||||
row = self.currentRow()
|
|
||||||
else:
|
|
||||||
row = self.rowCount()
|
|
||||||
self.insertRow(row)
|
|
||||||
|
|
||||||
# Add row metadata to userdata column
|
|
||||||
item: QTableWidgetItem = QTableWidgetItem()
|
|
||||||
item.setData(self.ROW_METADATA, 0)
|
|
||||||
self.setItem(row, columns['userdata'].idx, item)
|
|
||||||
|
|
||||||
# Prepare notes, start and end items for later
|
|
||||||
notes_item = QTableWidgetItem(row_data.note)
|
|
||||||
start_item = QTableWidgetItem()
|
|
||||||
end_item = QTableWidgetItem()
|
|
||||||
|
|
||||||
if row_data.track_id:
|
|
||||||
# Add track details to items
|
|
||||||
start_gap = row_data.track.start_gap
|
|
||||||
start_gap_item = QTableWidgetItem(str(start_gap))
|
|
||||||
if start_gap and start_gap >= 500:
|
|
||||||
start_gap_item.setBackground(QColor(Config.COLOUR_LONG_START))
|
|
||||||
|
|
||||||
title_item = QTableWidgetItem(row_data.track.title)
|
|
||||||
|
|
||||||
artist_item = QTableWidgetItem(row_data.track.artist)
|
|
||||||
|
|
||||||
duration_item = QTableWidgetItem(
|
|
||||||
helpers.ms_to_mmss(row_data.track.duration))
|
|
||||||
self._set_row_duration(row, row_data.track.duration)
|
|
||||||
|
|
||||||
last_playtime = Playdates.last_played(session, row_data.track.id)
|
|
||||||
last_played_str = get_relative_date(last_playtime)
|
|
||||||
last_played_item = QTableWidgetItem(last_played_str)
|
|
||||||
self.setItem(row, columns['lastplayed'], last_played_item)
|
|
||||||
|
|
||||||
# Mark track if file is unreadable
|
|
||||||
if not self._file_is_readable(row_data.track.path):
|
|
||||||
self._set_unreadable_row(row)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# This is a note row so make empty items (row background
|
|
||||||
# won't be coloured without items present)
|
|
||||||
start_gap_item = QTableWidgetItem()
|
|
||||||
title_item = QTableWidgetItem()
|
|
||||||
artist_item = QTableWidgetItem()
|
|
||||||
duration_item = QTableWidgetItem()
|
|
||||||
last_played_item = QTableWidgetItem()
|
|
||||||
|
|
||||||
# Add items to table
|
|
||||||
self.setItem(row, columns['start_gap'].idx, start_gap_item)
|
|
||||||
self.setItem(row, columns['title'].idx, title_item)
|
|
||||||
self.setItem(row, columns['artist'].idx, artist_item)
|
|
||||||
self.setItem(row, columns['duration'].idx, duration_item)
|
|
||||||
self.setItem(row, columns['start_time'].idx, start_item)
|
|
||||||
self.setItem(row, columns['end_time'].idx, end_item)
|
|
||||||
self.setItem(row, columns['row_notes'].idx, notes_item)
|
|
||||||
|
|
||||||
if not row_data.track_id:
|
|
||||||
# Span note across table
|
|
||||||
self.setSpan(row, 0, len(columns), 1)
|
|
||||||
|
|
||||||
# Scroll to new row
|
|
||||||
self.scrollToItem(title_item, QAbstractItemView.PositionAtCenter)
|
|
||||||
|
|
||||||
if repaint:
|
|
||||||
self.save_playlist(session)
|
|
||||||
self.update_display(session, clear_selection=False)
|
|
||||||
#
|
#
|
||||||
# def insert_track(self, session: Session, track: Tracks,
|
# def insert_track(self, session: Session, track: Tracks,
|
||||||
# repaint: bool = True) -> None:
|
# repaint: bool = True) -> None:
|
||||||
@ -608,37 +525,50 @@ class PlaylistTab(QTableWidget):
|
|||||||
#
|
#
|
||||||
# self._clear_current_track_row()
|
# self._clear_current_track_row()
|
||||||
# self.current_track_start_time = None
|
# self.current_track_start_time = None
|
||||||
|
#
|
||||||
def populate(self, session: Session, playlist_id: int) -> None:
|
# def populate(self, session: Session, playlist_id: int) -> None:
|
||||||
"""
|
# """
|
||||||
Populate from the associated playlist ID
|
# Populate from the associated playlist ID
|
||||||
"""
|
#
|
||||||
|
# We don't mandate that an item will be on its specified row, only
|
||||||
# data: List[Union[Tuple[List[int], Tracks], Tuple[List[int], Notes]]] \
|
# that it will be above larger-numbered row items, and below
|
||||||
# = []
|
# lower-numbered ones.
|
||||||
# item: Union[Notes, Tracks]
|
# """
|
||||||
# note: Notes
|
#
|
||||||
# row: int
|
# data: List[Union[Tuple[List[int], Tracks], Tuple[List[int], Notes]]] \
|
||||||
# track: Tracks
|
# = []
|
||||||
|
# item: Union[Notes, Tracks]
|
||||||
playlist = session.get(Playlists, playlist_id)
|
# note: Notes
|
||||||
|
# row: int
|
||||||
# Clear playlist
|
# track: Tracks
|
||||||
self.setRowCount(0)
|
#
|
||||||
|
# playlist = Playlists.get_by_id(session, playlist_id)
|
||||||
# Add the rows
|
#
|
||||||
for row in playlist.rows:
|
# for row, track in playlist.tracks.items():
|
||||||
self.insert_row(session, row, repaint=False)
|
# data.append(([row], track))
|
||||||
|
# for note in playlist.notes:
|
||||||
# Scroll to top
|
# data.append(([note.row], note))
|
||||||
scroll_to: QTableWidgetItem = self.item(0, 0)
|
#
|
||||||
self.scrollToItem(scroll_to, QAbstractItemView.PositionAtTop)
|
# # Clear playlist
|
||||||
|
# self.setRowCount(0)
|
||||||
# We possibly don't need to save the playlist here, but row
|
#
|
||||||
# numbers may have changed during population, and it's cheap to do
|
# # Now add data in row order
|
||||||
# KAE self.save_playlist(session)
|
# for i in sorted(data, key=lambda x: x[0]):
|
||||||
self.update_display(session)
|
# item = i[1]
|
||||||
|
# if isinstance(item, Tracks):
|
||||||
|
# self.insert_track(session, item, repaint=False)
|
||||||
|
# elif isinstance(item, Notes):
|
||||||
|
# self._insert_note(session, item, repaint=False)
|
||||||
|
#
|
||||||
|
# # Scroll to top
|
||||||
|
# scroll_to: QTableWidgetItem = self.item(0, 0)
|
||||||
|
# self.scrollToItem(scroll_to, QAbstractItemView.PositionAtTop)
|
||||||
|
#
|
||||||
|
# # We possibly don't need to save the playlist here, but row
|
||||||
|
# # numbers may have changed during population, and it's cheap to do
|
||||||
|
# self.save_playlist(session)
|
||||||
|
# self.update_display(session)
|
||||||
|
#
|
||||||
# def save_playlist(self, session) -> None:
|
# def save_playlist(self, session) -> None:
|
||||||
# """
|
# """
|
||||||
# Save playlist to database.
|
# Save playlist to database.
|
||||||
@ -1684,7 +1614,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
"""Column widths from settings"""
|
"""Column widths from settings"""
|
||||||
|
|
||||||
for column_name, data in columns.items():
|
for column_name, data in columns.items():
|
||||||
idx = data.idx
|
idx = data[0].idx
|
||||||
attr_name = f"playlist_{column_name}_col_width"
|
attr_name = f"playlist_{column_name}_col_width"
|
||||||
record: Settings = Settings.get_int_settings(session, attr_name)
|
record: Settings = Settings.get_int_settings(session, attr_name)
|
||||||
if record and record.f_int is not None:
|
if record and record.f_int is not None:
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
from sqlalchemy.orm import (sessionmaker, scoped_session)
|
|
||||||
s = sessionmaker(bind=engine)
|
|
||||||
from dbconfig import engine
|
|
||||||
s = sessionmaker(bind=engine)
|
|
||||||
s
|
|
||||||
playlist in s
|
|
||||||
s = scoped_session(sessionmaker(bind=engine))
|
|
||||||
playlist_id = 3
|
|
||||||
playlist = Playlists.get_by_id(session, playlist_id)
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
"""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 ###
|
|
||||||
94
play.py
94
play.py
@ -1,94 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
|
||||||
from sqlalchemy import text
|
|
||||||
from sqlalchemy import Table, Column, Integer, String
|
|
||||||
from sqlalchemy import ForeignKey
|
|
||||||
from sqlalchemy import select
|
|
||||||
from sqlalchemy import insert
|
|
||||||
from sqlalchemy.orm import Session
|
|
||||||
from sqlalchemy.orm import declarative_base
|
|
||||||
from sqlalchemy.orm import relationship
|
|
||||||
|
|
||||||
|
|
||||||
Base = declarative_base()
|
|
||||||
|
|
||||||
engine = create_engine("sqlite+pysqlite:///:memory:", echo=True, future=True)
|
|
||||||
|
|
||||||
|
|
||||||
class User(Base):
|
|
||||||
__tablename__ = 'user_account'
|
|
||||||
id = Column(Integer, primary_key=True)
|
|
||||||
name = Column(String(30))
|
|
||||||
fullname = Column(String)
|
|
||||||
addresses = relationship("Address", back_populates="user")
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return (
|
|
||||||
f"User(id={self.id!r}, name={self.name!r}, "
|
|
||||||
f"fullname={self.fullname!r})"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Address(Base):
|
|
||||||
__tablename__ = 'address'
|
|
||||||
id = Column(Integer, primary_key=True)
|
|
||||||
email_address = Column(String, nullable=False)
|
|
||||||
user_id = Column(Integer, ForeignKey('user_account.id'))
|
|
||||||
user = relationship("User", back_populates="addresses")
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"Address(id={self.id!r}, email_address={self.email_address!r})"
|
|
||||||
|
|
||||||
|
|
||||||
Base.metadata.create_all(engine)
|
|
||||||
|
|
||||||
squidward = User(name="squidward", fullname="Squidward Tentacles")
|
|
||||||
krabs = User(name="ehkrabs", fullname="Eugene H. Krabs")
|
|
||||||
|
|
||||||
session = Session(engine)
|
|
||||||
|
|
||||||
session.add(squidward)
|
|
||||||
session.add(krabs)
|
|
||||||
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
u1 = User(name='pkrabs', fullname='Pearl Krabs')
|
|
||||||
a1 = Address(email_address="pearl.krabs@gmail.com")
|
|
||||||
u1.addresses.append(a1)
|
|
||||||
a2 = Address(email_address="pearl@aol.com", user=u1)
|
|
||||||
|
|
||||||
session.add(u1)
|
|
||||||
session.add(a1)
|
|
||||||
session.add(a2)
|
|
||||||
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
# with engine.connect() as conn:
|
|
||||||
# conn.execute(text("CREATE TABLE some_table (x int, y int)"))
|
|
||||||
# conn.execute(
|
|
||||||
# text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
|
|
||||||
# [{"x": 1, "y": 1}, {"x": 2, "y": 4}]
|
|
||||||
# )
|
|
||||||
# conn.commit()
|
|
||||||
#
|
|
||||||
# with engine.begin() as conn:
|
|
||||||
# conn.execute(
|
|
||||||
# text("INSERT INTO some_table (x, y) VALUES (:x, :y)"),
|
|
||||||
# [{"x": 6, "y": 8}, {"x": 9, "y": 10}]
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# # with engine.connect() as conn:
|
|
||||||
# # result = conn.execute(text("SELECT x, y FROM some_table"))
|
|
||||||
# # for row in result:
|
|
||||||
# # print(f"x: {row.x} y: {row.y}")
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# stmt = text(
|
|
||||||
# "SELECT x, y FROM some_table WHERE y > :y ORDER BY x, y").bindparams(y=6)
|
|
||||||
#
|
|
||||||
# with Session(engine) as session:
|
|
||||||
# result = session.execute(stmt)
|
|
||||||
# for row in result:
|
|
||||||
# print(f"x: {row.x} y: {row.y}")
|
|
||||||
Loading…
Reference in New Issue
Block a user