Skip to content

Commit

Permalink
Merge branch 'main' into dockerfile
Browse files Browse the repository at this point in the history
  • Loading branch information
mindflayer authored Apr 17, 2024
2 parents 61d3dfb + 55e0dac commit 55c367b
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 75 deletions.
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
__pycache__
*.sqlite
/.coverage
/.pytest_cache
/.ruff_cache
.idea

# python
.python-version
.venv
__pycache__
.env

.idea
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ omit = [
addopts="--cov=stat_fastapi"
filterwarnings = [
"ignore:The 'app' shortcut is now deprecated.:DeprecationWarning",
"ignore:Pydantic serializer warnings:UserWarning",
]

[build-system]
Expand Down
6 changes: 3 additions & 3 deletions stat_fastapi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
OpportunityCollection,
OpportunitySearch,
)
from stat_fastapi.models.order import Order, OrderPayload
from stat_fastapi.models.order import Order
from stat_fastapi.models.product import Product, ProductsCollection
from stat_fastapi.models.root import RootResponse
from stat_fastapi.models.shared import HTTPException as HTTPExceptionModel
Expand Down Expand Up @@ -161,13 +161,13 @@ async def search_opportunities(
)

async def create_order(
self, payload: OrderPayload, request: Request
self, search: OpportunitySearch, request: Request
) -> JSONResponse:
"""
Create a new order.
"""
try:
order = await self.backend.create_order(payload, request)
order = await self.backend.create_order(search, request)
except ConstraintsException as exc:
raise HTTPException(status.HTTP_422_UNPROCESSABLE_ENTITY, detail=exc.detail)

Expand Down
4 changes: 2 additions & 2 deletions stat_fastapi/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from fastapi import Request

from stat_fastapi.models.opportunity import Opportunity, OpportunitySearch
from stat_fastapi.models.order import Order, OrderPayload
from stat_fastapi.models.order import Order
from stat_fastapi.models.product import Product


