python3 compatibility fixes

This commit is contained in:
Stefan Klug 2015-11-03 20:55:21 +01:00
parent 65565c7b16
commit 07adc8ce4c
16 changed files with 52 additions and 62 deletions

View file

@ -88,7 +88,7 @@ class Hack:
'''Injects any method or attribute from p_patchClass into klass.''' '''Injects any method or attribute from p_patchClass into klass.'''
patched = [] patched = []
added = [] added = []
for name, attr in patchClass.__dict__.iteritems(): for name, attr in patchClass.__dict__.items():
if name.startswith('__'): continue # Ignore special methods if name.startswith('__'): continue # Ignore special methods
# Unwrap functions from static methods # Unwrap functions from static methods
if attr.__class__.__name__ == 'staticmethod': if attr.__class__.__name__ == 'staticmethod':

View file

@ -69,7 +69,7 @@ class PodError(Exception):
'<%s:date>%s</%s:date><%s:p>' % \ '<%s:date>%s</%s:date><%s:p>' % \
(officeNs, dcNs, dcNs, dcNs, (officeNs, dcNs, dcNs, dcNs,
time.strftime('%Y-%m-%dT%H:%M:%S'), dcNs, textNs)) time.strftime('%Y-%m-%dT%H:%M:%S'), dcNs, textNs))
buffer.dumpContent(message) buffer.dumpContent(str(message))
buffer.write('</%s:p>' % textNs) buffer.write('</%s:p>' % textNs)
if dumpTb: if dumpTb:
# We don't dump the traceback if it is an expression error (it is # We don't dump the traceback if it is an expression error (it is

View file

@ -222,7 +222,7 @@ class FileBuffer(Buffer):
def __init__(self, env, result): def __init__(self, env, result):
Buffer.__init__(self, env, None) Buffer.__init__(self, env, None)
self.result = result self.result = result
self.content = file(result, 'w') self.content = open(result, 'w', encoding='utf-8')
self.content.write(xmlPrologue) self.content.write(xmlPrologue)
# getLength is used to manage insertions into sub-buffers. But in the case # getLength is used to manage insertions into sub-buffers. But in the case
@ -231,10 +231,7 @@ class FileBuffer(Buffer):
def getLength(self): return 0 def getLength(self): return 0
def write(self, something): def write(self, something):
try: self.content.write(something)
self.content.write(something.encode('utf-8'))
except UnicodeDecodeError:
self.content.write(something)
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.
@ -674,7 +671,7 @@ class MemoryBuffer(Buffer):
# Find the start position of the deepest element to remove # Find the start position of the deepest element to remove
deepestElem = self.action.elem.DEEPEST_TO_REMOVE deepestElem = self.action.elem.DEEPEST_TO_REMOVE
pos = self.content.find('<%s' % deepestElem.elem) pos = self.content.find('<%s' % deepestElem.elem)
for index in self.elements.keys(): for index in list(self.elements.keys()):
if index < pos: del self.elements[index] if index < pos: del self.elements[index]
reTagContent = re.compile('<(?P<p>[\w-]+):(?P<f>[\w-]+)(.*?)>.*</(?P=p):' \ reTagContent = re.compile('<(?P<p>[\w-]+):(?P<f>[\w-]+)(.*?)>.*</(?P=p):' \

View file

@ -150,7 +150,7 @@ class Expression(PodElement):
if resultType == 'NoneType': if resultType == 'NoneType':
res = '' res = ''
elif resultType == 'str': elif resultType == 'str':
res = res.decode('utf-8') pass
elif resultType == 'unicode': elif resultType == 'unicode':
pass # Don't perform any conversion, unicode is the target type. pass # Don't perform any conversion, unicode is the target type.
elif resultType == 'Px': elif resultType == 'Px':

View file

@ -38,7 +38,7 @@ class OdInsert:
styles). OdInsert instances define such 'inserts' (what to insert and styles). OdInsert instances define such 'inserts' (what to insert and
when).''' when).'''
def __init__(self, odtChunk, elem, nsUris={}): def __init__(self, odtChunk, elem, nsUris={}):
self.odtChunk = odtChunk.decode('utf-8') # The odt chunk to insert self.odtChunk = odtChunk # The odt chunk to insert
self.elem = elem # The p_odtChunk will be inserted just after the p_elem self.elem = elem # The p_odtChunk will be inserted just after the p_elem
# start, which must be an XmlElement instance. If more than one p_elem # start, which must be an XmlElement instance. If more than one p_elem
# is present in the odt file, the p_odtChunk will be inserted only at # is present in the odt file, the p_odtChunk will be inserted only at

View file

@ -177,8 +177,8 @@ class Renderer:
self.unzipFolder = os.path.join(self.tempFolder, 'unzip') self.unzipFolder = os.path.join(self.tempFolder, 'unzip')
os.mkdir(self.unzipFolder) os.mkdir(self.unzipFolder)
info = unzip(template, self.unzipFolder, odf=True) info = unzip(template, self.unzipFolder, odf=True)
self.contentXml = info['content.xml'] self.contentXml = info['content.xml'].decode('utf-8')
self.stylesXml = info['styles.xml'] self.stylesXml = info['styles.xml'].decode('utf-8')
self.stylesManager = StylesManager(self.stylesXml) self.stylesManager = StylesManager(self.stylesXml)
# From LibreOffice 3.5, it is not possible anymore to dump errors into # From LibreOffice 3.5, it is not possible anymore to dump errors into
# the resulting ods as annotations. Indeed, annotations can't reside # the resulting ods as annotations. Indeed, annotations can't reside
@ -524,11 +524,11 @@ class Renderer:
os.path.join(self.unzipFolder, innerFile)) os.path.join(self.unzipFolder, innerFile))
# Insert dynamic styles # Insert dynamic styles
contentXml = os.path.join(self.unzipFolder, 'content.xml') contentXml = os.path.join(self.unzipFolder, 'content.xml')
f = file(contentXml) f = open(contentXml, 'r+', encoding='utf-8')
dynamicStyles = ''.join(self.dynamicStyles) dynamicStyles = ''.join(self.dynamicStyles)
content = f.read().replace('<!DYNAMIC_STYLES!>', dynamicStyles) content = f.read().replace('<!DYNAMIC_STYLES!>', dynamicStyles)
f.close() f.seek(0)
f = file(contentXml, 'w') f.truncate(0)
f.write(content) f.write(content)
f.close() f.close()
# Call the user-defined "finalize" function when present # Call the user-defined "finalize" function when present

