<s> import hashlib <EOL> import pickle <EOL> import time <EOL> from functools import wraps <EOL> class RateLimitException ( Exception ) : <EOL> pass <EOL> class RateLimit ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , database , name , limit = <NUM_LIT:5> , per = <NUM_LIT> , debug = False ) : <EOL> """<STR_LIT>""" <EOL> self . database = database <EOL> self . name = name <EOL> self . _limit = limit <EOL> self . _per = per <EOL> self . _debug = debug <EOL> def limit ( self , key ) : <EOL> """<STR_LIT>""" <EOL> if self . _debug : <EOL> return False <EOL> counter = self . database . List ( self . name + '<STR_LIT::>' + key ) <EOL> n = len ( counter ) <EOL> is_limited = False <EOL> if n < self . _limit : <EOL> counter . prepend ( str ( time . time ( ) ) ) <EOL> else : <EOL> oldest = float ( counter [ - <NUM_LIT:1> ] ) <EOL> if time . time ( ) - oldest < self . _per : <EOL> is_limited = True <EOL> else : <EOL> counter . prepend ( str ( time . time ( ) ) ) <EOL> del counter [ : self . _limit ] <EOL> counter . pexpire ( int ( self . _per * <NUM_LIT> ) ) <EOL> return is_limited <EOL> def rate_limited ( self , key_function = None ) : <EOL> """<STR_LIT>""" <EOL> if key_function is None : <EOL> def key_function ( * args , ** kwargs ) : <EOL> data = pickle . dumps ( ( args , sorted ( kwargs . items ( ) ) ) ) <EOL> return hashlib . md5 ( data ) . hexdigest ( ) <EOL> def decorator ( fn ) : <EOL> @ wraps ( fn ) <EOL> def inner ( * args , ** kwargs ) : <EOL> key = key_function ( * args , ** kwargs ) <EOL> if self . limit ( key ) : <EOL> raise RateLimitException ( <EOL> '<STR_LIT>' % ( <EOL> fn . __name__ , self . _limit , self . _per ) ) <EOL> return fn ( * args , ** kwargs ) <EOL> return inner <EOL> return decorator </s>
