diff --git a/passerelle/contrib/iparapheur/models.py b/passerelle/contrib/iparapheur/models.py
index 521ed05c..8e7235e2 100644
--- a/passerelle/contrib/iparapheur/models.py
+++ b/passerelle/contrib/iparapheur/models.py
@@ -24,6 +24,10 @@ from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponse, Http404
from zeep.exceptions import Fault as WebFault, TransportError, XMLSyntaxError
+try:
+ from zeep import Settings # zeep version >= 3.x
+except ImportError:
+ Settings = None
from passerelle.base.models import BaseResource, HTTPResource
from passerelle.utils.api import endpoint
@@ -98,9 +102,9 @@ class IParapheur(BaseResource, HTTPResource):
def get_verbose_name(cls):
return cls._meta.verbose_name
- def get_client(self, strict_mode=True):
+ def get_client(self, **kwargs):
try:
- soap_client = self.soap_client(strict=strict_mode)
+ soap_client = self.soap_client(**kwargs)
# overrides the service port address URL defined in the WSDL.
if self.wsdl_endpoint_location:
@@ -116,7 +120,10 @@ class IParapheur(BaseResource, HTTPResource):
def call(self, service_name, *args, **kwargs):
strict_mode = kwargs.pop('strict_mode', True)
- client = self.get_client(strict_mode=strict_mode)
+ if Settings is not None: # zeep version >= 3.x:
+ client = self.get_client(settings=Settings(strict=strict_mode))
+ else:
+ client = self.get_client(strict=strict_mode)
try:
result = getattr(client.overridden_service, service_name)(*args, **kwargs)
except WebFault as exc:
diff --git a/setup.py b/setup.py
index 1820b6d2..8b002d7b 100755
--- a/setup.py
+++ b/setup.py
@@ -104,7 +104,7 @@ setup(name='passerelle',
'python-dateutil',
'Pillow',
'jsonschema < 3.1',
- 'zeep < 3.0',
+ 'zeep',
'pycrypto',
'unidecode',
'paramiko',
diff --git a/tests/data/soap.wsdl b/tests/data/soap.wsdl
index 57832709..399af5a1 100644
--- a/tests/data/soap.wsdl
+++ b/tests/data/soap.wsdl
@@ -48,9 +48,10 @@
-
+
+
-
+
diff --git a/tests/test_iparapheur.py b/tests/test_iparapheur.py
index 88b10654..2df3b048 100644
--- a/tests/test_iparapheur.py
+++ b/tests/test_iparapheur.py
@@ -8,6 +8,7 @@ import base64
import xml.etree.ElementTree as ET
from dateutil import parser
from requests import Response
+from zeep import __version__ as zeep_version
from requests.exceptions import ConnectionError
from django.core.urlresolvers import reverse
@@ -41,6 +42,12 @@ def conn():
resource_pk=conn.pk)
return conn
+def assert_invalid_xml(err_desc):
+ if zeep_version < '3':
+ assert "Server returned HTTP status 200 ()" in err_desc
+ else:
+ assert "Server returned response (200) with invalid XML" in err_desc
+
def xmlmime():
return os.path.join(os.path.dirname(__file__), 'data','xmlmime.xml')
@@ -70,7 +77,16 @@ def iph_mocked_get(url, params=None, **kwargs):
def test_call_ping(soap_client, app, conn):
service = mock.Mock()
service.echo.return_value = 'pong'
- mocked_client = mock.Mock(overridden_service=service)
+
+ class MockedSettings(object):
+ def __init__(self, **kwargs):
+ pass
+ def __enter__(self):
+ pass
+ def __exit__(self, exc_type, exc_value, traceback):
+ pass
+
+ mocked_client = mock.Mock(overridden_service=service, settings=MockedSettings)
soap_client.return_value = mocked_client
url = reverse('generic-endpoint', kwargs={'connector': 'iparapheur',
'endpoint': 'ping', 'slug': conn.slug})
@@ -187,7 +203,7 @@ def test_create_file(mocked_post, mocked_get, app, conn):
assert (BASE_URL,) == mocked_post.call_args[0]
assert resp.json['err'] == 1
assert 'zeep.exceptions.TransportError' in resp.json['err_class']
- assert 'Server returned HTTP status 200 ()' in resp.json['err_desc']
+ assert_invalid_xml(resp.json['err_desc'])
# Unknown value for "visibility"
err_data = data.copy()
@@ -211,7 +227,7 @@ def test_create_file(mocked_post, mocked_get, app, conn):
assert (BASE_URL,) == mocked_post.call_args[0]
assert resp.json['err'] == 1
assert 'zeep.exceptions.TransportError' in resp.json['err_class']
- assert 'Server returned HTTP status 200 ()' in resp.json['err_desc']
+ assert_invalid_xml(resp.json['err_desc'])
@mock.patch('passerelle.utils.Request.get', side_effect=iph_mocked_get)
@mock.patch('passerelle.utils.Request.post')
@@ -300,7 +316,7 @@ def test_get_file_status(mocked_post, mocked_get, app, conn):
assert resp.json['err'] == 1
#assert 'zeep.exceptions.TransportError' in resp.json['err_class']
assert 'passerelle.utils.jsonresponse.APIError' in resp.json['err_class']
- assert 'Server returned HTTP status 200 ()' in resp.json['err_desc']
+ assert_invalid_xml(resp.json['err_desc'])
@mock.patch('passerelle.utils.Request.get', side_effect=iph_mocked_get)
@mock.patch('passerelle.utils.Request.post')
@@ -325,7 +341,7 @@ def test_get_file(mocked_post, mocked_get, app, conn):
assert resp.text == 'Test Document'
# KO
- soap_response = """KOKOmessageINFO"""
+ soap_response = """KOKOmessageINFO"""
response._content = soap_response
mocked_post.return_value = response
resp = app.get(url, status=500)
@@ -334,7 +350,7 @@ def test_get_file(mocked_post, mocked_get, app, conn):
assert resp.json['err_desc'] == 'KOmessage'
# unknown response
- soap_response = """"""
+ soap_response = """"""
response._content = soap_response
mocked_post.return_value = response
resp = app.get(url, status=500)
diff --git a/tests/test_soap.py b/tests/test_soap.py
index 7752707f..b8bc7a59 100644
--- a/tests/test_soap.py
+++ b/tests/test_soap.py
@@ -1,5 +1,12 @@
+import pytest
+import mock
import requests
from zeep.plugins import Plugin
+from zeep.exceptions import XMLParseError
+try:
+ from zeep import Settings # zeep version >= 3.x
+except ImportError:
+ Settings = None
from passerelle.utils.soap import SOAPClient
@@ -30,3 +37,32 @@ def test_soap_client():
assert client.transport.session == soap_resource.requests
assert client.transport.cache
assert client.plugins == plugins
+
+@mock.patch('requests.sessions.Session.post')
+def test_disable_strict_mode(mocked_post):
+ response = requests.Response()
+ response.status_code = 200
+ response._content = '''
+
+
+
+ 4.20
+
+
+'''
+ mocked_post.return_value = response
+
+ soap_resource = SOAPResource()
+ client = SOAPClient(soap_resource)
+ with pytest.raises(
+ XMLParseError, match="Unexpected element u'price', expected u'skipMe'"):
+ client.service.GetLastTradePrice(tickerSymbol='banana')
+
+ if Settings is not None: # zeep version >= 3.x:
+ client = SOAPClient(soap_resource, settings=Settings(strict=False))
+ else:
+ client = SOAPClient(soap_resource, strict=False)
+ result = client.service.GetLastTradePrice(tickerSymbol='banana')
+ assert len(result) == 2
+ assert result['skipMe'] == None
+ assert result['price'] == 4.2
diff --git a/tox.ini b/tox.ini
index 4779c8bb..9a218c2e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
[tox]
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/passerelle/{env:BRANCH_NAME:}
-envlist = django111-pg
+envlist = django111-pg-zeep2
[testenv]
usedevelop = True
@@ -36,6 +36,8 @@ deps =
vobject
django-ratelimit
pyquery
+ zeep2: zeep < 3.0
+ zeep3: zeep >= 3.0
commands =
./get_wcs.sh
django111: py.test {posargs: {env:FAST:} --junitxml=test_{envname}_results.xml --cov-report xml --cov-report html --cov=passerelle/ --cov-config .coveragerc tests/}