Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-OWSLib for openSUSE:Factory 
checked in at 2021-01-25 18:23:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-OWSLib (Old)
 and      /work/SRC/openSUSE:Factory/.python-OWSLib.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-OWSLib"

Mon Jan 25 18:23:17 2021 rev:4 rq:866244 version:0.21.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-OWSLib/python-OWSLib.changes      
2020-12-08 13:25:49.574747971 +0100
+++ /work/SRC/openSUSE:Factory/.python-OWSLib.new.28504/python-OWSLib.changes   
2021-01-25 18:23:36.952428374 +0100
@@ -1,0 +2,18 @@
+Thu Jan 21 09:57:32 UTC 2021 - Guillaume GARDET <guillaume.gar...@opensuse.org>
+
+- Depend on python-PyYAML instead of python-pyyaml
+
+-------------------------------------------------------------------
+Tue Jan 19 08:47:04 UTC 2021 - Bruno Friedmann <br...@ioda-net.ch>
+
+- update to version 0.21.1
+  + This release adds the draft implementation of OGC API
+  + Coverages support as well as numerous fixes to the codebase.
+  + A full list of commits for 0.21.0 can be found at:
+    https://github.com/geopython/OWSLib/commits/0.21.0
+- packaging
+  + Update copyright year
+  + Sync list of Requires (pyproj > 2 and add pyyaml) with
+    requirements
+
+-------------------------------------------------------------------

Old:
----
  OWSLib-0.20.0.tar.gz

New:
----
  OWSLib-0.21.0.tar.gz

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

Other differences:
------------------
++++++ python-OWSLib.spec ++++++
--- /var/tmp/diff_new_pack.CzQuEx/_old  2021-01-25 18:23:37.624429333 +0100
+++ /var/tmp/diff_new_pack.CzQuEx/_new  2021-01-25 18:23:37.628429338 +0100
@@ -1,9 +1,9 @@
 #
 # spec file for package python-OWSLib
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 # Copyright (c) 2015 Angelos Tzotsos <tzot...@opensuse.org>
-# Copyright (c) 2020 Ioda-Net S??rl, Bruno Friedmann, Charmoille, Switzerland.
+# Copyright (c) 2021 Ioda-Net S??rl, Bruno Friedmann, Charmoille, Switzerland.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -22,7 +22,7 @@
 %define         oldpython python
 %define         skip_python2 1
 Name:           python-OWSLib
-Version:        0.20.0
+Version:        0.21.0
 Release:        0
 Summary:        Python interface to OGC Web Services
 License:        BSD-3-Clause
@@ -33,9 +33,10 @@
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-pyproj
+Requires:       python-pyproj >= 2
 Requires:       python-python-dateutil >= 1.5
 Requires:       python-pytz
+Requires:       python-PyYAML
 Requires:       python-requests >= 1.0
 Provides:       python-owslib = %{version}
 Obsoletes:      python-owslib < %{version}

++++++ OWSLib-0.20.0.tar.gz -> OWSLib-0.21.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/CHANGES.rst 
new/OWSLib-0.21.0/CHANGES.rst
--- old/OWSLib-0.20.0/CHANGES.rst       2020-06-05 14:29:33.000000000 +0200
+++ new/OWSLib-0.21.0/CHANGES.rst       2020-12-09 03:16:44.000000000 +0100
@@ -1,6 +1,19 @@
 Changes
 =======
 
