Skip to content

Commit ffca8d8

Browse files
committed
Moving to iterators in DNS.
1 parent d9824c6 commit ffca8d8

File tree

4 files changed

+206
-65
lines changed

4 files changed

+206
-65
lines changed

dns/google/cloud/dns/client.py

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717

1818
from google.cloud.client import JSONClient
19+
from google.cloud.iterator import Iterator
20+
from google.cloud.iterator import Page
1921
from google.cloud.dns.connection import Connection
2022
from google.cloud.dns.zone import ManagedZone
2123

@@ -75,26 +77,12 @@ def list_zones(self, max_results=None, page_token=None):
7577
not passed, the API will return the first page of
7678
zones.
7779
78-
:rtype: tuple, (list, str)
79-
:returns: list of :class:`google.cloud.dns.zone.ManagedZone`, plus a
80-
"next page token" string: if the token is not None,
81-
indicates that more zones can be retrieved with another
82-
call (pass that value as ``page_token``).
80+
:rtype: :class:`_ManagedZoneIterator`
81+
:returns: An iterator of :class:`~google.cloud.dns.zone.ManagedZone`
82+
objects.
8383
"""
84-
params = {}
85-
86-
if max_results is not None:
87-
params['maxResults'] = max_results
88-
89-
if page_token is not None:
90-
params['pageToken'] = page_token
91-
92-
path = '/projects/%s/managedZones' % (self.project,)
93-
resp = self.connection.api_request(method='GET', path=path,
94-
query_params=params)
95-
zones = [ManagedZone.from_api_repr(resource, self)
96-
for resource in resp['managedZones']]
97-
return zones, resp.get('nextPageToken')
84+
return _ManagedZoneIterator(self, page_token=page_token,
85+
max_results=max_results)
9886

9987
def zone(self, name, dns_name=None, description=None):
10088
"""Construct a zone bound to this client.
@@ -115,3 +103,53 @@ def zone(self, name, dns_name=None, description=None):
115103
"""
116104
return ManagedZone(name, dns_name, client=self,
117105
description=description)
106+
107+
108+
class _ManagedZonePage(Page):
109+
"""Iterator for a single page of results.
110+
111+
:type parent: :class:`_ManagedZoneIterator`
112+
:param parent: The iterator that owns the current page.
113+
114+
:type response: dict
115+
:param response: The JSON API response for a page of managed zones.
116+
"""
117+
118+
ITEMS_KEY = 'managedZones'
119+
120+
def _item_to_value(self, resource):
121+
"""Convert a JSON managed zone to the native object.
122+
123+
:type resource: dict
124+
:param resource: An item to be converted to a managed zone.
125+
126+
:rtype: :class:`.ManagedZone`
127+
:returns: The next managed zone in the page.
128+
"""
129+
return ManagedZone.from_api_repr(resource, self._parent.client)
130+
131+
132+
class _ManagedZoneIterator(Iterator):
133+
"""An iterator listing all managed zones.
134+
135+
:type client: :class:`~google.cloud.dns.client.Client`
136+
:param client: The client to use for making connections.
137+
138+
:type page_token: str
139+
:param page_token: (Optional) A token identifying a page in a result set.
140+
141+
:type max_results: int
142+
:param max_results: (Optional) The maximum number of results to fetch.
143+
144+
:type extra_params: dict or ``NoneType``
145+
:param extra_params: Extra query string parameters for the API call.
146+
"""
147+
148+
PAGE_CLASS = _ManagedZonePage
149+
150+
def __init__(self, client, page_token=None, max_results=None,
151+
extra_params=None):
152+
path = '/projects/%s/managedZones' % (client.project,)
153+
super(_ManagedZoneIterator, self).__init__(
154+
client=client, path=path, page_token=page_token,
155+
max_results=max_results, extra_params=extra_params)

dns/google/cloud/dns/zone.py

Lines changed: 125 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
# limitations under the License.
1414

1515
"""Define API ManagedZones."""
16+
1617
import six
1718

1819
from google.cloud._helpers import _rfc3339_to_datetime
1920
from google.cloud.exceptions import NotFound
2021
from google.cloud.dns.changes import Changes
2122
from google.cloud.dns.resource_record_set import ResourceRecordSet
23+
from google.cloud.iterator import Iterator
24+
from google.cloud.iterator import Page
2225

2326

2427
class ManagedZone(object):
@@ -330,29 +333,13 @@ def list_resource_record_sets(self, max_results=None, page_token=None,
330333
:param client: the client to use. If not passed, falls back to the
331334
``client`` stored on the current zone.
332335
333-
:rtype: tuple, (list, str)
334-
:returns: list of
335-
:class:`~.resource_record_set.ResourceRecordSet`,
336-
plus a "next page token" string: if the token is not None,
337-
indicates that more zones can be retrieved with another
338-
call (pass that value as ``page_token``).
336+
:rtype: :class:`_ResourceRecordSetIterator`
337+
:returns: An iterator of
338+
:class:`~.resource_record_set.ResourceRecordSet` objects.
339339
"""
340-
params = {}
341-
342-
if max_results is not None:
343-
params['maxResults'] = max_results
344-
345-
if page_token is not None:
346-
params['pageToken'] = page_token
347-
348-
path = '/projects/%s/managedZones/%s/rrsets' % (
349-
self.project, self.name)
350-
client = self._require_client(client)
351-
conn = client.connection
352-
resp = conn.api_request(method='GET', path=path, query_params=params)
353-
zones = [ResourceRecordSet.from_api_repr(resource, self)
354-
for resource in resp['rrsets']]
355-
return zones, resp.get('nextPageToken')
340+
return _ResourceRecordSetIterator(
341+
self, page_token=page_token,
342+
max_results=max_results, client=client)
356343

