-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
[REQ] Python: improve the typing of API clients #16788
Comments
Another option would be to drop the
|
Thanks a lot for looking into this at such detail! With "The REST API client request method", do you actually mean I think the generator should make a decision to only support either I fully support removing Have you considered using |
I suggest to split call_api. @validate_call
def get(self) -> Response:
...
param = self.param_serialize(...)
res = self.api_client.call_api(param)
return self.api_client.response_deserialize(res, ...).data
@validate_call
def get_with_http_info(self) -> ApiResponse[Response]:
...
param = self.param_serialize(...)
res = self.api_client.call_api(param)
return self.api_client.response_deserialize(res, ...)
@validate_call
def get_with_async(self) -> ApiResponse[Response]:
...
param = self.param_serialize(...)
res = self.api_client.call_api_async(param)
return self.api_client.response_deserialize(res, ...) |
@robertschweizer Thanks for the feedback!
I edited the message, sorry for the confusion. By "REST API client", I mean the
As long as we don't really care about typing, we can do these changes in whichever order. It's when we would like to enforce typing correctly that this will matter.
No, I didn't really consider using
The asynchronous requests feature from the synchronous client is very basic: it simply embeds the thread pool to defer requests in a dedicated thread. It should be fairly simple to remove and be reimplemented externally by whoever needs it IMO. |
Would it be too much of a lost if I feel the set of parameters that had to be passed to this method to actually return a That would remove the calls to |
I believe this is similar to the "ApiRequest" I explained in my initial message 👍
I think this call/function can completely be removed from the API client: deserialization doesn't use any state from the class. It would make the code simpler and easier to test. |
As python has added lots of features to its typing in recent years, I would absolutely love to see better typings. I'd love to help whatever way I can, is there any thing I can do? |
@UltimateLobster I think the best would be to keep an eye on #16802, help out if needed and reassess the status once it has been merged. |
Is your feature request related to a problem? Please describe.
In #16694, I tried to add typing information on the generated API clients, but the issues are a bit larger than expected.
Going from bottom (REST client) to up (the model API client):
REST API client
The REST API client
request()
method can return very different type of responses:ApiResponse
, a generic HTTP responseresponse_types_map
: the client can extract the payload of the response and deserialize it into any kind of object if the payload matches the format of that object (so, an int, datetime, or any model; but actually, almost any type)This has several issues:
Model API client
I'm taking a hypothetical
Foo
model with basic CRUD methods as an example, that would produce aFooApi
class.We can find the following kind of methods:
get_foo_by_id
method returning:Foo
(usual case)None
in some cases, sometimes for errors tooget_foo_by_id_with_http_info
, which could return either:ApiResponse
: a generic HTTP responseFoo
model, if_return_http_data_only
isFalse
List[Foo]
, etc. but the mechanism is the same as explained above.In addition, the
urllib3
client can also produce anAsyncResult
with one of the 2 behaviors explained just above.This behavior doesn't exist for the
aiohttp
-based client.This also has several issues, similar to those of the underlying REST Client explained above:
get_foo_by_id
and similar.AsyncResult
responses create additional complexity in the typing of the responses, since it also depends on the parameterasync_req
to be set.Describe the solution you'd like
After some good suggestions from @fa0311, @robertschweizer and @wing328 , I'd like to make the propose the following changes:
Remove all the parameters that change the response type and move the associated behaviors somewhere else:
Remove
_return_http_data_only
Remove the deserialization behavior away from the
RESTClientObject
class and move it into thexxx()
methods of the model API client:1. The
xxx_with_http_info()
methods would not be able to deserialize the response to high-level objects anymore2. The
xxx_with_http_info()
methods would only returnApiResponse
s object instead3. The deserialization logic would be moved outside of the REST Client:
1. It actually doesn't have any state and could be free functions instead.
2. This can all be moved to a dedicated
deserialization
module.Remove
async_req
Extract the
AsyncResult
into dedicated*_async()
methods.xxx()
+xxx_with_http_info()
methods, this would add 2 new methods:xxx_async()
xxx_with_http_info_async()
AsyncResult
object.xxx()
/xxx_async()
andxxx_with_http_info()
/xxx_with_http_info_async()
:xxx()
method would be moved into a_xxx_deserialization()
methodxxx()
would call this method directly before returning its resultxxx_async()
would call this method when the result is fetched.Create a new
ApiRequest
objectFinally, to makes it easier to reuse the code between the sync/async methods, I'd like to introduce a new
ApiRequest
object:*_with_http_info()
would be moved to a dedicated "private" methodApiRequest
object containing the right parameters to execute the requestxxx_with_http_info()
and thexxx_with_http_info_async()
methodsApiRequest
object and uses whatever it needs from that.Additional context
These changes are not really backward compatible. All the parameters removed will not be supported anymore.
Each changes could be done separately, although the typing benefits would only be seen once all the changes have been done
Ideally, the best order would be:
ApiRequest
object and use it both from the*_with_http_info()
methods and the REST Client. The REST Client can be kept backward compatible for the time being.async_req
can be extracted then be extracted. This simply duplicates the methods, removes the parameter and reuses theApiRequest
created above.The text was updated successfully, but these errors were encountered: