1#
2# Licensed to the Apache Software Foundation (ASF) under one
3# or more contributor license agreements. See the NOTICE file
4# distributed with this work for additional information
5# regarding copyright ownership. The ASF licenses this file
6# to you under the Apache License, Version 2.0 (the
7# "License"); you may not use this file except in compliance
8# with the License. You may obtain a copy of the License at
9#
10#   http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing,
13# software distributed under the License is distributed on an
14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15# KIND, either express or implied. See the License for the
16# specific language governing permissions and limitations
17# under the License.
18#
19
20import sys
21
22
23class TType(object):
24    STOP = 0
25    VOID = 1
26    BOOL = 2
27    BYTE = 3
28    I08 = 3
29    DOUBLE = 4
30    I16 = 6
31    I32 = 8
32    I64 = 10
33    STRING = 11
34    UTF7 = 11
35    STRUCT = 12
36    MAP = 13
37    SET = 14
38    LIST = 15
39    UTF8 = 16
40    UTF16 = 17
41
42    _VALUES_TO_NAMES = (
43        'STOP',
44        'VOID',
45        'BOOL',
46        'BYTE',
47        'DOUBLE',
48        None,
49        'I16',
50        None,
51        'I32',
52        None,
53        'I64',
54        'STRING',
55        'STRUCT',
56        'MAP',
57        'SET',
58        'LIST',
59        'UTF8',
60        'UTF16',
61    )
62
63
64class TMessageType(object):
65    CALL = 1
66    REPLY = 2
67    EXCEPTION = 3
68    ONEWAY = 4
69
70
71class TProcessor(object):
72    """Base class for processor, which works on two streams."""
73
74    def process(self, iprot, oprot):
75        pass
76
77
78class TException(Exception):
79    """Base class for all thrift exceptions."""
80
81    # BaseException.message is deprecated in Python v[2.6,3.0)
82    if (2, 6, 0) <= sys.version_info < (3, 0):
83        def _get_message(self):
84            return self._message
85
86        def _set_message(self, message):
87            self._message = message
88        message = property(_get_message, _set_message)
89
90    def __init__(self, message=None):
91        Exception.__init__(self, message)
92        self.message = message
93
94
95class TApplicationException(TException):
96    """Application level thrift exceptions."""
97
98    UNKNOWN = 0
99    UNKNOWN_METHOD = 1
100    INVALID_MESSAGE_TYPE = 2
101    WRONG_METHOD_NAME = 3
102    BAD_SEQUENCE_ID = 4
103    MISSING_RESULT = 5
104    INTERNAL_ERROR = 6
105    PROTOCOL_ERROR = 7
106    INVALID_TRANSFORM = 8
107    INVALID_PROTOCOL = 9
108    UNSUPPORTED_CLIENT_TYPE = 10
109
110    def __init__(self, type=UNKNOWN, message=None):
111        TException.__init__(self, message)
112        self.type = type
113
114    def __str__(self):
115        if self.message:
116            return self.message
117        elif self.type == self.UNKNOWN_METHOD:
118            return 'Unknown method'
119        elif self.type == self.INVALID_MESSAGE_TYPE:
120            return 'Invalid message type'
121        elif self.type == self.WRONG_METHOD_NAME:
122            return 'Wrong method name'
123        elif self.type == self.BAD_SEQUENCE_ID:
124            return 'Bad sequence ID'
125        elif self.type == self.MISSING_RESULT:
126            return 'Missing result'
127        elif self.type == self.INTERNAL_ERROR:
128            return 'Internal error'
129        elif self.type == self.PROTOCOL_ERROR:
130            return 'Protocol error'
131        elif self.type == self.INVALID_TRANSFORM:
132            return 'Invalid transform'
133        elif self.type == self.INVALID_PROTOCOL:
134            return 'Invalid protocol'
135        elif self.type == self.UNSUPPORTED_CLIENT_TYPE:
136            return 'Unsupported client type'
137        else:
138            return 'Default (unknown) TApplicationException'
139
140    def read(self, iprot):
141        iprot.readStructBegin()
142        while True:
143            (fname, ftype, fid) = iprot.readFieldBegin()
144            if ftype == TType.STOP:
145                break
146            if fid == 1:
147                if ftype == TType.STRING:
148                    self.message = iprot.readString()
149                else:
150                    iprot.skip(ftype)
151            elif fid == 2:
152                if ftype == TType.I32:
153                    self.type = iprot.readI32()
154                else:
155                    iprot.skip(ftype)
156            else:
157                iprot.skip(ftype)
158            iprot.readFieldEnd()
159        iprot.readStructEnd()
160
161    def write(self, oprot):
162        oprot.writeStructBegin('TApplicationException')
163        if self.message is not None:
164            oprot.writeFieldBegin('message', TType.STRING, 1)
165            oprot.writeString(self.message)
166            oprot.writeFieldEnd()
167        if self.type is not None:
168            oprot.writeFieldBegin('type', TType.I32, 2)
169            oprot.writeI32(self.type)
170            oprot.writeFieldEnd()
171        oprot.writeFieldStop()
172        oprot.writeStructEnd()
173
174
175class TFrozenDict(dict):
176    """A dictionary that is "frozen" like a frozenset"""
177
178    def __init__(self, *args, **kwargs):
179        super(TFrozenDict, self).__init__(*args, **kwargs)
180        # Sort the items so they will be in a consistent order.
181        # XOR in the hash of the class so we don't collide with
182        # the hash of a list of tuples.
183        self.__hashval = hash(TFrozenDict) ^ hash(tuple(sorted(self.items())))
184
185    def __setitem__(self, *args):
186        raise TypeError("Can't modify frozen TFreezableDict")
187
188    def __delitem__(self, *args):
189        raise TypeError("Can't modify frozen TFreezableDict")
190
191    def __hash__(self):
192        return self.__hashval
193