@@ -58,18 +58,19 @@ class Function(IOBase):
58
58
input_spec = FunctionInputSpec
59
59
output_spec = DynamicTraitedSpec
60
60
61
- def __init__ (self , input_names , output_names , function = None , imports = None ,
62
- ** inputs ):
61
+ def __init__ (self , input_names = None , output_names = 'out' , function = None ,
62
+ imports = None , ** inputs ):
63
63
"""
64
64
65
65
Parameters
66
66
----------
67
67
68
- input_names: single str or list
68
+ input_names: single str or list or None
69
69
names corresponding to function inputs
70
+ if ``None``, derive input names from function argument names
70
71
output_names: single str or list
71
- names corresponding to function outputs.
72
- has to match the number of outputs
72
+ names corresponding to function outputs (default: 'out') .
73
+ if list of length > 1, has to match the number of outputs
73
74
function : callable
74
75
callable python object. must be able to execute in an
75
76
isolated namespace (possibly in concert with the ``imports``
@@ -88,10 +89,18 @@ def __init__(self, input_names, output_names, function=None, imports=None,
88
89
raise Exception ('Interface Function does not accept '
89
90
'function objects defined interactively '
90
91
'in a python session' )
92
+ else :
93
+ if input_names is None :
94
+ fninfo = function .__code__
91
95
elif isinstance (function , (str , bytes )):
92
96
self .inputs .function_str = function
97
+ if input_names is None :
98
+ fninfo = create_function_from_source (
99
+ function , imports ).__code__
93
100
else :
94
101
raise Exception ('Unknown type of function' )
102
+ if input_names is None :
103
+ input_names = fninfo .co_varnames [:fninfo .co_argcount ]
95
104
self .inputs .on_trait_change (self ._set_function_string ,
96
105
'function_str' )
97
106
self ._input_names = filename_to_list (input_names )
@@ -106,10 +115,18 @@ def _set_function_string(self, obj, name, old, new):
106
115
if name == 'function_str' :
107
116
if hasattr (new , '__call__' ):
108
117
function_source = getsource (new )
118
+ fninfo = new .__code__
109
119
elif isinstance (new , (str , bytes )):
110
120
function_source = new
121
+ fninfo = create_function_from_source (
122
+ new , self .imports ).__code__
111
123
self .inputs .trait_set (trait_change_notify = False ,
112
124
** {'%s' % name : function_source })
125
+ # Update input traits
126
+ input_names = fninfo .co_varnames [:fninfo .co_argcount ]
127
+ new_names = set (input_names ) - set (self ._input_names )
128
+ add_traits (self .inputs , list (new_names ))
129
+ self ._input_names .extend (new_names )
113
130
114
131
def _add_output_traits (self , base ):
115
132
undefined_traits = {}
0 commit comments