[gen] First draft of using POD ODS (Calc) templates.
This commit is contained in:
parent
47bcf87a5c
commit
ad94fee755
|
@ -139,9 +139,10 @@ class Buffer:
|
||||||
|
|
||||||
def getLength(self): pass # To be overridden
|
def getLength(self): pass # To be overridden
|
||||||
|
|
||||||
def dumpStartElement(self, elem, attrs={}):
|
def dumpStartElement(self, elem, attrs={}, ignoreAttrs=()):
|
||||||
self.write('<%s' % elem)
|
self.write('<%s' % elem)
|
||||||
for name, value in attrs.items():
|
for name, value in attrs.items():
|
||||||
|
if ignoreAttrs and (name in ignoreAttrs): continue
|
||||||
self.write(' %s=%s' % (name, quoteattr(value)))
|
self.write(' %s=%s' % (name, quoteattr(value)))
|
||||||
self.write('>')
|
self.write('>')
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,8 @@ class PodEnvironment(OdfEnvironment):
|
||||||
self.ifActions = []
|
self.ifActions = []
|
||||||
# Currently walked named "if" actions
|
# Currently walked named "if" actions
|
||||||
self.namedIfActions = {} #~{s_statementName: IfAction}~
|
self.namedIfActions = {} #~{s_statementName: IfAction}~
|
||||||
|
# Currently parsed expression within an ODS template
|
||||||
|
self.currentOdsExpression = None
|
||||||
|
|
||||||
def getTable(self):
|
def getTable(self):
|
||||||
'''Gets the currently parsed table.'''
|
'''Gets the currently parsed table.'''
|
||||||
|
@ -208,14 +210,36 @@ class PodParser(OdfParser):
|
||||||
ns = e.onStartElement()
|
ns = e.onStartElement()
|
||||||
officeNs = ns[e.NS_OFFICE]
|
officeNs = ns[e.NS_OFFICE]
|
||||||
textNs = ns[e.NS_TEXT]
|
textNs = ns[e.NS_TEXT]
|
||||||
|
tableNs = ns[e.NS_TABLE]
|
||||||
if elem in e.ignorableElements:
|
if elem in e.ignorableElements:
|
||||||
e.state = e.IGNORING
|
e.state = e.IGNORING
|
||||||
elif elem == ('%s:annotation' % officeNs):
|
elif elem == ('%s:annotation' % officeNs):
|
||||||
|
# Be it in an ODT or ODS template, an annotation is considered to
|
||||||
|
# contain a POD statement.
|
||||||
e.state = e.READING_STATEMENT
|
e.state = e.READING_STATEMENT
|
||||||
elif (elem == ('%s:change-start' % textNs)) or \
|
elif (elem == ('%s:change-start' % textNs)) or \
|
||||||
(elem == ('%s:conditional-text' % textNs)):
|
(elem == ('%s:conditional-text' % textNs)):
|
||||||
|
# In an ODT template, any text in track-changes or any conditional
|
||||||
|
# field is considered to contain a POD expression.
|
||||||
e.state = e.READING_EXPRESSION
|
e.state = e.READING_EXPRESSION
|
||||||
e.exprHasStyle = False
|
e.exprHasStyle = False
|
||||||
|
elif (elem == ('%s:table-cell' % tableNs)) and \
|
||||||
|
attrs.has_key('%s:formula' % tableNs) and \
|
||||||
|
(attrs['%s:value-type' % officeNs] == 'string'):
|
||||||
|
# In an ODS template, any cell containing a formula of type "string"
|
||||||
|
# is considered to contain a POD expression. But here it is a
|
||||||
|
# special case: we need to dump the cell; the expression is not
|
||||||
|
# directly contained within this cell; the expression will be
|
||||||
|
# contained in the next inner paragraph. So we must here dump the
|
||||||
|
# cell, but without some attributes, because the "formula" will be
|
||||||
|
# converted to the result of evaluating the POD expression.
|
||||||
|
if e.mode == e.ADD_IN_SUBBUFFER:
|
||||||
|
e.addSubBuffer()
|
||||||
|
e.currentBuffer.addElement(e.currentElem.name)
|
||||||
|
e.currentBuffer.dumpStartElement(elem, attrs,
|
||||||
|
ignoreAttrs=('%s:formula'%tableNs, '%s:string-value'%officeNs))
|
||||||
|
# We already have the POD expression: remember it on the env.
|
||||||
|
e.currentOdsExpression = attrs['%s:string-value' % officeNs]
|
||||||
else:
|
else:
|
||||||
if e.state == e.IGNORING:
|
if e.state == e.IGNORING:
|
||||||
pass
|
pass
|
||||||
|
@ -258,6 +282,11 @@ class PodParser(OdfParser):
|
||||||
if e.state == e.IGNORING:
|
if e.state == e.IGNORING:
|
||||||
pass
|
pass
|
||||||
elif e.state == e.READING_CONTENT:
|
elif e.state == e.READING_CONTENT:
|
||||||
|
# Dump the ODS POD expression if any
|
||||||
|
if e.currentOdsExpression:
|
||||||
|
e.currentBuffer.addExpression(e.currentOdsExpression)
|
||||||
|
e.currentOdsExpression = None
|
||||||
|
# Dump the ending tag
|
||||||
e.currentBuffer.dumpEndElement(elem)
|
e.currentBuffer.dumpEndElement(elem)
|
||||||
if elem in e.impactableElements:
|
if elem in e.impactableElements:
|
||||||
if isinstance(e.currentBuffer, MemoryBuffer):
|
if isinstance(e.currentBuffer, MemoryBuffer):
|
||||||
|
@ -302,7 +331,12 @@ class PodParser(OdfParser):
|
||||||
if e.state == e.IGNORING:
|
if e.state == e.IGNORING:
|
||||||
pass
|
pass
|
||||||
elif e.state == e.READING_CONTENT:
|
elif e.state == e.READING_CONTENT:
|
||||||
e.currentBuffer.dumpContent(content)
|
if e.currentOdsExpression:
|
||||||
|
# Do not write content if we have encountered an ODS expression:
|
||||||
|
# we will replace this content with the expression's result.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
e.currentBuffer.dumpContent(content)
|
||||||
elif e.state == e.READING_STATEMENT:
|
elif e.state == e.READING_STATEMENT:
|
||||||
if e.currentElem.elem.startswith(e.namespaces[e.NS_TEXT]):
|
if e.currentElem.elem.startswith(e.namespaces[e.NS_TEXT]):
|
||||||
e.currentContent += content
|
e.currentContent += content
|
||||||
|
|
|
@ -494,7 +494,8 @@ class Renderer:
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print WARNING_FINALIZE_ERROR % str(e)
|
print WARNING_FINALIZE_ERROR % str(e)
|
||||||
# Re-zip the result.
|
# Re-zip the result.
|
||||||
resultOdtName = os.path.join(self.tempFolder, 'result.odt')
|
resExt = os.path.splitext(self.template)[1]
|
||||||
|
resultOdtName = os.path.join(self.tempFolder, 'result%s' % resExt)
|
||||||
try:
|
try:
|
||||||
resultOdt = zipfile.ZipFile(resultOdtName,'w', zipfile.ZIP_DEFLATED)
|
resultOdt = zipfile.ZipFile(resultOdtName,'w', zipfile.ZIP_DEFLATED)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
|
|
@ -78,6 +78,7 @@ class AnnotationsRemover(OdfParser):
|
||||||
class Test(appy.shared.test.Test):
|
class Test(appy.shared.test.Test):
|
||||||
'''Abstract test class.'''
|
'''Abstract test class.'''
|
||||||
interestingOdtContent = ('content.xml', 'styles.xml')
|
interestingOdtContent = ('content.xml', 'styles.xml')
|
||||||
|
|
||||||
def __init__(self, testData, testDescription, testFolder, config, flavour):
|
def __init__(self, testData, testDescription, testFolder, config, flavour):
|
||||||
appy.shared.test.Test.__init__(self, testData, testDescription,
|
appy.shared.test.Test.__init__(self, testData, testDescription,
|
||||||
testFolder, config, flavour)
|
testFolder, config, flavour)
|
||||||
|
@ -85,6 +86,7 @@ class Test(appy.shared.test.Test):
|
||||||
self.contextsFolder = os.path.join(self.testFolder, 'contexts')
|
self.contextsFolder = os.path.join(self.testFolder, 'contexts')
|
||||||
self.resultsFolder = os.path.join(self.testFolder, 'results')
|
self.resultsFolder = os.path.join(self.testFolder, 'results')
|
||||||
self.result = None
|
self.result = None
|
||||||
|
|
||||||
def getContext(self, contextName):
|
def getContext(self, contextName):
|
||||||
'''Gets the objects that are in the context.'''
|
'''Gets the objects that are in the context.'''
|
||||||
contextPy = os.path.join(self.contextsFolder, contextName + '.py')
|
contextPy = os.path.join(self.contextsFolder, contextName + '.py')
|
||||||
|
@ -98,13 +100,20 @@ class Test(appy.shared.test.Test):
|
||||||
if not elem.startswith('__'):
|
if not elem.startswith('__'):
|
||||||
exec 'res[elem] = %s.%s' % (contextPkg, elem)
|
exec 'res[elem] = %s.%s' % (contextPkg, elem)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def do(self):
|
def do(self):
|
||||||
self.result = os.path.join(
|
self.result = os.path.join(
|
||||||
self.tempFolder, '%s.%s' % (
|
self.tempFolder, '%s.%s' % (
|
||||||
self.data['Name'], self.data['Result']))
|
self.data['Name'], self.data['Result']))
|
||||||
# Get the path to the template to use for this test
|
# Get the path to the template to use for this test
|
||||||
|
if self.data['Template'].endswith('.ods'):
|
||||||
|
suffix = ''
|
||||||
|
else:
|
||||||
|
# For ODT, which is the most frequent case, no need to specify the
|
||||||
|
# file extension.
|
||||||
|
suffix = '.odt'
|
||||||
template = os.path.join(self.templatesFolder,
|
template = os.path.join(self.templatesFolder,
|
||||||
self.data['Template'] + '.odt')
|
self.data['Template'] + suffix)
|
||||||
if not os.path.exists(template):
|
if not os.path.exists(template):
|
||||||
raise TesterError(TEMPLATE_NOT_FOUND % template)
|
raise TesterError(TEMPLATE_NOT_FOUND % template)
|
||||||
# Get the context
|
# Get the context
|
||||||
|
@ -127,6 +136,7 @@ class Test(appy.shared.test.Test):
|
||||||
# os.mkdir(tempFolder2)
|
# os.mkdir(tempFolder2)
|
||||||
#print 'Result is', self.result, 'temp folder 2 is', tempFolder2
|
#print 'Result is', self.result, 'temp folder 2 is', tempFolder2
|
||||||
#shutil.copy(self.result, tempFolder2)
|
#shutil.copy(self.result, tempFolder2)
|
||||||
|
|
||||||
def getOdtContent(self, odtFile):
|
def getOdtContent(self, odtFile):
|
||||||
'''Creates in the temp folder content.xml and styles.xml extracted
|
'''Creates in the temp folder content.xml and styles.xml extracted
|
||||||
from p_odtFile.'''
|
from p_odtFile.'''
|
||||||
|
@ -151,9 +161,13 @@ class Test(appy.shared.test.Test):
|
||||||
OdfEnvironment(), self)
|
OdfEnvironment(), self)
|
||||||
annotationsRemover.parse(fileContent)
|
annotationsRemover.parse(fileContent)
|
||||||
fileContent = annotationsRemover.getResult()
|
fileContent = annotationsRemover.getResult()
|
||||||
f.write(fileContent.encode('utf-8'))
|
try:
|
||||||
|
f.write(fileContent.encode('utf-8'))
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
f.write(fileContent)
|
||||||
f.close()
|
f.close()
|
||||||
zipFile.close()
|
zipFile.close()
|
||||||
|
|
||||||
def checkResult(self):
|
def checkResult(self):
|
||||||
'''r_ is False if the test succeeded.'''
|
'''r_ is False if the test succeeded.'''
|
||||||
# Get styles.xml and content.xml from the actual result
|
# Get styles.xml and content.xml from the actual result
|
||||||
|
@ -161,7 +175,7 @@ class Test(appy.shared.test.Test):
|
||||||
self.getOdtContent(self.result)
|
self.getOdtContent(self.result)
|
||||||
# Get styles.xml and content.xml from the expected result
|
# Get styles.xml and content.xml from the expected result
|
||||||
expectedResult = os.path.join(self.resultsFolder,
|
expectedResult = os.path.join(self.resultsFolder,
|
||||||
self.data['Name'] + '.odt')
|
self.data['Name'] + '.' + self.data['Result'])
|
||||||
if not os.path.exists(expectedResult):
|
if not os.path.exists(expectedResult):
|
||||||
raise TesterError(EXPECTED_RESULT_NOT_FOUND % expectedResult)
|
raise TesterError(EXPECTED_RESULT_NOT_FOUND % expectedResult)
|
||||||
self.getOdtContent(expectedResult)
|
self.getOdtContent(expectedResult)
|
||||||
|
|
1192
pod/test/Tests.rtf
1192
pod/test/Tests.rtf
File diff suppressed because it is too large
Load diff
4
pod/test/contexts/OdsSimple.py
Normal file
4
pod/test/contexts/OdsSimple.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
data = [ \
|
||||||
|
['1', 2, 'three'],
|
||||||
|
['A', 'BB', 'CCC']
|
||||||
|
]
|
BIN
pod/test/results/odsSimple.ods
Normal file
BIN
pod/test/results/odsSimple.ods
Normal file
Binary file not shown.
BIN
pod/test/templates/OdsSimple.ods
Normal file
BIN
pod/test/templates/OdsSimple.ods
Normal file
Binary file not shown.
Loading…
Reference in a new issue