Skip to content
This repository was archived by the owner on Apr 2, 2025. It is now read-only.

Commit fe9124d

Browse files
author
Phil Varner
authored
RootBackend protocol uses library types Result and Maybe instead of exceptions (#107)
* RootBackend and ProductBackend protocol uses returns library types Result and Maybe instead of exceptions. * update pydantic version * run mypy in github ci correctly
1 parent 3125efc commit fe9124d

File tree

14 files changed

+398
-217
lines changed

14 files changed

+398
-217
lines changed

.github/workflows/pr.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@ jobs:
2424
run: |
2525
python -m pip install pre-commit
2626
pre-commit run --all-files
27+
- name: Type-check code
28+
if: ${{ matrix.python-version == 3.12 }}
29+
run: poetry run mypy src
2730
- name: Run tests
2831
run: poetry run nox

.pre-commit-config.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ repos:
1919
rev: v1.13.0
2020
hooks:
2121
- id: mypy
22-
files: ".*\\.py$"
22+
args: [] # override default of [--strict, --ignore-missing-imports]
23+
files: src/
2324
additional_dependencies:
2425
- types-pyRFC3339~=1.1.1
26+
- pydantic~=2.10.1
27+
- returns~=0.23.0
28+
- fastapi~=0.115.0
29+
- geojson_pydantic~=1.1.1

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ none
1313

1414
### Changed
1515

16+
- RootBackend and ProductBackend protocols use `returns` library types Result and Maybe instead of
17+
raising exceptions.
1618
- Create Order endpoint from `.../order` to `.../orders`
1719
- Order field `id` must be a string, instead of previously allowing int. This is because while an
1820
order ID may an integral numeric value, it is not a "number" in the sense that math will be performed

bin/server.py

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
from uuid import uuid4
33

44
from fastapi import FastAPI, Request
5+
from returns.maybe import Maybe
6+
from returns.result import Failure, Result, Success
57

68
from stapi_fastapi.backends.product_backend import ProductBackend
79
from stapi_fastapi.backends.root_backend import RootBackend
8-
from stapi_fastapi.exceptions import NotFoundException
910
from stapi_fastapi.models.conformance import CORE
1011
from stapi_fastapi.models.opportunity import (
1112
Opportunity,
@@ -37,20 +38,20 @@ class MockRootBackend(RootBackend):
3738
def __init__(self, orders: MockOrderDB) -> None:
3839
self._orders: MockOrderDB = orders
3940

40-
async def get_orders(self, request: Request) -> OrderCollection:
41+
async def get_orders(self, request: Request) -> Result[OrderCollection, Exception]:
4142
"""
4243
Show all orders.
4344
"""
44-
return OrderCollection(features=list(self._orders.values()))
45+
return Success(OrderCollection(features=list(self._orders.values())))
4546

46-
async def get_order(self, order_id: str, request: Request) -> Order:
47+
async def get_order(
48+
self, order_id: str, request: Request
49+
) -> Result[Maybe[Order], Exception]:
4750
"""
4851
Show details for order with `order_id`.
4952
"""
50-
try:
51-
return self._orders[order_id]
52-
except KeyError:
53-
raise NotFoundException()
53+
54+
return Success(Maybe.from_optional(self._orders.get(order_id)))
5455

5556

5657
class MockProductBackend(ProductBackend):
@@ -64,41 +65,49 @@ async def search_opportunities(
6465
product_router: ProductRouter,
6566
search: OpportunityRequest,
6667
request: Request,
67-
) -> list[Opportunity]:
68-
return [o.model_copy(update=search.model_dump()) for o in self._opportunities]
68+
) -> Result[list[Opportunity], Exception]:
69+
try:
70+
return Success(
71+
[o.model_copy(update=search.model_dump()) for o in self._opportunities]
72+
)
73+
except Exception as e:
74+
return Failure(e)
6975

7076
async def create_order(
7177
self, product_router: ProductRouter, payload: OrderRequest, request: Request
72-
) -> Order:
78+
) -> Result[Order, Exception]:
7379
"""
7480
Create a new order.
7581
"""
76-
order = Order(
77-
id=str(uuid4()),
78-
geometry=payload.geometry,
79-
properties={
80-
"product_id": product_router.product.id,
81-
"created": datetime.now(timezone.utc),
82-
"status": OrderStatus(
83-
timestamp=datetime.now(timezone.utc),
84-
status_code=OrderStatusCode.accepted,
85-
),
86-
"search_parameters": {
87-
"geometry": payload.geometry,
88-
"datetime": payload.datetime,
89-
"filter": payload.filter,
90-
},
91-
"order_parameters": payload.order_parameters.model_dump(),
92-
"opportunity_properties": {
93-
"datetime": "2024-01-29T12:00:00Z/2024-01-30T12:00:00Z",
94-
"off_nadir": 10,
82+
try:
83+
order = Order(
84+
id=str(uuid4()),
85+
geometry=payload.geometry,
86+
properties={
87+
"product_id": product_router.product.id,
88+
"created": datetime.now(timezone.utc),
89+
"status": OrderStatus(
90+
timestamp=datetime.now(timezone.utc),
91+
status_code=OrderStatusCode.accepted,
92+
),
93+
"search_parameters": {
94+
"geometry": payload.geometry,
95+
"datetime": payload.datetime,
96+
"filter": payload.filter,
97+
},
98+
"order_parameters": payload.order_parameters.model_dump(),
99+
"opportunity_properties": {
100+
"datetime": "2024-01-29T12:00:00Z/2024-01-30T12:00:00Z",
101+
"off_nadir": 10,
102+
},
95103
},
96-
},
97-
links=[],
98-
)
104+
links=[],
105+
)
99106

100-
self._orders[order.id] = order
101-
return order
107+
self._orders[order.id] = order
108+
return Success(order)
109+
except Exception as e:
110+
return Failure(e)
102111

103112

104113
class MyOpportunityProperties(OpportunityProperties):

0 commit comments

Comments
 (0)