mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Kobo driver: Use the closing context manager for sqlite connections
This commit is contained in:
parent
75172aa9cb
commit
8a21f74f32
@ -7,6 +7,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sqlite3 as sqlite
|
import sqlite3 as sqlite
|
||||||
|
from contextlib import closing
|
||||||
|
|
||||||
from calibre.devices.usbms.books import BookList
|
from calibre.devices.usbms.books import BookList
|
||||||
from calibre.devices.kobo.books import Book
|
from calibre.devices.kobo.books import Book
|
||||||
@ -192,77 +193,78 @@ class KOBO(USBMS):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
connection = sqlite.connect(self.normalize_path(self._main_prefix + '.kobo/KoboReader.sqlite'))
|
with closing(sqlite.connect(
|
||||||
|
self.normalize_path(self._main_prefix +
|
||||||
|
'.kobo/KoboReader.sqlite'))) as connection:
|
||||||
|
|
||||||
# return bytestrings if the content cannot the decoded as unicode
|
# return bytestrings if the content cannot the decoded as unicode
|
||||||
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
#query = 'select count(distinct volumeId) from volume_shortcovers'
|
#query = 'select count(distinct volumeId) from volume_shortcovers'
|
||||||
#cursor.execute(query)
|
#cursor.execute(query)
|
||||||
#for row in (cursor):
|
#for row in (cursor):
|
||||||
# numrows = row[0]
|
# numrows = row[0]
|
||||||
#cursor.close()
|
#cursor.close()
|
||||||
|
|
||||||
# Determine the database version
|
# Determine the database version
|
||||||
# 4 - Bluetooth Kobo Rev 2 (1.4)
|
# 4 - Bluetooth Kobo Rev 2 (1.4)
|
||||||
# 8 - WIFI KOBO Rev 1
|
# 8 - WIFI KOBO Rev 1
|
||||||
cursor.execute('select version from dbversion')
|
cursor.execute('select version from dbversion')
|
||||||
result = cursor.fetchone()
|
result = cursor.fetchone()
|
||||||
self.dbversion = result[0]
|
self.dbversion = result[0]
|
||||||
|
|
||||||
debug_print("Database Version: ", self.dbversion)
|
debug_print("Database Version: ", self.dbversion)
|
||||||
if self.dbversion >= 16:
|
if self.dbversion >= 16:
|
||||||
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
||||||
'ImageID, ReadStatus, ___ExpirationStatus, FavouritesIndex, Accessibility from content where ' \
|
'ImageID, ReadStatus, ___ExpirationStatus, FavouritesIndex, Accessibility from content where ' \
|
||||||
'BookID is Null and ( ___ExpirationStatus <> "3" or ___ExpirationStatus is Null)'
|
'BookID is Null and ( ___ExpirationStatus <> "3" or ___ExpirationStatus is Null)'
|
||||||
elif self.dbversion < 16 and self.dbversion >= 14:
|
elif self.dbversion < 16 and self.dbversion >= 14:
|
||||||
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
||||||
'ImageID, ReadStatus, ___ExpirationStatus, FavouritesIndex, "-1" as Accessibility from content where ' \
|
'ImageID, ReadStatus, ___ExpirationStatus, FavouritesIndex, "-1" as Accessibility from content where ' \
|
||||||
'BookID is Null and ( ___ExpirationStatus <> "3" or ___ExpirationStatus is Null)'
|
'BookID is Null and ( ___ExpirationStatus <> "3" or ___ExpirationStatus is Null)'
|
||||||
elif self.dbversion < 14 and self.dbversion >= 8:
|
elif self.dbversion < 14 and self.dbversion >= 8:
|
||||||
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
||||||
'ImageID, ReadStatus, ___ExpirationStatus, "-1" as FavouritesIndex, "-1" as Accessibility from content where ' \
|
'ImageID, ReadStatus, ___ExpirationStatus, "-1" as FavouritesIndex, "-1" as Accessibility from content where ' \
|
||||||
'BookID is Null and ( ___ExpirationStatus <> "3" or ___ExpirationStatus is Null)'
|
'BookID is Null and ( ___ExpirationStatus <> "3" or ___ExpirationStatus is Null)'
|
||||||
else:
|
else:
|
||||||
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
query= 'select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, ' \
|
||||||
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as FavouritesIndex, "-1" as Accessibility from content where BookID is Null'
|
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as FavouritesIndex, "-1" as Accessibility from content where BookID is Null'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.execute (query)
|
cursor.execute (query)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = str(e)
|
err = str(e)
|
||||||
if not ('___ExpirationStatus' in err or 'FavouritesIndex' in err or
|
if not ('___ExpirationStatus' in err or 'FavouritesIndex' in err or
|
||||||
'Accessibility' in err):
|
'Accessibility' in err):
|
||||||
raise
|
raise
|
||||||
query= ('select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
|
query= ('select Title, Attribution, DateCreated, ContentID, MimeType, ContentType, '
|
||||||
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as '
|
'ImageID, ReadStatus, "-1" as ___ExpirationStatus, "-1" as '
|
||||||
'FavouritesIndex, "-1" as Accessibility from content where '
|
'FavouritesIndex, "-1" as Accessibility from content where '
|
||||||
'BookID is Null')
|
'BookID is Null')
|
||||||
cursor.execute(query)
|
cursor.execute(query)
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
for i, row in enumerate(cursor):
|
for i, row in enumerate(cursor):
|
||||||
# self.report_progress((i+1) / float(numrows), _('Getting list of books on device...'))
|
# self.report_progress((i+1) / float(numrows), _('Getting list of books on device...'))
|
||||||
if row[3].startswith("file:///usr/local/Kobo/help/"):
|
if row[3].startswith("file:///usr/local/Kobo/help/"):
|
||||||
# These are internal to the Kobo device and do not exist
|
# These are internal to the Kobo device and do not exist
|
||||||
continue
|
continue
|
||||||
path = self.path_from_contentid(row[3], row[5], row[4], oncard)
|
path = self.path_from_contentid(row[3], row[5], row[4], oncard)
|
||||||
mime = mime_type_ext(path_to_ext(path)) if path.find('kepub') == -1 else 'application/epub+zip'
|
mime = mime_type_ext(path_to_ext(path)) if path.find('kepub') == -1 else 'application/epub+zip'
|
||||||
# debug_print("mime:", mime)
|
# debug_print("mime:", mime)
|
||||||
|
|
||||||
if oncard != 'carda' and oncard != 'cardb' and not row[3].startswith("file:///mnt/sd/"):
|
if oncard != 'carda' and oncard != 'cardb' and not row[3].startswith("file:///mnt/sd/"):
|
||||||
changed = update_booklist(self._main_prefix, path, row[0], row[1], mime, row[2], row[5], row[6], row[7], row[4], row[8], row[9], row[10])
|
changed = update_booklist(self._main_prefix, path, row[0], row[1], mime, row[2], row[5], row[6], row[7], row[4], row[8], row[9], row[10])
|
||||||
# print "shortbook: " + path
|
# print "shortbook: " + path
|
||||||
elif oncard == 'carda' and row[3].startswith("file:///mnt/sd/"):
|
elif oncard == 'carda' and row[3].startswith("file:///mnt/sd/"):
|
||||||
changed = update_booklist(self._card_a_prefix, path, row[0], row[1], mime, row[2], row[5], row[6], row[7], row[4], row[8], row[9], row[10])
|
changed = update_booklist(self._card_a_prefix, path, row[0], row[1], mime, row[2], row[5], row[6], row[7], row[4], row[8], row[9], row[10])
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
need_sync = True
|
need_sync = True
|
||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# Remove books that are no longer in the filesystem. Cache contains
|
# Remove books that are no longer in the filesystem. Cache contains
|
||||||
# indices into the booklist if book not in filesystem, None otherwise
|
# indices into the booklist if book not in filesystem, None otherwise
|
||||||
@ -292,56 +294,56 @@ class KOBO(USBMS):
|
|||||||
# 2) content
|
# 2) content
|
||||||
|
|
||||||
debug_print('delete_via_sql: ContentID: ', ContentID, 'ContentType: ', ContentType)
|
debug_print('delete_via_sql: ContentID: ', ContentID, 'ContentType: ', ContentType)
|
||||||
connection = sqlite.connect(self.normalize_path(self._main_prefix + '.kobo/KoboReader.sqlite'))
|
with closing(sqlite.connect(self.normalize_path(self._main_prefix +
|
||||||
|
'.kobo/KoboReader.sqlite'))) as connection:
|
||||||
|
|
||||||
# return bytestrings if the content cannot the decoded as unicode
|
# return bytestrings if the content cannot the decoded as unicode
|
||||||
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
t = (ContentID,)
|
t = (ContentID,)
|
||||||
cursor.execute('select ImageID from content where ContentID = ?', t)
|
cursor.execute('select ImageID from content where ContentID = ?', t)
|
||||||
|
|
||||||
ImageID = None
|
ImageID = None
|
||||||
for row in cursor:
|
for row in cursor:
|
||||||
# First get the ImageID to delete the images
|
# First get the ImageID to delete the images
|
||||||
ImageID = row[0]
|
ImageID = row[0]
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
if ContentType == 6 and self.dbversion < 8:
|
if ContentType == 6 and self.dbversion < 8:
|
||||||
# Delete the shortcover_pages first
|
# Delete the shortcover_pages first
|
||||||
cursor.execute('delete from shortcover_page where shortcoverid in (select ContentID from content where BookID = ?)', t)
|
cursor.execute('delete from shortcover_page where shortcoverid in (select ContentID from content where BookID = ?)', t)
|
||||||
|
|
||||||
#Delete the volume_shortcovers second
|
#Delete the volume_shortcovers second
|
||||||
cursor.execute('delete from volume_shortcovers where volumeid = ?', t)
|
cursor.execute('delete from volume_shortcovers where volumeid = ?', t)
|
||||||
|
|
||||||
# Delete the rows from content_keys
|
# Delete the rows from content_keys
|
||||||
if self.dbversion >= 8:
|
if self.dbversion >= 8:
|
||||||
cursor.execute('delete from content_keys where volumeid = ?', t)
|
cursor.execute('delete from content_keys where volumeid = ?', t)
|
||||||
|
|
||||||
# Delete the chapters associated with the book next
|
# Delete the chapters associated with the book next
|
||||||
t = (ContentID,)
|
t = (ContentID,)
|
||||||
# Kobo does not delete the Book row (ie the row where the BookID is Null)
|
# Kobo does not delete the Book row (ie the row where the BookID is Null)
|
||||||
# The next server sync should remove the row
|
# The next server sync should remove the row
|
||||||
cursor.execute('delete from content where BookID = ?', t)
|
cursor.execute('delete from content where BookID = ?', t)
|
||||||
try:
|
try:
|
||||||
cursor.execute('update content set ReadStatus=0, FirstTimeReading = \'true\', ___PercentRead=0, ___ExpirationStatus=3 ' \
|
cursor.execute('update content set ReadStatus=0, FirstTimeReading = \'true\', ___PercentRead=0, ___ExpirationStatus=3 ' \
|
||||||
'where BookID is Null and ContentID =?',t)
|
'where BookID is Null and ContentID =?',t)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if 'no such column' not in str(e):
|
if 'no such column' not in str(e):
|
||||||
raise
|
raise
|
||||||
cursor.execute('update content set ReadStatus=0, FirstTimeReading = \'true\', ___PercentRead=0 ' \
|
cursor.execute('update content set ReadStatus=0, FirstTimeReading = \'true\', ___PercentRead=0 ' \
|
||||||
'where BookID is Null and ContentID =?',t)
|
'where BookID is Null and ContentID =?',t)
|
||||||
|
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
if ImageID == None:
|
if ImageID == None:
|
||||||
print "Error condition ImageID was not found"
|
print "Error condition ImageID was not found"
|
||||||
print "You likely tried to delete a book that the kobo has not yet added to the database"
|
print "You likely tried to delete a book that the kobo has not yet added to the database"
|
||||||
|
|
||||||
connection.close()
|
|
||||||
# If all this succeeds we need to delete the images files via the ImageID
|
# If all this succeeds we need to delete the images files via the ImageID
|
||||||
return ImageID
|
return ImageID
|
||||||
|
|
||||||
@ -668,50 +670,49 @@ class KOBO(USBMS):
|
|||||||
# Needs to be outside books collection as in the case of removing
|
# Needs to be outside books collection as in the case of removing
|
||||||
# the last book from the collection the list of books is empty
|
# the last book from the collection the list of books is empty
|
||||||
# and the removal of the last book would not occur
|
# and the removal of the last book would not occur
|
||||||
connection = sqlite.connect(self.normalize_path(self._main_prefix + '.kobo/KoboReader.sqlite'))
|
with closing(sqlite.connect(self.normalize_path(self._main_prefix +
|
||||||
|
'.kobo/KoboReader.sqlite'))) as connection:
|
||||||
|
|
||||||
# return bytestrings if the content cannot the decoded as unicode
|
# return bytestrings if the content cannot the decoded as unicode
|
||||||
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
connection.text_factory = lambda x: unicode(x, "utf-8", "ignore")
|
||||||
|
|
||||||
if collections:
|
if collections:
|
||||||
|
|
||||||
# Need to reset the collections outside the particular loops
|
# Need to reset the collections outside the particular loops
|
||||||
# otherwise the last item will not be removed
|
# otherwise the last item will not be removed
|
||||||
self.reset_readstatus(connection, oncard)
|
self.reset_readstatus(connection, oncard)
|
||||||
if self.dbversion >= 14:
|
if self.dbversion >= 14:
|
||||||
self.reset_favouritesindex(connection, oncard)
|
self.reset_favouritesindex(connection, oncard)
|
||||||
|
|
||||||
# Process any collections that exist
|
# Process any collections that exist
|
||||||
for category, books in collections.items():
|
for category, books in collections.items():
|
||||||
debug_print("Category: ", category, " id = ", readstatuslist.get(category))
|
debug_print("Category: ", category, " id = ", readstatuslist.get(category))
|
||||||
for book in books:
|
for book in books:
|
||||||
debug_print(' Title:', book.title, 'category: ', category)
|
debug_print(' Title:', book.title, 'category: ', category)
|
||||||
if category not in book.device_collections:
|
if category not in book.device_collections:
|
||||||
book.device_collections.append(category)
|
book.device_collections.append(category)
|
||||||
|
|
||||||
extension = os.path.splitext(book.path)[1]
|
extension = os.path.splitext(book.path)[1]
|
||||||
ContentType = self.get_content_type_from_extension(extension) if extension != '' else self.get_content_type_from_path(book.path)
|
ContentType = self.get_content_type_from_extension(extension) if extension != '' else self.get_content_type_from_path(book.path)
|
||||||
|
|
||||||
ContentID = self.contentid_from_path(book.path, ContentType)
|
ContentID = self.contentid_from_path(book.path, ContentType)
|
||||||
|
|
||||||
if category in readstatuslist.keys():
|
if category in readstatuslist.keys():
|
||||||
# Manage ReadStatus
|
# Manage ReadStatus
|
||||||
self.set_readstatus(connection, ContentID, readstatuslist.get(category))
|
self.set_readstatus(connection, ContentID, readstatuslist.get(category))
|
||||||
elif category == 'Shortlist' and self.dbversion >= 14:
|
elif category == 'Shortlist' and self.dbversion >= 14:
|
||||||
# Manage FavouritesIndex/Shortlist
|
# Manage FavouritesIndex/Shortlist
|
||||||
self.set_favouritesindex(connection, ContentID)
|
self.set_favouritesindex(connection, ContentID)
|
||||||
elif category in accessibilitylist.keys():
|
elif category in accessibilitylist.keys():
|
||||||
# Do not manage the Accessibility List
|
# Do not manage the Accessibility List
|
||||||
pass
|
pass
|
||||||
else: # No collections
|
else: # No collections
|
||||||
# Since no collections exist the ReadStatus needs to be reset to 0 (Unread)
|
# Since no collections exist the ReadStatus needs to be reset to 0 (Unread)
|
||||||
debug_print("No Collections - reseting ReadStatus")
|
debug_print("No Collections - reseting ReadStatus")
|
||||||
self.reset_readstatus(connection, oncard)
|
self.reset_readstatus(connection, oncard)
|
||||||
if self.dbversion >= 14:
|
if self.dbversion >= 14:
|
||||||
debug_print("No Collections - reseting FavouritesIndex")
|
debug_print("No Collections - reseting FavouritesIndex")
|
||||||
self.reset_favouritesindex(connection, oncard)
|
self.reset_favouritesindex(connection, oncard)
|
||||||
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# debug_print('Finished update_device_database_collections', collections_attributes)
|
# debug_print('Finished update_device_database_collections', collections_attributes)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user