Skip to content

v2: add cli for orders api #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Jul 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
24bb853
initialize cli
jreiberkyle May 12, 2021
5701a24
add auth initalization and reporting
jreiberkyle May 13, 2021
ad4c5b6
add `planet orders list` to cli, remove unused options
jreiberkyle May 13, 2021
48eb715
initialize cli
jreiberkyle May 12, 2021
774f667
add auth initalization and reporting
jreiberkyle May 13, 2021
b69a180
add `planet orders list` to cli, remove unused options
jreiberkyle May 13, 2021
366ca26
implement `planet orders get` and `planet orders cancel` and pretty j…
jreiberkyle May 14, 2021
dbab81b
implement planet orderes download, refactor for reuse
jreiberkyle May 19, 2021
94413bc
fix merge conflicts
jreiberkyle May 19, 2021
b22537e
more merge cleanup
jreiberkyle May 19, 2021
19226d4
test cli auth
jreiberkyle May 26, 2021
f34900c
test ordersclient.list_orders asjson parameter
jreiberkyle May 27, 2021
cb70046
test cli `planet orders list`
jreiberkyle May 27, 2021
7b245ad
improved auth exception messaging, handle cli api exceptions
jreiberkyle May 28, 2021
15ed6a3
test remaining cli `planet orders` commands
jreiberkyle May 28, 2021
7edf88a
fix auth from file exception management
jreiberkyle May 28, 2021
df91003
add polling to cli download
jreiberkyle May 28, 2021
afc34d4
Delivery.from_dict creates a subclass aka AmazonsS3Delivery if inform…
jreiberkyle Jun 2, 2021
2908d42
make specs argument validation failure message look like click BadPar…
jreiberkyle Jun 2, 2021
94ff59e
implement cli planet orders create all args except tools
jreiberkyle Jun 8, 2021
05a0f7d
move geojson processing to geojson module
jreiberkyle Jun 8, 2021
ed1a24b
implement tools arg for planet orders create
jreiberkyle Jun 9, 2021
a529473
add geojson handling module
jreiberkyle Jun 9, 2021
521779e
orders.create_order now returns an Order instead of id, cli planet cr…
jreiberkyle Jun 9, 2021
a091d39
pin mkdocs to avoid build issue with 1.2.1
jreiberkyle Jun 9, 2021
7227663
add cli reference and usage details to docs
jreiberkyle Jun 9, 2021
75dffd9
Merge branch 'v2' into v2-cli-244
jreiberkyle Jun 9, 2021
c0a0fba
remove unused Delivery.from_file
jreiberkyle Jun 9, 2021
cb7aa8b
click echo proper json, fix create orders item-type and bundle parsing
jreiberkyle Jun 9, 2021
a9028a2
fix lint
jreiberkyle Jun 10, 2021
398be11
improved APIException message handling
jreiberkyle Jun 10, 2021
2d4f875
fall back to using the response text as the exception message if pars…
jreiberkyle Jun 16, 2021
dd3b63d
add reference for cli to docs
jreiberkyle Jun 16, 2021
67620c1
simplify geojson.Geometry by extending dict
jreiberkyle Jun 17, 2021
ad7c194
minor fix to cli args
jreiberkyle Jun 17, 2021
5688558
change geojson module from classes to functions
jreiberkyle Jun 17, 2021
6aac6b8
cleanup, log warning instead of raising warning
jreiberkyle Jun 18, 2021
10556e2
raise exception if attempting to get geometry from featureclass with …
jreiberkyle Jul 15, 2021
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
9 changes: 9 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# CLI Reference

This page provides documentation for our command line tools.

::: mkdocs-click
:module: planet.scripts.cli
:command: cli
:prog_name: planet
:depth: 1
128 changes: 124 additions & 4 deletions docs/guide.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# User Guide

## Session
## API
### Session

Communication with the Planet services is provided with the `Session` class.
The recommended way to use a `Session` is as a context manager. This will
Expand Down Expand Up @@ -32,7 +33,7 @@ Alternatively, use `await Session.aclose()` to close a `Session` explicitly:

```

## Authentication
### Authentication

There are two steps to managing authentication information, obtaining the
authentication information from Planet and then managing it for local retrieval
Expand Down Expand Up @@ -87,7 +88,7 @@ environment variable:

```

## Orders Client
### Orders Client

The Orders Client mostly mirrors the
[Orders API](https://developers.planet.com/docs/orders/reference/#tag/Orders),
Expand All @@ -106,7 +107,7 @@ order is completed and to download an entire order.

```

### Creating an Order
#### Creating an Order

When creating an order, the order details must be provided to the API. There
are two ways to specify the order details, a `JSON` blob and an `OrderDetails`
Expand Down Expand Up @@ -154,3 +155,122 @@ the context of a `Session` with the `OrdersClient`:
>>> asyncio.run(main())

```

## CLI

### Authentication

The `auth` command allows the CLI to authenticate with Planet servers. Before
any other command is run, the CLI authentication should be initiated with

```console
$ planet auth init
```

To store the authentication information in an environment variable, e.g.
for passing into a Docker instance:

```console
$ export PL_API_KEY=$(planet auth value)
```

### Orders API

Most `orders` cli commands are simple wrappers around the
[Planet Orders API](https://developers.planet.com/docs/orders/reference/#tag/Orders)
commands.


#### Create Order File Inputs

Creating an order supports JSON files as inputs and these need to follow certain
formats.


##### --cloudconfig
The file given with the `--cloudconfig` option should contain JSON that follows
the options and format given in
[Delivery to Cloud Storage](https://developers.planet.com/docs/orders/delivery/#delivery-to-cloud-storage).

An example would be:

Example: `cloudconfig.json`
```
{
"amazon_s3": {
"aws_access_key_id": "aws_access_key_id",
"aws_secret_access_key": "aws_secret_access_key",
"bucket": "bucket",
"aws_region": "aws_region"
},
"archive_type": "zip"
}
```

##### --clip
The file given with the `--clip` option should contain valid [GeoJSON](https://geojson.org/).
It can be a Polygon geometry, a Feature, or a FeatureClass. If it is a FeatureClass,
only the first Feature is used for the clip geometry.

Example: `aoi.geojson`
```
{
"type": "Polygon",
"coordinates": [
[
[
37.791595458984375,
14.84923123791421
],
[
37.90214538574219,
14.84923123791421
],
[
37.90214538574219,
14.945448293647944
],
[
37.791595458984375,
14.945448293647944
],
[
37.791595458984375,
14.84923123791421
]
]
]
}
```

##### --tools
The file given with the `--tools` option should contain JSON that follows the
format for a toolchain, the "tools" section of an order. The toolchain options
and format are given in
[Creating Toolchains](https://developers.planet.com/docs/orders/tools-toolchains/#creating-toolchains).

Example: `tools.json`
```
[
{
"toar": {
"scale_factor": 10000
}
},
{
"reproject": {
"projection": "WGS84",
"kernel": "cubic"
}
},
{
"tile": {
"tile_size": 1232,
"origin_x": -180,
"origin_y": -90,
"pixel_size": 2.7056277056e-05,
"name_template": "C1232_30_30_{tilex:04d}_{tiley:04d}"
}
}
```

2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ nav:
- User Guide: 'guide.md'
- Upgrading: 'upgrading.md'
- API Reference: 'api.md'
- CLI Reference: 'cli.md'

markdown_extensions:
- pymdownx.highlight
- pymdownx.superfences
- mkdocs-click

5 changes: 3 additions & 2 deletions planet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .api.order_details import (
OrderDetails, Product, Notifications, Delivery, AmazonS3Delivery,
AzureBlobStorageDelivery, GoogleCloudStorageDelivery,
GoogleEarthEngineDelivery, Tool)
GoogleEarthEngineDelivery, Tool, ClipTool)
from .api.__version__ import __version__ # NOQA
from .auth import Auth

Expand All @@ -34,6 +34,7 @@
AzureBlobStorageDelivery,
GoogleCloudStorageDelivery,
GoogleEarthEngineDelivery,
ClipTool,
Tool,
Auth
Auth,
]
52 changes: 46 additions & 6 deletions planet/api/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def _log_response(response):
f'{request.method} {request.url} - '
f'Status {response.status_code}')

@staticmethod
def _raise_for_status(response):
@classmethod
def _raise_for_status(cls, response):
# TODO: consider using http_response.reason_phrase
status = response.status_code

Expand All @@ -69,17 +69,48 @@ def _raise_for_status(response):
HTTPStatus.INTERNAL_SERVER_ERROR: exceptions.ServerError
}.get(status, None)

msg = response.text
LOGGER.debug(f"Exception type: {exception}")
LOGGER.debug(f"Response text: {response.text}")

if exception == exceptions.TooManyRequests:
# differentiate between over quota and rate-limiting
if 'quota' in response.text.lower():
exception = exceptions.OverQuota

# differentiate between over quota and rate-limiting
if status == 429 and 'quota' in msg.lower():
exception = exceptions.OverQuota
try:
msg = cls._parse_message(response)
except Exception:
msg = response.text

if exception:
raise exception(msg)

raise exceptions.APIException(f'{status}: {msg}')

@staticmethod
def _parse_message(response):
msg = response.json()
LOGGER.debug(f'Raw response message: {msg}')

try:
msg = msg['message']
except KeyError:
try:
new_msg = msg['general'][0]['message']
try:
msg_field = msg['field']
key = list(msg_field.keys())[0]
LOGGER.debug(f'key: {key}')
new_msg = (new_msg + ' - ' + msg_field[key][0]['message'])
except Exception:
pass
msg = new_msg
except Exception:
pass

LOGGER.debug(f'Processed response message: {msg}')
return msg


class Session(BaseSession):
'''Context manager for asynchronous communication with the Planet service.
Expand Down Expand Up @@ -244,6 +275,15 @@ def request(self, request):
http_resp = self._client.send(request.http_request)
return models.Response(request, http_resp)

@classmethod
def _raise_for_status(cls, response):
try:
super()._raise_for_status(response)
except exceptions.BadQuery:
raise exceptions.APIException('Not a valid email address.')
except exceptions.InvalidAPIKey:
raise exceptions.APIException('Incorrect email or password.')


class Stream():
'''Context manager for asynchronous response stream from Planet server.'''
Expand Down
4 changes: 4 additions & 0 deletions planet/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ def id(self):
'''
return self.data['id']

@property
def json(self):
return self.data


class Orders(Paged):
'''Asynchronous iterator over Orders from a paged response describing
Expand Down
Loading