Expand All @@ -29,7 +29,7 @@ async def search_opportunities(
`stat_fastapi.backend.exceptions.ConstraintsException` if not valid.
"""

async def create_order(self, payload: OrderPayload, request: Request) -> Order:
async def create_order(self, search: OpportunitySearch, request: Request) -> Order:
"""
Create a new order.
Expand Down
4 changes: 0 additions & 4 deletions stat_fastapi/models/constraints.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
from pydantic import BaseModel, ConfigDict

from stat_fastapi.types.datetime_interval import DatetimeInterval


class Constraints(BaseModel):
datetime: DatetimeInterval

model_config = ConfigDict(extra="allow")
16 changes: 11 additions & 5 deletions stat_fastapi/models/opportunity.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
from typing import Any, Literal, Mapping
from typing import Literal

from geojson_pydantic import Feature, FeatureCollection
from geojson_pydantic.geometries import Geometry
from pydantic import BaseModel

from stat_fastapi.models.constraints import Constraints
from stat_fastapi.types.datetime_interval import DatetimeInterval

OpportunityProperties = Mapping[str, Any]


class OpportunitySearch(Feature[Geometry, Constraints]):
# Copied and modified from stack_pydantic.item.ItemProperties
class OpportunityProperties(BaseModel):
datetime: DatetimeInterval
product_id: str
constraints: Constraints


class OpportunitySearch(OpportunityProperties):
geometry: Geometry


class Opportunity(Feature[Geometry, OpportunityProperties]):
type: Literal["Feature"] = "Feature"
constraints: Constraints


class OpportunityCollection(FeatureCollection[Opportunity]):
Expand Down
9 changes: 2 additions & 7 deletions stat_fastapi/models/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@
from geojson_pydantic import Feature
from geojson_pydantic.geometries import Geometry

from stat_fastapi.models.constraints import Constraints
from stat_fastapi.models.opportunity import OpportunityProperties
from stat_fastapi.models.shared import Link


class OrderPayload(Feature[Geometry, Constraints]):
product_id: str


class Order(Feature[Geometry, Constraints]):
class Order(Feature[Geometry, OpportunityProperties]):
type: Literal["Feature"] = "Feature"
product_id: str
links: list[Link]
20 changes: 10 additions & 10 deletions stat_fastapi_test_backend/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

from stat_fastapi.exceptions import ConstraintsException, NotFoundException
from stat_fastapi.models.opportunity import Opportunity, OpportunitySearch
from stat_fastapi.models.order import Order, OrderPayload
from stat_fastapi.models.order import Order
from stat_fastapi.models.product import Product


class TestBackend:
_products: list[Product] = []
_opportunities: list[Opportunity] = []
_allowed_order_payloads: list[OrderPayload] = []
_allowed_payloads: list[OpportunitySearch] = []
_orders: Mapping[str, Order] = {}

def products(self, request: Request) -> list[Product]:
Expand All @@ -36,22 +36,22 @@ def product(self, product_id: str, request: Request) -> Product | None:
async def search_opportunities(
self, search: OpportunitySearch, request: Request
) -> list[Opportunity]:
return [
o.model_copy(update={"constraints": search.properties})
for o in self._opportunities
]
return [o.model_copy(update=search.model_dump()) for o in self._opportunities]

async def create_order(self, payload: OrderPayload, request: Request) -> Order:
async def create_order(self, payload: OpportunitySearch, request: Request) -> Order:
"""
Create a new order.
"""
allowed = any(allowed == payload for allowed in self._allowed_order_payloads)
allowed = any(allowed == payload for allowed in self._allowed_payloads)
if allowed:
order = Order(
id=str(uuid4()),
geometry=payload.geometry,
properties=payload.properties,
product_id=payload.product_id,
properties={
"constraints": payload.constraints,
"datetime": payload.datetime,
"product_id": payload.product_id,
},
links=[],
)
self._orders[order.id] = order
Expand Down
11 changes: 4 additions & 7 deletions stat_fastapi_tle_backend/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@

from stat_fastapi.exceptions import ConstraintsException, NotFoundException
from stat_fastapi.models.opportunity import Opportunity, OpportunitySearch
from stat_fastapi.models.order import Order, OrderPayload
from stat_fastapi.models.order import Order
from stat_fastapi.models.product import Product, Provider, ProviderRole
from stat_fastapi_tle_backend.models import (
ValidatedOpportunitySearch,
ValidatedOrderPayload,
)
from stat_fastapi_tle_backend.models import ValidatedOpportunitySearch
from stat_fastapi_tle_backend.repository import Repository
from stat_fastapi_tle_backend.satellite import EarthObservationSatelliteModel
from stat_fastapi_tle_backend.settings import Settings
Expand Down Expand Up @@ -116,12 +113,12 @@ async def search_opportunities(
]
return opportunities

async def create_order(self, payload: OrderPayload, request: Request) -> Order:
async def create_order(self, search: OpportunitySearch, request: Request) -> Order:
"""
Create a new order.
"""
try:
validated = ValidatedOrderPayload(**payload.model_dump(by_alias=True))
validated = ValidatedOpportunitySearch(**search.model_dump(by_alias=True))
except ValidationError as exc:
raise ConstraintsException(exc.errors()) from exc

Expand Down
5 changes: 0 additions & 5 deletions stat_fastapi_tle_backend/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

from stat_fastapi.models.constraints import Constraints as BaseConstraints
from stat_fastapi.models.opportunity import OpportunitySearch
from stat_fastapi.models.order import OrderPayload


class Satellite(BaseModel):
Expand Down Expand Up @@ -77,7 +76,3 @@ class Constraints(BaseConstraints):

class ValidatedOpportunitySearch(OpportunitySearch):
properties: Constraints


class ValidatedOrderPayload(OrderPayload):
properties: Constraints
20 changes: 10 additions & 10 deletions stat_fastapi_tle_backend/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from stat_fastapi.models.constraints import Constraints
from stat_fastapi.models.order import Order

from .models import OffNadirRange, ValidatedOrderPayload
from .models import OffNadirRange, ValidatedOpportunitySearch

logger = getLogger(__name__)

Expand Down Expand Up @@ -41,17 +41,17 @@ class OrderEntity(Base):
)

@classmethod
def from_payload(cls, payload: ValidatedOrderPayload) -> "OrderEntity":
def from_search(cls, search: ValidatedOpportunitySearch) -> "OrderEntity":
order_id = str(uuid4())
geom = from_geojson(payload.geometry.model_dump_json(by_alias=True))
geom = from_geojson(search.geometry.model_dump_json(by_alias=True))
return OrderEntity(
id=order_id,
product_id=payload.product_id,
product_id=search.product_id,
geom=f"SRID=4326;{to_wkt(geom)}",
dt_start=payload.properties.datetime[0],
dt_end=payload.properties.datetime[1],
off_nadir_min=payload.properties.off_nadir.minimum,
off_nadir_max=payload.properties.off_nadir.maximum,
dt_start=search.datetime[0],
dt_end=search.datetime[1],
off_nadir_min=search.constraints.off_nadir.minimum,
off_nadir_max=search.constraints.off_nadir.maximum,
status="pending",
)

