[Git][debian-gis-team/owslib][master] 4 commits: New upstream version 0.22.0

Bas Couwenberg gitlab at salsa.debian.org
Thu Jan 21 05:08:09 GMT 2021



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


Commits:
88c4f812 by Bas Couwenberg at 2021-01-21T05:57:04+01:00
New upstream version 0.22.0
- - - - -
832972d5 by Bas Couwenberg at 2021-01-21T05:57:10+01:00
Update upstream source from tag 'upstream/0.22.0'

Update to upstream version '0.22.0'
with Debian dir a71c048950e18e74e152541d4264748044425239
- - - - -
85197a6f by Bas Couwenberg at 2021-01-21T05:57:33+01:00
New upstream release.

- - - - -
6680ab42 by Bas Couwenberg at 2021-01-21T05:58:49+01:00
Set distribution to unstable.

- - - - -


25 changed files:

- + .github/workflows/main.yml
- − .travis.yml
- MANIFEST.in
- README.rst
- VERSION.txt
- debian/changelog
- docs/en/index.rst
- owslib/__init__.py
- owslib/coverage/wcs100.py
- owslib/coverage/wcs110.py
- owslib/coverage/wcs200.py
- owslib/coverage/wcs201.py
- owslib/feature/wfs100.py
- owslib/feature/wfs110.py
- owslib/feature/wfs200.py
- owslib/iso.py
- requirements-dev.txt
- − tests/doctests/wfs1_generic.txt
- + tests/resources/iso_mi.xml
- tests/test_iso_parsing.py
- tests/test_ows_interfaces.py
- tests/test_remote_metadata.py
- + tests/test_wfs_generic.py
- tests/test_wfs_schema.py
- tests/test_wms_jpl_capabilities.py


Changes:

=====================================
.github/workflows/main.yml
=====================================
@@ -0,0 +1,38 @@
+name: build ⚙️
+
+on: [ push, pull_request ]
+
+jobs:
+  main:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: [3.6, 3.7, 3.8, 3.9]
+        lxml: [true, false]
+    env:
+        LXML: ${{ matrix.lxml }}
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        COVERALLS_SERVICE_NAME: github
+    steps:
+    - uses: actions/checkout at v2
+    - uses: actions/setup-python at v2
+      name: Setup Python ${{ matrix.python-version }}
+      with:
+        python-version: ${{ matrix.python-version }}
+    - name: Install requirements 📦
+      run: |
+        pip3 install -r requirements.txt
+        pip3 install -r requirements-dev.txt
+        echo "LXML => $LXML"
+        if [ "$LXML" == "true" ]; then pip install lxml; fi
+    - name: run tests ⚙️
+      run: python3 -m pytest
+    - name: run coveralls ⚙️
+      run: coveralls
+      if: matrix.python-version == 3.6
+    - name: build docs 🏗️
+      run: cd docs && make html
+      if: matrix.python-version == 3.6
+    - name: run flake8 ⚙️
+      run: flake8 owslib
+      if: matrix.python-version == 3.6


=====================================
.travis.yml deleted
=====================================
@@ -1,22 +0,0 @@
-language: python
-python:
-  - "3.6"
-  - "3.7"
-  - "3.8"
-  - "3.9"
-sudo: false
-env:
-  - LXML=true
-  - LXML=false
-install:
-  - pip install -r requirements.txt
-  - pip install -r requirements-dev.txt
-  - if [ "$LXML" == "true" ]; then pip install lxml; fi
-script:
-  - python -m pytest
-  - flake8 owslib
-after_success:
-  - coveralls
-notifications:
-  irc:
-    - "irc.freenode.org#geopython"


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


=====================================
README.rst
=====================================
@@ -1,9 +1,9 @@
 OWSLib
 ======
 
-.. image:: https://travis-ci.org/geopython/OWSLib.svg?branch=master
-   :target: https://travis-ci.org/geopython/OWSLib
-   :alt: Travis Build
+.. image:: https://github.com/geopython/OWSLib/workflows/build%20%E2%9A%99%EF%B8%8F/badge.svg
+   :target: https://github.com/geopython/OWSLib/actions
+   :alt: Build Status
 
 .. image:: https://api.codacy.com/project/badge/Grade/09f15588c99943e3976cdf20b7b32c8d
    :target: https://www.codacy.com/project/cehbrecht/OWSLib/dashboard?utm_source=github.com&utm_medium=referral&utm_content=geopython/OWSLib&utm_campaign=Badge_Grade_Dashboard
@@ -145,7 +145,8 @@ Releasing
   make html
   ./publish.sh
   # update on PyPI (must be a maintainer)
