mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make the validate_formatter use real instances of book metadata. This avoids type errors during validation in, for example, the Kobo driver..
This commit is contained in:
parent
da02180c4c
commit
fabb3f2849
@ -885,3 +885,39 @@ def field_from_string(field, raw, field_metadata):
|
|||||||
if val is object:
|
if val is object:
|
||||||
val = raw
|
val = raw
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def get_model_metadata_instance():
|
||||||
|
'''
|
||||||
|
Get a metadata instance that contains all the fields in the current database
|
||||||
|
with the fields to a plausible value. This function must only be used in
|
||||||
|
the GUI thread.
|
||||||
|
'''
|
||||||
|
from calibre.gui2 import is_gui_thread
|
||||||
|
if not is_gui_thread():
|
||||||
|
raise ValueError('get_model_metadata_instance() must only be used in the GUI thread')
|
||||||
|
|
||||||
|
mi = Metadata(_('Title'), [_('Author')])
|
||||||
|
mi.author_sort = _('Author Sort')
|
||||||
|
mi.series = ngettext('Series', 'Series', 1)
|
||||||
|
mi.series_index = 3
|
||||||
|
mi.rating = 4.0
|
||||||
|
mi.tags = [_('Tag 1'), _('Tag 2')]
|
||||||
|
mi.languages = ['eng']
|
||||||
|
mi.id = -1
|
||||||
|
from calibre.gui2.ui import get_gui
|
||||||
|
from calibre.utils.date import DEFAULT_DATE
|
||||||
|
fm = get_gui().current_db.new_api.field_metadata
|
||||||
|
mi.set_all_user_metadata(fm.custom_field_metadata())
|
||||||
|
for col in mi.get_all_user_metadata(False):
|
||||||
|
if fm[col]['datatype'] == 'datetime':
|
||||||
|
mi.set(col, DEFAULT_DATE)
|
||||||
|
elif fm[col]['datatype'] in ('int', 'float', 'rating'):
|
||||||
|
mi.set(col, 2)
|
||||||
|
elif fm[col]['datatype'] == 'bool':
|
||||||
|
mi.set(col, False)
|
||||||
|
elif fm[col]['is_multiple']:
|
||||||
|
mi.set(col, [col])
|
||||||
|
else:
|
||||||
|
mi.set(col, col, 1)
|
||||||
|
return mi
|
||||||
|
@ -44,7 +44,7 @@ from qt.core import (
|
|||||||
|
|
||||||
from calibre import sanitize_file_name
|
from calibre import sanitize_file_name
|
||||||
from calibre.constants import config_dir, iswindows
|
from calibre.constants import config_dir, iswindows
|
||||||
from calibre.ebooks.metadata.book.base import Metadata
|
from calibre.ebooks.metadata.book.base import get_model_metadata_instance
|
||||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||||
from calibre.gui2 import choose_files, choose_save_file, error_dialog, gprefs, info_dialog, pixmap_to_data, question_dialog, safe_open_url
|
from calibre.gui2 import choose_files, choose_save_file, error_dialog, gprefs, info_dialog, pixmap_to_data, question_dialog, safe_open_url
|
||||||
from calibre.gui2.dialogs.template_dialog_ui import Ui_TemplateDialog
|
from calibre.gui2.dialogs.template_dialog_ui import Ui_TemplateDialog
|
||||||
@ -52,13 +52,12 @@ from calibre.gui2.dialogs.template_general_info import GeneralInformationDialog
|
|||||||
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
|
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
|
||||||
from calibre.library.coloring import color_row_key, displayable_columns
|
from calibre.library.coloring import color_row_key, displayable_columns
|
||||||
from calibre.utils.config_base import tweaks
|
from calibre.utils.config_base import tweaks
|
||||||
from calibre.utils.date import DEFAULT_DATE
|
|
||||||
from calibre.utils.ffml_processor import MARKUP_ERROR, FFMLProcessor
|
from calibre.utils.ffml_processor import MARKUP_ERROR, FFMLProcessor
|
||||||
from calibre.utils.formatter import PythonTemplateContext, StopException
|
from calibre.utils.formatter import PythonTemplateContext, StopException
|
||||||
from calibre.utils.formatter_functions import StoredObjectType, formatter_functions
|
from calibre.utils.formatter_functions import StoredObjectType, formatter_functions
|
||||||
from calibre.utils.icu import lower as icu_lower
|
from calibre.utils.icu import lower as icu_lower
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
from calibre.utils.localization import localize_user_manual_link, ngettext
|
from calibre.utils.localization import localize_user_manual_link
|
||||||
from calibre.utils.resources import get_path as P
|
from calibre.utils.resources import get_path as P
|
||||||
|
|
||||||
|
|
||||||
@ -718,40 +717,11 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
|||||||
the contents of the field selectors for editing rules.
|
the contents of the field selectors for editing rules.
|
||||||
'''
|
'''
|
||||||
self.fm = fm
|
self.fm = fm
|
||||||
from calibre.gui2.ui import get_gui
|
|
||||||
if mi:
|
if mi:
|
||||||
if not isinstance(mi, (tuple, list)):
|
if not isinstance(mi, (tuple, list)):
|
||||||
mi = (mi, )
|
mi = (mi, )
|
||||||
else:
|
else:
|
||||||
mi = Metadata(_('Title'), [_('Author')])
|
mi = (get_model_metadata_instance(), )
|
||||||
mi.author_sort = _('Author Sort')
|
|
||||||
mi.series = ngettext('Series', 'Series', 1)
|
|
||||||
mi.series_index = 3
|
|
||||||
mi.rating = 4.0
|
|
||||||
mi.tags = [_('Tag 1'), _('Tag 2')]
|
|
||||||
mi.languages = ['eng']
|
|
||||||
mi.id = -1
|
|
||||||
if self.fm is not None:
|
|
||||||
mi.set_all_user_metadata(self.fm.custom_field_metadata())
|
|
||||||
else:
|
|
||||||
# No field metadata. Grab a copy from the current library so
|
|
||||||
# that we can validate any custom column names. The values for
|
|
||||||
# the columns will all be empty, which in some very unusual
|
|
||||||
# cases might cause formatter errors. We can live with that.
|
|
||||||
fm = get_gui().current_db.new_api.field_metadata
|
|
||||||
mi.set_all_user_metadata(fm.custom_field_metadata())
|
|
||||||
for col in mi.get_all_user_metadata(False):
|
|
||||||
if fm[col]['datatype'] == 'datetime':
|
|
||||||
mi.set(col, DEFAULT_DATE)
|
|
||||||
elif fm[col]['datatype'] in ('int', 'float', 'rating'):
|
|
||||||
mi.set(col, 2)
|
|
||||||
elif fm[col]['datatype'] == 'bool':
|
|
||||||
mi.set(col, False)
|
|
||||||
elif fm[col]['is_multiple']:
|
|
||||||
mi.set(col, [col])
|
|
||||||
else:
|
|
||||||
mi.set(col, col, 1)
|
|
||||||
mi = (mi, )
|
|
||||||
self.mi = mi
|
self.mi = mi
|
||||||
tv = self.template_value
|
tv = self.template_value
|
||||||
tv.setColumnCount(3)
|
tv.setColumnCount(3)
|
||||||
|
@ -2025,17 +2025,22 @@ class TemplateFormatter(string.Formatter):
|
|||||||
self.restore_state(state)
|
self.restore_state(state)
|
||||||
|
|
||||||
|
|
||||||
class ValidateFormatter(TemplateFormatter):
|
class ValidateFormatter:
|
||||||
'''
|
|
||||||
Provides a formatter that substitutes the validation string for every value
|
|
||||||
'''
|
'''
|
||||||
|
Provides a formatter that uses a fake book. This class must be used only
|
||||||
|
in the GUI thread.
|
||||||
|
|
||||||
def get_value(self, key, args, kwargs):
|
It is a class instead of a function for compatibility reasons.
|
||||||
return self._validation_string
|
'''
|
||||||
|
|
||||||
def validate(self, template):
|
def validate(self, template):
|
||||||
from calibre.ebooks.metadata.book.base import Metadata
|
from calibre.gui2 import is_gui_thread
|
||||||
return self.unsafe_format(template, {}, Metadata(''))
|
if not is_gui_thread():
|
||||||
|
raise ValueError('A ValidateFormatter must only be used in the GUI thread')
|
||||||
|
|
||||||
|
from calibre.ebooks.metadata.book.base import get_model_metadata_instance
|
||||||
|
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||||
|
return SafeFormat().unsafe_format(template, {}, get_model_metadata_instance())
|
||||||
|
|
||||||
|
|
||||||
validation_formatter = ValidateFormatter()
|
validation_formatter = ValidateFormatter()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user