+0.21.0 (2020-12-09)
+-------------------
+
+A full list of commits for 0.21.0 can be found at:
+
+https://github.com/geopython/OWSLib/commits/0.21.0
+
+- OGC API: Added support for Coverages (#699)
+- WFS: Added POST support to WFS GetFeature (#706)
+- WCS: Allow user to specify timeout on WCS GetCoverage calls (#714)
+- WPS: fixed bounding-box (#719)
+- Various fixes: #695, #707, #702, #716, #718, #722, #691, #720
+
 0.20.0 (2020-06-05)
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/OWSLib.egg-info/PKG-INFO 
new/OWSLib-0.21.0/OWSLib.egg-info/PKG-INFO
--- old/OWSLib-0.20.0/OWSLib.egg-info/PKG-INFO  2020-06-05 14:35:06.000000000 
+0200
+++ new/OWSLib-0.21.0/OWSLib.egg-info/PKG-INFO  2020-12-09 03:22:23.000000000 
+0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.2
+Metadata-Version: 2.1
 Name: OWSLib
-Version: 0.20.0
+Version: 0.21.0
 Summary: OGC Web Service utility library
 Home-page: https://geopython.github.io/OWSLib
 Author: Sean Gillies
@@ -169,7 +169,13 @@
 Classifier: Intended Audience :: Developers
 Classifier: Intended Audience :: Science/Research
 Classifier: License :: OSI Approved :: BSD License
+Classifier: Natural Language :: English
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
 Classifier: Topic :: Scientific/Engineering :: GIS
 Requires-Python: >=3.6
+Description-Content-Type: text/x-rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/OWSLib.egg-info/SOURCES.txt 
new/OWSLib-0.21.0/OWSLib.egg-info/SOURCES.txt
--- old/OWSLib-0.20.0/OWSLib.egg-info/SOURCES.txt       2020-06-05 
14:35:06.000000000 +0200
+++ new/OWSLib-0.21.0/OWSLib.egg-info/SOURCES.txt       2020-12-09 
03:22:23.000000000 +0100
@@ -44,6 +44,7 @@
 owslib/coverage/wcsdecoder.py
 owslib/feature/__init__.py
 owslib/feature/common.py
+owslib/feature/postrequest.py
 owslib/feature/schema.py
 owslib/feature/wfs100.py
 owslib/feature/wfs110.py
@@ -53,6 +54,7 @@
 owslib/map/wms111.py
 owslib/map/wms130.py
 owslib/ogcapi/__init__.py
+owslib/ogcapi/coverages.py
 owslib/ogcapi/features.py
 owslib/ogcapi/records.py
 owslib/owscontext/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/PKG-INFO new/OWSLib-0.21.0/PKG-INFO
--- old/OWSLib-0.20.0/PKG-INFO  2020-06-05 14:35:06.000000000 +0200
+++ new/OWSLib-0.21.0/PKG-INFO  2020-12-09 03:22:24.000000000 +0100
@@ -1,6 +1,6 @@
-Metadata-Version: 1.2
+Metadata-Version: 2.1
 Name: OWSLib
-Version: 0.20.0
+Version: 0.21.0
 Summary: OGC Web Service utility library
 Home-page: https://geopython.github.io/OWSLib
 Author: Sean Gillies
@@ -169,7 +169,13 @@
 Classifier: Intended Audience :: Developers
 Classifier: Intended Audience :: Science/Research
 Classifier: License :: OSI Approved :: BSD License
+Classifier: Natural Language :: English
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
 Classifier: Topic :: Scientific/Engineering :: GIS
 Requires-Python: >=3.6
+Description-Content-Type: text/x-rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/VERSION.txt 
new/OWSLib-0.21.0/VERSION.txt
--- old/OWSLib-0.20.0/VERSION.txt       2020-06-05 14:29:33.000000000 +0200
+++ new/OWSLib-0.21.0/VERSION.txt       2020-12-09 03:16:55.000000000 +0100
@@ -1 +1 @@
-0.20.0
+0.21.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/__init__.py 
new/OWSLib-0.21.0/owslib/__init__.py
--- old/OWSLib-0.20.0/owslib/__init__.py        2020-06-05 14:29:33.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/__init__.py        2020-12-09 03:17:02.000000000 
+0100
@@ -1 +1 @@
-__version__ = '0.20.0'
+__version__ = '0.21.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/coverage/wcs100.py 
new/OWSLib-0.21.0/owslib/coverage/wcs100.py
--- old/OWSLib-0.20.0/owslib/coverage/wcs100.py 2020-03-29 03:39:03.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/coverage/wcs100.py 2020-11-30 17:09:17.000000000 
+0100
@@ -95,7 +95,7 @@
         return items
 
     def getCoverage(self, identifier=None, bbox=None, time=None, format=None, 
crs=None, width=None, height=None,
-                    resx=None, resy=None, resz=None, parameter=None, 
method='Get', **kwargs):
+                    resx=None, resy=None, resz=None, parameter=None, 
method='Get', timeout=30, **kwargs):
         """Request and return a coverage from the WCS as a file-like object
         note: additional **kwargs helps with multi-version implementation
         core keyword arguments should be supported cross version
@@ -154,7 +154,7 @@
         data = urlencode(request)
         log.debug('WCS 1.0.0 DEBUG: Second part of URL: %s' % data)
 
-        u = openURL(base_url, data, method, self.cookies, auth=self.auth)
+        u = openURL(base_url, data, method, self.cookies, auth=self.auth, 
timeout=timeout)
         return u
 
     def getOperationByName(self, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/coverage/wcs110.py 
new/OWSLib-0.21.0/owslib/coverage/wcs110.py
--- old/OWSLib-0.20.0/owslib/coverage/wcs110.py 2019-11-05 01:04:04.000000000 
+0100
+++ new/OWSLib-0.21.0/owslib/coverage/wcs110.py 2020-11-30 17:09:17.000000000 
+0100
@@ -141,7 +141,7 @@
     # TO DO: Handle rest of the  WCS 1.1.0 keyword parameters e.g. GridCRS etc.
     def getCoverage(self, identifier=None, bbox=None, time=None, format=None, 
store=False, rangesubset=None,
                     gridbaseCRS=None, gridtype=None, gridCS=None, 
gridorigin=None, gridoffsets=None,
-                    method='Get', **kwargs):
+                    method='Get', timeout=30, **kwargs):
         """Request and return a coverage from the WCS as a file-like object
         note: additional **kwargs helps with multi-version implementation
         core keyword arguments should be supported cross version
@@ -205,7 +205,7 @@
         # encode and request
         data = urlencode(request)
 
-        u = openURL(base_url, data, method, self.cookies, auth=self.auth)
+        u = openURL(base_url, data, method, self.cookies, auth=self.auth, 
timeout=timeout)
         return u
 
     def getOperationByName(self, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/coverage/wcs200.py 
new/OWSLib-0.21.0/owslib/coverage/wcs200.py
--- old/OWSLib-0.20.0/owslib/coverage/wcs200.py 2020-03-29 03:39:03.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/coverage/wcs200.py 2020-11-30 17:09:17.000000000 
+0100
@@ -130,6 +130,7 @@
         resz=None,
         parameter=None,
         method="Get",
+        timeout=30,
         **kwargs
     ):
         """Request and return a coverage from the WCS as a file-like object
@@ -213,7 +214,7 @@
             data += param_list_to_url_string(sizes, 'size')
         log.debug("WCS 2.0.0 DEBUG: Second part of URL: %s" % data)
 
-        u = openURL(base_url, data, method, self.cookies, auth=self.auth)
+        u = openURL(base_url, data, method, self.cookies, auth=self.auth, 
timeout=timeout)
         return u
 
     def getOperationByName(self, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/coverage/wcs201.py 
new/OWSLib-0.21.0/owslib/coverage/wcs201.py
--- old/OWSLib-0.20.0/owslib/coverage/wcs201.py 2020-03-29 03:39:03.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/coverage/wcs201.py 2020-11-30 17:09:17.000000000 
+0100
@@ -130,6 +130,7 @@
         resz=None,
         parameter=None,
         method="Get",
+        timeout=30,
         **kwargs
     ):
         """Request and return a coverage from the WCS as a file-like object
@@ -214,7 +215,7 @@
 
         log.debug("WCS 2.0.1 DEBUG: Second part of URL: %s" % data)
 
-        u = openURL(base_url, data, method, self.cookies, auth=self.auth)
+        u = openURL(base_url, data, method, self.cookies, auth=self.auth, 
timeout=timeout)
         return u
 
     def getOperationByName(self, name):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/feature/__init__.py 
new/OWSLib-0.21.0/owslib/feature/__init__.py
--- old/OWSLib-0.20.0/owslib/feature/__init__.py        2020-06-05 
13:05:14.000000000 +0200
+++ new/OWSLib-0.21.0/owslib/feature/__init__.py        2020-11-30 
17:09:17.000000000 +0100
@@ -5,12 +5,11 @@
 #
 # =============================================================================
 
-from owslib.crs import Crs
-
 from urllib.parse import urlencode
-import logging
+from owslib.crs import Crs
 from owslib.util import log, Authentication
 from owslib.feature.schema import get_schema
+from owslib.feature.postrequest import PostRequest_1_1_0, PostRequest_2_0_0
 
 
 class WebFeatureService_(object):
@@ -77,6 +76,49 @@
                 srs.getcode(),
             )
 
+    def getBBOXPost(self, bbox, typename):
+        """Format bounding box for Post requests
+
+        @param bbox: (minx,miny,maxx,maxy[,srs])
+        @type bbox: List
+        @param typename:  feature name
+        @type typename: String
+        @returns: String properly formated according to version and
+            coordinate reference system
+        """
+        srs = None
+
+        # srs of the bbox is specified in the bbox as fifth paramter
+        if len(bbox) == 5:
+            srs = Crs(bbox[4])
+        # take default srs
+        else:
+            srs = self.contents[typename[0]].crsOptions[0]
+
+        formatted_bbox = [bbox[0], bbox[1], bbox[2], bbox[3]]
+        if self.version in ["1.1.0", "2.0.0"]:
+            if srs.axisorder == "yx" and srs.encoding == "urn":
+                formatted_bbox = [bbox[1], bbox[0], bbox[3], bbox[2]]
+
+            if self.version == "1.1.0":
+                formatted_bbox.append(srs.getcodeurn())
+                return formatted_bbox
+            if self.version == "2.0.0":
+                formatted_bbox.append(srs.getcodeuri1())
+                return formatted_bbox
+        else:
+            formatted_bbox.append(srs.getcode())
+            return formatted_bbox
+
+    def create_post_request(self):
+        """Creates an xml POST request according to WFS version."""
+
+        if self.version in ['1.1.0']:
+            return PostRequest_1_1_0()
+
+        if self.version in ['2.0', '2.0.0']:
+            return PostRequest_2_0_0()
+
     def getSRS(self, srsname, typename):
         """Returns None or Crs object for given name
 
@@ -206,6 +248,131 @@
 
         return base_url + data
 
+    def getPOSTGetFeatureRequest(
+        self,
+        typename=None,
+        filter=None,
+        bbox=None,
+        featureid=None,
+        featureversion=None,
+        propertyname=None,
+        maxfeatures=None,
+        storedQueryID=None,
+        storedQueryParams=None,
+        outputFormat=None,
+        method="Post",
+        startindex=None,
+        sortby=None,
+    ):
+        """Formulate proper GetFeature request using KVP encoding
+        ----------
+        typename : list
+            List of typenames (string)
+        filter : string
+            XML-encoded OGC filter expression.
+        bbox : tuple
+            (left, bottom, right, top) in the feature type's coordinates == 
(minx, miny, maxx, maxy)
+        featureid : list
+            List of unique feature ids (string)
+        featureversion : string
+            Default is most recent feature version.
+        propertyname : list
+            List of feature property names. Leave blank (None) to get all 
properties.
+        maxfeatures : int
+            Maximum number of features to be returned.
+        method : string
+            Qualified name of the HTTP DCP method to use.
+        outputFormat: string (optional)
+            Requested response format of the request.
+        startindex: int (optional)
+            Start position to return feature set (paging in combination with 
maxfeatures)
+        storedQueryID : string
+            A name identifying a prepared set available in WFS-service.
+            WFS version 2.0.0 and above only.
+        storedQueryParams : dict
+            Variable amount of extra information sent to server related to
+            storedQueryID to further define the requested data.
+            WFS version 2.0.0 and above only.
+            {'parameter_name': parameter_value}
+        sortby: list (optional)
+            List of property names whose values should be used to order
+            (upon presentation) the set of feature instances that
+            satify the query.
+
+        There are 5 different modes of use
+
+        1) typename and bbox (simple spatial query)
+        2) typename and filter (==query) (more expressive)
+        3) featureid (direct access to known features)
+        4) storedQueryID and optional storedQueryParams
+        5) filter only via Post method
+        """
+
+        try:
+            base_url = next(
+                (
+                    m.get("url")
+                    for m in self.getOperationByName("GetFeature").methods
+                    if m.get("type").lower() == method.lower()
+                )
+            )
+        except StopIteration:
+            base_url = self.url
+
+        if not typename and filter:
+            return base_url, filter
+
+        request = self.create_post_request()
+
+        if storedQueryID:
+            if self.version in ["1.0.0", "1.1.0"]:
+                log.warning("Stored queries are only supported in version 
2.0.0 and above.")
+                return None
+
+            storedQueryParams = storedQueryParams or {}
+            request.create_storedquery(storedQueryID, storedQueryParams)
+            data = request.to_string()
+            return base_url, data
+
+        typename = (
+            [typename] if isinstance(typename, str) else typename
+        )  # noqa: E721
+        typenames = ",".join(typename)
+
+        request.create_query(typenames)
+
+        if featureid:
+            featureid = (
+                [featureid] if isinstance(featureid, str) else featureid
+            )
+            request.set_featureid(featureid)
+        elif bbox:
+            request.set_bbox(self.getBBOXPost(bbox, typename))
+        elif filter:
+            request.set_filter(filter)
+
+        if featureversion:
+            request.set_featureversion(str(featureversion))
+        if maxfeatures:
+            request.set_maxfeatures(maxfeatures)
+        if outputFormat:
+            request.set_outputformat(outputFormat)
+        if propertyname:
+            propertyname = (
+                [propertyname] if isinstance(propertyname, str) else 
propertyname
+            )
+            request.set_propertyname(propertyname)
+        if sortby:
+            sortby = (
+                [sortby] if isinstance(sortby, str) else sortby
+            )
+            request.set_sortby(sortby)
+        if startindex:
+            request.set_startindex(startindex)
+
+        data = request.to_string()
+        return base_url, data
+
     def get_schema(self, typename):
         """
         Get layer schema compatible with :class:`fiona` schema object
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/feature/postrequest.py 
new/OWSLib-0.21.0/owslib/feature/postrequest.py
--- old/OWSLib-0.20.0/owslib/feature/postrequest.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/OWSLib-0.21.0/owslib/feature/postrequest.py     2020-11-30 
17:09:17.000000000 +0100
@@ -0,0 +1,197 @@
+# owslib imports:
+from owslib import util
+from owslib.etree import etree
+from owslib.namespaces import Namespaces
+
+n = Namespaces()
+FES_NAMESPACE = n.get_namespace("fes")
+GML_NAMESPACE = n.get_namespace("gml")
+GML32_NAMESPACE = n.get_namespace("gml32")
+OGC_NAMESPACE = n.get_namespace("ogc")
+WFS_NAMESPACE = n.get_namespace("wfs")
+WFS20_NAMESPACE = n.get_namespace("wfs20")
+
+
+class PostRequest():
+    """Superclass for POST request building"""
+
+    def __init__(self, version=None, namespace=None):
+        self._root = etree.Element(util.nspath('GetFeature', namespace))
+        self._root.set("service", "WFS")
+        self._root.set("version", version)
+        self._wfsnamespace = namespace
+        self._query = None
+
+    def _create_query(self, typename):
+        self._query = etree.SubElement(self._root, util.nspath('Query', 
self._wfsnamespace))
+
+    def set_featureversion(self, version):
+        self._query.set("featureVersion", version)
+
+    def set_propertyname(self, propertyname):
+        """Set which feature properties will be returned.
+
+        If not set, will return all properties."""
+        for pn in propertyname:
+            etree.SubElement(self._query, "PropertyName").text = pn
+
+    def set_startindex(self, startindex):
+        """Set the starting index value for the request"""
+        self._root.set("startIndex", str(startindex))
+
+    def to_string(self):
+        """Returns the xml request in string format.
+
+        Required in order to use the request with getfeature()"""
+        return etree.tostring(self._root)
+
+
+class PostRequest_1_1_0(PostRequest):
+    """XML Post request payload builder for WFS version 1.1.0"""
+
+    def __init__(self):
+        super().__init__(version='1.1.0', namespace=WFS_NAMESPACE)
+
+    def create_query(self, typename):
+        """Creates the query tag with the corresponding typenames.
+        Required element for each request."""
+        super()._create_query(typename)
+        self._query.set("typeName", typename)
+
+    def set_bbox(self, bbox):
+        """Set a bbox filter.
+
+        Cannot be used with set_featureid() or set_filter().
+        """
+        filter_tree = etree.SubElement(self._query, util.nspath('Filter', 
OGC_NAMESPACE))
+        bbox_tree = etree.SubElement(filter_tree, util.nspath('BBOX', 
OGC_NAMESPACE))
+        coords = etree.SubElement(bbox_tree, util.nspath('Envelope', 
GML_NAMESPACE))
+        if len(bbox) > 4:
+            coords.set('srsName', bbox[4])
+        lower = etree.SubElement(coords, util.nspath('lowerCorner', 
GML_NAMESPACE))
+        lower.text = '{} {}'.format(bbox[0], bbox[1])
+
+        upper = etree.SubElement(coords, util.nspath('upperCorner', 
GML_NAMESPACE))
+        upper.text = '{} {}'.format(bbox[2], bbox[3])
+
+    def set_featureid(self, featureid):
+        """Set filter by feature id.
+
+        Cannot be used with set_bbox() or set_filter().
+        """
+        feature_tree = etree.SubElement(self._query, util.nspath('Filter', 
OGC_NAMESPACE))
+
+        for ft in featureid:
+            prop_id = etree.Element(util.nspath('GmlObjectId', OGC_NAMESPACE))
+            prop_id.set(util.nspath('id', GML_NAMESPACE), ft)
+            feature_tree.append(prop_id)
+
+    def set_filter(self, filter):
+        """Set filter from existing filter.
+
+        Will integrate the filter tag of a provided xml filter to the query 
being built.
+
+        Cannot be used with set_bbox() or set_featureid().
+        """
+        f = etree.fromstring(filter)
+        sub_elem = f.find(util.nspath("Filter", OGC_NAMESPACE))
+        self._query.append(sub_elem)
+
+    def set_maxfeatures(self, maxfeatures):
+        """Set the maximum number of features to be returned."""
+        self._root.set("maxFeatures", str(maxfeatures))
+
+    def set_outputformat(self, outputFormat):
+        """Set the output format.
+
+        Verify the available formats with a GetCapabilites request."""
+        self._root.set("outputFormat", outputFormat)
+
+    def set_sortby(self, sortby):
+        """Set the properties by which the response will be sorted."""
+        sort_tree = etree.SubElement(self._query, util.nspath("SortBy", 
OGC_NAMESPACE))
+        for s in sortby:
+            prop_elem = etree.SubElement(sort_tree, 
util.nspath("SortProperty", OGC_NAMESPACE))
+            prop_name = etree.SubElement(prop_elem, 
util.nspath('PropertyName', OGC_NAMESPACE))
+            prop_name.text = s
+
+
+class PostRequest_2_0_0(PostRequest):
+    """XML Post request payload builder for WFS version 2.0.0."""
+
+    def __init__(self):
+        super().__init__(version='2.0.0', namespace=WFS20_NAMESPACE)
+
+    def create_query(self, typename):
+        """Creates the query tag with the corresponding typenames.
+        Required element for each request ecept for stored queries."""
+        super()._create_query(typename)
+        self._query.set("typenames", typename)
+
+    def create_storedquery(self, stored_id, parameters):
+        """Create the storedQuery tag and configure it's sub elements and 
attributes."""
+        storedquery = etree.SubElement(self._root, util.nspath('StoredQuery', 
self._wfsnamespace))
+        storedquery.set("id", str(stored_id))
+        for param in parameters:
+            p = etree.SubElement(storedquery, util.nspath('Parameter', 
self._wfsnamespace))
+            p.set("name", param)
+            p.text = parameters[param]
+
+    def set_bbox(self, bbox):
+        """Set a bbox filter.
+
+        Cannot be used with set_featureid() or set_filter().
+        """
+        filter_tree = etree.SubElement(self._query, util.nspath('Filter', 
FES_NAMESPACE))
+        bbox_tree = etree.SubElement(filter_tree, util.nspath('BBOX', 
FES_NAMESPACE))
+        coords = etree.SubElement(bbox_tree, util.nspath('Envelope', 
GML32_NAMESPACE))
+        if len(bbox) > 4:
+            coords.set('srsName', bbox[4])
+
+        lower = etree.SubElement(coords, util.nspath('lowerCorner', 
GML32_NAMESPACE))
+        lower.text = '{} {}'.format(bbox[0], bbox[1])
+
+        upper = etree.SubElement(coords, util.nspath('upperCorner', 
GML32_NAMESPACE))
+        upper.text = '{} {}'.format(bbox[2], bbox[3])
+
+    def set_featureid(self, featureid):
+        """Set filter by feature id.
+
+        Cannot be used with set_bbox() or set_filter().
+        """
+        feature_tree = etree.SubElement(self._query, util.nspath('Filter', 
FES_NAMESPACE))
+        for ft in featureid:
+            prop_id = etree.Element(util.nspath('ResourceId', FES_NAMESPACE))
+            prop_id.set('rid', ft)
+            feature_tree.append(prop_id)
+
+    def set_filter(self, filter):
+        """Set filter from existing filter.
+
+        Will integrate the filter tag of a provided xml filter to the current 
one
+        being built.
+
+        Cannot be used with set_bbox() or set_featureid().
+        """
+        f = etree.fromstring(filter)
+        sub_elem = f.find(util.nspath("Filter", FES_NAMESPACE))
+        self._query.append(sub_elem)
+
+    def set_maxfeatures(self, maxfeatures):
+        """Set the maximum number of features to be returned."""
+        self._root.set("count", str(maxfeatures))
+
+    def set_outputformat(self, outputFormat):
+        """Set the output format.
+
+        Verify the available formats with a GetCapabilites request.
+        """
+        self._root.set("outputformat", outputFormat)
+
+    def set_sortby(self, sortby):
+        """Set the properties by which the response will be sorted."""
+        sort_tree = etree.SubElement(self._query, util.nspath("SortBy", 
FES_NAMESPACE))
+        for s in sortby:
+            prop_elem = etree.SubElement(sort_tree, 
util.nspath("SortProperty", FES_NAMESPACE))
+            value = etree.SubElement(prop_elem, util.nspath('ValueReference', 
FES_NAMESPACE))
+            value.text = s
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/feature/schema.py 
new/OWSLib-0.21.0/owslib/feature/schema.py
--- old/OWSLib-0.20.0/owslib/feature/schema.py  2020-04-23 13:17:57.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/feature/schema.py  2020-10-28 12:48:50.000000000 
+0100
@@ -52,6 +52,8 @@
     if ":" in typename:
         typename = typename.split(":")[1]
     type_element = root.find("./{%s}element" % XS_NAMESPACE)
+    if type_element is None:
+        return None
     complex_type = type_element.attrib["type"].split(":")[1]
     elements = _get_elements(complex_type, root)
     nsmap = None
@@ -125,7 +127,8 @@
             schema["geometry"] = mappings[data_type]
             schema["geometry_column"] = name
         else:
-            schema["properties"][name] = data_type.replace(schema_key + ":", 
"")
+            if schema_key is not None:
+                schema["properties"][name] = data_type.replace(schema_key + 
":", "")
 
         if non_nillable:
             schema["required"].append(name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/feature/wfs110.py 
new/OWSLib-0.21.0/owslib/feature/wfs110.py
--- old/OWSLib-0.20.0/owslib/feature/wfs110.py  2020-04-23 13:17:57.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/feature/wfs110.py  2020-11-30 17:09:17.000000000 
+0100
@@ -220,7 +220,7 @@
         bbox=None,
         featureid=None,
         featureversion=None,
-        propertyname="*",
+        propertyname=None,
         maxfeatures=None,
         srsname=None,
         outputFormat=None,
@@ -243,7 +243,8 @@
         featureversion : string
             Default is most recent feature version.
         propertyname : list
-            List of feature property names. '*' matches all.
+            List of feature property names. For Get request, '*' matches all.
+            For Post request, leave blank (None) to get all properties.
         maxfeatures : int
             Maximum number of features to be returned.
         method : string
@@ -278,53 +279,72 @@
             base_url = self.url
         request = {"service": "WFS", "version": self.version, "request": 
"GetFeature"}
 
-        if not isinstance(typename, list):
-            typename = [typename]
+        if method.lower() == "get":
+            if not isinstance(typename, list):
+                typename = [typename]
+
+            if srsname is not None:
+                request["srsname"] = str(srsname)
+
+                # Check, if desired SRS is supported by the service for each
+                # typename. Warning will be thrown if that SRS is not allowed."
+                for name in typename:
+                    _ = self.getSRS(srsname, name)
+
+            # check featureid
+            if featureid:
+                request["featureid"] = ",".join(featureid)
+
+            # bbox
+            elif bbox and typename:
+                request["bbox"] = self.getBBOXKVP(bbox, typename)
+
+            # or filter
+            elif filter and typename:
+                request["filter"] = str(filter)
 
-        if srsname is not None:
-            request["srsname"] = str(srsname)
+            assert len(typename) > 0
+            request["typename"] = ",".join(typename)
 
-            # Check, if desired SRS is supported by the service for each
-            # typename. Warning will be thrown if that SRS is not allowed."
-            for name in typename:
-                _ = self.getSRS(srsname, name)
+            if propertyname is None:
+                propertyname = "*"
 
-        # check featureid
-        if featureid:
-            request["featureid"] = ",".join(featureid)
-
-        # bbox
-        elif bbox and typename:
-            request["bbox"] = self.getBBOXKVP(bbox, typename)
-
-        # or filter
-        elif filter and typename:
-            request["filter"] = str(filter)
-
-        assert len(typename) > 0
-        request["typename"] = ",".join(typename)
-
-        if propertyname is not None:
             if not isinstance(propertyname, list):
                 propertyname = [propertyname]
             request["propertyname"] = ",".join(propertyname)
 
-        if sortby is not None:
-            if not isinstance(sortby, list):
-                sortby = [sortby]
-            request["sortby"] = ",".join(sortby)
-
-        if featureversion is not None:
-            request["featureversion"] = str(featureversion)
-        if maxfeatures is not None:
-            request["maxfeatures"] = str(maxfeatures)
-        if startindex is not None:
-            request["startindex"] = str(startindex)
-        if outputFormat is not None:
-            request["outputFormat"] = outputFormat
+            if sortby is not None:
+                if not isinstance(sortby, list):
+                    sortby = [sortby]
+                request["sortby"] = ",".join(sortby)
+
+            if featureversion is not None:
+                request["featureversion"] = str(featureversion)
+            if maxfeatures is not None:
+                request["maxfeatures"] = str(maxfeatures)
+            if startindex is not None:
+                request["startindex"] = str(startindex)
+            if outputFormat is not None:
+                request["outputFormat"] = outputFormat
+
+            data = urlencode(request)
+            log.debug("Making request: %s?%s" % (base_url, data))
+
+        elif method.lower() == "post":
+            base_url, data = self.getPOSTGetFeatureRequest(
+                typename=typename,
+                filter=filter,
+                bbox=bbox,
+                featureid=featureid,
+                featureversion=featureversion,
+                propertyname=propertyname,
+                maxfeatures=maxfeatures,
+                outputFormat=outputFormat,
+                method='Post',
+                startindex=startindex,
+                sortby=sortby,
+            )
 
-        data = urlencode(request)
-        log.debug("Making request: %s?%s" % (base_url, data))
         u = openURL(base_url, data, method, timeout=self.timeout,
                     headers=self.headers, auth=self.auth)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/feature/wfs200.py 
new/OWSLib-0.21.0/owslib/feature/wfs200.py
--- old/OWSLib-0.20.0/owslib/feature/wfs200.py  2020-04-23 13:17:57.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/feature/wfs200.py  2020-11-30 17:09:17.000000000 
+0100
@@ -234,7 +234,9 @@
         sortby=None,
     ):
         """Request and return feature data as a file-like object.
+
         #TODO: NOTE: have changed property name from ['*'] to None - check the 
use of this in WFS 2.0
+
         Parameters
         ----------
         typename : list
@@ -248,9 +250,16 @@
         featureversion : string
             Default is most recent feature version.
         propertyname : list
-            List of feature property names. '*' matches all.
+            List of feature property names. For Get request, '*' matches all.
+            For Post request, leave blank (None) to get all properties.
         maxfeatures : int
             Maximum number of features to be returned.
+        storedQueryID : string
+            A name identifying a prepared set available in WFS-service
+        storedQueryParams : dict
+            Variable amount of extra information sent to server related to
+            storedQueryID to further define the requested data
+            {'parameter_name': parameter_value}
         method : string
             Qualified name of the HTTP DCP method to use.
         outputFormat: string (optional)
@@ -262,11 +271,19 @@
             (upon presentation) the set of feature instances that
             satify the query.
 
-        There are 3 different modes of use
+        There are 5 different modes of use
 
         1) typename and bbox (simple spatial query)
         2) typename and filter (==query) (more expressive)
         3) featureid (direct access to known features)
+        4) storedQueryID and optional storedQueryParams
+        5) filter only via Post method
+
+        Raises:
+            ServiceException: If there is an error during the request
+
+        Returns:
+            BytesIO -- Data returned from the service as a file-like object
         """
         storedQueryParams = storedQueryParams or {}
         url = data = None
