Merge branch 'device-kobo-improvements' of https://github.com/kyxap/calibre

This commit is contained in:
Kovid Goyal 2024-06-23 21:00:21 +05:30
commit aa4c720c48
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 71 additions and 25 deletions

View File

@ -24,11 +24,37 @@ from polyglot.builtins import itervalues, string_or_bytes
def debug_print(*args, **kw): def debug_print(*args, **kw):
'''
Prints debug information to the console if debugging is enabled.
This function prints a message prefixed with a timestamp showing the elapsed time
since the first call to this function. The message is printed only if debugging is enabled.
Parameters:
*args : tuple
Variable length argument list to be printed.
**kw : dict
Arbitrary keyword arguments to be passed to the `print` function.
Attributes:
base_time : float
The timestamp of the first call to this function. Stored as an attribute of the function.
Behavior:
- On the first call, initializes `base_time` to the current time using `time.monotonic()`.
- If `is_debugging()` returns True, prints the elapsed time since `base_time` along with the provided arguments.
'''
# Get the base_time attribute, initializing it on the first call
base_time = getattr(debug_print, 'base_time', None) base_time = getattr(debug_print, 'base_time', None)
if base_time is None: if base_time is None:
# Set base_time to the current monotonic time if it hasn't been set
debug_print.base_time = base_time = time.monotonic() debug_print.base_time = base_time = time.monotonic()
# Check if debugging is enabled
if is_debugging(): if is_debugging():
prints('DEBUG: %6.1f'%(time.monotonic()-base_time), *args, **kw) # Print the elapsed time and the provided arguments if debugging is enabled
prints('DEBUG: %6.1f' % (time.monotonic() - base_time), *args, **kw)
def safe_walk(top, topdown=True, onerror=None, followlinks=False, maxdepth=128): def safe_walk(top, topdown=True, onerror=None, followlinks=False, maxdepth=128):

View File

