Relax call details interface from interceptor

A gRPC Python client interceptor is passed an instance of a class
that implements the ClientCallDetails interface.  The interceptor
can choose to create its own object that implements the interface,
and pass it back to the continuation invoked by the interceptor.

To make it easy to add additional attributes to call details,
without breaking user code that hardcode the attributes required
by the interface, instead of interospecting the object passed
to the interceptor at runtime, and to ease authorship of
interceptors that want to keep some attributes intact and not
care about them, we relax the requirements on the object that
is expected to get passed by the interceptor and let the user
omit some attributes.  Omitted attributes will be replaced
by the original value of the attribute given to the interceptor.
pull/14105/head
Mehrdad Afshari 7 years ago
parent 5b48dc7371
commit 6615ef5eef
  1. 91
      src/python/grpcio/grpc/_interceptor.py

@ -51,6 +51,30 @@ class _ClientCallDetails(
pass
def _unwrap_client_call_details(call_details, default_details):
try:
method = call_details.method
except AttributeError:
method = default_details.method
try:
timeout = call_details.timeout
except AttributeError:
timeout = default_details.timeout
try:
metadata = call_details.metadata
except AttributeError:
metadata = default_details.metadata
try:
credentials = call_details.credentials
except AttributeError:
credentials = default_details.credentials
return method, timeout, metadata, credentials
class _LocalFailure(grpc.RpcError, grpc.Future, grpc.Call):
def __init__(self, exception, traceback):
@ -126,15 +150,18 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
def future(self, request, timeout=None, metadata=None, credentials=None):
def continuation(client_call_details, request):
return self._thunk(client_call_details.method).future(
request,
timeout=client_call_details.timeout,
metadata=client_call_details.metadata,
credentials=client_call_details.credentials)
client_call_details = _ClientCallDetails(self._method, timeout,
metadata, credentials)
def continuation(new_details, request):
new_method, new_timeout, new_metadata, new_credentials = (
_unwrap_client_call_details(new_details, client_call_details))
return self._thunk(new_method).future(
request,
timeout=new_timeout,
metadata=new_metadata,
credentials=new_credentials)
try:
return self._interceptor.intercept_unary_unary(
continuation, client_call_details, request)
@ -150,16 +177,18 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
self._interceptor = interceptor
def __call__(self, request, timeout=None, metadata=None, credentials=None):
client_call_details = _ClientCallDetails(self._method, timeout,
metadata, credentials)
def continuation(client_call_details, request):
return self._thunk(client_call_details.method)(
def continuation(new_details, request):
new_method, new_timeout, new_metadata, new_credentials = (
_unwrap_client_call_details(new_details, client_call_details))
return self._thunk(new_method)(
request,
timeout=client_call_details.timeout,
metadata=client_call_details.metadata,
credentials=client_call_details.credentials)
timeout=new_timeout,
metadata=new_metadata,
credentials=new_credentials)
client_call_details = _ClientCallDetails(self._method, timeout,
metadata, credentials)
try:
return self._interceptor.intercept_unary_stream(
continuation, client_call_details, request)
@ -203,17 +232,18 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
timeout=None,
metadata=None,
credentials=None):
def continuation(client_call_details, request_iterator):
return self._thunk(client_call_details.method).future(
request_iterator,
timeout=client_call_details.timeout,
metadata=client_call_details.metadata,
credentials=client_call_details.credentials)
client_call_details = _ClientCallDetails(self._method, timeout,
metadata, credentials)
def continuation(new_details, request_iterator):
new_method, new_timeout, new_metadata, new_credentials = (
_unwrap_client_call_details(new_details, client_call_details))
return self._thunk(new_method).future(
request_iterator,
timeout=new_timeout,
metadata=new_metadata,
credentials=new_credentials)
try:
return self._interceptor.intercept_stream_unary(
continuation, client_call_details, request_iterator)
@ -233,17 +263,18 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
timeout=None,
metadata=None,
credentials=None):
def continuation(client_call_details, request_iterator):
return self._thunk(client_call_details.method)(
request_iterator,
timeout=client_call_details.timeout,
metadata=client_call_details.metadata,
credentials=client_call_details.credentials)
client_call_details = _ClientCallDetails(self._method, timeout,
metadata, credentials)
def continuation(new_details, request_iterator):
new_method, new_timeout, new_metadata, new_credentials = (
_unwrap_client_call_details(new_details, client_call_details))
return self._thunk(new_method)(
request_iterator,
timeout=new_timeout,
metadata=new_metadata,
credentials=new_credentials)
try:
return self._interceptor.intercept_stream_stream(
continuation, client_call_details, request_iterator)

Loading…
Cancel
Save