@@ -290,9 +307,21 @@
             )
             log.debug("GetFeature WFS GET url %s" % url)
         else:
-            (url, data) = self.getPOSTGetFeatureRequest()
+            url, data = self.getPOSTGetFeatureRequest(
+                typename,
+                filter,
+                bbox,
+                featureid,
+                featureversion,
+                propertyname,
+                maxfeatures,
+                storedQueryID,
+                storedQueryParams,
+                outputFormat,
+                "Post",
+                startindex,
+                sortby)
 
-        # If method is 'Post', data will be None here
         u = openURL(url, data, method, timeout=self.timeout, 
headers=self.headers, auth=self.auth)
 
         # check for service exceptions, rewrap, and return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/map/wms111.py 
new/OWSLib-0.21.0/owslib/map/wms111.py
--- old/OWSLib-0.20.0/owslib/map/wms111.py      2019-11-05 01:04:04.000000000 
+0100
+++ new/OWSLib-0.21.0/owslib/map/wms111.py      2020-12-09 03:15:04.000000000 
+0100
@@ -535,14 +535,18 @@
         for s in elem.findall('Style'):
             name = s.find('Name')
             title = s.find('Title')
+            if name is None and title is None:
+                raise ValueError('%s missing name and title' % (s,))
             if name is None or title is None:
