[Git][debian-gis-team/owslib][master] 5 commits: New upstream version 0.17.1

Bas Couwenberg gitlab at salsa.debian.org
Sun Jan 13 08:37:49 GMT 2019


Bas Couwenberg pushed to branch master at Debian GIS Project / owslib


Commits:
6a418982 by Bas Couwenberg at 2019-01-13T08:18:32Z
New upstream version 0.17.1
- - - - -
283445b0 by Bas Couwenberg at 2019-01-13T08:18:35Z
Merge tag 'upstream/0.17.1'

Upstream version 0.17.1

- - - - -
28858721 by Bas Couwenberg at 2019-01-13T08:19:01Z
New upstream release.

- - - - -
e0fa879f by Bas Couwenberg at 2019-01-13T08:29:27Z
Update copyright holders.

- - - - -
fb6e6c27 by Bas Couwenberg at 2019-01-13T08:30:27Z
Set distribution to unstable.

- - - - -


28 changed files:

- MANIFEST.in
- README.rst
- VERSION.txt
- debian/changelog
- debian/copyright
- docs/en/index.rst
- examples/wps-birdhouse.py
- owslib/__init__.py
- + owslib/feature/wfs300.py
- owslib/map/wms111.py
- owslib/map/wms130.py
- owslib/wfs.py
- owslib/wps.py
- requirements-dev.txt
- + tests/resources/wps_EmuDescribeProcess_all.xml
- tests/resources/wps_EmuExecuteRequest7.xml
- + tests/test_wfs3_ldproxy.py
- + tests/test_wfs3_pygeoapi.py
- tests/test_wms_getmap.py
- tests/test_wps.py
- tests/test_wps_describeprocess_ceda.py
- + tests/test_wps_describeprocess_emu_all.py
- tests/test_wps_request10.py
- tests/test_wps_request2.py
- tests/test_wps_request3.py
- tests/test_wps_request4.py
- tests/test_wps_request7.py
- tests/utils.py


Changes:

=====================================
MANIFEST.in
=====================================
@@ -1,3 +1,4 @@
 include *.txt
+include LICENSE
 include *.rst
 recursive-include owslib


=====================================
README.rst
=====================================
@@ -121,6 +121,26 @@ configure your application to use the log messages like so:
     >>> # Add formatting and handlers as needed
     >>> owslib_log.setLevel(logging.DEBUG)
 
+Releasing
+---------
+
+.. code-block:: bash
+
+  # update version
+  vi VERSION.txt
+  vi owslib/__init__.py
+  git commit -m 'update release version' VERSION.txt owslib/__init__.py
+  # push changes
+  git push origin master
+  git tag -a x.y.z -m 'tagging OWSLib release x.y.z'
+  # push tag
+  git push --tags
+  # update live docs
+  cd docs
+  make html
+  ./publish.sh
+  # update on PyPI (must be a maintainer)
+  python setup.py sdist upload
 
 Support
 -------


=====================================
VERSION.txt
=====================================
@@ -1 +1 @@
-0.17.0
+0.17.1


=====================================
debian/changelog
=====================================
@@ -1,8 +1,11 @@
-owslib (0.17.0-2) UNRELEASED; urgency=medium
+owslib (0.17.1-1) unstable; urgency=medium
 
+  * Team upload.
+  * New upstream release.
   * Bump Standards-Version to 4.3.0, no changes.
+  * Update copyright holders.
 
- -- Bas Couwenberg <sebastic at debian.org>  Tue, 25 Dec 2018 22:52:37 +0100
+ -- Bas Couwenberg <sebastic at debian.org>  Sun, 13 Jan 2019 09:30:10 +0100
 
 owslib (0.17.0-1) unstable; urgency=medium
 


=====================================
debian/copyright
=====================================
@@ -4,41 +4,23 @@ Upstream-Name: OWSLib
 Source: https://github.com/geopython/owslib
 
 Files: *
