Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,27 @@ public boolean getHasDefaultResponse() {
return responses.stream().anyMatch(response -> response.isDefault);
}

public boolean getAllResponsesAreErrors() {
return responses.stream().allMatch(response -> response.is4xx || response.is5xx);
}

/**
* @return contentTypeToOperation
* returns a map where the key is the request body content type and the value is the current CodegenOperation
* this is needed by templates when a different signature is needed for each request body content type
*/
public Map<String, CodegenOperation> getContentTypeToOperation() {
LinkedHashMap<String, CodegenOperation> contentTypeToOperation = new LinkedHashMap<>();
if (bodyParam == null) {
return null;
}
LinkedHashMap<String, CodegenMediaType> content = bodyParam.getContent();
for (String contentType: content.keySet()) {
contentTypeToOperation.put(contentType, this);
}
return contentTypeToOperation;
}

/**
* Check if there's at least one vendor extension
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -997,12 +997,13 @@ public CodegenParameter fromParameter(Parameter parameter, Set<String> imports)
}
}
// clone this so we can change some properties on it
CodegenProperty schemaProp = cp.getSchema().clone();
CodegenProperty schemaProp = cp.getSchema();
// parameters may have valid python names like some_val or invalid ones like Content-Type
// we always set nameInSnakeCase to null so special handling will not be done for these names
// invalid python names will be handled in python by using a TypedDict which will allow us to have a type hint
// for keys that cannot be variable names to the schema baseName
if (schemaProp != null) {
schemaProp = schemaProp.clone();
schemaProp.nameInSnakeCase = null;
schemaProp.baseName = toModelName(cp.baseName) + "Schema";
cp.setSchema(schemaProp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class RequestField(RequestFieldBase):


class JSONEncoder(json.JSONEncoder):
compact_separators = (',', ':')

def default(self, obj):
if isinstance(obj, str):
return str(obj)
Expand Down Expand Up @@ -320,8 +322,25 @@ class StyleSimpleSerializer(ParameterSerializerBase):
)


class JSONDetector:
"""
Works for:
application/json
application/json; charset=UTF-8
application/json-patch+json
application/geo+json
"""
__json_content_type_pattern = re.compile("application/[^+]*[+]?(json);?.*")

@classmethod
def _content_type_is_json(cls, content_type: str) -> bool:
if cls.__json_content_type_pattern.match(content_type):
return True
return False


@dataclass
class ParameterBase:
class ParameterBase(JSONDetector):
name: str
in_type: ParameterInType
required: bool
Expand All @@ -348,7 +367,6 @@ class ParameterBase:
}
__disallowed_header_names = {'Accept', 'Content-Type', 'Authorization'}
_json_encoder = JSONEncoder()
_json_content_type = 'application/json'

@classmethod
def __verify_style_to_in_type(cls, style: typing.Optional[ParameterStyle], in_type: ParameterInType):
Expand Down Expand Up @@ -395,8 +413,11 @@ class ParameterBase:

def _serialize_json(
self,
in_data: typing.Union[None, int, float, str, bool, dict, list]
in_data: typing.Union[None, int, float, str, bool, dict, list],
eliminate_whitespace: bool = False
) -> str:
if eliminate_whitespace:
return json.dumps(in_data, separators=self._json_encoder.compact_separators)
return json.dumps(in_data)


Expand Down Expand Up @@ -491,7 +512,7 @@ class PathParameter(ParameterBase, StyleSimpleSerializer):
for content_type, schema in self.content.items():
cast_in_data = schema(in_data)
cast_in_data = self._json_encoder.default(cast_in_data)
if content_type == self._json_content_type:
if self._content_type_is_json(content_type):
value = self._serialize_json(cast_in_data)
return self._to_dict(self.name, value)
raise NotImplementedError('Serialization of {} has not yet been implemented'.format(content_type))
Expand All @@ -509,7 +530,7 @@ class QueryParameter(ParameterBase, StyleFormSerializer):
schema: typing.Optional[typing.Type[Schema]] = None,
content: typing.Optional[typing.Dict[str, typing.Type[Schema]]] = None
):
used_style = ParameterStyle.FORM if style is None and content is None and schema else style
used_style = ParameterStyle.FORM if style is None else style
used_explode = self._get_default_explode(used_style) if explode is None else explode

super().__init__(
Expand Down Expand Up @@ -572,8 +593,6 @@ class QueryParameter(ParameterBase, StyleFormSerializer):
return self._to_dict(self.name, value)

def get_prefix_separator_iterator(self) -> typing.Optional[PrefixSeparatorIterator]:
if not self.schema:
return None
if self.style is ParameterStyle.FORM:
return PrefixSeparatorIterator('?', '&')
elif self.style is ParameterStyle.SPACE_DELIMITED:
Expand Down Expand Up @@ -612,12 +631,17 @@ class QueryParameter(ParameterBase, StyleFormSerializer):
elif self.style is ParameterStyle.PIPE_DELIMITED:
return self.__serialize_pipe_delimited(cast_in_data, prefix_separator_iterator)
# self.content will be length one
if prefix_separator_iterator is None:
prefix_separator_iterator = self.get_prefix_separator_iterator()
for content_type, schema in self.content.items():
cast_in_data = schema(in_data)
cast_in_data = self._json_encoder.default(cast_in_data)
if content_type == self._json_content_type:
value = self._serialize_json(cast_in_data)
return self._to_dict(self.name, value)
if self._content_type_is_json(content_type):
value = self._serialize_json(cast_in_data, eliminate_whitespace=True)
return self._to_dict(
self.name,
next(prefix_separator_iterator) + self.name + '=' + quote(value)
)
raise NotImplementedError('Serialization of {} has not yet been implemented'.format(content_type))


Expand Down Expand Up @@ -676,7 +700,7 @@ class CookieParameter(ParameterBase, StyleFormSerializer):
for content_type, schema in self.content.items():
cast_in_data = schema(in_data)
cast_in_data = self._json_encoder.default(cast_in_data)
if content_type == self._json_content_type:
if self._content_type_is_json(content_type):
value = self._serialize_json(cast_in_data)
return self._to_dict(self.name, value)
raise NotImplementedError('Serialization of {} has not yet been implemented'.format(content_type))
Expand Down Expand Up @@ -733,7 +757,7 @@ class HeaderParameter(ParameterBase, StyleSimpleSerializer):
for content_type, schema in self.content.items():
cast_in_data = schema(in_data)
cast_in_data = self._json_encoder.default(cast_in_data)
if content_type == self._json_content_type:
if self._content_type_is_json(content_type):
value = self._serialize_json(cast_in_data)
return self.__to_headers(((self.name, value),))
raise NotImplementedError('Serialization of {} has not yet been implemented'.format(content_type))
Expand Down Expand Up @@ -796,23 +820,6 @@ class ApiResponseWithoutDeserialization(ApiResponse):
headers: typing.Union[Unset, typing.List[HeaderParameter]] = unset


class JSONDetector:
"""
Works for:
application/json
application/json; charset=UTF-8
application/json-patch+json
application/geo+json
"""
__json_content_type_pattern = re.compile("application/[^+]*[+]?(json);?.*")

@classmethod
def _content_type_is_json(cls, content_type: str) -> bool:
if cls.__json_content_type_pattern.match(content_type):
return True
return False


class OpenApiResponse(JSONDetector):
__filename_content_disposition_pattern = re.compile('filename="(.+?)"')

Expand Down Expand Up @@ -987,7 +994,7 @@ class ApiClient:
self.pool_threads = pool_threads

self.rest_client = rest.RESTClientObject(configuration)
self.default_headers = {}
self.default_headers = HTTPHeaderDict()
if header_name is not None:
self.default_headers[header_name] = header_value
self.cookie = cookie
Expand Down Expand Up @@ -1047,15 +1054,18 @@ class ApiClient:
) -> urllib3.HTTPResponse:

# header parameters
headers = headers or HTTPHeaderDict()
headers.update(self.default_headers)
used_headers = HTTPHeaderDict(self.default_headers)
if self.cookie:
headers['Cookie'] = self.cookie

# auth setting
self.update_params_for_auth(headers,
self.update_params_for_auth(used_headers,
auth_settings, resource_path, method, body)

# must happen after cookie setting and auth setting in case user is overriding those
if headers:
used_headers.update(headers)

# request url
if host is None:
url = self.configuration.host + resource_path
Expand All @@ -1067,7 +1077,7 @@ class ApiClient:
response = {{#if asyncio}}await {{/if}}{{#if tornado}}yield {{/if}}self.request(
method,
url,
headers=headers,
headers=used_headers,
fields=fields,
body=body,
stream=stream,
Expand Down
Loading