479 строки
18 KiB
Python
Исполняемый файл
479 строки
18 KiB
Python
Исполняемый файл
#!/usr/bin/env pytest
|
|
# -*- coding: utf-8 -*-
|
|
###############################################################################
|
|
# $Id$
|
|
#
|
|
# Project: GDAL/OGR Test Suite
|
|
# Purpose: Earth Engine Data API driver test suite.
|
|
# Author: Even Rouault, even dot rouault at spatialys.com
|
|
#
|
|
###############################################################################
|
|
# Copyright (c) 2017, 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 json
|
|
|
|
import gdaltest
|
|
import pytest
|
|
|
|
from osgeo import gdal, ogr
|
|
|
|
pytestmark = pytest.mark.require_driver("EEDA")
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
@pytest.fixture(autouse=True, scope="module")
|
|
def startup_and_cleanup():
|
|
with gdal.config_option("CPL_CURL_ENABLE_VSIMEM", "YES"):
|
|
yield
|
|
|
|
gdal.Unlink("/vsimem/ee/")
|
|
gdal.Unlink(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages?pageSize=1"
|
|
)
|
|
gdal.Unlink(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages?pageToken=myToken"
|
|
)
|
|
gdal.Unlink(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages?filter=raw%5Ffilter"
|
|
)
|
|
|
|
|
|
###############################################################################
|
|
# Nominal case
|
|
|
|
|
|
def test_eeda_2():
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages?pageSize=1",
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"properties": {
|
|
"string_field": "bar",
|
|
"int_field": 1,
|
|
"int64_field": 123456789012,
|
|
"double_field": 1.23,
|
|
}
|
|
}
|
|
]
|
|
}
|
|
),
|
|
)
|
|
|
|
# To please the unregistering of the persistent connection
|
|
gdal.FileFromMemBuffer("/vsimem/ee/", "")
|
|
|
|
with gdal.config_option("EEDA_BEARER", "mybearer"):
|
|
|
|
with gdal.config_option("EEDA_URL", "/vsimem/ee/"):
|
|
ds = ogr.Open("EEDA:collection")
|
|
|
|
lyr = ds.GetLayer(0)
|
|
|
|
assert lyr.TestCapability(ogr.OLCStringsAsUTF8) == 1
|
|
|
|
assert lyr.TestCapability("foo") == 0
|
|
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 8 + 7 + 4
|
|
|
|
assert lyr.GetExtent() == (-180.0, 180.0, -90.0, 90.0)
|
|
|
|
assert lyr.GetFeatureCount() == -1
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages",
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/first_feature",
|
|
"id": "collection/first_feature",
|
|
"updateTime": "2017-01-04T12:34:56.789Z",
|
|
"startTime": "2017-01-02T12:34:56.789Z",
|
|
"endTime": "2017-01-03T12:34:56.789Z",
|
|
"sizeBytes": 1,
|
|
"geometry": {
|
|
"type": "Polygon",
|
|
"coordinates": [
|
|
[
|
|
[2, 49],
|
|
[2.1, 49],
|
|
[2.1, 49.1],
|
|
[2, 49.1],
|
|
[2, 49],
|
|
]
|
|
],
|
|
},
|
|
"properties": {
|
|
"string_field": "bar",
|
|
"int_field": 1,
|
|
"int64_field": 123456789012,
|
|
"double_field": 1.23,
|
|
"another_prop": 3,
|
|
},
|
|
"bands": [
|
|
{
|
|
"id": "B1",
|
|
"dataType": {
|
|
"precision": "INT",
|
|
"range": {"max": 255},
|
|
},
|
|
"grid": {
|
|
"crsCode": "EPSG:32610",
|
|
"affineTransform": {
|
|
"translateX": 499980,
|
|
"translateY": 4200000,
|
|
"scaleX": 60,
|
|
"scaleY": -60,
|
|
},
|
|
"dimensions": {"width": 1830, "height": 1831},
|
|
},
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/second_feature"
|
|
},
|
|
],
|
|
"nextPageToken": "myToken",
|
|
}
|
|
),
|
|
)
|
|
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f.GetField("name")
|
|
!= "projects/earthengine-public/assets/collection/first_feature"
|
|
or f.GetField("id") != "collection/first_feature"
|
|
or f.GetField("gdal_dataset")
|
|
!= "EEDAI:projects/earthengine-public/assets/collection/first_feature"
|
|
or f.GetField("updateTime") != "2017/01/04 12:34:56.789+00"
|
|
or f.GetField("startTime") != "2017/01/02 12:34:56.789+00"
|
|
or f.GetField("endTime") != "2017/01/03 12:34:56.789+00"
|
|
or f.GetField("sizeBytes") != 1
|
|
or f.GetField("band_count") != 1
|
|
or f.GetField("band_max_width") != 1830
|
|
or f.GetField("band_max_height") != 1831
|
|
or f.GetField("band_min_pixel_size") != 60
|
|
or f.GetField("band_upper_left_x") != 499980
|
|
or f.GetField("band_upper_left_y") != 4200000
|
|
or f.GetField("band_crs") != "EPSG:32610"
|
|
or f.GetField("string_field") != "bar"
|
|
or f.GetField("int_field") != 1
|
|
or f.GetField("int64_field") != 123456789012
|
|
or f.GetField("double_field") != 1.23
|
|
or f.GetField("other_properties") != '{ "another_prop": 3 }'
|
|
or f.GetGeometryRef().ExportToWkt()
|
|
!= "MULTIPOLYGON (((2 49,2.1 49.0,2.1 49.1,2.0 49.1,2 49)))"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f.GetField("name")
|
|
!= "projects/earthengine-public/assets/collection/second_feature"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages?pageToken=myToken",
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/third_feature"
|
|
}
|
|
]
|
|
}
|
|
),
|
|
)
|
|
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f.GetField("name")
|
|
!= "projects/earthengine-public/assets/collection/third_feature"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
f = lyr.GetNextFeature()
|
|
assert f is None
|
|
|
|
lyr.ResetReading()
|
|
|
|
f = lyr.GetNextFeature()
|
|
if (
|
|
f.GetField("name")
|
|
!= "projects/earthengine-public/assets/collection/first_feature"
|
|
):
|
|
f.DumpReadable()
|
|
pytest.fail()
|
|
|
|
lyr.SetAttributeFilter("EEDA:raw_filter")
|
|
|
|
gdal.FileFromMemBuffer(
|
|
"/vsimem/ee/projects/earthengine-public/assets/collection:listImages?filter=raw%5Ffilter",
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/raw_filter"
|
|
}
|
|
]
|
|
}
|
|
),
|
|
)
|
|
|
|
f = lyr.GetNextFeature()
|
|
assert (
|
|
f.GetField("name")
|
|
== "projects/earthengine-public/assets/collection/raw_filter"
|
|
)
|
|
|
|
lyr.SetAttributeFilter(None)
|
|
lyr.SetAttributeFilter(
|
|
"startTime >= '1980-01-01T00:00:00Z' AND "
|
|
+ "string_field = 'bar' AND "
|
|
+ "int_field > 0 AND "
|
|
+ "int_field < 2 AND "
|
|
+ "int64_field >= 0 AND "
|
|
+ "int64_field <= 9999999999999 AND "
|
|
+ "double_field != 3.5 AND "
|
|
+ "string_field IN ('bar', 'baz') AND "
|
|
+ "NOT( int_field IN (0) OR double_field IN (3.5) )"
|
|
)
|
|
|
|
tmpfile = "/vsimem/ee/projects/earthengine-public/assets/collection:listImages?region=%7B%20%22type%22%3A%20%22Polygon%22%2C%20%22coordinates%22%3A%20%5B%20%5B%20%5B%20%2D180%2E0%2C%20%2D90%2E0%20%5D%2C%20%5B%20%2D180%2E0%2C%2090%2E0%20%5D%2C%20%5B%20180%2E0%2C%2090%2E0%20%5D%2C%20%5B%20180%2E0%2C%20%2D90%2E0%20%5D%2C%20%5B%20%2D180%2E0%2C%20%2D90%2E0%20%5D%20%5D%20%5D%20%7D&filter=%28%28%28string%5Ffield%20%3D%20%22bar%22%20AND%20%28int%5Ffield%20%3E%200%20AND%20int%5Ffield%20%3C%202%29%29%20AND%20%28%28int64%5Ffield%20%3E%3D%200%20AND%20int64%5Ffield%20%3C%3D%209999999999999%29%20AND%20%28double%5Ffield%20%21%3D%203%2E5%20AND%20string%5Ffield%20%3D%20%22bar%22%20OR%20string%5Ffield%20%3D%20%22baz%22%29%29%29%20AND%20%28NOT%20%28int%5Ffield%20%3D%200%20OR%20double%5Ffield%20%3D%203%2E5%29%29%29&startTime=1980%2D01%2D01T00%3A00%3A00Z"
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/filtered_feature",
|
|
"updateTime": "2017-01-03T12:34:56.789Z",
|
|
"startTime": "2017-01-02T12:34:56.789Z",
|
|
"sizeBytes": 1,
|
|
"geometry": {
|
|
"type": "Polygon",
|
|
"coordinates": [
|
|
[
|
|
[2, 49],
|
|
[2.1, 49],
|
|
[2.1, 49.1],
|
|
[2, 49.1],
|
|
[2, 49],
|
|
]
|
|
],
|
|
},
|
|
"properties": {
|
|
"string_field": "bar",
|
|
"int_field": 1,
|
|
"int64_field": 123456789012,
|
|
"double_field": 1.23,
|
|
"another_prop": 3,
|
|
},
|
|
},
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/second_feature"
|
|
},
|
|
]
|
|
}
|
|
),
|
|
):
|
|
|
|
lyr.SetSpatialFilterRect(-180, -90, 180, 90)
|
|
|
|
f = lyr.GetNextFeature()
|
|
|
|
assert (
|
|
f.GetField("name")
|
|
== "projects/earthengine-public/assets/collection/filtered_feature"
|
|
)
|
|
|
|
lyr.SetSpatialFilter(None)
|
|
|
|
# Test time equality with second granularity
|
|
lyr.SetAttributeFilter(
|
|
"startTime >= '1980-01-01T00:00:00Z' AND endTime <= '1980-01-02T23:59:59Z'"
|
|
)
|
|
|
|
tmpfile = "/vsimem/ee/projects/earthengine-public/assets/collection:listImages?startTime=1980%2D01%2D01T00%3A00%3A00Z&endTime=1980%2D01%2D02T23%3A59%3A59Z"
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/filtered_feature",
|
|
"startTime": "1980-01-01T00:00:00Z",
|
|
"endTime": "1980-01-02T23:59:59Z",
|
|
},
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/second_feature"
|
|
},
|
|
]
|
|
}
|
|
),
|
|
):
|
|
|
|
f = lyr.GetNextFeature()
|
|
|
|
assert (
|
|
f.GetField("name")
|
|
== "projects/earthengine-public/assets/collection/filtered_feature"
|
|
)
|
|
|
|
# Test time equality with day granularity
|
|
lyr.SetAttributeFilter("startTime = '1980-01-01' AND endTime = '1980-01-02'")
|
|
|
|
tmpfile = "/vsimem/ee/projects/earthengine-public/assets/collection:listImages?startTime=1980%2D01%2D01T00%3A00%3A00Z&endTime=1980%2D01%2D02T23%3A59%3A59Z"
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/filtered_feature",
|
|
"startTime": "1980-01-01T12:00:00Z",
|
|
"endTime": "1980-01-02T23:59:59Z",
|
|
},
|
|
{
|
|
"name": "projects/earthengine-public/assets/collection/second_feature"
|
|
},
|
|
]
|
|
}
|
|
),
|
|
):
|
|
|
|
f = lyr.GetNextFeature()
|
|
|
|
assert (
|
|
f.GetField("name")
|
|
== "projects/earthengine-public/assets/collection/filtered_feature"
|
|
)
|
|
|
|
ds = None
|
|
|
|
|
|
###############################################################################
|
|
# Nominal case where collection is in eedaconf.json
|
|
|
|
|
|
def test_eeda_3():
|
|
|
|
with gdal.config_options({"EEDA_BEARER": "mybearer", "EEDA_URL": "/vsimem/ee/"}):
|
|
ds = ogr.Open("EEDA:##example_collection/example_subcollection")
|
|
|
|
lyr = ds.GetLayer(0)
|
|
|
|
assert lyr.GetLayerDefn().GetFieldCount() == 8 + 7 + 4
|
|
ds = None
|
|
|
|
|
|
###############################################################################
|
|
# Test that name and id variants are handled correctly.
|
|
|
|
|
|
def test_eeda_4():
|
|
|
|
with gdaltest.config_options(
|
|
{"EEDA_BEARER": "mybearer", "EEDA_URL": "/vsimem/ee/"}
|
|
):
|
|
|
|
# User asset ID ("users/**").
|
|
tmpfile = "/vsimem/ee/projects/earthengine-legacy/assets/users/foo:listImages?pageSize=1"
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{"name": "projects/earthengine-legacy/assets/users/foo/bar"}
|
|
]
|
|
}
|
|
),
|
|
):
|
|
assert ogr.Open("EEDA:users/foo").GetLayer(0)
|
|
|
|
# Project asset ID ("projects/**").
|
|
tmpfile = "/vsimem/ee/projects/earthengine-legacy/assets/projects/foo:listImages?pageSize=1"
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{"name": "projects/earthengine-legacy/assets/projects/foo/bar"}
|
|
]
|
|
}
|
|
),
|
|
):
|
|
ds = ogr.Open("EEDA:projects/foo")
|
|
assert ds.GetLayer(0)
|
|
ds = None
|
|
|
|
# Multi-folder project asset ID ("projects/foo/bar/baz").
|
|
tmpfile = "/vsimem/ee/projects/earthengine-legacy/assets/projects/foo/bar/baz:listImages?pageSize=1"
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{
|
|
"images": [
|
|
{
|
|
"name": "projects/earthengine-legacy/assets/projects/foo/bar/baz/qux"
|
|
}
|
|
]
|
|
}
|
|
),
|
|
):
|
|
ds = ogr.Open("EEDA:projects/foo/bar/baz")
|
|
assert ds.GetLayer(0)
|
|
ds = None
|
|
|
|
# Public-catalog asset ID (e.g. "LANDSAT").
|
|
tmpfile = (
|
|
"/vsimem/ee/projects/earthengine-public/assets/foo:listImages?pageSize=1"
|
|
)
|
|
with gdaltest.tempfile(
|
|
tmpfile,
|
|
json.dumps(
|
|
{"images": [{"name": "projects/earthengine-public/assets/foo/bar"}]}
|
|
),
|
|
):
|
|
ds = ogr.Open("EEDA:foo")
|
|
assert ds.GetLayer(0)
|
|
ds = None
|
|
|
|
# Asset name ("projects/*/assets/**").
|
|
tmpfile = "/vsimem/ee/projects/foo/assets/bar:listImages?pageSize=1"
|
|
with gdaltest.tempfile(
|
|
tmpfile, json.dumps({"images": [{"name": "projects/foo/assets/bar/baz"}]})
|
|
):
|
|
ds = ogr.Open("EEDA:projects/foo/assets/bar")
|
|
assert ds.GetLayer(0)
|
|
ds = None
|