Repository: googleapis/google-cloud-python

Issue:
Add GAE/GCE support for datastore.set_default_dataset and add exception on failure
See discussion in #444 for comments on exception.

Something like [`oauth2client.client._get_environment`](https://github.com/google/oauth2client/blob/481b4b6310e5872fbd5ed6c7aa336938e564d729/oauth2client/client.py#L953) could be good to detect GAE/GCE dataset ID's but `_detect_gce_environment` should be better as discussed in google/oauth2client#93

Not blocking for M1.



Discussion:
Relevant to GAE:

``` python
>>> import os
>>> from google.appengine.api import app_identity
>>>
>>> print repr(os.getenv('APPLICATION_ID'))
's~foo'
>>> print repr(app_identity.get_application_id())
'foo'
```

Relevant to GCE:

``` python
>>> import urllib2
>>> BASE = 'http://metadata.google.internal/'
>>> PROJECT_PATH = 'computeMetadata/v1/project/project-id'
>>> URI = BASE + PROJECT_PATH
>>> request = urllib2.Request(URI, headers={'Metadata-Flavor': 'Google'})
>>> response = urllib2.urlopen(request)
>>> contents = response.read()
>>> response.close()
>>> contents
'foo'
```

No prefix there.

@tseaver I just realized that #572 does not raise when setting fails.

We can add this in a sweeping way for both packages after #572 goes through? We'll have to determine the difference between "required" defaults (always raise) and "optional" defaults (sometimes raise) for the `set_defaults` functions.

Re-opening until exception questions resolved.

This isn't possible with the current dataset_id situation requiring s~ or e~ prefixes in the key protobuf. Moving to Datastore Future since we don't know for sure when this will be fixed. 


Resolving patch:
diff --git a/gcloud/datastore/__init__.py b/gcloud/datastore/__init__.py
--- a/gcloud/datastore/__init__.py
+++ b/gcloud/datastore/__init__.py
@@ -80,6 +80,8 @@ def set_default_dataset_id(dataset_id=None):
 
     :type dataset_id: string
     :param dataset_id: Optional. The dataset ID to use as default.
+
+    :raises: :class:`EnvironmentError` if no dataset ID was implied.
     """
     if dataset_id is None:
         dataset_id = os.getenv(_DATASET_ENV_VAR_NAME)
@@ -92,6 +94,8 @@ def set_default_dataset_id(dataset_id=None):
 
     if dataset_id is not None:
         _implicit_environ.DATASET_ID = dataset_id
+    else:
+        raise EnvironmentError('No dataset ID could be inferred.')
 
 
 def set_default_connection(connection=None):


Test patch:
diff --git a/gcloud/datastore/test___init__.py b/gcloud/datastore/test___init__.py
--- a/gcloud/datastore/test___init__.py
+++ b/gcloud/datastore/test___init__.py
@@ -58,7 +58,7 @@ def test_no_env_var_set(self):
 
         with self._monkeyEnviron(None):
             with self._monkeyImplicit():
-                self._callFUT()
+                self.assertRaises(EnvironmentError, self._callFUT)
 
         self.assertEqual(_implicit_environ.DATASET_ID, None)
 
@@ -98,7 +98,7 @@ def test_set_explicit_None_wo_env_var_set(self):
 
         with self._monkeyEnviron(None):
             with self._monkeyImplicit():
-                self._callFUT(None)
+                self.assertRaises(EnvironmentError, self._callFUT, None)
 
         self.assertEqual(_implicit_environ.DATASET_ID, None)
 
@@ -152,7 +152,10 @@ def _implicit_compute_engine_helper(self, status):
 
         with self._monkeyEnviron(None):
             with self._monkeyImplicit(connection=connection):
-                self._callFUT()
+                if EXPECTED_ID is None:
+                    self.assertRaises(EnvironmentError, self._callFUT)
+                else:
+                    self._callFUT()
 
         self.assertEqual(_implicit_environ.DATASET_ID, EXPECTED_ID)
         self.assertEqual(connection.host, '169.254.169.254')