Beispiel #1
0
 def set_custom(self, book_id, val, label=None, num=None, append=False,
                notify=True, extra=None, commit=True, allow_case_change=False):
     field = self.custom_field_name(label, num)
     data = self.backend.custom_field_metadata(label, num)
     if data['datatype'] == 'composite':
         return set()
     if not data['editable']:
         raise ValueError('Column %r is not editable'%data['label'])
     if data['datatype'] == 'enumeration' and (
             val and val not in data['display']['enum_values']):
         return set()
     with self.new_api.write_lock:
         if append and data['is_multiple']:
             current = self.new_api._field_for(field, book_id)
             existing = {icu_lower(x) for x in current}
             val = current + tuple(x for x in self.new_api.fields[field].writer.adapter(val) if icu_lower(x) not in existing)
             affected_books = self.new_api._set_field(field, {book_id:val}, allow_case_change=allow_case_change)
         else:
             affected_books = self.new_api._set_field(field, {book_id:val}, allow_case_change=allow_case_change)
         if data['datatype'] == 'series':
             s, sidx = get_series_values(val)
             if sidx is None:
                 extra = 1.0 if extra is None else extra
                 self.new_api._set_field(field + '_index', {book_id:extra})
     if notify and affected_books:
         self.notify('metadata', list(affected_books))
     return affected_books
Beispiel #2
0
def convert_markdown_with_metadata(txt, title='', extensions=DEFAULT_MD_EXTENSIONS):
    from calibre.ebooks.metadata.book.base import Metadata
    from calibre.utils.date import parse_only_date
    from calibre.db.write import get_series_values
    if 'meta' not in extensions:
        extensions.append('meta')
    md = create_markdown_object(extensions)
    html = md.convert(txt)
    mi = Metadata(title or _('Unknown'))
    m = md.Meta
    for k, v in {'date':'pubdate', 'summary':'comments'}.iteritems():
        if v not in m and k in m:
            m[v] = m.pop(k)
    for k in 'title authors series tags pubdate comments publisher rating'.split():
        val = m.get(k)
        if val:
            mf = mi.metadata_for_field(k)
            if not mf.get('is_multiple'):
                val = val[0]
            if k == 'series':
                val, si = get_series_values(val)
                mi.series_index = 1 if si is None else si
            if k == 'rating':
                try:
                    val = max(0, min(int(float(val)), 10))
                except Exception:
                    continue
            if mf.get('datatype') == 'datetime':
                try:
                    val = parse_only_date(val, assume_utc=False)
                except Exception:
                    continue
            setattr(mi, k, val)
    return mi, HTML_TEMPLATE % (mi.title, html)
Beispiel #3
0
def convert_markdown_with_metadata(txt, title='', extensions=DEFAULT_MD_EXTENSIONS):
    from calibre.ebooks.metadata.book.base import Metadata
    from calibre.utils.date import parse_only_date
    from calibre.db.write import get_series_values
    if 'meta' not in extensions:
        extensions.append('meta')
    md = create_markdown_object(extensions)
    html = md.convert(txt)
    mi = Metadata(title or _('Unknown'))
    m = md.Meta
    for k, v in iteritems({'date':'pubdate', 'summary':'comments'}):
        if v not in m and k in m:
            m[v] = m.pop(k)
    for k in 'title authors series tags pubdate comments publisher rating'.split():
        val = m.get(k)
        if val:
            mf = mi.metadata_for_field(k)
            if not mf.get('is_multiple'):
                val = val[0]
            if k == 'series':
                val, si = get_series_values(val)
                mi.series_index = 1 if si is None else si
            if k == 'rating':
                try:
                    val = max(0, min(int(float(val)), 10))
                except Exception:
                    continue
            if mf.get('datatype') == 'datetime':
                try:
                    val = parse_only_date(val, assume_utc=False)
                except Exception:
                    continue
            setattr(mi, k, val)
    return mi, HTML_TEMPLATE % (mi.title, html)
