Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a93b848

Browse files
committed
Subsume the interact() function in a class. This should make it
possible to use this in PythonWin, and to replace Fredrik Lundh's PythonInterpreter class. Fredrik is credited with the class' API.
1 parent d9d2625 commit a93b848

1 file changed

Lines changed: 197 additions & 42 deletions

File tree

Lib/code.py

Lines changed: 197 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
"""Utilities dealing with code objects."""
22

3+
import sys
4+
import string
5+
import traceback
6+
37
def compile_command(source, filename="<input>", symbol="single"):
48
r"""Compile a command and determine whether it is incomplete.
59
@@ -60,51 +64,202 @@ def compile_command(source, filename="<input>", symbol="single"):
6064
raise SyntaxError, err1
6165

6266

63-
def interact(banner=None, readfunc=raw_input, local=None):
64-
# Due to Jeff Epler, with changes by Guido:
65-
"""Closely emulate the interactive Python console."""
66-
try: import readline # Enable GNU readline if available
67-
except: pass
68-
local = local or {}
69-
import sys, string, traceback
70-
sys.ps1 = '>>> '
71-
sys.ps2 = '... '
72-
if banner:
73-
print banner
74-
else:
75-
print "Python Interactive Console", sys.version
76-
print sys.copyright
77-
buf = []
78-
while 1:
79-
if buf: prompt = sys.ps2
80-
else: prompt = sys.ps1
81-
try: line = readfunc(prompt)
82-
except KeyboardInterrupt:
83-
print "\nKeyboardInterrupt"
84-
buf = []
85-
continue
86-
except EOFError: break
87-
buf.append(line)
88-
try: x = compile_command(string.join(buf, "\n"))
67+
class InteractiveConsole:
68+
"""Closely emulate the behavior of the interactive Python interpreter.
69+
70+
After code by Jeff Epler and Fredrik Lundh.
71+
"""
72+
73+
def __init__(self, filename="<console>", locals=None):
74+
"""Constructor.
75+
76+
The optional filename argument specifies the (file)name of the
77+
input stream; it will show up in tracebacks. It defaults to
78+
'<console>'.
79+
80+
"""
81+
self.filename = filename
82+
if locals is None:
83+
locals = {}
84+
self.locals = locals
85+
self.resetbuffer()
86+
87+
def resetbuffer(self):
88+
"""Reset the input buffer (but not the variables!)."""
89+
self.buffer = []
90+
91+
def interact(self, banner=None):
92+
"""Closely emulate the interactive Python console."""
93+
try:
94+
sys.ps1
95+
except AttributeError:
96+
sys.ps1 = ">>> "
97+
try:
98+
sys.ps2
99+
except AttributeError:
100+
sys.ps2 = "... "
101+
if banner is None:
102+
self.write("Python %s on %s\n%s\n(%s)\n" %
103+
(sys.version, sys.platform, sys.copyright,
104+
self.__class__.__name__))
105+
else:
106+
self.write("%s\n" % str(banner))
107+
more = 0
108+
while 1:
109+
try:
110+
if more:
111+
prompt = sys.ps2
112+
else:
113+
prompt = sys.ps1
114+
try:
115+
line = self.raw_input(prompt)
116+
except EOFError:
117+
self.write("\n")
118+
break
119+
else:
120+
more = self.push(line)
121+
except KeyboardInterrupt:
122+
self.write("\nKeyboardInterrupt\n")
123+
self.resetbuffer()
124+
more = 0
125+
126+
def push(self, line):
127+
"""Push a line to the interpreter.
128+
129+
The line should not have a trailing newline.
130+
131+
One of three things will happen:
132+
133+
1) The input is incorrect; compile_command() raised
134+
SyntaxError. A syntax traceback will be printed.
135+
136+
2) The input is incomplete, and more input is required;
137+
compile_command() returned None.
138+
139+
3) The input is complete; compile_command() returned a code
140+
object. The code is executed. When an exception occurs, a
141+
traceback is printed. All exceptions are caught except
142+
SystemExit, which is reraised.
143+
144+
The return value is 1 in case 2, 0 in the other cases. (The
145+
return value can be used to decide whether to use sys.ps1 or
146+
sys.ps2 to prompt the next line.)
147+
148+
A note about KeyboardInterrupt: this exception may occur
149+
elsewhere in this code, and will not always be caught. The
150+
caller should be prepared to deal with it.
151+
152+
"""
153+
self.buffer.append(line)
154+
155+
try:
156+
x = compile_command(string.join(self.buffer, "\n"),
157+
filename=self.filename)
89158
except SyntaxError:
90-
traceback.print_exc(0)
91-
buf = []
92-
continue
93-
if x == None: continue
159+
# Case 1
160+
self.showsyntaxerror()
161+
self.resetbuffer()
162+
return 0
163+
164+
if x is None:
165+
# Case 2
166+
return 1
167+
168+
# Case 3
169+
try:
170+
exec x in self.locals
171+
except SystemExit:
172+
raise
173+
except:
174+
self.showtraceback()
175+
self.resetbuffer()
176+
return 0
177+
178+
def showsyntaxerror(self):
179+
"""Display the syntax error that just occurred.
180+
181+
This doesn't display a stack trace because there isn't one.
182+
183+
The output is written by self.write(), below.
184+
185+
"""
186+
type, value = sys.exc_info()[:2]
187+
# Work hard to stuff the correct filename in the exception
188+
try:
189+
msg, (filename, lineno, offset, line) = value
190+
except:
191+
pass
94192
else:
95-
try: exec x in local
193+
try:
194+
value = SyntaxError(msg, (self.filename, lineno, offset, line))
96195
except:
97-
exc_type, exc_value, exc_traceback = \
98-
sys.exc_type, sys.exc_value, \
99-
sys.exc_traceback
100-
l = len(traceback.extract_tb(sys.exc_traceback))
101-
try: 1/0
102-
except:
103-
m = len(traceback.extract_tb(
104-
sys.exc_traceback))
105-
traceback.print_exception(exc_type,
106-
exc_value, exc_traceback, l-m)
107-
buf = []
196+
value = msg, (self.filename, lineno, offset, line)
197+
list = traceback.format_exception_only(type, value)
198+
map(self.write, list)
199+
200+
def showtraceback(self):
201+
"""Display the exception that just occurred.
202+
203+
We remove the first stack item because it is our own code.
204+
205+
The output is written by self.write(), below.
206+
207+
"""
208+
try:
209+
type, value, tb = sys.exc_info()
210+
tblist = traceback.extract_tb(tb)
211+
del tblist[0]
212+
list = traceback.format_list(tblist)
213+
list[len(list):] = traceback.format_exception_only(type, value)
214+
finally:
215+
tblist = tb = None
216+
map(self.write, list)
217+
218+
def write(self, data):
219+
"""Write a string.
220+
221+
The base implementation writes to sys.stderr; a subclass may
222+
replace this with a different implementation.
223+
224+
"""
225+
sys.stderr.write(data)
226+
227+
def raw_input(self, prompt=""):
228+
"""Write a prompt and read a line.
229+
230+
The returned line does not include the trailing newline.
231+
When the user enters the EOF key sequence, EOFError is raised.
232+
233+
The base implementation uses the built-in function
234+
raw_input(); a subclass may replace this with a different
235+
implementation.
236+
237+
"""
238+
return raw_input(prompt)
239+
240+
241+
def interact(banner=None, readfunc=None, locals=None):
242+
"""Closely emulate the interactive Python interpreter.
243+
244+
This is a backwards compatible interface to the InteractiveConsole
245+
class. It attempts to import the readline module to enable GNU
246+
readline if it is available.
247+
248+
Arguments (all optional, all default to None):
249+
250+
banner -- passed to InteractiveConsole.interact()
251+
readfunc -- if not None, replaces InteractiveConsole.raw_input()
252+
locals -- passed to InteractiveConsole.__init__()
253+
254+
"""
255+
try:
256+
import readline
257+
except:
258+
pass
259+
console = InteractiveConsole(locals=locals)
260+
if readfunc is not None:
261+
console.raw_input = readfunc
262+
console.interact(banner)
108263

109264
if __name__ == '__main__':
110265
interact()

0 commit comments

Comments
 (0)