spyne - использовать параметры по умолчанию в определениях сервисов
Я использую Spyne, и он работает хорошо. Я хотел бы иметь возможность использовать значения по умолчанию для моих дополнительных параметров. Как я понимаю, каждый тип можно использовать по своей обязательной форме или нет: я прав?
Вот мой сервис:
from spyne.model.primitive import Unicode, Boolean
@rpc(Unicode, _returns = Unicode)
def optional_parameter(ctx, input = "default value")
return input
Когда я вызываю его без параметров, он ничего не возвращает, точно так же, как если бы я звонил с помощью '' (пустая строка).
SOAP INPUT (из SoapUI):
<soapenv:Body>
<spy:optional_parameter>
<!--Optional:-->
<spy:input/>
</spy:optional_parameter>
</soapenv:Body>
МЫЛО ВЫХОД:
<senv:Body>
<tns:optional_parameterResponse>
<tns:optional_parameterResult/>
</tns:optional_parameterResponse>
</senv:Body>
С логическим значением это хуже, вот еще один сервис:
@rpc(Boolean, _returns = Boolean)
def optional_parameter_second(ctx, input = False)
return input
Там, когда я вызываю свой сервис с помощью SoapUI, я получаю следующую ошибку:
Запрос ВВОДА:
<soapenv:Body>
<spy:optional_parameter>
<!--Optional:-->
<spy:input/>
</spy:optional_parameter>
</soapenv:Body>
ВЫХОД:
<senv:Fault>
<faultcode>senv:Client.SchemaValidationError</faultcode>
<faultstring>:10:0:ERROR:SCHEMASV:SCHEMAV_CVC_DATATYPE_VALID_1_2_1: Element '{spyne.examples.hello}input': '' is not a valid value of the atomic type 'xs:boolean'.</faultstring>
<faultactor/>
</senv:Fault>
У вас есть идея, чтобы помочь мне?
Я использую Spyne 2.11.0
2 ответа
В spyne все параметры являются необязательными (min_occurs=0
а также nillable=True
) по умолчанию.
Когда аргумент опущен в запросе, Spyne передает его как None
в любом случае, аргументы Python по умолчанию никогда не используются. Вы должны пройти default
kwarg, чтобы печатать вместо маркеров.
Пример:
@rpc(Unicode(default='default value'), _returns=Unicode)
def optional_parameter(ctx, input)
return input
При этом рассмотрим следующую выдержку:
<soapenv:Body>
<spy:optional_parameter>
<spy:input/>
</spy:optional_parameter>
</soapenv:Body>
Вы не передаете пропущенный аргумент здесь, вы передаете пустую строку (""
). Если вы хотите пропустить этот параметр, вы должны пропустить тег. Что значит:
<soapenv:Body>
<spy:optional_parameter/>
</soapenv:Body>
Здесь содержимое тега снова представляет собой пустую строку, но поскольку процессор Soap ищет субэлементы, а не содержимое тега, здесь это не имеет значения.
Если вы хотите передать явное значение null, вот как вы это делаете:
<soapenv:Body>
<spy:optional_parameter>
<spy:input xmlns:xsi="http://w3.org/2001/XMLSchema-instance" xmlns:xsi="" xsi:nil="true"/>
</spy:optional_parameter>
</soapenv:Body>
Обратите внимание, что Spyne 2.11 по-прежнему будет использовать значение по умолчанию, если оно у вас есть, даже если передан явный ноль.
См.: https://github.com/arskom/spyne/blob/79f8120668ec471097f410e63fa48cdf797fae7a/spyne/protocol/xml.py
Я не уверен, что это ошибка или фича:)
Я обнаружил один способ, который кажется чистым:
Реализация сервиса с логическим значением по умолчанию:
def optional_parameter_second(ctx, input):
if input is not None:
return my_method(input)
else:
return my_method()
def my_method(param = True):
return param
И звонок от soapUI не должен содержать тег
<soapenv:Body>
<spy:optional_parameter>
<!--Optional:-->
</spy:optional_parameter>
</soapenv:Body>
Отлично работает
<senv:Body>
<tns:optional_booleanResponse>
<tns:optional_booleanResult>true</tns:optional_booleanResult>
</tns:optional_booleanResponse>
</senv:Body>