Repository: googleapis/google-cloud-python

Issue:
GAX iter.next() pattern seems to be breaking down
[For example](https://travis-ci.org/GoogleCloudPlatform/gcloud-python/builds/153445840), sometimes the iterable isn't an iterable

``` python
Traceback (most recent call last):
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/system_tests/logging_.py", line 215, in test_update_metric
    after_metrics, _ = Config.CLIENT.list_metrics()
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests3/lib/python3.4/site-packages/gcloud/logging/client.py", line 298, in list_metrics
    self.project, page_size, page_token)
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests3/lib/python3.4/site-packages/gcloud/logging/_gax.py", line 306, in list_metrics
    for log_metric_pb in page_iter.next()]
TypeError: 'LogMetric' object is not iterable
```

or

``` python
Traceback (most recent call last):
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/system_tests/pubsub.py", line 273, in test_fetch_delete_subscription_w_deleted_topic
    all_subs = retry_until_found_orphan(_fetch)()
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/system_tests/retry.py", line 126, in wrapped_function
    result = to_wrap(*args, **kwargs)
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/system_tests/pubsub.py", line 266, in _fetch
    return list(MethodIterator(Config.CLIENT.list_subscriptions))
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/gcloud/iterator.py", line 178, in __iter__
    page_token=self._token, page_size=self._page_size, **self._kw)
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/gcloud/pubsub/client.py", line 164, in list_subscriptions
    self.project, page_size, page_token)
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/gcloud/pubsub/_gax.py", line 242, in list_subscriptions
    for sub_pb in page_iter.next()]
TypeError: 'Subscription' object is not iterable
```

and sometimes it just gives a `StopIteration` when a new page is expected

``` python
Traceback (most recent call last):
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/system_tests/pubsub.py", line 130, in test_list_subscriptions
    empty, _ = topic.list_subscriptions()
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/gcloud/pubsub/topic.py", line 314, in list_subscriptions
    self.full_name, page_size, page_token)
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/gcloud/pubsub/_gax.py", line 198, in topic_list_subscriptions
    subs = page_iter.next()
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/google/gax/__init__.py", line 472, in next
    return self.__next__()
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/google/gax/__init__.py", line 478, in __next__
    self._current = next(self._page_iterator)
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/google/gax/__init__.py", line 435, in next
    return self.__next__()
  File "/home/travis/build/GoogleCloudPlatform/gcloud-python/.tox/system-tests/lib/python2.7/site-packages/google/gax/__init__.py", line 440, in __next__
    raise StopIteration
StopIteration
```

I withhold the `flaky` label because the same 10 test cases fail every time and in both Python 2 and 3:
1. `test_fetch_delete_subscription_w_deleted_topic (pubsub.TestPubsub)`
2. `test_list_subscriptions (pubsub.TestPubsub)`
3. `test_list_topics (pubsub.TestPubsub)`
4. `test_list_metrics (logging_.TestLogging)`
5. `test_list_sinks (logging_.TestLogging)`
6. `test_log_struct (logging_.TestLogging)`
7. `test_log_struct_w_metadata (logging_.TestLogging)`
8. `test_log_text (logging_.TestLogging)`
9. `test_log_text_w_metadata (logging_.TestLogging)`
10. `test_update_metric (logging_.TestLogging)`



Discussion:
@tseaver It seems like #2124 is the culprit

@tseaver ISTM that lines like

```
        token = page_iter.page_token or None
        return sinks, token
```

end up making `page_token=None` override the default value of `page_token=INITIAL_PAGE` in lots of these methods.

I'm gonna send a PR


Resolving patch:
diff --git a/gcloud/logging/_gax.py b/gcloud/logging/_gax.py
--- a/gcloud/logging/_gax.py
+++ b/gcloud/logging/_gax.py
@@ -44,7 +44,7 @@ def __init__(self, gax_api):
         self._gax_api = gax_api
 
     def list_entries(self, projects, filter_='', order_by='',
-                     page_size=0, page_token=INITIAL_PAGE):
+                     page_size=0, page_token=None):
         """Return a page of log entry resources.
 
         :type projects: list of strings
@@ -73,6 +73,8 @@ def list_entries(self, projects, filter_='', order_by='',
                   if not None, indicates that more entries can be retrieved
                   with another call (pass that value as ``page_token``).
         """
