-
Notifications
You must be signed in to change notification settings - Fork 21
Support Advanced Usages #33
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
5767d6c to
3852c55
Compare
|
@steve148 Do you have any idea why is the discrepancy with Black? Maybe, due to different versions being used?
|
3852c55 to
8a6da93
Compare
| self.endpoint, | ||
| json=request_body, | ||
| headers=self.__request_headers(headers), | ||
| self.endpoint, json=request_body, headers={**self.headers, **headers}, |
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.
options should be passed here as well. right ?
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.
aiohttp support auth argument.
https://docs.aiohttp.org/en/stable/client_reference.html
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.
Good point but I didn't add the options parameter to the exectue_async method intentionally in this PR to limit the scope to configuring the requests library. To expand the scope to cover the aiohttp library, I think we should consider that these two libraries can take options through the different parameter names. In case of auth, they use the same parameter name but aiohttp uses veryfy_ssl while requests uses verify for SSL cert verification. So, I'd like to tackle this separately after giving it some consideration unless you need this feature right now.
sreerajkksd
left a comment
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.
https://docs.aiohttp.org/en/stable/client_reference.html
options should be passed to aiohttp session as well. Otherwise, looks good.
|
@DaleSeo latest version of black gave me this. |
Yeah, I'm still trying to figure out why my VSCode auto-formats differently from the command line 😞 . |
masudias
left a comment
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.
Looks good to me! Thank you so much for the changes!!
Can you please update the README and provide an example of how we can turn off SSL verification and provide auth to our request? That would help other developers to find the options easily.
Again, thanks so much!
|
@sreerajkksd Fixed the formatting issues by updating pre-commit hooks so that the same latest version of Black is used by the pre-commit, on my terminal and IDE. ➜ python-graphql-client git:(support-options) ✗ pre-commit autoupdate
Updating https://github.com/psf/black ... [INFO] Initializing environment for https://github.com/psf/black.
updating stable -> 20.8b1.
Updating https://gitlab.com/pycqa/flake8 ... [INFO] Initializing environment for https://gitlab.com/pycqa/flake8.
updating -> 3.8.4. |
|
@masudias Thanks for the feedback. I've added the Advanced Usage section to README. Hope it helps clarify how to use this library. Please feel free to improve the docs if you want it to be more clear. |
| """Class which represents the interface to make graphQL requests through.""" | ||
|
|
||
| def __init__(self, endpoint: str, headers: dict = None): | ||
| def __init__(self, endpoint: str, headers: dict = {}, options: dict = {}): |
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 have a preference for options over **kwargs here? I think storing it on the instance as options still makes sense.
So this function would turn into:
def __init__(self, endpoint: str, headers: dict = {}, **kwargs: int):
...
self.options = kwargsAnd the execute function changes to:
def execute(
self,
query: str,
variables: dict = None,
operation_name: str = None,
headers: dict = None,
**kwargs: int,
):
...
result = requests.post(
...
**{self.options, **kwargs}
)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.
@steve148 I considered the following three approaches.
verify: bool, cert: Union[str, Sequence[str]], auth: ...options: dict = {}**kwargs: Any
I decided on the second option because the first option wasn't scalable and the third option, I would say, felt too flexible/generous and potentially, will get in our way when we want to add other parameters in the future.
I found the second option most balanced and explicit but I don't feel strongly about it.
Please let me know if you see any upsides in using **kwargs in this case.
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.
Option number 1 is definitely too rigid, we definitely don't want to be maintaining an exact replica of the arguments allowed by the different libraries we use under the hood.
I personally feel like **kwargs is a better choice of options since **kwargs is the more commonly used pattern for creating flexible functions in python. I would rather use the more common pattern over one that we come up with just for this project.
From my view, execute is just a nice wrapper overtop of requests.post. The distinguishing arguments to execute are query, variables, and operation_name. Looking at it now, headers isn't related to graphql but instead comes from the requests library. This will cause a breaking change in this function's interface, but headers should probably be made part of the **kwargs in the future after this change lands.
Either way, I think going forward we should split arguments into two groups:
- Arguments like
querywhich are related to graphql and the functionality this project provides. These arguments should be defined individually in each function (akadef execute(query: str, ...): - Arguments like
verifywhich are related to the underlying communication protocol and aren't specific to graphql or this library. These arguments should be defined as a group in**kwargsso the interface is flexible to changes to the underlying library.
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.
@steve148 That makes sense. I updated the API to use **kwargs as you suggested. I'm not sure how we can also take headers through **kwargs in the future. Would it be easy to determine which argument should be treated as headers and which ones should not when everything is passed together?
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.
🙏 thanks @DaleSeo! I'm probaably thinking a few too many steps ahead when I mention headers being part of **kwargs. One core piece of functionality we do have right now is being able to set headers on the class instance which gets used by all calls. This was pretty useful to us and probably isn't something we want to get rid of.
My thinking would be you could still set headers the class instantation and in the method call.
client = GraphqlClient(..., headers={ 'shared_key': 'shared_value' })
client.execute(..., headers={'another_key': 'another_value'})And then the HTTP call would be a merge of the two dictionaries
requests.post(..., headers={'shared_key': 'shared_value', 'another_key': 'another_value'})I think something like the following would achieve this idea https://stackoverflow.com/questions/20656135/python-deep-merge-dictionary-data. At the same time, this is starting to get complex and may not align with the goal of this project to be a simple graphql client.
|
|
||
| ### Custom Authentication | ||
|
|
||
| ```py |
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.
TIL py can be used as shorthand for python for markdown code blocks 🤯
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.
haha. I've also updated the other places to use py instead of python to save us a little bit of typing just for consistency.
Co-authored-by: Lennox Stevenson <lennox.stevenson@mail.utoronto.ca>
Co-authored-by: Lennox Stevenson <lennox.stevenson@mail.utoronto.ca>



What kind of change does this PR introduce?
fix #26 fix #32
What is the current behavior?
There's no way to specify additional options to configure the underlying
requestslibrary for advanced usages.What is the new behavior?
A new optional parameter
optionsis added to the constructor and theexecutemethod to support advanced usages like Custom Authentication, SSL Cert Verification and Client Side Certificates.Does this PR introduce a breaking change?
No