THRIFT-1857 Python 3 Support
Client: Python
Patch: Nobuaki Sukegawa

Add py3 cross test
diff --git a/test/py/TestClient.py b/test/py/TestClient.py
index 4689d63..5b858ef 100755
--- a/test/py/TestClient.py
+++ b/test/py/TestClient.py
@@ -26,47 +26,9 @@
 import unittest
 from optparse import OptionParser
 
-parser = OptionParser()
-parser.add_option('--genpydir', type='string', dest='genpydir',
-                  default='gen-py',
-                  help='include this local directory in sys.path for locating generated code')
-parser.add_option("--port", type="int", dest="port",
-    help="connect to server at port")
-parser.add_option("--host", type="string", dest="host",
-    help="connect to server")
-parser.add_option("--zlib", action="store_true", dest="zlib",
-    help="use zlib wrapper for compressed transport")
-parser.add_option("--ssl", action="store_true", dest="ssl",
-    help="use SSL for encrypted transport")
-parser.add_option("--http", dest="http_path",
-    help="Use the HTTP transport with the specified path")
-parser.add_option('-v', '--verbose', action="store_const",
-    dest="verbose", const=2,
-    help="verbose output")
-parser.add_option('-q', '--quiet', action="store_const",
-    dest="verbose", const=0,
-    help="minimal output")
-parser.add_option('--protocol',  dest="proto", type="string",
-    help="protocol to use, one of: accel, binary, compact, json")
-parser.add_option('--transport',  dest="trans", type="string",
-    help="transport to use, one of: buffered, framed")
-parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary')
-options, args = parser.parse_args()
-
-script_dir = os.path.abspath(os.path.dirname(__file__))
-lib_dir = os.path.join(os.path.dirname(os.path.dirname(script_dir)), 'lib', 'py', 'build', 'lib*')
-sys.path.insert(0, os.path.join(script_dir, options.genpydir))
-sys.path.insert(0, glob.glob(lib_dir)[0])
-
-from ThriftTest import ThriftTest
-from ThriftTest.ttypes import *
-from thrift.transport import TTransport
-from thrift.transport import TSocket
-from thrift.transport import THttpClient
-from thrift.transport import TZlibTransport
-from thrift.protocol import TBinaryProtocol
-from thrift.protocol import TCompactProtocol
-from thrift.protocol import TJSONProtocol
+SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
+ROOT_DIR = os.path.dirname(os.path.dirname(SCRIPT_DIR))
+DEFAULT_LIBDIR_GLOB = os.path.join(ROOT_DIR, 'lib', 'py', 'build', 'lib.*')
 
 
 class AbstractTest(unittest.TestCase):
@@ -90,11 +52,10 @@
       if options.zlib:
         self.transport = TZlibTransport.TZlibTransport(self.transport, 9)
     self.transport.open()
-    protocol = self.protocol_factory.getProtocol(self.transport)
+    protocol = self.get_protocol(self.transport)
     self.client = ThriftTest.Client(protocol)
 
   def tearDown(self):
-    # Close!
     self.transport.close()
 
   def testVoid(self):
@@ -190,7 +151,7 @@
 
   def testMap(self):
     print('testMap')
-    x = {0:1, 1:2, 2:3, 3:4, -1:-2}
+    x = {0: 1, 1: 2, 2: 3, 3: 4, -1: -2}
     y = self.client.testMap(x)
     self.assertEqual(y, x)
 
@@ -214,7 +175,7 @@
 
   def testTypedef(self):
     print('testTypedef')
-    x = 0xffffffffffffff # 7 bytes of 0xff
+    x = 0xffffffffffffff  # 7 bytes of 0xff
     y = self.client.testTypedef(x)
     self.assertEqual(y, x)
 
@@ -230,11 +191,11 @@
     print('testMulti')
     xpected = Xtruct(string_thing='Hello2', byte_thing=74, i32_thing=0xff00ff, i64_thing=0xffffffffd0d0)
     y = self.client.testMulti(xpected.byte_thing,
-          xpected.i32_thing,
-          xpected.i64_thing,
-          { 0:'abc' },
-          Numberz.FIVE,
-          0xf0f0f0)
+                              xpected.i32_thing,
+                              xpected.i64_thing,
+                              {0: 'abc'},
+                              Numberz.FIVE,
+                              0xf0f0f0)
     self.assertEqual(y, xpected)
 
   def testException(self):
