Custom User Title
Posts: 11,023
Karma: 75555555
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
|
While I suspect that davidfor would be the only one to know what happened here, can anybody understand the code enough to figure out why this error would occur upon running "update table of contents"? It also resulted in the book glitching out on Kobo and skipping directly to the end.
Details about the book:
- Originally AZW3 downloaded with Kindle for PC, DeDRM'd and converted to ePub.
- Table of contents is nested (1 sublevel)
- Using KoboTouchExtended.
Error:
Code:
calibre, version 6.11.0
ERROR: Unhandled exception: <b>ConstraintError</b>:ConstraintError: UNIQUE constraint failed: content.ContentID
calibre 6.11* embedded-python: True
Windows-10-10.0.19045-SP0 Windows ('64bit', 'WindowsPE')
('Windows', '10', '10.0.19045')
Python 3.10.1
Windows: ('10', '10.0.19045', 'SP0', 'Multiprocessor Free')
Interface language: None
Successfully initialized third party plugins: DeACSM (0, 0, 16) && DeDRM (10, 0, 2) && Action Chains (1, 18, 3) && Baen (1, 1, 0) && Barnes & Noble (1, 4, 0) && Comments Cleaner (1, 8, 0) && Count Pages (1, 12, 0) && Embed Comic Metadata (1, 6, 4) && EpubCheck (0, 2, 4) && EpubMerge (2, 15, 0) && EpubSplit (3, 5, 0) && Extract ISBN (1, 6, 0) && FanFicFare (4, 19, 0) && Fantastic Fiction (1, 6, 0) && Favourites Menu (1, 3, 0) && Find Duplicates (1, 10, 7) && Generate Cover (2, 3, 2) && GetFileName (0, 2, 0) && Goodreads (1, 7, 2) && Import List (1, 9, 0) && Job Spy (1, 0, 197) && Kindle hi-res covers (0, 5, 0) && KindleUnpack - The Plugin (0, 83, 1) && Kobo Books (1, 9, 2) && Kobo Utilities (2, 16, 7) && KoboTouchExtended (3, 6, 3) && Last Modified (0, 8, 4) && Manage Series (1, 5, 0) && Modify ePub (1, 8, 1) && MultiColumnSearch (1, 0, 95) && Obok DeDRM (7, 2, 1) && Open With (1, 8, 1) && Overdrive Link (2, 53, 0) && Quality Check (1, 13, 3) && Reading List (1, 14, 0) && Search The Internet (1, 10, 0) && SmartEject (2, 5, 0) && Standard Ebooks (1, 0, 0) && Sum Column (0, 3, 3) && View Manager (1, 10, 2) && Walk Search History (1, 5, 3) && Overdrive Link Metadata Source (2, 53, 0)
Traceback (most recent call last):
File "calibre_plugins.koboutilities.action", line 5390, in update_book_toc_on_device
File "calibre_plugins.koboutilities.action", line 5818, in update_device_toc_for_books
File "calibre_plugins.koboutilities.action", line 5852, in update_device_toc_for_book
File "calibre_plugins.koboutilities.action", line 6003, in addManifestEntryToDatabase
apsw.ConstraintError: ConstraintError: UNIQUE constraint failed: content.ContentID
Here are the lines in the traceback, all from actions.py:
Spoiler:
5381-5390:
Code:
debug_print("update_book_toc_on_device - update_books=%d" % len(update_books))
# only if there's some good ones.
update_books = list(filter(lambda x : not x['good'], update_books))
debug_print("update_book_toc_on_device - filtered update_books=%d" % len(update_books))
if len(update_books) > 0:
self.options = {}
self.options['version'] = self.version
debug_print("version=%s" % self.version)
self.update_device_toc_for_books( update_books )
5803-5820:
Code:
def update_device_toc_for_books(self, books):
self.gui.status_bar.show_message(_('Updating ToC in device database for {0} books.').format(len(books)), 3000)
debug_print("update_device_toc_for_books - books=", books)
self.progressbar(_("Updating ToC in device database"), on_top=False)
self.set_progressbar_label(_("Number of books to update {0}").format(len(books)))
self.show_progressbar(len(books))
with closing(self.device_database_connection()) as connection:
for book in books:
debug_print("update_device_toc_for_books - book=", book)
debug_print("update_device_toc_for_books - ContentID=", book['ContentID'])
self.increment_progressbar()
if len(book['kobo_chapters']) > 0:
self.remove_all_toc_entries(connection, book['ContentID'])
self.update_device_toc_for_book(connection, book, book['ContentID'], book['title'], book['kobo_format'])
self.hide_progressbar()
5823-6017
Code:
def update_device_toc_for_book(self, connection, book, bookID, bookTitle, book_format='EPUB'):
debug_print("update_device_toc_for_book - bookTitle=%s, len(book['library_chapters'])=%d" % (bookTitle, len(book['library_chapters'])))
num_chapters = len(book['kobo_chapters'])
for i, chapter in enumerate(book['kobo_chapters']):
debug_print("update_device_toc_for_book - chapter=", (chapter))
if book_format == 'KEPUB':
chapterContentId = "{0}!{1}!{2}".format(book['ContentID'], book['kobo_opf_dir'], chapter['path'])
else:
chapterContentId = book['ContentID'] + '#({0})'.format(i) + chapter['path']
debug_print("update_device_toc_for_book - chapterContentId=", chapterContentId)
databaseChapterId = self.getDatabaseChapterId(book['ContentID'], chapter['path'], connection)
has_chapter = not databaseChapterId is None
debug_print("update_device_toc_for_book - has_chapter=", has_chapter)
if has_chapter and chapter['path'].endswith('finish.xhtml') \
and not chapterContentId == databaseChapterId:
debug_print("update_device_toc_for_book - removing SOL finish chapter")
self.removeChapterFromDatabase(databaseChapterId, bookID, connection)
has_chapter = False
if not has_chapter:
self.addChapterToDatabase(chapterContentId, chapter, bookID, bookTitle, i, connection, book_format)
chapter['added'] = True
if book_format == 'KEPUB':
num_chapters = len(book['kobo_manifest'])
file_offset = 0
total_file_size = sum([manifest_entry['file_size'] for manifest_entry in book['kobo_manifest']])
for i, manifest_entry in enumerate(book['kobo_manifest']):
file_size = manifest_entry['file_size'] * 100 / total_file_size
manifest_entry_ContentId = "{0}!{1}!{2}".format(book['ContentID'][len('file://'):], book['kobo_opf_dir'], manifest_entry['path'])
self.addManifestEntryToDatabase(manifest_entry_ContentId, bookID, bookTitle, manifest_entry['path'], i, connection, book_format, file_size=int(file_size), file_offset=int(file_offset))
file_offset += file_size
self.update_database_content_entry(connection, book['ContentID'], num_chapters)
return 0
def getDatabaseChapterId(self, bookId, toc_file, connection):
cursor = connection.cursor()
t = ("{0}%{1}%".format(bookId,toc_file),)
cursor.execute('select ContentID from Content where ContentID like ?', t)
try:
result = next(cursor)
chapterContentId = result['ContentID']
except StopIteration:
chapterContentId = None
debug_print('getDatabaseChapterId - chapterContentId=%s' % chapterContentId)
cursor.close()
return chapterContentId
def removeChapterFromDatabase(self, chapterContentId, bookID, connection):
cursor = connection.cursor()
t = (chapterContentId,)
cursor.execute('delete from Content where ContentID = ?', t)
t = (bookID, chapterContentId,)
cursor.execute('delete from volume_shortcovers where volumeId = ? and shortcoverId = ?', t)
cursor.close()
return
def update_database_content_entry(self, connection, contentId, num_chapters):
cursor = connection.cursor()
t = (contentId, num_chapters)
cursor.execute('UPDATE content SET NumShortcovers = ? where ContentID = ?', t)
cursor.close()
return
def remove_all_toc_entries(self, connection, contentId):
debug_print("remove_all_toc_entries - contentId=", contentId)
cursor = connection.cursor()
t = (contentId,)
cursor.execute('DELETE FROM Content WHERE BookID = ?', t)
cursor.execute('DELETE FROM volume_shortcovers WHERE volumeId = ?', t)
cursor.close()
return
def addChapterToDatabase(self, chapterContentId, chapter, bookID, bookTitle, volumeIndex, connection, book_format='EPUB'):
cursorContent = connection.cursor()
insertContentQuery = 'INSERT INTO content '\
'(ContentID, ContentType, MimeType, BookID, BookTitle, Title, Attribution, adobe_location'\
', IsEncrypted, FirstTimeReading, ParagraphBookmarked, BookmarkWordOffset, VolumeIndex, ___NumPages'\
', ReadStatus, ___UserID, ___FileOffset, ___FileSize, ___PercentRead'\
', Depth, ChapterIDBookmarked'\
') VALUES ('\
"?, ?, ?, ?, ?, ?, null, ?"\
", 'false', 'true', 0, 0, ?, -1"\
", 0, ?, 0, 0, 0"\
", ?, ?" \
')'
if book_format == 'KEPUB':
mime_type = 'application/x-kobo-epub+zip'
content_type = 899
content_userid = ''
adobe_location = None
matches = re.match(r'(?:file://)?((.*?)(?:\#.*)?(?:-\d+))$', chapterContentId)
debug_print("addChapterToDatabase - regex matches=", matches.groups())
chapterContentId = chapterContentId[len('file://'):]
chapterContentId = matches.group(1)
fragment_start = chapterContentId.rfind("#")
chapter_id_bookmarked = chapterContentId if fragment_start < 0 else chapterContentId[:fragment_start]
chapter_id_bookmarked = matches.group(2)
# chapterContentId = "{0}-{1}".format(chapterContentId, chapter['toc_depth'])
else:
mime_type = 'application/epub+zip'
content_type = 9
content_userid = 'adobe_user'
chapter_id_bookmarked = None
if 'chapter_location' in chapter:
adobe_location = chapter['chapter_location']
else:
adobe_location = chapter['path']
insertContentData = (
chapterContentId,
content_type,
mime_type,
bookID,
bookTitle,
chapter['title'],
adobe_location,
volumeIndex,
content_userid,
chapter['toc_depth'],
chapter_id_bookmarked
)
debug_print("addChapterToDatabase - insertContentData=", insertContentData)
cursorContent.execute(insertContentQuery, insertContentData)
cursorContent.close()
if book_format == 'EPUB':
cursorShortCover = connection.cursor()
insertShortCoverQuery = 'INSERT INTO volume_shortcovers (volumeId, shortcoverId, VolumeIndex) VALUES (?,?,?)'
insertShortCoverData = (bookID, chapterContentId, volumeIndex, )
debug_print("addChapterToDatabase - insertShortCoverData=", insertShortCoverData)
cursorShortCover.execute(insertShortCoverQuery, insertShortCoverData)
cursorShortCover.close()
def addManifestEntryToDatabase(self, manifest_entry, bookID, bookTitle, title, volumeIndex, connection,
book_format='EPUB', file_size=None, file_offset=None):
cursorContent = connection.cursor()
insertContentQuery = 'INSERT INTO content '\
'(ContentID, ContentType, MimeType, BookID, BookTitle, Title, Attribution, adobe_location'\
', IsEncrypted, FirstTimeReading, ParagraphBookmarked, BookmarkWordOffset, VolumeIndex, ___NumPages'\
', ReadStatus, ___UserID, ___FileOffset, ___FileSize, ___PercentRead'\
', Depth, ChapterIDBookmarked'\
') VALUES ('\
"?, ?, ?, ?, ?, ?, null, ?"\
", 'false', 'true', 0, 0, ?, -1"\
", 0, ?, ?, ?, 0"\
", ?, ?" \
')'
mime_type = 'application/xhtml+xml'
content_type = 9
content_userid = ''
adobe_location = None
insertContentData = (
manifest_entry,
content_type,
mime_type,
bookID,
bookTitle,
title,
adobe_location,
volumeIndex,
content_userid,
file_offset,
file_size,
0,
None
)
debug_print("addManifestEntryToDatabase - insertContentData=", insertContentData)
cursorContent.execute(insertContentQuery, insertContentData)
cursorShortCover = connection.cursor()
insertShortCoverQuery = 'INSERT INTO volume_shortcovers (volumeId, shortcoverId, VolumeIndex) VALUES (?,?,?)'
insertShortCoverData = (bookID, manifest_entry, volumeIndex, )
debug_print("addManifestEntryToDatabase - insertShortCoverData=", insertShortCoverData)
cursorShortCover.execute(insertShortCoverQuery, insertShortCoverData)
cursorContent.close()
cursorShortCover.close()
'''
End ToC Updating
'''
|