##// END OF EJS Templates
support functools.partial as traitlet callback
Johan Forsberg -
Show More
@@ -280,6 +280,86 b' def dlink(source, *targets):'
280 """Shorter helper function returning a directional_link object"""
280 """Shorter helper function returning a directional_link object"""
281 return directional_link(source, *targets)
281 return directional_link(source, *targets)
282
282
283
284 # Alternative getargspec implementations taken from Sphinx
285 if sys.version_info >= (3, 0):
286
287 from functools import partial
288
289 def getargspec(func):
290 """Like inspect.getargspec but supports functools.partial as well."""
291 if inspect.ismethod(func):
292 func = func.__func__
293 if type(func) is partial:
294 orig_func = func.func
295 argspec = getargspec(orig_func)
296 args = list(argspec[0])
297 defaults = list(argspec[3] or ())
298 kwoargs = list(argspec[4])
299 kwodefs = dict(argspec[5] or {})
300 if func.args:
301 args = args[len(func.args):]
302 for arg in func.keywords or ():
303 try:
304 i = args.index(arg) - len(args)
305 del args[i]
306 try:
307 del defaults[i]
308 except IndexError:
309 pass
310 except ValueError: # must be a kwonly arg
311 i = kwoargs.index(arg)
312 del kwoargs[i]
313 del kwodefs[arg]
314 return inspect.FullArgSpec(args, argspec[1], argspec[2],
315 tuple(defaults), kwoargs,
316 kwodefs, argspec[6])
317 while hasattr(func, '__wrapped__'):
318 func = func.__wrapped__
319 if not inspect.isfunction(func):
320 raise TypeError('%r is not a Python function' % func)
321 return inspect.getfullargspec(func)
322 elif sys.version_info >= (2, 5):
323
324 from functools import partial
325
326 def getargspec(func):
327 """Like inspect.getargspec but supports functools.partial as well."""
328 if inspect.ismethod(func):
329 func = func.im_func
330 parts = 0, ()
331 if type(func) is partial:
332 keywords = func.keywords
333 if keywords is None:
334 keywords = {}
335 parts = len(func.args), keywords.keys()
336 func = func.func
337 if not inspect.isfunction(func):
338 raise TypeError('%r is not a Python function' % func)
339 args, varargs, varkw = inspect.getargs(func.func_code)
340 func_defaults = func.func_defaults
341 if func_defaults is None:
342 func_defaults = []
343 else:
344 func_defaults = list(func_defaults)
345 if parts[0]:
346 args = args[parts[0]:]
347 if parts[1]:
348 for arg in parts[1]:
349 i = args.index(arg) - len(args)
350 del args[i]
351 try:
352 del func_defaults[i]
353 except IndexError:
354 pass
355 if sys.version_info >= (2, 6):
356 return inspect.ArgSpec(args, varargs, varkw, func_defaults)
357 else:
358 return (args, varargs, varkw, func_defaults)
359 else:
360 getargspec = inspect.getargspec
361
362
283 #-----------------------------------------------------------------------------
363 #-----------------------------------------------------------------------------
284 # Base TraitType for all traits
364 # Base TraitType for all traits
285 #-----------------------------------------------------------------------------
365 #-----------------------------------------------------------------------------
@@ -570,7 +650,8 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):'
570 for c in callables:
650 for c in callables:
571 # Traits catches and logs errors here. I allow them to raise
651 # Traits catches and logs errors here. I allow them to raise
572 if callable(c):
652 if callable(c):
573 argspec = inspect.getargspec(c)
653 argspec = getargspec(c)
654
574 nargs = len(argspec[0])
655 nargs = len(argspec[0])
575 # Bound methods have an additional 'self' argument
656 # Bound methods have an additional 'self' argument
576 # I don't know how to treat unbound methods, but they
657 # I don't know how to treat unbound methods, but they
General Comments 0
You need to be logged in to leave comments. Login now