2323 # Python 2
2424 JSONDecodeError = ValueError
2525
26- import model
2726from api import ecdsa_to_hex
28- from exception import StorjBridgeApiError
29- import web_socket
27+ from exception import BridgeError , ClientError
28+
29+ from . import web_socket
30+ from . import model
31+
32+
33+ __logger = logging .getLogger (__name__ )
34+
35+
36+ def handle_nonhttp_errors (func ):
37+ """Handle non-HTTP errors."""
38+ def decorator (* args , ** kwargs ):
39+ try :
40+ return func (* args , ** kwargs )
41+ except requests .exceptions .RequestException as e :
42+ __logger .error ('Failed to contact the bridge: %s' , e )
43+ raise ClientError (message = 'Failed to contact the bridge' )
44+ return decorator
3045
3146
3247class Client (object ):
@@ -139,7 +154,7 @@ def _request(self, **kwargs):
139154 Args:
140155 kwargs (dict): keyword arguments.
141156 Raises:
142- :py:class:`StorjBridgeApiError `: in case::
157+ :py:class:`BridgeError `: in case::
143158 - internal server error
144159 - error attribute is present in the JSON response
145160 - HTTP response JSON decoding failed
@@ -153,7 +168,7 @@ def _request(self, **kwargs):
153168 except requests .exceptions .RequestException as e :
154169 self .logger .error (e )
155170 self .logger .debug ('response.text=%s' , response .text )
156- raise StorjBridgeApiError (response .text )
171+ raise BridgeError (response .text )
157172
158173 # Raise any errors as exceptions
159174 try :
@@ -163,15 +178,16 @@ def _request(self, **kwargs):
163178 return {}
164179
165180 if 'error' in response_json :
166- raise StorjBridgeApiError (response_json ['error' ])
181+ raise BridgeError (response_json ['error' ])
167182
168183 return response_json
169184
170185 except JSONDecodeError as e :
171186 self .logger .error (e )
172187 self .logger .error ('_request body %s' , response .text )
173- raise StorjBridgeApiError ('Could not decode response.' )
188+ raise BridgeError ('Could not decode response.' )
174189
190+ @handle_nonhttp_errors
175191 def bucket_create (self , name , storage = None , transfer = None ):
176192 """Create storage bucket.
177193 See `API buckets: POST /buckets
@@ -193,6 +209,7 @@ def bucket_create(self, name, storage=None, transfer=None):
193209
194210 return model .Bucket (** self ._request (method = 'POST' , path = '/buckets' , json = data ))
195211
212+ @handle_nonhttp_errors
196213 def bucket_delete (self , bucket_id ):
197214 """Destroy a storage bucket.
198215 See `API buckets: DELETE /buckets/{id}
@@ -203,6 +220,7 @@ def bucket_delete(self, bucket_id):
203220 self .logger .info ('bucket_delete(%s)' , bucket_id )
204221 self ._request (method = 'DELETE' , path = '/buckets/%s' % bucket_id )
205222
223+ @handle_nonhttp_errors
206224 def bucket_files (self , bucket_id ):
207225 """List all the file metadata stored in the bucket.
208226 See `API buckets: GET /buckets/{id}/files
@@ -218,6 +236,7 @@ def bucket_files(self, bucket_id):
218236 method = 'GET' ,
219237 path = '/buckets/%s/files/' % (bucket_id ), )
220238
239+ @handle_nonhttp_errors
221240 def bucket_get (self , bucket_id ):
222241 """Return the bucket object.
223242 See `API buckets: GET /buckets
@@ -239,8 +258,9 @@ def bucket_get(self, bucket_id):
239258 return None
240259 else :
241260 self .logger .error ('bucket_get() error=%s' , e )
242- raise StorjBridgeApiError ()
261+ raise BridgeError ()
243262
263+ @handle_nonhttp_errors
244264 def bucket_list (self ):
245265 """List all of the buckets belonging to the user.
246266 See `API buckets: GET /buckets
@@ -258,6 +278,7 @@ def bucket_list(self):
258278 else :
259279 raise StopIteration
260280
281+ @handle_nonhttp_errors
261282 def bucket_set_keys (self , bucket_id , bucket_name , keys ):
262283 """Update the bucket with the given public keys.
263284 See `API buckets: PATCH /buckets/{bucket_id}
@@ -278,6 +299,7 @@ def bucket_set_keys(self, bucket_id, bucket_name, keys):
278299 'name' : bucket_name ,
279300 'pubkeys' : keys }))
280301
302+ @handle_nonhttp_errors
281303 def bucket_set_mirrors (self , bucket_id , file_id , redundancy ):
282304 """Establishes a series of mirrors for the given file.
283305 See `API buckets: POST /buckets/{id}/mirrors
@@ -299,6 +321,7 @@ def bucket_set_mirrors(self, bucket_id, file_id, redundancy):
299321 'redundancy' : redundancy
300322 }))
301323
324+ @handle_nonhttp_errors
302325 def contact_list (self , page = 1 , address = None , protocol = None , user_agent = None , connected = None ):
303326 """Lists contacts.
304327 See `API contacts: GET /contacts
@@ -324,6 +347,7 @@ def contact_list(self, page=1, address=None, protocol=None, user_agent=None, con
324347 else :
325348 raise StopIteration
326349
350+ @handle_nonhttp_errors
327351 def contact_lookup (self , node_id ):
328352 """Lookup for contact information of a node.
329353 See `API contacts: GET /contacts/{nodeID}
@@ -339,6 +363,7 @@ def contact_lookup(self, node_id):
339363 method = 'GET' ,
340364 path = '/contacts/%s' % node_id ))
341365
366+ @handle_nonhttp_errors
342367 def file_pointers (self , bucket_id , file_id , skip , limit , exclude = None ):
343368 """Get list of pointers associated with a file.
344369
@@ -373,6 +398,7 @@ def file_pointers(self, bucket_id, file_id, skip, limit, exclude=None):
373398 path = '/buckets/%s/files/%s/?skip=%s&limit=%s' % (bucket_id , file_id , skip , limit ),
374399 headers = {'x-token' : pull_token .id })
375400
401+ @handle_nonhttp_errors
376402 def file_download (self , bucket_id , file_id ):
377403 self .logger .info ('file_pointers(%s, %s)' , bucket_id , file_id )
378404
@@ -388,6 +414,7 @@ def file_download(self, bucket_id, file_id):
388414
389415 return file_contents
390416
417+ @handle_nonhttp_errors
391418 def file_metadata (self , bucket_id , file_id ):
392419 """Get file metadata.
393420 See `API buckets: GET /buckets/{id}/files/{file_id}/info
@@ -408,6 +435,7 @@ def file_metadata(self, bucket_id, file_id):
408435 if response is not None :
409436 return model .File (** response )
410437
438+ @handle_nonhttp_errors
411439 def file_upload (self , bucket_id , file , frame ):
412440 """Upload file.
413441 See `API buckets: POST /buckets/{id}/files
@@ -446,6 +474,7 @@ def get_size(file_like_object):
446474 'filename' : file .filename ,
447475 })
448476
477+ @handle_nonhttp_errors
449478 def file_remove (self , bucket_id , file_id ):
450479 """Delete a file pointer from a specified bucket.
451480 See `API buckets: DELETE /buckets/{id}/files/{file_id}
@@ -460,6 +489,7 @@ def file_remove(self, bucket_id, file_id):
460489 method = 'DELETE' ,
461490 path = '/buckets/%s/files/%s' % (bucket_id , file_id ))
462491
492+ @handle_nonhttp_errors
463493 def frame_add_shard (self , shard , frame_id ):
464494 """Adds a shard item to the staging frame and negotiates a storage contract.
465495
@@ -487,6 +517,7 @@ def frame_add_shard(self, shard, frame_id):
487517
488518 return response
489519
520+ @handle_nonhttp_errors
490521 def file_mirrors (self , bucket_id , file_id ):
491522 """Get list of established and available mirrors associated with a file.
492523 Args:
@@ -511,6 +542,7 @@ def file_mirrors(self, bucket_id, file_id):
511542 else :
512543 raise StopIteration
513544
545+ @handle_nonhttp_errors
514546 def frame_create (self ):
515547 """Creates a file staging frame.
516548 See `API frames: POST /frames
@@ -527,6 +559,7 @@ def frame_create(self):
527559 if response is not None :
528560 return model .Frame (** response )
529561
562+ @handle_nonhttp_errors
530563 def frame_delete (self , frame_id ):
531564 """Destroys the file staging frame by it's unique ID.
532565 See `API frames: DELETE /frames/{frame_id}
@@ -541,6 +574,7 @@ def frame_delete(self, frame_id):
541574 path = '/frames/%s' % frame_id ,
542575 json = {'frame_id' : frame_id })
543576
577+ @handle_nonhttp_errors
544578 def frame_get (self , frame_id ):
545579 """Fetches the file staging frame by it's unique ID.
546580 See `API frame: GET /frames/{frame_id}
@@ -560,6 +594,7 @@ def frame_get(self, frame_id):
560594 if response is not None :
561595 return model .Frame (** response )
562596
597+ @handle_nonhttp_errors
563598 def frame_list (self ):
564599 """Returns all open file staging frames.
565600 See `API frame: GET /frames
@@ -579,6 +614,7 @@ def frame_list(self):
579614 else :
580615 raise StopIteration
581616
617+ @handle_nonhttp_errors
582618 def key_delete (self , public_key ):
583619 """Removes a public ECDSA keys.
584620 See `API keys: DELETE /keys/{pubkey}
@@ -649,6 +685,7 @@ def key_import(self, private_keyfile_path, public_keyfile_path):
649685
650686 self .key_register (self .public_key )
651687
688+ @handle_nonhttp_errors
652689 def key_list (self ):
653690 """Lists the public ECDSA keys associated with the user.
654691 See `API keys: GET /keys
@@ -663,6 +700,7 @@ def key_list(self):
663700 path = '/keys'
664701 )]
665702
703+ @handle_nonhttp_errors
666704 def key_register (self , public_key ):
667705 """Register an ECDSA public key.
668706 See `API keys: POST /keys
@@ -677,6 +715,7 @@ def key_register(self, public_key):
677715 path = '/keys' ,
678716 json = {'key' : ecdsa_to_hex (str (public_key ))})
679717
718+ @handle_nonhttp_errors
680719 def token_create (self , bucket_id , operation ):
681720 """Creates a token for the specified operation.
682721 See `API buckets: POST /buckets/{id}/tokens
@@ -694,6 +733,7 @@ def token_create(self, bucket_id, operation):
694733 path = '/buckets/%s/tokens' % bucket_id ,
695734 json = {'operation' : operation }))
696735
736+ @handle_nonhttp_errors
697737 def send_exchange_report (self , exchange_report_data ):
698738 """Send exchange report to bridge
699739 Args:
@@ -719,6 +759,7 @@ def send_exchange_report(self, exchange_report_data):
719759 path = '/reports/exchanges' ,
720760 json = data ))
721761
762+ @handle_nonhttp_errors
722763 def user_activate (self , token ):
723764 """Activate user.
724765 See `API users: GET /activations/{token}
@@ -748,6 +789,7 @@ def check_file_existence_in_bucket(self, bucket_id, filepath, file_id=None):
748789 else :
749790 return False
750791
792+ @handle_nonhttp_errors
751793 def user_activation_email (self , email , token ):
752794 """Send user activation email.
753795 See `API users: POST /activations/{token}
@@ -765,6 +807,7 @@ def user_activation_email(self, email, token):
765807 'email' : email ,
766808 })
767809
810+ @handle_nonhttp_errors
768811 def user_create (self , email , password ):
769812 """Create a new user with Storj bridge.
770813 See `API users: POST /users
@@ -787,6 +830,7 @@ def user_create(self, email, password):
787830
788831 return response
789832
833+ @handle_nonhttp_errors
790834 def user_deactivate (self , token ):
791835 """Discard activation token.
792836 See `API users: GET /activations/{token}
@@ -800,6 +844,7 @@ def user_deactivate(self, token):
800844 method = 'DELETE' ,
801845 path = '/activations/%s' % token )
802846
847+ @handle_nonhttp_errors
803848 def user_delete (self , email ):
804849 """Delete user account.
805850 See `API users: DELETE /users/{email}
@@ -813,6 +858,7 @@ def user_delete(self, email):
813858 method = 'DELETE' ,
814859 path = '/users/%s' % email )
815860
861+ @handle_nonhttp_errors
816862 def user_reset_password (self , email ):
817863 """Request a password reset.
818864 See `API users: PATCH /users/{email}
@@ -826,6 +872,7 @@ def user_reset_password(self, email):
826872 method = 'PATCH' ,
827873 path = '/users/%s' % email )
828874
875+ @handle_nonhttp_errors
829876 def user_reset_password_confirmation (self , token ):
830877 """Confirm a password reset request.
831878 See `API users: GET /resets/{token}
0 commit comments