[Git][debian-gis-team/owslib][upstream] New upstream version 0.19.2
Bas Couwenberg
gitlab at salsa.debian.org
Fri Mar 13 06:03:21 GMT 2020
Bas Couwenberg pushed to branch upstream at Debian GIS Project / owslib
Commits:
515bfbc1 by Bas Couwenberg at 2020-03-13T06:50:11+01:00
New upstream version 0.19.2
- - - - -
27 changed files:
- .travis.yml
- CHANGES.rst
- VERSION.txt
- docs/en/index.rst
- owslib/__init__.py
- owslib/coverage/wcs100.py
- owslib/coverage/wcs200.py
- owslib/coverage/wcs201.py
- owslib/feature/common.py
- owslib/feature/wfs100.py
- owslib/feature/wfs110.py
- owslib/feature/wfs200.py
- owslib/ogcapi/__init__.py
- owslib/util.py
- owslib/wmts.py
- owslib/wps.py
- requirements-dev.txt
- requirements.txt
- setup.py
- tests/doctests/wfs_MapServerWFSFeature.txt
- − tests/doctests/wmts_RESTonly.txt
- tests/test_ogcapi_features_ldproxy.py
- tests/test_wms_getfeatureinfo_130.py
- + tests/test_wmts_restonly.py
- + tests/test_wps_describeprocess_language.py
- + tests/test_wps_execute_language.py
- + tests/test_wps_getcapabilities_language.py
Changes:
=====================================
.travis.yml
=====================================
@@ -1,6 +1,5 @@
language: python
python:
- - "3.5"
- "3.6"
- "3.7"
- "3.8"
=====================================
CHANGES.rst
=====================================
@@ -1,6 +1,25 @@
Changes
=======
+0.19.2 (2020-03-13)
+-------------------
+
+This release is an update.
+It drops Python 3.5 support and adds language support to the WPS module.
+
+A full list of commits for 0.19.2 can be found at:
+
+https://github.com/geopython/OWSLib/commits/0.19.2
+
+- Dropped Python 3.5 support (#659).
+- Fix pyproj deprecation (only use pyproj>=2) (#661).
+- WPS: Added support for multiple languages (#654, #655).
+- OGC API: fix api media type handling (#653).
+- WMTS: fix cartopy examples (#656).
+- Tests: fix wms tests (#657).
+- WCS: added WCS code example do documentation (#658).
+- WCS: fix params list (#663).
+
0.19.1 (2020-01-29)
-------------------
=====================================
VERSION.txt
=====================================
@@ -1 +1 @@
-0.19.1
+0.19.2
=====================================
docs/en/index.rst
=====================================
@@ -36,7 +36,7 @@ Standards Support
+-----------------------+-----------------------------+
| `OGC WFS`_ | 1.0.0, 1.1.0, 2.0.0, 3.0 |
+-----------------------+-----------------------------+
-| `OGC WCS`_ | 1.0.0, 1.1.0 |
+| `OGC WCS`_ | 1.0.0, 1.1.0, 2.0, 2.0.1 |
+-----------------------+-----------------------------+
| `OGC WMC`_ | 1.1.0 |
+-----------------------+-----------------------------+
@@ -253,7 +253,7 @@ compatible with a `Fiona schema object <https://fiona.readthedocs.io/en/latest/f
::
- >>> wfs11.get_schema('bvv:vg_ex')
+ >>> wfs11.get_schema('bvv:vg_ex')
>>> {'properties': {'land': 'string', 'modellart': 'string', 'objart': 'string', 'objart_txt': 'string', 'objid': 'string', 'hdu_x': 'short', 'beginn': 'string', 'ende': 'string', 'adm': 'string', 'avg': 'string', 'bez_gem': 'string', 'bez_krs': 'string', 'bez_lan': 'string', 'bez_rbz': 'string', 'sch': 'string'}, 'geometry': '3D MultiPolygon', 'geometry_column': 'geom'}
Download GML using ``typename`` and ``filter``. OWSLib currently only
@@ -300,7 +300,7 @@ services)
OGC API - Features 1.0
----------------------
-The OGC API - Features standar is a clean break from the traditional OGC service architecture
+The OGC API - Features standard is a clean break from the traditional OGC service architecture
(RESTful, JSON, OpenAPI) and as such OWSLib the code follows the same pattern.
.. code-block:: python
@@ -329,6 +329,48 @@ The OGC API - Features standar is a clean break from the traditional OGC service
WCS
---
+.. code-block:: python
+
+ >>> # Import OWSLib in Python once installed
+ ... from owslib.wcs import WebCoverageService
+
+ >>> # Create coverage object
+ ... my_wcs = WebCoverageService('http://ows.rasdaman.org/rasdaman/ows',
+ ... version='2.0.1')
+
+ >>> # Get list of coverages
+ ... print my_wcs.contents.keys()
+ ['RadianceColor', 'test_irr_cube_2', 'test_mean_summer_airtemp', 'test_double_1d', 'INSPIRE_EL', 'AverageChlorophyllScaled', 'INSPIRE_OI_RGB', 'Temperature4D', 'INSPIRE_OI_IR', 'visible_human', 'INSPIRE_WS_LC', 'meris_lai', 'climate_earth', 'mean_summer_airtemp', 'multiband', 'ls8_coastal_aerosol', 'NN3_3', 'NN3_2', 'NN3_1', 'NN3_4', 'AvgTemperatureColorScaled', 'AverageChloroColorScaled', 'lena', 'Germany_DTM', 'climate_cloud', 'FiLCCoverageBit', 'AverageChloroColor', 'LandsatMultiBand', 'RadianceColorScaled', 'AvgLandTemp', 'NIR', 'BlueMarbleCov']
+
+ >>> # Get geo-bounding boxes and native CRS
+ ... my_wcs.contents['AverageChlorophyllScaled'].boundingboxes
+ [{'nativeSrs': 'http://ows.rasdaman.org/def/crs-compound?1=http://ows.rasdaman.org/def/crs/EPSG/0/4326&2=http://ows.rasdaman.org/def/crs/OGC/0/UnixTime', 'bbox': (-90.0, -180.0, 90.0, 180.0)}]
+
+ >>> # Get axis labels
+ ... my_wcs.contents['AverageChlorophyllScaled'].grid.axislabels
+ ['Lat', 'Long', 'unix']
+
+ >>> # Get dimension
+ ... my_wcs.contents['AverageChlorophyllScaled'].grid.dimension
+ 3
+
+ >>> # Get grid lower and upper bounds
+ ... my_wcs.contents['AverageChlorophyllScaled'].grid.lowlimits
+ ['0', '0', '0']
+
+ >>> my_wcs.contents['AverageChlorophyllScaled'].grid.highlimits
+ ['119', '239', '5']
+
+ >>> # Get offset vectors for geo axes
+ ... my_wcs.contents['AverageChlorophyllScaled'].grid.offsetvectors
+ [['-1.5', '0', '0'], ['0', '1.5', '0'], ['0', '0', '1']]
+
+ >>> # For coverage with time axis get the date time values
+ ... my_wcs.contents['AverageChlorophyllScaled'].timepositions
+ [datetime.datetime(2015, 1, 1, 0, 0), datetime.datetime(2015, 2, 1, 0, 0), datetime.datetime(2015, 3, 1, 0, 0), datetime.datetime(2015, 4, 1, 0, 0), datetime.datetime(2015, 5, 1, 0, 0), datetime.datetime(2015, 7, 1, 0, 0)]
+
+
+
CSW
---
=====================================
owslib/__init__.py
=====================================
@@ -1 +1 @@
-__version__ = '0.19.1'
+__version__ = '0.19.2'
=====================================
owslib/coverage/wcs100.py
=====================================
@@ -18,7 +18,7 @@ import os
import errno
import logging
-from owslib.util import log
+from owslib.util import log, makeString
# function to save writing out WCS namespace in full each time
@@ -94,14 +94,6 @@ class WebCoverageService_1_0_0(WCSBase):
items.append((item, self.contents[item]))
return items
- def __makeString(self, value):
- # using repr unconditionally breaks things in some circumstances if a value is already a string
- if type(value) is not str:
- sval = repr(value)
- else:
- sval = value
- return sval
-
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):
"""Request and return a coverage from the WCS as a file-like object
@@ -134,7 +126,7 @@ class WebCoverageService_1_0_0(WCSBase):
request['Coverage'] = identifier
# request['identifier'] = ','.join(identifier)
if bbox:
- request['BBox'] = ','.join([self.__makeString(x) for x in bbox])
+ request['BBox'] = ','.join([makeString(x) for x in bbox])
else:
request['BBox'] = None
if time:
=====================================
owslib/coverage/wcs200.py
=====================================
@@ -113,14 +113,6 @@ class WebCoverageService_2_0_0(WCSBase):
items.append((item, self.contents[item]))
return items
- def __makeString(self, value):
- # using repr unconditionally breaks things in some circumstances if a value is already a string
- if type(value) is not str:
- sval = repr(value)
- else:
- sval = value
- return sval
-
def getCoverage(
self,
identifier=None,
@@ -224,16 +216,6 @@ class WebCoverageService_2_0_0(WCSBase):
u = openURL(base_url, data, method, self.cookies, auth=self.auth)
return u
- def is_number(self, s):
- """simple helper to test if value is number as requests with numbers dont
- need quote marks
- """
- try:
- float(s)
- return True
- except ValueError:
- return False
-
def getOperationByName(self, name):
"""Return a named operation item."""
for item in self.operations:
=====================================
owslib/coverage/wcs201.py
=====================================
@@ -113,14 +113,6 @@ class WebCoverageService_2_0_1(WCSBase):
items.append((item, self.contents[item]))
return items
- def __makeString(self, value):
- # using repr unconditionally breaks things in some circumstances if a value is already a string
- if type(value) is not str:
- sval = repr(value)
- else:
- sval = value
- return sval
-
def getCoverage(
self,
identifier=None,
@@ -225,16 +217,6 @@ class WebCoverageService_2_0_1(WCSBase):
u = openURL(base_url, data, method, self.cookies, auth=self.auth)
return u
- def is_number(self, s):
- """simple helper to test if value is number as requests with numbers dont
- need quote marks
- """
- try:
- float(s)
- return True
- except ValueError:
- return False
-
def getOperationByName(self, name):
"""Return a named operation item."""
for item in self.operations:
=====================================
owslib/feature/common.py
=====================================
@@ -1,21 +1,9 @@
-from io import StringIO
from owslib.etree import etree
from owslib.util import Authentication, openURL
from urllib.parse import urlencode, parse_qsl
-def makeStringIO(strval):
- """
- Helper method to make sure the StringIO being returned will work.
-
- Differences between Python 2.7/3.x mean we have a lot of cases to handle.
-
- TODO: skipped Python 2.x support. Is this still necessary?
- """
- return StringIO(strval.decode())
-
-
class WFSCapabilitiesReader(object):
"""Read and parse capabilities document into a lxml.etree infoset
"""
=====================================
owslib/feature/wfs100.py
=====================================
@@ -8,6 +8,7 @@
from owslib import util
+from io import BytesIO
from urllib.parse import urlencode
from owslib.util import (
testXMLValue,
@@ -27,7 +28,6 @@ from owslib.feature.schema import get_schema
from owslib.feature.common import (
WFSCapabilitiesReader,
AbstractContentMetadata,
- makeStringIO,
)
import pyproj
@@ -308,16 +308,16 @@ class WebFeatureService_1_0_0(object):
tree = etree.fromstring(data)
except BaseException:
# Not XML
- return makeStringIO(data)
+ return BytesIO(data)
else:
if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE:
se = tree.find(nspath("ServiceException", OGC_NAMESPACE))
raise ServiceException(str(se.text).strip())
else:
- return makeStringIO(data)
+ return BytesIO(data)
else:
if have_read:
- return makeStringIO(data)
+ return BytesIO(data)
return u
def getOperationByName(self, name):
@@ -395,14 +395,16 @@ class ContentMetadata(AbstractContentMetadata):
self.boundingBoxWGS84 = None
if b is not None and srs is not None:
- wgs84 = pyproj.Proj(init="epsg:4326")
+ wgs84 = pyproj.Proj("epsg:4326")
try:
- src_srs = pyproj.Proj(init=srs.text)
+ src_srs = pyproj.Proj(srs.text)
mincorner = pyproj.transform(
- src_srs, wgs84, b.attrib["minx"], b.attrib["miny"]
+ src_srs, wgs84, b.attrib["minx"], b.attrib["miny"],
+ always_xy=True,
)
maxcorner = pyproj.transform(
- src_srs, wgs84, b.attrib["maxx"], b.attrib["maxy"]
+ src_srs, wgs84, b.attrib["maxx"], b.attrib["maxy"],
+ always_xy=True,
)
self.boundingBoxWGS84 = (
=====================================
owslib/feature/wfs110.py
=====================================
@@ -7,6 +7,7 @@
# Contact email: tomkralidis at gmail.com
# =============================================================================
+from io import BytesIO
from urllib.parse import urlencode
from owslib.util import (
testXMLValue,
@@ -33,7 +34,6 @@ from owslib.feature import WebFeatureService_
from owslib.feature.common import (
WFSCapabilitiesReader,
AbstractContentMetadata,
- makeStringIO,
)
from owslib.namespaces import Namespaces
from owslib.util import log, openURL
@@ -346,16 +346,16 @@ class WebFeatureService_1_1_0(WebFeatureService_):
tree = etree.fromstring(data)
except BaseException:
# Not XML
- return makeStringIO(data)
+ return BytesIO(data)
else:
if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]:
se = tree.find(nspath_eval("ServiceException", namespaces["ogc"]))
raise ServiceException(str(se.text).strip())
else:
- return makeStringIO(data)
+ return BytesIO(data)
else:
if have_read:
- return makeStringIO(data)
+ return BytesIO(data)
return u
def getOperationByName(self, name):
=====================================
owslib/feature/wfs200.py
=====================================
@@ -18,11 +18,11 @@ from owslib.feature import WebFeatureService_
from owslib.feature.common import (
WFSCapabilitiesReader,
AbstractContentMetadata,
- makeStringIO,
)
from owslib.namespaces import Namespaces
# other imports
+from io import BytesIO
from urllib.parse import urlencode
import logging
@@ -313,16 +313,16 @@ class WebFeatureService_2_0_0(WebFeatureService_):
tree = etree.fromstring(data)
except BaseException:
# Not XML
- return makeStringIO(data)
+ return BytesIO(data)
else:
if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE:
se = tree.find(nspath("ServiceException", OGC_NAMESPACE))
raise ServiceException(str(se.text).strip())
else:
- return makeStringIO(data)
+ return BytesIO(data)
else:
if have_read:
- return makeStringIO(data)
+ return BytesIO(data)
return u
def getpropertyvalue(
=====================================
owslib/ogcapi/__init__.py
=====================================
@@ -8,9 +8,10 @@
import json
import logging
-
from urllib.parse import urljoin
+import yaml
+
from owslib import __version__
from owslib.util import http_get
@@ -68,15 +69,33 @@ class API(object):
"""
url = None
+ openapi_format = None
+ openapi_json_mimetype = 'application/vnd.oai.openapi+json;version=3.0'
+ openapi_yaml_mimetype = 'application/vnd.oai.openapi;version=3.0'
+
+ LOGGER.debug('Searching for OpenAPI JSON Document')
for l in self.links:
- if l['rel'] == 'service-desc':
+ if l['rel'] == 'service-desc' and l['type'] == openapi_json_mimetype:
+ openapi_format = openapi_json_mimetype
url = l['href']
+ break
+
+ LOGGER.debug('Searching for OpenAPI YAML Document')
+ if url is None:
+ if l['rel'] == 'service-desc' and l['type'] == openapi_yaml_mimetype:
+ openapi_format = openapi_yaml_mimetype
+ url = l['href']
+ break
if url is not None:
LOGGER.debug('Request: {}'.format(url))
- response = http_get(url, headers=REQUEST_HEADERS, auth=self.auth).json()
- return response
+ response = http_get(url, headers=REQUEST_HEADERS, auth=self.auth)
+ if openapi_format == openapi_json_mimetype:
+ content = response.json()
+ elif openapi_format == openapi_yaml_mimetype:
+ content = yaml.load(response.text)
+ return content
else:
msg = 'Did not find service-desc link'
LOGGER.error(msg)
=====================================
owslib/util.py
=====================================
@@ -786,22 +786,43 @@ def datetime_from_ansi(ansi):
return datumOrigin + timedelta(ansi)
-def param_list_to_url_string(self, param_list, param_name):
- """Converts list of tuples for certain WCS GetCoverage keyword arguments (subsets, resolutions, sizes) to a url-enconded
- string
+def is_number(s):
+ """simple helper to test if value is number as requests with numbers don't
+ need quote marks
+ """
+ try:
+ float(s)
+ return True
+ except ValueError:
+ return False
+
+
+def makeString(value):
+ # using repr unconditionally breaks things in some circumstances if a
+ # value is already a string
+ if type(value) is not str:
+ sval = repr(value)
+ else:
+ sval = value
+ return sval
+
+
+def param_list_to_url_string(param_list, param_name):
+ """Converts list of tuples for certain WCS GetCoverage keyword arguments
+ (subsets, resolutions, sizes) to a url-encoded string
"""
string = ''
for param in param_list:
if len(param) > 2:
- if not self.is_number(param[1]):
- string += "&" + urlencode({param_name: param[0] + '("' + self.__makeString(param[1]) + '","' + self.__makeString(param[2]) + '")'}) # noqa
+ if not is_number(param[1]):
+ string += "&" + urlencode({param_name: param[0] + '("' + makeString(param[1]) + '","' + makeString(param[2]) + '")'}) # noqa
else:
- string += "&" + urlencode({param_name: param[0] + "(" + self.__makeString(param[1]) + "," + self.__makeString(param[2]) + ")"}) # noqa
+ string += "&" + urlencode({param_name: param[0] + "(" + makeString(param[1]) + "," + makeString(param[2]) + ")"}) # noqa
else:
- if not self.is_number(param[1]):
- string += "&" + urlencode({param_name: param[0] + '("' + self.__makeString(param[1]) + '")'})
+ if not is_number(param[1]):
+ string += "&" + urlencode({param_name: param[0] + '("' + makeString(param[1]) + '")'}) # noqa
else:
- string += "&" + urlencode({param_name: param[0] + "(" + self.__makeString(param[1]) + ")"})
+ string += "&" + urlencode({param_name: param[0] + "(" + makeString(param[1]) + ")"}) # noqa
return string
=====================================
owslib/wmts.py
=====================================
@@ -639,7 +639,7 @@ class TileMatrixSetLink(object):
if tml.tilematrix in tilematrixlimits:
msg = ('TileMatrixLimits with tileMatrix "%s" '
'already exists' % tml.tilematrix)
- raise KeyError(msg)
+ warnings.warn(msg, RuntimeWarning)
tilematrixlimits[tml.tilematrix] = tml
links.append(TileMatrixSetLink(uri, tilematrixlimits))
=====================================
owslib/wps.py
=====================================
@@ -224,7 +224,7 @@ class WebProcessingService(object):
"""
def __init__(self, url, version=WPS_DEFAULT_VERSION, username=None, password=None, verbose=False, skip_caps=False,
- headers=None, verify=None, cert=None, timeout=None, auth=None):
+ headers=None, verify=None, cert=None, timeout=None, auth=None, language=None):
"""
Initialization method resets the object status.
By default it will execute a GetCapabilities invocation to the remote service,
@@ -241,6 +241,7 @@ class WebProcessingService(object):
self.verbose = verbose
self.headers = headers
self.timeout = timeout
+ self.language = language
# fields populated by method invocations
self._capabilities = None
@@ -248,6 +249,7 @@ class WebProcessingService(object):
self.provider = None
self.operations = []
self.processes = []
+ self.languages = None
if not skip_caps:
self.getcapabilities()
@@ -260,7 +262,11 @@ class WebProcessingService(object):
# read capabilities document
reader = WPSCapabilitiesReader(
- version=self.version, verbose=self.verbose, auth=self.auth)
+ version=self.version,
+ verbose=self.verbose,
+ auth=self.auth,
+ language=self.language,
+ )
if xml:
# read from stored XML file
self._capabilities = reader.readFromString(xml)
@@ -283,7 +289,11 @@ class WebProcessingService(object):
# read capabilities document
reader = WPSDescribeProcessReader(
- version=self.version, verbose=self.verbose, auth=self.auth)
+ version=self.version,
+ verbose=self.verbose,
+ auth=self.auth,
+ language=self.language,
+ )
if xml:
# read from stored XML file
rootElement = reader.readFromString(xml)
@@ -333,7 +343,8 @@ class WebProcessingService(object):
verbose=self.verbose,
headers=self.headers,
timeout=self.timeout,
- auth=self.auth
+ auth=self.auth,
+ language=self.language,
)
# build XML request from parameters
@@ -401,7 +412,7 @@ class WebProcessingService(object):
# loop over children WITHOUT requiring a specific namespace
for element in root:
- # thie element's namespace
+ # this element's namespace
ns = getNamespace(element)
# <ows:ServiceIdentification> metadata
@@ -448,17 +459,33 @@ class WebProcessingService(object):
if self.verbose is True:
dump(self.processes[-1])
+ # <wps:Languages>
+ # <wps:Default>
+ # <ows:Language>en-US</ows:Language>
+ # </wps:Default>
+ # <wps:Supported>
+ # <ows:Language>en-US</ows:Language>
+ # <ows:Language>fr-CA</ows:Language>
+ # ......
+ # </wps:Supported>
+ # </wps:Languages>
+ elif element.tag.endswith('Languages'):
+ self.languages = Languages(element)
+ if self.verbose:
+ dump(self.languages)
+
class WPSReader(object):
"""
Superclass for reading a WPS document into a lxml.etree infoset.
"""
- def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False, timeout=30, auth=None):
+ def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False, timeout=30, auth=None, language=None):
self.version = version
self.verbose = verbose
self.timeout = timeout
self.auth = auth or Authentication()
+ self.language = language
def _readFromUrl(self, url, data, timeout, method='Get', username=None, password=None,
headers=None, verify=True, cert=None):
@@ -470,6 +497,8 @@ class WPSReader(object):
_fix_auth(self.auth, username, password, verify, cert)
if method == 'Get':
# full HTTP request url
+ if self.language:
+ data["language"] = self.language
request_url = build_get_url(url, data, overwrite=True)
log.debug(request_url)
@@ -506,10 +535,10 @@ class WPSCapabilitiesReader(WPSReader):
Utility class that reads and parses a WPS GetCapabilities document into a lxml.etree infoset.
"""
- def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False, timeout=None, auth=None):
+ def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False, timeout=None, auth=None, language=None):
# superclass initializer
super(WPSCapabilitiesReader, self).__init__(
- version=version, verbose=verbose, timeout=timeout, auth=auth)
+ version=version, verbose=verbose, timeout=timeout, auth=auth, language=language)
def readFromUrl(self, url, username=None, password=None,
headers=None, verify=None, cert=None):
@@ -532,10 +561,10 @@ class WPSDescribeProcessReader(WPSReader):
Class that reads and parses a WPS DescribeProcess document into a etree infoset
"""
- def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False, timeout=None, auth=None):
+ def __init__(self, version=WPS_DEFAULT_VERSION, verbose=False, timeout=None, auth=None, language=None):
# superclass initializer
super(WPSDescribeProcessReader, self).__init__(
- version=version, verbose=verbose, timeout=timeout, auth=auth)
+ version=version, verbose=verbose, timeout=timeout, auth=auth, language=language)
def readFromUrl(self, url, identifier, username=None, password=None,
headers=None, verify=None, cert=None):
@@ -559,9 +588,9 @@ class WPSExecuteReader(WPSReader):
Class that reads and parses a WPS Execute response document into a etree infoset
"""
- def __init__(self, verbose=False, timeout=None, auth=None):
+ def __init__(self, verbose=False, timeout=None, auth=None, language=None):
# superclass initializer
- super(WPSExecuteReader, self).__init__(verbose=verbose, timeout=timeout, auth=auth)
+ super(WPSExecuteReader, self).__init__(verbose=verbose, timeout=timeout, auth=auth, language=language)
def readFromUrl(self, url, data={}, method='Get', username=None, password=None,
headers=None, verify=None, cert=None):
@@ -581,7 +610,7 @@ class WPSExecution(object):
"""
def __init__(self, version=WPS_DEFAULT_VERSION, url=None, username=None, password=None, verbose=False,
- headers=None, verify=None, cert=None, timeout=None, auth=None):
+ headers=None, verify=None, cert=None, timeout=None, auth=None, language=None):
# initialize fields
self.url = url
@@ -591,6 +620,7 @@ class WPSExecution(object):
self.auth = auth or Authentication()
_fix_auth(self.auth, username, password, verify, cert)
self.timeout = timeout
+ self.language = language
# request document
self.request = None
@@ -648,6 +678,8 @@ class WPSExecution(object):
root = etree.Element(nspath_eval('wps:Execute', namespaces))
root.set('service', 'WPS')
root.set('version', WPS_DEFAULT_VERSION)
+ if self.language:
+ root.set('language', self.language)
root.set(nspath_eval('xsi:schemaLocation', namespaces), '%s %s' %
(namespaces['wps'], WPS_DEFAULT_SCHEMA_LOCATION))
@@ -765,7 +797,7 @@ class WPSExecution(object):
:param int sleepSecs: number of seconds to sleep before returning control to the caller.
"""
- reader = WPSExecuteReader(verbose=self.verbose, auth=self.auth)
+ reader = WPSExecuteReader(verbose=self.verbose, auth=self.auth, language=self.language)
if response is None:
# override status location
if url is not None:
@@ -1914,3 +1946,21 @@ def printInputOutput(value, indent=''):
indent, value.reference, value.mimeType)))
for datum in value.data:
print(('{} Data Value: {}'.format(indent, printValue(datum))))
+
+
+class Languages(object):
+ """Initialize a WPS Languages construct"""
+ def __init__(self, infoset):
+ self._root = infoset
+ self.default = None
+ self.supported = []
+
+ for element in self._root:
+ if element.tag.endswith('Default'):
+ self.default = testXMLValue(element[0])
+ elif element.tag.endswith('Supported'):
+ for child in element:
+ self.supported.append(testXMLValue(child))
+
+ def __repr__(self):
+ return "<owslib.wps.Languages default='{}' supported={}>".format(self.default, self.supported)
=====================================
requirements-dev.txt
=====================================
@@ -4,7 +4,3 @@ pytest>=3.6
pytest-cov
Pillow
tox
-# install libraries to stop SSL related InsecurePlatformWarning
-pyopenssl ; python_version < '2.7.9'
-ndg-httpsclient ; python_version < '2.7.9'
-pyasn1 ; python_version < '2.7.9'
=====================================
requirements.txt
=====================================
@@ -1,4 +1,5 @@
python-dateutil>=1.5
pytz
requests>=1.0
-pyproj
+pyproj >=2
+pyyaml
=====================================
setup.py
=====================================
@@ -28,7 +28,7 @@ setup(name = 'OWSLib',
maintainer_email = 'tomkralidis at gmail.com',
url = 'https://geopython.github.io/OWSLib',
install_requires = reqs,
- python_requires = '>=3.5',
+ python_requires = '>=3.6',
cmdclass = {'test': PyTest},
packages = find_packages(exclude=["docs", "etc", "examples", "tests"]),
classifiers = [
=====================================
tests/doctests/wfs_MapServerWFSFeature.txt
=====================================
@@ -7,7 +7,7 @@ Test the getfeature method
>>> wfs = WebFeatureService('http://nsidc.org/cgi-bin/atlas_south?', version='1.0.0')
>>> response = wfs.getfeature(typename=['glaciers'], maxfeatures=5)
- >>> response.read().find('<wfs:FeatureCollection') > 0
+ >>> response.read().find(b'<wfs:FeatureCollection') > 0
True
Handle service exception
=====================================
tests/doctests/wmts_RESTonly.txt deleted
=====================================
@@ -1,33 +0,0 @@
-Imports:
-
- >>> from tests.utils import scratch_file
-
-ServiceMetadata:
-
- >>> from owslib.wmts import WebMapTileService
- >>> wmts = WebMapTileService("http://geoserv.weichand.de/mapproxy/wmts/1.0.0/WMTSCapabilities.xml")
- >>> wmts.identification.type
- 'OGC WMTS'
- >>> wmts.identification.version
- '1.0.0'
- >>> wmts.identification.title
- 'WMTS-Testserver DOP80'
-
-Content:
-
- >>> sorted(list(wmts.contents))
- ['dop80']
-
-RESTful WMTS:
-
- >>> wmts.restonly
- True
-
- >>> wmts.buildTileResource(layer='dop80', tilematrixset='webmercator', tilematrix='11', row='706', column='1089')
- 'http://geoserv.weichand.de/mapproxy/wmts/dop80/webmercator/11/1089/706.png'
-
- >>> tile = wmts.gettile(layer='dop80', tilematrixset='webmercator', tilematrix='11', row='706', column='1089')
- >>> out = open(scratch_file('bvv_bayern_dop80.png'), 'wb')
- >>> bytes_written = out.write(tile.read())
- >>> out.close()
-
=====================================
tests/test_ogcapi_features_ldproxy.py
=====================================
@@ -8,7 +8,6 @@ SERVICE_URL = 'https://www.ldproxy.nrw.de/rest/services/kataster/?f=json'
@pytest.mark.online
- at pytest.mark.skip(reason='api() call fails. See issue #625')
@pytest.mark.skipif(not service_ok(SERVICE_URL),
reason='service is unreachable')
def test_ogcapi_features_ldproxy():
@@ -20,6 +19,8 @@ def test_ogcapi_features_ldproxy():
conformance = w.conformance()
assert len(conformance['conformsTo']) == 5
- api = w.api()
- assert api['components']['parameters'] is not None
- assert api['paths'] is not None
+ # TODO: remove pytest.raises once ldproxy is fixed/updated
+ with pytest.raises(RuntimeError):
+ api = w.api()
+ assert api['components']['parameters'] is not None
+ assert api['paths'] is not None
=====================================
tests/test_wms_getfeatureinfo_130.py
=====================================
@@ -18,7 +18,6 @@ def test_wms_getfeatureinfo_130():
info_format="text/html", xy=(250, 250))
html_string1 = res1.read().decode("utf-8")
assert 'lkr_ex' in html_string1
- assert 'gmd_ex' in html_string1
res2 = wms.getfeatureinfo(
layers=['bvv:lkr_ex', 'bvv:gmd_ex'], srs='EPSG:31468',
=====================================
tests/test_wmts_restonly.py
=====================================
@@ -0,0 +1,32 @@
+from tests.utils import scratch_file
+from tests.utils import service_ok
+
+from owslib.wmts import WebMapTileService
+
+import pytest
+
+SERVICE_URL = "http://geoserv.weichand.de/mapproxy/wmts/1.0.0/WMTSCapabilities.xml"
+
+
+ at pytest.mark.online
+ at pytest.mark.skipif(not service_ok(SERVICE_URL),
+ reason="WMTS service is unreachable")
+def test_wmts_rest_only():
+ # ServiceMetadata
+ wmts = WebMapTileService(SERVICE_URL)
+ assert wmts.identification.type == 'OGC WMTS'
+ assert wmts.identification.version == '1.0.0'
+ assert wmts.identification.title == 'WMTS-Testserver DOP80'
+ # Content
+ assert sorted(list(wmts.contents)) == ['dop80']
+ # RESTful WMTS
+ assert wmts.restonly
+ resource = wmts.buildTileResource(
+ layer='dop80', tilematrixset='webmercator', tilematrix='11', row='706', column='1089')
+ assert resource == 'http://geoserv.weichand.de/mapproxy/wmts/dop80/webmercator/11/1089/706.png'
+
+ tile = wmts.gettile(
+ layer='dop80', tilematrixset='webmercator', tilematrix='11', row='706', column='1089')
+ out = open(scratch_file('bvv_bayern_dop80.png'), 'wb')
+ bytes_written = out.write(tile.read())
+ out.close()
=====================================
tests/test_wps_describeprocess_language.py
=====================================
@@ -0,0 +1,18 @@
+from owslib.wps import WebProcessingService
+import owslib.wps
+
+
+def test_wps_describeprocess_language(monkeypatch):
+
+ def mock_open_url(*args, **kwargs):
+ assert 'language=fr-CA' in args[1]
+
+ class FakeResponse:
+ def read(self):
+ return b'<xml></xml>'
+
+ return FakeResponse()
+
+ monkeypatch.setattr(owslib.wps, "openURL", mock_open_url)
+ wps = WebProcessingService('http://www.example.com', language='fr-CA', skip_caps=True)
+ wps.describeprocess('all')
=====================================
tests/test_wps_execute_language.py
=====================================
@@ -0,0 +1,31 @@
+from owslib.wps import WebProcessingService
+import owslib.wps
+
+
+def test_wps_execute_language(monkeypatch):
+
+ def raise_on_log_error(*a):
+ """Make sure the errors are raised, not only caught and logged"""
+ raise AssertionError
+
+ monkeypatch.setattr(owslib.wps.log, "error", raise_on_log_error)
+
+ monkeypatch.setattr(owslib.wps.WPSExecution, "parseResponse", lambda *a: None)
+ wps = WebProcessingService('http://www.example.com', language='fr-CA', skip_caps=True)
+ execution = wps.execute('test', [], response=b'<xml></xml>')
+
+ assert b'language="fr-CA"' in execution.request
+
+ def mock_open_url(*args, **kwargs):
+ assert 'language=fr-CA' in args[1]
+
+ class FakeResponse:
+ def read(self):
+ return b'<xml></xml>'
+
+ return FakeResponse()
+
+ monkeypatch.setattr(owslib.wps, "openURL", mock_open_url)
+
+ execution.status = 'ProcessSucceeded'
+ execution.checkStatus(url='http://www.example.com', response=None, sleepSecs=0)
=====================================
tests/test_wps_getcapabilities_language.py
=====================================
@@ -0,0 +1,36 @@
+from owslib.wps import WebProcessingService
+import owslib.wps
+from owslib.etree import etree
+
+
+def test_wps_getcapabilities_language(monkeypatch):
+
+ def mock_open_url(*args, **kwargs):
+ assert 'language=fr-CA' in args[1]
+
+ class FakeResponse:
+ def read(self):
+ return b'<xml></xml>'
+
+ return FakeResponse()
+
+ monkeypatch.setattr(owslib.wps, "openURL", mock_open_url)
+ WebProcessingService('http://www.example.com', language='fr-CA')
+
+
+def test_wps_getcapabilities_parse_languages():
+ xml = """
+ <wps:Languages xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows">
+ <wps:Default>
+ <ows:Language>en-US</ows:Language>
+ </wps:Default>
+ <wps:Supported>
+ <ows:Language>en-US</ows:Language>
+ <ows:Language>fr-CA</ows:Language>
+ </wps:Supported>
+ </wps:Languages>
+ """
+ element = etree.fromstring(xml)
+ languages = owslib.wps.Languages(element)
+ assert languages.default == 'en-US'
+ assert languages.supported == ['en-US', 'fr-CA']
View it on GitLab: https://salsa.debian.org/debian-gis-team/owslib/-/commit/515bfbc1a8f63a0f763c0c6cb2b6d1d896701a96
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/owslib/-/commit/515bfbc1a8f63a0f763c0c6cb2b6d1d896701a96
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/20200313/8d63b016/attachment-0001.html>
More information about the Pkg-grass-devel
mailing list