Package user_functions :: Module objects'
[hide private]
[frames] | no frames]

Source Code for Module user_functions.objects'

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2012 Edward d'Auvergne                                        # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax is free software; you can redistribute it and/or modify               # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation; either version 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax is distributed in the hope that it will be useful,                    # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """The module of all the objects used to hold the user function details.""" 
 25   
 26  # Python module imports. 
 27  import wx 
 28   
 29  # relax module imports. 
 30  from graphics import IMAGE_PATH 
 31  from relax_errors import RelaxError 
 32   
 33   
34 -class Class_container:
35 """This class is used to process and store all of the user function class information. 36 37 @ivar title: The user function class description. 38 @type title: str 39 @ivar menu_text: The text to use for the GUI menu entry. 40 @type menu_text: str 41 @ivar gui_icon: The code for the icon to use in the GUI. 42 @type gui_icon: str or None 43 """ 44 45 # The list of modifiable objects (anything else will be rejected to prevent coding errors). 46 __mod_attr__ = [ 47 'title', 48 'menu_text', 49 'gui_icon' 50 ] 51
52 - def __init__(self):
53 """Initialise all the data.""" 54 55 # Initialise the variables for all user function classes. 56 self.title = None 57 self.menu_text = None 58 self.gui_icon = None
59 60
61 - def __setattr__(self, name, value):
62 """Override the class __setattr__ method. 63 64 @param name: The name of the attribute to modify. 65 @type name: str 66 @param value: The new value of the attribute. 67 @type value: anything 68 """ 69 70 # Test if the attribute that is trying to be set is modifiable. 71 if not name in self.__mod_attr__: 72 raise RelaxError("The object '%s' is not a modifiable attribute." % name) 73 74 # Set the attribute normally. 75 self.__dict__[name] = value
76 77 78
79 -class Container:
80 """An empty container object."""
81 82 83
84 -class Desc_container(object):
85 """A special object for holding and processing user function description information.""" 86
87 - def __init__(self, title="Description"):
88 """Set up the container. 89 90 @keyword section: The section title. 91 @type section: str 92 """ 93 94 # Store the title. 95 self._title = title 96 97 # Initialise internal storage objects. 98 self._data = [] 99 self._types = []
100 101
102 - def add_item_list_element(self, item, text):
103 """Add the element of an itemised list to the description. 104 105 @param item: The item text. 106 @type item: str 107 @param text: The itemised list element text. 108 @type text: str 109 """ 110 111 # Create a new block if needed. 112 if not len(self._types) or self._types[-1] != 'item list': 113 self._data.append([[item, text]]) 114 self._types.append('item list') 115 116 # Append the element to an existing itemised list structure. 117 else: 118 self._data[-1].append([item, text])
119 120
121 - def add_list_element(self, text):
122 """Add the element of a list to the description. 123 124 @param text: The list element text. 125 @type text: str 126 """ 127 128 # Create a new block if needed. 129 if not len(self._types) or self._types[-1] != 'list': 130 self._data.append([text]) 131 self._types.append('list') 132 133 # Append the element to an existing list structure. 134 else: 135 self._data[-1].append(text)
136 137
138 - def add_paragraph(self, text):
139 """Add a paragraph of text to the description. 140 141 @param text: The paragraph text. 142 @type text: str 143 """ 144 145 # Store the text. 146 self._data.append(text) 147 self._types.append('paragraph')
148 149
150 - def add_prompt(self, text):
151 """Add the text of a relax prompt example to the description. 152 153 @param text: The relax prompt text. 154 @type text: str 155 """ 156 157 # Create a new block if needed. 158 if not len(self._types) or self._types[-1] != 'prompt': 159 self._data.append([text]) 160 self._types.append('prompt') 161 162 # Append the example to an existing example block. 163 else: 164 self._data[-1].append(text)
165 166
167 - def add_table(self, label):
168 """Add a table to the description. 169 170 @param label: The unique label corresponding to a user_functions.objects.Table instance. 171 @type label: str 172 """ 173 174 # Check. 175 if not isinstance(label, str): 176 raise RelaxError("The table label '%s' is not a valid string.") 177 178 # Add the table. 179 self._data.append(label) 180 self._types.append('table')
181 182
183 - def add_verbatim(self, text):
184 """Add a section of verbatim text to the description. 185 186 @param text: The verbatim text. 187 @type text: str 188 """ 189 190 # Store the text. 191 self._data.append(text) 192 self._types.append('verbatim')
193 194
195 - def element_loop(self, title=False):
196 """Iterator method yielding the description elements. 197 198 @keyword title: A flag which if True will cause the title to be yielded first. 199 @type title: bool 200 @return: The element type and corresponding data. 201 @rtype: str and anything 202 """ 203 204 # The title. 205 if title: 206 yield 'title', self._title 207 208 # Loop over the elements. 209 for i in range(len(self._data)): 210 yield self._types[i], self._data[i]
211 212
213 - def get_title(self):
214 """Return the title of the section. 215 216 @return: The section title. 217 @rtype: str 218 """ 219 220 # The title. 221 return self._title
222 223 224
225 -class Table(object):
226 """A special class defining the tables used in the user function descriptions.""" 227
228 - def __init__(self, label=None, caption=None, caption_short=None, spacing=True, longtable=False):
229 """Set up the table container. 230 231 @keyword label: The unique label of the table. This is used to identify tables, and is also used in the table referencing in the LaTeX compilation of the user manual. 232 @type label: str 233 @keyword caption: The caption for the table. 234 @type caption: str 235 @keyword caption_short: The optional short caption for the table, used in the LaTeX user manual list of tables section for example. 236 @type caption_short: str 237 @keyword spacing: A flag which if True will cause empty rows to be placed between elements. 238 @type spacing: bool 239 @keyword longtable: A special LaTeX flag which if True will cause the longtables package to be used to spread a table across multiple pages. This should only be used for tables that do not fit on a single page. 240 @type longtable: bool 241 """ 242 243 # Store the args. 244 self.label = label 245 self.caption = caption 246 if caption_short: 247 self.caption_short = caption_short 248 else: 249 self.caption_short = caption 250 self.spacing = spacing 251 self.longtable = longtable 252 253 # Initialise some objects. 254 self.headings = None 255 self.cells = [] 256 self.num_cols = 0
257 258
259 - def add_headings(self, headings):
260 """Add a row of table headings. 261 262 @param headings: The table headings. 263 @type headings: list of str 264 """ 265 266 # Store the headings. 267 self.headings = headings 268 269 # The number of columns. 270 self.num_cols = len(self.headings)
271 272
273 - def add_row(self, row):
274 """Add a table row. 275 276 @param row: The table row. 277 @type row: list of str 278 """ 279 280 # Checks. 281 if self.headings == None: 282 raise RelaxError("A row cannot be added as the headings have not been set up.") 283 if len(row) != self.num_cols: 284 raise RelaxError("The number of columns in %s does not match the %s columns of the headings." % (row, self.num_cols)) 285 286 # Append the row. 287 self.cells.append(row)
288 289 290
291 -class Uf_container(object):
292 """This class is used to process and store all of the user function specific information. 293 294 @ivar title: The long title of the user function. 295 @type title: str 296 @ivar title_short: The optional short title. 297 @type title_short: str or None 298 @ivar kargs: The list of keyword argument details. 299 @type kargs: list of dict 300 @ivar 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)! 301 @type backend: executable object 302 @ivar display: A flag specifying if the user function displays output to STDOUT. This is used for certain UIs to display that output. 303 @type display: str 304 @ivar desc: The multi-paragraph description defined via the Desc_container class. 305 @type desc: list of Desc_container instances 306 @ivar menu_text: The text to use for the GUI menu entry. 307 @type menu_text: str 308 @ivar gui_icon: The code for the icon to use in the GUI. 309 @type gui_icon: str or None 310 @ivar wizard_size: The size for the GUI user function wizard. This defaults to (700, 500) if not supplied. 311 @type wizard_size: tuple of int or None 312 @ivar wizard_image: The 200 pixel wide image to use for the user function wizard. This should be the path to the bitmap image. This defaults to the relax Ulysses butterfly image. 313 @type wizard_image: str 314 @ivar wizard_height_desc: The height in pixels of the description part of the wizard. 315 @type wizard_height_desc: int 316 @ivar wizard_apply_button: A flag specifying if the apply button should be shown or not. This defaults to True. 317 @type wizard_apply_button: bool 318 @ivar gui_sync: A GUI flag which if left on the default of False will cause user functions to be called in asynchronous mode. If changed to True, then synchronous operation of the user functions will occur. 319 @type gui_sync: bool 320 """ 321 322 # The list of modifiable objects (anything else will be rejected to prevent coding errors). 323 __mod_attr__ = [ 324 'title', 325 'title_short', 326 'kargs', 327 'backend', 328 'display', 329 'desc', 330 'menu_text', 331 'gui_icon', 332 'wizard_size', 333 'wizard_image', 334 'wizard_height_desc', 335 'wizard_apply_button', 336 'gui_sync', 337 ] 338 339
340 - def __init__(self):
341 """Initialise all the data.""" 342 343 # Initialise the variables for all user functions. 344 self.title = None 345 self.title_short = None 346 self.kargs = [] 347 self.backend = None 348 self.display = False 349 self.desc = [] 350 self.menu_text = '' 351 self.gui_icon = None 352 self.wizard_size = (700, 500) 353 self.wizard_image = IMAGE_PATH + "relax.gif" 354 self.wizard_height_desc = 300 355 self.wizard_apply_button = True 356 self.gui_sync = False
357 358
359 - def __setattr__(self, name, value):
360 """Override the class __setattr__ method. 361 362 @param name: The name of the attribute to modify. 363 @type name: str 364 @param value: The new value of the attribute. 365 @type value: anything 366 """ 367 368 # Test if the attribute that is trying to be set is modifiable. 369 if not name in self.__mod_attr__: 370 raise RelaxError("The object '%s' is not a modifiable attribute." % name) 371 372 # Check for duplicative modifications (to catch typo coding errors). 373 if name in ['title', 'title_short', 'backend', 'gui_icon']: 374 # No object set yet. 375 if not hasattr(self, name): 376 obj = None 377 378 # Get the current object. 379 else: 380 obj = getattr(self, name) 381 382 # Not None! 383 if obj != None: 384 raise RelaxError("The variable '%s' is already set to %s." % (name, repr(obj))) 385 386 # Set the attribute normally. 387 self.__dict__[name] = value
388 389
390 - def add_keyarg(self, name=None, default=None, py_type=None, arg_type=None, dim=None, min=0, max=1000, desc_short=None, desc=None, list_titles=None, wiz_element_type='default', wiz_combo_choices=None, wiz_combo_data=None, wiz_combo_iter=None, wiz_combo_list_min=None, wiz_filesel_wildcard=wx.FileSelectorDefaultWildcardStr, wiz_filesel_style=None, wiz_dirsel_style=wx.DD_DEFAULT_STYLE, wiz_read_only=None, can_be_none=False, can_be_empty=False, none_elements=False):
391 """Wrapper method for adding keyword argument information to the container. 392 393 @keyword name: The name of the argument. 394 @type name: str 395 @keyword default: The default value of the argument. 396 @type default: anything 397 @keyword py_type: The Python object type that the argument must match (taking the can_be_none flag into account). 398 @type py_type: str 399 @keyword arg_type: The type of argument. This is reserved for special UI elements: 400 - 'file sel' will indicate to certain UIs that a file selection dialog is required. 401 - 'dir' will cause the argument to not be shown in certain UIs, as this indicates that the user function already has a 'file sel' type argument and hence a directory is not required. 402 - 'dir sel' will indicate to certain UIs that a dir selection dialog is required. 403 @type arg_type: str 404 @keyword dim: The fixed dimensions that a list or tuple must conform to. For a 1D sequence, this can be a single value or a tuple of possible sizes. For a 2D sequence (a numpy matrix or list of lists), this must be a tuple of the fixed dimension sizes, e.g. a 3x5 matrix should be specified as (3, 5). 405 @type dim: int, tuple of int or None 406 @keyword min: The minimum value allowed for integer types. This is used in the wx.SpinCtrl for example. 407 @type min: int 408 @keyword max: The maximum value allowed for integer types. This is used in the wx.SpinCtrl for example. 409 @type max: int 410 @keyword desc_short: The short human-readable description of the argument. This is used in the RelaxError messages to refer to the argument, as well as in the GUI user function page elements. 411 @type desc_short: str 412 @keyword desc: The long human-readable description of the argument. 413 @type desc: str 414 @keyword list_titles: The titles of each of the elements of the fixed width second dimension. This only applies to list of lists. 415 @type list_titles: list of str 416 @keyword wiz_element_type: The type of GUI element to create. If left to 'default', then the currently set default element will be used. If set to 'text', a wx.TextCtrl element will be used. If set to 'combo', a wx.ComboBox element will be used. 417 @type wiz_element_type: str 418 @keyword wiz_combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'. 419 @type wiz_combo_choices: list of str 420 @keyword wiz_combo_data: The data returned by a call to GetValue(). This is only used if the element_type is set to 'combo'. If supplied, it should be the same length at the combo_choices list. If not supplied, the combo_choices list will be used for the returned data. 421 @type wiz_combo_data: list 422 @keyword wiz_combo_iter: An iterator method for regenerating the ComboBox choices. 423 @type wiz_combo_iter: iterator or None 424 @keyword wiz_combo_list_min: The minimum length of the Combo_list element. 425 @type wiz_combo_list_min: int or None 426 @keyword wiz_filesel_wildcard: The file selection dialog wildcard string. For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB". 427 @type wiz_filesel_wildcard: str or None 428 @keyword wiz_filesel_style: The file selection dialog style. 429 @type wiz_filesel_style: int 430 @keyword wiz_dirsel_style: The directory selection dialog style. 431 @type wiz_dirsel_style: int 432 @keyword wiz_read_only: A flag which if True means that the text of the GUI wizard page element cannot be edited. If the default of None is given, then each UI element will decide for itself what to do. 433 @type wiz_read_only: bool or None 434 @keyword can_be_none: A flag which specifies if the argument is allowed to have the None value. 435 @type can_be_none: bool 436 @keyword can_be_empty: A flag which if True allows the sequence type object to be empty. 437 @type can_be_empty: bool 438 @keyword none_elements: A flag which if True allows the sequence type object to contain None elements. 439 @type none_elements: bool 440 """ 441 442 # Check that the args have been properly supplied. 443 if name == None: 444 raise RelaxError("The 'name' argument must be supplied.") 445 if py_type == None: 446 raise RelaxError("The 'py_type' argument must be supplied.") 447 if desc_short == None: 448 raise RelaxError("The 'desc_short' argument must be supplied.") 449 if desc == None: 450 raise RelaxError("The 'desc' argument must be supplied.") 451 452 # Check the file selection dialog. 453 if arg_type == "file sel" and wiz_filesel_style == None: 454 raise RelaxError("The file selection style must always be provided.") 455 456 # Append a new argument dictionary to the list, and alias it. 457 self.kargs.append({}) 458 arg = self.kargs[-1] 459 460 # Add the data. 461 arg['name'] = name 462 arg['default'] = default 463 arg['py_type'] = py_type 464 arg['arg_type'] = arg_type 465 arg['dim'] = dim 466 arg['min'] = min 467 arg['max'] = max 468 arg['desc_short'] = desc_short 469 arg['desc'] = desc 470 arg['list_titles'] = list_titles 471 arg['wiz_element_type'] = wiz_element_type 472 if wiz_combo_choices == None: 473 arg['wiz_combo_choices'] = [] 474 else: 475 arg['wiz_combo_choices'] = wiz_combo_choices 476 arg['wiz_combo_data'] = wiz_combo_data 477 arg['wiz_combo_iter'] = wiz_combo_iter 478 arg['wiz_combo_list_min'] = wiz_combo_list_min 479 arg['wiz_filesel_wildcard'] = wiz_filesel_wildcard 480 arg['wiz_filesel_style'] = wiz_filesel_style 481 arg['wiz_dirsel_style'] = wiz_dirsel_style 482 arg['wiz_read_only'] = wiz_read_only 483 arg['can_be_none'] = can_be_none 484 arg['can_be_empty'] = can_be_empty 485 arg['none_elements'] = none_elements
486