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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pass-thru:
- subset-reducer
version: ~3.0.6306
use-extension:
"@autorest/modelerfour": 4.15.407
"@autorest/modelerfour": 4.15.410

modelerfour:
group-parameters: true
Expand Down
78 changes: 17 additions & 61 deletions autorest/codegen/models/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
T = TypeVar('T')
OrderedSet = Dict[T, None]

_M4_HEADER_PARAMETERS = ["content_type", "accept"]

def _non_binary_schema_media_types(media_types: List[str]) -> OrderedSet[str]:
response_media_types: OrderedSet[str] = {}
Expand All @@ -44,50 +45,23 @@ def _non_binary_schema_media_types(media_types: List[str]) -> OrderedSet[str]:
response_media_types[xml_media_types[0]] = None
return response_media_types

def _remove_multiple_content_type_parameters(parameters: List[Parameter]) -> List[Parameter]:
content_type_params = [p for p in parameters if p.serialized_name == "content_type"]
remaining_params = [p for p in parameters if p.serialized_name != "content_type"]
json_content_type_param = [p for p in content_type_params if p.yaml_data["schema"]["type"] == "constant"]
if json_content_type_param:
remaining_params.append(json_content_type_param[0])
else:
remaining_params.append(content_type_params[0])
return remaining_params

def _accept_content_type_helper(responses: List[SchemaResponse]) -> OrderedSet[str]:
media_types = {
media_type: None for response in responses for media_type in response.media_types
}

if not media_types:
return media_types

