stac-fastapi-core 6.5.0__tar.gz → 6.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. stac_fastapi_core-6.6.0/.gitignore +143 -0
  2. stac_fastapi_core-6.6.0/PKG-INFO +53 -0
  3. stac_fastapi_core-6.6.0/README.md +20 -0
  4. stac_fastapi_core-6.6.0/pyproject.toml +59 -0
  5. stac_fastapi_core-6.6.0/pytest.ini +4 -0
  6. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/base_database_logic.py +14 -2
  7. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/core.py +72 -49
  8. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/extensions/collections_search.py +4 -0
  9. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/serializers.py +6 -0
  10. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/utilities.py +1 -9
  11. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/version.py +1 -1
  12. stac_fastapi_core-6.5.0/PKG-INFO +0 -713
  13. stac_fastapi_core-6.5.0/README.md +0 -695
  14. stac_fastapi_core-6.5.0/setup.cfg +0 -7
  15. stac_fastapi_core-6.5.0/setup.py +0 -46
  16. stac_fastapi_core-6.5.0/stac_fastapi_core.egg-info/PKG-INFO +0 -713
  17. stac_fastapi_core-6.5.0/stac_fastapi_core.egg-info/SOURCES.txt +0 -30
  18. stac_fastapi_core-6.5.0/stac_fastapi_core.egg-info/dependency_links.txt +0 -1
  19. stac_fastapi_core-6.5.0/stac_fastapi_core.egg-info/not-zip-safe +0 -1
  20. stac_fastapi_core-6.5.0/stac_fastapi_core.egg-info/requires.txt +0 -13
  21. stac_fastapi_core-6.5.0/stac_fastapi_core.egg-info/top_level.txt +0 -1
  22. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/__init__.py +0 -0
  23. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/base_settings.py +0 -0
  24. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/basic_auth.py +0 -0
  25. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/datetime_utils.py +0 -0
  26. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/extensions/__init__.py +0 -0
  27. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/extensions/aggregation.py +0 -0
  28. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/extensions/fields.py +0 -0
  29. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/extensions/filter.py +0 -0
  30. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/extensions/query.py +0 -0
  31. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/models/__init__.py +0 -0
  32. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/models/links.py +0 -0
  33. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/models/search.py +0 -0
  34. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/rate_limit.py +0 -0
  35. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/route_dependencies.py +0 -0
  36. {stac_fastapi_core-6.5.0 → stac_fastapi_core-6.6.0}/stac_fastapi/core/session.py +0 -0