View file

@ -94,7 +94,7 @@ class Test(appy.shared.test.Test):
raise TesterError(CONTEXT_NOT_FOUND % contextPy) raise TesterError(CONTEXT_NOT_FOUND % contextPy)
contextPkg = 'appy.pod.test.contexts.%s' % contextName contextPkg = 'appy.pod.test.contexts.%s' % contextName
exec('import %s' % contextPkg) exec('import %s' % contextPkg)
exec('context = dir(%s)' % contextPkg) context = eval('dir(%s)' % contextPkg)
res = {} res = {}
for elem in context: for elem in context:
if not elem.startswith('__'): if not elem.startswith('__'):
@ -149,7 +149,7 @@ class Test(appy.shared.test.Test):
zipFile = zipfile.ZipFile(odtFile) zipFile = zipfile.ZipFile(odtFile)
for zippedFile in zipFile.namelist(): for zippedFile in zipFile.namelist():
if zippedFile in self.interestingOdtContent: if zippedFile in self.interestingOdtContent:
f = file(os.path.join(self.tempFolder, f = open(os.path.join(self.tempFolder,
'%s.%s' % (filePrefix, zippedFile)), 'wb') '%s.%s' % (filePrefix, zippedFile)), 'wb')
fileContent = zipFile.read(zippedFile) fileContent = zipFile.read(zippedFile)
if zippedFile == 'content.xml': if zippedFile == 'content.xml':
@ -159,12 +159,10 @@ class Test(appy.shared.test.Test):
# to the other. So we remove those paths. # to the other. So we remove those paths.
annotationsRemover = AnnotationsRemover( annotationsRemover = AnnotationsRemover(
OdfEnvironment(), self) OdfEnvironment(), self)
annotationsRemover.parse(fileContent) annotationsRemover.parse(fileContent.decode('utf-8'))
fileContent = annotationsRemover.getResult() fileContent = annotationsRemover.getResult().encode('utf-8')
try:
f.write(fileContent.encode('utf-8')) f.write(fileContent)
except UnicodeDecodeError:
f.write(fileContent)
f.close() f.close()
zipFile.close() zipFile.close()

View file

