Skip to content

Commit dce0633

Browse files
committedMay 8, 2020
Unit tests for AFS temporal handling
1 parent 505a011 commit dce0633

File tree

1 file changed

+146
-14
lines changed

1 file changed

+146
-14
lines changed
 

‎tests/src/python/test_provider_afs.py

Lines changed: 146 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import tempfile
1717
import shutil
1818

19-
from qgis.PyQt.QtCore import QCoreApplication, Qt, QObject, QDate
19+
from qgis.PyQt.QtCore import QCoreApplication, Qt, QObject, QDate, QDateTime
2020

2121
from qgis.core import (NULL,
2222
QgsVectorLayer,
@@ -29,7 +29,8 @@
2929
QgsCategorizedSymbolRenderer,
3030
QgsProviderRegistry,
3131
QgsWkbTypes,
32-
QgsDataSourceUri
32+
QgsDataSourceUri,
33+
QgsVectorDataProviderTemporalCapabilities
3334
)
3435
from qgis.testing import (start_app,
3536
unittest
@@ -47,7 +48,9 @@ def sanitize(endpoint, x):
4748
# print('Before: ' + endpoint + x)
4849
# print('After: ' + ret)
4950
return ret
50-
return endpoint + x.replace('?', '_').replace('&', '_').replace('<', '_').replace('>', '_').replace('"', '_').replace("'", '_').replace(' ', '_').replace(':', '_').replace('/', '_').replace('\n', '_')
51+
return endpoint + x.replace('?', '_').replace('&', '_').replace('<', '_').replace('>', '_').replace('"',
52+
'_').replace(
53+
"'", '_').replace(' ', '_').replace(':', '_').replace('/', '_').replace('\n', '_')
5154

5255

5356
class MessageLogger(QObject):
@@ -221,7 +224,9 @@ def setUpClass(cls):
221224
]
222225
}""".encode('UTF-8'))
223226

224-
with open(sanitize(endpoint, '/query?f=json&objectIds=5,3,1,2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false&geometry=-71.123000,66.330000,-65.320000,78.300000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'), 'wb') as f:
227+
with open(sanitize(endpoint,
228+
'/query?f=json&objectIds=5,3,1,2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false&geometry=-71.123000,66.330000,-65.320000,78.300000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'),
229+
'wb') as f:
225230
f.write("""
226231
{
227232
"displayFieldName": "name",
@@ -364,7 +369,9 @@ def setUpClass(cls):
364369
]
365370
}""".encode('UTF-8'))
366371

367-
with open(sanitize(endpoint, '/query?f=json&where=1=1&returnIdsOnly=true&geometry=-70.000000,67.000000,-60.000000,80.000000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'), 'wb') as f:
372+
with open(sanitize(endpoint,
373+
'/query?f=json&where=1=1&returnIdsOnly=true&geometry=-70.000000,67.000000,-60.000000,80.000000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'),
374+
'wb') as f:
368375
f.write("""
369376
{
370377
"objectIdFieldName": "OBJECTID",
@@ -375,7 +382,9 @@ def setUpClass(cls):
375382
}
376383
""".encode('UTF-8'))
377384

378-
with open(sanitize(endpoint, '/query?f=json&where==1=&returnIdsOnly=true&geometry=-73.000000,70.000000,-63.000000,80.000000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'), 'wb') as f:
385+
with open(sanitize(endpoint,
386+
'/query?f=json&where==1=&returnIdsOnly=true&geometry=-73.000000,70.000000,-63.000000,80.000000&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'),
387+
'wb') as f:
379388
f.write("""
380389
{
381390
"objectIdFieldName": "OBJECTID",
@@ -386,7 +395,9 @@ def setUpClass(cls):
386395
}
387396
""".encode('UTF-8'))
388397

389-
with open(sanitize(endpoint, '/query?f=json&where=1=1&returnIdsOnly=true&geometry=-68.721119,68.177676,-64.678700,79.123755&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'), 'wb') as f:
398+
with open(sanitize(endpoint,
399+
'/query?f=json&where=1=1&returnIdsOnly=true&geometry=-68.721119,68.177676,-64.678700,79.123755&geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelEnvelopeIntersects'),
400+
'wb') as f:
390401
f.write("""
391402
{
392403
"objectIdFieldName": "OBJECTID",
@@ -401,7 +412,7 @@ def setUpClass(cls):
401412
def tearDownClass(cls):
402413
"""Run after all tests"""
403414
QgsSettings().clear()
404-
#shutil.rmtree(cls.basetestpath, True)
415+
# shutil.rmtree(cls.basetestpath, True)
405416
cls.vl = None # so as to properly close the provider and remove any temporary file
406417

407418
def testGetFeaturesSubsetAttributes2(self):
@@ -471,7 +482,9 @@ def testObjectIdDifferentName(self):
471482
}
472483
""".encode('UTF-8'))
473484

474-
with open(sanitize(endpoint, '/query?f=json&objectIds=5,3,1,2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false'), 'wb') as f:
485+
with open(sanitize(endpoint,
486+
'/query?f=json&objectIds=5,3,1,2,4&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false'),
487+
'wb') as f:
475488
f.write("""
476489
{
477490
"displayFieldName": "LABEL",
@@ -545,8 +558,12 @@ def testDateTime(self):
545558
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
546559

547560
self.assertTrue(vl.isValid())
561+
562+
self.assertFalse(vl.dataProvider().temporalCapabilities().hasTemporalCapabilities())
563+
548564
with open(sanitize(endpoint,
549-
'/query?f=json&objectIds=1,2&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false'), 'wb') as f:
565+
'/query?f=json&objectIds=1,2&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false'),
566+
'wb') as f:
550567
f.write("""
551568
{
552569
"displayFieldName": "name",
@@ -754,7 +771,9 @@ def testBboxRestriction(self):
754771
Test limiting provider to features within a preset bounding box
755772
"""
756773
endpoint = self.basetestpath + '/fake_qgis_http_endpoint'
757-
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326' bbox='-70.000000,67.000000,-60.000000,80.000000'", 'test', 'arcgisfeatureserver')
774+
vl = QgsVectorLayer(
775+
"url='http://" + endpoint + "' crs='epsg:4326' bbox='-70.000000,67.000000,-60.000000,80.000000'", 'test',
776+
'arcgisfeatureserver')
758777
self.assertTrue(vl.isValid())
759778
self.assertEqual(vl.featureCount(), 2)
760779
self.assertEqual([f['pk'] for f in vl.getFeatures()], [2, 4])
@@ -799,7 +818,8 @@ def testBadMultiPoints(self):
799818

800819
self.assertTrue(vl.isValid())
801820
with open(sanitize(endpoint,
802-
'/query?f=json&objectIds=1,2,3&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false'), 'wb') as f:
821+
'/query?f=json&objectIds=1,2,3&inSR=4326&outSR=4326&returnGeometry=true&outFields=*&returnM=false&returnZ=false'),
822+
'wb') as f:
803823
f.write("""
804824
{
805825
"displayFieldName": "name",
@@ -843,7 +863,8 @@ def testBadMultiPoints(self):
843863

844864
features = [f for f in vl.getFeatures()]
845865
self.assertEqual(len(features), 3)
846-
self.assertEqual([f.geometry().asWkt() for f in features], ['MultiPoint ((-70 66))', '', 'MultiPoint ((-68 70),(-22 21))'])
866+
self.assertEqual([f.geometry().asWkt() for f in features],
867+
['MultiPoint ((-70 66))', '', 'MultiPoint ((-68 70),(-22 21))'])
847868

848869
def testDomain(self):
849870
"""
@@ -908,7 +929,118 @@ def testDomain(self):
908929
self.assertTrue(vl.isValid())
909930
self.assertFalse(vl.fields()[0].editorWidgetSetup().type())
910931
self.assertEqual(vl.fields()[1].editorWidgetSetup().type(), 'ValueMap')
911-
self.assertEqual(vl.fields()[1].editorWidgetSetup().config(), {'map': [{'Value 1': 1.0}, {'Value 2': 2.0}, {'Value 3': 3.0}]})
932+
self.assertEqual(vl.fields()[1].editorWidgetSetup().config(),
933+
{'map': [{'Value 1': 1.0}, {'Value 2': 2.0}, {'Value 3': 3.0}]})
934+
935+
def testTemporal1(self):
936+
"""
937+
Test timeinfo parsing
938+
"""
939+
endpoint = self.basetestpath + '/temporal1_fake_qgis_http_endpoint'
940+
with open(sanitize(endpoint, '?f=json'), 'wb') as f:
941+
f.write("""
942+
{"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description":
943+
"QGIS Provider Test Layer.\n","geometryType":"esriGeometryPoint","copyrightText":"","parentLayer":{"id":0,"name":"QGIS Tests"},"subLayers":[],
944+
"minScale":72225,"maxScale":0,
945+
"defaultVisibility":true,
946+
"extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3,
947+
"spatialReference":{"wkid":4326,"latestWkid":4326}},
948+
"hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText",
949+
"displayField":"LABEL","typeIdField":null,
950+
"fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}
951+
],
952+
"timeInfo": {
953+
"startTimeField": "date_start",
954+
"endTimeField": null,
955+
"trackIdField": null,
956+
"timeExtent": [
957+
1142000000000,
958+
1487000000000
959+
]
960+
},
961+
"relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false,
962+
"capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true,
963+
"supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF",
964+
"ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}""".encode(
965+
'UTF-8'))
966+
967+
with open(sanitize(endpoint, '/query?f=json_where=1=1&returnIdsOnly=true'), 'wb') as f:
968+
f.write("""
969+
{
970+
"objectIdFieldName": "OBJECTID",
971+
"objectIds": [
972+
1,
973+
2,
974+
3
975+
]
976+
}
977+
""".encode('UTF-8'))
978+
979+
# Create test layer
980+
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
981+
982+
self.assertTrue(vl.isValid())
983+
self.assertTrue(vl.dataProvider().temporalCapabilities().hasTemporalCapabilities())
984+
self.assertEqual(vl.dataProvider().temporalCapabilities().startField(), 'date_start')
985+
self.assertFalse(vl.dataProvider().temporalCapabilities().endField())
986+
self.assertEqual(vl.dataProvider().temporalCapabilities().mode(), QgsVectorDataProviderTemporalCapabilities.ProviderStoresFeatureDateTimeInstantInField)
987+
self.assertEqual(vl.dataProvider().temporalCapabilities().availableTemporalRange().begin(), QDateTime(2006, 3, 11, 0, 13, 20))
988+
self.assertEqual(vl.dataProvider().temporalCapabilities().availableTemporalRange().end(), QDateTime(2017, 2, 14, 1, 33, 20))
989+
990+
def testTemporal2(self):
991+
"""
992+
Test timeinfo parsing
993+
"""
994+
endpoint = self.basetestpath + '/temporal2_fake_qgis_http_endpoint'
995+
with open(sanitize(endpoint, '?f=json'), 'wb') as f:
996+
f.write("""
997+
{"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description":
998+
"QGIS Provider Test Layer.\n","geometryType":"esriGeometryPoint","copyrightText":"","parentLayer":{"id":0,"name":"QGIS Tests"},"subLayers":[],
999+
"minScale":72225,"maxScale":0,
1000+
"defaultVisibility":true,
1001+
"extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3,
1002+
"spatialReference":{"wkid":4326,"latestWkid":4326}},
1003+
"hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText",
1004+
"displayField":"LABEL","typeIdField":null,
1005+
"fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}
1006+
],
1007+
"timeInfo": {
1008+
"startTimeField": "date_start",
1009+
"endTimeField": "date_end",
1010+
"trackIdField": null,
1011+
"timeExtent": [
1012+
1142000000000,
1013+
1487000000000
1014+
]
1015+
},
1016+
"relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false,
1017+
"capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true,
1018+
"supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF",
1019+
"ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}""".encode(
1020+
'UTF-8'))
1021+
1022+
with open(sanitize(endpoint, '/query?f=json_where=1=1&returnIdsOnly=true'), 'wb') as f:
1023+
f.write("""
1024+
{
1025+
"objectIdFieldName": "OBJECTID",
1026+
"objectIds": [
1027+
1,
1028+
2,
1029+
3
1030+
]
1031+
}
1032+
""".encode('UTF-8'))
1033+
1034+
# Create test layer
1035+
vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
1036+
1037+
self.assertTrue(vl.isValid())
1038+
self.assertTrue(vl.dataProvider().temporalCapabilities().hasTemporalCapabilities())
1039+
self.assertEqual(vl.dataProvider().temporalCapabilities().startField(), 'date_start')
1040+
self.assertEqual(vl.dataProvider().temporalCapabilities().endField(), 'date_end')
1041+
self.assertEqual(vl.dataProvider().temporalCapabilities().mode(), QgsVectorDataProviderTemporalCapabilities.ProviderStoresFeatureDateTimeStartAndEndInSeparateFields)
1042+
self.assertEqual(vl.dataProvider().temporalCapabilities().availableTemporalRange().begin(), QDateTime(2006, 3, 11, 0, 13, 20))
1043+
self.assertEqual(vl.dataProvider().temporalCapabilities().availableTemporalRange().end(), QDateTime(2017, 2, 14, 1, 33, 20))
9121044

9131045
def testImageServer(self):
9141046
"""

0 commit comments

Comments
 (0)
Please sign in to comment.