Skip to content

Commit 7eea8b6

Browse files
authored
feat: add conformance to product (#85)
## What I'm changing - Closes ##83 ## How I did it We're not populating it, but we at least have an endpoint ## Checklist - [x] Tests pass: `uv run pytest` - [x] Checks pass: `uv run pre-commit --all-files` - [x] CHANGELOG is updated (if necessary)
1 parent 7f141f4 commit 7eea8b6

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

stapi-fastapi/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1414
## Added
1515

1616
- Add constants for route names to be used in link href generation
17+
- Conformance url to product ([#85](https://github.com/stapi-spec/pystapi/pull/85))
1718

1819
## Changed
1920

stapi-fastapi/src/stapi_fastapi/routers/product_router.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from returns.maybe import Maybe, Some
1919
from returns.result import Failure, Success
2020
from stapi_pydantic import (
21+
Conformance,
2122
JsonSchemaModel,
2223
Link,
2324
OpportunityCollection,
@@ -37,6 +38,7 @@
3738
from stapi_fastapi.models.product import Product
3839
from stapi_fastapi.responses import GeoJSONResponse
3940
from stapi_fastapi.routers.route_names import (
41+
CONFORMANCE,
4042
CREATE_ORDER,
4143
GET_CONSTRAINTS,
4244
GET_OPPORTUNITY_COLLECTION,
@@ -91,6 +93,15 @@ def __init__(
9193
tags=["Products"],
9294
)
9395

96+
self.add_api_route(
97+
path="/conformance",
98+
endpoint=self.get_product_conformance,
99+
name=f"{self.root_router.name}:{self.product.id}:{CONFORMANCE}",
100+
methods=["GET"],
101+
summary="Get conformance urls for the product",
102+
tags=["Products"],
103+
)
104+
94105
self.add_api_route(
95106
path="/constraints",
96107
endpoint=self.get_product_constraints,
@@ -182,6 +193,15 @@ def get_product(self, request: Request) -> ProductPydantic:
182193
rel="self",
183194
type=TYPE_JSON,
184195
),
196+
Link(
197+
href=str(
198+
request.url_for(
199+
f"{self.root_router.name}:{self.product.id}:{CONFORMANCE}",
200+
),
201+
),
202+
rel="conformance",
203+
type=TYPE_JSON,
204+
),
185205
Link(
186206
href=str(
187207
request.url_for(
@@ -333,6 +353,12 @@ async def search_opportunities_async(
333353
case x:
334354
raise AssertionError(f"Expected code to be unreachable: {x}")
335355

356+
def get_product_conformance(self) -> Conformance:
357+
"""
358+
Return conformance urls of a specific product
359+
"""
360+
return Conformance.model_validate({"conforms_to": self.product.conformsTo})
361+
336362
def get_product_constraints(self) -> JsonSchemaModel:
337363
"""
338364
Return supported constraints of a specific product

stapi-fastapi/tests/test_product.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from fastapi import status
33
from fastapi.testclient import TestClient
44
from stapi_fastapi.models.product import Product
5+
from stapi_pydantic import Conformance
56

67
from .shared import pagination_tester
78

@@ -19,7 +20,7 @@ def test_products_response(stapi_client: TestClient):
1920

2021

2122
@pytest.mark.parametrize("product_id", ["test-spotlight"])
22-
def test_product_response_self_link(
23+
def test_product_response_links(
2324
product_id: str,
2425
stapi_client: TestClient,
2526
assert_link,
@@ -32,12 +33,28 @@ def test_product_response_self_link(
3233

3334
url = "GET /products"
3435
assert_link(url, body, "self", f"/products/{product_id}")
36+
assert_link(
37+
url, body, "conformance", f"/products/{product_id}/conformance"
38+
) # https://github.com/stapi-spec/stapi-spec/issues/253
3539
assert_link(url, body, "constraints", f"/products/{product_id}/constraints")
3640
assert_link(url, body, "order-parameters", f"/products/{product_id}/order-parameters")
3741
assert_link(url, body, "opportunities", f"/products/{product_id}/opportunities")
3842
assert_link(url, body, "create-order", f"/products/{product_id}/orders", method="POST")
3943

4044

45+
@pytest.mark.parametrize("product_id", ["test-spotlight"])
46+
def test_product_conformance_response(
47+
product_id: str,
48+
stapi_client: TestClient,
49+
):
50+
res = stapi_client.get(f"/products/{product_id}/constraints")
51+
assert res.status_code == status.HTTP_200_OK
52+
assert res.headers["Content-Type"] == "application/json"
53+
54+
Conformance.model_validate(res.json())
55+
# TODO unsure what conformance products should support, as of yet
56+
57+
4158
@pytest.mark.parametrize("product_id", ["test-spotlight"])
4259
def test_product_constraints_response(
4360
product_id: str,
@@ -83,6 +100,11 @@ def test_get_products_pagination(
83100
"rel": "self",
84101
"type": "application/json",
85102
},
103+
{
104+
"href": f"http://stapiserver/products/{product_id}/conformance",
105+
"rel": "conformance",
106+
"type": "application/json",
107+
},
86108
{
87109
"href": f"http://stapiserver/products/{product_id}/constraints",
88110
"rel": "constraints",

0 commit comments

Comments
 (0)