1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """The special auto-generated user function and class objects."""
25
26
27 import lib.arg_check
28 from prompt.uf_docstring import bold_text, build_subtitle, create_table, format_text
29 from prompt.help import relax_class_help
30 from lib.errors import RelaxError
31 from lib.text.string import strip_lead
32 from status import Status; status = Status()
33 from user_functions.data import Uf_info; uf_info = Uf_info()
34 from user_functions.objects import Desc_container
35
36
38 """The container for created the user function class objects."""
39
41 """Set up the container.
42
43 @param name: The name of the user function class.
44 @type name: str
45 @param desc: The description to be presented by the help system.
46 @type desc: str
47 """
48
49
50 self._name = name
51 self._desc = desc
52
53
55 """Replacement function for displaying an instance of this user function class."""
56
57
58 return "<The %s user function class object>" % self._name
59
60
108
109
110
112 """The object for auto-generating the user functions."""
113
114 - def __call__(self, *uf_args, **uf_kargs):
115 """Make the user function executable."""
116
117
118 for name in uf_kargs:
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 uf_kargs:
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:
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 == 'int_list_of_lists':
188 lib.arg_check.is_int_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty, none_elements=none_elements, list_of_lists=True)
189 elif py_type == 'list':
190 lib.arg_check.is_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
191 elif py_type == 'list_val_or_list_of_list_val':
192 lib.arg_check.is_list_val_or_list_of_list_val(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty, list_of_lists=True)
193 elif py_type == 'none':
194 lib.arg_check.is_none(value, desc_short)
195 elif py_type == 'num':
196 lib.arg_check.is_num(value, desc_short, can_be_none=can_be_none)
197 elif py_type == 'num_list':
198 lib.arg_check.is_num_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
199 elif py_type == 'num_or_num_tuple':
200 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)
201 elif py_type == 'num_tuple':
202 lib.arg_check.is_num_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
203 elif py_type == 'str':
204 lib.arg_check.is_str(value, desc_short, can_be_none=can_be_none)
205 elif py_type == 'str_list':
206 lib.arg_check.is_str_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
207 elif py_type == 'str_list_of_lists':
208 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)
209 elif py_type == 'str_or_inst':
210 lib.arg_check.is_str_or_inst(value, desc_short, can_be_none=can_be_none)
211 elif py_type == 'str_or_num_or_str_num_list':
212 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)
213 elif py_type == 'str_or_num_list':
214 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)
215 elif py_type == 'str_or_str_list':
216 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)
217 elif py_type == 'tuple':
218 lib.arg_check.is_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
219 elif py_type == 'val_or_list':
220 lib.arg_check.is_val_or_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
221 else:
222 raise RelaxError("User function %s - the Python object type '%s' is unknown." % (self._name, py_type))
223
224
225 self._backend(*new_args, **uf_kargs)
226
227
228 - def __init__(self, name, title=None, kargs=None, backend=None, desc=None):
229 """Set up the object.
230
231 @param name: The name of the user function.
232 @type name: str
233 @keyword title: The long title of the user function.
234 @type title: str
235 @keyword kargs: The list of keyword argument details.
236 @type kargs: list of dict
237 @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)!
238 @type backend: executable object
239 @keyword desc: The full, multi-paragraph description.
240 @type desc: str
241 """
242
243
244 self._name = name
245 self._title = title
246 self._kargs = kargs
247 self._backend = backend
248 self._desc = desc
249
250
251 if title == None:
252 raise RelaxError("The title must be given.")
253
254
255 self._karg_num = len(self._kargs)
256 self._karg_names = []
257 for i in range(self._karg_num):
258 self._karg_names.append(self._kargs[i]['name'])
259
260
262 """Replacement function for displaying an instance of this user function class."""
263
264
265 return "<The %s user function>" % self._name
266
267
269 """Create the user function documentation.
270
271 @return: The user function documentation to use in the help system.
272 @rtype: str
273 """
274
275
276 if not isinstance(self._desc, list):
277 raise RelaxError("The user function 'desc' variable must be a list of Desc_container instances.")
278 for i in range(len(self._desc)):
279 if not isinstance(self._desc[i], Desc_container):
280 raise RelaxError("The user function 'desc' list element '%s' must be a list of Desc_container instances." % self._desc[i])
281
282
283 doc = ""
284
285
286 doc += build_subtitle("The %s user function." % self._name, start_nl=False)
287
288
289 doc += build_subtitle("Synopsis")
290 doc += "%s" % self._title
291 doc += "\n\n"
292
293
294 doc += build_subtitle("Defaults")
295 keys = []
296 values = []
297 for i in range(self._karg_num):
298 keys.append(self._kargs[i]['name'])
299 values.append(self._kargs[i]['default'])
300 doc += "%s" % format_text(self._intro_text(keys, values, prompt=False))
301 doc += "\n\n"
302
303
304 if self._kargs != None:
305 doc += build_subtitle("Keyword Arguments")
306 for i in range(len(self._kargs)):
307
308 text = " %s: %s" % (self._kargs[i]['name'], self._kargs[i]['desc'])
309
310
311 text = format_text(text)
312
313
314 length = 7 + len(self._kargs[i]['name'])
315 text = " %s: %s" % (bold_text(self._kargs[i]['name']), text[length:])
316
317
318 doc += "%s\n" % text
319
320
321 if isinstance(self._desc, list) and len(self._desc):
322
323 for i in range(len(self._desc)):
324
325 doc += build_subtitle(self._desc[i].get_title())
326
327
328 for type, element in self._desc[i].element_loop():
329
330 if type == 'paragraph':
331 doc += format_text(element) + '\n'
332
333
334 elif type == 'verbatim':
335 doc += element + '\n\n'
336
337
338 elif type == 'list':
339
340 for j in range(len(element)):
341 doc += format_text(" - %s" % element[j])
342
343
344 doc += '\n'
345
346
347 elif type == 'item list':
348
349 for j in range(len(element)):
350
351 if element[j][0] in [None, '']:
352 doc += format_text(" %s" % element[j][1])
353 else:
354 doc += format_text(" %s: %s" % (element[j][0], element[j][1]))
355
356
357 doc += '\n'
358
359
360 elif type == 'table':
361 doc += create_table(element) + '\n'
362
363
364 elif type == 'prompt':
365
366 for j in range(len(element)):
367 doc += format_text(element[j])
368
369
370 doc += '\n\n'
371
372
373 return doc
374
375
376 - def _intro_text(self, keys, values, prompt=True):
377 """Build and return the user function intro text.
378
379 @param keys: The user function keys.
380 @type keys: list of str
381 @param values: The values corresponding to the keys.
382 @type values: list
383 @keyword prompt: A flag which if True will cause the prompt text to be included.
384 @type prompt: bool
385 @return: The user function intro text.
386 @rtype: str
387 """
388
389
390 text = ""
391
392
393 if prompt:
394 text += status.ps3
395
396
397 text += "%s(" % self._name
398
399
400 for i in range(len(keys)):
401
402 if i >= 1:
403 text += ", "
404
405
406 text += "%s=%s" % (keys[i], repr(values[i]))
407
408
409 text += ")"
410
411
412 return text
413