mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
...
This commit is contained in:
commit
0df278521a
@ -62,6 +62,7 @@ class SocialMetadata(QDialog):
|
||||
return
|
||||
if not self.worker.is_alive():
|
||||
self.accept()
|
||||
return
|
||||
QTimer.singleShot(50, self.update)
|
||||
|
||||
def accept(self):
|
||||
|
@ -25,37 +25,49 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
template function is written in python. It takes information from the
|
||||
book, processes it in some way, then returns a string result. Functions
|
||||
defined here are usable in templates in the same way that builtin
|
||||
functions are usable. The function must be named evaluate, and must
|
||||
have the signature shown below.</p>
|
||||
<p><code>evaluate(self, formatter, kwargs, mi, locals, your_arguments)
|
||||
functions are usable. The function must be named <b>evaluate</b>, and
|
||||
must have the signature shown below.</p>
|
||||
<p><code>evaluate(self, formatter, kwargs, mi, locals, your parameters)
|
||||
→ returning a unicode string</code></p>
|
||||
<p>The arguments to evaluate are:
|
||||
<p>The parameters of the evaluate function are:
|
||||
<ul>
|
||||
<li><b>formatter:</b> the instance of the formatter being used to
|
||||
<li><b>formatter</b>: the instance of the formatter being used to
|
||||
evaluate the current template. You can use this to do recursive
|
||||
template evaluation.</li>
|
||||
<li><b>kwargs:</b> a dictionary of metadata. Field values are in this
|
||||
dictionary. mi: a Metadata instance. Used to get field information.
|
||||
<li><b>kwargs</b>: a dictionary of metadata. Field values are in this
|
||||
dictionary.
|
||||
<li><b>mi</b>: a Metadata instance. Used to get field information.
|
||||
This parameter can be None in some cases, such as when evaluating
|
||||
non-book templates.</li>
|
||||
<li><b>locals:</b> the local variables assigned to by the current
|
||||
<li><b>locals</b>: the local variables assigned to by the current
|
||||
template program.</li>
|
||||
<li><b>Your_arguments</b> must be one or more parameter (number
|
||||
matching the arg count box), or the value *args for a variable number
|
||||
of arguments. These are values passed into the function. One argument
|
||||
is required, and is usually the value of the field being operated upon.
|
||||
Note that when writing in basic template mode, the user does not
|
||||
provide this first argument. Instead it is the value of the field the
|
||||
function is operating upon.</li>
|
||||
<li><b>your parameters</b>: You must supply one or more formal
|
||||
parameters. The number must match the arg count box, unless arg count is
|
||||
-1 (variable number or arguments), in which case the last argument must
|
||||
be *args. At least one argument is required, and is usually the value of
|
||||
the field being operated upon. Note that when writing in basic template
|
||||
mode, the user does not provide this first argument. Instead it is
|
||||
supplied by the formatter.</li>
|
||||
</ul></p>
|
||||
<p>
|
||||
The following example function looks for various values in the tags
|
||||
metadata field, returning those values that appear in tags.
|
||||
The following example function checks the value of the field. If the
|
||||
field is not empty, the field's value is returned, otherwise the value
|
||||
EMPTY is returned.
|
||||
<pre>
|
||||
name: my_ifempty
|
||||
arg count: 1
|
||||
doc: my_ifempty(val) -- return val if it is not empty, otherwise the string 'EMPTY'
|
||||
program code:
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||
awards=['allbooks', 'PBook', 'ggff']
|
||||
return ', '.join([t for t in kwargs.get('tags') if t in awards])
|
||||
</pre>
|
||||
if val:
|
||||
return val
|
||||
else:
|
||||
return 'EMPTY'</pre>
|
||||
This function can be called in any of the three template program modes:
|
||||
<ul>
|
||||
<li>single-function mode: {tags:my_ifempty()}</li>
|
||||
<li>template program mode: {tags:'my_ifempty($)'}</li>
|
||||
<li>general program mode: program: my_ifempty(field('tags'))</li>
|
||||
</p>
|
||||
''')
|
||||
self.textBrowser.setHtml(help_text)
|
||||
@ -67,14 +79,22 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.build_function_names_box()
|
||||
self.function_name.currentIndexChanged[str].connect(self.function_index_changed)
|
||||
self.function_name.editTextChanged.connect(self.function_name_edited)
|
||||
self.argument_count.valueChanged.connect(self.enable_replace_button)
|
||||
self.documentation.textChanged.connect(self.enable_replace_button)
|
||||
self.program.textChanged.connect(self.enable_replace_button)
|
||||
self.create_button.clicked.connect(self.create_button_clicked)
|
||||
self.delete_button.clicked.connect(self.delete_button_clicked)
|
||||
self.create_button.setEnabled(False)
|
||||
self.delete_button.setEnabled(False)
|
||||
self.replace_button.setEnabled(False)
|
||||
self.clear_button.clicked.connect(self.clear_button_clicked)
|
||||
self.replace_button.clicked.connect(self.replace_button_clicked)
|
||||
self.program.setTabStopWidth(20)
|
||||
self.highlighter = PythonHighlighter(self.program.document())
|
||||
|
||||
def enable_replace_button(self):
|
||||
self.replace_button.setEnabled(self.delete_button.isEnabled())
|
||||
|
||||
def clear_button_clicked(self):
|
||||
self.build_function_names_box()
|
||||
self.program.clear()
|
||||
@ -112,6 +132,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.create_button.setEnabled(True)
|
||||
self.delete_button.setEnabled(False)
|
||||
self.build_function_names_box(set_to=name)
|
||||
self.program.setReadOnly(False)
|
||||
else:
|
||||
error_dialog(self.gui, _('Template functions'),
|
||||
_('Function not defined'), show=True)
|
||||
@ -143,6 +164,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
self.documentation.setReadOnly(False)
|
||||
self.argument_count.setReadOnly(False)
|
||||
self.create_button.setEnabled(True)
|
||||
self.replace_button.setEnabled(False)
|
||||
self.program.setReadOnly(False)
|
||||
|
||||
def function_index_changed(self, txt):
|
||||
txt = unicode(txt)
|
||||
@ -156,15 +179,21 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
func = self.funcs[txt]
|
||||
self.argument_count.setValue(func.arg_count)
|
||||
self.documentation.setText(func.doc)
|
||||
self.program.setPlainText(func.program_text)
|
||||
if txt in self.builtins:
|
||||
self.documentation.setReadOnly(True)
|
||||
self.argument_count.setReadOnly(True)
|
||||
self.program.clear()
|
||||
self.program.setReadOnly(True)
|
||||
self.delete_button.setEnabled(False)
|
||||
else:
|
||||
self.program.setPlainText(func.program_text)
|
||||
self.delete_button.setEnabled(True)
|
||||
self.program.setReadOnly(False)
|
||||
self.replace_button.setEnabled(False)
|
||||
|
||||
def replace_button_clicked(self):
|
||||
self.delete_button_clicked()
|
||||
self.create_button_clicked()
|
||||
def refresh_gui(self, gui):
|
||||
pass
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="function_name">
|
||||
<property name="toolTip">
|
||||
<string>Enter the name of the function to create</string>
|
||||
<string>Enter the name of the function to create.</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
@ -48,7 +48,7 @@
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="toolTip">
|
||||
<string></string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Arg &count:</string>
|
||||
@ -100,6 +100,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="replace_button">
|
||||
<property name="text">
|
||||
<string>&Replace</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="create_button">
|
||||
<property name="text">
|
||||
@ -144,8 +151,7 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTextBrowser" name="textBrowser">
|
||||
</widget>
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -96,7 +96,7 @@ class _Parser(object):
|
||||
# classic assignment statement
|
||||
self.consume()
|
||||
cls = funcs['assign']
|
||||
return cls.eval(self.parent, self.parent.kwargs,
|
||||
return cls.eval_(self.parent, self.parent.kwargs,
|
||||
self.parent.book, self.parent.locals, id, self.expr())
|
||||
return self.parent.locals.get(id, _('unknown id ') + id)
|
||||
# We have a function.
|
||||
@ -130,7 +130,7 @@ class _Parser(object):
|
||||
cls = funcs[id]
|
||||
if cls.arg_count != -1 and len(args) != cls.arg_count:
|
||||
self.error('incorrect number of arguments for function {}'.format(id))
|
||||
return cls.eval(self.parent, self.parent.kwargs,
|
||||
return cls.eval_(self.parent, self.parent.kwargs,
|
||||
self.parent.book, self.parent.locals, *args)
|
||||
else:
|
||||
f = self.parent.functions[id]
|
||||
@ -284,14 +284,13 @@ class TemplateFormatter(string.Formatter):
|
||||
else:
|
||||
args = self.arg_parser.scan(fmt[p+1:])[0]
|
||||
args = [self.backslash_comma_to_comma.sub(',', a) for a in args]
|
||||
if (func.arg_count == 1 and (len(args) != 0)) or \
|
||||
if (func.arg_count == 1 and (len(args) != 1 or args[0])) or \
|
||||
(func.arg_count > 1 and func.arg_count != len(args)+1):
|
||||
print args
|
||||
raise ValueError('Incorrect number of arguments for function '+ fmt[0:p])
|
||||
if func.arg_count == 1:
|
||||
val = func.eval(self, self.kwargs, self.book, self.locals, val).strip()
|
||||
val = func.eval_(self, self.kwargs, self.book, self.locals, val).strip()
|
||||
else:
|
||||
val = func.eval(self, self.kwargs, self.book, self.locals,
|
||||
val = func.eval_(self, self.kwargs, self.book, self.locals,
|
||||
val, *args).strip()
|
||||
if val:
|
||||
val = self._do_format(val, dispfmt)
|
||||
|
@ -8,7 +8,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re, traceback
|
||||
import inspect, re, traceback, sys
|
||||
|
||||
from calibre.utils.titlecase import titlecase
|
||||
from calibre.utils.icu import capitalize, strcmp
|
||||
@ -58,13 +58,10 @@ class FormatterFunction(object):
|
||||
name = 'no name provided'
|
||||
arg_count = 0
|
||||
|
||||
def __init__(self):
|
||||
formatter_functions.register_builtin(self)
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, *args):
|
||||
raise NotImplementedError()
|
||||
|
||||
def eval(self, formatter, kwargs, mi, locals, *args):
|
||||
def eval_(self, formatter, kwargs, mi, locals, *args):
|
||||
try:
|
||||
ret = self.evaluate(formatter, kwargs, mi, locals, *args)
|
||||
if isinstance(ret, (str, unicode)):
|
||||
@ -75,9 +72,21 @@ class FormatterFunction(object):
|
||||
return ','.join(list)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return _('Function threw exception' + traceback.format_exc())
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
info = ': '.join(traceback.format_exception(exc_type, exc_value,
|
||||
exc_traceback)[-2:]).replace('\n', '')
|
||||
return _('Exception ' + info)
|
||||
|
||||
class BuiltinStrcmp(FormatterFunction):
|
||||
|
||||
class BuiltinFormatterFunction(FormatterFunction):
|
||||
def __init__(self):
|
||||
formatter_functions.register_builtin(self)
|
||||
eval_func = inspect.getmembers(self.__class__,
|
||||
lambda x: inspect.ismethod(x) and x.__name__ == 'evaluate')
|
||||
lines = [l[4:] for l in inspect.getsourcelines(eval_func[0][1])[0]]
|
||||
self.program_text = ''.join(lines)
|
||||
|
||||
class BuiltinStrcmp(BuiltinFormatterFunction):
|
||||
name = 'strcmp'
|
||||
arg_count = 5
|
||||
doc = _('strcmp(x, y, lt, eq, gt) -- does a case-insensitive comparison of x '
|
||||
@ -92,7 +101,7 @@ class BuiltinStrcmp(FormatterFunction):
|
||||
return eq
|
||||
return gt
|
||||
|
||||
class BuiltinCmp(FormatterFunction):
|
||||
class BuiltinCmp(BuiltinFormatterFunction):
|
||||
name = 'cmp'
|
||||
arg_count = 5
|
||||
doc = _('cmp(x, y, lt, eq, gt) -- compares x and y after converting both to '
|
||||
@ -107,7 +116,7 @@ class BuiltinCmp(FormatterFunction):
|
||||
return eq
|
||||
return gt
|
||||
|
||||
class BuiltinStrcat(FormatterFunction):
|
||||
class BuiltinStrcat(BuiltinFormatterFunction):
|
||||
name = 'strcat'
|
||||
arg_count = -1
|
||||
doc = _('strcat(a, b, ...) -- can take any number of arguments. Returns a '
|
||||
@ -120,7 +129,7 @@ class BuiltinStrcat(FormatterFunction):
|
||||
res += args[i]
|
||||
return res
|
||||
|
||||
class BuiltinAdd(FormatterFunction):
|
||||
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.')
|
||||
@ -130,7 +139,7 @@ class BuiltinAdd(FormatterFunction):
|
||||
y = float(y if y else 0)
|
||||
return unicode(x + y)
|
||||
|
||||
class BuiltinSubtract(FormatterFunction):
|
||||
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.')
|
||||
@ -140,7 +149,7 @@ class BuiltinSubtract(FormatterFunction):
|
||||
y = float(y if y else 0)
|
||||
return unicode(x - y)
|
||||
|
||||
class BuiltinMultiply(FormatterFunction):
|
||||
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.')
|
||||
@ -150,7 +159,7 @@ class BuiltinMultiply(FormatterFunction):
|
||||
y = float(y if y else 0)
|
||||
return unicode(x * y)
|
||||
|
||||
class BuiltinDivide(FormatterFunction):
|
||||
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.')
|
||||
@ -160,7 +169,7 @@ class BuiltinDivide(FormatterFunction):
|
||||
y = float(y if y else 0)
|
||||
return unicode(x / y)
|
||||
|
||||
class BuiltinTemplate(FormatterFunction):
|
||||
class BuiltinTemplate(BuiltinFormatterFunction):
|
||||
name = 'template'
|
||||
arg_count = 1
|
||||
doc = _('template(x) -- evaluates x as a template. The evaluation is done '
|
||||
@ -168,17 +177,17 @@ class BuiltinTemplate(FormatterFunction):
|
||||
'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 '
|
||||
'For example, template(\'[[title_sort]]\') will evaluate the '
|
||||
'template {title_sort} and return its value.')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, template):
|
||||
template = template.replace('[[', '{').replace(']]', '}')
|
||||
return formatter.safe_format(template, kwargs, 'TEMPLATE', mi)
|
||||
|
||||
class BuiltinEval(FormatterFunction):
|
||||
class BuiltinEval(BuiltinFormatterFunction):
|
||||
name = 'eval'
|
||||
arg_count = 1
|
||||
doc = _('eval(template)`` -- evaluates the template, passing the local '
|
||||
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.')
|
||||
@ -188,7 +197,7 @@ class BuiltinEval(FormatterFunction):
|
||||
template = template.replace('[[', '{').replace(']]', '}')
|
||||
return eval_formatter.safe_format(template, locals, 'EVAL', None)
|
||||
|
||||
class BuiltinAssign(FormatterFunction):
|
||||
class BuiltinAssign(BuiltinFormatterFunction):
|
||||
name = 'assign'
|
||||
arg_count = 2
|
||||
doc = _('assign(id, val) -- assigns val to id, then returns val. '
|
||||
@ -198,7 +207,7 @@ class BuiltinAssign(FormatterFunction):
|
||||
locals[target] = value
|
||||
return value
|
||||
|
||||
class BuiltinPrint(FormatterFunction):
|
||||
class BuiltinPrint(BuiltinFormatterFunction):
|
||||
name = 'print'
|
||||
arg_count = -1
|
||||
doc = _('print(a, b, ...) -- prints the arguments to standard output. '
|
||||
@ -209,7 +218,7 @@ class BuiltinPrint(FormatterFunction):
|
||||
print args
|
||||
return None
|
||||
|
||||
class BuiltinField(FormatterFunction):
|
||||
class BuiltinField(BuiltinFormatterFunction):
|
||||
name = 'field'
|
||||
arg_count = 1
|
||||
doc = _('field(name) -- returns the metadata field named by name')
|
||||
@ -217,7 +226,7 @@ class BuiltinField(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, name):
|
||||
return formatter.get_value(name, [], kwargs)
|
||||
|
||||
class BuiltinSubstr(FormatterFunction):
|
||||
class BuiltinSubstr(BuiltinFormatterFunction):
|
||||
name = 'substr'
|
||||
arg_count = 3
|
||||
doc = _('substr(str, start, end) -- returns the start\'th through the end\'th '
|
||||
@ -230,7 +239,7 @@ class BuiltinSubstr(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, str_, start_, end_):
|
||||
return str_[int(start_): len(str_) if int(end_) == 0 else int(end_)]
|
||||
|
||||
class BuiltinLookup(FormatterFunction):
|
||||
class BuiltinLookup(BuiltinFormatterFunction):
|
||||
name = 'lookup'
|
||||
arg_count = -1
|
||||
doc = _('lookup(val, pattern, field, pattern, field, ..., else_field) -- '
|
||||
@ -257,7 +266,7 @@ class BuiltinLookup(FormatterFunction):
|
||||
return formatter.vformat('{'+args[i+1].strip() + '}', [], kwargs)
|
||||
i += 2
|
||||
|
||||
class BuiltinTest(FormatterFunction):
|
||||
class BuiltinTest(BuiltinFormatterFunction):
|
||||
name = 'test'
|
||||
arg_count = 3
|
||||
doc = _('test(val, text if not empty, text if empty) -- return `text if not '
|
||||
@ -269,7 +278,7 @@ class BuiltinTest(FormatterFunction):
|
||||
else:
|
||||
return value_not_set
|
||||
|
||||
class BuiltinContains(FormatterFunction):
|
||||
class BuiltinContains(BuiltinFormatterFunction):
|
||||
name = 'contains'
|
||||
arg_count = 4
|
||||
doc = _('contains(val, pattern, text if match, text if not match) -- checks '
|
||||
@ -284,13 +293,13 @@ class BuiltinContains(FormatterFunction):
|
||||
else:
|
||||
return value_if_not
|
||||
|
||||
class BuiltinSwitch(FormatterFunction):
|
||||
class BuiltinSwitch(BuiltinFormatterFunction):
|
||||
name = 'switch'
|
||||
arg_count = -1
|
||||
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. '
|
||||
'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. '
|
||||
'You can have as many `pattern, value` pairs as you want')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val, *args):
|
||||
@ -304,7 +313,7 @@ class BuiltinSwitch(FormatterFunction):
|
||||
return args[i+1]
|
||||
i += 2
|
||||
|
||||
class BuiltinRe(FormatterFunction):
|
||||
class BuiltinRe(BuiltinFormatterFunction):
|
||||
name = 're'
|
||||
arg_count = 3
|
||||
doc = _('re(val, pattern, replacement) -- return the field after applying '
|
||||
@ -315,10 +324,10 @@ class BuiltinRe(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val, pattern, replacement):
|
||||
return re.sub(pattern, replacement, val)
|
||||
|
||||
class BuiltinEvaluate(FormatterFunction):
|
||||
name = 'evaluate'
|
||||
class BuiltinIfempty(BuiltinFormatterFunction):
|
||||
name = 'ifempty'
|
||||
arg_count = 2
|
||||
doc = _('evaluate(val, text if empty) -- return val if val is not empty, '
|
||||
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):
|
||||
@ -327,7 +336,7 @@ class BuiltinEvaluate(FormatterFunction):
|
||||
else:
|
||||
return value_if_empty
|
||||
|
||||
class BuiltinShorten(FormatterFunction):
|
||||
class BuiltinShorten(BuiltinFormatterFunction):
|
||||
name = 'shorten'
|
||||
arg_count = 4
|
||||
doc = _('shorten(val, left chars, middle text, right chars) -- Return a '
|
||||
@ -352,7 +361,7 @@ class BuiltinShorten(FormatterFunction):
|
||||
else:
|
||||
return val
|
||||
|
||||
class BuiltinCount(FormatterFunction):
|
||||
class BuiltinCount(BuiltinFormatterFunction):
|
||||
name = 'count'
|
||||
arg_count = 2
|
||||
doc = _('count(val, separator) -- interprets the value as a list of items '
|
||||
@ -363,7 +372,7 @@ class BuiltinCount(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val, sep):
|
||||
return unicode(len(val.split(sep)))
|
||||
|
||||
class BuiltinListitem(FormatterFunction):
|
||||
class BuiltinListitem(BuiltinFormatterFunction):
|
||||
name = 'list_item'
|
||||
arg_count = 3
|
||||
doc = _('list_item(val, index, separator) -- interpret the value as a list of '
|
||||
@ -383,7 +392,7 @@ class BuiltinListitem(FormatterFunction):
|
||||
except:
|
||||
return ''
|
||||
|
||||
class BuiltinUppercase(FormatterFunction):
|
||||
class BuiltinUppercase(BuiltinFormatterFunction):
|
||||
name = 'uppercase'
|
||||
arg_count = 1
|
||||
doc = _('uppercase(val) -- return value of the field in upper case')
|
||||
@ -391,7 +400,7 @@ class BuiltinUppercase(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||
return val.upper()
|
||||
|
||||
class BuiltinLowercase(FormatterFunction):
|
||||
class BuiltinLowercase(BuiltinFormatterFunction):
|
||||
name = 'lowercase'
|
||||
arg_count = 1
|
||||
doc = _('lowercase(val) -- return value of the field in lower case')
|
||||
@ -399,7 +408,7 @@ class BuiltinLowercase(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||
return val.lower()
|
||||
|
||||
class BuiltinTitlecase(FormatterFunction):
|
||||
class BuiltinTitlecase(BuiltinFormatterFunction):
|
||||
name = 'titlecase'
|
||||
arg_count = 1
|
||||
doc = _('titlecase(val) -- return value of the field in title case')
|
||||
@ -407,7 +416,7 @@ class BuiltinTitlecase(FormatterFunction):
|
||||
def evaluate(self, formatter, kwargs, mi, locals, val):
|
||||
return titlecase(val)
|
||||
|
||||
class BuiltinCapitalize(FormatterFunction):
|
||||
class BuiltinCapitalize(BuiltinFormatterFunction):
|
||||
name = 'capitalize'
|
||||
arg_count = 1
|
||||
doc = _('capitalize(val) -- return value of the field capitalized')
|
||||
@ -423,7 +432,7 @@ builtin_contains = BuiltinContains()
|
||||
builtin_count = BuiltinCount()
|
||||
builtin_divide = BuiltinDivide()
|
||||
builtin_eval = BuiltinEval()
|
||||
builtin_evaluate = BuiltinEvaluate()
|
||||
builtin_ifempty = BuiltinIfempty()
|
||||
builtin_field = BuiltinField()
|
||||
builtin_list_item = BuiltinListitem()
|
||||
builtin_lookup = BuiltinLookup()
|
||||
|
Loading…
x
Reference in New Issue
Block a user