-  python setup.py sdist bdist_wheel --universal upload
+  python setup.py sdist bdist_wheel --universal
+  twine upload dist/*
 
 Support
 -------


=====================================
VERSION.txt
=====================================
@@ -1 +1 @@
-0.21.0
+0.22.0


=====================================
debian/changelog
=====================================
@@ -1,3 +1,10 @@
+owslib (0.22.0-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Thu, 21 Jan 2021 05:58:42 +0100
+
 owslib (0.21.0-1) unstable; urgency=medium
 
   * Team upload.


=====================================
docs/en/index.rst
=====================================
@@ -60,6 +60,8 @@ Standards Support
 +-----------------------+-----------------------------+
 | `ISO 19139`_          | 2007                        |
 +-----------------------+-----------------------------+
+| `ISO 19139-2`_        | 2012                        |
++-----------------------+-----------------------------+
 | `Dublin Core`_        | 1.1                         |
 +-----------------------+-----------------------------+
 | `Swiss GM03`_         | 2.3                         |
@@ -843,6 +845,7 @@ Credits
 .. _`FGDC CSDGM`: https://www.fgdc.gov/metadata/csdgm-standard
 .. _`ISO 19115`: https://www.iso.org/standard/26020.html
 .. _`ISO 19139`: https://www.iso.org/standard/32557.html
+.. _`ISO 19139-2`: https://www.iso.org/standard/57104.html
 .. _`Dublin Core`: https://www.dublincore.org/
 .. _`freenode`: https://freenode.net/
 .. _`OpenHub`: https://www.openhub.net/p/OWSLib


=====================================
owslib/__init__.py
=====================================
@@ -1 +1 @@
-__version__ = '0.21.0'
+__version__ = '0.22.0'


=====================================
owslib/coverage/wcs100.py
=====================================
@@ -38,17 +38,18 @@ class WebCoverageService_1_0_0(WCSBase):
         else:
             raise KeyError("No content named %s" % name)
 
-    def __init__(self, url, xml, cookies, auth=None):
+    def __init__(self, url, xml, cookies, auth=None, timeout=30):
         super(WebCoverageService_1_0_0, self).__init__(auth)
         self.version = '1.0.0'
         self.url = url
         self.cookies = cookies
+        self.timeout = timeout
         # initialize from saved capability document or access the server
         reader = WCSCapabilitiesReader(self.version, self.cookies, self.auth)
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
 
         # check for exceptions
         se = self._capabilities.find('ServiceException')


=====================================
owslib/coverage/wcs110.py
=====================================
@@ -51,7 +51,7 @@ class WebCoverageService_1_1_0(WCSBase):
         else:
             raise KeyError("No content named %s" % name)
 
-    def __init__(self, url, xml, cookies, auth=None):
+    def __init__(self, url, xml, cookies, auth=None, timeout=30):
         super(WebCoverageService_1_1_0, self).__init__(auth=auth)
 
         self.url = url
@@ -61,7 +61,7 @@ class WebCoverageService_1_1_0(WCSBase):
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
 
         # check for exceptions
         se = self._capabilities.find(self.ns.OWS('Exception'))


=====================================
owslib/coverage/wcs200.py
=====================================
@@ -53,7 +53,7 @@ class WebCoverageService_2_0_0(WCSBase):
         else:
             raise KeyError("No content named %s" % name)
 
-    def __init__(self, url, xml, cookies, auth=None):
+    def __init__(self, url, xml, cookies, auth=None, timeout=30):
         super(WebCoverageService_2_0_0, self).__init__(auth=auth)
         self.version = "2.0.0"
         self.url = url
@@ -64,7 +64,7 @@ class WebCoverageService_2_0_0(WCSBase):
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
 
         # check for exceptions
         se = self._capabilities.find("ServiceException")


=====================================
owslib/coverage/wcs201.py
=====================================
@@ -53,7 +53,7 @@ class WebCoverageService_2_0_1(WCSBase):
         else:
             raise KeyError("No content named %s" % name)
 
-    def __init__(self, url, xml, cookies, auth=None):
+    def __init__(self, url, xml, cookies, auth=None, timeout=30):
         super(WebCoverageService_2_0_1, self).__init__(auth=auth)
         self.version = "2.0.1"
         self.url = url
@@ -64,7 +64,7 @@ class WebCoverageService_2_0_1(WCSBase):
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
 
         # check for exceptions
         se = self._capabilities.find("ServiceException")


=====================================
owslib/feature/wfs100.py
=====================================
@@ -140,7 +140,7 @@ class WebFeatureService_1_0_0(object):
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
         self._buildMetadata(parse_remote_metadata)
 
     def _buildMetadata(self, parse_remote_metadata=False):


=====================================
owslib/feature/wfs110.py
=====================================
@@ -132,7 +132,7 @@ class WebFeatureService_1_1_0(WebFeatureService_):
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
         self._buildMetadata(parse_remote_metadata)
 
     def _buildMetadata(self, parse_remote_metadata=False):


=====================================
owslib/feature/wfs200.py
=====================================
@@ -125,7 +125,7 @@ class WebFeatureService_2_0_0(WebFeatureService_):
         if xml:
             self._capabilities = reader.readString(xml)
         else:
-            self._capabilities = reader.read(self.url)
+            self._capabilities = reader.read(self.url, self.timeout)
         self._buildMetadata(parse_remote_metadata)
 
     def _buildMetadata(self, parse_remote_metadata=False):


=====================================
owslib/iso.py
=====================================
@@ -20,7 +20,7 @@ from owslib.namespaces import Namespaces
 # default variables
 def get_namespaces():
     n = Namespaces()
-    ns = n.get_namespaces(["gco", "gfc", "gmd", "gml", "gml32", "gmx", "gts", "srv", "xlink"])
+    ns = n.get_namespaces(["gco", "gfc", "gmd", "gmi", "gml", "gml32", "gmx", "gts", "srv", "xlink"])
     ns[None] = n.get_namespace("gmd")
     return ns
 
@@ -49,11 +49,13 @@ class MD_Metadata(object):
             self.locales = []
             self.referencesystem = None
             self.identification = None
+            self.contentinfo = None
             self.serviceidentification = None
             self.identificationinfo = []
             self.contentinfo = []
             self.distribution = None
             self.dataquality = None
+            self.acquisition = None
         else:
             if hasattr(md, 'getroot'):  # standalone document
                 self.xml = etree.tostring(md.getroot())
@@ -149,6 +151,9 @@ class MD_Metadata(object):
             for contentinfo in md.findall(
                     util.nspath_eval('gmd:contentInfo/gmd:MD_FeatureCatalogueDescription', namespaces)):
                 self.contentinfo.append(MD_FeatureCatalogueDescription(contentinfo))
+            for contentinfo in md.findall(
+                    util.nspath_eval('gmd:contentInfo/gmd:MD_ImageDescription', namespaces)):
+                self.contentinfo.append(MD_ImageDescription(contentinfo))
 
             val = md.find(util.nspath_eval('gmd:distributionInfo/gmd:MD_Distribution', namespaces))
 
@@ -163,6 +168,10 @@ class MD_Metadata(object):
             else:
                 self.dataquality = None
 
+            val = md.find(util.nspath_eval('gmi:acquisitionInformation/gmi:MI_AcquisitionInformation', namespaces))
+            if val is not None:
+                self.acquisition = MI_AcquisitionInformation(val)
+
     def get_default_locale(self):
         """ get default gmd:PT_Locale based on gmd:language """
 
@@ -1225,3 +1234,98 @@ class FC_ListedValue(object):
 
             val = lv.find(util.nspath_eval('gfc:definition/gco:CharacterString', namespaces))
             self.definition = util.testXMLValue(val)
+
+
+class MD_ImageDescription(object):
+    """Process gmd:MD_ImageDescription"""
+    def __init__(self, img_desc=None):
+        self.type = 'image'
+        self.bands = []
+
+        if img_desc is None:
+            self.attribute_description = None
+            self.cloud_cover = None
+            self.processing_level = None
+        else:
+            val = img_desc.find(util.nspath_eval('gmd:attributeDescription/gco:RecordType', namespaces))
+            self.attribute_description = util.testXMLValue(val)
+
+            val = img_desc.find(util.nspath_eval('gmd:contentType/gmd:MD_CoverageContentTypeCode', namespaces))
+            self.type = util.testXMLAttribute(val, 'codeListValue')
+
+            val = img_desc.find(util.nspath_eval('gmd:cloudCoverPercentage/gco:Real', namespaces))
+            self.cloud_cover = util.testXMLValue(val)
+
+            val = img_desc.find(util.nspath_eval(
+                'gmd:processingLevelCode/gmd:RS_Identifier/gmd:code/gco:CharacterString', namespaces))
+            self.processing_level = util.testXMLValue(val)
+
+            for i in img_desc.findall(util.nspath_eval('gmd:dimension/gmd:MD_Band', namespaces)):
+                bid = util.testXMLAttribute(i, 'id')
+                self.bands.append(MD_Band(i, bid))
+
+
+class MD_Band(object):
+    """Process gmd:MD_Band"""
+    def __init__(self, band, band_id=None):
+        if band is None:
+            self.id = None
+            self.units = None
+            self.min = None
+            self.max = None
+        else:
+            self.id = band_id
+
+            val = band.find(util.nspath_eval('gmd:units/gml:UnitDefinition/gml:identifier', namespaces))
+            self.units = util.testXMLValue(val)
+
+            val = band.find(util.nspath_eval('gmd:minValue/gco:Real', namespaces))
+            self.min = util.testXMLValue(val)
+
+            val = band.find(util.nspath_eval('gmd:maxValue/gco:Real', namespaces))
+            self.max = util.testXMLValue(val)
+
+
+class MI_AcquisitionInformation(object):
+    """Process gmi:MI_AcquisitionInformation"""
+
+    def __init__(self, acq=None):
+        self.platforms = []
+
+        for i in acq.findall(util.nspath_eval('gmi:platform/gmi:MI_Platform', namespaces)):
+            self.platforms.append(MI_Platform(i))
+
+
+class MI_Platform(object):
+    """Process gmi:MI_Platform"""
+
+    def __init__(self, plt=None):
+        self.instruments = []
+
+        if plt is None:
+            self.identifier = None
+            self.description = None
+        else:
+            val = plt.find(util.nspath_eval('gmi:identifier', namespaces))
+            self.identifier = util.testXMLValue(val)
+
+            val = plt.find(util.nspath_eval('gmi:description', namespaces))
+            self.description = util.testXMLValue(val)
+
+            for i in plt.findall(util.nspath_eval('gmi:instrument/gmi:MI_Instrument', namespaces)):
+                self.instruments.append(MI_Instrument(i))
+
+
+class MI_Instrument(object):
+    """Process gmi:MI_Instrument"""
+
+    def __init__(self, inst=None):
+        if inst is None:
+            self.identifier = None
+            self.type = None
+        else:
+            val = inst.find(util.nspath_eval('gmi:identifier', namespaces))
+            self.identifier = util.testXMLValue(val)
+
+            val = inst.find(util.nspath_eval('gmi:type', namespaces))
+            self.type = util.testXMLValue(val)


=====================================
requirements-dev.txt
=====================================
@@ -1,9 +1,11 @@
 -r requirements.txt
 flake8
-pytest>=3.6
+pytest>=3.8
 pytest-cov
 Pillow
 sphinx
 tox
 twine
 wheel
+coverage
+coveralls


=====================================
tests/doctests/wfs1_generic.txt deleted
=====================================
@@ -1,148 +0,0 @@
-Imports and initialize
-
-    >>> from owslib.wfs import WebFeatureService
-    >>> try:
-    ...     from urlparse import urlparse
-    ... except ImportError:
-    ...     from urllib.parse import urlparse
-    >>> from tests.utils import resource_file, sorted_url_query
-
-    >>> getcapsin = open(resource_file("wfs_HSRS_GetCapabilities_1_1_0.xml"), "rb").read()
-    >>> wfs = WebFeatureService('http://gis.bnhelp.cz/ows/crwfs', xml=getcapsin, version='1.1.0')
-
-Test the capabilities info
-    >>> wfs.identification.service
-    'OGC WFS'
-    >>> wfs.identification.version
-    '1.1.0'
-    >>> wfs.identification.title
-    'Help Service Gazeteer'
-    >>> wfs.identification.abstract
-    'Vyhledavani sidel WFS'
-    >>> wfs.identification.keywords
-    ['Czech republic', 'gazeeteer']
-    >>> wfs.identification.fees
-    'none'
-    >>> wfs.identification.accessconstraints
-    'for non profit use'
-    >>> wfs.provider.name
-    'Help Service Remote Sensing, ltd.'
-    >>> wfs.provider.url
-    'http://www.hsrs.cz'
-    >>> wfs.provider.contact.email
-    >>> wfs.provider.contact.phone
-    >>> wfs.provider.contact.name   #doctest: +SKIP
-    u'Stanislav Hol\xfd'
-    >>> wfs.provider.contact.organization
-    >>> wfs.provider.contact.city
-    >>> wfs.provider.contact.region
-    >>> wfs.provider.contact.postcode
-    >>> wfs.provider.contact.country
-
-Test the getfeature method
-
-    >>> sorted(wfs.contents.keys())
-    ['kraje', 'nuts1', 'nuts2', 'nuts3', 'okresy', 'orp', 'sidla', 'states']
-
-    >>> wfs.contents['okresy'].crsOptions[0].getcodeurn()
-    'urn:ogc:def:crs:EPSG::4326'
-
-    >>> sorted_url_query(wfs.getGETGetFeatureRequest(typename=['okresy'], maxfeatures=2))
-    ['maxfeatures=2', 'request=GetFeature', 'service=WFS', 'typename=okresy', 'version=1.1.0']
-
-    >>> sorted_url_query(wfs.getGETGetFeatureRequest(typename=['okresy'], maxfeatures=2, bbox=[15,49,16,51,'urn:ogc:def:crs:EPSG:4326']))
-    ['bbox=49%2C15%2C51%2C16%2Curn%3Aogc%3Adef%3Acrs%3AEPSG%3A%3A4326', 'maxfeatures=2', 'request=GetFeature', 'service=WFS', 'typename=okresy', 'version=1.1.0']
-
-    >>> sorted_url_query(wfs.getGETGetFeatureRequest(typename=['okresy'], maxfeatures=2, bbox=[-685336,-993518,-684996,-993285]))
-    ['bbox=-993518%2C-685336%2C-993285%2C-684996%2Curn%3Aogc%3Adef%3Acrs%3AEPSG%3A%3A4326', 'maxfeatures=2', 'request=GetFeature', 'service=WFS', 'typename=okresy', 'version=1.1.0']
-
-
-Test outputFormat
-
-WFS 1.0.0
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.0.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json')
-    >>> json.dumps(json.loads(feature.read()))
-    '{...}'
-
-WFS 1.1.0
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.1.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json')
-    >>> json.dumps(json.loads(feature.read()))
-    '{...}'
-
-WFS 2.0.0
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='2.0.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json')
-    >>> json.dumps(json.loads(feature.read()))
-    '{...}'
-
-
-Test srsName
-
-WFS 1.0.0
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.0.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json', srsname="EPSG:99999999")  #doctest: +IGNORE_EXCEPTION_DETAIL
-    ...
-    Traceback (most recent call last):
-    ...
-    ServiceException: Unable to support srsName: EPSG:99999999
-    ...
-
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.0.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json', srsname="urn:x-ogc:def:crs:EPSG:4326")
-    >>> json.dumps(json.loads(feature.read()))
-    '{...}'
-
-WFS 1.1.0
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.1.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json', srsname="EPSG:99999999")  #doctest: +IGNORE_EXCEPTION_DETAIL
-    ...
-    Traceback (most recent call last):
-    ...
-    ServiceException: SRSNAME EPSG:99999999 not supported.  Options: urn:x-ogc:def:crs:EPSG:102715
-
-    >>> import json
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.0.0')
-    >>> feature = wfs.getfeature(typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json', srsname="urn:x-ogc:def:crs:EPSG:4326")
-    >>> json.dumps(json.loads(feature.read()))
-    '{...}'
-
-Test schema WFS 1.0.0
-
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.0.0')
-    >>> schema = wfs.get_schema('footprint')
-    >>> len(schema['properties'])
-    4
-    >>> schema['properties']['summary']
-    'string'
-    >>> schema['geometry']
-    'Polygon'
-
-Test schema WFS 1.1.0
-
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='1.1.0')
-    >>> schema = wfs.get_schema('footprint')
-    >>> len(schema['properties'])
-    4
-    >>> schema['properties']['summary']
-    'string'
-    >>> schema['geometry']
-    '3D Polygon'
-
-Test schema WFS 2.0.0
-
-    >>> wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288', version='2.0.0')
-    >>> schema = wfs.get_schema('footprint')
-    >>> len(schema['properties'])
-    4
-    >>> schema['properties']['summary']
-    'string'
-    >>> schema['geometry']
-    '3D Polygon'


=====================================
tests/resources/iso_mi.xml
=====================================
@@ -0,0 +1,497 @@
+<?xml version="1.0" ?>
+<gmi:MI_Metadata xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gmi="http://www.isotc211.org/2005/gmi" xmlns:gml="http://www.opengis.net/gml" xmlns:gmx="http://www.isotc211.org/2005/gmx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://www.isotc211.org/2005/gmd/gmd.xsd http://www.isotc211.org/2005/gmx http://www.isotc211.org/2005/gmx/gmx.xsd http://www.isotc211.org/2005/gmi http://www.isotc211.org/2005/gmx/gmi.xsd">
+  <gmd:fileIdentifier>
+    <gco:CharacterString>3f342f64-9348-11df-ba6a-0014c2c00eab</gco:CharacterString>
+  </gmd:fileIdentifier>
+  <gmd:language>
+    <gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="en" codeSpace="ISO 639-2">en</gmd:LanguageCode>
+  </gmd:language>
+  <gmd:characterSet>
+    <gmd:MD_CharacterSetCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="utf8" codeSpace="ISOTC211/19115">utf8</gmd:MD_CharacterSetCode>
+  </gmd:characterSet>
+  <gmd:parentIdentifier>
+    <gco:CharacterString>someparentid</gco:CharacterString>
+  </gmd:parentIdentifier>
+  <gmd:hierarchyLevel>
+    <gmd:MD_ScopeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="dataset" codeSpace="ISOTC211/19115">dataset</gmd:MD_ScopeCode>
+  </gmd:hierarchyLevel>
+  <gmd:contact>
+    <gmd:CI_ResponsibleParty id="contact-pointOfContact">
+      <gmd:individualName>
+        <gco:CharacterString>Tom Kralidis</gco:CharacterString>
+      </gmd:individualName>
+      <gmd:organisationName>
+        <gco:CharacterString>Environment Canada</gco:CharacterString>
+      </gmd:organisationName>
+      <gmd:positionName>
+        <gco:CharacterString>Senior Systems Scientist</gco:CharacterString>
+      </gmd:positionName>
+      <gmd:contactInfo>
+        <gmd:CI_Contact>
+          <gmd:phone>
+            <gmd:CI_Telephone>
+              <gmd:voice>
+                <gco:CharacterString>+01-123-456-7890</gco:CharacterString>
+              </gmd:voice>
+              <gmd:facsimile>
+                <gco:CharacterString>+01-123-456-7890</gco:CharacterString>
+              </gmd:facsimile>
+            </gmd:CI_Telephone>
+          </gmd:phone>
+          <gmd:address>
+            <gmd:CI_Address>
+              <gmd:deliveryPoint>
+                <gco:CharacterString>4905 Dufferin Street</gco:CharacterString>
+              </gmd:deliveryPoint>
+              <gmd:city>
+                <gco:CharacterString>Toronto</gco:CharacterString>
+              </gmd:city>
+              <gmd:administrativeArea>
+                <gco:CharacterString>Ontario</gco:CharacterString>
+              </gmd:administrativeArea>
+              <gmd:postalCode>
+                <gco:CharacterString>M3H 5T4</gco:CharacterString>
+              </gmd:postalCode>
+              <gmd:country>
+                <gco:CharacterString>Canada</gco:CharacterString>
+              </gmd:country>
+              <gmd:electronicMailAddress>
+                <gco:CharacterString>foo at bar.tld</gco:CharacterString>
+              </gmd:electronicMailAddress>
+            </gmd:CI_Address>
+          </gmd:address>
+          <gmd:onlineResource>
+            <gmd:CI_OnlineResource>
+              <gmd:linkage>
+                <gmd:URL>https://www.ec.gc.ca/</gmd:URL>
+              </gmd:linkage>
+              <gmd:protocol>
+                <gco:CharacterString>WWW:LINK</gco:CharacterString>
+              </gmd:protocol>
+              <gmd:function>
+                <gmd:CI_OnLineFunctionCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="information" codeSpace="ISOTC211/19115">information</gmd:CI_OnLineFunctionCode>
+              </gmd:function>
+            </gmd:CI_OnlineResource>
+          </gmd:onlineResource>
+          <gmd:hoursOfService>
+            <gco:CharacterString>0700h - 1500h EST</gco:CharacterString>
+          </gmd:hoursOfService>
+          <gmd:contactInstructions>
+            <gco:CharacterString>email</gco:CharacterString>
+          </gmd:contactInstructions>
+        </gmd:CI_Contact>
+      </gmd:contactInfo>
+      <gmd:role>
+        <gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact" codeSpace="ISOTC211/19115">pointOfContact</gmd:CI_RoleCode>
+      </gmd:role>
+    </gmd:CI_ResponsibleParty>
+  </gmd:contact>
+  <gmd:dateStamp>
+    <gco:Date>2014-11-11</gco:Date>
+  </gmd:dateStamp>
+  <gmd:metadataStandardName>
+    <gco:CharacterString>ISO 19115:2003 - Geographic information - Metadata</gco:CharacterString>
+  </gmd:metadataStandardName>
+  <gmd:metadataStandardVersion>
+    <gco:CharacterString>ISO 19115:2003</gco:CharacterString>
+  </gmd:metadataStandardVersion>
+  <gmd:dataSetURI>
+    <gco:CharacterString>http://some/minted/uri</gco:CharacterString>
+  </gmd:dataSetURI>
+  <gmd:locale>
+    <gmd:PT_Locale id="locale-fr">
+      <gmd:languageCode>
+        <gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="fr" codeSpace="ISO 639-2">fr</gmd:LanguageCode>
+      </gmd:languageCode>
+      <gmd:characterEncoding>
+        <gmd:MD_CharacterSetCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="utf8" codeSpace="ISOTC211/19115">utf8</gmd:MD_CharacterSetCode>
+      </gmd:characterEncoding>
+    </gmd:PT_Locale>
+  </gmd:locale>
+  <gmd:spatialRepresentationInfo>
+    <gmd:MD_VectorSpatialRepresentation>
+      <gmd:topologyLevel>
+        <gmd:MD_TopologyLevelCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_TopologyLevelCode" codeListValue="geometryOnly" codeSpace="ISOTC211/19115">geometryOnly</gmd:MD_TopologyLevelCode>
+      </gmd:topologyLevel>
+      <gmd:geometricObjects>
+        <gmd:MD_GeometricObjects>
+          <gmd:geometricObjectType>
+            <gmd:MD_GeometricObjectTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_GeometricObjectTypeCode" codeListValue="point" codeSpace="ISOTC211/19115">point</gmd:MD_GeometricObjectTypeCode>
+          </gmd:geometricObjectType>
+        </gmd:MD_GeometricObjects>
+      </gmd:geometricObjects>
+    </gmd:MD_VectorSpatialRepresentation>
+  </gmd:spatialRepresentationInfo>
+  <gmd:referenceSystemInfo>
+    <gmd:MD_ReferenceSystem>
+      <gmd:referenceSystemIdentifier>
+        <gmd:RS_Identifier>
+          <gmd:authority>
+            <gmd:CI_Citation>
+              <gmd:title>
+                <gco:CharacterString>European Petroleum Survey Group (EPSG) Geodetic Parameter Registry</gco:CharacterString>
+              </gmd:title>
+              <gmd:date>
+                <gmd:CI_Date>
+                  <gmd:date>
+                    <gco:Date>2008-11-12</gco:Date>
+                  </gmd:date>
+                  <gmd:dateType>
+                    <gmd:CI_DateTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication" codeSpace="ISOTC211/19115">publication</gmd:CI_DateTypeCode>
+                  </gmd:dateType>
+                </gmd:CI_Date>
+              </gmd:date>
+              <gmd:citedResponsibleParty>
+                <gmd:CI_ResponsibleParty>
+                  <gmd:organisationName>
+                    <gco:CharacterString>European Petroleum Survey Group</gco:CharacterString>
+                  </gmd:organisationName>
+                  <gmd:contactInfo>
+                    <gmd:CI_Contact>
+                      <gmd:onlineResource>
+                        <gmd:CI_OnlineResource>
+                          <gmd:linkage>
+                            <gmd:URL>http://www.epsg-registry.org</gmd:URL>
+                          </gmd:linkage>
+                        </gmd:CI_OnlineResource>
+                      </gmd:onlineResource>
+                    </gmd:CI_Contact>
+                  </gmd:contactInfo>
+                  <gmd:role>
+                    <gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="originator" codeSpace="ISOTC211/19115">originator</gmd:CI_RoleCode>
+                  </gmd:role>
+                </gmd:CI_ResponsibleParty>
+              </gmd:citedResponsibleParty>
+            </gmd:CI_Citation>
+          </gmd:authority>
+          <gmd:code>
+            <gco:CharacterString>urn:ogc:def:crs:EPSG:4326</gco:CharacterString>
+          </gmd:code>
+          <gmd:version>
+            <gco:CharacterString>6.18.3</gco:CharacterString>
+          </gmd:version>
+        </gmd:RS_Identifier>
+      </gmd:referenceSystemIdentifier>
+    </gmd:MD_ReferenceSystem>
+  </gmd:referenceSystemInfo>
+  <gmd:identificationInfo>
+    <gmd:MD_DataIdentification>
+      <gmd:citation>
+        <gmd:CI_Citation>
+          <gmd:title xsi:type="gmd:PT_FreeText_PropertyType">
+            <gco:CharacterString>title in English</gco:CharacterString>
+            <gmd:PT_FreeText>
+              <gmd:textGroup>
+                <gmd:LocalisedCharacterString locale="#fr">title in French</gmd:LocalisedCharacterString>
+              </gmd:textGroup>
+            </gmd:PT_FreeText>
+          </gmd:title>
+          <gmd:date>
+            <gmd:CI_Date>
+              <gmd:date>
+                <gco:Date>2011-11-11</gco:Date>
+              </gmd:date>
+              <gmd:dateType>
+                <gmd:CI_DateTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="creation" codeSpace="ISOTC211/19115">creation</gmd:CI_DateTypeCode>
+              </gmd:dateType>
+            </gmd:CI_Date>
+          </gmd:date>
+          <gmd:date>
+            <gmd:CI_Date>
+              <gmd:date>
+                <gco:Date>2000-09-01</gco:Date>
+              </gmd:date>
+              <gmd:dateType>
+                <gmd:CI_DateTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication" codeSpace="ISOTC211/19115">publication</gmd:CI_DateTypeCode>
+              </gmd:dateType>
+            </gmd:CI_Date>
+          </gmd:date>
+        </gmd:CI_Citation>
+      </gmd:citation>
+      <gmd:abstract xsi:type="gmd:PT_FreeText_PropertyType">
+        <gco:CharacterString>abstract in English</gco:CharacterString>
+        <gmd:PT_FreeText>
+          <gmd:textGroup>
+            <gmd:LocalisedCharacterString locale="#fr">abstract in French</gmd:LocalisedCharacterString>
+          </gmd:textGroup>
+        </gmd:PT_FreeText>
+      </gmd:abstract>
+      <gmd:status>
+        <gmd:MD_ProgressCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ProgressCode" codeListValue="onGoing" codeSpace="ISOTC211/19115">onGoing</gmd:MD_ProgressCode>
+      </gmd:status>
+      <gmd:resourceMaintenance>
+        <gmd:MD_MaintenanceInformation>
+          <gmd:maintenanceAndUpdateFrequency>
+            <gmd:MD_MaintenanceFrequencyCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_MaintenanceFrequencyCode" codeListValue="continual" codeSpace="ISOTC211/19115">continual</gmd:MD_MaintenanceFrequencyCode>
+          </gmd:maintenanceAndUpdateFrequency>
+        </gmd:MD_MaintenanceInformation>
+      </gmd:resourceMaintenance>
+      <gmd:descriptiveKeywords>
+        <gmd:MD_Keywords>
+          <gmd:keyword xsi:type="gmd:PT_FreeText_PropertyType">
+            <gco:CharacterString>kw1 in English</gco:CharacterString>
+            <gmd:PT_FreeText>
+              <gmd:textGroup>
+                <gmd:LocalisedCharacterString locale="#fr">kw1 in French</gmd:LocalisedCharacterString>
+              </gmd:textGroup>
+            </gmd:PT_FreeText>
+          </gmd:keyword>
+          <gmd:keyword xsi:type="gmd:PT_FreeText_PropertyType">
+            <gco:CharacterString>kw2 in English</gco:CharacterString>
+            <gmd:PT_FreeText>
+              <gmd:textGroup>
+                <gmd:LocalisedCharacterString locale="#fr">kw2 in French</gmd:LocalisedCharacterString>
+              </gmd:textGroup>
+            </gmd:PT_FreeText>
+          </gmd:keyword>
+          <gmd:keyword xsi:type="gmd:PT_FreeText_PropertyType">
+            <gco:CharacterString>kw3 in English</gco:CharacterString>
+            <gmd:PT_FreeText>
+              <gmd:textGroup>
+                <gmd:LocalisedCharacterString locale="#fr">kw3 in French</gmd:LocalisedCharacterString>
+              </gmd:textGroup>
+            </gmd:PT_FreeText>
+          </gmd:keyword>
+          <gmd:type>
+            <gmd:MD_KeywordTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_KeywordTypeCode" codeListValue="" codeSpace="ISOTC211/19115"/>
+          </gmd:type>
+        </gmd:MD_Keywords>
+      </gmd:descriptiveKeywords>
+      <gmd:descriptiveKeywords>
+        <gmd:MD_Keywords>
+          <gmd:keyword>
+            <gco:CharacterString>FOO</gco:CharacterString>
+          </gmd:keyword>
+          <gmd:keyword>
+            <gco:CharacterString>BAR</gco:CharacterString>
+          </gmd:keyword>
+          <gmd:type>
+            <gmd:MD_KeywordTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_KeywordTypeCode" codeListValue="theme" codeSpace="ISOTC211/19115">theme</gmd:MD_KeywordTypeCode>
+          </gmd:type>
+        </gmd:MD_Keywords>
+      </gmd:descriptiveKeywords>
+      <gmd:descriptiveKeywords>
+        <gmd:MD_Keywords>
+          <gmd:keyword xsi:type="gmd:PT_FreeText_PropertyType">
+            <gco:CharacterString>kw1</gco:CharacterString>
+            <gmd:PT_FreeText>
+              <gmd:textGroup>
+                <gmd:LocalisedCharacterString locale="#fr">kw1</gmd:LocalisedCharacterString>
+              </gmd:textGroup>
+            </gmd:PT_FreeText>
+          </gmd:keyword>
+          <gmd:keyword xsi:type="gmd:PT_FreeText_PropertyType">
+            <gco:CharacterString>kw2</gco:CharacterString>
+            <gmd:PT_FreeText>
+              <gmd:textGroup>
+                <gmd:LocalisedCharacterString locale="#fr">kw2</gmd:LocalisedCharacterString>
+              </gmd:textGroup>
+            </gmd:PT_FreeText>
+          </gmd:keyword>
+          <gmd:type>
+            <gmd:MD_KeywordTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_KeywordTypeCode" codeListValue="" codeSpace="ISOTC211/19115"/>
+          </gmd:type>
+        </gmd:MD_Keywords>
+      </gmd:descriptiveKeywords>
+      <gmd:resourceConstraints>
+        <gmd:MD_LegalConstraints>
+          <gmd:accessConstraints>
+            <gmd:MD_RestrictionCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_RestrictionCode" codeListValue="otherRestrictions" codeSpace="ISOTC211/19115">otherRestrictions</gmd:MD_RestrictionCode>
+          </gmd:accessConstraints>
+        </gmd:MD_LegalConstraints>
+      </gmd:resourceConstraints>
+      <gmd:spatialRepresentationType>
+        <gmd:MD_SpatialRepresentationTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_SpatialRepresentationTypeCode" codeListValue="vector" codeSpace="ISOTC211/19115">vector</gmd:MD_SpatialRepresentationTypeCode>
+      </gmd:spatialRepresentationType>
+      <gmd:language>
+        <gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/" codeListValue="eng; CAN" codeSpace="ISO 639-2">eng; CAN</gmd:LanguageCode>
+      </gmd:language>
+      <gmd:characterSet>
+        <gmd:MD_CharacterSetCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="utf8" codeSpace="ISOTC211/19115">utf8</gmd:MD_CharacterSetCode>
+      </gmd:characterSet>
+      <gmd:topicCategory>
+        <gmd:MD_TopicCategoryCode>climatologyMeteorologyAtmosphere</gmd:MD_TopicCategoryCode>
+      </gmd:topicCategory>
+      <gmd:extent>
+        <gmd:EX_Extent>
+          <gmd:geographicElement>
+            <gmd:EX_GeographicBoundingBox>
+              <gmd:extentTypeCode>
+                <gco:Boolean>1</gco:Boolean>
+              </gmd:extentTypeCode>
+              <gmd:westBoundLongitude>
+                <gco:Decimal>-141</gco:Decimal>
+              </gmd:westBoundLongitude>
+              <gmd:eastBoundLongitude>
+                <gco:Decimal>-52</gco:Decimal>
+              </gmd:eastBoundLongitude>
+              <gmd:southBoundLatitude>
+                <gco:Decimal>42</gco:Decimal>
+              </gmd:southBoundLatitude>
+              <gmd:northBoundLatitude>
+                <gco:Decimal>84</gco:Decimal>
+              </gmd:northBoundLatitude>
+            </gmd:EX_GeographicBoundingBox>
+          </gmd:geographicElement>
+          <gmd:temporalElement>
+            <gmd:EX_TemporalExtent>
+              <gmd:extent>
+                <gml:TimePeriod gml:id="T001">
+                  <gml:beginPosition>1950-07-31</gml:beginPosition>
+                  <gml:endPosition indeterminatePosition="now"/>
+                </gml:TimePeriod>
+              </gmd:extent>
+            </gmd:EX_TemporalExtent>
+          </gmd:temporalElement>
+        </gmd:EX_Extent>
+      </gmd:extent>
+      <gmd:supplementalInformation>
+        <gco:CharacterString>http://geogratis.ca/geogratis/en/product/search.do?id=08DB5E85-7405-FE3A-2860-CC3663245625</gco:CharacterString>
+      </gmd:supplementalInformation>
+    </gmd:MD_DataIdentification>
+  </gmd:identificationInfo>
+  <gmd:contentInfo>
+    <gmd:MD_ImageDescription>
+      <gmd:attributeDescription>
+        <gco:RecordType>image</gco:RecordType>
+      </gmd:attributeDescription>
+      <gmd:contentType>
+        <gmd:MD_CoverageContentTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="image" codeSpace="ISOTC211/19115">image</gmd:MD_CoverageContentTypeCode>
+      </gmd:contentType>
+      <gmd:dimension>
+        <gmd:MD_Band id="B1">
+          <gmd:maxValue>
+            <gco:Real>958</gco:Real>
+          </gmd:maxValue>
+          <gmd:minValue>
+            <gco:Real>932</gco:Real>
+          </gmd:minValue>
+          <gmd:units>
+            <gml:UnitDefinition gml:id="units-1">
+              <gml:identifier codeSpace="none">nm</gml:identifier>
+            </gml:UnitDefinition>
+          </gmd:units>
+        </gmd:MD_Band>
+      </gmd:dimension>
+      <gmd:cloudCoverPercentage>
+        <gco:Real>72</gco:Real>
+      </gmd:cloudCoverPercentage>
+      <gmd:processingLevelCode>
+        <gmd:RS_Identifier>
+          <gmd:code>
+            <gco:CharacterString>1.0</gco:CharacterString>
+          </gmd:code>
+        </gmd:RS_Identifier>
+      </gmd:processingLevelCode>
+    </gmd:MD_ImageDescription>
+  </gmd:contentInfo>
+  <gmd:distributionInfo>
+    <gmd:MD_Distribution>
+      <gmd:distributor>
+        <gmd:MD_Distributor>
+          <gmd:distributorContact>
+            <gmd:CI_ResponsibleParty id="contact-distributor">
+              <gmd:individualName>
+                <gco:CharacterString>Tom Kralidis</gco:CharacterString>
+              </gmd:individualName>
+              <gmd:organisationName>
+                <gco:CharacterString>Environment Canada</gco:CharacterString>
+              </gmd:organisationName>
+              <gmd:positionName>
+                <gco:CharacterString>Senior Systems Scientist</gco:CharacterString>
+              </gmd:positionName>
+              <gmd:contactInfo>
+                <gmd:CI_Contact>
+                  <gmd:phone>
+                    <gmd:CI_Telephone>
+                      <gmd:voice>
+                        <gco:CharacterString>+01-123-456-7890</gco:CharacterString>
+                      </gmd:voice>
+                      <gmd:facsimile>
+                        <gco:CharacterString>+01-123-456-7890</gco:CharacterString>
+                      </gmd:facsimile>
+                    </gmd:CI_Telephone>
+                  </gmd:phone>
+                  <gmd:address>
+                    <gmd:CI_Address>
+                      <gmd:deliveryPoint>
+                        <gco:CharacterString>4905 Dufferin Street</gco:CharacterString>
+                      </gmd:deliveryPoint>
+                      <gmd:city>
+                        <gco:CharacterString>Toronto</gco:CharacterString>
+                      </gmd:city>
+                      <gmd:administrativeArea>
+                        <gco:CharacterString>Ontario</gco:CharacterString>
+                      </gmd:administrativeArea>
+                      <gmd:postalCode>
+                        <gco:CharacterString>M3H 5T4</gco:CharacterString>
+                      </gmd:postalCode>
+                      <gmd:country>
+                        <gco:CharacterString>Canada</gco:CharacterString>
+                      </gmd:country>
+                      <gmd:electronicMailAddress>
+                        <gco:CharacterString>foo at bar.tld</gco:CharacterString>
+                      </gmd:electronicMailAddress>
+                    </gmd:CI_Address>
+                  </gmd:address>
+                  <gmd:onlineResource>
+                    <gmd:CI_OnlineResource>
+                      <gmd:linkage>
+                        <gmd:URL>https://www.ec.gc.ca/</gmd:URL>
+                      </gmd:linkage>
+                      <gmd:protocol>
+                        <gco:CharacterString>WWW:LINK</gco:CharacterString>
+                      </gmd:protocol>
+                      <gmd:function>
+                        <gmd:CI_OnLineFunctionCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="information" codeSpace="ISOTC211/19115">information</gmd:CI_OnLineFunctionCode>
+                      </gmd:function>
+                    </gmd:CI_OnlineResource>
+                  </gmd:onlineResource>
+                  <gmd:hoursOfService>
+                    <gco:CharacterString>0700h - 1500h EST</gco:CharacterString>
+                  </gmd:hoursOfService>
+                  <gmd:contactInstructions>
+                    <gco:CharacterString>email</gco:CharacterString>
+                  </gmd:contactInstructions>
+                </gmd:CI_Contact>
+              </gmd:contactInfo>
+              <gmd:role>
+                <gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="distributor" codeSpace="ISOTC211/19115">distributor</gmd:CI_RoleCode>
+              </gmd:role>
+            </gmd:CI_ResponsibleParty>
+          </gmd:distributorContact>
+        </gmd:MD_Distributor>
+      </gmd:distributor>
+      <gmd:transferOptions>
+        <gmd:MD_DigitalTransferOptions>
+        </gmd:MD_DigitalTransferOptions>
+      </gmd:transferOptions>
+    </gmd:MD_Distribution>
+  </gmd:distributionInfo>
+  <gmd:metadataMaintenance>
+    <gmd:MD_MaintenanceInformation>
+      <gmd:maintenanceAndUpdateFrequency>
+        <gmd:MD_MaintenanceFrequencyCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_MaintenanceFrequencyCode" codeListValue="continual" codeSpace="ISOTC211/19115">continual</gmd:MD_MaintenanceFrequencyCode>
+      </gmd:maintenanceAndUpdateFrequency>
+      <gmd:maintenanceNote>
+        <gco:CharacterString>This metadata record was generated by pygeometa-0.6.dev0 (https://github.com/geopython/pygeometa)</gco:CharacterString>
+      </gmd:maintenanceNote>
+    </gmd:MD_MaintenanceInformation>
+  </gmd:metadataMaintenance>
+  <gmi:acquisitionInformation>
+    <gmi:MI_AcquisitionInformation>
+      <gmi:platform>
+        <gmi:MI_Platform>
+          <gmi:identifier>LANDSAT_8</gmi:identifier>
+          <gmi:description>Landsat 8</gmi:description>
+          <gmi:instrument>
+            <gmi:MI_Instrument>
+              <gmi:identifier>OLI_TIRS</gmi:identifier>
+              <gmi:type>INS-NOBS</gmi:type>
+            </gmi:MI_Instrument>
+          </gmi:instrument>
+        </gmi:MI_Platform>
+      </gmi:platform>
+    </gmi:MI_AcquisitionInformation>
+  </gmi:acquisitionInformation>
+</gmi:MI_Metadata>


=====================================
tests/test_iso_parsing.py
=====================================
@@ -33,7 +33,8 @@ def get_md_resource(file_path):
             'gmd:MD_Metadata', namespaces)) or data.find(
             './/' + util.nspath_eval('gmi:MI_Metadata', namespaces))
 
-        if mdelem is None and data.tag == '{http://www.isotc211.org/2005/gmd}MD_Metadata':
+        if mdelem is None and data.tag in ['{http://www.isotc211.org/2005/gmd}MD_Metadata',
+                                           '{http://www.isotc211.org/2005/gmi}MI_Metadata']:
             mdelem = data
 
     return mdelem
@@ -551,4 +552,39 @@ def test_md_parsing_geobretagne():
     assert_list(ci.language, 0)
     assert ci.includedwithdataset == False
     assert_list(ci.featuretypenames, 0)
-    assert_list(ci.featurecatalogues, 0)
\ No newline at end of file
+    assert_list(ci.featurecatalogues, 0)
+
+
+def test_md_parsing_19115_2():
+    """Test the parsing of a 19115-2 document
+
+    MD_Metadata record available in
+    tests/resources/iso_mi.xml
+
+    """
+    md_resource = get_md_resource(
+        'tests/resources/iso_mi.xml')
+    md = MD_Metadata(md_resource)
+
+    assert type(md) is MD_Metadata
+
+    assert md.identifier == '3f342f64-9348-11df-ba6a-0014c2c00eab'
+
+    ci = md.contentinfo[0]
+    assert ci.type == 'image'
+    assert ci.cloud_cover == '72'
+    assert ci.processing_level == '1.0'
+
+    band = ci.bands[0]
+    assert band.id == 'B1'
+    assert band.units == 'nm'
+    assert band.min == '932'
+    assert band.max == '958'
+
+    plt = md.acquisition.platforms[0]
+    assert plt.identifier == 'LANDSAT_8'
+    assert plt.description == 'Landsat 8'
+
+    inst = plt.instruments[0]
+    assert inst.identifier == 'OLI_TIRS'
+    assert inst.type == 'INS-NOBS'


=====================================
tests/test_ows_interfaces.py
=====================================
@@ -16,7 +16,7 @@ from owslib.util import OrderedDict
 
 # TODO, we should run all these from local XML documents (as per the WMS and WFS services)
 # CSW_SERVICE_URL = 'http://data.nodc.noaa.gov/geoportal/csw'
-CSW_SERVICE_URL = 'http://demo.pycsw.org/cite/csw'
+CSW_SERVICE_URL = 'https://demo.pycsw.org/cite/csw'
 WCS_SERVICE_URL = 'http://thredds.ucar.edu/thredds/wcs/grib/NCEP/NAM/CONUS_80km/best'
 
 


=====================================
tests/test_remote_metadata.py
=====================================
@@ -60,6 +60,7 @@ def mp_wfs_110(monkeypatch):
     monkeypatch.setattr(
         owslib.feature.common.WFSCapabilitiesReader, 'read', read)
 
+
 @pytest.fixture
 def mp_wfs_110_nometadata(monkeypatch):
     """Monkeypatch the call to the remote GetCapabilities request of WFS
@@ -821,6 +822,7 @@ class TestOffline(object):
 
 
 class TestOnline(object):
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -848,6 +850,7 @@ class TestOnline(object):
         for m in mdrecords:
             assert type(m) is owslib.iso.MD_Metadata
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -874,6 +877,7 @@ class TestOnline(object):
         for m in mdrecords:
             assert type(m) is owslib.iso.MD_Metadata
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -897,6 +901,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -922,6 +927,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -946,6 +952,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -969,6 +976,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WMS_SERVICE_URL),
                         reason="WMS service is unreachable")
@@ -996,6 +1004,7 @@ class TestOnline(object):
         for m in mdrecords:
             assert type(m) is owslib.iso.MD_Metadata
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WMS_SERVICE_URL),
                         reason="WMS service is unreachable")
@@ -1022,6 +1031,7 @@ class TestOnline(object):
         for m in mdrecords:
             assert type(m) is owslib.iso.MD_Metadata
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WMS_SERVICE_URL),
                         reason="WMS service is unreachable")
@@ -1045,6 +1055,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WMS_SERVICE_URL),
                         reason="WMS service is unreachable")
@@ -1070,6 +1081,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WMS_SERVICE_URL),
                         reason="WMS service is unreachable")
@@ -1094,6 +1106,7 @@ class TestOnline(object):
         assert type(mdrecords) is list
         assert len(mdrecords) == 0
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WMS_SERVICE_URL),
                         reason="WMS service is unreachable")


=====================================
tests/test_wfs_generic.py
=====================================
@@ -0,0 +1,168 @@
+from owslib.wfs import WebFeatureService
+from urllib.parse import urlparse
+from tests.utils import resource_file, sorted_url_query, service_ok
+
+import pytest
+
+SERVICE_URL = 'https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288'
+
+
+def test_caps_info():
+    getcapsin = open(resource_file("wfs_HSRS_GetCapabilities_1_1_0.xml"), "rb").read()
+    wfs = WebFeatureService('http://gis.bnhelp.cz/ows/crwfs', xml=getcapsin, version='1.1.0')
+    assert wfs.identification.service == 'OGC WFS'
+    assert wfs.identification.version == '1.1.0'
+    assert wfs.identification.title == 'Help Service Gazeteer'
+    assert wfs.identification.abstract == 'Vyhledavani sidel WFS'
+    assert wfs.identification.keywords == ['Czech republic', 'gazeeteer']
+    assert wfs.identification.fees == 'none'
+    assert wfs.identification.accessconstraints == 'for non profit use'
+    assert wfs.provider.name == 'Help Service Remote Sensing, ltd.'
+    assert wfs.provider.url == 'http://www.hsrs.cz'
+    assert wfs.provider.contact.email is None
+    assert wfs.provider.contact.phone is None
+    assert wfs.provider.contact.name == 'Stanislav Hol\xfd'
+    assert wfs.provider.contact.organization is None
+    assert wfs.provider.contact.city is None
+    assert wfs.provider.contact.region is None
+    assert wfs.provider.contact.postcode is None
+    assert wfs.provider.contact.country is None
+
+
+def test_getfeature():
+    getcapsin = open(resource_file("wfs_HSRS_GetCapabilities_1_1_0.xml"), "rb").read()
+    wfs = WebFeatureService('http://gis.bnhelp.cz/ows/crwfs', xml=getcapsin, version='1.1.0')
+
+    assert sorted(wfs.contents.keys()) == ['kraje', 'nuts1', 'nuts2', 'nuts3', 'okresy', 'orp', 'sidla', 'states']
+    assert wfs.contents['okresy'].crsOptions[0].getcodeurn() == 'urn:ogc:def:crs:EPSG::4326'
+    assert sorted_url_query(wfs.getGETGetFeatureRequest(typename=['okresy'], maxfeatures=2)) == [
+        'maxfeatures=2', 'request=GetFeature', 'service=WFS', 'typename=okresy', 'version=1.1.0']
+
+    assert sorted_url_query(wfs.getGETGetFeatureRequest(
+        typename=['okresy'], maxfeatures=2, bbox=[15, 49, 16, 51, 'urn:ogc:def:crs:EPSG:4326'])) == [
+        'bbox=49%2C15%2C51%2C16%2Curn%3Aogc%3Adef%3Acrs%3AEPSG%3A%3A4326',
+        'maxfeatures=2', 'request=GetFeature', 'service=WFS', 'typename=okresy', 'version=1.1.0']
+
+    assert sorted_url_query(wfs.getGETGetFeatureRequest(
+        typename=['okresy'], maxfeatures=2, bbox=[-685336, -993518, -684996, -993285])) == [
+        'bbox=-993518%2C-685336%2C-993285%2C-684996%2Curn%3Aogc%3Adef%3Acrs%3AEPSG%3A%3A4326',
+        'maxfeatures=2', 'request=GetFeature', 'service=WFS', 'typename=okresy', 'version=1.1.0']
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_outputformat_wfs_100():
+    import json
+    wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+                            version='1.0.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json')
+    assert json.dumps(json.loads(feature.read())) == '{...}'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_outputformat_wfs_110():
+    import json
+    wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+                            version='1.1.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json')
+    assert json.dumps(json.loads(feature.read())) == '{...}'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_outputformat_wfs_200():
+    import json
+    wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+                            version='2.0.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json')
+    assert json.dumps(json.loads(feature.read())) == '{...}'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_srsname_wfs_100():
+    import json
+    wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+                            version='1.0.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json',
+        srsname="EPSG:99999999")
+    # ServiceException: Unable to support srsName: EPSG:99999999
+
+    import json
+    wfs = WebFeatureService('https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+                            version='1.0.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json',
+        srsname="urn:x-ogc:def:crs:EPSG:4326")
+    assert json.dumps(json.loads(feature.read())) == '{...}'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_srsname_wfs_110():
+    import json
+    wfs = WebFeatureService(
+        'https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+        version='1.1.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json',
+        srsname="EPSG:99999999")
+    # ServiceException: SRSNAME EPSG:99999999 not supported.  Options: urn:x-ogc:def:crs:EPSG:102715
+
+    import json
+    wfs = WebFeatureService(
+        'https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+        version='1.0.0')
+    feature = wfs.getfeature(
+        typename=['sb:Project_Area'], maxfeatures=1, propertyname=None, outputFormat='application/json',
+        srsname="urn:x-ogc:def:crs:EPSG:4326")
+    assert json.dumps(json.loads(feature.read())) == '{...}'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_schema_wfs_100():
+    wfs = WebFeatureService(
+        'https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+        version='1.0.0')
+    schema = wfs.get_schema('footprint')
+    assert len(schema['properties']) == 4
+    assert schema['properties']['summary'] == 'string'
+    assert schema['geometry'] == 'Polygon'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_schema_wfs_110():
+    wfs = WebFeatureService(
+        'https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+        version='1.1.0')
+    schema = wfs.get_schema('footprint')
+    assert len(schema['properties']) == 4
+    assert schema['properties']['summary'] == 'string'
+    assert schema['geometry'] == '3D Polygon'
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+                    reason="WFS service is unreachable")
+def test_schema_wfs_200():
+    wfs = WebFeatureService(
+        'https://www.sciencebase.gov/catalogMaps/mapping/ows/53398e51e4b0db25ad10d288',
+        version='2.0.0')
+    schema = wfs.get_schema('footprint')
+    assert len(schema['properties']) == 4
+    assert schema['properties']['summary'] == 'string'
+    assert schema['geometry'] == '3D Polygon'


=====================================
tests/test_wfs_schema.py
=====================================
@@ -84,6 +84,7 @@ def mp_remote_describefeaturetype_typename_eq_attribute(monkeypatch):
 
 class TestOnline(object):
     """Class grouping online tests for the WFS get_schema method."""
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")
@@ -93,6 +94,7 @@ class TestOnline(object):
         wfs = WebFeatureService(WFS_SERVICE_URL, version=wfs_version)
         schema = wfs.get_schema('dov-pub:Boringen')
 
+    @pytest.mark.xfail
     @pytest.mark.online
     @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
                         reason="WFS service is unreachable")


=====================================
tests/test_wms_jpl_capabilities.py
=====================================
@@ -101,6 +101,7 @@ def test_wms_capabilities_style_without_title():
 SERVICE_URL = 'http://giswebservices.massgis.state.ma.us/geoserver/wms'
 
 
+ at pytest.mark.xfail
 @pytest.mark.online
 @pytest.mark.skipif(not service_ok(SERVICE_URL),
                     reason="WMS service is unreachable")



View it on GitLab: https://salsa.debian.org/debian-gis-team/owslib/-/compare/f4a6337c1f59faa729fa453d05cb14029aa0954c...6680ab425f343379388c47f384caa0cbcea1fb80

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/owslib/-/compare/f4a6337c1f59faa729fa453d05cb14029aa0954c...6680ab425f343379388c47f384caa0cbcea1fb80
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/20210121/bf91e596/attachment-0001.html>


More information about the Pkg-grass-devel mailing list