Support for writing identifiers

This commit is contained in:
Kovid Goyal 2013-03-26 10:43:51 +05:30
parent 0335a44424
commit 96d71be87d
2 changed files with 54 additions and 1 deletions

View File

@ -266,7 +266,16 @@ class WritingTest(BaseTest):
ae(sf('languages', {3:None}), set([3])) ae(sf('languages', {3:None}), set([3]))
ae(cache.field_for('languages', 3), ()) ae(cache.field_for('languages', 3), ())
# TODO: identifiers # Identifiers
f = cache.fields['identifiers']
ae(sf('identifiers', {3: 'one:1,two:2'}), set([3]))
ae(sf('identifiers', {2:None}), set([2]))
ae(sf('identifiers', {1: {'test':'1', 'two':'2'}}), set([1]))
cache2 = self.init_cache(cl)
for c in (cache, cache2):
ae(c.field_for('identifiers', 3), {'one':'1', 'two':'2'})
ae(c.field_for('identifiers', 2), {})
ae(c.field_for('identifiers', 1), {'test':'1', 'two':'2'})
# }}} # }}}

View File

@ -106,6 +106,21 @@ def adapt_languages(to_tuple, x):
ans.append(lc) ans.append(lc)
return tuple(ans) return tuple(ans)
def clean_identifier(typ, val):
typ = icu_lower(typ).strip().replace(':', '').replace(',', '')
val = val.strip().replace(',', '|').replace(':', '|')
return typ, val
def adapt_identifiers(to_tuple, x):
if not isinstance(x, dict):
x = {k:v for k, v in (y.partition(':')[0::2] for y in to_tuple(x))}
ans = {}
for k, v in x.iteritems():
k, v = clean_identifier(k, v)
if k and v:
ans[k] = v
return ans
def get_adapter(name, metadata): def get_adapter(name, metadata):
dt = metadata['datatype'] dt = metadata['datatype']
if dt == 'text': if dt == 'text':
@ -145,6 +160,8 @@ def get_adapter(name, metadata):
return lambda x: 1.0 if ans(x) is None else ans(x) return lambda x: 1.0 if ans(x) is None else ans(x)
if name == 'languages': if name == 'languages':
return partial(adapt_languages, ans) return partial(adapt_languages, ans)
if name == 'identifiers':
return partial(adapt_identifiers, ans)
return ans return ans
# }}} # }}}
@ -396,6 +413,31 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args):
# }}} # }}}
def identifiers(book_id_val_map, db, field, *args): # {{{
table = field.table
updates = set()
for book_id, identifiers in book_id_val_map.iteritems():
if book_id not in table.book_col_map:
table.book_col_map[book_id] = {}
current_ids = table.book_col_map[book_id]
remove_keys = set(current_ids) - set(identifiers)
for key in remove_keys:
table.col_book_map.get(key, set()).discard(book_id)
current_ids.pop(key, None)
current_ids.update(identifiers)
for key, val in identifiers.iteritems():
if key not in table.col_book_map:
table.col_book_map[key] = set()
table.col_book_map[key].add(book_id)
updates.add((book_id, key, val))
db.conn.executemany('DELETE FROM identifiers WHERE book=?',
((x,) for x in book_id_val_map))
if updates:
db.conn.executemany('INSERT OR REPLACE INTO identifiers (book, type, val) VALUES (?, ?, ?)',
tuple(updates))
return set(book_id_val_map)
# }}}
def dummy(book_id_val_map, *args): def dummy(book_id_val_map, *args):
return set() return set()
@ -412,6 +454,8 @@ class Writer(object):
self.set_books_func = dummy self.set_books_func = dummy
elif self.name[0] == '#' and self.name.endswith('_index'): elif self.name[0] == '#' and self.name.endswith('_index'):
self.set_books_func = custom_series_index self.set_books_func = custom_series_index
elif self.name == 'identifiers':
self.set_books_func = identifiers
elif field.is_many_many: elif field.is_many_many:
self.set_books_func = many_many self.set_books_func = many_many
elif field.is_many: elif field.is_many: