Skip to content

Commit 6b5ea15

Browse files
committed
fix(service): provide defaults for optional catalog operations
1 parent 3a2450b commit 6b5ea15

3 files changed

Lines changed: 36 additions & 10 deletions

File tree

‎README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ service = (
238238
Every Service integration must implement `list-offerings` and `get-offering`. `StaticCatalog` is the
239239
small-Service implementation: it adds Collection operations when Collections are provided and uses
240240
integrity-protected, stateless continuations that expire after one hour. Larger Services can
241-
implement the typed `Catalog` protocol over their existing indexed catalog and search infrastructure.
241+
subclass the typed `Catalog` protocol over their existing indexed catalog and search infrastructure.
242+
The protocol supplies rejecting defaults for optional operations; override an optional method and
243+
include its matching `Operation` only when the Service implements it.
242244

243245
Service responses are validated against the bundled normative schemas before they are returned.
244246
The handler enforces fixed operation paths and methods, ODP media types, request and response byte

‎src/offering_protocol/service/service.py‎

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,29 @@ async def get_offering(self, identifier: str, request: CatalogRequest) -> Offeri
9898

9999
async def search_offerings(
100100
self, query: OfferingSearchRequest, request: CatalogRequest
101-
) -> OfferingPage[Offering]: ...
101+
) -> OfferingPage[Offering]:
102+
del query, request
103+
raise CatalogError("Offering search is not supported")
102104

103-
async def list_collections(self, request: CatalogRequest) -> Page[Collection]: ...
105+
async def list_collections(self, request: CatalogRequest) -> Page[Collection]:
106+
del request
107+
raise CatalogError("Collection listing is not supported")
104108

105-
async def get_collection(
106-
self, identifier: str, request: CatalogRequest
107-
) -> Collection | None: ...
109+
async def get_collection(self, identifier: str, request: CatalogRequest) -> Collection | None:
110+
del identifier, request
111+
raise CatalogError("Collection retrieval is not supported")
108112

109113
async def search_collections(
110114
self, query: CollectionSearchRequest, request: CatalogRequest
111-
) -> Page[Collection]: ...
115+
) -> Page[Collection]:
116+
del query, request
117+
raise CatalogError("Collection search is not supported")
112118

113119
async def list_collection_offerings(
114120
self, collection_id: str, request: CatalogRequest
115-
) -> OfferingPage[Offering]: ...
121+
) -> OfferingPage[Offering]:
122+
del collection_id, request
123+
raise CatalogError("Collection Offering listing is not supported")
116124

117125

118126
class ServiceBuilder:

‎tests/test_service.py‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ async def get_collection(
283283
assert (await service.handle(Request("GET", "/odp/offerings/rubber-plant"))).status == 500
284284
assert (await service.handle(Request("GET", "/odp/collections/plants"))).status == 500
285285

286-
class ApplicationCatalog:
286+
class ApplicationCatalog(Catalog):
287287
def operations(self) -> list[Operation]:
288288
return [Operation.GET_OFFERING, Operation.LIST_OFFERINGS]
289289

@@ -296,9 +296,25 @@ async def get_offering(self, identifier: str, request: CatalogRequest) -> Offeri
296296
del identifier, request
297297
return None
298298

299-
application_service = _service(cast(Catalog, ApplicationCatalog()))
299+
application_service = _service(ApplicationCatalog())
300300
assert (await application_service.handle(Request("GET", "/odp/offerings"))).status == 500
301301

302+
application_catalog = ApplicationCatalog()
303+
with pytest.raises(CatalogError):
304+
await application_catalog.search_offerings(
305+
OfferingSearchRequest(query="plant"), CatalogRequest()
306+
)
307+
with pytest.raises(CatalogError):
308+
await application_catalog.list_collections(CatalogRequest())
309+
with pytest.raises(CatalogError):
310+
await application_catalog.get_collection("plants", CatalogRequest())
311+
with pytest.raises(CatalogError):
312+
await application_catalog.search_collections(
313+
CollectionSearchRequest(query="plant"), CatalogRequest()
314+
)
315+
with pytest.raises(CatalogError):
316+
await application_catalog.list_collection_offerings("plants", CatalogRequest())
317+
302318
enrollment = EnrollmentProtocol(name=Protocol.AEP)
303319
payment = PaymentProtocol(
304320
authentication=AuthenticationRequirement.NOT_REQUIRED, name=Protocol.MPP

0 commit comments

Comments
 (0)