@ -282,7 +282,7 @@ class HtmlTable:
decl = '<%s:style %s:name="%s.%d" %s:family="table-column">' \ decl = '<%s:style %s:name="%s.%d" %s:family="table-column">' \
'<%s:table-column-properties %s:rel-column-width="%d*"' \ '<%s:table-column-properties %s:rel-column-width="%d*"' \
'/></%s:style>' % (s, s, self.name, i, s, s, s, width, s) '/></%s:style>' % (s, s, self.name, i, s, s, s, width, s)
renderer.dynamicStyles.append(decl.encode('utf-8')) renderer.dynamicStyles.append(decl)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class XhtmlEnvironment(XmlEnvironment): class XhtmlEnvironment(XmlEnvironment):
@ -512,7 +512,7 @@ class XhtmlEnvironment(XmlEnvironment):
sizes = table.columnContentSizes sizes = table.columnContentSizes
# Insert None values if the list is too small # Insert None values if the list is too small
while (len(sizes)-1) < table.cellIndex: sizes.append(None) while (len(sizes)-1) < table.cellIndex: sizes.append(None)
highest = max(sizes[table.cellIndex], table.cellContentSize, 5) highest = max(sizes[table.cellIndex] or 0, table.cellContentSize, 5)
# Put a maximum # Put a maximum
highest = min(highest, 100) highest = min(highest, 100)
sizes[table.cellIndex] = highest sizes[table.cellIndex] = highest

View file

@ -10,7 +10,7 @@ def parseStyleAttribute(value, asDict=False):
else: res = [] else: res = []
for attr in value.split(';'): for attr in value.split(';'):
if not attr.strip(): continue if not attr.strip(): continue
name, value = attr.split(':') name, value = attr.split(':', 1)
if asDict: res[name.strip()] = value.strip() if asDict: res[name.strip()] = value.strip()
else: res.append( (name.strip(), value.strip()) ) else: res.append( (name.strip(), value.strip()) )
return res return res
@ -42,9 +42,9 @@ class CssStyles:
'''Analyses styles as found in p_attrs and sets, for every found style, '''Analyses styles as found in p_attrs and sets, for every found style,
an attribute on self.''' an attribute on self.'''
# First, parse the "style" attr if present # First, parse the "style" attr if present
if attrs.has_key('style'): if 'style' in attrs.keys():
styles = parseStyleAttribute(attrs['style'], asDict=True) styles = parseStyleAttribute(attrs['style'], asDict=True)
for name, value in styles.iteritems(): for name, value in styles.items():
if name in CssStyles.withUnit: if name in CssStyles.withUnit:
value = CssValue(value) value = CssValue(value)
setattr(self, name.replace('-', ''), value) setattr(self, name.replace('-', ''), value)
@ -52,12 +52,12 @@ class CssStyles:
# override corresponding attributes from the "styles" attributes if # override corresponding attributes from the "styles" attributes if
# found. # found.
for name in ('width', 'height'): for name in ('width', 'height'):
if not hasattr(self, name) and attrs.has_key(name): if not hasattr(self, name) and name in attrs.keys():
setattr(self, name, CssValue(attrs[name])) setattr(self, name, CssValue(attrs[name]))
def __repr__(self): def __repr__(self):
res = '<CSS' res = '<CSS'
for name, value in self.__dict__.iteritems(): for name, value in self.__dict__.items():
res += ' %s:%s' % (name, value) res += ' %s:%s' % (name, value)
return res + '>' return res + '>'
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -111,15 +111,15 @@ class CsvParser:
Python type specified in p_basicType (int, float, ...).''' Python type specified in p_basicType (int, float, ...).'''
if (basicType != str) and (basicType != str): if (basicType != str) and (basicType != str):
try: try:
exec('res = %s' % str(value)) res = eval('%s' % str(value))
except SyntaxError as se: except SyntaxError as se:
res = None res = None
else: else:
try: try:
exec('res = """%s"""' % str(value)) res = eval('"""%s"""' % str(value))
except SyntaxError as se: except SyntaxError as se:
try: try:
exec("res = '''%s'''" % str(value)) res = eval("res = '''%s'''" % str(value))
except SyntaxError as se: except SyntaxError as se:
res = None res = None
return res return res

View file

@ -34,7 +34,7 @@ class FormDataEncoder:
def encode(self): def encode(self):
res = [] res = []
for name, value in self.data.iteritems(): for name, value in self.data.items():
res.append(self.marshalValue(name, value)) res.append(self.marshalValue(name, value))
return '&'.join(res) return '&'.join(res)

