Description
CC @atulep
The following commit causes a regression in the test suite:
commit ef6f0fcfdfe771172056e35e3c990998b3b00416
Author: Aza Tulepbergenov <[email protected]>
Date: 2021-10-19 20:17:49 +0200
feat: add 'GoogleAPICallError.error_details' property (#286)
Based on 'google.rpc.status.details'.
Prior to this commit, the package handled both missing and present grpc
consistently. However, the following condition in exceptions.py
:
try:
import grpc
from grpc_status import rpc_status
except ImportError: # pragma: NO COVER
grpc = None
rpc_status = None
means that if grpc_status
module is not installed, the exception module behaves as if grpc
wasn't present even though other modules (notably tests) behave as if it was present. As a result, people having one but not the other module installed get a bunch of test failures because grpc-based tests are run but e.g. the exception
module's from_grpc_error()
function fails since grpc
is forced to None
.
This is especially problematic since grpcio-status
is a new optional dependency, and since it's not packaged on Gentoo, we'd effectively have to force people to uninstall grpcio
.
Environment details
- OS type and version: Gentoo Linux
- Python version:
python --version
3.8.12, 3.9.7 - pip version:
pip --version
n/a google-api-core
version:pip show google-api-core
2.2.0, 2.2.1, git master (d2a729e)
Steps to reproduce
git clone https://github.com/googleapis/python-api-core
cd python-api-core
python3.9 -m venv .venv
. .venv/bin/activate
pip install . grpcio pytest mock proto-plus pytest-asyncio
pytest
Stack trace
Example test failure:
_______________________________________________________ test_wrap_unary_errors ________________________________________________________
self = <google.api_core.grpc_helpers_async._WrappedUnaryUnaryCall object at 0x7fe0e3de3790>
def __await__(self):
try:
> response = yield from self._call.__await__()
.venv/lib/python3.9/site-packages/google/api_core/grpc_helpers_async.py:84:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
_mock_self = <AsyncMock id='140603872279952'>, args = (1, 2), kwargs = {'three': 'four'}, self = <AsyncMock id='140603872279952'>
_call = call(1, 2, three='four'), effect = RpcErrorImpl()
async def _execute_mock_call(_mock_self, *args, **kwargs):
self = _mock_self
# This is nearly just like super(), except for special handling
# of coroutines
_call = _Call((args, kwargs), two=True)
self.await_count += 1
self.await_args = _call
self.await_args_list.append(_call)
effect = self.side_effect
if effect is not None:
if _is_exception(effect):
> raise effect
E tests.asyncio.test_grpc_helpers_async.RpcErrorImpl
.venv/lib/python3.9/site-packages/mock/mock.py:2169: RpcErrorImpl
During handling of the above exception, another exception occurred:
@pytest.mark.asyncio
async def test_wrap_unary_errors():
grpc_error = RpcErrorImpl(grpc.StatusCode.INVALID_ARGUMENT)
callable_ = mock.AsyncMock(spec=["__call__"], side_effect=grpc_error)
wrapped_callable = grpc_helpers_async._wrap_unary_errors(callable_)
with pytest.raises(exceptions.InvalidArgument) as exc_info:
> await wrapped_callable(1, 2, three="four")
tests/asyncio/test_grpc_helpers_async.py:57:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.9/site-packages/google/api_core/grpc_helpers_async.py:87: in __await__
raise exceptions.from_grpc_error(rpc_error) from rpc_error
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
rpc_exc = RpcErrorImpl()
def from_grpc_error(rpc_exc):
"""Create a :class:`GoogleAPICallError` from a :class:`grpc.RpcError`.
Args:
rpc_exc (grpc.RpcError): The gRPC error.
Returns:
GoogleAPICallError: An instance of the appropriate subclass of
:class:`GoogleAPICallError`.
"""
# NOTE(lidiz) All gRPC error shares the parent class grpc.RpcError.
# However, check for grpc.RpcError breaks backward compatibility.
> if isinstance(rpc_exc, grpc.Call) or _is_informative_grpc_error(rpc_exc):
E AttributeError: 'NoneType' object has no attribute 'Call'
.venv/lib/python3.9/site-packages/google/api_core/exceptions.py:532: AttributeError
======================================================= short test summary info =======================================================
FAILED tests/asyncio/test_grpc_helpers_async.py::test_wrap_unary_errors - AttributeError: 'NoneType' object has no attribute 'Call'