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
20
21class TType(object):
22    STOP = 0
23    VOID = 1
24    BOOL = 2
25    BYTE = 3
26    I08 = 3
27    DOUBLE = 4
28    I16 = 6
29    I32 = 8
30    I64 = 10
31    STRING = 11
32    UTF7 = 11
33    STRUCT = 12
34    MAP = 13
35    SET = 14
36    LIST = 15
37    UTF8 = 16
38    UTF16 = 17
39
40    _VALUES_TO_NAMES = (
41        'STOP',
42        'VOID',
43        'BOOL',
44        'BYTE',
45        'DOUBLE',
46        None,
47        'I16',
48        None,
49        'I32',
50        None,
51        'I64',
52        'STRING',
53        'STRUCT',
54        'MAP',
55        'SET',
56        'LIST',
57        'UTF8',
58        'UTF16',
59    )
60
61
62class TMessageType(object):
63    CALL = 1
64    REPLY = 2
65    EXCEPTION = 3
66    ONEWAY = 4
67
68
69class TProcessor(object):
70    """Base class for processor, which works on two streams."""
71
72    def process(self, iprot, oprot):
73        """
74        Process a request.  The normal behvaior is to have the
75        processor invoke the correct handler and then it is the
76        server's responsibility to write the response to oprot.
77        """
78        pass
79
80    def on_message_begin(self, func):
81        """
82        Install a callback that receives (name, type, seqid)
83        after the message header is read.
84        """
85        pass
86
87
88class TException(Exception):
89    """Base class for all thrift exceptions."""
90
91    def __init__(self, message=None):
92        Exception.__init__(self, message)
93        super(TException, self).__setattr__("message", message)
94
95
96class TApplicationException(TException):
97    """Application level thrift exceptions."""
98
99    UNKNOWN = 0
100    UNKNOWN_METHOD = 1
101    INVALID_MESSAGE_TYPE = 2
102    WRONG_METHOD_NAME = 3
103    BAD_SEQUENCE_ID = 4
104    MISSING_RESULT = 5
105    INTERNAL_ERROR = 6
106    PROTOCOL_ERROR = 7
107    INVALID_TRANSFORM = 8
108    INVALID_PROTOCOL = 9
109    UNSUPPORTED_CLIENT_TYPE = 10
110
111    def __init__(self, type=UNKNOWN, message=None):
112        TException.__init__(self, message)
113        self.type = type
114
115    def __str__(self):
116        if self.message:
117            return self.message
118        elif self.type == self.UNKNOWN_METHOD:
119            return 'Unknown method'
120        elif self.type == self.INVALID_MESSAGE_TYPE:
121            return 'Invalid message type'
122        elif self.type == self.WRONG_METHOD_NAME:
123            return 'Wrong method name'
124        elif self.type == self.BAD_SEQUENCE_ID:
125            return 'Bad sequence ID'
126        elif self.type == self.MISSING_RESULT:
127            return 'Missing result'
128        elif self.type == self.INTERNAL_ERROR:
129            return 'Internal error'
130        elif self.type == self.PROTOCOL_ERROR:
131            return 'Protocol error'
132        elif self.type == self.INVALID_TRANSFORM:
133            return 'Invalid transform'
134        elif self.type == self.INVALID_PROTOCOL:
135            return 'Invalid protocol'
136        elif self.type == self.UNSUPPORTED_CLIENT_TYPE:
137            return 'Unsupported client type'
138        else:
139            return 'Default (unknown) TApplicationException'
140
141    def read(self, iprot):
142        iprot.readStructBegin()
143        while True:
144            (fname, ftype, fid) = iprot.readFieldBegin()
145            if ftype == TType.STOP:
146                break
147            if fid == 1:
148                if ftype == TType.STRING:
149                    self.message = iprot.readString()
150                else:
151                    iprot.skip(ftype)
152            elif fid == 2:
153                if ftype == TType.I32:
154                    self.type = iprot.readI32()
155                else:
156                    iprot.skip(ftype)
157            else:
158                iprot.skip(ftype)
159            iprot.readFieldEnd()
160        iprot.readStructEnd()
161
162    def write(self, oprot):
163        oprot.writeStructBegin('TApplicationException')
164        if self.message is not None:
165            oprot.writeFieldBegin('message', TType.STRING, 1)
166            oprot.writeString(self.message)
167            oprot.writeFieldEnd()
168        if self.type is not None:
169            oprot.writeFieldBegin('type', TType.I32, 2)
170            oprot.writeI32(self.type)
171            oprot.writeFieldEnd()
172        oprot.writeFieldStop()
173        oprot.writeStructEnd()
174
175
176class TFrozenDict(dict):
177    """A dictionary that is "frozen" like a frozenset"""
178
179    def __init__(self, *args, **kwargs):
180        super(TFrozenDict, self).__init__(*args, **kwargs)
181        # Sort the items so they will be in a consistent order.
182        # XOR in the hash of the class so we don't collide with
183        # the hash of a list of tuples.
184        self.__hashval = hash(TFrozenDict) ^ hash(tuple(sorted(self.items())))
185
186    def __setitem__(self, *args):
187        raise TypeError("Can't modify frozen TFreezableDict")
188
189    def __delitem__(self, *args):
190        raise TypeError("Can't modify frozen TFreezableDict")
191
192    def __hash__(self):
193        return self.__hashval
194