def edit_track(self, edit_track): if self.mix.id_existing: print_help("Editing track "+edit_track+" in \""+ self.mix.name+"\":") track_details = self.mix.get_one_mix_track(edit_track) if track_details: print_help("{} - {} - {}".format( track_details['discogs_title'], track_details['d_track_no'], track_details['d_track_name'])) log.info("current d_release_id: %s", track_details['d_release_id']) edit_answers = self._edit_track_ask_details(track_details, self.cli._edit_track_questions) for a in edit_answers.items(): log.info("answers: %s", str(a)) update_ok = self.mix.update_track_in_mix(track_details, edit_answers) if update_ok: print_help("Track edit was successful.") else: log.error("Something went wrong on mix_track edit!") raise SystemExit(1) self.view() else: print_help("No track "+edit_track+" in \""+ self.mix.name+"\".") else: print_help("Mix unknown: \"{}\".".format(self.mix.name_or_id))
def d_artists_parse(self, d_tracklist, track_number, d_artists): '''gets Artist name from discogs release (child)objects via track_number, eg. A1''' for tr in d_tracklist: #log.info("d_artists_parse: this is the tr object: {}".format(dir(tr))) if tr.position == track_number: #log.info("d_tracklist_parse: found by track number.") if len(tr.artists) == 1: name = tr.artists[0].name log.info( "MODEL: d_artists_parse: just one artist, returning name: {}" .format(name)) return name elif len(tr.artists) == 0: #log.info( # "MODEL: d_artists_parse: tr.artists len 0: this is it: {}".format( # dir(tr.artists))) log.info( "MODEL: d_artists_parse: no artists in tracklist, checking d_artists object.." ) combined_name = self.d_artists_to_str(d_artists) return combined_name else: log.info("tr.artists len: {}".format(len(tr.artists))) for a in tr.artists: log.info("release.artists debug loop: {}".format( a.name)) combined_name = self.d_artists_to_str(tr.artists) log.info( "MODEL: d_artists_parse: several artists, returning combined named {}" .format(combined_name)) return combined_name
def create_table(conn, create_table_sql): try: c = conn.cursor() c.execute(create_table_sql) log.info("DB: Executed sql: %s", create_table_sql) except Error as e: log.error("DB: %s", e)
def get_mix_tracks_to_copy(conn, _mix_id): cur = conn.cursor() log.info('DB: Getting tracks for mix ID %s', _mix_id) cur.execute('''SELECT d_release_id, d_track_no, track_pos, trans_rating, trans_notes FROM mix_track WHERE mix_id == ?''',(_mix_id, )) rows = cur.fetchall() return rows
def track_report_snippet(self, track_pos, mix_id): track_pos_before = track_pos - 1 track_pos_after = track_pos + 1 sql_sel = '''SELECT track_pos, discogs_title, d_track_name, mix_track.d_track_no, key, bpm, key_notes, trans_rating, trans_notes, notes FROM''' sql_sel += ''' mix_track INNER JOIN mix ON mix.mix_id = mix_track.mix_id INNER JOIN release ON mix_track.d_release_id = release.discogs_id LEFT OUTER JOIN track ON mix_track.d_release_id = track.d_release_id AND mix_track.d_track_no = track.d_track_no LEFT OUTER JOIN track_ext ON mix_track.d_release_id = track_ext.d_release_id AND mix_track.d_track_no = track_ext.d_track_no WHERE (mix_track.track_pos == "{}" OR mix_track.track_pos == "{}" OR mix_track.track_pos == "{}") AND mix_track.mix_id == "{}" ORDER BY mix_track.track_pos'''.format( track_pos, track_pos_before, track_pos_after, mix_id) tracks_snippet = self._select(sql_sel, fetchone=False) if not tracks_snippet: return False else: log.info("MODEL: Returning track_report_snippet data.") #self.cli.print_help(tracks_snippet) return tracks_snippet
def create_track(self, release_id, track_no, track_name, track_artist): insert_tuple = (release_id, track_artist, track_no, track_name) update_tuple = (release_id, track_artist, track_no, track_name, release_id, track_no) c = self.db_conn.cursor() with self.db_conn: try: c.execute( '''INSERT INTO track(d_release_id, d_artist, d_track_no, d_track_name, import_timestamp) VALUES(?, ?, ?, ?, datetime('now', 'localtime'))''', insert_tuple) return c.rowcount except sqlerr as e: if "UNIQUE constraint failed" in e.args[0]: log.warning( "Track details already in DiscoBASE, updating ...") try: c.execute( '''UPDATE track SET (d_release_id, d_artist, d_track_no, d_track_name, import_timestamp) = (?, ?, ?, ?, datetime('now', 'localtime')) WHERE d_release_id == ? AND d_track_no == ?''', update_tuple) log.info("MODEL: rowcount: %d, lastrowid: %d", c.rowcount, c.lastrowid) return c.rowcount except sqlerr as e: log.error("MODEL: %s", e.args[0]) return False else: log.error("MODEL: %s", e.args[0]) return False
def update_track_in_mix(self, track_details, edit_answers): try: db.update_track_in_mix(self.db_conn, track_details['mix_track_id'], edit_answers['d_release_id'], edit_answers['d_track_no'], edit_answers['track_pos'], edit_answers['trans_rating'], edit_answers['trans_notes']) db.update_or_insert_track_ext( self.db_conn, track_details['d_release_id'], edit_answers['d_release_id'], edit_answers['d_track_no'], edit_answers['key'], edit_answers['key_notes'], edit_answers['bpm'], edit_answers['notes'], ) log.info("MODEL: Track edit was successful.") return True except Exception as edit_err: log.error("MODEL: Something went wrong in update_track_in_mix!") raise edit_err return False
def create(self, _played, _venue, new_mix_name=False): if not new_mix_name: new_mix_name = self.name created_id = db.add_new_mix(self.db_conn, new_mix_name, _played, _venue) self.db_conn.commit() log.info("MODEL: New mix created with ID {}.".format(created_id)) return created_id
def reorder_tracks(self, startpos = 1): reorder_pos = int(startpos) reordered = self.mix.reorder_tracks(startpos) if not reordered: log.error("Reorder failed. No track {} in mix.".format(startpos)) else: log.info("Reordering tracks successful") self.view()
def track_report_occurences(self, release_id, track_no): occurences_data = self._select_simple( ['track_pos', 'mix_track.mix_id', 'mix.name'], 'mix_track INNER JOIN MIX ON mix.mix_id = mix_track.mix_id', 'd_release_id == "{}" AND d_track_no == "{}"'.format( release_id, track_no)) log.info("MODEL: Returning track_report_occurences data.") return occurences_data
def add_new_mix(conn, name, played='', venue=''): log.debug("DB: add_new_mix got: {}, {}, {}.".format(name, played, venue)) cur = conn.cursor() cur.execute('''INSERT INTO mix (name, created, updated, played, venue) VALUES (?, datetime('now', 'localtime'), '', date(?), ?)''', (name, played, venue)) log.info("DB: cur.rowcount: %s", cur.rowcount) return cur.lastrowid
def create_track(conn, release_id, track_no, track_title): with conn: cur = conn.cursor() cur.execute('''INSERT INTO track(d_release_id, d_track_no, d_track_name, import_timestamp) VALUES(?, ?, ?, datetime('now', 'localtime'))''', (release_id, track_no, track_title)) log.info("DB: cur.rowcount: %s\n", cur.rowcount) return cur.lastrowid
def mix_id_existing(conn, mix_id): cur = conn.cursor() log.info('DB: Checking if mix_id is existing') cur.execute('''SELECT mix_id FROM mix WHERE mix_id == ?''', (mix_id, )) rows = cur.fetchone() if rows: return rows else: return rows
def delete_track_from_mix(conn, _mix_id, _pos): cur = conn.cursor() log.info('DB: Deleting track %i from mix %i', _pos, int(_mix_id)) del_successful = cur.execute('''DELETE FROM mix_track WHERE mix_id == ? AND track_pos ==?''', (_mix_id, _pos)) log.info('DB: DELETE successful? %i', del_successful.rowcount) if del_successful.rowcount: return True else: return False
def d_artists_to_str(self, d_artists): '''gets a combined string from discogs artistlist object''' artist_str = '' for cnt, artist in enumerate(d_artists): if cnt == 0: artist_str = artist.name else: artist_str += ' / {}'.format(artist.name) log.info( 'MODEL: combined artistlist to string \"{}\"'.format(artist_str)) return artist_str
def _add_track(self, _release_id, _release_title, _track_no, _pos): if not _track_no: track_to_add = self.cli.ask_user_for_track() else: log.debug("_track_no was given, value is".format(_track_no)) track_to_add = _track_no if _pos == None: log.debug("_pos was None, setting to 0") _pos = 0 log.debug("This is _pos: {}".format(_pos)) log.debug("This is track_to_add: {}".format(track_to_add)) log.debug("This is _release_id: %s", _release_id) log.debug("This is _release_title: %s", _release_title) if self.mix.id_existing: last_track = self.mix.get_last_track() log.debug("Currently last track in mix is: %s", last_track[0]) current_id = False if _pos: # a position to squeeze in the track was given # get current tracks >= pos tracks_to_shift = self.mix.get_tracks_from_position(_pos) if self.cli.really_add_track(track_to_add, _release_title, self.mix.id, _pos): current_id = self.mix.add_track(_release_id, track_to_add, track_pos = _pos) # all good? reorder tracks if current_id: log.info("Add track to mix successful, now reordering ...") self.mix.reorder_tracks_squeeze_in(_pos, tracks_to_shift) elif is_number(last_track[0]): # no position was given, tracks already mix if self.cli.really_add_track(track_to_add, _release_title, self.mix.id, last_track[0]+1): current_id = self.mix.add_track(_release_id, track_to_add, track_pos = last_track[0] + 1) else: # no position and it's the first track ever added if self.cli.really_add_track(track_to_add, _release_title, self.mix.id, 1): current_id = self.mix.add_track(_release_id, track_to_add, track_pos = 1) # FIXME untested if this is actually a proper sanity check log.debug("Value of current_id in add_offline_track: {}".format(current_id)) if current_id: self.view() #return True else: log.error("Add track to DB failed!") #return False else: self.cli.print_help("Mix ID {} is not existing yet.".format(self.mix.id)) return False
def get_mix_id(conn, mixname): cur = conn.cursor() log.info('DB: Getting mix_id via mix name "%s". Only returns first match', mixname) cur.execute('''SELECT mix_id FROM mix WHERE name LIKE ?''', ("%"+mixname+"%", )) rows = cur.fetchone() if rows: return rows else: log.info("DB: Can't fetch mix ID by name") return False
def create_release(conn, release_id, release_title): cur = conn.cursor() #if collection_item == True: cur.execute('''INSERT INTO release(discogs_id, discogs_title, import_timestamp) VALUES(?, ?, datetime('now', 'localtime'))''', (release_id, release_title)) #else: # cur.execute('''INSERT INTO release(discogs_id, discogs_title, import_timestamp) # VALUES(?, ?, datetime('now', 'localtime'))''', # (release.id, release.title)) log.info("cur.rowcount: %s\n", cur.rowcount) return cur.lastrowid
def rate_limit_slow_downer(self, remaining=10, sleep=2): '''Discogs util: stay in 60/min rate limit''' if int(self.d._fetcher.rate_limit_remaining) < remaining: log.info( "Discogs request rate limit is about to exceed,\ let's wait a bit: %s\n", self.d._fetcher.rate_limit_remaining) #while int(self.d._fetcher.rate_limit_remaining) < remaining: time.sleep(sleep) else: log.info("Discogs rate limit info: %s remaining.", self.d._fetcher.rate_limit_remaining)
def get_tracks_from_position(conn, _mix_id, _pos): conn.row_factory = sqlite3.Row cur = conn.cursor() cur.execute('''SELECT mix_track_id, track_pos FROM mix_track WHERE mix_id == ? AND track_pos >= ? ''', (_mix_id, _pos)) rows = cur.fetchall() log.debug('DB: get_tracks_from_position: %s\n', rows) if len(rows) == 0: log.info('DB: get_tracks_from_position: Nothing found') return False else: return rows
def add_track_to_mix(conn, mix_id, release_id, track_no, track_pos=0, trans_rating='', trans_notes=''): log.debug("DB: add_track_to_mix got this: mix_id: {}, d_release_id: {}, track_no: {}, track_pos: {}, trans_rating: {}, trans_notes: {}".format(mix_id, release_id, track_no, track_pos, trans_rating, trans_notes)) cur = conn.cursor() cur.execute('''INSERT INTO mix_track (mix_id, d_release_id, d_track_no, track_pos, trans_rating, trans_notes) VALUES(?, ?, ?, ?, ?, ?)''', (mix_id, release_id, track_no, track_pos, trans_rating, trans_notes)) log.info("DB: cur.rowcount: %s", cur.rowcount) conn.commit() return cur.lastrowid
def get_releases_of_one_mix(self, start_pos=False): if not start_pos: where = "mix_id == {}".format(self.id) else: where = "mix_id == {} and track_pos >= {}".format( self.id, start_pos) log.info("MODEL: Returning tracks of a mix.") return self._select_simple(['*'], 'mix_track', where, fetchone=False, orderby='track_pos')
def __init__(self, _db_conn, _user_int, _userToken, _appIdentifier): self.user = _user_int # take an instance of the User_int class and set as attribute self.db_conn = _db_conn self.user = _user_int self.collection = Collection(self.db_conn) self.cli = Collection_view_cli() # instantiate cli frontend class if self.user.WANTS_ONLINE: if not self.collection.discogs_connect(_userToken, _appIdentifier): log.error("connecting to Discogs API, let's stay offline!\n") # just set this for compatibilty reasons, currently used in cli.py, will prob. removed #self.ONLINE = self.collection.ONLINE log.info("CTRL: Initial ONLINE status is %s", self.ONLINE)
def reorder_tracks_squeeze_in(self, pos, tracks_to_shift): log.info("MODEL: reorder_tracks got pos {}".format(pos)) #tracks_to_shift = db.get_tracks_from_position(self.db_conn, self.id, pos) if not tracks_to_shift: return False for t in tracks_to_shift: new_pos = t['track_pos'] + 1 log.info("MODEL: Shifting mix_track_id %i from pos %i to %i", t['mix_track_id'], t['track_pos'], new_pos) if not db.update_pos_in_mix(self.db_conn, t['mix_track_id'], new_pos): return False return True
def get_mix_info(self): """ get metadata of ONE mix from db @param @return sqlite fetchone rows object @author """ mix_info = self._select_simple(['*'], 'mix', "mix_id == {}".format(self.id), fetchone=True) log.info("MODEL: Returning mix info.") return mix_info
def update_pos_in_mix(conn, mix_track_id, track_pos_new): log.info("DB: update_pos_in_mix: track_pos_new is {}".format(track_pos_new)) cur = conn.cursor() try: cur.execute('''UPDATE mix_track SET track_pos = ? WHERE mix_track_id == ? ''', (track_pos_new, mix_track_id)) conn.commit() log.info("DB: update_pos_in_mix rowcount: %s", cur.rowcount) return True except sqlite3.Error as er: log.error("DB: update_pos_in_mix error: %s", er.message) return False
def __init__(self, db_conn, mix_name_or_id, db_file=False): super(Mix, self).__init__(db_conn, db_file) # figuring out names and IDs, just logs and sets instance attributes, no exits here! self.name_or_id = mix_name_or_id self.id_existing = False self.name_existing = False self.info = [] self.name = False self.created = False self.updated = False self.played = False self.venue = False if is_number(mix_name_or_id): self.id = mix_name_or_id # if it's a mix-id, get mix-name and info try: self.info = self.get_mix_info() # FIXME info should also be available as single attrs: created, venue, etc. self.name = self.info[1] self.id_existing = True self.name_existing = True except: log.info("Mix ID is not existing yet!") #raise Exception # use this for debugging #raise SystemExit(1) else: self.name = mix_name_or_id # if it's a mix-name, get the id unless it's "all" # (default value, should only show mix list) if not self.name == "all": try: mix_id_tuple = db.get_mix_id(db_conn, self.name) log.info('%s', mix_id_tuple) self.id = mix_id_tuple[0] self.id_existing = True self.name_existing = True # load basic mix-info from DB # FIXME info should also be available as single attrs: created, venue, etc. # FIXME or okay? here we assume mix is existing and id could be fetched try: self.info = self.get_mix_info() self.name = self.info[1] except: log.info("Can't get mix info.") #raise Exception # use this for debugging except: log.info( "Can't get mix-name from id. Mix not existing yet?") #raise Exception # use this for debugging #raise SystemExit(1) if self.id_existing: self.created = self.info[2] self.played = self.info[4] self.venue = self.info[5] log.debug("MODEL: Mix info is {}.".format(self.info)) log.debug("MODEL: Name is {}.".format(self.name)) log.debug("MODEL: Played is {}.".format(self.played)) log.debug("MODEL: Venue is {}.".format(self.venue))
def get_all_mixes(self): """ get metadata of all mixes from db @param @return sqlite fetchall rows object @author """ #mixes_data = db.get_all_mixes(self.db_conn) # we want to select * but in a different order: mixes_data = self._select_simple( ['mix_id', 'name', 'played', 'venue', 'created', 'updated'], 'mix', condition=False, orderby='played') log.info("MODEL: Returning mixes table.") return mixes_data
def get_full_mix(conn, mix_id, detail="coarse"): cur = conn.cursor() log.info('DB getting mix table by ID: %s\n', mix_id) if detail == "coarse": cur.execute('''SELECT track_pos, discogs_title, mix_track.d_track_no, trans_rating, key, bpm FROM mix_track INNER JOIN mix ON mix.mix_id = mix_track.mix_id INNER JOIN release ON mix_track.d_release_id = release.discogs_id LEFT OUTER JOIN track ON mix_track.d_release_id = track.d_release_id AND mix_track.d_track_no = track.d_track_no LEFT OUTER JOIN track_ext ON mix_track.d_release_id = track_ext.d_release_id AND mix_track.d_track_no = track_ext.d_track_no WHERE mix_track.mix_id == ? ORDER BY mix_track.track_pos''', (mix_id, )) else: cur.execute('''SELECT track_pos, discogs_title, d_track_name, mix_track.d_track_no, key, bpm, key_notes, trans_rating, trans_notes, notes FROM mix_track INNER JOIN mix ON mix.mix_id = mix_track.mix_id INNER JOIN release ON mix_track.d_release_id = release.discogs_id LEFT OUTER JOIN track ON mix_track.d_release_id = track.d_release_id AND mix_track.d_track_no = track.d_track_no LEFT OUTER JOIN track_ext ON mix_track.d_release_id = track_ext.d_release_id AND mix_track.d_track_no = track_ext.d_track_no WHERE mix_track.mix_id == ? ORDER BY mix_track.track_pos''', (mix_id, )) rows = cur.fetchall() if len(rows) == 0: log.info('DB nothing found') return False else: return rows
def import_collection(self): self.cli.exit_if_offline(self.collection.ONLINE) self.cli.print_help( "Gathering your Discogs collection and importing necessary fields into DiscoBASE") insert_count = 0 for r in self.collection.me.collection_folders[0].releases: self.collection.rate_limit_slow_downer(remaining=20, sleep=3) artists = self.collection.d_artists_to_str(r.release.artists) print("Release :", r.release.id, "-", artists, "-", r.release.title) rowcount = self.collection.create_release(r.release.id, r.release.title, artists, d_coll = True) # create_release will return False if unsuccessful if rowcount: insert_count = insert_count + 1 print("Created so far:", insert_count, "") log.info("discogs-rate-limit-remaining: %s", self.collection.d._fetcher.rate_limit_remaining) print() else: log.error("Something wrong while importing \"{}\"\n".format(r.release.title))