SUDS - программный доступ к методам и типам
Я исследую SUDS как клиент SOAP для python. Я хочу проверить методы, доступные из указанной службы, и типы, требуемые указанным методом.
Цель состоит в том, чтобы создать пользовательский интерфейс, позволяющий пользователям выбирать метод, а затем заполнять значения в динамически генерируемой форме.
Я могу получить некоторую информацию о конкретном методе, но не уверен, как его проанализировать:
client = Client(url)
method = client.sd.service.methods['MyMethod']
Я не могу программно определить, какой тип объекта мне нужно создать, чтобы иметь возможность вызывать службу
obj = client.factory.create('?')
res = client.service.MyMethod(obj, soapheaders=authen)
У кого-нибудь есть пример кода?
6 ответов
Итак, SUDS делает немного магии.
suds.client.Client
, построен из файла WSDL:
client = suds.client.Client("http://mssoapinterop.org/asmx/simple.asmx?WSDL")
Он загружает WSDL и создает определение в client.wsdl
, Когда вы вызываете метод, используя SUDS через client.service.<method>
на самом деле он делает много рекурсивного волшебства разрешения за кулисами против этого интерпретированного WSDL. Чтобы узнать параметры и типы методов, вам необходимо проанализировать этот объект.
Например:
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))
Это должно напечатать что-то вроде:
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)
Итак, первый элемент кортежа типа детали, вероятно, то, что вы ищете:
>>> client.factory.create(u'ArrayOfInt')
(ArrayOfInt){
_arrayType = ""
_offset = ""
_id = ""
_href = ""
_arrayType = ""
}
Обновить:
Для службы погоды выясняется, что "параметры" являются частью element
не 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
}
Но это волшебство в параметры вызова метода (а-ля client.service.GetWeatherByZipCode("12345")
, IIRC это стиль связывания SOAP RPC? Я думаю, что здесь достаточно информации, чтобы вы начали. Подсказка: интерфейс командной строки Python - ваш друг!
В соответствии с suds
документацию, вы можете проверить service
объект с __str()__
, Таким образом, следующее получает список методов и сложных типов:
from suds.client import Client;
url = 'http://www.webservicex.net/WeatherForecast.asmx?WSDL'
client = Client(url)
temp = str(client);
Код выше дает следующий результат (содержимое 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
Это было бы намного проще разобрать. Также каждый метод указан со своими параметрами вместе с их типами. Вы могли бы, вероятно, даже использовать только регулярное выражение для извлечения необходимой информации.
Вот быстрый скрипт, который я написал на основе приведенной выше информации, чтобы перечислить отчеты о методах ввода suds как доступные в WSDL. Передайте в WSDL URL. Работаю над проектом, в котором я сейчас работаю, я не могу гарантировать его за ваш.
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))
Вы можете получить доступ к объекту ServiceDefinition suds. Вот быстрый пример:
from suds.client import Client
c = Client('http://some/wsdl/link')
types = c.sd[0].types
Теперь, если вы хотите узнать префиксное имя типа, это также довольно просто:
c.sd[0].xlate(c.sd[0].types[0][0])
Это двойное обозначение в скобках, потому что типы являются списком (отсюда сначала [0]), а затем в каждом элементе этого списка может быть два элемента. Однако внутренняя реализация suds __unicode__
делает именно это (т.е. принимает только первый элемент в списке):
s.append('Types (%d):' % len(self.types))
for t in self.types:
s.append(indent(4))
s.append(self.xlate(t[0]))
Удачного кодирования;)
После того, как вы создали объект метода WSDL, вы можете получить информацию о нем из __metadata__
в том числе список имен аргументов.
Учитывая имя аргумента, вы можете получить доступ к его фактическому экземпляру в созданном методе. Этот экземпляр также содержит информацию в __metadata__
, там вы можете получить его имя типа
# 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]
Отказ от ответственности: это работает только со сложными типами WSDL. Простые типы, такие как строки и числа, по умолчанию имеют значение None.
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)
Мне нужен был пример использования пены с объектами. Помимо ответов, найденных здесь, я нашел очень хорошую статью, которая еще больше ответила на мой вопрос.
вот краткое изложение:
сначала распечатайте клиент, чтобы увидеть обзор его содержимого.
from suds.client import Client client =
Client("https://wsvc.cdiscount.com/MarketplaceAPIService.svc?wsdl")
print client
во-вторых, создайте экземпляр типа (используя его имя, включая префикс ns*.) и распечатайте его, чтобы увидеть данные его члена.
HeaderMessage = client.factory.create('ns0:HeaderMessage')
print HeaderMessage
чтобы заполнить элементы данных вашего объекта, либо назначьте им скалярное значение для скалярных элементов, либо dict для членов объекта.
HeaderMessage.Context = {
"CatalogID": "XXXXX"
"CustomerID": 'XXXXX'
"SiteID": 123
}
члены, чье имя типа начинается с ArrayOf, ожидают список объектов типа, упомянутого в остальной части имени типа.
ArrayOfDomainRights = client.factory.create('ns0:ArrayOfDomainRights')
ArrayOfDomainRights.DomainRights = [XXXXXXXXXXXXX, XXXXXXXXXXXX]
Мне нужен был пример использования пены с объектами. Помимо ответов, найденных здесь, я нашел очень хорошую статью, которая еще больше ответила на мой вопрос.
вот краткое изложение:
сначала распечатайте клиент, чтобы увидеть обзор его содержимого.
from suds.client import Client client =
Client("https://wsvc.cdiscount.com/MarketplaceAPIService.svc?wsdl")
print client
во-вторых, создайте экземпляр типа (используя его имя, включая префикс ns*.) и распечатайте его, чтобы увидеть данные его члена.
HeaderMessage = client.factory.create('ns0:HeaderMessage')
print HeaderMessage
Чтобы заполнить элементы данных вашего объекта, либо присвойте им скалярное значение для скалярных элементов, либо dict для членов объекта.
HeaderMessage.Context = {
"CatalogID": "XXXXX"
"CustomerID": 'XXXXX'
"SiteID": 123
}
члены, имя типа которых начинается с ArrayOf, ожидают список объектов типа, упомянутого в остальной части имени типа.
ArrayOfDomainRights = client.factory.create('ns0:ArrayOfDomainRights')
ArrayOfDomainRights.DomainRights = [XXXXXXXXXXXXX, XXXXXXXXXXXX]