diff --git a/Makefile b/Makefile
index 91c94c8071e250badbc974bdd09bf1563e2fbba6..e1dedb591290bea43ea0ae02ed55f651ed01c420 100644
--- a/Makefile
+++ b/Makefile
@@ -332,7 +332,7 @@ endif
 
 .SECONDARY = %.pb.h %.pb.cc
 
-PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
+PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin
 ifeq ($(DEP_MISSING),)
 all: static shared plugins
 dep_error:
@@ -499,6 +499,8 @@ transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test
 async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
 channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
 grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
+grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
+grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
 credentials_test: $(BINDIR)/$(CONFIG)/credentials_test
 end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
 interop_client: $(BINDIR)/$(CONFIG)/interop_client
@@ -508,7 +510,6 @@ pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test
 pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test
 qps_client: $(BINDIR)/$(CONFIG)/qps_client
 qps_server: $(BINDIR)/$(CONFIG)/qps_server
-grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
 status_test: $(BINDIR)/$(CONFIG)/status_test
 thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test
 chttp2_fake_security_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test
@@ -2047,6 +2048,7 @@ else
 	$(E) "[INSTALL] Installing grpc protoc plugins"
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin
 	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin
+	$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin
 endif
 
 clean:
@@ -7413,6 +7415,70 @@ ifneq ($(NO_DEPS),true)
 endif
 
 
+GRPC_RUBY_PLUGIN_SRC = \
+    src/compiler/ruby_generator.cc \
+    src/compiler/ruby_plugin.cc \
+
+GRPC_RUBY_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_RUBY_PLUGIN_SRC))))
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/grpc_ruby_plugin: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpc_ruby_plugin: $(PROTOBUF_DEP) $(GRPC_RUBY_PLUGIN_OBJS)
+	$(E) "[HOSTLD]  Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_RUBY_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/compiler/ruby_generator.o: 
+$(OBJDIR)/$(CONFIG)/src/compiler/ruby_plugin.o: 
+
+deps_grpc_ruby_plugin: $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep)
+endif
+
+
+GRPC_PYTHON_PLUGIN_SRC = \
+    src/compiler/python_generator.cc \
+    src/compiler/python_plugin.cc \
+
+GRPC_PYTHON_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_PYTHON_PLUGIN_SRC))))
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/grpc_python_plugin: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpc_python_plugin: $(PROTOBUF_DEP) $(GRPC_PYTHON_PLUGIN_OBJS)
+	$(E) "[HOSTLD]  Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_PYTHON_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_python_plugin
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/compiler/python_generator.o: 
+$(OBJDIR)/$(CONFIG)/src/compiler/python_plugin.o: 
+
+deps_grpc_python_plugin: $(GRPC_PYTHON_PLUGIN_OBJS:.o=.dep)
+
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_PYTHON_PLUGIN_OBJS:.o=.dep)
+endif
+
+
 CREDENTIALS_TEST_SRC = \
     test/cpp/client/credentials_test.cc \
 
@@ -7708,38 +7774,6 @@ endif
 endif
 
 
-GRPC_RUBY_PLUGIN_SRC = \
-    src/compiler/ruby_generator.cc \
-    src/compiler/ruby_plugin.cc \
-
-GRPC_RUBY_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_RUBY_PLUGIN_SRC))))
-
-
-ifeq ($(NO_PROTOBUF),true)
-
-# You can't build the protoc plugins if you don't have protobuf 3.0.0+.
-
-$(BINDIR)/$(CONFIG)/grpc_ruby_plugin: protobuf_dep_error
-
-else
-
-$(BINDIR)/$(CONFIG)/grpc_ruby_plugin: $(PROTOBUF_DEP) $(GRPC_RUBY_PLUGIN_OBJS)
-	$(E) "[HOSTLD]  Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_RUBY_PLUGIN_OBJS) $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
-
-endif
-
-$(OBJDIR)/$(CONFIG)/src/compiler/ruby_generator.o: 
-$(OBJDIR)/$(CONFIG)/src/compiler/ruby_plugin.o: 
-
-deps_grpc_ruby_plugin: $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep)
-
-ifneq ($(NO_DEPS),true)
--include $(GRPC_RUBY_PLUGIN_OBJS:.o=.dep)
-endif
-
-
 STATUS_TEST_SRC = \
     test/cpp/util/status_test.cc \
 
