From 76f770bd2e1ae25efda41490e182b493d65c1ca6 Mon Sep 17 00:00:00 2001 From: asonnenschein Date: Tue, 24 Mar 2026 14:16:17 -0400 Subject: [PATCH 1/5] update subs get_results* methods with missing query params --- planet/cli/subscriptions.py | 34 ++++++++++-- planet/clients/subscriptions.py | 98 +++++++++++++++++++++++++-------- planet/sync/subscriptions.py | 68 +++++++++++++++++++---- 3 files changed, 159 insertions(+), 41 deletions(-) diff --git a/planet/cli/subscriptions.py b/planet/cli/subscriptions.py index 2cd15dfe..415952ba 100644 --- a/planet/cli/subscriptions.py +++ b/planet/cli/subscriptions.py @@ -437,11 +437,21 @@ async def get_subscription_cmd(ctx, subscription_id, pretty): default=False, help="Get subscription results as comma-separated fields. When " "this flag is included, --limit is ignored") +@click.option( + '--created', + help="""Filter results by creation time or interval. See documentation + for examples.""") +@click.option( + '--updated', + help="""Filter results by update time or interval. See documentation + for examples.""") +@click.option( + '--completed', + help="""Filter results by completion time or interval. See documentation + for examples.""") +@click.option('--user-id', + help="Filter by user ID. Accepts 'all' or a specific user ID.") @limit -# TODO: the following 3 options. -# –created: timestamp instant or range. -# –updated: timestamp instant or range. -# –completed: timestamp instant or range. @click.pass_context @translate_exceptions @coro @@ -450,6 +460,10 @@ async def list_subscription_results_cmd(ctx, pretty, status, csv_flag, + created, + updated, + completed, + user_id, limit): """Print the results of a subscription to stdout. @@ -474,12 +488,20 @@ async def list_subscription_results_cmd(ctx, async with subscriptions_client(ctx) as client: if csv_flag: async for result in client.get_results_csv(subscription_id, - status=status): + status=status, + created=created, + updated=updated, + completed=completed, + user_id=user_id): click.echo(result) else: async for result in client.get_results(subscription_id, status=status, - limit=limit): + limit=limit, + created=created, + updated=updated, + completed=completed, + user_id=user_id): echo_json(result, pretty) diff --git a/planet/clients/subscriptions.py b/planet/clients/subscriptions.py index 372b6eb6..1a0a2e7b 100644 --- a/planet/clients/subscriptions.py +++ b/planet/clients/subscriptions.py @@ -514,15 +514,19 @@ async def get_subscription(self, subscription_id: str) -> dict: sub = resp.json() return sub - async def get_results(self, - subscription_id: str, - status: Optional[Sequence[Literal[ - "created", - "queued", - "processing", - "failed", - "success"]]] = None, - limit: int = 100) -> AsyncIterator[dict]: + async def get_results( + self, + subscription_id: str, + status: Optional[Sequence[Literal["created", + "queued", + "processing", + "failed", + "success"]]] = None, + limit: int = 100, + created: Optional[str] = None, + updated: Optional[str] = None, + completed: Optional[str] = None, + user_id: Optional[Union[str, int]] = None) -> AsyncIterator[dict]: """Iterate over results of a Subscription. Notes: @@ -536,6 +540,20 @@ async def get_results(self, filter out results with status not in this set. limit (int): limit the number of subscriptions in the results. When set to 0, no maximum is applied. + created (str): filter by created time or interval. + updated (str): filter by updated time or interval. + completed (str): filter by completed time or interval. + user_id (str or int): filter by user ID. Only available to organization admins. + Accepts "all" or a specific user ID. + + Datetime args (created, updated, completed) can either be a + date-time or an interval, open or closed. Date and time expressions adhere + to RFC 3339. Open intervals are expressed using double-dots. + + Examples: + * A date-time: "2018-02-12T23:20:50Z" + * A closed interval: "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" + * Open intervals: "2018-02-12T00:00:00Z/.." or "../2018-03-18T12:31:12Z" Yields: dict: description of a subscription results. @@ -545,13 +563,22 @@ async def get_results(self, ClientError: on a client error. """ - # TODO from old doc string, which breaks strict document checking: - # Add Parameters created, updated, completed, user_id class _ResultsPager(Paged): """Navigates pages of messages about subscription results.""" ITEMS_KEY = 'results' - params = {'status': [val for val in status or {}]} + params: Dict[str, Any] = {} + if status is not None: + params['status'] = [val for val in status] + if created is not None: + params['created'] = created + if updated is not None: + params['updated'] = updated + if completed is not None: + params['completed'] = completed + if user_id is not None: + params['user_id'] = user_id + url = f'{self._base_url}/{subscription_id}/results' try: @@ -570,20 +597,37 @@ class _ResultsPager(Paged): raise async def get_results_csv( - self, - subscription_id: str, - status: Optional[Sequence[Literal["created", - "queued", - "processing", - "failed", - "success"]]] = None - ) -> AsyncIterator[str]: + self, + subscription_id: str, + status: Optional[Sequence[Literal["created", + "queued", + "processing", + "failed", + "success"]]] = None, + created: Optional[str] = None, + updated: Optional[str] = None, + completed: Optional[str] = None, + user_id: Optional[Union[str, int]] = None) -> AsyncIterator[str]: """Iterate over rows of results CSV for a Subscription. Parameters: subscription_id (str): id of a subscription. status (Set[str]): pass result with status in this set, filter out results with status not in this set. + created (str): filter by created time or interval. + updated (str): filter by updated time or interval. + completed (str): filter by completed time or interval. + user_id (str or int): filter by user ID. Only available to organization admins. + Accepts "all" or a specific user ID. + + Datetime args (created, updated, completed) can either be a + date-time or an interval, open or closed. Date and time expressions adhere + to RFC 3339. Open intervals are expressed using double-dots. + + Examples: + * A date-time: "2018-02-12T23:20:50Z" + * A closed interval: "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" + * Open intervals: "2018-02-12T00:00:00Z/.." or "../2018-03-18T12:31:12Z" Yields: str: a row from a CSV file. @@ -592,10 +636,18 @@ async def get_results_csv( APIError: on an API server error. ClientError: on a client error. """ - # TODO from old doc string, which breaks strict document checking: - # Add Parameters created, updated, completed, user_id url = f'{self._base_url}/{subscription_id}/results' - params = {'status': [val for val in status or {}], 'format': 'csv'} + params: Dict[str, Any] = {'format': 'csv'} + if status is not None: + params['status'] = [val for val in status] + if created is not None: + params['created'] = created + if updated is not None: + params['updated'] = updated + if completed is not None: + params['completed'] = completed + if user_id is not None: + params['user_id'] = user_id # Note: retries are not implemented yet. This project has # retry logic for HTTP requests, but does not handle errors diff --git a/planet/sync/subscriptions.py b/planet/sync/subscriptions.py index 9ec656c2..afff7fcf 100644 --- a/planet/sync/subscriptions.py +++ b/planet/sync/subscriptions.py @@ -338,6 +338,10 @@ def get_results( "failed", "success"]]] = None, limit: int = 100, + created: Optional[str] = None, + updated: Optional[str] = None, + completed: Optional[str] = None, + user_id: Optional[Union[str, int]] = None ) -> Iterator[Union[Dict[str, Any], str]]: """Iterate over results of a Subscription. @@ -352,7 +356,20 @@ def get_results( filter out results with status not in this set. limit (int): limit the number of subscriptions in the results. When set to 0, no maximum is applied. - TODO: created, updated, completed, user_id + created (str): filter by created time or interval. + updated (str): filter by updated time or interval. + completed (str): filter by completed time or interval. + user_id (str or int): filter by user ID. Only available to organization admins. + Accepts "all" or a specific user ID. + + Datetime args (created, updated, completed) can either be a + date-time or an interval, open or closed. Date and time expressions adhere + to RFC 3339. Open intervals are expressed using double-dots. + + Examples: + * A date-time: "2018-02-12T23:20:50Z" + * A closed interval: "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" + * Open intervals: "2018-02-12T00:00:00Z/.." or "../2018-03-18T12:31:12Z" Yields: dict: description of a subscription results. @@ -362,24 +379,46 @@ def get_results( ClientError: on a client error. """ return self._client._aiter_to_iter( - self._client.get_results(subscription_id, status, limit)) + self._client.get_results(subscription_id, + status, + limit, + created, + updated, + completed, + user_id)) def get_results_csv( - self, - subscription_id: str, - status: Optional[Sequence[Literal["created", - "queued", - "processing", - "failed", - "success"]]] = None - ) -> Iterator[str]: + self, + subscription_id: str, + status: Optional[Sequence[Literal["created", + "queued", + "processing", + "failed", + "success"]]] = None, + created: Optional[str] = None, + updated: Optional[str] = None, + completed: Optional[str] = None, + user_id: Optional[Union[str, int]] = None) -> Iterator[str]: """Iterate over rows of results CSV for a Subscription. Parameters: subscription_id (str): id of a subscription. status (Set[str]): pass result with status in this set, filter out results with status not in this set. - TODO: created, updated, completed, user_id + created (str): filter by created time or interval. + updated (str): filter by updated time or interval. + completed (str): filter by completed time or interval. + user_id (str or int): filter by user ID. Only available to organization admins. + Accepts "all" or a specific user ID. + + Datetime args (created, updated, completed) can either be a + date-time or an interval, open or closed. Date and time expressions adhere + to RFC 3339. Open intervals are expressed using double-dots. + + Examples: + * A date-time: "2018-02-12T23:20:50Z" + * A closed interval: "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" + * Open intervals: "2018-02-12T00:00:00Z/.." or "../2018-03-18T12:31:12Z" Yields: str: a row from a CSV file. @@ -394,7 +433,12 @@ def get_results_csv( # for this entire method a la stamina: # https://github.com/hynek/stamina. return self._client._aiter_to_iter( - self._client.get_results_csv(subscription_id, status)) + self._client.get_results_csv(subscription_id, + status, + created, + updated, + completed, + user_id)) def get_summary(self) -> Dict[str, Any]: """Summarize the status of all subscriptions via GET. From d3524eb3d73fbcd59f06af05701c32836314a495 Mon Sep 17 00:00:00 2001 From: asonnenschein Date: Tue, 24 Mar 2026 14:25:28 -0400 Subject: [PATCH 2/5] update cli docs --- docs/cli/cli-subscriptions.md | 40 ++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/cli/cli-subscriptions.md b/docs/cli/cli-subscriptions.md index 2269775b..dc8d7ba3 100644 --- a/docs/cli/cli-subscriptions.md +++ b/docs/cli/cli-subscriptions.md @@ -228,12 +228,50 @@ planet subscriptions results SUBSCRIPTION_ID By default this displays the first 100 results. As with other commands, you can use the `--limit` param to set a higher limit, or set it to 0 to see all results (this can be quite large with subscriptions results). -You can also filter by status: +#### Filtering Results + +The `results` command supports filtering on several fields: + +* `--status`: Filter on the status of results. Status options include `created`, `queued`, `processing`, `failed`, and `success`. Multiple status args are allowed. +* `--created`: Filter results by creation time or an interval of creation times. +* `--updated`: Filter results by update time or an interval of update times. +* `--completed`: Filter results by completion time or an interval of completion times. +* `--user-id`: Filter by user ID. Only available to organization admins. Accepts "all" or a specific user ID. + +Datetime args (`--created`, `--updated`, and `--completed`) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. + +* A date-time: `2018-02-12T23:20:50Z` +* A closed interval: `2018-02-12T00:00:00Z/2018-03-18T12:31:12Z` +* Open intervals: `2018-02-12T00:00:00Z/..` or `../2018-03-18T12:31:12Z` + +Examples: + +To see results that are currently processing: ```sh planet subscriptions results SUBSCRIPTION_ID --status processing ``` +To see successful results completed in the last week: + +```sh +planet subscriptions results SUBSCRIPTION_ID --status success \ + --completed 2026-03-17T00:00:00Z/.. +``` + +To see results created in a specific time range: + +```sh +planet subscriptions results SUBSCRIPTION_ID \ + --created 2024-01-01T00:00:00Z/2024-02-01T00:00:00Z +``` + +To see results for all users in your organization (organization admin only): + +```sh +planet subscriptions results SUBSCRIPTION_ID --user-id all +``` + See the Subscriptions API documentation for the [official list of available statuses](https://docs.planet.com/develop/apis/subscriptions/#states--status-descriptions). #### Results as comma-separated values (CSV) From 4118290584377cfd5cfd181fb775c00ba3c8cea4 Mon Sep 17 00:00:00 2001 From: asonnenschein Date: Tue, 24 Mar 2026 16:14:59 -0400 Subject: [PATCH 3/5] tests --- tests/integration/test_subscriptions_api.py | 135 ++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/tests/integration/test_subscriptions_api.py b/tests/integration/test_subscriptions_api.py index 72c0e7a2..c431afbe 100644 --- a/tests/integration/test_subscriptions_api.py +++ b/tests/integration/test_subscriptions_api.py @@ -830,6 +830,141 @@ def test_get_results_csv_sync(): assert rows == [['id', 'status'], ['1234-abcd', 'SUCCESS']] +# Mock router for testing query parameter filtering +results_filter_mock = respx.mock(assert_all_called=False) + +# More specific routes (multiple params) must come first +results_filter_mock.route( + M(url__startswith=TEST_URL), + M(params__contains={ + 'created': '2024-01-01T00:00:00Z/..', 'user_id': 'all' + }) +).mock( + side_effect=[Response(200, json={ + 'results': [{ + 'id': '5' + }], '_links': {} + })]) + +results_filter_mock.route( + M(url__startswith=TEST_URL), + M(params__contains={ + 'format': 'csv', 'completed': '2024-01-01T00:00:00Z/..' + })).mock(side_effect=[Response(200, text="id,status\n6,SUCCESS\n")]) + +# Single parameter routes +results_filter_mock.route( + M(url__startswith=TEST_URL), + M(params__contains={'created': '2024-01-01T00:00:00Z/..'}) +).mock( + side_effect=[Response(200, json={ + 'results': [{ + 'id': '1' + }], '_links': {} + })]) + +results_filter_mock.route( + M(url__startswith=TEST_URL), + M(params__contains={'updated': '../2024-12-31T23:59:59Z'}) +).mock( + side_effect=[Response(200, json={ + 'results': [{ + 'id': '2' + }], '_links': {} + })]) + +results_filter_mock.route( + M(url__startswith=TEST_URL), + M(params__contains={ + 'completed': '2024-01-01T00:00:00Z/2024-02-01T00:00:00Z' + }) +).mock( + side_effect=[Response(200, json={ + 'results': [{ + 'id': '3' + }], '_links': {} + })]) + +results_filter_mock.route( + M(url__startswith=TEST_URL), M(params__contains={'user_id': 'all'}) +).mock( + side_effect=[Response(200, json={ + 'results': [{ + 'id': '4' + }], '_links': {} + })]) + + +@pytest.mark.parametrize( + "filter_param,expected_id", + [ + ({ + "created": "2024-01-01T00:00:00Z/.." + }, '1'), + ({ + "updated": "../2024-12-31T23:59:59Z" + }, '2'), + ({ + "completed": "2024-01-01T00:00:00Z/2024-02-01T00:00:00Z" + }, '3'), + ({ + "user_id": "all" + }, '4'), + ]) +@pytest.mark.anyio +@results_filter_mock +async def test_get_results_with_filter_params(filter_param, expected_id): + """get_results passes filter parameters to API.""" + async with Session() as session: + client = SubscriptionsClient(session, base_url=TEST_URL) + results = [ + res async for res in client.get_results("42", **filter_param) + ] + assert len(results) == 1 + assert results[0]['id'] == expected_id + + +@pytest.mark.anyio +@results_filter_mock +async def test_get_results_with_multiple_filters(): + """get_results passes multiple filter parameters to API.""" + async with Session() as session: + client = SubscriptionsClient(session, base_url=TEST_URL) + results = [ + res async for res in client.get_results( + "42", created="2024-01-01T00:00:00Z/..", user_id="all") + ] + assert len(results) == 1 + assert results[0]['id'] == '5' + + +@pytest.mark.anyio +@results_filter_mock +async def test_get_results_csv_with_filter(): + """get_results_csv passes filter parameters to API.""" + async with Session() as session: + client = SubscriptionsClient(session, base_url=TEST_URL) + results = [ + res async for res in client.get_results_csv( + "42", completed="2024-01-01T00:00:00Z/..") + ] + rows = list(csv.reader(results)) + assert rows == [['id', 'status'], ['6', 'SUCCESS']] + + +@results_filter_mock +def test_get_results_with_filters_sync(): + """Sync get_results passes filter parameters to API.""" + pl = Planet() + pl.subscriptions._client._base_url = TEST_URL + results = list( + pl.subscriptions.get_results("42", + created="2024-01-01T00:00:00Z/..", + user_id="all")) + assert len(results) == 1 + assert results[0]['id'] == '5' + + paging_cycle_api_mock = respx.mock() # Identical next links is a hangup we want to avoid. From f7c6ba4ea0aacde7ca3a951b81f5bcb51f48834f Mon Sep 17 00:00:00 2001 From: asonnenschein Date: Tue, 24 Mar 2026 20:53:37 -0400 Subject: [PATCH 4/5] fix hallucination --- docs/cli/cli-subscriptions.md | 9 +++-- planet/cli/subscriptions.py | 36 ++++++++++-------- planet/clients/subscriptions.py | 22 +++++------ planet/sync/subscriptions.py | 41 ++++++++++----------- tests/integration/test_subscriptions_api.py | 20 ++++++---- 5 files changed, 66 insertions(+), 62 deletions(-) diff --git a/docs/cli/cli-subscriptions.md b/docs/cli/cli-subscriptions.md index dc8d7ba3..7554e2e6 100644 --- a/docs/cli/cli-subscriptions.md +++ b/docs/cli/cli-subscriptions.md @@ -236,9 +236,9 @@ The `results` command supports filtering on several fields: * `--created`: Filter results by creation time or an interval of creation times. * `--updated`: Filter results by update time or an interval of update times. * `--completed`: Filter results by completion time or an interval of completion times. -* `--user-id`: Filter by user ID. Only available to organization admins. Accepts "all" or a specific user ID. +* `--item-datetime`: Filter results by item datetime or an interval of item datetimes. -Datetime args (`--created`, `--updated`, and `--completed`) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. +Datetime args (`--created`, `--updated`, `--completed`, and `--item-datetime`) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. * A date-time: `2018-02-12T23:20:50Z` * A closed interval: `2018-02-12T00:00:00Z/2018-03-18T12:31:12Z` @@ -266,10 +266,11 @@ planet subscriptions results SUBSCRIPTION_ID \ --created 2024-01-01T00:00:00Z/2024-02-01T00:00:00Z ``` -To see results for all users in your organization (organization admin only): +To see results for imagery captured after a specific date: ```sh -planet subscriptions results SUBSCRIPTION_ID --user-id all +planet subscriptions results SUBSCRIPTION_ID \ + --item-datetime 2024-01-01T00:00:00Z/.. ``` See the Subscriptions API documentation for the [official list of available statuses](https://docs.planet.com/develop/apis/subscriptions/#states--status-descriptions). diff --git a/planet/cli/subscriptions.py b/planet/cli/subscriptions.py index 415952ba..2c20ef6f 100644 --- a/planet/cli/subscriptions.py +++ b/planet/cli/subscriptions.py @@ -449,8 +449,10 @@ async def get_subscription_cmd(ctx, subscription_id, pretty): '--completed', help="""Filter results by completion time or interval. See documentation for examples.""") -@click.option('--user-id', - help="Filter by user ID. Accepts 'all' or a specific user ID.") +@click.option( + '--item-datetime', + help="""Filter results by item datetime or interval. See documentation + for examples.""") @limit @click.pass_context @translate_exceptions @@ -463,7 +465,7 @@ async def list_subscription_results_cmd(ctx, created, updated, completed, - user_id, + item_datetime, limit): """Print the results of a subscription to stdout. @@ -487,21 +489,23 @@ async def list_subscription_results_cmd(ctx, """ async with subscriptions_client(ctx) as client: if csv_flag: - async for result in client.get_results_csv(subscription_id, - status=status, - created=created, - updated=updated, - completed=completed, - user_id=user_id): + async for result in client.get_results_csv( + subscription_id, + status=status, + created=created, + updated=updated, + completed=completed, + item_datetime=item_datetime): click.echo(result) else: - async for result in client.get_results(subscription_id, - status=status, - limit=limit, - created=created, - updated=updated, - completed=completed, - user_id=user_id): + async for result in client.get_results( + subscription_id, + status=status, + limit=limit, + created=created, + updated=updated, + completed=completed, + item_datetime=item_datetime): echo_json(result, pretty) diff --git a/planet/clients/subscriptions.py b/planet/clients/subscriptions.py index 1a0a2e7b..85c23289 100644 --- a/planet/clients/subscriptions.py +++ b/planet/clients/subscriptions.py @@ -526,7 +526,7 @@ async def get_results( created: Optional[str] = None, updated: Optional[str] = None, completed: Optional[str] = None, - user_id: Optional[Union[str, int]] = None) -> AsyncIterator[dict]: + item_datetime: Optional[str] = None) -> AsyncIterator[dict]: """Iterate over results of a Subscription. Notes: @@ -543,10 +543,9 @@ async def get_results( created (str): filter by created time or interval. updated (str): filter by updated time or interval. completed (str): filter by completed time or interval. - user_id (str or int): filter by user ID. Only available to organization admins. - Accepts "all" or a specific user ID. + item_datetime (str): filter by item datetime or interval. - Datetime args (created, updated, completed) can either be a + Datetime args (created, updated, completed, item_datetime) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. @@ -576,8 +575,8 @@ class _ResultsPager(Paged): params['updated'] = updated if completed is not None: params['completed'] = completed - if user_id is not None: - params['user_id'] = user_id + if item_datetime is not None: + params['item_datetime'] = item_datetime url = f'{self._base_url}/{subscription_id}/results' @@ -607,7 +606,7 @@ async def get_results_csv( created: Optional[str] = None, updated: Optional[str] = None, completed: Optional[str] = None, - user_id: Optional[Union[str, int]] = None) -> AsyncIterator[str]: + item_datetime: Optional[str] = None) -> AsyncIterator[str]: """Iterate over rows of results CSV for a Subscription. Parameters: @@ -617,10 +616,9 @@ async def get_results_csv( created (str): filter by created time or interval. updated (str): filter by updated time or interval. completed (str): filter by completed time or interval. - user_id (str or int): filter by user ID. Only available to organization admins. - Accepts "all" or a specific user ID. + item_datetime (str): filter by item datetime or interval. - Datetime args (created, updated, completed) can either be a + Datetime args (created, updated, completed, item_datetime) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. @@ -646,8 +644,8 @@ async def get_results_csv( params['updated'] = updated if completed is not None: params['completed'] = completed - if user_id is not None: - params['user_id'] = user_id + if item_datetime is not None: + params['item_datetime'] = item_datetime # Note: retries are not implemented yet. This project has # retry logic for HTTP requests, but does not handle errors diff --git a/planet/sync/subscriptions.py b/planet/sync/subscriptions.py index afff7fcf..cdbc6827 100644 --- a/planet/sync/subscriptions.py +++ b/planet/sync/subscriptions.py @@ -341,7 +341,7 @@ def get_results( created: Optional[str] = None, updated: Optional[str] = None, completed: Optional[str] = None, - user_id: Optional[Union[str, int]] = None + item_datetime: Optional[str] = None ) -> Iterator[Union[Dict[str, Any], str]]: """Iterate over results of a Subscription. @@ -359,10 +359,9 @@ def get_results( created (str): filter by created time or interval. updated (str): filter by updated time or interval. completed (str): filter by completed time or interval. - user_id (str or int): filter by user ID. Only available to organization admins. - Accepts "all" or a specific user ID. + item_datetime (str): filter by item datetime or interval. - Datetime args (created, updated, completed) can either be a + Datetime args (created, updated, completed, item_datetime) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. @@ -385,20 +384,19 @@ def get_results( created, updated, completed, - user_id)) - - def get_results_csv( - self, - subscription_id: str, - status: Optional[Sequence[Literal["created", - "queued", - "processing", - "failed", - "success"]]] = None, - created: Optional[str] = None, - updated: Optional[str] = None, - completed: Optional[str] = None, - user_id: Optional[Union[str, int]] = None) -> Iterator[str]: + item_datetime)) + + def get_results_csv(self, + subscription_id: str, + status: Optional[Sequence[Literal["created", + "queued", + "processing", + "failed", + "success"]]] = None, + created: Optional[str] = None, + updated: Optional[str] = None, + completed: Optional[str] = None, + item_datetime: Optional[str] = None) -> Iterator[str]: """Iterate over rows of results CSV for a Subscription. Parameters: @@ -408,10 +406,9 @@ def get_results_csv( created (str): filter by created time or interval. updated (str): filter by updated time or interval. completed (str): filter by completed time or interval. - user_id (str or int): filter by user ID. Only available to organization admins. - Accepts "all" or a specific user ID. + item_datetime (str): filter by item datetime or interval. - Datetime args (created, updated, completed) can either be a + Datetime args (created, updated, completed, item_datetime) can either be a date-time or an interval, open or closed. Date and time expressions adhere to RFC 3339. Open intervals are expressed using double-dots. @@ -438,7 +435,7 @@ def get_results_csv( created, updated, completed, - user_id)) + item_datetime)) def get_summary(self) -> Dict[str, Any]: """Summarize the status of all subscriptions via GET. diff --git a/tests/integration/test_subscriptions_api.py b/tests/integration/test_subscriptions_api.py index c431afbe..10d0b9aa 100644 --- a/tests/integration/test_subscriptions_api.py +++ b/tests/integration/test_subscriptions_api.py @@ -836,9 +836,11 @@ def test_get_results_csv_sync(): # More specific routes (multiple params) must come first results_filter_mock.route( M(url__startswith=TEST_URL), - M(params__contains={ - 'created': '2024-01-01T00:00:00Z/..', 'user_id': 'all' - }) + M( + params__contains={ + 'created': '2024-01-01T00:00:00Z/..', + 'item_datetime': '2024-06-01T00:00:00Z/..' + }) ).mock( side_effect=[Response(200, json={ 'results': [{ @@ -886,7 +888,8 @@ def test_get_results_csv_sync(): })]) results_filter_mock.route( - M(url__startswith=TEST_URL), M(params__contains={'user_id': 'all'}) + M(url__startswith=TEST_URL), + M(params__contains={'item_datetime': '2024-06-01T00:00:00Z/..'}) ).mock( side_effect=[Response(200, json={ 'results': [{ @@ -908,7 +911,7 @@ def test_get_results_csv_sync(): "completed": "2024-01-01T00:00:00Z/2024-02-01T00:00:00Z" }, '3'), ({ - "user_id": "all" + "item_datetime": "2024-06-01T00:00:00Z/.." }, '4'), ]) @pytest.mark.anyio @@ -931,8 +934,9 @@ async def test_get_results_with_multiple_filters(): async with Session() as session: client = SubscriptionsClient(session, base_url=TEST_URL) results = [ - res async for res in client.get_results( - "42", created="2024-01-01T00:00:00Z/..", user_id="all") + res async for res in + client.get_results("42", created="2024-01-01T00:00:00Z/..", + item_datetime="2024-06-01T00:00:00Z/..") ] assert len(results) == 1 assert results[0]['id'] == '5' @@ -960,7 +964,7 @@ def test_get_results_with_filters_sync(): results = list( pl.subscriptions.get_results("42", created="2024-01-01T00:00:00Z/..", - user_id="all")) + item_datetime="2024-06-01T00:00:00Z/..")) assert len(results) == 1 assert results[0]['id'] == '5' From f8681d1de044182cb6fe637c6fc36c28117b6f36 Mon Sep 17 00:00:00 2001 From: asonnenschein Date: Tue, 24 Mar 2026 21:09:22 -0400 Subject: [PATCH 5/5] update docstring w/ rfc3339 --- planet/cli/subscriptions.py | 51 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/planet/cli/subscriptions.py b/planet/cli/subscriptions.py index 2c20ef6f..2ad1072c 100644 --- a/planet/cli/subscriptions.py +++ b/planet/cli/subscriptions.py @@ -54,12 +54,11 @@ def subscriptions(ctx, base_url): @pretty @click.option( '--created', - help="""Filter subscriptions by creation time or interval. See documentation - for examples.""") -@click.option( - '--end-time', - help="""Filter subscriptions by end time or interval. See documentation - for examples.""") + help="""Filter subscriptions by creation time or interval (RFC 3339). + See documentation for examples.""") +@click.option('--end-time', + help="""Filter subscriptions by end time or interval (RFC 3339). + See documentation for examples.""") @click.option( '--hosting', type=click.BOOL, @@ -76,8 +75,8 @@ def subscriptions(ctx, base_url): available types. Default is all.""") @click.option( '--start-time', - help="""Filter subscriptions by start time or interval. See documentation - for examples.""") + help="""Filter subscriptions by start time or interval (RFC 3339). + See documentation for examples.""") @click.option( '--status', type=click.Choice([ @@ -102,10 +101,10 @@ def subscriptions(ctx, base_url): Supported fields: [name, created, updated, start_time, end_time]. Example: 'name ASC,created DESC'""") -@click.option('--updated', - help="""Filter subscriptions by update time or interval. See - documentation - for examples.""") +@click.option( + '--updated', + help="""Filter subscriptions by update time or interval (RFC 3339). See + documentation for examples.""") @click.option( '--destination-ref', help="Filter subscriptions created with the provided destination reference." @@ -437,22 +436,18 @@ async def get_subscription_cmd(ctx, subscription_id, pretty): default=False, help="Get subscription results as comma-separated fields. When " "this flag is included, --limit is ignored") -@click.option( - '--created', - help="""Filter results by creation time or interval. See documentation - for examples.""") -@click.option( - '--updated', - help="""Filter results by update time or interval. See documentation - for examples.""") -@click.option( - '--completed', - help="""Filter results by completion time or interval. See documentation - for examples.""") -@click.option( - '--item-datetime', - help="""Filter results by item datetime or interval. See documentation - for examples.""") +@click.option('--created', + help="""Filter results by creation time or interval (RFC 3339). + See documentation for examples.""") +@click.option('--updated', + help="""Filter results by update time or interval (RFC 3339). + See documentation for examples.""") +@click.option('--completed', + help="""Filter results by completion time or interval (RFC 3339). + See documentation for examples.""") +@click.option('--item-datetime', + help="""Filter results by item datetime or interval (RFC 3339). + See documentation for examples.""") @limit @click.pass_context @translate_exceptions