Package client :: Module IPythonShell
[hide private]
[frames] | no frames]

Source Code for Module client.IPythonShell

   1  from PyQt4.QtGui  import * 
   2  from PyQt4.QtCore import * 
   3   
   4  import re 
   5  import sys 
   6  import os 
   7  from StringIO import StringIO 
   8  import string 
   9   
  10  import Constants 
  11   
  12  import IPython 
  13   
  14  # Much of the ipython code here is taken from http://ipython.scipy.org/moin/Cookbook/EmbeddingInGTK 
  15  # which is released under the BSD license 
  16  #  
  17  # It provides the backend to a pygtk application, which I have used for a PyQt4 frontend 
  18   
19 -class IPShell:
20 - def __init__ (self, user_ns = None, user_global_ns = None, cin = None, \ 21 cout = None, cerr = None, input_func = None):
22 if input_func: 23 IPython.iplib.raw_input_original = input_func 24 if cin: 25 IPython.Shell.Term.cin = cin 26 if cout: 27 IPython.Shell.Term.cout = cout 28 if cerr: 29 IPython.Shell.Term.cerr = cerr 30 31 # This is to get rid of the blockage that accurs during 32 # IPython.Shell.InteractiveShell.user_setup() 33 IPython.iplib.raw_input = lambda x: None 34 35 self.term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr) 36 os.environ['TERM'] = 'dumb' 37 excepthook = sys.excepthook 38 self.IP = IPython.Shell.make_IPython ([], user_ns = user_ns, 39 user_global_ns = user_global_ns, embedded = True, 40 shell_class = IPython.Shell.InteractiveShell) 41 self.IP.system = lambda cmd: self.shell (self.IP.var_expand (cmd), \ 42 header = 'IPython system call: ', verbose = self.IP.rc.system_verbose) 43 sys.excepthook = excepthook 44 self.iter_more = 0 45 self.history_level = 0 46 self.complete_sep = re.compile('[\s\{\}\[\]\(\)]')
47
48 - def execute(self):
49 orig_stdout = sys.stdout 50 sys.stdout = IPython.Shell.Term.cout 51 try: 52 line = self.IP.raw_input (None, self.iter_more) 53 if self.IP.autoindent: 54 self.IP.readline_startup_hook(None) 55 except KeyboardInterrupt: 56 self.IP.write('\nKeyboardInterrupt\n') 57 self.IP.resetbuffer() 58 self.IP.outputcache.prompt_count -= 1 59 60 if self.IP.autoindent: 61 self.IP.indent_current_nsp = 0 62 self.iter_more = 0 63 except: 64 self.IP.showtraceback() 65 else: 66 self.iter_more = self.IP.push(line) 67 if (self.IP.SyntaxTB.last_syntax_error and 68 self.IP.rc.autoedit_syntax): 69 self.IP.edit_syntax_error() 70 if self.iter_more: 71 self.prompt = stripColor (str(self.IP.outputcache.prompt2).strip()) 72 if self.IP.autoindent: 73 self.IP.readline_startup_hook(self.IP.pre_readline) 74 else: 75 self.prompt = stripColor (str(self.IP.outputcache.prompt1).strip()) 76 sys.stdout = orig_stdout
77 78
79 - def shell (self, cmd,verbose=0,debug=0,header=''):
80 stat = 0 81 if verbose or debug: print header+cmd 82 if not debug: 83 input, output = os.popen4(cmd) 84 output.close() 85 input.close()
86
87 - def complete (self, text):
88 return self.IP.complete (text)
89 90
91 -class CommandHistory (QTextEdit):
92 - def __init__ (self, shell, bridge):
93 """ 94 CommandHistory.__init__ (self, shell, bridge) 95 96 This initialization sets up a normal QTextEdit, then 97 sets up a bunch of color/font/size settings to be used 98 later. After the default settings are loaded, it will 99 attempt to load them from the configuration file C{~/.basin/client/ipython_appearance.conf} 100 """ 101 QTextEdit.__init__ (self) 102 self._bridge = bridge 103 self._shell = shell 104 self.setTextInteractionFlags (Qt.TextBrowserInteraction) 105 shell.addWidget (self) 106 shell.setStretchFactor (self, 8) 107 108 # Defaults if no settings file is found 109 self._bgColor = "#ffffff" 110 self._commandSize = "4" 111 self._commandColor = "#000000" 112 self._commandFont = "Courier" 113 self._commandDecorations = ["b"] 114 self._resultSize = "4" 115 self._resultColor = "#20aa20" 116 self._resultFont = "Courier" 117 self._resultDecorations = [] 118 self._commentSize = "3" 119 self._commentColor = "#808080" 120 self._commentFont = "Courier" 121 self._commentDecorations = ["i"] 122 self.loadSettings ()
123
124 - def scrollToBottom (self):
125 self.moveCursor (QTextCursor.End) 126 self.ensureCursorVisible ()
127
128 - def correctString (self, string):
129 """ 130 CommandHistory.correctString (self, string) 131 132 This will simply return a string, given a string. 133 It is 'corrected' in the sense that it is passed a 134 normal string, however, it will be re-formatted 135 to be used as html. This means newlines become <br>, 136 spaces become &nbsp;, etc... 137 """ 138 string = str (string) 139 string = string.replace ("<", "&lt;") 140 string = string.replace (">", "&gt;") 141 string = string.replace ("\n", "<br>") 142 string = string.replace (" ", "&nbsp;") 143 return string
144
145 - def writeCommand (self, string):
146 """ 147 CommandHistory.writeCommand (self, string) 148 149 Commands are text strings that either the user has 150 typed and entered via the CommandLine, or commands 151 that were pragmatically entered (and decided that 152 user should be informed of). 153 154 This method takes a given string and displays it on 155 itself (a QTextEdit) given the pre-loaded settings 156 of what a "Command" looks like. These settings are 157 loaded at startup, or anytime the user edits them 158 in the preferences menu. Note that editing these 159 display settings will NOT retroactively change 160 previous commands written. 161 162 Settings may be found in the following file: C{~/.basin/client/ipython_appearance.conf} 163 """ 164 string = self.correctString (string) 165 166 dec1, dec2 = "", "" 167 for dec in self._commandDecorations: 168 dec1 += "<" + dec + ">" 169 count = len (self._commandDecorations) - 1 170 while count > 0: 171 dec2 += "</" + self._commandDecorations[count] + ">" 172 count -= 1 173 174 self.append ("<font class=\"Command\" size=\"" + \ 175 self._commandSize + "\" color=\"" + self._commandColor + "\" face=\"" + \ 176 self._commandFont + "\">" + dec1 + string + dec2 + "</font>") 177 self.scrollToBottom ()
178
179 - def writeResult (self, string):
180 """ 181 CommandHistory.writeResult (self, string) 182 183 Results are what the ipython environment returns 184 after having received a command. Quite often this 185 includes the command entered as well (notably 186 ipython's magic commands will not include the 187 command as a part of the output). There is an 188 optional setting, kept in the bridge, to reduce 189 the output displayed. If this option is set then 190 the results are more of an abridged version of the 191 ipython output (notably that output won't be 192 for every node in use, just one). Otherwise results 193 are exact copies, with their color having been 194 stripped, of ipython environment results. 195 196 This method takes a given string and displays it on 197 itself (a QTextEdit) given the pre-loaded settings 198 of what a "Result" looks like. These settings are 199 loaded at startup, or anytime the user edits them 200 in the preferences menu. Note that editing these 201 display settings will NOT retroactively change 202 previous results written. 203 204 Settings may be found in the following file: C{~/.basin/client/ipython_appearance.conf} 205 """ 206 string = self.correctString (string) 207 208 # Option set in preferences: 209 # It will prevent the cluster from generating 210 # output for each node, but rather output one 211 # nodes data and rename it from `0` to `Cluster` 212 if self._bridge._limitOut: 213 index = string.find ("[1]&nbsp;") 214 if index != -1: 215 string = string[:index] 216 string = string.replace ("[0]", "[Cluster]").replace ("&lt;Results&nbsp;List&gt;<br>", "") 217 218 dec1, dec2 = "", "" 219 for dec in self._resultDecorations: 220 dec1 += "<" + dec + ">" 221 count = len (self._resultDecorations) - 1 222 while count > 0: 223 dec2 += "</" + self._resultDecorations[count] + ">" 224 count -= 1 225 226 self.append ("<font class=\"Result\"size=\"" + \ 227 self._resultSize + "\" color=\"" + self._resultColor + "\" face=\"" + \ 228 self._resultFont + "\">" + dec1 + string + dec2 + "</font>") 229 self.scrollToBottom ()
230
231 - def writeComment (self, string):
232 """ 233 CommandHistory.writeComment (self, string) 234 235 Comments (probably not the best name to describe 236 these) are messages that aren't associated with 237 a normal python/ipython session. They are messages 238 this gui has decided to display in the ipython box. 239 For instance, if you enter a command with 'def', 240 'for', 'if', or 'while', then it will tell you that 241 you are in multi-line mode, and that you need to 242 enter a blank line to get out of it. Not a python 243 command, but certainly pertinant to ipython. 244 245 This method takes a given string and displays it on 246 itself (a QTextEdit) given the pre-loaded settings 247 of what a "Comment" looks like. These settings are 248 loaded at startup, or anytime the user edits them 249 in the preferences menu. Note that editing these 250 display settings will NOT retroactively change 251 previous comments written. 252 253 Settings may be found in the following file: C{~/.basin/client/ipython_appearance.conf} 254 """ 255 string = self.correctString (string) 256 257 dec1, dec2 = "", "" 258 for dec in self._commentDecorations: 259 dec1 += "<" + dec + ">" 260 count = len (self._commentDecorations) - 1 261 while count > 0: 262 dec2 += "</" + self._commentDecorations[count] + ">" 263 count -= 1 264 265 self.append ("<font class=\"Comment\"size=\"" + self._commentSize + "\" color=\"" + \ 266 self._commentColor + "\" face=\"" + self._commentFont + "\">" + \ 267 dec1 + string + dec2 + "</font>") 268 self.scrollToBottom ()
269
270 - def writeMetaComment (self):
271 """ 272 CommandHistory.writeMetaComment (self) 273 274 This method prints out a standard message to the command 275 history stating that the command entered is a meta-command, 276 one which isn't an actual python command, but that the client 277 will break up into a bunch of commands to be executed. This 278 is merely a message stating this as a comment. 279 """ 280 self._shell._commandHistory.writeComment ("Entered a basin meta-command for plotting...") 281 self._shell._commandHistory.writeComment ("Note that this isn't a valid python command," + \ 282 " but is converted into several valid commands.")
283
284 - def mousePressEvent (self, ev):
285 """ 286 CommandHistory.mousePressEvent (self, ev) 287 288 This method is called whenever the user clicks on the CommandHistory. 289 It is only looking to see if it was a right click, in which case it 290 calls rightClick, otherwise behaves like a normal QTextEdit. 291 """ 292 if ev.button () == Qt.RightButton: 293 self.rightClick (ev.globalPos ()) 294 else: 295 QTextEdit.mousePressEvent (self, ev)
296
297 - def keyPressEvent (self, ev):
298 """ 299 CommandHistory.keyPressEvent (self, ev) 300 301 This method is called whenever the user presses on a key 302 while the CommandHistory is in focus. It is only searching 303 to see if the `+` or `-` keys were pressed. 304 305 - `+` Increases the font size 306 - `-` Decreases the font size 307 Both will do this to everything in the entire CommandHistory. 308 309 If netiher were pressed, it proceeds to call the standard QTextEdit's 310 keyPressEvent to behave normally. 311 """ 312 313 key = ev.key () 314 if key == Qt.Key_Plus: 315 self.zoomIn () 316 elif key == Qt.Key_Minus: 317 self.zoomOut () 318 else: 319 QTextEdit.keyPressEvent (self, ev)
320
321 - def rightClick (self, position):
322 """ 323 CommandHistory.rightClick (self, position) 324 325 This method will be called whenever the user performs 326 a right click. It will display three options in a menu 327 at the point `position`, where the user had clicked. 328 329 The options are to: 330 - Save the current history to a log file 331 - Increase the font size 332 - Decrease the font size 333 """ 334 335 menu = QMenu ("Log") 336 menu.addAction (QIcon (Constants.ICON_DIR + "/file/python.png"), \ 337 "Save IPython Log", self._bridge.SaveIPythonSession) 338 menu.addSeparator () 339 menu.addAction (QIcon (Constants.ICON_DIR + "/misc/zoomin.png"), \ 340 "Increase Font Size", self.zoomIn) 341 menu.addAction (QIcon (Constants.ICON_DIR + "/misc/zoomout.png"), \ 342 "Decrease Font Size", self.zoomOut) 343 menu.addSeparator () 344 menu.addAction ("Copy", self.copy) 345 menu.exec_ (position)
346
347 - def zoomIn (self):
348 """ 349 CommandHistory.zoomIn (self) 350 351 This method is attached to the '+' (note it needs shift) key as 352 well as a right-click menu when right-clicking on the CommandHistory. 353 354 It will increase everything in the history's font size by 1. 355 """ 356 357 QTextEdit.zoomIn (self)
358
359 - def zoomOut (self):
360 """ 361 CommandHistory.zoomIn (self) 362 363 This method is attached to the '-' key as well as a right-click 364 menu when right-clicking on the CommandHistory. 365 366 It will decrease everything in the history's font size by 1. 367 """ 368 QTextEdit.zoomOut (self)
369
370 - def loadSettings (self):
371 file = QFile (str (QDir.home ().path ()) + "/.basin/client/ipython_appearance.conf") 372 if file.exists (): 373 file.open (QIODevice.ReadOnly | QIODevice.Text) 374 stream = QTextStream (file) 375 376 reBGColor = re.compile ("\s*BGCOLOR\s*:\s*.*\s*") 377 378 reSize = re.compile ("\s*.*\s*:\s*SIZE\s*:\s*.*\s*") 379 reFont = re.compile ("\s*.*\s*:\s*FONT\s*:\s*.*\s*") 380 reColor = re.compile ("\s*.*\s*:\s*COLOR\s*:\s*.*\s*") 381 reDecorations = re.compile ("\s*.*\s*:\s*DECORATIONS\s*:\s*.*\s*") 382 383 reCommand = re.compile ("\s*COMMAND\s*:\s*.*\s*:\s*.*\s*") 384 reResult = re.compile ("\s*RESULT\s*:\s*.*\s*:\s*.*\s*") 385 reComment = re.compile ("\s*COMMENT\s*:\s*.*\s*:\s*.*\s*") 386 387 while not stream.atEnd (): 388 line = str (stream.readLine ()) 389 val = line[line.rfind (":") + 1:] 390 if reCommand.match (line): 391 if reSize.match (line): 392 self._commandSize = val 393 elif reFont.match (line): 394 self._commandFont = val 395 elif reColor.match (line): 396 self._commandColor = val 397 elif reDecorations.match (line): 398 self._commandDecorations = val.split (",") 399 elif reResult.match (line): 400 if reSize.match (line): 401 self._resultSize = val 402 elif reFont.match (line): 403 self._resultFont = val 404 elif reColor.match (line): 405 self._resultColor = val 406 elif reDecorations.match (line): 407 self._resultDecorations = val.split (",") 408 elif reComment.match (line): 409 if reSize.match (line): 410 self._commentSize = val 411 elif reFont.match (line): 412 self._commentFont = val 413 elif reColor.match (line): 414 self._commentColor = val 415 elif reDecorations.match (line): 416 self._commentDecorations = val.split (",") 417 elif reBGColor.match (line): 418 self._bgColor = val 419 file.close ()
420 421
422 -class CommandLine (QLineEdit):
423 - def __init__ (self, shell, bridge):
424 self._bridge = bridge 425 self._autopx = False 426 self._shell = shell 427 self._history = [] 428 self._historyCount = -1 429 self._update = False 430 self._singleLine = True 431 self._visitStart = False 432 QLineEdit.__init__ (self) 433 self.setFocusPolicy (Qt.ClickFocus) 434 self.setReadOnly (True) 435 shell.addWidget (self) 436 shell.setStretchFactor (self, 2) 437 self._multiLineHistoryBuffer = [] 438 439 QObject.connect (shell._commandStatus.toggleButton, SIGNAL ("clicked ()"), self.setFocus)
440
441 - def keyPressEvent (self, ev):
442 key = ev.key () 443 if key == Qt.Key_Enter or key == Qt.Key_Return: 444 self.enterCommand () 445 elif key == Qt.Key_Up: 446 self.upHistory () 447 elif key == Qt.Key_Down: 448 self.downHistory () 449 elif key == Qt.Key_AsciiTilde: 450 print self._bridge._ipyShell.complete (self.text ()) 451 else: 452 QLineEdit.keyPressEvent (self, ev)
453 454 455 # Should be called everytime a Command (non-silent) is issued, 456 # it accumulates these for re-use
457 - def addToHistory (self):
458 self._historyCount = -1 459 command = self.text () 460 self._history.insert (0, command)
461 462 # traverse backwards-in-time for issued commands 463 # currently no limit on how many are stored
464 - def upHistory (self):
465 self._historyCount += 1 466 if self._historyCount >= len (self._history): 467 self._historyCount = len (self._history) - 1 468 if self._historyCount != -1: 469 self.setText (self._history[self._historyCount])
470 471 # traverse forwards-in-time for issued commands 472 # it catches any attempt to go "down" from the current line
473 - def downHistory (self):
474 self._historyCount -= 1 475 if self._historyCount < 0: 476 self._historyCount = -1 477 self.clear () 478 else: 479 self.setText (self._history[self._historyCount])
480
481 - def enterCommand (self, autoUpdate = True):
482 command = str (self.text ()) 483 self.addToHistory () 484 485 # There are commands entered before a session is 'initialized'. They don't need to 486 # be recorded, because for the buffer history to be useful, you must already be 487 # initialized 488 if self._bridge._ipyShell._initialized: 489 # Store the original command, there's a good possibility things will 490 # be done before this gets executed... 491 command = str (self.text ()) 492 if self._singleLine: 493 # If there was a multi-line statement before this one, then there are 494 # a bunch of commands that were stuck into this buffer (because they 495 # couldn't be appended to the server's history). It is now safe to 496 # append them, so do that first 497 while len (self._multiLineHistoryBuffer) > 0: 498 buffer = self._multiLineHistoryBuffer.pop (0) 499 self._bridge._ipyShell.ControllerCommand ("buffer_history.append (\"" + 500 self._bridge._user + "@" + buffer.replace ("\n", 501 "\\\\\n").replace ("\"", "\\\\\"").replace ("\'", "\\\\\'") + 502 "\")", False) 503 # And then append the actual command you just entered to the sever's history 504 self._bridge._ipyShell.ControllerCommand ("buffer_history.append (\"" + 505 self._bridge._user + "@" + command.replace ("\n", 506 "\\\\\n").replace ("\"", "\\\\\"").replace ("\'", "\\\\\'") + 507 "\")", False) 508 else: 509 # If its here, its a multi-line statement, so its history gets tacked to 510 # a buffer until you're back to single-line mode 511 self._multiLineHistoryBuffer.append (command) 512 # Restore the original command to be executed 513 self.setText (command) 514 515 self.filter () 516 rv = self._shell._processLine () 517 518 # Write command & result to CommandHistory, 519 # Then clear out the commandline 520 self._shell._commandHistory.writeCommand (str (self.text ())) 521 self._shell._commandHistory.writeResult (rv) 522 523 if rv == "" and self._bridge._parallel: 524 self._shell._commandHistory.writeComment ("Multi-line: enter a blank line to finish") 525 self._singleLine = False 526 elif rv != "": 527 self._singleLine = True 528 529 if self._singleLine: 530 self.determineUpdate (autoUpdate) 531 532 self.clear () 533 return rv
534
535 - def enterSilentCommand (self, autoUpdate = True):
536 self.filter () 537 rv = self._shell._processLine () 538 self.clear () 539 540 if self._singleLine: 541 self.determineUpdate (autoUpdate) 542 return rv
543
544 - def determineUpdate (self, autoUpdate):
545 if not autoUpdate: 546 self._update = False 547 elif self._update and self._bridge._connected \ 548 and self._bridge._parallel: 549 self._update = False 550 self.setUpdateLine () 551 self._bridge.Update ()
552
553 - def setUpdateLine (self):
554 self.setText ("print \"\\n\" + BASIN_UPDATE") 555 result = self.enterSilentCommand (False).split ("\n") 556 lineNumber = result[1][result[1].find ("[", 1) + \ 557 1:result[1].find ("]", result[1].find ("[", 1))] 558 self.setText ("BASIN_UPDATE = '" + lineNumber + "'") 559 self.enterSilentCommand (False)
560
561 - def filter (self):
562 if (not self._singleLine) or self.text () == "": 563 return True 564 565 self.setText (str (self.text ()).strip ()) 566 567 if self.filterExit (): 568 return True 569 if self.filterVisitStart (): 570 return True 571 # This only applies for "one-touch" visit, which requires the visit python module 572 if self._bridge._dock._visit._visitModuleLoaded: 573 if self.filterVisitExpose (): 574 return True 575 if self.filterBuffer (): 576 return True 577 if self.filterAutopx (): 578 return True 579 if self._shell._initialized == True and self._bridge._parallel and self._bridge._connected: 580 if self.filterPlotting (): 581 return False 582 if self.filterDataModification (): 583 return True 584 if self.filterRegions (): 585 return True 586 if self.filterVars (): 587 return True 588 if self.filterGenericAssignment (): 589 return True
590 591 592 # I'm not really happy with the way this is handled right now, 593 # but for now it manages the number of times visit_module_start () 594 # is executed. For it to work properly, it should only ever be 595 # done once per session.
596 - def filterVisitStart (self):
597 command = str (self.text ()) 598 if command.find ("visit_module_start") != -1 and command.find ("@") == -1: 599 if self._bridge._visitModuleStarted: 600 self.clear () 601 else: 602 result = self._shell.getVisitModuleStatus () 603 if result == "False": 604 self._bridge._ipyShell.SilentCommand ( \ 605 "BASIN_VISIT_START = True") 606 self.setText ("visit_module_start ()") 607 return True 608 else: 609 self._bridge._visitModuleStarted = True 610 self.clear () 611 return False 612 return False
613 614 615 # This will populate host-side variables consisting of the plot names that have been exposed
616 - def filterVisitExpose (self):
617 discreteRegExp = re.compile ("visit_expose_discrete\s\(.*\)") 618 continuousRegExp = re.compile ("visit_expose_continuous\s\(.*\)") 619 command = str (self.text ()) 620 if discreteRegExp.match (command): 621 quote2 = command.rfind ("\"") 622 quote1 = command[:quote2].rfind ("\"") + 1 623 name = command[quote1:quote2] 624 exposeList, windowList = self._bridge._ipyShell.getVisItExposeDiscrete () 625 626 _append = True 627 for each in exposeList: 628 if each == name: 629 _append = False 630 if _append: 631 exposeList.append (name) 632 windowList.append (str (self._bridge._dock._visit._visit._windowCount)) 633 discreteString = "" 634 for index in xrange (len (exposeList)): 635 discreteString += exposeList[index] + ":" + windowList[index] + "\\n" 636 self.setText ("BASIN_VISIT_DISCRETE_LIST = \"" + discreteString + "\"") 637 self.enterSilentCommand (False) 638 639 self.setText (command) 640 641 if self._bridge._importVisIt: 642 # Starts thread if it hasn't been (includes launching & connecting) 643 if not self._bridge._dock._visit.StartVisItThread (): 644 # If the thread was already started (gives an initial window), add a window manually 645 self._bridge._dock._visit.emit (SIGNAL ("threadAddWindow ()")) 646 self._bridge._dock._visit._visitWindows += 1 647 windows = self._bridge._dock._visit._visitWindows 648 self._bridge._dock._visit.emit (SIGNAL ("threadSetActiveWindow (PyQt_PyObject)"), windows) 649 self._bridge._dock._visit.emit (SIGNAL ("threadReOpenSimulation ()")) 650 self._bridge._dock._visit.emit (SIGNAL ("threadAddPlotPseudocolor (PyQt_PyObject)"), name) 651 self._bridge._dock._visit.emit (SIGNAL ("threadDrawPlots ()")) 652 self._update = True 653 return True 654 if continuousRegExp.match (command): 655 quote2 = command.rfind ("\"") 656 quote1 = command[:quote2].rfind ("\"") + 1 657 name = command[quote1:quote2] 658 exposeList, windowList = self._bridge._ipyShell.getVisItExposeContinuous () 659 660 _append = True 661 for each in exposeList: 662 if each == name: 663 _append = False 664 if _append: 665 exposeList.append (name) 666 windowList.append (str (self._bridge._dock._visit._visit._windowCount)) 667 continuousString = "" 668 for index in xrange (len (exposeList)): 669 continuousString += exposeList[index] + ":" + windowList[index] + "\\n" 670 self.setText ("BASIN_VISIT_CONTINUOUS_LIST = \"" + continuousString + "\"") 671 self.enterSilentCommand (False) 672 673 self.setText (command) 674 675 if self._bridge._importVisIt: 676 # Starts thread if it hasn't been (includes launching & connecting) 677 if not self._bridge._dock._visit.StartVisItThread (): 678 # If the thread was already started (gives an initial window), add a window manually 679 self._bridge._dock._visit.emit (SIGNAL ("threadAddWindow ()")) 680 self._bridge._dock._visit._visitWindows += 1 681 windows = self._bridge._dock._visit._visitWindows 682 self._bridge._dock._visit.emit (SIGNAL ("threadSetActiveWindow (PyQt_PyObject)"), windows) 683 self._bridge._dock._visit.emit (SIGNAL ("threadReOpenSimulation ()")) 684 self._bridge._dock._visit.emit (SIGNAL ("threadAddPlotVolume (PyQt_PyObject)"), name) 685 self._bridge._dock._visit.emit (SIGNAL ("threadDrawPlots ()")) 686 self._update = True 687 return True 688 return False
689
690 - def filterPlotting (self):
691 command = str (self.text ()).replace (" ", "").replace ("\t", "") 692 expPylab = "plot\(.*,\"[Pp][Yy][Ll][Aa][Bb].*\)" 693 if re.compile (expPylab).match (str (command)): 694 self._bridge._ipyShell._commandHistory.writeCommand (str (self.text ())) 695 command = command [command.index ("(") + 1:command.rindex (")")] 696 lastParen = command.rindex ("\"") 697 secondlastParen = command.rindex ("\"", 0, lastParen - 1) 698 699 options = command [secondlastParen + 1:lastParen].split (",") 700 data = command[:secondlastParen - 1].split (",") 701 style = "" 702 703 if data[-1].find ("PLOT_STYLE=") != -1: 704 style = data.pop () 705 equals = style.index ("=") 706 style = ", \"" + style[equals + 1:] + "\"" 707 708 # Make sure there are atleast 2 options, otherwise it can't be performed 709 if len (options) < 2: 710 self.setText ("") 711 return True 712 713 self._shell._commandHistory.writeMetaComment () 714 715 if options[1] == "scatter": 716 self._bridge.CursorBusy () 717 # Get data types for each data input, and if they aren't basin Attributes 718 # or python lists, then get out of here, because this function is useless 719 types = [] 720 for each in data: 721 type = self._bridge._ipyShell.getVariableType (each) 722 if type != "list" and type != "_basin.Attribute": 723 self.setText ("") 724 return 725 types.append (type) 726 727 # Convert all attributes to lists, leave the lists alone... 728 for index in xrange (len (data)): 729 if types[index] == "_basin.Attribute": 730 self._bridge._ipyShell.Command ("BASIN_TEMP_" + str (index) + " = " + \ 731 data[index] + ".to_list ()") 732 733 # This section must be done locally (note the only way to get to this point 734 # was to be in parallel) 735 self._bridge._ipyShell.toggleAutopx () 736 737 # Pull the data from the cluster to the remote side, the naming conventions 738 # are a tad different depnding on whether a data conversion had to be made 739 # As variables are being pulled to the local side, tack them onto a string 740 # which will serve as an arguments list to a function. 741 _dataString = "" 742 for index in xrange (len (data)): 743 if types[index] == "_basin.Attribute": 744 self._bridge._ipyShell.Command ("BASIN_TEMP_" + str (index) + \ 745 " = rc.pull (0, '" + "BASIN_TEMP_" + str (index) + "')[0]") 746 _dataString += "BASIN_TEMP_" + str (index) + "," 747 else: 748 self._bridge._ipyShell.Command ("BASIN_TEMP_" + data[index] + \ 749 " = rc.pull (0, '" + data[index] + "')[0]") 750 _dataString += "BASIN_TEMP_" + data[index] + "," 751 _dataString = _dataString[:-1] 752 753 # the second element of options better be the plot type, i haven't implemented 754 # a way to check this as of yet. 755 self._bridge._ipyShell.Command ("pylab.plot (" + _dataString + style + \ 756 ")", False) 757 758 if len (options) > 2: 759 for command in PyLabOptionsParse (options[2:]): 760 self._bridge._ipyShell.Command (command, False) 761 762 self._bridge._ipyShell.Command ("pylab.xlabel (\"" + data[0].replace ("\"", "\\\"") + \ 763 "\")", False) 764 self._bridge._ipyShell.Command ("pylab.ylabel (\"" + data[1].replace ("\"", "\\\"") + \ 765 "\")", False) 766 767 self._bridge.CursorNorm () 768 self._bridge._ipyShell.Command ("pylab.show ()", False) 769 self._bridge.CursorBusy () 770 771 # Wipe off local temporary variables! 772 for index in xrange (len (data)): 773 if types[index] == "_basin.Attribute": 774 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + str (index) + ")") 775 else: 776 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + data[index] + ")") 777 778 # Go back to the parallel side and delete any temporary variables you 779 # may have made 780 self._bridge._ipyShell.toggleAutopx () 781 for index in xrange (len (data)): 782 if types[index] == "_basin.Attribute": 783 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + str (index) + ")") 784 self._bridge.CursorNorm () 785 786 787 elif options[1] == "contour" or options[1] == "pcolor": 788 self._bridge.CursorBusy () 789 # Get data types for each data input, and if they aren't basin Attributes 790 # or python lists, then get out of here, because this function is useless 791 types = [] 792 for each in data: 793 type = self._bridge._ipyShell.getVariableType (each) 794 print type 795 if type != "pylab.array" and type != "_basin.Attribute": 796 self.setText ("") 797 return 798 types.append (type) 799 800 # Convert all attributes to lists, leave the lists alone... 801 for index in xrange (len (data)): 802 if types[index] == "_basin.Attribute": 803 self._bridge._ipyShell.Command ("BASIN_TEMP_" + str (index) + " = " + \ 804 data[index] + ".to_list ()") 805 self._bridge._ipyShell.Command ("BASIN_NX_TEMP_" +str(index) + "="+\ 806 data[index]+".get_dims()") 807 808 self._bridge._ipyShell.toggleAutopx () 809 810 #if len (data) == 3: 811 # self._bridge._ipyShell.Command ("BASIN_TEMP_0 = [[], [], []]") 812 # for index in xrange (len (data)): 813 # if types[index] == "_basin.Attribute": 814 # self._bridge._ipyShell.Command ("BASIN_TEMP_0[" + \ 815 # str (index) + "] = rc.pull (0, '" + "BASIN_TEMP_" + \ 816 # str (index) + "')[0]") 817 # else: 818 # self._bridge._ipyShell.Command ("BASIN_TEMP_0[" + \ 819 # data[index] + "] = rc.pull (0, '" + \ 820 ## data[index] + "')[0]") 821 # self._bridge._ipyShell.Command ("pylab.contour (BASIN_TEMP_0)", False) 822 if len (data) == 1: 823 if types[0] == "_basin.Attribute": 824 self._bridge._ipyShell.Command ("BASIN_TEMP_0" + \ 825 " = rc.pull (0, 'BASIN_TEMP_0')[0]") 826 self._bridge._ipyShell.Command ("BASIN_NX_TEMP_0" + \ 827 " = rc.pull (0, 'BASIN_NX_TEMP_0')[0]") 828 # Now, convert to an array 829 self._bridge._ipyShell.Command ("BASIN_ARR_TEMP=pylab.array(BASIN_TEMP_0)") 830 self._bridge._ipyShell.Command ("BASIN_ARR_TEMP.shape=BASIN_NX_TEMP_0") 831 #else: 832 # self._bridge._ipyShell.Command ("BASIN_TEMP_" + \ 833 # data[0] + " = rc.pull (0, '" + \ 834 # data[0] + "')[0]") 835 self._bridge._ipyShell.Command ("pylab."+options[1]+" (BASIN_ARR_TEMP)", False) 836 837 838 if len (options) > 2: 839 for command in PyLabOptionsParse (options[2:]): 840 self._bridge._ipyShell.Command (command, False) 841 842 if len (data) == 3: 843 self._bridge._ipyShell.Command ("pylab.xlabel (\"" + \ 844 data[0].replace ("\"", "\\\"") + "\")", False) 845 self._bridge._ipyShell.Command ("pylab.ylabel (\"" + \ 846 data[1].replace ("\"", "\\\"") + "\")", False) 847 848 self._bridge.CursorNorm () 849 self._bridge._ipyShell.Command ("pylab.show ()", False) 850 self._bridge.CursorBusy () 851 self._bridge._ipyShell.Command ("del (BASIN_TEMP_0)", False) 852 853 self._bridge._ipyShell.toggleAutopx () 854 855 for index in xrange (len (data)): 856 if types[index] == "_basin.Attribute": 857 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + str (index) + ")") 858 self._bridge.CursorNorm () 859 860 861 elif options[1] == "hist": 862 self._bridge.CursorBusy () 863 # Get data types for each data input, and if they aren't basin Attributes 864 # or python lists, then get out of here, because this function is useless 865 type = self._bridge._ipyShell.getVariableType (data[0]) 866 if type != "list" and type != "_basin.Attribute": 867 self.setText ("") 868 return 869 870 if type == "_basin.Attribute": 871 self._bridge._ipyShell.Command ("BASIN_TEMP_0 = " + \ 872 data[0] + ".to_list ()") 873 874 self._bridge._ipyShell.toggleAutopx () 875 876 if type == "_basin.Attribute": 877 self._bridge._ipyShell.Command ("BASIN_TEMP_0 = rc.pull (0, '" + \ 878 "BASIN_TEMP_0')[0]") 879 else: 880 self._bridge._ipyShell.Command ("BASIN_TEMP_0 = rc.pull (0, '" + \ 881 data[0] + "')[0]") 882 883 self._bridge._ipyShell.Command ("pylab.hist (BASIN_TEMP_0, " + data[1] + ")") 884 self._bridge.CursorNorm () 885 self._bridge._ipyShell.Command ("pylab.show ()") 886 self._bridge.CursorBusy () 887 888 self._bridge._ipyShell.Command ("del (BASIN_TEMP_0)") 889 self._bridge._ipyShell.toggleAutopx () 890 if type == "_basin.Attribute": 891 self._bridge._ipyShell.Command ("del (BASIN_TEMP_0)") 892 self._bridge.CursorNorm () 893 elif options[1] == "errorbar": 894 self._bridge.CursorBusy () 895 # Get data types for each data input, and if they aren't basin Attributes 896 # or python lists, then get out of here, because this function is useless 897 types = [] 898 for each in data[:-2]: 899 type = self._bridge._ipyShell.getVariableType (each) 900 if type != "list" and type != "_basin.Attribute": 901 self.setText ("") 902 return 903 types.append (type) 904 905 # Convert all attributes to lists, leave the lists alone... 906 for index in xrange (len (data[:-2])): 907 if types[index] == "_basin.Attribute": 908 self._bridge._ipyShell.Command ("BASIN_TEMP_" + str (index) + " = " + \ 909 data[index] + ".to_list ()") 910 911 # This section must be done locally (note the only way to get to this point 912 # was to be in parallel) 913 self._bridge._ipyShell.toggleAutopx () 914 915 # Pull the data from the cluster to the remote side, the naming conventions 916 # are a tad different depnding on whether a data conversion had to be made 917 # As variables are being pulled to the local side, tack them onto a string 918 # which will serve as an arguments list to a function. 919 _dataString = "" 920 for index in xrange (len (data[:-2])): 921 if types[index] == "_basin.Attribute": 922 self._bridge._ipyShell.Command ("BASIN_TEMP_" + str (index) + \ 923 " = rc.pull (0, '" + "BASIN_TEMP_" + str (index) + "')[0]") 924 _dataString += "BASIN_TEMP_" + str (index) + "," 925 else: 926 self._bridge._ipyShell.Command ("BASIN_TEMP_" + data[index] + \ 927 " = rc.pull (0, '" + data[index] + "')[0]") 928 _dataString += "BASIN_TEMP_" + data[index] + "," 929 _dataString = _dataString[:-1] 930 _dataString += ", " + data[-2] + ", " + data[-1] 931 932 # the second element of options better be the plot type, i haven't implemented 933 # a way to check this as of yet. 934 self._bridge._ipyShell.Command ("pylab.errorbar (" + _dataString + style + \ 935 ")", False) 936 937 if len (options) > 2: 938 for command in PyLabOptionsParse (options[2:]): 939 self._bridge._ipyShell.Command (command, False) 940 941 self._bridge._ipyShell.Command ("pylab.xlabel (\"" + data[0].replace ("\"", "\\\"") + \ 942 "\")", False) 943 self._bridge._ipyShell.Command ("pylab.ylabel (\"" + data[1].replace ("\"", "\\\"") + \ 944 "\")", False) 945 946 self._bridge.CursorNorm () 947 self._bridge._ipyShell.Command ("pylab.show ()", False) 948 self._bridge.CursorBusy () 949 950 # Wipe off local temporary variables! 951 for index in xrange (len (data[:-2])): 952 if types[index] == "_basin.Attribute": 953 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + str (index) + ")") 954 else: 955 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + data[index] + ")") 956 957 # Go back to the parallel side and delete any temporary variables you 958 # may have made 959 self._bridge._ipyShell.toggleAutopx () 960 for index in xrange (len (data[:-2])): 961 if types[index] == "_basin.Attribute": 962 self._bridge._ipyShell.Command ("del (BASIN_TEMP_" + str (index) + ")") 963 self._bridge.CursorNorm () 964 else: 965 self._shell._commandHistory.writeComment ("PyLab plot type '" + options[1] + "' unkown!") 966 967 # Wow... you converted one pseudo command into a zillion different commands... 968 # Remember that the actual command entered has yet to be executed, so whatever 969 # gets set to the command line now is still going to be executed! (For now I 970 # blank it out) 971 self.setText ("") 972 return True 973 return False
974
975 - def filterGenericAssignment (self):
976 """ 977 CommandLine.filterGenericAssignment (self) 978 979 This method is a standard filter method which is meant 980 to catch any assignments being made. All the filter does 981 is ensure that the bridge will update itself, as it should 982 happen after data has potentially been altered. 983 """ 984 assignRegExp = re.compile (".*\s*=\s*.*") 985 command = str (self.text ()) 986 if assignRegExp.match (command): 987 self._update = True 988 return True 989 return False
990
991 - def filterExit (self):
992 """ 993 CommandLine.filterExit (self) 994 995 This method is a standard filter method which is meant 996 to catch the user from using the exit function/command 997 to exit from the ipython shell. Doing this will actually 998 make the client hang for eternity, so users must close 999 the actual client to stop the ipython session. 1000 """ 1001 exitRegExp = re.compile ("\s*exit\s*(\(\s*\))?\s*") 1002 command = str (self.text ()) 1003 if exitRegExp.match (command): 1004 return True 1005 return False
1006
1007 - def filterBuffer (self):
1008 command = str (self.text ()) 1009 if command.find ("buffer_history") != -1: 1010 return True 1011 return False
1012
1013 - def filterAutopx (self):
1014 command = str (self.text ()).strip () 1015 if command.find ("%autopx") != -1 or command.find ("autopx") != -1: 1016 if self._bridge._parallel == True: 1017 self._bridge.parallelOff () 1018 else: 1019 self._bridge.parallelOn () 1020 return True 1021 return False
1022
1023 - def filterDataModification (self):
1024 command = str (self.text ()) 1025 1026 # Regular expression for a method being called with one argument that is a string 1027 exp = ".*(delete_grid|delete_list|delete_attribute|set_name)\s*\(\s*\".*\"\s*\)\s*" 1028 if re.compile (exp).match (str (command)): 1029 self._update = True 1030 return 1031 1032 # Regular expression for a method being called with one argument that is not a string 1033 exp = ".*(delete_child|add_child|fft|del|power_spectrum)\s*\(\s*.*\s*\)\s*" 1034 if re.compile (exp).match (str (command)): 1035 self._update = True 1036 return 1037 1038 # Regular expression for a method being called with two arguments that are strings 1039 exp = ".*(change_attribute_key)\s*\(\s*\".*\"\s*\,\s*\".*\"\s*\)\s*" 1040 if re.compile (exp).match (str (command)): 1041 self._update = True 1042 return 1043 1044 # Regular expression for a method being called with two arguments that are not strings 1045 exp = ".*(convolve)\s*\(\s*.*\s*\,\s*.*\s*\)\s*" 1046 if re.compile (exp).match (str (command)): 1047 self._update = True 1048 return 1049 1050 # Regular expression for a method being called with two arguments, one a string, the other not 1051 exp = ".*(add_list|add_grid|add_attribute)\s*\(\s*\".*\"\s*\,\s*.*\s*\)\s*" 1052 if re.compile (exp).match (str (command)): 1053 self._update = True 1054 return 1055 1056 # Regular expression for transformations 1057 exp = ".*(equatorial_to_xyz|xyz_to_equatorial" + \ 1058 "|spherical_to_xyz|xyz_to_spherical" + \ 1059 "|cylindrical_to_xyz|xyz_to_cylindrical)" + \ 1060 "\s*\(\s*.*\s*,\s*\".*\"\s*\,\s*\".*\"\s*,\s*\".*\"\s*,\s*\".*\"\s*\)\s*" 1061 if re.compile (exp).match (str (command)): 1062 self._update = True 1063 return 1064 1065 # Regular expression for transformations 1066 exp = ".*(equatorial_to_xyz|xyz_to_equatorial" + \ 1067 "|spherical_to_xyz|xyz_to_spherical" + \ 1068 "|cylindrical_to_xyz|xyz_to_cylindrical)" + \ 1069 "\s*\(\s*.*\s*\,\s*.*\s*,\s*.*\s*,\s*.*\s*\)\s*" 1070 1071 if re.compile (exp).match (str (command)): 1072 self._update = True 1073 return 1074 # Regular expression for transformations 1075 exp = ".*(polar_to_xy|xy_to_polar)" + \ 1076 "\s*\(\s*.*\s*,\s*\".*\"\s*\,\s*\".*\"\s*\)\s*" 1077 if re.compile (exp).match (str (command)): 1078 self._update = True 1079 return 1080 1081 # Regular expression for transformations 1082 exp = ".*(polar_to_xy|xy_to_polar)" + \ 1083 "\s*\(\s*.*\s*,\s*.*\s*\,\s*.*\s*\)\s*" 1084 if re.compile (exp).match (str (command)): 1085 self._update = True 1086 return 1087 1088 # Regular expression for cosmology, 1 non-string. 2 strings, 2 non-strings 1089 exp = ".*(redshift_to_distance)" + \ 1090 "\s*\(\s*.*\s*,\s*\".*\"\s*,\s*\".*\"\s*,\s*.*\s*\,\s*.*\s*\)\s*" 1091 1092 if re.compile (exp).match (str (command)): 1093 self._update = True 1094 return
1095
1096 - def filterRegions (self):
1097 # Preserve original ipython command, one will be entered first 1098 commandOrig = str (self.text ()) 1099 command = commandOrig.replace (" ", "").replace ("\t", "") 1100 regionList = self._bridge._ipyShell.getTopLevelRegions () 1101 equalIndex = command.find ("=") 1102 if equalIndex != -1: 1103 # should be a regular expression of the form: 1104 # something = Region ("something") 1105 # but with more liberal whitespacing 1106 exp = ".*=\s*Region\s*\(\s*.*\s*\)\s*" 1107 if re.compile (exp).match (str (command)): 1108 var = command[:equalIndex] 1109 _append = True 1110 for each in regionList: 1111 if each == var: 1112 _append = False 1113 if _append: 1114 regionList.append (var) 1115 toplevelString = "" 1116 for each in regionList: 1117 toplevelString += each + "\\n" 1118 self.setText ("BASIN_TOPLEVEL_REGION_LIST = \"" + toplevelString + "\"") 1119 self.enterSilentCommand (False) 1120 1121 self.setText ( var + " = " + var) 1122 self.filterVars () 1123 1124 self.setText (commandOrig) 1125 self._update = True 1126 return True 1127 self.setText (commandOrig) 1128 return False
1129
1130 - def filterVars (self):
1131 # Preserve original ipython command, two will be entered first 1132 commandOrig = str (self.text ()) 1133 command = commandOrig.replace (" ", "").replace ("\t", "") 1134 equalIndex = command.find ("=") 1135 if command.find ("BASIN_") == -1 and equalIndex != -1 and command[equalIndex + 1] != "=" \ 1136 and equalIndex < (len (command) - 1) and command[:equalIndex].find ("[") == -1: 1137 self.setText ("BASIN_FREE_VARIABLE_LIST += \"" + command[:equalIndex] + "\\n\"") 1138 self.enterSilentCommand (False) 1139 reference = command[equalIndex + 1:] 1140 real_ref = "" 1141 for i in xrange (len (reference)): 1142 if not re.compile ("\s").match (reference[i]): 1143 if re.compile ("\"").match (reference[i]): 1144 real_ref += "\\\"" 1145 else: 1146 real_ref += reference[i] 1147 self.setText ("BASIN_FREE_VARIABLE_LIST += \"-" + real_ref + "-\\n\"") 1148 self.enterSilentCommand (False) 1149 self.setText (commandOrig) 1150 self._update = True 1151 return True 1152 return False
1153
1154 - def dropEvent (self, ev):
1155 if self._bridge._drugItem and ev.mimeData ().hasFormat ("text/plain"): 1156 self.insert (self._bridge._drugItem._shellAccess) 1157 1158 self._bridge.PopDrugItem () 1159 self.setFocus () 1160 1161 if ev.source () == self._bridge._regionViewer: 1162 ev.setDropAction (Qt.LinkAction) 1163 ev.accept () 1164 else: 1165 ev.acceptProposedAction () 1166 else: 1167 ev.ignore ()
1168
1169 - def dragEnterEvent (self, ev):
1170 ev.accept ()
1171
1172 - def dragMoveEvent (self, ev):
1173 ev.accept ()
1174 1175
1176 -class CommandStatus (QLabel):
1177 - def __init__ (self, shell):
1178 QLabel.__init__ (self) 1179 self._shell = shell 1180 1181 layout = QHBoxLayout () 1182 shell.addLayout (layout) 1183 layout.addWidget (self) 1184 1185 self.toggleButton = Constants.BQPushButton ("Toggle Parallel Mode", layout) 1186 self.toggleButton.setEnabled (False) 1187 QObject.connect (self.toggleButton, SIGNAL ("clicked ()"), shell.toggleAutopx)
1188
1189 - def showStatus (self, string):
1190 self.setText (QString (str (string)))
1191
1192 - def toggleSingleLine (self):
1193 self._shell._commandLine._singleLine = not self._shell._commandLine._singleLine 1194 if self._shell._commandLine._singleLine: 1195 self._shell.Command ("", False)
1196 1197
1198 -class ConsoleView (QVBoxLayout):
1199 - def __init__ (self, layout, bridge):
1200 QVBoxLayout.__init__ (self) 1201 self._commandHistory = CommandHistory (self, bridge) 1202 self._commandStatus = CommandStatus (self) 1203 self._commandLine = CommandLine (self, bridge)
1204
1205 - def setMenuBar (self, menubar):
1206 self._commandHistory.setMenuBar (menubar)
1207
1208 - def write(self, text, editable=False):
1209 self.showReturned (unicode (text))
1210
1211 - def showPrompt(self, prompt):
1212 self._commandHistory.append ("")
1213
1214 - def showStatus (self, string):
1215 self._commandStatus.showStatus (string)
1216
1217 - def showReturned(self, text):
1218 for line in stripColor (text).split ("\n"): 1219 self._commandHistory.writeResult (line)
1220
1221 - def getHistory (self):
1222 return self._commandLine._history
1223
1224 - def raw_input (self, prompt = ''):
1225 return str (self._commandLine.text ().toUtf8 ())
1226
1227 - def _processLine (self):
1228 self.history_pos = 0 1229 self.execute() 1230 rv = self.cout.getvalue() 1231 while rv.find ("PBConnectionLost:") != -1: 1232 self.execute() 1233 rv = self.cout.getvalue() 1234 self.cout.truncate(0) 1235 return stripColor (rv.strip ("\n"))
1236 1237
1238 -class IPythonView(ConsoleView, IPShell):
1239 - def __init__(self, layout, bridge):
1240 ConsoleView.__init__(self, layout, bridge) 1241 self._scriptPath = None 1242 1243 self._bridge = bridge 1244 bridge.setIPyShell (self) 1245 1246 shell = QGroupBox ("IPython Shell") 1247 shell.setLayout (self) 1248 layout.addWidget (shell) 1249 self._initialized = False
1250 1251
1252 - def Init (self, host, port, user):
1253 self.cout = StringIO() 1254 IPShell.__init__(self, cout=self.cout,cerr=self.cout, 1255 input_func=self.raw_input) 1256 self.execute() 1257 self.cout.truncate(0) 1258 self._host = host 1259 self._port = port 1260 self._user = user 1261 1262 self.Command ("import subprocess") 1263 1264 self.attemptImportPylab () 1265 self.attemptImportNumpy () 1266 self.attemptImportScipy () 1267 1268 self.Command ("import ipython1.kernel.api as kernel") 1269 self.Command ("rc = kernel.RemoteController(('" + str (host) + "' ," + str (port) + "))") 1270 self.Command ("rc.activate()") 1271 self._bridge._nodes = self.SilentCommand ("print \"\\n\" + str (rc.getIDs ())")\ 1272 [1:-1].replace (" ", "").split (",") 1273 self._bridge._numNodes = len (self._bridge._nodes) 1274 self.toggleAutopx () 1275 1276 # This is the first time a command is issued across the cluster, 1277 # if it fails from a socket.error, then the connection failed 1278 connectCheck = self.Command ("import sys, os") 1279 if connectCheck.find ("error") != -1: 1280 # Get back to local commands 1281 self.toggleAutopx () 1282 1283 # Generate error dialog 1284 error = QDialog (self._bridge._mainWindow) 1285 error.setWindowTitle ("Connection Error") 1286 errorLayout = QVBoxLayout () 1287 error.setLayout (errorLayout) 1288 errorLayout.addWidget (QLabel (QString ( 1289 "Connection Failure!\n\n" + 1290 "Please ensure that you entered\n" + 1291 "a valid server name and port.\n\n" + 1292 "You should also check to make\n" + 1293 "sure that the basin_start.sh\n" + 1294 "script is running properly on\n" + 1295 "the cluster server.\n\n" + 1296 "You may try connecting again."))) 1297 acceptButton = Constants.BQPushButton ("Ok", errorLayout) 1298 QObject.connect (acceptButton, SIGNAL ("clicked ()"), error.accept) 1299 error.exec_ () 1300 return False 1301 1302 self._bridge.Connect () 1303 self.Command ("sys.setdlopenflags(258)") 1304 self.Command ("from basin import *") 1305 self._scriptPath = self.ScriptPath () 1306 self.ControllerCommand ("sys.path.append(\"" + self._scriptPath + "\")") 1307 self.ControllerCommand ("import buffer_history, filesystem") 1308 1309 _update = False 1310 1311 result = self.SilentCommand ("print BASIN_TOPLEVEL_REGION_LIST") 1312 if result.find ("NameError") != -1: 1313 self.SilentCommand ("BASIN_TOPLEVEL_REGION_LIST = ''") 1314 else: 1315 _update = True 1316 1317 result = self.SilentCommand ("print BASIN_FREE_VARIABLE_LIST") 1318 if result.find ("NameError") != -1: 1319 self.SilentCommand ("BASIN_FREE_VARIABLE_LIST = ''") 1320 else: 1321 _update = True 1322 1323 result = self.SilentCommand ("print BASIN_VISIT_DISCRETE_LIST") 1324 if result.find ("NameError") != -1: 1325 self.SilentCommand ("BASIN_VISIT_DISCRETE_LIST = ''") 1326 else: 1327 _update = True 1328 1329 result = self.SilentCommand ("print BASIN_VISIT_CONTINUOUS_LIST") 1330 if result.find ("NameError") != -1: 1331 self.SilentCommand ("BASIN_VISIT_CONTINUOUS_LIST = ''") 1332 else: 1333 _update = True 1334 1335 result = self.SilentCommand ("print BASIN_UPDATE") 1336 if result.find ("NameError") != -1: 1337 self.SilentCommand ("BASIN_UPDATE = '0'") 1338 else: 1339 _update = True 1340 1341 result = self.SilentCommand ("print COSMOLOGY") 1342 if result.find ("NameError") != -1: 1343 self.SilentCommand ("COSMOLOGY = cosmology ()") 1344 1345 result = self.SilentCommand ("print CONVOLVE") 1346 if result.find ("NameError") != -1: 1347 self.SilentCommand ("CONVOLVE = ConvKernel ()") 1348 1349 result = self.SilentCommand ("print BASIN_VISIT_START") 1350 if result.find ("NameError") != -1: 1351 self.SilentCommand ("BASIN_VISIT_START = False") 1352 1353 if _update: 1354 self._bridge.Update () 1355 else: 1356 self.ControllerCommand ("buffer_history.delete ()") 1357 1358 1359 self._initialized = True 1360 return True
1361
1362 - def attemptImportNumpy (self):
1363 """ 1364 IPythonView.attemptImportNumpy (self) 1365 1366 This function will try to import the module 1367 `numpy` onto the local machine. It will record 1368 its success in the bridge's ._importNumpy 1369 so that the client knows whether or not it can 1370 handle commands using the `numpy` module or not. 1371 1372 This method is assumed to be done while local. 1373 I omit checking for parallelism since this is 1374 performed in an initialization stage, where 1375 its status is in limbo. 1376 """ 1377 result = self.SilentCommand ("import numpy") 1378 if result.find ("ImportError") != -1: 1379 self._bridge._importNumpy = False 1380 else: 1381 self._bridge._importNumpy = True
1382
1383 - def attemptImportScipy (self):
1384 """ 1385 IPythonView.attemptImportScipy (self) 1386 1387 This function will try to import the module 1388 `scipy` onto the local machine. It will record 1389 its success in the bridge's ._importScipy 1390 so that the client knows whether or not it can 1391 handle commands using the `scipy` module or not. 1392 1393 This method is assumed to be done while local. 1394 I omit checking for parallelism since this is 1395 performed in an initialization stage, where 1396 its status is in limbo. 1397 """ 1398 result = self.SilentCommand ("import scipy") 1399 if result.find ("ImportError") != -1: 1400 self._bridge._importScipy = False 1401 else: 1402 self._bridge._importScipy = True
1403
1404 - def attemptImportPylab (self):
1405 """ 1406 IPythonView.attemptImportPylab (self) 1407 1408 This function will try to import the module 1409 `pylab` onto the local machine. It will record 1410 its success in the bridge's ._importPylab 1411 so that the client knows whether or not it can 1412 handle commands using the `pylab` module or not. 1413 1414 This method is assumed to be done while local. 1415 I omit checking for parallelism since this is 1416 performed in an initialization stage, where 1417 its status is in limbo. 1418 """ 1419 result = self.SilentCommand ("import pylab") 1420 if result.find ("ImportError") != -1: 1421 self._bridge._importPylab = False 1422 else: 1423 self._bridge._importPylab = True
1424
1425 - def Command (self, string, autoUpdate = True):
1426 # I used to catch if you were in multi-line mode here... 1427 # It was removed, but keep in mind it was here incase something else 1428 # goes haywire. 1429 self._commandLine.setText (str (string)) 1430 return self._commandLine.enterCommand (autoUpdate)
1431
1432 - def SilentCommand (self, string, autoUpdate = True):
1433 if not self._bridge._ipyShell._commandLine._singleLine: 1434 self._bridge._statusBar.showTimed ("Can't perform while in multi-line statement...", STATUS_WAIT) 1435 return 1436 self._commandLine.setText (str (string)) 1437 return self._commandLine.enterSilentCommand (autoUpdate)
1438
1439 - def ControllerCommand (self, string, autoUpdate = True):
1440 if not self._bridge._ipyShell._commandLine._singleLine: 1441 self._bridge._statusBar.showTimed ("Can't perform while in multi-line statement...", STATUS_WAIT) 1442 return 1443 alreadyLocal = self._bridge._parallel 1444 self._bridge.makeLocal () 1445 command = "rc.execute (0, \"" + string.replace ("\"", "\\\"") + "\")" 1446 result = self.SilentCommand (command, autoUpdate) 1447 if alreadyLocal: 1448 self._bridge.makeParallel () 1449 return result
1450 1451 # Meant to do a series of Command () calls, generally speaking the last command ought to be caught by 1452 # the filters and trigger an update, otherwise none will occur
1453 - def BatchCommands (self, commands, finalUpdate = True):
1454 self._bridge.CursorBusy () 1455 for command in commands: 1456 self.Command (command, False) 1457 self._bridge.CursorNorm () 1458 if finalUpdate: 1459 self.setUpdateLine () 1460 self._bridge.Update ()
1461
1462 - def toggleAutopx (self):
1463 result = self.Command ("%autopx") 1464 if result.find ("rror") != -1: 1465 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", "toggleAutopx", result)
1466
1467 - def toggleSilentAutopx (self):
1468 result = self.SilentCommand ("%autopx") 1469 if result.find ("rror") != -1: 1470 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1471 "toggleSilentAutopx", result)
1472
1473 - def VisItPath (self):
1474 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1475 self.SilentCommand ("BASIN_TEMP_FILE = open (os.getenv ('HOME') + '/.basin/host/visit.path', 'r+')") 1476 result = self.SilentCommand ("print \"\\n\" + BASIN_TEMP_FILE.read ()[:-1]") 1477 self.SilentCommand ("BASIN_TEMP_FILE.close ()") 1478 self.SilentCommand ("del (BASIN_TEMP_FILE)") 1479 if result.find ("rror") != -1: 1480 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", "VisItPath", result) 1481 return 1482 result = result.split ("\n") 1483 index = 0 1484 for i in xrange (len (result)): 1485 if outRegexp.match (result[i]): 1486 index = i 1487 result = str (result[index + 1]) 1488 result = result[:result.rfind ('/')] 1489 result = result[:result.rfind ('/')] 1490 return result
1491
1492 - def ScriptPath (self):
1493 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1494 self.SilentCommand ("BASIN_TEMP_FILE = open (os.getenv ('HOME') + '/.basin/host/client_script.path', 'r+')") 1495 result = self.SilentCommand ("print \"\\n\" + BASIN_TEMP_FILE.read ()[:-1]") 1496 self.SilentCommand ("BASIN_TEMP_FILE.close ()") 1497 self.SilentCommand ("del (BASIN_TEMP_FILE)") 1498 if result.find ("rror") != -1: 1499 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1500 "ScriptPath", result) 1501 return 1502 result = result.split ("\n") 1503 index = 0 1504 for i in xrange (len (result)): 1505 if outRegexp.match (result[i]): 1506 index = i 1507 return str (result[index + 1])
1508
1509 - def getVariableType (self, var):
1510 result = self.SilentCommand ("print \"\\n\" + str (type (" + var + "))").split ("\n")[3] 1511 result = result[result.index ("'") + 1:result.rindex ("'")] 1512 return result
1513
1514 - def getVisitModuleStatus (self):
1515 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1516 result = self.ControllerCommand ("print \"\\\\n\" + str (BASIN_VISIT_START)", False) 1517 if result.find ("rror") != -1: 1518 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1519 "getVisitModuleStatus", result) 1520 return False 1521 result = result.split ("\n") 1522 index = 0 1523 for i in xrange (len (result)): 1524 if outRegexp.match (result[i]): 1525 index = i 1526 return str (result[index + 1])
1527
1528 - def getVisItExposeContinuous (self):
1529 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1530 result = self.ControllerCommand ("print \"\\\\n\" + BASIN_VISIT_CONTINUOUS_LIST", False) 1531 if result.find ("rror") != -1: 1532 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1533 "getVisItExposeContinuous", result) 1534 return [] 1535 result = result.split ("\n") 1536 index = 0 1537 for i in xrange (len (result)): 1538 if outRegexp.match (result[i]): 1539 index = i 1540 result = result[index + 1:] 1541 1542 exposeList = [] 1543 windowList = [] 1544 for line in result: 1545 colon = line.rfind (":") 1546 exposeList.append (line[:colon]) 1547 windowList.append (line[colon + 1:]) 1548 return exposeList, windowList
1549
1550 - def getVisItExposeDiscrete (self):
1551 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1552 result = self.ControllerCommand ("print \"\\\\n\" + BASIN_VISIT_DISCRETE_LIST", False) 1553 if result.find ("rror") != -1: 1554 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1555 "getVisItExposeDiscrete", result) 1556 return [] 1557 result = result.split ("\n") 1558 index = 0 1559 for i in xrange (len (result)): 1560 if outRegexp.match (result[i]): 1561 index = i 1562 result = result[index + 1:] 1563 1564 exposeList = [] 1565 windowList = [] 1566 for line in result: 1567 colon = line.rfind (":") 1568 exposeList.append (line[:colon]) 1569 windowList.append (line[colon + 1:]) 1570 return exposeList, windowList
1571 1572
1573 - def getTopLevelRegions (self):
1574 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1575 result = self.ControllerCommand ("print \"\\\\n\" + BASIN_TOPLEVEL_REGION_LIST", False) 1576 if result.find ("rror") != -1: 1577 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1578 "getTopLevelRegions", result) 1579 return [] 1580 result = result.split ("\n") 1581 index = 0 1582 for i in xrange (len (result)): 1583 if outRegexp.match (result[i]): 1584 index = i 1585 return result[index + 1:]
1586
1587 - def removeTopLevelRegion (self, oldname):
1588 regionList = self.getTopLevelRegions () 1589 finalString = "" 1590 # swap out all occurances of oldname in regionList with newname 1591 for each in regionList: 1592 if each != oldname: 1593 finalString += str (each) + "\\n" 1594 result = self.SilentCommand ("BASIN_TOPLEVEL_REGION_LIST = \'" + \ 1595 str (finalString) + "\'", False) 1596 if result.find ("rror") != -1: 1597 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1598 "removeTopLevelRegion", result)
1599
1600 - def removeFreeVariable (self, oldname):
1601 freeVars, freeAccesses = self.getFreeVariables () 1602 finalString = "" 1603 index = 0 1604 while index < len (freeVars): 1605 if freeVars[index] != oldname: 1606 finalString += str (freeVars[index]) + "\\n" 1607 finalString += "-" + str (freeAccesses[index]) + "-\\n" 1608 index += 1 1609 result = self.SilentCommand ("BASIN_FREE_VARIABLE_LIST = \'" + \ 1610 str (finalString) + "\'", False) 1611 if result.find ("rror") != -1: 1612 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1613 "removeFreeVariable", result)
1614
1615 - def replaceFreeVariable (self, varName, shellAccess):
1616 freeVars, freeAccesses = self.getFreeVariables () 1617 finalString = "" 1618 index = 0 1619 while index < len (freeVars): 1620 if freeVars[index] != varName: 1621 finalString += str (freeVars[index]) + "\\n" 1622 finalString += "-" + str (freeAccesses[index]) + "-\\n" 1623 else: 1624 finalString += str (varName) + "\\n" 1625 finalString += "-" + str (shellAccess) + "-\\n" 1626 index += 1 1627 result = self.SilentCommand ("BASIN_FREE_VARIABLE_LIST = \'" + \ 1628 str (finalString) + "\'", False) 1629 if result.find ("rror") != -1: 1630 self._bridge.Error ("BASIN_ipython_shell.py", "IPythonView", \ 1631 "replaceFreeVariable", result)
1632
1633 - def getFreeVariables (self):
1634 # Retrieve the entire free variable storage variable 1635 # and split it into a list of string lines 1636 outRegexp = re.compile ("\[.*\]\s*Out\s*\[.*\]:") 1637 result = self.ControllerCommand ("print \"\\\\n\" + BASIN_FREE_VARIABLE_LIST", False) 1638 result = result.split ("\n") 1639 index = 0 1640 for i in xrange (len (result)): 1641 if outRegexp.match (result[i]): 1642 index = i 1643 1644 # garbage lines 1645 result = result[index + 1:] 1646 1647 temp = None 1648 real_result, real_access = [], [] 1649 for elem in result: 1650 # This conditional checks for the second line needed for a fv 1651 # which is the shell access, also denoted by being surrounded by -'s 1652 if elem[0] == "-" and elem[-1] == "-": 1653 if len (real_result) == len (real_access) + 1: 1654 real_access.append (elem[1:-1]) 1655 elif temp: 1656 real_access[real_result.index (temp)] = elem[1:-1] 1657 temp = None 1658 # And if it isn't surrounded by -'s, it is the actual free variable 1659 else: 1660 if real_result.count (elem) < 1: 1661 real_result.append (elem) 1662 else: 1663 temp = elem 1664 return real_result, real_access
1665 1666 # Checks to see if the command-line has anything in it
1667 - def isClear (self):
1668 if self._commandLine.text () == "": 1669 return True 1670 return False
1671 1672 # So that objects using the bridge don't need to type so much, 1673 # I extract the method to this higher-level object
1674 - def setUpdateLine (self):
1675 self._commandLine.setUpdateLine ()
1676 1677
1678 -def stripColor (string):
1679 """ 1680 stripColor (string): 1681 1682 Takes in a string, and returns that same string with 1683 all console colors having been removed. 1684 """ 1685 result, show, index, L = "", True, 0, len (string) 1686 while index < L: 1687 if (not show) and (string[index] in ['m']): 1688 show = True 1689 elif show: 1690 n = string.find('\x1B', index) 1691 if n == -1: 1692 return result + string[index:] 1693 else: 1694 result += string[index:n] 1695 index = n 1696 show = False 1697 index += 1 1698 return result
1699 1700
1701 -def PyLabOptionsParse (options):
1702 commands = [] 1703 for option in options: 1704 if "=" in option: 1705 equalsIndex = option.index ("=") 1706 type = option[:equalsIndex] 1707 value = option[equalsIndex + 1:] 1708 commands.append ("pylab." + type + " (\"" + value + "\")") 1709 else: 1710 commands.append ("pylab." + option + " ()") 1711 1712 return commands
1713