-
Notifications
You must be signed in to change notification settings - Fork 95
Add client method to Session class #858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It gets a client by name. Resolves #857
@@ -24,7 +24,7 @@ The best way of doing this is wrapping any code that invokes a client class in a | |||
|
|||
```python | |||
async with Session() as session: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I mean by "centers the Session class". Creating one is the first thing we do and it's the manager for the context of a block of code.
from .io import collect | ||
|
||
__all__ = [ | ||
'Auth', | ||
'collect', | ||
'DataClient' | ||
'OrdersClient', | ||
'SubscriptionsClient', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found that this was missing!
planet/http.py
Outdated
# To avoid circular dependency. | ||
from planet.clients.data import DataClient | ||
from planet.clients.orders import OrdersClient | ||
from planet.clients.subscriptions import SubscriptionsClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Session and clients aren't fully decoupled because the client modules import http
. We could fix that in the future if it became important to do so. For now, we can tolerate some imports here. They don't have a significant impact on performance. By the time this method is called, those modules will already have been loaded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to file a ticket for fixing that in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, not now. I'm not sure it's important. I changed the text above to reflect that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: the client modules import http in order to use http.Session in their type hints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw that!
planet/http.py
Outdated
return { | ||
'data': DataClient, | ||
'orders': OrdersClient, | ||
'subscriptions': SubscriptionsClient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I'm statically configuring the mapping between names and clients here. Getting too fancy would be a mistake. We have no plans to have multiple clients per API or support user-supplied client plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at my PR as if I was a reviewer, it occurs to me that this static mapping could be moved to planet/client/__init__.py
. That would let us reduce those 3 imports to 1.
"""Get an exception when no such client exists.""" | ||
session = Session() | ||
with pytest.raises(ClientError): | ||
_ = session.client('bogus') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test coverage of the new code is 100%.
"""Get a client by its module name. | ||
|
||
Parameters: | ||
name: the name of the client module: data, orders, or | ||
subscriptions. | ||
name: one of 'data', 'orders', or 'subscriptions'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This typing hint IS nice! This would be great to use this for all of the other arguments that have a set number of 'valid' entries, we already have them defined either at the top of the client module or in the specs module.
@@ -30,6 +30,7 @@ | |||
'jsonschema', | |||
'pyjwt>=2.1', | |||
'tqdm>=4.56', | |||
'typing-extensions', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This module provides a backport of Literal
for Python 3.7.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment for you, but good to go!
|
||
try: | ||
return client_directory[name](self, base_url=base_url) | ||
return _client_directory[name](self, base_url=base_url) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way the Session class only needs to know that it can get a client with a name, it's not responsible for the directory. Looser coupling.
Restoring the branch, we might be reverting this. |
Reverted pending more discussion. |
This PR looks great and is ready to go. I really like the use of |
It gets a client by the name of the client module.
orders
->planet.clients.orders.OrdersClient
.The intent is to simplify the API for casual users. The API centers the Session class. It feels natural to let Session be a factory for clients. And it goes well with code autocompletion. Type
session.
in VS Code and we get a prompt for.client()
.Type
session.client(
and we get a prompt to call it with a name like data, orders, or subscriptions. Actually, I think the docs could be slightly improved to help even more.The new method is intended to be a convenience for users and documentation writers. The Session and three client classes are not otherwise changed. They don't need to be and much testing implementation hinges on the existing relationship between client classes and Session. The pattern used by
OrdersClient(session)
is a form of dependency injection; it really does make writing good tests easier.The CLI commands are left as they are.
Under docs/, all examples of
client = SomethingClient(session)
have been changed toclient = session.client('something')
.Resolves #857.