|
20 | 20 | # Avoid the grpc and google.cloud.grpc collision. |
21 | 21 | from __future__ import absolute_import |
22 | 22 |
|
| 23 | +import contextlib |
23 | 24 | import copy |
| 25 | +import sys |
24 | 26 |
|
25 | 27 | import six |
26 | 28 |
|
27 | | -from google.cloud._helpers import _to_bytes |
28 | | - |
29 | 29 | try: |
| 30 | + from google.gax.errors import GaxError |
| 31 | + from google.gax.grpc import exc_to_code |
| 32 | + from grpc import StatusCode |
30 | 33 | from grpc._channel import _Rendezvous |
31 | 34 | except ImportError: # pragma: NO COVER |
| 35 | + _HAVE_GRPC = False |
32 | 36 | _Rendezvous = None |
| 37 | +else: |
| 38 | + _HAVE_GRPC = True |
| 39 | + |
| 40 | +from google.cloud._helpers import _to_bytes |
| 41 | + |
| 42 | +_HTTP_CODE_TO_EXCEPTION = {} # populated at end of module |
33 | 43 |
|
34 | 44 | _HTTP_CODE_TO_EXCEPTION = {} # populated at end of module |
35 | 45 |
|
@@ -244,8 +254,50 @@ def _walk_subclasses(klass): |
244 | 254 | yield subsub |
245 | 255 |
|
246 | 256 |
|
| 257 | +@contextlib.contextmanager |
| 258 | +def _catch_remap_gax_error(): |
| 259 | + """Remap GAX exceptions that happen in context. |
| 260 | +
|
| 261 | + .. _code.proto: https://github.com/googleapis/googleapis/blob/\ |
| 262 | + master/google/rpc/code.proto |
| 263 | +
|
| 264 | + Remaps gRPC exceptions to the classes defined in |
| 265 | + :mod:`~google.cloud.exceptions` (according to the description |
| 266 | + in `code.proto`_). |
| 267 | + """ |
| 268 | + try: |
| 269 | + yield |
| 270 | + except GaxError as exc: |
| 271 | + error_code = exc_to_code(exc.cause) |
| 272 | + error_class = _GRPC_ERROR_MAPPING.get(error_code) |
| 273 | + if error_class is None: |
| 274 | + raise |
| 275 | + else: |
| 276 | + new_exc = error_class(exc.cause.details()) |
| 277 | + six.reraise(error_class, new_exc, sys.exc_info()[2]) |
| 278 | + |
| 279 | + |
247 | 280 | # Build the code->exception class mapping. |
248 | 281 | for _eklass in _walk_subclasses(GoogleCloudError): |
249 | 282 | code = getattr(_eklass, 'code', None) |
250 | 283 | if code is not None: |
251 | 284 | _HTTP_CODE_TO_EXCEPTION[code] = _eklass |
| 285 | + |
| 286 | +if _HAVE_GRPC: |
| 287 | + _GRPC_ERROR_MAPPING = { |
| 288 | + StatusCode.UNKNOWN: InternalServerError, |
| 289 | + StatusCode.INVALID_ARGUMENT: BadRequest, |
| 290 | + StatusCode.DEADLINE_EXCEEDED: GatewayTimeout, |
| 291 | + StatusCode.NOT_FOUND: NotFound, |
| 292 | + StatusCode.ALREADY_EXISTS: Conflict, |
| 293 | + StatusCode.PERMISSION_DENIED: Forbidden, |
| 294 | + StatusCode.UNAUTHENTICATED: Unauthorized, |
| 295 | + StatusCode.RESOURCE_EXHAUSTED: TooManyRequests, |
| 296 | + StatusCode.FAILED_PRECONDITION: PreconditionFailed, |
| 297 | + StatusCode.ABORTED: Conflict, |
| 298 | + StatusCode.OUT_OF_RANGE: BadRequest, |
| 299 | + StatusCode.UNIMPLEMENTED: MethodNotImplemented, |
| 300 | + StatusCode.INTERNAL: InternalServerError, |
| 301 | + StatusCode.UNAVAILABLE: ServiceUnavailable, |
| 302 | + StatusCode.DATA_LOSS: InternalServerError, |
| 303 | + } |
0 commit comments