Fix sorting for composite cols that are marked as numeric

Incidentally, the implementation of size suffixes in the old db was
broken.
This commit is contained in:
Kovid Goyal 2013-08-25 10:08:29 +05:30
parent 109066baf3
commit 4cf1539c37
2 changed files with 31 additions and 4 deletions

View File

@ -8,6 +8,7 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from locale import atof
from threading import Lock
from collections import defaultdict, Counter
from functools import partial
@ -175,17 +176,35 @@ class OneToOneField(Field):
class CompositeField(OneToOneField):
is_composite = True
SIZE_SUFFIX_MAP = {suffix:i for i, suffix in enumerate(('', 'K', 'M', 'G', 'T', 'P', 'E'))}
def __init__(self, *args, **kwargs):
OneToOneField.__init__(self, *args, **kwargs)
self._render_cache = {}
self._lock = Lock()
self._composite_name = '#' + self.metadata['label']
m = self.metadata
self._composite_name = '#' + m['label']
try:
self.splitter = self.metadata['is_multiple'].get('cache_to_list', None)
self.splitter = m['is_multiple'].get('cache_to_list', None)
except AttributeError:
self.splitter = None
composite_sort = m.get('display', {}).get('composite_sort', None)
if composite_sort == 'number':
self._sort_key = self.number_sort_key
else:
self._sort_key = sort_key
def number_sort_key(self, val):
try:
p = 1
if val and val.endswith('B'):
p = 1 << (10 * self.SIZE_SUFFIX_MAP.get(val[-2:-1], 0))
val = val[:(-2 if p > 1 else -1)].strip()
val = atof(val) * p
except (TypeError, AttributeError, ValueError):
val = 0.0
return val
def render_composite(self, book_id, mi):
with self._lock:
@ -215,7 +234,7 @@ class CompositeField(OneToOneField):
return ans
def sort_keys_for_books(self, get_metadata, lang_map, all_book_ids):
return {id_: sort_key(self.get_value_with_cache(id_, get_metadata)) for id_ in
return {id_: self._sort_key(self.get_value_with_cache(id_, get_metadata)) for id_ in
all_book_ids}
def iter_searchable_values(self, get_metadata, candidates, default_value=None):

View File

@ -558,7 +558,9 @@ class ReadingTest(BaseTest):
def test_composites(self): # {{{
cache = self.init_cache()
cache.create_custom_column('mult', 'CC1', 'composite', True, display={'composite_template': 'b,a,c'})
cache.create_custom_column('single', 'CC1', 'composite', False, display={'composite_template': 'b,a,c'})
cache.create_custom_column('single', 'CC2', 'composite', False, display={'composite_template': 'b,a,c'})
cache.create_custom_column('number', 'CC3', 'composite', False, display={'composite_template': '{#float}', 'composite_sort':'number'})
cache.create_custom_column('size', 'CC4', 'composite', False, display={'composite_template': '{#float:human_readable()}', 'composite_sort':'number'})
cache = self.init_cache()
# Test searching
@ -566,5 +568,11 @@ class ReadingTest(BaseTest):
self.assertEqual(set(), cache.search('#mult:=b,a,c'))
self.assertEqual({1,2,3}, cache.search('#single:=b,a,c'))
self.assertEqual(set(), cache.search('#single:=b'))
# Test numeric sorting
cache.set_field('#float', {1:2, 2:10, 3:0.0001})
self.assertEqual([3, 1, 2], cache.multisort([('#number', True)]))
cache.set_field('#float', {1:3, 2:2*1024, 3:3*1024*1024})
self.assertEqual([1, 2, 3], cache.multisort([('#size', True)]))
# }}}