Repository: googleapis/google-cloud-python

Issue:
Add key_filter helper for __key__ filter queries
See https://github.com/GoogleCloudPlatform/python-docs-samples/pull/158



Discussion:

Resolving patch:
diff --git a/gcloud/datastore/query.py b/gcloud/datastore/query.py
--- a/gcloud/datastore/query.py
+++ b/gcloud/datastore/query.py
@@ -248,6 +248,18 @@ def keys_only(self):
         """Set the projection to include only keys."""
         self._projection[:] = ['__key__']
 
+    def key_filter(self, key, operator='='):
+        """Filter on a key.
+
+        :type key: :class:`gcloud.datastore.key.Key`
+        :param key: The key to filter on.
+
+        :type operator: string
+        :param operator: (Optional) One of ``=``, ``<``, ``<=``, ``>``, ``>=``.
+                         Defaults to ``=``.
+        """
+        self.add_filter('__key__', operator, key)
+
     @property
     def order(self):
         """Names of fields used to sort query results.


Test patch:
diff --git a/gcloud/datastore/test_query.py b/gcloud/datastore/test_query.py
--- a/gcloud/datastore/test_query.py
+++ b/gcloud/datastore/test_query.py
@@ -244,6 +244,26 @@ def test_keys_only(self):
         query.keys_only()
         self.assertEqual(query.projection, ['__key__'])
 
+    def test_key_filter_defaults(self):
+        from gcloud.datastore.key import Key
+
+        client = self._makeClient()
+        query = self._makeOne(client)
+        self.assertEqual(query.filters, [])
+        key = Key('Kind', 1234, project='project')
+        query.key_filter(key)
+        self.assertEqual(query.filters, [('__key__', '=', key)])
+
+    def test_key_filter_explicit(self):
+        from gcloud.datastore.key import Key
+
+        client = self._makeClient()
+        query = self._makeOne(client)
+        self.assertEqual(query.filters, [])
+        key = Key('Kind', 1234, project='project')
+        query.key_filter(key, operator='>')
+        self.assertEqual(query.filters, [('__key__', '>', key)])
+
     def test_order_setter_empty(self):
         query = self._makeOne(self._makeClient(), order=['foo', '-bar'])
         query.order = []
diff --git a/system_tests/clear_datastore.py b/system_tests/clear_datastore.py
--- a/system_tests/clear_datastore.py
+++ b/system_tests/clear_datastore.py
@@ -42,7 +42,8 @@ def print_func(message):
 
 def fetch_keys(kind, client, fetch_max=FETCH_MAX, query=None, cursor=None):
     if query is None:
-        query = client.query(kind=kind, projection=['__key__'])
+        query = client.query(kind=kind)
+        query.keys_only()
 
     iterator = query.fetch(limit=fetch_max, start_cursor=cursor)
 
@@ -89,7 +90,7 @@ def remove_kind(kind, client):
 def remove_all_entities(client=None):
     if client is None:
         # Get a client that uses the test dataset.
-        client = datastore.Client(project=TESTS_DATASET)
+        client = datastore.Client(project=os.getenv(TESTS_DATASET))
     for kind in ALL_KINDS:
         remove_kind(kind, client)
 
diff --git a/system_tests/datastore.py b/system_tests/datastore.py
--- a/system_tests/datastore.py
+++ b/system_tests/datastore.py
@@ -273,12 +273,12 @@ def test_ancestor_query(self):
         entities = list(filtered_query.fetch(limit=expected_matches + 1))
         self.assertEqual(len(entities), expected_matches)
 
-    def test_query___key___filter(self):
+    def test_query_key_filter(self):
         # Use the client for this test instead of the global.
         rickard_key = self.CLIENT.key(*populate_datastore.RICKARD)
 
         query = self._base_query()
-        query.add_filter('__key__', '=', rickard_key)
+        query.key_filter(rickard_key)
         expected_matches = 1
         # We expect 1, but allow the query to get 1 extra.
         entities = list(query.fetch(limit=expected_matches + 1))
diff --git a/system_tests/populate_datastore.py b/system_tests/populate_datastore.py
--- a/system_tests/populate_datastore.py
+++ b/system_tests/populate_datastore.py
@@ -91,7 +91,7 @@ def print_func(message):
 def add_characters(client=None):
     if client is None:
         # Get a client that uses the test dataset.
-        client = datastore.Client(project=TESTS_DATASET)
+        client = datastore.Client(project=os.getenv(TESTS_DATASET))
     with client.transaction() as xact:
         for key_path, character in zip(KEY_PATHS, CHARACTERS):
             if key_path[-1] != character['name']: