Skip to content

Commit 07d4513

Browse files
authored
refactor: s/constraints/queryables (#74)
## What I'm changing - Closes #69 ## How I did it - Lots of find-replace - I didn't touch the ADR ## Checklist - [x] Tests pass: `uv run pytest` - [x] Checks pass: `uv run pre-commit --all-files` - [x] CHANGELOG is updated (if necessary)
1 parent 7ea239f commit 07d4513

File tree

11 files changed

+47
-48
lines changed

11 files changed

+47
-48
lines changed

stapi-fastapi/src/stapi_fastapi/backends/product_backend.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
- Returning returns.result.Failure[Exception] will result in a 500.
4343
4444
Note:
45-
Backends must validate search constraints and return
46-
returns.result.Failure[stapi_fastapi.exceptions.ConstraintsException] if not valid.
45+
Backends must validate search queryables and return
46+
returns.result.Failure[stapi_fastapi.exceptions.QueryablesException] if not valid.
4747
"""
4848

4949
SearchOpportunitiesAsync = Callable[
@@ -63,8 +63,8 @@
6363
- Should return returns.result.Success[OpportunitySearchRecord]
6464
- Returning returns.result.Failure[Exception] will result in a 500.
6565
66-
Backends must validate search constraints and return
67-
returns.result.Failure[stapi_fastapi.exceptions.ConstraintsException] if not valid.
66+
Backends must validate search queryables and return
67+
returns.result.Failure[stapi_fastapi.exceptions.QueryablesException] if not valid.
6868
"""
6969

7070
GetOpportunityCollection = Callable[
@@ -105,5 +105,5 @@
105105
106106
Note:
107107
Backends must validate order payload and return
108-
returns.result.Failure[stapi_fastapi.exceptions.ConstraintsException] if not valid.
108+
returns.result.Failure[stapi_fastapi.exceptions.QueryablesException] if not valid.
109109
"""

stapi-fastapi/src/stapi_fastapi/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class StapiException(HTTPException):
77
pass
88

99

10-
class ConstraintsException(StapiException):
10+
class QueryablesException(StapiException):
1111
def __init__(self, detail: Any) -> None:
1212
super().__init__(status.HTTP_422_UNPROCESSABLE_ENTITY, detail)
1313

stapi-fastapi/src/stapi_fastapi/models/product.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from typing import TYPE_CHECKING, Any
44

5-
from stapi_pydantic import Constraints, OpportunityProperties, OrderParameters
5+
from stapi_pydantic import OpportunityProperties, OrderParameters, Queryables
66
from stapi_pydantic import Product as BaseProduct
77

88
if TYPE_CHECKING:
@@ -21,7 +21,7 @@ class Product(BaseProduct):
2121
_get_opportunity_collection: GetOpportunityCollection | None
2222

2323
# we don't want to include these in the model fields
24-
_constraints: type[Constraints]
24+
_queryables: type[Queryables]
2525
_opportunity_properties: type[OpportunityProperties]
2626
_order_parameters: type[OrderParameters]
2727

@@ -32,7 +32,7 @@ def __init__(
3232
search_opportunities: SearchOpportunities | None = None,
3333
search_opportunities_async: SearchOpportunitiesAsync | None = None,
3434
get_opportunity_collection: GetOpportunityCollection | None = None,
35-
constraints: type[Constraints],
35+
queryables: type[Queryables],
3636
opportunity_properties: type[OpportunityProperties],
3737
order_parameters: type[OrderParameters],
3838
**kwargs: Any,
@@ -49,7 +49,7 @@ def __init__(
4949
self._search_opportunities = search_opportunities
5050
self._search_opportunities_async = search_opportunities_async
5151
self._get_opportunity_collection = get_opportunity_collection
52-
self._constraints = constraints
52+
self._queryables = queryables
5353
self._opportunity_properties = opportunity_properties
5454
self._order_parameters = order_parameters
5555

@@ -84,8 +84,8 @@ def supports_async_opportunity_search(self) -> bool:
8484
return self._search_opportunities_async is not None and self._get_opportunity_collection is not None
8585

8686
@property
87-
def constraints(self) -> type[Constraints]:
88-
return self._constraints
87+
def queryables(self) -> type[Queryables]:
88+
return self._queryables
8989

9090
@property
9191
def opportunity_properties(self) -> type[OpportunityProperties]:

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,16 @@
3434
)
3535

3636
from stapi_fastapi.constants import TYPE_JSON
37-
from stapi_fastapi.exceptions import ConstraintsException, NotFoundException
37+
from stapi_fastapi.exceptions import NotFoundException, QueryablesException
3838
from stapi_fastapi.models.product import Product
3939
from stapi_fastapi.responses import GeoJSONResponse
4040
from stapi_fastapi.routers.route_names import (
4141
CONFORMANCE,
4242
CREATE_ORDER,
43-
GET_CONSTRAINTS,
4443
GET_OPPORTUNITY_COLLECTION,
4544
GET_ORDER_PARAMETERS,
4645
GET_PRODUCT,
46+
GET_QUERYABLES,
4747
SEARCH_OPPORTUNITIES,
4848
)
4949

@@ -103,11 +103,11 @@ def __init__(
103103
)
104104

105105
self.add_api_route(
106-
path="/constraints",
107-
endpoint=self.get_product_constraints,
108-
name=f"{self.root_router.name}:{self.product.id}:{GET_CONSTRAINTS}",
106+
path="/queryables",
107+
endpoint=self.get_product_queryables,
108+
name=f"{self.root_router.name}:{self.product.id}:{GET_QUERYABLES}",
109109
methods=["GET"],
110-
summary="Get constraints for the product",
110+
summary="Get queryables for the product",
111111
tags=["Products"],
112112
)
113113

@@ -156,7 +156,7 @@ async def _create_order(
156156
name=f"{self.root_router.name}:{self.product.id}:{SEARCH_OPPORTUNITIES}",
157157
methods=["POST"],
158158
response_class=GeoJSONResponse,
159-
# unknown why mypy can't see the constraints property on Product, ignoring
159+
# unknown why mypy can't see the queryables property on Product, ignoring
160160
response_model=OpportunityCollection[
161161
Geometry,
162162
self.product.opportunity_properties, # type: ignore
@@ -205,10 +205,10 @@ def get_product(self, request: Request) -> ProductPydantic:
205205
Link(
206206
href=str(
207207
request.url_for(
208-
f"{self.root_router.name}:{self.product.id}:{GET_CONSTRAINTS}",
208+
f"{self.root_router.name}:{self.product.id}:{GET_QUERYABLES}",
209209
),
210210
),
211-
rel="constraints",
211+
rel="queryables",
212212
type=TYPE_JSON,
213213
),
214214
Link(
@@ -255,7 +255,7 @@ async def search_opportunities(
255255
prefer: Prefer | None = Depends(get_prefer),
256256
) -> OpportunityCollection | Response: # type: ignore
257257
"""
258-
Explore the opportunities available for a particular set of constraints
258+
Explore the opportunities available for a particular set of queryables
259259
"""
260260
# sync
261261
if not self.root_router.supports_async_opportunity_search or (
@@ -300,7 +300,7 @@ async def search_opportunities_sync(
300300
links.append(self.pagination_link(request, search, x))
301301
case Maybe.empty:
302302
pass
303-
case Failure(e) if isinstance(e, ConstraintsException):
303+
case Failure(e) if isinstance(e, QueryablesException):
304304
raise e
305305
case Failure(e):
306306
logger.error(
@@ -339,7 +339,7 @@ async def search_opportunities_async(
339339
content=search_record.model_dump(mode="json"),
340340
headers=headers,
341341
)
342-
case Failure(e) if isinstance(e, ConstraintsException):
342+
case Failure(e) if isinstance(e, QueryablesException):
343343
raise e
344344
case Failure(e):
345345
logger.error(
@@ -359,15 +359,15 @@ def get_product_conformance(self) -> Conformance:
359359
"""
360360
return Conformance.model_validate({"conforms_to": self.product.conformsTo})
361361

362-
def get_product_constraints(self) -> JsonSchemaModel:
362+
def get_product_queryables(self) -> JsonSchemaModel:
363363
"""
364-
Return supported constraints of a specific product
364+
Return supported queryables of a specific product
365365
"""
366-
return self.product.constraints
366+
return self.product.queryables
367367

368368
def get_product_order_parameters(self) -> JsonSchemaModel:
369369
"""
370-
Return supported constraints of a specific product
370+
Return supported order parameters of a specific product
371371
"""
372372
return self.product.order_parameters
373373

@@ -385,7 +385,7 @@ async def create_order(self, payload: OrderPayload, request: Request, response:
385385
location = str(self.root_router.generate_order_href(request, order.id))
386386
response.headers["Location"] = location
387387
return order # type: ignore
388-
case Failure(e) if isinstance(e, ConstraintsException):
388+
case Failure(e) if isinstance(e, QueryablesException):
389389
raise e
390390
case Failure(e):
391391
logger.error(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
LIST_PRODUCTS = "list-products"
77
LIST_PRODUCTS = "list-products"
88
GET_PRODUCT = "get-product"
9-
GET_CONSTRAINTS = "get-constraints"
9+
GET_QUERYABLES = "get-queryables"
1010
GET_ORDER_PARAMETERS = "get-order-parameters"
1111

1212
# Opportunity

stapi-fastapi/tests/shared.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def put_opportunity_collection(self, collection: OpportunityCollection) -> None:
9090
self._collections[collection.id] = deepcopy(collection)
9191

9292

93-
class MyProductConstraints(BaseModel):
93+
class MyProductQueryables(BaseModel):
9494
off_nadir: int
9595

9696

@@ -134,7 +134,7 @@ class MyOrderParameters(OrderParameters):
134134
search_opportunities=None,
135135
search_opportunities_async=None,
136136
get_opportunity_collection=None,
137-
constraints=MyProductConstraints,
137+
queryables=MyProductQueryables,
138138
opportunity_properties=MyOpportunityProperties,
139139
order_parameters=MyOrderParameters,
140140
)
@@ -151,7 +151,7 @@ class MyOrderParameters(OrderParameters):
151151
search_opportunities=mock_search_opportunities,
152152
search_opportunities_async=None,
153153
get_opportunity_collection=None,
154-
constraints=MyProductConstraints,
154+
queryables=MyProductQueryables,
155155
opportunity_properties=MyOpportunityProperties,
156156
order_parameters=MyOrderParameters,
157157
)
@@ -169,7 +169,7 @@ class MyOrderParameters(OrderParameters):
169169
search_opportunities=None,
170170
search_opportunities_async=mock_search_opportunities_async,
171171
get_opportunity_collection=mock_get_opportunity_collection,
172-
constraints=MyProductConstraints,
172+
queryables=MyProductQueryables,
173173
opportunity_properties=MyOpportunityProperties,
174174
order_parameters=MyOrderParameters,
175175
)
@@ -186,7 +186,7 @@ class MyOrderParameters(OrderParameters):
186186
search_opportunities=mock_search_opportunities,
187187
search_opportunities_async=mock_search_opportunities_async,
188188
get_opportunity_collection=mock_get_opportunity_collection,
189-
constraints=MyProductConstraints,
189+
queryables=MyProductQueryables,
190190
opportunity_properties=MyOpportunityProperties,
191191
order_parameters=MyOrderParameters,
192192
)
@@ -203,7 +203,7 @@ class MyOrderParameters(OrderParameters):
203203
search_opportunities=mock_search_opportunities,
204204
search_opportunities_async=None,
205205
get_opportunity_collection=None,
206-
constraints=MyProductConstraints,
206+
queryables=MyProductQueryables,
207207
opportunity_properties=MyOpportunityProperties,
208208
order_parameters=MyOrderParameters,
209209
)

