diff --git a/gen/mixins/__init__.py b/gen/mixins/__init__.py index 9c4238c..aea95e2 100644 --- a/gen/mixins/__init__.py +++ b/gen/mixins/__init__.py @@ -450,6 +450,9 @@ class BaseMixin: if isNew and initiator: return self.goto(initiator.getUrl(page=initiatorPage, nav='')) 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': # Go to the previous page for this object. # 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 # or view pages depending on page.show. phaseObj = self.getAppyPhases(currentOnly=True, layoutType='edit') - pageName, pageInfo = phaseObj.getPreviousPage(rq['page']) + pageName, pageInfo = phaseObj.getPreviousPage(pageName) if pageName: # Return to the edit or view page? if pageInfo.showOnEdit: @@ -476,10 +479,8 @@ class BaseMixin: return self.goto(obj.getUrl(inPopup=inPopup)) if buttonClicked == 'next': # 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') - pageName, pageInfo = phaseObj.getNextPage(rq['page']) + pageName, pageInfo = phaseObj.getNextPage(pageName) if pageName: # Return to the edit or view page? if pageInfo.showOnEdit: diff --git a/pod/actions.py b/pod/actions.py index f0d6125..9c87c49 100644 --- a/pod/actions.py +++ b/pod/actions.py @@ -46,8 +46,6 @@ class BufferAction: # content. If 'from', we must dump what comes from the 'from' part of # the action (='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 # BufferAction instances, defined via the following attribute. self.subAction = None @@ -59,8 +57,8 @@ class BufferAction: def manageError(self, result, context, errorMessage, dumpTb=True): '''Manage the encountered error: dump it into the buffer or raise an - exception if self.raiseErrors is True.''' - if self.raiseErrors: + exception.''' + if self.buffer.env.raiseOnError: if not self.buffer.pod: # Add in the error message the line nb where the errors occurs # within the PX. diff --git a/pod/buffers.py b/pod/buffers.py index 9b80724..3b561c7 100644 --- a/pod/buffers.py +++ b/pod/buffers.py @@ -224,7 +224,11 @@ class FileBuffer(Buffer): if escape: self.dumpContent(res) else: self.write(res) 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): # Into a FileBuffer, it is not possible to insert Attributes. Every @@ -666,10 +670,10 @@ class MemoryBuffer(Buffer): if escape: result.dumpContent(res) else: result.write(res) except Exception, e: - if self.pod: + if not self.env.raiseOnError: PodError.dump(result, EVAL_EXPR_ERROR % ( evalEntry.expr, e), dumpTb=False) - else: # px + else: raise Exception(EVAL_EXPR_ERROR %(evalEntry.expr,e)) elif isinstance(evalEntry, Attributes) or \ isinstance(evalEntry, Attribute): diff --git a/pod/pod_parser.py b/pod/pod_parser.py index 41a1b5a..ea85fe7 100644 --- a/pod/pod_parser.py +++ b/pod/pod_parser.py @@ -107,6 +107,9 @@ class PodEnvironment(OdfEnvironment): self.currentOdsHook = None # Names of some tags, that we will compute after namespace propagation 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): '''Gets the currently parsed table.''' @@ -219,6 +222,7 @@ class PodEnvironment(OdfEnvironment): class PodParser(OdfParser): def __init__(self, env, caller): OdfParser.__init__(self, env, caller) + env.raiseOnError = caller.raiseOnError def endDocument(self): self.env.currentBuffer.content.close() diff --git a/pod/renderer.py b/pod/renderer.py index 6117ab6..8e7cf2f 100644 --- a/pod/renderer.py +++ b/pod/renderer.py @@ -101,21 +101,21 @@ class Renderer: def __init__(self, template, context, result, pythonWithUnoPath=None, ooPort=2002, stylesMapping={}, forceOoCall=False, finalizeFunction=None, overwriteExisting=False, - imageResolver=None): + raiseOnError=False, imageResolver=None): '''This Python Open Document Renderer (PodRenderer) loads a document - template (p_template) which is an ODT file with some elements - written in Python. Based on this template and some Python objects - defined in p_context, the renderer generates an ODT file - (p_result) that instantiates the p_template and fills it with objects - from the p_context. + template (p_template) which is an ODT file with some elements written + in Python. Based on this template and some Python objects defined in + p_context, the renderer generates an ODT file (p_result) that + instantiates the p_template and fills it with objects from the + p_context. - - If p_result does not end with .odt, the Renderer - will call LibreOffice to perform a conversion. If p_forceOoCall is - True, even if p_result ends with .odt, LibreOffice will be called, not - for performing a conversion, but for updating some elements like - indexes (table of contents, etc) and sections containing links to - external files (which is the case, for example, if you use the - default function "document"). + - If p_result does not end with .odt, the Renderer will call + LibreOffice to perform a conversion. If p_forceOoCall is True, even + if p_result ends with .odt, LibreOffice will be called, not for + performing a conversion, but for updating some elements like indexes + (table of contents, etc) and sections containing links to externa + files (which is the case, for example, if you use the default + function "document"). - If the Python interpreter which runs the current script is not 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 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 XHTML content. Indeed, POD may not be able (ie, may not have the permission to) perform a HTTP GET on those images. Currently, the @@ -156,6 +160,7 @@ class Renderer: self.forceOoCall = forceOoCall self.finalizeFunction = finalizeFunction self.overwriteExisting = overwriteExisting + self.raiseOnError = raiseOnError self.imageResolver = imageResolver # Remember potential files or images that will be included through # "do ... from document" statements: we will need to declare them in @@ -424,17 +429,20 @@ class Renderer: # Public interface def run(self): '''Renders the result.''' - # Remember which parser is running - self.currentParser = self.contentParser - # Create the resulting content.xml - self.currentParser.parse(self.contentXml) - self.currentParser = self.stylesParser - # Create the resulting styles.xml - self.currentParser.parse(self.stylesXml) - # Patch META-INF/manifest.xml - self.patchManifest() - # Re-zip the result - self.finalize() + try: + # Remember which parser is running + self.currentParser = self.contentParser + # Create the resulting content.xml + self.currentParser.parse(self.contentXml) + self.currentParser = self.stylesParser + # Create the resulting styles.xml + self.currentParser.parse(self.stylesXml) + # Patch META-INF/manifest.xml + self.patchManifest() + # Re-zip the result + self.finalize() + finally: + FolderDeleter.delete(self.tempFolder) def getStyles(self): '''Returns a dict of the styles that are defined into the template.''' @@ -582,31 +590,28 @@ class Renderer: resultZip.writestr(zInfo, '') resultZip.close() resultType = os.path.splitext(self.result)[1].strip('.') - try: - if (resultType in self.templateTypes) and not self.forceOoCall: - # Simply move the ODT result to the result - os.rename(resultName, self.result) - else: - if resultType not in FILE_TYPES: - raise PodError(BAD_RESULT_TYPE % ( - self.result, FILE_TYPES.keys())) - # Call LibreOffice to perform the conversion or document update. - output = self.callLibreOffice(resultName, resultType) - # I (should) have the result. Move it to the correct name. - resPrefix = os.path.splitext(resultName)[0] - if resultType in self.templateTypes: - # converter.py has (normally!) created a second file - # suffixed .res.[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 (resultType in self.templateTypes) and not self.forceOoCall: + # Simply move the ODT result to the result + os.rename(resultName, self.result) + else: + if resultType not in FILE_TYPES: + raise PodError(BAD_RESULT_TYPE % ( + self.result, FILE_TYPES.keys())) + # Call LibreOffice to perform the conversion or document update. + output = self.callLibreOffice(resultName, resultType) + # I (should) have the result. Move it to the correct name. + resPrefix = os.path.splitext(resultName)[0] + if resultType in self.templateTypes: + # converter.py has (normally!) created a second file + # suffixed .res.[resultType] + finalResultName = '%s.res.%s' % (resPrefix, resultType) if not os.path.exists(finalResultName): - raise PodError(CONVERT_ERROR % output) - os.rename(finalResultName, self.result) - finally: - FolderDeleter.delete(self.tempFolder) + 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): + raise PodError(CONVERT_ERROR % output) + os.rename(finalResultName, self.result) # ------------------------------------------------------------------------------ diff --git a/px/px_parser.py b/px/px_parser.py index 5eca112..2df697d 100644 --- a/px/px_parser.py +++ b/px/px_parser.py @@ -30,6 +30,8 @@ class PxEnvironment(XmlEnvironment): # XmlParser for better performance. Indeed, the base parser and env # process namespaces, and we do not need this for the PX parser. self.currentElem = None + # Exceptions are always raised (for pod, it is not the case) + self.raiseOnError = True def addSubBuffer(self): subBuffer = self.currentBuffer.addSubBuffer()