From 12541e1ff79b126f988a615f2876428b632704de Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Tue, 9 Aug 2022 17:08:18 +0100 Subject: [PATCH] WIP: delete playlist rows working --- app/models.py | 41 ++++++++++++++++++++-- app/playlists.py | 88 +++++++++++++++++++----------------------------- poetry.lock | 46 +++---------------------- 3 files changed, 78 insertions(+), 97 deletions(-) diff --git a/app/models.py b/app/models.py index 66b3cb2..58b9339 100644 --- a/app/models.py +++ b/app/models.py @@ -15,13 +15,14 @@ from sqlalchemy import ( Boolean, Column, DateTime, + delete, Float, ForeignKey, # func, Integer, + select, String, UniqueConstraint, - select, ) # from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import ( @@ -466,10 +467,46 @@ class PlaylistRows(Base): return for row in rows_to_go: - log.debu(f"Should delete: {row}") + log.debug(f"Should delete: {row}") # If needed later: # session.delete(row) + rows_to_go = session.execute( + select(PlaylistRows) + .where(PlaylistRows.playlist_id == playlist_id, + PlaylistRows.row_number > row) + ).scalars().all() + @staticmethod + def delete_rows(session: Session, ids: List[int]) -> None: + """ + Delete passed ids + """ + + session.execute( + delete(PlaylistRows) + .where(PlaylistRows.id.in_(ids)) + ) + # Delete won't take effect until commit() + session.commit() + + @staticmethod + def fixup_rownumbers(session: Session, playlist_id: int) -> None: + """ + Ensure the row numbers for passed playlist have no gaps + """ + + plrs = session.execute( + select(PlaylistRows) + .where(PlaylistRows.playlist_id == playlist_id) + .order_by(PlaylistRows.row_number) + ).scalars().all() + + for i, plr in enumerate(plrs): + print(f"{i=}, {plr.row_number=}") + plr.row_number = i + + # Ensure new row numbers are available to the caller + session.commit() # @classmethod # def get_playlist_rows(cls, playlist_id: int) -> \ diff --git a/app/playlists.py b/app/playlists.py index f3a171b..cb0da9e 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -1244,52 +1244,32 @@ class PlaylistTab(QTableWidget): # self._meta_clear_attribute(row, RowMeta.PLAYED) def _delete_rows(self) -> None: - """Delete mutliple rows""" + """ + Delete mutliple rows - # ***KAE - pass + Actions required: + - Delete the rows from the PlaylistRows table + - Correct the row numbers in the PlaylistRows table + - Remove the rows from the display + """ -# log.debug("playlist._delete_rows()") -# -# selected_rows: List[int] = sorted( -# set(item.row() for item in self.selectedItems()) -# ) -# rows_to_delete: List[int] = [] -# note_rows: Optional[List[int]] = self._get_notes_rows() -# row: int -# row_object: Union[Tracks, Notes] -# -# with Session() as session: -# for row in selected_rows: -# title = self.item(row, self.COL_TITLE).text() -# msg = QMessageBox(self) -# msg.setIcon(QMessageBox.Warning) -# msg.setText(f"Delete '{title}'?") -# msg.setStandardButtons( -# QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel -# ) -# msg.setDefaultButton(QMessageBox.No) -# msg.setWindowTitle("Delete row") -# # Store list of rows to delete -# response = msg.exec() -# if response == QMessageBox.Yes: -# rows_to_delete.append(row) -# elif response == QMessageBox.Cancel: -# return -# -# # delete in reverse row order so row numbers don't -# # change -# playlist = Playlists.get_by_id(session, self.playlist_id) -# for row in sorted(rows_to_delete, reverse=True): -# if row in note_rows: -# note: Notes = self._get_row_notes_object(row, session) -# note.delete_note(session) -# else: -# playlist.remove_track(session, row) -# self.removeRow(row) -# -# self.save_playlist(session) -# self.update_display(session) + # Delete rows from database + # Each item in a row will be returned from selectedItems(), so + # make a set to remove duplicate row numbers + selected_rows = sorted( + set(item.row() for item in self.selectedItems()) + ) + plr_ids = [self._get_playlistrow_id(a) for a in selected_rows] + with Session() as session: + PlaylistRows.delete_rows(session, plr_ids) + + # Fix up row numbers left in this playlist + PlaylistRows.fixup_rownumbers(session, self.playlist_id) + + # Remove rows from display. Do so in reverse order so that + # row numbers remain valid. + for row in sorted(selected_rows, reverse=True): + self.removeRow(row) def _drop_on(self, event): """ @@ -1571,16 +1551,16 @@ class PlaylistTab(QTableWidget): # if self._meta_get(row) & (1 << RowMeta.NOTE): # return True # return False -# -# def _meta_clear_attribute(self, row: int, attribute: int) -> None: -# """Clear given metadata for row""" -# -# if row is None: -# raise ValueError(f"_meta_clear_attribute({row=}, {attribute=})") -# -# new_metadata: int = self._meta_get(row) & ~(1 << attribute) -# self.item(row, self.COL_USERDATA).setData( -# self.ROW_FLAGS, new_metadata) + + def _meta_clear_attribute(self, row: int, attribute: int) -> None: + """Clear given metadata for row""" + + if row is None: + raise ValueError(f"_meta_clear_attribute({row=}, {attribute=})") + + new_metadata: int = self._meta_get(row) & ~(1 << attribute) + self.item(row, columns['userdata'].idx).setData( + self.ROW_FLAGS, new_metadata) def _meta_clear_next(self) -> None: """ diff --git a/poetry.lock b/poetry.lock index a2b7d23..abd3158 100644 --- a/poetry.lock +++ b/poetry.lock @@ -499,7 +499,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "sqlalchemy" -version = "1.4.32" +version = "1.4.40" description = "Database Abstraction Library" category = "main" optional = false @@ -512,8 +512,8 @@ greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platfo aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"] asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3)"] -mariadb_connector = ["mariadb (>=1.0.1)"] +asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3,!=0.2.4)"] +mariadb_connector = ["mariadb (>=1.0.1,!=1.1.2)"] mssql = ["pyodbc"] mssql_pymssql = ["pymssql"] mssql_pyodbc = ["pyodbc"] @@ -523,7 +523,7 @@ mysql_connector = ["mysql-connector-python"] oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] postgresql = ["psycopg2 (>=2.7)"] postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] -postgresql_pg8000 = ["pg8000 (>=1.16.6)"] +postgresql_pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] postgresql_psycopg2binary = ["psycopg2-binary"] postgresql_psycopg2cffi = ["psycopg2cffi"] pymysql = ["pymysql (<1)", "pymysql"] @@ -972,43 +972,7 @@ six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] -sqlalchemy = [ - {file = "SQLAlchemy-1.4.32-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:4b2bcab3a914715d332ca783e9bda13bc570d8b9ef087563210ba63082c18c16"}, - {file = "SQLAlchemy-1.4.32-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:159c2f69dd6efd28e894f261ffca1100690f28210f34cfcd70b895e0ea7a64f3"}, - {file = "SQLAlchemy-1.4.32-cp27-cp27m-win_amd64.whl", hash = "sha256:d7e483f4791fbda60e23926b098702340504f7684ce7e1fd2c1bf02029288423"}, - {file = "SQLAlchemy-1.4.32-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4aa96e957141006181ca58e792e900ee511085b8dae06c2d08c00f108280fb8a"}, - {file = "SQLAlchemy-1.4.32-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:576684771456d02e24078047c2567025f2011977aa342063468577d94e194b00"}, - {file = "SQLAlchemy-1.4.32-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fff677fa4522dafb5a5e2c0cf909790d5d367326321aeabc0dffc9047cb235bd"}, - {file = "SQLAlchemy-1.4.32-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8679f9aba5ac22e7bce54ccd8a77641d3aea3e2d96e73e4356c887ebf8ff1082"}, - {file = "SQLAlchemy-1.4.32-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7046f7aa2db445daccc8424f50b47a66c4039c9f058246b43796aa818f8b751"}, - {file = "SQLAlchemy-1.4.32-cp310-cp310-win32.whl", hash = "sha256:bedd89c34ab62565d44745212814e4b57ef1c24ad4af9b29c504ce40f0dc6558"}, - {file = "SQLAlchemy-1.4.32-cp310-cp310-win_amd64.whl", hash = "sha256:199dc6d0068753b6a8c0bd3aceb86a3e782df118260ebc1fa981ea31ee054674"}, - {file = "SQLAlchemy-1.4.32-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:8e1e5d96b744a4f91163290b01045430f3f32579e46d87282449e5b14d27d4ac"}, - {file = "SQLAlchemy-1.4.32-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edfcf93fd92e2f9eef640b3a7a40db20fe3c1d7c2c74faa41424c63dead61b76"}, - {file = "SQLAlchemy-1.4.32-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:04164e0063feb7aedd9d073db0fd496edb244be40d46ea1f0d8990815e4b8c34"}, - {file = "SQLAlchemy-1.4.32-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba59761c19b800bc2e1c9324da04d35ef51e4ee9621ff37534bc2290d258f71"}, - {file = "SQLAlchemy-1.4.32-cp36-cp36m-win32.whl", hash = "sha256:708973b5d9e1e441188124aaf13c121e5b03b6054c2df59b32219175a25aa13e"}, - {file = "SQLAlchemy-1.4.32-cp36-cp36m-win_amd64.whl", hash = "sha256:316270e5867566376e69a0ac738b863d41396e2b63274616817e1d34156dff0e"}, - {file = "SQLAlchemy-1.4.32-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:9a0195af6b9050c9322a97cf07514f66fe511968e623ca87b2df5e3cf6349615"}, - {file = "SQLAlchemy-1.4.32-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7e4a3c0c3c596296b37f8427c467c8e4336dc8d50f8ed38042e8ba79507b2c9"}, - {file = "SQLAlchemy-1.4.32-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bca714d831e5b8860c3ab134c93aec63d1a4f493bed20084f54e3ce9f0a3bf99"}, - {file = "SQLAlchemy-1.4.32-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9a680d9665f88346ed339888781f5236347933906c5a56348abb8261282ec48"}, - {file = "SQLAlchemy-1.4.32-cp37-cp37m-win32.whl", hash = "sha256:9cb5698c896fa72f88e7ef04ef62572faf56809093180771d9be8d9f2e264a13"}, - {file = "SQLAlchemy-1.4.32-cp37-cp37m-win_amd64.whl", hash = "sha256:8b9a395122770a6f08ebfd0321546d7379f43505882c7419d7886856a07caa13"}, - {file = "SQLAlchemy-1.4.32-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:3f88a4ee192142eeed3fe173f673ea6ab1f5a863810a9d85dbf6c67a9bd08f97"}, - {file = "SQLAlchemy-1.4.32-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd93162615870c976dba43963a24bb418b28448fef584f30755990c134a06a55"}, - {file = "SQLAlchemy-1.4.32-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5a2e73508f939175363d8a4be9dcdc84cf16a92578d7fa86e6e4ca0e6b3667b2"}, - {file = "SQLAlchemy-1.4.32-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfec934aac7f9fa95fc82147a4ba5db0a8bdc4ebf1e33b585ab8860beb10232f"}, - {file = "SQLAlchemy-1.4.32-cp38-cp38-win32.whl", hash = "sha256:bb42f9b259c33662c6a9b866012f6908a91731a419e69304e1261ba3ab87b8d1"}, - {file = "SQLAlchemy-1.4.32-cp38-cp38-win_amd64.whl", hash = "sha256:7ff72b3cc9242d1a1c9b84bd945907bf174d74fc2519efe6184d6390a8df478b"}, - {file = "SQLAlchemy-1.4.32-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5dc9801ae9884e822ba942ca493642fb50f049c06b6dbe3178691fce48ceb089"}, - {file = "SQLAlchemy-1.4.32-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4607d2d16330757818c9d6fba322c2e80b4b112ff24295d1343a80b876eb0ed"}, - {file = "SQLAlchemy-1.4.32-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:20e9eba7fd86ef52e0df25bea83b8b518dfdf0bce09b336cfe51671f52aaaa3f"}, - {file = "SQLAlchemy-1.4.32-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:290cbdf19129ae520d4bdce392648c6fcdbee763bc8f750b53a5ab51880cb9c9"}, - {file = "SQLAlchemy-1.4.32-cp39-cp39-win32.whl", hash = "sha256:1bbac3e8293b34c4403d297e21e8f10d2a57756b75cff101dc62186adec725f5"}, - {file = "SQLAlchemy-1.4.32-cp39-cp39-win_amd64.whl", hash = "sha256:b3f1d9b3aa09ab9adc7f8c4b40fc3e081eb903054c9a6f9ae1633fe15ae503b4"}, - {file = "SQLAlchemy-1.4.32.tar.gz", hash = "sha256:6fdd2dc5931daab778c2b65b03df6ae68376e028a3098eb624d0909d999885bc"}, -] +sqlalchemy = [] sqlalchemy-stubs = [ {file = "sqlalchemy-stubs-0.4.tar.gz", hash = "sha256:c665d6dd4482ef642f01027fa06c3d5e91befabb219dc71fc2a09e7d7695f7ae"}, {file = "sqlalchemy_stubs-0.4-py3-none-any.whl", hash = "sha256:5eec7aa110adf9b957b631799a72fef396b23ff99fe296df726645d01e312aa5"},