-                raise ValueError('%s missing name or title' % (s,))
-            style = {'title': title.text}
+                warnings.warn('%s missing name or title' % (s,))
+            title_ = title.text if title is not None else name.text
+            name_ = name.text if name is not None else title.text
+            style = {'title': title_}
             # legend url
             legend = s.find('LegendURL/OnlineResource')
             if legend is not None:
                 style['legend'] = 
legend.attrib['{http://www.w3.org/1999/xlink}href']
-            self.styles[name.text] = style
+            self.styles[name_] = style
 
         # keywords
         self.keywords = [f.text for f in elem.findall('KeywordList/Keyword')]
@@ -579,9 +583,11 @@
         self.dataUrls = []
         for m in elem.findall('DataURL'):
             dataUrl = {
-                'format': m.find('Format').text.strip(),
+                'format': testXMLValue(m.find('Format')),
                 'url': 
m.find('OnlineResource').attrib['{http://www.w3.org/1999/xlink}href']
             }
+            if dataUrl['format']:
+                dataUrl['format'] = dataUrl['format'].strip()
             self.dataUrls.append(dataUrl)
 
         self.layers = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/map/wms130.py 
new/OWSLib-0.21.0/owslib/map/wms130.py
--- old/OWSLib-0.20.0/owslib/map/wms130.py      2019-11-05 01:04:04.000000000 
+0100
+++ new/OWSLib-0.21.0/owslib/map/wms130.py      2020-12-09 03:15:04.000000000 
+0100
@@ -581,9 +581,13 @@
         for s in elem.findall(nspath('Style', WMS_NAMESPACE)):
             name = s.find(nspath('Name', WMS_NAMESPACE))
             title = s.find(nspath('Title', WMS_NAMESPACE))
