forked from loafle/openapi-generator-original
[python-experimental] fixes json + charset use case (#12114)
* Adds code to detect json content type when charset is also set * Updates template to properly render content type, regenerates samples * Adds test_json_with_charset * Reverts version file * Fixes typo
This commit is contained in:
parent
d17316e8d9
commit
b29b5e1045
@ -719,7 +719,20 @@ class ApiResponseWithoutDeserialization(ApiResponse):
|
|||||||
headers: typing.Union[Unset, typing.List[HeaderParameter]] = unset
|
headers: typing.Union[Unset, typing.List[HeaderParameter]] = unset
|
||||||
|
|
||||||
|
|
||||||
class OpenApiResponse:
|
class JSONDetector:
|
||||||
|
@staticmethod
|
||||||
|
def content_type_is_json(content_type: str) -> bool:
|
||||||
|
"""
|
||||||
|
for when content_type strings also include charset info like:
|
||||||
|
application/json; charset=UTF-8
|
||||||
|
"""
|
||||||
|
content_type_piece = content_type.split(';')[0]
|
||||||
|
if content_type_piece == 'application/json':
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class OpenApiResponse(JSONDetector):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
response_cls: typing.Type[ApiResponse] = ApiResponse,
|
response_cls: typing.Type[ApiResponse] = ApiResponse,
|
||||||
@ -734,8 +747,8 @@ class OpenApiResponse:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __deserialize_json(response: urllib3.HTTPResponse) -> typing.Any:
|
def __deserialize_json(response: urllib3.HTTPResponse) -> typing.Any:
|
||||||
decoded_data = response.data.decode("utf-8")
|
# python must be >= 3.9 so we can pass in bytes into json.loads
|
||||||
return json.loads(decoded_data)
|
return json.loads(response.data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]:
|
def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]:
|
||||||
@ -796,7 +809,7 @@ class OpenApiResponse:
|
|||||||
deserialized_body = unset
|
deserialized_body = unset
|
||||||
streamed = response.supports_chunked_reads()
|
streamed = response.supports_chunked_reads()
|
||||||
if self.content is not None:
|
if self.content is not None:
|
||||||
if content_type == 'application/json':
|
if self.content_type_is_json(content_type):
|
||||||
body_data = self.__deserialize_json(response)
|
body_data = self.__deserialize_json(response)
|
||||||
elif content_type == 'application/octet-stream':
|
elif content_type == 'application/octet-stream':
|
||||||
body_data = self.__deserialize_application_octet_stream(response)
|
body_data = self.__deserialize_application_octet_stream(response)
|
||||||
@ -1245,7 +1258,7 @@ class SerializedRequestBody(typing.TypedDict, total=False):
|
|||||||
fields: typing.Tuple[typing.Union[RequestField, tuple[str, str]], ...]
|
fields: typing.Tuple[typing.Union[RequestField, tuple[str, str]], ...]
|
||||||
|
|
||||||
|
|
||||||
class RequestBody(StyleFormSerializer):
|
class RequestBody(StyleFormSerializer, JSONDetector):
|
||||||
"""
|
"""
|
||||||
A request body parameter
|
A request body parameter
|
||||||
content: content_type to MediaType Schema info
|
content: content_type to MediaType Schema info
|
||||||
@ -1382,7 +1395,7 @@ class RequestBody(StyleFormSerializer):
|
|||||||
cast_in_data = media_type.schema(in_data)
|
cast_in_data = media_type.schema(in_data)
|
||||||
# TODO check for and use encoding if it exists
|
# TODO check for and use encoding if it exists
|
||||||
# and content_type is multipart or application/x-www-form-urlencoded
|
# and content_type is multipart or application/x-www-form-urlencoded
|
||||||
if content_type == 'application/json':
|
if self.content_type_is_json(content_type):
|
||||||
return self.__serialize_json(cast_in_data)
|
return self.__serialize_json(cast_in_data)
|
||||||
elif content_type == 'text/plain':
|
elif content_type == 'text/plain':
|
||||||
return self.__serialize_text_plain(cast_in_data)
|
return self.__serialize_text_plain(cast_in_data)
|
||||||
|
@ -182,7 +182,7 @@ class RequestCookieParams(RequestRequiredCookieParams, RequestOptionalCookiePara
|
|||||||
request_body_{{paramName}} = api_client.RequestBody(
|
request_body_{{paramName}} = api_client.RequestBody(
|
||||||
content={
|
content={
|
||||||
{{#each content}}
|
{{#each content}}
|
||||||
'{{@key}}': api_client.MediaType(
|
'{{{@key}}}': api_client.MediaType(
|
||||||
schema={{this.schema.baseName}}),
|
schema={{this.schema.baseName}}),
|
||||||
{{/each}}
|
{{/each}}
|
||||||
},
|
},
|
||||||
@ -323,7 +323,7 @@ _response_for_{{code}} = api_client.OpenApiResponse(
|
|||||||
{{#if @first}}
|
{{#if @first}}
|
||||||
content={
|
content={
|
||||||
{{/if}}
|
{{/if}}
|
||||||
'{{@key}}': api_client.MediaType(
|
'{{{@key}}}': api_client.MediaType(
|
||||||
schema={{this.schema.baseName}}),
|
schema={{this.schema.baseName}}),
|
||||||
{{#if @last}}
|
{{#if @last}}
|
||||||
},
|
},
|
||||||
@ -351,7 +351,7 @@ _status_code_to_response = {
|
|||||||
{{#if @first}}
|
{{#if @first}}
|
||||||
_all_accept_content_types = (
|
_all_accept_content_types = (
|
||||||
{{/if}}
|
{{/if}}
|
||||||
'{{this.mediaType}}',
|
'{{{this.mediaType}}}',
|
||||||
{{#if @last}}
|
{{#if @last}}
|
||||||
)
|
)
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -382,7 +382,7 @@ class {{operationIdCamelCase}}(api_client.Api):
|
|||||||
{{#with bodyParam}}
|
{{#with bodyParam}}
|
||||||
{{#each content}}
|
{{#each content}}
|
||||||
{{#if @first}}
|
{{#if @first}}
|
||||||
content_type: str = '{{@key}}',
|
content_type: str = '{{{@key}}}',
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/with}}
|
{{/with}}
|
||||||
|
@ -1530,6 +1530,22 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: ok
|
description: ok
|
||||||
|
'/fake/jsonWithCharset':
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- fake
|
||||||
|
summary: json with charset tx and rx
|
||||||
|
operationId: jsonWithCharset
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json; charset=utf-8:
|
||||||
|
schema: {}
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: success
|
||||||
|
content:
|
||||||
|
application/json; charset=utf-8:
|
||||||
|
schema: {}
|
||||||
servers:
|
servers:
|
||||||
- url: 'http://{server}.swagger.io:{port}/v2'
|
- url: 'http://{server}.swagger.io:{port}/v2'
|
||||||
description: petstore server
|
description: petstore server
|
||||||
|
@ -100,6 +100,7 @@ Class | Method | HTTP request | Description
|
|||||||
*FakeApi* | [**inline_additional_properties**](docs/FakeApi.md#inline_additional_properties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
|
*FakeApi* | [**inline_additional_properties**](docs/FakeApi.md#inline_additional_properties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
|
||||||
*FakeApi* | [**inline_composition**](docs/FakeApi.md#inline_composition) | **POST** /fake/inlineComposition/ | testing composed schemas at inline locations
|
*FakeApi* | [**inline_composition**](docs/FakeApi.md#inline_composition) | **POST** /fake/inlineComposition/ | testing composed schemas at inline locations
|
||||||
*FakeApi* | [**json_form_data**](docs/FakeApi.md#json_form_data) | **GET** /fake/jsonFormData | test json serialization of form data
|
*FakeApi* | [**json_form_data**](docs/FakeApi.md#json_form_data) | **GET** /fake/jsonFormData | test json serialization of form data
|
||||||
|
*FakeApi* | [**json_with_charset**](docs/FakeApi.md#json_with_charset) | **POST** /fake/jsonWithCharset | json with charset tx and rx
|
||||||
*FakeApi* | [**mammal**](docs/FakeApi.md#mammal) | **POST** /fake/refs/mammal |
|
*FakeApi* | [**mammal**](docs/FakeApi.md#mammal) | **POST** /fake/refs/mammal |
|
||||||
*FakeApi* | [**number_with_validations**](docs/FakeApi.md#number_with_validations) | **POST** /fake/refs/number |
|
*FakeApi* | [**number_with_validations**](docs/FakeApi.md#number_with_validations) | **POST** /fake/refs/number |
|
||||||
*FakeApi* | [**object_in_query**](docs/FakeApi.md#object_in_query) | **GET** /fake/objInQuery | user list
|
*FakeApi* | [**object_in_query**](docs/FakeApi.md#object_in_query) | **GET** /fake/objInQuery | user list
|
||||||
|
@ -20,6 +20,7 @@ Method | HTTP request | Description
|
|||||||
[**inline_additional_properties**](FakeApi.md#inline_additional_properties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
|
[**inline_additional_properties**](FakeApi.md#inline_additional_properties) | **POST** /fake/inline-additionalProperties | test inline additionalProperties
|
||||||
[**inline_composition**](FakeApi.md#inline_composition) | **POST** /fake/inlineComposition/ | testing composed schemas at inline locations
|
[**inline_composition**](FakeApi.md#inline_composition) | **POST** /fake/inlineComposition/ | testing composed schemas at inline locations
|
||||||
[**json_form_data**](FakeApi.md#json_form_data) | **GET** /fake/jsonFormData | test json serialization of form data
|
[**json_form_data**](FakeApi.md#json_form_data) | **GET** /fake/jsonFormData | test json serialization of form data
|
||||||
|
[**json_with_charset**](FakeApi.md#json_with_charset) | **POST** /fake/jsonWithCharset | json with charset tx and rx
|
||||||
[**mammal**](FakeApi.md#mammal) | **POST** /fake/refs/mammal |
|
[**mammal**](FakeApi.md#mammal) | **POST** /fake/refs/mammal |
|
||||||
[**number_with_validations**](FakeApi.md#number_with_validations) | **POST** /fake/refs/number |
|
[**number_with_validations**](FakeApi.md#number_with_validations) | **POST** /fake/refs/number |
|
||||||
[**object_in_query**](FakeApi.md#object_in_query) | **GET** /fake/objInQuery | user list
|
[**object_in_query**](FakeApi.md#object_in_query) | **GET** /fake/objInQuery | user list
|
||||||
@ -1618,6 +1619,87 @@ No authorization required
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **json_with_charset**
|
||||||
|
> bool, date, datetime, dict, float, int, list, str, none_type json_with_charset()
|
||||||
|
|
||||||
|
json with charset tx and rx
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```python
|
||||||
|
import petstore_api
|
||||||
|
from petstore_api.api import fake_api
|
||||||
|
from pprint import pprint
|
||||||
|
# Defining the host is optional and defaults to http://petstore.swagger.io:80/v2
|
||||||
|
# See configuration.py for a list of all supported configuration parameters.
|
||||||
|
configuration = petstore_api.Configuration(
|
||||||
|
host = "http://petstore.swagger.io:80/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Enter a context with an instance of the API client
|
||||||
|
with petstore_api.ApiClient(configuration) as api_client:
|
||||||
|
# Create an instance of the API class
|
||||||
|
api_instance = fake_api.FakeApi(api_client)
|
||||||
|
|
||||||
|
# example passing only optional values
|
||||||
|
body = None
|
||||||
|
try:
|
||||||
|
# json with charset tx and rx
|
||||||
|
api_response = api_instance.json_with_charset(
|
||||||
|
body=body,
|
||||||
|
)
|
||||||
|
pprint(api_response)
|
||||||
|
except petstore_api.ApiException as e:
|
||||||
|
print("Exception when calling FakeApi->json_with_charset: %s\n" % e)
|
||||||
|
```
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
body | typing.Union[SchemaForRequestBodyApplicationJsonCharsetutf8, Unset] | optional, default is unset |
|
||||||
|
content_type | str | optional, default is 'application/json; charset=utf-8' | Selects the schema and serialization of the request body
|
||||||
|
accept_content_types | typing.Tuple[str] | default is ('application/json; charset=utf-8', ) | Tells the server the content type(s) that are accepted by the client
|
||||||
|
stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
|
||||||
|
timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
|
||||||
|
skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
|
||||||
|
|
||||||
|
### body
|
||||||
|
|
||||||
|
#### SchemaForRequestBodyApplicationJsonCharsetutf8
|
||||||
|
|
||||||
|
Type | Description | Notes
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
typing.Union[dict, frozendict, str, date, datetime, int, float, bool, Decimal, None, list, tuple, bytes] | |
|
||||||
|
|
||||||
|
### Return Types, Responses
|
||||||
|
|
||||||
|
Code | Class | Description
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
|
||||||
|
200 | ApiResponseFor200 | success
|
||||||
|
|
||||||
|
#### ApiResponseFor200
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
response | urllib3.HTTPResponse | Raw response |
|
||||||
|
body | typing.Union[SchemaFor200ResponseBodyApplicationJsonCharsetutf8, ] | |
|
||||||
|
headers | Unset | headers were not defined |
|
||||||
|
|
||||||
|
#### SchemaFor200ResponseBodyApplicationJsonCharsetutf8
|
||||||
|
|
||||||
|
Type | Description | Notes
|
||||||
|
------------- | ------------- | -------------
|
||||||
|
typing.Union[dict, frozendict, str, date, datetime, int, float, bool, Decimal, None, list, tuple, bytes] | |
|
||||||
|
|
||||||
|
|
||||||
|
**bool, date, datetime, dict, float, int, list, str, none_type**
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
No authorization required
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **mammal**
|
# **mammal**
|
||||||
> Mammal mammal(mammal)
|
> Mammal mammal(mammal)
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ from petstore_api.api.fake_api_endpoints.group_parameters import GroupParameters
|
|||||||
from petstore_api.api.fake_api_endpoints.inline_additional_properties import InlineAdditionalProperties
|
from petstore_api.api.fake_api_endpoints.inline_additional_properties import InlineAdditionalProperties
|
||||||
from petstore_api.api.fake_api_endpoints.inline_composition import InlineComposition
|
from petstore_api.api.fake_api_endpoints.inline_composition import InlineComposition
|
||||||
from petstore_api.api.fake_api_endpoints.json_form_data import JsonFormData
|
from petstore_api.api.fake_api_endpoints.json_form_data import JsonFormData
|
||||||
|
from petstore_api.api.fake_api_endpoints.json_with_charset import JsonWithCharset
|
||||||
from petstore_api.api.fake_api_endpoints.mammal import Mammal
|
from petstore_api.api.fake_api_endpoints.mammal import Mammal
|
||||||
from petstore_api.api.fake_api_endpoints.number_with_validations import NumberWithValidations
|
from petstore_api.api.fake_api_endpoints.number_with_validations import NumberWithValidations
|
||||||
from petstore_api.api.fake_api_endpoints.object_in_query import ObjectInQuery
|
from petstore_api.api.fake_api_endpoints.object_in_query import ObjectInQuery
|
||||||
@ -57,6 +58,7 @@ class FakeApi(
|
|||||||
InlineAdditionalProperties,
|
InlineAdditionalProperties,
|
||||||
InlineComposition,
|
InlineComposition,
|
||||||
JsonFormData,
|
JsonFormData,
|
||||||
|
JsonWithCharset,
|
||||||
Mammal,
|
Mammal,
|
||||||
NumberWithValidations,
|
NumberWithValidations,
|
||||||
ObjectInQuery,
|
ObjectInQuery,
|
||||||
|
@ -0,0 +1,161 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
Generated by: https://openapi-generator.tech
|
||||||
|
"""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import re # noqa: F401
|
||||||
|
import sys # noqa: F401
|
||||||
|
import typing
|
||||||
|
import urllib3
|
||||||
|
from urllib3._collections import HTTPHeaderDict
|
||||||
|
|
||||||
|
from petstore_api import api_client, exceptions
|
||||||
|
import decimal # noqa: F401
|
||||||
|
from datetime import date, datetime # noqa: F401
|
||||||
|
from frozendict import frozendict # noqa: F401
|
||||||
|
|
||||||
|
from petstore_api.schemas import ( # noqa: F401
|
||||||
|
AnyTypeSchema,
|
||||||
|
ComposedSchema,
|
||||||
|
DictSchema,
|
||||||
|
ListSchema,
|
||||||
|
StrSchema,
|
||||||
|
IntSchema,
|
||||||
|
Int32Schema,
|
||||||
|
Int64Schema,
|
||||||
|
Float32Schema,
|
||||||
|
Float64Schema,
|
||||||
|
NumberSchema,
|
||||||
|
DateSchema,
|
||||||
|
DateTimeSchema,
|
||||||
|
DecimalSchema,
|
||||||
|
BoolSchema,
|
||||||
|
BinarySchema,
|
||||||
|
NoneSchema,
|
||||||
|
none_type,
|
||||||
|
Configuration,
|
||||||
|
Unset,
|
||||||
|
unset,
|
||||||
|
ComposedBase,
|
||||||
|
ListBase,
|
||||||
|
DictBase,
|
||||||
|
NoneBase,
|
||||||
|
StrBase,
|
||||||
|
IntBase,
|
||||||
|
Int32Base,
|
||||||
|
Int64Base,
|
||||||
|
Float32Base,
|
||||||
|
Float64Base,
|
||||||
|
NumberBase,
|
||||||
|
DateBase,
|
||||||
|
DateTimeBase,
|
||||||
|
BoolBase,
|
||||||
|
BinaryBase,
|
||||||
|
Schema,
|
||||||
|
_SchemaValidator,
|
||||||
|
_SchemaTypeChecker,
|
||||||
|
_SchemaEnumMaker
|
||||||
|
)
|
||||||
|
|
||||||
|
# body param
|
||||||
|
SchemaForRequestBodyApplicationJsonCharsetutf8 = AnyTypeSchema
|
||||||
|
|
||||||
|
|
||||||
|
request_body_body = api_client.RequestBody(
|
||||||
|
content={
|
||||||
|
'application/json; charset=utf-8': api_client.MediaType(
|
||||||
|
schema=SchemaForRequestBodyApplicationJsonCharsetutf8),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
_path = '/fake/jsonWithCharset'
|
||||||
|
_method = 'POST'
|
||||||
|
SchemaFor200ResponseBodyApplicationJsonCharsetutf8 = AnyTypeSchema
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ApiResponseFor200(api_client.ApiResponse):
|
||||||
|
response: urllib3.HTTPResponse
|
||||||
|
body: typing.Union[
|
||||||
|
SchemaFor200ResponseBodyApplicationJsonCharsetutf8,
|
||||||
|
]
|
||||||
|
headers: Unset = unset
|
||||||
|
|
||||||
|
|
||||||
|
_response_for_200 = api_client.OpenApiResponse(
|
||||||
|
response_cls=ApiResponseFor200,
|
||||||
|
content={
|
||||||
|
'application/json; charset=utf-8': api_client.MediaType(
|
||||||
|
schema=SchemaFor200ResponseBodyApplicationJsonCharsetutf8),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
_status_code_to_response = {
|
||||||
|
'200': _response_for_200,
|
||||||
|
}
|
||||||
|
_all_accept_content_types = (
|
||||||
|
'application/json; charset=utf-8',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class JsonWithCharset(api_client.Api):
|
||||||
|
|
||||||
|
def json_with_charset(
|
||||||
|
self: api_client.Api,
|
||||||
|
body: typing.Union[SchemaForRequestBodyApplicationJsonCharsetutf8, Unset] = unset,
|
||||||
|
content_type: str = 'application/json; charset=utf-8',
|
||||||
|
accept_content_types: typing.Tuple[str] = _all_accept_content_types,
|
||||||
|
stream: bool = False,
|
||||||
|
timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None,
|
||||||
|
skip_deserialization: bool = False,
|
||||||
|
) -> typing.Union[
|
||||||
|
ApiResponseFor200,
|
||||||
|
api_client.ApiResponseWithoutDeserialization
|
||||||
|
]:
|
||||||
|
"""
|
||||||
|
json with charset tx and rx
|
||||||
|
:param skip_deserialization: If true then api_response.response will be set but
|
||||||
|
api_response.body and api_response.headers will not be deserialized into schema
|
||||||
|
class instances
|
||||||
|
"""
|
||||||
|
|
||||||
|
_headers = HTTPHeaderDict()
|
||||||
|
# TODO add cookie handling
|
||||||
|
if accept_content_types:
|
||||||
|
for accept_content_type in accept_content_types:
|
||||||
|
_headers.add('Accept', accept_content_type)
|
||||||
|
|
||||||
|
_fields = None
|
||||||
|
_body = None
|
||||||
|
if body is not unset:
|
||||||
|
serialized_data = request_body_body.serialize(body, content_type)
|
||||||
|
_headers.add('Content-Type', content_type)
|
||||||
|
if 'fields' in serialized_data:
|
||||||
|
_fields = serialized_data['fields']
|
||||||
|
elif 'body' in serialized_data:
|
||||||
|
_body = serialized_data['body']
|
||||||
|
response = self.api_client.call_api(
|
||||||
|
resource_path=_path,
|
||||||
|
method=_method,
|
||||||
|
headers=_headers,
|
||||||
|
fields=_fields,
|
||||||
|
body=_body,
|
||||||
|
stream=stream,
|
||||||
|
timeout=timeout,
|
||||||
|
)
|
||||||
|
|
||||||
|
if skip_deserialization:
|
||||||
|
api_response = api_client.ApiResponseWithoutDeserialization(response=response)
|
||||||
|
else:
|
||||||
|
response_for_status = _status_code_to_response.get(str(response.status))
|
||||||
|
if response_for_status:
|
||||||
|
api_response = response_for_status.deserialize(response, self.api_client.configuration)
|
||||||
|
else:
|
||||||
|
api_response = api_client.ApiResponseWithoutDeserialization(response=response)
|
||||||
|
|
||||||
|
if not 200 <= response.status <= 299:
|
||||||
|
raise exceptions.ApiException(api_response=api_response)
|
||||||
|
|
||||||
|
return api_response
|
@ -723,7 +723,20 @@ class ApiResponseWithoutDeserialization(ApiResponse):
|
|||||||
headers: typing.Union[Unset, typing.List[HeaderParameter]] = unset
|
headers: typing.Union[Unset, typing.List[HeaderParameter]] = unset
|
||||||
|
|
||||||
|
|
||||||
class OpenApiResponse:
|
class JSONDetector:
|
||||||
|
@staticmethod
|
||||||
|
def content_type_is_json(content_type: str) -> bool:
|
||||||
|
"""
|
||||||
|
for when content_type strings also include charset info like:
|
||||||
|
application/json; charset=UTF-8
|
||||||
|
"""
|
||||||
|
content_type_piece = content_type.split(';')[0]
|
||||||
|
if content_type_piece == 'application/json':
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class OpenApiResponse(JSONDetector):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
response_cls: typing.Type[ApiResponse] = ApiResponse,
|
response_cls: typing.Type[ApiResponse] = ApiResponse,
|
||||||
@ -738,8 +751,8 @@ class OpenApiResponse:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __deserialize_json(response: urllib3.HTTPResponse) -> typing.Any:
|
def __deserialize_json(response: urllib3.HTTPResponse) -> typing.Any:
|
||||||
decoded_data = response.data.decode("utf-8")
|
# python must be >= 3.9 so we can pass in bytes into json.loads
|
||||||
return json.loads(decoded_data)
|
return json.loads(response.data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]:
|
def __file_name_from_content_disposition(content_disposition: typing.Optional[str]) -> typing.Optional[str]:
|
||||||
@ -800,7 +813,7 @@ class OpenApiResponse:
|
|||||||
deserialized_body = unset
|
deserialized_body = unset
|
||||||
streamed = response.supports_chunked_reads()
|
streamed = response.supports_chunked_reads()
|
||||||
if self.content is not None:
|
if self.content is not None:
|
||||||
if content_type == 'application/json':
|
if self.content_type_is_json(content_type):
|
||||||
body_data = self.__deserialize_json(response)
|
body_data = self.__deserialize_json(response)
|
||||||
elif content_type == 'application/octet-stream':
|
elif content_type == 'application/octet-stream':
|
||||||
body_data = self.__deserialize_application_octet_stream(response)
|
body_data = self.__deserialize_application_octet_stream(response)
|
||||||
@ -1244,7 +1257,7 @@ class SerializedRequestBody(typing.TypedDict, total=False):
|
|||||||
fields: typing.Tuple[typing.Union[RequestField, tuple[str, str]], ...]
|
fields: typing.Tuple[typing.Union[RequestField, tuple[str, str]], ...]
|
||||||
|
|
||||||
|
|
||||||
class RequestBody(StyleFormSerializer):
|
class RequestBody(StyleFormSerializer, JSONDetector):
|
||||||
"""
|
"""
|
||||||
A request body parameter
|
A request body parameter
|
||||||
content: content_type to MediaType Schema info
|
content: content_type to MediaType Schema info
|
||||||
@ -1381,7 +1394,7 @@ class RequestBody(StyleFormSerializer):
|
|||||||
cast_in_data = media_type.schema(in_data)
|
cast_in_data = media_type.schema(in_data)
|
||||||
# TODO check for and use encoding if it exists
|
# TODO check for and use encoding if it exists
|
||||||
# and content_type is multipart or application/x-www-form-urlencoded
|
# and content_type is multipart or application/x-www-form-urlencoded
|
||||||
if content_type == 'application/json':
|
if self.content_type_is_json(content_type):
|
||||||
return self.__serialize_json(cast_in_data)
|
return self.__serialize_json(cast_in_data)
|
||||||
elif content_type == 'text/plain':
|
elif content_type == 'text/plain':
|
||||||
return self.__serialize_text_plain(cast_in_data)
|
return self.__serialize_text_plain(cast_in_data)
|
||||||
|
@ -679,6 +679,29 @@ class TestFakeApi(unittest.TestCase):
|
|||||||
accept_content_types=(content_type,)
|
accept_content_types=(content_type,)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_json_with_charset(self):
|
||||||
|
# serialization + deserialization of json with charset works
|
||||||
|
with patch.object(RESTClientObject, 'request') as mock_request:
|
||||||
|
body = None
|
||||||
|
content_type_with_charset = 'application/json; charset=utf-8'
|
||||||
|
mock_request.return_value = self.__response(
|
||||||
|
self.__json_bytes(body),
|
||||||
|
content_type=content_type_with_charset
|
||||||
|
)
|
||||||
|
|
||||||
|
api_response = self.api.json_with_charset(body=body)
|
||||||
|
self.__assert_request_called_with(
|
||||||
|
mock_request,
|
||||||
|
'http://petstore.swagger.io:80/v2/fake/jsonWithCharset',
|
||||||
|
body=self.__json_bytes(body),
|
||||||
|
content_type=content_type_with_charset,
|
||||||
|
accept_content_type=content_type_with_charset
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(api_response.body, schemas.AnyTypeSchema)
|
||||||
|
assert isinstance(api_response.body, schemas.NoneClass)
|
||||||
|
assert api_response.body.is_none()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user