@ -30,6 +30,7 @@ from calibre.devices.errors import (
from calibre.devices.folder_device.driver import FOLDER_DEVICE from calibre.devices.folder_device.driver import FOLDER_DEVICE
from calibre.devices.interface import DevicePlugin, currently_connected_device from calibre.devices.interface import DevicePlugin, currently_connected_device
from calibre.devices.scanner import DeviceScanner from calibre.devices.scanner import DeviceScanner
from calibre.devices.usbms.driver import debug_print
from calibre.ebooks.covers import cprefs, generate_cover, override_prefs, scale_cover from calibre.ebooks.covers import cprefs, generate_cover, override_prefs, scale_cover
from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata import authors_to_string
from calibre.gui2 import ( from calibre.gui2 import (
@ -1215,12 +1216,10 @@ class DeviceMixin: # {{{
self.device_manager.slow_driveinfo() self.device_manager.slow_driveinfo()
# set_books_in_library might schedule a sync_booklists job # set_books_in_library might schedule a sync_booklists job
if DEBUG: debug_print('DeviceJob: metadata_downloaded: Starting set_books_in_library')
prints('DeviceJob: metadata_downloaded: Starting set_books_in_library')
self.set_books_in_library(job.result, reset=True, add_as_step_to_job=job) self.set_books_in_library(job.result, reset=True, add_as_step_to_job=job)
if DEBUG: debug_print('DeviceJob: metadata_downloaded: updating views')
prints('DeviceJob: metadata_downloaded: updating views')
mainlist, cardalist, cardblist = job.result mainlist, cardalist, cardblist = job.result
self.memory_view.set_database(mainlist) self.memory_view.set_database(mainlist)
self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA, self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA,
@ -1234,17 +1233,14 @@ class DeviceMixin: # {{{
self.card_b_view.set_editable(self.device_manager.device.CAN_SET_METADATA, self.card_b_view.set_editable(self.device_manager.device.CAN_SET_METADATA,
self.device_manager.device.BACKLOADING_ERROR_MESSAGE self.device_manager.device.BACKLOADING_ERROR_MESSAGE
is None) is None)
if DEBUG: debug_print('DeviceJob: metadata_downloaded: syncing')
prints('DeviceJob: metadata_downloaded: syncing')
self.sync_news() self.sync_news()
self.sync_catalogs() self.sync_catalogs()
if DEBUG: debug_print('DeviceJob: metadata_downloaded: refreshing ondevice')
prints('DeviceJob: metadata_downloaded: refreshing ondevice')
self.refresh_ondevice() self.refresh_ondevice()
if DEBUG: debug_print('DeviceJob: metadata_downloaded: sending metadata_available signal')
prints('DeviceJob: metadata_downloaded: sending metadata_available signal')
device_signals.device_metadata_available.emit() device_signals.device_metadata_available.emit()
def refresh_ondevice(self, reset_only=False): def refresh_ondevice(self, reset_only=False):
@ -1851,13 +1847,16 @@ class DeviceMixin: # {{{
except: except:
return False return False
# Define the cleaning function
string_pat = re.compile(r'(?u)\W|[_]') string_pat = re.compile(r'(?u)\W|[_]')
def clean_string(x): def clean_string(x):
try: try:
# Convert to lowercase if x is not None or empty
x = x.lower() if x else '' x = x.lower() if x else ''
except Exception: except Exception:
x = '' x = ''
# Perform regex substitution
return string_pat.sub('', x) return string_pat.sub('', x)
update_metadata = ( update_metadata = (
@ -1909,6 +1908,23 @@ class DeviceMixin: # {{{
if get_covers and desired_thumbnail_height != 0: if get_covers and desired_thumbnail_height != 0:
self.update_thumbnail(book) self.update_thumbnail(book)
def extract_id_from_dict(author_to_look_for, target_dict):
'''
Extracts id from dict with full match by author or partial match for cases when
book has multiple authors.
'''
debug_print('Trying to extract id for author:', author_to_look_for, ' in:', target_dict)
if author_to_look_for in target_dict:
return target_dict[book_authors]
else:
# for cases when multiple authors like: Author A & Author B => 'authoraauthorb' need to match 'authorb'
for author in target_dict:
if author_to_look_for in author:
return target_dict[author]
debug_print('Id is not extracted!')
return None
def updateq(id_, book): def updateq(id_, book):
try: try:
if not update_metadata: if not update_metadata:
@ -1948,8 +1964,7 @@ class DeviceMixin: # {{{
for book in booklist: for book in booklist:
if book: if book:
total_book_count += 1 total_book_count += 1
if DEBUG: debug_print('DeviceJob: set_books_in_library: books to process=', total_book_count)
prints('DeviceJob: set_books_in_library: books to process=', total_book_count)
start_time = time.time() start_time = time.time()
@ -2010,16 +2025,23 @@ class DeviceMixin: # {{{
# Compare against both author and author sort, because # Compare against both author and author sort, because
# either can appear as the author # either can appear as the author
book_authors = clean_string(authors_to_string(book.authors)) book_authors = clean_string(authors_to_string(book.authors))
if book_authors in d['authors']: extracted_id = None
id_ = d['authors'][book_authors] authors_id = extract_id_from_dict(book_authors, d['authors'])
update_book(id_, book) if authors_id is not None:
extracted_id = authors_id
book.in_library = 'AUTHOR' book.in_library = 'AUTHOR'
book.application_id = id_ else:
elif book_authors in d['author_sort']: author_sort_id = extract_id_from_dict(book_authors, d['author_sort'])
id_ = d['author_sort'][book_authors] if author_sort_id is not None:
update_book(id_, book) extracted_id = author_sort_id
book.in_library = 'AUTH_SORT' book.in_library = 'AUTH_SORT'
book.application_id = id_
update_book(extracted_id, book)
book.application_id = extracted_id
if extracted_id is None:
debug_print('No author match for a book:\n', book)
else: else:
# Book definitely not matched. Clear its application ID # Book definitely not matched. Clear its application ID
book.application_id = None book.application_id = None
@ -2089,9 +2111,7 @@ class DeviceMixin: # {{{
except: except:
traceback.print_exc() traceback.print_exc()
if DEBUG: debug_print('DeviceJob: set_books_in_library finished: time=', time.time() - start_time)
prints('DeviceJob: set_books_in_library finished: time=',
time.time() - start_time)
# The status line is reset when the job finishes # The status line is reset when the job finishes
return update_metadata return update_metadata
# }}} # }}}