未验证 提交 a9e8225f 编写于 作者: M Maxim Zhiltsov 提交者: GitHub

Fix SDK documentation problems (#5903)

Resolves #5871
Related: https://github.com/opencv/cvat/issues/5847,
https://github.com/opencv/cvat/issues/5814

This PR makes SDK examples valid Python code and adds some missing info.

- Fixed incorrect method names in examples
- Added missing `api_client.` use in method examples
- Fixed invalid return types in examples
- Fixed imports in examples
- Added notes about binary files in low-level API, extra method args and
returned values
- Removed html escapes from method and field descriptions
- Changed function signatures to be closer to the most popular variants
上级 409fac52
......@@ -13,7 +13,13 @@ Method | HTTP request | Description
{{#operations}}
{{#operation}}
## **{{>operation_name}}**
> {{#returnType}}{{{.}}} {{/returnType}}{{>operation_name}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}})
> {{>operation_name}}({{#requiredParams}}{{^defaultValue}}
> {{paramName}},{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}
> {{paramName}}={{{defaultValue}}},{{/defaultValue}}{{/requiredParams}}{{#optionalParams}}
> {{paramName}}=None,{{/optionalParams}}
> **kwargs
> )
{{{summary}}}{{#notes}}
......@@ -26,14 +32,24 @@ Method | HTTP request | Description
{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}}
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}}
{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**](../models/{{baseType}}){{/baseType}}| {{description}} |
{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**](../models/{{baseType}}){{/baseType}}| {{description}} | defaults to {{{.}}}
{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**](../models/{{baseType}}){{/baseType}}| {{description}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}}
{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**](../models/{{baseType}}){{/baseType}}| {{{description}}} |
{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**](../models/{{baseType}}){{/baseType}}| {{{description}}} | defaults to {{{.}}}
{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**](../models/{{baseType}}){{/baseType}}| {{{description}}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}}
{{/optionalParams}}
### Return type
There are also optional kwargs that control the function invocation behavior.
[Read more here](https://opencv.github.io/cvat/docs/api_sdk/sdk/lowlevel-api/#sending-requests).
### Returned values
Returned type: `Tuple[{{>return_type}}, urllib3.HTTPResponse]`.
Returns a tuple with 2 values: `({{#returnType}}parsed_response{{/returnType}}{{^returnType}}None{{/returnType}}, raw_response)`.
{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**](../models/{{returnBaseType}}){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}None (empty response body){{/returnType}}
{{#returnType}}The first value is a model parsed from the response data.{{/returnType}}{{^returnType}}This endpoint does not have any return value, so `None` is always returned as the first value.{{/returnType}}
The second value is the raw response, which can be useful to get response parameters, such as
status code, headers, or raw response data. Read more about invocation parameters
and returned values [here](https://opencv.github.io/cvat/docs/api_sdk/sdk/lowlevel-api/#sending-requests).
### Authorization
......@@ -51,7 +67,7 @@ Name | Type | Description | Notes
| Status code | Description | Response headers |
|-------------|-------------|------------------|
{{#responses}}
**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} |
**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{{description}}} <br> {{/headers}}{{^headers.0}} - {{/headers.0}} |
{{/responses}}
{{/responses.0}}
......
```python
import time
from {{{packageName}}} import Configuration, ApiClient, exceptions
{{#imports}}
{{.}}
{{/imports}}
from pprint import pprint
from {{{packageName}}} import Configuration, ApiClient, exceptions
from {{{packageName}}}.models import *
# Set up an API client
# Read Configuration class docs for more info about parameters and authentication methods
configuration = Configuration(
......@@ -32,7 +30,7 @@ with ApiClient(configuration) as api_client:
{{/optionalParams}}
try:
{{#returnType}}(data, response) = {{/returnType}}%%%make_api_name!!!{{classname}}%%%.{{{operationId}}}({{#requiredParams}}
{{#returnType}}(data, response) = {{/returnType}}api_client.%%%make_api_name!!!{{classname}}%%%.{{>operation_name}}({{#requiredParams}}
{{^defaultValue}}{{paramName}},{{/defaultValue}}{{/requiredParams}}{{#optionalParams}}
{{paramName}}={{paramName}},{{#-last}}
{{/-last}}{{/optionalParams}})
......@@ -40,5 +38,5 @@ with ApiClient(configuration) as api_client:
pprint(data)
{{/returnType}}
except exceptions.ApiException as e:
print("Exception when calling {{classname}}.{{operationId}}: %s\n" % e)
print("Exception when calling {{classname}}.{{>operation_name}}(): %s\n" % e)
```
{{#models}}{{#model}}# {{classname}}
{{#description}}{{&description}}
{{#description}}{{description}}
{{/description}}
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
{{#isEnum}}
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}{{#allowableValues}}{{#defaultValue}}, {{/defaultValue}} must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}}
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{{description}}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}{{#allowableValues}}{{#defaultValue}}, {{/defaultValue}} must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}}
{{/isEnum}}
{{#isAlias}}
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{{description}}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}
{{/isAlias}}
{{#isArray}}
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}){{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}
**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}){{/arrayModelType}} | {{{description}}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}
{{/isArray}}
{{#requiredVars}}
{{^defaultValue}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}){{/complexType}} | {{{description}}} | {{#isReadOnly}}[readonly] {{/isReadOnly}}
{{/defaultValue}}
{{/requiredVars}}
{{#requiredVars}}
{{#defaultValue}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}){{/complexType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}){{/complexType}} | {{{description}}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}}
{{/defaultValue}}
{{/requiredVars}}
{{#optionalVars}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}){{/complexType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}}
**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}){{/complexType}} | {{{description}}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}}
{{/optionalVars}}
{{/model}}{{/models}}
......@@ -292,7 +292,18 @@ class. You can find summary about available API classes and supported endpoints
server endpoints.
By default, all operations return 2 objects: the parsed response data and the response itself.
A typical call looks like this:
The first returned value is a model parsed from the response data. If a method does
not have any return value, `None` is always returned as the first value. You can control
automatic parsing using the `_parse_response` method kwarg. When disabled, `None` is returned.
The second value is the raw response, which can be useful to get response parameters, such as
status code, headers, or raw response data. By default, the status code of the response is
checked to be positive. In the case of request failure, an exception is raised by default.
This behavior can be controlled by the `_check_status` method kwarg. If the status is not
checked, you will need to manually check the response status code and perform actions needed.
A typical endpoint call looks like this:
```python
from cvat_sdk.api_client import ApiClient, apis
......@@ -303,20 +314,28 @@ with ApiClient(...) as api_client:
# process the response ...
```
Operation parameters can be passed as positional or keyword arguments. There are also several
extra arguments which change invocation logic:
Operation parameters can be passed as positional or keyword arguments. API methods provide
extra common arguments which control invocation logic:
- `_parse_response` - Allows to enable and disable response data parsing. When enabled,
- `_parse_response` (`bool`) - Allows to enable and disable response data parsing. When enabled,
the response data is parsed into a model or a basic type and returned as the first value.
When disabled, the response is not parsed, and `None` is returned. Can be useful,
for instance, if you need to parse data manually, or if you expect an error in the response.
- `_check_status` - Allows to enable or disable response status checks. When enabled, the
Default is `True`.
- `_check_status` (`bool`) - Allows to enable or disable response status checks. When enabled, the
response status code is checked to be positive as defined in the [HTTP standards](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes).
In case of negative status, an exception is raised.
- `_request_timeout` - Allows to control timeout
- `_content_type` - Allows to specify the `Content-Type` header value for the request. Endpoints
can support different content types and behave differently depending on the value. For file
uploads `_content_type="multipart/form-data"` must be specified.
In the case of negative status, an exception is raised. Default is `True`.
- `_validate_inputs` (`bool`): specifies if type checking should be done on the data
sent to the server. Default is `True`.
- `_validate_outputs` (`bool`): specifies if type checking should be done on the data
received from the server. Default is `True`.
- `_request_timeout` (`None | int | float | Tuple[int | float, int | float]`) -
Allows to control timeouts. If one number is provided, it will be the total request timeout. It can also
be a tuple with (connection, read) timeouts. Default is `None`, which means no timeout.
- `_content_type` (`None | str`) - Allows to specify the `Content-Type` header value
for the request. Endpoints can support different content types and behave differently
depending on the value. For file uploads `_content_type="multipart/form-data"` must be specified.
Read more about file uploads [here](#sending-data). Default is `application/json`.
> **NOTE**: the API is autogenerated. In some cases the server API schema may be incomplete
or underspecified. Please report to us all the problems found. A typical problem is that a
......@@ -363,3 +382,104 @@ project_tasks = get_paginated_collection(
id=project_id,
)
```
### Binary data in requests and responses
At the moment, sending and receiving binary data - such as files - can be difficult via the
low-level SDK API. Please use the following recommendations.
#### Sending data
By default, requests use the `application/json` content type, which is a text type.
However, it's inefficient to send binary data in this encoding, and the data passed
won't be converted automatically. If you need to send files or other binary data,
please specify `_content_type="multipart/form-data"` in the request parameters:
Example:
```python
(_, response) = api_client.tasks_api.create_data(
id=42,
data_request=models.DataRequest(
client_files=[
open("image.jpg", 'rb')
],
image_quality=70,
),
_content_type="multipart/form-data", # required
)
```
Please also note that if there are complex fields in the data (such as nested lists or dicts),
they, in turn, cannot be encoded as `multipart/form-data`, so the recommended solution is to
split fields into files and others, and send them in different requests with different content
types:
Example:
```python
data = {
'client_files': [...], # a list of binary files
'image_quality': ..., # a simple type - int
'job_file_mapping': [...], # a complex type - list
}
# Initialize uploading
api_client.tasks_api.create_data(
id=42,
data_request=models.DataRequest(image_quality=data["image_quality"]),
upload_start=True,
)
# Upload binary data
api_client.tasks_api.create_data(
id=42,
data_request=models.DataRequest(
client_files=data.pop("client_files"),
image_quality=data["image_quality"],
),
upload_multiple=True,
_content_type="multipart/form-data",
)
# Finalize the uploading and send the remaining fields
api_client.tasks_api.create_data(
id=42,
data_request=models.DataRequest(**data),
upload_finish=True,
)
```
#### Receiving data
Receiving binary files can also be difficult with the low-level API. To avoid unexpected
behavior, it is recommended to specify `_parse_response=False` in the request parameters.
In this case, SDK will not try to parse models from responses, and the response data
can be fetched directly from the response:
```python
from time import sleep
# Export a task as a dataset
while True:
(_, response) = api_client.tasks_api.retrieve_dataset(
id=42,
format='COCO 1.0',
_parse_response=False,
)
if response.status == HTTPStatus.CREATED:
break
sleep(interval)
(_, response) = api_client.tasks_api.retrieve_dataset(
id=42,
format='COCO 1.0',
action="download",
_parse_response=False,
)
# Save the resulting file
with open('output_file', 'wb') as output_file:
output_file.write(response.data)
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册