@@ -0,0 +1,143 @@
1
+ elasticsearch/snapshots/
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ pip-wheel-metadata/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ .python-version
88
+
89
+ # pipenv
90
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
92
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
93
+ # install all needed dependencies.
94
+ #Pipfile.lock
95
+
96
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
97
+ __pypackages__/
98
+
99
+ # Celery stuff
100
+ celerybeat-schedule
101
+ celerybeat.pid
102
+
103
+ # SageMath parsed files
104
+ *.sage.py
105
+
106
+ # Environments
107
+ .env
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+ .dmypy.json
128
+ dmypy.json
129
+
130
+ # Pyre type checker
131
+ .pyre/
132
+
133
+ /esdata
134
+
135
+ # Virtualenv
136
+ venv
137
+
138
+ # VSCode folder
139
+ .vscode
140
+
141
+ /docs/src/api/*
142
+
143
+ .DS_Store
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.4
2
+ Name: stac_fastapi_core
3
+ Version: 6.6.0
4
+ Summary: Core library for the Elasticsearch and Opensearch stac-fastapi backends.
5
+ Project-URL: Homepage, https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
6
+ License: MIT
7
+ Keywords: Elasticsearch,FastAPI,Opensearch,STAC,STAC-API,stac-fastapi
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Intended Audience :: Information Technology
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Requires-Python: >=3.9
19
+ Requires-Dist: attrs>=23.2.0
20
+ Requires-Dist: fastapi~=0.109.0
21
+ Requires-Dist: geojson-pydantic~=1.0.0
22
+ Requires-Dist: jsonschema~=4.0.0
23
+ Requires-Dist: orjson~=3.11.0
24
+ Requires-Dist: overrides~=7.4.0
25
+ Requires-Dist: pydantic<3.0.0,>=2.4.1
26
+ Requires-Dist: pygeofilter~=0.3.1
27
+ Requires-Dist: slowapi~=0.1.9
28
+ Requires-Dist: stac-fastapi-api==6.0.0
29
+ Requires-Dist: stac-fastapi-extensions==6.0.0
30
+ Requires-Dist: stac-fastapi-types==6.0.0
31
+ Requires-Dist: stac-pydantic~=3.3.0
32
+ Description-Content-Type: text/markdown
33
+
34
+ # stac-fastapi-core
35
+
36
+ Core functionality for stac-fastapi. For full documentation, please see the [main README](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/blob/main/README.md).
37
+
38
+ ## Package Information
39
+
40
+ - **Package name**: stac-fastapi-core
41
+ - **Description**: Core functionality for STAC API implementations.
42
+ - **Documentation**: [https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/)
43
+ - **Source**: [GitHub Repository](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/)
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install stac-fastapi-core
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ For detailed usage and examples, please refer to the [main documentation](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/).
@@ -0,0 +1,20 @@
1
+ # stac-fastapi-core
2
+
3
+ Core functionality for stac-fastapi. For full documentation, please see the [main README](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/blob/main/README.md).
4
+
5
+ ## Package Information
6
+
7
+ - **Package name**: stac-fastapi-core
8
+ - **Description**: Core functionality for STAC API implementations.
9
+ - **Documentation**: [https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/)
10
+ - **Source**: [GitHub Repository](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/)
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install stac-fastapi-core
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ For detailed usage and examples, please refer to the [main documentation](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/).
@@ -0,0 +1,59 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "stac_fastapi_core"
7
+ description = "Core library for the Elasticsearch and Opensearch stac-fastapi backends."
8
+ readme = "README.md"
9
+ requires-python = ">=3.9"
10
+ license = {text = "MIT"}
11
+ authors = []
12
+ classifiers = [
13
+ "Intended Audience :: Developers",
14
+ "Intended Audience :: Information Technology",
15
+ "Intended Audience :: Science/Research",
16
+ "Programming Language :: Python :: 3.9",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
22
+ "License :: OSI Approved :: MIT License",
23
+ ]
24
+ keywords = [
25
+ "STAC",
26
+ "STAC-API",
27
+ "FastAPI",
28
+ "stac-fastapi",
29
+ "Elasticsearch",
30
+ "Opensearch",
31
+ ]
32
+ dynamic = ["version"]
33
+ dependencies = [
34
+ "fastapi~=0.109.0",
35
+ "attrs>=23.2.0",
36
+ "pydantic>=2.4.1,<3.0.0",
37
+ "stac_pydantic~=3.3.0",
38
+ "stac-fastapi.types==6.0.0",
39
+ "stac-fastapi.api==6.0.0",
40
+ "stac-fastapi.extensions==6.0.0",
41
+ "orjson~=3.11.0",
42
+ "overrides~=7.4.0",
43
+ "geojson-pydantic~=1.0.0",
44
+ "pygeofilter~=0.3.1",
45
+ "jsonschema~=4.0.0",
46
+ "slowapi~=0.1.9",
47
+ ]
48
+
49
+ [project.urls]
50
+ Homepage = "https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch"
51
+
52
+ [tool.hatch.version]
53
+ path = "stac_fastapi/core/version.py"
54
+
55
+ [tool.hatch.build.targets.sdist]
56
+ exclude = ["alembic", "tests", "scripts"]
57
+
58
+ [tool.hatch.build.targets.wheel]
59
+ only-include = ["stac_fastapi"]
@@ -0,0 +1,4 @@
1
+ [pytest]
2
+ testpaths = tests
3
+ addopts = -sv
4
+ asyncio_mode = auto
@@ -3,6 +3,8 @@
3
3
  import abc
4
4
  from typing import Any, Dict, Iterable, List, Optional, Tuple
5
5
 
6
+ from stac_pydantic.shared import BBox
7
+
6
8
 
7
9
  class BaseDatabaseLogic(abc.ABC):
8
10
  """
@@ -19,7 +21,12 @@ class BaseDatabaseLogic(abc.ABC):
19
21
  limit: int,
20
22
  request: Any = None,
21
23
  sort: Optional[List[Dict[str, Any]]] = None,
22
- ) -> Tuple[List[Dict[str, Any]], Optional[str]]:
24
+ bbox: Optional[BBox] = None,
25
+ q: Optional[List[str]] = None,
26
+ filter: Optional[Dict[str, Any]] = None,
27
+ query: Optional[Dict[str, Dict[str, Any]]] = None,
28
+ datetime: Optional[str] = None,
29
+ ) -> Tuple[List[Dict[str, Any]], Optional[str], Optional[int]]:
23
30
  """Retrieve a list of collections from the database, supporting pagination.
24
31
 
25
32
  Args:
@@ -27,9 +34,14 @@ class BaseDatabaseLogic(abc.ABC):
27
34
  limit (int): The number of results to return.
28
35
  request (Any, optional): The FastAPI request object. Defaults to None.
29
36
  sort (Optional[List[Dict[str, Any]]], optional): Optional sort parameter. Defaults to None.
37
+ bbox (Optional[BBox], optional): Bounding box to filter collections by spatial extent. Defaults to None.
38
+ q (Optional[List[str]], optional): Free text search terms. Defaults to None.
39
+ filter (Optional[Dict[str, Any]], optional): Structured query in CQL2 format. Defaults to None.
40
+ query (Optional[Dict[str, Dict[str, Any]]], optional): Query extension parameters. Defaults to None.
41
+ datetime (Optional[str], optional): Temporal filter. Defaults to None.
30
42
 
31
43
  Returns:
32
- A tuple of (collections, next pagination token if any).
44
+ A tuple of (collections, next pagination token if any, optional count).
33
45
  """
34
46
  pass
35
47
 
@@ -201,17 +201,6 @@ class CoreClient(AsyncBaseCoreClient):
201
201
  ]
202
202
  )
203
203
 
204
- collections = await self.all_collections(request=kwargs["request"])
205
- for collection in collections["collections"]:
206
- landing_page["links"].append(
207
- {
208
- "rel": Relations.child.value,
209
- "type": MimeTypes.json.value,
210
- "title": collection.get("title") or collection.get("id"),
211
- "href": urljoin(base_url, f"collections/{collection['id']}"),
212
- }
213
- )
214
-
215
204
  # Add OpenAPI URL
216
205
  landing_page["links"].append(
217
206
  {
@@ -240,65 +229,69 @@ class CoreClient(AsyncBaseCoreClient):
240
229
 
241
230
  async def all_collections(
242
231
  self,
243
- datetime: Optional[str] = None,
244
232
  limit: Optional[int] = None,
233
+ bbox: Optional[BBox] = None,
234
+ datetime: Optional[str] = None,
245
235
  fields: Optional[List[str]] = None,
246
236
  sortby: Optional[Union[str, List[str]]] = None,
247
237
  filter_expr: Optional[str] = None,
248
238
  filter_lang: Optional[str] = None,
249
239
  q: Optional[Union[str, List[str]]] = None,
250
240
  query: Optional[str] = None,
241
+ request: Request = None,
242
+ token: Optional[str] = None,
251
243
  **kwargs,
252
244
  ) -> stac_types.Collections:
253
245
  """Read all collections from the database.
254
246
 
255
247
  Args:
256
- datetime (Optional[str]): Filter collections by datetime range.
257
248
  limit (Optional[int]): Maximum number of collections to return.
249
+ bbox (Optional[BBox]): Bounding box to filter collections by spatial extent.
250
+ datetime (Optional[str]): Filter collections by datetime range.
258
251
  fields (Optional[List[str]]): Fields to include or exclude from the results.
259
- sortby (Optional[str]): Sorting options for the results.
252
+ sortby (Optional[Union[str, List[str]]]): Sorting options for the results.
260
253
  filter_expr (Optional[str]): Structured filter expression in CQL2 JSON or CQL2-text format.
261
- query (Optional[str]): Legacy query parameter (deprecated).
262
254
  filter_lang (Optional[str]): Must be 'cql2-json' or 'cql2-text' if specified, other values will result in an error.
263
255
  q (Optional[Union[str, List[str]]]): Free text search terms.
256
+ query (Optional[str]): Legacy query parameter (deprecated).
257
+ request (Request): FastAPI Request object.
258
+ token (Optional[str]): Pagination token for retrieving the next page of results.
264
259
  **kwargs: Keyword arguments from the request.
265
260
 
266
261
  Returns:
267
262
  A Collections object containing all the collections in the database and links to various resources.
268
263
  """
269
- request = kwargs["request"]
270
264
  base_url = str(request.base_url)
271
265
 
272
- # Get the global limit from environment variable
273
- global_limit = None
274
- env_limit = os.getenv("STAC_ITEM_LIMIT")
275
- if env_limit:
276
- try:
277
- global_limit = int(env_limit)
278
- except ValueError:
279
- # Handle invalid integer in environment variable
280
- pass
281
-
282
- # Apply global limit if it exists
283
- if global_limit is not None:
284
- # If a limit was provided, use the smaller of the two
285
- if limit is not None:
286
- limit = min(limit, global_limit)
287
- else:
288
- limit = global_limit
266
+ global_max_limit = (
267
+ int(os.getenv("STAC_GLOBAL_COLLECTION_MAX_LIMIT"))
268
+ if os.getenv("STAC_GLOBAL_COLLECTION_MAX_LIMIT")
269
+ else None
270
+ )
271
+ query_limit = request.query_params.get("limit")
272
+ default_limit = int(os.getenv("STAC_DEFAULT_COLLECTION_LIMIT", 300))
273
+
274
+ body_limit = None
275
+ try:
276
+ if request.method == "POST" and request.body():
277
+ body_data = await request.json()
278
+ body_limit = body_data.get("limit")
279
+ except Exception:
280
+ pass
281
+
282
+ if body_limit is not None:
283
+ limit = int(body_limit)
284
+ elif query_limit:
285
+ limit = int(query_limit)
289
286
  else:
290
- # No global limit, use provided limit or default
291
- if limit is None:
292
- query_limit = request.query_params.get("limit")
293
- if query_limit:
294
- try:
295
- limit = int(query_limit)
296
- except ValueError:
297
- limit = 10
298
- else:
299
- limit = 10
287
+ limit = default_limit
300
288
 
301
- token = request.query_params.get("token")
289
+ if global_max_limit is not None:
290
+ limit = min(limit, global_max_limit)
291
+
292
+ # Get token from query params only if not already provided (for GET requests)
293
+ if token is None:
294
+ token = request.query_params.get("token")
302
295
 
303
296
  # Process fields parameter for filtering collection properties
304
297
  includes, excludes = set(), set()
@@ -398,6 +391,7 @@ class CoreClient(AsyncBaseCoreClient):
398
391
  limit=limit,
399
392
  request=request,
400
393
  sort=sort,
394
+ bbox=bbox,
401
395
  q=q_list,
402
396
  filter=parsed_filter,
403
397
  query=parsed_query,
@@ -499,6 +493,11 @@ class CoreClient(AsyncBaseCoreClient):
499
493
  # Pass all parameters from search_request to all_collections
500
494
  return await self.all_collections(
501
495
  limit=search_request.limit if hasattr(search_request, "limit") else None,
496
+ bbox=search_request.bbox if hasattr(search_request, "bbox") else None,
497
+ datetime=search_request.datetime
498
+ if hasattr(search_request, "datetime")
499
+ else None,
500
+ token=search_request.token if hasattr(search_request, "token") else None,
502
501
  fields=fields,
503
502
  sortby=sortby,
504
503
  filter_expr=search_request.filter
@@ -562,7 +561,7 @@ class CoreClient(AsyncBaseCoreClient):
562
561
  request (Request): FastAPI Request object.
563
562
  bbox (Optional[BBox]): Optional bounding box filter.
564
563
  datetime (Optional[str]): Optional datetime or interval filter.
565
- limit (Optional[int]): Optional page size. Defaults to env ``STAC_ITEM_LIMIT`` when unset.
564
+ limit (Optional[int]): Optional page size. Defaults to env `STAC_DEFAULT_ITEM_LIMIT` when unset.
566
565
  sortby (Optional[str]): Optional sort specification. Accepts repeated values
567
566
  like ``sortby=-properties.datetime`` or ``sortby=+id``. Bare fields (e.g. ``sortby=id``)
568
567
  imply ascending order.
@@ -653,15 +652,12 @@ class CoreClient(AsyncBaseCoreClient):
653
652
  q (Optional[List[str]]): Free text query to filter the results.
654
653
  intersects (Optional[str]): GeoJSON geometry to search in.
655
654
  kwargs: Additional parameters to be passed to the API.
656
-
657
655
  Returns:
658
656
  ItemCollection: Collection of `Item` objects representing the search results.
659
657
 
660
658
  Raises:
661
659
  HTTPException: If any error occurs while searching the catalog.
662
660
  """
663
- limit = int(request.query_params.get("limit", os.getenv("STAC_ITEM_LIMIT", 10)))
664
-
665
661
  base_args = {
666
662
  "collections": collections,
667
663
  "ids": ids,
@@ -736,6 +732,34 @@ class CoreClient(AsyncBaseCoreClient):
736
732
  Raises:
737
733
  HTTPException: If there is an error with the cql2_json filter.
738
734
  """
735
+ global_max_limit = (
736
+ int(os.getenv("STAC_GLOBAL_ITEM_MAX_LIMIT"))
737
+ if os.getenv("STAC_GLOBAL_ITEM_MAX_LIMIT")
738
+ else None
739
+ )
740
+ query_limit = request.query_params.get("limit")
741
+ default_limit = int(os.getenv("STAC_DEFAULT_ITEM_LIMIT", 10))
742
+
743
+ body_limit = None
744
+ try:
745
+ if request.method == "POST" and request.body():
746
+ body_data = await request.json()
747
+ body_limit = body_data.get("limit")
748
+ except Exception:
749
+ pass
750
+
751
+ if body_limit is not None:
752
+ limit = int(body_limit)
753
+ elif query_limit:
754
+ limit = int(query_limit)
755
+ else:
756
+ limit = default_limit
757
+
758
+ if global_max_limit:
759
+ limit = min(limit, global_max_limit)
760
+
761
+ search_request.limit = limit
762
+
739
763
  base_url = str(request.base_url)
740
764
 
741
765
  search = self.database.make_search()
@@ -812,7 +836,6 @@ class CoreClient(AsyncBaseCoreClient):
812
836
  if hasattr(search_request, "sortby") and getattr(search_request, "sortby"):
813
837
  sort = self.database.populate_sort(getattr(search_request, "sortby"))
814
838
 
815
- limit = 10
816
839
  if search_request.limit:
817
840
  limit = search_request.limit
818
841
 
@@ -18,6 +18,10 @@ class CollectionsSearchRequest(ExtendedSearch):
18
18
  """Extended search model for collections with free text search support."""
19
19
 
20
20
  q: Optional[Union[str, List[str]]] = None
21
+ token: Optional[str] = None
22
+ query: Optional[
23
+ str
24
+ ] = None # Legacy query extension (deprecated but still supported)
21
25
 
22
26
 
23
27
  class CollectionsSearchEndpointExtension(ApiExtension):
@@ -1,6 +1,7 @@
1
1
  """Serializers."""
2
2
 
3
3
  import abc
4
+ import logging
4
5
  from copy import deepcopy
5
6
  from typing import Any, List, Optional
6
7
 
@@ -13,6 +14,8 @@ from stac_fastapi.core.utilities import get_bool_env
13
14
  from stac_fastapi.types import stac as stac_types
14
15
  from stac_fastapi.types.links import ItemLinks, resolve_links
15
16
 
17
+ logger = logging.getLogger(__name__)
18
+
16
19
 
17
20
  @attr.s
18
21
  class Serializer(abc.ABC):
@@ -168,6 +171,9 @@ class CollectionSerializer(Serializer):
168
171
  # Avoid modifying the input dict in-place ... doing so breaks some tests
169
172
  collection = deepcopy(collection)
170
173
 
174
+ # Remove internal bbox_shape field (not part of STAC spec)
175
+ collection.pop("bbox_shape", None)
176
+
171
177
  # Set defaults
172
178
  collection_id = collection.get("id")
173
179
  collection.setdefault("type", "Collection")
@@ -10,15 +10,7 @@ from typing import Any, Dict, List, Optional, Set, Union
10
10
 
11
11
  from stac_fastapi.types.stac import Item
12
12
 
13
-
14
- def get_max_limit():
15
- """
16
- Retrieve a MAX_LIMIT value from an environment variable.
17
-
18
- Returns:
19
- int: The int value parsed from the environment variable.
20
- """
21
- return int(os.getenv("ENV_MAX_LIMIT", 10000))
13
+ MAX_LIMIT = 10000
22
14
 
23
15
 
24
16
  def get_bool_env(name: str, default: Union[bool, str] = False) -> bool:
@@ -1,2 +1,2 @@
1
1
  """library version."""
2
- __version__ = "6.5.0"
2
+ __version__ = "6.6.0"