Merge pull request #8246 from soltanmm-google/bob-and-weave

Enable split code generation
pull/8587/head
Masood Malekghassemi 8 years ago committed by GitHub
commit 6937c8f362
  1. 454
      src/compiler/python_generator.cc
  2. 4
      src/compiler/python_generator.h
  3. 1
      src/python/grpcio_health_checking/.gitignore
  4. 1
      src/python/grpcio_tests/.gitignore
  5. 10
      src/python/grpcio_tests/setup.py
  6. 4
      src/python/grpcio_tests/tests/_loader.py
  7. 304
      src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
  8. 30
      src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py
  9. 39
      src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/same.proto
  10. 30
      src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py
  11. 35
      src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/messages.proto
  12. 30
      src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py
  13. 38
      src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/services.proto
  14. 90
      src/python/grpcio_tests/tests/tests.json

@ -35,6 +35,8 @@
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
#include <cstring> #include <cstring>
#include <fstream>
#include <iostream>
#include <map> #include <map>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
@ -66,66 +68,11 @@ using std::vector;
namespace grpc_python_generator { namespace grpc_python_generator {
GeneratorConfiguration::GeneratorConfiguration()
: grpc_package_root("grpc"), beta_package_root("grpc.beta") {}
PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
: config_(config) {}
PythonGrpcGenerator::~PythonGrpcGenerator() {}
bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
const grpc::string& parameter,
GeneratorContext* context,
grpc::string* error) const {
// Get output file name.
grpc::string file_name;
static const int proto_suffix_length = strlen(".proto");
if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
file->name().find_last_of(".proto") == file->name().size() - 1) {
file_name =
file->name().substr(0, file->name().size() - proto_suffix_length) +
"_pb2.py";
} else {
*error = "Invalid proto file name. Proto file must end with .proto";
return false;
}
std::unique_ptr<ZeroCopyOutputStream> output(
context->OpenForInsert(file_name, "module_scope"));
CodedOutputStream coded_out(output.get());
bool success = false;
grpc::string code = "";
tie(success, code) = grpc_python_generator::GetServices(file, config_);
if (success) {
coded_out.WriteRaw(code.data(), code.size());
return true;
} else {
return false;
}
}
namespace { namespace {
//////////////////////////////////
// BEGIN FORMATTING BOILERPLATE // typedef vector<const Descriptor*> DescriptorVector;
////////////////////////////////// typedef map<grpc::string, grpc::string> StringMap;
typedef vector<grpc::string> StringVector;
// Converts an initializer list of the form { key0, value0, key1, value1, ... }
// into a map of key* to value*. Is merely a readability helper for later code.
map<grpc::string, grpc::string> ListToDict(
const initializer_list<grpc::string>& values) {
assert(values.size() % 2 == 0);
map<grpc::string, grpc::string> value_map;
auto value_iter = values.begin();
for (unsigned i = 0; i < values.size() / 2; ++i) {
grpc::string key = *value_iter;
++value_iter;
grpc::string value = *value_iter;
value_map[key] = value;
++value_iter;
}
return value_map;
}
// Provides RAII indentation handling. Use as: // Provides RAII indentation handling. Use as:
// { // {
@ -146,10 +93,6 @@ class IndentScope {
Printer* printer_; Printer* printer_;
}; };
////////////////////////////////
// END FORMATTING BOILERPLATE //
////////////////////////////////
// TODO(https://github.com/google/protobuf/issues/888): // TODO(https://github.com/google/protobuf/issues/888):
// Export `ModuleName` from protobuf's // Export `ModuleName` from protobuf's
// `src/google/protobuf/compiler/python/python_generator.cc` file. // `src/google/protobuf/compiler/python/python_generator.cc` file.
@ -173,11 +116,61 @@ grpc::string ModuleAlias(const grpc::string& filename) {
return module_name; return module_name;
} }
bool GetModuleAndMessagePath(const Descriptor* type, // Tucks all generator state in an anonymous namespace away from
const ServiceDescriptor* service, // PythonGrpcGenerator and the header file, mostly to encourage future changes
grpc::string* out) { // to not require updates to the grpcio-tools C++ code part. Assumes that it is
// only ever used from a single thread.
struct PrivateGenerator {
const GeneratorConfiguration& config;
const FileDescriptor* file;
bool generate_in_pb2_grpc;
Printer* out;
PrivateGenerator(const GeneratorConfiguration& config,
const FileDescriptor* file);
std::pair<bool, grpc::string> GetGrpcServices();
private:
bool PrintPreamble();
bool PrintBetaPreamble();
bool PrintGAServices();
bool PrintBetaServices();
bool PrintAddServicerToServer(
const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service);
bool PrintServicer(const ServiceDescriptor* service);
bool PrintStub(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service);
bool PrintBetaServicer(const ServiceDescriptor* service);
bool PrintBetaServerFactory(
const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service);
bool PrintBetaStub(const ServiceDescriptor* service);
bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service);
// Get all comments (leading, leading_detached, trailing) and print them as a
// docstring. Any leading space of a line will be removed, but the line
// wrapping will not be changed.
template <typename DescriptorType>
void PrintAllComments(const DescriptorType* descriptor);
bool GetModuleAndMessagePath(const Descriptor* type, grpc::string* out);
};
PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config,
const FileDescriptor* file)
: config(config), file(file) {}
bool PrivateGenerator::GetModuleAndMessagePath(const Descriptor* type,
grpc::string* out) {
const Descriptor* path_elem_type = type; const Descriptor* path_elem_type = type;
vector<const Descriptor*> message_path; DescriptorVector message_path;
do { do {
message_path.push_back(path_elem_type); message_path.push_back(path_elem_type);
path_elem_type = path_elem_type->containing_type(); path_elem_type = path_elem_type->containing_type();
@ -188,12 +181,16 @@ bool GetModuleAndMessagePath(const Descriptor* type,
file_name.find_last_of(".proto") == file_name.size() - 1)) { file_name.find_last_of(".proto") == file_name.size() - 1)) {
return false; return false;
} }
grpc::string service_file_name = service->file()->name(); grpc::string generator_file_name = file->name();
grpc::string module = grpc::string module;
service_file_name == file_name ? "" : ModuleAlias(file_name) + "."; if (generator_file_name != file_name || generate_in_pb2_grpc) {
module = ModuleAlias(file_name) + ".";
} else {
module = "";
}
grpc::string message_type; grpc::string message_type;
for (auto path_iter = message_path.rbegin(); path_iter != message_path.rend(); for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin();
++path_iter) { path_iter != message_path.rend(); ++path_iter) {
message_type += (*path_iter)->name() + "."; message_type += (*path_iter)->name() + ".";
} }
// no pop_back prior to C++11 // no pop_back prior to C++11
@ -202,33 +199,31 @@ bool GetModuleAndMessagePath(const Descriptor* type,
return true; return true;
} }
// Get all comments (leading, leading_detached, trailing) and print them as a
// docstring. Any leading space of a line will be removed, but the line wrapping
// will not be changed.
template <typename DescriptorType> template <typename DescriptorType>
static void PrintAllComments(const DescriptorType* desc, Printer* printer) { void PrivateGenerator::PrintAllComments(const DescriptorType* descriptor) {
std::vector<grpc::string> comments; StringVector comments;
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, grpc_generator::GetComment(
&comments); descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments);
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING, grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING,
&comments); &comments);
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING, grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING,
&comments); &comments);
if (comments.empty()) { if (comments.empty()) {
return; return;
} }
printer->Print("\"\"\""); out->Print("\"\"\"");
for (auto it = comments.begin(); it != comments.end(); ++it) { for (StringVector::iterator it = comments.begin(); it != comments.end();
++it) {
size_t start_pos = it->find_first_not_of(' '); size_t start_pos = it->find_first_not_of(' ');
if (start_pos != grpc::string::npos) { if (start_pos != grpc::string::npos) {
printer->Print(it->c_str() + start_pos); out->Print(it->c_str() + start_pos);
} }
printer->Print("\n"); out->Print("\n");
} }
printer->Print("\"\"\"\n"); out->Print("\"\"\"\n");
} }
bool PrintBetaServicer(const ServiceDescriptor* service, Printer* out) { bool PrivateGenerator::PrintBetaServicer(const ServiceDescriptor* service) {
out->Print("\n\n"); out->Print("\n\n");
out->Print("class Beta$Service$Servicer(object):\n", "Service", out->Print("class Beta$Service$Servicer(object):\n", "Service",
service->name()); service->name());
@ -241,16 +236,16 @@ bool PrintBetaServicer(const ServiceDescriptor* service, Printer* out) {
"generated\n" "generated\n"
"only to ease transition from grpcio<0.15.0 to " "only to ease transition from grpcio<0.15.0 to "
"grpcio>=0.15.0.\"\"\"\n"); "grpcio>=0.15.0.\"\"\"\n");
PrintAllComments(service, out); PrintAllComments(service);
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
auto meth = service->method(i); const MethodDescriptor* method = service->method(i);
grpc::string arg_name = grpc::string arg_name =
meth->client_streaming() ? "request_iterator" : "request"; method->client_streaming() ? "request_iterator" : "request";
out->Print("def $Method$(self, $ArgName$, context):\n", "Method", out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
meth->name(), "ArgName", arg_name); method->name(), "ArgName", arg_name);
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
PrintAllComments(meth, out); PrintAllComments(method);
out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n"); out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
} }
} }
@ -258,7 +253,7 @@ bool PrintBetaServicer(const ServiceDescriptor* service, Printer* out) {
return true; return true;
} }
bool PrintBetaStub(const ServiceDescriptor* service, Printer* out) { bool PrivateGenerator::PrintBetaStub(const ServiceDescriptor* service) {
out->Print("\n\n"); out->Print("\n\n");
out->Print("class Beta$Service$Stub(object):\n", "Service", service->name()); out->Print("class Beta$Service$Stub(object):\n", "Service", service->name());
{ {
@ -270,30 +265,33 @@ bool PrintBetaStub(const ServiceDescriptor* service, Printer* out) {
"generated\n" "generated\n"
"only to ease transition from grpcio<0.15.0 to " "only to ease transition from grpcio<0.15.0 to "
"grpcio>=0.15.0.\"\"\"\n"); "grpcio>=0.15.0.\"\"\"\n");
PrintAllComments(service, out); PrintAllComments(service);
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i); const MethodDescriptor* method = service->method(i);
grpc::string arg_name = grpc::string arg_name =
meth->client_streaming() ? "request_iterator" : "request"; method->client_streaming() ? "request_iterator" : "request";
auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); StringMap method_dict;
out->Print(methdict, method_dict["Method"] = method->name();
method_dict["ArgName"] = arg_name;
out->Print(method_dict,
"def $Method$(self, $ArgName$, timeout, metadata=None, " "def $Method$(self, $ArgName$, timeout, metadata=None, "
"with_call=False, protocol_options=None):\n"); "with_call=False, protocol_options=None):\n");
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
PrintAllComments(meth, out); PrintAllComments(method);
out->Print("raise NotImplementedError()\n"); out->Print("raise NotImplementedError()\n");
} }
if (!meth->server_streaming()) { if (!method->server_streaming()) {
out->Print(methdict, "$Method$.future = None\n"); out->Print(method_dict, "$Method$.future = None\n");
} }
} }
} }
return true; return true;
} }
bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name, bool PrivateGenerator::PrintBetaServerFactory(
const ServiceDescriptor* service, Printer* out) { const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service) {
out->Print("\n\n"); out->Print("\n\n");
out->Print( out->Print(
"def beta_create_$Service$_server(servicer, pool=None, " "def beta_create_$Service$_server(servicer, pool=None, "
@ -307,9 +305,9 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
"file not marked beta) for all further purposes. This function was\n" "file not marked beta) for all further purposes. This function was\n"
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0" "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
"\"\"\"\n"); "\"\"\"\n");
map<grpc::string, grpc::string> method_implementation_constructors; StringMap method_implementation_constructors;
map<grpc::string, grpc::string> input_message_modules_and_classes; StringMap input_message_modules_and_classes;
map<grpc::string, grpc::string> output_message_modules_and_classes; StringMap output_message_modules_and_classes;
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i); const MethodDescriptor* method = service->method(i);
const grpc::string method_implementation_constructor = const grpc::string method_implementation_constructor =
@ -317,12 +315,12 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
grpc::string(method->server_streaming() ? "stream_" : "unary_") + grpc::string(method->server_streaming() ? "stream_" : "unary_") +
"inline"; "inline";
grpc::string input_message_module_and_class; grpc::string input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service, if (!GetModuleAndMessagePath(method->input_type(),
&input_message_module_and_class)) { &input_message_module_and_class)) {
return false; return false;
} }
grpc::string output_message_module_and_class; grpc::string output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service, if (!GetModuleAndMessagePath(method->output_type(),
&output_message_module_and_class)) { &output_message_module_and_class)) {
return false; return false;
} }
@ -334,7 +332,7 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
make_pair(method->name(), output_message_module_and_class)); make_pair(method->name(), output_message_module_and_class));
} }
out->Print("request_deserializers = {\n"); out->Print("request_deserializers = {\n");
for (auto name_and_input_module_class_pair = for (StringMap::iterator name_and_input_module_class_pair =
input_message_modules_and_classes.begin(); input_message_modules_and_classes.begin();
name_and_input_module_class_pair != name_and_input_module_class_pair !=
input_message_modules_and_classes.end(); input_message_modules_and_classes.end();
@ -349,7 +347,7 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
} }
out->Print("}\n"); out->Print("}\n");
out->Print("response_serializers = {\n"); out->Print("response_serializers = {\n");
for (auto name_and_output_module_class_pair = for (StringMap::iterator name_and_output_module_class_pair =
output_message_modules_and_classes.begin(); output_message_modules_and_classes.begin();
name_and_output_module_class_pair != name_and_output_module_class_pair !=
output_message_modules_and_classes.end(); output_message_modules_and_classes.end();
@ -365,7 +363,7 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
} }
out->Print("}\n"); out->Print("}\n");
out->Print("method_implementations = {\n"); out->Print("method_implementations = {\n");
for (auto name_and_implementation_constructor = for (StringMap::iterator name_and_implementation_constructor =
method_implementation_constructors.begin(); method_implementation_constructors.begin();
name_and_implementation_constructor != name_and_implementation_constructor !=
method_implementation_constructors.end(); method_implementation_constructors.end();
@ -395,11 +393,11 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
return true; return true;
} }
bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name, bool PrivateGenerator::PrintBetaStubFactory(
const ServiceDescriptor* service, Printer* out) { const grpc::string& package_qualified_service_name,
map<grpc::string, grpc::string> dict = ListToDict({ const ServiceDescriptor* service) {
"Service", service->name(), StringMap dict;
}); dict["Service"] = service->name();
out->Print("\n\n"); out->Print("\n\n");
out->Print(dict, out->Print(dict,
"def beta_create_$Service$_stub(channel, host=None," "def beta_create_$Service$_stub(channel, host=None,"
@ -412,21 +410,21 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
"file not marked beta) for all further purposes. This function was\n" "file not marked beta) for all further purposes. This function was\n"
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0" "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
"\"\"\"\n"); "\"\"\"\n");
map<grpc::string, grpc::string> method_cardinalities; StringMap method_cardinalities;
map<grpc::string, grpc::string> input_message_modules_and_classes; StringMap input_message_modules_and_classes;
map<grpc::string, grpc::string> output_message_modules_and_classes; StringMap output_message_modules_and_classes;
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i); const MethodDescriptor* method = service->method(i);
const grpc::string method_cardinality = const grpc::string method_cardinality =
grpc::string(method->client_streaming() ? "STREAM" : "UNARY") + "_" + grpc::string(method->client_streaming() ? "STREAM" : "UNARY") + "_" +
grpc::string(method->server_streaming() ? "STREAM" : "UNARY"); grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
grpc::string input_message_module_and_class; grpc::string input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service, if (!GetModuleAndMessagePath(method->input_type(),
&input_message_module_and_class)) { &input_message_module_and_class)) {
return false; return false;
} }
grpc::string output_message_module_and_class; grpc::string output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service, if (!GetModuleAndMessagePath(method->output_type(),
&output_message_module_and_class)) { &output_message_module_and_class)) {
return false; return false;
} }
@ -438,7 +436,7 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
make_pair(method->name(), output_message_module_and_class)); make_pair(method->name(), output_message_module_and_class));
} }
out->Print("request_serializers = {\n"); out->Print("request_serializers = {\n");
for (auto name_and_input_module_class_pair = for (StringMap::iterator name_and_input_module_class_pair =
input_message_modules_and_classes.begin(); input_message_modules_and_classes.begin();
name_and_input_module_class_pair != name_and_input_module_class_pair !=
input_message_modules_and_classes.end(); input_message_modules_and_classes.end();
@ -453,7 +451,7 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
} }
out->Print("}\n"); out->Print("}\n");
out->Print("response_deserializers = {\n"); out->Print("response_deserializers = {\n");
for (auto name_and_output_module_class_pair = for (StringMap::iterator name_and_output_module_class_pair =
output_message_modules_and_classes.begin(); output_message_modules_and_classes.begin();
name_and_output_module_class_pair != name_and_output_module_class_pair !=
output_message_modules_and_classes.end(); output_message_modules_and_classes.end();
@ -469,7 +467,8 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
} }
out->Print("}\n"); out->Print("}\n");
out->Print("cardinalities = {\n"); out->Print("cardinalities = {\n");
for (auto name_and_cardinality = method_cardinalities.begin(); for (StringMap::iterator name_and_cardinality =
method_cardinalities.begin();
name_and_cardinality != method_cardinalities.end(); name_and_cardinality != method_cardinalities.end();
name_and_cardinality++) { name_and_cardinality++) {
IndentScope raii_descriptions_indent(out); IndentScope raii_descriptions_indent(out);
@ -493,13 +492,14 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
return true; return true;
} }
bool PrintStub(const grpc::string& package_qualified_service_name, bool PrivateGenerator::PrintStub(
const ServiceDescriptor* service, Printer* out) { const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service) {
out->Print("\n\n"); out->Print("\n\n");
out->Print("class $Service$Stub(object):\n", "Service", service->name()); out->Print("class $Service$Stub(object):\n", "Service", service->name());
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
PrintAllComments(service, out); PrintAllComments(service);
out->Print("\n"); out->Print("\n");
out->Print("def __init__(self, channel):\n"); out->Print("def __init__(self, channel):\n");
{ {
@ -513,17 +513,17 @@ bool PrintStub(const grpc::string& package_qualified_service_name,
} }
out->Print("\"\"\"\n"); out->Print("\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i); const MethodDescriptor* method = service->method(i);
auto multi_callable_constructor = grpc::string multi_callable_constructor =
grpc::string(method->client_streaming() ? "stream" : "unary") + grpc::string(method->client_streaming() ? "stream" : "unary") +
"_" + grpc::string(method->server_streaming() ? "stream" : "unary"); "_" + grpc::string(method->server_streaming() ? "stream" : "unary");
grpc::string request_module_and_class; grpc::string request_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service, if (!GetModuleAndMessagePath(method->input_type(),
&request_module_and_class)) { &request_module_and_class)) {
return false; return false;
} }
grpc::string response_module_and_class; grpc::string response_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service, if (!GetModuleAndMessagePath(method->output_type(),
&response_module_and_class)) { &response_module_and_class)) {
return false; return false;
} }
@ -550,14 +550,14 @@ bool PrintStub(const grpc::string& package_qualified_service_name,
return true; return true;
} }
bool PrintServicer(const ServiceDescriptor* service, Printer* out) { bool PrivateGenerator::PrintServicer(const ServiceDescriptor* service) {
out->Print("\n\n"); out->Print("\n\n");
out->Print("class $Service$Servicer(object):\n", "Service", service->name()); out->Print("class $Service$Servicer(object):\n", "Service", service->name());
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
PrintAllComments(service, out); PrintAllComments(service);
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i); const MethodDescriptor* method = service->method(i);
grpc::string arg_name = grpc::string arg_name =
method->client_streaming() ? "request_iterator" : "request"; method->client_streaming() ? "request_iterator" : "request";
out->Print("\n"); out->Print("\n");
@ -565,7 +565,7 @@ bool PrintServicer(const ServiceDescriptor* service, Printer* out) {
method->name(), "ArgName", arg_name); method->name(), "ArgName", arg_name);
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
PrintAllComments(method, out); PrintAllComments(method);
out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n"); out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
out->Print("context.set_details('Method not implemented!')\n"); out->Print("context.set_details('Method not implemented!')\n");
out->Print("raise NotImplementedError('Method not implemented!')\n"); out->Print("raise NotImplementedError('Method not implemented!')\n");
@ -575,9 +575,9 @@ bool PrintServicer(const ServiceDescriptor* service, Printer* out) {
return true; return true;
} }
bool PrintAddServicerToServer( bool PrivateGenerator::PrintAddServicerToServer(
const grpc::string& package_qualified_service_name, const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) { const ServiceDescriptor* service) {
out->Print("\n\n"); out->Print("\n\n");
out->Print("def add_$Service$Servicer_to_server(servicer, server):\n", out->Print("def add_$Service$Servicer_to_server(servicer, server):\n",
"Service", service->name()); "Service", service->name());
@ -588,19 +588,19 @@ bool PrintAddServicerToServer(
IndentScope raii_dict_first_indent(out); IndentScope raii_dict_first_indent(out);
IndentScope raii_dict_second_indent(out); IndentScope raii_dict_second_indent(out);
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
auto method = service->method(i); const MethodDescriptor* method = service->method(i);
auto method_handler_constructor = grpc::string method_handler_constructor =
grpc::string(method->client_streaming() ? "stream" : "unary") + grpc::string(method->client_streaming() ? "stream" : "unary") +
"_" + "_" +
grpc::string(method->server_streaming() ? "stream" : "unary") + grpc::string(method->server_streaming() ? "stream" : "unary") +
"_rpc_method_handler"; "_rpc_method_handler";
grpc::string request_module_and_class; grpc::string request_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(), service, if (!GetModuleAndMessagePath(method->input_type(),
&request_module_and_class)) { &request_module_and_class)) {
return false; return false;
} }
grpc::string response_module_and_class; grpc::string response_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(), service, if (!GetModuleAndMessagePath(method->output_type(),
&response_module_and_class)) { &response_module_and_class)) {
return false; return false;
} }
@ -635,53 +635,173 @@ bool PrintAddServicerToServer(
return true; return true;
} }
bool PrintPreamble(const FileDescriptor* file, bool PrivateGenerator::PrintBetaPreamble() {
const GeneratorConfiguration& config, Printer* out) {
out->Print("import $Package$\n", "Package", config.grpc_package_root);
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", out->Print("from $Package$ import interfaces as beta_interfaces\n", "Package",
config.beta_package_root); config.beta_package_root);
return true;
}
bool PrivateGenerator::PrintPreamble() {
out->Print("import $Package$\n", "Package", config.grpc_package_root);
out->Print("from grpc.framework.common import cardinality\n"); out->Print("from grpc.framework.common import cardinality\n");
out->Print( out->Print(
"from grpc.framework.interfaces.face import utilities as " "from grpc.framework.interfaces.face import utilities as "
"face_utilities\n"); "face_utilities\n");
if (generate_in_pb2_grpc) {
out->Print("\n");
for (int i = 0; i < file->service_count(); ++i) {
const ServiceDescriptor* service = file->service(i);
for (int j = 0; j < service->method_count(); ++j) {
const MethodDescriptor* method = service->method(j);
const Descriptor* types[2] = {method->input_type(),
method->output_type()};
for (int k = 0; k < 2; ++k) {
const Descriptor* type = types[k];
grpc::string type_file_name = type->file()->name();
grpc::string module_name = ModuleName(type_file_name);
grpc::string module_alias = ModuleAlias(type_file_name);
out->Print("import $ModuleName$ as $ModuleAlias$\n", "ModuleName",
module_name, "ModuleAlias", module_alias);
}
}
}
}
return true; return true;
} }
} // namespace bool PrivateGenerator::PrintGAServices() {
grpc::string package = file->package();
if (!package.empty()) {
package = package.append(".");
}
for (int i = 0; i < file->service_count(); ++i) {
const ServiceDescriptor* service = file->service(i);
grpc::string package_qualified_service_name = package + service->name();
if (!(PrintStub(package_qualified_service_name, service) &&
PrintServicer(service) &&
PrintAddServicerToServer(package_qualified_service_name, service))) {
return false;
}
}
return true;
}
pair<bool, grpc::string> GetServices(const FileDescriptor* file, bool PrivateGenerator::PrintBetaServices() {
const GeneratorConfiguration& config) { grpc::string package = file->package();
if (!package.empty()) {
package = package.append(".");
}
for (int i = 0; i < file->service_count(); ++i) {
const ServiceDescriptor* service = file->service(i);
grpc::string package_qualified_service_name = package + service->name();
if (!(PrintBetaServicer(service) && PrintBetaStub(service) &&
PrintBetaServerFactory(package_qualified_service_name, service) &&
PrintBetaStubFactory(package_qualified_service_name, service))) {
return false;
}
}
return true;
}
pair<bool, grpc::string> PrivateGenerator::GetGrpcServices() {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
StringOutputStream output_stream(&output); StringOutputStream output_stream(&output);
Printer out(&output_stream, '$'); Printer out_printer(&output_stream, '$');
if (!PrintPreamble(file, config, &out)) { out = &out_printer;
return make_pair(false, "");
} if (generate_in_pb2_grpc) {
auto package = file->package(); if (!PrintPreamble()) {
if (!package.empty()) { return make_pair(false, "");
package = package.append("."); }
} if (!PrintGAServices()) {
for (int i = 0; i < file->service_count(); ++i) {
auto service = file->service(i);
auto package_qualified_service_name = package + service->name();
if (!(PrintStub(package_qualified_service_name, service, &out) &&
PrintServicer(service, &out) &&
PrintAddServicerToServer(package_qualified_service_name, service,
&out) &&
PrintBetaServicer(service, &out) && PrintBetaStub(service, &out) &&
PrintBetaServerFactory(package_qualified_service_name, service,
&out) &&
PrintBetaStubFactory(package_qualified_service_name, service,
&out))) {
return make_pair(false, ""); return make_pair(false, "");
} }
} else {
out->Print("try:\n");
{
IndentScope raii_dict_try_indent(out);
out->Print(
"# THESE ELEMENTS WILL BE DEPRECATED.\n"
"# Please use the generated *_pb2_grpc.py files instead.\n");
if (!PrintPreamble()) {
return make_pair(false, "");
}
if (!PrintBetaPreamble()) {
return make_pair(false, "");
}
if (!PrintGAServices()) {
return make_pair(false, "");
}
if (!PrintBetaServices()) {
return make_pair(false, "");
}
}
out->Print("except ImportError:\n");
{
IndentScope raii_dict_except_indent(out);
out->Print("pass");
}
} }
} }
return make_pair(true, std::move(output)); return make_pair(true, std::move(output));
} }
} // namespace
GeneratorConfiguration::GeneratorConfiguration()
: grpc_package_root("grpc"), beta_package_root("grpc.beta") {}
PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
: config_(config) {}
PythonGrpcGenerator::~PythonGrpcGenerator() {}
bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
const grpc::string& parameter,
GeneratorContext* context,
grpc::string* error) const {
// Get output file name.
grpc::string pb2_file_name;
grpc::string pb2_grpc_file_name;
static const int proto_suffix_length = strlen(".proto");
if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
file->name().find_last_of(".proto") == file->name().size() - 1) {
grpc::string base =
file->name().substr(0, file->name().size() - proto_suffix_length);
pb2_file_name = base + "_pb2.py";
pb2_grpc_file_name = base + "_pb2_grpc.py";
} else {
*error = "Invalid proto file name. Proto file must end with .proto";
return false;
}
PrivateGenerator generator(config_, file);
std::unique_ptr<ZeroCopyOutputStream> pb2_output(
context->OpenForAppend(pb2_file_name));
std::unique_ptr<ZeroCopyOutputStream> grpc_output(
context->Open(pb2_grpc_file_name));
CodedOutputStream pb2_coded_out(pb2_output.get());
CodedOutputStream grpc_coded_out(grpc_output.get());
bool success = false;
grpc::string pb2_code;
grpc::string grpc_code;
generator.generate_in_pb2_grpc = false;
tie(success, pb2_code) = generator.GetGrpcServices();
if (success) {
generator.generate_in_pb2_grpc = true;
tie(success, grpc_code) = generator.GetGrpcServices();
if (success) {
pb2_coded_out.WriteRaw(pb2_code.data(), pb2_code.size());
grpc_coded_out.WriteRaw(grpc_code.data(), grpc_code.size());
return true;
}
}
return false;
}
} // namespace grpc_python_generator } // namespace grpc_python_generator