+            if name is None and title is None:
+                raise ValueError('%s missing name and title' % (s,))
             if name is None or title is None:
-                raise ValueError('%s missing name or title' % (s,))
-            style = {'title': title.text}
+                warnings.warn('%s missing name or title' % (s,))
+            title_ = title.text if title is not None else name.text
+            name_ = name.text if name is not None else title.text
+            style = {'title': title_}
             # legend url
             legend = s.find(nspath('LegendURL/OnlineResource', WMS_NAMESPACE))
             if legend is not None:
@@ -599,7 +603,7 @@
                 lgd_format = lgd.find(nspath('Format', WMS_NAMESPACE))
                 if lgd_format is not None:
                     style['legend_format'] = lgd_format.text.strip()
-            self.styles[name.text] = style
+            self.styles[name_] = style
 
         # keywords
         self.keywords = [f.text for f in 
elem.findall(nspath('KeywordList/Keyword', WMS_NAMESPACE))]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/ogcapi/__init__.py 
new/OWSLib-0.21.0/owslib/ogcapi/__init__.py
--- old/OWSLib-0.20.0/owslib/ogcapi/__init__.py 2020-06-05 13:39:21.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/ogcapi/__init__.py 2020-12-03 12:53:17.000000000 
+0100
@@ -123,7 +123,7 @@
         path = 'collections'
         return self._request(path)
 
