summaryrefslogtreecommitdiff
path: root/suds/bindings/binding.py
diff options
context:
space:
mode:
authorjortel <devnull@localhost>2008-10-17 21:52:52 +0000
committerjortel <devnull@localhost>2008-10-17 21:52:52 +0000
commita411b66489a5ac25b041a6a54c64e0d7a3a873b7 (patch)
treeeee0bf1cf43fea6639d0101b5039a1d68bfa86db /suds/bindings/binding.py
parente957bf5be329ecf3c7d5a2bc17b30bd712fbfcee (diff)
downloadsuds-a411b66489a5ac25b041a6a54c64e0d7a3a873b7.tar.gz
Refactor xsd queries and shift query execution away from the schema and to the specialized query. This better enables deep element lookups; Enhance soap header processing in that soap headers are processed using the same approach as method parameters. The type is positionally resolved making it possible to pass simple header types like strings and integers as python types (no longer need to get from factory).
Diffstat (limited to 'suds/bindings/binding.py')
-rw-r--r--suds/bindings/binding.py92
1 files changed, 55 insertions, 37 deletions
diff --git a/suds/bindings/binding.py b/suds/bindings/binding.py
index 445d4d7..689d6ca 100644
--- a/suds/bindings/binding.py
+++ b/suds/bindings/binding.py
@@ -26,7 +26,7 @@ from suds.sax.element import Element
from suds.sudsobject import Factory, Object
from suds.bindings.marshaller import Marshaller
from suds.bindings.unmarshaller import Unmarshaller
-from suds.xsd.query import Query
+from suds.xsd.query import TypeQuery, ElementQuery
from suds.bindings.multiref import MultiRef
log = getLogger(__name__)
@@ -107,10 +107,11 @@ class Binding:
@return: The soap message.
@rtype: str
"""
+ content = self.headercontent(method, soapheaders)
+ header = self.header(content)
content = self.bodycontent(method, args)
body = self.body(content)
- header = self.header(soapheaders)
- env = self.envelope(body, header)
+ env = self.envelope(header, body)
env.promotePrefixes()
return env
@@ -247,13 +248,13 @@ class Binding:
return tags
return marshaller.process(object, pdef[1], pdef[0])
- def envelope(self, body, header):
+ def envelope(self, header, body):
"""
Build the B{<Envelope/>} for an soap outbound message.
- @param body: The soap message B{body}.
- @type body: L{Element}
@param header: The soap message B{header}.
@type header: L{Element}
+ @param body: The soap message B{body}.
+ @type body: L{Element}
@return: The soap envelope containing the body and header.
@rtype: L{Element}
"""
@@ -264,45 +265,52 @@ class Binding:
env.append(body)
return env
- def header(self, headers):
+ def header(self, content):
"""
- Build the B{<Header/>} for an soap outbound message.
- @param headers: A collection of header objects.
- @type headers: [L{Object},..]
- @return: The soap header fragment.
+ Build the B{<Body/>} for an soap outbound message.
+ @param method: The name of the method.
+ @return: the soap body fragment.
@rtype: L{Element}
"""
- hdr = Element('Header', ns=envns)
- if not isinstance(headers, (list,tuple)):
- headers = (headers,)
- if self.encoded:
- marshaller = self.marshaller.encoded
- else:
- marshaller = self.marshaller.literal
- for h in headers:
- tag = h.__class__.__name__
- if isinstance(h, Object):
- value = h
- type = h.__metadata__.__type__
- node = marshaller.process(value, type, tag)
- hdr.append(node)
- else:
- log.error('soapheader (%s) must be Object', tag)
- return hdr
+ header = Element('Header', ns=envns)
+ header.append(content)
+ return header
+
+ def headercontent(self, method, headers):
+ """
+ Get the content for the soap I{Header} node.
+ @param method: A service method.
+ @type method: I{service.Method}
+ @param headers: method parameter values
+ @type headers: list
+ @return: The xml content for the <body/>
+ @rtype: [L{Element},..]
+ """
+ n = 0
+ content = []
+ if len(headers):
+ pts = self.part_types(method, header=True)
+ for header in headers:
+ if len(pts) == n: break
+ p = self.param(method, pts[n], header)
+ if p is not None:
+ content.append(p)
+ n += 1
+ return content
+
- def body(self, method):
+ def body(self, content):
"""
Build the B{<Body/>} for an soap outbound message.
@param method: The name of the method.
@return: the soap body fragment.
@rtype: L{Element}
"""
- ns = self.wsdl.tns
body = Element('Body', ns=envns)
- body.append(method)
+ body.append(content)
return body
- def part_types(self, method, input=True):
+ def part_types(self, method, input=True, header=False):
"""
Get a list of I{parameter definitions} (pdef) defined for the specified method.
Each I{pdef} is a tuple (I{name}, L{xsd.sxbase.SchemaObject})
@@ -310,17 +318,27 @@ class Binding:
@type method: I{service.Method}
@param input: Defines input/output message.
@type input: boolean
+ @param header: Defines if parts are for soapheader.
+ @type header: boolean
@return: A list of parameter definitions
@rtype: [I{pdef},]
"""
result = []
if input:
- parts = method.message.input.parts
+ if header:
+ parts = method.soap.input.header.message.parts
+ else:
+ parts = method.message.input.parts
else:
- parts = method.message.output.parts
+ if header:
+ parts = method.soap.input.header.message.parts
+ else:
+ parts = method.message.output.parts
for p in parts:
- qref = p.xsref()
- query = Query(qref)
+ if p.element is not None:
+ query = ElementQuery(p.element)
+ else:
+ query = TypeQuery(p.type)
pt = query.execute(self.schema)
if pt is None:
raise TypeNotFound(qref)
@@ -339,6 +357,6 @@ class Binding:
@rtype: [I{rtype},..]
"""
result = []
- for rt in self.part_types(method, False):
+ for rt in self.part_types(method, input=False):
result.append(rt)
return result