From 1bb92dbb57583caa463499400a58d306f7fb4688 Mon Sep 17 00:00:00 2001 From: vincentsarago Date: Tue, 28 Oct 2025 10:16:49 +0100 Subject: [PATCH 1/3] update pypgstac version and tests multiple versions --- .github/workflows/cicd.yaml | 12 +++------- setup.py | 9 ++++--- tests/conftest.py | 15 ++++++------ tests/resources/test_collection.py | 38 +++++++++++++++++++++++------- tests/resources/test_item.py | 8 ++++--- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml index 308ccc1..177d683 100644 --- a/.github/workflows/cicd.yaml +++ b/.github/workflows/cicd.yaml @@ -11,12 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - include: - - {python: '3.12', pypgstac: '0.9.*'} - - {python: '3.12', pypgstac: '0.8.*'} - - {python: '3.11', pypgstac: '0.8.*'} - - {python: '3.10', pypgstac: '0.8.*'} - - {python: '3.9', pypgstac: '0.8.*'} + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14'] timeout-minutes: 20 @@ -45,7 +40,6 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install .[dev,server,validation] - python -m pip install "pypgstac==${{ matrix.pypgstac }}" - name: Run test suite run: python -m pytest --cov stac_fastapi.pgstac --cov-report xml --cov-report term-missing @@ -78,7 +72,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: "3.11" + python-version: "3.14" cache: pip cache-dependency-path: setup.py @@ -107,7 +101,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: "3.11" + python-version: "3.14" cache: pip cache-dependency-path: setup.py diff --git a/setup.py b/setup.py index b9fe741..517e556 100644 --- a/setup.py +++ b/setup.py @@ -16,17 +16,16 @@ "buildpg", "brotli_asgi", "cql2>=0.3.6", - "pypgstac>=0.8,<0.10", + "pypgstac>=0.9,<0.10", + "hydraters>=0.1.3", "typing_extensions>=4.9.0", "jsonpatch>=1.33.0", "json-merge-patch>=0.3.0", - "hydraters>=0.1.3", ] extra_reqs = { "dev": [ "pystac[validation]", - "pypgstac[psycopg]==0.9.*", "pytest-postgresql", "pytest", "pytest-cov", @@ -37,6 +36,8 @@ "httpx", "twine", "wheel", + "psycopg[binary]==3.1.*", + "psycopg-pool==3.1.*", ], "docs": [ "black>=23.10.1", @@ -68,6 +69,8 @@ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "License :: OSI Approved :: MIT License", ], keywords="STAC FastAPI COG", diff --git a/tests/conftest.py b/tests/conftest.py index 6bba3ef..4a71d05 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,7 +9,6 @@ import pytest from fastapi import APIRouter from httpx import ASGITransport, AsyncClient -from pypgstac import __version__ as pgstac_version from pypgstac.db import PgstacDB from pypgstac.migrate import Migrate from pytest_postgresql.janitor import DatabaseJanitor @@ -54,12 +53,6 @@ logger = logging.getLogger(__name__) -requires_pgstac_0_9_2 = pytest.mark.skipif( - tuple(map(int, pgstac_version.split("."))) < (0, 9, 2), - reason="PgSTAC>=0.9.2 required", -) - - @pytest.fixture(scope="session") def database(postgresql_proc): with DatabaseJanitor( @@ -79,7 +72,13 @@ def database(postgresql_proc): yield jan -@pytest.fixture(autouse=True) +@pytest.fixture( + params=[ + "0.8.6", + "0.9.8", + ], + autouse=True, +) async def pgstac(database): connection = f"postgresql://{database.user}:{quote(database.password)}@{database.host}:{database.port}/{database.dbname}" yield diff --git a/tests/resources/test_collection.py b/tests/resources/test_collection.py index 013f9ba..049ff82 100644 --- a/tests/resources/test_collection.py +++ b/tests/resources/test_collection.py @@ -4,8 +4,6 @@ import pytest from stac_pydantic import Collection -from ..conftest import requires_pgstac_0_9_2 - async def test_create_collection(app_client, load_test_data: Callable): in_json = load_test_data("test_collection.json") @@ -349,11 +347,15 @@ async def test_get_collections_search( assert len(resp.json()["collections"]) == 2 -@requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_collection_search_freetext( app_client, load_test_collection, load_test2_collection ): + res = await app_client.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + # free-text resp = await app_client.get( "/collections", @@ -388,11 +390,15 @@ async def test_collection_search_freetext( assert len(resp.json()["collections"]) == 0 -@requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_collection_search_freetext_advanced( app_client_advanced_freetext, load_test_collection, load_test2_collection ): + res = await app_client_advanced_freetext.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + # free-text resp = await app_client_advanced_freetext.get( "/collections", @@ -436,9 +442,13 @@ async def test_collection_search_freetext_advanced( assert len(resp.json()["collections"]) == 0 -@requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_all_collections_with_pagination(app_client, load_test_data): + res = await app_client.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + data = load_test_data("test_collection.json") collection_id = data["id"] for ii in range(0, 12): @@ -468,9 +478,13 @@ async def test_all_collections_with_pagination(app_client, load_test_data): assert {"root", "self"} == {link["rel"] for link in links} -@requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_all_collections_without_pagination(app_client_no_ext, load_test_data): + res = await app_client_no_ext.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + data = load_test_data("test_collection.json") collection_id = data["id"] for ii in range(0, 12): @@ -491,11 +505,15 @@ async def test_all_collections_without_pagination(app_client_no_ext, load_test_d assert {"root", "self"} == {link["rel"] for link in links} -@requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_get_collections_search_pagination( app_client, load_test_collection, load_test2_collection ): + res = await app_client.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + resp = await app_client.get("/collections") assert resp.json()["numberReturned"] == 2 assert resp.json()["numberMatched"] == 2 @@ -621,12 +639,16 @@ async def test_get_collections_search_pagination( assert {"root", "self"} == {link["rel"] for link in links} -@requires_pgstac_0_9_2 @pytest.mark.xfail(strict=False) @pytest.mark.asyncio async def test_get_collections_search_offset_1( app_client, load_test_collection, load_test2_collection ): + res = await app_client.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + # BUG: pgstac doesn't return a `prev` link when limit is not set # offset=1, should have a `previous` link resp = await app_client.get( diff --git a/tests/resources/test_item.py b/tests/resources/test_item.py index b6d3664..b7795fb 100644 --- a/tests/resources/test_item.py +++ b/tests/resources/test_item.py @@ -18,8 +18,6 @@ from stac_fastapi.pgstac.models.links import CollectionLinks -from ..conftest import requires_pgstac_0_9_2 - async def test_create_collection(app_client, load_test_data: Callable): in_json = load_test_data("test_collection.json") @@ -1693,9 +1691,13 @@ async def test_get_search_link_media(app_client): assert get_self_link["type"] == "application/geo+json" -@requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_item_search_freetext(app_client, load_test_data, load_test_collection): + res = await app_client.get("/_mgmt/health") + pgstac_version = res.json()["pgstac"]["pgstac_version"] + if tuple(map(int, pgstac_version.split("."))) < (0, 9, 2): + pass + test_item = load_test_data("test_item.json") resp = await app_client.post( f"/collections/{test_item['collection']}/items", json=test_item From d3012fc12346d34aa66869d44627dbb4673821a8 Mon Sep 17 00:00:00 2001 From: vincentsarago Date: Tue, 28 Oct 2025 15:23:18 +0100 Subject: [PATCH 2/3] use python 3.11 --- .github/workflows/cicd.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml index 177d683..3e850ec 100644 --- a/.github/workflows/cicd.yaml +++ b/.github/workflows/cicd.yaml @@ -72,7 +72,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: "3.14" + python-version: "3.11" cache: pip cache-dependency-path: setup.py @@ -101,7 +101,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v6 with: - python-version: "3.14" + python-version: "3.11" cache: pip cache-dependency-path: setup.py From ff7b02bef538036cb2740c717a933d2ebfb02592 Mon Sep 17 00:00:00 2001 From: vincentsarago Date: Tue, 28 Oct 2025 16:14:27 +0100 Subject: [PATCH 3/3] revert --- .github/workflows/cicd.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml index 3e850ec..5c2df79 100644 --- a/.github/workflows/cicd.yaml +++ b/.github/workflows/cicd.yaml @@ -5,7 +5,6 @@ on: pull_request: branches: [main] - jobs: test: runs-on: ubuntu-latest