-    def collection(self, collection_id) -> dict:
+    def collection(self, collection_id: str) -> dict:
         """
         implements /collections/{collectionId}
 
@@ -136,7 +136,7 @@
         path = 'collections/{}'.format(collection_id)
         return self._request(path)
 
-    def collection_queryables(self, collection_id) -> dict:
+    def collection_queryables(self, collection_id: str) -> dict:
         """
         implements /collections/{collectionId}/queryables
 
@@ -149,7 +149,7 @@
         path = 'collections/{}/queryables'.format(collection_id)
         return self._request(path)
 
-    def _build_url(self, path=None) -> str:
+    def _build_url(self, path: str = None) -> str:
         """
         helper function to build an OGC API URL
 
@@ -171,12 +171,15 @@
 
         return url
 
-    def _request(self, path=None, kwargs={}) -> dict:
+    def _request(self, path: str = None, as_dict: bool = True,
+                 kwargs: dict = {}) -> dict:
         """
         helper function for request/response patterns against OGC API endpoints
 
         @type path: string
         @param path: path of request
+        @type as_dict: bool
+        @param as_dict: whether to return JSON dict (default True)
         @type kwargs: string
         @param kwargs: ``dict`` of keyword value pair request parameters
 
@@ -186,10 +189,17 @@
         url = self._build_url(path)
 
         LOGGER.debug('Request: {}'.format(url))
+        LOGGER.debug('Params: {}'.format(kwargs))
 
         response = http_get(url, headers=self.headers, auth=self.auth,
                             params=kwargs)
+
+        LOGGER.debug('URL: {}'.format(response.url))
+
         if response.status_code != requests.codes.ok:
             raise RuntimeError(response.text)
 
-        return response.json()
+        if as_dict:
+            return response.json()
+        else:
+            return response.content
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/ogcapi/coverages.py 
new/OWSLib-0.21.0/owslib/ogcapi/coverages.py
--- old/OWSLib-0.20.0/owslib/ogcapi/coverages.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/OWSLib-0.21.0/owslib/ogcapi/coverages.py        2020-12-02 
18:21:37.000000000 +0100
@@ -0,0 +1,98 @@
+# =============================================================================
+# Copyright (c) 2020 Tom Kralidis
+#
+# Author: Tom Kralidis <tomkrali...@gmail.com>
+#
+# Contact email: tomkrali...@gmail.com
+# =============================================================================
+
+from io import BytesIO
+import logging
+
+from owslib.ogcapi import API
+from owslib.util import Authentication
+
+LOGGER = logging.getLogger(__name__)
+
+
+class Coverages(API):
+    """Abstraction for OGC API - Coverages"""
+
+    def __init__(self, url: str, json_: str = None, timeout: int = 30,
+                 headers: dict = None, auth: Authentication = None):
+        __doc__ = API.__doc__  # noqa
+        super().__init__(url, json_, timeout, headers, auth)
+
+    def coverages(self) -> dict:
+        """
+        implements /collections filtered on coverages
+
+        @returns: `dict` of filtered collections object
+        """
+
+        coverages_ = []
+        collections_ = super().collections()
+
+        for c_ in collections_['collections']:
+            for l_ in c_['links']:
+                if 'coverage' in l_['rel']:
+                    coverages_.append(c_['id'])
+                    break
+
+        return coverages_
+
+    def coverage_domainset(self, collection_id: str, **kwargs: dict) -> dict:
+        """
+        implements /collection/{collectionId}/coverage/domainset
+
+        @type collection_id: string
+        @param collection_id: id of collection
+
+        @returns: coverage domainset results
+        """
+
+        path = 'collections/{}/coverage/domainset'.format(collection_id)
+        return self._request(path=path, kwargs=kwargs)
+
+    def coverage_rangetype(self, collection_id: str, **kwargs: dict) -> dict:
+        """
+        implements /collection/{collectionId}/coverage/rangetype
+
+        @type collection_id: string
+        @param collection_id: id of collection
+
+        @returns: coverage rangetype results
+        """
+
+        path = 'collections/{}/coverage/rangetype'.format(collection_id)
+        return self._request(path=path, kwargs=kwargs)
+
+    def coverage(self, collection_id: str, **kwargs: dict) -> dict:
+        """
+        implements /collection/{collectionId}/coverage/
+
+        @type collection_id: string
+        @param collection_id: id of collection
+        @type range_subset: list
+        @param range_subset: range subset
+        @type subsets: list of tuples
+        @param subsets: [(name, lower bound, upper bound)]
+
+        @returns: coverage data
+        """
+
+        kwargs_ = {}
+
+        if 'range_subset' in kwargs:
+            kwargs_['rangeSubset'] = ','.join(
+                [str(x) for x in kwargs['range_subset']])
+
+        if 'subsets' in kwargs:
+            kwargs_['subset'] = []
+            for s in kwargs['subsets']:
+                val = '{}({},{})'.format(s[0], s[1], s[2])
+                kwargs_['subset'].append(val)
+
+        path = 'collections/{}/coverage'.format(collection_id)
+
+        return BytesIO(self._request(path=path, as_dict=False, kwargs=kwargs_))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/ogcapi/features.py 
new/OWSLib-0.21.0/owslib/ogcapi/features.py
--- old/OWSLib-0.20.0/owslib/ogcapi/features.py 2020-06-05 13:39:21.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/ogcapi/features.py 2020-12-02 18:21:37.000000000 
+0100
@@ -22,6 +22,22 @@
         __doc__ = API.__doc__  # noqa
         super().__init__(url, json_, timeout, headers, auth)
 
