diff --git a/tests/conftest.py b/tests/conftest.py index 4b58541..0f0adf8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,7 +9,6 @@ import pytest import rasterio from pypgstac.db import PgstacDB -from pypgstac.load import Loader from pypgstac.migrate import Migrate from pytest_postgresql.janitor import DatabaseJanitor from rasterio.errors import NotGeoreferencedWarning @@ -67,9 +66,25 @@ def database(postgresql_proc): yield jan -@pytest.fixture(scope="session") -def pgstac(database): +def load_json(filepath: str): + """yield JSON file content.""" + with open(filepath, "r") as f: + for line in f: + yield line.strip() + + +@pytest.fixture( + params=[ + "0.7.10", + "0.8.5", + "0.9.1", + ], + scope="session", +) +def pgstac(request, database): """Create PgSTAC fixture.""" + pgstac_version = request.param + connection = f"postgresql://{database.user}:{quote(database.password)}@{database.host}:{database.port}/{database.dbname}" # Clear PgSTAC @@ -80,15 +95,22 @@ def pgstac(database): print("Running to PgSTAC migration...") with PgstacDB(dsn=connection) as db: migrator = Migrate(db) - version = migrator.run_migration() + version = migrator.run_migration(pgstac_version) assert version print(f"PgSTAC version: {version}") - print("Load items and collection into PgSTAC") - loader = Loader(db=db) - loader.load_collections(collection) - loader.load_collections(collection_maxar) - loader.load_items(items) + with psycopg.connect(connection) as conn: + with conn.cursor() as cur: + for col in load_json(collection): + cur.execute( + "SELECT * FROM pgstac.create_collection(%s::jsonb);", (col,) + ) + for col in load_json(collection_maxar): + cur.execute( + "SELECT * FROM pgstac.create_collection(%s::jsonb);", (col,) + ) + for item in load_json(items): + cur.execute("SELECT * FROM pgstac.create_item(%s::jsonb);", (item,)) # Make sure we have 1 collection and 163 items in pgstac with psycopg.connect(connection) as conn: @@ -104,7 +126,7 @@ def pgstac(database): yield connection -@pytest.fixture(autouse=True) +@pytest.fixture def app(pgstac, monkeypatch): """Create app with connection to the pytest database.""" monkeypatch.setenv("AWS_ACCESS_KEY_ID", "jqt") diff --git a/tests/fixtures/maxar_BayOfBengal.json b/tests/fixtures/maxar_BayOfBengal.json index ffd02b0..1bfc3fe 100644 --- a/tests/fixtures/maxar_BayOfBengal.json +++ b/tests/fixtures/maxar_BayOfBengal.json @@ -1,133 +1 @@ -{ - "id": "MAXAR_BayofBengal_Cyclone_Mocha_May_23", - "type": "Collection", - "links": [], - "title": "Bay of Bengal Cyclone Mocha 2023", - "extent": { - "spatial": { - "bbox": [ - [ - 91.831615, - 19.982078842323997, - 92.97426268500965, - 21.666101 - ], - [ - 92.567815, - 20.18811887678192, - 92.74417544237298, - 20.62968532404085 - ], - [ - 92.72278776887262, - 20.104801, - 92.893524, - 20.630214 - ], - [ - 92.75855246040959, - 19.982078842323997, - 92.89682495377032, - 20.514473160464657 - ], - [ - 92.84253515935835, - 19.984656587012033, - 92.97426268500965, - 20.514418665444474 - ], - [ - 91.831615, - 21.518411, - 91.957078, - 21.666101 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2023-01-03T04:30:17Z", - "2023-05-22T04:35:25Z" - ] - ] - } - }, - "license": "CC-BY-NC-4.0", - "renders": { - "visual": { - "title": "Visual Image", - "assets": [ - "visual" - ], - "asset_bidx": ["visual|1,2,3"], - "minmax_zoom": [ - 8, - 22 - ], - "tilematrixsets": { - "WebMercatorQuad": [ - 8, - 22 - ] - } - }, - "color": { - "title": "Colored Image", - "assets": [ - "visual" - ], - "asset_bidx": ["visual|1"], - "colormap": { - "1": [0, 0, 0, 255], - "1000": [255, 255, 255, 255] - } - }, - "visualr": { - "title": "Rescaled Image", - "assets": [ - "visual" - ], - "asset_bidx": ["visual|1"], - "rescale": [ - [0, 100] - ] - } - }, - "description": "Maxar OpenData | Cyclone Mocha, a category five cyclone with 130 mph winds and torrential rain, hit parts of Myanmar and Bangladesh, forcing mass evacuations ahead of the storm. The cyclone, one of the most powerful to hit the region in the last decade, made landfall on Sunday, May 14, 2023, near Sittwe in Myanmar's Rakhine state. Rain and a storm surge caused widespread flooding in low-lying areas. The United National Office Coordination of Humanitarian Affairs stated that there had been extensive damage among already vulnerable communities and that communications with the affected areas have been difficult.", - "item_assets": { - "visual": { - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "roles": [ - "visual" - ], - "title": "Visual Image" - }, - "data-mask": { - "type": "application/geopackage+sqlite3", - "roles": [ - "data-mask" - ], - "title": "Data Mask" - }, - "ms_analytic": { - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "roles": [ - "data" - ], - "title": "Multispectral Image" - }, - "pan_analytic": { - "type": "image/tiff; application=geotiff; profile=cloud-optimized", - "roles": [ - "data" - ], - "title": "Panchromatic Image" - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/item-assets/v1.0.0/schema.json", - "https://stac-extensions.github.io/render/v1.0.0/schema.json" - ] -} +{"id":"MAXAR_BayofBengal_Cyclone_Mocha_May_23","type":"Collection","links":[],"title":"Bay of Bengal Cyclone Mocha 2023","extent":{"spatial":{"bbox":[[91.831615,19.982078842323997,92.97426268500965,21.666101],[92.567815,20.18811887678192,92.74417544237298,20.62968532404085],[92.72278776887262,20.104801,92.893524,20.630214],[92.75855246040959,19.982078842323997,92.89682495377032,20.514473160464657],[92.84253515935835,19.984656587012033,92.97426268500965,20.514418665444474],[91.831615,21.518411,91.957078,21.666101]]},"temporal":{"interval":[["2023-01-03T04:30:17Z","2023-05-22T04:35:25Z"]]}},"license":"CC-BY-NC-4.0","renders":{"visual":{"title":"Visual Image","assets":["visual"],"asset_bidx":["visual|1,2,3"],"minmax_zoom":[8,22],"tilematrixsets":{"WebMercatorQuad":[8,22]}},"color":{"title":"Colored Image","assets":["visual"],"asset_bidx":["visual|1"],"colormap":{"1":[0,0,0,255],"1000":[255,255,255,255]}},"visualr":{"title":"Rescaled Image","assets":["visual"],"asset_bidx":["visual|1"],"rescale":[[0,100]]}},"description":"Maxar OpenData | Cyclone Mocha, a category five cyclone with 130 mph winds and torrential rain, hit parts of Myanmar and Bangladesh, forcing mass evacuations ahead of the storm. The cyclone, one of the most powerful to hit the region in the last decade, made landfall on Sunday, May 14, 2023, near Sittwe in Myanmar's Rakhine state. Rain and a storm surge caused widespread flooding in low-lying areas. The United National Office Coordination of Humanitarian Affairs stated that there had been extensive damage among already vulnerable communities and that communications with the affected areas have been difficult.","item_assets":{"visual":{"type":"image/tiff; application=geotiff; profile=cloud-optimized","roles":["visual"],"title":"Visual Image"},"data-mask":{"type":"application/geopackage+sqlite3","roles":["data-mask"],"title":"Data Mask"},"ms_analytic":{"type":"image/tiff; application=geotiff; profile=cloud-optimized","roles":["data"],"title":"Multispectral Image"},"pan_analytic":{"type":"image/tiff; application=geotiff; profile=cloud-optimized","roles":["data"],"title":"Panchromatic Image"}},"stac_version":"1.0.0","stac_extensions":["https://stac-extensions.github.io/item-assets/v1.0.0/schema.json","https://stac-extensions.github.io/render/v1.0.0/schema.json"]} diff --git a/tests/fixtures/noaa-emergency-response.json b/tests/fixtures/noaa-emergency-response.json index 82c5cdb..3b0fbfc 100644 --- a/tests/fixtures/noaa-emergency-response.json +++ b/tests/fixtures/noaa-emergency-response.json @@ -1,30 +1 @@ -{ - "id": "noaa-emergency-response", - "type": "Collection", - "title": "NOAA Emergency Response Imagery", - "description": "NOAA Emergency Response Imagery hosted on AWS Public Dataset.", - "stac_version": "1.0.0", - "license": "public-domain", - "links": [], - "extent": { - "spatial": { - "bbox": [ - [ - -180, - -90, - 180, - 90 - ] - ] - }, - "temporal": { - "interval": [ - [ - "2005-01-01T00:00:00Z", - null - ] - ] - } - }, - "stac_extensions": [] -} +{"id":"noaa-emergency-response","type":"Collection","title":"NOAA Emergency Response Imagery","description":"NOAA Emergency Response Imagery hosted on AWS Public Dataset.","stac_version":"1.0.0","license":"public-domain","links":[],"extent":{"spatial":{"bbox":[[-180,-90,180,90]]},"temporal":{"interval":[["2005-01-01T00:00:00Z",null]]}},"stac_extensions":[]} diff --git a/titiler/pgstac/dependencies.py b/titiler/pgstac/dependencies.py index 45921b1..08eb9ab 100644 --- a/titiler/pgstac/dependencies.py +++ b/titiler/pgstac/dependencies.py @@ -103,11 +103,17 @@ def get_collection_id(pool: ConnectionPool, collection_id: str) -> str: # noqa: # TODO: adapt Mosaic Backend to accept Search object directly # we technically don't need to register the search request for /collections - cursor.execute("SELECT pgstac.readonly()") - if cursor.fetchone()["readonly"]: - raise ReadOnlyPgSTACError( - "PgSTAC instance is set to `read-only`, cannot register search query." - ) + try: + cursor.execute("SELECT pgstac.readonly()") + if cursor.fetchone()["readonly"]: + raise ReadOnlyPgSTACError( + "PgSTAC instance is set to `read-only`, cannot register search query." + ) + + # before pgstac 0.8.2, the read-only mode didn't exist + except pgErrors.UndefinedFunction: + conn.rollback() + pass cursor.row_factory = class_row(model.Search) cursor.execute( diff --git a/titiler/pgstac/factory.py b/titiler/pgstac/factory.py index d2c6a80..83d8c43 100644 --- a/titiler/pgstac/factory.py +++ b/titiler/pgstac/factory.py @@ -24,6 +24,7 @@ from fastapi import Body, Depends, FastAPI, HTTPException, Path, Query from fastapi.dependencies.utils import get_dependant, request_params_to_args from geojson_pydantic import Feature, FeatureCollection +from psycopg import errors as pgErrors from psycopg import sql from psycopg.rows import class_row, dict_row from pydantic import conint @@ -976,7 +977,7 @@ def point( } -def add_search_register_route( +def add_search_register_route( # noqa: C901 app: FastAPI, *, prefix: str = "", @@ -1003,11 +1004,18 @@ def register_search(request: Request, search_query=Depends(search_dependency)): with request.app.state.dbpool.connection() as conn: with conn.cursor(row_factory=dict_row) as cursor: - cursor.execute("SELECT pgstac.readonly()") - if cursor.fetchone()["readonly"]: - raise ReadOnlyPgSTACError( - "PgSTAC instance is set to `read-only`, cannot register search query." - ) + + try: + cursor.execute("SELECT pgstac.readonly()") + if cursor.fetchone()["readonly"]: + raise ReadOnlyPgSTACError( + "PgSTAC instance is set to `read-only`, cannot register search query." + ) + + # before pgstac 0.8.2, the read-only mode didn't exist + except pgErrors.UndefinedFunction: + conn.rollback() + pass cursor.row_factory = class_row(model.Search) cursor.execute(