Coverage for bilby/core/utils/introspection.py: 97%

34 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-05-06 04:57 +0000

1import inspect 

2import types 

3 

4 

5def infer_parameters_from_function(func): 

6 """ Infers the arguments of a function 

7 (except the first arg which is assumed to be the dep. variable). 

8 

9 Throws out `*args` and `**kwargs` type arguments 

10 

11 Can deal with type hinting! 

12 

13 Parameters 

14 ========== 

15 func: function or method 

16 The function or method for which the parameters should be inferred. 

17 

18 Returns 

19 ======= 

20 list: A list of strings with the parameters 

21 

22 Raises 

23 ====== 

24 ValueError 

25 If the object passed to the function is neither a function nor a method. 

26 

27 Notes 

28 ===== 

29 In order to handle methods the `type` of the function is checked, and 

30 if a method has been passed the first *two* arguments are removed rather than just the first one. 

31 This allows the reference to the instance (conventionally named `self`) 

32 to be removed. 

33 """ 

34 if isinstance(func, types.MethodType): 

35 return infer_args_from_function_except_n_args(func=func, n=2) 

36 elif isinstance(func, types.FunctionType): 

37 return _infer_args_from_function_except_for_first_arg(func=func) 

38 else: 

39 raise ValueError("This doesn't look like a function.") 

40 

41 

42def infer_args_from_method(method): 

43 """ Infers all arguments of a method except for `self` 

44 

45 Throws out `*args` and `**kwargs` type arguments. 

46 

47 Can deal with type hinting! 

48 

49 Returns 

50 ======= 

51 list: A list of strings with the parameters 

52 """ 

53 return infer_args_from_function_except_n_args(func=method, n=1) 

54 

55 

56def infer_args_from_function_except_n_args(func, n=1): 

57 """ Inspects a function to find its arguments, and ignoring the 

58 first n of these, returns a list of arguments from the function's 

59 signature. 

60 

61 Parameters 

62 ========== 

63 func : function or method 

64 The function from which the arguments should be inferred. 

65 n : int 

66 The number of arguments which should be ignored, staring at the beginning. 

67 

68 Returns 

69 ======= 

70 parameters: list 

71 A list of parameters of the function, omitting the first `n`. 

72 

73 Extended Summary 

74 ================ 

75 This function is intended to allow the handling of named arguments 

76 in both functions and methods; this is important, since the first 

77 argument of an instance method will be the instance. 

78 

79 See Also 

80 ======== 

81 infer_args_from_method: Provides the arguments for a method 

82 infer_args_from_function: Provides the arguments for a function 

83 infer_args_from_function_except_first_arg: Provides all but first argument of a function or method. 

84 

85 Examples 

86 ======== 

87 

88 .. code-block:: python 

89 

90 >>> def hello(a, b, c, d): 

91 >>> pass 

92 >>> 

93 >>> infer_args_from_function_except_n_args(hello, 2) 

94 ['c', 'd'] 

95 

96 """ 

97 parameters = inspect.getfullargspec(func).args 

98 del parameters[:n] 

99 return parameters 

100 

101 

102def _infer_args_from_function_except_for_first_arg(func): 

103 return infer_args_from_function_except_n_args(func=func, n=1) 

104 

105 

106def get_dict_with_properties(obj): 

107 property_names = [p for p in dir(obj.__class__) 

108 if isinstance(getattr(obj.__class__, p), property)] 

109 dict_with_properties = obj.__dict__.copy() 

110 for key in property_names: 

111 dict_with_properties[key] = getattr(obj, key) 

112 return dict_with_properties 

113 

114 

115def get_function_path(func): 

116 if hasattr(func, "__module__") and hasattr(func, "__name__"): 

117 return "{}.{}".format(func.__module__, func.__name__) 

118 else: 

119 return func 

120 

121 

122class PropertyAccessor(object): 

123 """ 

124 Generic descriptor class that allows handy access of properties without long 

125 boilerplate code. The properties of Interferometer are defined as instances 

126 of this class. 

127 

128 This avoids lengthy code like 

129 

130 .. code-block:: python 

131 

132 @property 

133 def length(self): 

134 return self.geometry.length 

135 

136 @length_setter 

137 def length(self, length) 

138 self.geometry.length = length 

139 

140 in the Interferometer class 

141 """ 

142 

143 def __init__(self, container_instance_name, property_name): 

144 self.property_name = property_name 

145 self.container_instance_name = container_instance_name 

146 

147 def __get__(self, instance, owner): 

148 return getattr(getattr(instance, self.container_instance_name), self.property_name) 

149 

150 def __set__(self, instance, value): 

151 setattr(getattr(instance, self.container_instance_name), self.property_name, value)