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
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)
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)
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
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