class TypeWriter(SchemaItemWriter): """contains/generates a single definition""" logger = _GetLogger("TypeWriter") def fromSchemaItem(self, item): if item.isDefinition() is False or item.isLocal() is True: raise TypeError('expecting global type definition not: %s' % item.getItemTrace()) self.content = None if item.isSimple(): if item.content.isRestriction(): self.content = RestrictionContainer() elif item.content.isUnion(): self.content = UnionContainer() elif item.content.isList(): self.content = ListContainer() else: raise Wsdl2PythonError('unknown simple type definition: %s' % item.getItemTrace()) self.content.setUp(item) return if item.isComplex(): kw = {} if item.content is None or item.content.isModelGroup(): self.content = \ ComplexTypeContainer(\ do_extended=self.do_extended, extPyClasses=self.extPyClasses ) kw['empty'] = item.content is None elif item.content.isSimple(): self.content = ComplexTypeSimpleContentContainer() elif item.content.isComplex(): self.content = \ ComplexTypeComplexContentContainer(\ do_extended=self.do_extended ) else: raise Wsdl2PythonError('unknown complex type definition: %s' % item.getItemTrace()) self.logger.debug( 'TypeWriter setUp container "%r", Schema Item "%s"' % (self.content, item.getItemTrace())) try: self.content.setUp(item, **kw) except Exception as ex: args = ['Failure in setUp: %s' % item.getItemTrace()] args += ex.args ex.args = tuple(args) raise return raise TypeError('expecting SimpleType or ComplexType: %s' % item.getItemTrace())
class SchemaDescription: """generates classes for defs and decs in the schema instance. """ logger = _GetLogger("SchemaDescription") def __init__(self, do_extended=False, extPyClasses=None): self.classHead = NamespaceClassHeaderContainer() self.classFoot = NamespaceClassFooterContainer() self.items = [] self.__types = [] self.__elements = [] self.targetNamespace = None self.do_extended = do_extended self.extPyClasses = extPyClasses def fromSchema(self, schema): ''' Can be called multiple times, but will not redefine a previously defined type definition or element declaration. ''' ns = schema.getTargetNamespace() assert self.targetNamespace is None or self.targetNamespace == ns,\ 'SchemaDescription instance represents %s, not %s'\ %(self.targetNamespace, ns) if self.targetNamespace is None: self.targetNamespace = ns self.classHead.ns = self.classFoot.ns = ns for item in [ t for t in schema.types.values() if t.getAttributeName() not in self.__types ]: self.__types.append(item.getAttributeName()) self.items.append( TypeWriter(do_extended=self.do_extended, extPyClasses=self.extPyClasses)) self.items[-1].fromSchemaItem(item) for item in [ e for e in schema.elements.values() if e.getAttributeName() not in self.__elements ]: self.__elements.append(item.getAttributeName()) self.items.append(ElementWriter(do_extended=self.do_extended)) self.items[-1].fromSchemaItem(item) def getTypes(self): return self.__types def getElements(self): return self.__elements def write(self, fd): """write out to file descriptor. """ print(self.classHead, file=fd) for t in self.items: print(t, file=fd) print(self.classFoot, file=fd)
class Struct(ComplexType): '''Struct is a complex type for accessors identified by name. Constraint: No element may have the same name as any other, nor may any element have a maxOccurs > 1. <xs:group name="Struct" > <xs:sequence> <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" /> </xs:sequence> </xs:group> <xs:complexType name="Struct" > <xs:group ref="tns:Struct" minOccurs="0" /> <xs:attributeGroup ref="tns:commonAttributes"/> </xs:complexType> ''' logger = _GetLogger('ZSI.TCcompound.Struct') def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, mutable=True, **kw): '''pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the struct inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations ''' ComplexType.__init__(self, pyclass, ofwhat, pname=pname, inorder=inorder, inline=inline, mutable=mutable, **kw) # Check Constraints whats = [(what.nspname, what.pname) for what in self.ofwhat] for idx in range(len(self.ofwhat)): what = self.ofwhat[idx] key = (what.nspname, what.pname) if not isinstance(what, AnyElement) and what.maxOccurs > 1: raise TypeError( 'Constraint: no element can have a maxOccurs>1') if key in whats[idx + 1:]: raise TypeError( 'Constraint: No element may have the same name as any other' )
class NamedParamBinding(Binding): '''Like Binding, except the argument list for invocation is named parameters. ''' logger = _GetLogger('ZSI.client.Binding') def __getattr__(self, name): '''Return a callable object that will invoke the RPC method named by the attribute. ''' if name[:2] == '__' and len(name) > 5 and name[-2:] == '__': if hasattr(self, name): return getattr(self, name) return getattr(self.__class__, name) return _NamedParamCaller(self, name, self.namespace)
class AttachmentRef(SimpleType): '''Type code for Attachment. This attachment will work only with axis... ''' logger = _GetLogger('ZSI.TC.Attachment') type = (Apache.NS, "DataHandler") parselist = [(Apache.NS, "DataHandler")] #seriallist = [ types.FileType ] def __init__(self, pname=None, format='%s', **kw): TypeCode.__init__(self, pname, **kw) self.format = format def parse(self, elt, ps): #never invoked ??? #print "elt is: " + str(elt) #print "while ps: " + str(ps) return def get_formatted_content(self, pyobj): return self.format % pyobj def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): '''This function is in charge of serializing the attachment fist it add the <attachment href=""/> tag then it wraps up everything pyobj is the file descriptor pointing to the file we wanna attach elt is the ElementProxy containing the <inputFile> tag with the attachment tag sw SoapWriter ''' #print "serialize called with pyobj: " + str(pyobj) #adding the attachment tag if pyobj is None: return if not sw.Known(pyobj): sw.addAttachment(pyobj) idhref = id(pyobj) attachmentElement = elt.createAppendElement(None, "attachment", prefix="") attachmentElement.setAttributeNS(None, "href", "cid:" + str(idhref)) else: #print "the file " + pyobj + " was already attached" #do nothing #this should not happen pass
class SchemaItemWriter: """contains/generates a single declaration""" logger = _GetLogger("SchemaItemWriter") def __init__(self, do_extended=False, extPyClasses=None): self.content = None self.do_extended = do_extended self.extPyClasses = extPyClasses def __str__(self): '''this appears to set up whatever is in self.content.localElements, local elements simpleType|complexType. ''' assert self.content is not None, 'Must call fromSchemaItem to setup.' return str(self.content) def fromSchemaItem(self, item): raise NotImplementedError('')
class ElementWriter(SchemaItemWriter): """contains/generates a single declaration""" logger = _GetLogger("ElementWriter") def fromSchemaItem(self, item): """set up global elements. """ if item.isElement() is False or item.isLocal() is True: raise TypeError('expecting global element declaration: %s' % item.getItemTrace()) local = False qName = item.getAttribute('type') if not qName: etp = item.content local = True else: etp = item.getTypeDefinition('type') if etp is None: if local is True: self.content = ElementLocalComplexTypeContainer( do_extended=self.do_extended) else: self.content = ElementSimpleTypeContainer() elif etp.isLocal() is False: self.content = ElementGlobalDefContainer() elif etp.isSimple() is True: self.content = ElementLocalSimpleTypeContainer() elif etp.isComplex(): self.content = ElementLocalComplexTypeContainer( do_extended=self.do_extended) else: raise Wsdl2PythonError("Unknown element declaration: %s" % item.getItemTrace()) self.logger.debug( 'ElementWriter setUp container "%r", Schema Item "%s"' % (self.content, item.getItemTrace())) self.content.setUp(item)
class MessageWriter: logger = _GetLogger("MessageWriter") def __init__(self, do_extended=False): """Representation of a WSDL Message and associated WSDL Binding. operation -- boperation -- input -- rpc -- literal -- simple -- """ self.content = None self.do_extended = do_extended def __str__(self): if not self.content: raise Wsdl2PythonError('Must call setUp.') return self.content.getvalue() def setUp(self, soc, port, input=False): assert isinstance(soc, ServiceOperationContainer),\ 'expecting a ServiceOperationContainer instance' assert isinstance(port, WSDLTools.Port),\ 'expecting a WSDL.Port instance' rpc, literal = soc.isRPC(), soc.isLiteral(input) kw, klass = {}, None if rpc and literal: klass = ServiceRPCLiteralMessageContainer elif not rpc and literal: kw['do_extended'] = self.do_extended klass = ServiceDocumentLiteralMessageContainer elif rpc and not literal: klass = ServiceRPCEncodedMessageContainer else: raise WsdlGeneratorError('doc/enc not supported.') self.content = klass(**kw) self.content.setUp(port, soc, input)
class Binding(_Binding): '''Object that represents a binding (connection) to a SOAP server. Can be used in the "name overloading" style. class attr: gettypecode -- funcion that returns typecode from typesmodule, can be set so can use whatever mapping you desire. ''' gettypecode = staticmethod( lambda mod, e: getattr(mod, str(e.localName)).typecode) logger = _GetLogger('ZSI.client.Binding') def __init__(self, url, namespace=None, typesmodule=None, **kw): """ Parameters: url -- location of service namespace -- optional root element namespace typesmodule -- optional response only. dict(name=typecode), lookup for all children of root element. """ self.typesmodule = typesmodule self.namespace = namespace _Binding.__init__(self, url=url, **kw) def __getattr__(self, name): '''Return a callable object that will invoke the RPC method named by the attribute. ''' if name[:2] == '__' and len(name) > 5 and name[-2:] == '__': if hasattr(self, name): return getattr(self, name) return getattr(self.__class__, name) return _Caller(self, name, self.namespace) def __parse_child(self, node): '''for rpc-style map each message part to a class in typesmodule ''' try: tc = self.gettypecode(self.typesmodule, node) except: self.logger.debug( 'didnt find typecode for "%s" in typesmodule: %s', node.localName, self.typesmodule) tc = TC.Any(aslist=1) return tc.parse(node, self.ps) self.logger.debug('parse child with typecode : %s', tc) try: return tc.parse(node, self.ps) except Exception: self.logger.debug('parse failed try Any : %s', tc) tc = TC.Any(aslist=1) return tc.parse(node, self.ps) def Receive(self, replytype, **kw): '''Parse message, create Python object. KeyWord data: faults -- list of WSDL operation.fault typecodes wsaction -- If using WS-Address, must specify Action value we expect to receive. ''' self.ReceiveSOAP(**kw) ps = self.ps tp = _find_type(ps.body_root) isarray = ((type(tp) in (tuple, list) and tp[1] == 'Array') or _find_arraytype(ps.body_root)) if self.typesmodule is None or isarray: return _Binding.Receive(self, replytype, **kw) if ps.IsAFault(): msg = FaultFromFaultMessage(ps) raise FaultException(msg) tc = replytype if hasattr(replytype, 'typecode'): tc = replytype.typecode #Ignore response wrapper reply = {} for elt in _child_elements(ps.body_root): name = str(elt.localName) reply[name] = self.__parse_child(elt) if self.address is not None: self.address.checkResponse(ps, kw.get('wsaction')) return reply
class _Binding: '''Object that represents a binding (connection) to a SOAP server. Once the binding is created, various ways of sending and receiving SOAP messages are available. ''' defaultHttpTransport = http.client.HTTPConnection defaultHttpsTransport = http.client.HTTPSConnection logger = _GetLogger('ZSI.client.Binding') def __init__(self, nsdict=None, transport=None, url=None, tracefile=None, readerclass=None, writerclass=None, soapaction='', wsAddressURI=None, sig_handler=None, transdict=None, **kw): '''Initialize. Keyword arguments include: transport -- default use HTTPConnection. transdict -- dict of values to pass to transport. url -- URL of resource, POST is path soapaction -- value of SOAPAction header auth -- (type, name, password) triplet; default is unauth nsdict -- namespace entries to add tracefile -- file to dump packet traces cert_file, key_file -- SSL data (q.v.) readerclass -- DOM reader class writerclass -- DOM writer class, implements MessageInterface wsAddressURI -- namespaceURI of WS-Address to use. By default it's not used. sig_handler -- XML Signature handler, must sign and verify. endPointReference -- optional Endpoint Reference. ''' self.data = None self.ps = None self.user_headers = [] self.nsdict = nsdict or {} self.transport = transport self.transdict = transdict or {} self.url = url self.trace = tracefile self.readerclass = readerclass self.writerclass = writerclass self.soapaction = soapaction self.wsAddressURI = wsAddressURI self.sig_handler = sig_handler self.address = None self.endPointReference = kw.get('endPointReference', None) self.cookies = http.cookies.SimpleCookie() self.http_callbacks = {} if 'auth' in kw: self.SetAuth(*kw['auth']) else: self.SetAuth(AUTH.none) def SetAuth(self, style, user=None, password=None): '''Change auth style, return object to user. ''' self.auth_style, self.auth_user, self.auth_pass = \ style, user, password return self def SetURL(self, url): '''Set the URL we post to. ''' self.url = url return self def ResetHeaders(self): '''Empty the list of additional headers. ''' self.user_headers = [] return self def ResetCookies(self): '''Empty the list of cookies. ''' self.cookies = http.cookies.SimpleCookie() def AddHeader(self, header, value): '''Add a header to send. ''' self.user_headers.append((header, value)) return self def __addcookies(self): '''Add cookies from self.cookies to request in self.h ''' for cname, morsel in list(self.cookies.items()): attrs = [] value = morsel.get('version', '') if value != '' and value != '0': attrs.append('$Version=%s' % value) attrs.append('%s=%s' % (cname, morsel.coded_value)) value = morsel.get('path') if value: attrs.append('$Path=%s' % value) value = morsel.get('domain') if value: attrs.append('$Domain=%s' % value) self.h.putheader('Cookie', "; ".join(attrs)) def RPC(self, url, opname, obj, replytype=None, **kw): '''Send a request, return the reply. See Send() and Recieve() docstrings for details. ''' self.Send(url, opname, obj, **kw) return self.Receive(replytype, **kw) def Send(self, url, opname, obj, nsdict={}, soapaction=None, wsaction=None, endPointReference=None, soapheaders=(), **kw): '''Send a message. If url is None, use the value from the constructor (else error). obj is the object (data) to send. Data may be described with a requesttypecode keyword, the default is the class's typecode (if there is one), else Any. Try to serialize as a Struct, if this is not possible serialize an Array. If data is a sequence of built-in python data types, it will be serialized as an Array, unless requesttypecode is specified. arguments: url -- opname -- struct wrapper obj -- python instance key word arguments: nsdict -- soapaction -- wsaction -- WS-Address Action, goes in SOAP Header. endPointReference -- set by calling party, must be an EndPointReference type instance. soapheaders -- list of pyobj, typically w/typecode attribute. serialized in the SOAP:Header. requesttypecode -- ''' url = url or self.url endPointReference = endPointReference or self.endPointReference # Serialize the object. d = {} d.update(self.nsdict) d.update(nsdict) sw = SoapWriter( nsdict=d, header=True, outputclass=self.writerclass, encodingStyle=kw.get('encodingStyle'), ) requesttypecode = kw.get('requesttypecode') if '_args' in kw: #NamedParamBinding tc = requesttypecode or TC.Any(pname=opname, aslist=False) sw.serialize(kw['_args'], tc) elif not requesttypecode: tc = getattr(obj, 'typecode', None) or TC.Any(pname=opname, aslist=False) try: if type(obj) in _seqtypes: obj = dict([(i.typecode.pname, i) for i in obj]) except AttributeError: # can't do anything but serialize this in a SOAP:Array tc = TC.Any(pname=opname, aslist=True) else: tc = TC.Any(pname=opname, aslist=False) sw.serialize(obj, tc) else: sw.serialize(obj, requesttypecode) for i in soapheaders: sw.serialize_header(i) # # Determine the SOAP auth element. SOAP:Header element if self.auth_style & AUTH.zsibasic: sw.serialize_header(_AuthHeader(self.auth_user, self.auth_pass), _AuthHeader.typecode) # # Serialize WS-Address if self.wsAddressURI is not None: if self.soapaction and wsaction.strip('\'"') != self.soapaction: raise WSActionException('soapAction(%s) and WS-Action(%s) must match'\ %(self.soapaction,wsaction)) self.address = Address(url, self.wsAddressURI) self.address.setRequest(endPointReference, wsaction) self.address.serialize(sw) # # WS-Security Signature Handler if self.sig_handler is not None: self.sig_handler.sign(sw) scheme, netloc, path, nil, nil, nil = urllib.parse.urlparse(url) transport = self.transport if transport is None and url is not None: if scheme == 'https': transport = self.defaultHttpsTransport elif scheme == 'http': transport = self.defaultHttpTransport else: raise RuntimeError( 'must specify transport or url startswith https/http') # Send the request. if issubclass(transport, http.client.HTTPConnection) is False: raise TypeError('transport must be a HTTPConnection') soapdata = str(sw) self.h = transport(netloc, None, **self.transdict) self.h.connect() self.SendSOAPData(soapdata, url, soapaction, **kw) def SendSOAPData(self, soapdata, url, soapaction, headers={}, **kw): if isinstance(soapdata, str): soapdata = soapdata.encode(UNICODE_ENCODING) # Tracing? if self.trace: print("_" * 33, time.ctime(time.time()), "REQUEST:", file=self.trace) print(soapdata, file=self.trace) url = url or self.url request_uri = _get_postvalue_from_absoluteURI(url) self.h.putrequest("POST", request_uri) self.h.putheader("Content-Length", "%d" % len(soapdata)) self.h.putheader("Content-Type", 'text/xml; charset="%s"' % UNICODE_ENCODING) self.__addcookies() for header, value in list(headers.items()): self.h.putheader(header, value) SOAPActionValue = '"%s"' % (soapaction or self.soapaction) self.h.putheader("SOAPAction", SOAPActionValue) if self.auth_style & AUTH.httpbasic: val = _b64_encode(self.auth_user + ':' + self.auth_pass) \ .replace("\012", "") self.h.putheader('Authorization', 'Basic ' + val) elif self.auth_style == AUTH.httpdigest and 'Authorization' not in headers \ and 'Expect' not in headers: def digest_auth_cb(response): self.SendSOAPDataHTTPDigestAuth(response, soapdata, url, request_uri, soapaction, **kw) self.http_callbacks[401] = None self.http_callbacks[401] = digest_auth_cb for header, value in self.user_headers: self.h.putheader(header, value) self.h.endheaders() self.h.send(soapdata) # Clear prior receive state. self.data, self.ps = None, None def SendSOAPDataHTTPDigestAuth(self, response, soapdata, url, request_uri, soapaction, **kw): '''Resend the initial request w/http digest authorization headers. The SOAP server has requested authorization. Fetch the challenge, generate the authdict for building a response. ''' if self.trace: print("------ Digest Auth Header", file=self.trace) url = url or self.url if response.status != 401: raise RuntimeError('Expecting HTTP 401 response.') if self.auth_style != AUTH.httpdigest: raise RuntimeError( 'Auth style(%d) does not support requested digest authorization.' % self.auth_style) from pysphere.ZSI.digest_auth import fetch_challenge,\ generate_response,\ build_authorization_arg,\ dict_fetch chaldict = fetch_challenge(response.getheader('www-authenticate')) if dict_fetch(chaldict,'challenge','').lower() == 'digest' and \ dict_fetch(chaldict,'nonce',None) and \ dict_fetch(chaldict,'realm',None) and \ dict_fetch(chaldict,'qop',None): authdict = generate_response(chaldict, request_uri, self.auth_user, self.auth_pass, method='POST') headers = {\ 'Authorization':build_authorization_arg(authdict), 'Expect':'100-continue', } self.SendSOAPData(soapdata, url, soapaction, headers, **kw) return raise RuntimeError('Client expecting digest authorization challenge.') def ReceiveRaw(self, **kw): '''Read a server reply, unconverted to any format and return it. ''' if self.data: return self.data trace = self.trace while 1: response = self.h.getresponse() self.reply_code, self.reply_msg, self.reply_headers, self.data = \ response.status, response.reason, response.msg, response.read() if trace: print("_" * 33, time.ctime(time.time()), "RESPONSE:", file=trace) for i in ( self.reply_code, self.reply_msg, ): print(str(i), file=trace) print("-------", file=trace) print(str(self.reply_headers), file=trace) print(self.data, file=trace) saved = None for d in response.msg.get_all('set-cookie', []): if d[0] in [' ', '\t']: saved += d.strip() else: if saved: self.cookies.load(saved) saved = d.strip() if saved: self.cookies.load(saved) if response.status == 401: if not isinstance( self.http_callbacks.get(response.status, None), collections.Callable): raise RuntimeError('HTTP Digest Authorization Failed') self.http_callbacks[response.status](response) continue if response.status != 100: break # The httplib doesn't understand the HTTP continuation header. # Horrible internals hack to patch things up. self.h._HTTPConnection__state = http.client._CS_REQ_SENT self.h._HTTPConnection__response = None return self.data def IsSOAP(self): if self.ps: return 1 self.ReceiveRaw() mimetype = self.reply_headers.get_content_type() return mimetype == 'text/xml' def ReceiveSOAP(self, readerclass=None, **kw): '''Get back a SOAP message. ''' if self.ps: return self.ps if not self.IsSOAP(): raise TypeError('Response is "%s", not "text/xml"' % self.reply_headers.get_content_type()) if len(self.data) == 0: raise TypeError('Received empty response') self.ps = ParsedSoap(self.data, readerclass=readerclass or self.readerclass, encodingStyle=kw.get('encodingStyle')) if self.sig_handler is not None: self.sig_handler.verify(self.ps) return self.ps def IsAFault(self): '''Get a SOAP message, see if it has a fault. ''' self.ReceiveSOAP() return self.ps.IsAFault() def ReceiveFault(self, **kw): '''Parse incoming message as a fault. Raise TypeError if no fault found. ''' self.ReceiveSOAP(**kw) if not self.ps.IsAFault(): raise TypeError("Expected SOAP Fault not found") return FaultFromFaultMessage(self.ps) def Receive(self, replytype, **kw): '''Parse message, create Python object. KeyWord data: faults -- list of WSDL operation.fault typecodes wsaction -- If using WS-Address, must specify Action value we expect to receive. ''' self.ReceiveSOAP(**kw) if self.ps.IsAFault(): msg = FaultFromFaultMessage(self.ps) raise FaultException(msg) tc = replytype if hasattr(replytype, 'typecode'): tc = replytype.typecode reply = self.ps.Parse(tc) if self.address is not None: self.address.checkResponse(self.ps, kw.get('wsaction')) return reply def __repr__(self): return "<%s instance %s>" % (self.__class__.__name__, _get_idstr(self))
class ComplexType(TypeCode): '''Represents an element of complexType, potentially containing other elements. ''' logger = _GetLogger('ZSI.TCcompound.ComplexType') def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, mutable=True, mixed=False, mixed_aname='_text', **kw): '''pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the complexType inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations type -- the (URI,localname) of the datatype mixed -- mixed content model? True/False mixed_aname -- if mixed is True, specify text content here. Default _text ''' TypeCode.__init__(self, pname, pyclass=pyclass, **kw) self.inorder = inorder self.inline = inline self.mutable = mutable self.mixed = mixed self.mixed_aname = None if mixed is True: self.mixed_aname = mixed_aname if self.mutable is True: self.inline = True self.type = kw.get('type') or _get_xsitype(self) t = type(ofwhat) if t not in _seqtypes: raise TypeError( 'Struct ofwhat must be list or sequence, not ' + str(t)) self.ofwhat = tuple(ofwhat) if TypeCode.typechecks: # XXX Not sure how to determine if new-style class.. if self.pyclass is not None and \ type(self.pyclass) is not type and not isinstance(self.pyclass, object): raise TypeError('pyclass must be None or an old-style/new-style class, not ' + str(type(self.pyclass))) _check_typecode_list(self.ofwhat, 'ComplexType') def parse(self, elt, ps): debug = self.logger.debugOn() debug and self.logger.debug('parse') xtype = self.checkname(elt, ps) if self.type and xtype not in [ self.type, (None,None) ]: if not isinstance(self, TypeDefinition): raise EvaluateException(\ 'ComplexType for %s has wrong type(%s), looking for %s' % (self.pname, self.checktype(elt,ps), self.type), ps.Backtrace(elt)) else: #TODO: mabye change MRO to handle this debug and self.logger.debug('delegate to substitute type') what = TypeDefinition.getSubstituteType(self, elt, ps) return what.parse(elt, ps) href = _find_href(elt) if href: if _children(elt): raise EvaluateException('Struct has content and HREF', ps.Backtrace(elt)) elt = ps.FindLocalHREF(href, elt) c = _child_elements(elt) count = len(c) if self.nilled(elt, ps): return Nilled # Create the object. v = {} # parse all attributes contained in attribute_typecode_dict (user-defined attributes), # the values (if not None) will be keyed in self.attributes dictionary. attributes = self.parse_attributes(elt, ps) if attributes: v[self.attrs_aname] = attributes #MIXED if self.mixed is True: v[self.mixed_aname] = self.simple_value(elt,ps, mixed=True) # Clone list of kids (we null it out as we process) c, crange = c[:], list(range(len(c))) # Loop over all items we're expecting if debug: self.logger.debug("ofwhat: %s",str(self.ofwhat)) any = None for i,what in [ (i, self.ofwhat[i]) for i in range(len(self.ofwhat)) ]: # retrieve typecode if it is hidden if isinstance(what, collections.Callable): what = what() # Loop over all available kids if debug: self.logger.debug("what: (%s,%s)", what.nspname, what.pname) for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]: # Parse value, and mark this one done. if debug: self.logger.debug("child node: (%s,%s)", c_elt.namespaceURI, c_elt.tagName) match = False if what.name_match(c_elt): match = True value = what.parse(c_elt, ps) else: # substitutionGroup head must be a global element declaration # if successful delegate to matching GED subwhat = _get_substitute_element(what, c_elt, ps) if subwhat: match = True value = subwhat.parse(c_elt, ps) if debug: self.logger.debug("substitutionGroup: %s", subwhat) if match: if what.maxOccurs == UNBOUNDED or what.maxOccurs > 1: if what.aname in v: v[what.aname].append(value) else: v[what.aname] = [value] c[j] = None continue else: v[what.aname] = value c[j] = None break if debug: self.logger.debug("no element (%s,%s)", what.nspname, what.pname) # No match; if it was supposed to be here, that's an error. if self.inorder is True and i == j: raise EvaluateException('Out of order complexType', ps.Backtrace(c_elt)) else: # only supporting 1 <any> declaration in content. if isinstance(what,AnyElement): any = what elif hasattr(what, 'default'): v[what.aname] = what.default elif what.minOccurs > 0 and what.aname not in v: raise EvaluateException('Element "' + what.aname + \ '" missing from complexType', ps.Backtrace(elt)) # Look for wildcards and unprocessed children # XXX Stick all this stuff in "any", hope for no collisions if any is not None: occurs = 0 v[any.aname] = [] for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]: value = any.parse(c_elt, ps) if any.maxOccurs == UNBOUNDED or any.maxOccurs > 1: v[any.aname].append(value) else: v[any.aname] = value occurs += 1 # No such thing as nillable <any> if any.maxOccurs == 1 and occurs == 0: v[any.aname] = None elif occurs < any.minOccurs or (any.maxOccurs!=UNBOUNDED and any.maxOccurs<occurs): raise EvaluateException('occurances of <any> elements(#%d) bound by (%d,%s)' %( occurs, any.minOccurs,str(any.maxOccurs)), ps.Backtrace(elt)) if not self.pyclass: return v # type definition must be informed of element tag (nspname,pname), # element declaration is initialized with a tag. try: pyobj = self.pyclass() except Exception as e: raise TypeError("Constructing element (%s,%s) with pyclass(%s), %s" \ %(self.nspname, self.pname, self.pyclass.__name__, str(e))) for key in list(v.keys()): setattr(pyobj, key, v[key]) return pyobj def serialize(self, elt, sw, pyobj, inline=False, name=None, **kw): if inline or self.inline: self.cb(elt, sw, pyobj, name=name, **kw) else: objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) el = elt.createAppendElement(ns, n) el.setAttributeNS(None, 'href', "#%s" %objid) sw.AddCallback(self.cb, elt, sw, pyobj) def cb(self, elt, sw, pyobj, name=None, **kw): debug = self.logger.debugOn() if debug: self.logger.debug("cb: %s" %str(self.ofwhat)) objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) if pyobj is None: if self.nillable is True: elem = elt.createAppendElement(ns, n) self.serialize_as_nil(elem) return raise EvaluateException('element(%s,%s) is not nillable(%s)' %( self.nspname,self.pname,self.nillable)) if self.mutable is False and sw.Known(pyobj): return if debug: self.logger.debug("element: (%s, %s)", str(ns), n) if n is not None: elem = elt.createAppendElement(ns, n) self.set_attributes(elem, pyobj) if kw.get('typed', self.typed) is True: self.set_attribute_xsi_type(elem) #MIXED For now just stick it in front. if self.mixed is True and self.mixed_aname is not None: if hasattr(pyobj, self.mixed_aname): textContent = getattr(pyobj, self.mixed_aname) if hasattr(textContent, 'typecode'): textContent.typecode.serialize_text_node(elem, sw, textContent) elif type(textContent) in _stringtypes: if debug: self.logger.debug("mixed text content:\n\t%s", textContent) elem.createAppendTextNode(textContent) else: raise EvaluateException('mixed test content in element (%s,%s) must be a string type' %( self.nspname,self.pname), sw.Backtrace(elt)) else: if debug: self.logger.debug("mixed NO text content in %s", self.mixed_aname) else: #For information items w/o tagNames # ie. model groups,SOAP-ENC:Header elem = elt if self.inline: pass elif not self.inline and self.unique: raise EvaluateException('Not inline, but unique makes no sense. No href/id.', sw.Backtrace(elt)) elif n is not None: self.set_attribute_id(elem, objid) if self.pyclass and type(self.pyclass) is type: f = lambda attr: getattr(pyobj, attr, None) elif self.pyclass: d = pyobj.__dict__ f = lambda attr: d.get(attr) else: d = pyobj f = lambda attr: pyobj.get(attr) if TypeCode.typechecks and type(d) != dict: raise TypeError("Classless complexType didn't get dictionary") indx, lenofwhat = 0, len(self.ofwhat) if debug: self.logger.debug('element declaration (%s,%s)', self.nspname, self.pname) if self.type: self.logger.debug('xsi:type definition (%s,%s)', self.type[0], self.type[1]) else: self.logger.warning('NO xsi:type') while indx < lenofwhat: occurs = 0 what = self.ofwhat[indx] # retrieve typecode if hidden if isinstance(what, collections.Callable): what = what() if debug: self.logger.debug('serialize what -- %s', what.__class__.__name__) # No way to order <any> instances, so just grab any unmatched # anames and serialize them. Only support one <any> in all content. # Must be self-describing instances # Regular handling of declared elements aname = what.aname v = f(aname) indx += 1 if what.minOccurs == 0 and v is None: continue # Default to typecode, if self-describing instance, and check # to make sure it is derived from what. whatTC = what if (whatTC.maxOccurs == UNBOUNDED or whatTC.maxOccurs > 1) and v is not None: if type(v) not in _seqtypes: raise EvaluateException('pyobj (%s,%s), aname "%s": maxOccurs %s, expecting a %s' %( self.nspname,self.pname,what.aname,whatTC.maxOccurs,_seqtypes), sw.Backtrace(elt)) for v2 in v: occurs += 1 if whatTC.maxOccurs != UNBOUNDED and occurs > whatTC.maxOccurs: raise EvaluateException('occurances (%d) exceeded maxOccurs(%d) for <%s>' %( occurs, whatTC.maxOccurs, what.pname), sw.Backtrace(elt)) what = _get_type_or_substitute(whatTC, v2, sw, elt) if debug and what is not whatTC: self.logger.debug('substitute derived type: %s' % what.__class__) what.serialize(elem, sw, v2, **kw) # try: # what.serialize(elem, sw, v2, **kw) # except Exception, e: # raise EvaluateException('Serializing %s.%s, %s %s' % # (n, whatTC.aname or '?', e.__class__.__name__, str(e))) if occurs < whatTC.minOccurs: raise EvaluateException(\ 'occurances(%d) less than minOccurs(%d) for <%s>' % (occurs, whatTC.minOccurs, what.pname), sw.Backtrace(elt)) continue if v is not None or what.nillable is True: what = _get_type_or_substitute(whatTC, v, sw, elt) if debug and what is not whatTC: self.logger.debug('substitute derived type: %s' % what.__class__) what.serialize(elem, sw, v, **kw) # try: # what.serialize(elem, sw, v, **kw) # except (ParseException, EvaluateException), e: # raise # except Exception, e: # raise EvaluateException('Serializing %s.%s, %s %s' % # (n, whatTC.aname or '?', e.__class__.__name__, str(e)), # sw.Backtrace(elt)) continue raise EvaluateException('Got None for nillable(%s), minOccurs(%d) element (%s,%s), %s' % (what.nillable, what.minOccurs, what.nspname, what.pname, elem), sw.Backtrace(elt)) def setDerivedTypeContents(self, extensions=None, restrictions=None): """For derived types set appropriate parameter and """ if extensions: ofwhat = list(self.ofwhat) if type(extensions) in _seqtypes: ofwhat += list(extensions) else: ofwhat.append(extensions) elif restrictions: if type(restrictions) in _seqtypes: ofwhat = restrictions else: ofwhat = (restrictions,) else: return self.ofwhat = tuple(ofwhat) self.lenofwhat = len(self.ofwhat)
class Array(TypeCode): '''An array. atype -- arrayType, (namespace,ncname) mutable -- object could change between multiple serializations undeclared -- do not serialize/parse arrayType attribute. ''' logger = _GetLogger('ZSI.TCcompound.Array') def __init__(self, atype, ofwhat, pname=None, dimensions=1, fill=None, sparse=False, mutable=False, size=None, nooffset=0, undeclared=False, childnames=None, **kw): TypeCode.__init__(self, pname, **kw) self.dimensions = dimensions self.atype = atype if undeclared is False and self.atype[1].endswith(']') is False: self.atype = (self.atype[0], '%s[]' %self.atype[1]) # Support multiple dimensions if self.dimensions != 1: raise TypeError("Only single-dimensioned arrays supported") self.fill = fill self.sparse = sparse #if self.sparse: ofwhat.minOccurs = 0 self.mutable = mutable self.size = size self.nooffset = nooffset self.undeclared = undeclared self.childnames = childnames if self.size: t = type(self.size) if t in _inttypes: self.size = (self.size,) elif t in _seqtypes: self.size = tuple(self.size) elif TypeCode.typechecks: raise TypeError('Size must be integer or list, not ' + str(t)) # by default use Any ofwhat = ofwhat or Any() if TypeCode.typechecks: if self.undeclared is False and type(atype) not in _seqtypes and len(atype) == 2: raise TypeError("Array type must be a sequence of len 2.") t = type(ofwhat) if not isinstance(ofwhat, TypeCode): raise TypeError( 'Array ofwhat outside the TypeCode hierarchy, ' + str(ofwhat.__class__)) if self.size: if len(self.size) != self.dimensions: raise TypeError('Array dimension/size mismatch') for s in self.size: if type(s) not in _inttypes: raise TypeError('Array size "' + str(s) + '" is not an integer.') self.ofwhat = ofwhat def parse_offset(self, elt, ps): o = _find_arrayoffset(elt) if not o: return 0 if not _offset_pat.match(o): raise EvaluateException('Bad offset "' + o + '"', ps.Backtrace(elt)) return int(o[1:-1]) def parse_position(self, elt, ps): o = _find_arrayposition(elt) if not o: return None if o.find(',') > -1: raise EvaluateException('Sorry, no multi-dimensional arrays', ps.Backtrace(elt)) if not _position_pat.match(o): raise EvaluateException('Bad array position "' + o + '"', ps.Backtrace(elt)) return int(o[1:-1]) def parse(self, elt, ps): href = _find_href(elt) if href: if _children(elt): raise EvaluateException('Array has content and HREF', ps.Backtrace(elt)) elt = ps.FindLocalHREF(href, elt) if self.nilled(elt, ps): return Nilled if not _find_arraytype(elt) and self.undeclared is False: raise EvaluateException('Array expected', ps.Backtrace(elt)) t = _find_type(elt) if t: pass # XXX should check the type, but parsing that is hairy. offset = self.parse_offset(elt, ps) v, vlen = [], 0 if offset and not self.sparse: while vlen < offset: vlen += 1 v.append(self.fill) for c in _child_elements(elt): item = self.ofwhat.parse(c, ps) position = self.parse_position(c, ps) or offset if self.sparse: v.append((position, item)) else: while offset < position: offset += 1 v.append(self.fill) v.append(item) offset += 1 return v def serialize(self, elt, sw, pyobj, name=None, childnames=None, **kw): debug = self.logger.debugOn() if debug: self.logger.debug("serialize: %r" %pyobj) if self.mutable is False and sw.Known(pyobj): return objid = _get_idstr(pyobj) ns,n = self.get_name(name, objid) el = elt.createAppendElement(ns, n) # nillable if self.nillable is True and pyobj is None: self.serialize_as_nil(el) return None # other attributes self.set_attributes(el, pyobj) # soap href attribute unique = self.unique or kw.get('unique', False) if unique is False and sw.Known(pyobj): self.set_attribute_href(el, objid) return None # xsi:type attribute if kw.get('typed', self.typed) is True: self.set_attribute_xsi_type(el, **kw) # soap id attribute if self.unique is False: self.set_attribute_id(el, objid) offset = 0 if self.sparse is False and self.nooffset is False: offset, end = 0, len(pyobj) while offset < end and pyobj[offset] == self.fill: offset += 1 if offset: el.setAttributeNS(SOAP.ENC, 'offset', '[%d]' %offset) if self.undeclared is False: el.setAttributeNS(SOAP.ENC, 'arrayType', '%s:%s' %(el.getPrefix(self.atype[0]), self.atype[1]) ) if debug: self.logger.debug("ofwhat: %r" %self.ofwhat) d = {} kn = childnames or self.childnames if kn: d['name'] = kn elif not self.ofwhat.aname: d['name'] = 'element' if self.sparse is False: for e in pyobj[offset:]: self.ofwhat.serialize(el, sw, e, **d) else: position = 0 for pos, v in pyobj: if pos != position: el.setAttributeNS(SOAP.ENC, 'position', '[%d]' %pos) position = pos self.ofwhat.serialize(el, sw, v, **d) position += 1
class WriteServiceModule: """top level driver class invoked by wsd2py class variables: client_module_suffix -- suffix of client module. types_module_suffix -- suffix of types module. """ client_module_suffix = '_client' messages_module_suffix = '_messages' types_module_suffix = '_types' logger = _GetLogger("WriteServiceModule") def __init__(self, wsdl, addressing=False, notification=False, do_extended=False, extPyClasses=None, configParser=None): self._wsdl = wsdl self._addressing = addressing self._notification = notification self._configParser = configParser self.usedNamespaces = None self.services = [] self.client_module_path = None self.types_module_name = None self.types_module_path = None self.messages_module_path = None # used in extended generation self.do_extended = do_extended self.extPyClasses = extPyClasses def getClientModuleName(self): """client module name. """ name = GetModuleBaseNameFromWSDL(self._wsdl) if not name: raise WsdlGeneratorError('could not determine a service name') if self.client_module_suffix is None: return name return '%s%s' % (name, self.client_module_suffix) # def getMessagesModuleName(self): # name = GetModuleBaseNameFromWSDL(self._wsdl) # if not name: # raise WsdlGeneratorError, 'could not determine a service name' # # if self.messages_module_suffix is None: # return name # # if len(self.messages_module_suffix) == 0: # return self.getClientModuleName() # # return '%s%s' %(name, self.messages_module_suffix) def setTypesModuleName(self, name): self.types_module_name = name def getTypesModuleName(self): """types module name. """ if self.types_module_name is not None: return self.types_module_name name = GetModuleBaseNameFromWSDL(self._wsdl) if not name: raise WsdlGeneratorError('could not determine a service name') if self.types_module_suffix is None: return name return '%s%s' % (name, self.types_module_suffix) def setClientModulePath(self, path): """setup module path to where client module before calling fromWsdl. module path to types module eg. MyApp.client """ self.client_module_path = path def getTypesModulePath(self): """module path to types module eg. MyApp.types """ return self.types_module_path # def getMessagesModulePath(self): # '''module path to messages module # same as types path # ''' # return self.messages_module_path def setTypesModulePath(self, path): """setup module path to where service module before calling fromWsdl. module path to types module eg. MyApp.types """ self.types_module_path = path # def setMessagesModulePath(self, path): # """setup module path to where message module before calling fromWsdl. # module path to types module eg. MyApp.types # """ # self.messages_module_path = path def gatherNamespaces(self): '''This method must execute once.. Grab all schemas representing each targetNamespace. ''' if self.usedNamespaces is not None: return self.logger.debug('gatherNamespaces') self.usedNamespaces = {} # Add all schemas defined in wsdl # to used namespace and to the Alias dict for schema in list(self._wsdl.types.values()): tns = schema.getTargetNamespace() self.logger.debug('Register schema(%s) -- TNS(%s)'\ %(_get_idstr(schema), tns),) if (tns in self.usedNamespaces) is False: self.usedNamespaces[tns] = [] self.usedNamespaces[tns].append(schema) NAD.add(tns) # Add all xsd:import schema instances # to used namespace and to the Alias dict for k, v in list(SchemaReader.namespaceToSchema.items()): self.logger.debug('Register schema(%s) -- TNS(%s)'\ %(_get_idstr(v), k),) if (k in self.usedNamespaces) is False: self.usedNamespaces[k] = [] self.usedNamespaces[k].append(v) NAD.add(k) def writeClient(self, fd, sdClass=None, **kw): """write out client module to file descriptor. Parameters and Keywords arguments: fd -- file descriptor sdClass -- service description class name imports -- list of imports readerclass -- class name of ParsedSoap reader writerclass -- class name of SoapWriter writer """ sdClass = sdClass or ServiceDescription assert issubclass(sdClass, ServiceDescription), \ 'parameter sdClass must subclass ServiceDescription' # header = '%s \n# %s.py \n# generated by %s\n%s\n'\ # %('#'*50, self.getClientModuleName(), self.__module__, '#'*50) print('#' * 50, file=fd) print('# file: %s.py' % self.getClientModuleName(), file=fd) print('# ', file=fd) print('# client stubs generated by "%s"' % self.__class__, file=fd) print('# %s' % ' '.join(sys.argv), file=fd) print('# ', file=fd) print('#' * 50, file=fd) self.services = [] for service in self._wsdl.services.values(): sd = sdClass(self._addressing, do_extended=self.do_extended, wsdl=self._wsdl) if len(self._wsdl.types) > 0: sd.setTypesModuleName(self.getTypesModuleName(), self.getTypesModulePath()) # sd.setMessagesModuleName(self.getMessagesModuleName(), # self.getMessagesModulePath()) self.gatherNamespaces() sd.fromWsdl(service, **kw) sd.write(fd) self.services.append(sd) def writeTypes(self, fd): """write out types module to file descriptor. """ print('#' * 50, file=fd) print('# file: %s.py' % self.getTypesModuleName(), file=fd) print('#', file=fd) print('# schema types generated by "%s"' % self.__class__, file=fd) print('# %s' % ' '.join(sys.argv), file=fd) print('#', file=fd) print('#' * 50, file=fd) print(TypesHeaderContainer(), file=fd) self.gatherNamespaces() for l in list(self.usedNamespaces.values()): sd = SchemaDescription(do_extended=self.do_extended, extPyClasses=self.extPyClasses) for schema in l: sd.fromSchema(schema) sd.write(fd)
class ServiceDescription: """client interface - locator, port, etc classes""" separate_messages = False logger = _GetLogger("ServiceDescription") def __init__(self, addressing=False, do_extended=False, wsdl=None): self.typesModuleName = None self.messagesModuleName = None self.wsAddressing = addressing self.imports = ServiceHeaderContainer() self.messagesImports = ServiceHeaderContainer() self.locator = ServiceLocatorContainer() self.bindings = [] self.messages = [] self.do_extended = do_extended self._wsdl = wsdl # None unless do_extended == True def setTypesModuleName(self, name, modulePath=None): """The types module to be imported. Parameters name -- name of types module modulePath -- optional path where module is located. """ self.typesModuleName = '%s' % name if modulePath is not None: self.typesModuleName = '%s.%s' % (modulePath, name) # def setMessagesModuleName(self, name, modulePath=None): # '''The types module to be imported. # Parameters # name -- name of types module # modulePath -- optional path where module is located. # ''' # self.messagesModuleName = '%s' %name # if modulePath is not None: # self.messagesModuleName = '%s.%s' %(modulePath,name) def fromWsdl(self, service, **kw): self.imports.setTypesModuleName(self.typesModuleName) # if self.separate_messages: # self.messagesImports.setMessagesModuleName(self.messagesModuleName) self.imports.appendImport(kw.get('imports', [])) self.locator.setUp(service) try: bindings = [p.binding for p in service.ports.values()] except: warnings.warn('not all ports have binding declared,') bindings = () for port in service.ports.values(): if port.binding not in bindings: continue while port.binding in bindings: bindings.remove(port.binding) desc = BindingDescription(useWSA=self.wsAddressing, do_extended=self.do_extended, wsdl=self._wsdl) try: desc.setUp(port.getBinding()) except Wsdl2PythonError as ex: self.logger.warning('Skipping port(%s)' % port.name) if len(ex.args): self.logger.warning(ex.args[0]) continue desc.setReaderClass(kw.get('readerclass')) desc.setWriterClass(kw.get('writerclass')) for soc in desc.operations: if soc.hasInput() is True: mw = MessageWriter(do_extended=self.do_extended) mw.setUp(soc, port, input=True) self.messages.append(mw) if soc.hasOutput() is True: mw = MessageWriter(do_extended=self.do_extended) mw.setUp(soc, port, input=False) self.messages.append(mw) self.bindings.append(desc) def write(self, fd, msg_fd=None): """write out module to file descriptor. fd -- file descriptor to write out service description. msg_fd -- optional file descriptor for messages module. """ # if msg_fd != None: # print >>fd, self.messagesImports # print >>msg_fd, self.imports # else: print(self.imports, file=fd) print(self.locator, file=fd) for m in self.bindings: print(m, file=fd) # if msg_fd != None: # for m in self.messages: # print >>msg_fd, m # else: for m in self.messages: print(m, file=fd)
class ComplexType(TypeCode): '''Represents an element of complexType, potentially containing other elements. ''' logger = _GetLogger('ZSI.TCcompound.ComplexType') class _DictHolder: pass def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, mutable=True, mixed=False, mixed_aname='_text', **kw): """pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the complexType inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations type -- the (URI,localname) of the datatype mixed -- mixed content model? True/False mixed_aname -- if mixed is True, specify text content here. Default _text """ TypeCode.__init__(self, pname, pyclass=pyclass, **kw) self.inorder = inorder self.inline = inline self.mutable = mutable self.mixed = mixed self.mixed_aname = None if mixed is True: self.mixed_aname = mixed_aname if self.mutable is True: self.inline = True self.type = kw.get('type') or _get_xsitype(self) t = type(ofwhat) if not isinstance(ofwhat, _seqtypes): raise TypeError('Struct ofwhat must be list or sequence, not ' + str(t)) self.ofwhat = tuple(ofwhat) if TypeCode.typechecks: # XXX Not sure how to determine if new-style class.. if self.pyclass is not None and \ not isinstance(self.pyclass, type) and not isinstance(self.pyclass, object): raise TypeError( 'pyclass must be None or an old-style/new-style class, not ' + str(type(self.pyclass))) _check_typecode_list(self.ofwhat, 'ComplexType') def parse(self, elt, ps): debug = self.logger.debugOn() debug and self.logger.debug('parse') xtype = self.checkname(elt, ps) if self.type and xtype not in [self.type, (None, None)]: if not isinstance(self, TypeDefinition): raise EvaluateException(\ 'ComplexType for %s has wrong type(%s), looking for %s' % (self.pname, self.checktype(elt,ps), self.type), ps.Backtrace(elt)) else: #TODO: mabye change MRO to handle this debug and self.logger.debug('delegate to substitute type') what = TypeDefinition.getSubstituteType(self, elt, ps) return what.parse(elt, ps) href = _find_href(elt) if href: if _children(elt): raise EvaluateException('Struct has content and HREF', ps.Backtrace(elt)) elt = ps.FindLocalHREF(href, elt) c = _child_elements(elt) if self.nilled(elt, ps): return Nilled # Create the object. if self.pyclass: # type definition must be informed of element tag (nspname,pname), # element declaration is initialized with a tag. try: pyobj = self.pyclass() except Exception, e: raise TypeError("Constructing element (%s,%s) with pyclass(%s), %s" \ %(self.nspname, self.pname, self.pyclass.__name__, str(e))) else: