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 == 'list_val_or_list_of_list_val':
190 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)
191 elif py_type == 'none':
192 lib.arg_check.is_none(value, desc_short)
193 elif py_type == 'num':
194 lib.arg_check.is_num(value, desc_short, can_be_none=can_be_none)
195 elif py_type == 'num_list':
196 lib.arg_check.is_num_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
197 elif py_type == 'num_or_num_tuple':
198 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)
199 elif py_type == 'num_tuple':
200 lib.arg_check.is_num_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
201 elif py_type == 'str':
202 lib.arg_check.is_str(value, desc_short, can_be_none=can_be_none)
203 elif py_type == 'str_list':
204 lib.arg_check.is_str_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
205 elif py_type == 'str_list_of_lists':
206 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)
207 elif py_type == 'str_or_inst':
208 lib.arg_check.is_str_or_inst(value, desc_short, can_be_none=can_be_none)
209 elif py_type == 'str_or_num_or_str_num_list':
210 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)
211 elif py_type == 'str_or_num_list':
212 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)
213 elif py_type == 'str_or_str_list':
214 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)
215 elif py_type == 'tuple':
216 lib.arg_check.is_tuple(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
217 elif py_type == 'val_or_list':
218 lib.arg_check.is_val_or_list(value, desc_short, size=dim, can_be_none=can_be_none, can_be_empty=can_be_empty)
219 else:
220 raise RelaxError("User function %s - the Python object type '%s' is unknown." % (self._name, py_type))
221
222
223 self._backend(*new_args, **uf_kargs)
224
225
226 - def __init__(self, name, title=None, kargs=None, backend=None, desc=None):
227 """Set up the object.
228
229 @param name: The name of the user function.
230 @type name: str
231 @keyword title: The long title of the user function.
232 @type title: str
233 @keyword kargs: The list of keyword argument details.
234 @type kargs: list of dict
235 @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)!
236 @type backend: executable object
237 @keyword desc: The full, multi-paragraph description.
238 @type desc: str
239 """
240
241
242 self._name = name
243 self._title = title
244 self._kargs = kargs
245 self._backend = backend
246 self._desc = desc
247
248
249 if title == None:
250 raise RelaxError("The title must be given.")
251
252
253 self._karg_num = len(self._kargs)
254 self._karg_names = []
255 for i in range(self._karg_num):
256 self._karg_names.append(self._kargs[i]['name'])
257
258
260 """Replacement function for displaying an instance of this user function class."""
261
262
263 return "<The %s user function>" % self._name
264
265
267 """Create the user function documentation.
268
269 @return: The user function documentation to use in the help system.
270 @rtype: str
271 """
272
273
274 if not isinstance(self._desc, list):
275 raise RelaxError("The user function 'desc' variable must be a list of Desc_container instances.")
276 for i in range(len(self._desc)):
277 if not isinstance(self._desc[i], Desc_container):
278 raise RelaxError("The user function 'desc' list element '%s' must be a list of Desc_container instances." % self._desc[i])
279
280
281 doc = ""
282
283
284 doc += build_subtitle("The %s user function." % self._name, start_nl=False)
285
286
287 doc += build_subtitle("Synopsis")
288 doc += "%s" % self._title
289 doc += "\n\n"
290
291
292 doc += build_subtitle("Defaults")
293 keys = []
294 values = []
295 for i in range(self._karg_num):
296 keys.append(self._kargs[i]['name'])
297 values.append(self._kargs[i]['default'])
298 doc += "%s" % format_text(self._intro_text(keys, values, prompt=False))
299 doc += "\n\n"
300
301
302 if self._kargs != None:
303 doc += build_subtitle("Keyword Arguments")
304 for i in range(len(self._kargs)):
305
306 text = " %s: %s" % (self._kargs[i]['name'], self._kargs[i]['desc'])
307
308
309 text = format_text(text)
310
311
312 length = 7 + len(self._kargs[i]['name'])
313 text = " %s: %s" % (bold_text(self._kargs[i]['name']), text[length:])
314
315
316 doc += "%s\n" % text
317
318
319 if isinstance(self._desc, list) and len(self._desc):
320
321 for i in range(len(self._desc)):
322
323 doc += build_subtitle(self._desc[i].get_title())
324
325
326 for type, element in self._desc[i].element_loop():
327
328 if type == 'paragraph':
329 doc += format_text(element) + '\n'
330
331
332 elif type == 'verbatim':
333 doc += element + '\n\n'
334
335
336 elif type == 'list':
337
338 for j in range(len(element)):
339 doc += format_text(" - %s" % element[j])
340
341
342 doc += '\n'
343
344
345 elif type == 'item list':
346
347 for j in range(len(element)):
348
349 if element[j][0] in [None, '']:
350 doc += format_text(" %s" % element[j][1])
351 else:
352 doc += format_text(" %s: %s" % (element[j][0], element[j][1]))
353
354
355 doc += '\n'
356
357
358 elif type == 'table':
359 doc += create_table(element) + '\n'
360
361
362 elif type == 'prompt':
363
364 for j in range(len(element)):
365 doc += format_text(element[j])
366
367
368 doc += '\n\n'
369
370
371 return doc
372
373
374 - def _intro_text(self, keys, values, prompt=True):
375 """Build and return the user function intro text.
376
377 @param keys: The user function keys.
378 @type keys: list of str
379 @param values: The values corresponding to the keys.
380 @type values: list
381 @keyword prompt: A flag which if True will cause the prompt text to be included.
382 @type prompt: bool
383 @return: The user function intro text.
384 @rtype: str
385 """
386
387
388 text = ""
389
390
391 if prompt:
392 text += status.ps3
393
394
395 text += "%s(" % self._name
396
397
398 for i in range(len(keys)):
399
400 if i >= 1:
401 text += ", "
402
403
404 text += "%s=%s" % (keys[i], repr(values[i]))
405
406
407 text += ")"
408
409
410 return text
411