| 1 | """Interpreter executes Python commands.""" |
| 2 | |
| 3 | __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" |
| 4 | __cvsid__ = "$Id$" |
| 5 | __revision__ = "$Revision$"[11:-2] |
| 6 | |
| 7 | import os |
| 8 | import sys |
| 9 | from code import InteractiveInterpreter |
| 10 | import dispatcher |
| 11 | import introspect |
| 12 | import wx |
| 13 | |
| 14 | class Interpreter(InteractiveInterpreter): |
| 15 | """Interpreter based on code.InteractiveInterpreter.""" |
| 16 | |
| 17 | revision = __revision__ |
| 18 | |
| 19 | def __init__(self, locals=None, rawin=None, |
| 20 | stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr): |
| 21 | """Create an interactive interpreter object.""" |
| 22 | InteractiveInterpreter.__init__(self, locals=locals) |
| 23 | self.stdin = stdin |
| 24 | self.stdout = stdout |
| 25 | self.stderr = stderr |
| 26 | if rawin: |
| 27 | import __builtin__ |
| 28 | __builtin__.raw_input = rawin |
| 29 | del __builtin__ |
| 30 | copyright = 'Type "help", "copyright", "credits" or "license"' |
| 31 | copyright += ' for more information.' |
| 32 | self.introText = 'Python %s on %s%s%s' % \ |
| 33 | (sys.version, sys.platform, os.linesep, copyright) |
| 34 | try: |
| 35 | sys.ps1 |
| 36 | except AttributeError: |
| 37 | sys.ps1 = '>>> ' |
| 38 | try: |
| 39 | sys.ps2 |
| 40 | except AttributeError: |
| 41 | sys.ps2 = '... ' |
| 42 | self.more = 0 |
| 43 | # List of lists to support recursive push(). |
| 44 | self.commandBuffer = [] |
| 45 | self.startupScript = None |
| 46 | |
| 47 | |
| 48 | def push(self, command): |
| 49 | """Send command to the interpreter to be executed. |
| 50 | |
| 51 | Because this may be called recursively, we append a new list |
| 52 | onto the commandBuffer list and then append commands into |
| 53 | that. If the passed in command is part of a multi-line |
| 54 | command we keep appending the pieces to the last list in |
| 55 | commandBuffer until we have a complete command. If not, we |
| 56 | delete that last list.""" |
| 57 | |
| 58 | # In case the command is unicode try encoding it |
| 59 | if type(command) == unicode: |
| 60 | try: |
| 61 | command = command.encode(wx.GetDefaultPyEncoding()) |
| 62 | except UnicodeEncodeError: |
| 63 | pass # otherwise leave it alone |
| 64 | |
| 65 | if not self.more: |
| 66 | try: del self.commandBuffer[-1] |
| 67 | except IndexError: pass |
| 68 | if not self.more: self.commandBuffer.append([]) |
| 69 | self.commandBuffer[-1].append(command) |
| 70 | source = '\n'.join(self.commandBuffer[-1]) |
| 71 | more = self.more = self.runsource(source) |
| 72 | dispatcher.send(signal='Interpreter.push', sender=self, |
| 73 | command=command, more=more, source=source) |
| 74 | return more |
| 75 | |
| 76 | def runsource(self, source): |
| 77 | """Compile and run source code in the interpreter.""" |
| 78 | stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr |
| 79 | sys.stdin, sys.stdout, sys.stderr = \ |
| 80 | self.stdin, self.stdout, self.stderr |
| 81 | more = InteractiveInterpreter.runsource(self, source) |
| 82 | # If sys.std* is still what we set it to, then restore it. |
| 83 | # But, if the executed source changed sys.std*, assume it was |
| 84 | # meant to be changed and leave it. Power to the people. |
| 85 | if sys.stdin == self.stdin: |
| 86 | sys.stdin = stdin |
| 87 | if sys.stdout == self.stdout: |
| 88 | sys.stdout = stdout |
| 89 | if sys.stderr == self.stderr: |
| 90 | sys.stderr = stderr |
| 91 | return more |
| 92 | |
| 93 | def getAutoCompleteKeys(self): |
| 94 | """Return list of auto-completion keycodes.""" |
| 95 | return [ord('.')] |
| 96 | |
| 97 | def getAutoCompleteList(self, command='', *args, **kwds): |
| 98 | """Return list of auto-completion options for a command. |
| 99 | |
| 100 | The list of options will be based on the locals namespace.""" |
| 101 | stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr |
| 102 | sys.stdin, sys.stdout, sys.stderr = \ |
| 103 | self.stdin, self.stdout, self.stderr |
| 104 | l = introspect.getAutoCompleteList(command, self.locals, |
| 105 | *args, **kwds) |
| 106 | sys.stdin, sys.stdout, sys.stderr = stdin, stdout, stderr |
| 107 | return l |
| 108 | |
| 109 | def getCallTip(self, command='', *args, **kwds): |
| 110 | """Return call tip text for a command. |
| 111 | |
| 112 | Call tip information will be based on the locals namespace.""" |
| 113 | return introspect.getCallTip(command, self.locals, *args, **kwds) |
| 114 | |
| 115 | |
| 116 | class InterpreterAlaCarte(Interpreter): |
| 117 | """Demo Interpreter.""" |
| 118 | |
| 119 | def __init__(self, locals, rawin, stdin, stdout, stderr, |
| 120 | ps1='main prompt', ps2='continuation prompt'): |
| 121 | """Create an interactive interpreter object.""" |
| 122 | Interpreter.__init__(self, locals=locals, rawin=rawin, |
| 123 | stdin=stdin, stdout=stdout, stderr=stderr) |
| 124 | sys.ps1 = ps1 |
| 125 | sys.ps2 = ps2 |
| 126 | |
| 127 | |