1) Put the embedded import statements back

2) Fix syncing not to attempt to sync if either column is bad
3) Make independent syncing of the date read work
This commit is contained in:
Charles Haley 2014-03-02 09:33:54 +01:00
parent 130e6d9649
commit 91adef995f

View File

@ -33,7 +33,6 @@ from calibre.ebooks.metadata.book.json_codec import JsonCodec
from calibre.library import current_library_name from calibre.library import current_library_name
from calibre.library.server import server_config as content_server_config from calibre.library.server import server_config as content_server_config
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.utils.date import isoformat, now, parse_date
from calibre.utils.ipc import eintr_retry_call from calibre.utils.ipc import eintr_retry_call
from calibre.utils.config_base import tweaks from calibre.utils.config_base import tweaks
from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to
@ -387,6 +386,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
# copied from USBMS. Perhaps this could be a classmethod in usbms? # copied from USBMS. Perhaps this could be a classmethod in usbms?
def _update_driveinfo_record(self, dinfo, prefix, location_code, name=None): def _update_driveinfo_record(self, dinfo, prefix, location_code, name=None):
from calibre.utils.date import isoformat, now
import uuid import uuid
if not isinstance(dinfo, dict): if not isinstance(dinfo, dict):
dinfo = {} dinfo = {}
@ -692,6 +692,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
return None return None
def _metadata_in_cache(self, uuid, ext_or_lpath, lastmod): def _metadata_in_cache(self, uuid, ext_or_lpath, lastmod):
from calibre.utils.date import now, parse_date
try: try:
key = self._make_metadata_cache_key(uuid, ext_or_lpath) key = self._make_metadata_cache_key(uuid, ext_or_lpath)
if isinstance(lastmod, unicode): if isinstance(lastmod, unicode):
@ -792,6 +793,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
traceback.print_exc() traceback.print_exc()
def _write_metadata_cache(self): def _write_metadata_cache(self):
from calibre.utils.date import now
self._debug() self._debug()
from calibre.utils.config import to_json from calibre.utils.config import to_json
cache_file_name = os.path.join(cache_dir(), cache_file_name = os.path.join(cache_dir(),
@ -829,6 +831,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
return key return key
def _set_known_metadata(self, book, remove=False): def _set_known_metadata(self, book, remove=False):
from calibre.utils.date import now
lpath = book.lpath lpath = book.lpath
ext = os.path.splitext(lpath)[1] ext = os.path.splitext(lpath)[1]
uuid = book.get('uuid', None) uuid = book.get('uuid', None)
@ -958,6 +961,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
@synchronous('sync_lock') @synchronous('sync_lock')
def open(self, connected_device, library_uuid): def open(self, connected_device, library_uuid):
from calibre.utils.date import isoformat, now
self._debug() self._debug()
if not self.is_connected: if not self.is_connected:
# We have been called to retry the connection. Give up immediately # We have been called to retry the connection. Give up immediately
@ -1460,70 +1464,100 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
@synchronous('sync_lock') @synchronous('sync_lock')
def synchronize_with_db(self, db, id_, book): def synchronize_with_db(self, db, id_, book):
from calibre.utils.date import parse_date, UNDEFINED_DATE
def show_message(message): def show_message(message):
self._call_client("DISPLAY_MESSAGE", self._call_client("DISPLAY_MESSAGE",
{'messageKind': self.MESSAGE_SHOW_TOAST, {'messageKind': self.MESSAGE_SHOW_TOAST,
'message': message}) 'message': message})
if not (self.is_read_sync_col or self.is_read_date_sync_col): if self.have_bad_sync_columns or not (self.is_read_sync_col or
# Not syncing self.is_read_date_sync_col):
# Not syncing or sync columns are invalid
return None return None
# Check the validity of the columns once per connection. We do it
# here because we have access to the db to get field_metadata
if not self.have_checked_sync_columns: if not self.have_checked_sync_columns:
# Check the validity of the columns once per connection. We do it
# here because we have access to the db to get field_metadata
fm = db.field_metadata.custom_field_metadata() fm = db.field_metadata.custom_field_metadata()
if self.is_read_sync_col: if self.is_read_sync_col:
if self.is_read_sync_col not in fm: if self.is_read_sync_col not in fm:
self._debug('is_read_sync_col not in field_metadata') self._debug('is_read_sync_col not in field_metadata')
show_message(_("The read sync column %s is " show_message(_("The read sync column %s is "
"not in calibre's library")%self.is_read_sync_col) "not in calibre's library")%self.is_read_sync_col)
self.have_bad_sync_columns = True
elif fm[self.is_read_sync_col]['datatype'] != 'bool': elif fm[self.is_read_sync_col]['datatype'] != 'bool':
self._debug('is_read_sync_col not bool type') self._debug('is_read_sync_col not bool type')
show_message(_("The read sync column %s is " show_message(_("The read sync column %s is "
"not a Yes/No column")%self.is_read_sync_col) "not a Yes/No column")%self.is_read_sync_col)
self.have_bad_sync_columns = True
if self.is_read_date_sync_col: if self.is_read_date_sync_col:
if self.is_read_date_sync_col not in fm: if self.is_read_date_sync_col not in fm:
self._debug('is_read_date_sync_col not in field_metadata') self._debug('is_read_date_sync_col not in field_metadata')
show_message(_("The read date sync column %s is " show_message(_("The read date sync column %s is "
"not in calibre's library")%self.is_read_date_sync_col) "not in calibre's library")%self.is_read_date_sync_col)
self.have_bad_sync_columns = True
elif fm[self.is_read_date_sync_col]['datatype'] != 'datetime': elif fm[self.is_read_date_sync_col]['datatype'] != 'datetime':
self._debug('is_read_date_sync_col not date type') self._debug('is_read_date_sync_col not date type')
show_message(_("The read date sync column %s is " show_message(_("The read date sync column %s is "
"not a Date column")%self.is_read_date_sync_col) "not a Date column")%self.is_read_date_sync_col)
self.have_bad_sync_columns = True
self.have_checked_sync_columns = True self.have_checked_sync_columns = True
if self.have_bad_sync_columns:
return None
is_changed = book.get('_is_read_changed_', None); is_changed = book.get('_is_read_changed_', None);
is_read = book.get('_is_read_', None) is_read = book.get('_is_read_', None)
# This returns UNDEFINED_DATE if the value is None
is_read_date = parse_date(book.get('_last_read_date_', None));
value_to_return = None
if is_changed == 2 and is_read is None: if is_changed == 2:
# This is a special case where the user just set the sync column. In # This is a special case where the user just set the sync column. In
# this case the device value wins if it is not None by falling # this case the device value wins if it is not None by falling
# through to the normal sync situation below, otherwise the calibre # through to the normal sync situation below, otherwise the calibre
# value wins. # value wins. The orig_* values are set to None to force the normal
calibre_val = db.new_api.field_for(self.is_read_sync_col, # sync code to actually sync because the values are different
id_, default_value=None) orig_is_read_date = UNDEFINED_DATE
if calibre_val is not None: orig_is_read = None
# This will force the metadata for the book to be sent . Note if is_read is None:
# that because the devices last_read date is one-way sync, this calibre_val = db.new_api.field_for(self.is_read_sync_col,
# could leave an empty date in the device. id_, default_value=None)
book.set('_force_send_metadata_', True) if calibre_val is not None:
self._debug('special update book', book.get('title', 'huh?'), # This forces the metadata for the book to be sent to the
'to', calibre_val) # device even if the mod dates haven't changed.
return set() book.set('_force_send_metadata_', True)
# Both values are None. Do nothing self._debug('special update is_read', book.get('title', 'huh?'),
return None 'to', calibre_val)
value_to_return = set()
if is_read_date == UNDEFINED_DATE:
calibre_val = db.new_api.field_for(self.is_read_date_sync_col,
id_, default_value=None)
if calibre_val != UNDEFINED_DATE:
book.set('_force_send_metadata_', True)
self._debug('special update is_read_date', book.get('title', 'huh?'),
'to', calibre_val)
value_to_return = set()
# Fall through to the normal sync. At this point either the is_read*
# values are different from the orig_is_read* which will cause a
# sync below, or they are both None which will cause the code below
# to do nothing. If either of the calibre data fields were set, the
# method will return set(), which will force updated metadata to be
# given back to the device, effectively forcing the sync of the
# calibre values back to the device.
else:
orig_is_read = book.get(self.is_read_sync_col, None)
orig_is_read_date = book.get(self.is_read_date_sync_col, None)
changed_books = set() changed_books = set()
try: try:
orig_is_read = book.get(self.is_read_sync_col, None)
if is_read != orig_is_read: if is_read != orig_is_read:
# The value in the device's is_read checkbox is not the same as the # The value in the device's is_read checkbox is not the same as the
# last one that came to the device from calibre during the last # last one that came to the device from calibre during the last
# connect, meaning that the user changed it. Write the one from the # connect, meaning that the user changed it. Write the one from the
# checkbox to calibre's db. # device to calibre's db.
self._debug('standard update book is_read', book.get('title', 'huh?'), self._debug('standard update book is_read', book.get('title', 'huh?'),
'to', is_read) 'to', is_read)
if self.is_read_sync_col: if self.is_read_sync_col:
@ -1534,8 +1568,6 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
traceback.print_exc() traceback.print_exc()
try: try:
is_read_date = parse_date(book.get('_last_read_date_', None));
orig_is_read_date = book.get(self.is_read_date_sync_col, None)
if is_read_date != orig_is_read_date: if is_read_date != orig_is_read_date:
self._debug('standard update book is_read_date', book.get('title', 'huh?'), self._debug('standard update book is_read_date', book.get('title', 'huh?'),
'to', is_read_date) 'to', is_read_date)
@ -1547,6 +1579,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
traceback.print_exc() traceback.print_exc()
if changed_books: if changed_books:
# One of the two values was synced, giving a list of changed books.
# Return that.
return changed_books return changed_books
# The user might have changed the value in calibre. If so, that value # The user might have changed the value in calibre. If so, that value
@ -1554,7 +1588,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
# updated value has already been synced and so will also be sent, the # updated value has already been synced and so will also be sent, the
# device should put the calibre value into its checkbox (or whatever it # device should put the calibre value into its checkbox (or whatever it
# uses) # uses)
return None return value_to_return
@synchronous('sync_lock') @synchronous('sync_lock')
def startup(self): def startup(self):
@ -1582,6 +1616,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self.is_read_sync_col = None self.is_read_sync_col = None
self.is_read_date_sync_col = None self.is_read_date_sync_col = None
self.have_checked_sync_columns = False self.have_checked_sync_columns = False
self.have_bad_sync_columns = False
message = None message = None
compression_quality_ok = True compression_quality_ok = True