Skip to content

Commit 618f192

Browse files
busunkim96tseaver
andauthored
fix: do not error on LROs with no response or error (#258)
Co-authored-by: Tres Seaver <tseaver@palladion.com>
1 parent 82ca2fd commit 618f192

File tree

4 files changed

+15
-17
lines changed

4 files changed

+15
-17
lines changed

google/api_core/operation.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ def _set_result_from_operation(self):
140140
)
141141
self.set_exception(exception)
142142
else:
143-
exception = exceptions.GoogleAPICallError(
144-
"Unexpected state: Long-running operation had neither "
145-
"response nor error set."
146-
)
147-
self.set_exception(exception)
143+
# Some APIs set `done: true`, with an empty response.
144+
# Set the result to an empty message of the expected
145+
# result type.
146+
# https://google.aip.dev/151
147+
self.set_result(self._result_type())
148148

149149
def _refresh_and_update(self, retry=polling.DEFAULT_RETRY):
150150
"""Refresh the operation and update the result if needed.

google/api_core/operation_async.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ def _set_result_from_operation(self):
136136
)
137137
self.set_exception(exception)
138138
else:
139-
exception = exceptions.GoogleAPICallError(
140-
"Unexpected state: Long-running operation had neither "
141-
"response nor error set."
142-
)
143-
self.set_exception(exception)
139+
# Some APIs set `done: true`, with an empty response.
140+
# Set the result to an empty message of the expected
141+
# result type.
142+
# https://google.aip.dev/151
143+
self.set_result(self._result_type())
144144

145145
async def _refresh_and_update(self, retry=async_future.DEFAULT_RETRY):
146146
"""Refresh the operation and update the result if needed.

tests/asyncio/test_operation_async.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,17 @@ async def test_exception():
153153

154154
@mock.patch("asyncio.sleep", autospec=True)
155155
@pytest.mark.asyncio
156-
async def test_unexpected_result(unused_sleep):
156+
async def test_done_with_no_error_or_response(unused_sleep):
157157
responses = [
158158
make_operation_proto(),
159159
# Second operation response is done, but has not error or response.
160160
make_operation_proto(done=True),
161161
]
162162
future, _, _ = make_operation_future(responses)
163163

164-
exception = await future.exception()
164+
result = await future.result()
165165

166-
assert "Unexpected state" in "{!r}".format(exception)
166+
assert isinstance(result, struct_pb2.Struct)
167167

168168

169169
def test_from_gapic():

tests/unit/test_operation.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,15 @@ def test_exception_with_error_code():
163163
assert isinstance(exception, exceptions.NotFound)
164164

165165

166-
def test_unexpected_result():
166+
def test_done_with_no_error_or_response():
167167
responses = [
168168
make_operation_proto(),
169169
# Second operation response is done, but has not error or response.
170170
make_operation_proto(done=True),
171171
]
172172
future, _, _ = make_operation_future(responses)
173173

174-
exception = future.exception()
175-
176-
assert "Unexpected state" in "{!r}".format(exception)
174+
assert isinstance(future.result(), struct_pb2.Struct)
177175

178176

179177
def test__refresh_http():

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy