Skip to content

Commit ab22afd

Browse files
chore: avoid checking instance on each stream call (#529)
* chore: avoid checking instance on each stream call * fixed indentation * added check for unary call * fixed type check * fixed tests * fixed coverage * added exception to test class * added comment to test * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent 7d87462 commit ab22afd

File tree

2 files changed

+73
-29
lines changed

2 files changed

+73
-29
lines changed

google/api_core/grpc_helpers_async.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ class _WrappedStreamStreamCall(
159159

160160
def _wrap_unary_errors(callable_):
161161
"""Map errors for Unary-Unary async callables."""
162-
grpc_helpers._patch_callable_name(callable_)
163162

164163
@functools.wraps(callable_)
165164
def error_remapped_callable(*args, **kwargs):
@@ -169,23 +168,13 @@ def error_remapped_callable(*args, **kwargs):
169168
return error_remapped_callable
170169

171170

172-
def _wrap_stream_errors(callable_):
171+
def _wrap_stream_errors(callable_, wrapper_type):
173172
"""Map errors for streaming RPC async callables."""
174-
grpc_helpers._patch_callable_name(callable_)
175173

176174
@functools.wraps(callable_)
177175
async def error_remapped_callable(*args, **kwargs):
178176
call = callable_(*args, **kwargs)
179-
180-
if isinstance(call, aio.UnaryStreamCall):
181-
call = _WrappedUnaryStreamCall().with_call(call)
182-
elif isinstance(call, aio.StreamUnaryCall):
183-
call = _WrappedStreamUnaryCall().with_call(call)
184-
elif isinstance(call, aio.StreamStreamCall):
185-
call = _WrappedStreamStreamCall().with_call(call)
186-
else:
187-
raise TypeError("Unexpected type of call %s" % type(call))
188-
177+
call = wrapper_type().with_call(call)
189178
await call.wait_for_connection()
190179
return call
191180

@@ -207,10 +196,17 @@ def wrap_errors(callable_):
207196
208197
Returns: Callable: The wrapped gRPC callable.
209198
"""
199+
grpc_helpers._patch_callable_name(callable_)
210200
if isinstance(callable_, aio.UnaryUnaryMultiCallable):
211201
return _wrap_unary_errors(callable_)
202+
elif isinstance(callable_, aio.UnaryStreamMultiCallable):
203+
return _wrap_stream_errors(callable_, _WrappedUnaryStreamCall)
204+
elif isinstance(callable_, aio.StreamUnaryMultiCallable):
205+
return _wrap_stream_errors(callable_, _WrappedStreamUnaryCall)
206+
elif isinstance(callable_, aio.StreamStreamMultiCallable):
207+
return _wrap_stream_errors(callable_, _WrappedStreamStreamCall)
212208
else:
213-
return _wrap_stream_errors(callable_)
209+
raise TypeError("Unexpected type of callable: {}".format(type(callable_)))
214210

215211

216212
def create_channel(

tests/asyncio/test_grpc_helpers_async.py

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,40 @@ async def test_common_methods_in_wrapped_call():
9797
assert mock_call.wait_for_connection.call_count == 1
9898

9999

100+
@pytest.mark.asyncio
101+
@pytest.mark.parametrize(
102+
"callable_type,expected_wrapper_type",
103+
[
104+
(grpc.aio.UnaryStreamMultiCallable, grpc_helpers_async._WrappedUnaryStreamCall),
105+
(grpc.aio.StreamUnaryMultiCallable, grpc_helpers_async._WrappedStreamUnaryCall),
106+
(
107+
grpc.aio.StreamStreamMultiCallable,
108+
grpc_helpers_async._WrappedStreamStreamCall,
109+
),
110+
],
111+
)
112+
async def test_wrap_errors_w_stream_type(callable_type, expected_wrapper_type):
113+
class ConcreteMulticallable(callable_type):
114+
def __call__(self, *args, **kwargs):
115+
raise NotImplementedError("Should not be called")
116+
117+
with mock.patch.object(
118+
grpc_helpers_async, "_wrap_stream_errors"
119+
) as wrap_stream_errors:
120+
callable_ = ConcreteMulticallable()
121+
grpc_helpers_async.wrap_errors(callable_)
122+
assert wrap_stream_errors.call_count == 1
123+
wrap_stream_errors.assert_called_once_with(callable_, expected_wrapper_type)
124+
125+
100126
@pytest.mark.asyncio
101127
async def test_wrap_stream_errors_unary_stream():
102128
mock_call = mock.Mock(aio.UnaryStreamCall, autospec=True)
103129
multicallable = mock.Mock(return_value=mock_call)
104130

105-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
131+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
132+
multicallable, grpc_helpers_async._WrappedUnaryStreamCall
133+
)
106134

107135
await wrapped_callable(1, 2, three="four")
108136
multicallable.assert_called_once_with(1, 2, three="four")
@@ -114,7 +142,9 @@ async def test_wrap_stream_errors_stream_unary():
114142
mock_call = mock.Mock(aio.StreamUnaryCall, autospec=True)
115143
multicallable = mock.Mock(return_value=mock_call)
116144

117-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
145+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
146+
multicallable, grpc_helpers_async._WrappedStreamUnaryCall
147+
)
118148

119149
await wrapped_callable(1, 2, three="four")
120150
multicallable.assert_called_once_with(1, 2, three="four")
@@ -126,22 +156,26 @@ async def test_wrap_stream_errors_stream_stream():
126156
mock_call = mock.Mock(aio.StreamStreamCall, autospec=True)
127157
multicallable = mock.Mock(return_value=mock_call)
128158

129-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
159+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
160+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
161+
)
130162

131163
await wrapped_callable(1, 2, three="four")
132164
multicallable.assert_called_once_with(1, 2, three="four")
133165
assert mock_call.wait_for_connection.call_count == 1
134166

135167

136168
@pytest.mark.asyncio
137-
async def test_wrap_stream_errors_type_error():
169+
async def test_wrap_errors_type_error():
170+
"""
171+
If wrap_errors is called with an unexpected type, it should raise a TypeError.
172+
"""
138173
mock_call = mock.Mock()
139174
multicallable = mock.Mock(return_value=mock_call)
140175

141-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
142-
143-
with pytest.raises(TypeError):
144-
await wrapped_callable()
176+
with pytest.raises(TypeError) as exc:
177+
grpc_helpers_async.wrap_errors(multicallable)
178+
assert "Unexpected type" in str(exc.value)
145179

146180

147181
@pytest.mark.asyncio
@@ -151,7 +185,9 @@ async def test_wrap_stream_errors_raised():
151185
mock_call.wait_for_connection = mock.AsyncMock(side_effect=[grpc_error])
152186
multicallable = mock.Mock(return_value=mock_call)
153187

154-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
188+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
189+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
190+
)
155191

156192
with pytest.raises(exceptions.InvalidArgument):
157193
await wrapped_callable()
@@ -166,7 +202,9 @@ async def test_wrap_stream_errors_read():
166202
mock_call.read = mock.AsyncMock(side_effect=grpc_error)
167203
multicallable = mock.Mock(return_value=mock_call)
168204

169-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
205+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
206+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
207+
)
170208

171209
wrapped_call = await wrapped_callable(1, 2, three="four")
172210
multicallable.assert_called_once_with(1, 2, three="four")
@@ -189,7 +227,9 @@ async def test_wrap_stream_errors_aiter():
189227
mock_call.__aiter__ = mock.Mock(return_value=mocked_aiter)
190228
multicallable = mock.Mock(return_value=mock_call)
191229

192-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
230+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
231+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
232+
)
193233
wrapped_call = await wrapped_callable()
194234

195235
with pytest.raises(exceptions.InvalidArgument) as exc_info:
@@ -210,7 +250,9 @@ async def test_wrap_stream_errors_aiter_non_rpc_error():
210250
mock_call.__aiter__ = mock.Mock(return_value=mocked_aiter)
211251
multicallable = mock.Mock(return_value=mock_call)
212252

213-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
253+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
254+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
255+
)
214256
wrapped_call = await wrapped_callable()
215257

216258
with pytest.raises(TypeError) as exc_info:
@@ -224,7 +266,9 @@ async def test_wrap_stream_errors_aiter_called_multiple_times():
224266
mock_call = mock.Mock(aio.StreamStreamCall, autospec=True)
225267
multicallable = mock.Mock(return_value=mock_call)
226268

227-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
269+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
270+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
271+
)
228272
wrapped_call = await wrapped_callable()
229273

230274
assert wrapped_call.__aiter__() == wrapped_call.__aiter__()
@@ -239,7 +283,9 @@ async def test_wrap_stream_errors_write():
239283
mock_call.done_writing = mock.AsyncMock(side_effect=[None, grpc_error])
240284
multicallable = mock.Mock(return_value=mock_call)
241285

242-
wrapped_callable = grpc_helpers_async._wrap_stream_errors(multicallable)
286+
wrapped_callable = grpc_helpers_async._wrap_stream_errors(
287+
multicallable, grpc_helpers_async._WrappedStreamStreamCall
288+
)
243289

244290
wrapped_call = await wrapped_callable()
245291

@@ -295,7 +341,9 @@ def test_wrap_errors_streaming(wrap_stream_errors):
295341
result = grpc_helpers_async.wrap_errors(callable_)
296342

297343
assert result == wrap_stream_errors.return_value
298-
wrap_stream_errors.assert_called_once_with(callable_)
344+
wrap_stream_errors.assert_called_once_with(
345+
callable_, grpc_helpers_async._WrappedUnaryStreamCall
346+
)
299347

300348

301349
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)