From d341d81cf8488ffe5f9bf3b6e786285fdeaa91aa Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 21 May 2010 20:23:48 -0600 Subject: [PATCH] Disallow custom column names --- src/calibre/ebooks/metadata/book/__init__.py | 110 ++++++++++++++++++ src/calibre/ebooks/metadata/fetch.py | 3 +- src/calibre/ebooks/metadata/odt.py | 0 .../dialogs/config/create_custom_column.py | 3 + 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/calibre/ebooks/metadata/book/__init__.py mode change 100755 => 100644 src/calibre/ebooks/metadata/odt.py diff --git a/src/calibre/ebooks/metadata/book/__init__.py b/src/calibre/ebooks/metadata/book/__init__.py new file mode 100644 index 0000000000..76fe736f9c --- /dev/null +++ b/src/calibre/ebooks/metadata/book/__init__.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai + +__license__ = 'GPL v3' +__copyright__ = '2010, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +''' +All fields must have a NULL value represented as None +''' + +SOCIAL_METADATA_FIELDS = frozenset([ + 'tags', # Ordered list + # A floating point number between 0 and 10 + 'rating', + # A simple HTML enabled string + 'comments', + # A simple string + 'series', + # A floating point number + 'series_index', + # Of the form { scheme1:value1, scheme2:value2} + # For example: {'isbn':'123456789', 'doi':'xxxx', ... } + 'classifiers', + 'isbn', # Pseudo field for convenience, should get/set isbn classifier + +]) + +PUBLICATION_METADATA_FIELDS = frozenset([ + # title must never be None. Should be _('Unknown') + 'title', + # Pseudo field that can be set, but if not set is auto generated + # from title and languages + 'title_sort', + # Ordered list of authors. Must never be None, can be [_('Unknown')] + 'authors', + # Pseudo field that can be set, but if not set is auto generated + # from authors and languages + 'author_sort', + 'book_producer', + # Dates and times must be timezone aware + 'timestamp', + 'pubdate', + 'rights', + # So far only known publication type is periodical:calibre + # If None, means book + 'publication_type', + # A UUID usually of type 4 + 'uuid', + 'languages', # ordered list + # Simple string, no special semantics + 'publisher', + # Absolute path to image file encoded in filesystem_encoding + 'cover', + # Of the form (format, data) where format is, for e.g. 'jpeg', 'png', 'gif'... + 'cover_data', + # Either thumbnail data, or an object with the attribute + # image_path which is the path to an image file, encoded + # in filesystem_encoding + 'thumbnail', + ]) + +BOOK_STRUCTURE_FIELDS = frozenset([ + # These are used by code + 'toc', 'spine', 'guide', 'manifest', + ]) + +USER_METADATA_FIELDS = frozenset([ + # A dict of a form to be specified + 'user_metadata', +]) + +DEVICE_METADATA_FIELDS = frozenset([ + # Ordered list of strings + 'device_collections', + 'lpath', # Unicode, / separated + # In bytes + 'size', + # Mimetype of the book file being represented + 'mime', +]) + +CALIBRE_METADATA_FIELDS = frozenset([ + # An application id + # Semantics to be defined. Is it a db key? a db name + key? A uuid? + 'application_id', + ] +) + +RESERVED_METADATA_FIELDS = SOCIAL_METADATA_FIELDS.union( + PUBLICATION_METADATA_FIELDS).union( + BOOK_STRUCTURE_FIELDS).union( + USER_METADATA_FIELDS).union( + DEVICE_METADATA_FIELDS).union( + CALIBRE_METADATA_FIELDS) + +assert len(RESERVED_METADATA_FIELDS) == sum(map(len, ( + SOCIAL_METADATA_FIELDS, PUBLICATION_METADATA_FIELDS, + BOOK_STRUCTURE_FIELDS, USER_METADATA_FIELDS, + DEVICE_METADATA_FIELDS, CALIBRE_METADATA_FIELDS, + ))) + +SERIALIZABLE_FIELDS = SOCIAL_METADATA_FIELDS.union( + USER_METADATA_FIELDS).union( + PUBLICATION_METADATA_FIELDS).union( + CALIBRE_METADATA_FIELDS).union( + frozenset(['lpath'])) # I don't think we need device_collections + +# Serialization of covers/thumbnails will have to be handled carefully, maybe +# as an option to the serializer class diff --git a/src/calibre/ebooks/metadata/fetch.py b/src/calibre/ebooks/metadata/fetch.py index 8907a0e34b..a7fd76c661 100644 --- a/src/calibre/ebooks/metadata/fetch.py +++ b/src/calibre/ebooks/metadata/fetch.py @@ -9,7 +9,6 @@ from threading import Thread from calibre import prints from calibre.utils.config import OptionParser from calibre.utils.logging import default_log -from calibre.ebooks.metadata import MetaInformation from calibre.customize import Plugin metadata_config = None @@ -53,7 +52,7 @@ class MetadataSource(Plugin): if self.results: c = self.config_store().get(self.name, {}) res = self.results - if isinstance(res, MetaInformation): + if hasattr(res, 'authors'): res = [res] for mi in res: if not c.get('rating', True): diff --git a/src/calibre/ebooks/metadata/odt.py b/src/calibre/ebooks/metadata/odt.py old mode 100755 new mode 100644 diff --git a/src/calibre/gui2/dialogs/config/create_custom_column.py b/src/calibre/gui2/dialogs/config/create_custom_column.py index 5b470123a4..ce06e33603 100644 --- a/src/calibre/gui2/dialogs/config/create_custom_column.py +++ b/src/calibre/gui2/dialogs/config/create_custom_column.py @@ -10,6 +10,7 @@ from PyQt4.Qt import QDialog, Qt, QListWidgetItem, QVariant from calibre.gui2.dialogs.config.create_custom_column_ui import Ui_QCreateCustomColumn from calibre.gui2 import error_dialog +from calibre.metadata.book import RESERVED_METADATA_FIELDS class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn): @@ -102,6 +103,8 @@ class CreateCustomColumn(QDialog, Ui_QCreateCustomColumn): return self.simple_error('', _('No lookup name was provided')) if not col_heading: return self.simple_error('', _('No column heading was provided')) + if col in RESERVED_METADATA_FIELDS: + return self.simple_error('', _('The lookup name %s is reserved and cannot be used')%col) bad_col = False if col in self.parent.custcols: if not self.editing_col or self.parent.custcols[col]['num'] != self.orig_column_number: