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
diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc
index 487de87..8433058 100644
--- a/compiler/cpp/src/generate/t_py_generator.cc
+++ b/compiler/cpp/src/generate/t_py_generator.cc
@@ -67,9 +67,8 @@
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 <<
@@ -94,6 +93,19 @@
}
/**
+ * 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
*/
string t_py_generator::py_autogen_comment() {
@@ -361,6 +373,10 @@
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 @@
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 @@
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 @@
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 @@
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 c367525..723745f 100644
--- a/compiler/cpp/src/generate/t_py_generator.h
+++ b/compiler/cpp/src/generate/t_py_generator.h
@@ -128,6 +128,7 @@
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 3fd6b02..9755ada 100644
--- a/lib/py/src/protocol/TBinaryProtocol.py
+++ b/lib/py/src/protocol/TBinaryProtocol.py
@@ -219,7 +219,7 @@
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 9ea8a9f..ec58f66 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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')