[Git][debian-gis-team/pywps][upstream] New upstream version 4.5.1
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Thu Dec 2 05:47:14 GMT 2021
Bas Couwenberg pushed to branch upstream at Debian GIS Project / pywps
Commits:
52ec3457 by Bas Couwenberg at 2021-12-02T06:32:52+01:00
New upstream version 4.5.1
- - - - -
21 changed files:
- .github/workflows/main.yml
- + SECURITY.md
- VERSION.txt
- debian/changelog
- docs/api_rest.rst
- pywps/__init__.py
- pywps/app/Process.py
- pywps/app/WPSRequest.py
- pywps/dependencies.py
- pywps/inout/basic.py
- pywps/inout/storage/file.py
- pywps/validator/complexvalidator.py
- requirements-extra.txt
- − requirements-gdal.txt
- requirements.txt
- setup.cfg
- + tests/test_assync_inout.py
- tests/test_execute.py
- tests/test_ows.py
- tests/test_storage.py
- tests/validator/test_complexvalidators.py
Changes:
=====================================
.github/workflows/main.yml
=====================================
@@ -4,10 +4,10 @@ on: [ push, pull_request ]
jobs:
main:
- runs-on: ubuntu-18.04
+ runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.6, 3.7, 3.8, 3.9]
+ python-version: [3.7, 3.8, 3.9]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_SERVICE_NAME: github
@@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout at v2
- name: Install packages
run: |
- sudo apt-get update && sudo apt-get -y install gdal-bin libgdal-dev libnetcdf-dev libhdf5-dev
+ sudo apt-get update && sudo apt-get -y install libnetcdf-dev libhdf5-dev
- uses: actions/setup-python at v2
name: Setup Python ${{ matrix.python-version }}
with:
@@ -26,17 +26,16 @@ jobs:
pip3 install -r requirements.txt
pip3 install -r requirements-dev.txt
pip3 install -r requirements-extra.txt
- pip3 install -r requirements-gdal.txt
- name: run tests ⚙️
run: pytest -v tests
- name: run coveralls ⚙️
run: coveralls
- if: matrix.python-version == 3.6
+ if: matrix.python-version == 3.7
- name: build docs 🏗️
run: |
pip3 install -e .
cd docs && make html
- if: matrix.python-version == 3.6
+ if: matrix.python-version == 3.7
- name: run flake8 ⚙️
run: flake8 pywps
- if: matrix.python-version == 3.6
+ if: matrix.python-version == 3.7
=====================================
SECURITY.md
=====================================
@@ -0,0 +1,16 @@
+# PyWPS Security Policy
+
+## Reporting
+
+Security/vulnerability reports **should not** be submitted through GitHub issues or public discussions, but instead please send your report
+to **geopython-security nospam @ lists.osgeo.org** - (remove the blanks and 'nospam').
+
+## Supported Versions
+
+The PyWPS Project Steering Committee will release patches for security vulnerabilities for the following versions:
+
+| Version | Supported |
+| ------- | ------------------ |
+| 4.5.x | :white_check_mark: |
+| 4.4.x | :white_check_mark: |
+| < 4.4 | previous versions | :x: |
=====================================
VERSION.txt
=====================================
@@ -1 +1 @@
-4.5.0
+4.5.1
=====================================
debian/changelog
=====================================
@@ -1,3 +1,17 @@
+pywps (4.5.1) trusty; urgency=medium
+
+ * Fix app/Process.py to cope with None mimetype (#620)
+ * Add security policy (#621)
+ * Better error handling in WPSRequest.json() (#622)
+ * Fix output mimetype assuming string (#626)
+ * Resolve invalid Exception.msg unknown attribute (#629)
+ * An input default value is only set when min_occurs==0 (#631)
+ * Fix Sphinx build for UbuntuGIS packages (#634)
+ * Remove gdal from dependencies (#638)
+ * Fix bug triggered when storage requires the creation of recursive directories (#636)
+
+ -- Carsten Ehbrecht <ehbrecht at dkrz.de> Mon, 29 Nov 2021 18:00:00 +0000
+
pywps (4.5.0) trusty; urgency=medium
* Initial implementation of OGC API - Processes / REST API (#612, #614)
=====================================
docs/api_rest.rst
=====================================
@@ -33,14 +33,14 @@ The default mimetype (output format) can be set by adding `&f=json` or `&f=xml`
GET GetCapabilities Request URL:
-.. code-block::
+.. code-block:: json
http://localhost:5000/processes/?service=WPS
http://localhost:5000/wps/?request=GetCapabilities&service=WPS&f=json
GET GetCapabilities Response:
-.. code-block::
+.. code-block:: json
{
"pywps_version": "4.5.0",
@@ -113,14 +113,14 @@ GET GetCapabilities Response:
GET DescribeProcess Request URL:
-.. code-block::
+.. code-block:: json
http://localhost:5000/processes/say_hello?service=WPS
http://localhost:5000/wps/?request=DescribeProcess&service=WPS&identifier=say_hello&version=1.0.0&f=json
GET DescribeProcess Response:
-.. code-block::
+.. code-block:: json
{
"pywps_version": "4.5.0",
@@ -178,13 +178,13 @@ GET DescribeProcess Response:
GET Execute Request URL:
-.. code-block::
+.. code-block:: json
http://localhost:5000/wps?/service=wps&version=1.0.0&request=execute&Identifier=say_hello&storeExecuteResponse=true&DataInputs=name=Dude&f=json
GET Execute Response:
-.. code-block::
+.. code-block:: json
{
"status": {
@@ -200,13 +200,13 @@ GET Execute Response:
GET Execute Request URL (Raw output):
-.. code-block::
+.. code-block:: json
http://localhost:5000/wps?/service=wps&version=1.0.0&request=execute&Identifier=say_hello&storeExecuteResponse=true&DataInputs=name=Dude&RawDataOutput=output
GET Execute Response:
-.. code-block::
+.. code-block:: json
Hello Dude
@@ -224,13 +224,13 @@ Example of a `Say Hello` POST request:
POST Execute Request URL:
-.. code-block::
+.. code-block:: json
http://localhost:5000/jobs
POST Execute Request Body:
-.. code-block::
+.. code-block:: json
{
"identifier": "say_hello",
@@ -241,7 +241,7 @@ POST Execute Request Body:
POST Execute Response:
-.. code-block::
+.. code-block:: json
{
"status": {
@@ -260,7 +260,7 @@ Example of a `Say Hello` POST request with raw output:
POST Execute Request Body:
-.. code-block::
+.. code-block:: json
{
"identifier": "say_hello",
@@ -273,7 +273,7 @@ POST Execute Request Body:
POST Execute Response:
-.. code-block::
+.. code-block:: json
Hello Dude
@@ -281,13 +281,13 @@ Alternatively, the `identifier` and optionally the raw output name can be encode
POST Execute Request URL (with `identifier`):
-.. code-block::
+.. code-block:: json
http://localhost:5000/jobs/say_hello
POST Execute Request Body:
-.. code-block::
+.. code-block:: json
{
"name": "Dude"
@@ -295,7 +295,7 @@ POST Execute Request Body:
POST Execute Response:
-.. code-block::
+.. code-block:: json
{
"status": {
@@ -311,13 +311,13 @@ POST Execute Response:
POST Execute Request URL (with `identifier` and output name):
-.. code-block::
+.. code-block:: json
http://localhost:5000/jobs/say_hello/output
POST Execute Request Body:
-.. code-block::
+.. code-block:: json
{
"name": "Dude"
@@ -325,14 +325,14 @@ POST Execute Request Body:
POST Execute Response:
-.. code-block::
+.. code-block:: json
Hello Dude
Example for a reference input:
-.. code-block::
+.. code-block:: json
"raster": {
"type": "reference",
@@ -342,7 +342,7 @@ Example for a reference input:
Example for a BoundingBox input:
(bbox default axis order is yx (EPSG:4326), i.e. miny, minx, maxy, maxx)
-.. code-block::
+.. code-block:: json
"extent": {
"type": "bbox",
@@ -353,7 +353,7 @@ Example for a BoundingBox input:
Example for a ComplexInput input:
(the data is a standard GeoJSON)
-.. code-block::
+.. code-block:: json
"cutline": {
"type": "complex",
=====================================
pywps/__init__.py
=====================================
@@ -9,7 +9,7 @@ import os
from lxml.builder import ElementMaker
-__version__ = "4.5.0"
+__version__ = "4.5.1"
LOGGER = logging.getLogger('PYWPS')
LOGGER.debug('setting core variables')
=====================================
pywps/app/Process.py
=====================================
@@ -458,6 +458,9 @@ class Process(object):
is_reference = wps_request.outputs[wps_outpt].get('asReference', 'false')
mimetype = wps_request.outputs[wps_outpt].get('mimetype', '')
+ if not isinstance(mimetype, str):
+ mimetype = ''
+
if is_reference.lower() == 'true':
# check if store is supported
if self.store_supported == 'false':
@@ -471,9 +474,9 @@ class Process(object):
for outpt in self.outputs:
if outpt.identifier == wps_outpt:
outpt.as_reference = is_reference
- if isinstance(outpt, ComplexOutput) and mimetype != '':
+ if isinstance(outpt, ComplexOutput) and mimetype:
data_format = [f for f in outpt.supported_formats if f.mime_type == mimetype]
if len(data_format) == 0:
raise InvalidParameterValue(
- 'MimeType ' + mimetype + ' not valid')
+ f"MimeType {mimetype} not valid")
outpt.data_format = data_format[0]
=====================================
pywps/app/WPSRequest.py
=====================================
@@ -108,7 +108,7 @@ class WPSRequest(object):
try:
doc = etree.fromstring(self.http_request.get_data())
except Exception as e:
- raise NoApplicableCode(e.msg)
+ raise NoApplicableCode(str(e))
operation = doc.tag
version = get_version_from_ns(doc.nsmap[doc.prefix])
self.set_version(version)
@@ -122,7 +122,7 @@ class WPSRequest(object):
try:
jdoc = json.loads(self.http_request.get_data())
except Exception as e:
- raise NoApplicableCode(e.msg)
+ raise NoApplicableCode(str(e))
if self.identifier is not None:
jdoc = {'inputs': jdoc}
else:
@@ -491,8 +491,13 @@ class WPSRequest(object):
inpt_def = {"data": inpt_def}
if 'identifier' not in inpt_def:
inpt_def['identifier'] = identifier
- inpt = input_from_json(inpt_def)
- self.inputs[identifier].append(inpt)
+ try:
+ inpt = input_from_json(inpt_def)
+ self.inputs[identifier].append(inpt)
+ except Exception as e:
+ LOGGER.warning(e)
+ LOGGER.warning(f'skipping input: {identifier}')
+ pass
def get_inputs_from_xml(doc):
=====================================
pywps/dependencies.py
=====================================
@@ -6,13 +6,6 @@
import warnings
try:
- import osgeo
- from osgeo import gdal, ogr
-except ImportError:
- warnings.warn('Complex validation requires GDAL/OGR support.')
- ogr = None
-
-try:
- import netCDF4
+ import netCDF4 # noqa
except ImportError:
warnings.warn('Complex validation requires netCDF4 support.')
=====================================
pywps/inout/basic.py
=====================================
@@ -250,16 +250,23 @@ class IOHandler(object):
value_type = value_type or getattr(self, '_default_type')
if value:
- if value_type == SOURCE_TYPE.DATA:
- self.data = value
- elif value_type == SOURCE_TYPE.MEMORY:
- raise NotImplementedError
- elif value_type == SOURCE_TYPE.FILE:
- self.file = value
- elif value_type == SOURCE_TYPE.STREAM:
- self.stream = value
- elif value_type == SOURCE_TYPE.URL:
- self.url = value
+ # only set default when a value is optional
+ if self.min_occurs == 0:
+ if value_type == SOURCE_TYPE.DATA:
+ self.data = value
+ elif value_type == SOURCE_TYPE.MEMORY:
+ raise NotImplementedError
+ elif value_type == SOURCE_TYPE.FILE:
+ self.file = value
+ elif value_type == SOURCE_TYPE.STREAM:
+ self.stream = value
+ elif value_type == SOURCE_TYPE.URL:
+ self.url = value
+ else:
+ # when a value is requried the default value will be ignored
+ LOGGER.warning(
+ "The given default value will not be used"
+ " because is is required to provide a value.")
def _build_file_name(self, href=''):
"""Return a file name for the local system."""
=====================================
pywps/inout/storage/file.py
=====================================
@@ -69,6 +69,14 @@ class FileStorage(CachedStorage):
self.copy_function = copy_function
def _do_store(self, output):
+ """Copy output to final storage location.
+
+ - Create output directory
+ - Check available file space
+ - Create output file name, taking care of possible duplicates
+ - Copy / link output in work directory to output directory
+ - Return store type, output path and output URL
+ """
import platform
import math
import tempfile
@@ -78,6 +86,11 @@ class FileStorage(CachedStorage):
request_uuid = output.uuid or uuid.uuid1()
+ # Create a target folder for each request
+ target = os.path.join(self.target, str(request_uuid))
+ if not os.path.exists(target):
+ os.makedirs(target)
+
# st.blksize is not available in windows, skips the validation on windows
if platform.system() != 'Windows':
file_block_size = os.stat(file_name).st_blksize
@@ -91,11 +104,6 @@ class FileStorage(CachedStorage):
if avail_size < actual_file_size:
raise NotEnoughStorage('Not enough space in {} to store {}'.format(self.target, file_name))
- # create a target folder for each request
- target = os.path.join(self.target, str(request_uuid))
- if not os.path.exists(target):
- os.makedirs(target)
-
# build output name
output_name, suffix = _build_output_name(output)
# build tempfile in case of duplicates
@@ -116,7 +124,7 @@ class FileStorage(CachedStorage):
url = self.url("{}/{}".format(request_uuid, just_file_name))
LOGGER.info('File output URI: {}'.format(url))
- return (STORE_TYPE.PATH, output_name, url)
+ return STORE_TYPE.PATH, output_name, url
@staticmethod
def copy(src, dst, copy_function=None):
@@ -134,7 +142,7 @@ class FileStorage(CachedStorage):
try:
os.link(src, dst)
except Exception:
- LOGGER.warn("Could not create hardlink. Fallback to copy.")
+ LOGGER.warning("Could not create hardlink. Fallback to copy.")
FileStorage.copy(src, dst)
else:
shutil.copy2(src, dst)
=====================================
pywps/validator/complexvalidator.py
=====================================
@@ -35,7 +35,7 @@ def validategml(data_input, mode):
`MODE.SIMPLE`
the mimetype will be checked
`MODE.STRICT`
- `GDAL/OGR <http://gdal.org/>`_ is used for getting the proper format.
+ `Fiona` is used for getting the proper format.
`MODE.VERYSTRICT`
the :class:`lxml.etree` is used along with given input `schema` and the
GML file is properly validated against given schema.
@@ -55,11 +55,11 @@ def validategml(data_input, mode):
if mode >= MODE.STRICT:
- from pywps.dependencies import ogr
- data_source = ogr.Open(data_input.file)
- if data_source:
- passed = (data_source.GetDriver().GetName() == "GML")
- else:
+ try:
+ import fiona
+ data_source = fiona.open(data_input.file)
+ passed = (data_source.driver == "GML")
+ except (ModuleNotFoundError, ImportError):
passed = False
if mode >= MODE.VERYSTRICT:
@@ -89,7 +89,7 @@ def validategpx(data_input, mode):
`MODE.SIMPLE`
the mimetype will be checked
`MODE.STRICT`
- `GDAL/OGR <http://gdal.org/>`_ is used for getting the proper format.
+ `Fiona` is used for getting the proper format.
`MODE.VERYSTRICT`
the :class:`lxml.etree` is used along with given input `schema` and the
GPX file is properly validated against given schema.
@@ -109,11 +109,11 @@ def validategpx(data_input, mode):
if mode >= MODE.STRICT:
- from pywps.dependencies import ogr
- data_source = ogr.Open(data_input.file)
- if data_source:
- passed = (data_source.GetDriver().GetName() == "GPX")
- else:
+ try:
+ import fiona
+ data_source = fiona.open(data_input.file)
+ passed = (data_source.driver == "GPX")
+ except (ModuleNotFoundError, ImportError):
passed = False
if mode >= MODE.VERYSTRICT:
@@ -249,11 +249,11 @@ def validategeojson(data_input, mode):
if mode >= MODE.STRICT:
- from pywps.dependencies import ogr
- data_source = ogr.Open(data_input.file)
- if data_source:
- passed = (data_source.GetDriver().GetName() == "GeoJSON")
- else:
+ try:
+ import fiona
+ data_source = fiona.open(data_input.file)
+ passed = (data_source.driver == "GeoJSON")
+ except (ModuleNotFoundError, ImportError):
passed = False
if mode >= MODE.VERYSTRICT:
@@ -317,22 +317,11 @@ def validateshapefile(data_input, mode):
if mode >= MODE.STRICT:
- from pywps.dependencies import ogr
-
- import zipfile
- z = zipfile.ZipFile(data_input.file)
- shape_name = None
- for name in z.namelist():
- z.extract(name, data_input.tempdir)
- if os.path.splitext(name)[1].lower() == '.shp':
- shape_name = name
-
- if shape_name:
- data_source = ogr.Open(os.path.join(data_input.tempdir, shape_name))
-
- if data_source:
- passed = (data_source.GetDriver().GetName() == "ESRI Shapefile")
- else:
+ try:
+ import fiona
+ sf = fiona.open(data_input.file)
+ passed = (sf.driver == "ESRI Shapefile")
+ except (ModuleNotFoundError, ImportError):
passed = False
return passed
@@ -357,10 +346,10 @@ def validategeotiff(data_input, mode):
if mode >= MODE.STRICT:
try:
- from pywps.dependencies import osgeo # noqa
- data_source = osgeo.gdal.Open(data_input.file)
- passed = (data_source.GetDriver().ShortName == "GTiff")
- except ImportError:
+ from geotiff import GeoTiff
+ data_source = GeoTiff(data_input.file)
+ passed = (data_source.crs_code > 0)
+ except (ModuleNotFoundError, ImportError):
passed = False
return passed
=====================================
requirements-extra.txt
=====================================
@@ -1 +1 @@
-netCDF4
\ No newline at end of file
+netCDF4
=====================================
requirements-gdal.txt deleted
=====================================
@@ -1,3 +0,0 @@
-# On your system check the GDAL version using gdalinfo --version, and adjust
-# the GDAL version here to suit your system
-GDAL==2.1.0 --global-option=build_ext --global-option="-I/usr/include/gdal"
=====================================
requirements.txt
=====================================
@@ -8,3 +8,5 @@ SQLAlchemy
werkzeug
MarkupSafe
humanize
+geotiff
+fiona
=====================================
setup.cfg
=====================================
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 4.5.0
+current_version = 4.5.1
commit = False
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+).(?P<patch>\d+)
=====================================
tests/test_assync_inout.py
=====================================
@@ -0,0 +1,68 @@
+##################################################################
+# Copyright 2018 Open Source Geospatial Foundation and others #
+# licensed under MIT, Please consult LICENSE.txt for details #
+##################################################################
+
+from pywps import Service, Process, LiteralInput, ComplexOutput
+from pywps import FORMATS
+from pywps import get_ElementMakerForVersion
+from pywps.tests import client_for
+
+VERSION = "1.0.0"
+
+WPS, OWS = get_ElementMakerForVersion(VERSION)
+
+
+def create_inout():
+
+ def inout(request, response):
+ response.outputs['text'].data = request.inputs['text'][0].data
+ return response
+
+ return Process(handler=inout,
+ identifier='inout',
+ title='InOut',
+ inputs=[
+ LiteralInput('text', 'Text', data_type='string')
+ ],
+ outputs=[
+ ComplexOutput(
+ 'text',
+ title='Text',
+ supported_formats=[FORMATS.TEXT, ]
+ ),
+ ],
+ store_supported=True,
+ status_supported=True
+ )
+
+
+def test_assync_inout():
+ client = client_for(Service(processes=[create_inout()]))
+ request_doc = WPS.Execute(
+ OWS.Identifier('inout'),
+ WPS.DataInputs(
+ WPS.Input(
+ OWS.Identifier('text'),
+ WPS.Data(
+ WPS.LiteralData(
+ "Hello World"
+ )
+ )
+ )
+ ),
+ WPS.ResponseForm(
+ WPS.ResponseDocument(
+ WPS.Output(
+ OWS.Identifier("text")
+ ),
+ ),
+ ),
+ version="1.0.0"
+ )
+ resp = client.post_xml(doc=request_doc)
+ assert resp.status_code == 200
+
+ # TODO:
+ # . extract the status URL from the response
+ # . send a status request
=====================================
tests/test_execute.py
=====================================
@@ -131,6 +131,7 @@ def create_complex_proces(mime_type: str = 'gml'):
ComplexInput(
'complex',
'Complex input',
+ min_occurs=0,
default="DEFAULT COMPLEX DATA",
supported_formats=[frmt])
],
=====================================
tests/test_ows.py
=====================================
@@ -10,7 +10,6 @@ import os
import tempfile
import unittest
from pywps import Service, Process, ComplexInput, ComplexOutput, Format, FORMATS, get_format
-from pywps.dependencies import ogr
from pywps.exceptions import NoApplicableCode
from pywps import get_ElementMakerForVersion
import pywps.configuration as config
@@ -26,41 +25,8 @@ def create_feature():
def feature(request, response):
input = request.inputs['input'][0].file
- # What do we need to assert a Complex input?
- # assert type(input) is str
-
- # open the input file
- try:
- inSource = ogr.Open(input)
- except Exception as e:
- return "Could not open given vector file: {}".format(e)
- inLayer = inSource.GetLayer()
-
- # create output file
- out = 'point'
- outPath = os.path.join(tempfile.gettempdir(), out)
-
- driver = ogr.GetDriverByName('GML')
- outSource = driver.CreateDataSource(
- outPath,
- ["XSISCHEMAURI=http://schemas.opengis.net/gml/2.1.2/feature.xsd"])
- outLayer = outSource.CreateLayer(out, None, ogr.wkbUnknown)
-
- # get the first feature
- inFeature = inLayer.GetNextFeature()
- inGeometry = inFeature.GetGeometryRef()
-
- # make the buffer
- buff = inGeometry.Buffer(float(100000))
-
- # create output feature to the file
- outFeature = ogr.Feature(feature_def=outLayer.GetLayerDefn())
- outFeature.SetGeometryDirectly(buff)
- outLayer.CreateFeature(outFeature)
- outFeature.Destroy()
-
response.outputs['output'].data_format = FORMATS.GML
- response.outputs['output'].file = outPath
+ response.outputs['output'].file = input
return response
return Process(handler=feature,
=====================================
tests/test_storage.py
=====================================
@@ -2,6 +2,7 @@
# Copyright 2018 Open Source Geospatial Foundation and others #
# licensed under MIT, Please consult LICENSE.txt for details #
##################################################################
+import pytest
from pywps.inout.storage.builder import StorageBuilder
from pywps.inout.storage.file import FileStorage
@@ -9,26 +10,45 @@ from pywps.inout.storage.s3 import S3Storage
from pywps import configuration
+from pathlib import Path
import unittest
+import tempfile
-class StorageBuilderTests(unittest.TestCase):
+
+ at pytest.fixture
+def fake_output(tmp_path):
+ class FakeOutput(object):
+ """Fake output object for testing."""
+ def __init__(self):
+ self.identifier = "fake_output"
+ self.file = self._get_file()
+ self.uuid = None
+
+ def _get_file(self):
+ fn = tmp_path / 'file.tiff'
+ fn.touch()
+ return str(fn.absolute())
+
+ return FakeOutput()
+
+
+class TestStorageBuilder():
def test_default_storage(self):
storage = StorageBuilder.buildStorage()
- self.assertIsInstance(storage, FileStorage)
-
+ assert isinstance(storage, FileStorage)
def test_s3_storage(self):
configuration.CONFIG.set('server', 'storagetype', 's3')
storage = StorageBuilder.buildStorage()
- self.assertIsInstance(storage, S3Storage)
-
-def load_tests(loader=None, tests=None, pattern=None):
- """Load local tests
- """
- if not loader:
- loader = unittest.TestLoader()
- suite_list = [
- loader.loadTestsFromTestCase(StorageBuilderTests)
- ]
- return unittest.TestSuite(suite_list)
\ No newline at end of file
+ assert isinstance(storage, S3Storage)
+
+ def test_recursive_directory_creation(self, fake_output):
+ """Test that outputpath is created."""
+ configuration.CONFIG.set('server', 'storagetype', 'file')
+ outputpath = Path(tempfile.gettempdir()) / "a" / "b" / "c"
+ configuration.CONFIG.set('server', 'outputpath', str(outputpath))
+ storage = StorageBuilder.buildStorage()
+
+ storage.store(fake_output)
+ assert outputpath.exists()
=====================================
tests/validator/test_complexvalidators.py
=====================================
@@ -8,34 +8,40 @@
import unittest
import pytest
-import sys
-from pywps.validator.complexvalidator import *
+from pywps.validator.mode import MODE
+from pywps.validator.complexvalidator import (
+ validategml,
+ # validategpx,
+ # validatexml,
+ validatejson,
+ validategeojson,
+ validateshapefile,
+ validategeotiff,
+ validatenetcdf,
+ validatedods,
+)
from pywps.inout.formats import FORMATS
from pywps import ComplexInput
from pywps.inout.basic import SOURCE_TYPE
import tempfile
import os
-try:
- import osgeo
-except ImportError:
- WITH_GDAL = False
-else:
- WITH_GDAL = True
try:
- import netCDF4
+ import netCDF4 # noqa
except ImportError:
WITH_NC4 = False
else:
WITH_NC4 = True
+
def get_input(name, schema, mime_type):
class FakeFormat(object):
mimetype = 'text/plain'
schema = None
units = None
+
def validate(self, data):
return True
@@ -67,20 +73,17 @@ class ValidateTest(unittest.TestCase):
def setUp(self):
pass
-
def tearDown(self):
pass
- @unittest.skip('long')
def test_gml_validator(self):
"""Test GML validator
"""
gml_input = get_input('gml/point.gml', 'point.xsd', FORMATS.GML.mime_type)
self.assertTrue(validategml(gml_input, MODE.NONE), 'NONE validation')
self.assertTrue(validategml(gml_input, MODE.SIMPLE), 'SIMPLE validation')
- if WITH_GDAL:
- self.assertTrue(validategml(gml_input, MODE.STRICT), 'STRICT validation')
- self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
+ self.assertTrue(validategml(gml_input, MODE.STRICT), 'STRICT validation')
+ self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
gml_input.stream.close()
def test_json_validator(self):
@@ -99,9 +102,8 @@ class ValidateTest(unittest.TestCase):
FORMATS.GEOJSON.mime_type)
self.assertTrue(validategeojson(geojson_input, MODE.NONE), 'NONE validation')
self.assertTrue(validategeojson(geojson_input, MODE.SIMPLE), 'SIMPLE validation')
- if WITH_GDAL:
- self.assertTrue(validategeojson(geojson_input, MODE.STRICT), 'STRICT validation')
- self.assertTrue(validategeojson(geojson_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
+ self.assertTrue(validategeojson(geojson_input, MODE.STRICT), 'STRICT validation')
+ self.assertTrue(validategeojson(geojson_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
geojson_input.stream.close()
def test_shapefile_validator(self):
@@ -111,8 +113,7 @@ class ValidateTest(unittest.TestCase):
FORMATS.SHP.mime_type)
self.assertTrue(validateshapefile(shapefile_input, MODE.NONE), 'NONE validation')
self.assertTrue(validateshapefile(shapefile_input, MODE.SIMPLE), 'SIMPLE validation')
- if WITH_GDAL:
- self.assertTrue(validateshapefile(shapefile_input, MODE.STRICT), 'STRICT validation')
+ self.assertTrue(validateshapefile(shapefile_input, MODE.STRICT), 'STRICT validation')
shapefile_input.stream.close()
def test_geotiff_validator(self):
@@ -122,8 +123,6 @@ class ValidateTest(unittest.TestCase):
FORMATS.GEOTIFF.mime_type)
self.assertTrue(validategeotiff(geotiff_input, MODE.NONE), 'NONE validation')
self.assertTrue(validategeotiff(geotiff_input, MODE.SIMPLE), 'SIMPLE validation')
- if not WITH_GDAL:
- self.skipTest('GDAL not Installed')
self.assertTrue(validategeotiff(geotiff_input, MODE.STRICT), 'STRICT validation')
geotiff_input.stream.close()
@@ -161,12 +160,12 @@ class ValidateTest(unittest.TestCase):
default_type=SOURCE_TYPE.URL,
mode=MODE.SIMPLE)
-
def test_fail_validator(self):
fake_input = get_input('point.xsd', 'point.xsd', FORMATS.SHP.mime_type)
self.assertFalse(validategml(fake_input, MODE.SIMPLE), 'SIMPLE validation invalid')
fake_input.stream.close()
+
def load_tests(loader=None, tests=None, pattern=None):
if not loader:
loader = unittest.TestLoader()
View it on GitLab: https://salsa.debian.org/debian-gis-team/pywps/-/commit/52ec34574b5b16f2e56dc58ced66e5313a0544af
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/pywps/-/commit/52ec34574b5b16f2e56dc58ced66e5313a0544af
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/20211202/cfa326c6/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list