+        if page_token is None:
+            page_token = INITIAL_PAGE
         options = CallOptions(page_token=page_token)
         page_iter = self._gax_api.list_log_entries(
             projects, filter_, order_by, page_size, options)
@@ -135,7 +137,7 @@ class _SinksAPI(object):
     def __init__(self, gax_api):
         self._gax_api = gax_api
 
-    def list_sinks(self, project, page_size=0, page_token=INITIAL_PAGE):
+    def list_sinks(self, project, page_size=0, page_token=None):
         """List sinks for the project associated with this client.
 
         :type project: string
@@ -155,6 +157,8 @@ def list_sinks(self, project, page_size=0, page_token=INITIAL_PAGE):
                   if not None, indicates that more sinks can be retrieved
                   with another call (pass that value as ``page_token``).
         """
+        if page_token is None:
+            page_token = INITIAL_PAGE
         options = CallOptions(page_token=page_token)
         path = 'projects/%s' % (project,)
         page_iter = self._gax_api.list_sinks(path, page_size, options)
@@ -279,7 +283,7 @@ class _MetricsAPI(object):
     def __init__(self, gax_api):
         self._gax_api = gax_api
 
-    def list_metrics(self, project, page_size=0, page_token=INITIAL_PAGE):
+    def list_metrics(self, project, page_size=0, page_token=None):
         """List metrics for the project associated with this client.
 
         :type project: string
@@ -299,6 +303,8 @@ def list_metrics(self, project, page_size=0, page_token=INITIAL_PAGE):
                   if not None, indicates that more metrics can be retrieved
                   with another call (pass that value as ``page_token``).
         """
+        if page_token is None:
+            page_token = INITIAL_PAGE
         options = CallOptions(page_token=page_token)
         path = 'projects/%s' % (project,)
         page_iter = self._gax_api.list_log_metrics(path, page_size, options)
diff --git a/gcloud/pubsub/_gax.py b/gcloud/pubsub/_gax.py
--- a/gcloud/pubsub/_gax.py
+++ b/gcloud/pubsub/_gax.py
@@ -36,7 +36,7 @@ class _PublisherAPI(object):
     def __init__(self, gax_api):
         self._gax_api = gax_api
 
-    def list_topics(self, project, page_size=0, page_token=INITIAL_PAGE):
+    def list_topics(self, project, page_size=0, page_token=None):
         """List topics for the project associated with this API.
 
         See:
@@ -60,6 +60,8 @@ def list_topics(self, project, page_size=0, page_token=INITIAL_PAGE):
                   more topics can be retrieved with another call (pass that
                   value as ``page_token``).
         """
+        if page_token is None:
+            page_token = INITIAL_PAGE
         options = CallOptions(page_token=page_token)
         path = 'projects/%s' % (project,)
         page_iter = self._gax_api.list_topics(
@@ -162,7 +164,7 @@ def topic_publish(self, topic_path, messages):
         return result.message_ids
 
     def topic_list_subscriptions(self, topic_path, page_size=0,
-                                 page_token=INITIAL_PAGE):
+                                 page_token=None):
         """API call:  list subscriptions bound to a topic
 
         See:
@@ -187,6 +189,8 @@ def topic_list_subscriptions(self, topic_path, page_size=0,
         :raises: :exc:`gcloud.exceptions.NotFound` if the topic does not
                     exist
         """
+        if page_token is None:
+            page_token = INITIAL_PAGE
         options = CallOptions(page_token=page_token)
         try:
             page_iter = self._gax_api.list_topic_subscriptions(
@@ -209,8 +213,7 @@ class _SubscriberAPI(object):
     def __init__(self, gax_api):
         self._gax_api = gax_api
 
-    def list_subscriptions(self, project, page_size=0,
-                           page_token=INITIAL_PAGE):
+    def list_subscriptions(self, project, page_size=0, page_token=None):
         """List subscriptions for the project associated with this API.
 
         See:
@@ -234,6 +237,8 @@ def list_subscriptions(self, project, page_size=0,
                   more topics can be retrieved with another call (pass that
                   value as ``page_token``).
         """
+        if page_token is None:
+            page_token = INITIAL_PAGE
         options = CallOptions(page_token=page_token)
         path = 'projects/%s' % (project,)
         page_iter = self._gax_api.list_subscriptions(


Test patch: