#NEWLINE# def retry( func = None , retries = 5 , backoff = None , exceptions = ( IOError , OSError , EOFError ) , cleanup = None , sleep = time . sleep ) : #NEWLINE# #INDENT# '\n    Decorator that retries the call ``retries`` times if ``func`` raises ``exceptions``. Can use a ``backoff`` function\n    to sleep till next retry.\n\n    Example::\n\n        >>> should_fail = lambda foo=[1,2,3]: foo and foo.pop()\n        >>> @retry\n        ... def flaky_func():\n        ...     if should_fail():\n        ...         raise OSError(\'Tough luck!\')\n        ...     print("Success!")\n        ...\n        >>> flaky_func()\n        Success!\n\n    If it reaches the retry limit::\n\n        >>> @retry\n        ... def bad_func():\n        ...     raise OSError(\'Tough luck!\')\n        ...\n        >>> bad_func()\n        Traceback (most recent call last):\n        ...\n        OSError: Tough luck!\n\n    ' #NEWLINE# @ Aspect ( bind = True ) #NEWLINE# def retry_aspect( cutpoint , * args , **kwargs ) : #NEWLINE# #INDENT# for count in range ( ( retries + 1 ) ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# if ( count and cleanup ) : #NEWLINE# #INDENT# cleanup ( * args , ** kwargs ) #NEWLINE# #UNINDENT# ( yield ) #NEWLINE# break #NEWLINE# #UNINDENT# except exceptions as exc : #NEWLINE# #INDENT# if ( count == retries ) : #NEWLINE# #INDENT# raise #NEWLINE# #UNINDENT# if ( not backoff ) : #NEWLINE# #INDENT# timeout = 0 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if isinstance ( backoff , ( int , float ) ) : #NEWLINE# #INDENT# timeout = backoff #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# timeout = backoff ( count ) #NEWLINE# #UNINDENT# #UNINDENT# logger . exception ( '%s(%s, %s) raised exception %s. %s retries left. Sleeping %s secs.' , cutpoint . __name__ , args , kwargs , exc , ( retries - count ) , timeout ) #NEWLINE# sleep ( timeout ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# return ( retries if ( func is None ) else retry_aspect ( func ) )