Beispiel #4
0
 def set_custom(self, book_id, val, label=None, num=None, append=False,
                notify=True, extra=None, commit=True, allow_case_change=False):
     field = self.custom_field_name(label, num)
     data = self.backend.custom_field_metadata(label, num)
     if data['datatype'] == 'composite':
         return set()
     if not data['editable']:
         raise ValueError('Column %r is not editable'%data['label'])
     if data['datatype'] == 'enumeration' and (
             val and val not in data['display']['enum_values']):
         return set()
     with self.new_api.write_lock:
         if append and data['is_multiple']:
             current = self.new_api._field_for(field, book_id)
             existing = {icu_lower(x) for x in current}
             val = current + tuple(x for x in self.new_api.fields[field].writer.adapter(val) if icu_lower(x) not in existing)
             affected_books = self.new_api._set_field(field, {book_id:val}, allow_case_change=allow_case_change)
         else:
             affected_books = self.new_api._set_field(field, {book_id:val}, allow_case_change=allow_case_change)
         if data['datatype'] == 'series':
             s, sidx = get_series_values(val)
             if sidx is None:
                 extra = 1.0 if extra is None else extra
                 self.new_api._set_field(field + '_index', {book_id:extra})
     if notify and affected_books:
         self.notify('metadata', list(affected_books))
     return affected_books
Beispiel #5
0
    def set_field(self,
                  name,
                  book_id_to_val_map,
                  allow_case_change=True,
                  do_path_update=True):
        f = self.fields[name]
        is_series = f.metadata['datatype'] == 'series'
        update_path = name in {'title', 'authors'}
        if update_path and iswindows:
            paths = (x for x in (self._field_for('path', book_id)
                                 for book_id in book_id_to_val_map) if x)
            self.backend.windows_check_if_files_in_use(paths)

        if is_series:
            bimap, simap = {}, {}
            for k, v in book_id_to_val_map.iteritems():
                if isinstance(v, basestring):
                    v, sid = get_series_values(v)
                else:
                    v = sid = None
                if name.startswith('#') and sid is None:
                    sid = 1.0  # The value will be set to 1.0 in the db table
                bimap[k] = v
                if sid is not None:
                    simap[k] = sid
            book_id_to_val_map = bimap

        dirtied = f.writer.set_books(book_id_to_val_map,
                                     self.backend,
                                     allow_case_change=allow_case_change)

        if is_series and simap:
            sf = self.fields[f.name + '_index']
            dirtied |= sf.writer.set_books(simap,
                                           self.backend,
                                           allow_case_change=False)

        if dirtied and self.composites:
            for name in self.composites:
                self.fields[name].pop_cache(dirtied)

        if dirtied and update_path and do_path_update:
            self._update_path(dirtied, mark_as_dirtied=False)

        self._mark_as_dirty(dirtied)

        return dirtied
Beispiel #6
0
    def set_field(self, name, book_id_to_val_map, allow_case_change=True, do_path_update=True):
        f = self.fields[name]
        is_series = f.metadata['datatype'] == 'series'
        update_path = name in {'title', 'authors'}
        if update_path and iswindows:
            paths = (x for x in (self._field_for('path', book_id) for book_id in book_id_to_val_map) if x)
            self.backend.windows_check_if_files_in_use(paths)

        if is_series:
            bimap, simap = {}, {}
            for k, v in book_id_to_val_map.iteritems():
                if isinstance(v, basestring):
                    v, sid = get_series_values(v)
                else:
                    v = sid = None
                if name.startswith('#') and sid is None:
                    sid = 1.0  # The value will be set to 1.0 in the db table
                bimap[k] = v
                if sid is not None:
                    simap[k] = sid
            book_id_to_val_map = bimap

        dirtied = f.writer.set_books(
            book_id_to_val_map, self.backend, allow_case_change=allow_case_change)

        if is_series and simap:
            sf = self.fields[f.name+'_index']
            dirtied |= sf.writer.set_books(simap, self.backend, allow_case_change=False)

        if dirtied and self.composites:
            for name in self.composites:
                self.fields[name].pop_cache(dirtied)

        if dirtied and update_path and do_path_update:
            self._update_path(dirtied, mark_as_dirtied=False)

        self._mark_as_dirty(dirtied)

        return dirtied