931 строка
34 KiB
Python
Исполняемый файл
931 строка
34 KiB
Python
Исполняемый файл
#!/usr/bin/env pytest
|
|
# -*- coding: utf-8 -*-
|
|
###############################################################################
|
|
# $Id$
|
|
#
|
|
# Project: GDAL/OGR Test Suite
|
|
# Purpose: PlanetLabs scene driver test suite.
|
|
# Author: Even Rouault, even dot rouault at spatialys.com
|
|
#
|
|
###############################################################################
|
|
# Copyright (c) 2015, Planet Labs
|
|
#
|
|
# 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 gdaltest
|
|
import pytest
|
|
|
|
from osgeo import gdal, ogr
|
|
|
|
|
|
###############################################################################
|
|
@pytest.fixture(autouse=True, scope="module")
|
|
def module_disable_exceptions():
|
|
with gdaltest.disable_exceptions():
|
|
yield
|
|
|
|
|
|
###############################################################################
|
|
# Find PLScenes driver
|
|
|
|
|
|
def test_ogr_plscenes_init():
|
|
|
|
gdaltest.plscenes_drv = ogr.GetDriverByName("PLScenes")
|
|
|
|
if gdaltest.plscenes_drv is not None:
|
|
return
|
|
pytest.skip()
|
|
|
|
|
|
###############################################################################
|
|
# Test Data V1 API catalog listing with a single catalog
|
|
|
|
|
|
def test_ogr_plscenes_data_v1_catalog_no_paging():
|
|
|
|
if gdaltest.plscenes_drv is None:
|
|
pytest.skip()
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types", '{ "item_types": [ { "id": "PSScene3Band" } ] }'
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds is not None
|
|
with gdaltest.error_handler():
|
|
assert ds.GetLayerByName("non_existing") is None
|
|
assert ds.GetLayerByName("PSScene3Band") is not None
|
|
assert ds.GetLayerCount() == 1
|
|
with gdaltest.error_handler():
|
|
assert ds.GetLayerByName("non_existing") is None
|
|
|
|
gdal.Unlink("/vsimem/data_v1/item-types")
|
|
|
|
|
|
###############################################################################
|
|
# Test Data V1 API catalog listing with catalog paging
|
|
|
|
|
|
def test_ogr_plscenes_data_v1_catalog_paging():
|
|
|
|
if gdaltest.plscenes_drv is None:
|
|
pytest.skip()
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types",
|
|
'{"_links": { "_next" : "/vsimem/data_v1/item-types/page_2"}, "item_types": [ { "id": "PSScene3Band" } ] }',
|
|
)
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/page_2",
|
|
'{ "item_types": [ { "id": "PSScene4Band" } ] }',
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds is not None
|
|
with gdaltest.error_handler():
|
|
assert ds.GetLayerByName("non_existing") is None
|
|
assert ds.GetLayerByName("PSScene3Band") is not None
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSScene4Band", '{ "id": "PSScene4Band"} }'
|
|
)
|
|
assert ds.GetLayerByName("PSScene4Band") is not None
|
|
assert ds.GetLayerCount() == 2
|
|
assert ds.GetLayerByName("PSScene4Band") is not None
|
|
with gdaltest.error_handler():
|
|
assert ds.GetLayerByName("non_existing") is None
|
|
|
|
gdal.Unlink("/vsimem/data_v1/item-types")
|
|
gdal.Unlink("/vsimem/data_v1/item-types/page_2")
|
|
gdal.Unlink("/vsimem/data_v1/item-types/PSScene4Band")
|
|
|
|
|
|
###############################################################################
|
|
# Test Data V1 API
|
|
|
|
|
|
def test_ogr_plscenes_data_v1_nominal():
|
|
|
|
if gdaltest.plscenes_drv is None:
|
|
pytest.skip()
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types",
|
|
"""{ "item_types": [
|
|
{"display_description" : "display_description",
|
|
"display_name" : "display_name",
|
|
"id": "PSOrthoTile"}
|
|
]}""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds is not None
|
|
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:version=data_v1,api_key=foo,FOLLOW_LINKS=YES", gdal.OF_VECTOR
|
|
)
|
|
assert ds is not None
|
|
|
|
lyr = ds.GetLayer(0)
|
|
assert lyr.GetName() == "PSOrthoTile"
|
|
assert (
|
|
lyr.TestCapability(ogr.OLCFastFeatureCount) == 1
|
|
and lyr.TestCapability(ogr.OLCStringsAsUTF8) == 1
|
|
and lyr.TestCapability(ogr.OLCRandomRead) == 0
|
|
)
|
|
# Different serialization depending on libjson versions
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/stats&POSTFIELDS={"interval":"year","item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"RangeFilter","field_name":"cloud_cover","config":{"gte":0.000000}}]}}""",
|
|
"""{ "buckets": [ { "count": 1 }, { "count": 1} ] }""",
|
|
)
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/stats&POSTFIELDS={"interval":"year","item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"RangeFilter","field_name":"cloud_cover","config":{"gte":0}}]}}""",
|
|
"""{ "buckets": [ { "count": 1 }, { "count": 1} ] }""",
|
|
)
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/stats&POSTFIELDS={"interval":"year","item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"RangeFilter","field_name":"cloud_cover","config":{"gte":0.0}}]}}""",
|
|
"""{ "buckets": [ { "count": 1 }, { "count": 1} ] }""",
|
|
)
|
|
assert lyr.GetFeatureCount() == 2
|
|
assert lyr.GetGeomType() == ogr.wkbMultiPolygon
|
|
ext = lyr.GetExtent()
|
|
assert ext == (-180.0, 180.0, -90.0, 90.0)
|
|
|
|
field_count = lyr.GetLayerDefn().GetFieldCount()
|
|
assert field_count == 106
|
|
|
|
# Regular /items/ fetching
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[]}}""",
|
|
"""{
|
|
"_links":
|
|
{
|
|
"_next": "/vsimem/data_v1/quick-search?page=2"
|
|
},
|
|
"features" : [
|
|
{
|
|
"id": "id",
|
|
"_links" : {
|
|
"_self" : "self",
|
|
"assets" : "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets"
|
|
},
|
|
"_permissions" : [ "download" ],
|
|
"properties": {
|
|
"acquired": "2016/02/11 12:34:56.789+00",
|
|
"anomalous_pixels": 1.23,
|
|
"columns": 1,
|
|
"item_type": "foo",
|
|
"ground_control": true
|
|
},
|
|
"geometry":
|
|
{
|
|
"type": "Polygon",
|
|
"coordinates" : [ [ [2,49],[2,49.1],[2.1,49.1],[2.1,49],[2,49] ] ]
|
|
}
|
|
}
|
|
]
|
|
}""",
|
|
)
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets",
|
|
"""{
|
|
"analytic" : {
|
|
"_permissions": ["download"],
|
|
"_links": {
|
|
"_self": "analytic_links_self",
|
|
"activate": "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/activate",
|
|
},
|
|
"location": "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff",
|
|
"status": "active",
|
|
"expires_at": "2016-02-11T12:34:56.789"
|
|
}
|
|
}""",
|
|
)
|
|
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_VECTOR,
|
|
open_options=["VERSION=data_v1", "API_KEY=foo", "FOLLOW_LINKS=YES"],
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f.GetFID() != 1
|
|
or f["id"] != "id"
|
|
or f["self_link"] != "self"
|
|
or f["assets_link"] != "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets"
|
|
or f["acquired"] != "2016/02/11 12:34:56.789+00"
|
|
or f["anomalous_pixels"] != 1.23
|
|
or f["item_type"] != "foo"
|
|
or f["columns"] != 1
|
|
or not f["ground_control"]
|
|
or f["asset_analytic_self_link"] != "analytic_links_self"
|
|
or f["asset_analytic_activate_link"]
|
|
!= "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/activate"
|
|
or f["asset_analytic_permissions"] != ["download"]
|
|
or f["asset_analytic_expires_at"] != "2016/02/11 12:34:56.789"
|
|
or f["asset_analytic_location"]
|
|
!= "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff"
|
|
or f["asset_analytic_status"] != "active"
|
|
or f.GetGeometryRef().ExportToWkt()
|
|
!= "MULTIPOLYGON (((2 49,2.0 49.1,2.1 49.1,2.1 49.0,2 49)))"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
lyr.ResetReading()
|
|
f = lyr.GetNextFeature()
|
|
if f.GetFID() != 1:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/quick-search?page=2",
|
|
"""{
|
|
"features" : [
|
|
{
|
|
"id": "id2"
|
|
}
|
|
]
|
|
}""",
|
|
)
|
|
|
|
f = lyr.GetNextFeature()
|
|
if f.GetFID() != 2 or f["id"] != "id2":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
lyr.ResetReading()
|
|
f = lyr.GetNextFeature()
|
|
if f.GetFID() != 1:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
f = lyr.GetNextFeature()
|
|
if f.GetFID() != 2:
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
f = lyr.GetNextFeature()
|
|
assert f is None
|
|
|
|
f = lyr.GetNextFeature()
|
|
assert f is None
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"GeometryFilter","field_name":"geometry","config":{"type":"Point","coordinates":[2.0,49.0]}}]}}""",
|
|
"""{"features" : [ { "id": "id3", "geometry": { "type": "Point", "coordinates": [2,49]} } ] }""",
|
|
)
|
|
|
|
# POINT spatial filter
|
|
lyr.SetSpatialFilterRect(2, 49, 2, 49)
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "id3":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Cannot find /vsimem/data_v1/stats&POSTFIELDS={"interval":"year","item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"GeometryFilter","field_name":"geometry","config":{"type":"Point","coordinates":[2.0,49.0]}}]}}
|
|
with gdaltest.error_handler():
|
|
assert lyr.GetFeatureCount() == 1
|
|
|
|
# Reset spatial filter
|
|
lyr.SetSpatialFilter(0, None)
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "id":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Test attribute filter on id
|
|
lyr.SetAttributeFilter("id = 'filtered_id'")
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"StringInFilter","field_name":"id","config":["filtered_id"]}]}}""",
|
|
"""{
|
|
"id": "filtered_id",
|
|
"properties": {}
|
|
}""",
|
|
)
|
|
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "filtered_id":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Test attribute filter fully evaluated on server side.
|
|
lyr.SetAttributeFilter(
|
|
"id != 'a' AND acquired >= '2016/02/11' AND acquired <= '2016/02/12' AND acquired > '1970/01/01 01:23:45' AND acquired < '2100/01/01 01:23:45' AND anomalous_pixels = 1.234567 AND (NOT id = 'b') AND columns > 0 AND columns < 2 AND columns = 1 AND columns IN (1, 2) AND (id IN ('filtered_2') OR id = 'foo') AND permissions = 'download' AND permissions IN ('download')"
|
|
)
|
|
content = """{
|
|
"features" : [
|
|
{
|
|
"id": "filtered_2",
|
|
"_links" : {
|
|
"_self" : "self",
|
|
"assets" : "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets"
|
|
},
|
|
"_permissions" : [ "download" ],
|
|
"properties": {
|
|
"acquired": "2016/02/11 12:34:56.789+00",
|
|
"anomalous_pixels": 1.23,
|
|
"columns": 1,
|
|
"item_type": "foo"
|
|
},
|
|
"geometry":
|
|
{
|
|
"type": "Polygon",
|
|
"coordinates" : [ [ [2,49],[2,49.1],[2.1,49.1],[2.1,49],[2,49] ] ]
|
|
}
|
|
}
|
|
]
|
|
}"""
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"NotFilter","config":{"type":"StringInFilter","field_name":"id","config":["a"]}},{"type":"DateRangeFilter","field_name":"acquired","config":{"gte":"2016-02-11T00:00:00Z"}}]},{"type":"AndFilter","config":[{"type":"DateRangeFilter","field_name":"acquired","config":{"lte":"2016-02-12T00:00:00Z"}},{"type":"DateRangeFilter","field_name":"acquired","config":{"gt":"1970-01-01T01:23:45Z"}}]}]},{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"DateRangeFilter","field_name":"acquired","config":{"lt":"2100-01-01T01:23:45Z"}},{"type":"RangeFilter","field_name":"anomalous_pixels","config":{"gte":1.234567,"lte":1.234567}}]},{"type":"AndFilter","config":[{"type":"NotFilter","config":{"type":"StringInFilter","field_name":"id","config":["b"]}},{"type":"RangeFilter","field_name":"columns","config":{"gt":0}}]}]}]},{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"RangeFilter","field_name":"columns","config":{"lt":2}},{"type":"NumberInFilter","field_name":"columns","config":[1]}]},{"type":"AndFilter","config":[{"type":"NumberInFilter","field_name":"columns","config":[1,2]},{"type":"OrFilter","config":[{"type":"StringInFilter","field_name":"id","config":["filtered_2"]},{"type":"StringInFilter","field_name":"id","config":["foo"]}]}]}]},{"type":"AndFilter","config":[{"type":"PermissionFilter","config":["download"]},{"type":"PermissionFilter","config":["download"]}]}]}]}]}}""",
|
|
content,
|
|
)
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"NotFilter","config":{"type":"StringInFilter","field_name":"id","config":["a"]}},{"type":"DateRangeFilter","field_name":"acquired","config":{"gte":"2016-02-11T00:00:00Z"}}]},{"type":"AndFilter","config":[{"type":"DateRangeFilter","field_name":"acquired","config":{"lte":"2016-02-12T00:00:00Z"}},{"type":"DateRangeFilter","field_name":"acquired","config":{"gt":"1970-01-01T01:23:45Z"}}]}]},{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"DateRangeFilter","field_name":"acquired","config":{"lt":"2100-01-01T01:23:45Z"}},{"type":"RangeFilter","field_name":"anomalous_pixels","config":{"gte":1.23456699,"lte":1.2345670099999999}}]},{"type":"AndFilter","config":[{"type":"NotFilter","config":{"type":"StringInFilter","field_name":"id","config":["b"]}},{"type":"RangeFilter","field_name":"columns","config":{"gt":0}}]}]}]},{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"AndFilter","config":[{"type":"RangeFilter","field_name":"columns","config":{"lt":2}},{"type":"NumberInFilter","field_name":"columns","config":[1]}]},{"type":"AndFilter","config":[{"type":"NumberInFilter","field_name":"columns","config":[1,2]},{"type":"OrFilter","config":[{"type":"StringInFilter","field_name":"id","config":["filtered_2"]},{"type":"StringInFilter","field_name":"id","config":["foo"]}]}]}]},{"type":"AndFilter","config":[{"type":"PermissionFilter","config":["download"]},{"type":"PermissionFilter","config":["download"]}]}]}]}]}}""",
|
|
content,
|
|
)
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "filtered_2":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Partly server / partly client
|
|
lyr.SetAttributeFilter("id = 'filtered_3' AND id > 'a'")
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"StringInFilter","field_name":"id","config":["filtered_3"]}]}}""",
|
|
"""{
|
|
"features" : [
|
|
{
|
|
"id": "filtered_3",
|
|
"properties": {
|
|
}
|
|
}
|
|
]
|
|
}""",
|
|
)
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "filtered_3":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
lyr.SetAttributeFilter("id > 'a' AND id = 'filtered_3'")
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "filtered_3":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Completely client side
|
|
lyr.SetAttributeFilter("id > 'a' OR id = 'id'")
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "id":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Completely client side
|
|
lyr.SetAttributeFilter("NOT id > 'z'")
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "id":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Reset attribute filter
|
|
lyr.SetAttributeFilter(None)
|
|
f = lyr.GetNextFeature()
|
|
if f["id"] != "id":
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
# Try raster access
|
|
|
|
# Missing catalog
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
with gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=["VERSION=data_v1", "API_KEY=foo", "SCENE=id"],
|
|
)
|
|
assert ds_raster is None and gdal.GetLastErrorMsg().find("Missing catalog") >= 0
|
|
|
|
# Invalid catalog
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=invalid",
|
|
"SCENE=id",
|
|
],
|
|
)
|
|
|
|
# visual not an object
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets",
|
|
"""{ "visual": false }""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
# Inactive file, and activation link not working
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets",
|
|
"""{
|
|
"analytic" : {
|
|
"_links": {
|
|
"_self": "analytic_links_self",
|
|
"activate": "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/activate",
|
|
},
|
|
"_permissions": ["download"],
|
|
"status": "inactive",
|
|
}
|
|
}""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
# File in activation
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets",
|
|
"""{
|
|
"analytic" : {
|
|
"_links": {
|
|
"_self": "analytic_links_self",
|
|
"activate": "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/activate",
|
|
},
|
|
"_permissions": ["download"],
|
|
"status": "activating",
|
|
}
|
|
}""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets",
|
|
"""{
|
|
"analytic" : {
|
|
"_permissions": ["download"],
|
|
"_links": {
|
|
"_self": "analytic_links_self",
|
|
"activate": "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/activate",
|
|
},
|
|
"location": "/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff",
|
|
"status": "active",
|
|
"expires_at": "2016-02-11T12:34:56.789"
|
|
}
|
|
}""",
|
|
)
|
|
|
|
# Missing /vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
# JSon content for /vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff",
|
|
"""{}""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
# Missing metadata
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile/items/id/assets/analytic/my.tiff",
|
|
open("../gcore/data/byte.tif", "rb").read(),
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is not None
|
|
ds_raster = None
|
|
|
|
# Failed filter by scene id
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types/PSOrthoTile", """{"id": "PSOrthoTile"}"""
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is not None
|
|
ds_raster = None
|
|
|
|
# Test metadata items attached to dataset
|
|
gdal.FileFromMemBuffer(
|
|
"""/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSOrthoTile"],"filter":{"type":"AndFilter","config":[{"type":"StringInFilter","field_name":"id","config":["id"]}]}}""",
|
|
"""{
|
|
"id": "id",
|
|
"properties": {
|
|
"anomalous_pixels": 1.23
|
|
},
|
|
}""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=analytic",
|
|
],
|
|
)
|
|
assert ds_raster is not None
|
|
assert ds_raster.GetMetadataItem("anomalous_pixels") == "1.23"
|
|
ds_raster = None
|
|
|
|
# Test invalid ASSET
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
"ACTIVATION_TIMEOUT=1",
|
|
"ASSET=invalid",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
# Test subdatasets
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"ASSET=list",
|
|
"SCENE=id",
|
|
],
|
|
)
|
|
assert len(ds_raster.GetSubDatasets()) == 1
|
|
ds_raster = None
|
|
|
|
# Unsupported option
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds_raster = gdal.OpenEx(
|
|
"PLScenes:unsupported=yes",
|
|
gdal.OF_RASTER,
|
|
open_options=[
|
|
"VERSION=data_v1",
|
|
"API_KEY=foo",
|
|
"ITEMTYPES=PSOrthoTile",
|
|
"SCENE=id",
|
|
],
|
|
)
|
|
assert ds_raster is None
|
|
|
|
# Test catalog with vector access
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds2 = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_VECTOR,
|
|
open_options=["VERSION=data_v1", "API_KEY=foo", "ITEMTYPES=PSOrthoTile"],
|
|
)
|
|
assert ds2 is not None and ds2.GetLayerCount() == 1
|
|
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds2 = gdal.OpenEx(
|
|
"PLScenes:",
|
|
gdal.OF_VECTOR,
|
|
open_options=["VERSION=data_v1", "API_KEY=foo", "ITEMTYPES=invalid"],
|
|
)
|
|
assert ds2 is None
|
|
|
|
fl = gdal.ReadDir("/vsimem/data_v1")
|
|
for filename in fl:
|
|
gdal.Unlink(filename)
|
|
|
|
|
|
###############################################################################
|
|
# Test robustness to errors in Data V1 API
|
|
|
|
|
|
def test_ogr_plscenes_data_v1_errors():
|
|
|
|
if gdaltest.plscenes_drv is None:
|
|
pytest.skip()
|
|
|
|
# No PL_API_KEY
|
|
with gdal.config_options(
|
|
{"PL_API_KEY": "", "PL_URL": "/vsimem/data_v1/"}
|
|
), gdaltest.error_handler():
|
|
ds = gdal.OpenEx("PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1"])
|
|
assert ds is None
|
|
|
|
# Invalid option
|
|
gdal.FileFromMemBuffer("/vsimem/data_v1/item-types", '{ "item-types": [] }')
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:version=data_v1,api_key=foo,invalid=invalid", gdal.OF_VECTOR
|
|
)
|
|
assert ds is None
|
|
|
|
# Invalid JSON
|
|
gdal.FileFromMemBuffer("/vsimem/data_v1/item-types", "{invalid_json")
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds is None
|
|
|
|
# Not an object
|
|
gdal.FileFromMemBuffer("/vsimem/data_v1/item-types", "false")
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds is None
|
|
|
|
# Lack of "item_types"
|
|
gdal.FileFromMemBuffer("/vsimem/data_v1/item-types", "{}")
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"), gdaltest.error_handler():
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds is None
|
|
|
|
# Invalid catalog objects
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types",
|
|
"""{"item_types": [{}, [], null, {"id":null},
|
|
{"id":"foo"}]}""",
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
assert ds.GetLayerCount() == 1
|
|
|
|
# Invalid next URL
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types",
|
|
'{"_links": { "_next": "/vsimem/inexisting" }, "item_types": [{"id": "my_catalog"}]}',
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
with gdaltest.error_handler():
|
|
lyr_count = ds.GetLayerCount()
|
|
assert lyr_count == 1
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/data_v1/item-types", '{"item_types": [{"id": "PSScene3Band"}]}'
|
|
)
|
|
with gdal.config_option("PL_URL", "/vsimem/data_v1/"):
|
|
ds = gdal.OpenEx(
|
|
"PLScenes:", gdal.OF_VECTOR, open_options=["VERSION=data_v1", "API_KEY=foo"]
|
|
)
|
|
lyr = ds.GetLayer(0)
|
|
|
|
# Invalid index
|
|
ds.GetLayer(-1)
|
|
ds.GetLayer(1)
|
|
|
|
with gdaltest.error_handler():
|
|
ds.GetLayerByName("invalid_name")
|
|
|
|
# Cannot find /vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSScene3Band"],"filter":{"type":"AndFilter","config":[]}}
|
|
with gdaltest.error_handler():
|
|
lyr.GetNextFeature()
|
|
|
|
# Empty object
|
|
gdal.FileFromMemBuffer(
|
|
'/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSScene3Band"],"filter":{"type":"AndFilter","config":[]}}',
|
|
"{}",
|
|
)
|
|
lyr.ResetReading()
|
|
lyr.GetNextFeature()
|
|
|
|
# null feature
|
|
gdal.FileFromMemBuffer(
|
|
'/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSScene3Band"],"filter":{"type":"AndFilter","config":[]}}',
|
|
'{ "features": [ null ] }',
|
|
)
|
|
lyr.ResetReading()
|
|
lyr.GetNextFeature()
|
|
|
|
gdal.Unlink("/vsimem/data_v1/item-types")
|
|
gdal.Unlink(
|
|
'/vsimem/data_v1/quick-search?_page_size=250&POSTFIELDS={"item_types":["PSScene3Band"],"filter":{"type":"AndFilter","config":[]}}'
|
|
)
|
|
|
|
|
|
###############################################################################
|
|
# Test Data V1 API against real server
|
|
|
|
|
|
def test_ogr_plscenes_data_v1_live():
|
|
|
|
if gdaltest.plscenes_drv is None:
|
|
pytest.skip()
|
|
|
|
api_key = gdal.GetConfigOption("PL_API_KEY")
|
|
if api_key is None:
|
|
pytest.skip("Skipping test as PL_API_KEY not defined")
|
|
|
|
with gdal.config_option("PLSCENES_PAGE_SIZE", "10"):
|
|
ds = ogr.Open("PLScenes:version=data_v1,FOLLOW_LINKS=YES")
|
|
assert ds is not None
|
|
|
|
lyr = ds.GetLayer(0)
|
|
assert lyr is not None
|
|
|
|
lyr.SetAttributeFilter("permissions = 'assets:download'")
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
catalog = lyr.GetName()
|
|
scene = f["id"]
|
|
f.DumpReadable()
|
|
|
|
lyr_defn = lyr.GetLayerDefn()
|
|
asset_name = None
|
|
for i in range(lyr_defn.GetFieldCount()):
|
|
fld_defn = lyr_defn.GetFieldDefn(i)
|
|
name = fld_defn.GetName()
|
|
if (
|
|
name.startswith("asset_")
|
|
and name.endswith("_activate_link")
|
|
and f.GetFieldAsString(i) != ""
|
|
):
|
|
asset_name = name[len("asset_") : -len("_activate_link")]
|
|
break
|
|
elif (
|
|
name.startswith("asset_")
|
|
and name.endswith("_location")
|
|
and f.GetFieldAsString(i) != ""
|
|
):
|
|
asset_name = name[len("asset_") : -len("_location")]
|
|
break
|
|
assert asset_name is not None
|
|
|
|
acquired_field = lyr_defn.GetFieldIndex("acquired")
|
|
assert (
|
|
acquired_field >= 0
|
|
and lyr_defn.GetFieldDefn(acquired_field).GetType() == ogr.OFTDateTime
|
|
)
|
|
|
|
if not f.IsFieldSet(acquired_field):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
int_field = -1
|
|
float_field = -1
|
|
string_field = -1
|
|
for i in range(lyr_defn.GetFieldCount()):
|
|
typ = lyr_defn.GetFieldDefn(i).GetType()
|
|
if int_field < 0 and typ == ogr.OFTInteger and f.IsFieldSet(i):
|
|
int_field = i
|
|
elif float_field < 0 and typ == ogr.OFTReal and f.IsFieldSet(i):
|
|
float_field = i
|
|
elif string_field < 0 and typ == ogr.OFTString and f.IsFieldSet(i):
|
|
string_field = i
|
|
|
|
filtr = "acquired='%s'" % f.GetFieldAsString(acquired_field)
|
|
if int_field >= 0:
|
|
name = lyr_defn.GetFieldDefn(int_field).GetName()
|
|
mini = f.GetField(int_field) - 1
|
|
maxi = f.GetField(int_field) + 1
|
|
filtr += " AND %s >= %d AND %s <= %d" % (name, mini, name, maxi)
|
|
if float_field >= 0:
|
|
name = lyr_defn.GetFieldDefn(float_field).GetName()
|
|
mini = f.GetField(float_field) - 0.01
|
|
maxi = f.GetField(float_field) + 0.01
|
|
filtr += " AND %s BETWEEN %f AND %f" % (name, mini, maxi)
|
|
if string_field >= 0:
|
|
name = lyr_defn.GetFieldDefn(string_field).GetName()
|
|
value = f.GetField(string_field)
|
|
filtr += " AND %s = '%s'" % (name, value)
|
|
|
|
lyr.SetAttributeFilter(filtr)
|
|
f = lyr.GetNextFeature()
|
|
assert f is not None
|
|
|
|
ds = None
|
|
|
|
dsname = "PLScenes:version=data_v1,itemtypes=%s,scene=%s,asset=%s" % (
|
|
catalog,
|
|
scene,
|
|
asset_name,
|
|
)
|
|
ds = gdal.Open(dsname)
|
|
assert ds is not None, dsname
|
|
assert ds.RasterCount != 0
|