From 0b946324be0b52430e7c3f7b5f498a880aaa8b3d Mon Sep 17 00:00:00 2001 From: Jon Wayne Parrott Date: Tue, 8 Aug 2017 14:03:04 -0700 Subject: [PATCH] Move google.cloud.future to google.api.core (#3764) --- bigquery/google/cloud/bigquery/job.py | 6 ++-- bigtable/google/cloud/bigtable/cluster.py | 2 +- bigtable/google/cloud/bigtable/instance.py | 2 +- bigtable/tests/unit/test_cluster.py | 4 +-- bigtable/tests/unit/test_instance.py | 4 +-- .../{cloud => api/core}/future/__init__.py | 2 +- .../{cloud => api/core}/future/_helpers.py | 0 .../google/{cloud => api/core}/future/base.py | 0 .../{cloud => api/core}/future/polling.py | 4 +-- .../{cloud/future => api/core}/operation.py | 35 +++++++++++++++---- .../unit/{ => api_core}/future/__init__.py | 0 .../{ => api_core}/future/test__helpers.py | 2 +- .../{ => api_core}/future/test_polling.py | 2 +- .../{future => api_core}/test_operation.py | 2 +- spanner/google/cloud/spanner/database.py | 4 +-- spanner/google/cloud/spanner/instance.py | 4 +-- 16 files changed, 48 insertions(+), 25 deletions(-) rename core/google/{cloud => api/core}/future/__init__.py (93%) rename core/google/{cloud => api/core}/future/_helpers.py (100%) rename core/google/{cloud => api/core}/future/base.py (100%) rename core/google/{cloud => api/core}/future/polling.py (98%) rename core/google/{cloud/future => api/core}/operation.py (91%) rename core/tests/unit/{ => api_core}/future/__init__.py (100%) rename core/tests/unit/{ => api_core}/future/test__helpers.py (96%) rename core/tests/unit/{ => api_core}/future/test_polling.py (98%) rename core/tests/unit/{future => api_core}/test_operation.py (99%) diff --git a/bigquery/google/cloud/bigquery/job.py b/bigquery/google/cloud/bigquery/job.py index 1519e2a0cf6e8..43d7fd8f23c31 100644 --- a/bigquery/google/cloud/bigquery/job.py +++ b/bigquery/google/cloud/bigquery/job.py @@ -19,6 +19,7 @@ import six from six.moves import http_client +import google.api.core.future.polling from google.cloud import exceptions from google.cloud.exceptions import NotFound from google.cloud._helpers import _datetime_from_microseconds @@ -31,7 +32,6 @@ from google.cloud.bigquery._helpers import UDFResourcesProperty from google.cloud.bigquery._helpers import _EnumProperty from google.cloud.bigquery._helpers import _TypedProperty -import google.cloud.future.polling _DONE_STATE = 'DONE' _STOPPED_REASON = 'stopped' @@ -140,7 +140,7 @@ class WriteDisposition(_EnumProperty): WRITE_EMPTY = 'WRITE_EMPTY' -class _AsyncJob(google.cloud.future.polling.PollingFuture): +class _AsyncJob(google.api.core.future.polling.PollingFuture): """Base class for asynchronous jobs. :type name: str @@ -496,7 +496,7 @@ def cancelled(self): This always returns False. It's not possible to check if a job was cancelled in the API. This method is here to satisfy the interface - for :class:`google.cloud.future.Future`. + for :class:`google.api.core.future.Future`. :rtype: bool :returns: False diff --git a/bigtable/google/cloud/bigtable/cluster.py b/bigtable/google/cloud/bigtable/cluster.py index 8d15547efae38..09a34e11bb05e 100644 --- a/bigtable/google/cloud/bigtable/cluster.py +++ b/bigtable/google/cloud/bigtable/cluster.py @@ -17,11 +17,11 @@ import re +from google.api.core import operation from google.cloud.bigtable._generated import ( instance_pb2 as data_v2_pb2) from google.cloud.bigtable._generated import ( bigtable_instance_admin_pb2 as messages_v2_pb2) -from google.cloud.future import operation _CLUSTER_NAME_RE = re.compile(r'^projects/(?P[^/]+)/' r'instances/(?P[^/]+)/clusters/' diff --git a/bigtable/google/cloud/bigtable/instance.py b/bigtable/google/cloud/bigtable/instance.py index 958f166029533..5e73ed2ba661f 100644 --- a/bigtable/google/cloud/bigtable/instance.py +++ b/bigtable/google/cloud/bigtable/instance.py @@ -17,6 +17,7 @@ import re +from google.api.core import operation from google.cloud.bigtable._generated import ( instance_pb2 as data_v2_pb2) from google.cloud.bigtable._generated import ( @@ -26,7 +27,6 @@ from google.cloud.bigtable.cluster import Cluster from google.cloud.bigtable.cluster import DEFAULT_SERVE_NODES from google.cloud.bigtable.table import Table -from google.cloud.future import operation _EXISTING_INSTANCE_LOCATION_ID = 'see-existing-cluster' diff --git a/bigtable/tests/unit/test_cluster.py b/bigtable/tests/unit/test_cluster.py index e244b55d6dff6..8ed54846d18ec 100644 --- a/bigtable/tests/unit/test_cluster.py +++ b/bigtable/tests/unit/test_cluster.py @@ -233,8 +233,8 @@ def test_reload(self): self.assertEqual(cluster.location, LOCATION) def test_create(self): + from google.api.core import operation from google.longrunning import operations_pb2 - from google.cloud.future import operation from google.cloud.bigtable._generated import ( bigtable_instance_admin_pb2 as messages_v2_pb2) from tests.unit._testing import _FakeStub @@ -275,8 +275,8 @@ def test_create(self): def test_update(self): import datetime + from google.api.core import operation from google.longrunning import operations_pb2 - from google.cloud.future import operation from google.protobuf.any_pb2 import Any from google.cloud._helpers import _datetime_to_pb_timestamp from google.cloud.bigtable._generated import ( diff --git a/bigtable/tests/unit/test_instance.py b/bigtable/tests/unit/test_instance.py index 03c0034fc49e8..ce475e0d5a669 100644 --- a/bigtable/tests/unit/test_instance.py +++ b/bigtable/tests/unit/test_instance.py @@ -232,13 +232,13 @@ def test_reload(self): def test_create(self): import datetime + from google.api.core import operation from google.longrunning import operations_pb2 from google.protobuf.any_pb2 import Any from google.cloud.bigtable._generated import ( bigtable_instance_admin_pb2 as messages_v2_pb2) from google.cloud._helpers import _datetime_to_pb_timestamp from tests.unit._testing import _FakeStub - from google.cloud.future import operation from google.cloud.bigtable.cluster import DEFAULT_SERVE_NODES NOW = datetime.datetime.utcnow() @@ -285,11 +285,11 @@ def test_create(self): self.assertEqual(kwargs, {}) def test_create_w_explicit_serve_nodes(self): + from google.api.core import operation from google.longrunning import operations_pb2 from google.cloud.bigtable._generated import ( bigtable_instance_admin_pb2 as messages_v2_pb2) from tests.unit._testing import _FakeStub - from google.cloud.future import operation SERVE_NODES = 5 diff --git a/core/google/cloud/future/__init__.py b/core/google/api/core/future/__init__.py similarity index 93% rename from core/google/cloud/future/__init__.py rename to core/google/api/core/future/__init__.py index e5cf2b20ce7ed..a61510d307e62 100644 --- a/core/google/cloud/future/__init__.py +++ b/core/google/api/core/future/__init__.py @@ -14,7 +14,7 @@ """Futures for dealing with asynchronous operations.""" -from google.cloud.future.base import Future +from google.api.core.future.base import Future __all__ = [ 'Future', diff --git a/core/google/cloud/future/_helpers.py b/core/google/api/core/future/_helpers.py similarity index 100% rename from core/google/cloud/future/_helpers.py rename to core/google/api/core/future/_helpers.py diff --git a/core/google/cloud/future/base.py b/core/google/api/core/future/base.py similarity index 100% rename from core/google/cloud/future/base.py rename to core/google/api/core/future/base.py diff --git a/core/google/cloud/future/polling.py b/core/google/api/core/future/polling.py similarity index 98% rename from core/google/cloud/future/polling.py rename to core/google/api/core/future/polling.py index 6b7ae4221f64f..40380d6ad938d 100644 --- a/core/google/cloud/future/polling.py +++ b/core/google/api/core/future/polling.py @@ -22,8 +22,8 @@ import six import tenacity -from google.cloud.future import _helpers -from google.cloud.future import base +from google.api.core.future import _helpers +from google.api.core.future import base class PollingFuture(base.Future): diff --git a/core/google/cloud/future/operation.py b/core/google/api/core/operation.py similarity index 91% rename from core/google/cloud/future/operation.py rename to core/google/api/core/operation.py index ec430cd9c55b4..1cc44f0b3d7bc 100644 --- a/core/google/cloud/future/operation.py +++ b/core/google/api/core/operation.py @@ -12,14 +12,36 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Futures for long-running operations returned from Google Cloud APIs.""" +"""Futures for long-running operations returned from Google Cloud APIs. + +These futures can be used to synchronously wait for the result of a +long-running operation using :meth:`Operation.result`: + + +.. code-block:: python + + operation = my_api_client.long_running_method() + result = operation.result() + +Or asynchronously using callbacks and :meth:`Operation.add_done_callback`: + +.. code-block:: python + + operation = my_api_client.long_running_method() + + def my_callback(future): + result = future.result() + + operation.add_done_callback(my_callback) + +""" import functools import threading +from google.api.core import exceptions +from google.api.core.future import polling from google.cloud import _helpers -from google.cloud import exceptions -from google.cloud.future import polling from google.longrunning import operations_pb2 from google.protobuf import json_format from google.rpc import code_pb2 @@ -85,12 +107,13 @@ def _set_result_from_operation(self): self._result_type, self._operation.response) self.set_result(response) elif self._operation.HasField('error'): - exception = exceptions.GoogleCloudError( + exception = exceptions.GoogleAPICallError( self._operation.error.message, - errors=(self._operation.error)) + errors=(self._operation.error), + response=self._operation) self.set_exception(exception) else: - exception = exceptions.GoogleCloudError( + exception = exceptions.GoogleAPICallError( 'Unexpected state: Long-running operation had neither ' 'response nor error set.') self.set_exception(exception) diff --git a/core/tests/unit/future/__init__.py b/core/tests/unit/api_core/future/__init__.py similarity index 100% rename from core/tests/unit/future/__init__.py rename to core/tests/unit/api_core/future/__init__.py diff --git a/core/tests/unit/future/test__helpers.py b/core/tests/unit/api_core/future/test__helpers.py similarity index 96% rename from core/tests/unit/future/test__helpers.py rename to core/tests/unit/api_core/future/test__helpers.py index cbca5ba4d4df8..534dd3696cb97 100644 --- a/core/tests/unit/future/test__helpers.py +++ b/core/tests/unit/api_core/future/test__helpers.py @@ -14,7 +14,7 @@ import mock -from google.cloud.future import _helpers +from google.api.core.future import _helpers @mock.patch('threading.Thread', autospec=True) diff --git a/core/tests/unit/future/test_polling.py b/core/tests/unit/api_core/future/test_polling.py similarity index 98% rename from core/tests/unit/future/test_polling.py rename to core/tests/unit/api_core/future/test_polling.py index c8fde1c203850..a359ba1a2152c 100644 --- a/core/tests/unit/future/test_polling.py +++ b/core/tests/unit/api_core/future/test_polling.py @@ -19,7 +19,7 @@ import mock import pytest -from google.cloud.future import polling +from google.api.core.future import polling class PollingFutureImpl(polling.PollingFuture): diff --git a/core/tests/unit/future/test_operation.py b/core/tests/unit/api_core/test_operation.py similarity index 99% rename from core/tests/unit/future/test_operation.py rename to core/tests/unit/api_core/test_operation.py index 2d281694001a7..2332c50fdf4b4 100644 --- a/core/tests/unit/future/test_operation.py +++ b/core/tests/unit/api_core/test_operation.py @@ -15,7 +15,7 @@ import mock -from google.cloud.future import operation +from google.api.core import operation from google.longrunning import operations_pb2 from google.protobuf import struct_pb2 from google.rpc import code_pb2 diff --git a/spanner/google/cloud/spanner/database.py b/spanner/google/cloud/spanner/database.py index acfcefdce891a..38dc1c7eaaf88 100644 --- a/spanner/google/cloud/spanner/database.py +++ b/spanner/google/cloud/spanner/database.py @@ -185,7 +185,7 @@ def create(self): See https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.CreateDatabase - :rtype: :class:`~google.cloud.future.operation.Operation` + :rtype: :class:`~google.api.core.operation.Operation` :returns: a future used to poll the status of the create request :raises Conflict: if the database already exists :raises NotFound: if the instance owning the database does not exist @@ -269,7 +269,7 @@ def update_ddl(self, ddl_statements): See https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase - :rtype: :class:`google.cloud.future.operation.Operation` + :rtype: :class:`google.api.core.operation.Operation` :returns: an operation instance :raises NotFound: if the database does not exist :raises GaxError: diff --git a/spanner/google/cloud/spanner/instance.py b/spanner/google/cloud/spanner/instance.py index 5bd4663764f5d..4a51c70557316 100644 --- a/spanner/google/cloud/spanner/instance.py +++ b/spanner/google/cloud/spanner/instance.py @@ -198,7 +198,7 @@ def create(self): before calling :meth:`create`. - :rtype: :class:`google.cloud.future.operation.Operation` + :rtype: :class:`google.api.core.operation.Operation` :returns: an operation instance :raises Conflict: if the instance already exists :raises GaxError: @@ -289,7 +289,7 @@ def update(self): before calling :meth:`update`. - :rtype: :class:`google.cloud.future.operation.Operation` + :rtype: :class:`google.api.core.operation.Operation` :returns: an operation instance :raises NotFound: if the instance does not exist :raises GaxError: for other errors returned from the call