diff --git a/build.json b/build.json
index 0f9e827422cbd35978f7b94884f46012073459a8..8fdca5a25507e4db560d6130ea08b5df4bd06a8d 100644
--- a/build.json
+++ b/build.json
@@ -1591,6 +1591,31 @@
       "deps": [],
       "secure": false
     },
+    {
+      "name": "grpc_ruby_plugin",
+      "build": "protoc",
+      "language": "c++",
+      "src": [
+        "src/compiler/ruby_generator.cc",
+        "src/compiler/ruby_plugin.cc"
+      ],
+      "deps": [],
+      "secure": false
+    },
+    {
+      "name": "grpc_python_plugin",
+      "build": "protoc",
+      "language": "c++",
+      "headers": [
+        "src/compiler/python_generator.h"
+      ],
+      "src": [
+        "src/compiler/python_generator.cc",
+        "src/compiler/python_plugin.cc"
+      ],
+      "deps": [],
+      "secure": false
+    },
     {
       "name": "credentials_test",
       "build": "test",
@@ -1748,17 +1773,6 @@
         "gpr"
       ]
     },
-    {
-      "name": "grpc_ruby_plugin",
-      "build": "protoc",
-      "language": "c++",
-      "src": [
-        "src/compiler/ruby_generator.cc",
-        "src/compiler/ruby_plugin.cc"
-      ],
-      "deps": [],
-      "secure": false
-    },
     {
       "name": "status_test",
       "build": "test",
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..48d90624d622bfe8b8f9e109aa4ce99c7b8e2025
--- /dev/null
+++ b/src/compiler/python_generator.cc
@@ -0,0 +1,332 @@
+/*
+ *
+ * Copyright 2015, 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.
+ *
+ */
+
+#include <cassert>
+#include <cctype>
+#include <map>
+#include <ostream>
+#include <sstream>
+
+#include "src/compiler/python_generator.h"
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+
+using google::protobuf::FileDescriptor;
+using google::protobuf::ServiceDescriptor;
+using google::protobuf::MethodDescriptor;
+using google::protobuf::io::Printer;
+using google::protobuf::io::StringOutputStream;
+using std::initializer_list;
+using std::map;
+using std::string;
+
+namespace grpc_python_generator {
+namespace {
+//////////////////////////////////
+// BEGIN FORMATTING BOILERPLATE //
+//////////////////////////////////
+
+// 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<string, string> ListToDict(const initializer_list<string>& values) {
+  assert(values.size() % 2 == 0);
+  map<string, string> value_map;
+  auto value_iter = values.begin();
+  for (unsigned i = 0; i < values.size()/2; ++i) {
+    string key = *value_iter;
+    ++value_iter;
+    string value = *value_iter;
+    value_map[key] = value;
+    ++value_iter;
+  }
+  return value_map;
+}
+
+// Provides RAII indentation handling. Use as:
+// {
+//   IndentScope raii_my_indent_var_name_here(my_py_printer);
+//   // constructor indented my_py_printer
+//   ...
+//   // destructor called at end of scope, un-indenting my_py_printer
+// }
+class IndentScope {
+ public:
+  explicit IndentScope(Printer* printer) : printer_(printer) {
+    printer_->Indent();
+  }
+
+  ~IndentScope() {
+    printer_->Outdent();
+  }
+
+ private:
+  Printer* printer_;
+};
+
+////////////////////////////////
+// END FORMATTING BOILERPLATE //
+////////////////////////////////
+
+void PrintService(const ServiceDescriptor* service,
+                  Printer* out) {
+  string doc = "<fill me in later!>";
+  map<string, string> dict = ListToDict({
+        "Service", service->name(),
+        "Documentation", doc,
+      });
+  out->Print(dict, "class $Service$Service(object):\n");
+  {
+    IndentScope raii_class_indent(out);
+    out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
+    out->Print("def __init__(self):\n");
+    {
+      IndentScope raii_method_indent(out);
+      out->Print("pass\n");
+    }
+  }
+}
+
+void PrintServicer(const ServiceDescriptor* service,
+                   Printer* out) {
+  string doc = "<fill me in later!>";
+  map<string, string> dict = ListToDict({
+        "Service", service->name(),
+        "Documentation", doc,
+      });
+  out->Print(dict, "class $Service$Servicer(object):\n");
+  {
+    IndentScope raii_class_indent(out);
+    out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
+    for (int i = 0; i < service->method_count(); ++i) {
+      auto meth = service->method(i);
+      out->Print("def $Method$(self, arg):\n", "Method", meth->name());
+      {
+        IndentScope raii_method_indent(out);
+        out->Print("raise NotImplementedError()\n");
+      }
+    }
+  }
+}
+
+void PrintStub(const ServiceDescriptor* service,
+               Printer* out) {
+  string doc = "<fill me in later!>";
+  map<string, string> dict = ListToDict({
+        "Service", service->name(),
+        "Documentation", doc,
+      });
+  out->Print(dict, "class $Service$Stub(object):\n");
+  {
+    IndentScope raii_class_indent(out);
+    out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
+    for (int i = 0; i < service->method_count(); ++i) {
+      const MethodDescriptor* meth = service->method(i);
+      auto methdict = ListToDict({"Method", meth->name()});
+      out->Print(methdict, "def $Method$(self, arg):\n");
+      {
+        IndentScope raii_method_indent(out);
+        out->Print("raise NotImplementedError()\n");
+      }
+      out->Print(methdict, "$Method$.async = None\n");
+    }
+  }
+}
+
+void PrintStubImpl(const ServiceDescriptor* service,
+                   Printer* out) {
+  map<string, string> dict = ListToDict({
+        "Service", service->name(),
+      });
+  out->Print(dict, "class _$Service$Stub($Service$Stub):\n");
+  {
+    IndentScope raii_class_indent(out);
+    out->Print("def __init__(self, face_stub, default_timeout):\n");
+    {
+      IndentScope raii_method_indent(out);
+      out->Print("self._face_stub = face_stub\n"
+                 "self._default_timeout = default_timeout\n"
+                 "stub_self = self\n");
+
+      for (int i = 0; i < service->method_count(); ++i) {
+        const MethodDescriptor* meth = service->method(i);
+        bool server_streaming = meth->server_streaming();
+        bool client_streaming = meth->client_streaming();
+        std::string blocking_call, future_call;
+        if (server_streaming) {
+          if (client_streaming) {
+            blocking_call = "stub_self._face_stub.inline_stream_in_stream_out";
+            future_call = blocking_call;
+          } else {
+            blocking_call = "stub_self._face_stub.inline_value_in_stream_out";
+            future_call = blocking_call;
+          }
+        } else {
+          if (client_streaming) {
+            blocking_call = "stub_self._face_stub.blocking_stream_in_value_out";
+            future_call = "stub_self._face_stub.future_stream_in_value_out";
+          } else {
+            blocking_call = "stub_self._face_stub.blocking_value_in_value_out";
+            future_call = "stub_self._face_stub.future_value_in_value_out";
+          }
+        }
+        // TODO(atash): use the solution described at
+        // http://stackoverflow.com/a/2982 to bind 'async' attribute
+        // functions to def'd functions instead of using callable attributes.
+        auto methdict = ListToDict({
+          "Method", meth->name(),
+          "BlockingCall", blocking_call,
+          "FutureCall", future_call
+        });
+        out->Print(methdict, "class $Method$(object):\n");
+        {
+          IndentScope raii_callable_indent(out);
+          out->Print("def __call__(self, arg):\n");
+          {
+            IndentScope raii_callable_call_indent(out);
+            out->Print(methdict,
+                       "return $BlockingCall$(\"$Method$\", arg, "
+                       "stub_self._default_timeout)\n");
+          }
+          out->Print("def async(self, arg):\n");
+          {
+            IndentScope raii_callable_async_indent(out);
+            out->Print(methdict,
+                       "return $FutureCall$(\"$Method$\", arg, "
+                       "stub_self._default_timeout)\n");
+          }
+        }
+        out->Print(methdict, "self.$Method$ = $Method$()\n");
+      }
+    }
+  }
+}
+
+void PrintStubGenerators(const ServiceDescriptor* service, Printer* out) {
+  map<string, string> dict = ListToDict({
+        "Service", service->name(),
+      });
+  // Write out a generator of linked pairs of Server/Stub
+  out->Print(dict, "def mock_$Service$(servicer, default_timeout):\n");
+  {
+    IndentScope raii_mock_indent(out);
+    out->Print("value_in_value_out = {}\n"
+               "value_in_stream_out = {}\n"
+               "stream_in_value_out = {}\n"
+               "stream_in_stream_out = {}\n");
+    for (int i = 0; i < service->method_count(); ++i) {
+      const MethodDescriptor* meth = service->method(i);
+      std::string super_interface, meth_dict;
+      bool server_streaming = meth->server_streaming();
+      bool client_streaming = meth->client_streaming();
+      if (server_streaming) {
+        if (client_streaming) {
+          super_interface = "InlineStreamInStreamOutMethod";
+          meth_dict = "stream_in_stream_out";
+        } else {
+          super_interface = "InlineValueInStreamOutMethod";
+          meth_dict = "value_in_stream_out";
+        }
+      } else {
+        if (client_streaming) {
+          super_interface = "InlineStreamInValueOutMethod";
+          meth_dict = "stream_in_value_out";
+        } else {
+          super_interface = "InlineValueInValueOutMethod";
+          meth_dict = "value_in_value_out";
+        }
+      }
+      map<string, string> methdict = ListToDict({
+            "Method", meth->name(),
+            "SuperInterface", super_interface,
+            "MethodDict", meth_dict
+          });
+      out->Print(
+          methdict, "class $Method$(_face_interfaces.$SuperInterface$):\n");
+      {
+        IndentScope raii_inline_class_indent(out);
+        out->Print("def service(self, request, context):\n");
+        {
+          IndentScope raii_inline_class_fn_indent(out);
+          out->Print(methdict, "return servicer.$Method$(request)\n");
+        }
+      }
+      out->Print(methdict, "$MethodDict$['$Method$'] = $Method$()\n");
+    }
+    out->Print(
+         "face_linked_pair = _face_testing.server_and_stub(default_timeout,"
+         "inline_value_in_value_out_methods=value_in_value_out,"
+         "inline_value_in_stream_out_methods=value_in_stream_out,"
+         "inline_stream_in_value_out_methods=stream_in_value_out,"
+         "inline_stream_in_stream_out_methods=stream_in_stream_out)\n");
+    out->Print("class LinkedPair(object):\n");
+    {
+      IndentScope raii_linked_pair(out);
+      out->Print("def __init__(self, server, stub):\n");
+      {
+        IndentScope raii_linked_pair_init(out);
+        out->Print("self.server = server\n"
+                   "self.stub = stub\n");
+      }
+    }
+    out->Print(
+        dict,
+        "stub = _$Service$Stub(face_linked_pair.stub, default_timeout)\n");
+    out->Print("return LinkedPair(None, stub)\n");
+  }
+}
+
+}  // namespace
+
+string GetServices(const FileDescriptor* file) {
+  string output;
+  StringOutputStream output_stream(&output);
+  Printer out(&output_stream, '$');
+  out.Print("import abc\n");
+  out.Print("import google3\n");
+  out.Print("from grpc.framework.face import demonstration as _face_testing\n");
+  out.Print("from grpc.framework.face import interfaces as _face_interfaces\n");
+
+  for (int i = 0; i < file->service_count(); ++i) {
+    auto service = file->service(i);
+    PrintService(service, &out);
+    PrintServicer(service, &out);
+    PrintStub(service, &out);
+    PrintStubImpl(service, &out);
+    PrintStubGenerators(service, &out);
+  }
+  return output;
+}
+
+}  // namespace grpc_python_generator
diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h
new file mode 100644
index 0000000000000000000000000000000000000000..673ef7b23b30730b1365038e11b8f08334031fe5
--- /dev/null
+++ b/src/compiler/python_generator.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2015, 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.
+ *
+ */
+
+#ifndef __GRPC_COMPILER_PYTHON_GENERATOR_H__
+#define __GRPC_COMPILER_PYTHON_GENERATOR_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor;
+}  // namespace protobuf
+}  // namespace google
+
+namespace grpc_python_generator {
+
+std::string GetServices(const google::protobuf::FileDescriptor* file);
+
+}  // namespace grpc_python_generator
+
+#endif  // __GRPC_COMPILER_PYTHON_GENERATOR_H__
diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ebe3660619b42b546e3ca7d81d39805f65f3922e
--- /dev/null
+++ b/src/compiler/python_plugin.cc
@@ -0,0 +1,87 @@
+/*
+ *
+ * Copyright 2015, 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.
+ *
+ */
+
+// Generates a Python gRPC service interface out of Protobuf IDL.
+
+#include <memory>
+#include <string>
+
+#include "src/compiler/python_generator.h"
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.h>
+
+using google::protobuf::FileDescriptor;
+using google::protobuf::compiler::CodeGenerator;
+using google::protobuf::compiler::GeneratorContext;
+using google::protobuf::compiler::PluginMain;
+using google::protobuf::io::CodedOutputStream;
+using google::protobuf::io::ZeroCopyOutputStream;
+using std::string;
+
+class PythonGrpcGenerator : public CodeGenerator {
+ public:
+  PythonGrpcGenerator() {}
+  ~PythonGrpcGenerator() override {}
+
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* context,
+                string* error) const override {
+    // Get output file name.
+    string file_name;
+    static const int proto_suffix_length = 6;  // length of ".proto"
+    if (file->name().size() > 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());
+    string code = grpc_python_generator::GetServices(file);
+    coded_out.WriteRaw(code.data(), code.size());
+    return true;
+  }
+};
+
+int main(int argc, char* argv[]) {
+  PythonGrpcGenerator generator;
+  return PluginMain(argc, argv, &generator);
+}
diff --git a/vsprojects/vs2013/gpr.vcxproj b/vsprojects/vs2013/gpr.vcxproj
index f6516b8953751adb02e76386fc4685451c45b8db..3d970079a423fa41147e4822ae2263221e4fe9c8 100644
--- a/vsprojects/vs2013/gpr.vcxproj
+++ b/vsprojects/vs2013/gpr.vcxproj
@@ -101,7 +101,6 @@
     <ClInclude Include="..\..\include\grpc\support\useful.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\src\core\support\cpu.h" />
     <ClInclude Include="..\..\src\core\support\env.h" />
     <ClInclude Include="..\..\src\core\support\file.h" />
     <ClInclude Include="..\..\src\core\support\murmur_hash.h" />
diff --git a/vsprojects/vs2013/gpr.vcxproj.filters b/vsprojects/vs2013/gpr.vcxproj.filters
index 1e908a5ba51fbdb384f45bfcdb2832c2f37d7e30..9b78c3a390a2c4d8447baeb6a83fa4332d970279 100644
--- a/vsprojects/vs2013/gpr.vcxproj.filters
+++ b/vsprojects/vs2013/gpr.vcxproj.filters
@@ -167,9 +167,6 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\src\core\support\cpu.h">
-      <Filter>src\core\support</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\src\core\support\env.h">
       <Filter>src\core\support</Filter>
     </ClInclude>
diff --git a/vsprojects/vs2013/gpr_shared.vcxproj b/vsprojects/vs2013/gpr_shared.vcxproj
index b9131e381c12ae7407e840b2eca7b2606d41f23f..892490e3248197edeb1b10f55b41facdd99c84f5 100644
--- a/vsprojects/vs2013/gpr_shared.vcxproj
+++ b/vsprojects/vs2013/gpr_shared.vcxproj
@@ -101,7 +101,6 @@
     <ClInclude Include="..\..\include\grpc\support\useful.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\src\core\support\cpu.h" />
     <ClInclude Include="..\..\src\core\support\env.h" />
     <ClInclude Include="..\..\src\core\support\file.h" />
     <ClInclude Include="..\..\src\core\support\murmur_hash.h" />
diff --git a/vsprojects/vs2013/gpr_shared.vcxproj.filters b/vsprojects/vs2013/gpr_shared.vcxproj.filters
index 1e908a5ba51fbdb384f45bfcdb2832c2f37d7e30..9b78c3a390a2c4d8447baeb6a83fa4332d970279 100644
--- a/vsprojects/vs2013/gpr_shared.vcxproj.filters
+++ b/vsprojects/vs2013/gpr_shared.vcxproj.filters
@@ -167,9 +167,6 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\src\core\support\cpu.h">
-      <Filter>src\core\support</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\src\core\support\env.h">
       <Filter>src\core\support</Filter>
     </ClInclude>