Fix bugs in Python code generator

Fixes module path finding in the Python code generator and the signatures
of generated servicer methods.
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc
index a93b08c..6aafc86 100644
--- a/src/compiler/python_generator.cc
+++ b/src/compiler/python_generator.cc
@@ -31,6 +31,7 @@
  *
  */
 
+#include <algorithm>
 #include <cassert>
 #include <cctype>
 #include <cstring>
@@ -44,17 +45,22 @@
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
 
 using google::protobuf::Descriptor;
 using google::protobuf::FileDescriptor;
-using google::protobuf::ServiceDescriptor;
+using google::protobuf::HasSuffixString;
 using google::protobuf::MethodDescriptor;
+using google::protobuf::ServiceDescriptor;
+using google::protobuf::StripString;
+using google::protobuf::StripSuffixString;
 using google::protobuf::io::Printer;
 using google::protobuf::io::StringOutputStream;
 using std::initializer_list;
 using std::make_pair;
 using std::map;
 using std::pair;
+using std::replace;
 using std::string;
 using std::strlen;
 using std::vector;
@@ -123,7 +129,7 @@
       string arg_name = meth->client_streaming() ?
           "request_iterator" : "request";
       out->Print("@abc.abstractmethod\n");
-      out->Print("def $Method$(self, $ArgName$):\n",
+      out->Print("def $Method$(self, $ArgName$, context):\n",
                  "Method", meth->name(), "ArgName", arg_name);
       {
         IndentScope raii_method_indent(out);
@@ -191,6 +197,21 @@
   return true;
 }
 
+// TODO(protobuf team): See TODO for `ModuleName`.
+string StripProto(const string& filename) {
+  const char* suffix = HasSuffixString(filename, ".protodevel")
+      ? ".protodevel" : ".proto";
+  return StripSuffixString(filename, suffix);
+}
+// TODO(protobuf team): Export `ModuleName` from protobuf's
+// `src/google/protobuf/compiler/python/python_generator.cc` file.
+string ModuleName(const string& filename) {
+  string basename = StripProto(filename);
+  StripString(&basename, "-", '_');
+  StripString(&basename, "/", '.');
+  return basename + "_pb2";
+}
+
 bool GetModuleAndMessagePath(const Descriptor* type,
                              pair<string, string>* out) {
   const Descriptor* path_elem_type = type;
@@ -200,17 +221,12 @@
     path_elem_type = path_elem_type->containing_type();
   } while (path_elem_type != nullptr);
   string file_name = type->file()->name();
-  string module_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;
   }
-  module_name = file_name.substr(
-      0, file_name.size() - proto_suffix_length) + "_pb2";
-  string package = type->file()->package();
-  string module = (package.empty() ? "" : package + ".") +
-      module_name;
+  string module = ModuleName(file_name);
   string message_type;
   for (auto path_iter = message_path.rbegin();
        path_iter != message_path.rend(); ++path_iter) {