""" Helper functions for use with the SQLite database. """ import sqlite3 import time from sqlite3 import Connection, Cursor from swingmusic import settings from swingmusic.models import Album, Playlist, Track def tuple_to_track(track: tuple): """ Takes a tuple and returns a Track object """ return Track(*track[1:]) # rowid is removed from the tuple def tuples_to_tracks(tracks: list[tuple]): """ Takes a list of tuples and returns a generator that yields a Track object for each tuple """ for track in tracks: yield tuple_to_track(track) def tuple_to_album(album: tuple): """ Takes a tuple and returns an Album object """ return Album(*album[1:]) # rowid is removed from the tuple def tuples_to_albums(albums: list[tuple]): """ Takes a list of tuples and returns a generator that yields an album object for each tuple """ for album in albums: yield tuple_to_album(album) def tuple_to_playlist(playlist: tuple): """ Takes a tuple and returns a Playlist object """ return Playlist(*playlist) def tuples_to_playlists(playlists: list[tuple]): """ Takes a list of tuples and returns a list of Playlist objects """ for playlist in playlists: yield tuple_to_playlist(playlist) class SQLiteManager: """ This is a context manager that handles the connection and cursor for you. It also commits and closes the connection when you're done. """ def __init__( self, conn: Connection | None = None, userdata_db=False, test_db_path: str = None, ) -> None: """ When a connection is passed in, don't close the connection, because it's a connection to the search database [in memory db]. """ self.conn = conn self.CLOSE_CONN = True self.userdata_db = userdata_db self.test_db_path = test_db_path if conn: self.conn = conn self.CLOSE_CONN = False def __enter__(self) -> Cursor: if self.conn is not None: cur = self.conn.cursor() cur.execute("PRAGMA foreign_keys = ON") return cur db_path = self.test_db_path or settings.Paths().app_db_path if self.userdata_db: db_path = settings.Paths().userdata_db_path self.conn = sqlite3.connect( db_path, timeout=15, ) cur = self.conn.cursor() cur.execute("PRAGMA foreign_keys = ON") return cur def __exit__(self, exc_type, exc_value, exc_traceback): trial_count = 0 while trial_count < 10: try: self.conn.commit() if self.CLOSE_CONN: self.conn.close() return except sqlite3.OperationalError: trial_count += 1 time.sleep(3) self.conn.close()