00001 """Robust apply mechanism 00002 00003 Provides a function "call", which can sort out 00004 what arguments a given callable object can take, 00005 and subset the given arguments to match only 00006 those which are acceptable. 00007 """ 00008 __version__ = "$Revision: 2.1 $" 00009 00010 def function( receiver ): 00011 """Get function-like callable object for given receiver 00012 00013 returns (function_or_method, codeObject, fromMethod) 00014 00015 If fromMethod is true, then the callable already 00016 has its first argument bound 00017 """ 00018 if hasattr(receiver, '__call__'): 00019 # receiver is a class instance; assume it is callable. 00020 # Reassign receiver to the actual method that will be called. 00021 if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'): 00022 receiver = receiver.__call__ 00023 if hasattr( receiver, 'im_func' ): 00024 # an instance-method... 00025 return receiver, receiver.im_func.func_code, 1 00026 elif not hasattr( receiver, 'func_code'): 00027 raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver))) 00028 return receiver, receiver.func_code, 0 00029 00030 def robustApply(receiver, *arguments, **named): 00031 """Call receiver with arguments and an appropriate subset of named 00032 """ 00033 receiver, codeObject, startIndex = function( receiver ) 00034 acceptable = codeObject.co_varnames[startIndex+len(arguments):codeObject.co_argcount] 00035 for name in codeObject.co_varnames[startIndex:startIndex+len(arguments)]: 00036 if named.has_key( name ): 00037 raise TypeError( 00038 """Argument %r specified both positionally and as a keyword for calling %r"""% ( 00039 name, receiver, 00040 ) 00041 ) 00042 if not (codeObject.co_flags & 8): 00043 # fc does not have a **kwds type parameter, therefore 00044 # remove unacceptable arguments. 00045 for arg in named.keys(): 00046 if arg not in acceptable: 00047 del named[arg] 00048 return receiver(*arguments, **named) 00049 00050