Skip to content

Commit 626e2cf

Browse files
Remove gdal (#638)
* removed gdal dependency * run on ubuntu latest * Update pywps/validator/complexvalidator.py Co-authored-by: Trevor James Smith <10819524+Zeitsperre@users.noreply.github.com> * clean up test_ows * update exception in complex validator Co-authored-by: Trevor James Smith <10819524+Zeitsperre@users.noreply.github.com>
1 parent ced1484 commit 626e2cf

8 files changed

Lines changed: 58 additions & 113 deletions

File tree

.github/workflows/main.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ on: [ push, pull_request ]
44

55
jobs:
66
main:
7-
runs-on: ubuntu-18.04
7+
runs-on: ubuntu-latest
88
strategy:
99
matrix:
10-
python-version: [3.6, 3.7, 3.8, 3.9]
10+
python-version: [3.7, 3.8, 3.9]
1111
env:
1212
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1313
COVERALLS_SERVICE_NAME: github
1414
steps:
1515
- uses: actions/checkout@v2
1616
- name: Install packages
1717
run: |
18-
sudo apt-get update && sudo apt-get -y install gdal-bin libgdal-dev libnetcdf-dev libhdf5-dev
18+
sudo apt-get update && sudo apt-get -y install libnetcdf-dev libhdf5-dev
1919
- uses: actions/setup-python@v2
2020
name: Setup Python ${{ matrix.python-version }}
2121
with:
@@ -26,17 +26,16 @@ jobs:
2626
pip3 install -r requirements.txt
2727
pip3 install -r requirements-dev.txt
2828
pip3 install -r requirements-extra.txt
29-
pip3 install -r requirements-gdal.txt
3029
- name: run tests ⚙️
3130
run: pytest -v tests
3231
- name: run coveralls ⚙️
3332
run: coveralls
34-
if: matrix.python-version == 3.6
33+
if: matrix.python-version == 3.7
3534
- name: build docs 🏗️
3635
run: |
3736
pip3 install -e .
3837
cd docs && make html
39-
if: matrix.python-version == 3.6
38+
if: matrix.python-version == 3.7
4039
- name: run flake8 ⚙️
4140
run: flake8 pywps
42-
if: matrix.python-version == 3.6
41+
if: matrix.python-version == 3.7

pywps/dependencies.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@
66
import warnings
77

88
try:
9-
import osgeo
10-
from osgeo import gdal, ogr
11-
except ImportError:
12-
warnings.warn('Complex validation requires GDAL/OGR support.')
13-
ogr = None
14-
15-
try:
16-
import netCDF4
9+
import netCDF4 # noqa
1710
except ImportError:
1811
warnings.warn('Complex validation requires netCDF4 support.')

pywps/validator/complexvalidator.py

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def validategml(data_input, mode):
3535
`MODE.SIMPLE`
3636
the mimetype will be checked
3737
`MODE.STRICT`
38-
`GDAL/OGR <http://gdal.org/>`_ is used for getting the proper format.
38+
`Fiona` is used for getting the proper format.
3939
`MODE.VERYSTRICT`
4040
the :class:`lxml.etree` is used along with given input `schema` and the
4141
GML file is properly validated against given schema.
@@ -55,11 +55,11 @@ def validategml(data_input, mode):
5555

5656
if mode >= MODE.STRICT:
5757

58-
from pywps.dependencies import ogr
59-
data_source = ogr.Open(data_input.file)
60-
if data_source:
61-
passed = (data_source.GetDriver().GetName() == "GML")
62-
else:
58+
try:
59+
import fiona
60+
data_source = fiona.open(data_input.file)
61+
passed = (data_source.driver == "GML")
62+
except (ModuleNotFoundError, ImportError):
6363
passed = False
6464

6565
if mode >= MODE.VERYSTRICT:
@@ -89,7 +89,7 @@ def validategpx(data_input, mode):
8989
`MODE.SIMPLE`
9090
the mimetype will be checked
9191
`MODE.STRICT`
92-
`GDAL/OGR <http://gdal.org/>`_ is used for getting the proper format.
92+
`Fiona` is used for getting the proper format.
9393
`MODE.VERYSTRICT`
9494
the :class:`lxml.etree` is used along with given input `schema` and the
9595
GPX file is properly validated against given schema.
@@ -109,11 +109,11 @@ def validategpx(data_input, mode):
109109

110110
if mode >= MODE.STRICT:
111111

112-
from pywps.dependencies import ogr
113-
data_source = ogr.Open(data_input.file)
114-
if data_source:
115-
passed = (data_source.GetDriver().GetName() == "GPX")
116-
else:
112+
try:
113+
import fiona
114+
data_source = fiona.open(data_input.file)
115+
passed = (data_source.driver == "GPX")
116+
except (ModuleNotFoundError, ImportError):
117117
passed = False
118118

119119
if mode >= MODE.VERYSTRICT:
@@ -249,11 +249,11 @@ def validategeojson(data_input, mode):
249249

250250
if mode >= MODE.STRICT:
251251

252-
from pywps.dependencies import ogr
253-
data_source = ogr.Open(data_input.file)
254-
if data_source:
255-
passed = (data_source.GetDriver().GetName() == "GeoJSON")
256-
else:
252+
try:
253+
import fiona
254+
data_source = fiona.open(data_input.file)
255+
passed = (data_source.driver == "GeoJSON")
256+
except (ModuleNotFoundError, ImportError):
257257
passed = False
258258

259259
if mode >= MODE.VERYSTRICT:
@@ -317,22 +317,11 @@ def validateshapefile(data_input, mode):
317317

318318
if mode >= MODE.STRICT:
319319

320-
from pywps.dependencies import ogr
321-
322-
import zipfile
323-
z = zipfile.ZipFile(data_input.file)
324-
shape_name = None
325-
for name in z.namelist():
326-
z.extract(name, data_input.tempdir)
327-
if os.path.splitext(name)[1].lower() == '.shp':
328-
shape_name = name
329-
330-
if shape_name:
331-
data_source = ogr.Open(os.path.join(data_input.tempdir, shape_name))
332-
333-
if data_source:
334-
passed = (data_source.GetDriver().GetName() == "ESRI Shapefile")
335-
else:
320+
try:
321+
import fiona
322+
sf = fiona.open(data_input.file)
323+
passed = (sf.driver == "ESRI Shapefile")
324+
except (ModuleNotFoundError, ImportError):
336325
passed = False
337326

338327
return passed
@@ -357,10 +346,10 @@ def validategeotiff(data_input, mode):
357346
if mode >= MODE.STRICT:
358347

359348
try:
360-
from pywps.dependencies import osgeo # noqa
361-
data_source = osgeo.gdal.Open(data_input.file)
362-
passed = (data_source.GetDriver().ShortName == "GTiff")
363-
except ImportError:
349+
from geotiff import GeoTiff
350+
data_source = GeoTiff(data_input.file)
351+
passed = (data_source.crs_code > 0)
352+
except (ModuleNotFoundError, ImportError):
364353
passed = False
365354

366355
return passed

requirements-extra.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
netCDF4
1+
netCDF4

requirements-gdal.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ SQLAlchemy
88
werkzeug
99
MarkupSafe
1010
humanize
11+
geotiff
12+
fiona

tests/test_ows.py

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import tempfile
1111
import unittest
1212
from pywps import Service, Process, ComplexInput, ComplexOutput, Format, FORMATS, get_format
13-
from pywps.dependencies import ogr
1413
from pywps.exceptions import NoApplicableCode
1514
from pywps import get_ElementMakerForVersion
1615
import pywps.configuration as config
@@ -26,41 +25,8 @@ def create_feature():
2625

2726
def feature(request, response):
2827
input = request.inputs['input'][0].file
29-
# What do we need to assert a Complex input?
30-
# assert type(input) is str
31-
32-
# open the input file
33-
try:
34-
inSource = ogr.Open(input)
35-
except Exception as e:
36-
return "Could not open given vector file: {}".format(e)
37-
inLayer = inSource.GetLayer()
38-
39-
# create output file
40-
out = 'point'
41-
outPath = os.path.join(tempfile.gettempdir(), out)
42-
43-
driver = ogr.GetDriverByName('GML')
44-
outSource = driver.CreateDataSource(
45-
outPath,
46-
["XSISCHEMAURI=http://schemas.opengis.net/gml/2.1.2/feature.xsd"])
47-
outLayer = outSource.CreateLayer(out, None, ogr.wkbUnknown)
48-
49-
# get the first feature
50-
inFeature = inLayer.GetNextFeature()
51-
inGeometry = inFeature.GetGeometryRef()
52-
53-
# make the buffer
54-
buff = inGeometry.Buffer(float(100000))
55-
56-
# create output feature to the file
57-
outFeature = ogr.Feature(feature_def=outLayer.GetLayerDefn())
58-
outFeature.SetGeometryDirectly(buff)
59-
outLayer.CreateFeature(outFeature)
60-
outFeature.Destroy()
61-
6228
response.outputs['output'].data_format = FORMATS.GML
63-
response.outputs['output'].file = outPath
29+
response.outputs['output'].file = input
6430
return response
6531

6632
return Process(handler=feature,

tests/validator/test_complexvalidators.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,40 @@
88

99
import unittest
1010
import pytest
11-
import sys
12-
from pywps.validator.complexvalidator import *
11+
from pywps.validator.mode import MODE
12+
from pywps.validator.complexvalidator import (
13+
validategml,
14+
# validategpx,
15+
# validatexml,
16+
validatejson,
17+
validategeojson,
18+
validateshapefile,
19+
validategeotiff,
20+
validatenetcdf,
21+
validatedods,
22+
)
1323
from pywps.inout.formats import FORMATS
1424
from pywps import ComplexInput
1525
from pywps.inout.basic import SOURCE_TYPE
1626
import tempfile
1727
import os
1828

19-
try:
20-
import osgeo
21-
except ImportError:
22-
WITH_GDAL = False
23-
else:
24-
WITH_GDAL = True
2529

2630
try:
27-
import netCDF4
31+
import netCDF4 # noqa
2832
except ImportError:
2933
WITH_NC4 = False
3034
else:
3135
WITH_NC4 = True
3236

37+
3338
def get_input(name, schema, mime_type):
3439

3540
class FakeFormat(object):
3641
mimetype = 'text/plain'
3742
schema = None
3843
units = None
44+
3945
def validate(self, data):
4046
return True
4147

@@ -67,20 +73,17 @@ class ValidateTest(unittest.TestCase):
6773
def setUp(self):
6874
pass
6975

70-
7176
def tearDown(self):
7277
pass
7378

74-
@unittest.skip('long')
7579
def test_gml_validator(self):
7680
"""Test GML validator
7781
"""
7882
gml_input = get_input('gml/point.gml', 'point.xsd', FORMATS.GML.mime_type)
7983
self.assertTrue(validategml(gml_input, MODE.NONE), 'NONE validation')
8084
self.assertTrue(validategml(gml_input, MODE.SIMPLE), 'SIMPLE validation')
81-
if WITH_GDAL:
82-
self.assertTrue(validategml(gml_input, MODE.STRICT), 'STRICT validation')
83-
self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
85+
self.assertTrue(validategml(gml_input, MODE.STRICT), 'STRICT validation')
86+
self.assertTrue(validategml(gml_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
8487
gml_input.stream.close()
8588

8689
def test_json_validator(self):
@@ -99,9 +102,8 @@ def test_geojson_validator(self):
99102
FORMATS.GEOJSON.mime_type)
100103
self.assertTrue(validategeojson(geojson_input, MODE.NONE), 'NONE validation')
101104
self.assertTrue(validategeojson(geojson_input, MODE.SIMPLE), 'SIMPLE validation')
102-
if WITH_GDAL:
103-
self.assertTrue(validategeojson(geojson_input, MODE.STRICT), 'STRICT validation')
104-
self.assertTrue(validategeojson(geojson_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
105+
self.assertTrue(validategeojson(geojson_input, MODE.STRICT), 'STRICT validation')
106+
self.assertTrue(validategeojson(geojson_input, MODE.VERYSTRICT), 'VERYSTRICT validation')
105107
geojson_input.stream.close()
106108

107109
def test_shapefile_validator(self):
@@ -111,8 +113,7 @@ def test_shapefile_validator(self):
111113
FORMATS.SHP.mime_type)
112114
self.assertTrue(validateshapefile(shapefile_input, MODE.NONE), 'NONE validation')
113115
self.assertTrue(validateshapefile(shapefile_input, MODE.SIMPLE), 'SIMPLE validation')
114-
if WITH_GDAL:
115-
self.assertTrue(validateshapefile(shapefile_input, MODE.STRICT), 'STRICT validation')
116+
self.assertTrue(validateshapefile(shapefile_input, MODE.STRICT), 'STRICT validation')
116117
shapefile_input.stream.close()
117118

118119
def test_geotiff_validator(self):
@@ -122,8 +123,6 @@ def test_geotiff_validator(self):
122123
FORMATS.GEOTIFF.mime_type)
123124
self.assertTrue(validategeotiff(geotiff_input, MODE.NONE), 'NONE validation')
124125
self.assertTrue(validategeotiff(geotiff_input, MODE.SIMPLE), 'SIMPLE validation')
125-
if not WITH_GDAL:
126-
self.skipTest('GDAL not Installed')
127126
self.assertTrue(validategeotiff(geotiff_input, MODE.STRICT), 'STRICT validation')
128127
geotiff_input.stream.close()
129128

@@ -161,12 +160,12 @@ def test_dods_default(self):
161160
default_type=SOURCE_TYPE.URL,
162161
mode=MODE.SIMPLE)
163162

164-
165163
def test_fail_validator(self):
166164
fake_input = get_input('point.xsd', 'point.xsd', FORMATS.SHP.mime_type)
167165
self.assertFalse(validategml(fake_input, MODE.SIMPLE), 'SIMPLE validation invalid')
168166
fake_input.stream.close()
169167

168+
170169
def load_tests(loader=None, tests=None, pattern=None):
171170
if not loader:
172171
loader = unittest.TestLoader()

0 commit comments

Comments
 (0)