[pod] Improved error handling. [px] More work on PX.

This commit is contained in:
Gaetan Delannay 2013-03-19 22:06:47 +01:00
parent d5296ba321
commit bfbf9bea82
9 changed files with 1853 additions and 1841 deletions

View file

@ -22,9 +22,9 @@ from appy.pod import PodError
from appy.pod.elements import * from appy.pod.elements import *
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
EVAL_ERROR = 'Error while evaluating expression "%s".' EVAL_ERROR = 'Error while evaluating expression "%s". %s'
FROM_EVAL_ERROR = 'Error while evaluating the expression "%s" defined in the ' \ FROM_EVAL_ERROR = 'Error while evaluating the expression "%s" defined in the ' \
'"from" part of a statement.' '"from" part of a statement. %s'
WRONG_SEQ_TYPE = 'Expression "%s" is not iterable.' WRONG_SEQ_TYPE = 'Expression "%s" is not iterable.'
TABLE_NOT_ONE_CELL = "The table you wanted to populate with '%s' " \ TABLE_NOT_ONE_CELL = "The table you wanted to populate with '%s' " \
"can\'t be dumped with the '-' option because it has " \ "can\'t be dumped with the '-' option because it has " \
@ -53,8 +53,24 @@ class BufferAction:
# We store the result of evaluation of expr and fromExpr # We store the result of evaluation of expr and fromExpr
self.exprResult = None self.exprResult = None
self.fromExprResult = None self.fromExprResult = None
# When an error is encountered, must we raise it or write it into the
# buffer?
self.raiseErrors = self.buffer.caller() == 'px'
def getExceptionLine(self, e):
'''Gets the line describing exception p_e, containing the pathname of
the exception class, the exception's message and line number.'''
return '%s.%s: %s' % (e.__module__, e.__class__.__name__, str(e))
def writeError(self, errorMessage, dumpTb=True): def writeError(self, errorMessage, dumpTb=True):
'''Write the encountered error into the buffer or raise an exception
if self.raiseErrors is True.'''
if self.raiseErrors:
if self.buffer.caller() == 'px':
# Add in the error message the line nb where the errors occurs
# within the PX.
import pdb; pdb.set_trace()
raise Exception(errorMessage)
# Empty the buffer # Empty the buffer
self.buffer.__init__(self.buffer.env, self.buffer.parent) self.buffer.__init__(self.buffer.env, self.buffer.parent)
PodError.dump(self.buffer, errorMessage, withinElement=self.elem, PodError.dump(self.buffer, errorMessage, withinElement=self.elem,
@ -67,9 +83,9 @@ class BufferAction:
try: try:
res = eval(expr, self.buffer.env.context) res = eval(expr, self.buffer.env.context)
error = False error = False
except: except Exception, e:
res = None res = None
self.writeError(EVAL_ERROR % expr) self.writeError(EVAL_ERROR % (expr, self.getExceptionLine(e)))
error = True error = True
return res, error return res, error
@ -91,17 +107,14 @@ class BufferAction:
else: else:
# Evaluate fromExpr # Evaluate fromExpr
self.fromExprResult = None self.fromExprResult = None
errorOccurred = False error = False
try: try:
self.fromExprResult= eval(self.fromExpr,self.buffer.env.context) self.fromExprResult= eval(self.fromExpr,self.buffer.env.context)
except PodError, pe: except Exception, e:
self.writeError(FROM_EVAL_ERROR % self.fromExpr + ' ' + str(pe), msg= FROM_EVAL_ERROR % (self.fromExpr, self.getExceptionLine(e))
dumpTb=False) self.writeError(msg, dumpTb=False)
errorOccurred = True error = True
except: if not error:
self.writeError(FROM_EVAL_ERROR % self.fromExpr)
errorOccurred = True
if not errorOccurred:
self.result.write(self.fromExprResult) self.result.write(self.fromExprResult)
class IfAction(BufferAction): class IfAction(BufferAction):
@ -171,9 +184,8 @@ class ForAction(BufferAction):
context = self.buffer.env.context context = self.buffer.env.context
# Check self.exprResult type # Check self.exprResult type
try: try:
# All "iterable" objects are OK.
iter(self.exprResult) iter(self.exprResult)
# All "iterable" objects are OK. Thanks to Bernhard Bender for this
# improvement.
except TypeError: except TypeError:
self.writeError(WRONG_SEQ_TYPE % self.expr) self.writeError(WRONG_SEQ_TYPE % self.expr)
return return
@ -264,31 +276,28 @@ class VariablesAction(BufferAction):
fromExpr) fromExpr)
# Definitions of variables: ~{s_name: s_expr}~ # Definitions of variables: ~{s_name: s_expr}~
self.variables = variables self.variables = variables
# Results of executing the variables: ~{s_name: exprResult}~
self.results = {}
def do(self): def do(self):
context = self.buffer.env.context context = self.buffer.env.context
# Evaluate the variables' expressions: because there are several # Evaluate the variables' expressions: because there are several
# expressions, we did not use the standard, single-expression-minded # expressions, we did not use the standard, single-expression-minded
# BufferAction code for evaluating the expression. # BufferAction code for evaluating our expressions.
# Also: remember the names and values of the variables that we will hide # Also: we remember the names and values of the variables that we will
# in the context: after execution of this buffer we will restore those # hide in the context: after execution of this buffer we will restore
# values in the context. # those values.
hidden = None hidden = None
for name, expr in self.variables.iteritems(): for name, expr in self.variables.iteritems():
# Evaluate the expression # Evaluate the expression
result, error = self.evaluateExpression(expr) result, error = self.evaluateExpression(expr)
if error: return if error: return
self.results[name] = result
# Remember the variable previous value if already in the context # Remember the variable previous value if already in the context
if name in context: if name in context:
if not hidden: if not hidden:
hidden = {name: context[name]} hidden = {name: context[name]}
else: else:
hidden[name] = context[name] hidden[name] = context[name]
# Add our variables to the context # Store the result into the context
context.update(self.results) context[name] = result
# Evaluate the buffer # Evaluate the buffer
self.evaluateBuffer() self.evaluateBuffer()
# Restore hidden variables if any # Restore hidden variables if any

