Repository: planetlabs/planet-client-python

Issue:
Create a migration guide to explain how to move from V1 to V2
**Is your feature request related to a problem? Please describe.**

With the release of the SDK V2, a migration guide for migrating scripts developed against SDK V1 would be useful.

**Describe the solution you'd like**

The most appropriate location for this material would likely be a subsection of https://planet-sdk-for-python-v2.readthedocs.io/en/latest/upgrading/

**Describe alternatives you've considered**

Description of differences inline in tutorials and other content.

**Additional context**

Requested by PM.


Discussion:

Patch:
diff --git a/docs/cli/cli-data.md b/docs/cli/cli-data.md
index dfb9cad..316927e 100644
--- a/docs/cli/cli-data.md
+++ b/docs/cli/cli-data.md
@@ -111,13 +111,13 @@ the `planet collect` method to transform the output from the Data API to valid G
 output to it:
 
 ```console
-planet data filter --geom geometry.json | planet data search PSScene - | planet collect -
+planet data filter | planet data search PSScene - | planet collect -
 ```
 
 If you want to visualize this you can save it as a file:
 
 ```console
-planet data filter --geom geometry.json | planet data search PSScene - | planet collect - > planet-search.geojson
+planet data filter | planet data search PSScene - | planet collect - > planet-search.geojson
 ```
 
 This you can then open with your favorite GIS program, or see this 
@@ -148,13 +148,12 @@ planet data filter | planet data search SkySatCollect --sort 'acquired desc' --l
 ```
 
 
-
 ## Filtering
 
 ### Run a search on a bounding box
 
 Most searches you'll likely want to run on a geometry. To try this out you can use the following bounding box
-of Iowa. You can copy it and save as a file called `geometry.json`
+of Iowa. You can copy it and save as a file called `geometry.geojson`
 
 ```json
 {
@@ -195,17 +194,22 @@ of Iowa. You can copy it and save as a file called `geometry.json`
 }
 ```
 
+!!!note ".geojson and .json files both work"
+    Here we save it as .geojson, but you can also save it as .json. The CLI is happy with any file
+    extension, even .txt, but different extensions may make it easier to open the files with other
+    programs. What's important is that the text inside the file is valid geojson.
+
 And then run it with this command:
 
 ```console
-planet data filter --geom geometry.json | planet data search PSScene -
+planet data filter --geom geometry.geojson | planet data search PSScene -
 ```
 
 Note that by default all searches with the command-line return 100 results, but you can easily increase that with
 the `--limit` flag:
 
 ```console
