Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
python sync and async cli with tests
  • Loading branch information
charcey committed Jul 17, 2025
commit e8e4f9ee4b1358cf8620d7e119b450c83b4319a4
3 changes: 2 additions & 1 deletion planet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from . import data_filter, order_request, reporting, subscription_request
from .__version__ import __version__ # NOQA
from .auth import Auth
from .clients import DataClient, FeaturesClient, OrdersClient, SubscriptionsClient # NOQA
from .clients import DataClient, DestinationsClient, FeaturesClient, OrdersClient, SubscriptionsClient # NOQA
from .io import collect
from .sync import Planet

Expand All @@ -25,6 +25,7 @@
'collect',
'DataClient',
'data_filter',
'DestinationsClient',
'FeaturesClient',
'OrdersClient',
'order_request',
Expand Down
4 changes: 3 additions & 1 deletion planet/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from .data import DataClient
from .destinations import DestinationsClient
from .features import FeaturesClient
from .orders import OrdersClient
from .subscriptions import SubscriptionsClient

__all__ = [
'DataClient', 'FeaturesClient', 'OrdersClient', 'SubscriptionsClient'
'DataClient', 'DestinationsClient', 'FeaturesClient', 'OrdersClient', 'SubscriptionsClient'
]

# Organize client classes by their module name to allow lookup.
_client_directory = {
'data': DataClient,
'destinations': DestinationsClient,
'features': FeaturesClient,
'orders': OrdersClient,
'subscriptions': SubscriptionsClient
Expand Down
178 changes: 178 additions & 0 deletions planet/clients/destinations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Copyright 2025 Planet Labs PBC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import logging
from typing import Any, AsyncIterator, Dict, Optional, Union, TypeVar

from planet.clients.base import _BaseClient
from planet.exceptions import APIError, ClientError
from planet.http import Session
from ..constants import PLANET_BASE_URL


BASE_URL = f'{PLANET_BASE_URL}/public/destinations/v1/'

LOGGER = logging.getLogger()

T = TypeVar("T")

class DestinationsClient(_BaseClient):
"""Asynchronous Destinations API client.

Example:
```python
>>> import asyncio
>>> from planet import Session
>>>
>>> async def main():
... async with Session() as sess:
... cl = sess.client('destinations')
... # use client here
...
>>> asyncio.run(main())
```
"""

def __init__(self,
session: Session,
base_url: Optional[str] = None) -> None:
"""
Parameters:
session: Open session connected to server.
base_url: The base URL to use. Defaults to production destinations
API base url.
"""
super().__init__(session, base_url or BASE_URL)

async def list_destinations(self,
archived: Optional[bool] = None,
is_owner: Optional[bool] = None,
can_write: Optional[bool] = None,
) -> Dict:
"""
List all destinations. By default, all non-archived destinations in the requesting user's org are returned.

Args:
archived (bool): If True, include archived destinations.
is_owner (bool): If True, include only destinations owned by the requesting user.
can_write (bool): If True, include only destinations the requesting user can modify.

Returns:
dict: A dictionary containing the list of destinations inside the 'destinations' key.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
params: Dict[str, Any] = {}
if archived is not None:
params["archived"] = archived
if is_owner is not None:
params["is_owner"] = is_owner
if can_write is not None:
params["can_write"] = can_write

try:
response = await self._session.request(method='GET',
url=self._base_url,
params=params)
except APIError:
raise
except ClientError: # pragma: no cover
raise
else:
dest_response = response.json()
return dest_response

async def get_destination(self, destination_id: str) -> Dict:
"""
Get a specific destination by its ID.

Args:
destination_id (str): The ID of the destination to retrieve.

Returns:
dict: A dictionary containing the destination details.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/{destination_id}'
try:
response = await self._session.request(method='GET',
url=url)
except APIError:
raise
except ClientError: # pragma: no cover
raise
else:
dest = response.json()
return dest

async def patch_destination(self,
destination_ref: str,
request: Dict[str, Any]) -> Dict:
"""
Update a specific destination by its ref.

Args:
destination_ref (str): The ref of the destination to update.
request (dict): Destination content to update, only attributes to update are required.

Returns:
dict: A dictionary containing the updated destination details.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/{destination_ref}'
try:
response = await self._session.request(method='PATCH',
url=url,
json=request)
except APIError:
raise
except ClientError: # pragma: no cover
raise
else:
dest = response.json()
return dest

async def create_destination(self, request: Dict[str, Any]) -> Dict:
"""
Create a new destination.

Args:
data (dict): Destination content to create, all attributes are required.

Returns:
dict: A dictionary containing the created destination details.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
try:
response = await self._session.request(method='POST',
url=self._base_url,
json=request)
except APIError:
raise
except ClientError: # pragma: no cover
raise
else:
dest = response.json()
return dest
3 changes: 3 additions & 0 deletions planet/sync/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .features import FeaturesAPI
from .data import DataAPI
from .destinations import DestinationsAPI
from .orders import OrdersAPI
from .subscriptions import SubscriptionsAPI
from planet.http import Session
Expand All @@ -18,6 +19,7 @@ class Planet:
Members:

- `data`: for interacting with the Planet Data API.
- `destinations`: Destinations API.
- `orders`: Orders API.
- `subscriptions`: Subscriptions API.
- `features`: Features API
Expand Down Expand Up @@ -48,6 +50,7 @@ def __init__(self, session: Optional[Session] = None) -> None:
})

