Change database code to PEP8 standards

This commit is contained in:
Adam 2015-03-02 00:31:16 +08:00 committed by adam
parent 40bd7907eb
commit 742efdb805
2 changed files with 62 additions and 69 deletions

View file

@ -23,6 +23,7 @@
* Remove unused force variable from code and PEP8 * Remove unused force variable from code and PEP8
* Change browser, bs4 parser and classes code to PEP8 standards * Change browser, bs4 parser and classes code to PEP8 standards
* Change common and config code to PEP8 standards * Change common and config code to PEP8 standards
* Change database code to PEP8 standards
[develop changelog] [develop changelog]
* Fix traceback error when using the menu item Manage/Update Kodi * Fix traceback error when using the menu item Manage/Update Kodi

View file

@ -25,15 +25,15 @@ import time
import threading import threading
import sickbeard import sickbeard
from sickbeard import encodingKludge as ek from sickbeard import encodingKludge as ek
from sickbeard import logger from sickbeard import logger
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
db_lock = threading.Lock() db_lock = threading.Lock()
def dbFilename(filename="sickbeard.db", suffix=None): def dbFilename(filename='sickbeard.db', suffix=None):
""" """
@param filename: The sqlite database filename to use. If not specified, @param filename: The sqlite database filename to use. If not specified,
will be made to be sickbeard.db will be made to be sickbeard.db
@ -42,16 +42,16 @@ def dbFilename(filename="sickbeard.db", suffix=None):
@return: the correct location of the database file. @return: the correct location of the database file.
""" """
if suffix: if suffix:
filename = "%s.%s" % (filename, suffix) filename = '%s.%s' % (filename, suffix)
return ek.ek(os.path.join, sickbeard.DATA_DIR, filename) return ek.ek(os.path.join, sickbeard.DATA_DIR, filename)
class DBConnection(object): class DBConnection(object):
def __init__(self, filename="sickbeard.db", suffix=None, row_type=None): def __init__(self, filename='sickbeard.db', suffix=None, row_type=None):
self.filename = filename self.filename = filename
self.connection = sqlite3.connect(dbFilename(filename), 20) self.connection = sqlite3.connect(dbFilename(filename), 20)
if row_type == "dict": if row_type == 'dict':
self.connection.row_factory = self._dict_factory self.connection.row_factory = self._dict_factory
else: else:
self.connection.row_factory = sqlite3.Row self.connection.row_factory = sqlite3.Row
@ -62,12 +62,12 @@ class DBConnection(object):
try: try:
if self.hasTable('db_version'): if self.hasTable('db_version'):
result = self.select("SELECT db_version FROM db_version") result = self.select('SELECT db_version FROM db_version')
except: except:
return 0 return 0
if result: if result:
return int(result[0]["db_version"]) return int(result[0]['db_version'])
else: else:
return 0 return 0
@ -90,27 +90,26 @@ class DBConnection(object):
sqlResult.append(self.connection.execute(qu[0]).fetchall()) sqlResult.append(self.connection.execute(qu[0]).fetchall())
elif len(qu) > 1: elif len(qu) > 1:
if logTransaction: if logTransaction:
logger.log(qu[0] + " with args " + str(qu[1]), logger.DB) logger.log(qu[0] + ' with args ' + str(qu[1]), logger.DB)
sqlResult.append(self.connection.execute(qu[0], qu[1]).fetchall()) sqlResult.append(self.connection.execute(qu[0], qu[1]).fetchall())
self.connection.commit() self.connection.commit()
logger.log(u"Transaction with " + str(len(querylist)) + u" query's executed", logger.DEBUG) logger.log(u'Transaction with ' + str(len(querylist)) + u' queries executed', logger.DEBUG)
return sqlResult return sqlResult
except sqlite3.OperationalError, e: except sqlite3.OperationalError, e:
sqlResult = [] sqlResult = []
if self.connection: if self.connection:
self.connection.rollback() self.connection.rollback()
if "unable to open database file" in e.args[0] or "database is locked" in e.args[0]: if 'unable to open database file' in e.args[0] or 'database is locked' in e.args[0]:
logger.log(u"DB error: " + ex(e), logger.WARNING) logger.log(u'DB error: ' + ex(e), logger.WARNING)
attempt += 1 attempt += 1
time.sleep(1) time.sleep(1)
else: else:
logger.log(u"DB error: " + ex(e), logger.ERROR) logger.log(u'DB error: ' + ex(e), logger.ERROR)
raise raise
except sqlite3.DatabaseError, e: except sqlite3.DatabaseError, e:
sqlResult = []
if self.connection: if self.connection:
self.connection.rollback() self.connection.rollback()
logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR) logger.log(u'Fatal error executing query: ' + ex(e), logger.ERROR)
raise raise
return sqlResult return sqlResult
@ -128,24 +127,24 @@ class DBConnection(object):
while attempt < 5: while attempt < 5:
try: try:
if args is None: if args is None:
logger.log(self.filename + ": " + query, logger.DB) logger.log(self.filename + ': ' + query, logger.DB)
sqlResult = self.connection.execute(query) sqlResult = self.connection.execute(query)
else: else:
logger.log(self.filename + ": " + query + " with args " + str(args), logger.DB) logger.log(self.filename + ': ' + query + ' with args ' + str(args), logger.DB)
sqlResult = self.connection.execute(query, args) sqlResult = self.connection.execute(query, args)
self.connection.commit() self.connection.commit()
# get out of the connection attempt loop since we were successful # get out of the connection attempt loop since we were successful
break break
except sqlite3.OperationalError, e: except sqlite3.OperationalError, e:
if "unable to open database file" in e.args[0] or "database is locked" in e.args[0]: if 'unable to open database file' in e.args[0] or 'database is locked' in e.args[0]:
logger.log(u"DB error: " + ex(e), logger.WARNING) logger.log(u'DB error: ' + ex(e), logger.WARNING)
attempt += 1 attempt += 1
time.sleep(1) time.sleep(1)
else: else:
logger.log(u"DB error: " + ex(e), logger.ERROR) logger.log(u'DB error: ' + ex(e), logger.ERROR)
raise raise
except sqlite3.DatabaseError, e: except sqlite3.DatabaseError, e:
logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR) logger.log(u'Fatal error executing query: ' + ex(e), logger.ERROR)
raise raise
return sqlResult return sqlResult
@ -159,41 +158,41 @@ class DBConnection(object):
return sqlResults return sqlResults
def upsert(self, tableName, valueDict, keyDict): def upsert(self, tableName, valueDict, keyDict):
changesBefore = self.connection.total_changes changesBefore = self.connection.total_changes
genParams = lambda myDict: [x + " = ?" for x in myDict.keys()] genParams = lambda myDict: [x + ' = ?' for x in myDict.keys()]
query = "UPDATE [" + tableName + "] SET " + ", ".join(genParams(valueDict)) + " WHERE " + " AND ".join( query = 'UPDATE [%s] SET %s WHERE %s' % (
genParams(keyDict)) tableName, ', '.join(genParams(valueDict)), ' AND '.join(genParams(keyDict)))
self.action(query, valueDict.values() + keyDict.values()) self.action(query, valueDict.values() + keyDict.values())
if self.connection.total_changes == changesBefore: if self.connection.total_changes == changesBefore:
query = "INSERT INTO [" + tableName + "] (" + ", ".join(valueDict.keys() + keyDict.keys()) + ")" + \ query = 'INSERT INTO [' + tableName + '] (' + ', '.join(valueDict.keys() + keyDict.keys()) + ')' + \
" VALUES (" + ", ".join(["?"] * len(valueDict.keys() + keyDict.keys())) + ")" ' VALUES (' + ', '.join(['?'] * len(valueDict.keys() + keyDict.keys())) + ')'
self.action(query, valueDict.values() + keyDict.values()) self.action(query, valueDict.values() + keyDict.values())
def tableInfo(self, tableName): def tableInfo(self, tableName):
# FIXME ? binding is not supported here, but I cannot find a way to escape a string manually # FIXME ? binding is not supported here, but I cannot find a way to escape a string manually
sqlResult = self.select("PRAGMA table_info([%s])" % tableName) sqlResult = self.select('PRAGMA table_info([%s])' % tableName)
columns = {} columns = {}
for column in sqlResult: for column in sqlResult:
columns[column['name']] = {'type': column['type']} columns[column['name']] = {'type': column['type']}
return columns return columns
# http://stackoverflow.com/questions/3300464/how-can-i-get-dict-from-sqlite-query # http://stackoverflow.com/questions/3300464/how-can-i-get-dict-from-sqlite-query
def _dict_factory(self, cursor, row): @staticmethod
def _dict_factory(cursor, row):
d = {} d = {}
for idx, col in enumerate(cursor.description): for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx] d[col[0]] = row[idx]
return d return d
def hasTable(self, tableName): def hasTable(self, tableName):
return len(self.select("SELECT 1 FROM sqlite_master WHERE name = ?;", (tableName, ))) > 0 return len(self.select('SELECT 1 FROM sqlite_master WHERE name = ?;', (tableName, ))) > 0
def hasColumn(self, tableName, column): def hasColumn(self, tableName, column):
return column in self.tableInfo(tableName) return column in self.tableInfo(tableName)
@ -205,17 +204,17 @@ class DBConnection(object):
return True return True
return False return False
def addColumn(self, table, column, type='NUMERIC', default=0):
def addColumn(self, table, column, type="NUMERIC", default=0): self.action('ALTER TABLE [%s] ADD %s %s' % (table, column, type))
self.action("ALTER TABLE [%s] ADD %s %s" % (table, column, type)) self.action('UPDATE [%s] SET %s = ?' % (table, column), (default,))
self.action("UPDATE [%s] SET %s = ?" % (table, column), (default,))
def close(self): def close(self):
"""Close database connection""" """Close database connection"""
if getattr(self, "connection", None) is not None: if getattr(self, 'connection', None) is not None:
self.connection.close() self.connection.close()
self.connection = None self.connection = None
def sanityCheckDatabase(connection, sanity_check): def sanityCheckDatabase(connection, sanity_check):
sanity_check(connection).check() sanity_check(connection).check()
@ -228,23 +227,19 @@ class DBSanityCheck(object):
pass pass
# ===============
# = Upgrade API =
# ===============
def upgradeDatabase(connection, schema): def upgradeDatabase(connection, schema):
logger.log(u"Checking database structure...", logger.MESSAGE) logger.log(u'Checking database structure...', logger.MESSAGE)
_processUpgrade(connection, schema) _processUpgrade(connection, schema)
def prettyName(class_name): def prettyName(class_name):
return ' '.join([x.group() for x in re.finditer("([A-Z])([a-z0-9]+)", class_name)]) return ' '.join([x.group() for x in re.finditer('([A-Z])([a-z0-9]+)', class_name)])
def restoreDatabase(version): def restoreDatabase(version):
logger.log(u"Restoring database before trying upgrade again") logger.log(u'Restoring database before trying upgrade again')
if not sickbeard.helpers.restoreVersionedFile(dbFilename(suffix='v' + str(version)), version): if not sickbeard.helpers.restoreVersionedFile(dbFilename(suffix='v%s' % version), version):
logger.log_error_and_exit(u"Database restore failed, abort upgrading database") logger.log_error_and_exit(u'Database restore failed, abort upgrading database')
return False return False
else: else:
return True return True
@ -252,9 +247,9 @@ def restoreDatabase(version):
def _processUpgrade(connection, upgradeClass): def _processUpgrade(connection, upgradeClass):
instance = upgradeClass(connection) instance = upgradeClass(connection)
logger.log(u"Checking " + prettyName(upgradeClass.__name__) + " database upgrade", logger.DEBUG) logger.log(u'Checking %s database upgrade' % prettyName(upgradeClass.__name__), logger.DEBUG)
if not instance.test(): if not instance.test():
logger.log(u"Database upgrade required: " + prettyName(upgradeClass.__name__), logger.MESSAGE) logger.log(u'Database upgrade required: %s' % prettyName(upgradeClass.__name__), logger.MESSAGE)
try: try:
instance.execute() instance.execute()
except sqlite3.DatabaseError, e: except sqlite3.DatabaseError, e:
@ -263,9 +258,9 @@ def _processUpgrade(connection, upgradeClass):
instance.execute() instance.execute()
except: except:
restored = False restored = False
result = connection.select("SELECT db_version FROM db_version") result = connection.select('SELECT db_version FROM db_version')
if result: if result:
version = int(result[0]["db_version"]) version = int(result[0]['db_version'])
# close db before attempting restore # close db before attempting restore
connection.close() connection.close()
@ -276,11 +271,11 @@ def _processUpgrade(connection, upgradeClass):
restored = True restored = True
if not restored: if not restored:
print "Error in " + str(upgradeClass.__name__) + ": " + ex(e) print 'Error in %s: %s ' % (upgradeClass.__name__, ex(e))
raise raise
logger.log(upgradeClass.__name__ + " upgrade completed", logger.DEBUG) logger.log('%s upgrade completed' % upgradeClass.__name__, logger.DEBUG)
else: else:
logger.log(upgradeClass.__name__ + " upgrade not required", logger.DEBUG) logger.log('%s upgrade not required' % upgradeClass.__name__, logger.DEBUG)
for upgradeSubClass in upgradeClass.__subclasses__(): for upgradeSubClass in upgradeClass.__subclasses__():
_processUpgrade(connection, upgradeSubClass) _processUpgrade(connection, upgradeSubClass)
@ -292,14 +287,14 @@ class SchemaUpgrade(object):
self.connection = connection self.connection = connection
def hasTable(self, tableName): def hasTable(self, tableName):
return len(self.connection.select("SELECT 1 FROM sqlite_master WHERE name = ?;", (tableName, ))) > 0 return len(self.connection.select('SELECT 1 FROM sqlite_master WHERE name = ?;', (tableName, ))) > 0
def hasColumn(self, tableName, column): def hasColumn(self, tableName, column):
return column in self.connection.tableInfo(tableName) return column in self.connection.tableInfo(tableName)
def addColumn(self, table, column, type="NUMERIC", default=0): def addColumn(self, table, column, type='NUMERIC', default=0):
self.connection.action("ALTER TABLE [%s] ADD %s %s" % (table, column, type)) self.connection.action('ALTER TABLE [%s] ADD %s %s' % (table, column, type))
self.connection.action("UPDATE [%s] SET %s = ?" % (table, column), (default,)) self.connection.action('UPDATE [%s] SET %s = ?' % (table, column), (default,))
def dropColumn(self, table, column): def dropColumn(self, table, column):
# get old table columns and store the ones we want to keep # get old table columns and store the ones we want to keep
@ -315,9 +310,7 @@ class SchemaUpgrade(object):
keptColumnsNames.append(column['name']) keptColumnsNames.append(column['name'])
cl = [] cl = [column['name'], column['type']]
cl.append(column['name'])
cl.append(column['type'])
''' '''
To be implemented if ever required To be implemented if ever required
@ -350,7 +343,7 @@ class SchemaUpgrade(object):
self.connection.action('INSERT INTO [%s_new] SELECT %s FROM [%s]' % (table, keptColumnsNames, table)) self.connection.action('INSERT INTO [%s_new] SELECT %s FROM [%s]' % (table, keptColumnsNames, table))
# copy the old indexes from the old table # copy the old indexes from the old table
result = self.connection.select('SELECT sql FROM sqlite_master WHERE tbl_name=? and type="index"', [table]) result = self.connection.select("SELECT sql FROM sqlite_master WHERE tbl_name=? and type='index'", [table])
# remove the old table and rename the new table to take it's place # remove the old table and rename the new table to take it's place
self.connection.action('DROP TABLE [%s]' % table) self.connection.action('DROP TABLE [%s]' % table)
@ -362,25 +355,24 @@ class SchemaUpgrade(object):
self.connection.action(index['sql']) self.connection.action(index['sql'])
# vacuum the db as we will have a lot of space to reclaim after dropping tables # vacuum the db as we will have a lot of space to reclaim after dropping tables
self.connection.action("VACUUM") self.connection.action('VACUUM')
def checkDBVersion(self): def checkDBVersion(self):
return self.connection.checkDBVersion() return self.connection.checkDBVersion()
def incDBVersion(self): def incDBVersion(self):
new_version = self.checkDBVersion() + 1 new_version = self.checkDBVersion() + 1
self.connection.action("UPDATE db_version SET db_version = ?", [new_version]) self.connection.action('UPDATE db_version SET db_version = ?', [new_version])
return new_version return new_version
def setDBVersion(self, new_version): def setDBVersion(self, new_version):
self.connection.action("UPDATE db_version SET db_version = ?", [new_version]) self.connection.action('UPDATE db_version SET db_version = ?', [new_version])
return new_version return new_version
def MigrationCode(myDB): def MigrationCode(myDB):
schema = { schema = {
0: sickbeard.mainDB.InitialSchema, # 0->20000 0: sickbeard.mainDB.InitialSchema,
9: sickbeard.mainDB.AddSizeAndSceneNameFields, 9: sickbeard.mainDB.AddSizeAndSceneNameFields,
10: sickbeard.mainDB.RenameSeasonFolders, 10: sickbeard.mainDB.RenameSeasonFolders,
11: sickbeard.mainDB.Add1080pAndRawHDQualities, 11: sickbeard.mainDB.Add1080pAndRawHDQualities,
@ -420,12 +412,12 @@ def MigrationCode(myDB):
10001: sickbeard.mainDB.RemoveDefaultEpStatusFromTvShows, 10001: sickbeard.mainDB.RemoveDefaultEpStatusFromTvShows,
20000: sickbeard.mainDB.DBIncreaseTo20001, 20000: sickbeard.mainDB.DBIncreaseTo20001,
#20001: sickbeard.mainDB.AddCoolSickGearFeature2, # 20001: sickbeard.mainDB.AddCoolSickGearFeature2,
#20002: sickbeard.mainDB.AddCoolSickGearFeature3, # 20002: sickbeard.mainDB.AddCoolSickGearFeature3,
} }
db_version = myDB.checkDBVersion() db_version = myDB.checkDBVersion()
logger.log(u'Detected database version: v' + str(db_version), logger.DEBUG) logger.log(u'Detected database version: v%s' % db_version, logger.DEBUG)
if not (db_version in schema): if not (db_version in schema):
if db_version == sickbeard.mainDB.MAX_DB_VERSION: if db_version == sickbeard.mainDB.MAX_DB_VERSION:
@ -443,10 +435,10 @@ def MigrationCode(myDB):
db_version = update.execute() db_version = update.execute()
except Exception, e: except Exception, e:
myDB.close() myDB.close()
logger.log(u'Failed to update database with error: ' + ex(e) + ' attempting recovery...', logger.ERROR) logger.log(u'Failed to update database with error: %s attempting recovery...' % ex(e), logger.ERROR)
if restoreDatabase(db_version): if restoreDatabase(db_version):
# initialize the main SB database # initialize the main SB database
logger.log_error_and_exit(u'Successfully restored database version:' + str(db_version)) logger.log_error_and_exit(u'Successfully restored database version: %s' % db_version)
else: else:
logger.log_error_and_exit(u'Failed to restore database version:' + str(db_version)) logger.log_error_and_exit(u'Failed to restore database version: %s' % db_version)