Expose per-call credentials to Python
diff --git a/src/python/grpcio/grpc/_adapter/_c/types.h b/src/python/grpcio/grpc/_adapter/_c/types.h
index ec0687a..31fd470 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types.h
+++ b/src/python/grpcio/grpc/_adapter/_c/types.h
@@ -112,6 +112,8 @@
 PyObject *pygrpc_Call_start_batch(Call *self, PyObject *args, PyObject *kwargs);
 PyObject *pygrpc_Call_cancel(Call *self, PyObject *args, PyObject *kwargs);
 PyObject *pygrpc_Call_peer(Call *self);
+PyObject *pygrpc_Call_set_credentials(Call *self, PyObject *args,
+                                      PyObject *kwargs);
 extern PyTypeObject pygrpc_Call_type;
 
 
diff --git a/src/python/grpcio/grpc/_adapter/_c/types/call.c b/src/python/grpcio/grpc/_adapter/_c/types/call.c
index 42a5015..5604aba 100644
--- a/src/python/grpcio/grpc/_adapter/_c/types/call.c
+++ b/src/python/grpcio/grpc/_adapter/_c/types/call.c
@@ -43,6 +43,8 @@
     {"start_batch", (PyCFunction)pygrpc_Call_start_batch, METH_KEYWORDS, ""},
     {"cancel", (PyCFunction)pygrpc_Call_cancel, METH_KEYWORDS, ""},
     {"peer", (PyCFunction)pygrpc_Call_peer, METH_NOARGS, ""},
+    {"set_credentials", (PyCFunction)pygrpc_Call_set_credentials, METH_KEYWORDS,
+     ""},
     {NULL}
 };
 const char pygrpc_Call_doc[] = "See grpc._adapter._types.Call.";
@@ -169,3 +171,16 @@
   gpr_free(peer);
   return py_peer;
 }
+PyObject *pygrpc_Call_set_credentials(Call *self, PyObject *args,
+                                      PyObject *kwargs) {
+  ClientCredentials *creds;
+  grpc_call_error errcode;
+  static char *keywords[] = {"creds", NULL};
+  if (!PyArg_ParseTupleAndKeywords(
+      args, kwargs, "O!:set_credentials", keywords,
+      &pygrpc_ClientCredentials_type, &creds)) {
+    return NULL;
+  }
+  errcode = grpc_call_set_credentials(self->c_call, creds->c_creds);
+  return PyInt_FromLong(errcode);
+}
diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py
index 06358e7..735ad20 100644
--- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py
+++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py
@@ -163,6 +163,9 @@
   def cancel(self):
     return self._internal.cancel()
 
+  def set_credentials(self, creds):
+    return self._internal.set_credentials(creds)
+
 
 class Channel(object):
   """Adapter from old _low.Channel interface to new _low.Channel."""
diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py
index 3859ebb..70ceb2a 100644
--- a/src/python/grpcio/grpc/_adapter/_low.py
+++ b/src/python/grpcio/grpc/_adapter/_low.py
@@ -78,6 +78,9 @@
   def peer(self):
     return self.call.peer()
 
+  def set_credentials(self, creds):
+    return self.call.set_credentials(creds)
+
 
 class Channel(_types.Channel):