diff options
author | Bu Sun Kim <8822365+busunkim96@users.noreply.github.com> | 2021-08-31 12:08:42 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-31 14:08:42 -0400 |
commit | 618f19201af729205892fcecd9c8e315ba3174a3 (patch) | |
tree | 5237847118c65fc70e0309195bda0ec060fdee1a | |
parent | 82ca2fd3792e20bea20ba96273fde4f2bb07b497 (diff) | |
download | python-api-core-618f19201af729205892fcecd9c8e315ba3174a3.tar.gz |
fix: do not error on LROs with no response or error (#258)
Co-authored-by: Tres Seaver <tseaver@palladion.com>
-rw-r--r-- | google/api_core/operation.py | 10 | ||||
-rw-r--r-- | google/api_core/operation_async.py | 10 | ||||
-rw-r--r-- | tests/asyncio/test_operation_async.py | 6 | ||||
-rw-r--r-- | tests/unit/test_operation.py | 6 |
4 files changed, 15 insertions, 17 deletions
diff --git a/google/api_core/operation.py b/google/api_core/operation.py index b17f753..a66e4a5 100644 --- a/google/api_core/operation.py +++ b/google/api_core/operation.py @@ -140,11 +140,11 @@ class Operation(polling.PollingFuture): ) self.set_exception(exception) else: - exception = exceptions.GoogleAPICallError( - "Unexpected state: Long-running operation had neither " - "response nor error set." - ) - self.set_exception(exception) + # Some APIs set `done: true`, with an empty response. + # Set the result to an empty message of the expected + # result type. + # https://google.aip.dev/151 + self.set_result(self._result_type()) def _refresh_and_update(self, retry=polling.DEFAULT_RETRY): """Refresh the operation and update the result if needed. diff --git a/google/api_core/operation_async.py b/google/api_core/operation_async.py index 6bae865..17624d6 100644 --- a/google/api_core/operation_async.py +++ b/google/api_core/operation_async.py @@ -136,11 +136,11 @@ class AsyncOperation(async_future.AsyncFuture): ) self.set_exception(exception) else: - exception = exceptions.GoogleAPICallError( - "Unexpected state: Long-running operation had neither " - "response nor error set." - ) - self.set_exception(exception) + # Some APIs set `done: true`, with an empty response. + # Set the result to an empty message of the expected + # result type. + # https://google.aip.dev/151 + self.set_result(self._result_type()) async def _refresh_and_update(self, retry=async_future.DEFAULT_RETRY): """Refresh the operation and update the result if needed. diff --git a/tests/asyncio/test_operation_async.py b/tests/asyncio/test_operation_async.py index 907cda7..342184f 100644 --- a/tests/asyncio/test_operation_async.py +++ b/tests/asyncio/test_operation_async.py @@ -153,7 +153,7 @@ async def test_exception(): @mock.patch("asyncio.sleep", autospec=True) @pytest.mark.asyncio -async def test_unexpected_result(unused_sleep): +async def test_done_with_no_error_or_response(unused_sleep): responses = [ make_operation_proto(), # Second operation response is done, but has not error or response. @@ -161,9 +161,9 @@ async def test_unexpected_result(unused_sleep): ] future, _, _ = make_operation_future(responses) - exception = await future.exception() + result = await future.result() - assert "Unexpected state" in "{!r}".format(exception) + assert isinstance(result, struct_pb2.Struct) def test_from_gapic(): diff --git a/tests/unit/test_operation.py b/tests/unit/test_operation.py index 28fbfe2..7a3e3c6 100644 --- a/tests/unit/test_operation.py +++ b/tests/unit/test_operation.py @@ -163,7 +163,7 @@ def test_exception_with_error_code(): assert isinstance(exception, exceptions.NotFound) -def test_unexpected_result(): +def test_done_with_no_error_or_response(): responses = [ make_operation_proto(), # Second operation response is done, but has not error or response. @@ -171,9 +171,7 @@ def test_unexpected_result(): ] future, _, _ = make_operation_future(responses) - exception = future.exception() - - assert "Unexpected state" in "{!r}".format(exception) + assert isinstance(future.result(), struct_pb2.Struct) def test__refresh_http(): |