Thrift and Python: Made to be together

Summary: Python client code generation for Thrift... HOTNESS!

Notes: Servers and asynchronous clients are coming soon...


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664779 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/Makefile b/compiler/cpp/Makefile
index b857e8c..b20ec3b 100644
--- a/compiler/cpp/Makefile
+++ b/compiler/cpp/Makefile
@@ -35,6 +35,7 @@
 # Source files
 SRC_FILES = main.cc \
             generate/t_generator.cc \
+            generate/t_py_generator.cc \
             generate/t_java_generator.cc \
             generate/t_php_generator.cc \
             generate/t_cpp_generator.cc
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index 74b73b9..5b575b4 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -341,7 +341,7 @@
     php_includes();
 
   f_service_ <<
-    "require_once dirname(__FILE__).'/" << service_name_ << "_types.php';" << endl << endl;
+    "require_once dirname(__FILE__).'/" << program_name_ << "_types.php';" << endl << endl;
 
   // Generate the three main parts of the service (well, two for now in PHP)
   generate_service_interface(tservice);
@@ -1287,7 +1287,7 @@
       result += " = 0";
     } else if (type->is_container()) {
       result += " = array()";
-    } else if (type->is_struct()) {
+    } else if (type->is_struct() || type->is_xception()) {
       if (obj) {
         result += " = new " + type->get_name() + "()";
       } else {
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index 944cd66..f75bd53 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -21,6 +21,7 @@
 #include "generate/t_cpp_generator.h"
 #include "generate/t_java_generator.h"
 #include "generate/t_php_generator.h"
+#include "generate/t_py_generator.h"
 
 using namespace std;
 
@@ -99,8 +100,8 @@
   fprintf(stderr, "  --java   Generate Java output files\n");
   fprintf(stderr, "  --php    Generate PHP output files\n");
   fprintf(stderr, "  --phpi   Generate PHP inlined files\n");
-  //fprintf(stderr, "  -python Generate Python output files\n");
-  fprintf(stderr, "  --debug      Print parse debugging to standard output\n");
+  fprintf(stderr, "  --py     Generate Python output files\n");
+  fprintf(stderr, "  --debug  Print parse debugging to standard output\n");
   exit(1);
 }
 
@@ -111,6 +112,7 @@
   int i;
   bool gen_cpp = false;
   bool gen_java = false;
+  bool gen_py = false;
   bool gen_php = false;
   bool php_inline = false;
 
@@ -136,13 +138,15 @@
     } else if (strcmp(argv[i], "--phpi") == 0) {
       gen_php = true;
       php_inline = true;
+    } else if (strcmp(argv[i], "--py") == 0) {
+      gen_py = true;
     } else {
       fprintf(stderr, "!!! Unrecognized option: %s\n", argv[i]);
       usage();
     }
   }
   
-  if (!gen_cpp && !gen_java && !gen_php) {
+  if (!gen_cpp && !gen_java && !gen_php && !gen_py) {
     fprintf(stderr, "!!! No output language(s) specified\n\n");
     usage();
   }
@@ -191,6 +195,12 @@
       php->generate_program(g_program);
       delete php;
     }
+
+    if (gen_py) {
+      t_py_generator* py = new t_py_generator();
+      py->generate_program(g_program);
+      delete py;
+    }
   } catch (string s) {
     printf("Error: %s\n", s.c_str());
   } catch (const char* exc) {
diff --git a/lib/php/src/protocol/TProtocol.php b/lib/php/src/protocol/TProtocol.php
index d703bd7..855d588 100644
--- a/lib/php/src/protocol/TProtocol.php
+++ b/lib/php/src/protocol/TProtocol.php
@@ -100,14 +100,14 @@
    * @param int $type message type TMessageType::CALL or TMessageType::REPLY
    * @parem int $seqid The sequence id of this message
    */
-  public abstract function readMessageBegin($out, &$name, &$type, &$seqid);
+  public abstract function readMessageBegin($in, &$name, &$type, &$seqid);
 
   /**
    * Read the close of message
    *
    * @param TTransport $out Output transport
    */
-  public abstract function readMessageEnd($out);
+  public abstract function readMessageEnd($in);
 
   public abstract function readStructBegin($in, &$name);
   
diff --git a/lib/py/setup.py b/lib/py/setup.py
index 4beaba7..1d5d023 100644
--- a/lib/py/setup.py
+++ b/lib/py/setup.py
@@ -6,7 +6,7 @@
       author = ['Mark Slee'],
       author_email = ['mcslee@facebook.com'],
       url = 'http://code.facebook.com/thrift',
-      packages = ['thrift', 'thrift.protocol', 'thrift.transport']
+      packages = ['thrift', 'thrift.protocol', 'thrift.transport'],
       package_dir = {'thrift' : 'src'},
       )
 
diff --git a/test/py/Makefile b/test/py/Makefile
new file mode 100644
index 0000000..05943dd
--- /dev/null
+++ b/test/py/Makefile
@@ -0,0 +1,18 @@
+# Makefile for Thrift test project.
+# 
+# Author:
+#   Mark Slee <mcslee@facebook.com>
+
+# Default target is everything
+target: all
+
+# Tools
+THRIFT = thrift
+
+all: stubs
+
+stubs: ../ThriftTest.thrift
+	$(THRIFT) --py ../ThriftTest.thrift
+
+clean:
+	rm -fr gen-py
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
new file mode 100755
index 0000000..a64b8d7
--- /dev/null
+++ b/test/py/TestClient.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+import sys
+sys.path.append('./gen-py')
+
+import ThriftTest
+from ThriftTest_types import *
+from thrift.transport import TSocket
+from thrift.protocol import TBinaryProtocol
+
+transport = TSocket.TSocket('localhost', 9090)
+protocol = TBinaryProtocol.TBinaryProtocol()
+client = ThriftTest.Client(transport, protocol)
+
+transport.open()
+
+print "testVoid()"
+print client.testVoid()
+
+print "testString('PythonTest')"
+print client.testString('PythonTest')
+
+print "testByte(63)"
+print client.testByte(63)
+
+print "testException('Safe')"
+print client.testException('Safe')
+
+print "textException('Xception')"
+try:
+  print client.testException('Xception')
+except Xception, x:
+  print 'Xception (%d, %s)' % (x.errorCode, x.message)
+
+transport.close()