[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"
|
<html metal:define-macro="main"
|
||||||
tal:define="user tool/getUser;
|
tal:define="user tool/getUser;
|
||||||
isAnon tool/userIsAnon;
|
isAnon tool/userIsAnon;
|
||||||
|
|
|
@ -69,7 +69,12 @@ class BufferAction:
|
||||||
if self.buffer.caller() == 'px':
|
if self.buffer.caller() == 'px':
|
||||||
# Add in the error message the line nb where the errors occurs
|
# Add in the error message the line nb where the errors occurs
|
||||||
# within the PX.
|
# 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)
|
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)
|
||||||
|
@ -274,7 +279,7 @@ class VariablesAction(BufferAction):
|
||||||
# every defined variable.
|
# every defined variable.
|
||||||
BufferAction.__init__(self, name, buffer, None, elem, minus, source,
|
BufferAction.__init__(self, name, buffer, None, elem, minus, source,
|
||||||
fromExpr)
|
fromExpr)
|
||||||
# Definitions of variables: ~{s_name: s_expr}~
|
# Definitions of variables: ~[(s_name, s_expr)]~
|
||||||
self.variables = variables
|
self.variables = variables
|
||||||
|
|
||||||
def do(self):
|
def do(self):
|
||||||
|
@ -286,7 +291,7 @@ class VariablesAction(BufferAction):
|
||||||
# hide in the context: after execution of this buffer we will restore
|
# hide in the context: after execution of this buffer we will restore
|
||||||
# those values.
|
# those values.
|
||||||
hidden = None
|
hidden = None
|
||||||
for name, expr in self.variables.iteritems():
|
for name, expr in self.variables:
|
||||||
# Evaluate the expression
|
# Evaluate the expression
|
||||||
result, error = self.evaluateExpression(expr)
|
result, error = self.evaluateExpression(expr)
|
||||||
if error: return
|
if error: return
|
||||||
|
@ -303,7 +308,7 @@ class VariablesAction(BufferAction):
|
||||||
# Restore hidden variables if any
|
# Restore hidden variables if any
|
||||||
if hidden: context.update(hidden)
|
if hidden: context.update(hidden)
|
||||||
# Delete not-hidden variables
|
# Delete not-hidden variables
|
||||||
for name in self.variables.iterkeys():
|
for name, expr in self.variables:
|
||||||
if hidden and (name in hidden): continue
|
if hidden and (name in hidden): continue
|
||||||
del context[name]
|
del context[name]
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -140,7 +140,7 @@ class Buffer:
|
||||||
def getLength(self): pass # To be overridden
|
def getLength(self): pass # To be overridden
|
||||||
|
|
||||||
def dumpStartElement(self, elem, attrs={}, ignoreAttrs=(),
|
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,
|
'''Inserts into this buffer the start tag p_elem, with its p_attrs,
|
||||||
excepted those listed in p_ignoreAttrs. If p_insertAttributesHook
|
excepted those listed in p_ignoreAttrs. If p_insertAttributesHook
|
||||||
is True (works only for MemoryBuffers), we will insert an Attributes
|
is True (works only for MemoryBuffers), we will insert an Attributes
|
||||||
|
@ -162,7 +162,12 @@ class Buffer:
|
||||||
res = self.addAttributes()
|
res = self.addAttributes()
|
||||||
else:
|
else:
|
||||||
res = None
|
res = None
|
||||||
self.write('>')
|
# Close the tag
|
||||||
|
if noEndTag:
|
||||||
|
suffix = '/>'
|
||||||
|
else:
|
||||||
|
suffix = '>'
|
||||||
|
self.write(suffix)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def dumpEndElement(self, elem):
|
def dumpEndElement(self, elem):
|
||||||
|
@ -201,7 +206,9 @@ class FileBuffer(Buffer):
|
||||||
def addExpression(self, expression, tiedHook=None):
|
def addExpression(self, expression, tiedHook=None):
|
||||||
# At 2013-02-06, this method was not called within the whole test suite.
|
# At 2013-02-06, this method was not called within the whole test suite.
|
||||||
try:
|
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:
|
except Exception, e:
|
||||||
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e), dumpTb=False)
|
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e), dumpTb=False)
|
||||||
|
|
||||||
|
@ -360,15 +367,15 @@ class MemoryBuffer(Buffer):
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def _getVariables(self, expr):
|
def _getVariables(self, expr):
|
||||||
'''Returns variable definitions in p_expr as a dict
|
'''Returns variable definitions in p_expr as a list
|
||||||
~{s_varName: s_expr}~.'''
|
~[(s_varName, s_expr)]~.'''
|
||||||
exprs = expr.strip().split(';')
|
exprs = expr.strip().split(';')
|
||||||
res = {}
|
res = []
|
||||||
for sub in exprs:
|
for sub in exprs:
|
||||||
varRes = MemoryBuffer.varRex.match(sub)
|
varRes = MemoryBuffer.varRex.match(sub)
|
||||||
if not varRes:
|
if not varRes:
|
||||||
raise ParsingError(BAD_VAR_EXPRESSION % sub)
|
raise ParsingError(BAD_VAR_EXPRESSION % sub)
|
||||||
res[varRes.group(1)] = varRes.group(2)
|
res.append(varRes.groups())
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def createAction(self, statementGroup):
|
def createAction(self, statementGroup):
|
||||||
|
@ -624,7 +631,9 @@ class MemoryBuffer(Buffer):
|
||||||
currentIndex = index + 1
|
currentIndex = index + 1
|
||||||
if isinstance(evalEntry, Expression):
|
if isinstance(evalEntry, Expression):
|
||||||
try:
|
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:
|
except Exception, e:
|
||||||
if self.caller() == 'pod':
|
if self.caller() == 'pod':
|
||||||
PodError.dump(result, EVAL_EXPR_ERROR % (
|
PodError.dump(result, EVAL_EXPR_ERROR % (
|
||||||
|
|
|
@ -89,7 +89,13 @@ class Expression(PodElement):
|
||||||
|
|
||||||
def evaluate(self, context):
|
def evaluate(self, context):
|
||||||
'''Evaluates the Python expression (self.expr) with a given
|
'''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
|
# Evaluate the expression, or get it from self.result if it has already
|
||||||
# been computed.
|
# been computed.
|
||||||
if self.evaluated:
|
if self.evaluated:
|
||||||
|
@ -103,16 +109,22 @@ class Expression(PodElement):
|
||||||
# Evaluates the Python expression
|
# Evaluates the Python expression
|
||||||
res = self.result = eval(self.expr, context)
|
res = self.result = eval(self.expr, context)
|
||||||
# Converts the expression result to a string that can be inserted into
|
# Converts the expression result to a string that can be inserted into
|
||||||
# the POD result.
|
# the POD/PX result.
|
||||||
if res == None:
|
resultType = res.__class__.__name__
|
||||||
|
if resultType == 'NoneType':
|
||||||
res = u''
|
res = u''
|
||||||
elif isinstance(res, str):
|
elif resultType == 'str':
|
||||||
res = unicode(res.decode('utf-8'))
|
res = res.decode('utf-8')
|
||||||
elif isinstance(res, unicode):
|
elif resultType == 'unicode':
|
||||||
pass
|
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:
|
else:
|
||||||
res = unicode(res)
|
res = unicode(res)
|
||||||
return res
|
return res, escapeXml
|
||||||
|
|
||||||
class Attributes(PodElement):
|
class Attributes(PodElement):
|
||||||
'''Represents a bunch of XML attributes that will be dumped for a given tag
|
'''Represents a bunch of XML attributes that will be dumped for a given tag
|
||||||
|
|
|
@ -54,6 +54,8 @@ 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')
|
||||||
|
# No-end tags
|
||||||
|
noEndTags = ('br', 'img')
|
||||||
|
|
||||||
def __init__(self, env, caller=None):
|
def __init__(self, env, caller=None):
|
||||||
XmlParser.__init__(self, env, caller)
|
XmlParser.__init__(self, env, caller)
|
||||||
|
@ -78,7 +80,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=self.pxAttributes)
|
ignoreAttrs=self.pxAttributes, noEndTag=elem in self.noEndTags)
|
||||||
|
|
||||||
def endElement(self, elem):
|
def endElement(self, elem):
|
||||||
e = self.env
|
e = self.env
|
||||||
|
@ -88,7 +90,8 @@ class PxParser(XmlParser):
|
||||||
e.currentBuffer.addExpression(e.currentContent)
|
e.currentBuffer.addExpression(e.currentContent)
|
||||||
e.currentContent = ''
|
e.currentContent = ''
|
||||||
# Dump the end element into the current buffer
|
# 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
|
# If this element is the main element of the current buffer, we must
|
||||||
# pop it and continue to work in the parent buffer.
|
# pop it and continue to work in the parent buffer.
|
||||||
if e.isActionElem(elem):
|
if e.isActionElem(elem):
|
||||||
|
|
Loading…
Reference in a new issue