blob: c390cbb54c12c19226c8b7b7d1f71e8d88635807 [file] [log] [blame]
Mark Slee89e2bb82007-03-01 00:20:36 +00001#
David Reissea2cba82009-03-30 21:35:00 +00002# 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#
Mark Slee89e2bb82007-03-01 00:20:36 +000019
David Reissc548b3d2010-03-09 05:19:18 +000020import sys
21
Bryan Duxbury69720412012-01-03 17:32:30 +000022
Nobuaki Sukegawab9c859a2015-12-21 01:10:25 +090023class TType(object):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090024 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
Mark Sleee74306a2007-02-21 05:38:12 +000041
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090042 _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 )
Bryan Duxbury69720412012-01-03 17:32:30 +000062
Roger Meierf4eec7a2011-09-11 18:16:21 +000063
Nobuaki Sukegawab9c859a2015-12-21 01:10:25 +090064class TMessageType(object):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090065 CALL = 1
66 REPLY = 2
67 EXCEPTION = 3
68 ONEWAY = 4
Mark Sleee74306a2007-02-21 05:38:12 +000069
Mark Sleec9676562006-09-05 17:34:52 +000070
Nobuaki Sukegawab9c859a2015-12-21 01:10:25 +090071class TProcessor(object):
James E. King, IIIe7611d02017-10-23 16:44:45 -040072 """Base class for processor, which works on two streams."""
Mark Sleec9676562006-09-05 17:34:52 +000073
James E. King, IIIe7611d02017-10-23 16:44:45 -040074 def process(self, iprot, oprot):
James E. King III393f6c92019-02-09 10:35:44 -050075 """
76 Process a request. The normal behvaior is to have the
77 processor invoke the correct handler and then it is the
78 server's responsibility to write the response to oprot.
79 """
80 pass
81
82 def on_message_begin(self, func):
83 """
84 Install a callback that receives (name, type, seqid)
85 after the message header is read.
86 """
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090087 pass
Mark Slee92195ae2007-02-21 05:16:30 +000088
Mark Slee92195ae2007-02-21 05:16:30 +000089
Bryan Duxbury69720412012-01-03 17:32:30 +000090class TException(Exception):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090091 """Base class for all thrift exceptions."""
Mark Slee92195ae2007-02-21 05:16:30 +000092
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090093 # BaseException.message is deprecated in Python v[2.6,3.0)
94 if (2, 6, 0) <= sys.version_info < (3, 0):
95 def _get_message(self):
96 return self._message
Bryan Duxbury69720412012-01-03 17:32:30 +000097
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090098 def _set_message(self, message):
99 self._message = message
100 message = property(_get_message, _set_message)
David Reissc548b3d2010-03-09 05:19:18 +0000101
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900102 def __init__(self, message=None):
103 Exception.__init__(self, message)
104 self.message = message
Mark Slee92195ae2007-02-21 05:16:30 +0000105
Mark Slee92195ae2007-02-21 05:16:30 +0000106
Bryan Duxbury69720412012-01-03 17:32:30 +0000107class TApplicationException(TException):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900108 """Application level thrift exceptions."""
Mark Slee92195ae2007-02-21 05:16:30 +0000109
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900110 UNKNOWN = 0
111 UNKNOWN_METHOD = 1
112 INVALID_MESSAGE_TYPE = 2
113 WRONG_METHOD_NAME = 3
114 BAD_SEQUENCE_ID = 4
115 MISSING_RESULT = 5
116 INTERNAL_ERROR = 6
117 PROTOCOL_ERROR = 7
118 INVALID_TRANSFORM = 8
119 INVALID_PROTOCOL = 9
120 UNSUPPORTED_CLIENT_TYPE = 10
Mark Slee92195ae2007-02-21 05:16:30 +0000121
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900122 def __init__(self, type=UNKNOWN, message=None):
123 TException.__init__(self, message)
124 self.type = type
Mark Slee92195ae2007-02-21 05:16:30 +0000125
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900126 def __str__(self):
127 if self.message:
128 return self.message
129 elif self.type == self.UNKNOWN_METHOD:
130 return 'Unknown method'
131 elif self.type == self.INVALID_MESSAGE_TYPE:
132 return 'Invalid message type'
133 elif self.type == self.WRONG_METHOD_NAME:
134 return 'Wrong method name'
135 elif self.type == self.BAD_SEQUENCE_ID:
136 return 'Bad sequence ID'
137 elif self.type == self.MISSING_RESULT:
138 return 'Missing result'
139 elif self.type == self.INTERNAL_ERROR:
140 return 'Internal error'
141 elif self.type == self.PROTOCOL_ERROR:
142 return 'Protocol error'
143 elif self.type == self.INVALID_TRANSFORM:
144 return 'Invalid transform'
145 elif self.type == self.INVALID_PROTOCOL:
146 return 'Invalid protocol'
147 elif self.type == self.UNSUPPORTED_CLIENT_TYPE:
148 return 'Unsupported client type'
Mark Slee92195ae2007-02-21 05:16:30 +0000149 else:
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900150 return 'Default (unknown) TApplicationException'
Mark Slee92195ae2007-02-21 05:16:30 +0000151
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900152 def read(self, iprot):
153 iprot.readStructBegin()
154 while True:
155 (fname, ftype, fid) = iprot.readFieldBegin()
156 if ftype == TType.STOP:
157 break
158 if fid == 1:
159 if ftype == TType.STRING:
160 self.message = iprot.readString()
161 else:
162 iprot.skip(ftype)
163 elif fid == 2:
164 if ftype == TType.I32:
165 self.type = iprot.readI32()
166 else:
167 iprot.skip(ftype)
168 else:
169 iprot.skip(ftype)
170 iprot.readFieldEnd()
171 iprot.readStructEnd()
172
173 def write(self, oprot):
174 oprot.writeStructBegin('TApplicationException')
175 if self.message is not None:
176 oprot.writeFieldBegin('message', TType.STRING, 1)
177 oprot.writeString(self.message)
178 oprot.writeFieldEnd()
179 if self.type is not None:
180 oprot.writeFieldBegin('type', TType.I32, 2)
181 oprot.writeI32(self.type)
182 oprot.writeFieldEnd()
183 oprot.writeFieldStop()
184 oprot.writeStructEnd()
Nobuaki Sukegawae841b3d2015-11-17 11:01:17 +0900185
186
187class TFrozenDict(dict):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900188 """A dictionary that is "frozen" like a frozenset"""
Nobuaki Sukegawae841b3d2015-11-17 11:01:17 +0900189
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900190 def __init__(self, *args, **kwargs):
191 super(TFrozenDict, self).__init__(*args, **kwargs)
192 # Sort the items so they will be in a consistent order.
193 # XOR in the hash of the class so we don't collide with
194 # the hash of a list of tuples.
195 self.__hashval = hash(TFrozenDict) ^ hash(tuple(sorted(self.items())))
Nobuaki Sukegawae841b3d2015-11-17 11:01:17 +0900196
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900197 def __setitem__(self, *args):
198 raise TypeError("Can't modify frozen TFreezableDict")
Nobuaki Sukegawae841b3d2015-11-17 11:01:17 +0900199
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900200 def __delitem__(self, *args):
201 raise TypeError("Can't modify frozen TFreezableDict")
Nobuaki Sukegawae841b3d2015-11-17 11:01:17 +0900202
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900203 def __hash__(self):
204 return self.__hashval