+    def feature_collections(self) -> dict:
+        """
+        implements /collections filtered on features
+
+        @returns: `dict` of filtered collections object
+        """
+
+        features_ = []
+        collections_ = super().collections()
+
+        for c_ in collections_['collections']:
+            if 'itemType' in c_ and c_['itemType'].lower() == 'feature':
+                features_.append(c_['id'])
+
+        return features_
+
     def collection_items(self, collection_id: str, **kwargs: dict) -> dict:
         """
         implements /collection/{collectionId}/items
@@ -46,7 +62,7 @@
             kwargs['bbox'] = ','.join(kwargs['bbox'])
 
         path = 'collections/{}/items'.format(collection_id)
-        return self._request(path, kwargs)
+        return self._request(path=path, kwargs=kwargs)
 
     def collection_item(self, collection_id: str, identifier: str) -> dict:
         """
@@ -61,4 +77,4 @@
         """
 
         path = 'collections/{}/items/{}'.format(collection_id, identifier)
-        return self._request(path)
+        return self._request(path=path)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/ogcapi/records.py 
new/OWSLib-0.21.0/owslib/ogcapi/records.py
--- old/OWSLib-0.20.0/owslib/ogcapi/records.py  2020-06-05 13:39:21.000000000 
+0200
+++ new/OWSLib-0.21.0/owslib/ogcapi/records.py  2020-10-12 13:18:50.000000000 
+0200
@@ -21,3 +21,19 @@
                  headers: dict = None, auth: Authentication = None):
         __doc__ = Features.__doc__  # noqa
         super().__init__(url, json_, timeout, headers, auth)
+
+    def records(self) -> dict:
+        """
+        implements /collections filtered on records
+
+        @returns: `dict` of filtered collections object
+        """
+
+        records_ = []
+        collections_ = super().collections()
+
+        for c_ in collections_['collections']:
+            if 'itemType' in c_ and c_['itemType'].lower() == 'record':
+                records_.append(c_['id'])
+
+        return records_
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/util.py 
new/OWSLib-0.21.0/owslib/util.py
--- old/OWSLib-0.20.0/owslib/util.py    2020-05-21 03:02:42.000000000 +0200
+++ new/OWSLib-0.21.0/owslib/util.py    2020-12-09 03:15:04.000000000 +0100
@@ -292,7 +292,7 @@
         # We can't re-add an existing namespaces.  Get a list of current
         # namespaces in use
         existing_namespaces = set()
-        for elem in root.getiterator():
+        for elem in root.iter():
             if elem.tag[0] == "{":
                 uri, tag = elem.tag[1:].split("}")
                 existing_namespaces.add(namespaces.get_namespace_from_url(uri))
@@ -591,6 +591,10 @@
 def getTypedValue(data_type, value):
     '''Utility function to cast a string value to the appropriate XSD type. '''
 
+    # If the default value is empty
+    if value is None:
+        return
+
     if data_type == 'boolean':
         return True if value.lower() == 'true' else False
     elif data_type == 'integer':
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/owslib/wps.py 
new/OWSLib-0.21.0/owslib/wps.py
--- old/OWSLib-0.20.0/owslib/wps.py     2020-05-20 17:00:56.000000000 +0200
+++ new/OWSLib-0.21.0/owslib/wps.py     2020-12-03 12:53:17.000000000 +0100
@@ -1398,10 +1398,7 @@
                 self.dataType = literalDataElement.get('dataType')
                 if literalDataElement.text is not None and 
literalDataElement.text.strip() != '':
                     self.data.append(literalDataElement.text.strip())
-            bboxDataElement = dataElement.find(nspath('BoundingBox', 
ns=namespaces['ows']))
-            if bboxDataElement is not None:
-                # TODO: just a workaround for data-inputs in lineage
-                bboxDataElement = dataElement.find(nspath('BoundingBoxData', 
ns=namespaces['wps']))
+            bboxDataElement = dataElement.find(nspath('BoundingBoxData', 
ns=namespaces['wps']))
             if bboxDataElement is not None:
                 self.dataType = "BoundingBoxData"
                 bbox = BoundingBox(bboxDataElement)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/OWSLib-0.20.0/setup.py new/OWSLib-0.21.0/setup.py
--- old/OWSLib-0.20.0/setup.py  2020-03-29 03:39:03.000000000 +0200
+++ new/OWSLib-0.21.0/setup.py  2020-10-12 13:18:50.000000000 +0200
@@ -20,6 +20,7 @@
       version           = owslib.__version__,
       description       = 'OGC Web Service utility library',
       long_description  = readme,
+      long_description_content_type = 'text/x-rst',
       license           = 'BSD',
       keywords          = 'gis ogc iso 19115 fgdc dif ows wfs wms sos csw wps 
wcs capabilities metadata wmts',
       author            = 'Sean Gillies',
@@ -36,8 +37,13 @@
         'Intended Audience :: Developers',
         'Intended Audience :: Science/Research',
         'License :: OSI Approved :: BSD License',
+        'Natural Language :: English',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
         'Topic :: Scientific/Engineering :: GIS',
         ],
 )

Reply via email to