[px] Added boolean param 'unicode' that defines if PX result must be unicode or an encoded str. [shared] dav: improved Resource.soap: better handling of HTTP header SOAPAction.

This commit is contained in:
Gaetan Delannay 2013-07-11 16:41:45 +02:00
parent 05292356e7
commit d4556306f2
3 changed files with 22 additions and 10 deletions

View file

@ -6,6 +6,7 @@
import xml.sax import xml.sax
from px_parser import PxParser, PxEnvironment from px_parser import PxParser, PxEnvironment
from appy.pod.buffers import MemoryBuffer from appy.pod.buffers import MemoryBuffer
from appy.shared.xml_parser import xmlPrologue, xhtmlPrologue
# Exception class -------------------------------------------------------------- # Exception class --------------------------------------------------------------
class PxError(Exception): pass class PxError(Exception): pass
@ -13,11 +14,11 @@ class PxError(Exception): pass
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class Px: class Px:
'''Represents a (chunk of) PX code.''' '''Represents a (chunk of) PX code.'''
xhtmlPrologue = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" '\ xmlPrologue = xmlPrologue
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' xhtmlPrologue = xhtmlPrologue
def __init__(self, content, isFileName=False, partial=True, def __init__(self, content, isFileName=False, partial=True,
template=None, hook=None, prologue=None): template=None, hook=None, prologue=None, unicode=True):
'''p_content is the PX code, as a string, or a file name if p_isFileName '''p_content is the PX code, as a string, or a file name if p_isFileName
is True. If this code represents a complete XML file, p_partial is is True. If this code represents a complete XML file, p_partial is
False. Else, we must surround p_content with a root tag to be able False. Else, we must surround p_content with a root tag to be able
@ -29,6 +30,9 @@ class Px:
If a p_prologue is specified, it will be rendered at the start of the If a p_prologue is specified, it will be rendered at the start of the
PX result. PX result.
By default, a PX's result will be a unicode. If you want to get an
encoded str instead, use p_unicode=False.
''' '''
# Get the PX content # Get the PX content
if isFileName: if isFileName:
@ -56,6 +60,8 @@ class Px:
self.hook = hook self.hook = hook
# Is there some (XML, XHTML...) prologue to dump? # Is there some (XML, XHTML...) prologue to dump?
self.prologue = prologue self.prologue = prologue
# Will the result be unicode or str?
self.unicode = unicode
def completeErrorMessage(self, parsingError): def completeErrorMessage(self, parsingError):
'''A p_parsingError occurred. Complete the error message with the '''A p_parsingError occurred. Complete the error message with the
@ -96,5 +102,7 @@ class Px:
res = result.content res = result.content
if self.prologue: if self.prologue:
res = self.prologue + res res = self.prologue + res
if not self.unicode:
res = res.encode('utf-8')
return res return res
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -58,7 +58,7 @@ class SoapDataEncoder:
def encode(self): def encode(self):
# Do nothing if we have a SOAP message already # Do nothing if we have a SOAP message already
if isinstance(self.data, basestring): return self.data if isinstance(self.data, basestring): return self.data
# self.data is here a Python object. Wrap it a SOAP Body. # self.data is here a Python object. Wrap it in a SOAP Body.
soap = Object(Body=self.data) soap = Object(Body=self.data)
# Marshall it. # Marshall it.
marshaller = XmlMarshaller(rootTag='Envelope', namespaces=self.ns, marshaller = XmlMarshaller(rootTag='Envelope', namespaces=self.ns,
@ -69,7 +69,7 @@ class SoapDataEncoder:
class HttpResponse: class HttpResponse:
'''Stores information about a HTTP response.''' '''Stores information about a HTTP response.'''
def __init__(self, code, text, headers, body, duration=None): def __init__(self, code, text, headers, body, duration=None):
self.code = code # The return code, ie 404, 200, ... self.code = code # The return code, ie 404, 200, 500...
self.text = text # Textual description of the code self.text = text # Textual description of the code
self.headers = headers # A dict-like object containing the headers self.headers = headers # A dict-like object containing the headers
self.body = body # The body of the HTTP response self.body = body # The body of the HTTP response
@ -260,17 +260,18 @@ class Resource:
headers['Content-Length'] = str(len(body)) headers['Content-Length'] = str(len(body))
return self.send('POST', uri, headers=headers, body=body) return self.send('POST', uri, headers=headers, body=body)
def soap(self, data, uri=None, headers={}, namespace=None): def soap(self, data, uri=None, headers={}, namespace=None, soapAction=None):
'''Sends a SOAP message to this resource. p_namespace is the URL of the '''Sends a SOAP message to this resource. p_namespace is the URL of the
server-specific namespace.''' server-specific namespace. If header value "SOAPAction" is different
from self.url, specify it in p_soapAction.'''
if not uri: uri = self.uri if not uri: uri = self.uri
# Prepare the data to send # Prepare the data to send
data = SoapDataEncoder(data, namespace).encode() data = SoapDataEncoder(data, namespace).encode()
headers['SOAPAction'] = self.url headers['SOAPAction'] = soapAction or self.url
headers['Content-Type'] = 'text/xml' headers['Content-Type'] = 'text/xml'
res = self.post(data, uri, headers=headers, encode=None) res = self.post(data, uri, headers=headers, encode=None)
# Unwrap content from the SOAP envelope # Unwrap content from the SOAP envelope
if hasattr(res.data, 'Body'):
res.data = res.data.Body res.data = res.data.Body
return res return res
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -31,6 +31,9 @@ from appy.shared.css import parseStyleAttribute
# Constants -------------------------------------------------------------------- # Constants --------------------------------------------------------------------
xmlPrologue = '<?xml version="1.0" encoding="utf-8" ?>\n' xmlPrologue = '<?xml version="1.0" encoding="utf-8" ?>\n'
xhtmlPrologue = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" '\
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n'
CONVERSION_ERROR = '"%s" value "%s" could not be converted by the XML ' \ CONVERSION_ERROR = '"%s" value "%s" could not be converted by the XML ' \
'unmarshaller.' 'unmarshaller.'
CUSTOM_CONVERSION_ERROR = 'Custom converter for "%s" values produced an ' \ CUSTOM_CONVERSION_ERROR = 'Custom converter for "%s" values produced an ' \