stapi-fastapi/tests/test_product.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def test_product_response_links(
3636
assert_link(
3737
url, body, "conformance", f"/products/{product_id}/conformance"
3838
) # https://github.com/stapi-spec/stapi-spec/issues/253
39-
assert_link(url, body, "constraints", f"/products/{product_id}/constraints")
39+
assert_link(url, body, "queryables", f"/products/{product_id}/queryables")
4040
assert_link(url, body, "order-parameters", f"/products/{product_id}/order-parameters")
4141
assert_link(url, body, "opportunities", f"/products/{product_id}/opportunities")
4242
assert_link(url, body, "create-order", f"/products/{product_id}/orders", method="POST")
@@ -47,7 +47,7 @@ def test_product_conformance_response(
4747
product_id: str,
4848
stapi_client: TestClient,
4949
):
50-
res = stapi_client.get(f"/products/{product_id}/constraints")
50+
res = stapi_client.get(f"/products/{product_id}/conformance")
5151
assert res.status_code == status.HTTP_200_OK
5252
assert res.headers["Content-Type"] == "application/json"
5353

@@ -56,11 +56,11 @@ def test_product_conformance_response(
5656

5757

5858
@pytest.mark.parametrize("product_id", ["test-spotlight"])
59-
def test_product_constraints_response(
59+
def test_product_queryables_response(
6060
product_id: str,
6161
stapi_client: TestClient,
6262
):
63-
res = stapi_client.get(f"/products/{product_id}/constraints")
63+
res = stapi_client.get(f"/products/{product_id}/queryables")
6464
assert res.status_code == status.HTTP_200_OK
6565
assert res.headers["Content-Type"] == "application/json"
6666

@@ -106,8 +106,8 @@ def test_get_products_pagination(
106106
"type": "application/json",
107107
},
108108
{
109-
"href": f"http://stapiserver/products/{product_id}/constraints",
110-
"rel": "constraints",
109+
"href": f"http://stapiserver/products/{product_id}/queryables",
110+
"rel": "queryables",
111111
"type": "application/json",
112112
},
113113
{

stapi-pydantic/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
1313

1414
### Changed
1515

16+
- `s/constraints/queryables/` ([#74](https://github.com/stapi-spec/pystapi/pull/74))
1617
- `s/canceled/cancelled/` ([#75](https://github.com/stapi-spec/pystapi/pull/75))
1718

1819
## [0.0.2] - 2025-04-02

stapi-pydantic/src/stapi_pydantic/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from .conformance import Conformance
2-
from .constraints import Constraints
32
from .datetime_interval import DatetimeInterval
43
from .filter import CQL2Filter
54
from .json_schema_model import JsonSchemaModel
@@ -26,12 +25,12 @@
2625
OrderStatuses,
2726
)
2827
from .product import Product, ProductsCollection, Provider, ProviderRole
28+
from .queryables import Queryables
2929
from .root import RootResponse
3030
from .shared import Link
3131

3232
__all__ = [
3333
"Conformance",
34-
"Constraints",
3534
"CQL2Filter",
3635
"DatetimeInterval",
3736
"JsonSchemaModel",
@@ -58,5 +57,6 @@
5857
"ProductsCollection",
5958
"Provider",
6059
"ProviderRole",
60+
"Queryables",
6161
"RootResponse",
6262
]

stapi-pydantic/src/stapi_pydantic/product.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
from enum import StrEnum
2-
from typing import Any, Literal, Self, TypeAlias
2+
from typing import Any, Literal, Self
33

44
from pydantic import AnyHttpUrl, BaseModel, Field
55

66
from .constants import STAPI_VERSION
77
from .shared import Link
88

9-
Constraints: TypeAlias = BaseModel
10-
119

1210
class ProviderRole(StrEnum):
1311
licensor = "licensor"

0 commit comments

Comments
 (0)