self.data = DataAPI(self._session)
self.destinations = DestinationsAPI(self._session)
self.orders = OrdersAPI(self._session)
self.subscriptions = SubscriptionsAPI(self._session)
self.features = FeaturesAPI(self._session)
114 changes: 114 additions & 0 deletions planet/sync/destinations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Copyright 2025 Planet Labs PBC.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

from typing import Any, Dict, Optional
from planet.clients.destinations import DestinationsClient
from planet.http import Session

class DestinationsAPI:

_client: DestinationsClient

def __init__(self, session: Session, base_url: Optional[str] = None):
"""
Parameters:
session: Open session connected to server.
base_url: The base URL to use. Defaults to production Destinations API
base url.
"""

self._client = DestinationsClient(session, base_url)


def list_destinations(self,
archived: Optional[bool] = None,
is_owner: Optional[bool] = None,
can_write: Optional[bool] = None,
) -> Dict:
"""
List all destinations. By default, all non-archived destinations in the requesting user's org are returned.

Args:
archived (bool): If True, include archived destinations.
is_owner (bool): If True, include only destinations owned by the requesting user.
can_write (bool): If True, include only destinations the requesting user can modify.

Returns:
dict: A dictionary containing the list of destinations inside the 'destinations' key.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
return self._client._call_sync(
self._client.list_destinations(archived,
is_owner,
can_write))

def get_destination(self, destination_id: str) -> Dict:
"""
Get a specific destination by its ID.

Args:
destination_id (str): The ID of the destination to retrieve.

Returns:
dict: A dictionary containing the destination details.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
return self._client._call_sync(
self._client.get_destination(destination_id)
)

def patch_destination(self,
destination_ref: str,
request: Dict[str, Any]) -> Dict:
"""
Update a specific destination by its ref.

Args:
destination_ref (str): The ref of the destination to update.
request (dict): Destination content to update, only attributes to update are required.

Returns:
dict: A dictionary containing the updated destination details.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
return self._client._call_sync(
self._client.patch_destination(destination_ref, request)
)

def create_destination(self, request: Dict[str, Any]) -> Dict:
"""
Create a new destination.

Args:
data (dict): Destination content to create, all attributes are required.

Returns:
dict: A dictionary containing the created destination details.

Raises:
APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
return self._client._call_sync(
self._client.create_destination(request)
)
Loading