Projet

Général

Profil

0001-utils-soap-upgrade-zeep-soap-library-version-35370.patch

Nicolas Roche, 25 octobre 2019 19:09

Télécharger (10,6 ko)

Voir les différences:

Subject: [PATCH] utils/soap: upgrade zeep soap library version (#35370)

 passerelle/contrib/iparapheur/models.py | 18 +++++++++---
 setup.py                                |  2 +-
 tests/data/soap.wsdl                    |  5 ++--
 tests/test_iparapheur.py                | 28 ++++++++++++++----
 tests/test_soap.py                      | 39 +++++++++++++++++++++++++
 tox.ini                                 |  4 ++-
 6 files changed, 82 insertions(+), 14 deletions(-)
passerelle/contrib/iparapheur/models.py
23 23
from django.http import HttpResponse, Http404
24 24

  
25 25
from zeep.exceptions import Fault as WebFault, TransportError, XMLSyntaxError
26
try:
27
    from zeep import Settings
28
    zeep_version = 3
29
except ImportError:
30
    zeep_version = 2
26 31

  
27 32
from passerelle.base.models import BaseResource, HTTPResource
28 33
from passerelle.utils.api import endpoint
......
107 112
    def get_verbose_name(cls):
108 113
        return cls._meta.verbose_name
109 114

  
110
    def get_client(self, strict_mode=True):
115
    def get_client(self, **kwargs):
111 116
        try:
112
            soap_client = self.soap_client(strict=strict_mode)
117
            soap_client = self.soap_client(**kwargs)
113 118

  
114 119
            # overrides the service port address URL defined in the WSDL.
115 120
            if self.wsdl_endpoint_location:
......
125 130

  
126 131
    def call(self, service_name, *args, **kwargs):
127 132
        strict_mode = kwargs.pop('strict_mode', True)
128
        client = self.get_client(strict_mode=strict_mode)
129 133
        try:
130
            result = getattr(client.overridden_service, service_name)(*args, **kwargs)
134
            if zeep_version == 2:
135
                client = self.get_client(strict=strict_mode)
136
                result = getattr(client.overridden_service, service_name)(*args, **kwargs)
137
            else:
138
                client = self.get_client()
139
                with client.settings(strict=strict_mode):
140
                    result = getattr(client.overridden_service, service_name)(*args, **kwargs)
131 141
        except WebFault as exc:
132 142
            # Remote Service Error: <SOAP-ENV:Fault> in response
133 143
            raise APIError('ServiceError: %s' % exc)
setup.py
104 104
            'python-dateutil',
105 105
            'Pillow',
106 106
            'jsonschema < 3.1',
107
            'zeep < 3.0',
107
            'zeep',
108 108
            'pycrypto',
109 109
            'unidecode',
110 110
            'paramiko',
tests/data/soap.wsdl
48 48
      </element>
49 49
      <element name="TradePrice">
50 50
        <complexType>
51
          <all>
51
          <sequence>
52
            <element name="skipMe" type="float"/>
52 53
            <element name="price" type="float"/>
53
          </all>
54
          </sequence>
54 55
        </complexType>
55 56
      </element>
56 57
      <complexType name="account">
tests/test_iparapheur.py
8 8
import xml.etree.ElementTree as ET
9 9
from dateutil import parser
10 10
from requests import Response
11
from zeep import __version__ as zeep_version
11 12

  
12 13
from requests.exceptions import ConnectionError
13 14
from django.core.urlresolvers import reverse
......
41 42
                    resource_pk=conn.pk)
42 43
    return conn
43 44

  
45
def assert_invalid_xml(err_desc):
46
    if zeep_version < '3':
47
        assert "Server returned HTTP status 200 (<nada>)" in err_desc
48
    else:
49
        assert "Server returned response (200) with invalid XML" in err_desc
50

  
44 51
def xmlmime():
45 52
    return os.path.join(os.path.dirname(__file__), 'data','xmlmime.xml')
46 53

  
......
70 77
def test_call_ping(soap_client, app, conn):
71 78
    service = mock.Mock()
72 79
    service.echo.return_value = 'pong'
73
    mocked_client = mock.Mock(overridden_service=service)
80

  
81
    class MockedSettings(object):
82
        def __init__(self, **kwargs):
83
            pass
84
        def __enter__(self):
85
            pass
86
        def __exit__(self, exc_type, exc_value, traceback):
87
            pass
88

  
89
    mocked_client = mock.Mock(overridden_service=service, settings=MockedSettings)
74 90
    soap_client.return_value = mocked_client
75 91
    url = reverse('generic-endpoint', kwargs={'connector': 'iparapheur',
76 92
                    'endpoint': 'ping', 'slug': conn.slug})
......
187 203
    assert (BASE_URL,) == mocked_post.call_args[0]
188 204
    assert resp.json['err'] == 1
189 205
    assert 'zeep.exceptions.TransportError' in resp.json['err_class']
190
    assert 'Server returned HTTP status 200 (<nada>)' in resp.json['err_desc']
206
    assert_invalid_xml(resp.json['err_desc'])
191 207

  
192 208
    # Unknown value for "visibility"
193 209
    err_data = data.copy()
......
211 227
    assert (BASE_URL,) == mocked_post.call_args[0]
212 228
    assert resp.json['err'] == 1
213 229
    assert 'zeep.exceptions.TransportError' in resp.json['err_class']
214
    assert 'Server returned HTTP status 200 (<nada>)' in resp.json['err_desc']
230
    assert_invalid_xml(resp.json['err_desc'])
215 231

  
216 232
@mock.patch('passerelle.utils.Request.get', side_effect=iph_mocked_get)
217 233
@mock.patch('passerelle.utils.Request.post')
......
300 316
    assert resp.json['err'] == 1
301 317
    #assert 'zeep.exceptions.TransportError' in resp.json['err_class']
302 318
    assert 'passerelle.utils.jsonresponse.APIError' in resp.json['err_class']
303
    assert 'Server returned HTTP status 200 (<nada>)' in resp.json['err_desc']
319
    assert_invalid_xml(resp.json['err_desc'])
304 320

  
305 321
@mock.patch('passerelle.utils.Request.get', side_effect=iph_mocked_get)
306 322
@mock.patch('passerelle.utils.Request.post')
......
325 341
    assert resp.body == 'Test Document'
326 342

  
327 343
    # KO
328
    soap_response = """<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><CreerDossierResponse xmlns="http://www.adullact.org/spring-ws/iparapheur/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"><MessageRetour><codeRetour>KO</codeRetour><message>KOmessage</message><severite>INFO</severite></MessageRetour></CreerDossierResponse></S:Body></S:Envelope>"""
344
    soap_response = """<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><GetDossierResponse xmlns="http://www.adullact.org/spring-ws/iparapheur/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"><MessageRetour><codeRetour>KO</codeRetour><message>KOmessage</message><severite>INFO</severite></MessageRetour></GetDossierResponse></S:Body></S:Envelope>"""
329 345
    response._content = soap_response
330 346
    mocked_post.return_value = response
331 347
    resp = app.get(url, status=500)
......
334 350
    assert resp.json['err_desc'] == 'KOmessage'
335 351

  
336 352
    # unknown response
337
    soap_response = """<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><CreerDossierResponse xmlns="http://www.adullact.org/spring-ws/iparapheur/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"></CreerDossierResponse></S:Body></S:Envelope>"""
353
    soap_response = """<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><GetDossierResponse xmlns="http://www.adullact.org/spring-ws/iparapheur/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime"></GetDossierResponse></S:Body></S:Envelope>"""
338 354
    response._content = soap_response
339 355
    mocked_post.return_value = response
340 356
    resp = app.get(url, status=500)
tests/test_soap.py
1
import pytest
2
import mock
1 3
import requests
2 4
from zeep.plugins import Plugin
5
from zeep.exceptions import XMLParseError
6
try:
7
    from zeep import Settings
8
    zeep_version = 3
9
except ImportError:
10
    zeep_version = 2
3 11

  
4 12
from passerelle.utils.soap import SOAPClient
5 13

  
......
30 38
    assert client.transport.session == soap_resource.requests
31 39
    assert client.transport.cache
32 40
    assert client.plugins == plugins
41

  
42
@mock.patch('requests.sessions.Session.post')
43
def test_disable_strict_mode(mocked_post):
44
    response = requests.Response()
45
    response.status_code = 200
46
    response._content = '''<?xml version='1.0' encoding='utf-8'?>
47
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
48
  <soap-env:Body>
49
    <ns0:TradePrice xmlns:ns0="http://example.com/stockquote.xsd">
50
      <price>4.20</price>
51
    </ns0:TradePrice>
52
  </soap-env:Body>
53
</soap-env:Envelope>'''
54
    mocked_post.return_value = response
55

  
56
    soap_resource = SOAPResource()
57
    client = SOAPClient(soap_resource)
58
    with pytest.raises(
59
            XMLParseError, match="Unexpected element u'price', expected u'skipMe'"):
60
        client.service.GetLastTradePrice(tickerSymbol='banana')
61

  
62
    if zeep_version == 2:
63
        client = SOAPClient(soap_resource, strict=False)
64
        result = client.service.GetLastTradePrice(tickerSymbol='banana')
65
    else:
66
        client = SOAPClient(soap_resource)
67
        with client.settings(strict=False):
68
            result = client.service.GetLastTradePrice(tickerSymbol='banana')
69
    assert len(result) == 2
70
    assert result['skipMe'] == None
71
    assert result['price'] == 4.2
tox.ini
1 1
[tox]
2 2
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/passerelle/{env:BRANCH_NAME:}
3
envlist = django111-pg
3
envlist = django111-pg-zeep2
4 4

  
5 5
[testenv]
6 6
usedevelop = True
......
36 36
  vobject
37 37
  django-ratelimit
38 38
  pyquery
39
  zeep2: zeep < 3.0
40
  zeep3: zeep >= 3.0
39 41
commands =
40 42
  ./get_wcs.sh
41 43
  django111: py.test {posargs: {env:FAST:} --junitxml=test_{envname}_results.xml --cov-report xml --cov-report html --cov=passerelle/ --cov-config .coveragerc tests/}
42
-