Use of a replacement to StringIO for managing encoding problems while marchalling Python objects.

This commit is contained in:
Gaetan Delannay 2010-02-02 16:25:10 +01:00
parent 36a740ed7e
commit 160c4960da
2 changed files with 30 additions and 20 deletions

View file

@ -37,6 +37,20 @@ class UnmarshalledFile:
self.content = '' # The binary content of the file of a file object
self.size = 0 # The length of the file in bytes.
class UnicodeBuffer:
'''With StringIO class, I have tons of encoding problems. So I define a
similar class here, that uses an internal unicode buffer.'''
def __init__(self):
self.buffer = u''
def write(self, s):
if s == None: return
if isinstance(s, unicode):
self.buffer += s
elif isinstance(s, str):
self.buffer += s.decode('utf-8')
else:
self.buffer += unicode(s)
# ------------------------------------------------------------------------------
class Dummy: pass
# ------------------------------------------------------------------------------

View file

@ -20,7 +20,7 @@
import xml.sax, difflib
from xml.sax.handler import ContentHandler, ErrorHandler
from xml.sax.xmlreader import InputSource
from StringIO import StringIO
from appy.shared import UnicodeBuffer
from appy.shared.errors import AppyError
# Error-related constants ------------------------------------------------------
@ -343,24 +343,16 @@ class XmlMarshaller:
def dumpString(self, res, s):
'''Dumps a string into the result.'''
if hasattr(self, 'cdata') and self.cdata: res.write('<![CDATA[')
# Try to solve encoding problems
try:
if hasattr(self, 'dumpUnicode') and self.dumpUnicode:
# Produce a unicode
s = s.decode('utf-8')
else:
# Produce a str
s = s.decode('utf-8').encode('utf-8')
except UnicodeEncodeError:
pass
if self.cdata: res.write('<![CDATA[')
if isinstance(s, str):
s = s.decode('utf-8')
# Replace special chars by XML entities
for c in s:
if self.xmlEntities.has_key(c):
res.write(self.xmlEntities[c])
else:
res.write(c)
if hasattr(self, 'cdata') and self.cdata: res.write(']]>')
if self.cdata: res.write(']]>')
def dumpFile(self, res, v):
'''Dumps a file into the result.'''
@ -443,12 +435,15 @@ class XmlMarshaller:
res.write('</'); res.write(fieldName); res.write('>')
def marshall(self, instance, objectType='popo'):
'''Returns in a StringIO the XML version of p_instance. If p_instance
corresponds to a Plain Old Python Object, specify 'popo' for
p_objectType. If p_instance corresponds to an Archetypes object
'''Returns in a UnicodeBuffer the XML version of p_instance. If
p_instance corresponds to a Plain Old Python Object, specify 'popo'
for p_objectType. If p_instance corresponds to an Archetypes object
(Zope/Plone), specify 'archetype' for p_objectType. if p_instance is
a Appy object, specify "appy" as p_objectType.'''
res = StringIO()
if not hasattr(self, 'cdata'):
# The constructor has not been called. Do it now.
XmlMarshaller.__init__(self)
res = UnicodeBuffer()
# Dump the XML prologue and root element
if objectType in ('archetype', 'appy'):
objectId = instance.UID() # ID in DB
@ -508,9 +503,10 @@ class XmlMarshaller:
self.marshallSpecificElements(instance, res)
# Return the result
res.write('</'); res.write(self.rootElementName); res.write('>')
data = res.getvalue()
res.close()
return data
res = res.buffer
if not self.dumpUnicode:
res = res.encode('utf-8')
return res
def marshallSpecificElements(self, instance, res):
'''You can use this marshaller as a base class for creating your own.