From f7d13cf7c6f34b79315e6c1cc45b26ddffbc2306 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 13 Jun 2022 16:13:48 -0700 Subject: [PATCH 01/11] centralize abstract setting --- autorest/codegen/models/base_builder.py | 17 +++++++++++++---- autorest/codegen/models/lro_operation.py | 2 -- autorest/codegen/models/operation.py | 20 -------------------- autorest/codegen/models/paging_operation.py | 2 -- autorest/codegen/models/request_builder.py | 19 ------------------- autorest/m4reformatter/__init__.py | 5 +++++ 6 files changed, 18 insertions(+), 47 deletions(-) diff --git a/autorest/codegen/models/base_builder.py b/autorest/codegen/models/base_builder.py index 17d7bc851fd..9b90d808f9f 100644 --- a/autorest/codegen/models/base_builder.py +++ b/autorest/codegen/models/base_builder.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- +import logging from abc import abstractmethod from typing import Any, Dict, List, Optional, TypeVar, Union, TYPE_CHECKING, Generic from .base_model import BaseModel @@ -27,6 +28,7 @@ from .operation import Operation from .request_builder import RequestBuilder +_LOGGER = logging.getLogger(__name__) class BaseBuilder(Generic[ParameterListType], BaseModel): """Base class for Operations and Request Builders""" @@ -39,7 +41,6 @@ def __init__( parameters: ParameterListType, *, overloads=None, - abstract: bool = False, want_tracing: bool = True, ) -> None: super().__init__(yaml_data=yaml_data, code_model=code_model) @@ -50,14 +51,22 @@ def __init__( overloads or [] ) self._summary: str = yaml_data.get("summary", "") - # for operations where we don't know what to do, we mark them as abstract so users implement - # in patch.py - self.abstract = abstract self.want_tracing = want_tracing self.group_name: str = yaml_data["groupName"] self.is_overload: bool = yaml_data["isOverload"] self.api_versions: List[str] = yaml_data["apiVersions"] + if code_model.options["version_tolerant"] and yaml_data.get("abstract"): + _LOGGER.warning( + 'Not going to generate operation "%s" because it we are unable to generate this type of operation right now. ' + 'Please write your own custom operation in the "_patch.py" file ' + "following https://aka.ms/azsdk/python/dpcodegen/python/customize", + name, + ) + self.abstract = True + else: + self.abstract = False + @property def summary(self) -> Optional[str]: if self.abstract: diff --git a/autorest/codegen/models/lro_operation.py b/autorest/codegen/models/lro_operation.py index cffd3b94b7d..60c0ee1c9d1 100644 --- a/autorest/codegen/models/lro_operation.py +++ b/autorest/codegen/models/lro_operation.py @@ -33,7 +33,6 @@ def __init__( overloads: Optional[List[Operation]] = None, public: bool = True, want_tracing: bool = True, - abstract: bool = False, ) -> None: super().__init__( code_model=code_model, @@ -46,7 +45,6 @@ def __init__( overloads=overloads, public=public, want_tracing=want_tracing, - abstract=abstract, ) self.name = "begin_" + self.name self.lro_options: Dict[str, Any] = self.yaml_data.get("lroOptions", {}) diff --git a/autorest/codegen/models/operation.py b/autorest/codegen/models/operation.py index 5e88b1b611f..a38f9a4e45e 100644 --- a/autorest/codegen/models/operation.py +++ b/autorest/codegen/models/operation.py @@ -3,7 +3,6 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -import logging from itertools import chain from typing import ( Dict, @@ -43,8 +42,6 @@ if TYPE_CHECKING: from .code_model import CodeModel -_LOGGER = logging.getLogger(__name__) - ResponseType = TypeVar( "ResponseType", bound=Union[Response, PagingResponse, LROResponse, LROPagingResponse], @@ -67,7 +64,6 @@ def __init__( overloads: Optional[List["Operation"]] = None, public: bool = True, want_tracing: bool = True, - abstract: bool = False, ) -> None: super().__init__( code_model=code_model, @@ -75,7 +71,6 @@ def __init__( name=name, parameters=parameters, overloads=overloads, - abstract=abstract, want_tracing=want_tracing, ) self.overloads: List["Operation"] = overloads or [] @@ -429,20 +424,6 @@ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"): cls.from_yaml(overload, code_model) for overload in yaml_data.get("overloads", []) ] - abstract = False - if ( - code_model.options["version_tolerant"] - and parameter_list.has_body - and isinstance(parameter_list.body_parameter, MultipartBodyParameter) - ): - _LOGGER.warning( - 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. ' - "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. " - 'Please write your own custom operation in the "_patch.py" file ' - "following https://aka.ms/azsdk/python/dpcodegen/python/customize", - name, - ) - abstract = True return cls( yaml_data=yaml_data, @@ -454,7 +435,6 @@ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"): responses=responses, exceptions=exceptions, want_tracing=not yaml_data["isOverload"], - abstract=abstract, ) diff --git a/autorest/codegen/models/paging_operation.py b/autorest/codegen/models/paging_operation.py index 7836a0250ef..e8f5fac0113 100644 --- a/autorest/codegen/models/paging_operation.py +++ b/autorest/codegen/models/paging_operation.py @@ -38,7 +38,6 @@ def __init__( overloads: Optional[List[Operation]] = None, public: bool = True, want_tracing: bool = True, - abstract: bool = False, override_success_response_to_200: bool = False, ) -> None: super().__init__( @@ -52,7 +51,6 @@ def __init__( overloads=overloads, public=public, want_tracing=want_tracing, - abstract=abstract, ) self.next_request_builder: Optional[ Union[RequestBuilder, OverloadedRequestBuilder] diff --git a/autorest/codegen/models/request_builder.py b/autorest/codegen/models/request_builder.py index 21e744595f9..e93b1b56192 100644 --- a/autorest/codegen/models/request_builder.py +++ b/autorest/codegen/models/request_builder.py @@ -43,7 +43,6 @@ def __init__( parameters: ParameterListType, *, overloads: Optional[List["RequestBuilder"]] = None, - abstract: bool = False, ) -> None: super().__init__( code_model=code_model, @@ -51,7 +50,6 @@ def __init__( name=name, parameters=parameters, overloads=overloads, - abstract=abstract, want_tracing=False, ) self.overloads: List["RequestBuilder"] = overloads or [] @@ -147,23 +145,7 @@ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"): RequestBuilder.from_yaml(rb_yaml_data, code_model) for rb_yaml_data in yaml_data.get("overloads", []) ] - abstract = False parameter_list = cls.parameter_list_type()(yaml_data, code_model) - if ( - code_model.options["version_tolerant"] - and parameter_list.has_body - and isinstance( - parameter_list.body_parameter, RequestBuilderMultipartBodyParameter - ) - ): - _LOGGER.warning( - 'Not going to generate operation "%s" because it has multipart / urlencoded body parameters. ' - "Multipart / urlencoded body parameters are not supported for version tolerant generation right now. " - 'Please write your own custom operation in the "_patch.py" file ' - "following https://aka.ms/azsdk/python/dpcodegen/python/customize", - name, - ) - abstract = True return cls( yaml_data=yaml_data, @@ -171,7 +153,6 @@ def from_yaml(cls, yaml_data: Dict[str, Any], code_model: "CodeModel"): name=name, parameters=parameter_list, overloads=overloads, - abstract=abstract, ) diff --git a/autorest/m4reformatter/__init__.py b/autorest/m4reformatter/__init__.py index 7108fbce718..ee9d5f8de48 100644 --- a/autorest/m4reformatter/__init__.py +++ b/autorest/m4reformatter/__init__.py @@ -494,6 +494,10 @@ def _update_operation_helper( in_overriden = ( body_parameter["type"]["type"] == "combined" if body_parameter else False ) + abstract = False + if body_parameter and body_parameter.get("entries"): + # this means it's formdata or urlencoded + abstract = True return { "name": yaml_data["language"]["default"]["name"], "description": yaml_data["language"]["default"]["description"], @@ -520,6 +524,7 @@ def _update_operation_helper( "discriminator": "operation", "isOverload": is_overload, "apiVersions": _get_api_versions(yaml_data.get("apiVersions", [])), + "abstract": abstract } def get_operation_creator( From 53e0007ef5030da2367a1f407077e9b13360873b Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 13 Jun 2022 16:56:52 -0700 Subject: [PATCH 02/11] mark operations with 3 body types abstract --- autorest/codegen/models/base_builder.py | 4 +++- autorest/codegen/models/request_builder.py | 3 --- autorest/m4reformatter/__init__.py | 9 ++++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/autorest/codegen/models/base_builder.py b/autorest/codegen/models/base_builder.py index 9b90d808f9f..11dca902621 100644 --- a/autorest/codegen/models/base_builder.py +++ b/autorest/codegen/models/base_builder.py @@ -30,6 +30,7 @@ _LOGGER = logging.getLogger(__name__) + class BaseBuilder(Generic[ParameterListType], BaseModel): """Base class for Operations and Request Builders""" @@ -58,7 +59,8 @@ def __init__( if code_model.options["version_tolerant"] and yaml_data.get("abstract"): _LOGGER.warning( - 'Not going to generate operation "%s" because it we are unable to generate this type of operation right now. ' + 'Not going to generate operation "%s" because it we are unable to generate this ' + 'type of operation right now. ' 'Please write your own custom operation in the "_patch.py" file ' "following https://aka.ms/azsdk/python/dpcodegen/python/customize", name, diff --git a/autorest/codegen/models/request_builder.py b/autorest/codegen/models/request_builder.py index e93b1b56192..f1cb45bc70f 100644 --- a/autorest/codegen/models/request_builder.py +++ b/autorest/codegen/models/request_builder.py @@ -3,7 +3,6 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -import logging from typing import ( Any, Callable, @@ -22,12 +21,10 @@ OverloadedRequestBuilderParameterList, ) from .imports import FileImport, ImportType, TypingSection, MsrestImportType -from .request_builder_parameter import RequestBuilderMultipartBodyParameter if TYPE_CHECKING: from .code_model import CodeModel -_LOGGER = logging.getLogger(__name__) ParameterListType = TypeVar( "ParameterListType", bound=Union[RequestBuilderParameterList, OverloadedRequestBuilderParameterList], diff --git a/autorest/m4reformatter/__init__.py b/autorest/m4reformatter/__init__.py index ee9d5f8de48..19e28e35b88 100644 --- a/autorest/m4reformatter/__init__.py +++ b/autorest/m4reformatter/__init__.py @@ -495,8 +495,11 @@ def _update_operation_helper( body_parameter["type"]["type"] == "combined" if body_parameter else False ) abstract = False - if body_parameter and body_parameter.get("entries"): - # this means it's formdata or urlencoded + if body_parameter and ( + body_parameter.get("entries") + or len(body_parameter["type"].get("types", [])) > 2 + ): + # this means it's formdata or urlencoded, or there are more than 2 types of body abstract = True return { "name": yaml_data["language"]["default"]["name"], @@ -524,7 +527,7 @@ def _update_operation_helper( "discriminator": "operation", "isOverload": is_overload, "apiVersions": _get_api_versions(yaml_data.get("apiVersions", [])), - "abstract": abstract + "abstract": abstract, } def get_operation_creator( From 43ab520c9fe245779c478fa3c2ffd0438eb765f5 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 10:27:28 -0700 Subject: [PATCH 03/11] improve wording of logged warning --- autorest/codegen/models/base_builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autorest/codegen/models/base_builder.py b/autorest/codegen/models/base_builder.py index 11dca902621..86736f9c979 100644 --- a/autorest/codegen/models/base_builder.py +++ b/autorest/codegen/models/base_builder.py @@ -59,8 +59,8 @@ def __init__( if code_model.options["version_tolerant"] and yaml_data.get("abstract"): _LOGGER.warning( - 'Not going to generate operation "%s" because it we are unable to generate this ' - 'type of operation right now. ' + 'Not going to generate operation "%s" because we are unable to generate this ' + "type of operation right now. " 'Please write your own custom operation in the "_patch.py" file ' "following https://aka.ms/azsdk/python/dpcodegen/python/customize", name, From e8efed7d91c76a4e419d45441ab2f9e0b681a304 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 10:33:28 -0700 Subject: [PATCH 04/11] regen new media types test --- .../_media_types_client_operations.py | 121 ++++++++++++++++ .../_media_types_client_operations.py | 135 ++++++++++++++++++ .../mediatypeslowlevel/rest/__init__.py | 2 + .../rest/_request_builders.py | 99 +++++++++++++ .../mediatypesversiontolerant/_client.py | 1 + .../_operations/_operations.py | 10 +- .../mediatypesversiontolerant/_vendor.py | 11 ++ .../mediatypesversiontolerant/aio/_client.py | 1 + .../aio/_operations/_operations.py | 10 +- .../mediatypesversiontolerant/aio/_vendor.py | 11 ++ 10 files changed, 399 insertions(+), 2 deletions(-) diff --git a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py index 7b1202fe821..a9a572213be 100644 --- a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py +++ b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py @@ -28,6 +28,7 @@ build_analyze_body_request, build_binary_body_with_three_content_types_request, build_binary_body_with_two_content_types_request, + build_body_three_types_request, build_content_type_with_encoding_request, build_put_text_and_json_body_request, ) @@ -396,6 +397,126 @@ async def binary_body_with_three_content_types(self, message: IO, **kwargs: Any) binary_body_with_three_content_types.metadata = {"url": "/mediatypes/binaryBodyThreeContentTypes"} # type: ignore + @overload + async def body_three_types(self, message: Any, *, content_type: str = "application/json", **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: any + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def body_three_types( + self, message: IO, *, content_type: str = "application/octet-stream", **kwargs: Any + ) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Known values are: 'application/json', 'application/octet-stream', 'text/plain'. Default value + is "application/octet-stream". + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def body_three_types(self, message: str, *, content_type: Optional[str] = None, **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: str + :keyword content_type: Body Parameter content-type. Content type parameter for string body. + Default value is None. + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + async def body_three_types(self, message: Union[Any, IO, str], **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Is one of the following types: any, IO, string Required. + :type message: any or IO or str + :keyword content_type: Body Parameter content-type. Known values are: 'application/json', + 'application/octet-stream', 'text/plain'. Default value is None. + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type = kwargs.pop("content_type", _headers.pop("Content-Type", None)) # type: Optional[str] + cls = kwargs.pop("cls", None) # type: ClsType[str] + + _json = None + _content = None + _content = None + if isinstance(message, (IO, bytes)): + content_type = content_type or "application/octet-stream" + _content = message + else: + _json = self._serialize.body(message, "object") + content_type = content_type or "application/json" + + request = build_body_three_types_request( + content_type=content_type, + json=_json, + content=_content, + content=_content, + template_url=self.body_three_types.metadata["url"], + headers=_headers, + params=_params, + ) + request = _convert_request(request) + request.url = self._client.format_url(request.url) # type: ignore + + pipeline_response = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + request, stream=False, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + deserialized = self._deserialize("str", pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + + body_three_types.metadata = {"url": "/mediatypes/bodyThreeTypes"} # type: ignore + @distributed_trace_async async def put_text_and_json_body(self, message: str, **kwargs: Any) -> str: """Body that's either text/plain or application/json. diff --git a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py index 78ca7e47627..ed249e72f9b 100644 --- a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py +++ b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py @@ -114,6 +114,23 @@ def build_binary_body_with_three_content_types_request(*, content: IO, **kwargs: return HttpRequest(method="POST", url=_url, headers=_headers, content=content, **kwargs) +def build_body_three_types_request(**kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + content_type = kwargs.pop("content_type", _headers.pop("Content-Type", None)) # type: Optional[str] + accept = _headers.pop("Accept", "text/plain") + + # Construct URL + _url = kwargs.pop("template_url", "/mediatypes/bodyThreeTypes") + + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, headers=_headers, **kwargs) + + def build_put_text_and_json_body_request(*, content: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) @@ -488,6 +505,124 @@ def binary_body_with_three_content_types(self, message: IO, **kwargs: Any) -> st binary_body_with_three_content_types.metadata = {"url": "/mediatypes/binaryBodyThreeContentTypes"} # type: ignore + @overload + def body_three_types(self, message: Any, *, content_type: str = "application/json", **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: any + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def body_three_types(self, message: IO, *, content_type: str = "application/octet-stream", **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Known values are: 'application/json', 'application/octet-stream', 'text/plain'. Default value + is "application/octet-stream". + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def body_three_types(self, message: str, *, content_type: Optional[str] = None, **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: str + :keyword content_type: Body Parameter content-type. Content type parameter for string body. + Default value is None. + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + def body_three_types(self, message: Union[Any, IO, str], **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Is one of the following types: any, IO, string Required. + :type message: any or IO or str + :keyword content_type: Body Parameter content-type. Known values are: 'application/json', + 'application/octet-stream', 'text/plain'. Default value is None. + :paramtype content_type: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: str or the result of cls(response) + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type = kwargs.pop("content_type", _headers.pop("Content-Type", None)) # type: Optional[str] + cls = kwargs.pop("cls", None) # type: ClsType[str] + + _json = None + _content = None + _content = None + if isinstance(message, (IO, bytes)): + content_type = content_type or "application/octet-stream" + _content = message + else: + _json = self._serialize.body(message, "object") + content_type = content_type or "application/json" + + request = build_body_three_types_request( + content_type=content_type, + json=_json, + content=_content, + content=_content, + template_url=self.body_three_types.metadata["url"], + headers=_headers, + params=_params, + ) + request = _convert_request(request) + request.url = self._client.format_url(request.url) # type: ignore + + pipeline_response = self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + request, stream=False, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + deserialized = self._deserialize("str", pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + + body_three_types.metadata = {"url": "/mediatypes/bodyThreeTypes"} # type: ignore + @distributed_trace def put_text_and_json_body(self, message: str, **kwargs: Any) -> str: """Body that's either text/plain or application/json. diff --git a/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/__init__.py b/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/__init__.py index 1c9162a396e..b29f866c15e 100644 --- a/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/__init__.py +++ b/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/__init__.py @@ -11,6 +11,7 @@ from ._request_builders import build_content_type_with_encoding_request from ._request_builders import build_binary_body_with_two_content_types_request from ._request_builders import build_binary_body_with_three_content_types_request +from ._request_builders import build_body_three_types_request from ._request_builders import build_put_text_and_json_body_request __all__ = [ @@ -19,5 +20,6 @@ "build_content_type_with_encoding_request", "build_binary_body_with_two_content_types_request", "build_binary_body_with_three_content_types_request", + "build_body_three_types_request", "build_put_text_and_json_body_request", ] diff --git a/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/_request_builders.py b/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/_request_builders.py index f3549294c36..5081f8902a4 100644 --- a/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/_request_builders.py +++ b/test/vanilla/low-level/Expected/AcceptanceTests/MediaTypesLowLevel/mediatypeslowlevel/rest/_request_builders.py @@ -282,6 +282,105 @@ def build_binary_body_with_three_content_types_request(*, content: IO, **kwargs: return HttpRequest(method="POST", url=_url, headers=_headers, content=content, **kwargs) +@overload +def build_body_three_types_request(*, json: Any, content_type: Optional[str] = None, **kwargs: Any) -> HttpRequest: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this request + builder into your code flow. + + :keyword json: The payload body. Required. + :paramtype json: any + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is None. + :paramtype content_type: str + :return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's + `send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to + incorporate this response into your code flow. + :rtype: ~azure.core.rest.HttpRequest + """ + + +@overload +def build_body_three_types_request(*, content: IO, content_type: Optional[str] = None, **kwargs: Any) -> HttpRequest: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this request + builder into your code flow. + + :keyword content: The payload body. Required. + :paramtype content: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Known values are: 'application/json', 'application/octet-stream', 'text/plain'. Default value + is None. + :paramtype content_type: str + :return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's + `send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to + incorporate this response into your code flow. + :rtype: ~azure.core.rest.HttpRequest + """ + + +@overload +def build_body_three_types_request(*, content: str, content_type: Optional[str] = None, **kwargs: Any) -> HttpRequest: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this request + builder into your code flow. + + :keyword content: The payload body. Required. + :paramtype content: str + :keyword content_type: Body Parameter content-type. Content type parameter for string body. + Default value is None. + :paramtype content_type: str + :return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's + `send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to + incorporate this response into your code flow. + :rtype: ~azure.core.rest.HttpRequest + """ + + +def build_body_three_types_request(**kwargs: Any) -> HttpRequest: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + See https://aka.ms/azsdk/dpcodegen/python/send_request for how to incorporate this request + builder into your code flow. + + :keyword json: The payload body. Is one of the following types: any, IO, string Required. + :paramtype json: any or IO or str + :keyword content_type: Body Parameter content-type. Known values are: 'application/json', + 'application/octet-stream', 'text/plain'. Default value is None. + :paramtype content_type: str + :return: Returns an :class:`~azure.core.rest.HttpRequest` that you will pass to the client's + `send_request` method. See https://aka.ms/azsdk/dpcodegen/python/send_request for how to + incorporate this response into your code flow. + :rtype: ~azure.core.rest.HttpRequest + """ + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + content_type = kwargs.pop("content_type", _headers.pop("Content-Type", None)) # type: Optional[str] + accept = _headers.pop("Accept", "text/plain") + + # Construct URL + _url = "/mediatypes/bodyThreeTypes" + + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, headers=_headers, **kwargs) + + def build_put_text_and_json_body_request(*, content: str, **kwargs: Any) -> HttpRequest: """Body that's either text/plain or application/json. diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_client.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_client.py index 5f1ec19e05d..63bd27bd0cc 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_client.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_client.py @@ -29,6 +29,7 @@ class MediaTypesClient(MediaTypesClientOperationsMixin): # pylint: disable=clie """ def __init__(self, *, endpoint: str = "http://localhost:3000", **kwargs: Any) -> None: + super().__init__() self._config = MediaTypesClientConfiguration(**kwargs) self._client = PipelineClient(base_url=endpoint, config=self._config, **kwargs) diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_operations.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_operations.py index 64733b95a9e..f505f321661 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_operations.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_operations.py @@ -23,7 +23,7 @@ from azure.core.utils import case_insensitive_dict from .._serialization import Serializer -from .._vendor import MixinABC +from .._vendor import MixinABC, raise_if_not_implemented if sys.version_info >= (3, 9): from collections.abc import MutableMapping @@ -137,6 +137,14 @@ def build_put_text_and_json_body_request(*, content: str, **kwargs: Any) -> Http class MediaTypesClientOperationsMixin(MixinABC): + def __init__(self): + raise_if_not_implemented( + self.__class__, + [ + "body_three_types", + ], + ) + @overload def analyze_body( self, input: Optional[JSON] = None, *, content_type: str = "application/json", **kwargs: Any diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_vendor.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_vendor.py index 20cc10a801f..8839247c62c 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_vendor.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_vendor.py @@ -24,3 +24,14 @@ class MixinABC(ABC): _config: MediaTypesClientConfiguration _serialize: "Serializer" _deserialize: "Deserializer" + + +def raise_if_not_implemented(cls, abstract_methods): + not_implemented = [f for f in abstract_methods if not callable(getattr(cls, f, None))] + if not_implemented: + raise NotImplementedError( + "The following methods on operation group '{}' are not implemented: '{}'." + " Please refer to https://aka.ms/azsdk/python/dpcodegen/python/customize to learn how to customize.".format( + cls.__name__, "', '".join(not_implemented) + ) + ) diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_client.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_client.py index 7bc22772932..58ab74f9a89 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_client.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_client.py @@ -29,6 +29,7 @@ class MediaTypesClient(MediaTypesClientOperationsMixin): # pylint: disable=clie """ def __init__(self, *, endpoint: str = "http://localhost:3000", **kwargs: Any) -> None: + super().__init__() self._config = MediaTypesClientConfiguration(**kwargs) self._client = AsyncPipelineClient(base_url=endpoint, config=self._config, **kwargs) diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_operations.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_operations.py index a8531be4be1..49cd1b6ccb7 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_operations.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_operations.py @@ -30,7 +30,7 @@ build_content_type_with_encoding_request, build_put_text_and_json_body_request, ) -from .._vendor import MixinABC +from .._vendor import MixinABC, raise_if_not_implemented if sys.version_info >= (3, 9): from collections.abc import MutableMapping @@ -42,6 +42,14 @@ class MediaTypesClientOperationsMixin(MixinABC): + def __init__(self) -> None: + raise_if_not_implemented( + self.__class__, + [ + "body_three_types", + ], + ) + @overload async def analyze_body( self, input: Optional[JSON] = None, *, content_type: str = "application/json", **kwargs: Any diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_vendor.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_vendor.py index 35dc5b70fb9..0916c05ae48 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_vendor.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_vendor.py @@ -24,3 +24,14 @@ class MixinABC(ABC): _config: MediaTypesClientConfiguration _serialize: "Serializer" _deserialize: "Deserializer" + + +def raise_if_not_implemented(cls, abstract_methods): + not_implemented = [f for f in abstract_methods if not callable(getattr(cls, f, None))] + if not_implemented: + raise NotImplementedError( + "The following methods on operation group '{}' are not implemented: '{}'." + " Please refer to https://aka.ms/azsdk/python/dpcodegen/python/customize to learn how to customize.".format( + cls.__name__, "', '".join(not_implemented) + ) + ) From 07b7caee8a7f48f76812fb6c638fcf63d37f93d4 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 10:57:23 -0700 Subject: [PATCH 05/11] patch media types --- .../_operations/_patch.py | 169 +++++++++++++++++- .../aio/_operations/_patch.py | 95 +++++++++- 2 files changed, 260 insertions(+), 4 deletions(-) diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_patch.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_patch.py index f7dd3251033..024cea6149d 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_patch.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/_operations/_patch.py @@ -6,9 +6,174 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List +from typing import List, Any, overload, IO, Optional, cast, Union, Tuple, Dict -__all__: List[str] = [] # Add all objects you want publicly available to users at this package level +from azure.core.exceptions import ( + ClientAuthenticationError, + ResourceExistsError, + ResourceNotFoundError, + HttpResponseError, + map_error, +) +from azure.core.rest import HttpRequest +from azure.core.utils import case_insensitive_dict +from azure.core.tracing.decorator import distributed_trace +from azure.core.pipeline import PipelineResponse + +from ._operations import MediaTypesClientOperationsMixin as _MediaTypesClientOperationsMixin +from .._serialization import Serializer + +_SERIALIZER = Serializer() +_SERIALIZER.client_side_validation = False + + +def build_body_three_types_request(**kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + + content_type = kwargs.pop("content_type", _headers.pop("Content-Type", None)) # type: Optional[str] + accept = _headers.pop("Accept", "text/plain") + + # Construct URL + _url = "/mediatypes/bodyThreeTypes" + + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, headers=_headers, **kwargs) + + +class MediaTypesSharedMixin: + def _prepare_body_three_types( + self, message: Union[Any, IO, str], **kwargs: Any + ) -> Tuple[HttpRequest, Dict[str, Any]]: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type = kwargs.pop("content_type", _headers.pop("Content-Type", None)) # type: Optional[str] + _json = None + _content: Optional[Union[IO, str, bytes]] = None + if isinstance(message, (IO, bytes)): + content_type = content_type or "application/octet-stream" + _content = message + elif isinstance(message, str): + content_type = content_type or "text/plain" + _content = message + else: + _json = message + content_type = content_type or "application/json" + + request = build_body_three_types_request( + content_type=content_type, + json=_json, + content=_content, + headers=_headers, + params=_params, + ) + request.url = self._client.format_url(request.url) # type: ignore + return request, kwargs + + @staticmethod + def _handle_body_three_types_response(pipeline_response: PipelineResponse, cls=None, error_map=None): + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if response.content: + deserialized = response.json() + else: + deserialized = None + + if cls: + return cls(pipeline_response, cast(str, deserialized), {}) + + return cast(str, deserialized) + + +class MediaTypesClientOperationsMixin(_MediaTypesClientOperationsMixin, MediaTypesSharedMixin): + @overload + def body_three_types(self, message: Any, *, content_type: str = "application/json", **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: any + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def body_three_types( # type: ignore + self, message: IO, *, content_type: str = "application/octet-stream", **kwargs: Any + ) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Known values are: 'application/json', 'application/octet-stream', 'text/plain'. Default value + is "application/octet-stream". + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def body_three_types(self, message: str, *, content_type: Optional[str] = None, **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: str + :keyword content_type: Body Parameter content-type. Content type parameter for string body. + Default value is None. + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + def body_three_types(self, message: Union[Any, IO, str], **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Is one of the following types: any, IO, string Required. + :type message: any or IO or str + :keyword content_type: Body Parameter content-type. Known values are: 'application/json', + 'application/octet-stream', 'text/plain'. Default value is None. + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + cls = kwargs.pop("cls", None) + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {}) or {}) + request, kwargs = self._prepare_body_three_types(message, **kwargs) + + pipeline_response = self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + request, stream=False, **kwargs + ) + return self._handle_body_three_types_response(pipeline_response, cls=cls, error_map=error_map) + + +__all__: List[str] = [ + "MediaTypesClientOperationsMixin" +] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_patch.py b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_patch.py index f7dd3251033..f75e4deb70f 100644 --- a/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_patch.py +++ b/test/vanilla/version-tolerant/Expected/AcceptanceTests/MediaTypesVersionTolerant/mediatypesversiontolerant/aio/_operations/_patch.py @@ -6,9 +6,100 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List +from typing import List, Any, overload, IO, Optional, Union -__all__: List[str] = [] # Add all objects you want publicly available to users at this package level +from azure.core.tracing.decorator_async import distributed_trace_async +from azure.core.exceptions import ( + ClientAuthenticationError, + ResourceExistsError, + ResourceNotFoundError, +) + +from ._operations import MediaTypesClientOperationsMixin as _MediaTypesClientOperationsMixin +from ..._operations._patch import MediaTypesSharedMixin + + +class MediaTypesClientOperationsMixin(_MediaTypesClientOperationsMixin, MediaTypesSharedMixin): + @overload + async def body_three_types(self, message: Any, *, content_type: str = "application/json", **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: any + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def body_three_types( # type: ignore + self, message: IO, *, content_type: str = "application/octet-stream", **kwargs: Any + ) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: IO + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Known values are: 'application/json', 'application/octet-stream', 'text/plain'. Default value + is "application/octet-stream". + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def body_three_types(self, message: str, *, content_type: Optional[str] = None, **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Required. + :type message: str + :keyword content_type: Body Parameter content-type. Content type parameter for string body. + Default value is None. + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + async def body_three_types(self, message: Union[Any, IO, str], **kwargs: Any) -> str: + """Body with three types. Can be stream, string, or JSON. Pass in string 'hello, world' with + content type 'text/plain', {'hello': world'} with content type 'application/json' and a byte + string for 'application/octet-stream'. + + :param message: The payload body. Is one of the following types: any, IO, string Required. + :type message: any or IO or str + :keyword content_type: Body Parameter content-type. Known values are: 'application/json', + 'application/octet-stream', 'text/plain'. Default value is None. + :paramtype content_type: str + :return: str + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + """ + cls = kwargs.pop("cls", None) + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {}) or {}) + request, kwargs = self._prepare_body_three_types(message, **kwargs) + + pipeline_response = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + request, stream=False, **kwargs + ) + return self._handle_body_three_types_response(pipeline_response, cls=cls, error_map=error_map) + + +__all__: List[str] = [ + "MediaTypesClientOperationsMixin" +] # Add all objects you want publicly available to users at this package level def patch_sdk(): From a3381974fba820d633aaec89e959d6e704b5e1de Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 13:16:31 -0700 Subject: [PATCH 06/11] add tests --- .../AcceptanceTests/asynctests/test_media_types.py | 11 +++++++++++ .../AcceptanceTests/test_media_types.py | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/test/vanilla/version-tolerant/AcceptanceTests/asynctests/test_media_types.py b/test/vanilla/version-tolerant/AcceptanceTests/asynctests/test_media_types.py index 1ad1dbfa59c..889506b95cb 100644 --- a/test/vanilla/version-tolerant/AcceptanceTests/asynctests/test_media_types.py +++ b/test/vanilla/version-tolerant/AcceptanceTests/asynctests/test_media_types.py @@ -81,3 +81,14 @@ async def test_binary_body_three_content_types(client): content = "hello, world" await client.binary_body_with_three_content_types(content, content_type="text/plain") + +@pytest.mark.asyncio +async def test_body_three_types(client): + json_input = {"hello":"world"} + await client.body_three_types(json_input) + + content = b"hello, world" + await client.body_three_types(content) + + content = "hello, world" + await client.body_three_types(content) diff --git a/test/vanilla/version-tolerant/AcceptanceTests/test_media_types.py b/test/vanilla/version-tolerant/AcceptanceTests/test_media_types.py index 46d95c4d6fe..f82c00a237e 100644 --- a/test/vanilla/version-tolerant/AcceptanceTests/test_media_types.py +++ b/test/vanilla/version-tolerant/AcceptanceTests/test_media_types.py @@ -71,3 +71,13 @@ def test_binary_body_three_content_types(client): content = "hello, world" client.binary_body_with_three_content_types(content, content_type="text/plain") + +def test_body_three_types(client): + json_input = {"hello":"world"} + client.body_three_types(json_input) + + content = b"hello, world" + client.body_three_types(content) + + content = "hello, world" + client.body_three_types(content) From c3d87044873c7e7fbecb11ba22182705a23a0a38 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 13:29:30 -0700 Subject: [PATCH 07/11] get legacy passing --- autorest/codegen/serializers/builder_serializer.py | 5 +++++ .../legacy/AcceptanceTests/asynctests/test_media_types.py | 8 ++++++++ test/vanilla/legacy/AcceptanceTests/test_media_types.py | 7 +++++++ .../aio/operations/_media_types_client_operations.py | 1 - .../operations/_media_types_client_operations.py | 1 - 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/autorest/codegen/serializers/builder_serializer.py b/autorest/codegen/serializers/builder_serializer.py index a1a1837993e..1741da66186 100644 --- a/autorest/codegen/serializers/builder_serializer.py +++ b/autorest/codegen/serializers/builder_serializer.py @@ -825,10 +825,15 @@ def _create_request_builder_call( f" {parameter.client_name}={parameter.name_in_high_level_operation}," ) if request_builder.overloads: + seen_body_params = set() for overload in request_builder.overloads: body_param = cast( RequestBuilderBodyParameter, overload.parameters.body_parameter ) + if body_param.client_name in seen_body_params: + continue + seen_body_params.add(body_param.client_name) + retval.append( f" {body_param.client_name}={body_param.name_in_high_level_operation}," ) diff --git a/test/vanilla/legacy/AcceptanceTests/asynctests/test_media_types.py b/test/vanilla/legacy/AcceptanceTests/asynctests/test_media_types.py index d828acdaa22..44404c6e370 100644 --- a/test/vanilla/legacy/AcceptanceTests/asynctests/test_media_types.py +++ b/test/vanilla/legacy/AcceptanceTests/asynctests/test_media_types.py @@ -83,3 +83,11 @@ async def test_binary_body_three_content_types(self, client): content = "hello, world" await client.binary_body_with_three_content_types(content, content_type="text/plain") + + @pytest.mark.asyncio + async def test_body_three_types(self, client): + json_input = {"hello":"world"} + await client.body_three_types(json_input) + + content = b"hello, world" + await client.body_three_types(content) diff --git a/test/vanilla/legacy/AcceptanceTests/test_media_types.py b/test/vanilla/legacy/AcceptanceTests/test_media_types.py index afa15add275..0d130deb1ac 100644 --- a/test/vanilla/legacy/AcceptanceTests/test_media_types.py +++ b/test/vanilla/legacy/AcceptanceTests/test_media_types.py @@ -75,6 +75,13 @@ def test_binary_body_three_content_types(self, client): content = "hello, world" client.binary_body_with_three_content_types(content, content_type="text/plain") + def test_body_three_types(self, client): + json_input = {"hello":"world"} + client.body_three_types(json_input) + + content = b"hello, world" + client.body_three_types(content) + def test_models(self): from mediatypes.models import SourcePath diff --git a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py index a9a572213be..73caa5aa629 100644 --- a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py +++ b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/aio/operations/_media_types_client_operations.py @@ -490,7 +490,6 @@ async def body_three_types(self, message: Union[Any, IO, str], **kwargs: Any) -> content_type=content_type, json=_json, content=_content, - content=_content, template_url=self.body_three_types.metadata["url"], headers=_headers, params=_params, diff --git a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py index ed249e72f9b..9563e6089b9 100644 --- a/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py +++ b/test/vanilla/legacy/Expected/AcceptanceTests/MediaTypes/mediatypes/operations/_media_types_client_operations.py @@ -596,7 +596,6 @@ def body_three_types(self, message: Union[Any, IO, str], **kwargs: Any) -> str: content_type=content_type, json=_json, content=_content, - content=_content, template_url=self.body_three_types.metadata["url"], headers=_headers, params=_params, From ec0759d4f7a3cb57b50a7e3d000353c7d72adcf5 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 13:33:05 -0700 Subject: [PATCH 08/11] add low level tests --- .../AcceptanceTests/asynctests/test_media_types.py | 13 +++++++++++++ .../low-level/AcceptanceTests/test_media_types.py | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/test/vanilla/low-level/AcceptanceTests/asynctests/test_media_types.py b/test/vanilla/low-level/AcceptanceTests/asynctests/test_media_types.py index e33d7361bd4..cdf34e4ba4e 100644 --- a/test/vanilla/low-level/AcceptanceTests/asynctests/test_media_types.py +++ b/test/vanilla/low-level/AcceptanceTests/asynctests/test_media_types.py @@ -96,3 +96,16 @@ async def test_binary_body_three_content_types(send_request): content = "hello, world" request = build_binary_body_with_three_content_types_request(content=content, content_type="text/plain") await send_request(request) + +@pytest.mark.asyncio +async def test_body_three_types(send_request): + request = build_body_three_types_request(json={"hello":"world"}) + await send_request(request) + + content = b"hello, world" + request = build_body_three_types_request(content=content, content_type="application/octet-stream") + await send_request(request) + + content = "hello, world" + request = build_body_three_types_request(content=content, content_type="text/plain") + await send_request(request) diff --git a/test/vanilla/low-level/AcceptanceTests/test_media_types.py b/test/vanilla/low-level/AcceptanceTests/test_media_types.py index 82f55d059b6..0a65745e3f7 100644 --- a/test/vanilla/low-level/AcceptanceTests/test_media_types.py +++ b/test/vanilla/low-level/AcceptanceTests/test_media_types.py @@ -86,3 +86,15 @@ def test_binary_body_three_content_types(send_request): content = "hello, world" request = build_binary_body_with_three_content_types_request(content=content, content_type="text/plain") send_request(request) + +def test_body_three_types(send_request): + request = build_body_three_types_request(json={"hello":"world"}) + send_request(request) + + content = b"hello, world" + request = build_body_three_types_request(content=content, content_type="application/octet-stream") + send_request(request) + + content = "hello, world" + request = build_body_three_types_request(content=content, content_type="text/plain") + send_request(request) From e01e170c59222f995ed8b6f6295c1b6b25d8535a Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 13:37:50 -0700 Subject: [PATCH 09/11] update testserver dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a971403f8aa..1c17734a0b5 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@autorest/system-requirements": "~1.0.0" }, "devDependencies": { - "@microsoft.azure/autorest.testserver": "^3.3.28" + "@microsoft.azure/autorest.testserver": "^3.3.29" }, "files": [ "autorest/**/*.py", From a1b732fa44a6a8d0fcdad1bfdb64882258459dba Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 13:39:11 -0700 Subject: [PATCH 10/11] update changelog --- ChangeLog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index cd664bb0b42..eca7795e6ef 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -14,6 +14,9 @@ - Only generate Python3 SDKs #1297 - Don't reformat initial query parameters into the next link #1297 +**Breaking Changes in Version Tolerant** +- Don't generate operations with more than two body types. SDK authors need to implement this operation themselves #1300 + ### 2022-07-13 - 5.19.0 | Library | Min Version | From 15a0b2cc4afa67207370a53086a0da531246db01 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 14 Jun 2022 14:18:41 -0700 Subject: [PATCH 11/11] fix unittests --- ChangeLog.md | 1 + test/unittests/test_optional_return_type.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index eca7795e6ef..f39099a549e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -15,6 +15,7 @@ - Don't reformat initial query parameters into the next link #1297 **Breaking Changes in Version Tolerant** + - Don't generate operations with more than two body types. SDK authors need to implement this operation themselves #1300 ### 2022-07-13 - 5.19.0 diff --git a/test/unittests/test_optional_return_type.py b/test/unittests/test_optional_return_type.py index 9b735e6f763..ae532db4b59 100644 --- a/test/unittests/test_optional_return_type.py +++ b/test/unittests/test_optional_return_type.py @@ -21,7 +21,8 @@ def code_model(): }}, options={ "show_send_request": True, - "builders_visibility": "public" + "builders_visibility": "public", + "version_tolerant": True }, )