Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d71eb89
Added set for the new registered command.
kevinlacaille Feb 28, 2023
0347cbc
Added a todo for the new callback function.
kevinlacaille Feb 28, 2023
3700ed6
Added a skelleton to a needed callback function, along with the outli…
kevinlacaille Feb 28, 2023
03998a8
Added commands: asset-download, get, activate, wait
kevinlacaille Mar 1, 2023
fd1077d
A working test for download.
kevinlacaille Mar 1, 2023
9200fcf
Removed commented out examples.
kevinlacaille Mar 1, 2023
cfcadbd
tests for activate and wait
kevinlacaille Mar 1, 2023
19a45a0
Docstrings.
kevinlacaille Mar 1, 2023
1bacfea
linting
kevinlacaille Mar 1, 2023
0dddfb2
test for asset-get
kevinlacaille Mar 1, 2023
23264d1
Removed commented out function.
kevinlacaille Mar 1, 2023
a246c06
Removed unused tests.
kevinlacaille Mar 1, 2023
7a087ce
removed plural item types.
kevinlacaille Mar 2, 2023
48ab53c
took echo out of context of data_client
kevinlacaille Mar 2, 2023
002b6d5
upgraded readability of CLI test
kevinlacaille Mar 2, 2023
f7362af
updated asset-download to follow the useage docs, commented out asset…
kevinlacaille Mar 2, 2023
da9c14a
updated asset-download test, commented out asset-get test
kevinlacaille Mar 2, 2023
3dd0ef7
Added callback function to item type in download call
kevinlacaille Mar 2, 2023
3970e1e
write bytes to tif, not text
kevinlacaille Mar 2, 2023
f106489
ensured asset-wait and -activate followed the docs.
kevinlacaille Mar 2, 2023
0b3a24d
More elegant version of removing item type from list.
kevinlacaille Mar 2, 2023
689517f
Added asset-get response to wait and activate
kevinlacaille Mar 2, 2023
8aa9be5
moved asset-get response into a fixture
kevinlacaille Mar 2, 2023
60057a0
linting
kevinlacaille Mar 2, 2023
b853a2f
Merge branch 'main' into data-asset-download-507
kevinlacaille Mar 2, 2023
9d1739c
fixed merge conflict linting issues
kevinlacaille Mar 2, 2023
c995a8c
added back decorator to a fixture, whoopsie
kevinlacaille Mar 2, 2023
6da207d
Added data asset commands to docs.
kevinlacaille Mar 2, 2023
f01a519
Added new test for check_item_type, renamed tests for check_item_types
kevinlacaille Mar 3, 2023
5d95584
Added new callback function to validate a single time type and edited…
kevinlacaille Mar 3, 2023
cf13ee9
Added BadParameter if more than 1 item type was provided.
kevinlacaille Mar 3, 2023
5574096
Added test if more than 1 item type was provided.
kevinlacaille Mar 3, 2023
faf07f5
move return outside of try/except block
kevinlacaille Mar 4, 2023
c753e9e
remove badparameter for more than 1 item type
kevinlacaille Mar 4, 2023
ee268a7
asset_type_id -> asset_type
kevinlacaille Mar 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/cli/cli-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,25 @@ that are of standard (aka not test) quality. Therefore, these filters can be eas
planet data filter --permission --std-quality --asset ortho_analytic_8b_sr | planet data search PSScene --filter -
```

## `data asset` command basics

To activate an asset for download three commands must be queried, in sequence:
1. `asset-activate` - activate an asset
2. `asset-wait` - wait for an asset to be activated
3. `asset-download` - download an activated asset

For example, if we want to download a `basic_udm2` asset from item ID
`20221003_002705_38_2461`, a `PSScene` item type:

```
planet data asset-activate PSScene 20221003_002705_38_2461 basic_udm2 && \
planet data asset-wait PSScene 20221003_002705_38_2461 basic_udm2 && \
planet data asset-download PSScene 20221003_002705_38_2461 basic_udm2 --directory /path/to/data/
00:00 - order my asset - state: active
{'_links': {'_self': 'https://api.planet.com/data/v1/assets/eyJpIjogIjIwMjIxMDAzXzAwMjcwNV8zOF8yNDYxIiwgImMiOiAiUFNTY2VuZSIsICJ0IjogImJhc2ljX3VkbTIiLCAiY3QiOiAiaXRlbS10eXBlIn0', 'activate': 'https://api.planet.com/data/v1/assets/eyJpIjogIjIwMjIxMDAzXzAwMjcwNV8zOF8yNDYxIiwgImMiOiAiUFNTY2VuZSIsICJ0IjogImJhc2ljX3VkbTIiLCAiY3QiOiAiaXRlbS10eXBlIn0/activate', 'type': 'https://api.planet.com/data/v1/asset-types/basic_udm2'}, '_permissions': ['download'], 'expires_at': '2023-03-02T19:30:48.942718', 'location': 'https://api.planet.com/data/v1/download?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJQYWtGNHZuUEs3WXRmSFNGUklHY2I3YTNXT3piaTlaam4zWUpZMmxnd0x5cVlFMVBRSHU5QXNCcjR5Q3FxSjBNbl9yN3VwVEFQYUI1ZzhYNUJmcDhmUT09IiwiZXhwIjoxNjc3Nzg1NDQ4LCJ0b2tlbl90eXBlIjoidHlwZWQtaXRlbSIsIml0ZW1fdHlwZV9pZCI6IlBTU2NlbmUiLCJpdGVtX2lkIjoiMjAyMjEwMDNfMDAyNzA1XzM4XzI0NjEiLCJhc3NldF90eXBlIjoiYmFzaWNfdWRtMiJ9.Dd0opDjW3bBS6qLLZoNiJkfBsO2n5Xz9pM5apEUz_K6viDPFexhJiy6bMbaySbby8W0YvuATdb1uYXS2FkweDg', 'md5_digest': '3a9f7dd1ce500f699d0a96afdd0e3aa2', 'status': 'active', 'type': 'basic_udm2'}
/path/to/data/20221003_002705_38_2461_1A_udm2.tif: 100%|██████████████████████████████████| 3.16k/3.16k [00:00<00:00, 32.0MB/s]
```

## Stats

TODO
148 changes: 141 additions & 7 deletions planet/cli/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@
"""The Planet Data CLI."""
from typing import List, Optional
from contextlib import asynccontextmanager
from pathlib import Path

import click

from planet.reporting import StateBar
from planet import data_filter, DataClient, exceptions
from planet.clients.data import (LIST_SEARCH_TYPE,
from planet.clients.data import (SEARCH_SORT,
LIST_SEARCH_TYPE,
LIST_SEARCH_TYPE_DEFAULT,
LIST_SORT_ORDER,
LIST_SORT_DEFAULT,
SEARCH_SORT,
SEARCH_SORT_DEFAULT,
STATS_INTERVAL)

from planet.specs import (get_item_types,
validate_item_type,
SpecificationException)
Expand Down Expand Up @@ -68,8 +71,8 @@ def assets_to_filter(ctx, param, assets: List[str]) -> Optional[dict]:


def check_item_types(ctx, param, item_types) -> Optional[List[dict]]:
'''Validates the item type by comparing the inputted item type to all
supported item types.'''
'''Validates each item types provided by comparing them to all supported
item types.'''
try:
for item_type in item_types:
validate_item_type(item_type)
Expand All @@ -78,6 +81,17 @@ def check_item_types(ctx, param, item_types) -> Optional[List[dict]]:
raise click.BadParameter(str(e))


def check_item_type(ctx, param, item_type) -> Optional[List[dict]]:
'''Validates the item type provided by comparing it to all supported
item types.'''
try:
validate_item_type(item_type)
except SpecificationException as e:
raise click.BadParameter(str(e))

return item_type


def check_search_id(ctx, param, search_id) -> str:
'''Ensure search id is a valix hex string'''
try:
Expand Down Expand Up @@ -480,8 +494,128 @@ async def search_update(ctx,
echo_json(items, pretty)


@data.command()
@click.pass_context
@translate_exceptions
@coro
@click.argument("item_type", type=str, callback=check_item_type)
@click.argument("item_id")
@click.argument("asset_type")
@click.option('--directory',
default='.',
help=('Base directory for file download.'),
type=click.Path(exists=True,
resolve_path=True,
writable=True,
file_okay=False))
@click.option('--filename',
default=None,
help=('Custom name to assign to downloaded file.'),
type=str)
@click.option('--overwrite',
is_flag=True,
default=False,
help=('Overwrite files if they already exist.'))
@click.option('--checksum',
is_flag=True,
default=None,
help=('Verify that checksums match.'))
async def asset_download(ctx,
item_type,
item_id,
asset_type,
directory,
filename,
overwrite,
checksum):
"""Download an activated asset.

This function will fail if the asset state is not activated. Consider
calling `asset-wait` before this command to ensure the asset is activated.

If --checksum is provided, the associated checksums given in the manifest
are compared against the downloaded files to verify that they match.

If --checksum is provided, files are already downloaded, and --overwrite is
not specified, this will simply validate the checksums of the files against
the manifest.

Output:
The full path of the downloaded file. If the quiet flag is not set, this
also provides ANSI download status reporting.
"""
quiet = ctx.obj['QUIET']
async with data_client(ctx) as cl:
asset = await cl.get_asset(item_type, item_id, asset_type)
path = await cl.download_asset(asset=asset,
filename=filename,
directory=Path(directory),
overwrite=overwrite,
progress_bar=not quiet)
if checksum:
cl.validate_checksum(asset, path)


@data.command()
@click.pass_context
@translate_exceptions
@coro
@click.argument("item_type", type=str, callback=check_item_type)
@click.argument("item_id")
@click.argument("asset_type")
async def asset_activate(ctx, item_type, item_id, asset_type):
'''Activate an asset.'''
async with data_client(ctx) as cl:
asset = await cl.get_asset(item_type, item_id, asset_type)
await cl.activate_asset(asset)


@data.command()
@click.pass_context
@translate_exceptions
@coro
@click.argument("item_type", type=str, callback=check_item_type)
@click.argument("item_id")
@click.argument("asset_type")
@click.option('--delay',
type=int,
default=5,
help='Time (in seconds) between polls.')
@click.option('--max-attempts',
type=int,
default=200,
show_default=True,
help='Maximum number of polls. Set to zero for no limit.')
async def asset_wait(ctx, item_type, item_id, asset_type, delay, max_attempts):
'''Wait for an asset to be activated.

Returns when the asset state has reached "activated" and the asset is
available.
'''
quiet = ctx.obj['QUIET']
async with data_client(ctx) as cl:
asset = await cl.get_asset(item_type, item_id, asset_type)
with StateBar(order_id="my asset", disable=quiet) as bar:
state = await cl.wait_asset(asset,
delay,
max_attempts,
callback=bar.update_state)
click.echo(state)


# @data.command()
# @click.pass_context
# @translate_exceptions
# @coro
# @click.argument("item_type")
# @click.argument("item_id")
# @click.argument("asset_type_id")
# @pretty
# async def asset_get(ctx, item_type, item_id, asset_type_id, pretty):
# '''Get an item asset.'''
# async with data_client(ctx) as cl:
# asset = await cl.get_asset(item_type, item_id, asset_type_id)
# echo_json(asset, pretty)

# TODO: search_run()".
# TODO: item_get()".
# TODO: asset_activate()".
# TODO: asset_wait()".
# TODO: asset_download()".
Loading