blob: ad42a9b1e6e184f3a22e59d6f9c904d86c7d24cd [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
Guido van Rossuma93b8481998-06-23 19:31:19 +00009import traceback
Tim Peters6cd6a822001-08-17 22:11:27 +000010from codeop import CommandCompiler, compile_command
Guido van Rossum90981e01997-10-07 14:47:24 +000011
Tim Peters6cd6a822001-08-17 22:11:27 +000012__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact",
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000013 "compile_command"]
14
Guido van Rossum4ec59c72001-01-13 22:10:41 +000015def softspace(file, newvalue):
16 oldvalue = 0
17 try:
18 oldvalue = file.softspace
19 except AttributeError:
20 pass
21 try:
22 file.softspace = newvalue
Guido van Rossum555d12f2001-09-18 13:33:01 +000023 except (AttributeError, TypeError):
24 # "attribute-less object" or "read-only attributes"
Guido van Rossum4ec59c72001-01-13 22:10:41 +000025 pass
26 return oldvalue
Guido van Rossum90981e01997-10-07 14:47:24 +000027
Guido van Rossum5227f0f1998-09-22 20:38:53 +000028class InteractiveInterpreter:
29 """Base class for InteractiveConsole.
Guido van Rossuma93b8481998-06-23 19:31:19 +000030
Guido van Rossum5227f0f1998-09-22 20:38:53 +000031 This class deals with parsing and interpreter state (the user's
32 namespace); it doesn't deal with input buffering or prompting or
33 input file naming (the filename is always passed in explicitly).
34
Guido van Rossuma93b8481998-06-23 19:31:19 +000035 """
36
Guido van Rossum5227f0f1998-09-22 20:38:53 +000037 def __init__(self, locals=None):
Guido van Rossuma93b8481998-06-23 19:31:19 +000038 """Constructor.
39
Guido van Rossum5227f0f1998-09-22 20:38:53 +000040 The optional 'locals' argument specifies the dictionary in
41 which code will be executed; it defaults to a newly created
42 dictionary with key "__name__" set to "__console__" and key
43 "__doc__" set to None.
Guido van Rossuma93b8481998-06-23 19:31:19 +000044
45 """
Guido van Rossuma93b8481998-06-23 19:31:19 +000046 if locals is None:
Guido van Rossum5227f0f1998-09-22 20:38:53 +000047 locals = {"__name__": "__console__", "__doc__": None}
Guido van Rossuma93b8481998-06-23 19:31:19 +000048 self.locals = locals
Tim Peters6cd6a822001-08-17 22:11:27 +000049 self.compile = CommandCompiler()
Guido van Rossum5227f0f1998-09-22 20:38:53 +000050
51 def runsource(self, source, filename="<input>", symbol="single"):
52 """Compile and run some source in the interpreter.
53
54 Arguments are as for compile_command().
55
56 One several things can happen:
57
58 1) The input is incorrect; compile_command() raised an
59 exception (SyntaxError or OverflowError). A syntax traceback
60 will be printed by calling the showsyntaxerror() method.
61
62 2) The input is incomplete, and more input is required;
63 compile_command() returned None. Nothing happens.
64
65 3) The input is complete; compile_command() returned a code
66 object. The code is executed by calling self.runcode() (which
67 also handles run-time exceptions, except for SystemExit).
68
69 The return value is 1 in case 2, 0 in the other cases (unless
70 an exception is raised). The return value can be used to
71 decide whether to use sys.ps1 or sys.ps2 to prompt the next
72 line.
73
74 """
75 try:
Tim Peters6cd6a822001-08-17 22:11:27 +000076 code = self.compile(source, filename, symbol)
Guido van Rossum48450cf2001-01-15 18:13:35 +000077 except (OverflowError, SyntaxError, ValueError):
Guido van Rossum5227f0f1998-09-22 20:38:53 +000078 # Case 1
79 self.showsyntaxerror(filename)
80 return 0
81
82 if code is None:
83 # Case 2
84 return 1
85
86 # Case 3
87 self.runcode(code)
88 return 0
89
90 def runcode(self, code):
91 """Execute a code object.
92
93 When an exception occurs, self.showtraceback() is called to
94 display a traceback. All exceptions are caught except
95 SystemExit, which is reraised.
96
97 A note about KeyboardInterrupt: this exception may occur
98 elsewhere in this code, and may not always be caught. The
99 caller should be prepared to deal with it.
100
101 """
102 try:
103 exec code in self.locals
104 except SystemExit:
105 raise
106 except:
107 self.showtraceback()
Guido van Rossum4ec59c72001-01-13 22:10:41 +0000108 else:
109 if softspace(sys.stdout, 0):
110 print
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000111
112 def showsyntaxerror(self, filename=None):
113 """Display the syntax error that just occurred.
114
115 This doesn't display a stack trace because there isn't one.
116
117 If a filename is given, it is stuffed in the exception instead
118 of what was there before (because Python's parser always uses
119 "<string>" when reading from a string).
120
121 The output is written by self.write(), below.
122
123 """
124 type, value, sys.last_traceback = sys.exc_info()
125 sys.last_type = type
126 sys.last_value = value
127 if filename and type is SyntaxError:
128 # Work hard to stuff the correct filename in the exception
129 try:
130 msg, (dummy_filename, lineno, offset, line) = value
131 except:
132 # Not the format we expect; leave it alone
133 pass
134 else:
135 # Stuff in the right filename
136 try:
137 # Assume SyntaxError is a class exception
138 value = SyntaxError(msg, (filename, lineno, offset, line))
139 except:
140 # If that failed, assume SyntaxError is a string
141 value = msg, (filename, lineno, offset, line)
Fred Drakec7745d42001-05-03 04:58:49 +0000142 sys.last_value = value
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000143 list = traceback.format_exception_only(type, value)
144 map(self.write, list)
145
146 def showtraceback(self):
147 """Display the exception that just occurred.
148
149 We remove the first stack item because it is our own code.
150
151 The output is written by self.write(), below.
152
153 """
154 try:
155 type, value, tb = sys.exc_info()
156 sys.last_type = type
157 sys.last_value = value
158 sys.last_traceback = tb
159 tblist = traceback.extract_tb(tb)
160 del tblist[:1]
161 list = traceback.format_list(tblist)
162 if list:
Guido van Rossum7dd06962000-12-27 19:12:58 +0000163 list.insert(0, "Traceback (most recent call last):\n")
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000164 list[len(list):] = traceback.format_exception_only(type, value)
165 finally:
166 tblist = tb = None
167 map(self.write, list)
168
169 def write(self, data):
170 """Write a string.
171
172 The base implementation writes to sys.stderr; a subclass may
173 replace this with a different implementation.
174
175 """
176 sys.stderr.write(data)
177
178
179class InteractiveConsole(InteractiveInterpreter):
180 """Closely emulate the behavior of the interactive Python interpreter.
181
182 This class builds on InteractiveInterpreter and adds prompting
183 using the familiar sys.ps1 and sys.ps2, and input buffering.
184
185 """
186
187 def __init__(self, locals=None, filename="<console>"):
188 """Constructor.
189
190 The optional locals argument will be passed to the
191 InteractiveInterpreter base class.
192
193 The optional filename argument should specify the (file)name
194 of the input stream; it will show up in tracebacks.
195
196 """
197 InteractiveInterpreter.__init__(self, locals)
198 self.filename = filename
Guido van Rossuma93b8481998-06-23 19:31:19 +0000199 self.resetbuffer()
200
201 def resetbuffer(self):
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000202 """Reset the input buffer."""
Guido van Rossuma93b8481998-06-23 19:31:19 +0000203 self.buffer = []
204
205 def interact(self, banner=None):
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000206 """Closely emulate the interactive Python console.
207
208 The optional banner argument specify the banner to print
209 before the first interaction; by default it prints a banner
210 similar to the one printed by the real Python interpreter,
211 followed by the current class name in parentheses (so as not
212 to confuse this with the real interpreter -- since it's so
213 close!).
214
215 """
Guido van Rossuma93b8481998-06-23 19:31:19 +0000216 try:
217 sys.ps1
218 except AttributeError:
219 sys.ps1 = ">>> "
220 try:
221 sys.ps2
222 except AttributeError:
223 sys.ps2 = "... "
Guido van Rossumc5f15b02001-01-14 23:04:22 +0000224 cprt = 'Type "copyright", "credits" or "license" for more information.'
Guido van Rossuma93b8481998-06-23 19:31:19 +0000225 if banner is None:
226 self.write("Python %s on %s\n%s\n(%s)\n" %
Guido van Rossumc5f15b02001-01-14 23:04:22 +0000227 (sys.version, sys.platform, cprt,
Guido van Rossuma93b8481998-06-23 19:31:19 +0000228 self.__class__.__name__))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000229 else:
Guido van Rossuma93b8481998-06-23 19:31:19 +0000230 self.write("%s\n" % str(banner))
231 more = 0
232 while 1:
233 try:
234 if more:
235 prompt = sys.ps2
236 else:
237 prompt = sys.ps1
238 try:
239 line = self.raw_input(prompt)
240 except EOFError:
241 self.write("\n")
242 break
243 else:
244 more = self.push(line)
245 except KeyboardInterrupt:
246 self.write("\nKeyboardInterrupt\n")
247 self.resetbuffer()
248 more = 0
249
250 def push(self, line):
251 """Push a line to the interpreter.
252
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000253 The line should not have a trailing newline; it may have
254 internal newlines. The line is appended to a buffer and the
255 interpreter's runsource() method is called with the
256 concatenated contents of the buffer as source. If this
257 indicates that the command was executed or invalid, the buffer
258 is reset; otherwise, the command is incomplete, and the buffer
259 is left as it was after the line was appended. The return
260 value is 1 if more input is required, 0 if the line was dealt
261 with in some way (this is the same as runsource()).
Guido van Rossuma93b8481998-06-23 19:31:19 +0000262
263 """
264 self.buffer.append(line)
Eric S. Raymond6b71e742001-02-09 08:56:30 +0000265 source = "\n".join(self.buffer)
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000266 more = self.runsource(source, self.filename)
267 if not more:
Guido van Rossuma93b8481998-06-23 19:31:19 +0000268 self.resetbuffer()
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000269 return more
Guido van Rossuma93b8481998-06-23 19:31:19 +0000270
271 def raw_input(self, prompt=""):
272 """Write a prompt and read a line.
273
274 The returned line does not include the trailing newline.
275 When the user enters the EOF key sequence, EOFError is raised.
276
277 The base implementation uses the built-in function
278 raw_input(); a subclass may replace this with a different
279 implementation.
280
281 """
282 return raw_input(prompt)
283
284
Guido van Rossumd90ae191998-10-19 18:42:53 +0000285def interact(banner=None, readfunc=None, local=None):
Guido van Rossuma93b8481998-06-23 19:31:19 +0000286 """Closely emulate the interactive Python interpreter.
287
288 This is a backwards compatible interface to the InteractiveConsole
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000289 class. When readfunc is not specified, it attempts to import the
290 readline module to enable GNU readline if it is available.
Guido van Rossuma93b8481998-06-23 19:31:19 +0000291
292 Arguments (all optional, all default to None):
293
294 banner -- passed to InteractiveConsole.interact()
295 readfunc -- if not None, replaces InteractiveConsole.raw_input()
Guido van Rossumd90ae191998-10-19 18:42:53 +0000296 local -- passed to InteractiveInterpreter.__init__()
Guido van Rossuma93b8481998-06-23 19:31:19 +0000297
298 """
Guido van Rossumd90ae191998-10-19 18:42:53 +0000299 console = InteractiveConsole(local)
Guido van Rossuma93b8481998-06-23 19:31:19 +0000300 if readfunc is not None:
301 console.raw_input = readfunc
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000302 else:
303 try:
304 import readline
305 except:
306 pass
Guido van Rossuma93b8481998-06-23 19:31:19 +0000307 console.interact(banner)
Guido van Rossum5227f0f1998-09-22 20:38:53 +0000308
309
Guido van Rossum90981e01997-10-07 14:47:24 +0000310if __name__ == '__main__':
311 interact()