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("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                  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 == 'float_object': 
178                  arg_check.is_float_object(value, desc_short, dim=dim, can_be_none=can_be_none) 
179              elif py_type == 'func': 
180                  arg_check.is_func(value, desc_short, can_be_none=can_be_none) 
181              elif py_type == 'int': 
182                  arg_check.is_int(value, desc_short, can_be_none=can_be_none) 
183              elif py_type == 'int_list': 
184                  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                  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                  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                  arg_check.is_none(value, desc_short) 
191              elif py_type == 'num': 
192                  arg_check.is_num(value, desc_short, can_be_none=can_be_none) 
193              elif py_type == 'num_list': 
194                  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                  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                  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                  arg_check.is_str(value, desc_short, can_be_none=can_be_none) 
201              elif py_type == 'str_list': 
202                  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                  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                  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                  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                  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                  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                  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                  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 'generic_fns.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