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