From 87c1bccd689bd3cd13ae4a3911b274557826240b Mon Sep 17 00:00:00 2001 From: Danny Hermes Date: Mon, 17 Oct 2016 12:06:30 -0700 Subject: [PATCH] Moving to iterators in DNS. --- dns/google/cloud/dns/client.py | 62 ++++++++++----- dns/google/cloud/dns/zone.py | 138 +++++++++++++++++++++++---------- dns/unit_tests/test_client.py | 10 ++- dns/unit_tests/test_zone.py | 20 ++++- 4 files changed, 165 insertions(+), 65 deletions(-) diff --git a/dns/google/cloud/dns/client.py b/dns/google/cloud/dns/client.py index d645b1499423..6f0ff64f5281 100644 --- a/dns/google/cloud/dns/client.py +++ b/dns/google/cloud/dns/client.py @@ -18,6 +18,7 @@ from google.cloud.client import JSONClient from google.cloud.dns.connection import Connection from google.cloud.dns.zone import ManagedZone +from google.cloud.iterator import Iterator class Client(JSONClient): @@ -75,26 +76,12 @@ def list_zones(self, max_results=None, page_token=None): not passed, the API will return the first page of zones. - :rtype: tuple, (list, str) - :returns: list of :class:`google.cloud.dns.zone.ManagedZone`, plus a - "next page token" string: if the token is not None, - indicates that more zones can be retrieved with another - call (pass that value as ``page_token``). + :rtype: :class:`_ManagedZoneIterator` + :returns: An iterator of :class:`~google.cloud.dns.zone.ManagedZone` + objects. """ - params = {} - - if max_results is not None: - params['maxResults'] = max_results - - if page_token is not None: - params['pageToken'] = page_token - - path = '/projects/%s/managedZones' % (self.project,) - resp = self.connection.api_request(method='GET', path=path, - query_params=params) - zones = [ManagedZone.from_api_repr(resource, self) - for resource in resp['managedZones']] - return zones, resp.get('nextPageToken') + return _ManagedZoneIterator(self, page_token=page_token, + max_results=max_results) def zone(self, name, dns_name=None, description=None): """Construct a zone bound to this client. @@ -115,3 +102,40 @@ def zone(self, name, dns_name=None, description=None): """ return ManagedZone(name, dns_name, client=self, description=description) + + +class _ManagedZoneIterator(Iterator): + """An iterator listing all managed zones. + + :type client: :class:`~google.cloud.dns.client.Client` + :param client: The client to use for making connections. + + :type page_token: str + :param page_token: (Optional) A token identifying a page in a result set. + + :type max_results: int + :param max_results: (Optional) The maximum number of results to fetch. + + :type extra_params: dict or ``NoneType`` + :param extra_params: Extra query string parameters for the API call. + """ + + ITEMS_KEY = 'managedZones' + + def __init__(self, client, page_token=None, max_results=None, + extra_params=None): + path = '/projects/%s/managedZones' % (client.project,) + super(_ManagedZoneIterator, self).__init__( + client=client, path=path, page_token=page_token, + max_results=max_results, extra_params=extra_params) + + def _item_to_value(self, resource): + """Convert a JSON managed zone to the native object. + + :type resource: dict + :param resource: An item to be converted to a managed zone. + + :rtype: :class:`.ManagedZone` + :returns: The next managed zone in the page. + """ + return ManagedZone.from_api_repr(resource, self.client) diff --git a/dns/google/cloud/dns/zone.py b/dns/google/cloud/dns/zone.py index 6558a3a6a8ab..adaa86b0bace 100644 --- a/dns/google/cloud/dns/zone.py +++ b/dns/google/cloud/dns/zone.py @@ -13,12 +13,14 @@ # limitations under the License. """Define API ManagedZones.""" + import six from google.cloud._helpers import _rfc3339_to_datetime from google.cloud.exceptions import NotFound from google.cloud.dns.changes import Changes from google.cloud.dns.resource_record_set import ResourceRecordSet +from google.cloud.iterator import Iterator class ManagedZone(object): @@ -330,29 +332,13 @@ def list_resource_record_sets(self, max_results=None, page_token=None, :param client: the client to use. If not passed, falls back to the ``client`` stored on the current zone. - :rtype: tuple, (list, str) - :returns: list of - :class:`~.resource_record_set.ResourceRecordSet`, - plus a "next page token" string: if the token is not None, - indicates that more zones can be retrieved with another - call (pass that value as ``page_token``). + :rtype: :class:`_ResourceRecordSetIterator` + :returns: An iterator of + :class:`~.resource_record_set.ResourceRecordSet` objects. """ - params = {} - - if max_results is not None: - params['maxResults'] = max_results - - if page_token is not None: - params['pageToken'] = page_token - - path = '/projects/%s/managedZones/%s/rrsets' % ( - self.project, self.name) - client = self._require_client(client) - conn = client.connection - resp = conn.api_request(method='GET', path=path, query_params=params) - zones = [ResourceRecordSet.from_api_repr(resource, self) - for resource in resp['rrsets']] - return zones, resp.get('nextPageToken') + return _ResourceRecordSetIterator( + self, page_token=page_token, + max_results=max_results, client=client) def list_changes(self, max_results=None, page_token=None, client=None): """List change sets for this zone. @@ -373,26 +359,98 @@ def list_changes(self, max_results=None, page_token=None, client=None): :param client: the client to use. If not passed, falls back to the ``client`` stored on the current zone. - :rtype: tuple, (list, str) - :returns: list of - :class:`~.resource_record_set.ResourceRecordSet`, - plus a "next page token" string: if the token is not None, - indicates that more zones can be retrieved with another - call (pass that value as ``page_token``). + :rtype: :class:`_ChangesIterator` + :returns: An iterator of :class:`~.changes.Changes` objects. """ - params = {} + return _ChangesIterator(self, page_token=page_token, + max_results=max_results, client=client) + + +class _ResourceRecordSetIterator(Iterator): + """An iterator listing all resource record sets. + + :type zone: :class:`ManagedZone` + :param zone: The managed zone from which to list resource record sets. + + :type page_token: str + :param page_token: (Optional) A token identifying a page in a result set. - if max_results is not None: - params['maxResults'] = max_results + :type max_results: int + :param max_results: (Optional) The maximum number of results to fetch. - if page_token is not None: - params['pageToken'] = page_token + :type extra_params: dict or ``NoneType`` + :param extra_params: Extra query string parameters for the API call. + + :type client: :class:`~google.cloud.dns.client.Client` + :param client: (Optional) The client to use for making connections. + Defaults to the zone's client. + """ + + ITEMS_KEY = 'rrsets' + + def __init__(self, zone, page_token=None, max_results=None, + extra_params=None, client=None): + if client is None: + client = zone._client + self.zone = zone + path = '/projects/%s/managedZones/%s/rrsets' % ( + zone.project, zone.name) + super(_ResourceRecordSetIterator, self).__init__( + client=client, path=path, page_token=page_token, + max_results=max_results, extra_params=extra_params) + + def _item_to_value(self, resource): + """Convert a JSON resource record set value to the native object. + + :type resource: dict + :param resource: An item to be converted to a resource record set. + :rtype: :class:`~.resource_record_set.ResourceRecordSet` + :returns: The next resource record set in the page. + """ + return ResourceRecordSet.from_api_repr(resource, self.zone) + + +class _ChangesIterator(Iterator): + """An iterator listing all changes. + + :type zone: :class:`ManagedZone` + :param zone: The managed zone from which to list changes. + + :type page_token: str + :param page_token: (Optional) A token identifying a page in a result set. + + :type max_results: int + :param max_results: (Optional) The maximum number of results to fetch. + + :type extra_params: dict or ``NoneType`` + :param extra_params: Extra query string parameters for the API call. + + :type client: :class:`~google.cloud.dns.client.Client` + :param client: (Optional) The client to use for making connections. + Defaults to the zone's client. + """ + + ITEMS_KEY = 'changes' + + def __init__(self, zone, page_token=None, max_results=None, + extra_params=None, client=None): + if client is None: + client = zone._client + self.zone = zone path = '/projects/%s/managedZones/%s/changes' % ( - self.project, self.name) - client = self._require_client(client) - conn = client.connection - resp = conn.api_request(method='GET', path=path, query_params=params) - zones = [Changes.from_api_repr(resource, self) - for resource in resp['changes']] - return zones, resp.get('nextPageToken') + zone.project, zone.name) + super(_ChangesIterator, self).__init__( + client=client, path=path, page_token=page_token, + max_results=max_results, extra_params=extra_params) + + def _item_to_value(self, resource): + """Convert a JSON "changes" value to the native object. + + :type resource: dict + :param resource: An item to be converted to a "changes". + + :rtype: :class:`.Changes` + :returns: The next "changes" in the page. + """ + return Changes.from_api_repr(resource, self.zone) diff --git a/dns/unit_tests/test_client.py b/dns/unit_tests/test_client.py index 6c8dcf0ebd0f..e49f43084d33 100644 --- a/dns/unit_tests/test_client.py +++ b/dns/unit_tests/test_client.py @@ -132,7 +132,10 @@ def test_list_zones_defaults(self): client = self._makeOne(self.PROJECT, creds) conn = client.connection = _Connection(DATA) - zones, token = client.list_zones() + iterator = client.list_zones() + iterator.update_page() + zones = list(iterator.page) + token = iterator.next_page_token self.assertEqual(len(zones), len(DATA['managedZones'])) for found, expected in zip(zones, DATA['managedZones']): @@ -173,7 +176,10 @@ def test_list_zones_explicit(self): client = self._makeOne(self.PROJECT, creds) conn = client.connection = _Connection(DATA) - zones, token = client.list_zones(max_results=3, page_token=TOKEN) + iterator = client.list_zones(max_results=3, page_token=TOKEN) + iterator.update_page() + zones = list(iterator.page) + token = iterator.next_page_token self.assertEqual(len(zones), len(DATA['managedZones'])) for found, expected in zip(zones, DATA['managedZones']): diff --git a/dns/unit_tests/test_zone.py b/dns/unit_tests/test_zone.py index dae6453d7c0b..2f51d38f6f72 100644 --- a/dns/unit_tests/test_zone.py +++ b/dns/unit_tests/test_zone.py @@ -440,7 +440,10 @@ def test_list_resource_record_sets_defaults(self): client = _Client(project=self.PROJECT, connection=conn) zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client) - rrsets, token = zone.list_resource_record_sets() + iterator = zone.list_resource_record_sets() + iterator.update_page() + rrsets = list(iterator.page) + token = iterator.next_page_token self.assertEqual(len(rrsets), len(DATA['rrsets'])) for found, expected in zip(rrsets, DATA['rrsets']): @@ -489,8 +492,11 @@ def test_list_resource_record_sets_explicit(self): client2 = _Client(project=self.PROJECT, connection=conn2) zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1) - rrsets, token = zone.list_resource_record_sets( + iterator = zone.list_resource_record_sets( max_results=3, page_token=TOKEN, client=client2) + iterator.update_page() + rrsets = list(iterator.page) + token = iterator.next_page_token self.assertEqual(len(rrsets), len(DATA['rrsets'])) for found, expected in zip(rrsets, DATA['rrsets']): @@ -551,7 +557,10 @@ def test_list_changes_defaults(self): client = _Client(project=self.PROJECT, connection=conn) zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client) - changes, token = zone.list_changes() + iterator = zone.list_changes() + iterator.update_page() + changes = list(iterator.page) + token = iterator.next_page_token self.assertEqual(len(changes), len(DATA['changes'])) for found, expected in zip(changes, DATA['changes']): @@ -628,8 +637,11 @@ def test_list_changes_explicit(self): client2 = _Client(project=self.PROJECT, connection=conn2) zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1) - changes, token = zone.list_changes( + iterator = zone.list_changes( max_results=3, page_token=TOKEN, client=client2) + iterator.update_page() + changes = list(iterator.page) + token = iterator.next_page_token self.assertEqual(len(changes), len(DATA['changes'])) for found, expected in zip(changes, DATA['changes']):