Merge from trunk

This commit is contained in:
Charles Haley 2011-06-01 05:39:56 +01:00
commit 65935db7d1
8 changed files with 408 additions and 101 deletions

View File

@ -1,27 +1,30 @@
__license__ = 'GPL v3'
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
__copyright__ = '2010 - 2011, Darko Miletic <darko.miletic at gmail.com>'
'''
news.bbc.co.uk
'''
import re
from calibre.web.feeds.recipes import BasicNewsRecipe
class BBC(BasicNewsRecipe):
title = 'BBC News (fast)'
__author__ = 'Darko Miletic, Starson17'
description = 'News from UK. A much faster version that does not download pictures'
description = 'Visit BBC News for up-to-the-minute news, breaking news, video, audio and feature stories. BBC News provides trusted World and UK news as well as local and regional perspectives. Also entertainment, business, science, technology and health news.'
oldest_article = 2
max_articles_per_feed = 100
no_stylesheets = True
#delay = 1
use_embedded_content = False
encoding = 'utf8'
publisher = 'BBC'
category = 'news, UK, world'
language = 'en_GB'
publication_type = 'newsportal'
extra_css = ' body{ font-family: Verdana,Helvetica,Arial,sans-serif } .introduction{font-weight: bold} .story-feature{display: block; padding: 0; border: 1px solid; width: 40%; font-size: small} .story-feature h2{text-align: center; text-transform: uppercase} '
preprocess_regexps = [(re.compile(r'<!--.*?-->', re.DOTALL), lambda m: '')]
masthead_url = 'http://news.bbcimg.co.uk/img/1_0_1/cream/hi/news/news-blocks.gif'
extra_css = """
body{ font-family: Verdana,Helvetica,Arial,sans-serif }
.introduction{font-weight: bold}
.story-feature{display: block; padding: 0; border: 1px solid; width: 40%; font-size: small}
.story-feature h2{text-align: center; text-transform: uppercase}
"""
conversion_options = {
'comments' : description
,'tags' : category
@ -31,31 +34,54 @@ class BBC(BasicNewsRecipe):
}
keep_only_tags = [
dict(name='div', attrs={'class':['layout-block-a layout-block']})
,dict(attrs={'class':['story-body','storybody']})
dict(name='div', attrs={'class':['layout-block-a layout-block']})
,dict(attrs={'class':['story-body','storybody']})
,dict(attrs={'id':['meta-information','story-body']})
]
remove_tags = [
dict(name='div', attrs={'class':['story-feature related narrow', 'share-help', 'embedded-hyper', \
'story-feature wide ', 'story-feature narrow']})
, dict(name=['img'])
]
dict(name='div', attrs={'class':['story-feature related narrow', \
'share-help', 'embedded-hyper', \
'story-feature wide ', \
'story-feature narrow', \
'hidden','story-actions', \
'embedded-hyper']})
,dict(name=['img','meta','link','object','embed','iframe','base'])
,dict(attrs={'class':['hidden','videoInStoryC']})
,dict(attrs={'id':['bbccom_sponsor_section','toggle-controls', \
'toggle-images','toggle-title']})
]
remove_attributes = ['width','height']
remove_attributes = ['width','height','xmlns:og','lang','clear']
feeds = [
('News Front Page', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml'),
('Science/Nature', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/science/nature/rss.xml'),
('Technology', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/technology/rss.xml'),
('Entertainment', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/entertainment/rss.xml'),
('Magazine', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/uk_news/magazine/rss.xml'),
('Business', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/business/rss.xml'),
('Health', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/health/rss.xml'),
('Americas', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/americas/rss.xml'),
('Europe', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/europe/rss.xml'),
('South Asia', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/south_asia/rss.xml'),
('UK', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/uk_news/rss.xml'),
('Asia-Pacific', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/asia-pacific/rss.xml'),
('Africa', 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/africa/rss.xml'),
('Top Stories' , 'http://feeds.bbci.co.uk/news/rss.xml' ),
('Science/Environment', 'http://feeds.bbci.co.uk/news/science_and_environment/rss.xml'),
('Technology' , 'http://feeds.bbci.co.uk/news/technology/rss.xml' ),
('Entertainment/Arts' , 'http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml' ),
('Magazine' , 'http://feeds.bbci.co.uk/news/magazine/rss.xml' ),
('Business' , 'http://feeds.bbci.co.uk/news/business/rss.xml' ),
('Politics' , 'http://feeds.bbci.co.uk/news/politics/rss.xml' ),
('Health' , 'http://feeds.bbci.co.uk/news/health/rss.xml' ),
('US&Canada' , 'http://feeds.bbci.co.uk/news/world/us_and_canada/rss.xml' ),
('Latin America' , 'http://feeds.bbci.co.uk/news/world/latin_america/rss.xml' ),
('Europe' , 'http://feeds.bbci.co.uk/news/world/europe/rss.xml' ),
('South Asia' , 'http://feeds.bbci.co.uk/news/world/south_asia/rss.xml' ),
('England' , 'http://feeds.bbci.co.uk/news/england/rss.xml' ),
('Asia-Pacific' , 'http://feeds.bbci.co.uk/news/world/asia_pacific/rss.xml' ),
('Africa' , 'http://feeds.bbci.co.uk/news/world/africa/rss.xml' )
]
def preprocess_html(self, soup):
for item in soup.findAll(style=True):
del item['style']
for item in soup.findAll('left'):
item.name='span'
for item in soup.findAll('a'):
if item.string is not None:
str = item.string
item.replaceWith(str)
else:
str = self.tag_to_string(item)
item.replaceWith(str)
return soup

View File

@ -109,7 +109,8 @@ class ANDROID(USBMS):
'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT', 'A70H',
'IDEOS_TABLET', 'MYTOUCH_4G', 'UMS_COMPOSITE', 'SCH-I800_CARD',
'7', 'A956', 'A955', 'A43', 'ANDROID_PLATFORM', 'TEGRA_2',
'MB860', 'MULTI-CARD', 'MID7015A', 'INCREDIBLE', 'A7EB', 'STREAK']
'MB860', 'MULTI-CARD', 'MID7015A', 'INCREDIBLE', 'A7EB', 'STREAK',
'MB525']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD']

View File

@ -101,7 +101,7 @@ class Container(object):
return None
return existing[0]
def add_name_to_manifest(self, name):
def add_name_to_manifest(self, name, mt=None):
item = self.manifest_item_for_name(name)
if item is not None:
return
@ -109,11 +109,27 @@ class Container(object):
item = manifest.makeelement('{%s}item'%OPF_NS, nsmap={'opf':OPF_NS},
href=self.name_to_href(name, posixpath.dirname(self.opf_name)),
id=self.generate_manifest_id())
mt = guess_type(posixpath.basename(name))[0]
if not mt:
mt = guess_type(posixpath.basename(name))[0]
if not mt:
mt = 'application/octest-stream'
item.set('media-type', mt)
manifest.append(item)
self.fix_tail(item)
def fix_tail(self, item):
'''
Designed only to work with self closing elements after item has
just been inserted/appended
'''
parent = item.getparent()
idx = parent.index(item)
if idx == 0:
item.tail = parent.text
else:
item.tail = parent[idx-1].tail
if idx == len(parent)-1:
parent[idx-1].tail = parent.text
def generate_manifest_id(self):
items = self.opf.xpath('//opf:manifest/opf:item[@id]',

View File

@ -46,6 +46,8 @@ cover_url = XPath("descendant::atom:link[@rel='image']/attribute::href")
def get_details(browser, url, timeout): # {{{
try:
if Douban.DOUBAN_API_KEY and Douban.DOUBAN_API_KEY != '':
url = url + "?apikey=" + Douban.DOUBAN_API_KEY
raw = browser.open_novisit(url, timeout=timeout).read()
except Exception as e:
gc = getattr(e, 'getcode', lambda : -1)

View File

@ -120,7 +120,19 @@ class Split(object):
for i, x in enumerate(page_breaks):
x.set('id', x.get('id', 'calibre_pb_%d'%i))
id = x.get('id')
page_breaks_.append((XPath('//*[@id=%r]'%id),
try:
xp = XPath('//*[@id="%s"]'%id)
except:
try:
xp = XPath("//*[@id='%s']"%id)
except:
# The id has both a quote and an apostrophe or some other
# Just replace it since I doubt its going to work anywhere else
# either
id = 'calibre_pb_%d'%i
x.set('id', id)
xp = XPath('//*[@id=%r]'%id)
page_breaks_.append((xp,
x.get('pb_before', False)))
page_break_ids.append(id)

View File

@ -268,20 +268,14 @@ The following functions are available in addition to those described in single-f
* ``subtract(x, y)`` -- returns x - y. Throws an exception if either x or y are not numbers.
* ``template(x)`` -- evaluates x as a template. The evaluation is done in its own context, meaning that variables are not shared between the caller and the template evaluation. Because the `{` and `}` characters are special, you must use `[[` for the `{` character and `]]` for the '}' character; they are converted automatically. For example, ``template('[[title_sort]]') will evaluate the template ``{title_sort}`` and return its value.
Function classification summary:
Function classification
---------------------------
.. toctree::
:maxdepth: 3
template_ref
* Get values from metadata: ``field``. ``raw_field``. In some situations, ``lookup`` can be used in place of ``field``.
* Arithmetic: ``add``, ``subtract``, ``multiply``, ``divide``
* Boolean: ``and``, ``or``, ``not``. The function ``if_empty`` is similar to ``and`` called with one argument.
* If-then-else: ``contains``, ``test``
* Iterating over values: ``first_non_empty``, ``lookup``, ``switch``
* List lookup: ``in_list``, ``list_item``, ``select``, ``str_in_list``
* List manipulation: ``count``, ``merge_lists``, ``sublist``, ``subitems``
* Recursion: ``eval``, ``template``
* Relational: ``cmp`` (for numbers), ``strcmp`` (for strings)
* String case changes: ``lowercase``, ``uppercase``, ``titlecase``, ``capitalize``
* String manipulation: ``re``, ``shorten``, ``substr``
* Other: ``assign``, ``booksize``, ``format_date``, ``ondevice`` ``print``
.. _general_mode:
@ -425,20 +419,9 @@ You might find the following tips useful.
* Templates can use other templates by referencing a composite custom column.
* In a plugboard, you can set a field to empty (or whatever is equivalent to empty) by using the special template ``{null}``. This template will always evaluate to an empty string.
* The technique described above to show numbers even if they have a zero value works with the standard field series_index.
API of the Metadata objects
----------------------------
.. module:: calibre.ebooks.metadata.book.base
.. toctree::
:hidden:
.. autoclass:: Metadata
:members:
:member-order: bysource
.. data:: STANDARD_METADATA_FIELDS
The set of standard metadata fields.
.. literalinclude:: ../ebooks/metadata/book/__init__.py
:lines: 7-
template_ref

View File

@ -0,0 +1,266 @@
.. include:: global.rst
.. _templaterefcalibre:
Reference for all builtin template language functions
========================================================
Here, we document all the builtin functions available in the |app| template language. Every function is implemented as a class in python and you can click the source links to see the source code, in case the documentation is insufficient. The functions are arranged in logical groups by type.
.. contents::
:depth: 2
:local:
.. module:: calibre.utils.formatter_functions
Get values from metadata
--------------------------
field(name)
^^^^^^^^^^^^^^
.. autoclass:: BuiltinField
raw_field(name)
^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinRaw_field
booksize()
^^^^^^^^^^^^
.. autoclass:: BuiltinBooksize
format_date(val, format_string)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinFormat_date
ondevice()
^^^^^^^^^^^
.. autoclass:: BuiltinOndevice
Arithmetic
-------------
add(x, y)
^^^^^^^^^^^^^
.. autoclass:: BuiltinAdd
subtract(x, y)
^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinSubtract
multiply(x, y)
^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinMultiply
divide(x, y)
^^^^^^^^^^^^^^^
.. autoclass:: BuiltinDivide
Boolean
------------
and(value1, value2, ...)
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinAnd
or(value1, value2, ...)
^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinOr
not(value)
^^^^^^^^^^^^^
.. autoclass:: BuiltinNot
If-then-else
-----------------
contains(val, pattern, text if match, text if not match)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinContains
test(val, text if not empty, text if empty)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinTest
ifempty(val, text if empty)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinIfempty
Iterating over values
------------------------
first_non_empty(value, value, ...)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinFirstNonEmpty
lookup(val, pattern, field, pattern, field, ..., else_field)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinLookup
switch(val, pattern, value, pattern, value, ..., else_value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinSwitch
List Lookup
---------------
in_list(val, separator, pattern, found_val, not_found_val)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinInList
str_in_list(val, separator, string, found_val, not_found_val)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinStrInList
list_item(val, index, separator)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinListitem
select(val, key)
^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinSelect
List Manipulation
-------------------
count(val, separator)
^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinCount
merge_lists(list1, list2, separator)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinMergeLists
sublist(val, start_index, end_index, separator)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinSublist
subitems(val, start_index, end_index)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinSubitems
Recursion
-------------
eval(template)
^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinEval
template(x)
^^^^^^^^^^^^
.. autoclass:: BuiltinTemplate
Relational
-----------
cmp(x, y, lt, eq, gt)
^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinCmp
strcmp(x, y, lt, eq, gt)
^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinStrcmp
String case changes
---------------------
lowercase(val)
^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinLowercase
uppercase(val)
^^^^^^^^^^^^^^^
.. autoclass:: BuiltinUppercase
titlecase(val)
^^^^^^^^^^^^^^^
.. autoclass:: BuiltinTitlecase
capitalize(val)
^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinCapitalize
String Manipulation
---------------------
re(val, pattern, replacement)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinRe
shorten(val, left chars, middle text, right chars)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinShorten
substr(str, start, end)
^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinSubstr
Other
--------
assign(id, val)
^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinAssign
print(a, b, ...)
^^^^^^^^^^^^^^^^^
.. autoclass:: BuiltinPrint
API of the Metadata objects
----------------------------
The python implementation of the template functions is passed in a Metadata object. Knowing it's API is useful if you want to define your own template functions.
.. module:: calibre.ebooks.metadata.book.base
.. autoclass:: Metadata
:members:
:member-order: bysource
.. data:: STANDARD_METADATA_FIELDS
The set of standard metadata fields.
.. literalinclude:: ../ebooks/metadata/book/__init__.py
:lines: 7-

View File

@ -87,7 +87,7 @@ class BuiltinFormatterFunction(FormatterFunction):
class BuiltinStrcmp(BuiltinFormatterFunction):
name = 'strcmp'
arg_count = 5
doc = _('strcmp(x, y, lt, eq, gt) -- does a case-insensitive comparison of x '
__doc__ = doc = _('strcmp(x, y, lt, eq, gt) -- does a case-insensitive comparison of x '
'and y as strings. Returns lt if x < y. Returns eq if x == y. '
'Otherwise returns gt.')
@ -102,7 +102,7 @@ class BuiltinStrcmp(BuiltinFormatterFunction):
class BuiltinCmp(BuiltinFormatterFunction):
name = 'cmp'
arg_count = 5
doc = _('cmp(x, y, lt, eq, gt) -- compares x and y after converting both to '
__doc__ = doc = _('cmp(x, y, lt, eq, gt) -- compares x and y after converting both to '
'numbers. Returns lt if x < y. Returns eq if x == y. Otherwise returns gt.')
def evaluate(self, formatter, kwargs, mi, locals, x, y, lt, eq, gt):
@ -117,7 +117,7 @@ class BuiltinCmp(BuiltinFormatterFunction):
class BuiltinStrcat(BuiltinFormatterFunction):
name = 'strcat'
arg_count = -1
doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
__doc__ = doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
'string formed by concatenating all the arguments')
def evaluate(self, formatter, kwargs, mi, locals, *args):
@ -130,7 +130,7 @@ class BuiltinStrcat(BuiltinFormatterFunction):
class BuiltinAdd(BuiltinFormatterFunction):
name = 'add'
arg_count = 2
doc = _('add(x, y) -- returns x + y. Throws an exception if either x or y are not numbers.')
__doc__ = doc = _('add(x, y) -- returns x + y. Throws an exception if either x or y are not numbers.')
def evaluate(self, formatter, kwargs, mi, locals, x, y):
x = float(x if x else 0)
@ -140,7 +140,7 @@ class BuiltinAdd(BuiltinFormatterFunction):
class BuiltinSubtract(BuiltinFormatterFunction):
name = 'subtract'
arg_count = 2
doc = _('subtract(x, y) -- returns x - y. Throws an exception if either x or y are not numbers.')
__doc__ = doc = _('subtract(x, y) -- returns x - y. Throws an exception if either x or y are not numbers.')
def evaluate(self, formatter, kwargs, mi, locals, x, y):
x = float(x if x else 0)
@ -150,7 +150,7 @@ class BuiltinSubtract(BuiltinFormatterFunction):
class BuiltinMultiply(BuiltinFormatterFunction):
name = 'multiply'
arg_count = 2
doc = _('multiply(x, y) -- returns x * y. Throws an exception if either x or y are not numbers.')
__doc__ = doc = _('multiply(x, y) -- returns x * y. Throws an exception if either x or y are not numbers.')
def evaluate(self, formatter, kwargs, mi, locals, x, y):
x = float(x if x else 0)
@ -160,7 +160,7 @@ class BuiltinMultiply(BuiltinFormatterFunction):
class BuiltinDivide(BuiltinFormatterFunction):
name = 'divide'
arg_count = 2
doc = _('divide(x, y) -- returns x / y. Throws an exception if either x or y are not numbers.')
__doc__ = doc = _('divide(x, y) -- returns x / y. Throws an exception if either x or y are not numbers.')
def evaluate(self, formatter, kwargs, mi, locals, x, y):
x = float(x if x else 0)
@ -170,7 +170,7 @@ class BuiltinDivide(BuiltinFormatterFunction):
class BuiltinTemplate(BuiltinFormatterFunction):
name = 'template'
arg_count = 1
doc = _('template(x) -- evaluates x as a template. The evaluation is done '
__doc__ = doc = _('template(x) -- evaluates x as a template. The evaluation is done '
'in its own context, meaning that variables are not shared between '
'the caller and the template evaluation. Because the { and } '
'characters are special, you must use [[ for the { character and '
@ -185,7 +185,7 @@ class BuiltinTemplate(BuiltinFormatterFunction):
class BuiltinEval(BuiltinFormatterFunction):
name = 'eval'
arg_count = 1
doc = _('eval(template) -- evaluates the template, passing the local '
__doc__ = doc = _('eval(template) -- evaluates the template, passing the local '
'variables (those \'assign\'ed to) instead of the book metadata. '
' This permits using the template processor to construct complex '
'results from local variables.')
@ -198,7 +198,7 @@ class BuiltinEval(BuiltinFormatterFunction):
class BuiltinAssign(BuiltinFormatterFunction):
name = 'assign'
arg_count = 2
doc = _('assign(id, val) -- assigns val to id, then returns val. '
__doc__ = doc = _('assign(id, val) -- assigns val to id, then returns val. '
'id must be an identifier, not an expression')
def evaluate(self, formatter, kwargs, mi, locals, target, value):
@ -208,7 +208,7 @@ class BuiltinAssign(BuiltinFormatterFunction):
class BuiltinPrint(BuiltinFormatterFunction):
name = 'print'
arg_count = -1
doc = _('print(a, b, ...) -- prints the arguments to standard output. '
__doc__ = doc = _('print(a, b, ...) -- prints the arguments to standard output. '
'Unless you start calibre from the command line (calibre-debug -g), '
'the output will go to a black hole.')
@ -219,7 +219,7 @@ class BuiltinPrint(BuiltinFormatterFunction):
class BuiltinField(BuiltinFormatterFunction):
name = 'field'
arg_count = 1
doc = _('field(name) -- returns the metadata field named by name')
__doc__ = doc = _('field(name) -- returns the metadata field named by name')
def evaluate(self, formatter, kwargs, mi, locals, name):
return formatter.get_value(name, [], kwargs)
@ -227,7 +227,7 @@ class BuiltinField(BuiltinFormatterFunction):
class BuiltinRaw_field(BuiltinFormatterFunction):
name = 'raw_field'
arg_count = 1
doc = _('raw_field(name) -- returns the metadata field named by name '
__doc__ = doc = _('raw_field(name) -- returns the metadata field named by name '
'without applying any formatting.')
def evaluate(self, formatter, kwargs, mi, locals, name):
@ -236,7 +236,7 @@ class BuiltinRaw_field(BuiltinFormatterFunction):
class BuiltinSubstr(BuiltinFormatterFunction):
name = 'substr'
arg_count = 3
doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
__doc__ = doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
'characters of str. The first character in str is the zero\'th '
'character. If end is negative, then it indicates that many '
'characters counting from the right. If end is zero, then it '
@ -249,7 +249,7 @@ class BuiltinSubstr(BuiltinFormatterFunction):
class BuiltinLookup(BuiltinFormatterFunction):
name = 'lookup'
arg_count = -1
doc = _('lookup(val, pattern, field, pattern, field, ..., else_field) -- '
__doc__ = doc = _('lookup(val, pattern, field, pattern, field, ..., else_field) -- '
'like switch, except the arguments are field (metadata) names, not '
'text. The value of the appropriate field will be fetched and used. '
'Note that because composite columns are fields, you can use this '
@ -276,7 +276,7 @@ class BuiltinLookup(BuiltinFormatterFunction):
class BuiltinTest(BuiltinFormatterFunction):
name = 'test'
arg_count = 3
doc = _('test(val, text if not empty, text if empty) -- return `text if not '
__doc__ = doc = _('test(val, text if not empty, text if empty) -- return `text if not '
'empty` if the field is not empty, otherwise return `text if empty`')
def evaluate(self, formatter, kwargs, mi, locals, val, value_if_set, value_not_set):
@ -288,7 +288,7 @@ class BuiltinTest(BuiltinFormatterFunction):
class BuiltinContains(BuiltinFormatterFunction):
name = 'contains'
arg_count = 4
doc = _('contains(val, pattern, text if match, text if not match) -- checks '
__doc__ = doc = _('contains(val, pattern, text if match, text if not match) -- checks '
'if field contains matches for the regular expression `pattern`. '
'Returns `text if match` if matches are found, otherwise it returns '
'`text if no match`')
@ -303,7 +303,7 @@ class BuiltinContains(BuiltinFormatterFunction):
class BuiltinSwitch(BuiltinFormatterFunction):
name = 'switch'
arg_count = -1
doc = _('switch(val, pattern, value, pattern, value, ..., else_value) -- '
__doc__ = doc = _('switch(val, pattern, value, pattern, value, ..., else_value) -- '
'for each `pattern, value` pair, checks if the field matches '
'the regular expression `pattern` and if so, returns that '
'`value`. If no pattern matches, then else_value is returned. '
@ -323,7 +323,7 @@ class BuiltinSwitch(BuiltinFormatterFunction):
class BuiltinInList(BuiltinFormatterFunction):
name = 'in_list'
arg_count = 5
doc = _('in_list(val, separator, pattern, found_val, not_found_val) -- '
__doc__ = doc = _('in_list(val, separator, pattern, found_val, not_found_val) -- '
'treat val as a list of items separated by separator, '
'comparing the pattern against each value in the list. If the '
'pattern matches a value, return found_val, otherwise return '
@ -340,7 +340,7 @@ class BuiltinInList(BuiltinFormatterFunction):
class BuiltinStrInList(BuiltinFormatterFunction):
name = 'str_in_list'
arg_count = 5
doc = _('str_in_list(val, separator, string, found_val, not_found_val) -- '
__doc__ = doc = _('str_in_list(val, separator, string, found_val, not_found_val) -- '
'treat val as a list of items separated by separator, '
'comparing the string against each value in the list. If the '
'string matches a value, return found_val, otherwise return '
@ -360,7 +360,7 @@ class BuiltinStrInList(BuiltinFormatterFunction):
class BuiltinRe(BuiltinFormatterFunction):
name = 're'
arg_count = 3
doc = _('re(val, pattern, replacement) -- return the field after applying '
__doc__ = doc = _('re(val, pattern, replacement) -- return the field after applying '
'the regular expression. All instances of `pattern` are replaced '
'with `replacement`. As in all of calibre, these are '
'python-compatible regular expressions')
@ -371,7 +371,7 @@ class BuiltinRe(BuiltinFormatterFunction):
class BuiltinIfempty(BuiltinFormatterFunction):
name = 'ifempty'
arg_count = 2
doc = _('ifempty(val, text if empty) -- return val if val is not empty, '
__doc__ = doc = _('ifempty(val, text if empty) -- return val if val is not empty, '
'otherwise return `text if empty`')
def evaluate(self, formatter, kwargs, mi, locals, val, value_if_empty):
@ -383,7 +383,7 @@ class BuiltinIfempty(BuiltinFormatterFunction):
class BuiltinShorten(BuiltinFormatterFunction):
name = 'shorten'
arg_count = 4
doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
__doc__ = doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
'shortened version of the field, consisting of `left chars` '
'characters from the beginning of the field, followed by '
'`middle text`, followed by `right chars` characters from '
@ -408,7 +408,7 @@ class BuiltinShorten(BuiltinFormatterFunction):
class BuiltinCount(BuiltinFormatterFunction):
name = 'count'
arg_count = 2
doc = _('count(val, separator) -- interprets the value as a list of items '
__doc__ = doc = _('count(val, separator) -- interprets the value as a list of items '
'separated by `separator`, returning the number of items in the '
'list. Most lists use a comma as the separator, but authors '
'uses an ampersand. Examples: {tags:count(,)}, {authors:count(&)}')
@ -419,7 +419,7 @@ class BuiltinCount(BuiltinFormatterFunction):
class BuiltinListitem(BuiltinFormatterFunction):
name = 'list_item'
arg_count = 3
doc = _('list_item(val, index, separator) -- interpret the value as a list of '
__doc__ = doc = _('list_item(val, index, separator) -- interpret the value as a list of '
'items separated by `separator`, returning the `index`th item. '
'The first item is number zero. The last item can be returned '
'using `list_item(-1,separator)`. If the item is not in the list, '
@ -439,7 +439,7 @@ class BuiltinListitem(BuiltinFormatterFunction):
class BuiltinSelect(BuiltinFormatterFunction):
name = 'select'
arg_count = 2
doc = _('select(val, key) -- interpret the value as a comma-separated list '
__doc__ = doc = _('select(val, key) -- interpret the value as a comma-separated list '
'of items, with the items being "id:value". Find the pair with the'
'id equal to key, and return the corresponding value.'
)
@ -456,9 +456,9 @@ class BuiltinSelect(BuiltinFormatterFunction):
class BuiltinSublist(BuiltinFormatterFunction):
name = 'sublist'
arg_count = 4
doc = _('sublist(val, start_index, end_index, separator) -- interpret the '
__doc__ = doc = _('sublist(val, start_index, end_index, separator) -- interpret the '
'value as a list of items separated by `separator`, returning a '
'new list made from the `start_index`th to the `end_index`th item. '
'new list made from the `start_index` to the `end_index` item. '
'The first item is number zero. If an index is negative, then it '
'counts from the end of the list. As a special case, an end_index '
'of zero is assumed to be the length of the list. Examples using '
@ -466,7 +466,8 @@ class BuiltinSublist(BuiltinFormatterFunction):
'comma-separated) contains "A, B, C": '
'{tags:sublist(0,1,\,)} returns "A". '
'{tags:sublist(-1,0,\,)} returns "C". '
'{tags:sublist(0,-1,\,)} returns "A, B".')
'{tags:sublist(0,-1,\,)} returns "A, B".'
)
def evaluate(self, formatter, kwargs, mi, locals, val, start_index, end_index, sep):
if not val:
@ -485,12 +486,12 @@ class BuiltinSublist(BuiltinFormatterFunction):
class BuiltinSubitems(BuiltinFormatterFunction):
name = 'subitems'
arg_count = 3
doc = _('subitems(val, start_index, end_index) -- This function is used to '
__doc__ = doc = _('subitems(val, start_index, end_index) -- This function is used to '
'break apart lists of items such as genres. It interprets the value '
'as a comma-separated list of items, where each item is a period-'
'separated list. Returns a new list made by first finding all the '
'period-separated items, then for each such item extracting the '
'start_index`th to the `end_index`th components, then combining '
'start_index` to the `end_index` components, then combining '
'the results back together. The first component in a period-'
'separated list has an index of zero. If an index is negative, '
'then it counts from the end of the list. As a special case, an '
@ -522,8 +523,8 @@ class BuiltinSubitems(BuiltinFormatterFunction):
class BuiltinFormat_date(BuiltinFormatterFunction):
name = 'format_date'
arg_count = 2
doc = _('format_date(val, format_string) -- format the value, which must '
'be a date, using the format_string, returning a string. '
__doc__ = doc = _('format_date(val, format_string) -- format the value, '
'which must be a date, using the format_string, returning a string. '
'The formatting codes are: '
'd : the day as number without a leading zero (1 to 31) '
'dd : the day as number with a leading zero (01 to 31) '
@ -550,7 +551,7 @@ class BuiltinFormat_date(BuiltinFormatterFunction):
class BuiltinUppercase(BuiltinFormatterFunction):
name = 'uppercase'
arg_count = 1
doc = _('uppercase(val) -- return value of the field in upper case')
__doc__ = doc = _('uppercase(val) -- return value of the field in upper case')
def evaluate(self, formatter, kwargs, mi, locals, val):
return val.upper()
@ -558,7 +559,7 @@ class BuiltinUppercase(BuiltinFormatterFunction):
class BuiltinLowercase(BuiltinFormatterFunction):
name = 'lowercase'
arg_count = 1
doc = _('lowercase(val) -- return value of the field in lower case')
__doc__ = doc = _('lowercase(val) -- return value of the field in lower case')
def evaluate(self, formatter, kwargs, mi, locals, val):
return val.lower()
@ -566,7 +567,7 @@ class BuiltinLowercase(BuiltinFormatterFunction):
class BuiltinTitlecase(BuiltinFormatterFunction):
name = 'titlecase'
arg_count = 1
doc = _('titlecase(val) -- return value of the field in title case')
__doc__ = doc = _('titlecase(val) -- return value of the field in title case')
def evaluate(self, formatter, kwargs, mi, locals, val):
return titlecase(val)
@ -574,7 +575,7 @@ class BuiltinTitlecase(BuiltinFormatterFunction):
class BuiltinCapitalize(BuiltinFormatterFunction):
name = 'capitalize'
arg_count = 1
doc = _('capitalize(val) -- return value of the field capitalized')
__doc__ = doc = _('capitalize(val) -- return value of the field capitalized')
def evaluate(self, formatter, kwargs, mi, locals, val):
return capitalize(val)
@ -582,7 +583,7 @@ class BuiltinCapitalize(BuiltinFormatterFunction):
class BuiltinBooksize(BuiltinFormatterFunction):
name = 'booksize'
arg_count = 0
doc = _('booksize() -- return value of the size field')
__doc__ = doc = _('booksize() -- return value of the size field')
def evaluate(self, formatter, kwargs, mi, locals):
if mi.book_size is not None:
@ -595,7 +596,7 @@ class BuiltinBooksize(BuiltinFormatterFunction):
class BuiltinOndevice(BuiltinFormatterFunction):
name = 'ondevice'
arg_count = 0
doc = _('ondevice() -- return Yes if ondevice is set, otherwise return '
__doc__ = doc = _('ondevice() -- return Yes if ondevice is set, otherwise return '
'the empty string')
def evaluate(self, formatter, kwargs, mi, locals):
@ -606,7 +607,7 @@ class BuiltinOndevice(BuiltinFormatterFunction):
class BuiltinFirstNonEmpty(BuiltinFormatterFunction):
name = 'first_non_empty'
arg_count = -1
doc = _('first_non_empty(value, value, ...) -- '
__doc__ = doc = _('first_non_empty(value, value, ...) -- '
'returns the first value that is not empty. If all values are '
'empty, then the empty value is returned.'
'You can have as many values as you want.')
@ -622,7 +623,7 @@ class BuiltinFirstNonEmpty(BuiltinFormatterFunction):
class BuiltinAnd(BuiltinFormatterFunction):
name = 'and'
arg_count = -1
doc = _('and(value, value, ...) -- '
__doc__ = doc = _('and(value, value, ...) -- '
'returns the string "1" if all values are not empty, otherwise '
'returns the empty string. This function works well with test or '
'first_non_empty. You can have as many values as you want.')
@ -638,7 +639,7 @@ class BuiltinAnd(BuiltinFormatterFunction):
class BuiltinOr(BuiltinFormatterFunction):
name = 'or'
arg_count = -1
doc = _('or(value, value, ...) -- '
__doc__ = doc = _('or(value, value, ...) -- '
'returns the string "1" if any value is not empty, otherwise '
'returns the empty string. This function works well with test or '
'first_non_empty. You can have as many values as you want.')
@ -654,7 +655,7 @@ class BuiltinOr(BuiltinFormatterFunction):
class BuiltinNot(BuiltinFormatterFunction):
name = 'not'
arg_count = 1
doc = _('not(value) -- '
__doc__ = doc = _('not(value) -- '
'returns the string "1" if the value is empty, otherwise '
'returns the empty string. This function works well with test or '
'first_non_empty. You can have as many values as you want.')
@ -670,7 +671,7 @@ class BuiltinNot(BuiltinFormatterFunction):
class BuiltinMergeLists(BuiltinFormatterFunction):
name = 'merge_lists'
arg_count = 3
doc = _('merge_lists(list1, list2, separator) -- '
__doc__ = doc = _('merge_lists(list1, list2, separator) -- '
'return a list made by merging the items in list1 and list2, '
'removing duplicate items using a case-insensitive compare. If '
'items differ in case, the one in list1 is used. '