@@ -85,7 +85,13 @@ def __init__(self, locals=None, encoding=None):
85
85
necessarily must be with the current factoring) and then an exception
86
86
callback can be added to the Interpreter instance afterwards - more
87
87
specifically, this is so that autoindentation does not occur after a
88
- traceback."""
88
+ traceback.
89
+
90
+ encoding is only used in Python 2, where it may be necessary to add an
91
+ encoding comment to a source bytestring before running it.
92
+ encoding must be a bytestring in Python 2 because it will be templated
93
+ into a bytestring source as part of an encoding comment.
94
+ """
89
95
90
96
self .encoding = encoding or sys .getdefaultencoding ()
91
97
self .syntaxerror_callback = None
@@ -98,15 +104,55 @@ def reset_running_time(self):
98
104
self .running_time = 0
99
105
100
106
def runsource (self , source , filename = None , symbol = 'single' ,
101
- encode = True ):
107
+ encode = 'auto' ):
102
108
"""Execute Python code.
103
109
104
110
source, filename and symbol are passed on to
105
- code.InteractiveInterpreter.runsource. If encode is True, the source
106
- will be encoded. On Python 3.X, encode will be ignored."""
107
- if not py3 and encode :
108
- source = u'# coding: %s\n \n %s' % (self .encoding , source )
109
- source = source .encode (self .encoding )
111
+ code.InteractiveInterpreter.runsource. If encode is True,
112
+ an encoding comment will be added to the source.
113
+ On Python 3.X, encode will be ignored.
114
+
115
+ encode should only be used for interactive interpreter input,
116
+ files should always already have an encoding comment or be ASCII.
117
+ By default an encoding line will be added if no filename is given.
118
+
119
+ In Python 3, source must be a unicode string
120
+ In Python 2, source may be latin-1 bytestring or unicode string,
121
+ following the interface of code.InteractiveInterpreter.
122
+
123
+ Because adding an encoding comment to a unicode string in Python 2
124
+ would cause a syntax error to be thrown which would reference code
125
+ the user did not write, setting encoding to True when source is a
126
+ unicode string in Python 2 will throw a ValueError."""
127
+ # str means bytestring in Py2
128
+ if encode and not py3 and isinstance (source , unicode ):
129
+ if encode != 'auto' :
130
+ raise ValueError ("can't add encoding line to unicode input" )
131
+ encode = False
132
+ if encode and filename is not None :
133
+ # files have encoding comments or implicit encoding of ASCII
134
+ if encode != 'auto' :
135
+ raise ValueError ("shouldn't add encoding line to file contents" )
136
+ encode = False
137
+
138
+ if encode and not py3 and isinstance (source , str ):
139
+ # encoding makes sense for bytestrings, so long as there
140
+ # isn't already an encoding comment
141
+ comment = inspection .get_encoding_comment (source )
142
+ if comment :
143
+ # keep the existing encoding comment, but add two lines
144
+ # because this interp always adds 2 to stack trace line
145
+ # numbers in Python 2
146
+ source = source .replace (comment , b'%s\n \n ' % comment , 1 )
147
+ else :
148
+ source = b'# coding: %s\n \n %s' % (self .encoding , source )
149
+ elif not py3 and filename is None :
150
+ # 2 blank lines still need to be added
151
+ # because this interpreter always adds 2 to stack trace line
152
+ # numbers in Python 2 when the filename is "<input>"
153
+ newlines = u'\n \n ' if isinstance (source , unicode ) else b'\n \n '
154
+ source = newlines + source
155
+ # we know we're in Python 2 here, so ok to reference unicode
110
156
if filename is None :
111
157
filename = filename_for_console_input (source )
112
158
with self .timer :
@@ -132,11 +178,11 @@ def showsyntaxerror(self, filename=None):
132
178
pass
133
179
else :
134
180
# Stuff in the right filename and right lineno
135
- if not py3 :
136
- lineno -= 2
137
181
# strip linecache line number
138
182
if re .match (r'<bpython-input-\d+>' , filename ):
139
183
filename = '<input>'
184
+ if filename == '<input>' and not py3 :
185
+ lineno -= 2
140
186
value = SyntaxError (msg , (filename , lineno , offset , line ))
141
187
sys .last_value = value
142
188
list = traceback .format_exception_only (type , value )
@@ -160,8 +206,7 @@ def showtraceback(self):
160
206
fname = '<input>'
161
207
tblist [i ] = (fname , lineno , module , something )
162
208
# Set the right lineno (encoding header adds an extra line)
163
- if not py3 :
164
- if fname == '<input>' :
209
+ if fname == '<input>' and not py3 :
165
210
tblist [i ] = (fname , lineno - 2 , module , something )
166
211
167
212
l = traceback .format_list (tblist )
0 commit comments