Skip to content

Commit 1f74347

Browse files
authored
Merge pull request #858 from planetlabs/issue857
Add client method to Session class
2 parents 7c4d4d1 + 977d51a commit 1f74347

File tree

8 files changed

+79
-13
lines changed

8 files changed

+79
-13
lines changed

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2.0b2 (TBD)
2+
3+
Added:
4+
- The Session class can now construct clients by name with its client method
5+
(#858).
6+
17
2.0.0-beta.1 (2022-12-07)
28

39
Changed:

docs/get-started/upgrading.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ The best way of doing this is wrapping any code that invokes a client class in a
2424

2525
```python
2626
async with Session() as session:
27-
client = OrdersClient(session)
27+
client = session.client('orders')
2828
result = await client.create_order(order)
2929
# Process result
3030
```
@@ -40,12 +40,12 @@ In V2, all `*Client` methods (for example, `DataClient().search`, `OrderClient()
4040
```python
4141
import asyncio
4242
from datetime import datetime
43-
from planet import Session, DataClient
43+
from planet import Session
4444
from planet import data_filter as filters
4545

4646
async def do_search():
4747
async with Session() as session:
48-
client = DataClient(session)
48+
client = session.client('data')
4949
date_filter = filters.date_range_filter('acquired', gte=datetime.fromisoformat("2022-11-18"), lte=datetime.fromisoformat("2022-11-21"))
5050
cloud_filter = filters.range_filter('cloud_cover', lte=0.1)
5151
download_filter = filters.permission_filter()
@@ -74,11 +74,11 @@ Is now
7474

7575
```python
7676
async with Session() as session:
77-
items = [i async for i in planet.DataClient(session).search(["PSScene"], all_filters)]
77+
items = [i async for i in session.client('data').search(["PSScene"], all_filters)]
7878
```
7979

8080
## Orders API
8181

82-
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`.)
82+
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 `OrdersClient(session).create_order`. (As with the `DataClient`, you must also use `async` and `Session` with `OrdersClient`.)
8383

8484
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).

docs/python/sdk-guide.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ from planet import OrdersClient
116116

117117
async def main():
118118
async with Session() as sess:
119-
client = OrdersClient(sess)
119+
client = sess.client('orders')
120120
# perform operations here
121121

122122
asyncio.run(main())
@@ -198,7 +198,7 @@ the context of a `Session` with the `OrdersClient`:
198198
```python
199199
async def main():
200200
async with Session() as sess:
201-
cl = OrdersClient(sess)
201+
cl = sess.client('orders')
202202
order = await cl.create_order(request)
203203

204204
asyncio.run(main())
@@ -222,7 +222,7 @@ from planet import reporting
222222

223223
async def create_wait_and_download():
224224
async with Session() as sess:
225-
cl = OrdersClient(sess)
225+
cl = sess.client('orders')
226226
with reporting.StateBar(state='creating') as bar:
227227
# create order
228228
order = await cl.create_order(request)
@@ -272,7 +272,7 @@ from planet import collect, OrdersClient, Session
272272

273273
async def main():
274274
async with Session() as sess:
275-
client = OrdersClient(sess)
275+
client = sess.client('orders')
276276
orders_list = collect(client.list_orders())
277277

278278
asyncio.run(main())
@@ -297,7 +297,7 @@ from planet import DataClient
297297

298298
async def main():
299299
async with Session() as sess:
300-
client = DataClient(sess)
300+
client = sess.client('data')
301301
# perform operations here
302302

303303
asyncio.run(main())
@@ -344,7 +344,7 @@ the context of a `Session` with the `DataClient`:
344344
```python
345345
async def main():
346346
async with Session() as sess:
347-
cl = DataClient(sess)
347+
cl = sess.client('data')
348348
items = [i async for i in cl.search(['PSScene'], sfilter)]
349349

350350
asyncio.run(main())
@@ -364,7 +364,7 @@ print command to report wait status. `download_asset` has reporting built in.
364364
```python
365365
async def download_and_validate():
366366
async with Session() as sess:
367-
cl = DataClient(sess)
367+
cl = sess.client('data')
368368

369369
# get asset description
370370
item_type_id = 'PSScene'

planet/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
from . import order_request, reporting
1717
from .__version__ import __version__ # NOQA
1818
from .auth import Auth
19-
from .clients import DataClient, OrdersClient # NOQA
19+
from .clients import DataClient, OrdersClient, SubscriptionsClient # NOQA
2020
from .io import collect
2121

2222
__all__ = [
2323
'Auth',
2424
'collect',
2525
'DataClient'
2626
'OrdersClient',
27+
'SubscriptionsClient',
2728
'order_request',
2829
'reporting',
2930
'Session',

planet/clients/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,20 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15+
1516
from .data import DataClient
1617
from .orders import OrdersClient
18+
from .subscriptions import SubscriptionsClient
1719

1820
__all__ = [
1921
'DataClient',
2022
'OrdersClient',
23+
'SubscriptionsClient',
2124
]
25+
26+
# Organize client classes by their module name to allow concise lookup.
27+
_client_directory = {
28+
'data': DataClient,
29+
'orders': OrdersClient,
30+
'subscriptions': SubscriptionsClient
31+
}

planet/http.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
import random
2323
import time
2424
from typing import AsyncGenerator, Optional
25+
2526
import httpx
27+
from typing_extensions import Literal
2628

2729
from .auth import Auth, AuthType
2830
from . import exceptions, models
@@ -413,6 +415,29 @@ async def stream(
413415
finally:
414416
await response.aclose()
415417

418+
def client(self,
419+
name: Literal['data', 'orders', 'subscriptions'],
420+
base_url: Optional[str] = None) -> object:
421+
"""Get a client by its module name.
422+
423+
Parameters:
424+
name: one of 'data', 'orders', or 'subscriptions'.
425+
426+
Returns:
427+
A client instance.
428+
429+
Raises:
430+
ClientError when no such client can be had.
431+
432+
"""
433+
# To avoid circular dependency.
434+
from planet.clients import _client_directory
435+
436+
try:
437+
return _client_directory[name](self, base_url=base_url)
438+
except KeyError:
439+
raise exceptions.ClientError("No such client.")
440+
416441

417442
class AuthSession(BaseSession):
418443
"""Synchronous connection to the Planet Auth service."""

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
'jsonschema',
3131
'pyjwt>=2.1',
3232
'tqdm>=4.56',
33+
'typing-extensions',
3334
]
3435

3536
test_requires = ['pytest', 'pytest-asyncio==0.16', 'pytest-cov', 'respx==0.19']

tests/unit/test_session.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Session module tests."""
2+
3+
import pytest
4+
5+
from planet import DataClient, OrdersClient, SubscriptionsClient, Session
6+
from planet.exceptions import ClientError
7+
8+
9+
@pytest.mark.parametrize("client_name,client_class",
10+
[('data', DataClient), ('orders', OrdersClient),
11+
('subscriptions', SubscriptionsClient)])
12+
def test_session_get_client(client_name, client_class):
13+
"""Get a client from a session."""
14+
session = Session()
15+
client = session.client(client_name)
16+
assert isinstance(client, client_class)
17+
18+
19+
def test_session_get_client_error():
20+
"""Get an exception when no such client exists."""
21+
session = Session()
22+
with pytest.raises(ClientError):
23+
_ = session.client('bogus')

0 commit comments

Comments
 (0)