Skip to content

Commit 01a57a7

Browse files
feat: support with_call for wrapped rpcs (googleapis#550)
1 parent 533fbde commit 01a57a7

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

google/api_core/gapic_v1/method.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ def wrap_method(
137137
default_timeout=None,
138138
default_compression=None,
139139
client_info=client_info.DEFAULT_CLIENT_INFO,
140+
*,
141+
with_call=False,
140142
):
141143
"""Wrap an RPC method with common behavior.
142144
@@ -216,13 +218,24 @@ def get_topic(name, timeout=None):
216218
passed as gRPC metadata to the method. If unspecified, then
217219
a sane default will be used. If ``None``, then no user agent
218220
metadata will be provided to the RPC method.
221+
with_call (bool): If True, wrapped grpc.UnaryUnaryMulticallables will
222+
return a tuple of (response, grpc.Call) instead of just the response.
223+
This is useful for extracting trailing metadata from unary calls.
224+
Defaults to False.
219225
220226
Returns:
221227
Callable: A new callable that takes optional ``retry``, ``timeout``,
222228
and ``compression``
223229
arguments and applies the common error mapping, retry, timeout, compression,
224230
and metadata behavior to the low-level RPC method.
225231
"""
232+
if with_call:
233+
try:
234+
func = func.with_call
235+
except AttributeError as exc:
236+
raise ValueError(
237+
"with_call=True is only supported for unary calls."
238+
) from exc
226239
func = grpc_helpers.wrap_errors(func)
227240
if client_info is not None:
228241
user_agent_metadata = [client_info.to_grpc_metadata()]

tests/unit/gapic/test_method.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,24 @@ def test_wrap_method_with_overriding_timeout_as_a_number():
201201

202202
assert result == 42
203203
method.assert_called_once_with(timeout=22, metadata=mock.ANY)
204+
205+
206+
def test_wrap_method_with_call():
207+
method = mock.Mock()
208+
mock_call = mock.Mock()
209+
method.with_call.return_value = 42, mock_call
210+
211+
wrapped_method = google.api_core.gapic_v1.method.wrap_method(method, with_call=True)
212+
result = wrapped_method()
213+
assert len(result) == 2
214+
assert result[0] == 42
215+
assert result[1] == mock_call
216+
217+
218+
def test_wrap_method_with_call_not_supported():
219+
"""Raises an error if wrapped callable doesn't have with_call method."""
220+
method = lambda: None # noqa: E731
221+
222+
with pytest.raises(ValueError) as exc_info:
223+
google.api_core.gapic_v1.method.wrap_method(method, with_call=True)
224+
assert "with_call=True is only supported for unary calls" in str(exc_info.value)

0 commit comments

Comments
 (0)