-Copyright: 2006-2016 OWSLib Contributors
- * Sean Gillies <sgillies at frii.com>
- * Julien Anguenot <ja at nuxeo.com>
- * Kai Lautaportti <kai.lautaportti at hexagonit.fi>
- * Dominic Lowe <D.Lowe at rl.ac.uk>
- * Jo Walsh <jo at frot.org>
- * Tom Kralidis <tomkralidis at gmail.com>
- * Jachym Cepicky <jachym.cepicky at gmail.com>
- * Luca Cinquini <luca.cinquini at jpl.nasa.gov>
- * Brad Hards <bradh at frogmouth.net>
- * Christian Ledermann <christian.ledermann at gmail.com>
- * Sean Cowan <scowan at asascience.com>
- * Kyle Wilcox <wilcox.kyle at gmail.com>
- * Angelos Tzotsos <gcpp.kalxas at gmail.com>
- * Brian Miles <selimnairb at gmail.com>
- * Eliott Sales de Andrade
- * David Blodgett <dblodgett at usgs.gov>
- * Thomas Kluyver
- * Kai Lautaportti
- * Richard Hattersley
- * Christian Ledermann <christian.ledermann at gmail.com>
- * Luke Campbell <luke.s.campbell at gmail.com>
- * Luís de Sousa <luis.a.de.sousa at gmail.com>
- * Julien Enselme <jujens+github at jujens.eu>
- * Dave Foster <dave.foster at gmail.com>
- * Nuxeo SARL <http://nuxeo.com>
- * STFC <http://www.stfc.ac.uk>
- * Pete Taylor
+Copyright:              2005, Nuxeo SARL <http:nuxeo.com>
+                   2004-2006, Sean C. Gillies
+                        2006, Ancient World Mapping Center
+                  2007, 2009, STFC <http:www.stfc.ac.uk>
+                        2012, Brad Hards <bradh at frogmouth.net>
+                        2013, Christian Ledermann <christian.ledermann at gmail.com>
+                        2014, Pete Taylor
+                  2012, 2015, Jachym Cepicky
+                        2015, Luís de Sousa
+ 2008-2011, 2013, 2015, 2018, Tom Kralidis
+                        2018, Luca Cinquini
 License: BSD-3-Clause
 
 Files: debian/*
-Copyright: 2014-2016
- * Angelos Tzotsos <gcpp.kalxas at gmail.com>
- * Johan Van de Wauw <johan.vandewauw at gmail.com>
- * Bas Couwenberg <sebastic at xs4all.nl>
+Copyright: 2014-2016, Angelos Tzotsos <gcpp.kalxas at gmail.com>
+           2014-2016, Johan Van de Wauw <johan.vandewauw at gmail.com>
+           2014-2016, Bas Couwenberg <sebastic at xs4all.nl>
 License: BSD-3-Clause
 
 License: BSD-3-Clause
@@ -65,4 +47,3 @@ License: BSD-3-Clause
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.
-


=====================================
docs/en/index.rst
=====================================
@@ -34,7 +34,7 @@ Standards Support
 +===================+=====================+
 | `OGC WMS`_        | 1.1.1               |
 +-------------------+---------------------+
-| `OGC WFS`_        | 1.0.0, 1.1.0, 2.0.0 |
+| `OGC WFS`_        | 1.0.0, 1.1.0, 2.0.0, 3.0 |
 +-------------------+---------------------+
 | `OGC WCS`_        | 1.0.0, 1.1.0        |
 +-------------------+---------------------+
@@ -285,6 +285,35 @@ services)
 
     >>> response = wfs20.getfeature(storedQueryID='urn:ogc:def:query:OGC-WFS::GetFeatureById', storedQueryParams={'ID':'gmd_ex.1'})
 
+WFS 3.0
+-------
+
+WFS 3.0 is a clean break from the traditional OGC service architecture
+(RESTful, JSON, OpenAPI) and as such OWSLib the code follows the same pattern.
+
+.. code-block:: python
+
+  >>> from owslib.wfs import WebFeatureService
+  >>> w = WebFeatureService('https://geo.kralidis.ca/pygeoapi, version='3.0')
+  >>> w.url
+  'http://geo.kralidis.ca/pygeoapi/'
+  >>> w.version
+  '3.0'
+  >>> conformance = w.conformance()
+  {u'conformsTo': [u'http://www.opengis.net/spec/wfs-1/3.0/req/core', u'http://www.opengis.net/spec/wfs-1/3.0/req/oas30', u'http://www.opengis.net/spec/wfs-1/3.0/req/html', u'http://www.opengis.net/spec/wfs-1/3.0/req/geojson']}
+  >>> collections = w.collections()
+  >>> len(collections)
+  3
+  >>> lakes = w.collection('lakes')
+  >>> lakes['name']
+  'lakes'
+  >>> lakes['title']
+  'Large Lakes'
+  >>> lakes['description']
+  'lakes of the world, public domain'
+  >>> lakes_query = w.collection_items('lakes')
+  >>> lakes_query['features'][0]['properties']
+  {u'scalerank': 0, u'name_alt': None, u'admin': None, u'featureclass': u'Lake', u'id': 0, u'name': u'Lake Baikal'}
 
 WCS
 ---


=====================================
examples/wps-birdhouse.py
=====================================
@@ -16,8 +16,9 @@ def multiple_outputs():
 
     processid = 'dummyprocess'
     inputs = [("input1", '1'), ("input2", '2')]
-    # list of tuple (output identifier, asReference attribute)
-    outputs = [("output1",True), ("output2",False)]
+    # list of tuple (output identifier, asReference attribute, mimeType attribute)
+    # when asReference or mimeType is None - the wps service will use its default option
+    outputs = [("output1",True,'some/mime-type'), ("output2",False,None)]
 
     execution = wps.execute(processid, inputs, output=outputs)
     monitorExecution(execution)
@@ -47,8 +48,9 @@ def complex_input_with_reference():
     processid = 'wordcount'
     textdoc = ComplexDataInput("http://www.gutenberg.org/files/28885/28885-h/28885-h.htm")   # alice in wonderland
     inputs = [("text", textdoc)]
-    # list of tuple (output identifier, asReference attribute)
-    outputs = [("output",True)]
+    # list of tuple (output identifier, asReference attribute, mimeType attribute)
+    # when asReference or mimeType is None - the wps service will use its default option
+    outputs = [("output",True,'some/mime-type')]
 
     execution = wps.execute(processid, inputs, output=outputs)
     monitorExecution(execution)
@@ -72,8 +74,9 @@ def complex_input_with_content():
     processid = 'wordcount'
     textdoc = ComplexDataInput("ALICE was beginning to get very tired ...")   # alice in wonderland
     inputs = [("text", textdoc)]
-    # list of tuple (output identifier, asReference attribute)
-    outputs = [("output",True)]
+    # list of tuple (output identifier, asReference attribute, mimeType attribute)
+    # when asReference or mimeType is None - the wps service will use its default option
+    outputs = [("output",True,'some/mime-type')]
 
     execution = wps.execute(processid, inputs, output=outputs)
     monitorExecution(execution)


=====================================
owslib/__init__.py
=====================================
@@ -1,3 +1,3 @@
 from __future__ import (absolute_import, division, print_function)
 
-__version__ = '0.17.0'
+__version__ = '0.17.1'


=====================================
owslib/feature/wfs300.py
=====================================
@@ -0,0 +1,166 @@
+# =============================================================================
+# Copyright (c) 2018 Tom Kralidis
+#
+# Authors : Tom Kralidis <tomkralidis at gmail.com>
+#
+# Contact email: tomkralidis at gmail.com
+# =============================================================================
+
+import json
+import logging
+
+from six.moves.urllib.parse import urljoin
+import requests
+
+from owslib import __version__
+
+LOGGER = logging.getLogger(__name__)
+
+REQUEST_HEADERS = {
+    'User-Agent': 'OWSLib {} (https://geopython.github.io/OWSLib)'.format(
+        __version__)
+}
+
+
+class WebFeatureService_3_0_0(object):
+    """Abstraction for OGC Web Feature Service (WFS) version 3.0"""
+    def __init__(self, url, version, json_, timeout=30, username=None,
+                 password=None):
+        """
+        initializer; implements Requirement 1 (/req/core/root-op)
+
+        @type url: string
+        @param url: url of WFS root document
+        @type json_: string
+        @param json_: json object
+        @param timeout: time (in seconds) after which requests should timeout
+        @param username: service authentication username
+        @param password: service authentication password
+
+        @return: initialized WebFeatureService_3_0_0 object
+        """
+
+        if '?' in url:
+            self.url, self.url_query_string = url.split('?')
+        else:
+            self.url = url.rstrip('/') + '/'
+            self.url_query_string = None
+
+        self.version = version
+        self.json_ = json_
+        self.timeout = timeout
+        self.username = username
+        self.password = password
+
+        if json_ is not None:  # static JSON string
+            self.links = json.loads(json_)['links']
+        else:
+            response = requests.get(url, headers=REQUEST_HEADERS).json()
+            self.links = response['links']
+
+    def conformance(self):
+        """
+        implements Requirement 5 (/req/core/conformance-op)
+
+        @returns: conformance object
+        """
+
+        url = self._build_url('conformance')
+        LOGGER.debug('Request: {}'.format(url))
+        response = requests.get(url, headers=REQUEST_HEADERS).json()
+        return response
+
+    def collections(self):
+        """
+        implements Requirement 9 (/req/core/collections-op)
+
+        @returns: collections object
+        """
+
+        url = self._build_url('collections')
+        LOGGER.debug('Request: {}'.format(url))
+        response = requests.get(url, headers=REQUEST_HEADERS).json()
+        return response['collections']
+
+    def collection(self, collection_name):
+        """
+        implements Requirement 15 (/req/core/sfc-md-op)
+
+        @type collection_name: string
+        @param collection_name: name of collection
+
+        @returns: feature collection metadata
+        """
+
+        path = 'collections/{}'.format(collection_name)
+        url = self._build_url(path)
+        LOGGER.debug('Request: {}'.format(url))
+        response = requests.get(url, headers=REQUEST_HEADERS).json()
+        return response
+
+    def collection_items(self, collection_name, **kwargs):
+        """
+        implements Requirement 17 (/req/core/fc-op)
+
+        @type collection_name: string
+        @param collection_name: name of collection
+        @type bbox: list
+        @param bbox: list of minx,miny,maxx,maxy
+        @type time: string
+        @param time: time extent or time instant
+        @type limit: int
+        @param limit: limit number of features
+        @type startindex: int
+        @param startindex: start position of results
+
+        @returns: feature results
+        """
+
+        if 'bbox' in kwargs:
+            kwargs['bbox'] = ','.join(kwargs['bbox'])
+
+        path = 'collections/{}/items'.format(collection_name)
+        url = self._build_url(path)
+        LOGGER.debug('Request: {}'.format(url))
+        response = requests.get(url, headers=REQUEST_HEADERS,
+                                params=kwargs).json()
+        return response
+
+    def collection_item(self, collection_name, identifier):
+        """
+        implements Requirement 30 (/req/core/f-op)
+
+        @type collection_name: string
+        @param collection_name: name of collection
+        @type identifier: string
+        @param identifier: feature identifier
+
+        @returns: single feature result
+        """
+
+        path = 'collections/{}/items/{}'.format(collection_name, identifier)
+        url = self._build_url(path)
+        LOGGER.debug('Request: {}'.format(url))
+        response = requests.get(url, headers=REQUEST_HEADERS).json()
+        return response
+
+    def _build_url(self, path=None):
+        """
+        helper function to build a WFS 3.0 URL
+
+        @type path: string
+        @param path: path of WFS URL
+
+        @returns: fully constructed URL path
+        """
+
+        url = self.url
+        if self.url_query_string is not None:
+            LOGGER.debug('base URL has a query string')
+            url = urljoin(url, path)
+            url = '?'.join([url, self.url_query_string])
+        else:
+            url = urljoin(url, path)
+
+        LOGGER.debug('URL: {}'.format(url))
+        return url


=====================================
owslib/map/wms111.py
=====================================
@@ -269,7 +269,7 @@ class WebMapService_1_1_1(object):
         u = openURL(base_url, data, method, username=self.username, password=self.password, timeout=timeout or self.timeout)
 
         # check for service exceptions, and return
-        if u.info()['Content-Type'].split(';')[0] in ['application/vnd.ogc.se_xml']:
+        if u.info().get('Content-Type', '').split(';')[0] in ['application/vnd.ogc.se_xml']:
             se_xml = u.read()
             se_tree = etree.fromstring(se_xml)
             err_message = six.text_type(se_tree.find('ServiceException').text).strip()
@@ -377,7 +377,10 @@ class ServiceProvider(object):
             self.name=name.text
         else:
             self.name=None
-        self.url=self._root.find('OnlineResource').attrib.get('{http://www.w3.org/1999/xlink}href', '')
+        self.url = None
+        online_resource = self._root.find('OnlineResource')
+        if online_resource is not None:
+            self.url = online_resource.attrib.get('{http://www.w3.org/1999/xlink}href', '')
         #contact metadata
         contact = self._root.find('ContactInformation')
         ## sometimes there is a contact block that is empty, so make


=====================================
owslib/map/wms130.py
=====================================
@@ -315,7 +315,7 @@ class WebMapService_1_3_0(object):
             headers[k.lower()] = v
 
         # handle the potential charset def
-        if headers['content-type'].split(';')[0] in ['application/vnd.ogc.se_xml', 'text/xml']:
+        if headers.get('content-type', '').split(';')[0] in ['application/vnd.ogc.se_xml', 'text/xml']:
             se_xml = u.read()
             se_tree = etree.fromstring(se_xml)
             err_message = six.text_type(se_tree.find(nspath('ServiceException', OGC_NAMESPACE)).text).strip()
@@ -411,7 +411,10 @@ class ServiceProvider(object):
             self.name = name.text
         else:
             self.name = None
-        self.url = self._root.find(nspath('OnlineResource', WMS_NAMESPACE)).attrib.get('{http://www.w3.org/1999/xlink}href', '')
+        self.url = None
+        online_resource = self._root.find(nspath('OnlineResource', WMS_NAMESPACE))
+        if online_resource is not None:
+            self.url = online_resource.attrib.get('{http://www.w3.org/1999/xlink}href', '')
         # contact metadata
         contact = self._root.find(nspath('ContactInformation', WMS_NAMESPACE))
         # sometimes there is a contact block that is empty, so make


=====================================
owslib/wfs.py
=====================================
@@ -15,12 +15,13 @@ Web Feature Server (WFS) methods and metadata. Factory function.
 
 from __future__ import (absolute_import, division, print_function)
 
-from .feature import wfs100, wfs110, wfs200
+from .feature import wfs100, wfs110, wfs200, wfs300
 from .util import clean_ows_url
 
 
-def WebFeatureService(url, version='1.0.0', xml=None, parse_remote_metadata=False,
-                      timeout=30, username=None, password=None):
+def WebFeatureService(url, version='1.0.0', xml=None, json_=None,
+                      parse_remote_metadata=False, timeout=30, username=None,
+                      password=None):
     ''' wfs factory function, returns a version specific WebFeatureService object
 
     @type url: string
@@ -32,7 +33,7 @@ def WebFeatureService(url, version='1.0.0', xml=None, parse_remote_metadata=Fals
     @param timeout: time (in seconds) after which requests should timeout
     @param username: service authentication username
     @param password: service authentication password
-    @return: initialized WebFeatureService_2_0_0 object
+    @return: initialized WebFeatureService object (version dependent)
     '''
 
     clean_url = clean_ows_url(url)
@@ -52,3 +53,8 @@ def WebFeatureService(url, version='1.0.0', xml=None, parse_remote_metadata=Fals
                                               timeout=timeout,
                                               username=username,
                                               password=password)
+    elif version in ['3.0', '3.0.0']:
+        return wfs300.WebFeatureService_3_0_0(clean_url, version, json_,
+                                              timeout=timeout,
+                                              username=username,
+                                              password=password)


=====================================
owslib/wps.py
=====================================
@@ -121,6 +121,7 @@ try:                    # Python 3
 except ImportError:     # Python 2
     from urlparse import urlparse
 
+import six
 # namespace definition
 n = Namespaces()
 
@@ -160,7 +161,7 @@ def is_reference(val):
     """
     try:
         parsed = urlparse(val)
-        is_ref = parsed.scheme != ''
+        is_ref = bool(parsed.scheme)
     except Exception:
         is_ref = False
     return is_ref
@@ -270,7 +271,9 @@ class WebProcessingService(object):
     def describeprocess(self, identifier, xml=None):
         """
         Requests a process document from a WPS service and populates the process metadata.
-        Returns the process object.
+        Returns the process object or a list of process objects.
+
+        :param str identifier: The process id. If `all`, return a list of all processes available.
         """
 
         # read capabilities document
@@ -287,7 +290,12 @@ class WebProcessingService(object):
         log.info(element_to_string(rootElement))
 
         # build metadata objects
-        return self._parseProcessMetadata(rootElement)
+        processes = self._parseProcessMetadata(rootElement)
+
+        if identifier == 'all':
+            return processes
+        else:
+            return processes[0]
 
     def execute(self, identifier, inputs, output=None, mode=ASYNC, lineage=False, request=None, response=None):
         """
@@ -296,10 +304,12 @@ class WebProcessingService(object):
         retrieve the result.
 
         :param str identifier: the requested process identifier
-        :param inputs: list of process inputs as (key, value) tuples (where value is either a string for LiteralData, or
-                an object for ComplexData)
-        :param output: optional identifier for process output reference (if not provided, output will be
-                embedded in the response)
+        :param inputs: list of process inputs as (input_identifier, value) tuples (where value is either a string
+                for LiteralData, or an object for ComplexData).
+        :param output: optional list of process outputs as tuples (output_identifier, as_ref, mime_type).
+                `as_ref` can be True (as reference),
+                False (embedded in response) or None (use service default).
+                `mime_type` should be text or None (use service default)
         :param mode: execution mode: SYNC, ASYNC or AUTO. Default: ASYNC
         :param lineage: if lineage is "true", the Execute operation response shall include the DataInputs and
                  OutputDefinitions elements.
@@ -341,27 +351,29 @@ class WebProcessingService(object):
         raise KeyError("No operation named %s" % name)
 
     def _parseProcessMetadata(self, rootElement):
-        """
-        Method to parse a <ProcessDescriptions> XML element and returned the constructed Process object
-        """
+        """Return a list of Process objects parsed from a <ProcessDescriptions> XML element."""
+
+        processDescriptionElements = rootElement.findall('ProcessDescription')
+        processes = []
+        for processDescriptionElement in processDescriptionElements:
+            process = Process(processDescriptionElement, verbose=self.verbose)
 
-        processDescriptionElement = rootElement.find('ProcessDescription')
-        process = Process(processDescriptionElement, verbose=self.verbose)
+            # override existing processes in object metadata, if existing already
+            found = False
+            for n, p in enumerate(self.processes):
+                if p.identifier == process.identifier:
+                    self.processes[n] = process
+                    found = True
+            # otherwise add it
+            if not found:
+                self.processes.append(process)
 
-        # override existing processes in object metadata, if existing already
-        found = False
-        for n, p in enumerate(self.processes):
-            if p.identifier == process.identifier:
-                self.processes[n] = process
-                found = True
-        # otherwise add it
-        if not found:
-            self.processes.append(process)
+            processes.append(process)
 
-        return process
+        return processes
 
     def _parseCapabilitiesMetadata(self, root):
-        ''' Sets up capabilities metadata objects '''
+        """Set up capabilities metadata objects."""
 
         # reset metdata
         self.operations = []
@@ -425,7 +437,6 @@ class WebProcessingService(object):
 
 
 class WPSReader(object):
-
     """
     Superclass for reading a WPS document into a lxml.etree infoset.
     """
@@ -550,7 +561,7 @@ class WPSExecuteReader(WPSReader):
                                  headers=headers, verify=verify, cert=cert)
 
 
-class WPSExecution():
+class WPSExecution(object):
 
     """
     Class that represents a single WPS process executed on a remote WPS service.
@@ -598,8 +609,9 @@ class WPSExecution():
               and the object must contain a 'getXml()' method that returns an XML infoset to be included in
               the WPS request
         :param output: array of outputs which should be returned:
-                expressed as tuples (key, as_ref) where key is the output identifier and as_ref is True
+                expressed as tuples (key, as_ref, mime_mype) where key is the output identifier and as_ref is True
                 if output should be returned as reference.
+                as_ref and mimeType may be null for using server's default value
         :param mode: execution mode: SYNC, ASYNC or AUTO.
         :param lineage: if lineage is "true", the Execute operation response shall include the DataInputs and
                  OutputDefinitions elements.
@@ -687,7 +699,7 @@ class WPSExecution():
 
         # <wps:ResponseForm>
         #   <wps:ResponseDocument storeExecuteResponse="true" status="true" lineage="false">
-        #     <wps:Output asReference="true">
+        #     <wps:Output asReference="true" mimeType="application/json">
         #       <ows:Identifier>OUTPUT</ows:Identifier>
         #     </wps:Output>
         #   </wps:ResponseDocument>
@@ -703,30 +715,38 @@ class WPSExecution():
                         'lineage': str(lineage).lower()})
             # keeping backward compability of output parameter
             if isinstance(output, str):
-                self._add_output(
-                    responseDocumentElement, output, asReference=True)
+                self._add_output(responseDocumentElement, output)
             elif isinstance(output, list):
-                for (identifier, as_reference) in output:
+                for ouputTuple in output:
+                    # tuple (identifier, as_reference) for backward compatibility
+                    if(len(ouputTuple) == 2):
+                        (identifier, as_reference) = ouputTuple
+                        mime_type = None
+                    else:
+                        (identifier, as_reference, mime_type) = ouputTuple
                     self._add_output(
-                        responseDocumentElement, identifier, asReference=as_reference)
+                        responseDocumentElement, identifier, asReference=as_reference, mimeType=mime_type)
             else:
                 raise Exception(
                     'output parameter is neither string nor list. output=%s' % output)
         return root
 
-    def _add_output(self, element, identifier, asReference=False):
-        outputElement = etree.SubElement(
-            element, nspath_eval('wps:Output', namespaces),
-            attrib={'asReference': str(asReference).lower()})
+    def _add_output(self, element, identifier, asReference=None, mimeType=None):
+        output_element = etree.SubElement(
+            element, nspath_eval('wps:Output', namespaces))
+        if isinstance(mimeType, str):
+            output_element.attrib['mimeType'] = mimeType
+        if isinstance(asReference, bool):
+            output_element.attrib['asReference'] = str(asReference).lower()
         # outputIdentifierElement
         etree.SubElement(
-            outputElement, nspath_eval('ows:Identifier', namespaces)).text = identifier
+            output_element, nspath_eval('ows:Identifier', namespaces)).text = identifier
 
     # wait for 60 seconds by default
     def checkStatus(self, url=None, response=None, sleepSecs=60):
         """
         Method to check the status of a job execution.
-        In the process, this method will upadte the object 'response' attribute.
+        In the process, this method will update the object 'response' attribute.
 
         :param str url: optional 'statusLocation' URL retrieved from a previous WPS Execute response document.
              If not provided, the current 'statusLocation' URL will be used.
@@ -923,11 +943,14 @@ class WPSExecution():
         element = root.find(nspath('Status', ns=wpsns))
         self.creationTime = testXMLAttribute(element, 'creationTime')
         # get progress info
-        try:
-            percentCompleted = int(statusEl.get('percentCompleted'))
-            self.percentCompleted = percentCompleted
-        except Exception:
-            pass
+        if self.status == 'ProcessSucceeded':
+            self.percentCompleted = 100
+        else:
+            try:
+                percentCompleted = int(statusEl.get('percentCompleted'))
+                self.percentCompleted = percentCompleted
+            except Exception:
+                pass
         # get status message
         self.statusMessage = statusEl.text
         # exceptions ?
@@ -1323,7 +1346,7 @@ class Output(InputOutput):
                 if literalDataElement.text is not None and literalDataElement.text.strip() is not '':
                     self.data.append(literalDataElement.text.strip())
             bboxDataElement = dataElement.find(nspath('BoundingBox', ns=namespaces['ows']))
-            if not bboxDataElement:
+            if bboxDataElement is not None:
                 # TODO: just a workaround for data-inputs in lineage
                 bboxDataElement = dataElement.find(nspath('BoundingBoxData', ns=namespaces['wps']))
             if bboxDataElement is not None:
@@ -1444,10 +1467,20 @@ class Process(object):
 
         wpsns = getNamespace(elem)
 
+        def get_bool_attribute(elem, attribute):
+            property = elem.get(attribute, '').lower()
+            if property == 'true':
+                value = True
+            elif property == 'false':
+                value = False
+            else:
+                value = None
+            return value
+
         # <ProcessDescription statusSupported="true" storeSupported="true" ns0:processVersion="1.0.0">
         self.processVersion = elem.get(nspath('processVersion', ns=wpsns))
-        self.statusSupported = bool(elem.get("statusSupported"))
-        self.storeSupported = bool(elem.get("storeSupported"))
+        self.statusSupported = get_bool_attribute(elem, "statusSupported")
+        self.storeSupported = get_bool_attribute(elem, "storeSupported")
         self.identifier = None
         self.title = None
         self.abstract = None
@@ -1581,8 +1614,14 @@ class ComplexDataInput(IComplexDataInput, ComplexData):
         """
            <wps:Reference xlink:href="http://somewhere/test.xml"/>
         """
-        refElement = etree.Element(nspath_eval('wps:Reference', namespaces),
-                                   attrib={nspath_eval("xlink:href", namespaces): self.value})
+        attrib = {nspath_eval("xlink:href", namespaces): self.value}
+        if self.encoding:
+            attrib['encoding'] = self.encoding
+        if self.schema:
+            attrib['schema'] = self.schema
+        if self.mimeType:
+            attrib['mimeType'] = self.mimeType
+        refElement = etree.Element(nspath_eval('wps:Reference', namespaces), attrib)
         return refElement
 
     def complexDataRaw(self):


=====================================
requirements-dev.txt
=====================================
@@ -1,6 +1,6 @@
 -r requirements.txt
 flake8
-pytest
+pytest>=3.6
 pytest-cov
 Pillow
 tox


=====================================
tests/resources/wps_EmuDescribeProcess_all.xml
=====================================
@@ -0,0 +1,928 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- PyWPS 4.3.dev0 -->
+<wps:ProcessDescriptions xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsDescribeProcess_response.xsd" service="WPS" version="1.0.0" xml:lang="en-US">
+    <ProcessDescription wps:processVersion="2.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>ultimate_question</ows:Identifier>
+        <ows:Title>Answer to the ultimate question</ows:Title>
+        <ows:Abstract>This process gives the answer to the ultimate question of "What is the meaning of life?"</ows:Abstract>
+        <ows:Metadata xlink:title="Ultimate Question" xlink:type="simple"
+        />
+        <ows:Metadata xlink:title="What is the meaning of life" xlink:type="simple"
+        />
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>answer</ows:Identifier>
+                <ows:Title>Answer to Ultimate Question</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>sleep</ows:Identifier>
+        <ows:Title>Sleep Process</ows:Title>
+        <ows:Abstract>Testing a long running process, in the sleep. This process will sleep for a given delay or 10 seconds if not a valid value.</ows:Abstract>
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="https://emu.readthedocs.io/en/latest/processes.html"
+        />
+        <ows:Metadata xlink:title="PyWPS Demo" xlink:type="simple"
+            xlink:href="https://pywps-demo.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>delay</ows:Identifier>
+                <ows:Title>Delay between every update</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>2.0</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>sleep_output</ows:Identifier>
+                <ows:Title>Sleep Output</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="false" statusSupported="false">
+        <ows:Identifier>nap</ows:Identifier>
+        <ows:Title>Afternoon Nap (supports sync calls only)</ows:Title>
+        <ows:Abstract>This process will have a short nap for a given delay or 1 second if not a valid value. This process only supports synchronous WPS requests... so, make sure the nap does not take to long.</ows:Abstract>
+        <ows:Metadata xlink:title="Birdhouse" xlink:type="simple"
+            xlink:href="http://bird-house.github.io/"
+        />
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>delay</ows:Identifier>
+                <ows:Title>Delay between every update</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>1.0</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Nap Output</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="0.2" storeSupported="true" statusSupported="true">
+        <ows:Identifier>bbox</ows:Identifier>
+        <ows:Title>Bounding box in- and out</ows:Title>
+        <ows:Abstract>Give bounding box, return the same</ows:Abstract>
+        <ows:Metadata xlink:title="Birdhouse" xlink:type="simple"
+            xlink:href="http://bird-house.github.io/"
+        />
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="0" maxOccurs="1">
+                <ows:Identifier>bbox</ows:Identifier>
+                <ows:Title>Bounding Box</ows:Title>
+                <ows:Abstract>Bounding Box Input.</ows:Abstract>
+                <BoundingBoxData>
+                    <Default>
+                        <CRS>epsg:4326</CRS>
+                    </Default>
+                    <Supported>
+                        <CRS>epsg:4326</CRS>
+                        <CRS>epsg:3035</CRS>
+                    </Supported>
+                </BoundingBoxData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>bbox</ows:Identifier>
+                <ows:Title>Bounding Box</ows:Title>
+                <ows:Abstract>Bounding Box Output.</ows:Abstract>
+                <BoundingBoxOutput>
+                    <Default>
+                        <CRS>epsg:4326</CRS>
+                    </Default>
+                    <Supported>
+                        <CRS>epsg:4326</CRS>
+                    </Supported>
+                </BoundingBoxOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.5" storeSupported="true" statusSupported="true">
+        <ows:Identifier>hello</ows:Identifier>
+        <ows:Title>Say Hello</ows:Title>
+        <ows:Abstract>Just says a friendly Hello. Returns a literal string output with Hello plus the inputed name.</ows:Abstract>
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="https://emu.readthedocs.io/en/latest/processes.html"
+        />
+        <ows:Metadata xlink:title="PyWPS Demo" xlink:type="simple"
+            xlink:href="https://pywps-demo.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>name</ows:Identifier>
+                <ows:Title>Your name</ows:Title>
+                <ows:Abstract>Please enter your name.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AnyValue />
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Output response</ows:Title>
+                <ows:Abstract>A friendly Hello from us.</ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="2.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>dummyprocess</ows:Identifier>
+        <ows:Title>Dummy Process</ows:Title>
+        <ows:Abstract>DummyProcess to check the WPS structure</ows:Abstract>
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>input1</ows:Identifier>
+                <ows:Title>Input1 number</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#integer">integer</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>100</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>input2</ows:Identifier>
+                <ows:Title>Input2 number</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#integer">integer</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>200</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output1</ows:Identifier>
+                <ows:Title>Output1 add 1 result</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>output2</ows:Identifier>
+                <ows:Title>Output2 substract 1 result</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>wordcounter</ows:Identifier>
+        <ows:Title>Word Counter</ows:Title>
+        <ows:Abstract>Counts words in a given text.</ows:Abstract>
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>text</ows:Identifier>
+                <ows:Title>Text document</ows:Title>
+                <ows:Abstract>URL pointing to a text document, for example "Alice in Wonderland": http://www.gutenberg.org/cache/epub/19033/pg19033.txt</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Word counter result</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>application/json</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/json</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>chomsky</ows:Identifier>
+        <ows:Title>Chomsky text generator</ows:Title>
+        <ows:Abstract>Generates a random chomsky text</ows:Abstract>
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>times</ows:Identifier>
+                <ows:Title>Times</ows:Title>
+                <ows:Abstract>Generates a random chomsky text.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#integer">integer</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>5</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Chomsky text</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>inout</ows:Identifier>
+        <ows:Title>In and Out</ows:Title>
+        <ows:Abstract>Testing all WPS input and output parameters.</ows:Abstract>
+        <ows:Metadata xlink:title="Birdhouse" xlink:type="simple"
+            xlink:href="http://bird-house.github.io/"
+        />
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+            xlink:role="http://www.opengis.net/spec/wps/2.0/def/process/description/documentation"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>string</ows:Identifier>
+                <ows:Title>String</ows:Title>
+                <ows:Abstract>Enter a simple string.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>This is just a string</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>int</ows:Identifier>
+                <ows:Title>Integer</ows:Title>
+                <ows:Abstract>Choose an integer number from allowed values.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#integer">integer</ows:DataType>
+                <ows:AllowedValues>
+                    <ows:Value>1</ows:Value>
+                    <ows:Value>2</ows:Value>
+                    <ows:Value>3</ows:Value>
+                    <ows:Value>5</ows:Value>
+                    <ows:Value>7</ows:Value>
+                    <ows:Value>11</ows:Value>
+                </ows:AllowedValues>
+                <DefaultValue>7</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>float</ows:Identifier>
+                <ows:Title>Float</ows:Title>
+                <ows:Abstract>Enter a float number.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>3.14</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>boolean</ows:Identifier>
+                <ows:Title>Boolean</ows:Title>
+                <ows:Abstract>Make your choice :)</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#boolean">boolean</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>True</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>angle</ows:Identifier>
+                <ows:Title>Angle</ows:Title>
+                <ows:Abstract>Enter an angle [0, 360] :)</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#angle">angle</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>90.0</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>time</ows:Identifier>
+                <ows:Title>Time</ows:Title>
+                <ows:Abstract>Enter a time like 12:00:00</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#time">time</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>12:00:00</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>date</ows:Identifier>
+                <ows:Title>Date</ows:Title>
+                <ows:Abstract>Enter a date like 2012-05-01</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#date">date</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>2012-05-01</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>datetime</ows:Identifier>
+                <ows:Title>Datetime</ows:Title>
+                <ows:Abstract>Enter a datetime like 2016-09-02T12:00:00Z</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#dateTime">dateTime</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>2016-09-02 12:00:00+00:00</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>string_choice</ows:Identifier>
+                <ows:Title>String Choice</ows:Title>
+                <ows:Abstract>Choose one item form list.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AllowedValues>
+                    <ows:Value>rock</ows:Value>
+                    <ows:Value>paper</ows:Value>
+                    <ows:Value>scissor</ows:Value>
+                </ows:AllowedValues>
+                <DefaultValue>scissor</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="0" maxOccurs="2">
+                <ows:Identifier>string_multiple_choice</ows:Identifier>
+                <ows:Title>String Multiple Choice</ows:Title>
+                <ows:Abstract>Choose one or two items from list.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AllowedValues>
+                    <ows:Value>sitting duck</ows:Value>
+                    <ows:Value>flying goose</ows:Value>
+                    <ows:Value>happy pinguin</ows:Value>
+                    <ows:Value>gentle albatros</ows:Value>
+                </ows:AllowedValues>
+                <DefaultValue>gentle albatros</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="0" maxOccurs="1">
+                <ows:Identifier>text</ows:Identifier>
+                <ows:Title>Text</ows:Title>
+                <ows:Abstract>Enter a URL pointing to a text document (optional)</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+            <Input minOccurs="0" maxOccurs="1">
+                <ows:Identifier>dataset</ows:Identifier>
+                <ows:Title>Dataset</ows:Title>
+                <ows:Abstract>Enter a URL pointing to a NetCDF file (optional)</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>string</ows:Identifier>
+                <ows:Title>String</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>int</ows:Identifier>
+                <ows:Title>Integer</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#integer">integer</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>float</ows:Identifier>
+                <ows:Title>Float</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>boolean</ows:Identifier>
+                <ows:Title>Boolean</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#boolean">boolean</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>angle</ows:Identifier>
+                <ows:Title>Angle</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#angle">angle</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>time</ows:Identifier>
+                <ows:Title>Time</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#time">time</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>date</ows:Identifier>
+                <ows:Title>Date</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#date">date</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>datetime</ows:Identifier>
+                <ows:Title>DateTime</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#dateTime">dateTime</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>string_choice</ows:Identifier>
+                <ows:Title>String Choice</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>string_multiple_choice</ows:Identifier>
+                <ows:Title>String Multiple Choice</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>text</ows:Identifier>
+                <ows:Title>Text</ows:Title>
+                <ows:Abstract>Copy of input text file.</ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>dataset</ows:Identifier>
+                <ows:Title>Dataset</ows:Title>
+                <ows:Abstract>Copy of input netcdf file.</ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                            <Encoding></Encoding>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>bbox</ows:Identifier>
+                <ows:Title>Bounding Box</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <BoundingBoxOutput>
+                    <Default>
+                        <CRS>epsg:4326</CRS>
+                    </Default>
+                    <Supported>
+                        <CRS>epsg:4326</CRS>
+                    </Supported>
+                </BoundingBoxOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>binaryoperatorfornumbers</ows:Identifier>
+        <ows:Title>Binary Operator for Numbers</ows:Title>
+        <ows:Abstract>Performs operation on two numbers and returns the answer. This example process is taken from Climate4Impact.</ows:Abstract>
+        <ows:Metadata xlink:title="Birdhouse" xlink:type="simple"
+            xlink:href="http://bird-house.github.io/"
+        />
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+        />
+        <ows:Metadata xlink:title="Climate4Impact" xlink:type="simple"
+            xlink:href="https://dev.climate4impact.eu"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>inputa</ows:Identifier>
+                <ows:Title>Input 1</ows:Title>
+                <ows:Abstract>Enter Input 1</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>2.0</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>inputb</ows:Identifier>
+                <ows:Title>Input 2</ows:Title>
+                <ows:Abstract>Enter Input 2</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>3.0</DefaultValue>
+                </LiteralData>
+            </Input>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>operator</ows:Identifier>
+                <ows:Title>Operator</ows:Title>
+                <ows:Abstract>Choose a binary Operator</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AllowedValues>
+                    <ows:Value>add</ows:Value>
+                    <ows:Value>substract</ows:Value>
+                    <ows:Value>divide</ows:Value>
+                    <ows:Value>multiply</ows:Value>
+                </ows:AllowedValues>
+                <DefaultValue>add</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Binary operator result</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#float">float</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>show_error</ows:Identifier>
+        <ows:Title>Show a WPS Error</ows:Title>
+        <ows:Abstract>This process will fail intentionally with a WPS error message.</ows:Abstract>
+        <ows:Metadata xlink:title="Birdhouse" xlink:type="simple"
+            xlink:href="http://bird-house.github.io/"
+        />
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>message</ows:Identifier>
+                <ows:Title>Error Message</ows:Title>
+                <ows:Abstract>Enter an error message that will be returned.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AnyValue />
+                <DefaultValue>This process failed intentionally :)</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.1" storeSupported="true" statusSupported="true">
+        <ows:Identifier>multiple_outputs</ows:Identifier>
+        <ows:Title>Multiple Outputs</ows:Title>
+        <ows:Abstract>Produces multiple files and returns a document with references to these files.</ows:Abstract>
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="https://emu.readthedocs.io/en/latest/processes.html"
+        />
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>count</ows:Identifier>
+                <ows:Title>Number of output files</ows:Title>
+                <ows:Abstract>The number of generated output files.</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#integer">integer</ows:DataType>
+                <ows:AllowedValues>
+                    <ows:Value>1</ows:Value>
+                    <ows:Value>2</ows:Value>
+                    <ows:Value>5</ows:Value>
+                    <ows:Value>10</ows:Value>
+                </ows:AllowedValues>
+                <DefaultValue>1</DefaultValue>
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Output</ows:Title>
+                <ows:Abstract>Text document with dummy content.</ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>reference</ows:Identifier>
+                <ows:Title>Output References</ows:Title>
+                <ows:Abstract>Document with references to produced output files.</ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>application/json</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/json</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>esgf_demo</ows:Identifier>
+        <ows:Title>ESGF Demo</ows:Title>
+        <ows:Abstract>Shows how to use WPS metadata for processes using ESGF data.</ows:Abstract>
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="https://emu.readthedocs.io/en/latest/processes.html"
+        />
+        <ows:Metadata xlink:title="ESGF Constraints" xlink:type="simple"
+            xlink:href="http://esgf-data.dkrz.de/esg-search/search?project=CMIP5&time_frequency=mon&variable=tas,tasmax,tasmin&experiment=historical"
+            xlink:role="https://www.earthsystemcog.org/spec/esgf_search/4.12.0/def/constraints"
+        />
+        <DataInputs>
+            <Input minOccurs="0" maxOccurs="100">
+                <ows:Identifier>dataset</ows:Identifier>
+                <ows:Title>Dataset</ows:Title>
+                <ows:Abstract>You may provide a URL or upload a NetCDF file.</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+            <Input minOccurs="0" maxOccurs="100">
+                <ows:Identifier>dataset_opendap</ows:Identifier>
+                <ows:Title>Remote OpenDAP Data URL</ows:Title>
+                <ows:Abstract>Or provide a remote OpenDAP data URL, for example: http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2.dailyavgs/surface/mslp.2016.nc</ows:Abstract>
+                <LiteralData>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                <ows:AnyValue />
+                </LiteralData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Output response</ows:Title>
+                <ows:Abstract>A summary report.</ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="2.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>output_formats</ows:Identifier>
+        <ows:Title>Return different output formats. </ows:Title>
+        <ows:Abstract>Dummy process returning various output file formats.</ows:Abstract>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>netcdf</ows:Identifier>
+                <ows:Title>netCDF dummy output file.</ows:Title>
+                <ows:Abstract>A very small test netCDF file. </ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+            <Output>
+                <ows:Identifier>json</ows:Identifier>
+                <ows:Title>json dummy output file.</ows:Title>
+                <ows:Abstract>A very small test json file. </ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>application/json</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/json</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="1.0" storeSupported="true" statusSupported="true">
+        <ows:Identifier>poly_centroid</ows:Identifier>
+        <ows:Title>Approximate centroid of a polygon.</ows:Title>
+        <ows:Abstract>Return the polygon's centroid coordinates. If the geometry contains multiple polygons, only the centroid of the first one will be computed. Do not use for serious computations, this is only a test process and uses a crude approximation. </ows:Abstract>
+        <DataInputs>
+            <Input minOccurs="1" maxOccurs="1">
+                <ows:Identifier>polygon</ows:Identifier>
+                <ows:Title>Region definition</ows:Title>
+                <ows:Abstract>A polygon defining a region.</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>application/gml+xml</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/gml+xml</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>The centroid of the polygon geometry.</ows:Title>
+                <ows:Abstract>The coordinates of the polygon's approximate centroid.</ows:Abstract>
+                <LiteralOutput>
+                <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType>
+                </LiteralOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+    <ProcessDescription wps:processVersion="4" storeSupported="true" statusSupported="true">
+        <ows:Identifier>ncmeta</ows:Identifier>
+        <ows:Title>Return NetCDF Metadata</ows:Title>
+        <ows:Abstract>Return metadata from a netCDF dataset, either on file or an OpenDAP service.</ows:Abstract>
+        <ows:Metadata xlink:title="User Guide" xlink:type="simple"
+            xlink:href="http://emu.readthedocs.io/en/latest/"
+        />
+        <DataInputs>
+            <Input minOccurs="0" maxOccurs="1">
+                <ows:Identifier>dataset</ows:Identifier>
+                <ows:Title>NetCDF Dataset</ows:Title>
+                <ows:Abstract>http://test.opendap.org:80/opendap/netcdf/examples/sresa1b_ncar_ccsm3_0_run1_200001.nc.nc4</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/x-netcdf</MimeType>
+                            <Encoding>base64</Encoding>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+            <Input minOccurs="0" maxOccurs="1">
+                <ows:Identifier>dataset_opendap</ows:Identifier>
+                <ows:Title>OpenDAP Dataset</ows:Title>
+                <ows:Abstract>http://test.opendap.org:80/opendap/netcdf/examples/sresa1b_ncar_ccsm3_0_run1_200001.nc</ows:Abstract>
+                <ComplexData maximumMegabytes="200">
+                    <Default>
+                        <Format>
+                            <MimeType>application/x-ogc-dods</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>application/x-ogc-dods</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexData>
+            </Input>
+        </DataInputs>
+        <ProcessOutputs>
+            <Output>
+                <ows:Identifier>output</ows:Identifier>
+                <ows:Title>Metadata</ows:Title>
+                <ows:Abstract></ows:Abstract>
+                <ComplexOutput>
+                    <Default>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Default>
+                    <Supported>
+                        <Format>
+                            <MimeType>text/plain</MimeType>
+                        </Format>
+                    </Supported>
+                </ComplexOutput>
+            </Output>
+        </ProcessOutputs>
+    </ProcessDescription>
+</wps:ProcessDescriptions>
\ No newline at end of file


=====================================
tests/resources/wps_EmuExecuteRequest7.xml
=====================================
@@ -1 +1 @@
-<wps100:Execute xmlns:wps100="http://www.opengis.net/wps/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" service="WPS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsExecute_request.xsd"><ows110:Identifier xmlns:ows110="http://www.opengis.net/ows/1.1">wordcount</ows110:Identifier><wps100:DataInputs><wps100:Input><ows110:Identifier xmlns:ows110="http://www.opengis.net/ows/1.1">text</ows110:Identifier><wps100:Reference xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://emu.readthedocs.org/en/latest/index.html"/></wps100:Input></wps100:DataInputs><wps100:ResponseForm><wps100:ResponseDocument lineage="false" status="false" storeExecuteResponse="false"><wps100:Output asReference="true"><ows110:Identifier xmlns:ows110="http://www.opengis.net/ows/1.1">output</ows110:Identifier></wps100:Output></wps100:ResponseDocument></wps100:ResponseForm></wps100:Execute>
+<wps100:Execute xmlns:wps100="http://www.opengis.net/wps/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" service="WPS" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsExecute_request.xsd"><ows110:Identifier xmlns:ows110="http://www.opengis.net/ows/1.1">wordcount</ows110:Identifier><wps100:DataInputs><wps100:Input><ows110:Identifier xmlns:ows110="http://www.opengis.net/ows/1.1">text</ows110:Identifier><wps100:Reference xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://emu.readthedocs.org/en/latest/index.html"/></wps100:Input></wps100:DataInputs><wps100:ResponseForm><wps100:ResponseDocument lineage="false" status="false" storeExecuteResponse="false"><wps100:Output asReference="false"><ows110:Identifier xmlns:ows110="http://www.opengis.net/ows/1.1">output</ows110:Identifier></wps100:Output></wps100:ResponseDocument></wps100:ResponseForm></wps100:Execute>


=====================================
tests/test_wfs3_ldproxy.py
=====================================
@@ -0,0 +1,21 @@
+from tests.utils import service_ok
+
+import pytest
+
+from owslib.wfs import WebFeatureService
+
+SERVICE_URL = 'https://www.ldproxy.nrw.de/rest/services/kataster/?f=json'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason='service is unreachable')
+def test_wfs3_ldproxy():
+    w = WebFeatureService(SERVICE_URL, version='3.0')
+
+    assert w.url == 'https://www.ldproxy.nrw.de/rest/services/kataster/'
+    assert w.version == '3.0'
+    assert w.url_query_string == 'f=json'
+
+    conformance = w.conformance()
+    assert len(conformance['conformsTo']) == 5


=====================================
tests/test_wfs3_pygeoapi.py
=====================================
@@ -0,0 +1,34 @@
+from tests.utils import service_ok
+
+import pytest
+
+from owslib.wfs import WebFeatureService
+
+SERVICE_URL = 'http://geo.kralidis.ca/pygeoapi'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason='service is unreachable')
+def test_wfs3_pygeoapi():
+    w = WebFeatureService(SERVICE_URL, version='3.0')
+
+    assert w.url == 'http://geo.kralidis.ca/pygeoapi/'
+    assert w.version == '3.0'
+    assert w.url_query_string is None
+
+    conformance = w.conformance()
+    assert len(conformance['conformsTo']) == 4
+
+    collections = w.collections()
+    assert len(collections) == 3
+
+    lakes = w.collection('lakes')
+    assert lakes['name'] == 'lakes'
+    assert lakes['title'] == 'Large Lakes'
+    assert lakes['description'] == 'lakes of the world, public domain'
+
+    lakes_query = w.collection_items('lakes', limit=0)
+    assert lakes_query['numberMatched'] == 25
+    assert lakes_query['numberReturned'] == 0
+    assert len(lakes_query['features']) == 0


=====================================
tests/test_wms_getmap.py
=====================================
@@ -1,3 +1,4 @@
+import pytest
 from tests.utils import service_ok
 
 from owslib.wms import WebMapService
@@ -5,9 +6,8 @@ from owslib.util import ServiceException
 from owslib.util import ResponseWrapper
 
 
-import pytest
-
 SERVICE_URL = 'http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r-t.cgi'
+NCWMS2_URL = "http://wms.stccmop.org:8080/ncWMS2/wms"
 
 
 @pytest.mark.online
@@ -36,7 +36,7 @@ def test_wms_getmap_111_service_exception():
     """GetMap 1.1.1 ServiceException for an invalid CRS"""
     wms = WebMapService(SERVICE_URL, version='1.1.1')
     try:
-        rsp = wms.getmap(
+        wms.getmap(
             layers=['nexrad_base_reflect'],
             styles=['default'],
             srs='EPSG:4328',
@@ -74,7 +74,7 @@ def test_wms_getmap_130_service_exception():
     """GetMap 1.3.0 ServiceException for an invalid CRS"""
     wms = WebMapService(SERVICE_URL, version='1.3.0')
     try:
-        rsp = wms.getmap(
+        wms.getmap(
             layers=['nexrad_base_reflect'],
             styles=['default'],
             srs='EPSG:4328',
@@ -120,3 +120,34 @@ def test_getmap_130_national_map():
     assert "height=300" in wms.request
     assert "format=image%2Fpng" in wms.request
     assert "transparent=TRUE" in wms.request
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(NCWMS2_URL), reason="WMS service is unreachable")
+def test_ncwms2():
+    """Test with an ncWMS2 server.
+    """
+    # Note that this does not exercise the bug in https://github.com/geopython/OWSLib/issues/556
+    wms = WebMapService(NCWMS2_URL, version='1.3.0')
+    rsp = wms.getmap(
+        layers=['f33_thredds/min_temp'],
+        styles=['default'],
+        srs='CRS:84',
+        bbox=(-124.17, 46.02, -123.29, 46.38),
+        size=(256, 256),
+        format='image/png',
+        transparent=True,
+        mode='32bit',
+
+    )
+    assert type(rsp) is ResponseWrapper
+    assert "service=WMS" in wms.request
+    assert "version=1.3.0" in wms.request
+    assert "request=GetMap" in wms.request
+    assert "layers=f33_thredds/min_temp" in wms.request
+    assert "styles=default" in wms.request
+    assert "crs=CRS%3A84" in wms.request
+    assert "width=256" in wms.request
+    assert "height=256" in wms.request
+    assert "format=image%2Fpng" in wms.request
+    assert "transparent=TRUE" in wms.request


=====================================
tests/test_wps.py
=====================================
@@ -2,7 +2,7 @@ import pytest
 
 
 from tests.utils import resource_file
-from owslib.wps import WebProcessingService, WPSExecution, Process
+from owslib.wps import WebProcessingService, WPSExecution, Process, is_reference
 from owslib.etree import etree
 
 
@@ -39,6 +39,12 @@ def test_wps_process_representation(wps):
     assert str(p) == 'WPS Process: CDMSSubsetVariable, title=Writes a text file and returns an output.'
 
 
+def test_wps_process_properties(wps):
+    p = wps.processes[0]
+    assert p.statusSupported is None
+    assert p.storeSupported is None
+
+
 def test_wps_process_with_invalid_identifer():
     p = Process(etree.Element('invalid'))
     assert repr(p) == '<owslib.wps.Process >'
@@ -69,3 +75,10 @@ def test_wps_response_with_lineage():
     assert outp.title == 'Test Report'
     assert outp.abstract == 'Compliance checker test report.'
     assert outp.reference.startswith('http://localhost:8090/wpsoutputs')
+
+
+def test_is_reference():
+    assert is_reference('http://testing.org')
+    assert is_reference(b'http://testing.org')
+    assert not is_reference('mumbo jumbo')
+    assert not is_reference(b'mumbo jumbo')


=====================================
tests/test_wps_describeprocess_ceda.py
=====================================
@@ -12,6 +12,9 @@ def test_wps_describeprocess_ceda():
     assert process.identifier == 'DoubleIt'
     assert process.title == 'Doubles the input number and returns value'
     assert process.abstract == 'This is test process used to demonstrate how the WPS and the WPS User Interface work. The process accepts an integer or floating point number and returns some XML containing the input number double.'  # NOQA
+    # Check process properties
+    assert process.statusSupported is False
+    assert process.storeSupported is True
     # Check process inputs
     # Example Input:
     #   identifier=NumberToDouble, title=NumberToDouble, abstract=NumberToDouble, data type=LiteralData


=====================================
tests/test_wps_describeprocess_emu_all.py
=====================================
@@ -0,0 +1,13 @@
+from tests.utils import resource_file
+from owslib.wps import WebProcessingService, Process
+
+
+def test_wps_describeprocess_emu_all():
+    # Initialize WPS client
+    wps = WebProcessingService('http://localhost:8094/wps', skip_caps=True)
+    # Execute fake invocation of DescribeProcess operation by parsing cached response from
+    xml = open(resource_file('wps_EmuDescribeProcess_all.xml'), 'rb').read()
+    process = wps.describeprocess('nap', xml=xml)
+    processes = wps.describeprocess('all', xml=xml)
+    assert isinstance(process, Process)
+    assert isinstance(processes, list)


=====================================
tests/test_wps_request10.py
=====================================
@@ -39,7 +39,7 @@ def test_wps_request10():
 
     # build XML request for WPS process execution
     execution = WPSExecution()
-    requestElement = execution.buildRequest(processid, inputs, output=output)
+    requestElement = execution.buildRequest(processid, inputs, output=[(output, True)])
     request = etree.tostring(requestElement)
 
     # Compare to cached XML request


=====================================
tests/test_wps_request2.py
=====================================
@@ -6,7 +6,7 @@ from owslib.wps import WPSExecution, WFSFeatureCollection, WFSQuery
 from owslib.etree import etree
 
 
-def test_wps_request3():
+def test_wps_request2():
     # Supply process input argument
     wfsUrl = "http://igsarm-cida-gdp2.er.usgs.gov:8082/geoserver/wfs"
     query = WFSQuery("sample:CONUS_States",
@@ -39,7 +39,7 @@ def test_wps_request3():
 
     # build XML request for WPS process execution
     execution = WPSExecution()
-    requestElement = execution.buildRequest(processid, inputs, output=output)
+    requestElement = execution.buildRequest(processid, inputs, output=[(output, True)])
     request = etree.tostring(requestElement)
 
     # Compare to cached XML request


=====================================
tests/test_wps_request3.py
=====================================
@@ -33,7 +33,7 @@ def test_wps_request3():
     output = "OUTPUT"
     # build XML request for WPS process execution
     execution = WPSExecution()
-    requestElement = execution.buildRequest(processid, inputs, output=output)
+    requestElement = execution.buildRequest(processid, inputs, output=[(output, True)])
     request = etree.tostring(requestElement)
     # Compare to cached XML request
     _request = open(resource_file('wps_USGSExecuteRequest3.xml'), 'rb').read()


=====================================
tests/test_wps_request4.py
=====================================
@@ -15,7 +15,7 @@ def test_wps_request4():
 
     # build XML request for WPS process execution
     execution = WPSExecution()
-    requestElement = execution.buildRequest(processid, inputs, output=output)
+    requestElement = execution.buildRequest(processid, inputs, output=[(output, True)])
     request = etree.tostring(requestElement)
 
     # Compare to cached XML request


=====================================
tests/test_wps_request7.py
=====================================
@@ -13,7 +13,7 @@ def test_wps_request7():
     processid = "wordcount"
     textdoc = ComplexDataInput("http://emu.readthedocs.org/en/latest/index.html")
     inputs = [("text", textdoc), ]
-    outputs = [("output", True)]
+    outputs = [("output", False)]
 
     # Build XML request for WPS process execution, sync request
     execution = WPSExecution()


=====================================
tests/utils.py
=====================================
@@ -10,6 +10,7 @@ try:                    # Python 3
 except ImportError:     # Python 2
     from urlparse import urlparse
 
+
 def setup_logging(loglevel='INFO'):
     """Helper function to setup logging for tests"""
     logger = logging.getLogger('owslib')
@@ -20,30 +21,36 @@ def setup_logging(loglevel='INFO'):
     logger.addHandler(sh)
     return logger
 
+
 def resource_file(filepath):
     return os.path.join(test_directory(), 'resources', filepath)
 
+
 def test_directory():
     """Helper function to return path to the tests directory"""
     return os.path.dirname(__file__)
 
+
 def scratch_directory():
     """Helper function to return path to the tests scratch directory"""
     return os.path.join(test_directory(), 'scratch')
 
+
 def scratch_file(filename):
     """Helper function to return file path in the tests scratch directory"""
     return os.path.join(scratch_directory(), filename)
 
-def compare_xml(a,b):
+
+def compare_xml(a, b):
     if not isinstance(a, ElementType):
         a = etree.fromstring(a)
     if not isinstance(b, ElementType):
         b = etree.fromstring(b)
 
-    return compare_elements(a,b)
+    return compare_elements(a, b)
+
 
-def compare_elements(a,b):
+def compare_elements(a, b):
     # Tag
     if a.tag != b.tag:
         return False
@@ -63,22 +70,29 @@ def compare_elements(a,b):
 
     return True
 
+
 def cast_tuple_int_list(tup):
     """Set tuple float values to int for more predictable test results"""
     return [int(a) for a in tup]
 
+
 def cast_tuple_int_list_srs(tup):
     tup2 = cast_tuple_int_list(tup[:4])
     tup2.append(tup[-1])
     return tup2
 
+
 def sorted_url_query(url):
     return sorted(urlparse(url).query.split("&"))
 
 
 def service_ok(url, timeout=5):
     try:
-        ok = requests.get(url, timeout=timeout).ok
+        resp = requests.get(url, timeout=timeout)
+        if 'html' in resp.headers['content-type']:
+            ok = False
+        else:
+            ok = resp.ok
     except requests.exceptions.ReadTimeout:
         ok = False
     except requests.exceptions.ConnectTimeout:



View it on GitLab: https://salsa.debian.org/debian-gis-team/owslib/compare/74a739a6721be77355ff492e31413d71eb4584ea...fb6e6c2728d31fe0c9a01d7c127e6f51bd2a9696

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/owslib/compare/74a739a6721be77355ff492e31413d71eb4584ea...fb6e6c2728d31fe0c9a01d7c127e6f51bd2a9696
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20190113/4085a442/attachment-0001.html>


More information about the Pkg-grass-devel mailing list