From 1fc08ebc5082497db008beb850d00c41b377617a Mon Sep 17 00:00:00 2001 From: Juan Lara Date: Tue, 24 May 2022 20:54:11 +0000 Subject: [PATCH] docs: add samples for IN, NOT_IN, and != operators. --- samples/requirements-test.txt | 4 ++ samples/requirements.txt | 1 + samples/snippets.py | 98 +++++++++++++++++++++++++++++++++++ samples/snippets_test.py | 78 ++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 samples/requirements-test.txt create mode 100644 samples/requirements.txt create mode 100644 samples/snippets.py create mode 100644 samples/snippets_test.py diff --git a/samples/requirements-test.txt b/samples/requirements-test.txt new file mode 100644 index 00000000..f1521089 --- /dev/null +++ b/samples/requirements-test.txt @@ -0,0 +1,4 @@ +backoff==1.11.1; python_version < "3.7" +backoff==2.0.0; python_version >= "3.7" +pytest==7.0.1 +flaky==3.7.0 \ No newline at end of file diff --git a/samples/requirements.txt b/samples/requirements.txt new file mode 100644 index 00000000..3fca62c0 --- /dev/null +++ b/samples/requirements.txt @@ -0,0 +1 @@ +google-cloud-datastore==2.4.0 \ No newline at end of file diff --git a/samples/snippets.py b/samples/snippets.py new file mode 100644 index 00000000..375ea6b5 --- /dev/null +++ b/samples/snippets.py @@ -0,0 +1,98 @@ +# Copyright 2022 Google, Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from collections import defaultdict +import datetime +from pprint import pprint + +import google.cloud.exceptions +from google.cloud import datastore # noqa: I100 + +def _preamble(): + # [START datastore_size_coloration_query] + from google.cloud import datastore + + # For help authenticating your client, visit + # https://cloud.google.com/docs/authentication/getting-started + client = datastore.Client() + + # [END datastore_size_coloration_query] + assert client is not None + +def in_query(client): + # [START datastore_in_query] + query = client.query(kind="Task") + query.add_filter("tag", "IN", ["learn", "study"]) + # [END datastore_in_query] + + return list(query.fetch()) + +def not_equals_query(client): + # [START datastore_not_equals_query] + query = client.query(kind="Task") + query.add_filter("category", "!=", "work") + # [END datastore_not_equals_query] + + return list(query.fetch()) + +def not_equals_query(client): + # [START datastore_not_in_query] + query = client.query(kind="Task") + query.add_filter("category", "NOT_IN", ["work", "chores", "school"]) + # [END datastore_not_in_query] + + return list(query.fetch()) + + +def eq_query_sorted(client): + # [START datastore_eq_query_sorted] + query = client.query(kind="Task") + query.add_filter("tag", "=", "learn") + # Ordering on equality filters are ignored + query.order = ['tag'] + # [END datastore_eq_query_sorted] + + return list(query.fetch()) + +def in_query_sorted(client): + # [START datastore_in_query_sorted] + query = client.query(kind="Task") + query.add_filter("tag", "IN", ["learn", "study"]) + # Ordering on equality filters are ignored + query.order = ['tag'] + # [END datastore_in_query_sorted] + + return list(query.fetch()) + +def main(project_id): + client = datastore.Client(project_id) + + for name, function in globals().items(): + if name in ("main", "_preamble", "defaultdict") or not callable(function): + continue + + print(name) + pprint(function(client)) + print("\n-----------------\n") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Demonstrates datastore API operations." + ) + parser.add_argument("project_id", help="Your cloud project ID.") + + args = parser.parse_args() + + main(args.project_id) diff --git a/samples/snippets_test.py b/samples/snippets_test.py new file mode 100644 index 00000000..f29d3108 --- /dev/null +++ b/samples/snippets_test.py @@ -0,0 +1,78 @@ +# Copyright 2022 Google, Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +import backoff +from google.cloud import datastore +import pytest + +import snippets + +PROJECT = os.environ["GOOGLE_CLOUD_PROJECT"] + + +class CleanupClient(datastore.Client): + def __init__(self, *args, **kwargs): + super(CleanupClient, self).__init__(*args, **kwargs) + self.entities_to_delete = [] + self.keys_to_delete = [] + + def cleanup(self): + with self.batch(): + self.delete_multi( + list(set([x.key for x in self.entities_to_delete if x])) + + list(set(self.keys_to_delete)) + ) + + +@pytest.yield_fixture +def client(): + client = CleanupClient(PROJECT) + yield client + client.cleanup() + + +@pytest.mark.flaky +class TestDatastoreSnippets: + # These tests mostly just test the absence of exceptions. + + @backoff.on_exception(backoff.expo, AssertionError, max_time=240) + def test_in_query(self, client): + tasks = snippets.in_query(client) + client.entities_to_delete.extend(tasks) + assert tasks + + @backoff.on_exception(backoff.expo, AssertionError, max_time=240) + def test_not_equals_query(self, client): + tasks = snippets.not_equals_query(client) + client.entities_to_delete.extend(tasks) + assert tasks + + @backoff.on_exception(backoff.expo, AssertionError, max_time=240) + def test_not_in_query(self, client): + tasks = snippets.not_in_query(client) + client.entities_to_delete.extend(tasks) + assert tasks + + @backoff.on_exception(backoff.expo, AssertionError, max_time=240) + def test_eq_query_sorted(self, client): + tasks = snippets.eq_query_sorted(client) + client.entities_to_delete.extend(tasks) + assert tasks + + @backoff.on_exception(backoff.expo, AssertionError, max_time=240) + def test_in_query_sorted(self, client): + tasks = snippets.in_query_sorted(client) + client.entities_to_delete.extend(tasks) + assert tasks