Skip to content

Commit e4b163b

Browse files
authored
Use token from headers in backends (#83)
1 parent d36dfcc commit e4b163b

10 files changed

Lines changed: 295 additions & 306 deletions

File tree

demo/api/api_types.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,15 @@
22
from typing import Any, Dict, List, Literal, Optional, Union
33

44
from geojson_pydantic.features import Feature, FeatureCollection
5-
from geojson_pydantic.geometries import (
6-
GeometryCollection,
7-
LineString,
8-
MultiLineString,
9-
MultiPoint,
10-
MultiPolygon,
11-
Point,
12-
Polygon,
13-
)
5+
from geojson_pydantic.geometries import (GeometryCollection, LineString,
6+
MultiLineString, MultiPoint,
7+
MultiPolygon, Point, Polygon)
148
from pydantic import BaseModel, Field
159
from pydantic.datetime_parse import parse_datetime
1610
from stac_pydantic.collection import Range
1711
from stac_pydantic.links import Link
1812
from stac_pydantic.shared import Provider
1913

20-
2114
Geometry = Union[
2215
Point,
2316
MultiPoint,
@@ -33,7 +26,6 @@
3326
ProductParameters = Dict[str, Union[Range, List[Any], Dict[str, Any]]]
3427

3528

36-
3729
class Order(BaseModel):
3830
id: str
3931

demo/api/backends/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
from api.backends.fake_backend import FakeBackend
1+
from api.backends.base import Backend
22
from api.backends.blacksky_backend import BlackskyBackend
3+
from api.backends.fake_backend import FakeBackend
34
from api.backends.planet_backend import PlanetBackend
45
from api.backends.sentinel_backend import HistoricalBackend
56
from api.backends.umbra_backend import UmbraBackend
67

7-
8-
BACKENDS: dict[str, HistoricalBackend] = {
9-
"fake": FakeBackend(),
10-
"historical": HistoricalBackend(),
11-
"blacksky": BlackskyBackend(),
12-
"planet": PlanetBackend(),
13-
"umbra": UmbraBackend(),
8+
BACKENDS: dict[str, Backend] = {
9+
"fake": FakeBackend,
10+
"historical": HistoricalBackend,
11+
"blacksky": BlackskyBackend,
12+
"planet": PlanetBackend,
13+
"umbra": UmbraBackend,
1414
}

demo/api/backends/base.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
from typing import Protocol, Optional
2-
import os
1+
from typing import Protocol
32

4-
from api.api_types import OpportunityCollection, Product, Search, Order
3+
from api.api_types import OpportunityCollection, Order, Product, Search
54

65

76
# backend protocol class
@@ -27,12 +26,3 @@ async def place_order(
2726
token: str,
2827
) -> Order:
2928
return NotImplemented
30-
31-
32-
def get_token(backend: str) -> Optional[str]:
33-
token_name = f"{backend.upper()}_TOKEN"
34-
35-
if token_name not in os.environ:
36-
# skip endpoint if token not provided
37-
return
38-
return os.environ[token_name]
Lines changed: 47 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,61 @@
1-
from datetime import datetime, timedelta
2-
import os
31
import requests
42

53
from api.api_types import Opportunity, OpportunityCollection, Search
64

75
BLACKSKY_BASE_URL = "https://api.dev.blacksky.com/v1"
86

9-
def stac_search_to_oppurtunities_request(search_request: Search):
107

8+
def stac_search_to_oppurtunities_request(search_request: Search):
119
"""
1210
:param search_request: STAC search as passed on to find_future_items
1311
:return: a triple of iw request body, geom and bbox (geom and bbox needed again later to construct STAC answers)
1412
"""
1513
bs_number, bs_product = "BS-TEST", "Standard"
1614
if search_request.product_id:
17-
bs_number, bs_product = search_request.product_id.split(':')
15+
bs_number, bs_product = search_request.product_id.split(":")
1816

1917
return {
20-
"item": {
21-
"name": "Blacksky_Request",
22-
"description": "STAC Sprint",
23-
"timeframe": {
24-
"lowerBoundType": "CLOSED",
25-
"lowerEndpoint": search_request.start_date.isoformat(),
26-
"upperBoundType": "CLOSED",
27-
"upperEndpoint": search_request.end_date.isoformat()
28-
},
29-
"geometry": {
30-
"type": "Point",
31-
"coordinates": [
32-
search_request.geometry.dict()['coordinates'][0],
33-
search_request.geometry.dict()['coordinates'][1],
34-
0
35-
]
36-
},
37-
"frequency": "ONCE",
38-
"offeringId": "391327b7-f4ee-4e7f-a894-3cffef19cae0",
39-
"frequency": "ONCE",
40-
"offeringParamValues": {
41-
"priority": "STANDARD",
42-
"sensor": "blacksky"
43-
},
44-
"externalId": "1234"
18+
"item": {
19+
"name": "Blacksky_Request",
20+
"description": "STAC Sprint",
21+
"timeframe": {
22+
"lowerBoundType": "CLOSED",
23+
"lowerEndpoint": search_request.start_date.isoformat(),
24+
"upperBoundType": "CLOSED",
25+
"upperEndpoint": search_request.end_date.isoformat(),
4526
},
46-
"includeWeather": True
47-
}
27+
"geometry": {
28+
"type": "Point",
29+
"coordinates": [
30+
search_request.geometry.dict()["coordinates"][0],
31+
search_request.geometry.dict()["coordinates"][1],
32+
0,
33+
],
34+
},
35+
"frequency": "ONCE",
36+
"offeringId": "391327b7-f4ee-4e7f-a894-3cffef19cae0",
37+
"frequency": "ONCE",
38+
"offeringParamValues": {"priority": "STANDARD", "sensor": "blacksky"},
39+
"externalId": "1234",
40+
},
41+
"includeWeather": True,
42+
}
4843

49-
def get_oppurtunities(blacksky_request):
5044

45+
def get_oppurtunities(blacksky_request, token):
5146
headers = {
52-
'accept': 'application/json',
53-
'Content-Type': 'application/json',
54-
'authorization': os.getenv("BLACKSKY_TOKEN")
47+
"accept": "application/json",
48+
"Content-Type": "application/json",
49+
"authorization": token,
5550
}
5651

5752
r = requests.post(
58-
f"{BLACKSKY_BASE_URL}/feasibility/plan",
59-
headers=headers,
60-
json=blacksky_request
53+
f"{BLACKSKY_BASE_URL}/feasibility/plan", headers=headers, json=blacksky_request
6154
)
62-
return r.json()['opportunities']
55+
return r.json()["opportunities"]
6356

6457

6558
def oppurtunity_to_stac_item(iw):
66-
6759
"""
6860
translates a Planet Imaging Windows into a STAC item
6961
:param iw: an element from the 'imaging_windows' array of a /imaging_windows/[search_id] response
@@ -72,39 +64,28 @@ def oppurtunity_to_stac_item(iw):
7264

7365
item = Opportunity(
7466
id=iw["satellite"],
75-
geometry={
76-
'type': 'Point',
77-
'coordinates': [
78-
iw['longitude'],
79-
iw['latitude'],
80-
0
81-
]
82-
},
67+
geometry={"type": "Point", "coordinates": [iw["longitude"], iw["latitude"], 0]},
8368
properties={
84-
'title': '',
85-
'datetime': f"{iw['timestamp']}/{iw['timestamp']}",
86-
'constraints': {
87-
'off_nadir': iw['offNadirAngleDegrees'],
88-
'cloud_cover': iw['weatherForecast']['cloudCover']
89-
}
90-
})
69+
"title": "",
70+
"datetime": f"{iw['timestamp']}/{iw['timestamp']}",
71+
"constraints": {
72+
"off_nadir": iw["offNadirAngleDegrees"],
73+
"cloud_cover": iw["weatherForecast"]["cloudCover"],
74+
},
75+
},
76+
)
9177

9278
return item
9379

94-
class BlackskyBackend:
9580

81+
class BlackskyBackend:
9682
async def find_opportunities(
97-
self,
98-
search_request: Search,
99-
token: str,
83+
self,
84+
search_request: Search,
85+
token: str,
10086
) -> OpportunityCollection:
101-
10287
blacksky_request = stac_search_to_oppurtunities_request(search_request)
103-
oppurtunities = get_oppurtunities(blacksky_request)
104-
stac_items = [
105-
oppurtunity_to_stac_item(iw)
106-
for iw
107-
in oppurtunities
108-
]
88+
oppurtunities = get_oppurtunities(blacksky_request, token)
89+
stac_items = [oppurtunity_to_stac_item(iw) for iw in oppurtunities]
10990

11091
return OpportunityCollection(features=stac_items, links=[])

demo/api/backends/fake_backend.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
11
import pystac
2-
from api.api_types import Opportunity, OpportunityCollection, Search, Product, Provider
32

3+
from api.api_types import (Opportunity, OpportunityCollection, Product,
4+
Provider, Search)
45

56
STAC_ITEM_URL = (
67
"https://raw.githubusercontent.com/stac-utils/pystac/main/"
78
"tests/data-files/item/sample-item.json"
89
)
910

1011

11-
class FakeBackend():
12+
class FakeBackend:
1213
async def find_opportunities(
1314
self,
1415
search: Search,
1516
token: str,
16-
) -> Opportunity:
17-
17+
) -> OpportunityCollection:
1818
item = pystac.Item.from_file(STAC_ITEM_URL)
1919
opportunity = Opportunity(geometry=item.geometry, properties=item.properties)
20-
opportunity_collection = OpportunityCollection(
21-
features=[opportunity]
22-
)
20+
opportunity_collection = OpportunityCollection(features=[opportunity])
2321
return opportunity_collection
2422

25-
2623
async def find_products(self, token: str) -> list[Product]:
2724
# todo: get real list of products
2825
# todo: consider proper reactions for all types of products
@@ -39,6 +36,6 @@ async def find_products(self, token: str) -> list[Product]:
3936
keywords=[],
4037
providers=[Provider(name="fake")],
4138
constraints={},
42-
parameters={}
39+
parameters={},
4340
)
44-
]
41+
]

0 commit comments

Comments
 (0)