Repository: googleapis/google-cloud-python

Issue:
Project inference is broken under Python 3.5.1
Project inference takes place in [_determine_default_project()](https://github.com/GoogleCloudPlatform/gcloud-python/blob/91be6938b26ba9198082f457ae37fba81b8f5ea0/gcloud/_helpers.py#L189), which hands off to [_compute_engine_id()](https://github.com/GoogleCloudPlatform/gcloud-python/blob/91be6938b26ba9198082f457ae37fba81b8f5ea0/gcloud/_helpers.py#L151). That returns the correct value -- but as `bytes`. The `Client` class checks if the project value is a `str` (using `six.string_types`) and raises an error because it is not (that code is [here](https://github.com/GoogleCloudPlatform/gcloud-python/blob/91be6938b26ba9198082f457ae37fba81b8f5ea0/gcloud/client.py#L144)).



Discussion:
Really appreciate the bugs @jlowin!

Happy to help :)

@jlowin Working on a fix now. Sorry for the delay!


Resolving patch:
diff --git a/gcloud/client.py b/gcloud/client.py
--- a/gcloud/client.py
+++ b/gcloud/client.py
@@ -141,6 +141,8 @@ def __init__(self, project=None):
         if project is None:
             raise ValueError('Project was not passed and could not be '
                              'determined from the environment.')
+        if isinstance(project, six.binary_type):
+            project = project.decode('utf-8')
         if not isinstance(project, six.string_types):
             raise ValueError('Project must be a string.')
         self.project = project


Test patch:
diff --git a/gcloud/test_client.py b/gcloud/test_client.py
--- a/gcloud/test_client.py
+++ b/gcloud/test_client.py
@@ -161,7 +161,7 @@ def mock_get_credentials():
                      _determine_default_project=mock_determine_proj):
             client_obj = self._makeOne()
 
-        self.assertTrue(client_obj.project is PROJECT)
+        self.assertEqual(client_obj.project, PROJECT)
         self.assertTrue(isinstance(client_obj.connection, _MockConnection))
         self.assertTrue(client_obj.connection.credentials is CREDENTIALS)
         self.assertEqual(
@@ -189,19 +189,31 @@ def test_ctor_w_invalid_project(self):
         with self.assertRaises(ValueError):
             self._makeOne(project=object(), credentials=CREDENTIALS, http=HTTP)
 
-    def test_ctor_explicit(self):
-        PROJECT = 'PROJECT'
+    def _explicit_ctor_helper(self, project):
+        import six
+
         CREDENTIALS = object()
         HTTP = object()
 
-        client_obj = self._makeOne(project=PROJECT, credentials=CREDENTIALS,
+        client_obj = self._makeOne(project=project, credentials=CREDENTIALS,
                                    http=HTTP)
 
-        self.assertTrue(client_obj.project is PROJECT)
+        if isinstance(project, six.binary_type):
+            self.assertEqual(client_obj.project, project.decode('utf-8'))
+        else:
+            self.assertEqual(client_obj.project, project)
         self.assertTrue(isinstance(client_obj.connection, _MockConnection))
         self.assertTrue(client_obj.connection.credentials is CREDENTIALS)
         self.assertTrue(client_obj.connection.http is HTTP)
 
+    def test_ctor_explicit_bytes(self):
+        PROJECT = b'PROJECT'
+        self._explicit_ctor_helper(PROJECT)
+
+    def test_ctor_explicit_unicode(self):
+        PROJECT = u'PROJECT'
+        self._explicit_ctor_helper(PROJECT)
+
 
 class _MockConnection(object):