From d06f96388d754ed41876f7fccb63f84241d44963 Mon Sep 17 00:00:00 2001 From: Michaƫl Ball Date: Sun, 26 Mar 2017 10:19:59 +0100 Subject: Works on python 2/pypy --- models/album.py | 80 ++++++++++++++--------------- models/artist.py | 75 ++++++++++++--------------- models/base.py | 13 +++-- models/track.py | 152 ++++++++++++++++++++++++++----------------------------- models/user.py | 17 ++++--- 5 files changed, 159 insertions(+), 178 deletions(-) (limited to 'models') diff --git a/models/album.py b/models/album.py index 96bea81..d55fb88 100644 --- a/models/album.py +++ b/models/album.py @@ -1,17 +1,16 @@ from common import utils -from db.db_manager import DbManager from models.base import BaseModel class Album(BaseModel): + """Represents an album.""" - def __init__(self, id=None, db=None, **kwargs): - if db: - self.db = db + def __init__(self, db, id=None, **kwargs): + self._db = db if id is not None: - for row in self.db.execute("SELECT * FROM album WHERE id = ?", - (id,)): + for row in self._db.execute("SELECT * FROM album WHERE id = ?", + (id,)): setattr(self, "id", id) setattr(self, "name", row[1]) setattr(self, "date", row[2]) @@ -23,25 +22,21 @@ class Album(BaseModel): for track in self.tracks: track.delete() - with self.db.conn: + with self._db.conn: delete_album = "DELETE FROM album WHERE id = ?" - self.db.execute(delete_album, (self.id,)) + self._db.execute(delete_album, (self.id,)) delete_track_rel = "DELETE FROM album_track WHERE album_id = ?" - self.db.execute(delete_track_rel, (self.id,)) + self._db.execute(delete_track_rel, (self.id,)) delete_artist_rel = "DELETE FROM album_artist WHERE album_id = ?" - self.db.execute(delete_artist_rel, (self.id,)) + self._db.execute(delete_artist_rel, (self.id,)) return True @property def db(self): - try: - return self._db - except AttributeError: - self._db = DbManager() - return self._db + return self._db @db.setter def db(self, db): @@ -54,12 +49,12 @@ class Album(BaseModel): if not hasattr(self, "_artists"): setattr(self, "_artists", []) - for row in self.db.execute("SELECT artist.* FROM artist INNER " - "JOIN album_artist ON artist.id = " - "album_artist.artist_id WHERE " - "album_id = ? ORDER BY name ASC", - (self.id,)): - artist = Artist(id=row[0], db=self.db, name=row[1], + for row in self._db.execute("SELECT artist.* FROM artist INNER " + "JOIN album_artist ON artist.id = " + "album_artist.artist_id WHERE " + "album_id = ? ORDER BY name ASC", + (self.id,)): + artist = Artist(id=row[0], db=self._db, name=row[1], sortname=row[2], musicbrainz_artistid=row[3]) self._artists.append(artist) @@ -72,13 +67,13 @@ class Album(BaseModel): if not hasattr(self, "_tracks"): setattr(self, "_tracks", []) - for row in self.db.execute("SELECT track.* FROM track INNER " - "JOIN album_track ON track.id = " - "album_track.track_id WHERE " - "album_id = ? ORDER BY tracknumber " - "ASC", (self.id,)): + for row in self._db.execute("SELECT track.* FROM track INNER " + "JOIN album_track ON track.id = " + "album_track.track_id WHERE " + "album_id = ? ORDER BY tracknumber " + "ASC", (self.id,)): - track = Track(id=row["id"], db=self.db, + track = Track(id=row["id"], db=self._db, tracknumber=row["tracknumber"], name=row["name"], grouping=row["grouping"], filename=row["filename"]) @@ -97,14 +92,15 @@ class Album(BaseModel): if len(dirty_attributes) > 0: set_clause = utils.update_clause_from_dict(dirty_attributes) - dirty_attributes[id] = self.id + dirty_attributes["id"] = self.id - sql = " ".join(("UPDATE album"), set_clause, "WHERE id = :id") + sql = " ".join(("UPDATE album", set_clause, "WHERE id = :id")) - with self.db.conn: - self.db.execute(sql, dirty_attributes) + with self._db.conn: + self._db.execute(sql, dirty_attributes) - def search(db=None, **search_params): + @classmethod + def search(cls, database, **search_params): """Find an album with the given params Args: @@ -114,9 +110,6 @@ class Album(BaseModel): """ albums = [] - if not db: - db = DbManager() - # unpack search params where_params = {} value_params = {} @@ -136,21 +129,21 @@ class Album(BaseModel): result = None if where_clause: statement = " ".join(("SELECT * FROM album", where_clause)) - result = db.execute(statement, value_params) + result = database.execute(statement, value_params) else: - result = db.execute("SELECT * FROM album") + result = database.execute("SELECT * FROM album") for row in result: albums.append( - Album(id=row["id"], db=db, name=row["name"], date=row["date"]) + Album(id=row["id"], db=database, name=row["name"], + date=row["date"]) ) return albums - def all(db=None, order="album.id", direction="ASC", limit=None, + @classmethod + def all(cls, database, order="album.id", direction="ASC", limit=None, offset=None): - if not db: - db = DbManager() albums = [] @@ -163,11 +156,12 @@ class Album(BaseModel): select_string = " ".join((select_string, "LIMIT %s OFFSET %s" % (limit, offset))) - result = db.execute(select_string) + result = database.execute(select_string) for row in result: albums.append( - Album(id=row["id"], db=db, name=row["name"], date=row["date"]) + Album(id=row["id"], db=database, name=row["name"], + date=row["date"]) ) return albums diff --git a/models/artist.py b/models/artist.py index a76b2ee..dada665 100644 --- a/models/artist.py +++ b/models/artist.py @@ -1,17 +1,15 @@ from common import utils -from db.db_manager import DbManager from models.base import BaseModel class Artist(BaseModel): - def __init__(self, id=None, db=None, **kwargs): - if db: - self.db = db + def __init__(self, db, id=None, **kwargs): + self._db = db if id is not None: - for row in self.db.execute("SELECT * FROM artist WHERE id = ?", - (id,)): + for row in self._db.execute("SELECT * FROM artist WHERE id = ?", + (id,)): for key in ["id", "name", "sortname", "musicbrainz_artistid"]: setattr(self, key, row[key]) else: @@ -22,25 +20,21 @@ class Artist(BaseModel): for album in self.albums: album.delete() - with self.db.conn: + with self._db.conn: delete_artist = "DELETE FROM artist WHERE id = ?" - self.db.execute(delete_artist, (self.id,)) + self._db.execute(delete_artist, (self.id,)) delete_track_rel = "DELETE FROM artist_track WHERE artist_id = ?" - self.db.execute(delete_track_rel, (self.id,)) + self._db.execute(delete_track_rel, (self.id,)) delete_album_rel = "DELETE FROM album_artist WHERE artist_id = ?" - self.db.execute(delete_album_rel, (self.id,)) + self._db.execute(delete_album_rel, (self.id,)) return True @property def db(self): - try: - return self._db - except AttributeError: - self._db = DbManager() - return self._db + return self._db @db.setter def db(self, db): @@ -53,13 +47,13 @@ class Artist(BaseModel): if not hasattr(self, "_tracks"): setattr(self, "_tracks", []) - for row in self.db.execute("SELECT track.* FROM track INNER " - "JOIN artist_track ON track.id = " - "artist_track.track_id WHERE " - "artist_id = ? ORDER BY name ASC", - (self.id,)): + for row in self._db.execute("SELECT track.* FROM track INNER " + "JOIN artist_track ON track.id = " + "artist_track.track_id WHERE " + "artist_id = ? ORDER BY name ASC", + (self.id,)): - track = Track(id=row["id"], db=self.db, + track = Track(id=row["id"], db=self._db, tracknumber=row["tracknumber"], name=row["name"], grouping=row["grouping"], filename=row["filename"]) @@ -74,12 +68,12 @@ class Artist(BaseModel): if not hasattr(self, "_albums"): setattr(self, "_albums", []) - for row in self.db.execute("SELECT album.* FROM album INNER " - "JOIN album_artist ON album.id = " - "album_artist.album_id WHERE " - "artist_id = ? ORDER BY date ASC", - (self.id,)): - album = Album(id=row["id"], db=self.db, name=row["name"], + for row in self._db.execute("SELECT album.* FROM album INNER " + "JOIN album_artist ON album.id = " + "album_artist.album_id WHERE " + "artist_id = ? ORDER BY date ASC", + (self.id,)): + album = Album(id=row["id"], db=self._db, name=row["name"], date=row["date"]) self._albums.append(album) @@ -98,12 +92,13 @@ class Artist(BaseModel): dirty_attributes[id] = self.id - sql = " ".join(("UPDATE artist"), set_clause, "WHERE id = :id") + sql = " ".join(("UPDATE artist", set_clause, "WHERE id = :id")) - with self.db.conn: - self.db.execute(sql, dirty_attributes) + with self._db.conn: + self._db.execute(sql, dirty_attributes) - def search(db=None, **search_params): + @classmethod + def search(cls, database, **search_params): """Find an artist with the given params Args: @@ -113,9 +108,6 @@ class Artist(BaseModel): """ artists = [] - if not db: - db = DbManager() - # unpack search params where_params = {} value_params = {} @@ -128,23 +120,22 @@ class Artist(BaseModel): result = [] if where_clause: statement = " ".join(("SELECT * FROM artist", where_clause)) - result = db.execute(statement, value_params) + result = database.execute(statement, value_params) else: - result = db.execute("SELECT * FROM artist") + result = database.execute("SELECT * FROM artist") for row in result: artists.append( - Artist(id=row["id"], db=db, name=row["name"], + Artist(id=row["id"], db=database, name=row["name"], sortname=row["sortname"], musicbrainz_artistid=row["musicbrainz_artistid"]) ) return artists - def all(db=None, order="sortname", direction="ASC", limit=None, + @classmethod + def all(cls, database, order="sortname", direction="ASC", limit=None, offset=None): - if not db: - db = DbManager() artists = [] @@ -155,11 +146,11 @@ class Artist(BaseModel): select_string = " ".join((select_string, "LIMIT %s OFFSET %s" % (limit, offset))) - result = db.execute(select_string) + result = database.execute(select_string) for row in result: artists.append( - Artist(id=row["id"], db=db, name=row["name"], + Artist(id=row["id"], db=database, name=row["name"], sortname=row["sortname"], musicbrainz_artistid=row["musicbrainz_artistid"]) ) diff --git a/models/base.py b/models/base.py index fd40001..8a6fc47 100644 --- a/models/base.py +++ b/models/base.py @@ -1,10 +1,15 @@ -class BaseModel(): +"""Implements a base model for other models to inherit.""" +from six import iteritems + +class BaseModel(object): + """BaseModel is meant to be inherited by other models.""" def as_dict(self): + """Exposes all the object's values as a dict.""" this_dict = {} - for k in self.__dict__.keys(): - if k != "_db": - this_dict[k] = getattr(self, k) + for key, val in iteritems(self.__dict__): + if key != "_db": + this_dict[key] = val return this_dict diff --git a/models/track.py b/models/track.py index e0905e6..2a92558 100644 --- a/models/track.py +++ b/models/track.py @@ -2,7 +2,6 @@ import logging import sqlite3 from common import utils -from db.db_manager import DbManager from models.artist import Artist from models.album import Album from models.base import BaseModel @@ -13,15 +12,14 @@ logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG) class Track(BaseModel): - def __init__(self, id=None, db=None, **kwargs): - if db: - self.db = db + def __init__(self, db, id=None, **kwargs): + self._db = db self.__data = {} if id is not None: - for row in self.db.execute("SELECT * FROM track WHERE id = ?", - (id,)): + for row in self._db.execute("SELECT * FROM track WHERE id = ?", + (id,)): for key in ["id", "tracknumber", "name", "grouping", "filename"]: setattr(self, key, row[key]) @@ -32,11 +30,10 @@ class Track(BaseModel): self.__data[key] = value def delete(self): - delete_sql = "DELETE FROM track WHERE id = ?" - with self.db.conn: - self.db.execute(delete_sql, (self.id,)) + with self._db.conn: + self._db.execute(delete_sql, (self.id,)) # If there is an old album, remove it if it no longer has any # tracks @@ -48,8 +45,8 @@ class Track(BaseModel): old_album = self.album if old_album: - self.db.execute("DELETE FROM album_track WHERE track_id = ?", - (self.id,)) + self._db.execute("DELETE FROM album_track WHERE track_id = ?", + (self.id,)) if not old_album.tracks: old_album.delete() @@ -63,8 +60,8 @@ class Track(BaseModel): old_artists = self.artists for old_artist in old_artists: - self.db.execute("DELETE FROM artist_track WHERE track_id = " - "?", (self.id,)) + self._db.execute("DELETE FROM artist_track WHERE track_id = " + "?", (self.id,)) if not old_artist.tracks: old_artist.delete() @@ -73,11 +70,8 @@ class Track(BaseModel): @property def db(self): - try: - return self._db - except AttributeError: - self._db = DbManager() - return self._db + return self._db + @db.setter def db(self, db): @@ -88,11 +82,11 @@ class Track(BaseModel): if not hasattr(self, "_album"): setattr(self, "_album", None) - for row in self.db.execute("SELECT album.* FROM album INNER " - "JOIN album_track ON album.id = " - "album_track.album_id WHERE " - "track_id = ? LIMIT 1", (self.id,)): - setattr(self, "_album", Album(id=row["id"], db=self.db, + for row in self._db.execute("SELECT album.* FROM album INNER " + "JOIN album_track ON album.id = " + "album_track.album_id WHERE " + "track_id = ? LIMIT 1", (self.id,)): + setattr(self, "_album", Album(id=row["id"], db=self._db, name=row["name"], date=row["date"])) @@ -101,7 +95,7 @@ class Track(BaseModel): @property def artists(self): if not hasattr(self, "_artists"): - cursor = self.db.cursor() + cursor = self._db.cursor() setattr(self, "_artists", []) for row in cursor.execute("SELECT artist.* FROM artist INNER JOIN " @@ -109,7 +103,7 @@ class Track(BaseModel): "artist_track.artist_id WHERE " "artist_track.track_id = ?", (self.id,)): - self._artists.append(Artist(id=row["id"], db=self.db, + self._artists.append(Artist(id=row["id"], db=self._db, name=row["name"], sortname=row["sortname"], musicbrainz_artistid=row[ @@ -118,7 +112,10 @@ class Track(BaseModel): return self._artists def update(self, metadata): - c = self.db.cursor() + c = self._db.cursor() + + artist_changed = False + album_changed = False artist_names = metadata["artist"] musicbrainz_artist_ids = [] @@ -136,6 +133,7 @@ class Track(BaseModel): artists = [] for artist_name in artist_names: + artist = None musicbrainz_artistid = None artistsort = None @@ -161,7 +159,7 @@ class Track(BaseModel): row = rows.fetchone() if row: - artist = Artist(id=row["id"], db=self.db, name=row["name"], + artist = Artist(id=row["id"], db=self._db, name=row["name"], sortname=row["sortname"], musicbrainz_artistid=row[ "musicbrainz_artistid"]) @@ -182,7 +180,7 @@ class Track(BaseModel): (artist_name, artistsort, musicbrainz_artistid)) artist = Artist( - id=c.lastrowid, db=self.db, name=artist_name, + id=c.lastrowid, db=self._db, name=artist_name, sortname=artistsort, musicbrainz_artistid=musicbrainz_artistid ) @@ -219,7 +217,7 @@ class Track(BaseModel): row = rows.fetchone() if row: - album = Album(id=row["id"], db=self.db, name=row["name"], + album = Album(id=row["id"], db=self._db, name=row["name"], date=row["date"], musicbrainz_albumid=row["musicbrainz_albumid"]) else: @@ -227,7 +225,7 @@ class Track(BaseModel): "musicbrainz_albumid) VALUES (?, ?, ?)", (album_name, album_date, mb_albumid)) - album = Album(id=c.lastrowid, db=self.db, name=album_name, + album = Album(id=c.lastrowid, db=self._db, name=album_name, date=album_date, musicbrainz_albumid=mb_albumid) elif album_name: @@ -239,14 +237,14 @@ class Track(BaseModel): row = rows.fetchone() if row: - album = Album(id=row["id"], db=self.db, name=row["name"], + album = Album(id=row["id"], db=self._db, name=row["name"], date=row["date"], musicbrainz_albumid=row["musicbrainz_albumid"]) else: c.execute("INSERT INTO album (name, `date`) VALUES (?, ?)", (album_name, album_date)) - album = Album(id=c.lastrowid, db=self.db, name=album_name, + album = Album(id=c.lastrowid, db=self._db, name=album_name, date=album_date) if album: @@ -290,12 +288,9 @@ class Track(BaseModel): pass old_album = self.album - if old_album: - c.execute("DELETE FROM album_track WHERE track_id = ?", (self.id,)) - - if not old_album.tracks: - old_album.delete() + c.execute("DELETE FROM album_track WHERE track_id = ?", + (self.id,)) # If there are old artists, remove them if they no longer have # any tracks @@ -309,9 +304,6 @@ class Track(BaseModel): c.execute("DELETE FROM artist_track WHERE track_id = ?", (self.id,)) - if not old_artist.tracks: - old_artist.delete() - if album: try: c.execute("INSERT INTO album_track (album_id, track_id) " @@ -319,6 +311,9 @@ class Track(BaseModel): except sqlite3.IntegrityError: pass + if not old_album.tracks: + old_album.delete() + setattr(self, "_album", album) for artist in artists: @@ -328,6 +323,9 @@ class Track(BaseModel): except sqlite3.IntegrityError: pass + if not old_artist.tracks: + old_artist.delete() + if album: try: c.execute( @@ -339,8 +337,8 @@ class Track(BaseModel): if artists: setattr(self, "_artists", artists) - self.db.commit() c.close() + self._db.commit() return True @@ -364,10 +362,11 @@ class Track(BaseModel): sql = " ".join(("UPDATE track", set_clause, "WHERE id = :id")) - with self.db.conn: - self.db.execute(sql, dirty_attributes) + with self._db.conn: + self._db.execute(sql, dirty_attributes) - def search(db=None, **search_params): + @classmethod + def search(cls, database, **search_params): """Find a track with the given params Args: @@ -376,10 +375,6 @@ class Track(BaseModel): grouping: dict, with 'data' and 'operator' keys filename: dict, with 'data' and 'operator' keys """ - - if not db: - db = DbManager() - tracks = [] # unpack search params @@ -394,40 +389,37 @@ class Track(BaseModel): result = None if where_clause: statement = " ".join(("SELECT * FROM track", where_clause)) - result = db.execute(statement, value_params) + result = database.execute(statement, value_params) else: - result = db.execute("SELECT * FROM track") + result = database.execute("SELECT * FROM track") for row in result: tracks.append( - Track(id=row["id"], db=db, tracknumber=row["tracknumber"], + Track(id=row["id"], db=database, tracknumber=row["tracknumber"], name=row["name"], grouping=row["grouping"], filename=row["filename"]) ) return tracks - def find_by_path(path, db=None): - if not db: - db = DbManager() + @classmethod + def find_by_path(cls, path, database): track = None - for row in db.execute("SELECT * FROM track WHERE filename = ? " - "LIMIT 1", (path,)): - track = Track(id=row["id"], db=db, tracknumber=row["tracknumber"], - name=row["name"], grouping=row["grouping"], - filename=row["filename"]) + for row in database.execute("SELECT * FROM track WHERE filename = ? " + "LIMIT 1", (path,)): + track = Track(id=row["id"], db=database, + tracknumber=row["tracknumber"], name=row["name"], + grouping=row["grouping"], filename=row["filename"]) return track - def store(filename, metadata, db=None): - if Track.find_by_path(filename, db=db): + @classmethod + def store(cls, filename, metadata, database): + if Track.find_by_path(filename, database): return True - if not db: - db = DbManager() - - c = db.cursor() + c = database.cursor() artist_names = metadata["artist"] musicbrainz_artist_ids = [] @@ -475,7 +467,7 @@ class Track(BaseModel): row = rows.fetchone() if row: - artist = Artist(id=row["id"], db=db, name=row["name"], + artist = Artist(id=row["id"], db=database, name=row["name"], sortname=row["sortname"], musicbrainz_artistid=row[ "musicbrainz_artistid"]) @@ -499,7 +491,7 @@ class Track(BaseModel): (artist_name, artistsort, musicbrainz_artistid)) artist = Artist( - id=c.lastrowid, db=db, name=artist_name, + id=c.lastrowid, db=database, name=artist_name, sortname=artistsort, musicbrainz_artistid=musicbrainz_artistid ) @@ -534,15 +526,15 @@ class Track(BaseModel): row = rows.fetchone() if row: - album = Album(id=row["id"], db=db, name=row["name"], + album = Album(id=row["id"], db=database, name=row["name"], date=row["date"], musicbrainz_albumid=row[ - "musicbrainz_albumid"]) + "musicbrainz_albumid"]) else: c.execute("INSERT INTO album (name, `date`, " "musicbrainz_albumid) VALUES (?, ?, ?)", (album_name, album_date, mb_albumid)) - album = Album(id=c.lastrowid, db=db, name=album_name, + album = Album(id=c.lastrowid, db=database, name=album_name, date=album_date, musicbrainz_albumid=mb_albumid) elif album_name: @@ -554,13 +546,13 @@ class Track(BaseModel): row = rows.fetchone() if row: - album = Album(id=row["id"], db=db, name=row["name"], + album = Album(id=row["id"], db=database, name=row["name"], date=row["date"]) else: c.execute("INSERT INTO album (name, `date`) VALUES(?, ?)", (album_name, album_date)) - album = Album(id=c.lastrowid, db=db, name=album_name, + album = Album(id=c.lastrowid, db=database, name=album_name, date=album_date) for artist in artists: @@ -591,7 +583,7 @@ class Track(BaseModel): rows = c.execute("SELECT * FROM track WHERE filename = ?", (filename,)) row = rows.fetchone() if row: - track = Track(id=row["id"], db=db, + track = Track(id=row["id"], db=database, tracknumber=row["tracknumber"], name=row["name"], grouping=row["grouping"], filename=row["filename"]) else: @@ -600,7 +592,7 @@ class Track(BaseModel): (track_number, track_name, track_grouping, filename)) - track = Track(id=c.lastrowid, db=db, tracknumber=track_number, + track = Track(id=c.lastrowid, db=database, tracknumber=track_number, name=track_name, grouping=track_grouping, filename=filename) @@ -618,16 +610,14 @@ class Track(BaseModel): except sqlite3.IntegrityError: pass - db.commit() + database.commit() c.close() return track - def all(db=None, order="track.id", direction="ASC", limit=None, + @classmethod + def all(cls, database, order="track.id", direction="ASC", limit=None, offset=None): - if not db: - db = DbManager() - tracks = [] select_string = "SELECT * FROM track LEFT JOIN artist_track ON " \ @@ -641,10 +631,10 @@ class Track(BaseModel): select_string = " ".join((select_string, "LIMIT %s OFFSET %s" % (limit, offset))) - result = db.execute(select_string) + result = database.execute(select_string) for row in result: - tracks.append(Track(id=row["id"], db=db, + tracks.append(Track(id=row["id"], db=database, tracknumber=row["tracknumber"], name=row["name"], grouping=row["name"], filename=row["filename"])) diff --git a/models/user.py b/models/user.py index 925df5e..ea90f39 100644 --- a/models/user.py +++ b/models/user.py @@ -1,11 +1,11 @@ -import os +from os import urandom -from flask.ext.login import make_secure_token +from itsdangerous import URLSafeTimedSerializer from common.security import pwd_context, secret_key -class User: +class User(object): def __init__(self, **kwargs): for (key, value) in kwargs.items(): setattr(self, key, value) @@ -43,16 +43,17 @@ class User: def new_password(self, password, category=None): if self.id: - hash = None + the_hash = None if category: - hash = pwd_context.encrypt(password, category=category) + the_hash = pwd_context.encrypt(password, category=category) else: - hash = pwd_context.encrypt(password) + the_hash = pwd_context.encrypt(password) - api_key = make_secure_token(hash, os.urandom(64), key=secret_key) + serializer = URLSafeTimedSerializer(password, salt=urandom(64)) + api_key = serializer.dumps(the_hash) - return hash, api_key + return the_hash, api_key else: raise ValueError("No user") -- cgit v1.2.3