Hello community,

here is the log from the commit of package python-zeep for openSUSE:Factory 
checked in at 2019-02-26 22:21:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-zeep (Old)
 and      /work/SRC/openSUSE:Factory/.python-zeep.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-zeep"

Tue Feb 26 22:21:09 2019 rev:2 rq:679181 version:3.2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-zeep/python-zeep.changes  2019-01-03 
18:09:51.907964891 +0100
+++ /work/SRC/openSUSE:Factory/.python-zeep.new.28833/python-zeep.changes       
2019-02-26 22:22:47.610057802 +0100
@@ -1,0 +2,16 @@
+Tue Feb 26 06:11:48 UTC 2019 - John Vandenberg <[email protected]>
+
+- Remove from builds undesirable pytest plugins suited for development
+- Add minimum build version for tornado
+- Remove inappropriate runtime dependency on aioresponses
+- Update to v3.2.0
+  * Fix abstract message check for NoneType before attempting to access parts
+  * Improve support for 'Chameleon' XSD schemas (#879, #888)
+  * Fix resolving qualified references (#879)
+  * Fix issue with duplicate soap:body tags when multiple parts used (#879)
+  * Fix Choice with unbound Any element (#871)
+  * Add xsd_ignore_sequence_order flag (#880)
+  * Add support for timestamp token in WSS headers (#817)
+  * Accept strings for xsd.DateTime (#886)
+
+-------------------------------------------------------------------

Old:
----
  zeep-3.1.0.tar.gz

New:
----
  zeep-3.2.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-zeep.spec ++++++
--- /var/tmp/diff_new_pack.qZowW0/_old  2019-02-26 22:22:48.106057625 +0100
+++ /var/tmp/diff_new_pack.qZowW0/_new  2019-02-26 22:22:48.110057624 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-zeep
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-zeep
-Version:        3.1.0
+Version:        3.2.0
 Release:        0
 Summary:        A Python SOAP client based on lxml/requests
 License:        MIT
@@ -46,32 +46,25 @@
 BuildRequires:  %{python_module attrs >= 17.2.0}
 BuildRequires:  %{python_module cached-property >= 1.3.0}
 BuildRequires:  %{python_module defusedxml >= 0.4.1}
-BuildRequires:  %{python_module flake8 >= 3.3.0}
-BuildRequires:  %{python_module flake8-blind-except >= 0.1.1}
-BuildRequires:  %{python_module flake8-debugger >= 1.4.0}
-BuildRequires:  %{python_module flake8-imports >= 0.1.1}
 BuildRequires:  %{python_module freezegun >= 0.3.8}
 BuildRequires:  %{python_module isodate >= 0.5.4}
-BuildRequires:  %{python_module isort >= 4.2.15}
 BuildRequires:  %{python_module lxml >= 3.1.0}
 BuildRequires:  %{python_module mock >= 2.0.0}
 BuildRequires:  %{python_module pretend >= 1.0.8}
 BuildRequires:  %{python_module pytest >= 3.1.3}
-BuildRequires:  %{python_module pytest-cov >= 2.5.1}
 BuildRequires:  %{python_module pytest-tornado >= 0.4.5}
 BuildRequires:  %{python_module pytz}
 BuildRequires:  %{python_module requests >= 2.7.0}
 BuildRequires:  %{python_module requests-mock >= 0.7.0}
 BuildRequires:  %{python_module requests-toolbelt >= 0.7.1}
 BuildRequires:  %{python_module six >= 1.9.0}
-BuildRequires:  %{python_module tornado}
+BuildRequires:  %{python_module tornado >= 4.0.2}
 BuildRequires:  %{python_module xmlsec >= 0.6.1}
 BuildRequires:  python3-aiohttp >= 1.0
 BuildRequires:  python3-aioresponses >= 0.4.1
 # /SECTION
 %ifpython3
 Requires:       python-aiohttp >= 1.0
-Requires:       python-aioresponses >= 0.4.1
 %endif
 %python_subpackages
 

++++++ zeep-3.1.0.tar.gz -> zeep-3.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/CHANGES new/zeep-3.2.0/CHANGES
--- old/zeep-3.1.0/CHANGES      2018-07-28 09:49:57.000000000 +0200
+++ new/zeep-3.2.0/CHANGES      2018-12-17 09:47:28.000000000 +0100
@@ -1,3 +1,15 @@
+3.2.0 (2018-12-17)
+------------------
+ - Fix abstract message check for NoneType before attempting to access parts
+ - Improve support for 'Chameleon' XSD schemas (#879, #888)
+ - Fix resolving qualified references (#879)
+ - Fix issue with duplicate soap:body tags when multiple parts used (#879)
+ - Fix Choice with unbound Any element (#871)
+ - Add xsd_ignore_sequence_order flag (#880)
+ - Add support for timestamp token in WSS headers (#817)
+ - Accept strings for xsd.DateTime (#886)
+
+
 3.1.0 (2018-07-28)
 ------------------
  - Fix SSL issue on with `TornadoAsyncTransport` (#792)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/PKG-INFO new/zeep-3.2.0/PKG-INFO
--- old/zeep-3.1.0/PKG-INFO     2018-07-28 09:50:37.000000000 +0200
+++ new/zeep-3.2.0/PKG-INFO     2018-12-17 10:05:53.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: zeep
-Version: 3.1.0
+Version: 3.2.0
 Summary: A modern/fast Python SOAP client based on lxml / requests
 Home-page: http://docs.python-zeep.org
 Author: Michael van Tellingen
@@ -13,7 +13,7 @@
         A fast and modern Python SOAP client
         
         Highlights:
-         * Compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6 and PyPy
+         * Compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6, 3.7 and PyPy
          * Build on top of lxml and requests
          * Support for Soap 1.1, Soap 1.2 and HTTP bindings
          * Support for WS-Addressing headers
@@ -62,10 +62,7 @@
         If you want to report a bug then please first read 
         http://docs.python-zeep.org/en/master/reporting_bugs.html
         
-        I'm also able to offer commercial support.  As in contracting work. 
Please
-        contact me at [email protected] for more information.  Note that 
asking 
-        questions or reporting bugs via this e-mail address will be ignored. 
Pleae use
-        the appropriate channels for that (e.g. stackoverflow)
+        Please only report bugs and not support requests to the GitHub issue 
tracker. 
         
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
@@ -76,5 +73,11 @@
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Provides-Extra: async
+Provides-Extra: tornado
+Provides-Extra: docs
+Provides-Extra: xmlsec
+Provides-Extra: test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/README.rst new/zeep-3.2.0/README.rst
--- old/zeep-3.1.0/README.rst   2017-11-04 09:15:21.000000000 +0100
+++ new/zeep-3.2.0/README.rst   2018-12-17 09:52:45.000000000 +0100
@@ -5,7 +5,7 @@
 A fast and modern Python SOAP client
 
 Highlights:
- * Compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6 and PyPy
+ * Compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6, 3.7 and PyPy
  * Build on top of lxml and requests
  * Support for Soap 1.1, Soap 1.2 and HTTP bindings
  * Support for WS-Addressing headers
@@ -77,7 +77,4 @@
 If you want to report a bug then please first read 
 http://docs.python-zeep.org/en/master/reporting_bugs.html
 
-I'm also able to offer commercial support.  As in contracting work. Please
-contact me at [email protected] for more information.  Note that asking 
-questions or reporting bugs via this e-mail address will be ignored. Pleae use
-the appropriate channels for that (e.g. stackoverflow)
+Please only report bugs and not support requests to the GitHub issue tracker. 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/setup.cfg new/zeep-3.2.0/setup.cfg
--- old/zeep-3.1.0/setup.cfg    2018-07-28 09:50:37.000000000 +0200
+++ new/zeep-3.2.0/setup.cfg    2018-12-17 10:05:53.000000000 +0100
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 3.1.0
+current_version = 3.2.0
 commit = true
 tag = true
 tag_name = {new_version}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/setup.py new/zeep-3.2.0/setup.py
--- old/zeep-3.1.0/setup.py     2018-07-28 09:50:09.000000000 +0200
+++ new/zeep-3.2.0/setup.py     2018-12-17 09:59:37.000000000 +0100
@@ -59,7 +59,7 @@
 
 setup(
     name='zeep',
-    version='3.1.0',
+    version='3.2.0',
     description='A modern/fast Python SOAP client based on lxml / requests',
     long_description=long_description,
     author="Michael van Tellingen",
@@ -89,6 +89,7 @@
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
     ],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/__init__.py 
new/zeep-3.2.0/src/zeep/__init__.py
--- old/zeep-3.1.0/src/zeep/__init__.py 2018-07-28 09:50:09.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/__init__.py 2018-12-17 09:59:27.000000000 +0100
@@ -4,4 +4,4 @@
 from zeep.settings import Settings  # noqa
 from zeep.xsd.valueobjects import AnyObject  # noqa
 
-__version__ = '3.1.0'
+__version__ = '3.2.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/asyncio/transport.py 
new/zeep-3.2.0/src/zeep/asyncio/transport.py
--- old/zeep-3.1.0/src/zeep/asyncio/transport.py        2018-06-16 
09:52:47.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/asyncio/transport.py        2018-12-03 
17:52:42.000000000 +0100
@@ -31,7 +31,7 @@
             ]
 
     def __init__(self, loop, cache=None, timeout=300, operation_timeout=None,
-                 session=None):
+                 session=None, verify_ssl=True, proxy=None):
 
         self.loop = loop if loop else asyncio.get_event_loop()
         self.cache = cache
@@ -39,6 +39,8 @@
         self.operation_timeout = operation_timeout
         self.logger = logging.getLogger(__name__)
 
+        self.verify_ssl = verify_ssl
+        self.proxy = proxy
         self.session = session or aiohttp.ClientSession(loop=self.loop)
         self._close_session = session is None
         self.session._default_headers['User-Agent'] = (
@@ -81,7 +83,8 @@
         self.logger.debug("HTTP Post to %s:\n%s", address, message)
         with aio_timeout(self.operation_timeout):
             response = await self.session.post(
-                address, data=message, headers=headers)
+                address, data=message, headers=headers,
+                verify_ssl=self.verify_ssl, proxy=self.proxy)
             self.logger.debug(
                 "HTTP Response from %s (status: %d):\n%s",
                 address, response.status, await response.read())
@@ -95,7 +98,8 @@
     async def get(self, address, params, headers):
         with aio_timeout(self.operation_timeout):
             response = await self.session.get(
-                address, params=params, headers=headers)
+                address, params=params, headers=headers,
+                verify_ssl=self.verify_ssl, proxy=self.proxy)
 
             return await self.new_response(response)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/proxy.py 
new/zeep-3.2.0/src/zeep/proxy.py
--- old/zeep-3.1.0/src/zeep/proxy.py    2018-06-16 09:53:25.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/proxy.py    2018-12-06 17:41:39.000000000 +0100
@@ -70,6 +70,10 @@
         except KeyError:
             raise AttributeError('Service has no operation %r' % key)
 
+    def __iter__(self):
+        """ Return iterator over the services and their callables. """
+        return iter(self._operations.items())
+
     def __dir__(self):
         """ Return the names of the operations. """
         return list(itertools.chain(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/settings.py 
new/zeep-3.2.0/src/zeep/settings.py
--- old/zeep-3.1.0/src/zeep/settings.py 2018-06-16 09:53:25.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/settings.py 2018-12-07 21:38:28.000000000 +0100
@@ -34,6 +34,10 @@
      approach to add http headers for specific calls.
     :type extra_headers: list
 
+    :param xsd_ignore_sequence_order: boolean to indicate whether to enforce 
sequence
+     order when parsing complex types. This is a workaround for servers that
+     don't respect sequence order.
+    :type xsd_ignore_sequence_order: boolean
     """
     strict = attr.ib(default=True)
     raw_response = attr.ib(default=False)
@@ -48,6 +52,9 @@
     forbid_entities = attr.ib(default=True)
     forbid_external = attr.ib(default=True)
 
+    # xsd workarounds
+    xsd_ignore_sequence_order = attr.ib(default=False)
+
     _tls = attr.ib(default=attr.Factory(threading.local))
 
     @contextmanager
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/tornado/transport.py 
new/zeep-3.2.0/src/zeep/tornado/transport.py
--- old/zeep-3.1.0/src/zeep/tornado/transport.py        2018-07-28 
08:21:16.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/tornado/transport.py        2018-11-18 
11:58:12.000000000 +0100
@@ -124,11 +124,12 @@
             kwargs['body'] = message
 
         http_req = httpclient.HTTPRequest(address, **kwargs)
-        response = yield async_client.fetch(http_req)
+        response = yield async_client.fetch(http_req, raise_error=False)
 
         raise gen.Return(self.new_response(response))
 
-    def new_response(self, response):
+    @staticmethod
+    def new_response(response):
         """Convert an tornado.HTTPResponse object to a requests.Response 
object"""
         new = Response()
         new._content = response.body
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/transports.py 
new/zeep-3.2.0/src/zeep/transports.py
--- old/zeep-3.1.0/src/zeep/transports.py       2018-07-28 09:46:50.000000000 
+0200
+++ new/zeep-3.2.0/src/zeep/transports.py       2018-11-18 11:17:39.000000000 
+0100
@@ -75,7 +75,7 @@
             else:
                 log_message = response.content
                 if isinstance(log_message, bytes):
-                    log_message = log_message.decode('utf-8')
+                    log_message = log_message.decode(response.encoding or 
'utf-8')
 
             self.logger.debug(
                 "HTTP Response from %s (status: %d):\n%s",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/utils.py 
new/zeep-3.2.0/src/zeep/utils.py
--- old/zeep-3.1.0/src/zeep/utils.py    2018-05-13 10:13:32.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/utils.py    2018-12-17 09:25:21.000000000 +0100
@@ -86,4 +86,4 @@
 def get_media_type(value):
     """Parse a HTTP content-type header and return the media-type"""
     main_value, parameters = cgi.parse_header(value)
-    return main_value
+    return main_value.lower()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/wsdl/messages/soap.py 
new/zeep-3.2.0/src/zeep/wsdl/messages/soap.py
--- old/zeep-3.1.0/src/zeep/wsdl/messages/soap.py       2018-06-16 
11:27:54.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/wsdl/messages/soap.py       2018-12-07 
21:34:15.000000000 +0100
@@ -41,6 +41,7 @@
         self.abstract = None  # Set during resolve()
         self.type = type
 
+        self._is_body_wrapped = False
         self.body = None
         self.header = None
         self.envelope = None
@@ -54,21 +55,30 @@
 
         soap = ElementMaker(namespace=self.nsmap['soap-env'], nsmap=nsmap)
 
+        # Create the soap:envelope
+        envelope = soap.Envelope()
+
         # Create the soap:header element
         headers_value = kwargs.pop('_soapheaders', None)
         header = self._serialize_header(headers_value, nsmap)
+        if header is not None:
+            envelope.append(header)
 
-        # Create the soap:body element
-        body = soap.Body()
+        # Create the soap:body element. The _is_body_wrapped attribute signals
+        # that the self.body element is of type soap:body, so we don't have to
+        # create it in that case. Otherwise we create a Element soap:body and
+        # render the content into this.
         if self.body:
             body_value = self.body(*args, **kwargs)
-            self.body.render(body, body_value)
-
-        # Create the soap:envelope
-        envelope = soap.Envelope()
-        if header is not None:
-            envelope.append(header)
-        envelope.append(body)
+            if self._is_body_wrapped:
+                self.body.render(envelope, body_value)
+            else:
+                body = soap.Body()
+                envelope.append(body)
+                self.body.render(body, body_value)
+        else:
+            body = soap.Body()
+            envelope.append(body)
 
         # XXX: This is only used in Soap 1.1 so should be moved to the the
         # Soap11Binding._set_http_headers(). But let's keep it like this for
@@ -279,7 +289,7 @@
 
         # If this message has no parts then we have nothing to do. This might
         # happen for output messages which don't return anything.
-        if not abstract_message.parts and self.type != 'input':
+        if (abstract_message is None or not abstract_message.parts) and 
self.type != 'input':
             return
 
         self.abstract = abstract_message
@@ -399,7 +409,6 @@
 
     def __init__(self, *args, **kwargs):
         super(DocumentMessage, self).__init__(*args, **kwargs)
-        self._is_body_wrapped = False
 
     def _deserialize_body(self, xmlelement):
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/wsdl/parse.py 
new/zeep-3.2.0/src/zeep/wsdl/parse.py
--- old/zeep-3.1.0/src/zeep/wsdl/parse.py       2018-06-16 11:13:16.000000000 
+0200
+++ new/zeep-3.2.0/src/zeep/wsdl/parse.py       2018-12-17 09:25:21.000000000 
+0100
@@ -39,8 +39,8 @@
 
     for part in xmlelement.findall('wsdl:part', namespaces=NSMAP):
         part_name = part.get('name')
-        part_element = qname_attr(part, 'element', tns)
-        part_type = qname_attr(part, 'type', tns)
+        part_element = qname_attr(part, 'element')
+        part_type = qname_attr(part, 'type')
 
         try:
             if part_element is not None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/wsse/__init__.py 
new/zeep-3.2.0/src/zeep/wsse/__init__.py
--- old/zeep-3.1.0/src/zeep/wsse/__init__.py    2017-03-12 13:53:30.000000000 
+0100
+++ new/zeep-3.2.0/src/zeep/wsse/__init__.py    2018-11-18 10:08:17.000000000 
+0100
@@ -1,3 +1,3 @@
 from .compose import Compose  # noqa
-from .signature import Signature  # noqa
+from .signature import BinarySignature, Signature  # noqa
 from .username import UsernameToken  # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/wsse/signature.py 
new/zeep-3.2.0/src/zeep/wsse/signature.py
--- old/zeep-3.1.0/src/zeep/wsse/signature.py   2017-11-04 09:15:21.000000000 
+0100
+++ new/zeep-3.2.0/src/zeep/wsse/signature.py   2018-11-18 11:17:39.000000000 
+0100
@@ -71,6 +71,17 @@
             _read_file(key_file), _read_file(certfile), password)
 
 
+class BinarySignature(Signature):
+    """Sign given SOAP envelope with WSSE sig usign given key file and cert 
file.
+
+    Place the key information into BinarySecurityElement."""
+
+    def apply(self, envelope, headers):
+        key = _make_sign_key(self.key_data, self.cert_data, self.password)
+        _sign_envelope_with_key_binary(envelope, key)
+        return envelope, headers
+
+
 def check_xmlsec_import():
     if xmlsec is None:
         raise ImportError(
@@ -173,7 +184,8 @@
     return _sign_envelope_with_key(envelope, key)
 
 
-def _sign_envelope_with_key(envelope, key):
+def _signature_prepare(envelope, key):
+    """Prepare envelope and sign."""
     soap_env = detect_soap_env(envelope)
 
     # Create the Signature node.
@@ -208,9 +220,31 @@
     # the X509 data (because it doesn't understand WSSE).
     sec_token_ref = etree.SubElement(
         key_info, QName(ns.WSSE, 'SecurityTokenReference'))
+    return security, sec_token_ref, x509_data
+
+
+def _sign_envelope_with_key(envelope, key):
+    _, sec_token_ref, x509_data = _signature_prepare(envelope, key)
     sec_token_ref.append(x509_data)
 
 
+def _sign_envelope_with_key_binary(envelope, key):
+    security, sec_token_ref, x509_data = _signature_prepare(envelope, key)
+    ref = etree.SubElement(sec_token_ref, QName(ns.WSSE, 'Reference'),
+                           {'ValueType': 
'http://docs.oasis-open.org/wss/2004/01/'
+                                         
'oasis-200401-wss-x509-token-profile-1.0#X509v3'})
+    ref_id = ensure_id(ref)
+    bintok = etree.Element(QName(ns.WSSE, 'BinarySecurityToken'), {
+        QName(ns.WSU, 'Id'): ref_id,
+        'ValueType': 'http://docs.oasis-open.org/wss/2004/01/'
+                     'oasis-200401-wss-x509-token-profile-1.0#X509v3',
+        'EncodingType': 'http://docs.oasis-open.org/wss/2004/01/'
+                        
'oasis-200401-wss-soap-message-security-1.0#Base64Binary'})
+    bintok.text = x509_data.find(QName(ns.DS, 'X509Certificate')).text
+    security.insert(1, bintok)
+    x509_data.getparent().remove(x509_data)
+
+
 def verify_envelope(envelope, certfile):
     """Verify WS-Security signature on given SOAP envelope with given cert.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/wsse/username.py 
new/zeep-3.2.0/src/zeep/wsse/username.py
--- old/zeep-3.1.0/src/zeep/wsse/username.py    2017-09-29 17:15:39.000000000 
+0200
+++ new/zeep-3.2.0/src/zeep/wsse/username.py    2018-12-07 21:40:00.000000000 
+0100
@@ -38,13 +38,14 @@
     soap_message_secutity_ns = 
'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0'
    # noqa
 
     def __init__(self, username, password=None, password_digest=None,
-                 use_digest=False, nonce=None, created=None):
+                 use_digest=False, nonce=None, created=None, 
timestamp_token=None):
         self.username = username
         self.password = password
         self.password_digest = password_digest
         self.nonce = nonce
         self.created = created
         self.use_digest = use_digest
+        self.timestamp_token = timestamp_token
 
     def apply(self, envelope, headers):
         security = utils.get_security_header(envelope)
@@ -56,6 +57,9 @@
             token = utils.WSSE.UsernameToken()
             security.append(token)
 
+        if self.timestamp_token is not None:
+            security.append(self.timestamp_token)
+
         # Create the sub elements of the UsernameToken element
         elements = [
             utils.WSSE.Username(self.username)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/xsd/elements/element.py 
new/zeep-3.2.0/src/zeep/xsd/elements/element.py
--- old/zeep-3.1.0/src/zeep/xsd/elements/element.py     2018-06-17 
08:56:38.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/xsd/elements/element.py     2018-12-07 
21:38:28.000000000 +0100
@@ -159,6 +159,18 @@
                 item = self.parse(
                     xmlelement, schema, allow_none=True, context=context)
                 result.append(item)
+            elif (
+                  schema is not None and
+                  schema.settings.xsd_ignore_sequence_order and
+                  list(filter(lambda elem: etree.QName(elem.tag).localname == 
self.qname.localname, xmlelements))
+            ):
+                # Search for the field in remaining elements, not only the 
leftmost
+                xmlelement = list(filter(lambda elem: 
etree.QName(elem.tag).localname == self.qname.localname, xmlelements))[0]
+                xmlelements.remove(xmlelement)
+                num_matches += 1
+                item = self.parse(
+                    xmlelement, schema, allow_none=True, context=context)
+                result.append(item)
             else:
                 # If the element passed doesn't match and the current one is
                 # not optional then throw an error
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/xsd/elements/indicators.py 
new/zeep-3.2.0/src/zeep/xsd/elements/indicators.py
--- old/zeep-3.1.0/src/zeep/xsd/elements/indicators.py  2018-05-11 
09:16:20.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/xsd/elements/indicators.py  2018-12-03 
17:52:42.000000000 +0100
@@ -426,7 +426,10 @@
                             result.append(choice_value)
                             break
                     else:
-                        if element.name in value:
+                        if isinstance(element, Any):
+                            result.append(value)
+                            break
+                        elif element.name in value:
                             choice_value = value.get(element.name)
                             result.append({element.name: choice_value})
                             break
@@ -539,7 +542,7 @@
                 if name is not None:
                     try:
                         choice_value = value[name]
-                    except KeyError:
+                    except (KeyError, TypeError):
                         choice_value = value
                 else:
                     choice_value = value
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/xsd/schema.py 
new/zeep-3.2.0/src/zeep/xsd/schema.py
--- old/zeep-3.1.0/src/zeep/xsd/schema.py       2018-07-28 08:18:55.000000000 
+0200
+++ new/zeep-3.2.0/src/zeep/xsd/schema.py       2018-12-17 09:25:21.000000000 
+0100
@@ -102,6 +102,13 @@
                     seen.add(type_.qname)
 
     def add_documents(self, schema_nodes, location):
+        """
+
+        :type schema_nodes: List[lxml.etree._Element]
+        :type location: str
+        :type target_namespace: Optional[str]
+
+        """
         resolve_queue = []
         for node in schema_nodes:
             document = self.create_new_document(node, location)
@@ -133,6 +140,7 @@
 
         :rtype: zeep.xsd.ComplexType or zeep.xsd.AnySimpleType
 
+
         """
         qname = self._create_qname(qname)
         try:
@@ -191,16 +199,17 @@
             return 'soap-env'
         return namespace
 
-    def create_new_document(self, node, url, base_url=None):
+    def create_new_document(self, node, url, base_url=None, 
target_namespace=None):
         """
 
         :rtype: zeep.xsd.schema.SchemaDocument
 
         """
         namespace = node.get('targetNamespace') if node is not None else None
+        if not namespace:
+            namespace = target_namespace
         if base_url is None:
             base_url = url
-
         schema = SchemaDocument(namespace, url, base_url)
         self.documents.add(schema)
         schema.load(self, node)
@@ -377,6 +386,7 @@
         self._location = location
         self._target_namespace = namespace
         self._is_internal = False
+        self._has_empty_import = False
 
         # Containers for specific types
         self._attribute_groups = {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/xsd/types/builtins.py 
new/zeep-3.2.0/src/zeep/xsd/types/builtins.py
--- old/zeep-3.1.0/src/zeep/xsd/types/builtins.py       2018-05-12 
12:09:30.000000000 +0200
+++ new/zeep-3.2.0/src/zeep/xsd/types/builtins.py       2018-12-17 
09:25:21.000000000 +0100
@@ -123,6 +123,8 @@
 
     @check_no_collection
     def xmlvalue(self, value):
+        if isinstance(value, six.string_types):
+            return value
 
         # Bit of a hack, since datetime is a subclass of date we can't just
         # test it with an isinstance(). And actually, we should not really
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep/xsd/visitor.py 
new/zeep-3.2.0/src/zeep/xsd/visitor.py
--- old/zeep-3.1.0/src/zeep/xsd/visitor.py      2018-07-28 08:17:11.000000000 
+0200
+++ new/zeep-3.2.0/src/zeep/xsd/visitor.py      2018-12-17 09:25:21.000000000 
+0100
@@ -91,6 +91,8 @@
         if not ref:
             return
 
+        ref = self._create_qname(ref)
+
         if node.tag == tags.element:
             cls = xsd_elements.RefElement
         elif node.tag == tags.attribute:
@@ -129,7 +131,12 @@
         """
         assert node is not None
 
-        self.document._target_namespace = node.get('targetNamespace')
+        # A schema should always have a targetNamespace attribute, otherwise
+        # it is called a chameleon schema. In that case the schema will inherit
+        # the namespace of the enclosing schema/node.
+        tns = node.get('targetNamespace')
+        if tns:
+            self.document._target_namespace = tns
         self.document._element_form = node.get('elementFormDefault', 
'unqualified')
         self.document._attribute_form = node.get('attributeFormDefault', 
'unqualified')
 
@@ -168,6 +175,16 @@
                 filename=self._document.location,
                 sourceline=node.sourceline)
 
+        # We found an empty <import/> statement, this needs to trigger 4.1.2
+        # from 
https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#src-resolve
+        # for QName resolving.
+        # In essence this means we will resolve QNames without a namespace to 
no
+        # namespace instead of the target namespace.
+        # The following code snippet works because imports have to occur 
before we
+        # visit elements.
+        if not namespace and not location:
+            self.document._has_empty_import = True
+
         # Check if the schema is already imported before based on the
         # namespace. Schema's without namespace are registered as 'None'
         document = 
self.schema.documents.get_by_namespace_and_location(namespace, location)
@@ -207,7 +224,13 @@
                 filename=self.document._location,
                 sourceline=node.sourceline)
 
-        schema = self.schema.create_new_document(schema_node, location)
+        # If the imported schema doesn't define a target namespace and the
+        # node doesn't specify it either then inherit the existing target
+        # namespace.
+        elif not schema_tns and not namespace:
+            namespace = self.document._target_namespace
+
+        schema = self.schema.create_new_document(schema_node, location, 
target_namespace=namespace)
         self.register_import(namespace, schema)
         return schema
 
@@ -1157,6 +1180,9 @@
                 namespace=name.namespace, schemaLocation=name.namespace)
             self.visit_import(import_node, None)
 
+        if (not name.namespace and self.document._element_form == 'qualified' 
and
+            self.document._target_namespace and not 
self.document._has_empty_import):
+                name = etree.QName(self.document._target_namespace, 
name.localname)
         return name
 
     def _pop_annotation(self, items):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep.egg-info/PKG-INFO 
new/zeep-3.2.0/src/zeep.egg-info/PKG-INFO
--- old/zeep-3.1.0/src/zeep.egg-info/PKG-INFO   2018-07-28 09:50:37.000000000 
+0200
+++ new/zeep-3.2.0/src/zeep.egg-info/PKG-INFO   2018-12-17 10:05:52.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: zeep
-Version: 3.1.0
+Version: 3.2.0
 Summary: A modern/fast Python SOAP client based on lxml / requests
 Home-page: http://docs.python-zeep.org
 Author: Michael van Tellingen
@@ -13,7 +13,7 @@
         A fast and modern Python SOAP client
         
         Highlights:
-         * Compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6 and PyPy
+         * Compatible with Python 2.7, 3.3, 3.4, 3.5, 3.6, 3.7 and PyPy
          * Build on top of lxml and requests
          * Support for Soap 1.1, Soap 1.2 and HTTP bindings
          * Support for WS-Addressing headers
@@ -62,10 +62,7 @@
         If you want to report a bug then please first read 
         http://docs.python-zeep.org/en/master/reporting_bugs.html
         
-        I'm also able to offer commercial support.  As in contracting work. 
Please
-        contact me at [email protected] for more information.  Note that 
asking 
-        questions or reporting bugs via this e-mail address will be ignored. 
Pleae use
-        the appropriate channels for that (e.g. stackoverflow)
+        Please only report bugs and not support requests to the GitHub issue 
tracker. 
         
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
@@ -76,5 +73,11 @@
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Provides-Extra: async
+Provides-Extra: tornado
+Provides-Extra: docs
+Provides-Extra: xmlsec
+Provides-Extra: test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep.egg-info/SOURCES.txt 
new/zeep-3.2.0/src/zeep.egg-info/SOURCES.txt
--- old/zeep-3.1.0/src/zeep.egg-info/SOURCES.txt        2018-07-28 
09:50:37.000000000 +0200
+++ new/zeep-3.2.0/src/zeep.egg-info/SOURCES.txt        2018-12-17 
10:05:52.000000000 +0100
@@ -109,6 +109,7 @@
 tests/test_wsdl_messages_document.py
 tests/test_wsdl_messages_http.py
 tests/test_wsdl_messages_rpc.py
+tests/test_wsdl_no_output_message_part.py
 tests/test_wsdl_soap.py
 tests/test_wsse_signature.py
 tests/test_wsse_username.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/src/zeep.egg-info/requires.txt 
new/zeep-3.2.0/src/zeep.egg-info/requires.txt
--- old/zeep-3.1.0/src/zeep.egg-info/requires.txt       2018-07-28 
09:50:37.000000000 +0200
+++ new/zeep-3.2.0/src/zeep.egg-info/requires.txt       2018-12-17 
10:05:52.000000000 +0100
@@ -31,7 +31,7 @@
 aioresponses>=0.4.1
 
 [tornado]
-tornado>=4.0.2,<5
+tornado<5,>=4.0.2
 
 [xmlsec]
 xmlsec>=0.6.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_tornado_transport.py 
new/zeep-3.2.0/tests/test_tornado_transport.py
--- old/zeep-3.1.0/tests/test_tornado_transport.py      2017-11-04 
09:15:21.000000000 +0100
+++ new/zeep-3.2.0/tests/test_tornado_transport.py      2018-12-03 
17:13:14.000000000 +0100
@@ -9,6 +9,22 @@
 from zeep.tornado import TornadoAsyncTransport
 
 
[email protected]
+@patch('tornado.httpclient.HTTPClient.fetch')
+def test_tornado_load(mock_httpclient_fetch):
+    cache = stub(get=lambda url: None, add=lambda url, content: None)
+    response = 
HTTPResponse(HTTPRequest('http://tests.python-zeep.org/test.xml'), 200)
+    response.buffer = True
+    response._body = 'x'
+    mock_httpclient_fetch.return_value = response
+
+    transport = TornadoAsyncTransport(cache=cache)
+
+    result = transport.load('http://tests.python-zeep.org/test.xml')
+
+    assert result == 'x'
+
+
 class TornadoAsyncTransportTest(AsyncTestCase):
     @pytest.mark.requests
     def test_no_cache(self):
@@ -16,22 +32,6 @@
         assert transport.cache is None
 
     @pytest.mark.requests
-    @patch('tornado.httpclient.HTTPClient.fetch')
-    @gen_test
-    def test_load(self, mock_httpclient_fetch):
-        cache = stub(get=lambda url: None, add=lambda url, content: None)
-        response = 
HTTPResponse(HTTPRequest('http://tests.python-zeep.org/test.xml'), 200)
-        response.buffer = True
-        response._body = 'x'
-        mock_httpclient_fetch.return_value = response
-
-        transport = TornadoAsyncTransport(cache=cache)
-
-        result = transport.load('http://tests.python-zeep.org/test.xml')
-
-        assert result == 'x'
-
-    @pytest.mark.requests
     @patch('tornado.httpclient.AsyncHTTPClient.fetch')
     @gen_test
     def test_post(self, mock_httpclient_fetch):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_wsdl.py 
new/zeep-3.2.0/tests/test_wsdl.py
--- old/zeep-3.1.0/tests/test_wsdl.py   2018-06-16 09:53:25.000000000 +0200
+++ new/zeep-3.2.0/tests/test_wsdl.py   2018-12-17 09:25:21.000000000 +0100
@@ -1034,3 +1034,125 @@
 
     assert headers['Authorization'] == 'Bearer 1234'
 
+
+def test_wsdl_no_schema_namespace():
+    wsdl_main = StringIO("""
+        <wsdl:definitions
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
+            xmlns:tns="http://Example.org";
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+            targetNamespace="http://Example.org";
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";>
+          <wsdl:types>
+            <xsd:schema elementFormDefault="qualified" >
+              <xsd:element name="AddResponse">
+                <xsd:complexType>
+                    <xsd:sequence>
+                    <xsd:element minOccurs="0" maxOccurs="1" ref="demo" />
+                    </xsd:sequence>
+                </xsd:complexType>
+              </xsd:element>
+              <xsd:element name="Add">
+                <xsd:complexType>
+                  <xsd:sequence>
+                    <xsd:element minOccurs="1" name="a" type="xsd:int" />
+                    <xsd:element minOccurs="1" name="b" type="xsd:int" />
+                  </xsd:sequence>
+                </xsd:complexType>
+              </xsd:element>
+              <xsd:element name="AddResponse">
+                <xsd:complexType>
+                  <xsd:sequence>
+                    <xsd:element minOccurs="0" name="result" type="xsd:int" />
+                  </xsd:sequence>
+                </xsd:complexType>
+              </xsd:element>
+            </xsd:schema>
+            <xsd:schema elementFormDefault="qualified" >
+              <xsd:element name="demo">
+              </xsd:element>
+            </xsd:schema>
+          </wsdl:types>
+          <wsdl:message name="ICalculator_Add_InputMessage">
+            <wsdl:part name="parameters" element="Add" />
+          </wsdl:message>
+          <wsdl:message name="ICalculator_Add_OutputMessage">
+            <wsdl:part name="parameters" element="AddResponse" />
+          </wsdl:message>
+          <wsdl:portType name="ICalculator">
+            <wsdl:operation name="Add">
+              <wsdl:input message="tns:ICalculator_Add_InputMessage" />
+              <wsdl:output message="tns:ICalculator_Add_OutputMessage" />
+            </wsdl:operation>
+          </wsdl:portType>
+          <wsdl:binding name="DefaultBinding_ICalculator" 
type="tns:ICalculator">
+            <soap:binding transport="http://schemas.xmlsoap.org/soap/http"; />
+            <wsdl:operation name="Add">
+              <soap:operation soapAction="http://Example.org/ICalculator/Add"; 
style="document" />
+              <wsdl:input>
+                <soap:body use="literal" />
+              </wsdl:input>
+              <wsdl:output>
+                <soap:body use="literal" />
+              </wsdl:output>
+            </wsdl:operation>
+          </wsdl:binding>
+          <wsdl:service name="CalculatorService">
+            <wsdl:port name="ICalculator" 
binding="tns:DefaultBinding_ICalculator">
+              <soap:address location="http://Example.org/ICalculator"; />
+            </wsdl:port>
+          </wsdl:service>
+        </wsdl:definitions>
+    """)
+    client = stub(settings=Settings(), plugins=[], wsse=None)
+
+    transport = DummyTransport()
+    document = wsdl.Document(wsdl_main, transport)
+    binding = 
document.services.get('CalculatorService').ports.get('ICalculator').binding
+
+    envelope, headers = binding._create(
+        'Add',
+        args=[3, 4],
+        kwargs={},
+        client=client,
+        options={'address': 'http://tests.python-zeep.org/test'})
+
+    expected = """
+        <soap-env:Envelope 
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/";>
+          <soap-env:Body>
+            <Add>
+                <a>3</a>
+                <b>4</b>
+            </Add>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, envelope)
+
+
+def test_namespaced_wsdl_with_empty_import():
+    # See https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#src-resolve 
for details
+    wsdl_main = StringIO("""
+        <wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema"; 
targetNamespace="weird_wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";>
+        <wsdl:types>
+            <s:schema elementFormDefault="qualified" 
targetNamespace="weird_wsdl">
+                <s:import />
+                <s:element name="GetVTInfoResponse">
+                    <s:complexType>
+                    <s:sequence>
+                        <s:element minOccurs="0" maxOccurs="1" 
ref="GetVTInfoResult" />
+                    </s:sequence>
+                    </s:complexType>
+                </s:element>
+            </s:schema>
+            <s:schema elementFormDefault="qualified">
+                <s:element name="GetVTInfoResult" />
+            </s:schema>
+        </wsdl:types>
+        </wsdl:definitions>
+    """)
+
+    transport = DummyTransport()
+    document = wsdl.Document(wsdl_main, transport)
+    document.dump()
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_wsdl_messages_document.py 
new/zeep-3.2.0/tests/test_wsdl_messages_document.py
--- old/zeep-3.1.0/tests/test_wsdl_messages_document.py 2017-11-04 
09:15:21.000000000 +0100
+++ new/zeep-3.2.0/tests/test_wsdl_messages_document.py 2018-12-07 
21:32:00.000000000 +0100
@@ -332,6 +332,78 @@
     assert_nodes_equal(expected, serialized.content)
 
 
+def test_serialize_multiple_parts():
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/";
+                 xmlns:tns="http://tests.python-zeep.org/tns";
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+                 targetNamespace="http://tests.python-zeep.org/tns";>
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns";
+                    elementFormDefault="qualified">
+          <xsd:element name="Request">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="arg1" type="xsd:string"/>
+                <xsd:element name="arg2" type="xsd:string"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part name="request1" element="tns:Request"/>
+        <part name="request2" element="tns:Request"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+        </operation>
+      </binding>
+    </definitions>
+    """.strip())
+
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+
+    serialized = operation.input.serialize(
+        request1={'arg1': 'ah1', 'arg2': 'ah2'},
+        request2={'arg1': 'ah1', 'arg2': 'ah2'}
+    )
+    expected = """
+        <?xml version="1.0"?>
+        <soap-env:Envelope
+            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/";>
+          <soap-env:Body>
+            <ns0:Request xmlns:ns0="http://tests.python-zeep.org/tns";>
+            <ns0:arg1>ah1</ns0:arg1>
+            <ns0:arg2>ah2</ns0:arg2>
+            </ns0:Request>
+            <ns1:Request xmlns:ns1="http://tests.python-zeep.org/tns";>
+            <ns1:arg1>ah1</ns1:arg1>
+            <ns1:arg2>ah2</ns1:arg2>
+            </ns1:Request>
+          </soap-env:Body>
+        </soap-env:Envelope>
+    """
+    assert_nodes_equal(expected, serialized.content)
+
+
 def test_serialize_with_header():
     wsdl_content = StringIO("""
     <definitions xmlns="http://schemas.xmlsoap.org/wsdl/";
@@ -394,8 +466,6 @@
 
     serialized = operation.input.serialize(
         arg1='ah1', arg2='ah2', _soapheaders=[auth_header])
-    serialized = operation.input.serialize(
-        arg1='ah1', arg2='ah2', _soapheaders=[auth_header])
     expected = """
         <?xml version="1.0"?>
         <soap-env:Envelope
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_wsdl_no_output_message_part.py 
new/zeep-3.2.0/tests/test_wsdl_no_output_message_part.py
--- old/zeep-3.1.0/tests/test_wsdl_no_output_message_part.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/zeep-3.2.0/tests/test_wsdl_no_output_message_part.py    2018-12-07 
21:23:22.000000000 +0100
@@ -0,0 +1,56 @@
+from six import StringIO
+from zeep.wsdl import wsdl
+
+
+def test_wsdl_parses_operations_with_no_output():
+
+    wsdl_content = StringIO("""
+    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/";
+                 xmlns:tns="http://tests.python-zeep.org/tns";
+                 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
+                 xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+                 targetNamespace="http://tests.python-zeep.org/tns";>
+      <types>
+        <xsd:schema targetNamespace="http://tests.python-zeep.org/tns";>
+          <xsd:element name="Request" type="xsd:string"/>
+          <xsd:element name="Response" type="xsd:string"/>
+        </xsd:schema>
+      </types>
+
+      <message name="Input">
+        <part element="tns:Request"/>
+      </message>
+      <message name="Output">
+        <part element="tns:Response"/>
+      </message>
+
+      <portType name="TestPortType">
+        <operation name="TestOperation">
+          <input message="Input"/>
+        </operation>
+      </portType>
+
+      <binding name="TestBinding" type="tns:TestPortType">
+        <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="TestOperation">
+          <soap:operation soapAction=""/>
+          <input>
+            <soap:body use="literal"/>
+          </input>
+          <output>
+            <soap:body use="literal"/>
+          </output>
+        </operation>
+      </binding>
+    </definitions>
+    """)
+    # parse the content
+    root = wsdl.Document(wsdl_content, None)
+
+    binding = root.bindings['{http://tests.python-zeep.org/tns}TestBinding']
+    operation = binding.get('TestOperation')
+    # General assertions on the input
+    assert operation.input.body.signature(schema=root.types) == 
'ns0:Request(xsd:string)'
+    assert operation.input.header.signature(schema=root.types) == 
'soap-env:Header()'
+    assert operation.input.envelope.signature(schema=root.types) == 
'soap-env:envelope(body: xsd:string)'
+    assert operation.input.signature(as_output=False) == 'xsd:string'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_wsse_signature.py 
new/zeep-3.2.0/tests/test_wsse_signature.py
--- old/zeep-3.1.0/tests/test_wsse_signature.py 2017-11-04 09:15:21.000000000 
+0100
+++ new/zeep-3.2.0/tests/test_wsse_signature.py 2018-11-18 10:08:17.000000000 
+0100
@@ -16,9 +16,14 @@
 KEY_FILE_PW = os.path.join(
     os.path.dirname(os.path.realpath(__file__)), 'cert_valid_pw.pem')
 
+# Check whether xmlsec library has been installed
+from zeep.wsse.signature import xmlsec as xmlsec_installed
+skip_if_no_xmlsec = pytest.mark.skipif(sys.platform == 'win32',
+                                       reason="does not run on windows") and \
+                    pytest.mark.skipif(xmlsec_installed is None,
+                                       reason="xmlsec library not installed")
 
[email protected](sys.platform == 'win32',
-                    reason="does not run on windows")
+@skip_if_no_xmlsec
 def test_sign():
     envelope = load_xml("""
         <soapenv:Envelope
@@ -39,8 +44,7 @@
     signature.verify_envelope(envelope, KEY_FILE)
 
 
[email protected](sys.platform == 'win32',
-                    reason="does not run on windows")
+@skip_if_no_xmlsec
 def test_sign_pw():
     envelope = load_xml("""
         <soapenv:Envelope
@@ -61,8 +65,7 @@
     signature.verify_envelope(envelope, KEY_FILE_PW)
 
 
[email protected](sys.platform == 'win32',
-                    reason="does not run on windows")
+@skip_if_no_xmlsec
 def test_verify_error():
     envelope = load_xml("""
         <soapenv:Envelope
@@ -89,8 +92,7 @@
         signature.verify_envelope(envelope, KEY_FILE)
 
 
[email protected](sys.platform == 'win32',
-                    reason="does not run on windows")
+@skip_if_no_xmlsec
 def test_signature():
     envelope = load_xml("""
         <soapenv:Envelope
@@ -110,3 +112,26 @@
     plugin = wsse.Signature(KEY_FILE_PW, KEY_FILE_PW, 'geheim')
     envelope, headers = plugin.apply(envelope, {})
     plugin.verify(envelope)
+
+
[email protected](sys.platform == 'win32',
+                    reason="does not run on windows")
+def test_signature_binary():
+    envelope = load_xml("""
+        <soapenv:Envelope
+            xmlns:tns="http://tests.python-zeep.org/";
+            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";
+            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/";
+            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";>
+          <soapenv:Header></soapenv:Header>
+          <soapenv:Body>
+            <tns:Function>
+              <tns:Argument>OK</tns:Argument>
+            </tns:Function>
+          </soapenv:Body>
+        </soapenv:Envelope>
+    """)
+
+    plugin = wsse.BinarySignature(KEY_FILE_PW, KEY_FILE_PW, 'geheim')
+    envelope, headers = plugin.apply(envelope, {})
+    plugin.verify(envelope)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_wsse_username.py 
new/zeep-3.2.0/tests/test_wsse_username.py
--- old/zeep-3.1.0/tests/test_wsse_username.py  2017-09-29 17:24:42.000000000 
+0200
+++ new/zeep-3.2.0/tests/test_wsse_username.py  2018-12-07 21:40:00.000000000 
+0100
@@ -1,13 +1,13 @@
 import datetime
 import os
-
 import pytest
 import requests_mock
-from freezegun import freeze_time
 
+from freezegun import freeze_time
 from tests.utils import assert_nodes_equal, load_xml
 from zeep import client
 from zeep.wsse import UsernameToken
+from zeep.wsse.utils import WSU
 
 
 @pytest.mark.requests
@@ -236,3 +236,67 @@
         </soap-env:Envelope>
     """  # noqa
     assert_nodes_equal(envelope, expected)
+
+
+def test_timestamp_token():
+    envelope = load_xml("""
+            <soap-env:Envelope
+                xmlns:ns0="http://example.com/stockquote.xsd";
+                xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
+                xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/";
+                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";
+                xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility";
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+            >
+              <soap-env:Header 
xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";>
+                <ns0:Security>
+                  <ns0:UsernameToken/>
+                </ns0:Security>
+              </soap-env:Header>
+              <soap-env:Body>
+                <ns0:TradePriceRequest>
+                  <tickerSymbol>foobar</tickerSymbol>
+                  <ns0:country/>
+                </ns0:TradePriceRequest>
+              </soap-env:Body>
+            </soap-env:Envelope>
+        """)  # noqa
+
+    timestamp_token = WSU.Timestamp()
+    timestamp_token.attrib['Id'] = 'id-21a27a50-9ebf-49cc-96bf-fcf7131e7858'
+    some_date_obj = datetime.datetime(2018, 11, 18, 15, 44, 27, 440252)
+    timestamp_elements = 
[WSU.Created(some_date_obj.strftime("%Y-%m-%dT%H:%M:%SZ")),
+                          WSU.Expires((some_date_obj + 
datetime.timedelta(minutes=10)).strftime("%Y-%m-%dT%H:%M:%SZ"))]
+    timestamp_token.extend(timestamp_elements)
+
+    token = UsernameToken('Vishu', 'Guntupalli', 
timestamp_token=timestamp_token)
+    envelope, headers = token.apply(envelope, {})
+    expected = """
+            <soap-env:Envelope
+                xmlns:ns0="http://example.com/stockquote.xsd";
+                xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/";
+                xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/";
+                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/";
+                xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility";
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
+              <soap-env:Header 
xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";>
+                <ns0:Security>
+                  <ns0:UsernameToken>
+                    <ns0:Username>Vishu</ns0:Username>
+                    <ns0:Password 
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";>Guntupalli</ns0:Password>
+                  </ns0:UsernameToken>
+                  <wsu:Timestamp 
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
 Id="id-21a27a50-9ebf-49cc-96bf-fcf7131e7858">
+                       <wsu:Created>2018-11-18T15:44:27Z</wsu:Created>
+                       <wsu:Expires>2018-11-18T15:54:27Z</wsu:Expires>
+                  </wsu:Timestamp>
+                </ns0:Security>
+              </soap-env:Header>
+              <soap-env:Body>
+                <ns0:TradePriceRequest>
+                  <tickerSymbol>foobar</tickerSymbol>
+                  <ns0:country/>
+                </ns0:TradePriceRequest>
+              </soap-env:Body>
+            </soap-env:Envelope>
+        """  # noqa
+    assert_nodes_equal(envelope, expected)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_xsd_builtins.py 
new/zeep-3.2.0/tests/test_xsd_builtins.py
--- old/zeep-3.1.0/tests/test_xsd_builtins.py   2018-05-12 12:06:55.000000000 
+0200
+++ new/zeep-3.2.0/tests/test_xsd_builtins.py   2018-12-17 09:25:21.000000000 
+0100
@@ -131,6 +131,9 @@
         value = value.astimezone(pytz.timezone('Europe/Amsterdam'))
         assert instance.xmlvalue(value) == '2016-03-04T22:14:42+01:00'
 
+        assert instance.xmlvalue('2016-03-04T22:14:42+01:00') == 
'2016-03-04T22:14:42+01:00'
+        assert instance.xmlvalue('2016-03-04') == '2016-03-04'
+
     def test_pythonvalue(self):
         instance = builtins.DateTime()
         value = datetime.datetime(2016, 3, 4, 21, 14, 42)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_xsd_complex_types.py 
new/zeep-3.2.0/tests/test_xsd_complex_types.py
--- old/zeep-3.1.0/tests/test_xsd_complex_types.py      2018-05-11 
09:16:20.000000000 +0200
+++ new/zeep-3.2.0/tests/test_xsd_complex_types.py      2018-12-07 
21:38:28.000000000 +0100
@@ -2,7 +2,7 @@
 from lxml import etree
 
 from tests.utils import assert_nodes_equal, load_xml, render_node
-from zeep import xsd
+from zeep import exceptions, xsd
 
 
 def test_xml_xml_single_node():
@@ -330,3 +330,56 @@
 
     obj = container_elm.parse(result[0], schema)
     assert obj._value_1 is None
+
+
+def test_ignore_sequence_order():
+    schema_doc = load_xml(b"""
+        <?xml version="1.0" encoding="utf-8"?>
+        <xsd:schema xmlns:tns="http://tests.python-zeep.org/attr";
+          xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+          elementFormDefault="qualified"
+          targetNamespace="http://tests.python-zeep.org/attr";>
+          <xsd:complexType name="Result">
+            <xsd:attribute name="id" type="xsd:int" use="required"/>
+          </xsd:complexType>
+          <xsd:element name="Response">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element minOccurs="0" maxOccurs="1" name="Foo" 
type="tns:Result"/>
+                <xsd:element minOccurs="0" maxOccurs="1" name="Bar" 
type="tns:Result"/>
+                <xsd:element minOccurs="0" maxOccurs="1" name="Baz" 
type="tns:Result"/>
+              </xsd:sequence>
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:schema>
+    """)
+
+    response_doc = load_xml(b"""
+        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/";>
+          <s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
+            <Response xmlns="http://tests.python-zeep.org/attr";>
+                <Foo id="1"/>
+                <Baz id="3"/>
+                <Bar id="2"/>
+            </Response>
+          </s:Body>
+        </s:Envelope>
+    """)
+
+    schema = xsd.Schema(schema_doc)
+    elm = schema.get_element('{http://tests.python-zeep.org/attr}Response')
+    schema.settings.xsd_ignore_sequence_order = False
+
+    node = response_doc.xpath(
+        '//ns0:Response', namespaces={
+            'xsd': 'http://www.w3.org/2001/XMLSchema',
+            'ns0': 'http://tests.python-zeep.org/attr',
+        })
+    with pytest.raises(exceptions.XMLParseError) as exc:
+        response = elm.parse(node[0], schema)
+    assert str(exc) is not None
+
+    schema.settings.xsd_ignore_sequence_order = True
+
+    response = elm.parse(node[0], schema)
+    assert response.Baz.id == 3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zeep-3.1.0/tests/test_xsd_indicators_choice.py 
new/zeep-3.2.0/tests/test_xsd_indicators_choice.py
--- old/zeep-3.1.0/tests/test_xsd_indicators_choice.py  2018-05-12 
10:46:19.000000000 +0200
+++ new/zeep-3.2.0/tests/test_xsd_indicators_choice.py  2018-12-03 
17:52:42.000000000 +0100
@@ -308,6 +308,50 @@
     assert result.item_1 == 'foo'
 
 
+def test_choice_element_with_only_any():
+    node = etree.fromstring("""
+        <?xml version="1.0"?>
+        <xsd:schema
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema";
+                xmlns:tns="http://tests.python-zeep.org/";
+                elementFormDefault="qualified"
+                targetNamespace="http://tests.python-zeep.org/";>
+          <xsd:element name="container">
+            <xsd:complexType>
+              <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                <xsd:any processContents="lax"/>
+              </xsd:choice>
+              <xsd:attribute name="name" type="xsd:QName" use="required" />
+              <xsd:attribute name="something" type="xsd:boolean" 
use="required" />
+              <xsd:anyAttribute namespace="##other" processContents="lax"/>
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="item_1" type="xsd:string" />
+        </xsd:schema>
+    """.strip())
+    schema = xsd.Schema(node)
+    element = schema.get_element('ns0:container')
+    item_1 = schema.get_element('ns0:item_1')
+    any_object = xsd.AnyObject(item_1, item_1('foo'))
+    value = element(_value_1=[any_object], name="foo", something="bar")
+
+    expected = """
+      <document>
+        <ns0:container xmlns:ns0="http://tests.python-zeep.org/"; name="foo" 
something="true">
+          <ns0:item_1>foo</ns0:item_1>
+        </ns0:container>
+      </document>
+    """
+    node = etree.Element('document')
+    element.render(node, value)
+    assert_nodes_equal(expected, node)
+
+    result = element.parse(node[0], schema)
+    assert result.name == 'foo'
+    assert result.something is True
+    assert result._value_1 == ['foo']
+
+
 def test_choice_element_with_any_max_occurs():
     schema = xsd.Schema(load_xml("""
         <schema targetNamespace="http://tests.python-zeep.org/";


Reply via email to