From 5db3e926713d6fba0e9d0348d29b58bb8ec29367 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Thu, 30 Aug 2007 23:07:45 +0000 Subject: [PATCH] Thrift: Handle absence of fastbinary.so Summary: - Wrap import of fastbinary in a try/catch, setting it to None if it fails. - Don't try to fastbinary.encode/decode if fastbinary is None. - Always generate thrift_spec, even if it is None. - Don't try to fastbinary.encode/decode if thrift_spec is None. Reviewed By: mcslee Test Plan: test/py/Test{Client,Server}.py Manually delete my fastbinary.so, they worked fine. Changed them to use Accelerated protocol. They still worked fine because the test falls through to the normal generated code. Installed fastbinary.so, everything worked fine (eventually). Revert Plan: ok git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665236 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_py_generator.cc | 39 ++++++++++++++++----- compiler/cpp/src/generate/t_py_generator.h | 1 + lib/py/src/protocol/TBinaryProtocol.py | 2 +- lib/py/src/reflection/limited/ttypes.py | 29 ++++++++------- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc index 487de8728..843305831 100644 --- a/compiler/cpp/src/generate/t_py_generator.cc +++ b/compiler/cpp/src/generate/t_py_generator.cc @@ -67,9 +67,8 @@ void t_py_generator::init_generator() { py_autogen_comment() << endl << py_imports() << endl << render_includes() << endl << - "from thrift.transport import TTransport" << endl << - "from thrift.protocol import fastbinary" << endl << - "from thrift.protocol import TBinaryProtocol" << endl << endl << endl; + render_fastbinary_includes() << + endl << endl; f_consts_ << py_autogen_comment() << endl << @@ -93,6 +92,19 @@ string t_py_generator::render_includes() { return result; } +/** + * Renders all the imports necessary to use the accelerated TBinaryProtocol + */ +string t_py_generator::render_fastbinary_includes() { + return + "from thrift.transport import TTransport\n" + "from thrift.protocol import TBinaryProtocol\n" + "try:\n" + " from thrift.protocol import fastbinary\n" + "except:\n" + " fastbinary = None\n"; +} + /** * Autogen'd comment */ @@ -361,6 +373,10 @@ void t_py_generator::generate_py_struct_definition(ofstream& out, TODO(dreiss): Consider making this work for structs with negative tags. */ + // TODO(dreiss): Look into generating an empty tuple instead of None + // for structures with no members. + // TODO(dreiss): Test encoding of structs where some inner structs + // don't have thrift_spec. if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) { indent(out) << "thrift_spec = (" << endl; indent_up(); @@ -386,8 +402,11 @@ void t_py_generator::generate_py_struct_definition(ofstream& out, indent_down(); indent(out) << ")" << endl << endl; + } else { + indent(out) << "thrift_spec = None" << endl; } + out << indent() << "def __init__(self, d=None):" << endl; indent_up(); @@ -466,7 +485,9 @@ void t_py_generator::generate_py_struct_reader(ofstream& out, indent(out) << "if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated " - "and isinstance(iprot.trans, TTransport.CReadableTransport):" << endl; + "and isinstance(iprot.trans, TTransport.CReadableTransport) " + "and self.thrift_spec is not None " + "and fastbinary is not None:" << endl; indent_up(); indent(out) << @@ -549,7 +570,9 @@ void t_py_generator::generate_py_struct_writer(ofstream& out, indent_up(); indent(out) << - "if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated:" << endl; + "if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated " + "and self.thrift_spec is not None " + "and fastbinary is not None:" << endl; indent_up(); indent(out) << @@ -614,10 +637,8 @@ void t_py_generator::generate_service(t_service* tservice) { f_service_ << "from ttypes import *" << endl << "from thrift.Thrift import TProcessor" << endl << - "from thrift.transport import TTransport" << endl << - "from thrift.protocol import fastbinary" << endl << - "from thrift.protocol import TBinaryProtocol" << endl << - endl; + render_fastbinary_includes() << + endl << endl; // Generate the three main parts of the service (well, two for now in PHP) generate_service_interface(tservice); diff --git a/compiler/cpp/src/generate/t_py_generator.h b/compiler/cpp/src/generate/t_py_generator.h index c36752565..723745feb 100644 --- a/compiler/cpp/src/generate/t_py_generator.h +++ b/compiler/cpp/src/generate/t_py_generator.h @@ -128,6 +128,7 @@ class t_py_generator : public t_generator { std::string py_autogen_comment(); std::string py_imports(); std::string render_includes(); + std::string render_fastbinary_includes(); std::string declare_field(t_field* tfield); std::string type_name(t_type* ttype); std::string function_signature(t_function* tfunction, std::string prefix=""); diff --git a/lib/py/src/protocol/TBinaryProtocol.py b/lib/py/src/protocol/TBinaryProtocol.py index 3fd6b02ab..9755ada71 100644 --- a/lib/py/src/protocol/TBinaryProtocol.py +++ b/lib/py/src/protocol/TBinaryProtocol.py @@ -219,7 +219,7 @@ class TBinaryProtocolAccelerated(TBinaryProtocol): our C module to do the encoding, bypassing this object entirely. We inherit from TBinaryProtocol so that the normal TBinaryProtocol encoding can happen if the fastbinary module doesn't work for some - reason. (TODO(dreiss): Make this happen sanely.) + reason. (TODO(dreiss): Make this happen sanely in more cases.) In order to take advantage of the C module, just use TBinaryProtocolAccelerated instead of TBinaryProtocol. diff --git a/lib/py/src/reflection/limited/ttypes.py b/lib/py/src/reflection/limited/ttypes.py index 9ea8a9f9d..ec58f6689 100644 --- a/lib/py/src/reflection/limited/ttypes.py +++ b/lib/py/src/reflection/limited/ttypes.py @@ -7,8 +7,11 @@ from thrift.Thrift import * from thrift.transport import TTransport -from thrift.protocol import fastbinary from thrift.protocol import TBinaryProtocol +try: + from thrift.protocol import fastbinary +except: + fastbinary = None class TTypeTag: @@ -45,7 +48,7 @@ class SimpleType: self.name = d['name'] def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) return iprot.readStructBegin() @@ -69,7 +72,7 @@ class SimpleType: iprot.readStructEnd() def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated: + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStructBegin('SimpleType') @@ -118,7 +121,7 @@ class ContainerType: self.subtype2 = d['subtype2'] def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) return iprot.readStructBegin() @@ -149,7 +152,7 @@ class ContainerType: iprot.readStructEnd() def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated: + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStructBegin('ContainerType') @@ -202,7 +205,7 @@ class ThriftType: self.container_type = d['container_type'] def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) return iprot.readStructBegin() @@ -233,7 +236,7 @@ class ThriftType: iprot.readStructEnd() def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated: + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStructBegin('ThriftType') @@ -286,7 +289,7 @@ class Argument: self.type = d['type'] def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) return iprot.readStructBegin() @@ -316,7 +319,7 @@ class Argument: iprot.readStructEnd() def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated: + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStructBegin('Argument') @@ -369,7 +372,7 @@ class Method: self.arguments = d['arguments'] def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) return iprot.readStructBegin() @@ -405,7 +408,7 @@ class Method: iprot.readStructEnd() def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated: + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStructBegin('Method') @@ -461,7 +464,7 @@ class Service: self.fully_reflected = d['fully_reflected'] def read(self, iprot): - if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport): + if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) return iprot.readStructBegin() @@ -496,7 +499,7 @@ class Service: iprot.readStructEnd() def write(self, oprot): - if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated: + if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return oprot.writeStructBegin('Service')