[px] PXs can be called by other PXs.
This commit is contained in:
parent
bfbf9bea82
commit
2a145ac890
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<!DOCTYPE html>
|
||||
<html metal:define-macro="main"
|
||||
tal:define="user tool/getUser;
|
||||
isAnon tool/userIsAnon;
|
||||
|
|
|
@ -69,7 +69,12 @@ class BufferAction:
|
|||
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()
|
||||
locator = self.buffer.env.parser.locator
|
||||
# The column number may not be given.
|
||||
col = locator.getColumnNumber()
|
||||
if col == None: col = ''
|
||||
else: col = ', column %d' % col
|
||||
errorMessage += ' (line %s%s)' % (locator.getLineNumber(), col)
|
||||
raise Exception(errorMessage)
|
||||
# Empty the buffer
|
||||
self.buffer.__init__(self.buffer.env, self.buffer.parent)
|
||||
|
@ -274,7 +279,7 @@ class VariablesAction(BufferAction):
|
|||
# every defined variable.
|
||||
BufferAction.__init__(self, name, buffer, None, elem, minus, source,
|
||||
fromExpr)
|
||||
# Definitions of variables: ~{s_name: s_expr}~
|
||||
# Definitions of variables: ~[(s_name, s_expr)]~
|
||||
self.variables = variables
|
||||
|
||||
def do(self):
|
||||
|
@ -286,7 +291,7 @@ class VariablesAction(BufferAction):
|
|||
# hide in the context: after execution of this buffer we will restore
|
||||
# those values.
|
||||
hidden = None
|
||||
for name, expr in self.variables.iteritems():
|
||||
for name, expr in self.variables:
|
||||
# Evaluate the expression
|
||||
result, error = self.evaluateExpression(expr)
|
||||
if error: return
|
||||
|
@ -303,7 +308,7 @@ class VariablesAction(BufferAction):
|
|||
# Restore hidden variables if any
|
||||
if hidden: context.update(hidden)
|
||||
# Delete not-hidden variables
|
||||
for name in self.variables.iterkeys():
|
||||
for name, expr in self.variables:
|
||||
if hidden and (name in hidden): continue
|
||||
del context[name]
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -140,7 +140,7 @@ class Buffer:
|
|||
def getLength(self): pass # To be overridden
|
||||
|
||||
def dumpStartElement(self, elem, attrs={}, ignoreAttrs=(),
|
||||
insertAttributesHook=False):
|
||||
insertAttributesHook=False, noEndTag=False):
|
||||
'''Inserts into this buffer the start tag p_elem, with its p_attrs,
|
||||
excepted those listed in p_ignoreAttrs. If p_insertAttributesHook
|
||||
is True (works only for MemoryBuffers), we will insert an Attributes
|
||||
|
@ -162,7 +162,12 @@ class Buffer:
|
|||
res = self.addAttributes()
|
||||
else:
|
||||
res = None
|
||||
self.write('>')
|
||||
# Close the tag
|
||||
if noEndTag:
|
||||
suffix = '/>'
|
||||
else:
|
||||
suffix = '>'
|
||||
self.write(suffix)
|
||||
return res
|
||||
|
||||
def dumpEndElement(self, elem):
|
||||
|
@ -201,7 +206,9 @@ class FileBuffer(Buffer):
|
|||
def addExpression(self, expression, tiedHook=None):
|
||||
# At 2013-02-06, this method was not called within the whole test suite.
|
||||
try:
|
||||
self.dumpContent(Expression(expression).evaluate(self.env.context))
|
||||
res, escape = Expression(expression).evaluate(self.env.context)
|
||||
if escape: self.dumpContent(res)
|
||||
else: self.write(res)
|
||||
except Exception, e:
|
||||
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e), dumpTb=False)
|
||||
|
||||
|
@ -360,15 +367,15 @@ class MemoryBuffer(Buffer):
|
|||
return attrs
|
||||
|
||||
def _getVariables(self, expr):
|
||||
'''Returns variable definitions in p_expr as a dict
|
||||
~{s_varName: s_expr}~.'''
|
||||
'''Returns variable definitions in p_expr as a list
|
||||
~[(s_varName, s_expr)]~.'''
|
||||
exprs = expr.strip().split(';')
|
||||
res = {}
|
||||
res = []
|
||||
for sub in exprs:
|
||||
varRes = MemoryBuffer.varRex.match(sub)
|
||||
if not varRes:
|
||||
raise ParsingError(BAD_VAR_EXPRESSION % sub)
|
||||
res[varRes.group(1)] = varRes.group(2)
|
||||
res.append(varRes.groups())
|
||||
return res
|
||||
|
||||
def createAction(self, statementGroup):
|
||||
|
@ -624,7 +631,9 @@ class MemoryBuffer(Buffer):
|
|||
currentIndex = index + 1
|
||||
if isinstance(evalEntry, Expression):
|
||||
try:
|
||||
result.dumpContent(evalEntry.evaluate(self.env.context))
|
||||
res, escape = evalEntry.evaluate(self.env.context)
|
||||
if escape: result.dumpContent(res)
|
||||
else: result.write(res)
|
||||
except Exception, e:
|
||||
if self.caller() == 'pod':
|
||||
PodError.dump(result, EVAL_EXPR_ERROR % (
|
||||
|
|
|
@ -89,7 +89,13 @@ class Expression(PodElement):
|
|||
|
||||
def evaluate(self, context):
|
||||
'''Evaluates the Python expression (self.expr) with a given
|
||||
p_context.'''
|
||||
p_context, and returns the result. More precisely, it returns a
|
||||
tuple (result, escapeXml). Boolean escapeXml indicates if XML chars
|
||||
must be escaped or not. For example, if the expression's result is a
|
||||
PX, the result of evaluating it (a chunk of XHTML) must be inserted
|
||||
as is, unescaped, into the buffer. In most situations, XML escaping
|
||||
will be enabled.'''
|
||||
escapeXml = True
|
||||
# Evaluate the expression, or get it from self.result if it has already
|
||||
# been computed.
|
||||
if self.evaluated:
|
||||
|
@ -103,16 +109,22 @@ class Expression(PodElement):
|
|||
# Evaluates the Python expression
|
||||
res = self.result = eval(self.expr, context)
|
||||
# Converts the expression result to a string that can be inserted into
|
||||
# the POD result.
|
||||
if res == None:
|
||||
# the POD/PX result.
|
||||
resultType = res.__class__.__name__
|
||||
if resultType == 'NoneType':
|
||||
res = u''
|
||||
elif isinstance(res, str):
|
||||
res = unicode(res.decode('utf-8'))
|
||||
elif isinstance(res, unicode):
|
||||
pass
|
||||
elif resultType == 'str':
|
||||
res = res.decode('utf-8')
|
||||
elif resultType == 'unicode':
|
||||
pass # Don't perform any conversion, unicode is the target type.
|
||||
elif resultType == 'Px':
|
||||
# A PX that must be called within the current PX. Call it with the
|
||||
# current context.
|
||||
res = res(context)
|
||||
escapeXml = False
|
||||
else:
|
||||
res = unicode(res)
|
||||
return res
|
||||
return res, escapeXml
|
||||
|
||||
class Attributes(PodElement):
|
||||
'''Represents a bunch of XML attributes that will be dumped for a given tag
|
||||
|
|
|
@ -54,6 +54,8 @@ class PxEnvironment(XmlEnvironment):
|
|||
class PxParser(XmlParser):
|
||||
'''PX parser that is specific for parsing PX data.'''
|
||||
pxAttributes = ('var', 'for', 'if')
|
||||
# No-end tags
|
||||
noEndTags = ('br', 'img')
|
||||
|
||||
def __init__(self, env, caller=None):
|
||||
XmlParser.__init__(self, env, caller)
|
||||
|
@ -78,7 +80,7 @@ class PxParser(XmlParser):
|
|||
e.currentBuffer.addElement(elem, elemType='px')
|
||||
if elem != 'x':
|
||||
e.currentBuffer.dumpStartElement(elem, attrs,
|
||||
ignoreAttrs=self.pxAttributes)
|
||||
ignoreAttrs=self.pxAttributes, noEndTag=elem in self.noEndTags)
|
||||
|
||||
def endElement(self, elem):
|
||||
e = self.env
|
||||
|
@ -88,7 +90,8 @@ class PxParser(XmlParser):
|
|||
e.currentBuffer.addExpression(e.currentContent)
|
||||
e.currentContent = ''
|
||||
# Dump the end element into the current buffer
|
||||
if elem != 'x': e.currentBuffer.dumpEndElement(elem)
|
||||
if (elem != 'x') and (elem not in self.noEndTags):
|
||||
e.currentBuffer.dumpEndElement(elem)
|
||||
# If this element is the main element of the current buffer, we must
|
||||
# pop it and continue to work in the parent buffer.
|
||||
if e.isActionElem(elem):
|
||||
|
|
Loading…
Reference in a new issue