#stdlib
import os
from atexit import register
from random import triangular
from time import sleep

#local
from semaphore import RedisSemaphore
from logger import Logger

def rate_limited(*args, **kwargs):
    '''
    Semaphore decorator.
    
    @rate_limited
    def foo():
        pass
        
    Will only allow one instance of foo to operate at one time - across all servers
    running your code.
    
    You can increase the limit easily:
    
    @rate_limited(5)
    def five_foo():
        pass
        
    Maintains locks on redis-db0/1 unless host/db are overwritten in kwargs
    '''
    
    if 'connection_pool' in kwargs:
        pass
    else:
        if 'host' not in kwargs:
            kwargs['host'] = os.environ.get('REDIS_HOST', 'localhost')
        if 'db' not in kwargs:
            kwargs['db'] = os.environ.get('REDIS_DB', 0)

    def _rate_limited(f):
        name = '.'.join((f.__module__, f.__name__))
        s = RedisSemaphore(name, limit, acquire=False, **kwargs)
        
        @register
        def exit():
            s._close_gracefully()
        
        def fx(*args, **fkwargs):
            s.acquire()
 
            try:
                ret = f(*args, **fkwargs)
            finally:
                s.release()

            return ret
    
        return fx
        
    if args and callable(args[0]):
        f = args[0]
        limit = 1
        return _rate_limited(f)
    else:
        if args:
            limit = args[0]
        else:
            limit = 1
        return _rate_limited
   
   
def retry(*args, **kwargs):
    def _retry(f):
        def _fx(*args, **fkwargs):
            success = False
            i = 0
            while not success:
                
                if i > limit:
                    raise Exception('Retry Limit Exceeded: %s.%s - %s %s'%(f.__module__, f.__name__,
                                                                           args, fkwargs))
                
                sleep(i*triangular(*interval))
                
                try:
                    success = f(*args, **fkwargs)
                except:
                    import traceback
                    traceback.print_exc()
                finally:
                    i += 1
                    
            return success
                    
                    
        return _fx

        
    limit = kwargs.get('limit', 15)
    interval = kwargs.get('interval', (3, 5))
    
    if args and callable(args[0]):
        return _retry(args[0])
    else:
        return _retry
                    
                
        
    
@@ -2062,23 +2062,22 @@
         
-success
+result
  = f(*ar
@@ -2083,32 +2083,217 @@
 rgs, **fkwargs)%0A
+                    %0A                    if exc_only:%0A                        success = True%0A                    else:%0A                        success = result%0A                        %0A
                 
@@ -2471,23 +2471,22 @@
  return 
-success
+result
 %0A       
@@ -2585,16 +2585,16 @@
 t', 15)%0A
-
     inte
@@ -2631,16 +2631,61 @@
 (3, 5))%0A
+    exc_only = kwargs.get('exc_only', False)%0A
     %0A   

Add exception only mode to retry decorator