14
14
"""The Planet Data CLI."""
15
15
from typing import List , Optional
16
16
from contextlib import asynccontextmanager
17
+ from pathlib import Path
17
18
18
19
import click
19
20
21
+ from planet .reporting import StateBar
20
22
from planet import data_filter , DataClient , exceptions
21
- from planet .clients .data import (LIST_SEARCH_TYPE ,
23
+ from planet .clients .data import (SEARCH_SORT ,
24
+ LIST_SEARCH_TYPE ,
22
25
LIST_SEARCH_TYPE_DEFAULT ,
23
26
LIST_SORT_ORDER ,
24
27
LIST_SORT_DEFAULT ,
25
- SEARCH_SORT ,
26
28
SEARCH_SORT_DEFAULT ,
27
29
STATS_INTERVAL )
30
+
28
31
from planet .specs import (get_item_types ,
29
32
validate_item_type ,
30
33
SpecificationException )
@@ -68,8 +71,8 @@ def assets_to_filter(ctx, param, assets: List[str]) -> Optional[dict]:
68
71
69
72
70
73
def check_item_types (ctx , param , item_types ) -> Optional [List [dict ]]:
71
- '''Validates the item type by comparing the inputted item type to all
72
- supported item types.'''
74
+ '''Validates each item types provided by comparing them to all supported
75
+ item types.'''
73
76
try :
74
77
for item_type in item_types :
75
78
validate_item_type (item_type )
@@ -78,6 +81,17 @@ def check_item_types(ctx, param, item_types) -> Optional[List[dict]]:
78
81
raise click .BadParameter (str (e ))
79
82
80
83
84
+ def check_item_type (ctx , param , item_type ) -> Optional [List [dict ]]:
85
+ '''Validates the item type provided by comparing it to all supported
86
+ item types.'''
87
+ try :
88
+ validate_item_type (item_type )
89
+ except SpecificationException as e :
90
+ raise click .BadParameter (str (e ))
91
+
92
+ return item_type
93
+
94
+
81
95
def check_search_id (ctx , param , search_id ) -> str :
82
96
'''Ensure search id is a valix hex string'''
83
97
try :
@@ -480,8 +494,128 @@ async def search_update(ctx,
480
494
echo_json (items , pretty )
481
495
482
496
497
+ @data .command ()
498
+ @click .pass_context
499
+ @translate_exceptions
500
+ @coro
501
+ @click .argument ("item_type" , type = str , callback = check_item_type )
502
+ @click .argument ("item_id" )
503
+ @click .argument ("asset_type" )
504
+ @click .option ('--directory' ,
505
+ default = '.' ,
506
+ help = ('Base directory for file download.' ),
507
+ type = click .Path (exists = True ,
508
+ resolve_path = True ,
509
+ writable = True ,
510
+ file_okay = False ))
511
+ @click .option ('--filename' ,
512
+ default = None ,
513
+ help = ('Custom name to assign to downloaded file.' ),
514
+ type = str )
515
+ @click .option ('--overwrite' ,
516
+ is_flag = True ,
517
+ default = False ,
518
+ help = ('Overwrite files if they already exist.' ))
519
+ @click .option ('--checksum' ,
520
+ is_flag = True ,
521
+ default = None ,
522
+ help = ('Verify that checksums match.' ))
523
+ async def asset_download (ctx ,
524
+ item_type ,
525
+ item_id ,
526
+ asset_type ,
527
+ directory ,
528
+ filename ,
529
+ overwrite ,
530
+ checksum ):
531
+ """Download an activated asset.
532
+
533
+ This function will fail if the asset state is not activated. Consider
534
+ calling `asset-wait` before this command to ensure the asset is activated.
535
+
536
+ If --checksum is provided, the associated checksums given in the manifest
537
+ are compared against the downloaded files to verify that they match.
538
+
539
+ If --checksum is provided, files are already downloaded, and --overwrite is
540
+ not specified, this will simply validate the checksums of the files against
541
+ the manifest.
542
+
543
+ Output:
544
+ The full path of the downloaded file. If the quiet flag is not set, this
545
+ also provides ANSI download status reporting.
546
+ """
547
+ quiet = ctx .obj ['QUIET' ]
548
+ async with data_client (ctx ) as cl :
549
+ asset = await cl .get_asset (item_type , item_id , asset_type )
550
+ path = await cl .download_asset (asset = asset ,
551
+ filename = filename ,
552
+ directory = Path (directory ),
553
+ overwrite = overwrite ,
554
+ progress_bar = not quiet )
555
+ if checksum :
556
+ cl .validate_checksum (asset , path )
557
+
558
+
559
+ @data .command ()
560
+ @click .pass_context
561
+ @translate_exceptions
562
+ @coro
563
+ @click .argument ("item_type" , type = str , callback = check_item_type )
564
+ @click .argument ("item_id" )
565
+ @click .argument ("asset_type" )
566
+ async def asset_activate (ctx , item_type , item_id , asset_type ):
567
+ '''Activate an asset.'''
568
+ async with data_client (ctx ) as cl :
569
+ asset = await cl .get_asset (item_type , item_id , asset_type )
570
+ await cl .activate_asset (asset )
571
+
572
+
573
+ @data .command ()
574
+ @click .pass_context
575
+ @translate_exceptions
576
+ @coro
577
+ @click .argument ("item_type" , type = str , callback = check_item_type )
578
+ @click .argument ("item_id" )
579
+ @click .argument ("asset_type" )
580
+ @click .option ('--delay' ,
581
+ type = int ,
582
+ default = 5 ,
583
+ help = 'Time (in seconds) between polls.' )
584
+ @click .option ('--max-attempts' ,
585
+ type = int ,
586
+ default = 200 ,
587
+ show_default = True ,
588
+ help = 'Maximum number of polls. Set to zero for no limit.' )
589
+ async def asset_wait (ctx , item_type , item_id , asset_type , delay , max_attempts ):
590
+ '''Wait for an asset to be activated.
591
+
592
+ Returns when the asset state has reached "activated" and the asset is
593
+ available.
594
+ '''
595
+ quiet = ctx .obj ['QUIET' ]
596
+ async with data_client (ctx ) as cl :
597
+ asset = await cl .get_asset (item_type , item_id , asset_type )
598
+ with StateBar (order_id = "my asset" , disable = quiet ) as bar :
599
+ state = await cl .wait_asset (asset ,
600
+ delay ,
601
+ max_attempts ,
602
+ callback = bar .update_state )
603
+ click .echo (state )
604
+
605
+
606
+ # @data.command()
607
+ # @click.pass_context
608
+ # @translate_exceptions
609
+ # @coro
610
+ # @click.argument("item_type")
611
+ # @click.argument("item_id")
612
+ # @click.argument("asset_type_id")
613
+ # @pretty
614
+ # async def asset_get(ctx, item_type, item_id, asset_type_id, pretty):
615
+ # '''Get an item asset.'''
616
+ # async with data_client(ctx) as cl:
617
+ # asset = await cl.get_asset(item_type, item_id, asset_type_id)
618
+ # echo_json(asset, pretty)
619
+
483
620
# TODO: search_run()".
484
621
# TODO: item_get()".
485
- # TODO: asset_activate()".
486
- # TODO: asset_wait()".
487
- # TODO: asset_download()".
0 commit comments