Introduce OGRProvider: WFS backend support (#119)
* #89 fix check_format function * #89 fix check_format function - fix default return * geopython/pygeoapi#58 first version OGRProvider with working WFS tests/config * geopython/pygeoapi#58 second version, ogr2ogr-like reprojection support - more to follow * geopython/pygeoapi#58 3rd version, support Sourcetypes SHP and GPKG with tests+travis stuff * geopython/pygeoapi#58 fixed geopython/pygeoapi#95 for OGR Provider and its tests * geopython/pygeoapi#58 use more performant backend-WFS in pygeoapi-config.yml * #58 4th version: WFS backend ok, including OGR Python paging gotchas fixed ready for PR * #58 fix Travis build for GDAL Python bindings * #58 fix Travis build: Unit tests failed: missing Shapefile .zip now added * #58 #119 rework from PR comments: config, tests, quotes
This commit is contained in:
committed by
Tom Kralidis
parent
1a3f4eeb02
commit
4e5233f39d
+17
-10
@@ -3,6 +3,12 @@ language: python
|
||||
dist: xenial
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- PYGEOAPI_CONFIG=pygeoapi-config.yml
|
||||
- CPLUS_INCLUDE_PATH=/usr/include/gdal
|
||||
- C_INCLUDE_PATH=/usr/include/gdal
|
||||
|
||||
python:
|
||||
- "3.6"
|
||||
- "3.7"
|
||||
@@ -14,24 +20,25 @@ services:
|
||||
addons:
|
||||
postgresql: 9.6
|
||||
|
||||
|
||||
before_install:
|
||||
- sudo apt-add-repository ppa:ubuntugis/ubuntugis-unstable -y
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -qq build-essential python3-dev python3-setuptools
|
||||
- sudo apt-get install -y libsqlite3-mod-spatialite pandoc devscripts
|
||||
- sudo apt-get install -y postgresql-9.6-postgis-2.4
|
||||
|
||||
- sudo apt-get install -y libgdal-dev gdal-bin
|
||||
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements-dev.txt
|
||||
- python setup.py install
|
||||
# follow GDAL installed version for Python bindings
|
||||
- pip3 install GDAL==`gdalinfo --version | cut -d' ' -f2 | cut -d',' -f1`
|
||||
- pip3 install -r requirements.txt
|
||||
- pip3 install -r requirements-dev.txt
|
||||
- python3 setup.py install
|
||||
|
||||
env:
|
||||
- PYGEOAPI_CONFIG=pygeoapi-config.yml
|
||||
|
||||
before_script:
|
||||
- sleep 20
|
||||
- python tests/load_es_data.py tests/data/ne_110m_populated_places_simple.geojson
|
||||
- python3 tests/load_es_data.py tests/data/ne_110m_populated_places_simple.geojson
|
||||
- pygeoapi generate-openapi-document -c pygeoapi-config.yml > pygeoapi-openapi.yml
|
||||
- psql -U postgres -c 'create database test'
|
||||
- psql -U postgres -d test -c 'create extension postgis'
|
||||
@@ -40,8 +47,8 @@ before_script:
|
||||
script:
|
||||
- pytest --cov=pygeoapi
|
||||
- find . -type f -name "*.py" | xargs flake8
|
||||
- python setup.py --long-description | rst2html5.py
|
||||
- python3 setup.py --long-description | rst2html5.py
|
||||
|
||||
after_success:
|
||||
- python setup.py sdist bdist_wheel --universal
|
||||
- python3 setup.py sdist bdist_wheel --universal
|
||||
- debuild -b -uc -us
|
||||
|
||||
@@ -226,6 +226,53 @@ datasets:
|
||||
id_field: osm_id
|
||||
table: hotosm_bdi_waterways
|
||||
|
||||
dutch_georef_stations:
|
||||
title: Dutch Georef Stations via OGR WFS
|
||||
description: Locations of RD/GNSS-reference stations from Dutch Kadaster PDOK a.k.a RDInfo. Uses MapServer WFS v2 backend via OGRProvider.
|
||||
keywords:
|
||||
- Netherlands
|
||||
- GNSS
|
||||
- Surveying
|
||||
- Holland
|
||||
- RD
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: http://www.nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search#/metadata/3ebe56dc-5f09-4fb3-b224-55c2db4ca2fd?tab=general
|
||||
hreflang: nl-NL
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [50.7539, 7.21097, 53.4658, 3.37087]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: WFS
|
||||
source: WFS:http://geodata.nationaalgeoregister.nl/rdinfo/wfs?
|
||||
source_srs: EPSG:28992
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
source_options:
|
||||
# OGR_WFS_VERSION: 1.1.0
|
||||
OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN: NO
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: gml_id
|
||||
layer: rdinfo:stations
|
||||
|
||||
processes:
|
||||
hello-world:
|
||||
processor:
|
||||
|
||||
@@ -38,6 +38,7 @@ PLUGINS = {
|
||||
'Elasticsearch': 'pygeoapi.provider.elasticsearch_.ElasticsearchProvider', # noqa
|
||||
'GeoJSON': 'pygeoapi.provider.geojson.GeoJSONProvider',
|
||||
'GeoPackage': 'pygeoapi.provider.geopackage.GeoPackageProvider',
|
||||
'OGR': 'pygeoapi.provider.ogr.OGRProvider',
|
||||
'PostgreSQL': 'pygeoapi.provider.postgresql.PostgreSQLProvider',
|
||||
'SQLite': 'pygeoapi.provider.sqlite.SQLiteProvider'
|
||||
},
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
# =================================================================
|
||||
#
|
||||
# Authors: Just van den Broecke <justb4@gmail.com>
|
||||
#
|
||||
# Copyright (c) 2019 Just van den Broecke
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation
|
||||
# files (the "Software"), to deal in the Software without
|
||||
# restriction, including without limitation the rights to use,
|
||||
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following
|
||||
# conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# =================================================================
|
||||
|
||||
import importlib
|
||||
import logging
|
||||
|
||||
from osgeo import gdal as osgeo_gdal
|
||||
from osgeo import ogr as osgeo_ogr
|
||||
from osgeo import osr as osgeo_osr
|
||||
|
||||
from pygeoapi.provider.base import (BaseProvider)
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OGRProvider(BaseProvider):
|
||||
"""OGR Provider"""
|
||||
|
||||
# To deal with some OGR Source-Driver specifics.
|
||||
SOURCE_HELPERS = {
|
||||
'WFS': 'pygeoapi.provider.ogr.WFSHelper',
|
||||
'ESRI Shapefile': 'pygeoapi.provider.ogr.ShapefileHelper',
|
||||
'ESRIJSON': 'pygeoapi.provider.ogr.ESRIJSONHelper',
|
||||
'GPKG': 'pygeoapi.provider.ogr.GPKGHelper'
|
||||
}
|
||||
|
||||
def __init__(self, provider_def):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
# Typical OGRProvider YAML config:
|
||||
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: WFS
|
||||
source: WFS:http://geodata.nationaalgeoregister.nl/rdinfo/wfs?
|
||||
source_srs: EPSG:28992
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
source_options:
|
||||
OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN: NO
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: gml_id
|
||||
layer: rdinfo:stations
|
||||
|
||||
|
||||
:param provider_def: provider definition
|
||||
|
||||
:returns: pygeoapi.providers.ogr.OGRProvider
|
||||
"""
|
||||
|
||||
BaseProvider.__init__(self, provider_def)
|
||||
|
||||
self.ogr = osgeo_ogr
|
||||
# http://trac.osgeo.org/gdal/wiki/PythonGotchas
|
||||
self.gdal = osgeo_gdal
|
||||
self.gdal.UseExceptions()
|
||||
LOGGER.info("Using GDAL/OGR version: %d"
|
||||
% int(osgeo_gdal.VersionInfo('VERSION_NUM')))
|
||||
|
||||
# GDAL error handler function
|
||||
# http://pcjericks.github.io/py-gdalogr-cookbook/gdal_general.html
|
||||
def gdal_error_handler(err_class, err_num, err_msg):
|
||||
err_type = {
|
||||
osgeo_gdal.CE_None: 'None',
|
||||
osgeo_gdal.CE_Debug: 'Debug',
|
||||
osgeo_gdal.CE_Warning: 'Warning',
|
||||
osgeo_gdal.CE_Failure: 'Failure',
|
||||
osgeo_gdal.CE_Fatal: 'Fatal'
|
||||
}
|
||||
err_msg = err_msg.replace('\n', ' ')
|
||||
err_class = err_type.get(err_class, 'None')
|
||||
LOGGER.error('Error Number: %s, Type: %s, Msg: %s'
|
||||
% (err_num, err_class, err_msg))
|
||||
|
||||
# install error handler
|
||||
self.gdal.PushErrorHandler(gdal_error_handler)
|
||||
LOGGER.debug('Setting OGR properties')
|
||||
|
||||
self.data_def = provider_def['data']
|
||||
|
||||
# Generic GDAL/OGR options (optional)
|
||||
gdal_ogr_options = self.data_def.get('gdal_ogr_options', {})
|
||||
for key in gdal_ogr_options:
|
||||
self.gdal.SetConfigOption(key, str(gdal_ogr_options[key]))
|
||||
|
||||
# Driver-specific options (optional)
|
||||
source_options = self.data_def.get('source_options', {})
|
||||
for key in source_options:
|
||||
self.gdal.SetConfigOption(key, str(source_options[key]))
|
||||
|
||||
self.source_capabilities = self.data_def.get('source_capabilities',
|
||||
{'paging': False})
|
||||
|
||||
self.source_srs = int(self.data_def.get('source_srs',
|
||||
'EPSG:4326').split(':')[1])
|
||||
self.target_srs = int(self.data_def.get('target_srs',
|
||||
'EPSG:4326').split(':')[1])
|
||||
|
||||
# Optional coordinate transformation inward (requests) and
|
||||
# outward (responses) when the source layers and WFS3 collections
|
||||
# differ in EPSG-codes.
|
||||
self.transform_in = None
|
||||
self.transform_out = None
|
||||
if self.source_srs != self.target_srs:
|
||||
source = osgeo_osr.SpatialReference()
|
||||
source.ImportFromEPSG(self.source_srs)
|
||||
|
||||
target = osgeo_osr.SpatialReference()
|
||||
target.ImportFromEPSG(self.target_srs)
|
||||
|
||||
self.transform_in = \
|
||||
osgeo_osr.CoordinateTransformation(target, source)
|
||||
self.transform_out = \
|
||||
osgeo_osr.CoordinateTransformation(source, target)
|
||||
|
||||
self._load_source_helper(self.data_def['source_type'])
|
||||
|
||||
# Init
|
||||
self.driver = None
|
||||
self.conn = None
|
||||
self.layer_name = provider_def.get('layer', None)
|
||||
|
||||
def _open(self):
|
||||
source_type = self.data_def['source_type']
|
||||
self.driver = self.ogr.GetDriverByName(source_type)
|
||||
if not self.driver:
|
||||
msg = 'No Driver for Source: {}'.format(source_type)
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
self.conn = self.driver.Open(self.data_def['source'], 0)
|
||||
if not self.conn:
|
||||
msg = 'Cannot open OGR Source: %s' % self.data_def['source']
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
# Always need to disable paging immediately after Open!
|
||||
if self.source_capabilities['paging']:
|
||||
self.source_helper.disable_paging()
|
||||
|
||||
def _close(self):
|
||||
self.conn = None
|
||||
LOGGER.debug('closed self.conn')
|
||||
|
||||
self.driver = None
|
||||
|
||||
def _get_layer(self):
|
||||
if not self.conn:
|
||||
self._open()
|
||||
|
||||
if not self.layer_name:
|
||||
# E.g. Shapefiles may not have explicitly named Layers
|
||||
layer = self.conn.GetLayer(0)
|
||||
else:
|
||||
layer = self.conn.GetLayerByName(self.layer_name)
|
||||
|
||||
if not layer:
|
||||
msg = 'Cannot get Layer {} from OGR Source'.format(self.layer_name)
|
||||
LOGGER.error(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
return layer
|
||||
|
||||
def get_fields(self):
|
||||
"""
|
||||
Get provider field information (names, types)
|
||||
|
||||
:returns: dict of fields
|
||||
"""
|
||||
|
||||
fields = {}
|
||||
try:
|
||||
layer_defn = self._get_layer().GetLayerDefn()
|
||||
for fld in range(layer_defn.GetFieldCount()):
|
||||
field_defn = layer_defn.GetFieldDefn(fld)
|
||||
fieldName = field_defn.GetName()
|
||||
fieldTypeCode = field_defn.GetType()
|
||||
fieldType = field_defn.GetFieldTypeName(fieldTypeCode)
|
||||
fields[fieldName] = fieldType.lower()
|
||||
# fieldWidth = layer_defn.GetFieldDefn(fld).GetWidth()
|
||||
# GetPrecision = layer_defn.GetFieldDefn(fld).GetPrecision()
|
||||
|
||||
except Exception as err:
|
||||
LOGGER.error(err)
|
||||
|
||||
finally:
|
||||
self._close()
|
||||
|
||||
return fields
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
Query OGR source
|
||||
|
||||
:param startindex: starting record to return (default 0)
|
||||
:param limit: number of records to return (default 10)
|
||||
:param resulttype: return results or hit limit (default results)
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: dict of 0..n GeoJSON features
|
||||
"""
|
||||
result = None
|
||||
try:
|
||||
if self.source_capabilities['paging']:
|
||||
self.source_helper.enable_paging(startindex, limit)
|
||||
|
||||
layer = self._get_layer()
|
||||
|
||||
if bbox:
|
||||
LOGGER.debug('processing bbox parameter')
|
||||
minx, miny, maxx, maxy = bbox
|
||||
|
||||
wkt = "POLYGON (({minx} {miny},{minx} {maxy},{maxx} {maxy}," \
|
||||
"{maxx} {miny},{minx} {miny}))".format(
|
||||
minx=float(minx), miny=float(miny),
|
||||
maxx=float(maxx), maxy=float(maxy))
|
||||
|
||||
polygon = self.ogr.CreateGeometryFromWkt(wkt)
|
||||
|
||||
if self.transform_in:
|
||||
polygon.Transform(self.transform_in)
|
||||
|
||||
layer.SetSpatialFilter(polygon)
|
||||
|
||||
# layer.SetSpatialFilterRect(
|
||||
# float(minx), float(miny), float(maxx), float(maxy))
|
||||
if resulttype == 'hits':
|
||||
LOGGER.debug('hits only specified')
|
||||
result = self._response_feature_hits(layer)
|
||||
elif resulttype == 'results':
|
||||
LOGGER.debug('results specified')
|
||||
result = self._response_feature_collection(layer, limit)
|
||||
else:
|
||||
LOGGER.error('Invalid resulttype: %s' % resulttype)
|
||||
|
||||
except Exception as err:
|
||||
LOGGER.error(err)
|
||||
|
||||
finally:
|
||||
self._close()
|
||||
|
||||
return result
|
||||
|
||||
def get(self, identifier):
|
||||
"""
|
||||
Get Feature by id
|
||||
|
||||
:param identifier: feature id
|
||||
|
||||
:returns: feature collection
|
||||
"""
|
||||
result = None
|
||||
try:
|
||||
LOGGER.debug('Fetching identifier {}'.format(identifier))
|
||||
layer = self._get_layer()
|
||||
|
||||
layer.SetAttributeFilter("{field} = '{id}'".format(
|
||||
field=self.id_field, id=identifier))
|
||||
|
||||
ogr_feature = layer.GetNextFeature()
|
||||
result = self._ogr_feature_to_json(ogr_feature)
|
||||
|
||||
except Exception as err:
|
||||
LOGGER.error(err)
|
||||
finally:
|
||||
self._close()
|
||||
|
||||
return result
|
||||
|
||||
def __repr__(self):
|
||||
return '<OGRProvider> {}'.format(self.data)
|
||||
|
||||
def _load_source_helper(self, source_type):
|
||||
"""
|
||||
Loads Source Helper by name.
|
||||
|
||||
:param Source type: Source type name
|
||||
|
||||
:returns: Source Helper object
|
||||
"""
|
||||
|
||||
if source_type not in OGRProvider.SOURCE_HELPERS.keys():
|
||||
msg = 'No Helper found for OGR Source type: {}'.format(source_type)
|
||||
LOGGER.exception(msg)
|
||||
raise InvalidHelperError(msg)
|
||||
|
||||
# Create object from full package.class name string.
|
||||
source_helper_class = OGRProvider.SOURCE_HELPERS[source_type]
|
||||
|
||||
packagename, classname = source_helper_class.rsplit('.', 1)
|
||||
module = importlib.import_module(packagename)
|
||||
class_ = getattr(module, classname)
|
||||
self.source_helper = class_(self)
|
||||
|
||||
def _ogr_feature_to_json(self, ogr_feature):
|
||||
geom = ogr_feature.GetGeometryRef()
|
||||
if self.transform_out:
|
||||
# Optionally reproject the geometry
|
||||
geom.Transform(self.transform_out)
|
||||
|
||||
json_feature = ogr_feature.ExportToJson(as_object=True)
|
||||
json_feature['id'] = json_feature['properties'].pop(self.id_field)
|
||||
return json_feature
|
||||
|
||||
def _response_feature_collection(self, layer, limit):
|
||||
"""
|
||||
Assembles output from Layer query as
|
||||
GeoJSON FeatureCollection structure.
|
||||
|
||||
:returns: GeoJSON FeatureCollection
|
||||
"""
|
||||
|
||||
feature_collection = {
|
||||
'type': 'FeatureCollection',
|
||||
'features': []
|
||||
}
|
||||
|
||||
# See https://github.com/OSGeo/gdal/blob/master/autotest/
|
||||
# ogr/ogr_wfs.py#L313
|
||||
layer.ResetReading()
|
||||
|
||||
ogr_feature = layer.GetNextFeature()
|
||||
count = 0
|
||||
while ogr_feature is not None:
|
||||
json_feature = self._ogr_feature_to_json(ogr_feature)
|
||||
|
||||
feature_collection['features'].append(json_feature)
|
||||
|
||||
count += 1
|
||||
if count == limit:
|
||||
break
|
||||
|
||||
ogr_feature = layer.GetNextFeature()
|
||||
|
||||
return feature_collection
|
||||
|
||||
def _response_feature_hits(self, layer):
|
||||
"""
|
||||
Assembles GeoJSON hits from OGR Feature count
|
||||
e.g: http://localhost:5000/collections/
|
||||
hotosm_bdi_waterways/items?resulttype=hits
|
||||
|
||||
:returns: GeoJSON FeaturesCollection
|
||||
"""
|
||||
|
||||
return {
|
||||
'type': 'FeatureCollection',
|
||||
'numberMatched': layer.GetFeatureCount(),
|
||||
'features': []
|
||||
}
|
||||
|
||||
|
||||
class InvalidHelperError(Exception):
|
||||
"""Invalid helper"""
|
||||
pass
|
||||
|
||||
|
||||
class SourceHelper:
|
||||
def __init__(self, provider):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
:param provider: provider instance
|
||||
|
||||
:returns: pygeoapi.providers.ogr.SourceHelper
|
||||
"""
|
||||
self.provider = provider
|
||||
|
||||
def enable_paging(self, startindex=-1, limit=-1):
|
||||
"""
|
||||
Enable paged access to dataset (OGR Driver-specific)
|
||||
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
def disable_paging(self):
|
||||
"""
|
||||
Disable paged access to dataset (OGR Driver-specific)
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class GPKGHelper(SourceHelper):
|
||||
|
||||
def __init__(self, provider):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
:param provider: provider instance
|
||||
|
||||
:returns: pygeoapi.providers.ogr.SourceHelper
|
||||
"""
|
||||
self.provider = provider
|
||||
SourceHelper.__init__(self, provider)
|
||||
|
||||
|
||||
class ShapefileHelper(SourceHelper):
|
||||
|
||||
def __init__(self, provider):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
:param provider: provider instance
|
||||
|
||||
:returns: pygeoapi.providers.ogr.SourceHelper
|
||||
"""
|
||||
self.provider = provider
|
||||
SourceHelper.__init__(self, provider)
|
||||
|
||||
|
||||
class ESRIJSONHelper(SourceHelper):
|
||||
|
||||
def __init__(self, provider):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
:param provider: provider instance
|
||||
|
||||
:returns: pygeoapi.providers.ogr.SourceHelper
|
||||
"""
|
||||
self.provider = provider
|
||||
SourceHelper.__init__(self, provider)
|
||||
|
||||
def enable_paging(self, startindex=-1, limit=-1):
|
||||
"""
|
||||
Enable paged access to dataset (OGR Driver-specific)
|
||||
|
||||
"""
|
||||
|
||||
if startindex < 0:
|
||||
return
|
||||
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'ESRIJSON_FEATURE_SERVER_PAGING', 'ON')
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_ESRIJSON_START_INDEX', str(startindex))
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_ESRIJSON_PAGE_SIZE', str(limit))
|
||||
|
||||
def disable_paging(self):
|
||||
"""
|
||||
Disable paged access to dataset (OGR Driver-specific)
|
||||
"""
|
||||
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'ESRIJSON_FEATURE_SERVER_PAGING', None)
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_ESRIJSON_PAGE_SIZE', None)
|
||||
|
||||
|
||||
class WFSHelper(SourceHelper):
|
||||
|
||||
def __init__(self, provider):
|
||||
"""
|
||||
Initialize object
|
||||
|
||||
:param provider: provider instance
|
||||
|
||||
:returns: pygeoapi.providers.ogr.SourceHelper
|
||||
"""
|
||||
self.provider = provider
|
||||
SourceHelper.__init__(self, provider)
|
||||
|
||||
def enable_paging(self, startindex=-1, limit=-1):
|
||||
"""
|
||||
Enable paged access to dataset (OGR Driver-specific)
|
||||
|
||||
"""
|
||||
|
||||
if startindex < 0:
|
||||
return
|
||||
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_WFS_PAGING_ALLOWED', 'ON')
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_WFS_BASE_START_INDEX', str(startindex))
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_WFS_PAGE_SIZE', str(limit))
|
||||
|
||||
def disable_paging(self):
|
||||
"""
|
||||
Disable paged access to dataset (OGR Driver-specific)
|
||||
"""
|
||||
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_WFS_PAGING_ALLOWED', None)
|
||||
self.provider.gdal.SetConfigOption(
|
||||
'OGR_WFS_PAGE_SIZE', None)
|
||||
@@ -15,3 +15,4 @@ pytest-env
|
||||
pyOpenSSL==17.5.0
|
||||
ndg-httpsclient==0.4.4
|
||||
pyasn1==0.4.2
|
||||
GDAL>=2.2
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,328 @@
|
||||
server:
|
||||
bind:
|
||||
host: 0.0.0.0
|
||||
port: 5000
|
||||
url: http://localhost:5000/
|
||||
mimetype: application/json; charset=UTF-8
|
||||
encoding: utf-8
|
||||
language: en-US
|
||||
cors: true
|
||||
pretty_print: true
|
||||
limit: 10
|
||||
# templates: /path/to/templates
|
||||
|
||||
logging:
|
||||
level: ERROR
|
||||
#logfile: /tmp/pygeoapi.log
|
||||
|
||||
metadata:
|
||||
identification:
|
||||
title: pygeoapi default instance
|
||||
description: pygeoapi provides an API to geospatial data
|
||||
keywords:
|
||||
- geospatial
|
||||
- data
|
||||
- api
|
||||
keywords_type: theme
|
||||
terms_of_service: None
|
||||
url: http://example.org
|
||||
license:
|
||||
name: CC-BY 4.0 license
|
||||
url: https://creativecommons.org/licenses/by/4.0/
|
||||
provider:
|
||||
name: Organization Name
|
||||
url: https://pygeoapi.io
|
||||
contact:
|
||||
name: Lastname, Firstname
|
||||
position: Position Title
|
||||
address: Mailing Address
|
||||
city: City
|
||||
stateorprovince: Administrative Area
|
||||
postalcode: Zip or Postal Code
|
||||
country: Country
|
||||
phone: +xx-xxx-xxx-xxxx
|
||||
fax: +xx-xxx-xxx-xxxx
|
||||
email: you@example.org
|
||||
url: Contact URL
|
||||
hours: Hours of Service
|
||||
instructions: During hours of service. Off on weekends.
|
||||
role: pointOfContact
|
||||
|
||||
datasets:
|
||||
|
||||
dutch_georef_stations:
|
||||
title: Dutch Georef Stations via OGR WFS
|
||||
description: Locations of RD/GNSS-reference stations from Dutch Kadaster PDOK a.k.a RDInfo. Uses MapServer WFS v2 backend via OGRProvider.
|
||||
keywords:
|
||||
- Netherlands
|
||||
- GNSS
|
||||
- Surveying
|
||||
- Holland
|
||||
- RD
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: http://www.nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search#/metadata/3ebe56dc-5f09-4fb3-b224-55c2db4ca2fd?tab=general
|
||||
hreflang: nl-NL
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [50.7539, 7.21097, 53.4658, 3.37087]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: WFS
|
||||
source: WFS:http://geodata.nationaalgeoregister.nl/rdinfo/wfs?
|
||||
source_srs: EPSG:28992
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
source_options:
|
||||
# OGR_WFS_VERSION: 1.1.0
|
||||
OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN: NO
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: gml_id
|
||||
layer: rdinfo:stations
|
||||
|
||||
# Warning: this layer contains about 10 million addresses, the backend WFS seems not optimized
|
||||
dutch_addresses:
|
||||
title: Dutch Addresses via OGR WFS
|
||||
description: All Dutch addresses as derived from the key registry BAG. Uses GeoServer WFS v2 backend via OGRProvider. SLOW BACKEND!
|
||||
keywords:
|
||||
- Netherlands
|
||||
- Addresses
|
||||
- Europe
|
||||
- Holland
|
||||
- BAG
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: http://www.nationaalgeoregister.nl/geonetwork/srv/dut/catalog.search#/metadata/3a97fbe4-2b0d-4e9c-9644-276883400dd7
|
||||
hreflang: nl-NL
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [50.7539, 7.21097, 53.4658, 3.37087]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: WFS
|
||||
source: WFS:http://geodata.nationaalgeoregister.nl/inspireadressen/wfs?
|
||||
source_srs: EPSG:28992
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
source_options:
|
||||
# OGR_WFS_VERSION: 2.0.0
|
||||
OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN: NO
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: gml_id
|
||||
layer: inspireadressen:inspireadressen
|
||||
|
||||
utah_city_locations:
|
||||
title: Cities in Utah via OGR WFS
|
||||
description: Data from the state of Utah. Standard demo dataset from the deegree WFS server that is used as backend WFS.
|
||||
keywords:
|
||||
- USA
|
||||
- deegree
|
||||
- Utah
|
||||
- Demo data
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: http://download.deegree.org/documentation/3.3.20/html/lightly.html#example-workspace-2-utah-webmapping-services
|
||||
hreflang: en-US
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [-112.108489, 39.854053, -111.028628, 40.460098]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: WFS
|
||||
source: WFS:http://demo.deegree.org/utah-workspace/services/wfs?TYPENAME=app:SGID93_LOCATION_UDOTMap_CityLocations
|
||||
source_srs: EPSG:26912
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
source_options:
|
||||
# OGR_WFS_VERSION: 2.0.0
|
||||
OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN: NO
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: NAME
|
||||
layer: app:SGID93_LOCATION_UDOTMap_CityLocations
|
||||
|
||||
unesco_pois_italy:
|
||||
title: Unesco POIs in Italy via OGR WFS
|
||||
description: Unesco Points of Interest in Italy. Using GeoSolutions GeoServer WFS demo-server as backend WFS.
|
||||
keywords:
|
||||
- Italy
|
||||
- Unesco
|
||||
- Demo
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: https://mapstore2.geo-solutions.it/mapstore/#/dashboard/5593
|
||||
hreflang: en-US
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [36.0, 17.0, 46.0, 18.0]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: WFS
|
||||
source: WFS:https://demo.geo-solutions.it/geoserver/wfs
|
||||
source_srs: EPSG:32632
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
source_options:
|
||||
# OGR_WFS_VERSION: 1.1.0
|
||||
OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN: NO
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: gml_id
|
||||
layer: unesco:Unesco_point
|
||||
|
||||
ogr_gpkg_poi:
|
||||
title: Portuguese Points of Interest via OGR GPKG
|
||||
description: Portuguese Points of Interest obtained from OpenStreetMap. Dataset includes Madeira and Azores islands. Uses GeoPackage backend via OGR provider.
|
||||
keywords:
|
||||
- Portugal
|
||||
- POI
|
||||
- Point of Interrest
|
||||
- Madeira
|
||||
- Azores
|
||||
- OSM
|
||||
- Open Street Map
|
||||
- NaturaGIS
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: https://wiki.openstreetmap.org/wiki/Points_of_interest/
|
||||
hreflang: en-US
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [-31.2687 32.5898 -6.18992 42.152]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: GPKG
|
||||
source: tests/data/poi_portugal.gpkg
|
||||
source_srs: EPSG:4326
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: osm_id
|
||||
layer: poi_portugal
|
||||
|
||||
|
||||
sf_311incidents:
|
||||
title: SF 311Incidents via OGR ESRI Feature Server
|
||||
description: OGR Provider - ESRI Feature Server - SF 311Incidents
|
||||
keywords:
|
||||
- USA
|
||||
- ESRI
|
||||
crs:
|
||||
- CRS84
|
||||
links:
|
||||
- type: text/html
|
||||
rel: canonical
|
||||
title: information
|
||||
href: http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/SanFrancisco/311Incidents/FeatureServer/0
|
||||
hreflang: en-US
|
||||
extents:
|
||||
spatial:
|
||||
bbox: [-180, -90, 180, 90]
|
||||
temporal:
|
||||
begin: None
|
||||
end: now # or empty
|
||||
provider:
|
||||
name: OGR
|
||||
data:
|
||||
source_type: ESRIJSON
|
||||
source: ESRIJSON:http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/SanFrancisco/311Incidents/FeatureServer/0/query?where=objectid+%3D+objectid&outfields=*&f=json
|
||||
source_srs: EPSG:4326
|
||||
target_srs: EPSG:4326
|
||||
source_capabilities:
|
||||
paging: True
|
||||
|
||||
gdal_ogr_options:
|
||||
EMPTY_AS_NULL: NO
|
||||
GDAL_CACHEMAX: 64
|
||||
# GDAL_HTTP_PROXY: (optional proxy)
|
||||
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
|
||||
CPL_DEBUG: NO
|
||||
|
||||
id_field: objectid
|
||||
|
||||
processes:
|
||||
hello-world:
|
||||
processor:
|
||||
name: HelloWorld
|
||||
@@ -0,0 +1,251 @@
|
||||
# Needs to be run like: python3 -m pytest
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.ogr import OGRProvider
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config_poi_portugal():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'GPKG',
|
||||
'source': './tests/data/poi_portugal.gpkg',
|
||||
'source_srs': 'EPSG:4326',
|
||||
'target_srs': 'EPSG:4326',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
},
|
||||
'id_field': 'osm_id',
|
||||
'layer': 'poi_portugal'
|
||||
}
|
||||
|
||||
|
||||
def test_query(config_poi_portugal):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_poi_portugal)
|
||||
feature_collection = p.query()
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert features is not None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
def test_get(config_poi_portugal):
|
||||
p = OGRProvider(config_poi_portugal)
|
||||
result = p.get(5156778016)
|
||||
assert result['id'] == 5156778016
|
||||
assert 'tourist_info' in result['properties']['fclass']
|
||||
|
||||
|
||||
# Testing with GeoPackage files with identical features
|
||||
# (all 2481 addresses in Otterlo Netherlands)
|
||||
# in different projections.
|
||||
|
||||
@pytest.fixture()
|
||||
def config_gpkg_4326():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'GPKG',
|
||||
'source':
|
||||
'./tests/data/dutch_addresses_4326.gpkg',
|
||||
'source_srs': 'EPSG:4326',
|
||||
'target_srs': 'EPSG:4326',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
},
|
||||
'id_field': 'id'
|
||||
}
|
||||
|
||||
|
||||
# Note that this Shapefile is zipped, as OGR supports /vsizip/!
|
||||
@pytest.fixture()
|
||||
def config_gpkg_28992():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'GPKG',
|
||||
'source':
|
||||
'./tests/data/dutch_addresses_28992.gpkg',
|
||||
'source_srs': 'EPSG:28992',
|
||||
'target_srs': 'EPSG:4326',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
},
|
||||
'id_field': 'id'
|
||||
}
|
||||
|
||||
|
||||
def test_get_fields_4326(config_gpkg_4326):
|
||||
"""Testing field types"""
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
results = p.get_fields()
|
||||
assert results['straatnaam'] == 'string'
|
||||
assert results['huisnummer'] == 'string'
|
||||
|
||||
|
||||
def test_get_28992(config_gpkg_28992):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
result = p.get('inspireadressen.1747652')
|
||||
assert result['id'] == 'inspireadressen.1747652'
|
||||
assert 'Mosselsepad' in result['properties']['straatnaam']
|
||||
|
||||
|
||||
def test_get_4326(config_gpkg_4326):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
result = p.get('inspireadressen.1747652')
|
||||
assert result['id'] == 'inspireadressen.1747652'
|
||||
assert 'Mosselsepad' in result['properties']['straatnaam']
|
||||
|
||||
|
||||
def test_query_hits_28992(config_gpkg_28992):
|
||||
"""Testing query on entire collection for hits"""
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
|
||||
def test_query_hits_4326(config_gpkg_4326):
|
||||
"""Testing query on entire collection for hits"""
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
|
||||
def test_query_bbox_hits_4326(config_gpkg_4326):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits is 1
|
||||
|
||||
|
||||
def test_query_bbox_hits_28992(config_gpkg_28992):
|
||||
"""Testing query for a valid JSON object with geometry, single address"""
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
# feature_collection = p.query(
|
||||
# bbox=(180800, 452500, 181200, 452700), resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits is 1
|
||||
|
||||
|
||||
def test_query_bbox_28992(config_gpkg_28992):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
|
||||
def test_query_bbox_4326(config_gpkg_4326):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
|
||||
def test_query_with_limit_28992(config_gpkg_28992):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_gpkg_28992)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
def test_query_with_limit_4326(config_gpkg_4326):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_gpkg_4326)
|
||||
feature_collection = p.query(limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
@@ -0,0 +1,209 @@
|
||||
# Needs to be run like: python3 -m pytest
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from pygeoapi.provider.ogr import OGRProvider
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Testing with Shapefiles with identical features
|
||||
# (all 2481 addresses in Otterlo Netherlands)
|
||||
# in different projections.
|
||||
|
||||
@pytest.fixture()
|
||||
def config_shapefile_4326():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'ESRI Shapefile',
|
||||
'source':
|
||||
'./tests/data/dutch_addresses_shape_4326/inspireadressen.shp',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
},
|
||||
'id_field': 'id'
|
||||
}
|
||||
|
||||
|
||||
# Note that this Shapefile is zipped, as OGR supports /vsizip/!
|
||||
@pytest.fixture()
|
||||
def config_shapefile_28992():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'ESRI Shapefile',
|
||||
'source':
|
||||
'/vsizip/./tests/data/dutch_addresses_shape_28992.zip',
|
||||
'source_srs': 'EPSG:28992',
|
||||
'target_srs': 'EPSG:4326',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
},
|
||||
'id_field': 'id'
|
||||
}
|
||||
|
||||
|
||||
def test_get_fields_4326(config_shapefile_4326):
|
||||
"""Testing field types"""
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
results = p.get_fields()
|
||||
assert results['straatnaam'] == 'string'
|
||||
assert results['huisnummer'] == 'string'
|
||||
|
||||
|
||||
def test_get_28992(config_shapefile_28992):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
result = p.get('inspireadressen.1747652')
|
||||
assert result['id'] == 'inspireadressen.1747652'
|
||||
assert 'Mosselsepad' in result['properties']['straatnaam']
|
||||
|
||||
|
||||
def test_get_4326(config_shapefile_4326):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
result = p.get('inspireadressen.1747652')
|
||||
assert result['id'] == 'inspireadressen.1747652'
|
||||
assert 'Mosselsepad' in result['properties']['straatnaam']
|
||||
|
||||
|
||||
def test_query_hits_28992(config_shapefile_28992):
|
||||
"""Testing query on entire collection for hits"""
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
|
||||
def test_query_hits_4326(config_shapefile_4326):
|
||||
"""Testing query on entire collection for hits"""
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
assert hits == 2481
|
||||
|
||||
|
||||
def test_query_bbox_hits_4326(config_shapefile_4326):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits is 1
|
||||
|
||||
|
||||
def test_query_bbox_hits_28992(config_shapefile_28992):
|
||||
"""Testing query for a valid JSON object with geometry, single address"""
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
# feature_collection = p.query(
|
||||
# bbox=(180800, 452500, 181200, 452700), resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[5.763409, 52.060197, 5.769256, 52.061976], resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits is 1
|
||||
|
||||
|
||||
def test_query_bbox_28992(config_shapefile_28992):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
|
||||
def test_query_bbox_4326(config_shapefile_4326):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
|
||||
def test_query_with_limit_28992(config_shapefile_28992):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_shapefile_28992)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
def test_query_with_limit_4326(config_shapefile_4326):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_shapefile_4326)
|
||||
feature_collection = p.query(limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
@@ -0,0 +1,335 @@
|
||||
# Needs to be run like: python3 -m pytest
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
from pygeoapi.provider.ogr import OGRProvider
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config_MapServer_WFS():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'WFS',
|
||||
'source': 'WFS:http://geodata.nationaalgeoregister.nl/rdinfo/wfs?',
|
||||
'source_srs': 'EPSG:28992',
|
||||
'target_srs': 'EPSG:4326',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
'source_options': {
|
||||
'OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN': 'NO'
|
||||
},
|
||||
'gdal_ogr_options': {
|
||||
|
||||
'GDAL_CACHEMAX': '64',
|
||||
# 'GDAL_HTTP_PROXY': (optional proxy)
|
||||
# 'GDAL_PROXY_AUTH': (optional auth for remote WFS)
|
||||
'CPL_DEBUG': 'NO'
|
||||
},
|
||||
},
|
||||
'id_field': 'gml_id',
|
||||
'layer': 'rdinfo:stations'
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config_GeoServer_WFS():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'WFS',
|
||||
'source':
|
||||
'WFS:https://geodata.nationaalgeoregister.nl'
|
||||
+ '/inspireadressen/wfs?',
|
||||
'source_srs': 'EPSG:28992',
|
||||
'target_srs': 'EPSG:28992',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
'source_options': {
|
||||
'OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN': 'NO'
|
||||
},
|
||||
'gdal_ogr_options': {
|
||||
|
||||
'GDAL_CACHEMAX': '64',
|
||||
# 'GDAL_HTTP_PROXY': (optional proxy)
|
||||
# 'GDAL_PROXY_AUTH': (optional auth for remote WFS)
|
||||
'CPL_DEBUG': 'NO'
|
||||
},
|
||||
},
|
||||
'id_field': 'gml_id',
|
||||
'layer': 'inspireadressen:inspireadressen'
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config_geosol_gs_WFS():
|
||||
return {
|
||||
'name': 'OGR',
|
||||
'data': {
|
||||
'source_type': 'WFS',
|
||||
'source':
|
||||
'WFS:https://demo.geo-solutions.it/geoserver/wfs?',
|
||||
'source_srs': 'EPSG:32632',
|
||||
'target_srs': 'EPSG:4326',
|
||||
'source_capabilities': {
|
||||
'paging': True
|
||||
},
|
||||
'source_options': {
|
||||
'OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN': 'NO'
|
||||
},
|
||||
'gdal_ogr_options': {
|
||||
|
||||
'GDAL_CACHEMAX': '64',
|
||||
# 'GDAL_HTTP_PROXY': (optional proxy)
|
||||
# 'GDAL_PROXY_AUTH': (optional auth for remote WFS)
|
||||
'CPL_DEBUG': 'NO'
|
||||
},
|
||||
},
|
||||
'id_field': 'gml_id',
|
||||
'layer': 'unesco:Unesco_point'
|
||||
}
|
||||
|
||||
|
||||
def test_get_fields_gs(config_GeoServer_WFS):
|
||||
"""Testing field types"""
|
||||
p = OGRProvider(config_GeoServer_WFS)
|
||||
results = p.get_fields()
|
||||
assert results['straatnaam'] == 'string'
|
||||
assert results['huisnummer'] == 'integer'
|
||||
|
||||
|
||||
def test_get_ms(config_MapServer_WFS):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_MapServer_WFS)
|
||||
result = p.get('stations.4403')
|
||||
assert result['id'] == 'stations.4403'
|
||||
assert '01' in result['properties']['station']
|
||||
|
||||
|
||||
def test_get_geosol_gs(config_geosol_gs_WFS):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_geosol_gs_WFS)
|
||||
result = p.get('Unesco_point.123')
|
||||
assert result['id'] == 'Unesco_point.123'
|
||||
assert 'Centro storico di San Gimignano' in result['properties']['sito']
|
||||
|
||||
|
||||
def test_get_gs(config_GeoServer_WFS):
|
||||
"""Testing query for a specific object"""
|
||||
p = OGRProvider(config_GeoServer_WFS)
|
||||
result = p.get('inspireadressen.1747652')
|
||||
assert result['id'] == 'inspireadressen.1747652'
|
||||
assert 'Mosselsepad' in result['properties']['straatnaam']
|
||||
|
||||
|
||||
def test_query_hits_ms(config_MapServer_WFS):
|
||||
"""Testing query on entire collection for hits"""
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
assert hits > 5000
|
||||
|
||||
|
||||
def test_query_hits_geosol_gs(config_geosol_gs_WFS):
|
||||
"""Testing query on entire collection for hits"""
|
||||
|
||||
p = OGRProvider(config_geosol_gs_WFS)
|
||||
feature_collection = p.query(resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
assert hits == 186
|
||||
|
||||
|
||||
# OK, but backend WFS takes too much time....
|
||||
# def test_query_hits_gs(config_GeoServer_WFS):
|
||||
# """Testing query on entire collection for hits"""
|
||||
#
|
||||
# p = OGRProvider(config_GeoServer_WFS)
|
||||
# feature_collection = p.query(resulttype='hits')
|
||||
# assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
# features = feature_collection.get('features', None)
|
||||
# assert len(features) is 0
|
||||
# hits = feature_collection.get('numberMatched', None)
|
||||
# assert hits is not None
|
||||
# assert hits > 8000000
|
||||
|
||||
|
||||
def test_query_bbox_hits_ms(config_MapServer_WFS):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='hits')
|
||||
feature_collection = p.query(
|
||||
bbox=[4.874016, 52.306852, 4.932020, 52.370004], resulttype='hits')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits > 1
|
||||
|
||||
|
||||
def test_query_bbox_hits_gs(config_GeoServer_WFS):
|
||||
"""Testing query for a valid JSON object with geometry, single address"""
|
||||
|
||||
p = OGRProvider(config_GeoServer_WFS)
|
||||
feature_collection = p.query(
|
||||
bbox=(180800, 452500, 181200, 452700), resulttype='hits')
|
||||
# feature_collection = p.query(bbox=(
|
||||
# 5.763409, 52.060197, 5.769256, 52.061976), resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits is 1
|
||||
|
||||
|
||||
def test_query_bbox_hits_geosol_gs(config_geosol_gs_WFS):
|
||||
"""Testing query for a valid JSON object with geometry, single address"""
|
||||
|
||||
p = OGRProvider(config_geosol_gs_WFS)
|
||||
feature_collection = p.query(
|
||||
bbox=(681417.0, 4849032.0, 681417.3, 4849032.3), resulttype='hits')
|
||||
# feature_collection = p.query(bbox=(
|
||||
# 5.763409, 52.060197, 5.769256, 52.061976), resulttype='hits')
|
||||
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) is 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is not None
|
||||
print('hits={}'.format(hits))
|
||||
assert hits is 1
|
||||
|
||||
|
||||
def test_query_bbox_ms(config_MapServer_WFS):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=[4.874016, 52.306852, 4.932020, 52.370004], resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) > 0
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
def test_query_bbox_gs(config_GeoServer_WFS):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_GeoServer_WFS)
|
||||
feature_collection = p.query(
|
||||
bbox=[180800, 452500, 181200, 452700], resulttype='results')
|
||||
# feature_collection = p.query(
|
||||
# bbox=(5.763409, 52.060197, 5.769256, 52.061976), resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
assert properties['straatnaam'] == 'Planken Wambuisweg'
|
||||
|
||||
|
||||
def test_query_bbox_geosol_gs(config_geosol_gs_WFS):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_geosol_gs_WFS)
|
||||
# feature_collection = p.query(
|
||||
# bbox=[120000, 480000, 124000, 487000], resulttype='results')
|
||||
feature_collection = p.query(
|
||||
bbox=(681417.0, 4849032.0, 681417.3, 4849032.3),
|
||||
resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 1
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
assert properties['sito'] == 'Centro storico di Firenze'
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
def test_query_with_limit_ms(config_MapServer_WFS):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS)
|
||||
feature_collection = p.query(limit=2, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 2
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
|
||||
|
||||
def test_query_with_startindex(config_MapServer_WFS):
|
||||
"""Testing query for a valid JSON object with geometry"""
|
||||
|
||||
p = OGRProvider(config_MapServer_WFS)
|
||||
feature_collection = p.query(startindex=20, limit=5, resulttype='results')
|
||||
assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
features = feature_collection.get('features', None)
|
||||
assert len(features) == 5
|
||||
hits = feature_collection.get('numberMatched', None)
|
||||
assert hits is None
|
||||
feature = features[0]
|
||||
properties = feature.get('properties', None)
|
||||
assert properties is not None
|
||||
assert feature['id'] == 'stations.21'
|
||||
assert '101696.68' in properties['xrd']
|
||||
geometry = feature.get('geometry', None)
|
||||
assert geometry is not None
|
||||
#
|
||||
# # OK, but backend GeoServer PDOK WFS takes too much time....
|
||||
# # def test_query_with_limit_gs(config_GeoServer_WFS):
|
||||
# #
|
||||
# # p = OGRProvider(config_GeoServer_WFS)
|
||||
# # feature_collection = p.query(limit=5, resulttype='results')
|
||||
# # assert feature_collection.get('type', None) == 'FeatureCollection'
|
||||
# # features = feature_collection.get('features', None)
|
||||
# # assert len(features) == 5
|
||||
# # hits = feature_collection.get('numberMatched', None)
|
||||
# # assert hits is None
|
||||
# # feature = features[0]
|
||||
# # properties = feature.get('properties', None)
|
||||
# # assert properties is not None
|
||||
# # geometry = feature.get('geometry', None)
|
||||
# # assert geometry is not None
|
||||
Reference in New Issue
Block a user