<s> """<STR_LIT>""" <EOL> from __future__ import absolute_import , print_function <EOL> import functools <EOL> import logging <EOL> import random <EOL> from django . core . cache import cache <EOL> from time import sleep , time <EOL> default_cache = cache <EOL> logger = logging . getLogger ( __name__ ) <EOL> class UnableToGetLock ( Exception ) : <EOL> pass <EOL> class LockAlreadyHeld ( UnableToGetLock ) : <EOL> pass <EOL> class Lock ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , lock_key , timeout = <NUM_LIT:3> , cache = None , nowait = False ) : <EOL> if cache is None : <EOL> self . cache = default_cache <EOL> else : <EOL> self . cache = cache <EOL> self . timeout = timeout <EOL> self . lock_key = lock_key <EOL> self . nowait = nowait <EOL> self . __acquired_at = None <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . lock_key , ) <EOL> def acquire ( self ) : <EOL> """<STR_LIT>""" <EOL> time_remaining = self . seconds_remaining <EOL> if time_remaining : <EOL> raise LockAlreadyHeld ( '<STR_LIT>' % ( time_remaining , self ) ) <EOL> self . __acquired_at = None <EOL> delay = <NUM_LIT> + random . random ( ) / <NUM_LIT:10> <EOL> for i in xrange ( int ( self . timeout // delay ) ) : <EOL> if i != <NUM_LIT:0> : <EOL> sleep ( delay ) <EOL> attempt_started_at = time ( ) <EOL> if self . cache . add ( self . lock_key , '<STR_LIT>' , self . timeout ) : <EOL> self . __acquired_at = attempt_started_at <EOL> break <EOL> if self . nowait : <EOL> break <EOL> return self . __acquired_at is not None <EOL> def release ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . held : <EOL> logger . warning ( '<STR_LIT>' , self ) <EOL> return False <EOL> try : <EOL> self . cache . delete ( self . lock_key ) <EOL> except Exception as e : <EOL> logger . exception ( e ) <EOL> finally : <EOL> self . __acquired_at = None <EOL> return True <EOL> @ property <EOL> def seconds_remaining ( self ) : <EOL> if self . __acquired_at is None : <EOL> return <NUM_LIT:0> <EOL> lifespan = time ( ) - self . __acquired_at <EOL> return max ( self . timeout - lifespan , <NUM_LIT:0> ) <EOL> @ property <EOL> def held ( self ) : <EOL> return bool ( self . seconds_remaining ) <EOL> def __enter__ ( self ) : <EOL> start = time ( ) <EOL> if not self . acquire ( ) : <EOL> raise UnableToGetLock ( '<STR_LIT>' % ( time ( ) - start , self , ) ) <EOL> return self <EOL> def __exit__ ( self , exc_type , exc_value , traceback ) : <EOL> self . release ( ) <EOL> class memoize ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , func ) : <EOL> self . __name__ = func . __name__ <EOL> self . __module__ = func . __module__ <EOL> self . __doc__ = func . __doc__ <EOL> self . func = func <EOL> def __get__ ( self , obj , type = None ) : <EOL> if obj is None : <EOL> return self <EOL> d , n = vars ( obj ) , self . __name__ <EOL> if n not in d : <EOL> value = self . func ( obj ) <EOL> d [ n ] = value <EOL> value = d [ n ] <EOL> return value <EOL> class cached_for_request ( memoize ) : <EOL> """<STR_LIT>""" <EOL> def _get_key ( self , args , kwargs ) : <EOL> return ( self , tuple ( args ) , tuple ( kwargs . items ( ) ) ) <EOL> def __call__ ( self , * args , ** kwargs ) : <EOL> from sentry . app import env <EOL> request = env . request <EOL> if not request : <EOL> return self . func ( * args , ** kwargs ) <EOL> if not hasattr ( request , '<STR_LIT>' ) : <EOL> data = request . __func_cache = { } <EOL> else : <EOL> data = request . __func_cache <EOL> key = self . _get_key ( args , kwargs ) <EOL> if key not in data : <EOL> value = self . func ( * args , ** kwargs ) <EOL> data [ key ] = value <EOL> return data [ key ] <EOL> def __get__ ( self , obj , type = None ) : <EOL> return functools . partial ( self . __call__ , obj ) </s>
