Merge lp:~nataliabidart/ubuntuone-storage-protocol/map-those-errors into lp:ubuntuone-storage-protocol
- map-those-errors
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | John O'Brien | ||||
Approved revision: | 98 | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~nataliabidart/ubuntuone-storage-protocol/map-those-errors | ||||
Merge into: | lp:ubuntuone-storage-protocol | ||||
Diff against target: |
632 lines (+309/-74) 9 files modified
pylintrc (+3/-1) tests/test_client.py (+1/-1) tests/test_errors.py (+51/-0) tests/test_request.py (+59/-6) tests/test_volumes.py (+1/-1) ubuntuone/storageprotocol/client.py (+22/-30) ubuntuone/storageprotocol/errors.py (+156/-0) ubuntuone/storageprotocol/request.py (+14/-35) ubuntuone/storageprotocol/volumes.py (+2/-0) |
||||
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-storage-protocol/map-those-errors | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John O'Brien (community) | Approve | ||
dobey (community) | Approve | ||
Review via email: mp+22640@code.launchpad.net |
Commit message
Added an internal mapping to correctly raise specific exceptions when an ERROR was received in a Request.
Description of the change
Added an internal mapping to correctly raise specific exceptions when an ERROR was received in a Request.
Natalia Bidart (nataliabidart) wrote : | # |
> Can you clarify the pylintrc change by also adding comments as per the other
> values for disable-msg= above the disable-msg= line, or revert the change,
> using localized disable-msg comments instead if necessary? I'd like to avoid
> globally disabling messages when possible, as doing so may mask warnings that
> we should fix.
>
> And can you use the following coding annotation instead, so that it's handled
> better by different editors?
> # -*- coding: utf-8 -*-
All changes added in revision 98.
- 98. By Natalia Bidart
-
Adding details to pylint disable-msg. Unified coding defs.
dobey (dobey) : | # |
John O'Brien (jdobrien) : | # |
Preview Diff
1 | === modified file 'pylintrc' |
2 | --- pylintrc 2009-03-26 15:47:10 +0000 |
3 | +++ pylintrc 2010-04-01 18:11:31 +0000 |
4 | @@ -24,7 +24,9 @@ |
5 | # :W0613: *Unused argument %r* (We get lots of these from interfaces) |
6 | # :W0621: *Redefining name %r from outer scope (line %s)* (pylint does a poor evaluation) |
7 | # :W0622: *Redefining built-in '%r' |
8 | -disable-msg=E0101,W0142,W0221,W0613,W0621,W0622 |
9 | +# :W0201: *Attribute '%r' defined outside __init__* |
10 | +# :W0212: *Access to a protected member %r of a client class* |
11 | +disable-msg=E0101,W0142,W0221,W0613,W0621,W0622,W0201,W0212 |
12 | |
13 | |
14 | [REPORTS] |
15 | |
16 | === modified file 'tests/test_client.py' |
17 | --- tests/test_client.py 2010-01-04 18:21:24 +0000 |
18 | +++ tests/test_client.py 2010-04-01 18:11:31 +0000 |
19 | @@ -1,4 +1,4 @@ |
20 | -# coding=utf-8 |
21 | +# -*- coding: utf-8 -*- |
22 | # |
23 | # Author: Natalia B. Bidart <natalia.bidart@canonical.com> |
24 | # |
25 | |
26 | === added file 'tests/test_errors.py' |
27 | --- tests/test_errors.py 1970-01-01 00:00:00 +0000 |
28 | +++ tests/test_errors.py 2010-04-01 18:11:31 +0000 |
29 | @@ -0,0 +1,51 @@ |
30 | +# -*- coding: utf-8 -*- |
31 | +# |
32 | +# Author: Natalia B. Bidart <natalia.bidart@canonical.com> |
33 | +# |
34 | +# Copyright (C) 2010 Canonical Ltd. |
35 | +# |
36 | +# This program is free software: you can redistribute it and/or modify it |
37 | +# under the terms of the GNU Affero General Public License version 3, |
38 | +# as published by the Free Software Foundation. |
39 | +# |
40 | +# This program is distributed in the hope that it will be useful, but |
41 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
42 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
43 | +# PURPOSE. See the GNU Affero General Public License for more details. |
44 | +# |
45 | +# You should have received a copy of the GNU Affero General Public License |
46 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
47 | +"""Tests for errors module.""" |
48 | + |
49 | +import unittest |
50 | + |
51 | +from ubuntuone.storageprotocol import errors, protocol_pb2 |
52 | + |
53 | +REQ_ARGS = dict(request=None, message=protocol_pb2.Message()) |
54 | + |
55 | +HIGH_LEVEL_ERRORS = {errors.StorageProtocolErrorSizeTooBig: dict(), |
56 | + errors.StorageProtocolProtocolError: dict(), |
57 | + errors.StorageRequestError: REQ_ARGS, |
58 | + errors.RequestCancelledError: dict()} |
59 | + |
60 | + |
61 | +class ErrorsTestCase(unittest.TestCase): |
62 | + """Basic testing of errors mapping.""" |
63 | + |
64 | + def setUp(self): |
65 | + """Init.""" |
66 | + |
67 | + def test_exceptions_are_storage_protocol_error(self): |
68 | + """High level exceptions inherit from StorageProtocolError.""" |
69 | + for e, args in HIGH_LEVEL_ERRORS.iteritems(): |
70 | + self.assertTrue(isinstance(e(**args), errors.StorageProtocolError), |
71 | + "%r must inherit from StorageProtocolError" % e) |
72 | + |
73 | + def test_mapping(self): |
74 | + """Protocol's specific exceptions are correct.""" |
75 | + for code_error, proto_error in errors._error_mapping.iteritems(): |
76 | + self.assertTrue(isinstance(proto_error(**REQ_ARGS), |
77 | + errors.StorageRequestError), |
78 | + "%r must inherit from StorageRequestError" % |
79 | + proto_error) |
80 | + self.assertEqual(proto_error, errors.error_to_exception(code_error)) |
81 | |
82 | === modified file 'tests/test_request.py' |
83 | --- tests/test_request.py 2009-06-26 16:23:19 +0000 |
84 | +++ tests/test_request.py 2010-04-01 18:11:31 +0000 |
85 | @@ -2,16 +2,17 @@ |
86 | # request class tests |
87 | # |
88 | # Author: Tim Cole <tim.cole@canonical.com> |
89 | +# Author: Natalia Bidart <natalia.bidart@canonical.com> |
90 | # |
91 | # Copyright (C) 2009 Canonical |
92 | # |
93 | -# This program is free software: you can redistribute it and/or modify it |
94 | +# This program is free software: you can redistribute it and/or modify it |
95 | # under the terms of the GNU Affero General Public License version 3, |
96 | # as published by the Free Software Foundation. |
97 | # |
98 | -# This program is distributed in the hope that it will be useful, but |
99 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
100 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
101 | +# This program is distributed in the hope that it will be useful, but |
102 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
103 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
104 | # PURPOSE. See the GNU Affero General Public License for more details. |
105 | # |
106 | # You should have received a copy of the GNU Affero General Public License |
107 | @@ -20,9 +21,13 @@ |
108 | |
109 | from __future__ import with_statement |
110 | |
111 | -from twisted.trial.unittest import TestCase |
112 | +import unittest |
113 | + |
114 | +from twisted.trial.unittest import TestCase as TwistedTestCase |
115 | from twisted.internet.defer import inlineCallbacks |
116 | from twisted.python.failure import Failure |
117 | + |
118 | +from ubuntuone.storageprotocol import errors, protocol_pb2 |
119 | from ubuntuone.storageprotocol.request import ( |
120 | RequestHandler, Request) |
121 | |
122 | @@ -50,7 +55,7 @@ |
123 | self.producer = None |
124 | |
125 | |
126 | -class TestRequests(TestCase): |
127 | +class TestRequests(TwistedTestCase): |
128 | """Tests for request handling.""" |
129 | |
130 | @inlineCallbacks |
131 | @@ -74,3 +79,51 @@ |
132 | pass # passed |
133 | else: |
134 | self.fail("Expected to fail with the correct reason.") |
135 | + |
136 | + |
137 | +class TestRequest(unittest.TestCase): |
138 | + """Tests for request object.""" |
139 | + |
140 | + def setUp(self): |
141 | + """Init.""" |
142 | + self.request = MindlessRequest(protocol=None) |
143 | + self.error = None |
144 | + self.request.error = lambda error: setattr(self, 'error', error) |
145 | + |
146 | + def tearDown(self): |
147 | + """Clean up.""" |
148 | + self.error = None |
149 | + self.request = None |
150 | + |
151 | + def test_default_process_message_basic(self): |
152 | + """_default_process_message maps errors to exceptions.""" |
153 | + message = protocol_pb2.Message() |
154 | + self.request._default_process_message(message) |
155 | + |
156 | + self.assertTrue(isinstance(self.error, errors.StorageRequestError)) |
157 | + self.assertEqual(self.request, self.error.request) |
158 | + self.assertEqual(message, self.error.error_message) |
159 | + |
160 | + def test_default_process_message_no_error_message(self): |
161 | + """_default_process_message maps errors to exceptions.""" |
162 | + message = protocol_pb2.Message() |
163 | + self.request._default_process_message(message) |
164 | + |
165 | + self.assertTrue(self.error.__class__ is errors.StorageRequestError) |
166 | + self.assertEqual(self.request, self.error.request) |
167 | + self.assertEqual(message, self.error.error_message) |
168 | + |
169 | + def test_default_process_message(self): |
170 | + """_default_process_message maps errors to exceptions.""" |
171 | + for code_error, proto_error in errors._error_mapping.iteritems(): |
172 | + message = protocol_pb2.Message() |
173 | + message.type = protocol_pb2.Message.ERROR |
174 | + message.error.type = code_error |
175 | + self.request._default_process_message(message) |
176 | + |
177 | + self.assertTrue(isinstance(self.error, proto_error), |
178 | + "must be an instance of %r" % proto_error) |
179 | + self.assertEqual(self.request, self.error.request) |
180 | + self.assertEqual(message, self.error.error_message) |
181 | + |
182 | + self.error = None |
183 | |
184 | === modified file 'tests/test_volumes.py' |
185 | --- tests/test_volumes.py 2009-12-23 16:29:02 +0000 |
186 | +++ tests/test_volumes.py 2010-04-01 18:11:31 +0000 |
187 | @@ -1,4 +1,4 @@ |
188 | -# coding=utf-8 |
189 | +# -*- coding: utf-8 -*- |
190 | # |
191 | # Author: Natalia B. Bidart <natalia.bidart@canonical.com> |
192 | # |
193 | |
194 | === modified file 'ubuntuone/storageprotocol/client.py' |
195 | --- ubuntuone/storageprotocol/client.py 2010-03-12 20:32:23 +0000 |
196 | +++ ubuntuone/storageprotocol/client.py 2010-04-01 18:11:31 +0000 |
197 | @@ -569,14 +569,12 @@ |
198 | if self.callback is None: |
199 | self.data = "".join(self.parts) |
200 | self.done() |
201 | - elif message.type == protocol_pb2.Message.ERROR: |
202 | - self.error(request.StorageRequestError(self, message)) |
203 | elif message.type == protocol_pb2.Message.OK: |
204 | self.done() |
205 | elif message.type == protocol_pb2.Message.CANCELLED: |
206 | self.error(request.RequestCancelledError("CANCELLED")) |
207 | else: |
208 | - self.error(request.StorageProtocolProtocolError(message)) |
209 | + self._default_process_message(message) |
210 | |
211 | def _cancel(self): |
212 | """Cancel the current download.""" |
213 | @@ -609,7 +607,7 @@ |
214 | elif message.type == protocol_pb2.Message.SHARES_END: |
215 | self.done() |
216 | else: |
217 | - self.error(request.StorageRequestError(self, message)) |
218 | + self._default_process_message(message) |
219 | |
220 | |
221 | class CreateShare(request.Request): |
222 | @@ -666,7 +664,7 @@ |
223 | # XXX: this is for PROTOCOL_VERSION=1 backward compatibility |
224 | self.done() |
225 | else: |
226 | - self.error(request.StorageRequestError(self, message)) |
227 | + self._default_process_message(message) |
228 | |
229 | |
230 | class AcceptShare(request.Request): |
231 | @@ -711,7 +709,7 @@ |
232 | if message.type == protocol_pb2.Message.OK: |
233 | self.done() |
234 | else: |
235 | - self.error(request.StorageRequestError(self, message)) |
236 | + self._default_process_message(message) |
237 | |
238 | |
239 | class DeleteShare(request.Request): |
240 | @@ -739,7 +737,7 @@ |
241 | if message.type == protocol_pb2.Message.OK: |
242 | self.done() |
243 | else: |
244 | - self.error(request.StorageRequestError(self, message)) |
245 | + self._default_process_message(message) |
246 | |
247 | |
248 | class CreateUDF(request.Request): |
249 | @@ -774,7 +772,7 @@ |
250 | self.node_id = message.volume_created.udf.node |
251 | self.done() |
252 | else: |
253 | - self.error(request.StorageRequestError(self, message)) |
254 | + self._default_process_message(message) |
255 | |
256 | |
257 | class ListVolumes(request.Request): |
258 | @@ -816,7 +814,7 @@ |
259 | elif message.type == protocol_pb2.Message.VOLUMES_END: |
260 | self.done() |
261 | else: |
262 | - self.error(request.StorageRequestError(self, message)) |
263 | + self._default_process_message(message) |
264 | |
265 | |
266 | class DeleteVolume(request.Request): |
267 | @@ -844,7 +842,7 @@ |
268 | if message.type == protocol_pb2.Message.OK: |
269 | self.done() |
270 | else: |
271 | - self.error(request.StorageRequestError(self, message)) |
272 | + self._default_process_message(message) |
273 | |
274 | |
275 | class Unlink(request.Request): |
276 | @@ -875,7 +873,7 @@ |
277 | if message.type == protocol_pb2.Message.OK: |
278 | self.done() |
279 | else: |
280 | - self.error(request.StorageRequestError(self, message)) |
281 | + self._default_process_message(message) |
282 | |
283 | |
284 | class Move(request.Request): |
285 | @@ -914,10 +912,8 @@ |
286 | if message.type == protocol_pb2.Message.OK: |
287 | self.done() |
288 | else: |
289 | - # XXX: |
290 | - # lucio.torre |
291 | - # handle more error messages |
292 | - self.error(request.StorageRequestError(self, message)) |
293 | + self._default_process_message(message) |
294 | + |
295 | |
296 | class MultiQuery(object): |
297 | """Create a Request-like object that encapsulates many Query requests |
298 | @@ -954,6 +950,7 @@ |
299 | for q in self.queries: |
300 | q.start() |
301 | |
302 | + |
303 | class Query(request.Request): |
304 | """Query about the hash of a node_id. |
305 | |
306 | @@ -1011,10 +1008,7 @@ |
307 | elif message.type == protocol_pb2.Message.QUERY_END: |
308 | self.done() |
309 | else: |
310 | - # XXX: |
311 | - # lucio.torre |
312 | - # handle more error messages |
313 | - self.error(message) |
314 | + self._default_process_message(message) |
315 | |
316 | |
317 | class BytesMessageProducer(object): |
318 | @@ -1122,7 +1116,7 @@ |
319 | elif message.type == protocol_pb2.Message.CANCELLED: |
320 | self.error(request.RequestCancelledError("CANCELLED")) |
321 | else: |
322 | - self.error(request.StorageRequestError(self, message)) |
323 | + self._default_process_message(message) |
324 | |
325 | def _cancel(self): |
326 | """Cancel the current upload.""" |
327 | @@ -1183,7 +1177,8 @@ |
328 | self.new_name = message.new.name |
329 | self.done() |
330 | else: |
331 | - self.error(request.StorageRequestError(self, message)) |
332 | + self._default_process_message(message) |
333 | + |
334 | |
335 | class MakeDir(MakeObject): |
336 | """Extend MakeObject to make directories.""" |
337 | @@ -1224,7 +1219,8 @@ |
338 | self.other_protocol_version = message.protocol.version |
339 | self.done() |
340 | else: |
341 | - self.error(request.StorageRequestError(self, message)) |
342 | + self._default_process_message(message) |
343 | + |
344 | |
345 | class Authenticate(request.Request): |
346 | """Request to authenticate the user.""" |
347 | @@ -1253,12 +1249,8 @@ |
348 | """Handle messages.""" |
349 | if message.type == protocol_pb2.Message.AUTH_AUTHENTICATED: |
350 | self.done() |
351 | - elif message.type == protocol_pb2.Message.ERROR: |
352 | - # as the error travels with the exception, we send all here |
353 | - self.error(request.StorageRequestError(self, message)) |
354 | else: |
355 | - self.error(request.StorageProtocolError( |
356 | - "Authentication Error:"+str(message))) |
357 | + self._default_process_message(message) |
358 | |
359 | |
360 | class QuerySetCaps(request.Request): |
361 | @@ -1304,7 +1296,7 @@ |
362 | self.redirect_srvrecord = message.accept_caps.redirect_srvrecord |
363 | self.done() |
364 | else: |
365 | - self.error(request.StorageRequestError(self, message)) |
366 | + self._default_process_message(message) |
367 | |
368 | |
369 | class FreeSpaceInquiry(request.Request): |
370 | @@ -1330,7 +1322,7 @@ |
371 | self.free_bytes = message.free_space_info.free_bytes |
372 | self.done() |
373 | else: |
374 | - self.error(request.StorageRequestError(self, message)) |
375 | + self._default_process_message(message) |
376 | |
377 | |
378 | class AccountInquiry(request.Request): |
379 | @@ -1350,7 +1342,7 @@ |
380 | self.purchased_bytes = message.account_info.purchased_bytes |
381 | self.done() |
382 | else: |
383 | - self.error(request.StorageRequestError(self, message)) |
384 | + self._default_process_message(message) |
385 | |
386 | |
387 | class ThrottlingStorageClient(StorageClient): |
388 | |
389 | === added file 'ubuntuone/storageprotocol/errors.py' |
390 | --- ubuntuone/storageprotocol/errors.py 1970-01-01 00:00:00 +0000 |
391 | +++ ubuntuone/storageprotocol/errors.py 2010-04-01 18:11:31 +0000 |
392 | @@ -0,0 +1,156 @@ |
393 | +# -*- coding: utf-8 -*- |
394 | +# |
395 | +# Author: Natalia B. Bidart <natalia.bidart@canonical.com> |
396 | +# |
397 | +# Copyright 2010 Canonical Ltd. |
398 | +# |
399 | +# This program is free software: you can redistribute it and/or modify it |
400 | +# under the terms of the GNU Affero General Public License version 3, |
401 | +# as published by the Free Software Foundation. |
402 | +# |
403 | +# This program is distributed in the hope that it will be useful, but |
404 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
405 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
406 | +# PURPOSE. See the GNU Affero General Public License for more details. |
407 | +# |
408 | +# You should have received a copy of the GNU Affero General Public License |
409 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
410 | +"""The errors abstraction.""" |
411 | + |
412 | +from ubuntuone.storageprotocol import protocol_pb2 |
413 | + |
414 | + |
415 | +class StorageProtocolError(Exception): |
416 | + """Base class for all client/server exceptions.""" |
417 | + |
418 | + |
419 | +class StorageProtocolErrorSizeTooBig(StorageProtocolError): |
420 | + """The size we received was too big.""" |
421 | + |
422 | + |
423 | +class StorageProtocolProtocolError(StorageProtocolError): |
424 | + """A protocol error on the storage protocol.""" |
425 | + |
426 | + |
427 | +class StorageRequestError(StorageProtocolError): |
428 | + """An exception that keeps the request that generated it around.""" |
429 | + |
430 | + def __init__(self, request, message): |
431 | + """Create a StorageRequestError. |
432 | + |
433 | + @param request: the request that generated this error. |
434 | + @param message: the message received that generated the error. |
435 | + """ |
436 | + error_name = protocol_pb2.Error.DESCRIPTOR \ |
437 | + .enum_types_by_name['ErrorType'] \ |
438 | + .values_by_number[message.error.type].name |
439 | + super(StorageRequestError, self).__init__(error_name) |
440 | + #: the request that generated the error |
441 | + self.request = request |
442 | + #: the message received that generated the error |
443 | + self.error_message = message |
444 | + |
445 | + |
446 | +class RequestCancelledError(StorageProtocolError): |
447 | + """The request was cancelled.""" |
448 | + |
449 | + |
450 | +# Request specific errors |
451 | + |
452 | + |
453 | +class UnsupportedVersionError(StorageRequestError): |
454 | + """The version is not supported.""" |
455 | + |
456 | + |
457 | +class AuthenticationFailedError(StorageRequestError): |
458 | + """The authencation failed.""" |
459 | + |
460 | + |
461 | +class InternalError(StorageRequestError): |
462 | + """There was an internal error on the other side.""" |
463 | + |
464 | + |
465 | +class AuthenticationRequiredError(StorageRequestError): |
466 | + """The authentication is required and hasn't been established yet.""" |
467 | + |
468 | + |
469 | +class NoPermissionError(StorageRequestError): |
470 | + """Current permissions are not the required ones.""" |
471 | + |
472 | + |
473 | +class AlreadyExistsError(StorageRequestError): |
474 | + """The node already exists.""" |
475 | + |
476 | + |
477 | +class DoesNotExistError(StorageRequestError): |
478 | + """The node does not exists.""" |
479 | + |
480 | + |
481 | +class NotADirectoryError(StorageRequestError): |
482 | + """The node is not a directory.""" |
483 | + |
484 | + |
485 | +class NotEmptyError(StorageRequestError): |
486 | + """The node is not empty.""" |
487 | + |
488 | + |
489 | +class NotAvailableError(StorageRequestError): |
490 | + """The node is not available.""" |
491 | + |
492 | + |
493 | +class UploadInProgressError(StorageRequestError): |
494 | + """There is already an upload in progress.""" |
495 | + |
496 | + |
497 | +class UploadCorruptError(StorageRequestError): |
498 | + """The upload is corrupted.""" |
499 | + |
500 | + |
501 | +class UploadCanceledError(StorageRequestError): |
502 | + """There upload was canceled.""" |
503 | + |
504 | + |
505 | +class ConflictError(StorageRequestError): |
506 | + """The was a conflict.""" |
507 | + |
508 | + |
509 | +class TryAgainError(StorageRequestError): |
510 | + """Server answered to try again.""" |
511 | + |
512 | + |
513 | +class ProtocolError(StorageRequestError): |
514 | + """There was a protocol error.""" |
515 | + |
516 | + |
517 | +class QuotaExceededError(StorageRequestError): |
518 | + """The quota was exceeded.""" |
519 | + |
520 | + |
521 | +class InvalidFilenameError(StorageRequestError): |
522 | + """The filename is invalid.""" |
523 | + |
524 | + |
525 | +_error_mapping = { |
526 | + protocol_pb2.Error.UNSUPPORTED_VERSION: UnsupportedVersionError, |
527 | + protocol_pb2.Error.AUTHENTICATION_FAILED: AuthenticationFailedError, |
528 | + protocol_pb2.Error.INTERNAL_ERROR: InternalError, |
529 | + protocol_pb2.Error.AUTHENTICATION_REQUIRED: AuthenticationRequiredError, |
530 | + protocol_pb2.Error.NO_PERMISSION: NoPermissionError, |
531 | + protocol_pb2.Error.ALREADY_EXISTS: AlreadyExistsError, |
532 | + protocol_pb2.Error.DOES_NOT_EXIST: DoesNotExistError, |
533 | + protocol_pb2.Error.NOT_A_DIRECTORY: NotADirectoryError, |
534 | + protocol_pb2.Error.NOT_EMPTY: NotEmptyError, |
535 | + protocol_pb2.Error.NOT_AVAILABLE: NotAvailableError, |
536 | + protocol_pb2.Error.UPLOAD_IN_PROGRESS: UploadInProgressError, |
537 | + protocol_pb2.Error.UPLOAD_CORRUPT: UploadCorruptError, |
538 | + protocol_pb2.Error.UPLOAD_CANCELED: UploadCanceledError, |
539 | + protocol_pb2.Error.CONFLICT: ConflictError, |
540 | + protocol_pb2.Error.TRY_AGAIN: TryAgainError, |
541 | + protocol_pb2.Error.PROTOCOL_ERROR: ProtocolError, |
542 | + protocol_pb2.Error.QUOTA_EXCEEDED: QuotaExceededError, |
543 | + protocol_pb2.Error.INVALID_FILENAME: InvalidFilenameError, |
544 | +} |
545 | + |
546 | +def error_to_exception(error_code): |
547 | + """Map protocol errors to specific exceptions.""" |
548 | + return _error_mapping[error_code] |
549 | |
550 | === modified file 'ubuntuone/storageprotocol/request.py' |
551 | --- ubuntuone/storageprotocol/request.py 2010-01-04 18:21:24 +0000 |
552 | +++ ubuntuone/storageprotocol/request.py 2010-04-01 18:11:31 +0000 |
553 | @@ -36,6 +36,12 @@ |
554 | from zope.interface import implements |
555 | |
556 | from ubuntuone.storageprotocol import protocol_pb2, validators |
557 | +from ubuntuone.storageprotocol.errors import ( |
558 | + StorageProtocolError, StorageProtocolErrorSizeTooBig, |
559 | + StorageProtocolProtocolError, StorageRequestError, |
560 | + RequestCancelledError, error_to_exception |
561 | +) |
562 | + |
563 | |
564 | # the max possible packet size is 2**32 (32 bits for size) |
565 | # although we will not allow packets that big for now |
566 | @@ -53,41 +59,6 @@ |
567 | # the referred is the own root node, and not any of the shares |
568 | ROOT = '' |
569 | |
570 | -class StorageProtocolError(Exception): |
571 | - """base class for all client/server exceptions.""" |
572 | - |
573 | - |
574 | -class StorageProtocolErrorSizeTooBig(StorageProtocolError): |
575 | - """the size we received was too big.""" |
576 | - |
577 | - |
578 | -class StorageProtocolProtocolError(StorageProtocolError): |
579 | - """A protocol error on the storage protocol.""" |
580 | - |
581 | - |
582 | -class StorageRequestError(StorageProtocolError): |
583 | - """an exception that keeps the request that generated it around.""" |
584 | - |
585 | - def __init__(self, request, message): |
586 | - """create a StorageRequestError. |
587 | - |
588 | - @param request: the request that generated this error. |
589 | - @param message: the message received that generated the error. |
590 | - """ |
591 | - error_name = protocol_pb2.Error.DESCRIPTOR \ |
592 | - .enum_types_by_name['ErrorType'] \ |
593 | - .values_by_number[message.error.type].name |
594 | - super(StorageRequestError, self).__init__(error_name) |
595 | - #: the request that generated the error |
596 | - self.request = request |
597 | - #: the message received that generated the error |
598 | - self.error_message = message |
599 | - |
600 | - |
601 | -class RequestCancelledError(Exception): |
602 | - """The request is cancelled.""" |
603 | - |
604 | - |
605 | class RequestHandler(Protocol): |
606 | """the base class for a network peer. |
607 | |
608 | @@ -419,6 +390,14 @@ |
609 | """override this method to start the request.""" |
610 | raise NotImplementedError("request needs to do something") |
611 | |
612 | + def _default_process_message(self, message): |
613 | + """Map ERROR message to a specific exception.""" |
614 | + if message.type == protocol_pb2.Message.ERROR: |
615 | + error_class = error_to_exception(message.error.type) |
616 | + else: |
617 | + error_class = StorageRequestError |
618 | + self.error(error_class(self, message)) |
619 | + |
620 | def processMessage(self, message): |
621 | """handle an incoming message for this request. override this. |
622 | |
623 | |
624 | === modified file 'ubuntuone/storageprotocol/volumes.py' |
625 | --- ubuntuone/storageprotocol/volumes.py 2009-12-22 19:25:50 +0000 |
626 | +++ ubuntuone/storageprotocol/volumes.py 2010-04-01 18:11:31 +0000 |
627 | @@ -1,3 +1,5 @@ |
628 | +# -*- coding: utf-8 -*- |
629 | +# |
630 | # Author: Natalia B. Bidart <natalia.bidart@canonical.com> |
631 | # |
632 | # Copyright 2009 Canonical Ltd. |
Can you clarify the pylintrc change by also adding comments as per the other values for disable-msg= above the disable-msg= line, or revert the change, using localized disable-msg comments instead if necessary? I'd like to avoid globally disabling messages when possible, as doing so may mask warnings that we should fix.
And can you use the following coding annotation instead, so that it's handled better by different editors?
# -*- coding: utf-8 -*-