#NEWLINE# @ classmethod #NEWLINE# def callable_info( cls , f ) : #NEWLINE# #INDENT# 'Info about a callable.\n    \n    The results are cached for efficiency.\n    \n    :param f:\n    :type  f: callable\n    :rtype: frozendict\n    ' #NEWLINE# if ( not callable ( f ) ) : #NEWLINE# #INDENT# return None #NEWLINE# #UNINDENT# if isinstance ( f , FunctionType ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# f = f . wrapped_func #NEWLINE# #UNINDENT# except AttributeError : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# #UNINDENT# cache_key = callable_cache_key ( f ) #NEWLINE# try : #NEWLINE# #INDENT# return cache_key . _info_cache [ cache_key ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# ( is_method , args , varargs , varkw , defaults ) = cls . getargspec ( f ) #NEWLINE# _args = [ ] #NEWLINE# args_len = len ( args ) #NEWLINE# defaults_len = 0 #NEWLINE# if ( defaults is not None ) : #NEWLINE# #INDENT# defaults_len = len ( defaults ) #NEWLINE# #UNINDENT# for ( i , n ) in enumerate ( args ) : #NEWLINE# #INDENT# default_index = ( i - ( args_len - defaults_len ) ) #NEWLINE# v = Undefined #NEWLINE# if ( default_index > ( - 1 ) ) : #NEWLINE# #INDENT# v = defaults [ default_index ] #NEWLINE# #UNINDENT# _args . append ( ( n , v ) ) #NEWLINE# #UNINDENT# info = frozendict ( { #NEWLINE# #INDENT# 'name' : f . func_name , #NEWLINE# 'args' : tuple ( _args ) , #NEWLINE# 'varargs' : bool ( varargs ) , #NEWLINE# 'varkw' : bool ( varkw ) , #NEWLINE# 'method' : is_method , #NEWLINE# #UNINDENT# } ) #NEWLINE# cls . _info_cache [ cache_key ] = info #NEWLINE# return info