-planet data filter --geom geometry.json | planet data search --limit 500 PSScene -
+planet data filter --geom geometry.geojson | planet data search --limit 500 PSScene -
 ```
 
 Creating geometries for search can be annoying in a command-line workflow, but there are some ideas in the
diff --git a/docs/cli/cli-orders.md b/docs/cli/cli-orders.md
index f2561c7..0485e81 100644
--- a/docs/cli/cli-orders.md
+++ b/docs/cli/cli-orders.md
@@ -301,7 +301,7 @@ combined with all the commands listed above.
 ### Clipping
 
 The most used tool is the `clip` operation, which lets you pass a geometry to the
-Orders API and it creates new images that only have pixels within theh geometry you
+Orders API and it creates new images that only have pixels within the geometry you
 gave it. 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.
diff --git a/docs/get-started/upgrading.md b/docs/get-started/upgrading.md
index b1793b8..f65de26 100644
--- a/docs/get-started/upgrading.md
+++ b/docs/get-started/upgrading.md
@@ -1,20 +1,84 @@
 ---
-title: Upgrading from V1 to V2
+title: Upgrade from Version 1 to Version 2
 ---
 
-The Planet SDK for Python is Version 2 of what was previously referred to as
-the Planet API client. 
+The Planet SDK for Python is Version 2 of what was previously referred to as the Planet API client. This V2 is a major update of the V1 SDK. As such, there are major structural changes to how it operates. However, many aspects are still quite similar to V1. Follow this migration guide to upgrade an application developed with V1 of the SDK to V2 with minimal fuss.
 
-Version 2 is essentially a complete rewrite and brings with it big changes to
-the Python library.
+## Imports
 
-In Version 1, a single client was created for all APIs,
-`client=api.ClientV1(api_key=API_KEY)`. With this client, all commumication 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.
+The V2 SDK has a flatter code structure. Everything of note previously found under `planet.api` is now available from the `planet` module. So, `import planet` should give you everything you need.
 
-In Version 2, a `Session` is used to manage all communication with the Planet
-APIs. This provides for multiple asynchronous connections. An API-specific
-client is created. This client manages polling and downloading, along with
-any other capabilities provided by the API.
+If you are migrating from V1, and are using the Data API filter builder (from `planet.api import filters`), we do recommend also including `from planet import data_filter as filters` in your imports for an easy migration from the old filter module to the new one.
+
+## Authentication
+
+If you have your API key stored in the `PL_API_KEY` environment variable you will be automatically authenticated to the V2 API, similar to how V1 worked. For other methods for authenticating against the V2 SDK, check out [Authenticate with the Planet server](quick-start-guide/#authenticate-with-the-planet-server).
+
+## Session for all communication
+
+In Version 2, sessions are used to manage all communication with the Planet APIs. This provides for multiple asynchronous connections. For each API, there is a specific client object. This client manages polling and downloading, along with any other capabilities provided by the API.
+
+Each client now requires a `Session` object, which stores connection information and authentication.
+
+The best way of doing this is wrapping any code that invokes a client class in a block like so:
+
+```python
+async with Session() as session:
+    client = OrdersClient(session)
+    result = await client.create_order(order)
+# Process result
+```
+
+For more information about Session, refer to the [Python SDK User Guide](../../python/sdk-guide/#session).
+
+## Asynchronous Methods
+
+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.
+
+```python
+import asyncio
+from datetime import datetime
+from planet import Session, DataClient
+from planet import data_filter as filters
+ 
+async def do_search():
+    async with Session() as session:
+        client = DataClient(session)
+        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]
+ 
+items = asyncio.run(do_search())
+```
+
+For more details on interacting with the asynchronous portions of the SDK, refer to the [Python SDK User Guide](../../python/sdk-guide/#session).
+
+## Data API
+The Data API portion of SDK V2 is quite similar to V1, although some filters have been renamed for consistency (also reference the note on imports):
+
+* `date_range` to `date_range_filter`
+* `geom_filter` to `geometry_filter`
+* `and_filter` and `or_filter` now takes a list of filters instead of multiple arguments, so just wrap the contents in `[]` 
+* `permissions_filter` is now split into `permissions_filter` and `asset_filter`, reflecting a recent change in API structure. If you were using this previously, you’ll want to convert the old `permissions_filter` into an `asset_filter` (this also involves changing the filter values, e.g. `assets.ortho_analytic_8b_sr:download` will become `ortho_analytic_8b_sr`) and adding an empty `permissions_filter`.
+
+`filters.build_seach_request` no longer exists, and has instead been integrated into the replacement for `client.quick_seach`. For example:
+
+```python
+planet.api.ClientV1().quick_search(filters.build_search_request(all_filters, ["PSScene"]))
+```
+
+Is now
+
+```python
+async with Session() as session: 
+    items_aiter = planet.DataClient(session).search_aiter(["PSScene"], all_filters)
+
+## Orders API
+
+The Orders API capabilities in V1 were quite primitive, but those that did exist have been retained in much the same form; `ClientV1().create_order` becomes `OrderClient(session).create_order`. (As with the `DataClient`, you must also use `async` and `Session` with `OrderClient`.)
+
+Additionally, there is now also an order builder in `planet.order_request`, similar to the preexisting search filter builder. For more details on this, refer to the [Creating an Order](../../python/sdk-guide/#creating-an-order).
diff --git a/docs/python/sdk-guide.md b/docs/python/sdk-guide.md
index e3495bd..7864847 100644
--- a/docs/python/sdk-guide.md
+++ b/docs/python/sdk-guide.md
@@ -109,13 +109,19 @@ Otherwise, the JSON blob is a list of the individual results.
 >>> async def main():
 ...     async with Session() as sess:
 ...         client = OrdersClient(sess)
-...         orders = client.list_orders()
-...         orders_list = collect(orders)
+...         orders_aiter = client.list_orders_aiter()
+...         orders_list = collect(orders_aiter)
 ...
 >>> 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 Client
 
diff --git a/mkdocs.yml b/mkdocs.yml
index a22ec97..1345e57 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -91,3 +91,5 @@ markdown_extensions:
   - pymdownx.superfences
   - mkdocs-click
   - admonition
+  - toc:
+      permalink: True
diff --git a/planet/cli/data.py b/planet/cli/data.py
index 73322cd..61688d6 100644
--- a/planet/cli/data.py
+++ b/planet/cli/data.py
@@ -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 = await cl.search(item_types,
-                                filter,
-                                name=name,
-                                sort=sort,
-                                limit=limit)
-        async for item in items:
+        items_aiter = cl.search_aiter(item_types,
+                                      filter,
+                                      name=name,
+                                      sort=sort,
+                                      limit=limit)
+        async for item in items_aiter:
             echo_json(item, pretty)
 
 
diff --git a/planet/cli/orders.py b/planet/cli/orders.py
index 60d52ae..b126a4d 100644
--- a/planet/cli/orders.py
+++ b/planet/cli/orders.py
@@ -67,8 +67,8 @@ async def list(ctx, state, limit, pretty):
     optionally pretty-printed.
     '''
     async with orders_client(ctx) as cl:
-        orders = await cl.list_orders(state=state, limit=limit)
-        async for o in orders:
+        orders_aiter = cl.list_orders_aiter(state=state, limit=limit)
+        async for o in orders_aiter:
             echo_json(o, pretty)
 
 
diff --git a/planet/cli/subscriptions.py b/planet/cli/subscriptions.py
index 42a4dad..41d2283 100644
--- a/planet/cli/subscriptions.py
+++ b/planet/cli/subscriptions.py
@@ -42,8 +42,9 @@ 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)
-        filtered_subs = client.list_subscriptions(status=status, limit=limit)
-        async for sub in filtered_subs:
+        subs_aiter = client.list_subscriptions_aiter(status=status,
+                                                     limit=limit)
+        async for sub in subs_aiter:
             echo_json(sub, pretty)
 
 
@@ -157,8 +158,8 @@ 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)
-        filtered_results = client.get_results(subscription_id,
-                                              status=status,
-                                              limit=limit)
-        async for result in filtered_results:
+        results_aiter = client.get_results_aiter(subscription_id,
+                                                 status=status,
+                                                 limit=limit)
+        async for result in results_aiter:
             echo_json(result, pretty)
diff --git a/planet/clients/data.py b/planet/clients/data.py
index fdba667..5f8399b 100644
--- a/planet/clients/data.py
+++ b/planet/clients/data.py
@@ -93,57 +93,18 @@ class DataClient:
     def _item_url(self, item_type, item_id):
         return f'{self._base_url}/item-types/{item_type}/items/{item_id}'
 
-    async def search(self,
-                     item_types: List[str],
-                     search_filter: dict,
-                     name: Optional[str] = None,
-                     sort: Optional[str] = None,
-                     limit: int = 100) -> AsyncIterator[dict]:
-        """Execute a quick search.
+    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]:
+        """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.
 
-        To filter to items you have access to download which are of standard
-        (aka not test) quality, use the following:
-
-        ```python
-        >>> from planet import data_filter
-        >>> data_filter.and_filter([
-        ...     data_filter.permission_filter(),
-        ...     data_filter.std_quality_filter()
-        >>> ])
-
-        ```
-
-        To avoid filtering out any imagery, supply a blank AndFilter, which can
-        be created with `data_filter.and_filter([])`.
-
-        Example:
-
-        ```python
-        >>> import asyncio
-        >>> from planet import Session, DataClient
-        >>>
-        >>> async def main():
-        ...     item_types = ['PSScene']
-        ...     sfilter = {
-        ...         "type":"DateRangeFilter",
-        ...         "field_name":"acquired",
-        ...         "config":{
-        ...             "gt":"2019-12-31T00:00:00Z",
-        ...             "lte":"2020-01-31T00:00:00Z"
-        ...         }
-        ...     }
-        ...     async with Session() as sess:
-        ...         cl = DataClient(sess)
-        ...         items = await cl.quick_search(item_types, sfilter)
-        ...
-        >>> asyncio.run(main())
-
-        ```
-
         Parameters:
             item_types: The item types to include in the search.
             search_filter: Structured search criteria.
@@ -153,8 +114,8 @@ class DataClient:
             limit: Maximum number of results to return. When set to 0, no
                 maximum is applied.
 
-        Returns:
-            Returns an iterator over all items matching the search.
+        Yields:
+            Description of an item.
 
         Raises:
             planet.exceptions.APIError: On API error.
@@ -178,7 +139,8 @@ class DataClient:
                                                url=url,
                                                json=request_json,
                                                params=params)
-        return Items(response, self._session.request, limit=limit)
+        async for i in Items(response, self._session.request, limit=limit):
+            yield i
 
     async def create_search(self,
                             name: str,
@@ -262,11 +224,11 @@ class DataClient:
                                                json=request)
         return response.json()
 
-    async def list_searches(self,
-                            sort: str = 'created desc',
-                            search_type: str = 'any',
-                            limit: int = 100) -> AsyncIterator[dict]:
-        """List all saved searches available to the authenticated user.
+    async def list_searches_aiter(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
@@ -279,8 +241,8 @@ class DataClient:
             limit: Maximum number of results to return. When set to 0, no
                 maximum is applied.
 
-        Returns:
-            An iterator over all searches that match filter.
+        Yields:
+            Description of a search.
 
         Raises:
             planet.exceptions.APIError: On API error.
@@ -300,7 +262,8 @@ class DataClient:
         url = f'{self._searches_url()}'
 
         response = await self._session.request(method='GET', url=url)
-        return Searches(response, self._session.request, limit=limit)
+        async for s in Searches(response, self._session.request, limit=limit):
+            yield s
 
     async def delete_search(self, search_id: str):
         """Delete an existing saved search.
@@ -332,18 +295,18 @@ class DataClient:
         response = await self._session.request(method='GET', url=url)
         return response.json()
 
-    async def run_search(self,
-                         search_id: str,
-                         limit: int = 100) -> AsyncIterator[dict]:
-        """Execute a saved search.
+    async def run_search_aiter(self,
+                               search_id: str,
+                               limit: int = 100) -> AsyncIterator[dict]:
+        """Iterate over results from a saved search.
 
         Parameters:
             search_id: Stored search identifier.
             limit: Maximum number of results to return. When set to 0, no
                 maximum is applied.
 
-        Returns:
-            Returns an iterator over all items matching the search.
+        Yields:
+            Description of an item.
 
         Raises:
             planet.exceptions.APIError: On API error.
@@ -351,7 +314,8 @@ class DataClient:
         url = f'{self._searches_url()}/{search_id}/results'
 
         response = await self._session.request(method='GET', url=url)
-        return Items(response, self._session.request, limit=limit)
+        async for i in Items(response, self._session.request, limit=limit):
+            yield i
 
     async def get_stats(self,
                         item_types: List[str],
diff --git a/planet/clients/orders.py b/planet/clients/orders.py
index 733e96f..b5c1cc5 100644
--- a/planet/clients/orders.py
+++ b/planet/clients/orders.py
@@ -463,10 +463,10 @@ class OrdersClient:
 
         return current_state
 
-    async def list_orders(self,
-                          state: Optional[str] = None,
-                          limit: int = 100) -> AsyncIterator[dict]:
-        """Get all order requests.
+    async def list_orders_aiter(self,
+                                state: Optional[str] = None,
+                                limit: int = 100) -> AsyncIterator[dict]:
+        """Iterate over the list of stored order requests.
 
         Parameters:
             state: Filter orders to given state.
@@ -474,7 +474,7 @@ class OrdersClient:
                 maximum is applied.
 
         Returns:
-            User orders that match the query
+            Iterator over user orders that match the query
 
         Raises:
             planet.exceptions.APIError: On API error.
@@ -493,4 +493,5 @@ class OrdersClient:
         response = await self._session.request(method='GET',
                                                url=url,
                                                params=params)
-        return Orders(response, self._session.request, limit=limit)
+        async for o in Orders(response, self._session.request, limit=limit):
+            yield o
diff --git a/planet/clients/subscriptions.py b/planet/clients/subscriptions.py
index 888abfc..5aba2d4 100644
--- a/planet/clients/subscriptions.py
+++ b/planet/clients/subscriptions.py
@@ -31,10 +31,11 @@ class SubscriptionsClient:
     def __init__(self, session: Session) -> None:
         self._session = session
 
-    async def list_subscriptions(self,
-                                 status: Optional[Set[str]] = None,
-                                 limit: int = 100) -> AsyncIterator[dict]:
-        """Get account subscriptions with optional filtering.
+    async def list_subscriptions_aiter(
+            self,
+            status: Optional[Set[str]] = None,
+            limit: int = 100) -> AsyncIterator[dict]:
+        """Iterate over list of account subscriptions with optional filtering.
 
         Note:
             The name of this method is based on the API's method name.
@@ -192,11 +193,11 @@ class SubscriptionsClient:
             sub = resp.json()
             return sub
 
-    async def get_results(self,
-                          subscription_id: str,
-                          status: Optional[Set[str]] = None,
-                          limit: int = 100) -> AsyncIterator[dict]:
-        """Get Results of a Subscription.
+    async def get_results_aiter(self,
+                                subscription_id: str,
+                                status: Optional[Set[str]] = None,
+                                limit: int = 100) -> AsyncIterator[dict]:
+        """Iterate over results of a Subscription.
 
         Note:
             The name of this method is based on the API's method name. This


Test patch:
diff --git a/tests/integration/test_data_api.py b/tests/integration/test_data_api.py
index 2e9522f..aba2bcd 100644
--- a/tests/integration/test_data_api.py
+++ b/tests/integration/test_data_api.py
@@ -67,10 +67,10 @@ def search_response(item_descriptions):
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_search_basic(item_descriptions,
-                            search_filter,
-                            search_response,
-                            session):
+async def test_search_aiter_basic(item_descriptions,
+                                  search_filter,
+                                  search_response,
+                                  session):
 
     quick_search_url = f'{TEST_URL}/quick-search'
     next_page_url = f'{TEST_URL}/blob/?page_marker=IAmATest'
@@ -89,8 +89,10 @@ async def test_search_basic(item_descriptions,
     respx.get(next_page_url).return_value = mock_resp2
 
     cl = DataClient(session, base_url=TEST_URL)
-    items = await cl.search(['PSScene'], search_filter, name='quick_search')
-    items_list = [i async for i in items]
+    item_aiter = cl.search_aiter(['PSScene'],
+                                 search_filter,
+                                 name='quick_search')
+    items_list = [i async for i in item_aiter]
 
     # check that request is correct
     expected_request = {
@@ -107,10 +109,10 @@ async def test_search_basic(item_descriptions,
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_search_sort(item_descriptions,
-                           search_filter,
-                           search_response,
-                           session):
+async def test_search_aiter_sort(item_descriptions,
+                                 search_filter,
+                                 search_response,
+                                 session):
 
     sort = 'acquired asc'
     quick_search_url = f'{TEST_URL}/quick-search?_sort={sort}'
@@ -123,18 +125,18 @@ async def test_search_sort(item_descriptions,
     # if the sort parameter is not used correctly, the client will not send
     # the request to the mocked endpoint and this test will fail
     cl = DataClient(session, base_url=TEST_URL)
-    items = await cl.search(['PSScene'], search_filter, sort=sort)
+    item_aiter = cl.search_aiter(['PSScene'], search_filter, sort=sort)
 
     # run through the iterator to actually initiate the call
-    [i async for i in items]
+    [i async for i in item_aiter]
 
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_search_limit(item_descriptions,
-                            search_filter,
-                            search_response,
-                            session):
+async def test_search_aiter_limit(item_descriptions,
+                                  search_filter,
+                                  search_response,
+                                  session):
 
     quick_search_url = f'{TEST_URL}/quick-search'
 
@@ -146,8 +148,8 @@ async def test_search_limit(item_descriptions,
     respx.post(quick_search_url).return_value = mock_resp
 
     cl = DataClient(session, base_url=TEST_URL)
-    items = await cl.search(['PSScene'], search_filter, limit=2)
-    items_list = [i async for i in items]
+    item_aiter = cl.search_aiter(['PSScene'], search_filter, limit=2)
+    items_list = [i async for i in item_aiter]
 
     # check only the first two results were returned
     assert items_list == item_descriptions[:2]
@@ -295,18 +297,18 @@ async def test_update_search_basic(search_filter, session):
 @respx.mock
 @pytest.mark.asyncio
 @pytest.mark.parametrize("limit, expected_list_length", [(None, 4), (3, 3)])
-async def test_list_searches_success(limit,
-                                     expected_list_length,
-                                     search_result,
-                                     session):
+async def test_list_searches_aiter_success(limit,
+                                           expected_list_length,
+                                           search_result,
+                                           session):
     page1_response = {"_links": {}, "searches": [search_result] * 4}
     route = respx.get(TEST_SEARCHES_URL)
     route.return_value = httpx.Response(200, json=page1_response)
 
     cl = DataClient(session, base_url=TEST_URL)
 
-    searches = await cl.list_searches(limit=limit)
-    searches_list_length = len([s async for s in searches])
+    search_aiter = cl.list_searches_aiter(limit=limit)
+    searches_list_length = len([s async for s in search_aiter])
     assert searches_list_length == expected_list_length
 
     assert route.called
@@ -318,17 +320,19 @@ async def test_list_searches_success(limit,
     "sort, search_type, expectation",
     [('DOESNOTEXIST', 'ANY', pytest.raises(exceptions.ClientError)),
      ('CREATED DESC', 'DOESNOTEXIST', pytest.raises(exceptions.ClientError))])
-async def test_list_searches_args_do_not_match(sort,
-                                               search_type,
-                                               expectation,
-                                               session):
+async def test_list_searches_aiter_args_do_not_match(sort,
+                                                     search_type,
+                                                     expectation,
+                                                     session):
     route = respx.get(TEST_SEARCHES_URL)
     route.return_value = httpx.Response(200, json={})
 
     cl = DataClient(session, base_url=TEST_URL)
 
     with expectation:
-        await cl.list_searches(sort=sort, search_type=search_type)
+        searches_aiter = cl.list_searches_aiter(sort=sort,
+                                                search_type=search_type)
+        [s async for s in searches_aiter]
 
     assert not route.called
 
@@ -353,7 +357,7 @@ async def test_delete_search(retcode, expectation, session):
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_run_search_success(item_descriptions, session):
+async def test_run_search_aiter_success(item_descriptions, session):
     sid = 'search_id'
     route = respx.get(f'{TEST_SEARCHES_URL}/{sid}/results')
 
@@ -372,8 +376,8 @@ async def test_run_search_success(item_descriptions, session):
     respx.get(next_page_url).return_value = mock_resp2
 
     cl = DataClient(session, base_url=TEST_URL)
-    items = await cl.run_search(sid)
-    items_list = [i async for i in items]
+    item_aiter = cl.run_search_aiter(sid)
+    items_list = [i async for i in item_aiter]
 
     assert route.called
 
@@ -383,17 +387,17 @@ async def test_run_search_success(item_descriptions, session):
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_run_search_doesnotexist(session):
+async def test_run_search_aiter_doesnotexist(session):
     sid = 'search_id'
     route = respx.get(f'{TEST_SEARCHES_URL}/{sid}/results')
     route.return_value = httpx.Response(404)
 
     cl = DataClient(session, base_url=TEST_URL)
     with pytest.raises(exceptions.APIError):
-        items = await cl.run_search(sid)
+        item_aiter = cl.run_search_aiter(sid)
         # this won't throw the error until the iterator is processed
         # issue 476
-        [i async for i in items]
+        [i async for i in item_aiter]
 
     assert route.called
 
diff --git a/tests/integration/test_orders_api.py b/tests/integration/test_orders_api.py
index bb1a63e..8ef8caf 100644
--- a/tests/integration/test_orders_api.py
+++ b/tests/integration/test_orders_api.py
@@ -97,7 +97,7 @@ def test_OrderStates_passed():
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_list_orders_basic(order_descriptions, session):
+async def test_list_orders_aiter_basic(order_descriptions, session):
     next_page_url = TEST_ORDERS_URL + 'blob/?page_marker=IAmATest'
 
     order1, order2, order3 = order_descriptions
@@ -116,13 +116,13 @@ async def test_list_orders_basic(order_descriptions, session):
     respx.get(next_page_url).return_value = mock_resp2
 
     cl = OrdersClient(session, base_url=TEST_URL)
-    orders = await cl.list_orders()
-    assert order_descriptions == [o async for o in orders]
+    order_aiter = cl.list_orders_aiter()
+    assert order_descriptions == [o async for o in order_aiter]
 
 
 @respx.mock
 @pytest.mark.asyncio
-async def test_list_orders_state(order_descriptions, session):
+async def test_list_orders_aiter_state_success(order_descriptions, session):
     list_url = TEST_ORDERS_URL + '?source_type=all&state=failed'
 
     order1, order2, _ = order_descriptions
@@ -139,26 +139,27 @@ async def test_list_orders_state(order_descriptions, session):
 
     # if the value of state doesn't get sent as a url parameter,
     # the mock will fail and this test will fail
-    orders = await cl.list_orders(state='failed')
-    assert [order1, order2] == [o async for o in orders]
+    order_aiter = cl.list_orders_aiter(state='failed')
+    assert [order1, order2] == [o async for o in order_aiter]
 
 
 @pytest.mark.asyncio
-async def test_list_orders_state_invalid_state(session):
+async def test_list_orders_aiter_state_invalid(session):
     cl = OrdersClient(session, base_url=TEST_URL)
 
     with pytest.raises(exceptions.ClientError):
-        await cl.list_orders(state='invalidstate')
+        order_aiter = cl.list_orders_aiter(state='invalidstate')
+        [o async for o in order_aiter]
 
 
 @respx.mock
 @pytest.mark.asyncio
 @pytest.mark.parametrize("limit,limited_list_length", [(None, 100), (0, 102),
                                                        (1, 1)])
-async def test_list_orders_limit(order_descriptions,
-                                 session,
-                                 limit,
-                                 limited_list_length):
+async def test_list_orders_aiter_limit(order_descriptions,
+                                       session,
+                                       limit,
+                                       limited_list_length):
     nono_page_url = None
 
     # Creating 102 (3x34) order descriptions
@@ -182,8 +183,8 @@ async def test_list_orders_limit(order_descriptions,
 
     cl = OrdersClient(session, base_url=TEST_URL)
 
-    orders = await cl.list_orders(limit=limit)
-    assert len([o async for o in orders]) == limited_list_length
+    order_aiter = cl.list_orders_aiter(limit=limit)
+    assert len([o async for o in order_aiter]) == limited_list_length
 
 
 @respx.mock
diff --git a/tests/integration/test_subscriptions_api.py b/tests/integration/test_subscriptions_api.py
index 4658660..65d84df 100644
--- a/tests/integration/test_subscriptions_api.py
+++ b/tests/integration/test_subscriptions_api.py
@@ -156,19 +156,19 @@ res_api_mock.route(
 
 @pytest.mark.asyncio
 @failing_api_mock
-async def test_list_subscriptions_failure():
+async def test_list_subscriptions_aiter_failure():
     """ServerError is raised if there is an internal server error (500)."""
     with pytest.raises(ServerError):
         async with Session() as session:
             client = SubscriptionsClient(session)
-            _ = [sub async for sub in client.list_subscriptions()]
+            _ = [sub async for sub in client.list_subscriptions_aiter()]
 
 
 @pytest.mark.parametrize("status, count", [({"created"}, 100), ({"failed"}, 0),
                                            (None, 100)])
 @pytest.mark.asyncio
 @api_mock
-async def test_list_subscriptions_success(
+async def test_list_subscriptions_aiter_success(
     status,
     count,
 ):
@@ -176,7 +176,7 @@ async def test_list_subscriptions_success(
     async with Session() as session:
         client = SubscriptionsClient(session)
         assert len([
-            sub async for sub in client.list_subscriptions(status=status)
+            sub async for sub in client.list_subscriptions_aiter(status=status)
         ]) == count
 
 
@@ -266,21 +266,21 @@ async def test_get_subscription_success(monkeypatch):
 
 @pytest.mark.asyncio
 @failing_api_mock
-async def test_get_results_failure():
+async def test_get_results_aiter_failure():
     """APIError is raised if there is a server error."""
     with pytest.raises(APIError):
         async with Session() as session:
             client = SubscriptionsClient(session)
-            _ = [res async for res in client.get_results("lolwut")]
+            _ = [res async for res in client.get_results_aiter("lolwut")]
 
 
 @pytest.mark.asyncio
 @res_api_mock
-async def test_get_results_success():
+async def test_get_results_aiter_success():
     """Subscription description fetched, has the expected items."""
     async with Session() as session:
         client = SubscriptionsClient(session)
-        results = [res async for res in client.get_results("42")]
+        results = [res async for res in client.get_results_aiter("42")]
         assert len(results) == 100
 
 
@@ -313,9 +313,9 @@ paging_cycle_api_mock.route(
 
 @pytest.mark.asyncio
 @paging_cycle_api_mock
-async def test_list_subscriptions_cycle_break():
+async def test_list_subscriptions_aiter_cycle_break():
     """PagingError is raised if there is a paging cycle."""
     with pytest.raises(PagingError):
         async with Session() as session:
             client = SubscriptionsClient(session)
-            _ = [sub async for sub in client.list_subscriptions()]
+            _ = [sub async for sub in client.list_subscriptions_aiter()]