31
31
from providertestbase import ProviderTestCase
32
32
33
33
34
- def sanitize (endpoint , x ):
35
- if len (endpoint + x ) > 256 :
36
- ret = endpoint + hashlib .md5 (x .replace ('/' , '_' ).encode ()).hexdigest ()
37
- # print('Before: ' + endpoint + x)
34
+ def sanitize (endpoint , query_params ):
35
+ # Implement the logic of QgsBaseNetworkRequest::sendGET()
36
+ # Note query_params can actually contain subpaths, so create the full url
37
+ # by concatenating boths, and then figure out things...
38
+
39
+ url = endpoint + query_params
40
+ # For REST API using URL subpaths, normalize the subpaths
41
+ afterEndpointStartPos = url .find ("fake_qgis_http_endpoint" ) + len ("fake_qgis_http_endpoint" )
42
+ afterEndpointStart = url [afterEndpointStartPos :]
43
+ afterEndpointStart = afterEndpointStart .replace ('/' , '_' )
44
+ url = url [0 :afterEndpointStartPos ] + afterEndpointStart
45
+ posQuotationMark = url .find ('?' )
46
+ endpoint = url [0 :posQuotationMark ]
47
+ query_params = url [posQuotationMark :]
48
+
49
+ if len (endpoint + query_params ) > 256 :
50
+ ret = endpoint + hashlib .md5 (query_params .encode ()).hexdigest ()
51
+ # print('Before: ' + endpoint + query_params)
38
52
# print('After: ' + ret)
39
53
return ret
40
- ret = endpoint + x .replace ('?' , '_' ).replace ('&' , '_' ).replace ('<' , '_' ).replace ('>' , '_' ).replace ('"' ,
41
- '_' ).replace ("'" ,
42
- '_' ).replace (
54
+ ret = endpoint + query_params .replace ('?' , '_' ).replace ('&' , '_' ).replace ('<' , '_' ).replace ('>' , '_' ).replace ('"' ,
55
+ '_' ).replace ("'" ,
56
+ '_' ).replace (
43
57
' ' , '_' ).replace (':' , '_' ).replace ('/' , '_' ).replace ('\n ' , '_' )
44
58
return ret
45
59
@@ -56,7 +70,8 @@ def GDAL_COMPUTE_VERSION(maj, min, rev):
56
70
57
71
def create_landing_page_api_collection (endpoint ,
58
72
extraparam = '' ,
59
- crs_url = "http://www.opengis.net/def/crs/EPSG/0/4326" ,
73
+ storageCrs = None ,
74
+ crsList = None ,
60
75
bbox = [- 71.123 , 66.33 , - 65.32 , 78.3 ]):
61
76
62
77
questionmark_extraparam = '?' + extraparam if extraparam else ''
@@ -102,9 +117,10 @@ def add_params(x, y):
102
117
}
103
118
}
104
119
}
105
- if crs_url :
106
- collection ["crs" ] = [crs_url ]
107
- collection ["extent" ]["spatial" ]["crs" ] = crs_url
120
+ if storageCrs :
121
+ collection ["storageCrs" ] = storageCrs
122
+ if crsList :
123
+ collection ["crs" ] = crsList
108
124
109
125
with open (sanitize (endpoint , '/collections/mycollection?' + add_params (extraparam , ACCEPT_COLLECTION )), 'wb' ) as f :
110
126
f .write (json .dumps (collection ).encode ('UTF-8' ))
@@ -175,6 +191,9 @@ def tearDownClass(cls):
175
191
shutil .rmtree (cls .basetestpath , True )
176
192
cls .vl = None # so as to properly close the provider and remove any temporary file
177
193
194
+ def testCrs (self ):
195
+ self .assertEqual (self .source .sourceCrs ().authid (), 'OGC:CRS84' )
196
+
178
197
def testExtentSubsetString (self ):
179
198
# can't run the base provider test suite here - WFS/OAPIF extent handling is different
180
199
# to other providers
@@ -253,14 +272,14 @@ def testFeaturePaging(self):
253
272
def testBbox (self ):
254
273
255
274
endpoint = self .__class__ .basetestpath + '/fake_qgis_http_endpoint_testBbox'
256
- create_landing_page_api_collection (endpoint )
275
+ create_landing_page_api_collection (endpoint , storageCrs = "http://www.opengis.net/def/crs/EPSG/0/4326" )
257
276
258
277
# first items
259
278
first_items = {
260
279
"type" : "FeatureCollection" ,
261
280
"features" : [
262
281
{"type" : "Feature" , "id" : "feat.1" , "properties" : {"pk" : 1 , "cnt" : 100 },
263
- "geometry" : {"type" : "Point" , "coordinates" : [- 70.332 , 66.33 ]}}
282
+ "geometry" : {"type" : "Point" , "coordinates" : [66.33 , - 70.332 ]}}
264
283
]
265
284
}
266
285
with open (sanitize (endpoint , '/collections/mycollection/items?limit=10&' + ACCEPT_ITEMS ), 'wb' ) as f :
@@ -274,12 +293,12 @@ def testBbox(self):
274
293
"type" : "FeatureCollection" ,
275
294
"features" : [
276
295
{"type" : "Feature" , "id" : "feat.1" , "properties" : {"pk" : 1 , "cnt" : 100 },
277
- "geometry" : {"type" : "Point" , "coordinates" : [- 70.332 , 66.33 ]}},
296
+ "geometry" : {"type" : "Point" , "coordinates" : [66.33 , - 70.332 ]}},
278
297
{"type" : "Feature" , "id" : "feat.2" , "properties" : {"pk" : 2 , "cnt" : 200 },
279
- "geometry" : {"type" : "Point" , "coordinates" : [- 68.2 , 70.8 ]}}
298
+ "geometry" : {"type" : "Point" , "coordinates" : [70.8 , - 68.2 ]}}
280
299
]
281
300
}
282
- with open (sanitize (endpoint , '/collections/mycollection/items?limit=1000&bbox=65.5,-71,78,-65&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/4326&' + ACCEPT_ITEMS ),
301
+ with open (sanitize (endpoint , '/collections/mycollection/items?limit=1000&bbox=65.5,-71,78,-65&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/4326&crs=http://www.opengis.net/def/crs/EPSG/0/4326& ' + ACCEPT_ITEMS ),
283
302
'wb' ) as f :
284
303
f .write (json .dumps (items ).encode ('UTF-8' ))
285
304
@@ -297,7 +316,7 @@ def testBbox(self):
297
316
298
317
# Test clamping of bbox
299
318
with open (
300
- sanitize (endpoint , '/collections/mycollection/items?limit=1000&bbox=64.5,-180,78,-65&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/4326&' + ACCEPT_ITEMS ),
319
+ sanitize (endpoint , '/collections/mycollection/items?limit=1000&bbox=64.5,-180,78,-65&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/4326&crs=http://www.opengis.net/def/crs/EPSG/0/4326& ' + ACCEPT_ITEMS ),
301
320
'wb' ) as f :
302
321
f .write (json .dumps (items ).encode ('UTF-8' ))
303
322
@@ -317,14 +336,14 @@ def testBbox(self):
317
336
"type" : "FeatureCollection" ,
318
337
"features" : [
319
338
{"type" : "Feature" , "id" : "feat.1" , "properties" : {"pk" : 1 , "cnt" : 100 },
320
- "geometry" : {"type" : "Point" , "coordinates" : [- 70.332 , 66.33 ]}},
339
+ "geometry" : {"type" : "Point" , "coordinates" : [66.33 , - 70.332 ]}},
321
340
{"type" : "Feature" , "id" : "feat.2" , "properties" : {"pk" : 2 , "cnt" : 200 },
322
- "geometry" : {"type" : "Point" , "coordinates" : [- 68.2 , 70.8 ]}},
341
+ "geometry" : {"type" : "Point" , "coordinates" : [70.8 , - 68.2 ]}},
323
342
{"type" : "Feature" , "id" : "feat.3" , "properties" : {"pk" : 4 , "cnt" : 400 },
324
- "geometry" : {"type" : "Point" , "coordinates" : [- 65.32 , 78.3 ]}}
343
+ "geometry" : {"type" : "Point" , "coordinates" : [78.3 , - 65.32 ]}}
325
344
]
326
345
}
327
- with open (sanitize (endpoint , '/collections/mycollection/items?limit=1000&bbox=-90,-180,90,180&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/4326&' + ACCEPT_ITEMS ), 'wb' ) as f :
346
+ with open (sanitize (endpoint , '/collections/mycollection/items?limit=1000&bbox=-90,-180,90,180&bbox-crs=http://www.opengis.net/def/crs/EPSG/0/4326&crs=http://www.opengis.net/def/crs/EPSG/0/4326& ' + ACCEPT_ITEMS ), 'wb' ) as f :
328
347
f .write (json .dumps (items ).encode ('UTF-8' ))
329
348
330
349
extent = QgsRectangle (- 181 , - 91 , 181 , 91 )
@@ -397,8 +416,7 @@ def testLayerMetadata(self):
397
416
["1980-01-01T12:34:56.789Z" , None ],
398
417
[None , "2020-01-01T00:00:00Z" ]
399
418
]
400
- },
401
- "crs" : ["http://www.opengis.net/def/crs/EPSG/0/4326" ]
419
+ }
402
420
},
403
421
"links" : [
404
422
{"href" : "href_self" , "rel" : "self" , "type" : "application/json" , "title" : "my self link" },
@@ -456,6 +474,7 @@ def testLayerMetadata(self):
456
474
assert md .keywords ()['keywords' ] == ["keyword_a" , "keyword_b" ]
457
475
458
476
assert md .crs ().isValid ()
477
+ assert md .crs ().authid () == "OGC:CRS84"
459
478
assert md .crs ().isGeographic ()
460
479
assert not md .crs ().hasAxisInverted ()
461
480
@@ -554,6 +573,40 @@ def testLayerMetadata(self):
554
573
assert len (md .licenses ()) == 1
555
574
assert md .licenses ()[0 ] == 'proprietary'
556
575
576
+ # Variant with storageCrs
577
+ collection = copy .deepcopy (base_collection )
578
+ collection ['storageCrs' ] = "http://www.opengis.net/def/crs/EPSG/0/4258"
579
+ collection ['storageCrsCoordinateEpoch' ] = 2020.0
580
+ with open (sanitize (endpoint , '/collections/mycollection?' + ACCEPT_COLLECTION ), 'wb' ) as f :
581
+ f .write (json .dumps (collection ).encode ('UTF-8' ))
582
+
583
+ vl = QgsVectorLayer ("url='http://" + endpoint + "' typename='mycollection' restrictToRequestBBOX=1" , 'test' ,
584
+ 'OAPIF' )
585
+ self .assertTrue (vl .isValid ())
586
+
587
+ md = vl .metadata ()
588
+ assert vl .sourceCrs ().isValid ()
589
+ assert vl .sourceCrs ().authid () == "EPSG:4258"
590
+ assert vl .sourceCrs ().isGeographic ()
591
+ assert vl .sourceCrs ().coordinateEpoch () == 2020.0
592
+ assert vl .sourceCrs ().hasAxisInverted ()
593
+
594
+ # Variant with a list of crs
595
+ collection = copy .deepcopy (base_collection )
596
+ collection ['crs' ] = ["http://www.opengis.net/def/crs/EPSG/0/4258" , "http://www.opengis.net/def/crs/EPSG/0/4326" ]
597
+ with open (sanitize (endpoint , '/collections/mycollection?' + ACCEPT_COLLECTION ), 'wb' ) as f :
598
+ f .write (json .dumps (collection ).encode ('UTF-8' ))
599
+
600
+ vl = QgsVectorLayer ("url='http://" + endpoint + "' typename='mycollection' restrictToRequestBBOX=1" , 'test' ,
601
+ 'OAPIF' )
602
+ self .assertTrue (vl .isValid ())
603
+
604
+ md = vl .metadata ()
605
+ assert vl .sourceCrs ().isValid ()
606
+ assert vl .sourceCrs ().authid () == "EPSG:4258"
607
+ assert vl .sourceCrs ().isGeographic ()
608
+ assert vl .sourceCrs ().hasAxisInverted ()
609
+
557
610
def testDateTimeFiltering (self ):
558
611
559
612
endpoint = self .__class__ .basetestpath + '/fake_qgis_http_endpoint_testDateTimeFiltering'
@@ -722,7 +775,6 @@ def testDefaultCRS(self):
722
775
endpoint = basetestpath + '/fake_qgis_http_endpoint_ogc84'
723
776
724
777
create_landing_page_api_collection (endpoint ,
725
- crs_url = "" , # OGC norm says that if crs is not explicitly defined it is OGC:CRS84
726
778
bbox = [66.33 , - 71.123 , 78.3 , - 65.32 ])
727
779
728
780
items = {
@@ -769,8 +821,8 @@ def testCRS2056(self):
769
821
endpoint = basetestpath + '/fake_qgis_http_endpoint_epsg_2056'
770
822
771
823
create_landing_page_api_collection (endpoint ,
772
- crs_url = "http://www.opengis.net/def/crs/EPSG/0/2056" ,
773
- bbox = [ 2508500 , 1152000 , 2513450 , 1156950 ])
824
+ storageCrs = "http://www.opengis.net/def/crs/EPSG/0/2056" ,
825
+ crsList = [ "http://www.opengis.net/def/crs/OGC/0/CRS84" , "http://www.opengis.net/def/crs/EPSG/0/2056" ])
774
826
775
827
items = {
776
828
"type" : "FeatureCollection" ,
@@ -815,9 +867,7 @@ def testFeatureCountFallback(self):
815
867
basetestpath = tempfile .mkdtemp ().replace ('\\ ' , '/' )
816
868
endpoint = basetestpath + '/fake_qgis_http_endpoint_feature_count_fallback'
817
869
818
- create_landing_page_api_collection (endpoint ,
819
- crs_url = "http://www.opengis.net/def/crs/EPSG/0/2056" ,
820
- bbox = [2508500 , 1152000 , 2513450 , 1156950 ])
870
+ create_landing_page_api_collection (endpoint , storageCrs = "http://www.opengis.net/def/crs/EPSG/0/2056" )
821
871
822
872
items = {
823
873
"type" : "FeatureCollection" ,
@@ -846,7 +896,7 @@ def testFeatureCountFallback(self):
846
896
f .write (json .dumps (items ).encode ('UTF-8' ))
847
897
848
898
# real page
849
- with open (sanitize (endpoint , '/collections/mycollection/items?limit=1000&' + ACCEPT_ITEMS ), 'wb' ) as f :
899
+ with open (sanitize (endpoint , '/collections/mycollection/items?limit=1000&crs=http://www.opengis.net/def/crs/EPSG/0/2056& ' + ACCEPT_ITEMS ), 'wb' ) as f :
850
900
f .write (json .dumps (items ).encode ('UTF-8' ))
851
901
852
902
# Create test layer
0 commit comments