newdb: Fix tweak to sort dates by visible fields not being respected

This commit is contained in:
Kovid Goyal 2013-08-24 16:38:57 +05:30
parent 7287ca8f59
commit d056f8fed7
4 changed files with 36 additions and 7 deletions

View File

@ -10,13 +10,14 @@ __docformat__ = 'restructuredtext en'
from threading import Lock
from collections import defaultdict, Counter
from functools import partial
from calibre.db.tables import ONE_ONE, MANY_ONE, MANY_MANY, null
from calibre.db.write import Writer
from calibre.ebooks.metadata import title_sort, author_to_author_sort
from calibre.utils.config_base import tweaks
from calibre.utils.icu import sort_key
from calibre.utils.date import UNDEFINED_DATE
from calibre.utils.date import UNDEFINED_DATE, clean_date_for_sort
from calibre.utils.localization import calibre_langcode_to_name
class Field(object):
@ -44,6 +45,14 @@ class Field(object):
self._default_sort_key = None
elif dt == 'datetime':
self._default_sort_key = UNDEFINED_DATE
if tweaks['sort_dates_using_visible_fields']:
fmt = None
if name in {'timestamp', 'pubdate', 'last_modified'}:
fmt = tweaks['gui_%s_display_format' % name]
elif self.metadata['is_custom']:
fmt = self.metadata.get('display', {}).get('date_format', None)
self._sort_key = partial(clean_date_for_sort, fmt=fmt)
if self.name == 'languages':
self._sort_key = lambda x:sort_key(calibre_langcode_to_name(x))
self.is_multiple = (bool(self.metadata['is_multiple']) or self.name ==

View File

@ -180,6 +180,15 @@ class ReadingTest(BaseTest):
self.assertEqual([1, 3, 2], cache.multisort([(field, True)], ids_to_sort=(1, 2, 3)))
self.assertEqual([2, 3, 1], cache.multisort([(field, False)], ids_to_sort=(1, 2, 3)))
# Test tweak to sort dates by visible format
from calibre.utils.date import parse_only_date as p
from calibre.utils.config_base import Tweak
self.assertEqual(cache.set_field('pubdate', {1:p('2001-3-3'), 2:p('2002-2-3'), 3:p('2003-1-3')}), {1, 2, 3})
self.assertEqual([1, 2, 3], cache.multisort([('pubdate', True)]))
with Tweak('gui_pubdate_display_format', 'MMM'), Tweak('sort_dates_using_visible_fields', True):
c2 = self.init_cache()
self.assertEqual([3, 2, 1], c2.multisort([('pubdate', True)]))
# }}}
def test_get_metadata(self): # {{{

View File

@ -478,3 +478,14 @@ def reset_tweaks_to_default():
exec default_tweaks in dg, dl
tweaks = dl
class Tweak(object):
def __init__(self, name, value):
self.name, self.value = name, value
def __enter__(self):
self.origval = tweaks[self.name]
tweaks[self.name] = self.value
def __exit__(self, *args):
tweaks[self.name] = self.origval

View File

@ -357,10 +357,10 @@ def cd_repl_func(tt, dt, match_object):
return ''
return cd_function_index[s[0]](tt, dt)
def clean_date_for_sort(dt, format):
def clean_date_for_sort(dt, fmt=None):
''' Return dt with fields not in shown in format set to a default '''
if not format:
format = 'yyMd'
if not fmt:
fmt = 'yyMd'
if not isinstance(dt, datetime):
dt = datetime.combine(dt, dtime())
@ -370,15 +370,15 @@ def clean_date_for_sort(dt, format):
dt = dt.replace(tzinfo=_local_tz)
dt = as_local_time(dt)
if format == 'iso':
format = 'yyMdhms'
if fmt == 'iso':
fmt = 'yyMdhms'
tt = {'year':UNDEFINED_DATE.year, 'mon':UNDEFINED_DATE.month,
'day':UNDEFINED_DATE.day, 'hour':UNDEFINED_DATE.hour,
'min':UNDEFINED_DATE.minute, 'sec':UNDEFINED_DATE.second}
repl_func = partial(cd_repl_func, tt, dt)
re.sub('(s{1,2})|(m{1,2})|(h{1,2})|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, format)
re.sub('(s{1,2})|(m{1,2})|(h{1,2})|(d{1,4}|M{1,4}|(?:yyyy|yy))', repl_func, fmt)
return dt.replace(year=tt['year'], month=tt['mon'], day=tt['day'], hour=tt['hour'],
minute=tt['min'], second=tt['sec'], microsecond=0)