diff --git a/test/azure/AcceptanceTests/asynctests/test_paging.py b/test/azure/AcceptanceTests/asynctests/test_paging.py index 4599874d0d9..14b9987a216 100644 --- a/test/azure/AcceptanceTests/asynctests/test_paging.py +++ b/test/azure/AcceptanceTests/asynctests/test_paging.py @@ -224,6 +224,14 @@ async def test_get_multiple_pages_lro(self, client): assert items[0].properties.id == 1 assert items[1].properties.id == 2 + @pytest.mark.asyncio + async def test_initial_response_no_items(self, client): + pages = client.paging.first_response_empty() + items = [] + async for item in pages: + items.append(item) + assert len(items) == 1 + @pytest.mark.asyncio async def test_item_name_with_xms_client_name(self, client): pages = client.paging.get_paging_model_with_item_name_with_xms_client_name() diff --git a/test/azure/AcceptanceTests/test_paging.py b/test/azure/AcceptanceTests/test_paging.py index b163b1a2e3e..79361c839f5 100644 --- a/test/azure/AcceptanceTests/test_paging.py +++ b/test/azure/AcceptanceTests/test_paging.py @@ -174,6 +174,11 @@ def test_item_name_with_xms_client_name(self, client): items = [i for i in pages] assert len(items) == 1 + def test_initial_response_no_items(self, client): + pages = client.paging.first_response_empty() + items = [i for i in pages] + assert len(items) == 1 + def test_models(self): from paging.models import OperationResult if sys.version_info >= (3,5): diff --git a/test/azure/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py b/test/azure/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py index 8eee8e75ea7..cd4f62b2d47 100644 --- a/test/azure/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py +++ b/test/azure/Expected/AcceptanceTests/Paging/paging/aio/operations/_paging_operations.py @@ -228,6 +228,68 @@ async def get_next(next_link=None): ) get_single_pages.metadata = {'url': '/paging/single'} # type: ignore + @distributed_trace + def first_response_empty( + self, + **kwargs + ) -> AsyncIterable["models.ProductResultValue"]: + """A paging operation whose first response's items list is empty, but still returns a next link. + Second (and final) call, will give you an items list of 1. + + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either ProductResultValue or the result of cls(response) + :rtype: ~azure.core.async_paging.AsyncItemPaged[~paging.models.ProductResultValue] + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["models.ProductResultValue"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.first_response_empty.metadata['url'] # type: ignore + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + request = self._client.get(url, query_parameters, header_parameters) + return request + + async def extract_data(pipeline_response): + deserialized = self._deserialize('ProductResultValue', pipeline_response) + list_of_elem = deserialized.value + 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(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, error_format=ARMErrorFormat) + + return pipeline_response + + return AsyncItemPaged( + get_next, extract_data + ) + first_response_empty.metadata = {'url': '/paging/firstResponseEmpty/1'} # type: ignore + @distributed_trace def get_multiple_pages( self, diff --git a/test/azure/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py b/test/azure/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py index 7b2c8dab169..adf9732e386 100644 --- a/test/azure/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py +++ b/test/azure/Expected/AcceptanceTests/Paging/paging/operations/_paging_operations.py @@ -234,6 +234,69 @@ def get_next(next_link=None): ) get_single_pages.metadata = {'url': '/paging/single'} # type: ignore + @distributed_trace + def first_response_empty( + self, + **kwargs # type: Any + ): + # type: (...) -> Iterable["models.ProductResultValue"] + """A paging operation whose first response's items list is empty, but still returns a next link. + Second (and final) call, will give you an items list of 1. + + :keyword callable cls: A custom type or function that will be passed the direct response + :return: An iterator like instance of either ProductResultValue or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~paging.models.ProductResultValue] + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["models.ProductResultValue"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.first_response_empty.metadata['url'] # type: ignore + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + request = self._client.get(url, query_parameters, header_parameters) + return request + + def extract_data(pipeline_response): + deserialized = self._deserialize('ProductResultValue', pipeline_response) + list_of_elem = deserialized.value + 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(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, error_format=ARMErrorFormat) + + return pipeline_response + + return ItemPaged( + get_next, extract_data + ) + first_response_empty.metadata = {'url': '/paging/firstResponseEmpty/1'} # type: ignore + @distributed_trace def get_multiple_pages( self,