2008-10-28 39 views
19

Estoy investigando SUDS como un cliente SOAP para python. Quiero inspeccionar los métodos disponibles de un servicio específico y los tipos requeridos por un método específico.SUDS - acceso programático a métodos y tipos

El objetivo es generar una interfaz de usuario, que permita a los usuarios seleccionar un método, y luego completar los valores en una forma generada dinámicamente.

puedo conseguir alguna información sobre un método particular, pero estoy seguro de cómo analizarlo:

client = Client(url) 
method = client.sd.service.methods['MyMethod'] 

Soy incapaz de programmaticaly averiguar qué tipo de objeto que necesito para crear al ser capaz de llamar el servicio

obj = client.factory.create('?') 

res = client.service.MyMethod(obj, soapheaders=authen) 

¿Alguien tiene algún código de muestra?

Respuesta

18

Según sudsdocumentation, puede inspeccionar el objeto service con __str()__. Así que la siguiente obtiene una lista de métodos y tipos complejos:

from suds.client import Client; 

url = 'http://www.webservicex.net/WeatherForecast.asmx?WSDL' 
client = Client(url) 

temp = str(client); 

El código anterior produce siguiente resultado (contenido de temp):

Suds (https://fedorahosted.org/suds/) version: 0.3.4 (beta) build: R418-20081208 

Service (WeatherForecast) tns="http://www.webservicex.net" 
    Prefixes (1) 
     ns0 = "http://www.webservicex.net" 
    Ports (2): 
     (WeatherForecastSoap) 
     Methods (2): 
      GetWeatherByPlaceName(xs:string PlaceName,) 
      GetWeatherByZipCode(xs:string ZipCode,) 
     Types (3): 
      ArrayOfWeatherData 
      WeatherData 
      WeatherForecasts 
     (WeatherForecastSoap12) 
     Methods (2): 
      GetWeatherByPlaceName(xs:string PlaceName,) 
      GetWeatherByZipCode(xs:string ZipCode,) 
     Types (3): 
      ArrayOfWeatherData 
      WeatherData 
      WeatherForecasts 

Esto sería mucho más fácil de analizar. Además, cada método se enumera con sus parámetros junto con sus tipos. Probablemente, incluso podría usar expresiones regulares para extraer la información que necesita.

24

De acuerdo, SUDS hace un poco de magia.

Un suds.client.Client, se construye a partir de un archivo WSDL:

client = suds.client.Client("http://mssoapinterop.org/asmx/simple.asmx?WSDL") 

que descarga el WSDL y crea una definición en client.wsdl. Cuando llamas a un método usando SUDS a través del client.service.<method>, de hecho está haciendo una gran cantidad de magia de resolución recursiva detrás de la escena contra el WSDL interpretado. Para descubrir los parámetros y tipos de métodos, deberá introspectar este objeto.

Por ejemplo:

for method in client.wsdl.services[0].ports[0].methods.values(): 
    print '%s(%s)' % (method.name, ', '.join('%s: %s' % (part.type, part.name) for part in method.soap.input.body.parts)) 

Esto debería imprimir algo como:

echoInteger((u'int', http://www.w3.org/2001/XMLSchema): inputInteger) 
echoFloatArray((u'ArrayOfFloat', http://soapinterop.org/): inputFloatArray) 
echoVoid() 
echoDecimal((u'decimal', http://www.w3.org/2001/XMLSchema): inputDecimal) 
echoStructArray((u'ArrayOfSOAPStruct', http://soapinterop.org/xsd): inputStructArray) 
echoIntegerArray((u'ArrayOfInt', http://soapinterop.org/): inputIntegerArray) 
echoBase64((u'base64Binary', http://www.w3.org/2001/XMLSchema): inputBase64) 
echoHexBinary((u'hexBinary', http://www.w3.org/2001/XMLSchema): inputHexBinary) 
echoBoolean((u'boolean', http://www.w3.org/2001/XMLSchema): inputBoolean) 
echoStringArray((u'ArrayOfString', http://soapinterop.org/): inputStringArray) 
echoStruct((u'SOAPStruct', http://soapinterop.org/xsd): inputStruct) 
echoDate((u'dateTime', http://www.w3.org/2001/XMLSchema): inputDate) 
echoFloat((u'float', http://www.w3.org/2001/XMLSchema): inputFloat) 
echoString((u'string', http://www.w3.org/2001/XMLSchema): inputString) 

Así que el primer elemento de tipo tupla de la pieza es probablemente lo que está buscando:

>>> client.factory.create(u'ArrayOfInt') 
(ArrayOfInt){ 
    _arrayType = "" 
    _offset = "" 
    _id = "" 
    _href = "" 
    _arrayType = "" 
} 

Actualización:

Para el servicio del tiempo parece que los "parámetros" son una parte con no un element un type:

>>> client = suds.client.Client('http://www.webservicex.net/WeatherForecast.asmx?WSDL') 
>>> client.wsdl.services[0].ports[0].methods.values()[0].soap.input.body.parts[0].element 
(u'GetWeatherByZipCode', http://www.webservicex.net) 
>>> client.factory.create(u'GetWeatherByZipCode') 
(GetWeatherByZipCode){ 
    ZipCode = None 
} 

pero esto es magic'd en los parámetros de la llamada al método (a la client.service.GetWeatherByZipCode("12345"). IIRC este es el estilo de enlace JAP de SOFTWARE? Creo que hay suficiente información aquí para comenzar. Sugerencia: ¡la interfaz de línea de comando de Python es tu amiga!

+1

Por alguna razón, todos estos son "None" con el WSDL que estoy trabajando, así que no obtienen los parámetros o el tipo, sin embargo , se muestran en str (cliente) y tienen el parámetro y el tipo allí. – Wyrmwood

8

Aquí hay una secuencia de comandos rápida que escribí sobre la base de la información anterior para enumerar los informes de los métodos de entrada de espuma disponibles en un WSDL. Pase en la URL WSDL. Funciona para el proyecto en el que estoy actualmente, no puedo garantizarlo para el suyo.

import suds 

def list_all(url): 
    client = suds.client.Client(url) 
    for service in client.wsdl.services: 
     for port in service.ports: 
      methods = port.methods.values() 
      for method in methods: 
       print(method.name) 
       for part in method.soap.input.body.parts: 
        part_type = part.type 
        if(not part_type): 
         part_type = part.element[0] 
        print(' ' + str(part.name) + ': ' + str(part_type)) 
        o = client.factory.create(part_type) 
        print(' ' + str(o)) 
+0

gracias! también funciona para mí :) –

3

Puede acceder al objeto ServiceDefinition de suds. He aquí una muestra rápida:

from suds.client import Client 
c = Client('http://some/wsdl/link') 

types = c.sd[0].types 

Ahora, si usted quiere saber el nombre prefijado de un tipo, también es muy fácil:

c.sd[0].xlate(c.sd[0].types[0][0]) 

Esta notación soporte doble se debe a que los tipos son una lista (de ahí una primera [0]) y luego en cada elemento de esta lista puede haber dos elementos. Sin embargo, la implementación interna de __unicode__ de espuma hace exactamente eso (es decir, toma sólo el primer elemento de la lista):

s.append('Types (%d):' % len(self.types)) 
    for t in self.types: 
     s.append(indent(4)) 
     s.append(self.xlate(t[0])) 

feliz de codificación;)

0

Una vez que ha creado el método WSDL objeto se puede obtener información sobre el tema de es __metadata__, incluida la lista de sus nombres de argumentos.

Dado el nombre del argumento, puede acceder a su instancia real en el método creado. Esa instancia también contiene información que es en __metadata__, allí se puede llegar es escribir el nombre

# creating method object 
method = client.factory.create('YourMethod') 
# getting list of arguments' names 
arg_names = method.__metadata__.ordering 
# getting types of those arguments 
types = [method.__getitem__(arg).__metadata__.sxtype.name for arg in arg_names] 

responsabilidad: esto sólo funciona con tipos WSDL complejas. Los tipos simples, como cadenas y números, están predeterminadas en Ninguno

0
from suds.client import Client 
url = 'http://localhost:1234/sami/2009/08/reporting?wsdl' 
client = Client(url) 
functions = [m for m in client.wsdl.services[0].ports[0].methods] 
count = 0 
for function_name in functions: 
    print (function_name) 
    count+=1 
print ("\nNumber of services exposed : " ,count) 
Cuestiones relacionadas