View file

@ -306,16 +306,16 @@ class HtmlDiff:
else: tag = 'span' else: tag = 'span'
# What message will it show in its 'title' attribute? # What message will it show in its 'title' attribute?
if not msg: if not msg:
exec('msg = self.%sMsg' % type) msg = eval('self.%sMsg' % type)
# What CSS class (or, if none, tag-specific style) will be used ? # What CSS class (or, if none, tag-specific style) will be used ?
exec('cssClass = self.%sCss' % type) cssClass = eval('self.%sCss' % type)
if cssClass: if cssClass:
style = 'class="%s"' % cssClass style = 'class="%s"' % cssClass
else: else:
exec('style = self.%sStyle' % type) style = eval('self.%sStyle' % type)
style = 'style="%s"' % style style = 'style="%s"' % style
# The 'name' attribute of the tag indicates the type of the update. # The 'name' attribute of the tag indicates the type of the update.
exec('tagName = self.%sName' % type) tagName = eval('self.%sName' % type)
# The idea is: if there are several lines, every line must be surrounded # The idea is: if there are several lines, every line must be surrounded
# by a tag. This way, we know that a surrounding tag can't span several # by a tag. This way, we know that a surrounding tag can't span several
# lines, which is a prerequisite for managing cumulative diffs. # lines, which is a prerequisite for managing cumulative diffs.

View file

@ -83,7 +83,7 @@ class LdapConfig:
dict of params usable for creating or updating the corresponding dict of params usable for creating or updating the corresponding
Appy user.''' Appy user.'''
res = {} res = {}
for name, appyName in self.ldapAttributes.iteritems(): for name, appyName in self.ldapAttributes.items():
if not appyName: continue if not appyName: continue
# Get the name of the attribute as known in the LDAP # Get the name of the attribute as known in the LDAP
ldapName = getattr(self, name) ldapName = getattr(self, name)
@ -111,7 +111,7 @@ class LdapConfig:
user = tool.search1('User', noSecurity=True, login=login) user = tool.search1('User', noSecurity=True, login=login)
if user: if user:
# Yes. Update it with info about him from the LDAP # Yes. Update it with info about him from the LDAP
for name, value in attrs.iteritems(): for name, value in attrs.items():
currentValue = getattr(user, name) currentValue = getattr(user, name)
if value != currentValue: if value != currentValue:
setattr(user, name, value) setattr(user, name, value)

View file

@ -69,11 +69,9 @@ class TestReport:
TestReport.instance = self TestReport.instance = self
else: else:
raise InternalError(TEST_REPORT_SINGLETON_ERROR) raise InternalError(TEST_REPORT_SINGLETON_ERROR)
def say(self, msg, force=False, encoding=None): def say(self, msg, force=False):
if self.verbose or force: if self.verbose or force:
print(msg) print(msg)
if encoding:
self.report.write(msg.encode(encoding))
else: else:
self.report.write(msg) self.report.write(msg)
self.report.write('\n') self.report.write('\n')

View file

@ -194,7 +194,7 @@ def flipDict(d):
'''Flips dict p_d: keys become values, values become keys. p_d is left '''Flips dict p_d: keys become values, values become keys. p_d is left
untouched: a new, flipped, dict is returned.''' untouched: a new, flipped, dict is returned.'''
res = {} res = {}
for k, v in d.iteritems(): res[v] = k for k, v in d.items(): res[v] = k
return res return res
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -291,7 +291,7 @@ def normalizeString(s, usage='fileName'):
for char in s: for char in s:
if char not in fileNameIgnore: res += char if char not in fileNameIgnore: res += char
elif usage.startswith('alpha'): elif usage.startswith('alpha'):
exec('rex = %sRex' % usage) rex = eval('%sRex' % usage)
res = '' res = ''
for char in s: for char in s:
if rex.match(char): res += char if rex.match(char): res += char

View file

@ -222,7 +222,7 @@ class XmlParser(ContentHandler, ErrorHandler):
'''This method is called every time expat does not recognize an entity. '''This method is called every time expat does not recognize an entity.
We provide here support for HTML entities.''' We provide here support for HTML entities.'''
if name in HTML_ENTITIES: if name in HTML_ENTITIES:
self.characters(HTML_ENTITIES[name].decode('utf-8')) self.characters(HTML_ENTITIES[name])
else: else:
# Put a question mark instead of raising an exception. # Put a question mark instead of raising an exception.
self.characters('?') self.characters('?')
@ -245,23 +245,20 @@ class XmlParser(ContentHandler, ErrorHandler):
- a file instance opened for reading. Note that in this case, this - a file instance opened for reading. Note that in this case, this
method will close it. method will close it.
''' '''
try: from io import BytesIO
from io import StringIO
except ImportError:
from io import StringIO
self._xml = xml self._xml = xml
self.parser.setContentHandler(self) self.parser.setContentHandler(self)
self.parser.setErrorHandler(self) self.parser.setErrorHandler(self)
self.parser.setFeature(feature_external_ges, False) self.parser.setFeature(feature_external_ges, False)
inputSource = InputSource() inputSource = InputSource()
if source == 'string': if source == 'string':
inputSource.setByteStream(StringIO(xml)) inputSource.setByteStream(BytesIO(xml.encode('utf-8')))
else: else:
if not isinstance(xml, file): if isinstance(xml, str):
xml = file(xml) xml = open(xml,'rb')
inputSource.setByteStream(xml) inputSource.setByteStream(xml)
self.parser.parse(inputSource) self.parser.parse(inputSource)
if isinstance(xml, file): xml.close() if hasattr(xml, 'close'): xml.close()
return self.res return self.res
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -464,7 +461,7 @@ class XmlUnmarshaller(XmlParser):
# If not, try a standard conversion # If not, try a standard conversion
elif e.currentBasicType in self.numericTypes: elif e.currentBasicType in self.numericTypes:
try: try:
exec('value = %s' % value) value = eval('%s' % value)
except SyntaxError: except SyntaxError:
raise AppyError(CONVERSION_ERROR % ( raise AppyError(CONVERSION_ERROR % (
e.currentBasicType, value)) e.currentBasicType, value))
@ -945,10 +942,10 @@ class XmlComparator:
# Perform the comparison # Perform the comparison
differ = difflib.Differ() differ = difflib.Differ()
if self.areXml: if self.areXml:
f = file(self.fileNameA) f = open(self.fileNameA, 'rb')
contentA = f.read() contentA = f.read()
f.close() f.close()
f = file(self.fileNameB) f = open(self.fileNameB, 'rb')
contentB = f.read() contentB = f.read()
f.close() f.close()
xmlHandler = XmlHandler(self.xmlTagsToIgnore, self.xmlAttrsToIgnore) xmlHandler = XmlHandler(self.xmlTagsToIgnore, self.xmlAttrsToIgnore)
@ -958,10 +955,10 @@ class XmlComparator:
xml.sax.parseString(contentB, xmlHandler) xml.sax.parseString(contentB, xmlHandler)
contentB = xmlHandler.res.split('\n') contentB = xmlHandler.res.split('\n')
else: else:
f = file(self.fileNameA) f = open(self.fileNameA, 'r', encoding=encoding)
contentA = f.readlines() contentA = f.readlines()
f.close() f.close()
f = file(self.fileNameB) f = open(self.fileNameB, 'r', encoding=encoding)
contentB = f.readlines() contentB = f.readlines()
f.close() f.close()
diffResult = list(differ.compare(contentA, contentB)) diffResult = list(differ.compare(contentA, contentB))
@ -975,17 +972,17 @@ class XmlComparator:
if not atLeastOneDiff: if not atLeastOneDiff:
msg = 'Difference(s) detected between files %s and %s:' % \ msg = 'Difference(s) detected between files %s and %s:' % \
(self.fileNameA, self.fileNameB) (self.fileNameA, self.fileNameB)
if report: report.say(msg, encoding='utf-8') if report: report.say(msg)
else: print(msg) else: print(msg)
atLeastOneDiff = True atLeastOneDiff = True
if not lastLinePrinted: if not lastLinePrinted:
if report: report.say('...') if report: report.say('...')
else: print('...') else: print('...')
if self.areXml: if self.areXml:
if report: report.say(line, encoding=encoding) if report: report.say(line)
else: print(line) else: print(line)
else: else:
if report: report.say(line[:-1], encoding=encoding) if report: report.say(line[:-1])
else: print((line[:-1])) else: print((line[:-1]))
lastLinePrinted = True lastLinePrinted = True
else: else: