summaryrefslogtreecommitdiff
path: root/lib/py
diff options
context:
space:
mode:
authorElvis Pranskevichus <elvispranskevichus@pinterest.com>2019-03-07 11:00:34 -0500
committerD. Can Celasun <can@dcc.im>2019-12-10 20:44:24 +0000
commitb40f5c227f8db61be523f23ca017519167589d97 (patch)
tree78b38c45fc8cf8104c912e2415eefb6b63103c01 /lib/py
parent45a9827f0f455d377ae87d9a35349c10181d6893 (diff)
downloadthrift-b40f5c227f8db61be523f23ca017519167589d97.tar.gz
THRIFT-4002: Make generated exception classes immutable by default
Currently, the generated exception classes are not hashable under Python 3 because of the generated `__eq__` method. Exception objects are generally expected to be hashable by the Python standard library. Post-construction mutation of an exception object seems like a very unlikely case, so enable hashing for all exceptions by making them immutable by default. This also adds a way to opt-out of immutability by setting the `python.immutable` annotation to `"false"`.
Diffstat (limited to 'lib/py')
-rw-r--r--lib/py/src/protocol/TBase.py4
-rw-r--r--lib/py/src/protocol/TProtocol.py10
2 files changed, 12 insertions, 2 deletions
diff --git a/lib/py/src/protocol/TBase.py b/lib/py/src/protocol/TBase.py
index 9ae1b1182..6c6ef18e8 100644
--- a/lib/py/src/protocol/TBase.py
+++ b/lib/py/src/protocol/TBase.py
@@ -80,3 +80,7 @@ class TFrozenBase(TBase):
[self.__class__, self.thrift_spec])
else:
return iprot.readStruct(cls, cls.thrift_spec, True)
+
+
+class TFrozenExceptionBase(TFrozenBase, TExceptionBase):
+ pass
diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py
index 3456e8f0e..339a2839d 100644
--- a/lib/py/src/protocol/TProtocol.py
+++ b/lib/py/src/protocol/TProtocol.py
@@ -303,8 +303,14 @@ class TProtocolBase(object):
def readContainerStruct(self, spec):
(obj_class, obj_spec) = spec
- obj = obj_class()
- obj.read(self)
+
+ # If obj_class.read is a classmethod (e.g. in frozen structs),
+ # call it as such.
+ if getattr(obj_class.read, '__self__', None) is obj_class:
+ obj = obj_class.read(self)
+ else:
+ obj = obj_class()
+ obj.read(self)
return obj
def readContainerMap(self, spec):