Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 4 additions & 5 deletions docs/get-started/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ For more information about Session, refer to the [Python SDK User Guide](../../p

With the V1 client, all communication was synchronous. Asynchronous bulk support was provided with the `downloader` module. There was no built-in support for polling when an order was ready to download or tracking when an order was downloaded.

In V2, all `*Client` methods (for example, `DataClient().search_aiter`, `OrderClient().create_order`) are asynchronous. Any functions that call such methods must include `async` in their definition. To invoke asynchronous methods from synchronous code, you can wrap the async method calls in `asyncio.run()`. The following is an example of using async with session.
In V2, all `*Client` methods (for example, `DataClient().search`, `OrderClient().create_order`) are asynchronous. Any functions that call such methods must include `async` in their definition. To invoke asynchronous methods from synchronous code, you can wrap the async method calls in `asyncio.run()`. The following is an example of using async with session.

```python
import asyncio
Expand All @@ -49,8 +49,7 @@ async def do_search():
date_filter = filters.date_range_filter('acquired', gte=datetime.fromisoformat("2022-11-18"), lte=datetime.fromisoformat("2022-11-21"))
cloud_filter = filters.range_filter('cloud_cover', lte=0.1)
download_filter = filters.permission_filter()
search_results = await client.search(["PSScene"], filters.and_filter([date_filter, cloud_filter, download_filter]))
return [item async for item in search_results]
return [item async for item in client.search(["PSScene"], filters.and_filter([date_filter, cloud_filter, download_filter]))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was purpose of shoving these two lines into a one-liner? I tend to find these code compressions confusing to read in retrospect and more difficult to maintain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kevinlacaille you've got a valid point. The state of the art for usage is

async for item in client.search(...):
    # do stuff

And this can also be turned into a list comprehension like [item async for item in client.search(...)].

The code on line 52 could be made easier to read if the filter construction were lifted out, maybe? Like

search_filters = filters.and_filter([date_filter, cloud_filter, download_filter])
async for item in client.search(["PSScene"], search_filters):
    # do stuff

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This certainly isn't worth re-opening this ticket for, but I do agree what @sgillies wrote would be easier to read and maintain in the future 👍


items = asyncio.run(do_search())
```
Expand All @@ -74,8 +73,8 @@ planet.api.ClientV1().quick_search(filters.build_search_request(all_filters, ["P
Is now

```python
async with Session() as session:
items_aiter = planet.DataClient(session).search_aiter(["PSScene"], all_filters)
async with Session() as session:
items = [i async for i in planet.DataClient(session).search(["PSScene"], all_filters)]
```

## Orders API
Expand Down
7 changes: 3 additions & 4 deletions docs/python/sdk-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,7 @@ from planet import collect, OrdersClient, Session
async def main():
async with Session() as sess:
client = OrdersClient(sess)
orders_aiter = client.list_orders_aiter()
orders_list = collect(orders_aiter)
orders_list = collect(client.list_orders())

asyncio.run(main())

Expand All @@ -278,7 +277,7 @@ asyncio.run(main())
Alternatively, these results can be converted to a list directly with

```python
orders_list = [o async for o in client.list_orders_aiter()]
orders_list = [o async for o in client.list_orders()]
```

## Query the data catalog
Expand Down Expand Up @@ -341,7 +340,7 @@ the context of a `Session` with the `DataClient`:
async def main():
async with Session() as sess:
cl = DataClient(sess)
items = await cl.search(['PSScene'], sfilter)
items = [i async for i in cl.search(['PSScene'], sfilter)]

asyncio.run(main())
```
Expand Down
12 changes: 6 additions & 6 deletions planet/cli/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,12 @@ async def search(ctx, item_types, filter, limit, name, sort, pretty):
parameter will be applied to the stored quick search.
"""
async with data_client(ctx) as cl:
items_aiter = cl.search_aiter(item_types,
filter,
name=name,
sort=sort,
limit=limit)
async for item in items_aiter:

async for item in cl.search(item_types,
filter,
name=name,
sort=sort,
limit=limit):
echo_json(item, pretty)


Expand Down
3 changes: 1 addition & 2 deletions planet/cli/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ async def list(ctx, state, limit, pretty):
optionally pretty-printed.
'''
async with orders_client(ctx) as cl:
orders_aiter = cl.list_orders_aiter(state=state, limit=limit)
async for o in orders_aiter:
async for o in cl.list_orders(state=state, limit=limit):
echo_json(o, pretty)


Expand Down
11 changes: 4 additions & 7 deletions planet/cli/subscriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ async def list_subscriptions_cmd(ctx, status, limit, pretty):
"""Prints a sequence of JSON-encoded Subscription descriptions."""
async with CliSession(auth=ctx.obj['AUTH']) as session:
client = SubscriptionsClient(session)
subs_aiter = client.list_subscriptions_aiter(status=status,
limit=limit)
async for sub in subs_aiter:
async for sub in client.list_subscriptions(status=status, limit=limit):
echo_json(sub, pretty)


Expand Down Expand Up @@ -158,8 +156,7 @@ async def list_subscription_results_cmd(ctx,
"""Gets results of a subscription and prints the API response."""
async with CliSession(auth=ctx.obj['AUTH']) as session:
client = SubscriptionsClient(session)
results_aiter = client.get_results_aiter(subscription_id,
status=status,
limit=limit)
async for result in results_aiter:
async for result in client.get_results(subscription_id,
status=status,
limit=limit):
echo_json(result, pretty)
44 changes: 27 additions & 17 deletions planet/clients/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,23 @@ def _searches_url(self):
def _item_url(self, item_type, item_id):
return f'{self._base_url}/item-types/{item_type}/items/{item_id}'

async def search_aiter(self,
item_types: List[str],
search_filter: dict,
name: Optional[str] = None,
sort: Optional[str] = None,
limit: int = 100) -> AsyncIterator[dict]:
async def search(self,
item_types: List[str],
search_filter: dict,
name: Optional[str] = None,
sort: Optional[str] = None,
limit: int = 100) -> AsyncIterator[dict]:
"""Iterate over results from a quick search.

Quick searches are saved for a short period of time (~month). The
`name` parameter of the search defaults to the id of the generated
search id if `name` is not specified.

Note:
The name of this method is based on the API's method name. This
method provides iteration over results, it does not get a
single result description or return a list of descriptions.

Parameters:
item_types: The item types to include in the search.
search_filter: Structured search criteria.
Expand Down Expand Up @@ -224,16 +229,16 @@ async def update_search(self,
json=request)
return response.json()

async def list_searches_aiter(self,
sort: str = 'created desc',
search_type: str = 'any',
limit: int = 100) -> AsyncIterator[dict]:
async def list_searches(self,
sort: str = 'created desc',
search_type: str = 'any',
limit: int = 100) -> AsyncIterator[dict]:
"""Iterate through list of searches available to the user.

NOTE: the term 'saved' is overloaded here. We want to list saved
searches that are 'quick' or list saved searches that are 'saved'? Do
we want to introduce a new term, 'stored' that encompasses 'saved' and
'quick' searches?
Note:
The name of this method is based on the API's method name. This
method provides iteration over results, it does not get a
single result description or return a list of descriptions.

Parameters:
sort: Field and direction to order results by.
Expand Down Expand Up @@ -295,11 +300,16 @@ async def get_search(self, search_id: str) -> dict:
response = await self._session.request(method='GET', url=url)
return response.json()

async def run_search_aiter(self,
search_id: str,
limit: int = 100) -> AsyncIterator[dict]:
async def run_search(self,
search_id: str,
limit: int = 100) -> AsyncIterator[dict]:
"""Iterate over results from a saved search.

Note:
The name of this method is based on the API's method name. This
method provides iteration over results, it does not get a
single result description or return a list of descriptions.

Parameters:
search_id: Stored search identifier.
limit: Maximum number of results to return. When set to 0, no
Expand Down
15 changes: 10 additions & 5 deletions planet/clients/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,18 +463,23 @@ async def wait(self,

return current_state

async def list_orders_aiter(self,
state: Optional[str] = None,
limit: int = 100) -> AsyncIterator[dict]:
async def list_orders(self,
state: Optional[str] = None,
limit: int = 100) -> AsyncIterator[dict]:
"""Iterate over the list of stored order requests.

Note:
The name of this method is based on the API's method name. This
method provides iteration over results, it does not get a
single result description or return a list of descriptions.

Parameters:
state: Filter orders to given state.
limit: Maximum number of results to return. When set to 0, no
maximum is applied.

Returns:
Iterator over user orders that match the query
Yields:
Description of an order.

Raises:
planet.exceptions.APIError: On API error.
Expand Down
15 changes: 7 additions & 8 deletions planet/clients/subscriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ class SubscriptionsClient:
def __init__(self, session: Session) -> None:
self._session = session

async def list_subscriptions_aiter(
self,
status: Optional[Set[str]] = None,
limit: int = 100) -> AsyncIterator[dict]:
async def list_subscriptions(self,
status: Optional[Set[str]] = None,
limit: int = 100) -> AsyncIterator[dict]:
"""Iterate over list of account subscriptions with optional filtering.

Note:
Expand Down Expand Up @@ -193,10 +192,10 @@ async def get_subscription(self, subscription_id: str) -> dict:
sub = resp.json()
return sub

async def get_results_aiter(self,
subscription_id: str,
status: Optional[Set[str]] = None,
limit: int = 100) -> AsyncIterator[dict]:
async def get_results(self,
subscription_id: str,
status: Optional[Set[str]] = None,
limit: int = 100) -> AsyncIterator[dict]:
"""Iterate over results of a Subscription.

Note:
Expand Down
Loading