1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The special auto-generated user function and class objects."""
24
25
26 import lib.arg_check
27 from prompt.uf_docstring import bold_text, build_subtitle, create_table, format_text
28 from prompt.help import relax_class_help
29 from lib.errors import RelaxError
30 from lib.text.string import strip_lead
31 from status import Status; status = Status()
32 from user_functions.data import Uf_info; uf_info = Uf_info()
33 from user_functions.objects import Desc_container
34
35
37 """The container for created the user function class objects."""
38
40 """Set up the container.
41
42 @param name: The name of the user function class.
43 @type name: str
44 @param desc: The description to be presented by the help system.
45 @type desc: str
46 """
47
48
49 self._name = name
50 self._desc = desc
51
52
54 """Replacement function for displaying an instance of this user function class."""
55
56
57 return "<The %s user function class object>" % self._name
58
59
107
108
109
111 """The object for auto-generating the user functions."""
112
113 - def __call__(self, *uf_args, **uf_kargs):
114 """Make the user function executable."""
115
116
117 keys = uf_kargs.keys()
118 for name in keys:
119
120 if name not in self._karg_names:
121 raise RelaxError("User function %s - the keyword argument '%s' is unknown." % (self._name, name))
122
123
124 num_args = len(uf_args)
125 new_args = []
126 if num_args:
127 for i in range(num_args):
128
129 if self._kargs[i]['name'] in keys:
130 raise RelaxError("User function %s - the argument '%s' and the keyword argument '%s' cannot both be supplied." % (self._name, uf_args[i], self._kargs[i]['name']))
131
132
133 uf_kargs[self._kargs[i]['name']] = uf_args[i]
134
135
136 for i in range(self._karg_num):
137
138 name = self._kargs[i]['name']
139
140
141 if name not in uf_kargs.keys():
142 uf_kargs[name] = self._kargs[i]['default']
143
144
145 if status.uf_intro:
146
147 keys = []
148 values = []
149 for i in range(self._karg_num):
150 keys.append(self._kargs[i]['name'])
151 values.append(uf_kargs[self._kargs[i]['name']])
152
153
154 print(self._intro_text(keys, values))
155
156
157 for i in range(self._karg_num):
158
159 value = uf_kargs[self._kargs[i]['name']]
160 arg = self._kargs[i]
161 py_type = arg['py_type']
162 desc_short = arg['desc_short']
163 dim = arg['dim']
164 can_be_none = arg['can_be_none']
165 can_be_empty = arg['can_be_empty']
166 none_elements = arg['none_elements']
167
168
169 if py_type == 'bool':
170 lib.arg_check.is_bool(value, desc_short)
171 elif py_type == 'float':
172 lib.arg_check.is_float(value, desc_short, can_be_none=can_be_none)
173 elif py_type == 'float_array':
174 lib.arg_check.is_float_array(value, desc_short, size=dim, can_be_none=can_be_none)
175 elif py_type == 'float_matrix':
176 lib.arg_check.is_float_matrix(value, desc_short, dim=dim, can_be_none=can_be_none)
177 elif py_type == 'float_object':
178 lib.arg_check.is_float_object(value, desc_short, dim=dim, can_be_none=can_be_none)
179 elif py_type == 'func':
180 lib.arg_check.is_func(value, desc_short, can_be_none=can_be_none)
181 elif py_type == 'int':
182 lib.arg_check.is_int(value, desc_short, can_be_none=can_be_none)
183 elif py_type == 'int_list':
184 lib.arg_check.is_int_list(value, desc_short, size=dim, can_be_none=can_be_none)
185 elif py_type == 'int_or_int_list':
186 lib.arg_check.is_int_or_int_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty, none_elements=none_elements)
187 elif py_type == 'list':
188 lib.arg_check.is_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
189 elif py_type == 'none':
190 lib.arg_check.is_none(value, desc_short)
191 elif py_type == 'num':
192 lib.arg_check.is_num(value, desc_short, can_be_none=can_be_none)
193 elif py_type == 'num_list':
194 lib.arg_check.is_num_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
195 elif py_type == 'num_or_num_tuple':
196 lib.arg_check.is_num_or_num_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
197 elif py_type == 'num_tuple':
198 lib.arg_check.is_num_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
199 elif py_type == 'str':
200 lib.arg_check.is_str(value, desc_short, can_be_none=can_be_none)
201 elif py_type == 'str_list':
202 lib.arg_check.is_str_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
203 elif py_type == 'str_list_of_lists':
204 lib.arg_check.is_str_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty, list_of_lists=True)
205 elif py_type == 'str_or_inst':
206 lib.arg_check.is_str_or_inst(value, desc_short, can_be_none=can_be_none)
207 elif py_type == 'str_or_num_or_str_num_list':
208 lib.arg_check.is_str_or_num_or_str_num_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
209 elif py_type == 'str_or_num_list':
210 lib.arg_check.is_str_or_num_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
211 elif py_type == 'str_or_str_list':
212 lib.arg_check.is_str_or_str_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
213 elif py_type == 'tuple':
214 lib.arg_check.is_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
215 elif py_type == 'val_or_list':
216 lib.arg_check.is_val_or_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
217 else:
218 raise RelaxError("User function %s - the Python object type '%s' is unknown." % (self._name, py_type))
219
220
221 self._backend(*new_args, **uf_kargs)
222
223
224 - def __init__(self, name, title=None, kargs=None, backend=None, desc=None):
225 """Set up the object.
226
227 @param name: The name of the user function.
228 @type name: str
229 @keyword title: The long title of the user function.
230 @type title: str
231 @keyword kargs: The list of keyword argument details.
232 @type kargs: list of dict
233 @keyword backend: The user function back end. This should be a string version with full module path of the function which executes the back end. For example 'pipe_control.pipes.create'. Note, this should be importable as __import__(backend)!
234 @type backend: executable object
235 @keyword desc: The full, multi-paragraph description.
236 @type desc: str
237 """
238
239
240 self._name = name
241 self._title = title
242 self._kargs = kargs
243 self._backend = backend
244 self._desc = desc
245
246
247 if title == None:
248 raise RelaxError("The title must be given.")
249
250
251 self._karg_num = len(self._kargs)
252 self._karg_names = []
253 for i in range(self._karg_num):
254 self._karg_names.append(self._kargs[i]['name'])
255
256
258 """Replacement function for displaying an instance of this user function class."""
259
260
261 return "<The %s user function>" % self._name
262
263
265 """Create the user function documentation.
266
267 @return: The user function documentation to use in the help system.
268 @rtype: str
269 """
270
271
272 if not isinstance(self._desc, list):
273 raise RelaxError("The user function 'desc' variable must be a list of Desc_container instances.")
274 for i in range(len(self._desc)):
275 if not isinstance(self._desc[i], Desc_container):
276 raise RelaxError("The user function 'desc' list element '%s' must be a list of Desc_container instances." % self._desc[i])
277
278
279 doc = ""
280
281
282 doc += build_subtitle("The %s user function." % self._name, start_nl=False)
283
284
285 doc += build_subtitle("Synopsis")
286 doc += "%s" % self._title
287 doc += "\n\n"
288
289
290 doc += build_subtitle("Defaults")
291 keys = []
292 values = []
293 for i in range(self._karg_num):
294 keys.append(self._kargs[i]['name'])
295 values.append(self._kargs[i]['default'])
296 doc += "%s" % format_text(self._intro_text(keys, values, prompt=False))
297 doc += "\n\n"
298
299
300 if self._kargs != None:
301 doc += build_subtitle("Keyword Arguments")
302 for i in range(len(self._kargs)):
303
304 text = " %s: %s" % (self._kargs[i]['name'], self._kargs[i]['desc'])
305
306
307 text = format_text(text)
308
309
310 length = 7 + len(self._kargs[i]['name'])
311 text = " %s: %s" % (bold_text(self._kargs[i]['name']), text[length:])
312
313
314 doc += "%s\n" % text
315
316
317 if isinstance(self._desc, list) and len(self._desc):
318
319 for i in range(len(self._desc)):
320
321 doc += build_subtitle(self._desc[i].get_title())
322
323
324 for type, element in self._desc[i].element_loop():
325
326 if type == 'paragraph':
327 doc += format_text(element) + '\n'
328
329
330 elif type == 'verbatim':
331 doc += element + '\n\n'
332
333
334 elif type == 'list':
335
336 for j in range(len(element)):
337 doc += format_text(" - %s" % element[j])
338
339
340 doc += '\n'
341
342
343 elif type == 'item list':
344
345 for j in range(len(element)):
346
347 if element[j][0] in [None, '']:
348 doc += format_text(" %s" % element[j][1])
349 else:
350 doc += format_text(" %s: %s" % (element[j][0], element[j][1]))
351
352
353 doc += '\n'
354
355
356 elif type == 'table':
357 doc += create_table(element) + '\n'
358
359
360 elif type == 'prompt':
361
362 for j in range(len(element)):
363 doc += format_text(element[j])
364
365
366 doc += '\n\n'
367
368
369 return doc
370
371
372 - def _intro_text(self, keys, values, prompt=True):
373 """Build and return the user function intro text.
374
375 @param keys: The user function keys.
376 @type keys: list of str
377 @param values: The values corresponding to the keys.
378 @type values: list
379 @keyword prompt: A flag which if True will cause the prompt text to be included.
380 @type prompt: bool
381 @return: The user function intro text.
382 @rtype: str
383 """
384
385
386 text = ""
387
388
389 if prompt:
390 text += status.ps3
391
392
393 text += "%s(" % self._name
394
395
396 for i in range(len(keys)):
397
398 if i >= 1:
399 text += ", "
400
401
402 text += "%s=%s" % (keys[i], repr(values[i]))
403
404
405 text += ")"
406
407
408 return text
409