Package prompt :: Module interpreter
[hide private]
[frames] | no frames]

Source Code for Module prompt.interpreter

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-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 prompt based relax user interface (UI).""" 
 25   
 26  # Dependency check module. 
 27  import dep_check 
 28   
 29  # Python module imports. 
 30  import ansi 
 31  from code import InteractiveConsole, softspace 
 32  from os import F_OK, access, chdir, getcwd, path 
 33  import platform 
 34  from re import search 
 35  if dep_check.readline_module: 
 36      import readline 
 37  if dep_check.runpy_module: 
 38      import runpy 
 39  import sys 
 40   
 41  # Python modules accessible on the command prompt. 
 42  from math import pi 
 43   
 44  # RelaxError system. 
 45  from relax_errors import AllRelaxErrors, RelaxBinError, RelaxError, RelaxNoneError, RelaxStrError 
 46   
 47  # Auxiliary modules. 
 48  from base_class import Exec_info 
 49  from command import Ls, Lh, Ll, system 
 50  from help import _Helper, _Helper_python 
 51  from info import Info_box 
 52  if dep_check.readline_module: 
 53      from tab_completion import Tab_completion 
 54  from status import Status; status = Status() 
 55   
 56  # User functions. 
 57  from angles import Angles 
 58  from dx import OpenDX 
 59  from eliminate import Eliminate 
 60  from fix import Fix 
 61  from gpl import GPL 
 62  from reset import Reset 
 63  from minimisation import Minimisation 
 64  from model_selection import Modsel 
 65  from sys_info import Sys_info 
 66  from temperature import Temp 
 67   
 68  # User classes. 
 69  from align_tensor import Align_tensor 
 70  from bmrb import BMRB 
 71  from bruker import Bruker 
 72  from consistency_tests import Consistency_tests 
 73  from dasha import Dasha 
 74  from diffusion_tensor import Diffusion_tensor 
 75  from frame_order import Frame_order 
 76  from frq import Frq 
 77  from grace import Grace 
 78  from jw_mapping import Jw_mapping 
 79  from model_free import Model_free 
 80  from molmol import Molmol 
 81  from molecule import Molecule 
 82  from monte_carlo import Monte_carlo 
 83  from n_state_model import N_state_model 
 84  from noe import Noe 
 85  from palmer import Palmer 
 86  from residue import Residue 
 87  from structure import Structure 
 88  from paramag import Paramag 
 89  from pcs import PCS 
 90  from pymol_control import Pymol 
 91  from rdc import RDC 
 92  from relax_data import Relax_data 
 93  from relax_fit import Relax_fit 
 94  from results import Results 
 95  from pipe import Pipe 
 96  from select import Select 
 97  from sequence import Sequence 
 98  from spectrum import Spectrum 
 99  from spin import Spin 
100  from state import State 
101  from deselect import Deselect 
102  from value import Value 
103  from vmd import Vmd 
104   
105   
106 -class Interpreter:
107 - def __init__(self, show_script=True, quit=True, raise_relax_error=False):
108 """The interpreter class. 109 110 @param show_script: If true, the relax will print the script contents prior to 111 executing the script. 112 @type show_script: bool 113 @param quit: If true, the default, then relax will exit after running the 114 run() method. 115 @type quit: bool 116 @param raise_relax_error: If false, the default, then relax will print a nice error 117 message to STDERR, without a traceback, when a RelaxError 118 occurs. This is to make things nicer for the user. 119 @type raise_relax_error: bool 120 """ 121 122 # Place the arguments in the class namespace. 123 self.__show_script = show_script 124 self.__quit_flag = quit 125 self.__raise_relax_error = raise_relax_error 126 127 # Build the intro string. 128 info = Info_box() 129 self.__intro_string = info.intro_text() 130 131 # Initialise the execution information container (info that can change during execution). 132 self._exec_info = Exec_info() 133 134 # The prompts (change the Python prompt, as well as the function print outs). 135 if ansi.enable_control_chars(stream=1): 136 self._exec_info.prompt_colour_on() 137 else: 138 self._exec_info.prompt_colour_off() 139 140 # The function intro flag (store in the execution information container). 141 self._exec_info.intro = False 142 143 # Set up the interpreter objects. 144 self._locals = self._setup()
145 146
147 - def _setup(self):
148 """Set up all the interpreter objects. 149 150 All objects are initialised and placed in a dictionary. These will be later placed in different namespaces such as the run() method local namespace. 151 152 @return: The dictionary of interpreter objects. 153 @rtype: dict 154 """ 155 156 # Initialise the dictionary. 157 objects = {} 158 159 # Python modules. 160 objects['pi'] = pi 161 162 # Import the functions emulating system commands. 163 objects['lh'] = Lh() 164 objects['ll'] = Ll() 165 objects['ls'] = Ls() 166 objects['system'] = system 167 168 # Place functions in the local namespace. 169 objects['gpl'] = objects['GPL'] = GPL() 170 171 # Initialise the user functions (those not in user function classes) 172 angles = Angles(self._exec_info) 173 eliminate = Eliminate(self._exec_info) 174 fix = Fix(self._exec_info) 175 reset = Reset(self._exec_info) 176 minimisation = Minimisation(self._exec_info) 177 modsel = Modsel(self._exec_info) 178 opendx = OpenDX(self._exec_info) 179 sys_info = Sys_info(self._exec_info) 180 temp = Temp(self._exec_info) 181 182 # Place the user functions in the local namespace. 183 objects['angle_diff_frame'] = angles.angle_diff_frame 184 objects['calc'] = minimisation.calc 185 objects['eliminate'] = eliminate.eliminate 186 objects['fix'] = fix.fix 187 objects['grid_search'] = minimisation.grid_search 188 objects['reset'] = reset.reset 189 objects['minimise'] = minimisation.minimise 190 objects['model_selection'] = modsel.model_selection 191 objects['sys_info'] = sys_info.sys_info 192 objects['temperature'] = temp.set 193 194 # Place the user classes in the local namespace. 195 objects['align_tensor'] = Align_tensor(self._exec_info) 196 objects['bmrb'] = BMRB(self._exec_info) 197 objects['bruker'] = Bruker(self._exec_info) 198 objects['consistency_tests'] = Consistency_tests(self._exec_info) 199 objects['dasha'] = Dasha(self._exec_info) 200 objects['deselect'] = Deselect(self._exec_info) 201 objects['diffusion_tensor'] = Diffusion_tensor(self._exec_info) 202 objects['frame_order'] = Frame_order(self._exec_info) 203 objects['dx'] = OpenDX(self._exec_info) 204 objects['frq'] = Frq(self._exec_info) 205 objects['grace'] = Grace(self._exec_info) 206 objects['jw_mapping'] = Jw_mapping(self._exec_info) 207 objects['model_free'] = Model_free(self._exec_info) 208 objects['molmol'] = Molmol(self._exec_info) 209 objects['molecule'] = Molecule(self._exec_info) 210 objects['monte_carlo'] = Monte_carlo(self._exec_info) 211 objects['n_state_model'] = N_state_model(self._exec_info) 212 objects['noe'] = Noe(self._exec_info) 213 objects['palmer'] = Palmer(self._exec_info) 214 objects['paramag'] = Paramag(self._exec_info) 215 objects['pcs'] = PCS(self._exec_info) 216 objects['pymol'] = Pymol(self._exec_info) 217 objects['rdc'] = RDC(self._exec_info) 218 objects['relax_data'] = Relax_data(self._exec_info) 219 objects['relax_fit'] = Relax_fit(self._exec_info) 220 objects['residue'] = Residue(self._exec_info) 221 objects['results'] = Results(self._exec_info) 222 objects['pipe'] = Pipe(self._exec_info) 223 objects['select'] = Select(self._exec_info) 224 objects['sequence'] = Sequence(self._exec_info) 225 objects['spectrum'] = Spectrum(self._exec_info) 226 objects['spin'] = Spin(self._exec_info) 227 objects['state'] = State(self._exec_info) 228 objects['structure'] = Structure(self._exec_info) 229 objects['value'] = Value(self._exec_info) 230 objects['vmd'] = Vmd(self._exec_info) 231 232 # Builtin interpreter functions. 233 objects['intro_off'] = self.off 234 objects['intro_on'] = self.on 235 objects['exit'] = objects['bye'] = objects['quit'] = objects['q'] = _Exit() 236 objects['script'] = self.script 237 238 # Modify the help system. 239 objects['help_python'] = _Helper_python() 240 objects['help'] = _Helper() 241 242 # Return the dictionary. 243 return objects
244 245
246 - def off(self, verbose=True):
247 """Turn the function introductions off.""" 248 249 self._exec_info.intro = False 250 251 # Print out. 252 if verbose: 253 print("Echoing of user function calls has been disabled.")
254 255
256 - def on(self, verbose=True):
257 """Turn the function introductions on.""" 258 259 self._exec_info.intro = True 260 261 # Print out. 262 if verbose: 263 print("Echoing of user function calls has been enabled.")
264 265
266 - def populate_self(self):
267 """Place all user functions and other special objects into self.""" 268 269 # Add the interpreter objects to the class namespace. 270 for name in self._locals.keys(): 271 setattr(self, name, self._locals[name])
272 273
274 - def run(self, script_file=None):
275 """Run the python interpreter. 276 277 The namespace of this function is the namespace seen inside the interpreter. All user 278 accessible functions, classes, etc, should be placed in this namespace. 279 280 281 @param script_file: The script file to be executed. For the interpreter mode, this 282 should be left as None. 283 @type script_file: None or str 284 """ 285 286 # Add the interpreter objects to the local run namespace. 287 for name in self._locals.keys(): 288 locals()[name] = self._locals[name] 289 290 # Setup tab completion. 291 if dep_check.readline_module: 292 readline.set_completer(Tab_completion(name_space=locals()).finish) 293 readline.set_completer_delims(' \t\n`~!@#$%^&*()=+{}\\|;:",<>/?') 294 readline.parse_and_bind("tab: complete") 295 296 # Execute the script file if given. 297 if script_file: 298 # Turn on the function intro flag. 299 self._exec_info.intro = True 300 301 # Run the script. 302 return run_script(intro=self.__intro_string, local=locals(), script_file=script_file, quit=self.__quit_flag, show_script=self.__show_script, raise_relax_error=self.__raise_relax_error) 303 304 # Go to the prompt. 305 else: 306 prompt(intro=self.__intro_string, local=locals())
307 308
309 - def script(self, file=None, quit=False):
310 """Function for executing a script file.""" 311 312 # Function intro text. 313 if self._exec_info.intro: 314 text = self._exec_info.ps3 + "script(" 315 text = text + "file=" + repr(file) 316 text = text + ", quit=" + repr(quit) + ")" 317 print(text) 318 319 # File argument. 320 if file == None: 321 raise RelaxNoneError('file') 322 elif not isinstance(file, str): 323 raise RelaxStrError('file', file) 324 325 # Test if the script file exists. 326 if not access(file, F_OK): 327 raise RelaxError("The script file '" + file + "' does not exist.") 328 329 # Quit argument. 330 if not isinstance(quit, int) or (quit != False and quit != True): 331 raise RelaxBinError('quit', quit) 332 333 # Turn on the function intro flag. 334 orig_intro_state = self._exec_info.intro 335 self._exec_info.intro = True 336 337 # Execute the script. 338 run_script(local=self._locals, script_file=file, quit=quit) 339 340 # Return the function intro flag to the original value. 341 self._exec_info.intro = orig_intro_state
342 343
344 -class _Exit:
345 - def __repr__(self):
346 """Exit the program.""" 347 348 print("Exiting the program.") 349 sys.exit()
350 351 352
353 -def exec_script(name, globals):
354 """Execute the script.""" 355 356 # Execution lock. 357 status.exec_lock.acquire('script UI', mode='script') 358 359 # The module path. 360 head, tail = path.split(name) 361 script_path = path.join(getcwd(), head) 362 sys.path.append(script_path) 363 364 # Switch directories for nested scripting. 365 if head: 366 orig_dir = getcwd() 367 chdir(head) 368 369 # The module name. 370 module, ext = path.splitext(tail) 371 372 # Check if the script name is ok. 373 if search('\.', module): 374 raise RelaxError("The relax script must not contain the '.' character (except before the extension '*.py').") 375 if ext != '.py': 376 raise RelaxError("The script must have the extension *.py.") 377 378 # Execute the module. 379 try: 380 # Reverse the system path so that the script path is first. 381 sys.path.reverse() 382 383 # Execute the script as a module. 384 if dep_check.runpy_module: 385 runpy.run_module(module, globals) 386 387 # Allow scripts to run under Python <= 2.4. 388 else: 389 exec(compile(open(name).read(), name, 'exec'), globals) 390 391 finally: 392 # Switch back to the original working directory. 393 if head: 394 chdir(orig_dir) 395 396 # Remove the script path. 397 sys.path.reverse() 398 sys.path.pop(sys.path.index(script_path)) 399 400 # Unlock execution if needed. 401 status.exec_lock.release()
402 403
404 -def interact_prompt(self, intro=None, local={}):
405 """Replacement function for 'code.InteractiveConsole.interact'. 406 407 This will enter into the prompt. 408 409 @param intro: The string to print prior to jumping to the prompt mode. 410 @type intro: str 411 @param local: A namespace which will become that of the prompt (i.e. the namespace visible to 412 the user when in the prompt mode). This should be the output of a function such 413 as locals(). 414 @type local: dict 415 """ 416 417 # Print the program introduction. 418 if intro: 419 sys.stdout.write("%s\n" % intro) 420 421 # Ignore SIGINT. 422 #signal.signal(2, 1) 423 424 # Prompt. 425 more = False 426 while True: 427 try: 428 if more: 429 prompt = sys.ps2 430 else: 431 prompt = sys.ps1 432 try: 433 line = self.raw_input(prompt) 434 except EOFError: 435 self.write("\n") 436 break 437 else: 438 more = self.push(line) 439 except KeyboardInterrupt: 440 self.write("\nKeyboardInterrupt\n") 441 self.resetbuffer() 442 more = False
443 444
445 -def interact_script(self, intro=None, local={}, script_file=None, quit=True, show_script=True, raise_relax_error=False):
446 """Replacement function for 'code.InteractiveConsole.interact'. 447 448 This will execute the script file. 449 450 451 @param intro: The string to print prior to jumping to the prompt mode. 452 @type intro: str 453 @param local: A namespace which will become that of the prompt (i.e. the namespace 454 visible to the user when in the prompt mode). This should be the 455 output of a function such as locals(). 456 @type local: dict 457 @param script_file: The script file to be executed. 458 @type script_file: None or str 459 @param quit: If true, the default, then relax will exit after running the script. 460 @type quit: bool 461 @param show_script: If true, the relax will print the script contents prior to executing 462 the script. 463 @type show_script: bool 464 @param raise_relax_error: If false, the default, then a nice error message will be sent to 465 STDERR, without a traceback, when a RelaxError occurs. This is to 466 make things nicer for the user. 467 @type raise_relax_error: bool 468 """ 469 470 # Print the program introduction. 471 if intro: 472 sys.stdout.write("%s\n" % intro) 473 474 # Print the script. 475 if show_script: 476 try: 477 file = open(script_file, 'r') 478 except IOError, warning: 479 try: 480 raise RelaxError("The script file '" + script_file + "' does not exist.") 481 except AllRelaxErrors, instance: 482 sys.stdout.write(instance.__str__()) 483 sys.stdout.write("\n") 484 return 485 486 # Coloured text. 487 if ansi.enable_control_chars(stream=1): 488 sys.stdout.write(ansi.script) 489 490 # Print the script. 491 sys.stdout.write("script = " + repr(script_file) + "\n") 492 sys.stdout.write("----------------------------------------------------------------------------------------------------\n") 493 sys.stdout.write(file.read()) 494 sys.stdout.write("----------------------------------------------------------------------------------------------------") 495 496 # End coloured text. 497 if ansi.enable_control_chars(stream=1): 498 sys.stdout.write(ansi.end) 499 500 # Terminating newline. 501 sys.stdout.write("\n") 502 503 # Close the script file handle. 504 file.close() 505 506 # The execution flag. 507 exec_pass = True 508 509 # Execute the script. 510 try: 511 exec_script(script_file, local) 512 513 # Catch ctrl-C. 514 except KeyboardInterrupt: 515 # Unlock execution. 516 status.exec_lock.release() 517 518 # Throw the error. 519 if status.debug: 520 raise 521 522 # Be nicer to the user. 523 else: 524 sys.stderr.write("\nScript execution cancelled.\n") 525 526 # The script failed. 527 exec_pass = False 528 529 # Catch the RelaxErrors. 530 except AllRelaxErrors, instance: 531 # Unlock execution. 532 status.exec_lock.release() 533 534 # Throw the error. 535 if raise_relax_error: 536 raise 537 538 # Nice output for the user. 539 else: 540 # Print the scary traceback normally hidden from the user. 541 if status.debug: 542 self.showtraceback() 543 544 # Print the RelaxError message line. 545 else: 546 sys.stderr.write(instance.__str__()) 547 548 # The script failed. 549 exec_pass = False 550 551 # Throw all other errors. 552 except: 553 # Unlock execution. 554 status.exec_lock.release() 555 556 # Raise the error. 557 raise 558 559 # Add an empty line to make exiting relax look better. 560 if show_script: 561 sys.stdout.write("\n") 562 563 # Quit relax. 564 # FIXME: need to drop off end of interpreter loop to exit cleanly 565 #if quit: 566 # sys.exit() 567 568 # Return the execution flag. 569 return exec_pass
570 571
572 -def prompt(intro=None, local=None):
573 """Python interpreter emulation. 574 575 This function replaces 'code.interact'. 576 577 578 @param intro: The string to print prior to jumping to the prompt mode. 579 @type intro: str 580 @param local: A namespace which will become that of the prompt (i.e. the namespace visible to 581 the user when in the prompt mode). This should be the output of a function such 582 as locals(). 583 @type local: dict 584 """ 585 586 # Replace the 'InteractiveConsole.interact' and 'InteractiveConsole.runcode' functions. 587 InteractiveConsole.interact = interact_prompt 588 InteractiveConsole.runcode = runcode 589 590 # The console. 591 console = InteractiveConsole(local) 592 console.interact(intro, local)
593 594
595 -def run_script(intro=None, local=None, script_file=None, quit=True, show_script=True, raise_relax_error=False):
596 """Python interpreter emulation. 597 598 This function replaces 'code.interact'. 599 600 601 @param intro: The string to print prior to jumping to the prompt mode. 602 @type intro: str 603 @param local: A namespace which will become that of the prompt (i.e. the namespace 604 visible to the user when in the prompt mode). This should be the 605 output of a function such as locals(). 606 @type local: dict 607 @param script_file: The script file to be executed. 608 @type script_file: None or str 609 @param quit: If true, the default, then relax will exit after running the script. 610 @type quit: bool 611 @param show_script: If true, the relax will print the script contents prior to executing 612 the script. 613 @type show_script: bool 614 @param raise_relax_error: If false, the default, then a nice error message will be sent to 615 STDERR, without a traceback, when a RelaxError occurs. This is to 616 make things nicer for the user. 617 @type raise_relax_error: bool 618 """ 619 620 # Replace the 'InteractiveConsole.interact' and 'InteractiveConsole.runcode' functions. 621 InteractiveConsole.interact = interact_script 622 InteractiveConsole.runcode = runcode 623 624 # The console. 625 console = InteractiveConsole(local) 626 return console.interact(intro, local, script_file, quit, show_script=show_script, raise_relax_error=raise_relax_error)
627 628
629 -def runcode(self, code):
630 """Replacement code for code.InteractiveInterpreter.runcode. 631 632 @param code: The code to execute. 633 @type code: str 634 """ 635 636 try: 637 exec(code, self.locals) 638 except SystemExit: 639 raise 640 except AllRelaxErrors, instance: 641 self.write(instance.__str__()) 642 self.write("\n") 643 except: 644 self.showtraceback() 645 else: 646 if softspace(sys.stdout, 0): 647 print('')
648