Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(423)

Side by Side Diff: third_party/twisted_8_1/twisted/words/protocols/jabber/error.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.words.test.test_jabbererror -*-
2 #
3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6 """
7 XMPP Error support.
8 """
9
10 import copy
11
12 from twisted.words.xish import domish
13
14 NS_XML = "http://www.w3.org/XML/1998/namespace"
15 NS_XMPP_STREAMS = "urn:ietf:params:xml:ns:xmpp-streams"
16 NS_XMPP_STANZAS = "urn:ietf:params:xml:ns:xmpp-stanzas"
17
18 STANZA_CONDITIONS = {
19 'bad-request': {'code': '400', 'type': 'modify'},
20 'conflict': {'code': '409', 'type': 'cancel'},
21 'feature-not-implemented': {'code': '501', 'type': 'cancel'},
22 'forbidden': {'code': '403', 'type': 'auth'},
23 'gone': {'code': '302', 'type': 'modify'},
24 'internal-server-error': {'code': '500', 'type': 'wait'},
25 'item-not-found': {'code': '404', 'type': 'cancel'},
26 'jid-malformed': {'code': '400', 'type': 'modify'},
27 'not-acceptable': {'code': '406', 'type': 'modify'},
28 'not-allowed': {'code': '405', 'type': 'cancel'},
29 'not-authorized': {'code': '401', 'type': 'auth'},
30 'payment-required': {'code': '402', 'type': 'auth'},
31 'recipient-unavailable': {'code': '404', 'type': 'wait'},
32 'redirect': {'code': '302', 'type': 'modify'},
33 'registration-required': {'code': '407', 'type': 'auth'},
34 'remote-server-not-found': {'code': '404', 'type': 'cancel'},
35 'remove-server-timeout': {'code': '504', 'type': 'wait'},
36 'resource-constraint': {'code': '500', 'type': 'wait'},
37 'service-unavailable': {'code': '503', 'type': 'cancel'},
38 'subscription-required': {'code': '407', 'type': 'auth'},
39 'undefined-condition': {'code': '500', 'type': None},
40 'unexpected-request': {'code': '400', 'type': 'wait'},
41 }
42
43 CODES_TO_CONDITIONS = {
44 '302': ('gone', 'modify'),
45 '400': ('bad-request', 'modify'),
46 '401': ('not-authorized', 'auth'),
47 '402': ('payment-required', 'auth'),
48 '403': ('forbidden', 'auth'),
49 '404': ('item-not-found', 'cancel'),
50 '405': ('not-allowed', 'cancel'),
51 '406': ('not-acceptable', 'modify'),
52 '407': ('registration-required', 'auth'),
53 '408': ('remote-server-timeout', 'wait'),
54 '409': ('conflict', 'cancel'),
55 '500': ('internal-server-error', 'wait'),
56 '501': ('feature-not-implemented', 'cancel'),
57 '502': ('service-unavailable', 'wait'),
58 '503': ('service-unavailable', 'cancel'),
59 '504': ('remote-server-timeout', 'wait'),
60 '510': ('service-unavailable', 'cancel'),
61 }
62
63 class BaseError(Exception):
64 """
65 Base class for XMPP error exceptions.
66
67 @cvar namespace: The namespace of the C{error} element generated by
68 C{getElement}.
69 @type namespace: C{str}
70 @ivar condition: The error condition. The valid values are defined by
71 subclasses of L{BaseError}.
72 @type contition: C{str}
73 @ivar text: Optional text message to supplement the condition or application
74 specific condition.
75 @type text: C{unicode}
76 @ivar textLang: Identifier of the language used for the message in C{text}.
77 Values are as described in RFC 3066.
78 @type textLang: C{str}
79 @ivar appCondition: Application specific condition element, supplementing
80 the error condition in C{condition}.
81 @type appCondition: object providing L{domish.IElement}.
82 """
83
84 namespace = None
85
86 def __init__(self, condition, text=None, textLang=None, appCondition=None):
87 Exception.__init__(self)
88 self.condition = condition
89 self.text = text
90 self.textLang = textLang
91 self.appCondition = appCondition
92
93
94 def __str__(self):
95 message = "%s with condition %r" % (self.__class__.__name__,
96 self.condition)
97
98 if self.text:
99 message += ': ' + self.text
100
101 return message
102
103
104 def getElement(self):
105 """
106 Get XML representation from self.
107
108 The method creates an L{domish} representation of the
109 error data contained in this exception.
110
111 @rtype: L{domish.Element}
112 """
113 error = domish.Element((None, 'error'))
114 error.addElement((self.namespace, self.condition))
115 if self.text:
116 text = error.addElement((self.namespace, 'text'),
117 content=self.text)
118 if self.textLang:
119 text[(NS_XML, 'lang')] = self.textLang
120 if self.appCondition:
121 error.addChild(self.appCondition)
122 return error
123
124
125
126 class StreamError(BaseError):
127 """
128 Stream Error exception.
129
130 Refer to RFC 3920, section 4.7.3, for the allowed values for C{condition}.
131 """
132
133 namespace = NS_XMPP_STREAMS
134
135 def getElement(self):
136 """
137 Get XML representation from self.
138
139 Overrides the base L{BaseError.getElement} to make sure the returned
140 element is in the XML Stream namespace.
141
142 @rtype: L{domish.Element}
143 """
144 from twisted.words.protocols.jabber.xmlstream import NS_STREAMS
145
146 error = BaseError.getElement(self)
147 error.uri = NS_STREAMS
148 return error
149
150
151
152 class StanzaError(BaseError):
153 """
154 Stanza Error exception.
155
156 Refer to RFC 3920, section 9.3, for the allowed values for C{condition} and
157 C{type}.
158
159 @ivar type: The stanza error type. Gives a suggestion to the recipient
160 of the error on how to proceed.
161 @type type: C{str}
162 @ivar code: A numeric identifier for the error condition for backwards
163 compatibility with pre-XMPP Jabber implementations.
164 """
165
166 namespace = NS_XMPP_STANZAS
167
168 def __init__(self, condition, type=None, text=None, textLang=None,
169 appCondition=None):
170 BaseError.__init__(self, condition, text, textLang, appCondition)
171
172 if type is None:
173 try:
174 type = STANZA_CONDITIONS[condition]['type']
175 except KeyError:
176 pass
177 self.type = type
178
179 try:
180 self.code = STANZA_CONDITIONS[condition]['code']
181 except KeyError:
182 self.code = None
183
184 self.children = []
185 self.iq = None
186
187
188 def getElement(self):
189 """
190 Get XML representation from self.
191
192 Overrides the base L{BaseError.getElement} to make sure the returned
193 element has a C{type} attribute and optionally a legacy C{code}
194 attribute.
195
196 @rtype: L{domish.Element}
197 """
198 error = BaseError.getElement(self)
199 error['type'] = self.type
200 if self.code:
201 error['code'] = self.code
202 return error
203
204
205 def toResponse(self, stanza):
206 """
207 Construct error response stanza.
208
209 The C{stanza} is transformed into an error response stanza by
210 swapping the C{to} and C{from} addresses and inserting an error
211 element.
212
213 @note: This creates a shallow copy of the list of child elements of the
214 stanza. The child elements themselves are not copied themselves,
215 and references to their parent element will still point to the
216 original stanza element.
217
218 The serialization of an element does not use the reference to
219 its parent, so the typical use case of immediately sending out
220 the constructed error response is not affected.
221
222 @param stanza: the stanza to respond to
223 @type stanza: L{domish.Element}
224 """
225 from twisted.words.protocols.jabber.xmlstream import toResponse
226 response = toResponse(stanza, stanzaType='error')
227 response.children = copy.copy(stanza.children)
228 response.addChild(self.getElement())
229 return response
230
231
232 def _getText(element):
233 for child in element.children:
234 if isinstance(child, basestring):
235 return unicode(child)
236
237 return None
238
239
240
241 def _parseError(error, errorNamespace):
242 """
243 Parses an error element.
244
245 @param error: The error element to be parsed
246 @type error: L{domish.Element}
247 @param errorNamespace: The namespace of the elements that hold the error
248 condition and text.
249 @type errorNamespace: C{str}
250 @return: Dictionary with extracted error information. If present, keys
251 C{condition}, C{text}, C{textLang} have a string value,
252 and C{appCondition} has an L{domish.Element} value.
253 @rtype: L{dict}
254 """
255 condition = None
256 text = None
257 textLang = None
258 appCondition = None
259
260 for element in error.elements():
261 if element.uri == errorNamespace:
262 if element.name == 'text':
263 text = _getText(element)
264 textLang = element.getAttribute((NS_XML, 'lang'))
265 else:
266 condition = element.name
267 else:
268 appCondition = element
269
270 return {
271 'condition': condition,
272 'text': text,
273 'textLang': textLang,
274 'appCondition': appCondition,
275 }
276
277
278
279 def exceptionFromStreamError(element):
280 """
281 Build an exception object from a stream error.
282
283 @param element: the stream error
284 @type element: L{domish.Element}
285 @return: the generated exception object
286 @rtype: L{StreamError}
287 """
288 error = _parseError(element, NS_XMPP_STREAMS)
289
290 exception = StreamError(error['condition'],
291 error['text'],
292 error['textLang'],
293 error['appCondition'])
294
295 return exception
296
297
298
299 def exceptionFromStanza(stanza):
300 """
301 Build an exception object from an error stanza.
302
303 @param stanza: the error stanza
304 @type stanza: L{domish.Element}
305 @return: the generated exception object
306 @rtype: L{StanzaError}
307 """
308 children = []
309 condition = text = textLang = appCondition = type = code = None
310
311 for element in stanza.elements():
312 if element.name == 'error' and element.uri == stanza.uri:
313 code = element.getAttribute('code')
314 type = element.getAttribute('type')
315 error = _parseError(element, NS_XMPP_STANZAS)
316 condition = error['condition']
317 text = error['text']
318 textLang = error['textLang']
319 appCondition = error['appCondition']
320
321 if not condition and code:
322 condition, type = CODES_TO_CONDITIONS[code]
323 text = _getText(stanza.error)
324 else:
325 children.append(element)
326
327 if condition is None:
328 # TODO: raise exception instead?
329 return StanzaError(None)
330
331 exception = StanzaError(condition, type, text, textLang, appCondition)
332
333 exception.children = children
334 exception.stanza = stanza
335
336 return exception
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698