357344
def list_changes(self, max_results=None, page_token=None, client=None):
358345
"""List change sets for this zone.
@@ -373,26 +360,124 @@ def list_changes(self, max_results=None, page_token=None, client=None):
373360
:param client: the client to use. If not passed, falls back to the
374361
``client`` stored on the current zone.
375362
376-
:rtype: tuple, (list, str)
377-
:returns: list of
378-
:class:`~.resource_record_set.ResourceRecordSet`,
379-
plus a "next page token" string: if the token is not None,
380-
indicates that more zones can be retrieved with another
381-
call (pass that value as ``page_token``).
363+
:rtype: :class:`_ChangesIterator`
364+
:returns: An iterator of :class:`~.changes.Changes` objects.
382365
"""
383-
params = {}
366+
return _ChangesIterator(self, page_token=page_token,
367+
max_results=max_results, client=client)
368+
384369

385-
if max_results is not None:
386-
params['maxResults'] = max_results
370+
class _ResourceRecordSetPage(Page):
371+
"""Iterator for a single page of results.
387372
388-
if page_token is not None:
389-
params['pageToken'] = page_token
373+
:type parent: :class:`_ResourceRecordSetIterator`
374+
:param parent: The iterator that owns the current page.
375+
376+
:type response: dict
377+
:param response: The JSON API response for a page of resource record sets.
378+
"""
379+
380+
ITEMS_KEY = 'rrsets'
381+
382+
def _item_to_value(self, resource):
383+
"""Convert a JSON resource record set value to the native object.
384+
385+
:type resource: dict
386+
:param resource: An item to be converted to a resource record set.
390387
388+
:rtype: :class:`~.resource_record_set.ResourceRecordSet`
389+
:returns: The next resource record set in the page.
390+
"""
391+
return ResourceRecordSet.from_api_repr(resource, self._parent.zone)
392+
393+
394+
class _ResourceRecordSetIterator(Iterator):
395+
"""An iterator listing all resource record sets.
396+
397+
:type zone: :class:`ManagedZone`
398+
:param zone: The managed zone from which to list resource record sets.
399+
400+
:type page_token: str
401+
:param page_token: (Optional) A token identifying a page in a result set.
402+
403+
:type max_results: int
404+
:param max_results: (Optional) The maximum number of results to fetch.
405+
406+
:type extra_params: dict or ``NoneType``
407+
:param extra_params: Extra query string parameters for the API call.
408+
409+
:type client: :class:`~google.cloud.dns.client.Client`
410+
:param client: (Optional) The client to use for making connections.
411+
Defaults to the zone's client.
412+
"""
413+
414+
PAGE_CLASS = _ResourceRecordSetPage
415+
416+
def __init__(self, zone, page_token=None, max_results=None,
417+
extra_params=None, client=None):
418+
if client is None:
419+
client = zone._client
420+
self.zone = zone
421+
path = '/projects/%s/managedZones/%s/rrsets' % (
422+
zone.project, zone.name)
423+
super(_ResourceRecordSetIterator, self).__init__(
424+
client=client, path=path, page_token=page_token,
425+
max_results=max_results, extra_params=extra_params)
426+
427+
428+
class _ChangesPage(Page):
429+
"""Iterator for a single page of results.
430+
431+
:type parent: :class:`_ChangesIterator`
432+
:param parent: The iterator that owns the current page.
433+
434+
:type response: dict
435+
:param response: The JSON API response for a page of "changes".
436+
"""
437+
438+
ITEMS_KEY = 'changes'
439+
440+
def _item_to_value(self, resource):
441+
"""Convert a JSON "changes" value to the native object.
442+
443+
:type resource: dict
444+
:param resource: An item to be converted to a "changes".
445+
446+
:rtype: :class:`.Changes`
447+
:returns: The next "changes" in the page.
448+
"""
449+
return Changes.from_api_repr(resource, self._parent.zone)
450+
451+
452+
class _ChangesIterator(Iterator):
453+
"""An iterator listing all changes.
454+
455+
:type zone: :class:`ManagedZone`
456+
:param zone: The managed zone from which to list changes.
457+
458+
:type page_token: str
459+
:param page_token: (Optional) A token identifying a page in a result set.
460+
461+
:type max_results: int
462+
:param max_results: (Optional) The maximum number of results to fetch.
463+
464+
:type extra_params: dict or ``NoneType``
465+
:param extra_params: Extra query string parameters for the API call.
466+
467+
:type client: :class:`~google.cloud.dns.client.Client`
468+
:param client: (Optional) The client to use for making connections.
469+
Defaults to the zone's client.
470+
"""
471+
472+
PAGE_CLASS = _ChangesPage
473+
474+
def __init__(self, zone, page_token=None, max_results=None,
475+
extra_params=None, client=None):
476+
if client is None:
477+
client = zone._client
478+
self.zone = zone
391479
path = '/projects/%s/managedZones/%s/changes' % (
392-
self.project, self.name)
393-
client = self._require_client(client)
394-
conn = client.connection
395-
resp = conn.api_request(method='GET', path=path, query_params=params)
396-
zones = [Changes.from_api_repr(resource, self)
397-
for resource in resp['changes']]
398-
return zones, resp.get('nextPageToken')
480+
zone.project, zone.name)
481+
super(_ChangesIterator, self).__init__(
482+
client=client, path=path, page_token=page_token,
483+
max_results=max_results, extra_params=extra_params)

