[pod] Added param Renderer.raiseOnError (False by default), that, if True, will force the Renderer to raise an error instead of dumping it into a note in the pod result.
This commit is contained in:
parent
114223a114
commit
f8f3c0e865
|
@ -450,6 +450,9 @@ class BaseMixin:
|
||||||
if isNew and initiator:
|
if isNew and initiator:
|
||||||
return self.goto(initiator.getUrl(page=initiatorPage, nav=''))
|
return self.goto(initiator.getUrl(page=initiatorPage, nav=''))
|
||||||
return self.goto(obj.getUrl())
|
return self.goto(obj.getUrl())
|
||||||
|
# Get the current page name. We keep it in "pageName" because rq['page']
|
||||||
|
# can be changed by m_getAppyPhases called below.
|
||||||
|
pageName = rq['page']
|
||||||
if buttonClicked == 'previous':
|
if buttonClicked == 'previous':
|
||||||
# Go to the previous page for this object.
|
# Go to the previous page for this object.
|
||||||
# We recompute the list of phases and pages because things
|
# We recompute the list of phases and pages because things
|
||||||
|
@ -459,7 +462,7 @@ class BaseMixin:
|
||||||
# pages may not be available in "edit" mode, so we return the edit
|
# pages may not be available in "edit" mode, so we return the edit
|
||||||
# or view pages depending on page.show.
|
# or view pages depending on page.show.
|
||||||
phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit')
|
phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit')
|
||||||
pageName, pageInfo = phaseObj.getPreviousPage(rq['page'])
|
pageName, pageInfo = phaseObj.getPreviousPage(pageName)
|
||||||
if pageName:
|
if pageName:
|
||||||
# Return to the edit or view page?
|
# Return to the edit or view page?
|
||||||
if pageInfo.showOnEdit:
|
if pageInfo.showOnEdit:
|
||||||
|
@ -476,10 +479,8 @@ class BaseMixin:
|
||||||
return self.goto(obj.getUrl(inPopup=inPopup))
|
return self.goto(obj.getUrl(inPopup=inPopup))
|
||||||
if buttonClicked == 'next':
|
if buttonClicked == 'next':
|
||||||
# Go to the next page for this object.
|
# Go to the next page for this object.
|
||||||
# We remember page name, because the next method may set a new
|
|
||||||
# current page if the current one is not visible anymore.
|
|
||||||
phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit')
|
phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit')
|
||||||
pageName, pageInfo = phaseObj.getNextPage(rq['page'])
|
pageName, pageInfo = phaseObj.getNextPage(pageName)
|
||||||
if pageName:
|
if pageName:
|
||||||
# Return to the edit or view page?
|
# Return to the edit or view page?
|
||||||
if pageInfo.showOnEdit:
|
if pageInfo.showOnEdit:
|
||||||
|
|
|
@ -46,8 +46,6 @@ class BufferAction:
|
||||||
# content. If 'from', we must dump what comes from the 'from' part of
|
# content. If 'from', we must dump what comes from the 'from' part of
|
||||||
# the action (='fromExpr')
|
# the action (='fromExpr')
|
||||||
self.fromExpr = fromExpr
|
self.fromExpr = fromExpr
|
||||||
# When an error occurs, must we raise it or write it into the buffer?
|
|
||||||
self.raiseErrors = not self.buffer.pod
|
|
||||||
# Several actions may co-exist for the same buffer, as a chain of
|
# Several actions may co-exist for the same buffer, as a chain of
|
||||||
# BufferAction instances, defined via the following attribute.
|
# BufferAction instances, defined via the following attribute.
|
||||||
self.subAction = None
|
self.subAction = None
|
||||||
|
@ -59,8 +57,8 @@ class BufferAction:
|
||||||
|
|
||||||
def manageError(self, result, context, errorMessage, dumpTb=True):
|
def manageError(self, result, context, errorMessage, dumpTb=True):
|
||||||
'''Manage the encountered error: dump it into the buffer or raise an
|
'''Manage the encountered error: dump it into the buffer or raise an
|
||||||
exception if self.raiseErrors is True.'''
|
exception.'''
|
||||||
if self.raiseErrors:
|
if self.buffer.env.raiseOnError:
|
||||||
if not self.buffer.pod:
|
if not self.buffer.pod:
|
||||||
# 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.
|
||||||
|
|
|
@ -224,7 +224,11 @@ class FileBuffer(Buffer):
|
||||||
if escape: self.dumpContent(res)
|
if escape: self.dumpContent(res)
|
||||||
else: self.write(res)
|
else: self.write(res)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e), dumpTb=False)
|
if not self.env.raiseOnError:
|
||||||
|
PodError.dump(self, EVAL_EXPR_ERROR % (expression, e),
|
||||||
|
dumpTb=False)
|
||||||
|
else:
|
||||||
|
raise Exception(EVAL_EXPR_ERROR % (expression, e))
|
||||||
|
|
||||||
def addAttributes(self):
|
def addAttributes(self):
|
||||||
# Into a FileBuffer, it is not possible to insert Attributes. Every
|
# Into a FileBuffer, it is not possible to insert Attributes. Every
|
||||||
|
@ -666,10 +670,10 @@ class MemoryBuffer(Buffer):
|
||||||
if escape: result.dumpContent(res)
|
if escape: result.dumpContent(res)
|
||||||
else: result.write(res)
|
else: result.write(res)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
if self.pod:
|
if not self.env.raiseOnError:
|
||||||
PodError.dump(result, EVAL_EXPR_ERROR % (
|
PodError.dump(result, EVAL_EXPR_ERROR % (
|
||||||
evalEntry.expr, e), dumpTb=False)
|
evalEntry.expr, e), dumpTb=False)
|
||||||
else: # px
|
else:
|
||||||
raise Exception(EVAL_EXPR_ERROR %(evalEntry.expr,e))
|
raise Exception(EVAL_EXPR_ERROR %(evalEntry.expr,e))
|
||||||
elif isinstance(evalEntry, Attributes) or \
|
elif isinstance(evalEntry, Attributes) or \
|
||||||
isinstance(evalEntry, Attribute):
|
isinstance(evalEntry, Attribute):
|
||||||
|
|
|
@ -107,6 +107,9 @@ class PodEnvironment(OdfEnvironment):
|
||||||
self.currentOdsHook = None
|
self.currentOdsHook = None
|
||||||
# Names of some tags, that we will compute after namespace propagation
|
# Names of some tags, that we will compute after namespace propagation
|
||||||
self.tags = None
|
self.tags = None
|
||||||
|
# When an error occurs, must we raise it or write it into he current
|
||||||
|
# buffer?
|
||||||
|
self.raiseOnError = None # Will be initialized by PodParser.__init__
|
||||||
|
|
||||||
def getTable(self):
|
def getTable(self):
|
||||||
'''Gets the currently parsed table.'''
|
'''Gets the currently parsed table.'''
|
||||||
|
@ -219,6 +222,7 @@ class PodEnvironment(OdfEnvironment):
|
||||||
class PodParser(OdfParser):
|
class PodParser(OdfParser):
|
||||||
def __init__(self, env, caller):
|
def __init__(self, env, caller):
|
||||||
OdfParser.__init__(self, env, caller)
|
OdfParser.__init__(self, env, caller)
|
||||||
|
env.raiseOnError = caller.raiseOnError
|
||||||
|
|
||||||
def endDocument(self):
|
def endDocument(self):
|
||||||
self.env.currentBuffer.content.close()
|
self.env.currentBuffer.content.close()
|
||||||
|
|
105
pod/renderer.py
105
pod/renderer.py
|
@ -101,21 +101,21 @@ class Renderer:
|
||||||
def __init__(self, template, context, result, pythonWithUnoPath=None,
|
def __init__(self, template, context, result, pythonWithUnoPath=None,
|
||||||
ooPort=2002, stylesMapping={}, forceOoCall=False,
|
ooPort=2002, stylesMapping={}, forceOoCall=False,
|
||||||
finalizeFunction=None, overwriteExisting=False,
|
finalizeFunction=None, overwriteExisting=False,
|
||||||
imageResolver=None):
|
raiseOnError=False, imageResolver=None):
|
||||||
'''This Python Open Document Renderer (PodRenderer) loads a document
|
'''This Python Open Document Renderer (PodRenderer) loads a document
|
||||||
template (p_template) which is an ODT file with some elements
|
template (p_template) which is an ODT file with some elements written
|
||||||
written in Python. Based on this template and some Python objects
|
in Python. Based on this template and some Python objects defined in
|
||||||
defined in p_context, the renderer generates an ODT file
|
p_context, the renderer generates an ODT file (p_result) that
|
||||||
(p_result) that instantiates the p_template and fills it with objects
|
instantiates the p_template and fills it with objects from the
|
||||||
from the p_context.
|
p_context.
|
||||||
|
|
||||||
- If p_result does not end with .odt, the Renderer
|
- If p_result does not end with .odt, the Renderer will call
|
||||||
will call LibreOffice to perform a conversion. If p_forceOoCall is
|
LibreOffice to perform a conversion. If p_forceOoCall is True, even
|
||||||
True, even if p_result ends with .odt, LibreOffice will be called, not
|
if p_result ends with .odt, LibreOffice will be called, not for
|
||||||
for performing a conversion, but for updating some elements like
|
performing a conversion, but for updating some elements like indexes
|
||||||
indexes (table of contents, etc) and sections containing links to
|
(table of contents, etc) and sections containing links to externa
|
||||||
external files (which is the case, for example, if you use the
|
files (which is the case, for example, if you use the default
|
||||||
default function "document").
|
function "document").
|
||||||
|
|
||||||
- If the Python interpreter which runs the current script is not
|
- If the Python interpreter which runs the current script is not
|
||||||
UNO-enabled, this script will run, in another process, a UNO-enabled
|
UNO-enabled, this script will run, in another process, a UNO-enabled
|
||||||
|
@ -137,6 +137,10 @@ class Renderer:
|
||||||
the result file. Else, an exception will be thrown if the result file
|
the result file. Else, an exception will be thrown if the result file
|
||||||
already exists.
|
already exists.
|
||||||
|
|
||||||
|
- If p_raiseOnError is False (the default value), any error encountered
|
||||||
|
during the generation of the result file will be dumped into it, as
|
||||||
|
a Python traceback within a note. Else, the error will be raised.
|
||||||
|
|
||||||
- p_imageResolver allows POD to retrieve images, from "img" tags within
|
- p_imageResolver allows POD to retrieve images, from "img" tags within
|
||||||
XHTML content. Indeed, POD may not be able (ie, may not have the
|
XHTML content. Indeed, POD may not be able (ie, may not have the
|
||||||
permission to) perform a HTTP GET on those images. Currently, the
|
permission to) perform a HTTP GET on those images. Currently, the
|
||||||
|
@ -156,6 +160,7 @@ class Renderer:
|
||||||
self.forceOoCall = forceOoCall
|
self.forceOoCall = forceOoCall
|
||||||
self.finalizeFunction = finalizeFunction
|
self.finalizeFunction = finalizeFunction
|
||||||
self.overwriteExisting = overwriteExisting
|
self.overwriteExisting = overwriteExisting
|
||||||
|
self.raiseOnError = raiseOnError
|
||||||
self.imageResolver = imageResolver
|
self.imageResolver = imageResolver
|
||||||
# Remember potential files or images that will be included through
|
# Remember potential files or images that will be included through
|
||||||
# "do ... from document" statements: we will need to declare them in
|
# "do ... from document" statements: we will need to declare them in
|
||||||
|
@ -424,17 +429,20 @@ class Renderer:
|
||||||
# Public interface
|
# Public interface
|
||||||
def run(self):
|
def run(self):
|
||||||
'''Renders the result.'''
|
'''Renders the result.'''
|
||||||
# Remember which parser is running
|
try:
|
||||||
self.currentParser = self.contentParser
|
# Remember which parser is running
|
||||||
# Create the resulting content.xml
|
self.currentParser = self.contentParser
|
||||||
self.currentParser.parse(self.contentXml)
|
# Create the resulting content.xml
|
||||||
self.currentParser = self.stylesParser
|
self.currentParser.parse(self.contentXml)
|
||||||
# Create the resulting styles.xml
|
self.currentParser = self.stylesParser
|
||||||
self.currentParser.parse(self.stylesXml)
|
# Create the resulting styles.xml
|
||||||
# Patch META-INF/manifest.xml
|
self.currentParser.parse(self.stylesXml)
|
||||||
self.patchManifest()
|
# Patch META-INF/manifest.xml
|
||||||
# Re-zip the result
|
self.patchManifest()
|
||||||
self.finalize()
|
# Re-zip the result
|
||||||
|
self.finalize()
|
||||||
|
finally:
|
||||||
|
FolderDeleter.delete(self.tempFolder)
|
||||||
|
|
||||||
def getStyles(self):
|
def getStyles(self):
|
||||||
'''Returns a dict of the styles that are defined into the template.'''
|
'''Returns a dict of the styles that are defined into the template.'''
|
||||||
|
@ -582,31 +590,28 @@ class Renderer:
|
||||||
resultZip.writestr(zInfo, '')
|
resultZip.writestr(zInfo, '')
|
||||||
resultZip.close()
|
resultZip.close()
|
||||||
resultType = os.path.splitext(self.result)[1].strip('.')
|
resultType = os.path.splitext(self.result)[1].strip('.')
|
||||||
try:
|
if (resultType in self.templateTypes) and not self.forceOoCall:
|
||||||
if (resultType in self.templateTypes) and not self.forceOoCall:
|
# Simply move the ODT result to the result
|
||||||
# Simply move the ODT result to the result
|
os.rename(resultName, self.result)
|
||||||
os.rename(resultName, self.result)
|
else:
|
||||||
else:
|
if resultType not in FILE_TYPES:
|
||||||
if resultType not in FILE_TYPES:
|
raise PodError(BAD_RESULT_TYPE % (
|
||||||
raise PodError(BAD_RESULT_TYPE % (
|
self.result, FILE_TYPES.keys()))
|
||||||
self.result, FILE_TYPES.keys()))
|
# Call LibreOffice to perform the conversion or document update.
|
||||||
# Call LibreOffice to perform the conversion or document update.
|
output = self.callLibreOffice(resultName, resultType)
|
||||||
output = self.callLibreOffice(resultName, resultType)
|
# I (should) have the result. Move it to the correct name.
|
||||||
# I (should) have the result. Move it to the correct name.
|
resPrefix = os.path.splitext(resultName)[0]
|
||||||
resPrefix = os.path.splitext(resultName)[0]
|
if resultType in self.templateTypes:
|
||||||
if resultType in self.templateTypes:
|
# converter.py has (normally!) created a second file
|
||||||
# converter.py has (normally!) created a second file
|
# suffixed .res.[resultType]
|
||||||
# suffixed .res.[resultType]
|
finalResultName = '%s.res.%s' % (resPrefix, resultType)
|
||||||
finalResultName = '%s.res.%s' % (resPrefix, resultType)
|
|
||||||
if not os.path.exists(finalResultName):
|
|
||||||
finalResultName = resultName
|
|
||||||
# In this case OO in server mode could not be called to
|
|
||||||
# update indexes, sections, etc.
|
|
||||||
else:
|
|
||||||
finalResultName = '%s.%s' % (resPrefix, resultType)
|
|
||||||
if not os.path.exists(finalResultName):
|
if not os.path.exists(finalResultName):
|
||||||
raise PodError(CONVERT_ERROR % output)
|
finalResultName = resultName
|
||||||
os.rename(finalResultName, self.result)
|
# In this case OO in server mode could not be called to
|
||||||
finally:
|
# update indexes, sections, etc.
|
||||||
FolderDeleter.delete(self.tempFolder)
|
else:
|
||||||
|
finalResultName = '%s.%s' % (resPrefix, resultType)
|
||||||
|
if not os.path.exists(finalResultName):
|
||||||
|
raise PodError(CONVERT_ERROR % output)
|
||||||
|
os.rename(finalResultName, self.result)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -30,6 +30,8 @@ class PxEnvironment(XmlEnvironment):
|
||||||
# XmlParser for better performance. Indeed, the base parser and env
|
# XmlParser for better performance. Indeed, the base parser and env
|
||||||
# process namespaces, and we do not need this for the PX parser.
|
# process namespaces, and we do not need this for the PX parser.
|
||||||
self.currentElem = None
|
self.currentElem = None
|
||||||
|
# Exceptions are always raised (for pod, it is not the case)
|
||||||
|
self.raiseOnError = True
|
||||||
|
|
||||||
def addSubBuffer(self):
|
def addSubBuffer(self):
|
||||||
subBuffer = self.currentBuffer.addSubBuffer()
|
subBuffer = self.currentBuffer.addSubBuffer()
|
||||||
|
|
Loading…
Reference in a new issue