~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Lib/code.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

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