Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Okay, I had a go at hacking my wsdl2interface (<a href="http://pypi.python.org/pypi/wsdl2interface" rel="nofollow noreferrer">http://pypi.python.org/pypi/wsdl2interface</a>) script to output soaplib code. I think I have something that works, though it's not pretty or especially well tested.</p> <p>I'll paste it here for the record. I could be persuaded to release it if someone needs it, though it's not exactly my best code. Note that it uses Suds' WSDL parser to generate soaplib code, which is a bit strange in itself.</p> <p>Run like this:</p> <pre><code>$ wsdl2soaplib &lt;url or filename of WSDL&gt; &gt; wsdl.py </code></pre> <p>The code (you'll need suds in your path, ideally in a virtualenv):</p> <pre><code>from StringIO import StringIO import os.path import sys import textwrap import keyword import re import suds.client VALID_IDENTIFIER_RE = re.compile(r"[_A-Za-z][_A-Za-z1-9]*") VALID_IDENTIFIER_FIRST_LETTER_RE = re.compile(r"[_A-Za-z]") VALID_IDENTIFIER_SUBSEQUENT_LETTER_RE = re.compile(r"[_A-Za-z1-9]") HEADER = '''\ """SOAP web services generated from: %(wsdl)s. """ from soaplib.serializers.primitive import ( String, Integer, Float, Double, DateTime, Bolean, Null, Array, Map, Any ) from soaplib.serializers.clazz import ClassSerializer from soaplib.service import SoapServiceBase from soaplib.service import soapmethod ''' INTERFACE = '''\ class %(name)s(%(bases)s): """%(docstring)s""" ''' SERVICE_INTERFACE_DOCSTRING = '''\ SOAP service ``%(serviceName)s`` with target namespace %(tns)s. ''' TYPE_INTERFACE_DOCSTRING = '''\ SOAP %(type)s ``{%(namespace)s}%(name)s`` ''' TYPE_MAP = '''\ WSDL_TYPES = { %(items)s } ''' SOAPMETHOD = ''' @soapmethod(%(args)s, _returns=%(response)s)''' METHOD = ''' def %(name)s(self, %(args)s):''' METHOD_DOCSTRING = '''\ """Parameters: %(args)s Returns: %(response)s """ ''' STANDARD_TYPE_NAMESPACES = [ 'http://schemas.xmlsoap.org/soap/encoding/', 'http://schemas.xmlsoap.org/wsdl/', 'http://www.w3.org/2001/XMLSchema' ] SCHEMA_TYPE_MAPPING = { None: '%(typeName)s', 'None': 'None', 'boolean': 'Boolean', 'string': 'String', 'long': 'Integer', 'int': 'Integer', 'short': 'Integer', 'byte': 'Integer', 'unsignedLong': 'Integer', 'unsignedInt': 'Integer', 'unsignedShort': 'Integer', 'unsignedByte': 'Integer', 'positiveInteger': 'Integer', 'nonPositiveInteger': 'Integer', 'negativeInteger': 'Integer', 'nonNegativeInteger': 'Integer', 'float': 'Float', 'double': 'Float', 'decimal': 'Decimal', 'dateTime': 'DateTime', 'date': 'DateTime', 'anyURI': 'String', 'token': 'String', 'normalizedString': 'String', 'base64Binary': 'String', 'hexBinary': 'String', } def formatDocstring(text, indent=4, colwidth=78): width = colwidth - indent joiner = '\n' + ' ' * indent return joiner.join(textwrap.wrap(text, width) + ['']) def typeName(type, sd): resolved = type.resolve() return resolved.name or '' def schemaTypeName(type, sd, deps=None): resolved = type.resolve() name = resolved.name or '' schemaType = SCHEMA_TYPE_MAPPING.get(name) if schemaType is None: # not a standard type # user default schemaType = SCHEMA_TYPE_MAPPING[None] # possibly save dependency link if deps is not None: deps.append(unicode(name)) required = type.required() schemaType = schemaType % dict(typeName=name, required=required) if type.unbounded(): schemaType = "Array(%s)" % schemaType return schemaType def normalizeIdentifier(identifier): if not VALID_IDENTIFIER_RE.match(identifier): newIdentifierLetters = [] firstLetter = True for letter in identifier: if firstLetter: if VALID_IDENTIFIER_FIRST_LETTER_RE.match(letter): newIdentifierLetters.append(letter) else: newIdentifierLetters.append('_') firstLetter = False else: if VALID_IDENTIFIER_SUBSEQUENT_LETTER_RE.match(letter): newIdentifierLetters.append(letter) else: newIdentifierLetters.append('_') identifier = ''.join(newIdentifierLetters) if keyword.iskeyword(identifier): identifier = identifier + '_' return identifier def generate(client, url=None, standardTypeNamespaces=STANDARD_TYPE_NAMESPACES, removeInputOutputMesssages=True): """Given a WSDL URL, return a file that could become your interfaces.py """ printed = [] # sequence of type name -&gt; string for sd in client.sd: serviceOut = StringIO() print &gt;&gt;serviceOut, HEADER % dict( wsdl=url, ) printed.append(('', serviceOut.getvalue(),)) # Types typeMap = {} typeSeq = [] typeDeps = {} typeAttributes = {} typesPrinted = [] for type_ in sd.types: typeOut = StringIO() resolved = type_[0].resolve() namespaceURL = resolved.namespace()[1] if namespaceURL not in standardTypeNamespaces: if resolved.enum(): typeDescription = "enumeration" else: typeDescription = "complex type" # Look for basess interfaceBases = [] if resolved.extension(): def find(t): for c in t.rawchildren: if c.extension(): find(c) if c.ref is not None: interfaceBases.append(c.ref[0]) find(resolved) if not interfaceBases: interfaceBases = ['ClassSerializer'] rawTypeName = typeName(type_[0], sd) typeInterfaceName = normalizeIdentifier(rawTypeName) typeMap[rawTypeName] = typeInterfaceName typeSeq.append((rawTypeName, typeInterfaceName,)) typeAttributes[rawTypeName] = {} print &gt;&gt;typeOut, INTERFACE % dict( name=normalizeIdentifier(typeInterfaceName), bases=', '.join(interfaceBases), docstring=formatDocstring(TYPE_INTERFACE_DOCSTRING % dict( type=typeDescription, name=rawTypeName, namespace=namespaceURL, ) ) ) print &gt;&gt;typeOut, " class types:" if resolved.enum(): for attr in type_[0].children(): name = attr[0].name.replace(' ', '_') print &gt;&gt;typeOut, " %s = String # XXX: Enumeration value" % name else: for attr in type_[0].children(): name = attr[0].name.replace(' ', '_') attrTypeName = typeName(attr[0], sd) typeAttributes[rawTypeName][name] = attrTypeName schemaType = schemaTypeName(attr[0], sd, deps=typeDeps.setdefault(unicode(rawTypeName), [])) print &gt;&gt;typeOut, " %s = %s" % (normalizeIdentifier(name), schemaType,) print &gt;&gt;typeOut typesPrinted.append((rawTypeName, typeOut.getvalue(),)) serviceInterfaceOut = StringIO() # Main service interface print &gt;&gt;serviceInterfaceOut, INTERFACE % dict( name=normalizeIdentifier(sd.service.name), bases=u"SoapServiceBase", docstring=formatDocstring(SERVICE_INTERFACE_DOCSTRING % dict( serviceName=sd.service.name, tns=sd.wsdl.tns[1], ) ) ) methods = {} # name -&gt; (response type, list of parameters,) for p in sd.ports: for m in p[1]: methodName = m[0] methodArgs = m[1] if methodName not in methods: methodDef = p[0].method(methodName) # XXX: This is discards the namespace part if methodDef.soap.output.body.wrapped: inputMessage = methodDef.soap.input.body.parts[0].element[0] outputMessage = methodDef.soap.output.body.parts[0].element[0] if outputMessage in typeAttributes: if len(typeAttributes[outputMessage]) &gt; 0: response = typeAttributes[outputMessage].values()[0] else: response = "None" else: response = outputMessage # Remove types used as input/output messages if removeInputOutputMesssages: remove = False for idx, (t, x) in enumerate(typesPrinted): if t == inputMessage: remove = True break if remove: del typesPrinted[idx] if inputMessage in typeMap: del typeMap[inputMessage] remove = False for idx, (t, x) in enumerate(typesPrinted): if t == outputMessage: remove = True break if remove: del typesPrinted[idx] if outputMessage in typeMap: del typeMap[outputMessage] else: response = methodDef.soap.output.body.parts[0].element[0] methods[methodName] = (response, methodArgs,) for methodName in sorted(methods): methodArgNames = [m[0] for m in methods[methodName][1]] methodReturnType = methods[methodName][0] methodArgDetails = [] methodArgSpecs = [] for m in methods[methodName][1]: argDetail = m[1] # for docstring methodModifierParts = [] if not argDetail.required(): methodModifierParts.append('optional') if argDetail.nillable: methodModifierParts.append('may be None') methodModifiers = "" if methodModifierParts: methodModifiers = ' (%s)' % ', '.join(methodModifierParts) argTypeName = typeName(argDetail, sd) methodSpec = "``%s`` -- %s%s" % ( argDetail.name, argTypeName, methodModifiers ) methodArgDetails.append(methodSpec) # for @soapmethod decorator schemaType = schemaTypeName(argDetail, sd) methodArgSpecs.append(schemaType) # TODO: Probably not aware of array return types if methodReturnType not in typeMap and methodReturnType in SCHEMA_TYPE_MAPPING: methodReturnType = SCHEMA_TYPE_MAPPING[methodReturnType] print &gt;&gt;serviceInterfaceOut, SOAPMETHOD % dict( args=', '.join(methodArgSpecs), response=methodReturnType, ) print &gt;&gt;serviceInterfaceOut, METHOD % dict( name=normalizeIdentifier(methodName), args=', '.join(methodArgNames), ) print &gt;&gt;serviceInterfaceOut, METHOD_DOCSTRING % dict( args='\n '.join(methodArgDetails), response=methodReturnType, ) print &gt;&gt;serviceInterfaceOut # Sort list of complex types based on internal dependencies def sortDeps(printed): printed = list(reversed(printed)) queue = [item for item in printed if len(typeDeps.get(unicode(item[0]), [])) == 0] satisfied = set(queue) remaining = [item for item in printed if item not in queue] sortedPrinted = [] while queue: item = queue.pop() itemTypeName = unicode(item[0]) sortedPrinted.append(item) satisfied.add(itemTypeName) for item in remaining: remainingItemTypeName = unicode(item[0]) depsList = typeDeps.get(remainingItemTypeName, []) remainingDeps = [] for dep in depsList: if dep not in satisfied: remainingDeps.append(dep) typeDeps[remainingItemTypeName] = remainingDeps if len(remainingDeps) == 0: queue.append(item) remaining.remove(item) return sortedPrinted typesPrinted = sortDeps(typesPrinted) # Print everything printed.extend(typesPrinted) printed.append((sd.service.name, serviceInterfaceOut.getvalue(),)) typeMapOut = StringIO() print &gt;&gt;typeMapOut, TYPE_MAP % dict( items=',\n'.join([" '%s': %s" % k for k in typeSeq if k[0] in typeMap]) ) print &gt;&gt;typeMapOut printed.append(('', typeMapOut.getvalue(),)) return '\n'.join([v[1] for v in printed]) def main(): if len(sys.argv) &lt; 2: print "Usage: %s &lt;url&gt;" % sys.argv[0] print "The output will be printed to the console" return if not '://' in sys.argv[1]: sys.argv[1] = 'file://' + os.path.abspath(sys.argv[1]) client = suds.client.Client(sys.argv[1]) print generate(client, sys.argv[1]) if __name__ == '__main__': main() </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload