Skip to content

Commit a6c6d8c

Browse files
authored
Merge pull request #240 from planetlabs/v2-orders-217-async
Move v2 orders client over to async
2 parents b48af70 + e476019 commit a6c6d8c

28 files changed

+2394
-1850
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
language: python
22
python:
3-
- "3.6"
43
- "3.7"
54
- "3.8"
5+
- "3.9"
66
cache:
77
directories:
88
- $HOME/.cache/pip

README.md

+139-30
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![Build Status](https://travis-ci.org/planetlabs/planet-client-python.svg?branch=master)](https://travis-ci.org/planetlabs/planet-client-python)
44

5-
Python client library and CLI for Planet's public APIs.
5+
Python client library for Planet's APIs.
66

77
The client provides access to the following Planet APIs:
88
* [analytics](https://developers.planet.com/docs/analytics/)
@@ -14,7 +14,7 @@ The client provides access to the following Planet APIs:
1414

1515
### Prerequisites
1616

17-
* Python version 3.6+
17+
* Python version 3.7+
1818

1919
### Install package
2020

@@ -28,49 +28,158 @@ flag is highly recommended for those new to [pip](https://pip.pypa.io).
2828
A PEX executable (Windows not supported) and source releases are
2929
[here](https://github.com/planetlabs/planet-client-python/releases/latest).
3030

31-
## Documentation
31+
## Authentication
3232

33-
Online documentation:
34-
https://planetlabs.github.io/planet-client-python/index.html
33+
Planet's APIs require an account for use.
34+
[Sign up here](https://www.planet.com/explorer/?signup).
3535

36-
Documentation is also provided for download
37-
[here](https://github.com/planetlabs/planet-client-python/releases/latest).
3836

37+
## Quick Start
3938

40-
## Development
39+
The client modules within the Python library are asynchronous, which greatly
40+
speeds up many interactions with Planet's APIs. Support for asynchronous
41+
development is native to Python 3.6+ via the
42+
[`asyncio` module](https://docs.python.org/3/library/asyncio.html). A great
43+
resource for getting started with asynchronous programming in Python is
44+
https://project-awesome.org/timofurrer/awesome-asyncio. The Writings and Talks
45+
sections are particularly helpful in getting oriented.
4146

42-
To contribute or develop with this library, see
43-
[CONTRIBUTING](https://github.com/planetlabs/planet-client-python/CONTRIBUTING.md)
47+
```python
48+
import asyncio
49+
import os
4450

51+
import planet
4552

46-
## API Key
53+
API_KEY = os.getenv('PL_API_KEY')
4754

48-
The API requires an account for use. [Signup here](https://www.planet.com/explorer/?signup).
55+
image_ids = ['3949357_1454705_2020-12-01_241c']
56+
order_details = planet.OrderDetails(
57+
'test_order',
58+
[planet.Product(image_ids, 'analytic', 'psorthotile')]
59+
)
4960

50-
This can be provided via the environment variable `PL_API_KEY` or the flag `-k` or `--api-key`.
61+
async def create_order(order_details):
62+
async with planet.Session(auth=(API_KEY, '')) as ps:
63+
client = planet.OrdersClient(ps)
64+
return await client.create_order(order_details)
5165

52-
Using `planet init` your account credentials (login/password) can be used to obtain the api key.
66+
oid = asyncio.run(create_order(order_details))
67+
print(oid)
68+
```
5369

70+
Not into async? No problem. Just wrap the library and async operations together
71+
and call from your synchronous code.
5472

55-
# Example CLI Usage
73+
```python
74+
def sync_create_order(order_details):
75+
return asyncio.run(create_order(order_details))
5676

57-
**Hint:** autocompletion can be enabled in some shells using:
58-
```console
59-
$ eval "$(_PLANET_COMPLETE=source planet)"
77+
oid = sync_create_order(order_details)
78+
print(oid)
6079
```
6180

62-
Basics and help:
63-
64-
```console
65-
$ planet --help
81+
When using `asyncio.run` to develop synchronous code with the async library,
82+
keep in mind this excerpt from the
83+
[asyncio.run](https://docs.python.org/3/library/asyncio-task.html#asyncio.run)
84+
documentation:
85+
86+
"*This function always creates a new event loop and closes it at the end. It
87+
should be used as a main entry point for asyncio programs, and should ideally
88+
only be called once.*"
89+
90+
Do you have a use case where native synchronous support is essential? If so,
91+
please contribute to
92+
[Determine need for synchronous support](https://github.com/planetlabs/planet-client-python/issues/251)
93+
94+
95+
Why async? Because things get *really cool* when you want to work with multiple
96+
orders. Here's an example of submitting two orders, waiting for them to
97+
complete, and downloading them. The orders each clip a set of images to a
98+
specific area of interest (AOI), so they cannot be combined into one order.
99+
(hint: [Planet Explorer](https://www.planet.com/explorer/) was used to define
100+
the AOIs and get the image ids.)
101+
102+
103+
```python
104+
import asyncio
105+
import os
106+
107+
import planet
108+
109+
API_KEY = os.getenv('PL_API_KEY')
110+
111+
iowa_aoi = {
112+
"type": "Polygon",
113+
"coordinates": [[
114+
[-91.198465, 42.893071],
115+
[-91.121931, 42.893071],
116+
[-91.121931, 42.946205],
117+
[-91.198465, 42.946205],
118+
[-91.198465, 42.893071]]]
119+
}
120+
121+
iowa_images = [
122+
'20200925_161029_69_2223',
123+
'20200925_161027_48_2223'
124+
]
125+
iowa_order = planet.OrderDetails(
126+
'iowa_order',
127+
[planet.Product(iowa_images, 'analytic', 'PSScene4Band')],
128+
tools=[planet.Tool('clip', {'aoi': iowa_aoi})]
129+
)
130+
131+
oregon_aoi = {
132+
"type": "Polygon",
133+
"coordinates": [[
134+
[-117.558734, 45.229745],
135+
[-117.452447, 45.229745],
136+
[-117.452447, 45.301865],
137+
[-117.558734, 45.301865],
138+
[-117.558734, 45.229745]]]
139+
}
140+
141+
oregon_images = [
142+
'20200909_182525_1014',
143+
'20200909_182524_1014'
144+
]
145+
oregon_order = planet.OrderDetails(
146+
'oregon_order',
147+
[planet.Product(oregon_images, 'analytic', 'PSScene4Band')],
148+
tools=[planet.Tool('clip', {'aoi': oregon_aoi})]
149+
)
150+
151+
152+
async def create_and_download(order_detail, client):
153+
oid = await client.create_order(order_detail)
154+
print(oid)
155+
state = await client.poll(oid, verbose=True)
156+
print(state)
157+
filenames = await client.download_order(oid, progress_bar=True)
158+
print(f'downloaded {oid}, {len(filenames)} files downloaded.')
159+
160+
161+
async def main():
162+
async with planet.Session(auth=(API_KEY, '')) as ps:
163+
client = planet.OrdersClient(ps)
164+
await asyncio.gather(
165+
create_and_download(iowa_order, client),
166+
create_and_download(oregon_order, client)
167+
)
168+
169+
asyncio.run(main())
66170
```
171+
[Example output](example_output.md)
67172

68-
Specific API client usage:
69-
```console
70-
$ planet data
71-
```
72173

73-
Specific command help:
74-
```console
75-
$ planet data download --help
76-
```
174+
## Documentation
175+
176+
Online documentation:
177+
https://planetlabs.github.io/planet-client-python/index.html
178+
179+
Documentation is also provided for download
180+
[here](https://github.com/planetlabs/planet-client-python/releases/latest).
181+
182+
## Development
183+
184+
To contribute or develop with this library, see
185+
[CONTRIBUTING](https://github.com/planetlabs/planet-client-python/CONTRIBUTING.md)

example_output.md

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
```
2+
a27c63c9-a076-4db2-a2e3-c1ff35655cbd
3+
5d5892b5-3ec0-4df7-9852-a27a40baf0c1
4+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: queued
5+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: queued
6+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
7+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
8+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
9+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
10+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
11+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
12+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
13+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
14+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
15+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
16+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
17+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
18+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
19+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
20+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
21+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
22+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
23+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
24+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
25+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
26+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
27+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
28+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
29+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
30+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
31+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
32+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
33+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
34+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
35+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
36+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
37+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
38+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: running
39+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
40+
order a27c63c9-a076-4db2-a2e3-c1ff35655cbd state: success
41+
success
42+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: running
43+
./20200909_182525_1014_3B_AnalyticMS_clip.tif: 100%|███████████████████████████████████████████████████████████████████████████████████| 35.8k/35.8k [00:03<00:00, 9.97MB/s]
44+
./20200909_182525_1014_metadata.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████| 0.00k/0.00k [00:00<00:00, 4.08MB/s]
45+
./20200909_182525_1014_3B_AnalyticMS_metadata_clip.xml: 100%|██████████████████████████████████████████████████████████████████████████| 0.01k/0.01k [00:00<00:00, 7.12MB/s]
46+
./20200909_182525_1014_3B_AnalyticMS_DN_udm_clip.tif: 100%|████████████████████████████████████████████████████████████████████████████| 0.06k/0.06k [00:00<00:00, 1.81MB/s]
47+
./20200909_182524_1014_3B_AnalyticMS_clip.tif: 100%|███████████████████████████████████████████████████████████████████████████████████| 33.6k/33.6k [00:02<00:00, 12.2MB/s]
48+
./20200909_182524_1014_3B_AnalyticMS_DN_udm_clip.tif: 100%|████████████████████████████████████████████████████████████████████████████| 0.08k/0.08k [00:00<00:00, 1.78MB/s]
49+
order 5d5892b5-3ec0-4df7-9852-a27a40baf0c1 state: success
50+
success
51+
./20200909_182524_1014_3B_AnalyticMS_metadata_clip.xml: 100%|██████████████████████████████████████████████████████████████████████████| 0.01k/0.01k [00:00<00:00, 9.77MB/s]
52+
./20200909_182524_1014_metadata.json: 100%|████████████████████████████████████████████████████████████████████████████████████████████| 0.00k/0.00k [00:00<00:00, 3.12MB/s]
53+
./manifest.json: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 0.00k/0.00k [00:00<00:00, 8.29MB/s]
54+
downloaded a27c63c9-a076-4db2-a2e3-c1ff35655cbd, 9 files downloaded.
55+
./20200925_161029_69_2223_3B_AnalyticMS_metadata_clip.xml: 100%|███████████████████████████████████████████████████████████████████████| 0.01k/0.01k [00:00<00:00, 8.93MB/s]
56+
./20200925_161029_69_2223_3B_AnalyticMS_clip.tif: 100%|████████████████████████████████████████████████████████████████████████████████| 21.3k/21.3k [00:01<00:00, 12.0MB/s]
57+
./20200925_161029_69_2223_3B_AnalyticMS_DN_udm_clip.tif: 100%|█████████████████████████████████████████████████████████████████████████| 0.07k/0.07k [00:00<00:00, 1.99MB/s]
58+
./20200925_161029_69_2223_metadata.json: 100%|█████████████████████████████████████████████████████████████████████████████████████████| 0.00k/0.00k [00:00<00:00, 1.78MB/s]
59+
./20200925_161027_48_2223_metadata.json: 100%|█████████████████████████████████████████████████████████████████████████████████████████| 0.00k/0.00k [00:00<00:00, 2.24MB/s]
60+
./20200925_161027_48_2223_3B_AnalyticMS_clip.tif: 100%|████████████████████████████████████████████████████████████████████████████████| 33.9k/33.9k [00:02<00:00, 11.9MB/s]
61+
./20200925_161027_48_2223_3B_AnalyticMS_DN_udm_clip.tif: 100%|█████████████████████████████████████████████████████████████████████████| 0.08k/0.08k [00:00<00:00, 1.85MB/s]
62+
./20200925_161027_48_2223_3B_AnalyticMS_metadata_clip.xml: 100%|███████████████████████████████████████████████████████████████████████| 0.01k/0.01k [00:00<00:00, 11.7MB/s]
63+
./manifest.json: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 0.00k/0.00k [00:00<00:00, 8.52MB/s]
64+
downloaded 5d5892b5-3ec0-4df7-9852-a27a40baf0c1, 9 files downloaded.
65+
```
66+

planet/__init__.py

+23
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,26 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
from .api.http import Session
15+
from .api.models import Order
16+
from .api.orders import OrdersClient
17+
from .api.order_details import (
18+
OrderDetails, Product, Notifications, Delivery, AmazonS3Delivery,
19+
AzureBlobStorageDelivery, GoogleCloudStorageDelivery,
20+
GoogleEarthEngineDelivery, Tool)
21+
from .api.__version__ import __version__ # NOQA
22+
23+
__all__ = [
24+
Session,
25+
OrdersClient,
26+
Order,
27+
OrderDetails,
28+
Product,
29+
Notifications,
30+
Delivery,
31+
AmazonS3Delivery,
32+
AzureBlobStorageDelivery,
33+
GoogleCloudStorageDelivery,
34+
GoogleEarthEngineDelivery,
35+
Tool
36+
]

planet/api/__init__.py

-7
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,3 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
15-
from .orders import OrdersClient
16-
from .__version__ import __version__ # NOQA
17-
18-
__all__ = [
19-
OrdersClient
20-
]

planet/api/auth.py

-58
This file was deleted.

0 commit comments

Comments
 (0)