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