dns/unit_tests/test_client.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ def test_list_zones_defaults(self):
132132
client = self._makeOne(self.PROJECT, creds)
133133
conn = client.connection = _Connection(DATA)
134134

135-
zones, token = client.list_zones()
135+
iterator = client.list_zones()
136+
iterator._update_page()
137+
zones = list(iterator.page)
138+
token = iterator.next_page_token
136139

137140
self.assertEqual(len(zones), len(DATA['managedZones']))
138141
for found, expected in zip(zones, DATA['managedZones']):
@@ -173,7 +176,10 @@ def test_list_zones_explicit(self):
173176
client = self._makeOne(self.PROJECT, creds)
174177
conn = client.connection = _Connection(DATA)
175178

176-
zones, token = client.list_zones(max_results=3, page_token=TOKEN)
179+
iterator = client.list_zones(max_results=3, page_token=TOKEN)
180+
iterator._update_page()
181+
zones = list(iterator.page)
182+
token = iterator.next_page_token
177183

178184
self.assertEqual(len(zones), len(DATA['managedZones']))
179185
for found, expected in zip(zones, DATA['managedZones']):

dns/unit_tests/test_zone.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,10 @@ def test_list_resource_record_sets_defaults(self):
440440
client = _Client(project=self.PROJECT, connection=conn)
441441
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
442442

443-
rrsets, token = zone.list_resource_record_sets()
443+
iterator = zone.list_resource_record_sets()
444+
iterator._update_page()
445+
rrsets = list(iterator.page)
446+
token = iterator.next_page_token
444447

445448
self.assertEqual(len(rrsets), len(DATA['rrsets']))
446449
for found, expected in zip(rrsets, DATA['rrsets']):
@@ -489,8 +492,11 @@ def test_list_resource_record_sets_explicit(self):
489492
client2 = _Client(project=self.PROJECT, connection=conn2)
490493
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
491494

492-
rrsets, token = zone.list_resource_record_sets(
495+
iterator = zone.list_resource_record_sets(
493496
max_results=3, page_token=TOKEN, client=client2)
497+
iterator._update_page()
498+
rrsets = list(iterator.page)
499+
token = iterator.next_page_token
494500

495501
self.assertEqual(len(rrsets), len(DATA['rrsets']))
496502
for found, expected in zip(rrsets, DATA['rrsets']):
@@ -551,7 +557,10 @@ def test_list_changes_defaults(self):
551557
client = _Client(project=self.PROJECT, connection=conn)
552558
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
553559

554-
changes, token = zone.list_changes()
560+
iterator = zone.list_changes()
561+
iterator._update_page()
562+
changes = list(iterator.page)
563+
token = iterator.next_page_token
555564

556565
self.assertEqual(len(changes), len(DATA['changes']))
557566
for found, expected in zip(changes, DATA['changes']):
@@ -628,8 +637,11 @@ def test_list_changes_explicit(self):
628637
client2 = _Client(project=self.PROJECT, connection=conn2)
629638
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
630639

631-
changes, token = zone.list_changes(
640+
iterator = zone.list_changes(
632641
max_results=3, page_token=TOKEN, client=client2)
642+
iterator._update_page()
643+
changes = list(iterator.page)
644+
token = iterator.next_page_token
633645

634646
self.assertEqual(len(changes), len(DATA['changes']))
635647
for found, expected in zip(changes, DATA['changes']):

0 commit comments

Comments
 (0)