diff --git a/CHANGES.md b/CHANGES.md index c99d49b2..992d23c3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,11 +2,29 @@ ## [Unreleased] -## [3.0.0b3] - 2024-07-25 +## [3.0.0] - 2024-07-29 + +Full changelog: https://stac-utils.github.io/stac-fastapi/migrations/v3.0.0/#changelog + +**Changes since 3.0.0b3:** + +### Changed + +* Add version pinning (`~=3.0`) for stac-fastapi submodules +* Moved `AsyncBaseFiltersClient` and `BaseFiltersClient` classes in `stac_fastapi.extensions.core.filter.client` submodule + +### Removed + +* Removed the `Context` extension +* Removed deprecated `stac_fastapi.api.openapi.config_openapi` method and `stac_fastapi.api.openapi.VndOaiResponse` class +* Removed `response_class` argument in `stac_fastapi.api.routes.create_async_endpoint` method +* Removed `filter_fields` property in `stac_fastapi.extensions.core.fields.request.PostFieldsExtension` class + +## 3.0.0b3 - 2024-07-25 ### Changed -* Add more openapi metadata in input models [#734](https://github.com/stac-utils/stac-fastapi/pull/734) +* Add more openapi metadata in input models ([#734](https://github.com/stac-utils/stac-fastapi/pull/734)) * Use same `Limit` (capped to `10_000`) for `/items` and `GET - /search` input models ([#738](https://github.com/stac-utils/stac-fastapi/pull/738)) ### Added @@ -14,13 +32,13 @@ * Add Free-text Extension ([#655](https://github.com/stac-utils/stac-fastapi/pull/655)) * Add Collection-Search Extension ([#736](https://github.com/stac-utils/stac-fastapi/pull/736), [#739](https://github.com/stac-utils/stac-fastapi/pull/739)) -## [3.0.0b2] - 2024-07-09 +## 3.0.0b2 - 2024-07-09 ### Changed -* move back to `@attrs` (instead of dataclass) for `APIRequest` (model for GET request) class type [#729](https://github.com/stac-utils/stac-fastapi/pull/729) +* move back to `@attrs` (instead of dataclass) for `APIRequest` (model for GET request) class type ([#729](https://github.com/stac-utils/stac-fastapi/pull/729)) -## [3.0.0b1] - 2024-07-05 +## 3.0.0b1 - 2024-07-05 ### Added @@ -32,33 +50,33 @@ ### Removed -* Removed the Filter Extension dependency from `AggregationExtensionPostRequest` and `AggregationExtensionGetRequest` [#716](https://github.com/stac-utils/stac-fastapi/pull/716) +* Removed the Filter Extension dependency from `AggregationExtensionPostRequest` and `AggregationExtensionGetRequest` ([#716](https://github.com/stac-utils/stac-fastapi/pull/716)) * Removed `pagination_extension` attribute in `stac_fastapi.api.app.StacApi` * Removed use of `pagination_extension` in `register_get_item_collection` function (User now need to construct the request model and pass it using `items_get_request_model` attribute) * Removed use of `FieldsExtension` in `stac_fastapi.api.app.StacApi`. If users use `FieldsExtension`, they would have to handle overpassing the model validation step by returning a `JSONResponse` from the `post_search` and `get_search` client methods. ### Changed -* Replaced `@attrs` with python `@dataclass` for `APIRequest` (model for GET request) class type [#714](https://github.com/stac-utils/stac-fastapi/pull/714) -* Moved `GETPagination`, `POSTPagination`, `GETTokenPagination` and `POSTTokenPagination` to `stac_fastapi.extensions.core.pagination.request` submodule [#717](https://github.com/stac-utils/stac-fastapi/pull/717) +* Replaced `@attrs` with python `@dataclass` for `APIRequest` (model for GET request) class type ([#714](https://github.com/stac-utils/stac-fastapi/pull/714)) +* Moved `GETPagination`, `POSTPagination`, `GETTokenPagination` and `POSTTokenPagination` to `stac_fastapi.extensions.core.pagination.request` submodule ([#717](https://github.com/stac-utils/stac-fastapi/pull/717)) * update FastAPI requirement to `>=0.111.0` -## [3.0.0a4] - 2024-06-27 +## 3.0.0a4 - 2024-06-27 ### Fixed -* Updated default filter language in filter extension's POST search request model to match the extension's documentation [#711](https://github.com/stac-utils/stac-fastapi/issues/711) +* Updated default filter language in filter extension's POST search request model to match the extension's documentation ([#711](https://github.com/stac-utils/stac-fastapi/issues/711)) ### Removed -* Removed the Filter Extension depenency from `AggregationExtensionPostRequest` and `AggregationExtensionGetRequest` [#716](https://github.com/stac-utils/stac-fastapi/pull/716) -* Removed `add_middleware` method in `StacApi` object and let starlette handle the middleware stack creation [721](https://github.com/stac-utils/stac-fastapi/pull/721) +* Removed the Filter Extension depenency from `AggregationExtensionPostRequest` and `AggregationExtensionGetRequest` ([#716](https://github.com/stac-utils/stac-fastapi/pull/716)) +* Removed `add_middleware` method in `StacApi` object and let starlette handle the middleware stack creation ([#721](https://github.com/stac-utils/stac-fastapi/pull/721)) -## [3.0.0a3] - 2024-06-13 +## 3.0.0a3 - 2024-06-13 ### Added -* Add base support for the Aggregation extension [#684](https://github.com/stac-utils/stac-fastapi/pull/684) +* Add base support for the Aggregation extension ([#684](https://github.com/stac-utils/stac-fastapi/pull/684)) ### Changed @@ -67,13 +85,13 @@ * Removed `default_includes` from `stac_fastapi.types.config.ApiSettings` ([#706](https://github.com/stac-utils/stac-fastapi/pull/706)) * Deprecated *Fields* extension `PostFieldsExtension.filter_fields` property ([#706](https://github.com/stac-utils/stac-fastapi/pull/706)) -## [3.0.0a2] - 2024-05-31 +## 3.0.0a2 - 2024-05-31 ### Fixed * Fix missing default (`None`) for optional `query` attribute in `QueryExtensionPostRequest` model ([#701](https://github.com/stac-utils/stac-fastapi/pull/701)) -## [3.0.0a1] - 2024-05-22 +## 3.0.0a1 - 2024-05-22 ### Changed @@ -89,7 +107,7 @@ * Make `str_to_interval` not return a tuple for single-value input (fixing `datetime` argument as passed to `get_search`). ([#692](https://github.com/stac-utils/stac-fastapi/pull/692)) -## [3.0.0a0] - 2024-05-06 +## 3.0.0a0 - 2024-05-06 ### Added @@ -450,15 +468,8 @@ * First PyPi release! -[Unreleased]: -[3.0.0b3]: -[3.0.0b2]: -[3.0.0b1]: -[3.0.0a4]: -[3.0.0a3]: -[3.0.0a2]: -[3.0.0a1]: -[3.0.0a0]: +[Unreleased]: +[3.0.0]: [2.5.5.post1]: [2.5.5]: [2.5.4]: diff --git a/VERSION b/VERSION index 005e92c1..4a36342f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0b3 +3.0.0 diff --git a/docs/src/migrations/v3.0.0.md b/docs/src/migrations/v3.0.0.md index f781687c..bc0b03b7 100644 --- a/docs/src/migrations/v3.0.0.md +++ b/docs/src/migrations/v3.0.0.md @@ -3,6 +3,60 @@ This document aims to help you update your application from **stac-fastapi** 2.5 to 3.0.0. +## CHANGELOG + +### Removed + +* Removed the `Context` extension +* Removed `stac_fastapi.api.openapi.config_openapi` method and `stac_fastapi.api.openapi.VndOaiResponse` class +* Removed `response_class` argument in `stac_fastapi.api.routes.create_async_endpoint` method +* Removed `filter_fields` property in `stac_fastapi.extensions.core.fields.request.PostFieldsExtension` class +* Removed `pagination_extension` attribute in `stac_fastapi.api.app.StacApi` +* Removed `default_includes` from `stac_fastapi.types.config.ApiSettings` ([#706](https://github.com/stac-utils/stac-fastapi/pull/706)) +* Removed use of `pagination_extension` in `register_get_item_collection` function (User now need to construct the request model and pass it using `items_get_request_model` attribute) +* Removed use of `FieldsExtension` in `stac_fastapi.api.app.StacApi`. NOTE: If users use `FieldsExtension`, they HAVE TO handle skipping the model validation step by returning a `JSONResponse` from the `post_search` and `get_search` client methods +* Removed `add_middleware` method in `StacApi` object and let starlette handle the middleware stack creation ([#721](https://github.com/stac-utils/stac-fastapi/pull/721)) +* Removed `pystac` dependecy, as it was just used for a *datetime-to-string* function ([#690](https://github.com/stac-utils/stac-fastapi/pull/690)) +* Removed internal Search and Operator Types in favor of stac_pydantic Types ([#625](https://github.com/stac-utils/stac-fastapi/pull/625)) + +### Changed + +* Update to **pydantic 2.0** ([#625](https://github.com/stac-utils/stac-fastapi/pull/625)) +* Update stac-pydantic requirement to `~3.1` ([#697](https://github.com/stac-utils/stac-fastapi/pull/697)) +* Switch from `fastapi` to `fastapi-slim` to avoid installing unwanted dependencies ([#687](https://github.com/stac-utils/stac-fastapi/pull/687)) +* Update FastAPI requirement to `>=0.111.0` +* Moved `AsyncBaseFiltersClient` and `BaseFiltersClient` classes in `stac_fastapi.extensions.core.filter.client` submodule +* Add more openapi metadata in input models ([#734](https://github.com/stac-utils/stac-fastapi/pull/734)) +* Use same `Limit` (capped to `10_000`) for `/items` and `GET - /search` input models ([#738](https://github.com/stac-utils/stac-fastapi/pull/738)) +* Moved `GETPagination`, `POSTPagination`, `GETTokenPagination` and `POSTTokenPagination` to `stac_fastapi.extensions.core.pagination.request` submodule ([#717](https://github.com/stac-utils/stac-fastapi/pull/717)) +* Added option for default route dependencies `*` can be used for `path` or `method` to match all allowed route. ([#705](https://github.com/stac-utils/stac-fastapi/pull/705)) +* Moved `AsyncBaseFiltersClient` and `BaseFiltersClient` classes in `stac_fastapi.extensions.core.filter.client` submodule ([#704](https://github.com/stac-utils/stac-fastapi/pull/704)) +* Replace Enum with `Literal` for `FilterLang`. ([#686](https://github.com/stac-utils/stac-fastapi/pull/686)) +* Fix response model *validation* ([#625](https://github.com/stac-utils/stac-fastapi/pull/625)) +* Use status code 201 for Item/Collection creation ([#625](https://github.com/stac-utils/stac-fastapi/pull/625)) +* Add `response_class` attribute in `FilterExtension` class +* Add version pinning (`~=3.0`) for stac-fastapi submodules + +### Fixed + +* Updated default `filter` language in filter extension's POST search request model to match the extension's documentation ([#711](https://github.com/stac-utils/stac-fastapi/issues/711)) +* Fix missing default (`None`) for optional `query` attribute in `QueryExtensionPostRequest` model ([#701](https://github.com/stac-utils/stac-fastapi/pull/701)) +* Make `str_to_interval` not return a tuple for single-value input (fixing `datetime` argument as passed to `get_search`). ([#692](https://github.com/stac-utils/stac-fastapi/pull/692)) + +### Added + +* Add enhanced middleware configuration to the StacApi class, enabling specific middleware options and dynamic addition post-application initialization. ([#442](https://github.com/stac-utils/stac-fastapi/pull/442)) +* Add *response* pydantic models to OpenAPI, even if model validation is turned off ([#625](https://github.com/stac-utils/stac-fastapi/pull/625)) +* Add attributes to `stac_fastapi.api.app.StacApi` to enable customization of request model for: + - `/collections`: **collections_get_request_model**, default to `EmptyRequest` + - `/collections/{collection_id}`: **collection_get_request_model**, default to `CollectionUri` + - `/collections/{collection_id}/items`: **items_get_request_model**, default to `ItemCollectionUri` + - `/collections/{collection_id}/items/{item_id}`: **item_get_request_model**, default to `ItemUri` +* Add **Aggregation** extension ([#684](https://github.com/stac-utils/stac-fastapi/pull/684)) +* Add **Free-text** extension ([#655](https://github.com/stac-utils/stac-fastapi/pull/655)) +* Add **Collection-Search** extension ([#736](https://github.com/stac-utils/stac-fastapi/pull/736), [#739](https://github.com/stac-utils/stac-fastapi/pull/739)) + + ## Dependencies - **pydantic~=2.0** diff --git a/pyproject.toml b/pyproject.toml index 8c1943d6..4786a7dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ section-order = ["future", "standard-library", "third-party", "first-party", "lo quote-style = "double" [tool.bumpversion] -current_version = "3.0.0b3" +current_version = "3.0.0" parse = """(?x) (?P\\d+)\\. (?P\\d+)\\. diff --git a/stac_fastapi/api/setup.py b/stac_fastapi/api/setup.py index 5050d3a7..7f4b541f 100644 --- a/stac_fastapi/api/setup.py +++ b/stac_fastapi/api/setup.py @@ -7,7 +7,7 @@ install_requires = [ "brotli_asgi", - "stac-fastapi.types", + "stac-fastapi.types~=3.0", ] extra_reqs = { diff --git a/stac_fastapi/api/stac_fastapi/api/config.py b/stac_fastapi/api/stac_fastapi/api/config.py index 275159a0..90ed60a4 100644 --- a/stac_fastapi/api/stac_fastapi/api/config.py +++ b/stac_fastapi/api/stac_fastapi/api/config.py @@ -12,7 +12,6 @@ class ApiExtensions(enum.Enum): Ref: https://github.com/stac-api-extensions """ - context = "context" fields = "fields" filter = "filter" query = "query" diff --git a/stac_fastapi/api/stac_fastapi/api/openapi.py b/stac_fastapi/api/stac_fastapi/api/openapi.py index ab90ce42..5aad3523 100644 --- a/stac_fastapi/api/stac_fastapi/api/openapi.py +++ b/stac_fastapi/api/stac_fastapi/api/openapi.py @@ -1,30 +1,10 @@ """openapi.""" -import warnings - from fastapi import FastAPI -from fastapi.openapi.utils import get_openapi from starlette.requests import Request from starlette.responses import JSONResponse, Response from starlette.routing import Route, request_response -from stac_fastapi.api.config import ApiExtensions -from stac_fastapi.types.config import ApiSettings - - -class VndOaiResponse(JSONResponse): - """JSON with custom, vendor content-type.""" - - media_type = "application/vnd.oai.openapi+json;version=3.0" - - def __init__(self, *args, **kwargs): - """Init function with deprecation warning.""" - warnings.warn( - "VndOaiResponse is deprecated and will be removed in v3.0", - DeprecationWarning, - ) - super().__init__(*args, **kwargs) - def update_openapi(app: FastAPI) -> FastAPI: """Update OpenAPI response content-type. @@ -55,33 +35,3 @@ async def patched_openapi_endpoint(req: Request) -> Response: # return the patched app return app - - -def config_openapi(app: FastAPI, settings: ApiSettings): - """Config openapi.""" - warnings.warn( - "config_openapi is deprecated and will be removed in v3.0", - DeprecationWarning, - ) - - def custom_openapi(): - """Config openapi.""" - if app.openapi_schema: - return app.openapi_schema - - openapi_schema = get_openapi( - title="Arturo STAC API", version="0.1", routes=app.routes - ) - - if settings.api_extension_is_enabled(ApiExtensions.fields): - openapi_schema["paths"]["/search"]["get"]["responses"]["200"]["content"][ - "application/json" - ]["schema"] = {"$ref": "#/components/schemas/ItemCollection"} - openapi_schema["paths"]["/search"]["post"]["responses"]["200"]["content"][ - "application/json" - ]["schema"] = {"$ref": "#/components/schemas/ItemCollection"} - - app.openapi_schema = openapi_schema - return app.openapi_schema - - app.openapi = custom_openapi diff --git a/stac_fastapi/api/stac_fastapi/api/routes.py b/stac_fastapi/api/stac_fastapi/api/routes.py index bd6f4d9c..c159facc 100644 --- a/stac_fastapi/api/stac_fastapi/api/routes.py +++ b/stac_fastapi/api/stac_fastapi/api/routes.py @@ -3,7 +3,6 @@ import copy import functools import inspect -import warnings from typing import Any, Callable, Dict, List, Optional, Type, TypedDict, Union from fastapi import Depends, params @@ -38,19 +37,12 @@ async def run(*args, **kwargs): def create_async_endpoint( func: Callable, request_model: Union[Type[APIRequest], Type[BaseModel], Dict], - response_class: Optional[Type[Response]] = None, ): """Wrap a function in a coroutine which may be used to create a FastAPI endpoint. Synchronous functions are executed asynchronously using a background thread. """ - if response_class: - warnings.warn( - "`response_class` option is deprecated, please set the Response class directly in the endpoint.", # noqa: E501 - DeprecationWarning, - ) - if not inspect.iscoroutinefunction(func): func = sync_to_async(func) diff --git a/stac_fastapi/api/stac_fastapi/api/version.py b/stac_fastapi/api/stac_fastapi/api/version.py index c09ebf00..5996faa4 100644 --- a/stac_fastapi/api/stac_fastapi/api/version.py +++ b/stac_fastapi/api/stac_fastapi/api/version.py @@ -1,2 +1,3 @@ """Library version.""" -__version__ = "3.0.0b3" + +__version__ = "3.0.0" diff --git a/stac_fastapi/extensions/setup.py b/stac_fastapi/extensions/setup.py index 39bc59b3..cf49b5d0 100644 --- a/stac_fastapi/extensions/setup.py +++ b/stac_fastapi/extensions/setup.py @@ -7,8 +7,8 @@ desc = f.read() install_requires = [ - "stac-fastapi.types", - "stac-fastapi.api", + "stac-fastapi.types~=3.0", + "stac-fastapi.api~=3.0", ] extra_reqs = { diff --git a/stac_fastapi/extensions/stac_fastapi/extensions/core/__init__.py b/stac_fastapi/extensions/stac_fastapi/extensions/core/__init__.py index 17eccde7..7fb122e8 100644 --- a/stac_fastapi/extensions/stac_fastapi/extensions/core/__init__.py +++ b/stac_fastapi/extensions/stac_fastapi/extensions/core/__init__.py @@ -2,7 +2,6 @@ from .aggregation import AggregationExtension from .collection_search import CollectionSearchExtension, CollectionSearchPostExtension -from .context import ContextExtension from .fields import FieldsExtension from .filter import FilterExtension from .free_text import FreeTextAdvancedExtension, FreeTextExtension @@ -13,7 +12,6 @@ __all__ = ( "AggregationExtension", - "ContextExtension", "FieldsExtension", "FilterExtension", "FreeTextExtension", diff --git a/stac_fastapi/extensions/stac_fastapi/extensions/core/context.py b/stac_fastapi/extensions/stac_fastapi/extensions/core/context.py deleted file mode 100644 index 4037ba93..00000000 --- a/stac_fastapi/extensions/stac_fastapi/extensions/core/context.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Context extension.""" - -import warnings -from typing import List, Optional - -import attr -from fastapi import FastAPI - -from stac_fastapi.types.extension import ApiExtension - - -@attr.s -class ContextExtension(ApiExtension): - """Context Extension. - - The Context extension adds a JSON object to ItemCollection responses (`/search`, - `/collections/{collection_id}/items`) which includes the number of items matched, - returned, and the limit requested. - https://github.com/stac-api-extensions/context - """ - - conformance_classes: List[str] = attr.ib( - factory=lambda: ["https://api.stacspec.org/v1.0.0-rc.2/item-search#context"] - ) - schema_href: Optional[str] = attr.ib( - default="https://raw.githubusercontent.com/stac-api-extensions/context/v1.0.0-rc.2/json-schema/schema.json" - ) - - def __attrs_post_init__(self): - """init.""" - warnings.warn( - "The ContextExtension is deprecated and will be removed in 3.0.", - DeprecationWarning, - stacklevel=1, - ) - - def register(self, app: FastAPI) -> None: - """Register the extension with a FastAPI application. - - Args: - app: target FastAPI application. - - Returns: - None - """ - pass diff --git a/stac_fastapi/extensions/stac_fastapi/extensions/core/fields/request.py b/stac_fastapi/extensions/stac_fastapi/extensions/core/fields/request.py index d3737ea4..02d3dd19 100644 --- a/stac_fastapi/extensions/stac_fastapi/extensions/core/fields/request.py +++ b/stac_fastapi/extensions/stac_fastapi/extensions/core/fields/request.py @@ -1,6 +1,5 @@ """Request models for the fields extension.""" -import warnings from typing import Dict, List, Optional, Set import attr @@ -44,31 +43,6 @@ def _get_field_dict(fields: Optional[Set[str]]) -> Dict: return field_dict - @property - def filter_fields(self) -> Dict: - """Create pydantic include/exclude expression. - - Create dictionary of fields to include/exclude on model export based on - the included and excluded fields passed to the API - Ref: https://pydantic-docs.helpmanual.io/usage/exporting_models/#advanced-include-and-exclude - """ - warnings.warn( - """The `PostFieldsExtension.filter_fields` - method is deprecated and will be removed in 3.0.""", - DeprecationWarning, - stacklevel=1, - ) - - # Always include default_includes, even if they - # exist in the exclude list. - include = (self.include or set()) - (self.exclude or set()) - include |= set() - - return { - "include": self._get_field_dict(include), - "exclude": self._get_field_dict(self.exclude), - } - def _fields_converter( val: Annotated[ diff --git a/stac_fastapi/extensions/stac_fastapi/extensions/version.py b/stac_fastapi/extensions/stac_fastapi/extensions/version.py index c09ebf00..5996faa4 100644 --- a/stac_fastapi/extensions/stac_fastapi/extensions/version.py +++ b/stac_fastapi/extensions/stac_fastapi/extensions/version.py @@ -1,2 +1,3 @@ """Library version.""" -__version__ = "3.0.0b3" + +__version__ = "3.0.0" diff --git a/stac_fastapi/types/stac_fastapi/types/core.py b/stac_fastapi/types/stac_fastapi/types/core.py index 003a765e..18381b7c 100644 --- a/stac_fastapi/types/stac_fastapi/types/core.py +++ b/stac_fastapi/types/stac_fastapi/types/core.py @@ -1,8 +1,6 @@ """Base clients.""" import abc -import importlib -import warnings from typing import Any, Dict, List, Optional, Union from urllib.parse import urljoin @@ -784,18 +782,3 @@ async def item_collection( An ItemCollection. """ ... - - -# TODO: remove for 3.0.0 final release -def __getattr__(name: str) -> Any: - if name in ["AsyncBaseFiltersClient", "BaseFiltersClient"]: - warnings.warn( - f"""importing {name} from `stac_fastapi.types.core` is deprecated, - please import it from `stac_fastapi.extensions.core.filter.client`.""", - DeprecationWarning, - stacklevel=2, - ) - clients = importlib.import_module("stac_fastapi.extensions.core.filter.client") - return getattr(clients, name) - - raise AttributeError(f"module {__name__} has no attribute {name}") diff --git a/stac_fastapi/types/stac_fastapi/types/version.py b/stac_fastapi/types/stac_fastapi/types/version.py index c09ebf00..5996faa4 100644 --- a/stac_fastapi/types/stac_fastapi/types/version.py +++ b/stac_fastapi/types/stac_fastapi/types/version.py @@ -1,2 +1,3 @@ """Library version.""" -__version__ = "3.0.0b3" + +__version__ = "3.0.0"