THRIFT-162 Thrift structures are unhashable, preventing them from being used as set elements
Client: Python
Patch: David Reiss, Nobuaki Sukegawa

This closes #714
diff --git a/lib/py/src/Thrift.py b/lib/py/src/Thrift.py
index 9890af7..cbb9184 100644
--- a/lib/py/src/Thrift.py
+++ b/lib/py/src/Thrift.py
@@ -168,3 +168,23 @@
       oprot.writeFieldEnd()
     oprot.writeFieldStop()
     oprot.writeStructEnd()
+
+
+class TFrozenDict(dict):
+  """A dictionary that is "frozen" like a frozenset"""
+
+  def __init__(self, *args, **kwargs):
+    super(TFrozenDict, self).__init__(*args, **kwargs)
+    # Sort the items so they will be in a consistent order.
+    # XOR in the hash of the class so we don't collide with
+    # the hash of a list of tuples.
+    self.__hashval = hash(TFrozenDict) ^ hash(tuple(sorted(self.items())))
+
+  def __setitem__(self, *args):
+    raise TypeError("Can't modify frozen TFreezableDict")
+
+  def __delitem__(self, *args):
+    raise TypeError("Can't modify frozen TFreezableDict")
+
+  def __hash__(self):
+    return self.__hashval