View file

@ -459,8 +459,9 @@ class MemoryBuffer(Buffer):
def createPxAction(self, elem, actionType, statement): def createPxAction(self, elem, actionType, statement):
res = 0 res = 0
statement = statement.strip()
if actionType == 'for': if actionType == 'for':
forRes = MemoryBuffer.forRex.match(statement.strip()) forRes = MemoryBuffer.forRex.match(statement)
if not forRes: if not forRes:
raise ParsingError(BAD_FOR_EXPRESSION % statement) raise ParsingError(BAD_FOR_EXPRESSION % statement)
iter, subExpr = forRes.groups() iter, subExpr = forRes.groups()

View file

@ -77,7 +77,7 @@ class Expression(PodElement):
OD = None OD = None
def __init__(self, pyExpr): def __init__(self, pyExpr):
# The Python expression # The Python expression
self.expr = pyExpr self.expr = pyExpr.strip()
# We will store here the expression's true result (before being # We will store here the expression's true result (before being
# converted to a string) # converted to a string)
self.result = None self.result = None

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -5,8 +5,6 @@ from appy.pod.buffers import MemoryBuffer
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class PxEnvironment(XmlEnvironment): class PxEnvironment(XmlEnvironment):
'''Environment for the PX parser.''' '''Environment for the PX parser.'''
# PX-specific attributes must not be dumped into the result.
undumpableAttrs = ('for', 'if')
def __init__(self): def __init__(self):
# We try to mimic POD. POD has a root buffer that is a FileBuffer, which # We try to mimic POD. POD has a root buffer that is a FileBuffer, which
@ -55,7 +53,6 @@ class PxEnvironment(XmlEnvironment):
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class PxParser(XmlParser): class PxParser(XmlParser):
'''PX parser that is specific for parsing PX data.''' '''PX parser that is specific for parsing PX data.'''
pxAttributes = ('var', 'for', 'if') pxAttributes = ('var', 'for', 'if')
def __init__(self, env, caller=None): def __init__(self, env, caller=None):
@ -81,7 +78,7 @@ class PxParser(XmlParser):
e.currentBuffer.addElement(elem, elemType='px') e.currentBuffer.addElement(elem, elemType='px')
if elem != 'x': if elem != 'x':
e.currentBuffer.dumpStartElement(elem, attrs, e.currentBuffer.dumpStartElement(elem, attrs,
ignoreAttrs=e.undumpableAttrs) ignoreAttrs=self.pxAttributes)
def endElement(self, elem): def endElement(self, elem):
e = self.env e = self.env