From edc97e9a68da64b4cc6d09c9ed120d2fdbb41127 Mon Sep 17 00:00:00 2001 From: Erik Seglem Date: Thu, 9 Feb 2023 08:15:58 -0500 Subject: [PATCH] Replace values above limit with limit value. (#526) * Set limit to max value rather than error. Fixes #496. * Update limit tests. * Update changelog. --- CHANGES.md | 1 + stac_fastapi/pgstac/tests/api/test_api.py | 2 +- stac_fastapi/sqlalchemy/tests/api/test_api.py | 2 +- .../types/stac_fastapi/types/search.py | 30 +++++++++++++++++-- stac_fastapi/types/tests/test_limit.py | 22 ++++++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 stac_fastapi/types/tests/test_limit.py diff --git a/CHANGES.md b/CHANGES.md index 7cbbe524e..b29958eaa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ * Updated CI to test against [pgstac v0.6.12](https://github.com/stac-utils/pgstac/releases/tag/v0.6.12) ([#511](https://github.com/stac-utils/stac-fastapi/pull/511)) * Reworked `update_openapi` and added a test for it ([#523](https://github.com/stac-utils/stac-fastapi/pull/523)) +* Limit values above 10,000 are now replaced with 10,000 instead of returning a 400 error ([#526](https://github.com/stac-utils/stac-fastapi/pull/526)) ### Removed diff --git a/stac_fastapi/pgstac/tests/api/test_api.py b/stac_fastapi/pgstac/tests/api/test_api.py index 7e030c923..e3baf32c1 100644 --- a/stac_fastapi/pgstac/tests/api/test_api.py +++ b/stac_fastapi/pgstac/tests/api/test_api.py @@ -202,7 +202,7 @@ async def test_app_query_extension_limit_gt10000( params = {"limit": 10001} resp = await app_client.post("/search", json=params) - assert resp.status_code == 400 + assert resp.status_code == 200 async def test_app_query_extension_gt(load_test_data, app_client, load_test_collection): diff --git a/stac_fastapi/sqlalchemy/tests/api/test_api.py b/stac_fastapi/sqlalchemy/tests/api/test_api.py index 69dccab3b..6fdbb6ed8 100644 --- a/stac_fastapi/sqlalchemy/tests/api/test_api.py +++ b/stac_fastapi/sqlalchemy/tests/api/test_api.py @@ -209,7 +209,7 @@ def test_app_query_extension_limit_gt10000( params = {"limit": 10001} resp = app_client.post("/search", json=params) - assert resp.status_code == 400 + assert resp.status_code == 200 def test_app_query_extension_limit_10000( diff --git a/stac_fastapi/types/stac_fastapi/types/search.py b/stac_fastapi/types/stac_fastapi/types/search.py index 67f0125b9..185ec4754 100644 --- a/stac_fastapi/types/stac_fastapi/types/search.py +++ b/stac_fastapi/types/stac_fastapi/types/search.py @@ -8,7 +8,7 @@ from datetime import datetime from enum import auto from types import DynamicClassAttribute -from typing import Any, Callable, Dict, List, Optional, Union +from typing import Any, Callable, Dict, Generator, List, Optional, Union import attr from geojson_pydantic.geometries import ( @@ -20,7 +20,9 @@ Polygon, _GeometryBase, ) -from pydantic import BaseModel, conint, validator +from pydantic import BaseModel, ConstrainedInt, validator +from pydantic.errors import NumberNotGtError +from pydantic.validators import int_validator from stac_pydantic.shared import BBox from stac_pydantic.utils import AutoValueEnum @@ -30,6 +32,28 @@ NumType = Union[float, int] +class Limit(ConstrainedInt): + """An positive integer that maxes out at 10,000.""" + + ge: int = 1 + le: int = 10_000 + + @classmethod + def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]: + """Yield the relevant validators.""" + yield int_validator + yield cls.validate + + @classmethod + def validate(cls, value: int) -> int: + """Validate the integer value.""" + if value < cls.ge: + raise NumberNotGtError(limit_value=cls.ge) + if value > cls.le: + return cls.le + return value + + class Operator(str, AutoValueEnum): """Defines the set of operators supported by the API.""" @@ -97,7 +121,7 @@ class BaseSearchPostRequest(BaseModel): Union[Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon] ] datetime: Optional[str] - limit: Optional[conint(gt=0, le=10000)] = 10 + limit: Optional[Limit] = 10 @property def start_date(self) -> Optional[datetime]: diff --git a/stac_fastapi/types/tests/test_limit.py b/stac_fastapi/types/tests/test_limit.py new file mode 100644 index 000000000..e5b2125bd --- /dev/null +++ b/stac_fastapi/types/tests/test_limit.py @@ -0,0 +1,22 @@ +import pytest +from pydantic import ValidationError + +from stac_fastapi.types.search import BaseSearchPostRequest + + +@pytest.mark.parametrize("value", [0, -1]) +def test_limit_ge(value): + with pytest.raises(ValidationError): + BaseSearchPostRequest(limit=value) + + +@pytest.mark.parametrize("value", [1, 10_000]) +def test_limit(value): + search = BaseSearchPostRequest(limit=value) + assert search.limit == value + + +@pytest.mark.parametrize("value", [10_001, 100_000, 1_000_000]) +def test_limit_le(value): + search = BaseSearchPostRequest(limit=value) + assert search.limit == 10_000