From db0404c7849147dcc5bafe797e23cdb5364b381b Mon Sep 17 00:00:00 2001 From: Maciej Strzelczyk Date: Tue, 10 Aug 2021 19:05:56 +0200 Subject: [PATCH] docs(samples): Adding pagination sample. (#78) --- samples/snippets/quickstart.py | 7 +- samples/snippets/sample_pagination.py | 80 ++++++++++++++++++++++ samples/snippets/test_sample_pagination.py | 30 ++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 samples/snippets/sample_pagination.py create mode 100644 samples/snippets/test_sample_pagination.py diff --git a/samples/snippets/quickstart.py b/samples/snippets/quickstart.py index 341217e62..462733bc3 100644 --- a/samples/snippets/quickstart.py +++ b/samples/snippets/quickstart.py @@ -73,9 +73,14 @@ def list_all_instances( iterable collections of Instance objects as values. """ instance_client = compute_v1.InstancesClient() - agg_list = instance_client.aggregated_list(project=project_id) + # Use the `max_results` parameter to limit the number of results that the API returns per response page. + request = compute_v1.AggregatedListInstancesRequest(project=project_id, max_results=5) + agg_list = instance_client.aggregated_list(request=request) all_instances = {} print("Instances found:") + # Despite using the `max_results` parameter, you don't need to handle the pagination + # yourself. The returned `AggregatedListPager` object handles pagination + # automatically, returning separated pages as you iterate over the results. for zone, response in agg_list: if response.instances: all_instances[zone] = response.instances diff --git a/samples/snippets/sample_pagination.py b/samples/snippets/sample_pagination.py new file mode 100644 index 000000000..99ab80b09 --- /dev/null +++ b/samples/snippets/sample_pagination.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START compute_images_list_page ] +# [START compute_images_list ] +import google.cloud.compute_v1 as compute_v1 +# [END compute_images_list ] +# [END compute_images_list_page ] + + +# [START compute_images_list ] +def print_images_list(project: str) -> None: + """ + Prints a list of all non-deprecated image names available in given project. + + Args: + project: project ID or project number of the Cloud project you want to list images from. + + Returns: + None. + """ + images_client = compute_v1.ImagesClient() + # Listing only non-deprecated images to reduce the size of the reply. + images_list_request = compute_v1.ListImagesRequest(project=project, max_results=3, + filter="deprecated.state != DEPRECATED") + + # Although the `max_results` parameter is specified in the request, the iterable returned + # by the `list()` method hides the pagination mechanic. The library makes multiple + # requests to the API for you, so you can simply iterate over all the images. + for img in images_client.list(request=images_list_request): + print(f" - {img.name}") +# [END compute_images_list ] + + +# [START compute_images_list_page ] +def print_images_list_by_page(project: str, page_size: int = 10) -> None: + """ + Prints a list of all non-deprecated image names available in a given project, + divided into pages as returned by the Compute Engine API. + + Args: + project: project ID or project number of the Cloud project you want to list images from. + page_size: size of the pages you want the API to return on each call. + + Returns: + None. + """ + images_client = compute_v1.ImagesClient() + # Listing only non-deprecated images to reduce the size of the reply. + images_list_request = compute_v1.ListImagesRequest(project=project, max_results=page_size, + filter="deprecated.state != DEPRECATED") + + # Use the `pages` attribute of returned iterable to have more granular control of + # iteration over paginated results from the API. Each time you want to access the + # next page, the library retrieves that page from the API. + for page_num, page in enumerate(images_client.list(request=images_list_request).pages, start=1): + print(f"Page {page_num}: ") + for img in page.items: + print(f" - {img.name}") +# [END compute_images_list_page ] + + +if __name__ == '__main__': + print("=================== Flat list of images ===================") + print_images_list('windows-sql-cloud') + print("================= Paginated list of images ================") + print_images_list_by_page('windows-sql-cloud', 5) diff --git a/samples/snippets/test_sample_pagination.py b/samples/snippets/test_sample_pagination.py new file mode 100644 index 000000000..c881ccd1a --- /dev/null +++ b/samples/snippets/test_sample_pagination.py @@ -0,0 +1,30 @@ +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import typing + +from sample_pagination import print_images_list, print_images_list_by_page + +PROJECT = 'windows-sql-cloud' + + +def test_pagination(capsys: typing.Any) -> None: + print_images_list(PROJECT) + out, _ = capsys.readouterr() + assert(len(out.splitlines()) > 2) + + +def test_pagination_page(capsys: typing.Any) -> None: + print_images_list_by_page(PROJECT, 2) + out, _ = capsys.readouterr() + assert("Page 2" in out)