mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
The formatter functions to support extra book files.
This commit is contained in:
parent
259a8555db
commit
cdc4a0a4d3
@ -469,7 +469,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
|
||||
* ``booksize()`` -- returns the value of the calibre 'size' field. Returns '' if there are no formats.
|
||||
* ``check_yes_no(field_name, is_undefined, is_false, is_true)`` -- checks if the value of the yes/no field named by the lookup name ``field_name`` is one of the values specified by the parameters, returning ``'yes'`` if a match is found otherwise returning the empty string. Set the parameter ``is_undefined``, ``is_false``, or ``is_true`` to 1 (the number) to check that condition, otherwise set it to 0. Example:
|
||||
|
||||
``check_yes_no("#bool", 1, 0, 1)`` returns ``'yes'`` if the yes/no field ``#bool`` is either True or undefined (neither True nor False).
|
||||
``check_yes_no("#bool", 1, 0, 1)`` returns ``'Yes'`` if the yes/no field ``#bool`` is either True or undefined (neither True nor False).
|
||||
|
||||
More than one of ``is_undefined``, ``is_false``, or ``is_true`` can be set to 1.
|
||||
* ``ceiling(x)`` -- returns the smallest integer greater than or equal to ``x``. Throws an exception if ``x`` is not a number.
|
||||
@ -493,6 +493,9 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
|
||||
* ``days_between(date1, date2)`` -- return the number of days between ``date1`` and ``date2``. The number is positive if ``date1`` is greater than ``date2``, otherwise negative. If either ``date1`` or ``date2`` are not dates, the function returns the empty string.
|
||||
* ``divide(x, y)`` -- returns ``x / y``. Throws an exception if either ``x`` or ``y`` are not numbers. This function can usually be replaced by the ``/`` operator.
|
||||
* ``eval(string)`` -- evaluates the string as a program, passing the local variables. This permits using the template processor to construct complex results from local variables. In :ref:`Template Program Mode <template_mode>`, because the `{` and `}` characters are interpreted before the template is evaluated you must use `[[` for the `{` character and `]]` for the ``}`` character. They are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using :ref:`Template Program Mode <template_mode>`.
|
||||
* ``extra_file_size(file_name)`` -- returns the size in bytes of the extra file ``file_name`` in the book's ``data/`` folder if it exists, otherwise ``-1``. See also the functions ``has_extra_files()``, ``extra_file_names()`` and ``extra_file_modtime()``. This function can be used only in the GUI.
|
||||
* ``extra_file_modtime(file_name, format_spec)`` -- returns the modification time of the extra file ``file_name`` in the book's ``data/`` folder if it exists, otherwise ``-1``. The modtime is formatted according to ``format_string`` (see ``format_date()`` for details). If ``format_string`` is the empty string, returns the modtime as the floating point number of seconds since the epoch. See also the functions ``has_extra_files()``, ``extra_file_names()`` and ``extra_file_size()``. The epoch is OS dependent. This function can be used only in the GUI.
|
||||
* ``extra_file_names(sep)`` -- returns a ``sep``-separated list of extra files in the book's ``data/`` folder. See also the functions ``has_extra_files()``, ``extra_file_size()`` and ``extra_file_modtime()``. This function can be used only in the GUI.
|
||||
* ``field(lookup_name)`` -- returns the value of the metadata field with lookup name ``lookup_name``.
|
||||
* ``field_exists(field_name)`` -- checks if a field (column) with the lookup name ``field_name`` exists, returning ``'1'`` if so and the empty string if not.
|
||||
* ``finish_formatting(val, fmt, prefix, suffix)`` -- apply the format, prefix, and suffix to a value in the same way as done in a template like ``{series_index:05.2f| - |- }``. This function is provided to ease conversion of complex single-function- or template-program-mode templates to `GPM` Templates. For example, the following program produces the same output as the above template::
|
||||
@ -554,6 +557,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
|
||||
* ``formats_sizes()`` -- return a comma-separated list of colon-separated ``FMT:SIZE`` items giving the sizes in bytes of the formats of a book. You can use the select function to get the size for a specific format. Note that format names are always uppercase, as in EPUB.
|
||||
* ``fractional_part(x)`` -- returns the value after the decimal point. For example, ``fractional_part(3.14)`` returns ``0.14``. Throws an exception if ``x`` is not a number.
|
||||
* ``has_cover()`` -- return ``'Yes'`` if the book has a cover, otherwise the empty string.
|
||||
* ``has_extra_files()`` -- returns ``'Yes'`` if there are any extra files for the book (files in the folder ``data/`` in the book's folder), otherwise ``''`` (the empty string). See also the functions ``extra_file_names()``, ``extra_file_size()`` and ``extra_file_modtime()`` This function can be used only in the GUI.
|
||||
* ``is_marked()`` -- check whether the book is `marked` in calibre. If it is then return the value of the mark, either ``'true'`` (lower case) or a comma-separated list of named marks. Returns ``''`` (the empty string) if the book is not marked. This function works only in the GUI.
|
||||
* ``language_codes(lang_strings)`` -- return the `language codes <https://www.loc.gov/standards/iso639-2/php/code_list.php>`_ for the language names passed in `lang_strings`. The strings must be in the language of the current locale. ``Lang_strings`` is a comma-separated list.
|
||||
* ``list_contains(value, separator, [ pattern, found_val, ]* not_found_val)`` -- (Alias of ``in_list``) Interpreting the value as a list of items separated by ``separator``, evaluate the ``pattern`` against each value in the list. If the ``pattern`` matches any value then return ``found_val``, otherwise return ``not_found_val``. The ``pattern`` and ``found_value`` can be repeated as many times as desired, permitting returning different values depending on the search. The patterns are checked in order. The first match is returned. Aliases: ``in_list()``, ``list_contains()``
|
||||
|
@ -2144,14 +2144,14 @@ class BuiltinCheckYesNo(BuiltinFormatterFunction):
|
||||
res = getattr(mi, field, None)
|
||||
if res is None:
|
||||
if is_undefined == '1':
|
||||
return 'yes'
|
||||
return 'Yes'
|
||||
return ""
|
||||
if not isinstance(res, bool):
|
||||
raise ValueError(_('check_yes_no requires the field be a Yes/No custom column'))
|
||||
if is_false == '1' and not res:
|
||||
return 'yes'
|
||||
return 'Yes'
|
||||
if is_true == '1' and res:
|
||||
return 'yes'
|
||||
return 'Yes'
|
||||
return ""
|
||||
|
||||
|
||||
@ -2387,6 +2387,95 @@ class BuiltinBookValues(BuiltinFormatterFunction):
|
||||
raise ValueError(e)
|
||||
|
||||
|
||||
class BuiltinHasExtraFiles(BuiltinFormatterFunction):
|
||||
name = 'has_extra_files'
|
||||
arg_count = 0
|
||||
category = 'Template database functions'
|
||||
__doc__ = doc = _("has_extra_files() -- returns 'Yes' if there are any extra "
|
||||
"files, otherwise '' (the empty string). "
|
||||
'This function can be used only in the GUI.')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals):
|
||||
db = self.get_database(mi).new_api
|
||||
try:
|
||||
files = db.list_extra_files(mi.id, use_cache=True, pattern='data/**/*')
|
||||
return 'Yes' if files else ''
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
raise ValueError(e)
|
||||
|
||||
|
||||
class BuiltinExtraFileNames(BuiltinFormatterFunction):
|
||||
name = 'extra_file_names'
|
||||
arg_count = 1
|
||||
category = 'Template database functions'
|
||||
__doc__ = doc = _("extra_file_names(sep) -- returns a sep-separated list of "
|
||||
"extra files in the book's 'data/' folder. "
|
||||
'This function can be used only in the GUI.')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, sep):
|
||||
db = self.get_database(mi).new_api
|
||||
try:
|
||||
files = db.list_extra_files(mi.id, use_cache=True, pattern='data/**/*')
|
||||
return sep.join([file[0][5:] for file in files])
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
raise ValueError(e)
|
||||
|
||||
|
||||
class BuiltinExtraFileSize(BuiltinFormatterFunction):
|
||||
name = 'extra_file_size'
|
||||
arg_count = 1
|
||||
category = 'Template database functions'
|
||||
__doc__ = doc = _("extra_file_size(file_name) -- returns the size in bytes of "
|
||||
"the extra file 'file_name' in the book's 'data/' folder if "
|
||||
"it exists, otherwise -1."
|
||||
'This function can be used only in the GUI.')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, file_name):
|
||||
db = self.get_database(mi).new_api
|
||||
try:
|
||||
file_name = 'data/' + file_name
|
||||
files = db.list_extra_files(mi.id, use_cache=True, pattern='data/**/*')
|
||||
for f in files:
|
||||
if f[0] == file_name:
|
||||
return str(f[2].st_size)
|
||||
return str(-1)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
raise ValueError(e)
|
||||
|
||||
|
||||
class BuiltinExtraFileModtime(BuiltinFormatterFunction):
|
||||
name = 'extra_file_modtime'
|
||||
arg_count = 2
|
||||
category = 'Template database functions'
|
||||
__doc__ = doc = _("extra_file_modtime(file_name, format_spec) -- returns the "
|
||||
"modification time of the extra file 'file_name' in the "
|
||||
"book's 'data/' folder if it exists, otherwise -1.0. The "
|
||||
"modtime is formatted according to 'format_string' "
|
||||
"(see format_date()). If 'format_string' is empty, returns "
|
||||
"the modtime as the floating point number of seconds since "
|
||||
"the epoch. The epoch is OS dependent. "
|
||||
"This function can be used only in the GUI.")
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, file_name, format_string):
|
||||
db = self.get_database(mi).new_api
|
||||
try:
|
||||
file_name = 'data/' + file_name
|
||||
files = db.list_extra_files(mi.id, use_cache=True, pattern='data/**/*')
|
||||
for f in files:
|
||||
if f[0] == file_name:
|
||||
val = f[2].st_mtime
|
||||
if format_string:
|
||||
return format_date(datetime.fromtimestamp(val), format_string)
|
||||
return str(val)
|
||||
return str(1.0)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
raise ValueError(e)
|
||||
|
||||
|
||||
_formatter_builtins = [
|
||||
BuiltinAdd(), BuiltinAnd(), BuiltinApproximateFormats(), BuiltinArguments(),
|
||||
BuiltinAssign(),
|
||||
@ -2396,12 +2485,13 @@ _formatter_builtins = [
|
||||
BuiltinCmp(), BuiltinConnectedDeviceName(), BuiltinConnectedDeviceUUID(), BuiltinContains(),
|
||||
BuiltinCount(), BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(),
|
||||
BuiltinCurrentVirtualLibraryName(), BuiltinDateArithmetic(),
|
||||
BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(),
|
||||
BuiltinField(), BuiltinFieldExists(),
|
||||
BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(),
|
||||
BuiltinExtraFileNames(), BuiltinExtraFileSize(), BuiltinExtraFileModtime(),
|
||||
BuiltinFirstNonEmpty(), BuiltinField(), BuiltinFieldExists(),
|
||||
BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(), BuiltinFloor(),
|
||||
BuiltinFormatDate(), BuiltinFormatNumber(), BuiltinFormatsModtimes(),
|
||||
BuiltinFormatsPaths(), BuiltinFormatsSizes(), BuiltinFractionalPart(),
|
||||
BuiltinGlobals(),
|
||||
BuiltinGlobals(), BuiltinHasExtraFiles(),
|
||||
BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(),
|
||||
BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(),
|
||||
BuiltinInList(), BuiltinIsMarked(), BuiltinListCountMatching(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user