Merge pull request #1101 from soltanmm/sanitize

Sanitize Python protoc plugin
pull/1109/head
Nicolas Noble 10 years ago
commit f280409f9c
  1. 119
      src/compiler/python_generator.cc
  2. 26
      src/compiler/python_generator.h
  3. 6
      src/compiler/python_plugin.cc

@ -39,30 +39,25 @@
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>
#include "grpc++/config.h"
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
#include "src/compiler/python_generator.h"
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
using grpc_generator::StringReplace;
using grpc_generator::StripProto;
using google::protobuf::Descriptor;
using google::protobuf::FileDescriptor;
using google::protobuf::MethodDescriptor;
using google::protobuf::ServiceDescriptor;
using google::protobuf::compiler::GeneratorContext;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::io::Printer;
using google::protobuf::io::StringOutputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::compiler::GeneratorContext;
using grpc::protobuf::io::CodedOutputStream;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using grpc::protobuf::io::ZeroCopyOutputStream;
using std::initializer_list;
using std::make_pair;
using std::map;
@ -78,10 +73,10 @@ PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
PythonGrpcGenerator::~PythonGrpcGenerator() {}
bool PythonGrpcGenerator::Generate(
const FileDescriptor* file, const std::string& parameter,
GeneratorContext* context, std::string* error) const {
const FileDescriptor* file, const grpc::string& parameter,
GeneratorContext* context, grpc::string* error) const {
// Get output file name.
std::string 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) {
@ -96,7 +91,7 @@ bool PythonGrpcGenerator::Generate(
context->OpenForInsert(file_name, "module_scope"));
CodedOutputStream coded_out(output.get());
bool success = false;
std::string code = "";
grpc::string code = "";
tie(success, code) = grpc_python_generator::GetServices(file, config_);
if (success) {
coded_out.WriteRaw(code.data(), code.size());
@ -113,15 +108,15 @@ namespace {
// 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<std::string, std::string> ListToDict(
const initializer_list<std::string>& values) {
map<grpc::string, grpc::string> ListToDict(
const initializer_list<grpc::string>& values) {
assert(values.size() % 2 == 0);
map<std::string, std::string> value_map;
map<grpc::string, grpc::string> value_map;
auto value_iter = values.begin();
for (unsigned i = 0; i < values.size()/2; ++i) {
std::string key = *value_iter;
grpc::string key = *value_iter;
++value_iter;
std::string value = *value_iter;
grpc::string value = *value_iter;
value_map[key] = value;
++value_iter;
}
@ -155,8 +150,8 @@ class IndentScope {
bool PrintServicer(const ServiceDescriptor* service,
Printer* out) {
std::string doc = "<fill me in later!>";
map<std::string, std::string> dict = ListToDict({
grpc::string doc = "<fill me in later!>";
map<grpc::string, grpc::string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
@ -167,7 +162,7 @@ bool PrintServicer(const ServiceDescriptor* service,
out->Print("__metaclass__ = abc.ABCMeta\n");
for (int i = 0; i < service->method_count(); ++i) {
auto meth = service->method(i);
std::string arg_name = meth->client_streaming() ?
grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request";
out->Print("@abc.abstractmethod\n");
out->Print("def $Method$(self, $ArgName$, context):\n",
@ -182,8 +177,8 @@ bool PrintServicer(const ServiceDescriptor* service,
}
bool PrintServer(const ServiceDescriptor* service, Printer* out) {
std::string doc = "<fill me in later!>";
map<std::string, std::string> dict = ListToDict({
grpc::string doc = "<fill me in later!>";
map<grpc::string, grpc::string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
@ -211,8 +206,8 @@ bool PrintServer(const ServiceDescriptor* service, Printer* out) {
bool PrintStub(const ServiceDescriptor* service,
Printer* out) {
std::string doc = "<fill me in later!>";
map<std::string, std::string> dict = ListToDict({
grpc::string doc = "<fill me in later!>";
map<grpc::string, grpc::string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
@ -223,7 +218,7 @@ bool PrintStub(const ServiceDescriptor* service,
out->Print("__metaclass__ = abc.ABCMeta\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
std::string arg_name = meth->client_streaming() ?
grpc::string arg_name = meth->client_streaming() ?
"request_iterator" : "request";
auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
out->Print("@abc.abstractmethod\n");
@ -240,29 +235,29 @@ bool PrintStub(const ServiceDescriptor* service,
// TODO(protobuf team): Export `ModuleName` from protobuf's
// `src/google/protobuf/compiler/python/python_generator.cc` file.
std::string ModuleName(const std::string& filename) {
std::string basename = StripProto(filename);
grpc::string ModuleName(const grpc::string& filename) {
grpc::string basename = StripProto(filename);
basename = StringReplace(basename, "-", "_");
basename = StringReplace(basename, "/", ".");
return basename + "_pb2";
}
bool GetModuleAndMessagePath(const Descriptor* type,
pair<std::string, std::string>* out) {
pair<grpc::string, grpc::string>* out) {
const Descriptor* path_elem_type = type;
vector<const Descriptor*> message_path;
do {
message_path.push_back(path_elem_type);
path_elem_type = path_elem_type->containing_type();
} while (path_elem_type != nullptr);
std::string file_name = type->file()->name();
grpc::string file_name = type->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)) {
return false;
}
std::string module = ModuleName(file_name);
std::string message_type;
grpc::string module = ModuleName(file_name);
grpc::string message_type;
for (auto path_iter = message_path.rbegin();
path_iter != message_path.rend(); ++path_iter) {
message_type += (*path_iter)->name() + ".";
@ -273,30 +268,30 @@ bool GetModuleAndMessagePath(const Descriptor* type,
return true;
}
bool PrintServerFactory(const std::string& package_qualified_service_name,
bool PrintServerFactory(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
out->Print("def early_adopter_create_$Service$_server(servicer, port, "
"root_certificates, key_chain_pairs):\n",
"Service", service->name());
{
IndentScope raii_create_server_indent(out);
map<std::string, std::string> method_description_constructors;
map<std::string, pair<std::string, std::string>>
map<grpc::string, grpc::string> method_description_constructors;
map<grpc::string, pair<grpc::string, grpc::string>>
input_message_modules_and_classes;
map<std::string, pair<std::string, std::string>>
map<grpc::string, pair<grpc::string, grpc::string>>
output_message_modules_and_classes;
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
const std::string method_description_constructor =
std::string(method->client_streaming() ? "stream_" : "unary_") +
std::string(method->server_streaming() ? "stream_" : "unary_") +
const grpc::string method_description_constructor =
grpc::string(method->client_streaming() ? "stream_" : "unary_") +
grpc::string(method->server_streaming() ? "stream_" : "unary_") +
"service_description";
pair<std::string, std::string> input_message_module_and_class;
pair<grpc::string, grpc::string> input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(),
&input_message_module_and_class)) {
return false;
}
pair<std::string, std::string> output_message_module_and_class;
pair<grpc::string, grpc::string> output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(),
&output_message_module_and_class)) {
return false;
@ -317,7 +312,7 @@ bool PrintServerFactory(const std::string& package_qualified_service_name,
for (auto& name_and_description_constructor :
method_description_constructors) {
IndentScope raii_descriptions_indent(out);
const std::string method_name = name_and_description_constructor.first;
const grpc::string method_name = name_and_description_constructor.first;
auto input_message_module_and_class =
input_message_modules_and_classes.find(method_name);
auto output_message_module_and_class =
@ -350,31 +345,31 @@ bool PrintServerFactory(const std::string& package_qualified_service_name,
return true;
}
bool PrintStubFactory(const std::string& package_qualified_service_name,
bool PrintStubFactory(const grpc::string& package_qualified_service_name,
const ServiceDescriptor* service, Printer* out) {
map<std::string, std::string> dict = ListToDict({
map<grpc::string, grpc::string> dict = ListToDict({
"Service", service->name(),
});
out->Print(dict, "def early_adopter_create_$Service$_stub(host, port):\n");
{
IndentScope raii_create_server_indent(out);
map<std::string, std::string> method_description_constructors;
map<std::string, pair<std::string, std::string>>
map<grpc::string, grpc::string> method_description_constructors;
map<grpc::string, pair<grpc::string, grpc::string>>
input_message_modules_and_classes;
map<std::string, pair<std::string, std::string>>
map<grpc::string, pair<grpc::string, grpc::string>>
output_message_modules_and_classes;
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
const std::string method_description_constructor =
std::string(method->client_streaming() ? "stream_" : "unary_") +
std::string(method->server_streaming() ? "stream_" : "unary_") +
const grpc::string method_description_constructor =
grpc::string(method->client_streaming() ? "stream_" : "unary_") +
grpc::string(method->server_streaming() ? "stream_" : "unary_") +
"invocation_description";
pair<std::string, std::string> input_message_module_and_class;
pair<grpc::string, grpc::string> input_message_module_and_class;
if (!GetModuleAndMessagePath(method->input_type(),
&input_message_module_and_class)) {
return false;
}
pair<std::string, std::string> output_message_module_and_class;
pair<grpc::string, grpc::string> output_message_module_and_class;
if (!GetModuleAndMessagePath(method->output_type(),
&output_message_module_and_class)) {
return false;
@ -395,7 +390,7 @@ bool PrintStubFactory(const std::string& package_qualified_service_name,
for (auto& name_and_description_constructor :
method_description_constructors) {
IndentScope raii_descriptions_indent(out);
const std::string method_name = name_and_description_constructor.first;
const grpc::string method_name = name_and_description_constructor.first;
auto input_message_module_and_class =
input_message_modules_and_classes.find(method_name);
auto output_message_module_and_class =
@ -437,9 +432,9 @@ bool PrintPreamble(const FileDescriptor* file,
} // namespace
pair<bool, std::string> GetServices(const FileDescriptor* file,
pair<bool, grpc::string> GetServices(const FileDescriptor* file,
const GeneratorConfiguration& config) {
std::string output;
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
StringOutputStream output_stream(&output);

@ -34,41 +34,33 @@
#ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
#include <string>
#include <utility>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
class FileDescriptor;
} // namespace protobuf
} // namespace google
#include "src/compiler/config.h"
namespace grpc_python_generator {
// Data pertaining to configuration of the generator with respect to anything
// that may be used internally at Google.
struct GeneratorConfiguration {
std::string implementations_package_root;
grpc::string implementations_package_root;
};
class PythonGrpcGenerator : public google::protobuf::compiler::CodeGenerator {
class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
public:
PythonGrpcGenerator(const GeneratorConfiguration& config);
~PythonGrpcGenerator();
bool Generate(const google::protobuf::FileDescriptor* file,
const std::string& parameter,
google::protobuf::compiler::GeneratorContext* context,
std::string* error) const;
bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const;
private:
GeneratorConfiguration config_;
};
std::pair<bool, std::string> GetServices(
const google::protobuf::FileDescriptor* file,
std::pair<bool, grpc::string> GetServices(
const grpc::protobuf::FileDescriptor* file,
const GeneratorConfiguration& config);
} // namespace grpc_python_generator

@ -33,14 +33,12 @@
// Generates a Python gRPC service interface out of Protobuf IDL.
#include "src/compiler/config.h"
#include "src/compiler/python_generator.h"
#include <google/protobuf/compiler/plugin.h>
using google::protobuf::compiler::PluginMain;
int main(int argc, char* argv[]) {
grpc_python_generator::GeneratorConfiguration config;
config.implementations_package_root = "grpc.early_adopter";
grpc_python_generator::PythonGrpcGenerator generator(config);
return PluginMain(argc, argv, &generator);
return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}

Loading…
Cancel
Save