Merge pull request #6330 from soltanmm/6264

Allow additive changes to protos w/o forcing user implementation
pull/6357/head
Jan Tattermusch 9 years ago
commit 2e4bfed082
  1. 10
      src/compiler/python_generator.cc
  2. 41
      src/python/grpcio/tests/protoc_plugin/beta_python_plugin_test.py

@ -190,7 +190,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service,
"Documentation", doc, "Documentation", doc,
}); });
out->Print("\n"); out->Print("\n");
out->Print(dict, "class Beta$Service$Servicer(six.with_metaclass(abc.ABCMeta, object)):\n"); out->Print(dict, "class Beta$Service$Servicer(object):\n");
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
@ -198,12 +198,11 @@ bool PrintBetaServicer(const ServiceDescriptor* service,
auto meth = service->method(i); auto meth = service->method(i);
grpc::string arg_name = meth->client_streaming() ? grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request"; "request_iterator" : "request";
out->Print("@abc.abstractmethod\n");
out->Print("def $Method$(self, $ArgName$, context):\n", out->Print("def $Method$(self, $ArgName$, context):\n",
"Method", meth->name(), "ArgName", arg_name); "Method", meth->name(), "ArgName", arg_name);
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n"); out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
} }
} }
} }
@ -218,7 +217,7 @@ bool PrintBetaStub(const ServiceDescriptor* service,
"Documentation", doc, "Documentation", doc,
}); });
out->Print("\n"); out->Print("\n");
out->Print(dict, "class Beta$Service$Stub(six.with_metaclass(abc.ABCMeta, object)):\n"); out->Print(dict, "class Beta$Service$Stub(object):\n");
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
@ -227,7 +226,6 @@ bool PrintBetaStub(const ServiceDescriptor* service,
grpc::string arg_name = meth->client_streaming() ? grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request"; "request_iterator" : "request";
auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
out->Print("@abc.abstractmethod\n");
out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n"); out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n");
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
@ -450,6 +448,8 @@ bool PrintPreamble(const FileDescriptor* file,
out->Print("import six\n"); out->Print("import six\n");
out->Print("from $Package$ import implementations as beta_implementations\n", out->Print("from $Package$ import implementations as beta_implementations\n",
"Package", config.beta_package_root); "Package", config.beta_package_root);
out->Print("from $Package$ import interfaces as beta_interfaces\n",
"Package", config.beta_package_root);
out->Print("from grpc.framework.common import cardinality\n"); out->Print("from grpc.framework.common import cardinality\n");
out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n"); out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n");
return true; return true;

@ -45,6 +45,7 @@ import unittest
from six import moves from six import moves
from grpc.beta import implementations from grpc.beta import implementations
from grpc.beta import interfaces
from grpc.framework.foundation import future from grpc.framework.foundation import future
from grpc.framework.interfaces.face import face from grpc.framework.interfaces.face import face
from tests.unit.framework.common import test_constants from tests.unit.framework.common import test_constants
@ -178,6 +179,36 @@ def _CreateService(test_pb2):
server.stop(0) server.stop(0)
@contextlib.contextmanager
def _CreateIncompleteService(test_pb2):
"""Provides a servicer backend that fails to implement methods and its stub.
The servicer is just the implementation of the actual servicer passed to the
face player of the python RPC implementation; the two are detached.
Args:
test_pb2: The test_pb2 module generated by this test.
Yields:
A (servicer_methods, stub) pair where servicer_methods is the back-end of
the service bound to the stub and and stub is the stub on which to invoke
RPCs.
"""
servicer_methods = _ServicerMethods(test_pb2)
class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)):
pass
servicer = Servicer()
server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer)
port = server.add_insecure_port('[::]:0')
server.start()
channel = implementations.insecure_channel('localhost', port)
stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel)
yield servicer_methods, stub
server.stop(0)
def _streaming_input_request_iterator(test_pb2): def _streaming_input_request_iterator(test_pb2):
for _ in range(3): for _ in range(3):
request = test_pb2.StreamingInputCallRequest() request = test_pb2.StreamingInputCallRequest()
@ -264,6 +295,16 @@ class PythonPluginTest(unittest.TestCase):
with _CreateService(test_pb2) as (servicer, stub): with _CreateService(test_pb2) as (servicer, stub):
request = test_pb2.SimpleRequest(response_size=13) request = test_pb2.SimpleRequest(response_size=13)
def testIncompleteServicer(self):
import protoc_plugin_test_pb2 as test_pb2
moves.reload_module(test_pb2)
with _CreateIncompleteService(test_pb2) as (servicer, stub):
request = test_pb2.SimpleRequest(response_size=13)
try:
response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT)
except face.AbortionError as error:
self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, error.code)
def testUnaryCall(self): def testUnaryCall(self):
import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top import protoc_plugin_test_pb2 as test_pb2 # pylint: disable=g-import-not-at-top
moves.reload_module(test_pb2) moves.reload_module(test_pb2)

Loading…
Cancel
Save