blob: 5f65b7c9946b3b6c1118c21152f0edc9a6844635 [file] [log] [blame]
Guido van Rossum5d42b5b1998-10-22 21:56:44 +00001"""Utilities needed to emulate Python's interactive interpreter.
Guido van Rossum5227f0f1998-09-22 20:38:53 +00002
Guido van Rossum5227f0f1998-09-22 20:38:53 +00003"""
Guido van Rossum1557a731997-07-18 16:57:52 +00004
Guido van Rossum98d9fd32000-02-28 15:12:25 +00005# Inspired by similar code by Jeff Epler and Fredrik Lundh.
6
Guido van Rossum5d42b5b1998-10-22 21:56:44 +00007
Guido van Rossuma93b8481998-06-23 19:31:19 +00008import sys
9import string
10import traceback
Guido van Rossum5d42b5b1998-10-22 21:56:44 +000011from codeop import compile_command
Guido van Rossum90981e01997-10-07 14:47:24 +000012
13
Guido van Rossum5227f0f1998-09-22 20:38:53 +000014class InteractiveInterpreter:
15 """Base class for InteractiveConsole.
Guido van Rossuma93b8481998-06-23 19:31:19 +000016
Guido van Rossum5227f0f1998-09-22 20:38:53 +000017 This class deals with parsing and interpreter state (the user's
18 namespace); it doesn't deal with input buffering or prompting or
19 input file naming (the filename is always passed in explicitly).
20
Guido van Rossuma93b8481998-06-23 19:31:19 +000021 """
22
Guido van Rossum5227f0f1998-09-22 20:38:53 +000023 def __init__(self, locals=None):
Guido van Rossuma93b8481998-06-23 19:31:19 +000024 """Constructor.
25
Guido van Rossum5227f0f1998-09-22 20:38:53 +000026 The optional 'locals' argument specifies the dictionary in
27 which code will be executed; it defaults to a newly created
28 dictionary with key "__name__" set to "__console__" and key
29 "__doc__" set to None.
Guido van Rossuma93b8481998-06-23 19:31:19 +000030
31 """
Guido van Rossuma93b8481998-06-23 19:31:19 +000032 if locals is None:
Guido van Rossum5227f0f1998-09-22 20:38:53 +000033 locals = {"__name__": "__console__", "__doc__": None}
Guido van Rossuma93b8481998-06-23 19:31:19 +000034 self.locals = locals
Guido van Rossum5227f0f1998-09-22 20:38:53 +000035
36 def runsource(self, source, filename="<input>", symbol="single"):
37 """Compile and run some source in the interpreter.
38
39 Arguments are as for compile_command().
40
41 One several things can happen:
42
43 1) The input is incorrect; compile_command() raised an
44 exception (SyntaxError or OverflowError). A syntax traceback
45 will be printed by calling the showsyntaxerror() method.
46
47 2) The input is incomplete, and more input is required;
48 compile_command() returned None. Nothing happens.
49
50 3) The input is complete; compile_command() returned a code
51 object. The code is executed by calling self.runcode() (which
52 also handles run-time exceptions, except for SystemExit).
53
54 The return value is 1 in case 2, 0 in the other cases (unless
55 an exception is raised). The return value can be used to
56 decide whether to use sys.ps1 or sys.ps2 to prompt the next
57 line.
58
59 """
60 try:
61 code = compile_command(source, filename, symbol)
62 except (OverflowError, SyntaxError):
63 # Case 1
64 self.showsyntaxerror(filename)
65 return 0
66
67 if code is None:
68 # Case 2
69 return 1
70
71 # Case 3
72 self.runcode(code)
73 return 0
74
75 def runcode(self, code):
76 """Execute a code object.
77
78 When an exception occurs, self.showtraceback() is called to
79 display a traceback. All exceptions are caught except
80 SystemExit, which is reraised.
81
82 A note about KeyboardInterrupt: this exception may occur
83 elsewhere in this code, and may not always be caught. The
84 caller should be prepared to deal with it.
85
86 """
87 try:
88 exec code in self.locals
89 except SystemExit:
90 raise
91 except:
92 self.showtraceback()
93
94 def showsyntaxerror(self, filename=None):
95 """Display the syntax error that just occurred.
96
97 This doesn't display a stack trace because there isn't one.
98
99 If a filename is given, it is stuffed in the exception instead
100 of what was there before (because Python's parser always uses
101 "<string>" when reading from a string).
102
103 The output is written by self.write(), below.
104
105 """
106 type, value, sys.last_traceback = sys.exc_info()
107 sys.last_type = type
108 sys.last_value = value
109 if filename and type is SyntaxError:
110 # Work hard to stuff the correct filename in the exception
111 try:
112 msg, (dummy_filename, lineno, offset, line) = value
113 except:
114 # Not the format we expect; leave it alone
115 pass
116 else:
117 # Stuff in the right filename
118 try:
119 # Assume SyntaxError is a class exception
120 value = SyntaxError(msg, (filename, lineno, offset, line))
121 except:
122 # If that failed, assume SyntaxError is a string
123 value = msg, (filename, lineno, offset, line)
124 list = traceback.format_exception_only(type, value)
125 map(self.write, list)
126
127 def showtraceback(self):
128 """Display the exception that just occurred.
129
130 We remove the first stack item because it is our own code.
131
132 The output is written by self.write(), below.
133
134 """
135 try:
136 type, value, tb = sys.exc_info()
137 sys.last_type = type
138 sys.last_value = value
139 sys.last_traceback = tb
140 tblist = traceback.extract_tb(tb)
141 del tblist[:1]
142 list = traceback.format_list(tblist)
143 if list:
144 list.insert(0, "Traceback (innermost last):\n")
145 list[len(list):] = traceback.format_exception_only(type, value)
146 finally:
147 tblist = tb = None
148 map(self.write, list)
149
150 def write(self, data):
151 """Write a string.
152
153 The base implementation writes to sys.stderr; a subclass may
154 replace this with a different implementation.
155
156 """
157 sys.stderr.write(data)
158
159
160class InteractiveConsole(InteractiveInterpreter):
161 """Closely emulate the behavior of the interactive Python interpreter.
162
163 This class builds on InteractiveInterpreter and adds prompting
164 using the familiar sys.ps1 and sys.ps2, and input buffering.
165
166 """
167
168 def __init__(self, locals=None, filename="<console>"):
169 """Constructor.
170
171 The optional locals argument will be passed to the
172 InteractiveInterpreter base class.
173
174 The optional filename argument should specify the (file)name
175 of the input stream; it will show up in tracebacks.
176
177 """
178 InteractiveInterpreter.__init__(self, locals)
179 self.filename = filename
Guido van Rossuma93b8481998-06-23 19:31:19 +0000180 self.resetbuffer()
181
182 def resetbuffer(self):
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000183 """Reset the input buffer."""
Guido van Rossuma93b8481998-06-23 19:31:19 +0000184 self.buffer = []
185
186 def interact(self, banner=None):
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000187 """Closely emulate the interactive Python console.
188
189 The optional banner argument specify the banner to print
190 before the first interaction; by default it prints a banner
191 similar to the one printed by the real Python interpreter,
192 followed by the current class name in parentheses (so as not
193 to confuse this with the real interpreter -- since it's so
194 close!).
195
196 """
Guido van Rossuma93b8481998-06-23 19:31:19 +0000197 try:
198 sys.ps1
199 except AttributeError:
200 sys.ps1 = ">>> "
201 try:
202 sys.ps2
203 except AttributeError:
204 sys.ps2 = "... "
205 if banner is None:
206 self.write("Python %s on %s\n%s\n(%s)\n" %
207 (sys.version, sys.platform, sys.copyright,
208 self.__class__.__name__))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000209 else:
Guido van Rossuma93b8481998-06-23 19:31:19 +0000210 self.write("%s\n" % str(banner))
211 more = 0
212 while 1:
213 try:
214 if more:
215 prompt = sys.ps2
216 else:
217 prompt = sys.ps1
218 try:
219 line = self.raw_input(prompt)
220 except EOFError:
221 self.write("\n")
222 break
223 else:
224 more = self.push(line)
225 except KeyboardInterrupt:
226 self.write("\nKeyboardInterrupt\n")
227 self.resetbuffer()
228 more = 0
229
230 def push(self, line):
231 """Push a line to the interpreter.
232
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000233 The line should not have a trailing newline; it may have
234 internal newlines. The line is appended to a buffer and the
235 interpreter's runsource() method is called with the
236 concatenated contents of the buffer as source. If this
237 indicates that the command was executed or invalid, the buffer
238 is reset; otherwise, the command is incomplete, and the buffer
239 is left as it was after the line was appended. The return
240 value is 1 if more input is required, 0 if the line was dealt
241 with in some way (this is the same as runsource()).
Guido van Rossuma93b8481998-06-23 19:31:19 +0000242
243 """
244 self.buffer.append(line)
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000245 source = string.join(self.buffer, "\n")
246 more = self.runsource(source, self.filename)
247 if not more:
Guido van Rossuma93b8481998-06-23 19:31:19 +0000248 self.resetbuffer()
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000249 return more
Guido van Rossuma93b8481998-06-23 19:31:19 +0000250
251 def raw_input(self, prompt=""):
252 """Write a prompt and read a line.
253
254 The returned line does not include the trailing newline.
255 When the user enters the EOF key sequence, EOFError is raised.
256
257 The base implementation uses the built-in function
258 raw_input(); a subclass may replace this with a different
259 implementation.
260
261 """
262 return raw_input(prompt)
263
264
Guido van Rossumd90ae191998-10-19 18:42:53 +0000265def interact(banner=None, readfunc=None, local=None):
Guido van Rossuma93b8481998-06-23 19:31:19 +0000266 """Closely emulate the interactive Python interpreter.
267
268 This is a backwards compatible interface to the InteractiveConsole
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000269 class. When readfunc is not specified, it attempts to import the
270 readline module to enable GNU readline if it is available.
Guido van Rossuma93b8481998-06-23 19:31:19 +0000271
272 Arguments (all optional, all default to None):
273
274 banner -- passed to InteractiveConsole.interact()
275 readfunc -- if not None, replaces InteractiveConsole.raw_input()
Guido van Rossumd90ae191998-10-19 18:42:53 +0000276 local -- passed to InteractiveInterpreter.__init__()
Guido van Rossuma93b8481998-06-23 19:31:19 +0000277
278 """
Guido van Rossumd90ae191998-10-19 18:42:53 +0000279 console = InteractiveConsole(local)
Guido van Rossuma93b8481998-06-23 19:31:19 +0000280 if readfunc is not None:
281 console.raw_input = readfunc
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000282 else:
283 try:
284 import readline
285 except:
286 pass
Guido van Rossuma93b8481998-06-23 19:31:19 +0000287 console.interact(banner)
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000288
289
Guido van Rossum90981e01997-10-07 14:47:24 +0000290if __name__ == '__main__':
291 interact()