Coverage for /Users/Newville/Codes/xraylarch/larch/closure.py: 76%

46 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-09 10:08 -0600

1#!/usr/bin/env python 

2 

3import inspect 

4 

5class Closure(object): 

6 """Give a reference to a function with arguments so that it 

7 can be called later, optionally changing the argument list. 

8 

9 The class provids a simple callback function which is then 

10 executed when called as a function. It can be defined as: 

11 

12 >>>def my_action(x=None): 

13 ... print 'my action: x = ', x 

14 >>>c = Closure(my_action,x=1) 

15 

16 and used as: 

17 >>>c() 

18 my action: x = 1 

19 >>>c(x=2) 

20 my action: x = 2 

21 

22 The code is based on the Command class from 

23 J. Grayson's Tkinter book. 

24 """ 

25 def __init__(self, func=None, _name=None, _larch=None, **kwds): 

26 self.func = func 

27 self.kwds = kwds 

28 self.__name__ = _name 

29 if _name is None: 

30 self.__name__ = self.func.__name__ 

31 

32 self._larch = None 

33 argspec = inspect.getfullargspec(self.func) 

34 self._haskwargs = argspec.varkw is not None 

35 self._hasvarargs = argspec.varargs is not None 

36 self._argvars = argspec.args 

37 if (_larch is not None and ('_larch' in argspec.args or 

38 '_larch' in argspec.kwonlyargs)): 

39 self._larch = _larch 

40 self._nkws = 0 

41 if argspec.defaults is not None: 

42 self._nkws = len(argspec.defaults) 

43 self._nargs = len(self._argvars) - self._nkws 

44 self.argspec = argspec 

45 

46 def __repr__(self): 

47 return "<function %s, file=%s>" % (self.__name__, self.__file__) 

48 

49 __str__ = __repr__ 

50 

51 @property 

52 def __doc__(self): 

53 if self.func is not None: 

54 return self.func.__doc__ 

55 

56 @property 

57 def __file__(self): 

58 fname = getattr(self.func, '__filename__', 'unknown') 

59 if fname in ('unknown', None) and hasattr(self.func, '__code__'): 

60 fname = self.func.__code__.co_filename 

61 return fname 

62 

63 def __call__(self, *args, **c_kwds): 

64 if self.func is None: 

65 return None 

66 kwds = self.kwds.copy() 

67 kwds.update(c_kwds) 

68 ngot = len(args) + len(kwds) 

69 nexp = self._nargs + self._nkws 

70 if not self._haskwargs and not self._hasvarargs and (ngot > nexp): 

71 exc_msg = "%s expected %i arguments, got %i " 

72 raise TypeError(exc_msg % (self.__name__, nexp, ngot)) 

73 if self._larch is not None and kwds.get('_larch', None) is None: 

74 kwds['_larch'] = self._larch 

75 

76 return self.func(*args, **kwds)