@ -62,10 +62,6 @@ class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
GeneratorConfiguration config_; GeneratorConfiguration config_;
}; };
std::pair<bool, grpc::string> GetServices(
const grpc::protobuf::FileDescriptor* file,
const GeneratorConfiguration& config);
} // namespace grpc_python_generator } // namespace grpc_python_generator
#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H #endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H

@ -1,5 +1,6 @@
*.proto *.proto
*_pb2.py *_pb2.py
*_pb2_grpc.py
build/ build/
grpcio_health_checking.egg-info/ grpcio_health_checking.egg-info/
dist/ dist/

@ -1,4 +1,5 @@
proto/ proto/
src/ src/
*_pb2.py *_pb2.py
*_pb2_grpc.py
*.egg-info/ *.egg-info/

@ -80,8 +80,14 @@ PACKAGE_DATA = {
'credentials/server1.key', 'credentials/server1.key',
'credentials/server1.pem', 'credentials/server1.pem',
], ],
'tests.protoc_plugin': [ 'tests.protoc_plugin.protos.invocation_testing': [
'protoc_plugin_test.proto', 'same.proto',
],
'tests.protoc_plugin.protos.invocation_testing.split_messages': [
'messages.proto',
],
'tests.protoc_plugin.protos.invocation_testing.split_services': [
'services.proto',
], ],
'tests.unit': [ 'tests.unit': [
'credentials/ca.pem', 'credentials/ca.pem',

@ -84,11 +84,9 @@ class Loader(object):
along. along.
""" """
for importer, module_name, is_package in ( for importer, module_name, is_package in (
pkgutil.iter_modules(package_paths)): pkgutil.walk_packages(package_paths)):
module = importer.find_module(module_name).load_module(module_name) module = importer.find_module(module_name).load_module(module_name)
self.visit_module(module) self.visit_module(module)
if is_package:
self.walk_packages(module.__path__)
def visit_module(self, module): def visit_module(self, module):
"""Visits the module, adding discovered tests to the test suite. """Visits the module, adding discovered tests to the test suite.

@ -0,0 +1,304 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import collections
from concurrent import futures
import contextlib
import distutils.spawn
import errno
import importlib
import os
import os.path
import pkgutil
import shutil
import subprocess
import sys
import tempfile
import threading
import unittest
import grpc
from grpc.tools import protoc
from tests.unit.framework.common import test_constants
_MESSAGES_IMPORT = b'import "messages.proto";'
@contextlib.contextmanager
def _system_path(path):
old_system_path = sys.path[:]
sys.path = sys.path[0:1] + path + sys.path[1:]
yield
sys.path = old_system_path
class DummySplitServicer(object):
def __init__(self, request_class, response_class):
self.request_class = request_class
self.response_class = response_class
def Call(self, request, context):
return self.response_class()
class SeparateTestMixin(object):
def testImportAttributes(self):
with _system_path([self.python_out_directory]):
pb2 = importlib.import_module(self.pb2_import)
pb2.Request
pb2.Response
if self.should_find_services_in_pb2:
pb2.TestServiceServicer
else:
with self.assertRaises(AttributeError):
pb2.TestServiceServicer
with _system_path([self.grpc_python_out_directory]):
pb2_grpc = importlib.import_module(self.pb2_grpc_import)
pb2_grpc.TestServiceServicer
with self.assertRaises(AttributeError):
pb2_grpc.Request
with self.assertRaises(AttributeError):
pb2_grpc.Response
def testCall(self):
with _system_path([self.python_out_directory]):
pb2 = importlib.import_module(self.pb2_import)
with _system_path([self.grpc_python_out_directory]):
pb2_grpc = importlib.import_module(self.pb2_grpc_import)
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE))
pb2_grpc.add_TestServiceServicer_to_server(
DummySplitServicer(
pb2.Request, pb2.Response), server)
port = server.add_insecure_port('[::]:0')
server.start()
channel = grpc.insecure_channel('localhost:{}'.format(port))
stub = pb2_grpc.TestServiceStub(channel)
request = pb2.Request()
expected_response = pb2.Response()
response = stub.Call(request)
self.assertEqual(expected_response, response)
class CommonTestMixin(object):
def testImportAttributes(self):
with _system_path([self.python_out_directory]):
pb2 = importlib.import_module(self.pb2_import)
pb2.Request
pb2.Response
if self.should_find_services_in_pb2:
pb2.TestServiceServicer
else:
with self.assertRaises(AttributeError):
pb2.TestServiceServicer
with _system_path([self.grpc_python_out_directory]):
pb2_grpc = importlib.import_module(self.pb2_grpc_import)
pb2_grpc.TestServiceServicer
with self.assertRaises(AttributeError):
pb2_grpc.Request
with self.assertRaises(AttributeError):
pb2_grpc.Response
def testCall(self):
with _system_path([self.python_out_directory]):
pb2 = importlib.import_module(self.pb2_import)
with _system_path([self.grpc_python_out_directory]):
pb2_grpc = importlib.import_module(self.pb2_grpc_import)
server = grpc.server(
futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE))
pb2_grpc.add_TestServiceServicer_to_server(
DummySplitServicer(
pb2.Request, pb2.Response), server)
port = server.add_insecure_port('[::]:0')
server.start()
channel = grpc.insecure_channel('localhost:{}'.format(port))
stub = pb2_grpc.TestServiceStub(channel)
request = pb2.Request()
expected_response = pb2.Response()
response = stub.Call(request)
self.assertEqual(expected_response, response)
class SameSeparateTest(unittest.TestCase, SeparateTestMixin):
def setUp(self):
same_proto_contents = pkgutil.get_data(
'tests.protoc_plugin.protos.invocation_testing', 'same.proto')
self.directory = tempfile.mkdtemp(suffix='same_separate', dir='.')
self.proto_directory = os.path.join(self.directory, 'proto_path')
self.python_out_directory = os.path.join(self.directory, 'python_out')
self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out')
os.makedirs(self.proto_directory)
os.makedirs(self.python_out_directory)
os.makedirs(self.grpc_python_out_directory)
same_proto_file = os.path.join(self.proto_directory, 'same_separate.proto')
open(same_proto_file, 'wb').write(same_proto_contents)
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
'--python_out={}'.format(self.python_out_directory),
'--grpc_python_out={}'.format(self.grpc_python_out_directory),
same_proto_file,
])
if protoc_result != 0:
raise Exception("unexpected protoc error")
open(os.path.join(self.grpc_python_out_directory, '__init__.py'), 'w').write('')
open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
self.pb2_import = 'same_separate_pb2'
self.pb2_grpc_import = 'same_separate_pb2_grpc'
self.should_find_services_in_pb2 = False
def tearDown(self):
shutil.rmtree(self.directory)
class SameCommonTest(unittest.TestCase, CommonTestMixin):
def setUp(self):
same_proto_contents = pkgutil.get_data(
'tests.protoc_plugin.protos.invocation_testing', 'same.proto')
self.directory = tempfile.mkdtemp(suffix='same_common', dir='.')
self.proto_directory = os.path.join(self.directory, 'proto_path')
self.python_out_directory = os.path.join(self.directory, 'python_out')
self.grpc_python_out_directory = self.python_out_directory
os.makedirs(self.proto_directory)
os.makedirs(self.python_out_directory)
same_proto_file = os.path.join(self.proto_directory, 'same_common.proto')
open(same_proto_file, 'wb').write(same_proto_contents)
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
'--python_out={}'.format(self.python_out_directory),
'--grpc_python_out={}'.format(self.grpc_python_out_directory),
same_proto_file,
])
if protoc_result != 0:
raise Exception("unexpected protoc error")
open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
self.pb2_import = 'same_common_pb2'
self.pb2_grpc_import = 'same_common_pb2_grpc'
self.should_find_services_in_pb2 = True
def tearDown(self):
shutil.rmtree(self.directory)
class SplitCommonTest(unittest.TestCase, CommonTestMixin):
def setUp(self):
services_proto_contents = pkgutil.get_data(
'tests.protoc_plugin.protos.invocation_testing.split_services',
'services.proto')
messages_proto_contents = pkgutil.get_data(
'tests.protoc_plugin.protos.invocation_testing.split_messages',
'messages.proto')
self.directory = tempfile.mkdtemp(suffix='split_common', dir='.')
self.proto_directory = os.path.join(self.directory, 'proto_path')
self.python_out_directory = os.path.join(self.directory, 'python_out')
self.grpc_python_out_directory = self.python_out_directory
os.makedirs(self.proto_directory)
os.makedirs(self.python_out_directory)
services_proto_file = os.path.join(self.proto_directory,
'split_common_services.proto')
messages_proto_file = os.path.join(self.proto_directory,
'split_common_messages.proto')
open(services_proto_file, 'wb').write(services_proto_contents.replace(
_MESSAGES_IMPORT,
b'import "split_common_messages.proto";'
))
open(messages_proto_file, 'wb').write(messages_proto_contents)
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
'--python_out={}'.format(self.python_out_directory),
'--grpc_python_out={}'.format(self.python_out_directory),
services_proto_file,
messages_proto_file,
])
if protoc_result != 0:
raise Exception("unexpected protoc error")
open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
self.pb2_import = 'split_common_messages_pb2'
self.pb2_grpc_import = 'split_common_services_pb2_grpc'
self.should_find_services_in_pb2 = False
def tearDown(self):
shutil.rmtree(self.directory)
class SplitSeparateTest(unittest.TestCase, SeparateTestMixin):
def setUp(self):
services_proto_contents = pkgutil.get_data(
'tests.protoc_plugin.protos.invocation_testing.split_services',
'services.proto')
messages_proto_contents = pkgutil.get_data(
'tests.protoc_plugin.protos.invocation_testing.split_messages',
'messages.proto')
self.directory = tempfile.mkdtemp(suffix='split_separate', dir='.')
self.proto_directory = os.path.join(self.directory, 'proto_path')
self.python_out_directory = os.path.join(self.directory, 'python_out')
self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out')
os.makedirs(self.proto_directory)
os.makedirs(self.python_out_directory)
os.makedirs(self.grpc_python_out_directory)
services_proto_file = os.path.join(self.proto_directory,
'split_separate_services.proto')
messages_proto_file = os.path.join(self.proto_directory,
'split_separate_messages.proto')
open(services_proto_file, 'wb').write(services_proto_contents.replace(
_MESSAGES_IMPORT,
b'import "split_separate_messages.proto";'
))
open(messages_proto_file, 'wb').write(messages_proto_contents)
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
'--python_out={}'.format(self.python_out_directory),
'--grpc_python_out={}'.format(self.grpc_python_out_directory),
services_proto_file,
messages_proto_file,
])
if protoc_result != 0:
raise Exception("unexpected protoc error")
open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('')
self.pb2_import = 'split_separate_messages_pb2'
self.pb2_grpc_import = 'split_separate_services_pb2_grpc'
self.should_find_services_in_pb2 = False
def tearDown(self):
shutil.rmtree(self.directory)
if __name__ == '__main__':
unittest.main(verbosity=2)

