<s> import functools <EOL> __version__ = "<STR_LIT>" <EOL> __all__ = "<STR_LIT>" . split ( ) <EOL> import inspect <EOL> import sys <EOL> py32 = sys . version_info >= ( <NUM_LIT:3> , <NUM_LIT:2> , <NUM_LIT:0> ) <EOL> class InjectError ( RuntimeError ) : <EOL> pass <EOL> class _InjectionPoint ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , config = None , implicit = False ) : <EOL> self . name = name <EOL> self . config = config or { } <EOL> self . implicit = implicit <EOL> def __eq__ ( self , other ) : <EOL> if isinstance ( other , _InjectionPoint ) : <EOL> return self . __dict__ == other . __dict__ <EOL> return False <EOL> class _ProviderCache ( dict ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , injector ) : <EOL> super ( _ProviderCache , self ) . __init__ ( ) <EOL> self . injector = injector <EOL> def __missing__ ( self , func ) : <EOL> self [ func ] = value = list ( self . injector . _resolve ( func ) . items ( ) ) <EOL> return value <EOL> def _unwrap ( func ) : <EOL> if inspect . isclass ( func ) : <EOL> func = func . __init__ <EOL> while hasattr ( func , '<STR_LIT>' ) : <EOL> func = func . __wrapped__ <EOL> return func <EOL> def _make_null_resolver ( name , provider ) : <EOL> msg = "<STR_LIT>" % name <EOL> def null_resolver ( * a , ** ka ) : <EOL> if a or ka : <EOL> raise InjectError ( msg ) <EOL> return provider <EOL> return null_resolver <EOL> class Injector ( object ) : <EOL> def __init__ ( self ) : <EOL> self . __cache = _ProviderCache ( self ) <EOL> self . _resolvers = { } <EOL> self . _never_inject = set ( ( '<STR_LIT>' , ) ) <EOL> def add_value ( self , name , value , alias = ( ) ) : <EOL> """<STR_LIT>""" <EOL> self . add_provider ( name , lambda : value , alias = alias ) <EOL> def add_provider ( self , name , func , alias = ( ) ) : <EOL> """<STR_LIT>""" <EOL> self . add_resolver ( name , _make_null_resolver ( name , func ) , alias = alias ) <EOL> def add_resolver ( self , name , func , alias = ( ) ) : <EOL> """<STR_LIT>""" <EOL> self . _resolvers [ name ] = func <EOL> for name in alias : <EOL> self . _resolvers [ name ] = func <EOL> self . __cache . clear ( ) <EOL> def remove ( self , name ) : <EOL> """<STR_LIT>""" <EOL> if self . _resolvers . pop ( name ) : <EOL> self . __cache . clear ( ) <EOL> def provider ( self , name , alias = ( ) ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( name , str ) <EOL> def decorator ( func ) : <EOL> self . add_provider ( name , func , alias = alias ) <EOL> return func <EOL> return decorator <EOL> def resolver ( self , name , alias = ( ) ) : <EOL> """<STR_LIT>""" <EOL> def decorator ( func ) : <EOL> self . add_resolver ( name , func , alias = alias ) <EOL> return func <EOL> return decorator <EOL> def inspect ( self , func ) : <EOL> """<STR_LIT>""" <EOL> func = _unwrap ( func ) <EOL> if py32 : <EOL> args , varargs , varkw , defaults , kwonlyargs , kwonlydefaults , annotations = inspect . getfullargspec ( func ) <EOL> else : <EOL> args , varargs , keywords , defaults = inspect . getargspec ( func ) <EOL> kwonlyargs , kwonlydefaults , annotations = [ ] , { } , { } <EOL> defaults = defaults or ( ) <EOL> kwonlydefaults = kwonlydefaults or { } <EOL> injection_points = { } <EOL> for arg in args [ : len ( args ) - len ( defaults or [ ] ) ] : <EOL> if arg not in self . _never_inject : <EOL> injection_points [ arg ] = _InjectionPoint ( arg , implicit = True ) <EOL> for arg , value in zip ( args [ : : - <NUM_LIT:1> ] , defaults [ : : - <NUM_LIT:1> ] ) : <EOL> if isinstance ( value , _InjectionPoint ) : <EOL> injection_points [ arg ] = value <EOL> for arg , value in kwonlydefaults . items ( ) : <EOL> if isinstance ( value , _InjectionPoint ) : <EOL> injection_points [ arg ] = value <EOL> for arg , value in annotations . items ( ) : <EOL> if isinstance ( value , _InjectionPoint ) : <EOL> injection_points [ arg ] = value <EOL> return injection_points <EOL> def _resolve ( self , func ) : <EOL> """<STR_LIT>""" <EOL> results = { } <EOL> for arg , ip in self . inspect ( func ) . items ( ) : <EOL> results [ arg ] = self . _prime ( ip ) <EOL> return results <EOL> def _prime ( self , ip ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> provider_resolver = self . _resolvers [ ip . name ] <EOL> except KeyError : <EOL> err = InjectError ( "<STR_LIT>" % ip . name ) <EOL> if not ip . implicit : <EOL> raise err <EOL> def fail_if_injected ( ) : <EOL> raise err <EOL> return fail_if_injected <EOL> provider = self . call_inject ( provider_resolver , ** ip . config ) <EOL> return self . wrap ( provider ) <EOL> def call_inject ( self , func , ** ka ) : <EOL> """<STR_LIT>""" <EOL> for key , producer in self . __cache [ func ] : <EOL> if key not in ka : <EOL> ka [ key ] = producer ( ) <EOL> return func ( ** ka ) <EOL> def wrap ( self , func ) : <EOL> """<STR_LIT>""" <EOL> cache = self . __cache <EOL> if not self . inspect ( func ) : <EOL> return func <EOL> @ functools . wraps ( func ) <EOL> def wrapper ( ** ka ) : <EOL> for key , producer in cache [ func ] : <EOL> if key not in ka : <EOL> ka [ key ] = producer ( ) <EOL> return func ( ** ka ) <EOL> wrapper . __injector__ = self <EOL> return wrapper <EOL> class Plugin ( Injector ) : <EOL> api = <NUM_LIT:2> <EOL> def __init__ ( self ) : <EOL> super ( Plugin , self ) . __init__ ( ) <EOL> self . app = None <EOL> def setup ( self , app ) : <EOL> from bottle import request , response <EOL> self . app = app <EOL> self . add_value ( '<STR_LIT>' , self ) <EOL> self . add_value ( '<STR_LIT>' , app . config ) <EOL> self . add_value ( '<STR_LIT>' , app ) <EOL> self . add_value ( '<STR_LIT>' , request , alias = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> self . add_value ( '<STR_LIT>' , response , alias = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> def apply ( self , callback , route ) : <EOL> if self . inspect ( callback ) : <EOL> return self . wrap ( callback ) <EOL> return callback <EOL> def inject ( name , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> return _InjectionPoint ( name , config = kwargs ) </s>
