From 895df26b702e796ef11f30eae23b8178cb7fbb04 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Feb 2022 14:50:41 -0500 Subject: [PATCH 1/5] regen and add patch file for legacy --- .../AcceptanceTests/asynctests/test_paging.py | 7 ++ .../legacy/AcceptanceTests/test_paging.py | 6 ++ .../AcceptanceTests/Paging/paging/_patch.py | 35 ++++++- .../Paging/paging/aio/_patch.py | 16 +++- .../aio/operations/_paging_operations.py | 64 +++++++++++++ .../paging/operations/_paging_operations.py | 96 +++++++++++++++++++ .../paginglowlevel/rest/paging/__init__.py | 3 + .../rest/paging/_request_builders.py | 59 ++++++++++++ .../rest/paging/_request_builders_py3.py | 48 ++++++++++ .../AcceptanceTests/test_paging.py | 3 + .../aio/operations/_operations.py | 73 ++++++++++++++ .../operations/_operations.py | 90 +++++++++++++++++ 12 files changed, 498 insertions(+), 2 deletions(-) diff --git a/test/azure/legacy/AcceptanceTests/asynctests/test_paging.py b/test/azure/legacy/AcceptanceTests/asynctests/test_paging.py index f023a68bcb6..a143dc5b8ac 100644 --- a/test/azure/legacy/AcceptanceTests/asynctests/test_paging.py +++ b/test/azure/legacy/AcceptanceTests/asynctests/test_paging.py @@ -240,3 +240,10 @@ async def test_item_name_with_xms_client_name(self, client): async for item in pages: items.append(item) assert len(items) == 1 + + @pytest.mark.asyncio + async def test_duplicate_params(self, client): + pages = [p async for p in client.paging.duplicate_params(filter="foo")] + assert len(pages) == 1 + assert pages[0].properties.id == 1 + assert pages[0].properties.name == "Product" diff --git a/test/azure/legacy/AcceptanceTests/test_paging.py b/test/azure/legacy/AcceptanceTests/test_paging.py index e7c5f78f751..def8a1c2f4a 100644 --- a/test/azure/legacy/AcceptanceTests/test_paging.py +++ b/test/azure/legacy/AcceptanceTests/test_paging.py @@ -180,6 +180,12 @@ def test_initial_response_no_items(self, client): items = [i for i in pages] assert len(items) == 1 + def test_duplicate_params(self, client): + pages = list(client.paging.duplicate_params(filter="foo")) + assert len(pages) == 1 + assert pages[0].properties.id == 1 + assert pages[0].properties.name == "Product" + def test_models(self): from paging.models import OperationResult if sys.version_info >= (3,5): diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py index f99e77fef98..80cf90f4215 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py @@ -24,8 +24,41 @@ # IN THE SOFTWARE. # # -------------------------------------------------------------------------- +import copy +from typing import List +import importlib +import urllib.parse +from ._auto_rest_paging_test_service import AutoRestPagingTestService as AutoRestPagingTestServiceGenerated +from azure.core.pipeline.policies import SansIOHTTPPolicy + +class RemoveDuplicateParamsPolicy(SansIOHTTPPolicy): + def __init__(self, duplicate_param_names): + # type: (List[str]) -> None + self.duplicate_param_names = duplicate_param_names + + def on_request(self, request): + parsed_url = urllib.parse.urlparse(request.http_request.url) + query_params = urllib.parse.parse_qs(parsed_url.query) + updated_query_params = copy.copy(query_params) + for query in query_params: + if query in self.duplicate_param_names and (isinstance(query_params[query], list) and len(query_params[query]) > 1): + updated_query_params[query] = [query_params[query][-1]] + # service returned will be later in the url because of how we format + request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urllib.parse.urlencode(updated_query_params, doseq=True) + return super().on_request(request) + +class AutoRestPagingTestService(AutoRestPagingTestServiceGenerated): + def __init__(self, *args, **kwargs): + per_call_policies = kwargs.pop("per_call_policies", []) + params_policy = RemoveDuplicateParamsPolicy(duplicate_param_names=["$filter", "$skiptoken"]) + try: + per_call_policies.append(params_policy) + except AttributeError: + per_call_policies = [per_call_policies, params_policy] + super().__init__(*args, per_call_policies=per_call_policies, **kwargs) # This file is used for handwritten extensions to the generated code. Example: # https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/customize_code/how-to-patch-sdk-code.md def patch_sdk(): - pass + curr_package = importlib.import_module("paging") + curr_package.AutoRestPagingTestService = AutoRestPagingTestService diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/_patch.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/_patch.py index f99e77fef98..e3c8b2037ba 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/_patch.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/_patch.py @@ -24,8 +24,22 @@ # IN THE SOFTWARE. # # -------------------------------------------------------------------------- +import importlib +from .._patch import RemoveDuplicateParamsPolicy +from ._auto_rest_paging_test_service import AutoRestPagingTestService as AutoRestPagingTestServiceGenerated + +class AutoRestPagingTestService(AutoRestPagingTestServiceGenerated): + def __init__(self, *args, **kwargs): + per_call_policies = kwargs.pop("per_call_policies", []) + params_policy = RemoveDuplicateParamsPolicy(duplicate_param_names=["$filter", "$skiptoken"]) + try: + per_call_policies.append(params_policy) + except AttributeError: + per_call_policies = [per_call_policies, params_policy] + super().__init__(*args, per_call_policies=per_call_policies, **kwargs) # This file is used for handwritten extensions to the generated code. Example: # https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/customize_code/how-to-patch-sdk-code.md def patch_sdk(): - pass + curr_package = importlib.import_module("paging.aio") + curr_package.AutoRestPagingTestService = AutoRestPagingTestService diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py index 244389e22ef..b2888c90608 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py @@ -27,6 +27,7 @@ from ... import models as _models from ..._vendor import _convert_request from ...operations._paging_operations import ( + build_duplicate_params_request, build_first_response_empty_request, build_get_multiple_pages_failure_request, build_get_multiple_pages_failure_uri_request, @@ -458,6 +459,69 @@ async def get_next(next_link=None): get_with_query_params.metadata = {"url": "/paging/multiple/getWithQueryParams"} # type: ignore + @distributed_trace + def duplicate_params(self, filter: Optional[str] = None, **kwargs: Any) -> AsyncIterable["_models.ProductResult"]: + """Define ``filter`` as a query param for all calls. However, the returned next link will also + include the ``filter`` as part of it. Make sure you don't end up duplicating the ``filter`` + param in the url sent. + + :param filter: OData filter options. Pass in 'foo'. + :type filter: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either ProductResult or the result of cls(response) + :rtype: ~azure.core.async_paging.AsyncItemPaged[~paging.models.ProductResult] + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop("cls", None) # type: ClsType["_models.ProductResult"] + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {})) + + def prepare_request(next_link=None): + if not next_link: + + request = build_duplicate_params_request( + filter=filter, + template_url=self.duplicate_params.metadata["url"], + ) + request = _convert_request(request) + request.url = self._client.format_url(request.url) + + else: + + request = build_duplicate_params_request( + filter=filter, + template_url=next_link, + ) + request = _convert_request(request) + request.url = self._client.format_url(request.url) + request.method = "GET" + return request + + async def extract_data(pipeline_response): + deserialized = self._deserialize("ProductResult", pipeline_response) + list_of_elem = deserialized.values + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.next_link or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = await self._client._pipeline.run( # 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) + + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + + duplicate_params.metadata = {"url": "/paging/multiple/duplicateParams/1"} # type: ignore + @distributed_trace def get_odata_multiple_pages( self, diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py index 413472d4e26..7ac66fd24b4 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py @@ -178,6 +178,34 @@ def build_get_with_query_params_request( ) +def build_duplicate_params_request( + **kwargs # type: Any +): + # type: (...) -> HttpRequest + filter = kwargs.pop('filter', None) # type: Optional[str] + + accept = "application/json" + # Construct URL + _url = kwargs.pop("template_url", "/paging/multiple/duplicateParams/1") + + # Construct parameters + _query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if filter is not None: + _query_parameters['$filter'] = _SERIALIZER.query("filter", filter, 'str') + + # Construct headers + _header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + _header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str') + + return HttpRequest( + method="GET", + url=_url, + params=_query_parameters, + headers=_header_parameters, + **kwargs + ) + + def build_next_operation_with_query_params_request( **kwargs # type: Any ): @@ -978,6 +1006,74 @@ def get_next(next_link=None): get_with_query_params.metadata = {"url": "/paging/multiple/getWithQueryParams"} # type: ignore + @distributed_trace + def duplicate_params( + self, + filter=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> Iterable["_models.ProductResult"] + """Define ``filter`` as a query param for all calls. However, the returned next link will also + include the ``filter`` as part of it. Make sure you don't end up duplicating the ``filter`` + param in the url sent. + + :param filter: OData filter options. Pass in 'foo'. + :type filter: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either ProductResult or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~paging.models.ProductResult] + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop("cls", None) # type: ClsType["_models.ProductResult"] + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {})) + + def prepare_request(next_link=None): + if not next_link: + + request = build_duplicate_params_request( + filter=filter, + template_url=self.duplicate_params.metadata["url"], + ) + request = _convert_request(request) + request.url = self._client.format_url(request.url) + + else: + + request = build_duplicate_params_request( + filter=filter, + template_url=next_link, + ) + request = _convert_request(request) + request.url = self._client.format_url(request.url) + request.method = "GET" + return request + + def extract_data(pipeline_response): + deserialized = self._deserialize("ProductResult", pipeline_response) + list_of_elem = deserialized.values + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.next_link or None, iter(list_of_elem) + + def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = self._client._pipeline.run( # 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) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + duplicate_params.metadata = {"url": "/paging/multiple/duplicateParams/1"} # type: ignore + @distributed_trace def get_odata_multiple_pages( self, diff --git a/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/__init__.py b/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/__init__.py index 94cb2afe469..381f5914e53 100644 --- a/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/__init__.py +++ b/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/__init__.py @@ -13,6 +13,7 @@ from ._request_builders_py3 import build_first_response_empty_request from ._request_builders_py3 import build_get_multiple_pages_request from ._request_builders_py3 import build_get_with_query_params_request + from ._request_builders_py3 import build_duplicate_params_request from ._request_builders_py3 import build_next_operation_with_query_params_request from ._request_builders_py3 import build_get_odata_multiple_pages_request from ._request_builders_py3 import build_get_multiple_pages_with_offset_request @@ -34,6 +35,7 @@ from ._request_builders import build_first_response_empty_request # type: ignore from ._request_builders import build_get_multiple_pages_request # type: ignore from ._request_builders import build_get_with_query_params_request # type: ignore + from ._request_builders import build_duplicate_params_request # type: ignore from ._request_builders import build_next_operation_with_query_params_request # type: ignore from ._request_builders import build_get_odata_multiple_pages_request # type: ignore from ._request_builders import build_get_multiple_pages_with_offset_request # type: ignore @@ -56,6 +58,7 @@ "build_first_response_empty_request", "build_get_multiple_pages_request", "build_get_with_query_params_request", + "build_duplicate_params_request", "build_next_operation_with_query_params_request", "build_get_odata_multiple_pages_request", "build_get_multiple_pages_with_offset_request", diff --git a/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders.py b/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders.py index 62c68d3d114..b6265399c41 100644 --- a/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders.py +++ b/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders.py @@ -339,6 +339,65 @@ def build_get_with_query_params_request( ) +def build_duplicate_params_request( + **kwargs # type: Any +): + # type: (...) -> HttpRequest + """Define ``filter`` as a query param for all calls. However, the returned next link will also + include the ``filter`` as part of it. Make sure you don't end up duplicating the ``filter`` + param in the url sent. + + See https://aka.ms/azsdk/python/protocol/quickstart for how to incorporate this request builder + into your code flow. + + :keyword filter: OData filter options. Pass in 'foo'. + :paramtype filter: 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/python/protocol/quickstart for how to + incorporate this response into your code flow. + :rtype: ~azure.core.rest.HttpRequest + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response.json() == { + "nextLink": "str", # Optional. + "values": [ + { + "properties": { + "id": 0, # Optional. + "name": "str" # Optional. + } + } + ] + } + """ + + filter = kwargs.pop('filter', None) # type: Optional[str] + + accept = "application/json" + # Construct URL + _url = "/paging/multiple/duplicateParams/1" + + # Construct parameters + _query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if filter is not None: + _query_parameters['$filter'] = _SERIALIZER.query("filter", filter, 'str') + + # Construct headers + _header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + _header_parameters['Accept'] = _SERIALIZER.header("accept", accept, 'str') + + return HttpRequest( + method="GET", + url=_url, + params=_query_parameters, + headers=_header_parameters, + **kwargs + ) + + def build_next_operation_with_query_params_request( **kwargs # type: Any ): diff --git a/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders_py3.py b/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders_py3.py index 787419ee390..11bdcd747be 100644 --- a/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders_py3.py +++ b/test/azure/low-level/Expected/AcceptanceTests/PagingLowLevel/paginglowlevel/rest/paging/_request_builders_py3.py @@ -288,6 +288,54 @@ def build_get_with_query_params_request(*, required_query_parameter: int, **kwar return HttpRequest(method="GET", url=_url, params=_query_parameters, headers=_header_parameters, **kwargs) +def build_duplicate_params_request(*, filter: Optional[str] = None, **kwargs: Any) -> HttpRequest: + """Define ``filter`` as a query param for all calls. However, the returned next link will also + include the ``filter`` as part of it. Make sure you don't end up duplicating the ``filter`` + param in the url sent. + + See https://aka.ms/azsdk/python/protocol/quickstart for how to incorporate this request builder + into your code flow. + + :keyword filter: OData filter options. Pass in 'foo'. + :paramtype filter: 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/python/protocol/quickstart for how to + incorporate this response into your code flow. + :rtype: ~azure.core.rest.HttpRequest + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response.json() == { + "nextLink": "str", # Optional. + "values": [ + { + "properties": { + "id": 0, # Optional. + "name": "str" # Optional. + } + } + ] + } + """ + + accept = "application/json" + # Construct URL + _url = "/paging/multiple/duplicateParams/1" + + # Construct parameters + _query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if filter is not None: + _query_parameters["$filter"] = _SERIALIZER.query("filter", filter, "str") + + # Construct headers + _header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + _header_parameters["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_query_parameters, headers=_header_parameters, **kwargs) + + def build_next_operation_with_query_params_request(**kwargs: Any) -> HttpRequest: """Next operation for getWithQueryParams. Pass in next=True to pass test. Returns a ProductResult. diff --git a/test/azure/version-tolerant/AcceptanceTests/test_paging.py b/test/azure/version-tolerant/AcceptanceTests/test_paging.py index 407d8918fb0..f95ee8394fd 100644 --- a/test/azure/version-tolerant/AcceptanceTests/test_paging.py +++ b/test/azure/version-tolerant/AcceptanceTests/test_paging.py @@ -164,3 +164,6 @@ def test_initial_response_no_items(client): pages = client.paging.first_response_empty() items = [i for i in pages] assert len(items) == 1 + +def test_duplicate_params(client: AutoRestPagingTestService): + pages = list(client.paging.duplicate_params("duplicateParams", filter="foo")) diff --git a/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/aio/operations/_operations.py b/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/aio/operations/_operations.py index 4f12e8c1308..047e20e3f81 100644 --- a/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/aio/operations/_operations.py +++ b/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/aio/operations/_operations.py @@ -25,6 +25,7 @@ from azure.core.tracing.decorator_async import distributed_trace_async from ...operations._operations import ( + build_paging_duplicate_params_request, build_paging_first_response_empty_request, build_paging_get_multiple_pages_failure_request, build_paging_get_multiple_pages_failure_uri_request, @@ -492,6 +493,78 @@ async def get_next(next_link=None): return AsyncItemPaged(get_next, extract_data) + @distributed_trace + def duplicate_params(self, *, filter: Optional[str] = None, **kwargs: Any) -> AsyncIterable[JSONType]: + """Define ``filter`` as a query param for all calls. However, the returned next link will also + include the ``filter`` as part of it. Make sure you don't end up duplicating the ``filter`` + param in the url sent. + + :keyword filter: OData filter options. Pass in 'foo'. + :paramtype filter: str + :return: An iterator like instance of JSON object + :rtype: ~azure.core.async_paging.AsyncItemPaged[JSONType] + :raises: ~azure.core.exceptions.HttpResponseError + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response.json() == { + "nextLink": "str", # Optional. + "values": [ + { + "properties": { + "id": 0, # Optional. + "name": "str" # Optional. + } + } + ] + } + """ + cls = kwargs.pop("cls", None) # type: ClsType[JSONType] + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {})) + + def prepare_request(next_link=None): + if not next_link: + + request = build_paging_duplicate_params_request( + filter=filter, + ) + request.url = self._client.format_url(request.url) + + else: + + request = build_paging_duplicate_params_request( + filter=filter, + ) + request.url = self._client.format_url(next_link) + request.method = "GET" + return request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = deserialized["values"] + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.get("nextLink", None), AsyncList(list_of_elem) + + async def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = await self._client._pipeline.run( # 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) + + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + @distributed_trace def get_odata_multiple_pages( self, diff --git a/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/operations/_operations.py b/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/operations/_operations.py index 452e7b6da9a..142574af12f 100644 --- a/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/operations/_operations.py +++ b/test/azure/version-tolerant/Expected/AcceptanceTests/PagingVersionTolerant/pagingversiontolerant/operations/_operations.py @@ -128,6 +128,23 @@ def build_paging_get_with_query_params_request(*, required_query_parameter: int, return HttpRequest(method="GET", url=_url, params=_query_parameters, headers=_header_parameters, **kwargs) +def build_paging_duplicate_params_request(*, filter: Optional[str] = None, **kwargs: Any) -> HttpRequest: + accept = "application/json" + # Construct URL + _url = "/paging/multiple/duplicateParams/1" + + # Construct parameters + _query_parameters = kwargs.pop("params", {}) # type: Dict[str, Any] + if filter is not None: + _query_parameters["$filter"] = _SERIALIZER.query("filter", filter, "str") + + # Construct headers + _header_parameters = kwargs.pop("headers", {}) # type: Dict[str, Any] + _header_parameters["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_query_parameters, headers=_header_parameters, **kwargs) + + def build_paging_next_operation_with_query_params_request(**kwargs: Any) -> HttpRequest: query_constant = kwargs.pop("query_constant", True) # type: bool @@ -829,6 +846,79 @@ def get_next(next_link=None): return ItemPaged(get_next, extract_data) + @distributed_trace + def duplicate_params(self, *, filter: Optional[str] = None, **kwargs: Any) -> Iterable[JSONType]: + """Define ``filter`` as a query param for all calls. However, the returned next link will also + include the ``filter`` as part of it. Make sure you don't end up duplicating the ``filter`` + param in the url sent. + + :keyword filter: OData filter options. Pass in 'foo'. + :paramtype filter: str + :return: An iterator like instance of JSON object + :rtype: ~azure.core.paging.ItemPaged[JSONType] + :raises: ~azure.core.exceptions.HttpResponseError + + Example: + .. code-block:: python + + # response body for status code(s): 200 + response.json() == { + "nextLink": "str", # Optional. + "values": [ + { + "properties": { + "id": 0, # Optional. + "name": "str" # Optional. + } + } + ] + } + """ + + cls = kwargs.pop("cls", None) # type: ClsType[JSONType] + error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} + error_map.update(kwargs.pop("error_map", {})) + + def prepare_request(next_link=None): + if not next_link: + + request = build_paging_duplicate_params_request( + filter=filter, + ) + request.url = self._client.format_url(request.url) + + else: + + request = build_paging_duplicate_params_request( + filter=filter, + ) + request.url = self._client.format_url(next_link) + request.method = "GET" + return request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = deserialized["values"] + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.get("nextLink", None), iter(list_of_elem) + + def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = self._client._pipeline.run( # 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) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + @distributed_trace def get_odata_multiple_pages( self, From 20805f64870dcca32840dbc1a5f3df97a477f9cd Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Feb 2022 16:52:38 -0500 Subject: [PATCH 2/5] update patch file --- .../AcceptanceTests/Paging/paging/_patch.py | 11 +- test/azure/legacy/coverage/report-azure.json | 185 +++++++++--------- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py index 80cf90f4215..cd33b6594a7 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py @@ -24,7 +24,6 @@ # IN THE SOFTWARE. # # -------------------------------------------------------------------------- -import copy from typing import List import importlib import urllib.parse @@ -39,12 +38,12 @@ def __init__(self, duplicate_param_names): def on_request(self, request): parsed_url = urllib.parse.urlparse(request.http_request.url) query_params = urllib.parse.parse_qs(parsed_url.query) - updated_query_params = copy.copy(query_params) - for query in query_params: - if query in self.duplicate_param_names and (isinstance(query_params[query], list) and len(query_params[query]) > 1): - updated_query_params[query] = [query_params[query][-1]] # service returned will be later in the url because of how we format - request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urllib.parse.urlencode(updated_query_params, doseq=True) + filtered_query_params = { + k: v[-1:] if k in self.duplicate_param_names else v + for k, v in query_params.items() + } + request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urllib.parse.urlencode(filtered_query_params, doseq=True) return super().on_request(request) class AutoRestPagingTestService(AutoRestPagingTestServiceGenerated): diff --git a/test/azure/legacy/coverage/report-azure.json b/test/azure/legacy/coverage/report-azure.json index fc04d3b16cb..7dc8c346581 100644 --- a/test/azure/legacy/coverage/report-azure.json +++ b/test/azure/legacy/coverage/report-azure.json @@ -1,92 +1,93 @@ { - "LROPostDoubleHeadersFinalLocationPost": 2, - "LROPostDoubleHeadersFinalLocationAsync": 3, - "LROPostDoubleHeadersFinalLocationGet": 3, - "LROConstantParameterizedPost": 1, - "LROConstantParameterizedGet": 1, - "PostParameterGroupingWithReservedWords": 1, - "LROPutInlineComplete": 2, - "LROPutInlineComplete201": 1, - "CustomHeaderPutAsyncSucceded": 1, - "CustomHeaderPostAsyncSucceded": 1, - "CustomHeaderPutSucceeded": 1, - "CustomHeaderPostSucceeded": 1, - "LROPut200InlineCompleteNoState": 1, + "LROPostDoubleHeadersFinalLocationPost": 0, + "LROPostDoubleHeadersFinalLocationAsync": 0, + "LROPostDoubleHeadersFinalLocationGet": 0, + "LROConstantParameterizedPost": 0, + "LROConstantParameterizedGet": 0, + "PagingDuplicateParameters": 2, + "PostParameterGroupingWithReservedWords": 0, + "LROPutInlineComplete": 0, + "LROPutInlineComplete201": 0, + "CustomHeaderPutAsyncSucceded": 0, + "CustomHeaderPostAsyncSucceded": 0, + "CustomHeaderPutSucceeded": 0, + "CustomHeaderPostSucceeded": 0, + "LROPut200InlineCompleteNoState": 0, "LROPatchInlineCompleteIgnoreHeaders": 0, - "LROPatch201WithAsyncHeader": 1, - "LROPatch202WithAsyncAndLocationHeader": 1, - "LROPut202Retry200": 1, - "LROPutSucceededWithBody": 1, - "LROPutSucceededNoBody": 1, - "LROPutFailed": 1, - "LROPutCanceled": 1, - "LROPutAsyncRetrySucceeded": 1, - "LROPutAsyncNoRetrySucceeded": 1, - "LROPutAsyncRetryFailed": 1, - "LROPutAsyncNoRetryCanceled": 1, - "LROPutNoHeaderInRetry": 1, - "LROPutAsyncNoHeaderInRetry": 1, - "LRODeleteNoHeaderInRetry": 1, - "LRODeleteAsyncNoHeaderInRetry": 1, - "LROPutSubResourceInRetry": 1, - "LROPutSubResourceAsyncInRetry": 2, - "LROPutNonResourceInRetry": 1, - "LROPutNonResourceAsyncInRetry": 1, - "LRODeleteProvisioningSucceededWithBody": 1, - "LRODeleteProvisioningFailed": 1, - "LRODeleteProvisioningCanceled": 1, - "LRODeleteInlineComplete": 1, - "LRODelete200": 1, - "LRODelete204": 1, - "LRODeleteAsyncRetrySucceeded": 1, - "LRODeleteAsyncNoRetrySucceeded": 1, - "LRODeleteAsyncRetryFailed": 1, - "LRODeleteAsyncRetryCanceled": 1, - "LROPostSuccededWithBody": 1, - "LROPostSuccededNoBody": 1, - "LROPost200": 1, - "LROPostDoubleHeadersFinalAzureHeaderGet": 1, - "LROPostDoubleHeadersFinalAzureHeaderGetDefault": 5, - "LROPostAndGetList": 1, - "LROPostAsyncRetrySucceeded": 1, - "LROPostAsyncNoRetrySucceeded": 1, - "LROPostAsyncRetryFailed": 1, - "LROPostAsyncRetryCanceled": 1, - "LRORetryPutSucceededWithBody": 1, - "LRORetryErrorPutAsyncSucceeded": 1, - "LRORetryErrorPutAsyncSucceededPolling": 1, - "LRORetryErrorDelete202Accepted200Succeeded": 1, - "LRORetryErrorDelete202Retry200Succeeded": 1, - "LRORetryErrorDeleteAsyncRetrySucceeded": 1, - "LRORetryErrorPost202Retry200Succeeded": 1, - "LRORetryErrorPostAsyncRetrySucceeded": 2, - "LRONonRetryPut400": 1, - "LRONonRetryPut201Creating400": 1, - "LRONonRetryPut201Creating400InvalidJson": 1, - "LRONonRetryPutAsyncRetry400": 1, - "LRONonRetryDelete400": 1, - "LRONonRetryDelete202Retry400": 1, - "LRONonRetryDeleteAsyncRetry400": 1, - "LRONonRetryPost400": 1, - "LRONonRetryPost202Retry400": 1, - "LRONonRetryPostAsyncRetry400": 1, - "LROErrorPut201NoProvisioningStatePayload": 1, - "LROErrorPutAsyncNoPollingStatus": 1, - "LROErrorPutAsyncNoPollingStatusPayload": 1, - "LROErrorPut200InvalidJson": 1, - "LROErrorPutAsyncInvalidHeader": 1, - "LROErrorPutAsyncInvalidJsonPolling": 1, - "LROErrorDeleteNoLocation": 1, - "LROErrorDelete202RetryInvalidHeader": 1, - "LROErrorDeleteAsyncNoPollingStatus": 1, - "LROErrorDeleteAsyncInvalidHeader": 1, - "LROErrorDeleteAsyncInvalidJsonPolling": 1, - "LROErrorPostNoLocation": 1, - "LROErrorPost202RetryInvalidHeader": 1, - "LROErrorPostAsyncNoPollingPayload": 1, - "LROErrorPostAsyncInvalidHeader": 1, - "LROErrorPostAsyncInvalidJsonPolling": 1, - "LROParameterizedEndpoint": 1, + "LROPatch201WithAsyncHeader": 0, + "LROPatch202WithAsyncAndLocationHeader": 0, + "LROPut202Retry200": 0, + "LROPutSucceededWithBody": 0, + "LROPutSucceededNoBody": 0, + "LROPutFailed": 0, + "LROPutCanceled": 0, + "LROPutAsyncRetrySucceeded": 0, + "LROPutAsyncNoRetrySucceeded": 0, + "LROPutAsyncRetryFailed": 0, + "LROPutAsyncNoRetryCanceled": 0, + "LROPutNoHeaderInRetry": 0, + "LROPutAsyncNoHeaderInRetry": 0, + "LRODeleteNoHeaderInRetry": 0, + "LRODeleteAsyncNoHeaderInRetry": 0, + "LROPutSubResourceInRetry": 0, + "LROPutSubResourceAsyncInRetry": 0, + "LROPutNonResourceInRetry": 0, + "LROPutNonResourceAsyncInRetry": 0, + "LRODeleteProvisioningSucceededWithBody": 0, + "LRODeleteProvisioningFailed": 0, + "LRODeleteProvisioningCanceled": 0, + "LRODeleteInlineComplete": 0, + "LRODelete200": 0, + "LRODelete204": 0, + "LRODeleteAsyncRetrySucceeded": 0, + "LRODeleteAsyncNoRetrySucceeded": 0, + "LRODeleteAsyncRetryFailed": 0, + "LRODeleteAsyncRetryCanceled": 0, + "LROPostSuccededWithBody": 0, + "LROPostSuccededNoBody": 0, + "LROPost200": 0, + "LROPostDoubleHeadersFinalAzureHeaderGet": 0, + "LROPostDoubleHeadersFinalAzureHeaderGetDefault": 0, + "LROPostAndGetList": 0, + "LROPostAsyncRetrySucceeded": 0, + "LROPostAsyncNoRetrySucceeded": 0, + "LROPostAsyncRetryFailed": 0, + "LROPostAsyncRetryCanceled": 0, + "LRORetryPutSucceededWithBody": 0, + "LRORetryErrorPutAsyncSucceeded": 0, + "LRORetryErrorPutAsyncSucceededPolling": 0, + "LRORetryErrorDelete202Accepted200Succeeded": 0, + "LRORetryErrorDelete202Retry200Succeeded": 0, + "LRORetryErrorDeleteAsyncRetrySucceeded": 0, + "LRORetryErrorPost202Retry200Succeeded": 0, + "LRORetryErrorPostAsyncRetrySucceeded": 0, + "LRONonRetryPut400": 0, + "LRONonRetryPut201Creating400": 0, + "LRONonRetryPut201Creating400InvalidJson": 0, + "LRONonRetryPutAsyncRetry400": 0, + "LRONonRetryDelete400": 0, + "LRONonRetryDelete202Retry400": 0, + "LRONonRetryDeleteAsyncRetry400": 0, + "LRONonRetryPost400": 0, + "LRONonRetryPost202Retry400": 0, + "LRONonRetryPostAsyncRetry400": 0, + "LROErrorPut201NoProvisioningStatePayload": 0, + "LROErrorPutAsyncNoPollingStatus": 0, + "LROErrorPutAsyncNoPollingStatusPayload": 0, + "LROErrorPut200InvalidJson": 0, + "LROErrorPutAsyncInvalidHeader": 0, + "LROErrorPutAsyncInvalidJsonPolling": 0, + "LROErrorDeleteNoLocation": 0, + "LROErrorDelete202RetryInvalidHeader": 0, + "LROErrorDeleteAsyncNoPollingStatus": 0, + "LROErrorDeleteAsyncInvalidHeader": 0, + "LROErrorDeleteAsyncInvalidJsonPolling": 0, + "LROErrorPostNoLocation": 0, + "LROErrorPost202RetryInvalidHeader": 0, + "LROErrorPostAsyncNoPollingPayload": 0, + "LROErrorPostAsyncInvalidHeader": 0, + "LROErrorPostAsyncInvalidJsonPolling": 0, + "LROParameterizedEndpoint": 0, "PagingNoItemName": 1, "PagingNextLinkNameNull": 1, "PagingSingle": 2, @@ -134,9 +135,9 @@ "AzureXmsCustomNamedRequestIdParameterGroup": 0, "AzureRequestClientIdInError": 0, "AzureODataFilter": 0, - "SubscriptionIdAndApiVersion": 1, - "postParameterGroupingOptionalParameters": 2, - "postParameterGroupingRequiredParameters": 2, - "postParameterGroupingMultipleParameterGroups": 2, - "postParameterGroupingSharedParameterGroupObject": 1 + "SubscriptionIdAndApiVersion": 0, + "postParameterGroupingOptionalParameters": 0, + "postParameterGroupingRequiredParameters": 0, + "postParameterGroupingMultipleParameterGroups": 0, + "postParameterGroupingSharedParameterGroupObject": 0 } \ No newline at end of file From 3833b3fdd44c5b7e612d58ef98a0efa2ab9e6a2d Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 17 Feb 2022 12:28:37 -0500 Subject: [PATCH 3/5] add test for LLC and skip for version tolerant --- .../AcceptanceTests/asynctests/test_paging.py | 9 +++++ .../low-level/AcceptanceTests/test_paging.py | 8 +++++ .../low-level/coverage/report-azure.json | 35 ++++++++++--------- .../AcceptanceTests/test_zzz.py | 1 + 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/test/azure/low-level/AcceptanceTests/asynctests/test_paging.py b/test/azure/low-level/AcceptanceTests/asynctests/test_paging.py index a46f5ea85cb..6d5cac10dd5 100644 --- a/test/azure/low-level/AcceptanceTests/asynctests/test_paging.py +++ b/test/azure/low-level/AcceptanceTests/asynctests/test_paging.py @@ -328,3 +328,12 @@ async def test_initial_response_no_items(get_pager): async for page in pages: items.append(page) assert len(items) == 1 + +@pytest.mark.asyncio +async def test_duplicate_params(get_pager): + pages = get_pager( + initial_request=functools.partial(paging.build_duplicate_params_request, filter="foo"), + item_name="values" + ) + items = [i async for i in pages] + assert len(items) == 1 diff --git a/test/azure/low-level/AcceptanceTests/test_paging.py b/test/azure/low-level/AcceptanceTests/test_paging.py index 01ffb23a5ee..8df1bd09565 100644 --- a/test/azure/low-level/AcceptanceTests/test_paging.py +++ b/test/azure/low-level/AcceptanceTests/test_paging.py @@ -279,3 +279,11 @@ def test_initial_response_no_items(get_pager): ) items = [i for i in pages] assert len(items) == 1 + +def test_duplicate_params(get_pager): + pages = get_pager( + initial_request=functools.partial(paging.build_duplicate_params_request, filter="foo"), + item_name="values" + ) + items = [i for i in pages] + assert len(items) == 1 diff --git a/test/azure/low-level/coverage/report-azure.json b/test/azure/low-level/coverage/report-azure.json index b512e492f2d..aa5a5478029 100644 --- a/test/azure/low-level/coverage/report-azure.json +++ b/test/azure/low-level/coverage/report-azure.json @@ -1,9 +1,10 @@ { - "LROPostDoubleHeadersFinalLocationPost": 1, - "LROPostDoubleHeadersFinalLocationAsync": 1, - "LROPostDoubleHeadersFinalLocationGet": 1, + "LROPostDoubleHeadersFinalLocationPost": 0, + "LROPostDoubleHeadersFinalLocationAsync": 0, + "LROPostDoubleHeadersFinalLocationGet": 0, "LROConstantParameterizedPost": 0, "LROConstantParameterizedGet": 0, + "PagingDuplicateParameters": 6, "PostParameterGroupingWithReservedWords": 0, "LROPutInlineComplete": 0, "LROPutInlineComplete201": 0, @@ -87,24 +88,24 @@ "LROErrorPostAsyncInvalidHeader": 0, "LROErrorPostAsyncInvalidJsonPolling": 0, "LROParameterizedEndpoint": 0, - "PagingNoItemName": 0, - "PagingNextLinkNameNull": 0, - "PagingSingle": 0, - "PagingMultiple": 0, - "PagingMultipleWithQueryParameters": 0, - "PagingOdataMultiple": 0, - "PagingMultiplePath": 0, - "PagingMultipleRetryFirst": 0, - "PagingMultipleRetrySecond": 0, - "PagingSingleFailure": 0, - "PagingMultipleFailure": 0, - "PagingMultipleFailureUri": 0, - "PagingFragment": 0, + "PagingNoItemName": 2, + "PagingNextLinkNameNull": 2, + "PagingSingle": 2, + "PagingMultiple": 2, + "PagingMultipleWithQueryParameters": 2, + "PagingOdataMultiple": 2, + "PagingMultiplePath": 2, + "PagingMultipleRetryFirst": 2, + "PagingMultipleRetrySecond": 2, + "PagingSingleFailure": 2, + "PagingMultipleFailure": 2, + "PagingMultipleFailureUri": 2, + "PagingFragment": 2, "PagingMultipleLRO": 0, "PagingCustomUrlPartialNextLink": 0, "PagingCustomUrlPartialOperationNextLink": 0, "PagingReturnModelWithXMSClientName": 0, - "PagingFirstResponseEmpty": 0, + "PagingFirstResponseEmpty": 2, "AzureSubscriptionMethodLocalValid": 0, "AzureSubscriptionMethodGlobalValid": 0, "AzureSubscriptionMethodGlobalNotProvidedValid": 0, diff --git a/test/azure/version-tolerant/AcceptanceTests/test_zzz.py b/test/azure/version-tolerant/AcceptanceTests/test_zzz.py index ebc7000630b..4141c1f11ad 100644 --- a/test/azure/version-tolerant/AcceptanceTests/test_zzz.py +++ b/test/azure/version-tolerant/AcceptanceTests/test_zzz.py @@ -41,6 +41,7 @@ def test_ensure_coverage(self): # Please add missing features or failing tests here missing_features_or_bugs = { "LROPatchInlineCompleteIgnoreHeaders": 1, + "PagingDuplicateParameters": 1 # skipping for now, going to do another PR soon changing paging behavior for version tolerant } print("Coverage:") From baf65abaefdfdc203a55510caf3ae439701b1aba Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 17 Feb 2022 13:00:01 -0500 Subject: [PATCH 4/5] update 2.7 test and version tolerant acceptance test --- .../AcceptanceTests/Paging/paging/_patch.py | 12 ++++-- .../low-level/coverage/report-azure.json | 38 +++++++++---------- .../AcceptanceTests/test_paging.py | 3 -- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py index cd33b6594a7..5ba92f52915 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py @@ -29,6 +29,12 @@ import urllib.parse from ._auto_rest_paging_test_service import AutoRestPagingTestService as AutoRestPagingTestServiceGenerated from azure.core.pipeline.policies import SansIOHTTPPolicy +try: + binary_type = str + import urlparse # type: ignore +except ImportError: + binary_type = bytes # type: ignore + from urllib import parse as urlparse class RemoveDuplicateParamsPolicy(SansIOHTTPPolicy): def __init__(self, duplicate_param_names): @@ -36,14 +42,14 @@ def __init__(self, duplicate_param_names): self.duplicate_param_names = duplicate_param_names def on_request(self, request): - parsed_url = urllib.parse.urlparse(request.http_request.url) - query_params = urllib.parse.parse_qs(parsed_url.query) + parsed_url = urlparse.urlparse(request.http_request.url) + query_params = urlparse.parse_qs(parsed_url.query) # service returned will be later in the url because of how we format filtered_query_params = { k: v[-1:] if k in self.duplicate_param_names else v for k, v in query_params.items() } - request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urllib.parse.urlencode(filtered_query_params, doseq=True) + request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urlparse.urlencode(filtered_query_params, doseq=True) return super().on_request(request) class AutoRestPagingTestService(AutoRestPagingTestServiceGenerated): diff --git a/test/azure/low-level/coverage/report-azure.json b/test/azure/low-level/coverage/report-azure.json index aa5a5478029..3e320ce6469 100644 --- a/test/azure/low-level/coverage/report-azure.json +++ b/test/azure/low-level/coverage/report-azure.json @@ -4,7 +4,7 @@ "LROPostDoubleHeadersFinalLocationGet": 0, "LROConstantParameterizedPost": 0, "LROConstantParameterizedGet": 0, - "PagingDuplicateParameters": 6, + "PagingDuplicateParameters": 8, "PostParameterGroupingWithReservedWords": 0, "LROPutInlineComplete": 0, "LROPutInlineComplete201": 0, @@ -88,24 +88,24 @@ "LROErrorPostAsyncInvalidHeader": 0, "LROErrorPostAsyncInvalidJsonPolling": 0, "LROParameterizedEndpoint": 0, - "PagingNoItemName": 2, - "PagingNextLinkNameNull": 2, - "PagingSingle": 2, - "PagingMultiple": 2, - "PagingMultipleWithQueryParameters": 2, - "PagingOdataMultiple": 2, - "PagingMultiplePath": 2, - "PagingMultipleRetryFirst": 2, - "PagingMultipleRetrySecond": 2, - "PagingSingleFailure": 2, - "PagingMultipleFailure": 2, - "PagingMultipleFailureUri": 2, - "PagingFragment": 2, - "PagingMultipleLRO": 0, - "PagingCustomUrlPartialNextLink": 0, - "PagingCustomUrlPartialOperationNextLink": 0, - "PagingReturnModelWithXMSClientName": 0, - "PagingFirstResponseEmpty": 2, + "PagingNoItemName": 3, + "PagingNextLinkNameNull": 3, + "PagingSingle": 4, + "PagingMultiple": 4, + "PagingMultipleWithQueryParameters": 3, + "PagingOdataMultiple": 3, + "PagingMultiplePath": 3, + "PagingMultipleRetryFirst": 3, + "PagingMultipleRetrySecond": 3, + "PagingSingleFailure": 3, + "PagingMultipleFailure": 3, + "PagingMultipleFailureUri": 3, + "PagingFragment": 3, + "PagingMultipleLRO": 1, + "PagingCustomUrlPartialNextLink": 3, + "PagingCustomUrlPartialOperationNextLink": 3, + "PagingReturnModelWithXMSClientName": 1, + "PagingFirstResponseEmpty": 3, "AzureSubscriptionMethodLocalValid": 0, "AzureSubscriptionMethodGlobalValid": 0, "AzureSubscriptionMethodGlobalNotProvidedValid": 0, diff --git a/test/azure/version-tolerant/AcceptanceTests/test_paging.py b/test/azure/version-tolerant/AcceptanceTests/test_paging.py index f95ee8394fd..407d8918fb0 100644 --- a/test/azure/version-tolerant/AcceptanceTests/test_paging.py +++ b/test/azure/version-tolerant/AcceptanceTests/test_paging.py @@ -164,6 +164,3 @@ def test_initial_response_no_items(client): pages = client.paging.first_response_empty() items = [i for i in pages] assert len(items) == 1 - -def test_duplicate_params(client: AutoRestPagingTestService): - pages = list(client.paging.duplicate_params("duplicateParams", filter="foo")) From f524c8397848448136f34cb41610f5ed9b0d570b Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 17 Feb 2022 14:40:59 -0500 Subject: [PATCH 5/5] skip duplicate params test in 2.7 --- .../legacy/AcceptanceTests/test_paging.py | 1 + .../AcceptanceTests/Paging/paging/_patch.py | 9 +++-- .../low-level/coverage/report-azure.json | 38 +++++++++---------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/test/azure/legacy/AcceptanceTests/test_paging.py b/test/azure/legacy/AcceptanceTests/test_paging.py index def8a1c2f4a..9be0518de8a 100644 --- a/test/azure/legacy/AcceptanceTests/test_paging.py +++ b/test/azure/legacy/AcceptanceTests/test_paging.py @@ -180,6 +180,7 @@ def test_initial_response_no_items(self, client): items = [i for i in pages] assert len(items) == 1 + @pytest.mark.skipif(sys.version_info < (3,5), reason="2.7 does different url encoding") def test_duplicate_params(self, client): pages = list(client.paging.duplicate_params(filter="foo")) assert len(pages) == 1 diff --git a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py index 5ba92f52915..99986a22c8f 100644 --- a/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py +++ b/test/azure/legacy/Expected/AcceptanceTests/Paging/paging/_patch.py @@ -26,15 +26,16 @@ # -------------------------------------------------------------------------- from typing import List import importlib -import urllib.parse from ._auto_rest_paging_test_service import AutoRestPagingTestService as AutoRestPagingTestServiceGenerated from azure.core.pipeline.policies import SansIOHTTPPolicy try: binary_type = str import urlparse # type: ignore + from urllib import urlencode except ImportError: binary_type = bytes # type: ignore from urllib import parse as urlparse + from urllib.parse import urlencode class RemoveDuplicateParamsPolicy(SansIOHTTPPolicy): def __init__(self, duplicate_param_names): @@ -49,8 +50,8 @@ def on_request(self, request): k: v[-1:] if k in self.duplicate_param_names else v for k, v in query_params.items() } - request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urlparse.urlencode(filtered_query_params, doseq=True) - return super().on_request(request) + request.http_request.url = request.http_request.url.replace(parsed_url.query, "") + urlencode(filtered_query_params, doseq=True) + return super(RemoveDuplicateParamsPolicy, self).on_request(request) class AutoRestPagingTestService(AutoRestPagingTestServiceGenerated): def __init__(self, *args, **kwargs): @@ -60,7 +61,7 @@ def __init__(self, *args, **kwargs): per_call_policies.append(params_policy) except AttributeError: per_call_policies = [per_call_policies, params_policy] - super().__init__(*args, per_call_policies=per_call_policies, **kwargs) + super(AutoRestPagingTestService, self).__init__(*args, per_call_policies=per_call_policies, **kwargs) # This file is used for handwritten extensions to the generated code. Example: # https://github.com/Azure/azure-sdk-for-python/blob/main/doc/dev/customize_code/how-to-patch-sdk-code.md diff --git a/test/azure/low-level/coverage/report-azure.json b/test/azure/low-level/coverage/report-azure.json index 3e320ce6469..07af3471cf1 100644 --- a/test/azure/low-level/coverage/report-azure.json +++ b/test/azure/low-level/coverage/report-azure.json @@ -4,7 +4,7 @@ "LROPostDoubleHeadersFinalLocationGet": 0, "LROConstantParameterizedPost": 0, "LROConstantParameterizedGet": 0, - "PagingDuplicateParameters": 8, + "PagingDuplicateParameters": 13, "PostParameterGroupingWithReservedWords": 0, "LROPutInlineComplete": 0, "LROPutInlineComplete201": 0, @@ -88,24 +88,24 @@ "LROErrorPostAsyncInvalidHeader": 0, "LROErrorPostAsyncInvalidJsonPolling": 0, "LROParameterizedEndpoint": 0, - "PagingNoItemName": 3, - "PagingNextLinkNameNull": 3, - "PagingSingle": 4, - "PagingMultiple": 4, - "PagingMultipleWithQueryParameters": 3, - "PagingOdataMultiple": 3, - "PagingMultiplePath": 3, - "PagingMultipleRetryFirst": 3, - "PagingMultipleRetrySecond": 3, - "PagingSingleFailure": 3, - "PagingMultipleFailure": 3, - "PagingMultipleFailureUri": 3, - "PagingFragment": 3, - "PagingMultipleLRO": 1, - "PagingCustomUrlPartialNextLink": 3, - "PagingCustomUrlPartialOperationNextLink": 3, - "PagingReturnModelWithXMSClientName": 1, - "PagingFirstResponseEmpty": 3, + "PagingNoItemName": 6, + "PagingNextLinkNameNull": 6, + "PagingSingle": 10, + "PagingMultiple": 10, + "PagingMultipleWithQueryParameters": 6, + "PagingOdataMultiple": 6, + "PagingMultiplePath": 6, + "PagingMultipleRetryFirst": 6, + "PagingMultipleRetrySecond": 6, + "PagingSingleFailure": 6, + "PagingMultipleFailure": 6, + "PagingMultipleFailureUri": 6, + "PagingFragment": 6, + "PagingMultipleLRO": 4, + "PagingCustomUrlPartialNextLink": 8, + "PagingCustomUrlPartialOperationNextLink": 8, + "PagingReturnModelWithXMSClientName": 4, + "PagingFirstResponseEmpty": 6, "AzureSubscriptionMethodLocalValid": 0, "AzureSubscriptionMethodGlobalValid": 0, "AzureSubscriptionMethodGlobalNotProvidedValid": 0,