@@ -248,8 +209,8 @@
       self.assertEqual(x.message, 'Xception')
       # TODO ensure same behavior for repr within generated python variants
       # ensure exception's repr method works
-      #x_repr = repr(x)
-      #self.assertEqual(x_repr, 'Xception(errorCode=1001, message=\'Xception\')')
+      # x_repr = repr(x)
+      # self.assertEqual(x_repr, 'Xception(errorCode=1001, message=\'Xception\')')
 
     try:
       self.client.testException('TException')
@@ -280,31 +241,35 @@
   def testOneway(self):
     print('testOneway')
     start = time.time()
-    self.client.testOneway(1) # type is int, not float
+    self.client.testOneway(1)  # type is int, not float
     end = time.time()
     self.assertTrue(end - start < 3,
                     "oneway sleep took %f sec" % (end - start))
 
   def testOnewayThenNormal(self):
     print('testOnewayThenNormal')
-    self.client.testOneway(1) # type is int, not float
+    self.client.testOneway(1)  # type is int, not float
     self.assertEqual(self.client.testString('Python'), 'Python')
 
 
 class NormalBinaryTest(AbstractTest):
-  protocol_factory = TBinaryProtocol.TBinaryProtocolFactory()
+  def get_protocol(self, transport):
+    return TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)
 
 
 class CompactTest(AbstractTest):
-  protocol_factory = TCompactProtocol.TCompactProtocolFactory()
+  def get_protocol(self, transport):
+    return TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)
 
 
 class JSONTest(AbstractTest):
-  protocol_factory = TJSONProtocol.TJSONProtocolFactory()
+  def get_protocol(self, transport):
+    return TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)
 
 
 class AcceleratedBinaryTest(AbstractTest):
-  protocol_factory = TBinaryProtocol.TBinaryProtocolAcceleratedFactory()
+  def get_protocol(self, transport):
+    return TBinaryProtocol.TBinaryProtocolAcceleratedFactory().getProtocol(transport)
 
 
 def suite():
@@ -328,8 +293,54 @@
         if args:
             self.testNames = args
         else:
-            self.testNames = (self.defaultTest,)
+            self.testNames = ([self.defaultTest])
         self.createTests()
 
 if __name__ == "__main__":
+  parser = OptionParser()
+  parser.add_option('--libpydir', type='string', dest='libpydir',
+                    help='include this directory in sys.path for locating library code')
+  parser.add_option('--genpydir', type='string', dest='genpydir',
+                    default='gen-py',
+                    help='include this directory in sys.path for locating generated code')
+  parser.add_option("--port", type="int", dest="port",
+                    help="connect to server at port")
+  parser.add_option("--host", type="string", dest="host",
+                    help="connect to server")
+  parser.add_option("--zlib", action="store_true", dest="zlib",
+                    help="use zlib wrapper for compressed transport")
+  parser.add_option("--ssl", action="store_true", dest="ssl",
+                    help="use SSL for encrypted transport")
+  parser.add_option("--http", dest="http_path",
+                    help="Use the HTTP transport with the specified path")
+  parser.add_option('-v', '--verbose', action="store_const",
+                    dest="verbose", const=2,
+                    help="verbose output")
+  parser.add_option('-q', '--quiet', action="store_const",
+                    dest="verbose", const=0,
+                    help="minimal output")
+  parser.add_option('--protocol', dest="proto", type="string",
+                    help="protocol to use, one of: accel, binary, compact, json")
+  parser.add_option('--transport', dest="trans", type="string",
+                    help="transport to use, one of: buffered, framed")
+  parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary')
+  options, args = parser.parse_args()
+
+  sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir))
+  if options.libpydir:
+    sys.path.insert(0, glob.glob(options.libpydir)[0])
+  else:
+    sys.path.insert(0, glob.glob(DEFAULT_LIBDIR_GLOB)[0])
+
+  from ThriftTest import ThriftTest
+  from ThriftTest.ttypes import Xtruct, Xtruct2, Numberz, Xception, Xception2
+  from thrift.Thrift import TException
+  from thrift.transport import TTransport
+  from thrift.transport import TSocket
+  from thrift.transport import THttpClient
+  from thrift.transport import TZlibTransport
+  from thrift.protocol import TBinaryProtocol
+  from thrift.protocol import TCompactProtocol
+  from thrift.protocol import TJSONProtocol
+
   OwnArgsTestProgram(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=1))