Skip to content

Commit 39b8ee9

Browse files
Emma SteuerEmma Steuer
authored andcommitted
Merge branch 'main' into release-2.5.0
2 parents de23807 + 074b5e0 commit 39b8ee9

File tree

4 files changed

+107
-12
lines changed

4 files changed

+107
-12
lines changed

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2.5.0 (2024-04-04)
2+
3+
Added:
4+
- Support Subscriptions API hosting block for Sentinel Hub in the CLI (#1029).
5+
6+
- Support for field_boundaries_sentinel_2_p1m in Subscriptions API (#1026)
7+
18
2.4.0 (2024-03-19)
29

310
Added:

planet/cli/subscriptions.py

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .session import CliSession
1212
from planet.clients.subscriptions import SubscriptionsClient
1313
from .. import subscription_request
14+
from ..subscription_request import sentinel_hub
1415
from ..specs import get_item_types, validate_item_type, SpecificationException
1516

1617
ALL_ITEM_TYPES = get_item_types()
@@ -87,21 +88,46 @@ async def list_subscriptions_cmd(ctx, status, limit, pretty):
8788
echo_json(sub, pretty)
8889

8990

90-
@subscriptions.command(name='create') # type: ignore
91-
@click.argument('request', type=types.JSON())
91+
@subscriptions.command(name="create") # type: ignore
92+
@click.argument("request", type=types.JSON())
93+
@click.option(
94+
"--hosting",
95+
type=click.Choice([
96+
"sentinel_hub",
97+
]),
98+
default=None,
99+
help='Hosting type. Currently, only "sentinel_hub" is supported.',
100+
)
101+
@click.option("--collection-id",
102+
default=None,
103+
help='Collection ID for Sentinel Hub.'
104+
'If omitted, a new collection will be created.')
92105
@pretty
93106
@click.pass_context
94107
@translate_exceptions
95108
@coro
96-
async def create_subscription_cmd(ctx, request, pretty):
109+
async def create_subscription_cmd(ctx, request, pretty, **kwargs):
97110
"""Create a subscription.
98111
99112
Submits a subscription request for creation and prints the created
100113
subscription description, optionally pretty-printed.
101114
102115
REQUEST is the full description of the subscription to be created. It must
103116
be JSON and can be specified a json string, filename, or '-' for stdin.
117+
118+
Other flag options are hosting and collection_id. The hosting flag
119+
specifies the hosting type, and the collection_id flag specifies the
120+
collection ID for Sentinel Hub. If the collection_id is omitted, a new
121+
collection will be created.
104122
"""
123+
124+
hosting = kwargs.get("hosting", None)
125+
collection_id = kwargs.get("collection_id", None)
126+
127+
if hosting == "sentinel_hub":
128+
hosting_info = sentinel_hub(collection_id)
129+
request["hosting"] = hosting_info
130+
105131
async with subscriptions_client(ctx) as client:
106132
sub = await client.create_subscription(request)
107133
echo_json(sub, pretty)
@@ -263,20 +289,28 @@ async def list_subscription_results_cmd(ctx,
263289
help='Toolchain JSON. Can be a string, filename, or - for stdin.')
264290
@click.option(
265291
'--hosting',
266-
type=types.JSON(),
267-
help='Hosting JSON. Can be a string, a filename, or - for stdin.')
292+
default=None,
293+
type=click.Choice([
294+
"sentinel_hub",
295+
]),
296+
help='Hosting configuration. Can be JSON, "sentinel_hub", or omitted.')
268297
@click.option(
269298
'--clip-to-source',
270299
is_flag=True,
271300
default=False,
272301
help="Clip to the source geometry without specifying a clip tool.")
302+
@click.option("--collection-id",
303+
default=None,
304+
help='Collection ID for Sentinel Hub.'
305+
'If omitted, a new collection will be created.')
273306
@pretty
274307
def request(name,
275308
source,
276309
delivery,
277310
notifications,
278311
tools,
279312
hosting,
313+
collection_id,
280314
clip_to_source,
281315
pretty):
282316
"""Generate a subscriptions request.
@@ -286,12 +320,14 @@ def request(name,
286320
--clip-to-source option is a preview of the next API version's
287321
default behavior.
288322
"""
323+
289324
res = subscription_request.build_request(name,
290325
source,
291326
delivery,
292327
notifications=notifications,
293328
tools=tools,
294329
hosting=hosting,
330+
collection_id=collection_id,
295331
clip_to_source=clip_to_source)
296332
echo_json(res, pretty)
297333

@@ -349,6 +385,7 @@ def request_catalog(item_types,
349385
time_range_type,
350386
pretty):
351387
"""Generate a subscriptions request catalog source description."""
388+
352389
res = subscription_request.catalog_source(
353390
item_types,
354391
asset_types,
@@ -373,7 +410,8 @@ def request_catalog(item_types,
373410
"land_surface_temperature",
374411
"soil_water_content",
375412
"vegetation_optical_depth",
376-
"forest_carbon_diligence_30m"
413+
"forest_carbon_diligence_30m",
414+
"field_boundaries_sentinel_2_p1m"
377415
]),
378416
)
379417
@click.option('--var-id', required=True, help='Planetary variable id.')

planet/subscription_request.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ def build_request(name: str,
5252
delivery: Optional[Mapping] = None,
5353
notifications: Optional[Mapping] = None,
5454
tools: Optional[List[Mapping]] = None,
55-
hosting: Optional[Mapping] = None,
55+
hosting: Optional[Union[Mapping, str]] = None,
56+
collection_id: Optional[str] = None,
5657
clip_to_source: Optional[bool] = False) -> dict:
5758
"""Construct a Subscriptions API request.
5859
@@ -150,8 +151,15 @@ def build_request(name: str,
150151

151152
details['tools'] = tool_list
152153

153-
if hosting:
154-
details['hosting'] = dict(hosting)
154+
if hosting == "sentinel_hub":
155+
hosting_info: Dict[str, Any] = {
156+
"type": "sentinel_hub", "parameters": {}
157+
}
158+
if collection_id:
159+
hosting_info["parameters"]["collection_id"] = collection_id
160+
details['hosting'] = hosting_info
161+
elif isinstance(hosting, dict):
162+
details['hosting'] = hosting
155163

156164
return details
157165

@@ -276,7 +284,8 @@ def planetary_variable_source(
276284
"land_surface_temperature",
277285
"soil_water_content",
278286
"vegetation_optical_depth",
279-
"forest_carbon_diligence_30m"],
287+
"forest_carbon_diligence_30m",
288+
"field_boundaries_sentinel_2_p1m"],
280289
var_id: str,
281290
geometry: Mapping,
282291
start_time: datetime,
@@ -296,8 +305,8 @@ def planetary_variable_source(
296305
297306
Parameters:
298307
var_type: one of "biomass_proxy", "land_surface_temperature",
299-
"soil_water_content", "vegetation_optical_depth", or
300-
"forest_carbon_diligence_30m".
308+
"soil_water_content", "vegetation_optical_depth",
309+
"forest_carbon_diligence_30m, or field_boundaries_sentinel_2_p1m".
301310
var_id: a value such as "SWC-AMSR2-C_V1.0_100" for soil water
302311
content derived from AMSR2 C band.
303312
geometry: The area of interest of the subscription that will be

tests/integration/test_subscriptions_cli.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,3 +435,44 @@ def test_catalog_source_time_range_type(invoke, geom_geojson, time_range_type):
435435
assert result.exit_code == 0 # success.
436436
req = json.loads(result.output)
437437
assert req['parameters']['time_range_type'] == time_range_type
438+
439+
440+
@pytest.mark.parametrize(
441+
"hosting_option, collection_id_option, expected_success",
442+
[
443+
("--hosting=sentinel_hub", None, True),
444+
("--hosting=sentinel_hub",
445+
"--collection-id=7ff105c4-e0de-4910-96db-8345d86ab734",
446+
True),
447+
])
448+
def test_request_hosting(invoke,
449+
geom_geojson,
450+
hosting_option,
451+
collection_id_option,
452+
expected_success):
453+
"""Test request command with various hosting and collection ID options."""
454+
source = json.dumps({
455+
"type": "catalog",
456+
"parameters": {
457+
"geometry": geom_geojson,
458+
"start_time": "2021-03-01T00:00:00Z",
459+
"end_time": "2023-11-01T00:00:00Z",
460+
"rrule": "FREQ=MONTHLY;BYMONTH=3,4,5,6,7,8,9,10",
461+
"item_types": ["PSScene"],
462+
"asset_types": ["ortho_analytic_4b"]
463+
}
464+
})
465+
466+
cmd = [
467+
'request',
468+
'--name=test',
469+
f'--source={source}',
470+
hosting_option,
471+
]
472+
473+
if collection_id_option:
474+
cmd.append(collection_id_option)
475+
476+
result = invoke(cmd)
477+
478+
assert result.exit_code == 0, "Expected command to succeed."

0 commit comments

Comments
 (0)