if len(media_types.keys()) == 1:
# if there's just one media type, we return it
return media_types
# if not, we want to return them as binary_media_types + non_binary_media types
binary_media_types = {
media_type: None for media_type in list(media_types.keys())
if not "json" in media_type and not "xml" in media_type
def _remove_multiple_m4_header_parameters(parameters: List[Parameter]) -> List[Parameter]:
m4_header_params_in_schema = {
k: [p for p in parameters if p.serialized_name == k]
for k in _M4_HEADER_PARAMETERS
}
non_binary_schema_media_types = {
media_type: None for media_type in list(media_types.keys())
if "json" in media_type or "xml" in media_type
remaining_params = [p for p in parameters if p.serialized_name not in _M4_HEADER_PARAMETERS]
json_m4_header_params = {
k: [p for p in m4_header_params_in_schema[k] if p.yaml_data["schema"]["type"] == "constant"]
for k in m4_header_params_in_schema
}
if all([response.binary for response in responses]):
response_media_types = binary_media_types
elif all([response.schema for response in responses]):
response_media_types = _non_binary_schema_media_types(
list(non_binary_schema_media_types.keys())
)
else:
non_binary_schema_media_types = _non_binary_schema_media_types(
list(non_binary_schema_media_types.keys())
)
response_media_types = binary_media_types
response_media_types.update(non_binary_schema_media_types)
for k, v in json_m4_header_params.items():
if v:
remaining_params.append(v[0])
else:
remaining_params.append(m4_header_params_in_schema[k][0])

return response_media_types
return remaining_params

class Operation(BaseModel): # pylint: disable=too-many-public-methods, too-many-instance-attributes
"""Represent an operation.
Expand Down Expand Up @@ -140,24 +114,6 @@ def request_content_type(self) -> str:
]
))

@property
def accept_content_type(self) -> str:
if not self.has_response_body:
raise TypeError(
"There is an error in the code model we're being supplied. We're getting response media types " +
f"even though no response of {self.name} has a body"
)
response_content_types = _accept_content_type_helper(self.responses)
response_content_types.update(_accept_content_type_helper(self.exceptions))

if not response_content_types.keys():
raise TypeError(
f"Operation {self.name} has tried to get its accept_content_type even though it has no media types"
)

return ", ".join(list(response_content_types.keys()))


@property
def is_stream_request(self) -> bool:
"""Is the request is a stream, like an upload."""
Expand Down Expand Up @@ -339,7 +295,7 @@ def from_yaml(cls, yaml_data: Dict[str, Any]) -> "Operation":
for request in yaml_data["requests"]:
for yaml in request.get("parameters", []):
parameter = Parameter.from_yaml(yaml)
if yaml["language"]["python"]["name"] == "content_type":
if yaml["language"]["python"]["name"] in _M4_HEADER_PARAMETERS:
parameter.is_kwarg = True
parameters.append(parameter)
elif multiple_requests:
Expand All @@ -348,7 +304,7 @@ def from_yaml(cls, yaml_data: Dict[str, Any]) -> "Operation":
parameters.append(parameter)

if multiple_requests:
parameters = _remove_multiple_content_type_parameters(parameters)
parameters = _remove_multiple_m4_header_parameters(parameters)
chosen_parameter = multiple_media_type_parameters[0]

# binary body parameters are required, while object
Expand Down
3 changes: 0 additions & 3 deletions autorest/codegen/templates/operation_tools.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,6 @@ if {{ header_parameter.full_serialized_name }} is not None:
header_parameters['{{ header_parameter.rest_api_name }}'] = {{ operation.build_serialize_data_call(header_parameter, "header") }}
{% endif %}
{% endfor %}
{% endif %}
{% if operation.has_response_body %}
header_parameters['Accept'] = '{{ operation.accept_content_type }}'
{% endif %}{% endmacro %}
{# helper for stream body params #}
{% macro stream_body_params(operation) %}body_content_kwargs['stream_content'] = {{ operation.parameters.body[0].serialized_name }}{% endmacro %}
Expand Down
15 changes: 10 additions & 5 deletions autorest/namer/name_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ def _convert_object_schema(schema: Dict[str, Any]) -> None:
for prop in schema.get("properties", []):
NameConverter._convert_language_default_python_case(schema=prop, pad_string=PadType.Property)

@staticmethod
def _is_schema_an_m4_header_parameter(schema_name: str, schema: Dict[str, Any]) -> bool:
m4_header_parameters = ["content_type", "accept"]
return (
schema_name in m4_header_parameters and
schema.get('protocol', {}).get('http', {}).get('in', {}) == 'header'
)

@staticmethod
def _convert_language_default_python_case(
schema: Dict[str, Any],
Expand All @@ -111,11 +119,8 @@ def _convert_language_default_python_case(
schema_name = schema['language']['default']['name']
schema_python_name = schema['language']['python']['name']

if not(
schema_name == 'content_type' and
schema.get('protocol') and
schema['protocol'].get('http') and
schema['protocol']['http']['in'] == "header"
if not NameConverter._is_schema_an_m4_header_parameter(
schema_name, schema
):
# only escaping name if it's not a content_type header parameter
schema_python_name = NameConverter._to_valid_python_name(
Expand Down
1 change: 1 addition & 0 deletions autorest/namer/python_mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class PadType(Enum):
"self",
# these are kwargs we've reserved for our autorest generated operations
"content_type",
"accept",
"cls",
"polling",
"continuation_token", # for LRO calls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ async def get_null(
cls = kwargs.pop('cls', None) # type: ClsType[datetime.timedelta]
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
accept = "application/json"

# Construct URL
url = self.get_null.metadata['url'] # type: ignore
Expand All @@ -65,7 +66,7 @@ async def get_null(

# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Accept'] = 'application/json'
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.get(url, query_parameters, header_parameters)
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down Expand Up @@ -103,6 +104,7 @@ async def put_positive_duration(
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
content_type = kwargs.pop("content_type", "application/json")
accept = "application/json"

# Construct URL
url = self.put_positive_duration.metadata['url'] # type: ignore
Expand All @@ -113,6 +115,7 @@ async def put_positive_duration(
# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

body_content_kwargs = {} # type: Dict[str, Any]
body_content = self._serialize.body(duration_body, 'duration')
Expand Down Expand Up @@ -146,6 +149,7 @@ async def get_positive_duration(
cls = kwargs.pop('cls', None) # type: ClsType[datetime.timedelta]
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
accept = "application/json"

# Construct URL
url = self.get_positive_duration.metadata['url'] # type: ignore
Expand All @@ -155,7 +159,7 @@ async def get_positive_duration(

# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Accept'] = 'application/json'
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.get(url, query_parameters, header_parameters)
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down Expand Up @@ -189,6 +193,7 @@ async def get_invalid(
cls = kwargs.pop('cls', None) # type: ClsType[datetime.timedelta]
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
accept = "application/json"

# Construct URL
url = self.get_invalid.metadata['url'] # type: ignore
Expand All @@ -198,7 +203,7 @@ async def get_invalid(

# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Accept'] = 'application/json'
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.get(url, query_parameters, header_parameters)
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def get_null(
cls = kwargs.pop('cls', None) # type: ClsType[datetime.timedelta]
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
accept = "application/json"

# Construct URL
url = self.get_null.metadata['url'] # type: ignore
Expand All @@ -70,7 +71,7 @@ def get_null(

# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Accept'] = 'application/json'
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.get(url, query_parameters, header_parameters)
pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down Expand Up @@ -109,6 +110,7 @@ def put_positive_duration(
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
content_type = kwargs.pop("content_type", "application/json")
accept = "application/json"

# Construct URL
url = self.put_positive_duration.metadata['url'] # type: ignore
Expand All @@ -119,6 +121,7 @@ def put_positive_duration(
# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

body_content_kwargs = {} # type: Dict[str, Any]
body_content = self._serialize.body(duration_body, 'duration')
Expand Down Expand Up @@ -153,6 +156,7 @@ def get_positive_duration(
cls = kwargs.pop('cls', None) # type: ClsType[datetime.timedelta]
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
accept = "application/json"

# Construct URL
url = self.get_positive_duration.metadata['url'] # type: ignore
Expand All @@ -162,7 +166,7 @@ def get_positive_duration(

# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Accept'] = 'application/json'
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.get(url, query_parameters, header_parameters)
pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down Expand Up @@ -197,6 +201,7 @@ def get_invalid(
cls = kwargs.pop('cls', None) # type: ClsType[datetime.timedelta]
error_map = {404: ResourceNotFoundError, 409: ResourceExistsError}
error_map.update(kwargs.pop('error_map', {}))
accept = "application/json"

# Construct URL
url = self.get_invalid.metadata['url'] # type: ignore
Expand All @@ -206,7 +211,7 @@ def get_invalid(

# Construct headers
header_parameters = {} # type: Dict[str, Any]
header_parameters['Accept'] = 'application/json'
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.get(url, query_parameters, header_parameters)
pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ async def post_required(
_path = parameter_grouping_post_required_parameters.path
_body = parameter_grouping_post_required_parameters.body
content_type = kwargs.pop("content_type", "application/json")
accept = "application/json"

# Construct URL
url = self.post_required.metadata['url'] # type: ignore
Expand All @@ -87,6 +88,7 @@ async def post_required(
if _custom_header is not None:
header_parameters['customHeader'] = self._serialize.header("custom_header", _custom_header, 'str')
header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str')
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

body_content_kwargs = {} # type: Dict[str, Any]
body_content = self._serialize.body(_body, 'int')
Expand Down Expand Up @@ -129,6 +131,7 @@ async def post_optional(
if parameter_grouping_post_optional_parameters is not None:
_custom_header = parameter_grouping_post_optional_parameters.custom_header
_query = parameter_grouping_post_optional_parameters.query
accept = "application/json"

# Construct URL
url = self.post_optional.metadata['url'] # type: ignore
Expand All @@ -142,6 +145,7 @@ async def post_optional(
header_parameters = {} # type: Dict[str, Any]
if _custom_header is not None:
header_parameters['customHeader'] = self._serialize.header("custom_header", _custom_header, 'str')
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.post(url, query_parameters, header_parameters)
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down Expand Up @@ -189,6 +193,7 @@ async def post_multi_param_groups(
if parameter_grouping_post_multi_param_groups_second_param_group is not None:
_header_two = parameter_grouping_post_multi_param_groups_second_param_group.header_two
_query_two = parameter_grouping_post_multi_param_groups_second_param_group.query_two
accept = "application/json"

# Construct URL
url = self.post_multi_param_groups.metadata['url'] # type: ignore
Expand All @@ -206,6 +211,7 @@ async def post_multi_param_groups(
header_parameters['header-one'] = self._serialize.header("header_one", _header_one, 'str')
if _header_two is not None:
header_parameters['header-two'] = self._serialize.header("header_two", _header_two, 'str')
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.post(url, query_parameters, header_parameters)
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down Expand Up @@ -245,6 +251,7 @@ async def post_shared_parameter_group_object(
if first_parameter_group is not None:
_header_one = first_parameter_group.header_one
_query_one = first_parameter_group.query_one
accept = "application/json"

# Construct URL
url = self.post_shared_parameter_group_object.metadata['url'] # type: ignore
Expand All @@ -258,6 +265,7 @@ async def post_shared_parameter_group_object(
header_parameters = {} # type: Dict[str, Any]
if _header_one is not None:
header_parameters['header-one'] = self._serialize.header("header_one", _header_one, 'str')
header_parameters['Accept'] = self._serialize.header("accept", accept, 'str')

request = self._client.post(url, query_parameters, header_parameters)
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
Expand Down
Loading