@ -0,0 +1,30 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,39 @@
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package grpc_protoc_plugin.invocation_testing;
message Request {}
message Response {}
service TestService {
rpc Call(Request) returns (Response);
}

@ -0,0 +1,30 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,35 @@
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package grpc_protoc_plugin.invocation_testing.split;
message Request {}
message Response {}

@ -0,0 +1,30 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,38 @@
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
import "messages.proto";
package grpc_protoc_plugin.invocation_testing.split;
service TestService {
rpc Call(Request) returns (Response);
}

@ -1,45 +1,49 @@
[ [
"_api_test.AllTest", "health_check._health_servicer_test.HealthServicerTest",
"_api_test.ChannelConnectivityTest", "interop._insecure_interop_test.InsecureInteropTest",
"_api_test.ChannelTest", "interop._secure_interop_test.SecureInteropTest",
"_auth_test.AccessTokenCallCredentialsTest", "protoc_plugin._python_plugin_test.PythonPluginTest",
"_auth_test.GoogleCallCredentialsTest", "protoc_plugin._split_definitions_test.SameCommonTest",
"_beta_features_test.BetaFeaturesTest", "protoc_plugin._split_definitions_test.SameSeparateTest",
"_beta_features_test.ContextManagementAndLifecycleTest", "protoc_plugin._split_definitions_test.SplitCommonTest",
"_cancel_many_calls_test.CancelManyCallsTest", "protoc_plugin._split_definitions_test.SplitSeparateTest",
"_channel_args_test.ChannelArgsTest", "protoc_plugin.beta_python_plugin_test.PythonPluginTest",
"_channel_connectivity_test.ChannelConnectivityTest", "reflection._reflection_servicer_test.ReflectionServicerTest",
"_channel_ready_future_test.ChannelReadyFutureTest", "unit._api_test.AllTest",
"_channel_test.ChannelTest", "unit._api_test.ChannelConnectivityTest",
"_compression_test.CompressionTest", "unit._api_test.ChannelTest",
"_connectivity_channel_test.ConnectivityStatesTest", "unit._auth_test.AccessTokenCallCredentialsTest",
"_credentials_test.CredentialsTest", "unit._auth_test.GoogleCallCredentialsTest",
"_empty_message_test.EmptyMessageTest", "unit._channel_args_test.ChannelArgsTest",
"_exit_test.ExitTest", "unit._channel_connectivity_test.ChannelConnectivityTest",
"_face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest", "unit._channel_ready_future_test.ChannelReadyFutureTest",
"_face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest", "unit._compression_test.CompressionTest",
"_face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest", "unit._credentials_test.CredentialsTest",
"_face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest", "unit._cython._cancel_many_calls_test.CancelManyCallsTest",
"_face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest", "unit._cython._channel_test.ChannelTest",
"_face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest", "unit._cython._read_some_but_not_all_responses_test.ReadSomeButNotAllResponsesTest",
"_health_servicer_test.HealthServicerTest", "unit._cython.cygrpc_test.InsecureServerInsecureClient",
"_implementations_test.CallCredentialsTest", "unit._cython.cygrpc_test.SecureServerSecureClient",
"_implementations_test.ChannelCredentialsTest", "unit._cython.cygrpc_test.TypeSmokeTest",
"_insecure_interop_test.InsecureInteropTest", "unit._empty_message_test.EmptyMessageTest",
"_logging_pool_test.LoggingPoolTest", "unit._exit_test.ExitTest",
"_metadata_code_details_test.MetadataCodeDetailsTest", "unit._metadata_code_details_test.MetadataCodeDetailsTest",
"_metadata_test.MetadataTest", "unit._metadata_test.MetadataTest",
"_not_found_test.NotFoundTest", "unit._rpc_test.RPCTest",
"_python_plugin_test.PythonPluginTest", "unit._sanity._sanity_test.Sanity",
"_read_some_but_not_all_responses_test.ReadSomeButNotAllResponsesTest", "unit._thread_cleanup_test.CleanupThreadTest",
"_reflection_servicer_test.ReflectionServicerTest", "unit.beta._beta_features_test.BetaFeaturesTest",
"_rpc_test.RPCTest", "unit.beta._beta_features_test.ContextManagementAndLifecycleTest",
"_sanity_test.Sanity", "unit.beta._connectivity_channel_test.ConnectivityStatesTest",
"_secure_interop_test.SecureInteropTest", "unit.beta._face_interface_test.DynamicInvokerBlockingInvocationInlineServiceTest",
"_thread_cleanup_test.CleanupThreadTest", "unit.beta._face_interface_test.DynamicInvokerFutureInvocationAsynchronousEventServiceTest",
"_utilities_test.ChannelConnectivityTest", "unit.beta._face_interface_test.GenericInvokerBlockingInvocationInlineServiceTest",
"beta_python_plugin_test.PythonPluginTest", "unit.beta._face_interface_test.GenericInvokerFutureInvocationAsynchronousEventServiceTest",
"cygrpc_test.InsecureServerInsecureClient", "unit.beta._face_interface_test.MultiCallableInvokerBlockingInvocationInlineServiceTest",
"cygrpc_test.SecureServerSecureClient", "unit.beta._face_interface_test.MultiCallableInvokerFutureInvocationAsynchronousEventServiceTest",
"cygrpc_test.TypeSmokeTest" "unit.beta._implementations_test.CallCredentialsTest",
"unit.beta._implementations_test.ChannelCredentialsTest",
"unit.beta._not_found_test.NotFoundTest",
"unit.beta._utilities_test.ChannelConnectivityTest",
"unit.framework.foundation._logging_pool_test.LoggingPoolTest"
] ]

Loading…
Cancel
Save