11import copy
22import json
33import urllib .parse
4- from typing import Any
4+ from typing import Any , cast
55
66from fastapi import HTTPException
77from pydantic import ValidationError
8+ from stacrs import DuckdbClient
89from starlette .requests import Request
910
1011from stac_fastapi .api .models import BaseSearchPostRequest
@@ -18,9 +19,10 @@ class Client(AsyncBaseCoreClient): # type: ignore
1819 """A stac-fastapi-geoparquet client."""
1920
2021 async def all_collections (self , * , request : Request , ** kwargs : Any ) -> Collections :
22+ collections = cast (dict [str , dict [str , Any ]], request .state .collections )
2123 return Collections (
2224 collections = [
23- collection_with_links (c , request ) for c in request . app . state . collections
25+ collection_with_links (c , request ) for c in collections . values ()
2426 ],
2527 links = [
2628 {
@@ -39,25 +41,29 @@ async def all_collections(self, *, request: Request, **kwargs: Any) -> Collectio
3941 async def get_collection (
4042 self , * , request : Request , collection_id : str , ** kwargs : Any
4143 ) -> Collection :
42- if collection := next (
43- (c for c in request .app .state .collections if c ["id" ] == collection_id ), None
44- ):
44+ collections = cast (dict [str , dict [str , Any ]], request .state .collections )
45+ if collection := collections .get (collection_id ):
4546 return collection_with_links (collection , request )
4647 else :
4748 raise NotFoundError (f"Collection does not exist: { collection_id } " )
4849
4950 async def get_item (
5051 self , * , request : Request , item_id : str , collection_id : str , ** kwargs : Any
5152 ) -> Item :
52- item_collection = request .app .state .client .search (
53- request .app .state .href , ids = [item_id ], collections = [collection_id ], ** kwargs
54- )
55- if len (item_collection ["features" ]) == 1 :
56- return Item (** item_collection ["features" ][0 ])
57- else :
58- raise NotFoundError (
59- f"Item does not exist: { item_id } in collection { collection_id } "
53+ client = cast (DuckdbClient , request .state .client )
54+ hrefs = cast (dict [str , str ], request .state .hrefs )
55+ if href := hrefs .get (collection_id ):
56+ item_collection = client .search (
57+ href , ids = [item_id ], collections = [collection_id ], ** kwargs
6058 )
59+ if len (item_collection ["features" ]) == 1 :
60+ return Item (** item_collection ["features" ][0 ])
61+ else :
62+ raise NotFoundError (
63+ f"Item does not exist: { item_id } in collection { collection_id } "
64+ )
65+ else :
66+ raise NotFoundError (f"Collection does not exist: { collection_id } " )
6167
6268 async def get_search (
6369 self ,
@@ -157,10 +163,30 @@ async def search(
157163 search : BaseSearchPostRequest ,
158164 ** kwargs : Any ,
159165 ) -> ItemCollection :
166+ client = cast (DuckdbClient , request .state .client )
167+ hrefs = cast (dict [str , str ], request .state .hrefs )
168+
169+ hrefs_to_search = set ()
170+ if search .collections :
171+ for collection in search .collections :
172+ if href := hrefs .get (collection ):
173+ hrefs_to_search .add (href )
174+ else :
175+ hrefs_to_search .update (hrefs .values ())
176+
177+ if len (hrefs ) > 1 :
178+ raise ValidationError (
179+ "Cannot search multiple geoparquet files (don't know how to page)"
180+ )
181+ elif len (hrefs ) == 0 :
182+ return ItemCollection ()
183+ else :
184+ href = hrefs_to_search .pop ()
185+
160186 search_dict = search .model_dump (exclude_none = True )
161187 search_dict .update (** kwargs )
162- item_collection = request . app . state . client .search (
163- request . app . state . href ,
188+ item_collection = client .search (
189+ href ,
164190 ** search_dict ,
165191 )
166192 num_items = len (item_collection ["features" ])
0 commit comments