<s> from datetime import datetime , timedelta <EOL> from collections import Hashable <EOL> import time <EOL> import threading <EOL> from . cross import imap , xrange <EOL> from . decorators import decorator , wraps , get_argnames , arggetter <EOL> __all__ = [ '<STR_LIT>' , '<STR_LIT:ignore>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> def raiser ( exception_or_class = Exception , * args , ** kwargs ) : <EOL> def _raiser ( * a , ** kw ) : <EOL> if args or kwargs : <EOL> raise exception_or_class ( * args , ** kwargs ) <EOL> else : <EOL> raise exception_or_class <EOL> return _raiser <EOL> def ignore ( errors , default = None ) : <EOL> def decorator ( func ) : <EOL> @ wraps ( func ) <EOL> def wrapper ( * args , ** kwargs ) : <EOL> try : <EOL> return func ( * args , ** kwargs ) <EOL> except errors : <EOL> return default <EOL> return wrapper <EOL> return decorator <EOL> silent = ignore ( Exception ) <EOL> try : <EOL> from contextlib import suppress <EOL> except ImportError : <EOL> class suppress ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * exceptions ) : <EOL> self . _exceptions = exceptions <EOL> def __enter__ ( self ) : <EOL> pass <EOL> def __exit__ ( self , exctype , excinst , exctb ) : <EOL> return exctype is not None and issubclass ( exctype , self . _exceptions ) <EOL> @ decorator <EOL> def retry ( call , tries , errors = Exception , timeout = <NUM_LIT:0> ) : <EOL> if isinstance ( errors , list ) : <EOL> errors = tuple ( errors ) <EOL> for attempt in xrange ( tries ) : <EOL> try : <EOL> return call ( ) <EOL> except errors : <EOL> if attempt + <NUM_LIT:1> == tries : <EOL> raise <EOL> else : <EOL> timeout_value = timeout ( attempt ) if callable ( timeout ) else timeout <EOL> if timeout_value > <NUM_LIT:0> : <EOL> time . sleep ( timeout_value ) <EOL> def fallback ( * approaches ) : <EOL> for approach in approaches : <EOL> func , catch = ( approach , Exception ) if callable ( approach ) else approach <EOL> try : <EOL> return func ( ) <EOL> except catch : <EOL> pass <EOL> class ErrorRateExceeded ( Exception ) : <EOL> pass <EOL> def limit_error_rate ( fails , timeout , exception = ErrorRateExceeded ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( timeout , int ) : <EOL> timeout = timedelta ( seconds = timeout ) <EOL> def decorator ( func ) : <EOL> func . fails = <NUM_LIT:0> <EOL> func . blocked = None <EOL> @ wraps ( func ) <EOL> def wrapper ( * args , ** kwargs ) : <EOL> if func . blocked : <EOL> if datetime . now ( ) - func . blocked < timeout : <EOL> raise exception <EOL> else : <EOL> func . blocked = None <EOL> try : <EOL> result = func ( * args , ** kwargs ) <EOL> except : <EOL> func . fails += <NUM_LIT:1> <EOL> if func . fails >= fails : <EOL> func . blocked = datetime . now ( ) <EOL> raise <EOL> else : <EOL> func . fails = <NUM_LIT:0> <EOL> return result <EOL> return wrapper <EOL> return decorator <EOL> @ decorator <EOL> def post_processing ( call , func ) : <EOL> return func ( call ( ) ) <EOL> collecting = post_processing ( list ) <EOL> @ decorator <EOL> def joining ( call , sep ) : <EOL> return sep . join ( imap ( sep . __class__ , call ( ) ) ) <EOL> def once_per ( * argnames ) : <EOL> def once ( func ) : <EOL> lock = threading . Lock ( ) <EOL> done_set = set ( ) <EOL> done_list = list ( ) <EOL> get_arg = arggetter ( func ) <EOL> @ wraps ( func ) <EOL> def wrapper ( * args , ** kwargs ) : <EOL> with lock : <EOL> values = tuple ( get_arg ( name , args , kwargs ) for name in argnames ) <EOL> if isinstance ( values , Hashable ) : <EOL> done , add = done_set , done_set . add <EOL> else : <EOL> done , add = done_list , done_list . append <EOL> if values not in done : <EOL> add ( values ) <EOL> return func ( * args , ** kwargs ) <EOL> return wrapper <EOL> return once <EOL> once = once_per ( ) <EOL> def once_per_args ( func ) : <EOL> return once_per ( * get_argnames ( func ) ) ( func ) </s>
