diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py
index 10fdff75b5..b2323c63c2 100644
--- a/src/calibre/gui2/dialogs/template_dialog.py
+++ b/src/calibre/gui2/dialogs/template_dialog.py
@@ -397,9 +397,6 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(_('&OK'))
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel'))
- self.textbox.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
- self.textbox.customContextMenuRequested.connect(self.show_context_menu)
-
self.color_copy_button.clicked.connect(self.color_to_clipboard)
self.filename_button.clicked.connect(self.filename_button_clicked)
self.icon_copy_button.clicked.connect(self.icon_to_clipboard)
@@ -443,6 +440,9 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.set_up_font_boxes()
self.toggle_button.clicked.connect(self.toggle_button_pressed)
self.remove_all_button.clicked.connect(self.remove_all_button_pressed)
+
+ self.load_button.clicked.connect(self.load_template)
+ self.save_button.clicked.connect(self.save_template)
# Now geometry
try:
geom = gprefs.get('template_editor_dialog_geometry', None)
@@ -451,15 +451,6 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
except Exception:
pass
- def show_context_menu(self, point):
- m = self.textbox.createStandardContextMenu()
- m.addSeparator()
- ca = m.addAction(_('Load template from file'))
- ca.triggered.connect(self.load_template)
- ca = m.addAction(_('Save template to file'))
- ca.triggered.connect(self.store_template)
- m.exec_(self.textbox.mapToGlobal(point))
-
def load_template(self):
filename = choose_files(self, 'template_dialog_save_templates',
_('Load template from file'),
@@ -470,7 +461,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
with open(filename[0], 'r') as f:
self.textbox.setPlainText(f.read())
- def store_template(self):
+ def save_template(self):
filename = choose_save_file(self, 'template_dialog_save_templates',
_('Save template to file'),
filters=[
diff --git a/src/calibre/gui2/dialogs/template_dialog.ui b/src/calibre/gui2/dialogs/template_dialog.ui
index 937c603edb..974c823343 100644
--- a/src/calibre/gui2/dialogs/template_dialog.ui
+++ b/src/calibre/gui2/dialogs/template_dialog.ui
@@ -274,12 +274,12 @@ you the value as well as all the local variables</p>
999
-
- 1
-
-
- Qt::AlignRight
-
+
+ 1
+
+
+ Qt::AlignRight
+
-
@@ -330,6 +330,12 @@ you the value as well as all the local variables</p>
The template program text
+
+
+ 0
+ 1
+
+
-
@@ -523,7 +529,7 @@ you the value as well as all the local variables</p>
-
- Current font:
+ Font:
font_box
@@ -557,14 +563,51 @@ you the value as well as all the local variables</p>
-
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
+
+
-
+
+
+ QFrame::VLine
+
+
+ QFrame::Raised
+
+
+ 3
+
+
+
+ -
+
+
+ Lo&ad
+
+
+ Load the template from a file
+
+
+
+ -
+
+
+ &Save
+
+
+ Save the template in a file
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
-
diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py
index c5c0ac4182..07da6ee481 100644
--- a/src/calibre/utils/formatter.py
+++ b/src/calibre/utils/formatter.py
@@ -41,19 +41,23 @@ class Node(object):
NODE_BINARY_ARITHOP = 19
NODE_UNARY_ARITHOP = 20
NODE_PRINT = 21
- NODE_LINE_NUMBER = 22
def __init__(self, line_number, name):
- self.line_number = line_number
+ self.my_line_number = line_number
self.my_node_name = name
+ @property
def node_name(self):
return self.my_node_name
+ @property
+ def line_number(self):
+ return self.my_line_number
+
class IfNode(Node):
def __init__(self, line_number, condition, then_part, else_part):
- Node.__init__(self, line_number, 'IF')
+ Node.__init__(self, line_number, 'if ...')
self.node_type = self.NODE_IF
self.condition = condition
self.then_part = then_part
@@ -62,7 +66,7 @@ class IfNode(Node):
class ForNode(Node):
def __init__(self, line_number, variable, list_field_expr, separator, block):
- Node.__init__(self, line_number, 'FOR')
+ Node.__init__(self, line_number, 'for ...:')
self.node_type = self.NODE_FOR
self.variable = variable
self.list_field_expr = list_field_expr
@@ -72,7 +76,7 @@ class ForNode(Node):
class AssignNode(Node):
def __init__(self, line_number, left, right):
- Node.__init__(self, line_number, 'ASSIGN')
+ Node.__init__(self, line_number, 'assign to ' + left)
self.node_type = self.NODE_ASSIGN
self.left = left
self.right = right
@@ -80,7 +84,7 @@ class AssignNode(Node):
class FunctionNode(Node):
def __init__(self, line_number, function_name, expression_list):
- Node.__init__(self, line_number, 'FUNCTION CALL')
+ Node.__init__(self, line_number, function_name + '()')
self.node_type = self.NODE_FUNC
self.name = function_name
self.expression_list = expression_list
@@ -88,7 +92,7 @@ class FunctionNode(Node):
class CallNode(Node):
def __init__(self, line_number, function, expression_list):
- Node.__init__(self, line_number, 'TEMPLATE CALL')
+ Node.__init__(self, line_number, 'call template: ' + function)
self.node_type = self.NODE_CALL
self.function = function
self.expression_list = expression_list
@@ -96,28 +100,28 @@ class CallNode(Node):
class ArgumentsNode(Node):
def __init__(self, line_number, expression_list):
- Node.__init__(self, line_number, 'ARGUMENTS')
+ Node.__init__(self, line_number, 'arguments()')
self.node_type = self.NODE_ARGUMENTS
self.expression_list = expression_list
class GlobalsNode(Node):
def __init__(self, line_number, expression_list):
- Node.__init__(self, line_number, 'GLOBALS')
+ Node.__init__(self, line_number, 'globals()')
self.node_type = self.NODE_GLOBALS
self.expression_list = expression_list
class SetGlobalsNode(Node):
def __init__(self, line_number, expression_list):
- Node.__init__(self, line_number, 'SET_GLOBALS')
+ Node.__init__(self, line_number, 'set_globals()')
self.node_type = self.NODE_SET_GLOBALS
self.expression_list = expression_list
class StringCompareNode(Node):
def __init__(self, line_number, operator, left, right):
- Node.__init__(self, line_number, 'COMPARE STRING')
+ Node.__init__(self, line_number, 'comparision: ' + operator)
self.node_type = self.NODE_COMPARE_STRING
self.operator = operator
self.left = left
@@ -126,7 +130,7 @@ class StringCompareNode(Node):
class NumericCompareNode(Node):
def __init__(self, line_number, operator, left, right):
- Node.__init__(self, line_number, 'COMPARE NUMBERS')
+ Node.__init__(self, line_number, 'comparison: ' + operator)
self.node_type = self.NODE_COMPARE_NUMERIC
self.operator = operator
self.left = left
@@ -135,7 +139,7 @@ class NumericCompareNode(Node):
class LogopBinaryNode(Node):
def __init__(self, line_number, operator, left, right):
- Node.__init__(self, line_number, 'BINARY LOGICAL OP')
+ Node.__init__(self, line_number, 'binary operator: ' + operator)
self.node_type = self.NODE_BINARY_LOGOP
self.operator = operator
self.left = left
@@ -144,7 +148,7 @@ class LogopBinaryNode(Node):
class LogopUnaryNode(Node):
def __init__(self, line_number, operator, expr):
- Node.__init__(self, line_number, 'UNARY LOGICAL OP')
+ Node.__init__(self, line_number, 'unary operator: ' + operator)
self.node_type = self.NODE_UNARY_LOGOP
self.operator = operator
self.expr = expr
@@ -152,7 +156,7 @@ class LogopUnaryNode(Node):
class NumericBinaryNode(Node):
def __init__(self, line_number, operator, left, right):
- Node.__init__(self, line_number, 'BINARY ARITHMETIC OP')
+ Node.__init__(self, line_number, 'binary operator: ' + operator)
self.node_type = self.NODE_BINARY_ARITHOP
self.operator = operator
self.left = left
@@ -161,7 +165,7 @@ class NumericBinaryNode(Node):
class NumericUnaryNode(Node):
def __init__(self, line_number, operator, expr):
- Node.__init__(self, line_number, 'UNARY ARITHMETIC OP')
+ Node.__init__(self, line_number, 'unary operator: '+ operator)
self.node_type = self.NODE_UNARY_ARITHOP
self.operator = operator
self.expr = expr
@@ -169,28 +173,28 @@ class NumericUnaryNode(Node):
class ConstantNode(Node):
def __init__(self, line_number, value):
- Node.__init__(self, line_number, 'CONSTANT')
+ Node.__init__(self, line_number, 'constant: ' + value)
self.node_type = self.NODE_CONSTANT
self.value = value
class VariableNode(Node):
def __init__(self, line_number, name):
- Node.__init__(self, line_number, 'VARIABLE')
+ Node.__init__(self, line_number, 'variable: ' + name)
self.node_type = self.NODE_RVALUE
self.name = name
class FieldNode(Node):
def __init__(self, line_number, expression):
- Node.__init__(self, line_number, 'FIELD FUNCTION')
+ Node.__init__(self, line_number, 'field()')
self.node_type = self.NODE_FIELD
self.expression = expression
class RawFieldNode(Node):
def __init__(self, line_number, expression, default=None):
- Node.__init__(self, line_number, 'RAW_FIELD FUNCTION')
+ Node.__init__(self, line_number, 'raw_field()')
self.node_type = self.NODE_RAW_FIELD
self.expression = expression
self.default = default
@@ -198,14 +202,14 @@ class RawFieldNode(Node):
class FirstNonEmptyNode(Node):
def __init__(self, line_number, expression_list):
- Node.__init__(self, line_number, 'FIRST_NON_EMPTY FUNCTION')
+ Node.__init__(self, line_number, 'first_non_empty()')
self.node_type = self.NODE_FIRST_NON_EMPTY
self.expression_list = expression_list
class ContainsNode(Node):
def __init__(self, line_number, arguments):
- Node.__init__(self, line_number, 'CONTAINS FUNCTION')
+ Node.__init__(self, line_number, 'contains()')
self.node_type = self.NODE_CONTAINS
self.value_expression = arguments[0]
self.test_expression = arguments[1]
@@ -215,17 +219,11 @@ class ContainsNode(Node):
class PrintNode(Node):
def __init__(self, line_number, arguments):
- Node.__init__(self, line_number, 'PRINT')
+ Node.__init__(self, line_number, 'print')
self.node_type = self.NODE_PRINT
self.arguments = arguments
-class LineNumberNode(Node):
- def __init__(self, line_number):
- Node.__init__(self, line_number, 'LINE NUMBER')
- self.node_type = self.NODE_LINE_NUMBER
-
-
class _Parser(object):
LEX_OP = 1
LEX_ID = 2
@@ -513,7 +511,6 @@ class _Parser(object):
while True:
while self.token_is_newline():
self.line_number += 1
- expr_list.append(LineNumberNode(self.line_number))
self.consume()
if self.token_is_eof():
break
@@ -529,7 +526,7 @@ class _Parser(object):
line_number = self.line_number
condition = self.top_expr()
if not self.token_is_then():
- self.error(_("Missing 'then' in if statement"))
+ self.error(_("Expected '%s' in '%s' statement")%('then', 'if'))
self.consume()
then_part = self.expression_list()
if self.token_is_elif():
@@ -540,17 +537,18 @@ class _Parser(object):
else:
else_part = None
if not self.token_is_fi():
- self.error(_("Missing 'fi' in if statement"))
+ self.error(_("Expected '%s' in '%s' statement")%('fi', 'if'))
self.consume()
return IfNode(line_number, condition, then_part, else_part)
def for_expression(self):
+ line_number = self.line_number
self.consume()
if not self.token_is_id():
- self.error(_("Missing identifier in for statement"))
+ self.error(_("Expected identifier in '%s' statement")%'for')
variable = self.token()
if not self.token_is_in():
- self.error(_("Missing 'in' in for statement"))
+ self.error(_("Expected '%s' in '%s' statement")%('in', 'for'))
self.consume()
list_expr = self.top_expr()
if self.token_is_separator():
@@ -559,13 +557,13 @@ class _Parser(object):
else:
separator = None
if not self.token_op_is_colon():
- self.error(_("Missing colon (':') in for statement"))
+ self.error(_("Expected colon in '%s' statement")%'for')
self.consume()
block = self.expression_list()
if not self.token_is_rof():
- self.error(_("Missing 'rof' in for statement"))
+ self.error(_("Expected '%s' in '%s' statement")%('rof', 'for'))
self.consume()
- return ForNode(self.line_number, variable, list_expr, separator, block)
+ return ForNode(line_number, variable, list_expr, separator, block)
def top_expr(self):
return self.or_expr()
@@ -644,7 +642,7 @@ class _Parser(object):
self.consume()
rv = self.expression_list()
if not self.token_op_is_rparen():
- self.error(_('Missing )'))
+ self.error(_("Expected a right parenthesis"))
self.consume()
return rv
if self.token_is_if():
@@ -652,19 +650,20 @@ class _Parser(object):
if self.token_is_for():
return self.for_expression()
if self.token_is_id():
+ line_number = self.line_number
id_ = self.token()
# We have an identifier. Check if it is a field reference
if len(id_) > 1 and id_[0] == '$':
if id_[1] == '$':
- return RawFieldNode(self.line_number, ConstantNode(self.line_number, id_[2:]))
- return FieldNode(self.line_number, ConstantNode(self.line_number, id_[1:]))
+ return RawFieldNode(line_number, ConstantNode(self.line_number, id_[2:]))
+ return FieldNode(line_number, ConstantNode(self.line_number, id_[1:]))
# Determine if it is a function
if not self.token_op_is_lparen():
if self.token_op_is_equals():
# classic assignment statement
self.consume()
- return AssignNode(self.line_number, id_, self.top_expr())
- return VariableNode(self.line_number, id_)
+ return AssignNode(line_number, id_, self.top_expr())
+ return VariableNode(line_number, id_)
# We have a function.
# Check if it is a known one. We do this here so error reporting is
@@ -682,17 +681,17 @@ class _Parser(object):
break
self.consume()
if self.token() != ')':
- self.error(_('Missing closing parenthesis'))
+ self.error(_("Expected a closing right parenthesis for function call"))
if id_ == 'field' and len(arguments) == 1:
- return FieldNode(self.line_number, arguments[0])
+ return FieldNode(line_number, arguments[0])
if id_ == 'raw_field' and (len(arguments) in (1, 2)):
- return RawFieldNode(self.line_number, *arguments)
+ return RawFieldNode(line_number, *arguments)
if id_ == 'test' and len(arguments) == 3:
- return IfNode(self.line_number, arguments[0], (arguments[1],), (arguments[2],))
+ return IfNode(line_number, arguments[0], (arguments[1],), (arguments[2],))
if id_ == 'first_non_empty' and len(arguments) > 0:
- return FirstNonEmptyNode(self.line_number, arguments)
+ return FirstNonEmptyNode(line_number, arguments)
if (id_ == 'assign' and len(arguments) == 2 and arguments[0].node_type == Node.NODE_RVALUE):
- return AssignNode(self.line_number, arguments[0].name, arguments[1])
+ return AssignNode(line_number, arguments[0].name, arguments[1])
if id_ == 'arguments' or id_ == 'globals' or id_ == 'set_globals':
new_args = []
for arg_list in arguments:
@@ -701,23 +700,23 @@ class _Parser(object):
self.error(_("Parameters to '{}' must be "
"variables or assignments").format(id_))
if arg.node_type == Node.NODE_RVALUE:
- arg = AssignNode(self.line_number, arg.name, ConstantNode(self.line_number, ''))
+ arg = AssignNode(line_number, arg.name, ConstantNode(self.line_number, ''))
new_args.append(arg)
if id_ == 'arguments':
- return ArgumentsNode(self.line_number, new_args)
+ return ArgumentsNode(line_number, new_args)
if id_ == 'set_globals':
- return SetGlobalsNode(self.line_number, new_args)
- return GlobalsNode(self.line_number, new_args)
+ return SetGlobalsNode(line_number, new_args)
+ return GlobalsNode(line_number, new_args)
if id_ == 'contains' and len(arguments) == 4:
- return ContainsNode(self.line_number, arguments)
+ return ContainsNode(line_number, arguments)
if id_ == 'print':
- return PrintNode(self.line_number, arguments)
+ return PrintNode(line_number, arguments)
if id_ in self.func_names and not self.funcs[id_].is_python:
return self.call_expression(id_, arguments)
cls = self.funcs[id_]
if cls.arg_count != -1 and len(arguments) != cls.arg_count:
self.error(_('Incorrect number of arguments for function {0}').format(id_))
- return FunctionNode(self.line_number, id_, arguments)
+ return FunctionNode(line_number, id_, arguments)
elif self.token_is_constant():
# String or number
return ConstantNode(self.line_number, self.token())
@@ -726,8 +725,8 @@ class _Parser(object):
class _Interpreter(object):
- def error(self, message):
- m = _('Interpreter: {0} - line number {1}').format(message, self.line_number)
+ def error(self, message, line_number):
+ m = _('Interpreter: {0} - line number {1}').format(message, line_number)
raise ValueError(m)
def program(self, funcs, parent, prog, val, is_call=False, args=None,
@@ -735,7 +734,6 @@ class _Interpreter(object):
self.parent = parent
self.parent_kwargs = parent.kwargs
self.parent_book = parent.book
- self.line_number = 1
self.funcs = funcs
self.locals = {'$':val}
self.global_vars = global_vars if isinstance(global_vars, dict) else {}
@@ -746,21 +744,16 @@ class _Interpreter(object):
self.break_reporter = None
if is_call:
- return self.do_node_call(CallNode(self.line_number, prog, None), args=args)
+ return self.do_node_call(CallNode(1, prog, None), args=args)
return self.expression_list(prog)
- def call_break_reporter(self, txt, val, line_number=None):
- self.real_break_reporter(txt, val, self.locals,
- line_number if line_number else self.line_number)
+ def call_break_reporter(self, txt, val, line_number):
+ self.real_break_reporter(txt, val, self.locals, line_number)
def expression_list(self, prog):
val = ''
for p in prog:
val = self.expr(p)
- if (self.break_reporter and
- p.node_type != Node.NODE_LINE_NUMBER and
- p.node_type != Node.NODE_IF):
- self.break_reporter(p.node_name(), val)
return val
INFIX_STRING_COMPARE_OPS = {
@@ -777,9 +770,14 @@ class _Interpreter(object):
try:
left = self.expr(prog.left)
right = self.expr(prog.right)
- return ('1' if self.INFIX_STRING_COMPARE_OPS[prog.operator](left, right) else '')
+ res = '1' if self.INFIX_STRING_COMPARE_OPS[prog.operator](left, right) else ''
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Error during string comparison. Operator {0}').format(prog.operator))
+ self.error(
+ _('Error during string comparison. Operator {0}').format(prog.operator),
+ prog.line_number)
INFIX_NUMERIC_COMPARE_OPS = {
"==#": lambda x, y: x == y,
@@ -799,32 +797,40 @@ class _Interpreter(object):
try:
left = self.float_deal_with_none(self.expr(prog.left))
right = self.float_deal_with_none(self.expr(prog.right))
- return '1' if self.INFIX_NUMERIC_COMPARE_OPS[prog.operator](left, right) else ''
+ res = '1' if self.INFIX_NUMERIC_COMPARE_OPS[prog.operator](left, right) else ''
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Value used in comparison is not a number. Operator {0}').format(prog.operator))
+ self.error(
+ _('Value used in comparison is not a number. Operator {0}').format(prog.operator),
+ prog.line_number)
def do_node_if(self, prog):
line_number = prog.line_number
test_part = self.expr(prog.condition)
if self.break_reporter:
- self.break_reporter('if: condition', test_part, line_number=line_number)
+ self.break_reporter("'if': condition value", test_part, line_number)
if test_part:
v = self.expression_list(prog.then_part)
if self.break_reporter:
- self.break_reporter('if: then part', v, line_number=line_number)
+ self.break_reporter("'if': then-block value", v, line_number)
return v
elif prog.else_part:
v = self.expression_list(prog.else_part)
if self.break_reporter:
- self.break_reporter('if: else part', v, line_number=line_number)
+ self.break_reporter("'if': else-block value", v, line_number)
return v
return ''
def do_node_rvalue(self, prog):
try:
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, self.locals[prog.name], prog.line_number)
return self.locals[prog.name]
except:
- self.error(_('Unknown identifier {0}').format(prog.name))
+ self.error(_('Unknown identifier {0}').format(prog.name),
+ prog.line_number)
def do_node_func(self, prog):
args = list()
@@ -834,8 +840,11 @@ class _Interpreter(object):
# Evaluate the function.
id_ = prog.name.strip()
cls = self.funcs[id_]
- return cls.eval_(self.parent, self.parent_kwargs,
+ res = cls.eval_(self.parent, self.parent_kwargs,
self.parent_book, self.locals, *args)
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
def do_node_call(self, prog, args=None):
if args is None:
@@ -849,53 +858,78 @@ class _Interpreter(object):
self.locals['*arg_'+ str(dex)] = v
val = self.expression_list(prog.function)
self.locals = saved_locals
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, val, prog.line_number)
return val
def do_node_arguments(self, prog):
for dex, arg in enumerate(prog.expression_list):
self.locals[arg.left] = self.locals.get('*arg_'+ str(dex), self.expr(arg.right))
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, '', prog.line_number)
return ''
def do_node_globals(self, prog):
res = ''
for arg in prog.expression_list:
res = self.locals[arg.left] = self.global_vars.get(arg.left, self.expr(arg.right))
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
return res
def do_node_set_globals(self, prog):
res = ''
for arg in prog.expression_list:
res = self.global_vars[arg.left] = self.locals.get(arg.left, self.expr(arg.right))
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
return res
def do_node_constant(self, prog):
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, prog.value, prog.line_number)
return prog.value
def do_node_field(self, prog):
try:
name = self.expr(prog.expression)
try:
- return self.parent.get_value(name, [], self.parent_kwargs)
+ res = self.parent.get_value(name, [], self.parent_kwargs)
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Unknown field {0}').format(name))
+ self.error(_('Unknown field {0}').format(name),
+ prog.line_number)
except ValueError as e:
raise e
except:
- self.error(_('Unknown field {0}').format('internal parse error'))
+ self.error(_('Unknown field {0}').format('internal parse error'),
+ prog.line_number)
def do_node_raw_field(self, prog):
try:
name = self.expr(prog.expression)
res = getattr(self.parent_book, name, None)
if res is None and prog.default is not None:
- return self.expr(prog.default)
+ res = self.expr(prog.default)
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
if res is not None:
if isinstance(res, list):
fm = self.parent_book.metadata_for_field(name)
if fm is None:
- return ', '.join(res)
- return fm['is_multiple']['list_to_ui'].join(res)
- return unicode_type(res)
+ res = ', '.join(res)
+ else:
+ res = fm['is_multiple']['list_to_ui'].join(res)
+ else:
+ res = unicode_type(res)
+ else:
+ res = unicode_type(res) # Should be the string "None"
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except ValueError as e:
raise e
except:
@@ -904,15 +938,22 @@ class _Interpreter(object):
def do_node_assign(self, prog):
t = self.expr(prog.right)
self.locals[prog.left] = t
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, t, prog.line_number)
return t
def do_node_first_non_empty(self, prog):
for expr in prog.expression_list:
if v := self.expr(expr):
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, v, prog.line_number)
return v
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, '', prog.line_number)
return ''
def do_node_for(self, prog):
+ line_number = prog.line_number
try:
separator = ',' if prog.separator is None else self.expr(prog.separator)
v = prog.variable
@@ -923,26 +964,33 @@ class _Interpreter(object):
res = [r.strip() for r in res.split(separator) if r.strip()]
ret = ''
if self.break_reporter:
- self.break_reporter(_("'for' value list"), separator.join(res))
+ self.break_reporter("'for' list value", separator.join(res), line_number)
for x in res:
self.locals[v] = x
ret = self.expression_list(prog.block)
- return ret
+ if (self.break_reporter):
+ self.break_reporter("'for' block value", ret, line_number)
elif self.break_reporter:
- self.break_reporter(_("'for' value list"), '')
-
- self.error(_('The field {0} is not a list').format(f))
+ # Shouldn't get here
+ self.break_reporter("'for' list value", '', line_number)
+ ret = ''
+ return ret
except ValueError as e:
raise e
except Exception as e:
- self.error(_('Unhandled exception {0}').format(e))
+ self.error(_('Unhandled exception {0}').format(e), line_number)
def do_node_contains(self, prog):
v = self.expr(prog.value_expression)
t = self.expr(prog.test_expression)
if re.search(t, v, flags=re.I):
- return self.expr(prog.match_expression)
- return self.expr(prog.not_match_expression)
+ res = self.expr(prog.match_expression)
+ else:
+ res = self.expr(prog.not_match_expression)
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
+
LOGICAL_BINARY_OPS = {
'and': lambda self, x, y: self.expr(x) and self.expr(y),
@@ -951,9 +999,14 @@ class _Interpreter(object):
def do_node_logop(self, prog):
try:
- return ('1' if self.LOGICAL_BINARY_OPS[prog.operator](self, prog.left, prog.right) else '')
+ res = ('1' if self.LOGICAL_BINARY_OPS[prog.operator](self, prog.left, prog.right) else '')
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Error during operator evaluation. Operator {0}').format(prog.operator))
+ self.error(
+ _('Error during operator evaluation. Operator {0}').format(prog.operator),
+ prog.line_number)
LOGICAL_UNARY_OPS = {
'not': lambda x: not x,
@@ -962,9 +1015,14 @@ class _Interpreter(object):
def do_node_logop_unary(self, prog):
try:
expr = self.expr(prog.expr)
- return ('1' if self.LOGICAL_UNARY_OPS[prog.operator](expr) else '')
+ res = ('1' if self.LOGICAL_UNARY_OPS[prog.operator](expr) else '')
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Error during operator evaluation. Operator {0}').format(prog.operator))
+ self.error(
+ _('Error during operator evaluation. Operator {0}').format(prog.operator),
+ prog.line_number)
ARITHMETIC_BINARY_OPS = {
'+': lambda x, y: x + y,
@@ -977,9 +1035,14 @@ class _Interpreter(object):
try:
answer = self.ARITHMETIC_BINARY_OPS[prog.operator](float(self.expr(prog.left)),
float(self.expr(prog.right)))
- return unicode_type(answer if modf(answer)[0] != 0 else int(answer))
+ res = unicode_type(answer if modf(answer)[0] != 0 else int(answer))
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Error during arithmetic operator evaluation. Operator {0}').format(prog.operator))
+ self.error(
+ _('Error during operator evaluation. Operator {0}').format(prog.operator),
+ prog.line_number)
ARITHMETIC_UNARY_OPS = {
'+': lambda x: x,
@@ -989,9 +1052,14 @@ class _Interpreter(object):
def do_node_unary_arithop(self, prog):
try:
expr = self.ARITHMETIC_UNARY_OPS[prog.operator](float(self.expr(prog.expr)))
- return unicode_type(expr if modf(expr)[0] != 0 else int(expr))
+ res = unicode_type(expr if modf(expr)[0] != 0 else int(expr))
+ if (self.break_reporter):
+ self.break_reporter(prog.node_name, res, prog.line_number)
+ return res
except:
- self.error(_('Error during arithmetic operator evaluation. Operator {0}').format(prog.operator))
+ self.error(
+ _('Error during operator evaluation. Operator {0}').format(prog.operator),
+ prog.line_number)
def do_node_print(self, prog):
res = []
@@ -1000,10 +1068,6 @@ class _Interpreter(object):
print(res)
return res[0] if res else ''
- def do_node_line_number(self, prog):
- self.line_number = prog.line_number
- return ''
-
NODE_OPS = {
Node.NODE_IF: do_node_if,
Node.NODE_ASSIGN: do_node_assign,
@@ -1026,7 +1090,6 @@ class _Interpreter(object):
Node.NODE_BINARY_ARITHOP: do_node_binary_arithop,
Node.NODE_UNARY_ARITHOP: do_node_unary_arithop,
Node.NODE_PRINT: do_node_print,
- Node.NODE_LINE_NUMBER: do_node_line_number,
}
def expr(self, prog):
@@ -1039,7 +1102,7 @@ class _Interpreter(object):
except:
if (DEBUG):
traceback.print_exc()
- self.error(_('Internal error evaluating an expression'))
+ self.error(_('Internal error evaluating an expression'), prog.line_number)
class TemplateFormatter(string.Formatter):