Expand Down Expand Up @@ -107,8 +107,8 @@ def __enter__(self) -> Session:
def __exit__(self, exception_type, exception_value, exception_traceback):
self.session.close()

def add_order(self, payload: ValidatedOrderPayload) -> Order:
entity = OrderEntity.from_payload(payload)
def add_order(self, search: ValidatedOpportunitySearch) -> Order:
entity = OrderEntity.from_search(search)
with self as session:
session.add(entity)
session.commit()
Expand Down
20 changes: 11 additions & 9 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
from pytest import fixture

from stat_fastapi.models.constraints import Constraints
from stat_fastapi.models.opportunity import Opportunity
from stat_fastapi.models.order import OrderPayload
from stat_fastapi.models.opportunity import Opportunity, OpportunitySearch
from stat_fastapi.models.product import Product, Provider, ProviderRole


Expand Down Expand Up @@ -39,23 +38,26 @@ class Constraints(BaseModel):


@fixture
def opportunities():
def opportunities(products: list[Product]):
yield [
Opportunity(
geometry=Point(type="Point", coordinates=[13.4, 52.5]),
properties={},
constraints=Constraints(datetime=(datetime.now(UTC), datetime.now(UTC))),
properties={
"product_id": products[0].id,
"datetime": (datetime.now(UTC), datetime.now(UTC)),
"constraints": {},
},
)
]


@fixture
def allowed_order_payloads(products: list[Product]):
def allowed_payloads(products: list[Product]):
yield [
OrderPayload(
type="Feature",
OpportunitySearch(
geometry=Point(type="Point", coordinates=[13.4, 52.5]),
product_id=products[0].id,
properties=Constraints(datetime=(datetime.now(UTC), datetime.now(UTC))),
datetime=(datetime.now(UTC), datetime.now(UTC)),
constraints=Constraints(),
),
]
4 changes: 2 additions & 2 deletions tests/opportunity_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def test_search_opportunities_response(
"coordinates": [0, 0],
},
"product_id": products[0].id,
"properties": {
"datetime": f"{start.isoformat()}/{end.isoformat()}",
"datetime": f"{start.isoformat()}/{end.isoformat()}",
"constraints": {
"off_nadir": {
"minimum": 0,
"maximum": 45,
Expand Down
16 changes: 7 additions & 9 deletions tests/order_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from httpx import Response
from pytest import fixture

from stat_fastapi.models.order import OrderPayload
from stat_fastapi.models.opportunity import OpportunitySearch
from stat_fastapi_test_backend.backend import TestBackend

from .utils import find_link
Expand All @@ -20,13 +20,13 @@
def new_order_response(
stat_backend: TestBackend,
stat_client: TestClient,
allowed_order_payloads: list[OrderPayload],
allowed_payloads: list[OpportunitySearch],
) -> Generator[Response, None, None]:
stat_backend._allowed_order_payloads = allowed_order_payloads
stat_backend._allowed_payloads = allowed_payloads

res = stat_client.post(
"/orders",
json=allowed_order_payloads[0].model_dump(),
json=allowed_payloads[0].model_dump(),
)

assert res.status_code == status.HTTP_201_CREATED
Expand All @@ -48,21 +48,19 @@ def get_order_response(
order_id = new_order_response.json()["id"]

res = stat_client.get(f"/orders/{order_id}")
print(res.text)
assert res.status_code == status.HTTP_200_OK
assert res.headers["Content-Type"] == "application/geo+json"
yield res


def test_get_order_properties(get_order_response: Response, allowed_order_payloads):
def test_get_order_properties(get_order_response: Response, allowed_payloads):
order = get_order_response.json()

assert order["geometry"] == {
"type": "Point",
"coordinates": list(allowed_order_payloads[0].geometry.coordinates),
"coordinates": list(allowed_payloads[0].geometry.coordinates),
}

assert (
order["properties"]["datetime"]
== allowed_order_payloads[0].properties.model_dump()["datetime"]
order["properties"]["datetime"] == allowed_payloads[0].model_dump()["datetime"]
)

0 comments on commit 55c367b

Please sign in to comment.