From 7e1d8a96e9452893e454288c44377ab5f1b7c0cf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 23 Jun 2016 16:06:50 +0530 Subject: [PATCH] Implement series --- src/calibre/ebooks/metadata/opf3.py | 46 ++++++++++++++++++++++-- src/calibre/ebooks/metadata/opf3_test.py | 17 ++++++++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/metadata/opf3.py b/src/calibre/ebooks/metadata/opf3.py index 108d3215a7..a8a16e74ad 100644 --- a/src/calibre/ebooks/metadata/opf3.py +++ b/src/calibre/ebooks/metadata/opf3.py @@ -621,13 +621,51 @@ def set_rating(root, prefixes, refines, val): remove_element(meta, refines) if val: ensure_prefix(root, prefixes, 'calibre', CALIBRE_PREFIX) - m = XPath('./opf:metadata')(root)[0] - if val: + m = XPath('./opf:metadata')(root)[0] d = m.makeelement(OPF('meta'), attrib={'property':'calibre:rating'}) d.text = '%.2g' % val m.append(d) # }}} +# Series {{{ + +def read_series(root, prefixes, refines): + series_index = 1.0 + for meta in XPath('./opf:metadata/opf:meta[@property="belongs-to-collection" and @id]')(root): + val = (meta.text or '').strip() + if val: + props = properties_for_id(meta.get('id'), refines) + if props.get('collection-type') == 'series': + try: + series_index = float(props.get('group-position').strip()) + except Exception: + pass + return normalize_whitespace(val), series_index + for si in XPath('./opf:metadata/opf:meta[@name="calibre:series_index"]/@content')(root): + try: + series_index = float(si) + break + except: + pass + for s in XPath('./opf:metadata/opf:meta[@name="calibre:series"]/@content')(root): + s = normalize_whitespace(s) + if s: + return s, series_index + return None, series_index + +def set_series(root, prefixes, refines, series, series_index): + for meta in XPath('./opf:metadata/opf:meta[@name="calibre:series" or @name="calibre:series_index"]')(root): + remove_element(meta, refines) + for meta in XPath('./opf:metadata/opf:meta[@property="belongs-to-collection"]')(root): + remove_element(meta, refines) + m = XPath('./opf:metadata')(root)[0] + if series: + d = m.makeelement(OPF('meta'), attrib={'property':'belongs-to-collection'}) + d.text = series + m.append(d) + set_refines(d, refines, refdef('collection-type', 'series'), refdef('group-position', '%.2g' % series_index)) +# }}} + def read_metadata(root): ans = Metadata(_('Unknown'), [_('Unknown')]) prefixes, refines = read_prefixes(root), read_refines(root) @@ -663,6 +701,9 @@ def read_metadata(root): ans.publisher = read_publisher(root, prefixes, refines) or ans.publisher ans.tags = read_tags(root, prefixes, refines) or ans.tags ans.rating = read_rating(root, prefixes, refines) or ans.rating + s, si = read_series(root, prefixes, refines) + if s: + ans.series, ans.series_index = s, si return ans def get_metadata(stream): @@ -685,6 +726,7 @@ def apply_metadata(root, mi, cover_prefix='', cover_data=None, apply_null=False, set_publisher(root, prefixes, refines, mi.publisher) set_tags(root, prefixes, refines, mi.tags) set_rating(root, prefixes, refines, mi.rating) + set_series(root, prefixes, refines, mi.series, mi.series_index) pretty_print_opf(root) diff --git a/src/calibre/ebooks/metadata/opf3_test.py b/src/calibre/ebooks/metadata/opf3_test.py index 7629f7e2fe..a6ef06b8ea 100644 --- a/src/calibre/ebooks/metadata/opf3_test.py +++ b/src/calibre/ebooks/metadata/opf3_test.py @@ -17,7 +17,7 @@ from calibre.ebooks.metadata.opf3 import ( read_book_producers, set_book_producers, read_timestamp, set_timestamp, read_pubdate, set_pubdate, CALIBRE_PREFIX, read_last_modified, read_comments, set_comments, read_publisher, set_publisher, read_tags, set_tags, read_rating, - set_rating + set_rating, read_series, set_series ) TEMPLATE = '''{metadata}''' % CALIBRE_PREFIX # noqa @@ -220,6 +220,21 @@ class TestOPF3(unittest.TestCase): self.ae(1, st(root,1)) # }}} + def test_series(self): # {{{ + def rt(root): + return read_series(root, read_prefixes(root), read_refines(root)) + def st(root, val, i): + set_series(root, read_prefixes(root), read_refines(root), val, i) + return rt(root) + root = self.get_opf('''''') + self.ae(('xxx', 5), rt(root)) + root = self.get_opf('''''' + 'yyyseries' + '2.1') + self.ae(('yyy', 2.1), rt(root)) + self.ae(('zzz', 3.3), st(root, 'zzz', 3.3)) + # }}} + # Run tests {{{ def suite():