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>
Другие вопросы по тегам