@@ -85,7 +85,13 @@ def __init__(self, locals=None, encoding=None):
8585 necessarily must be with the current factoring) and then an exception
8686 callback can be added to the Interpreter instance afterwards - more
8787 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+ """
8995
9096 self .encoding = encoding or sys .getdefaultencoding ()
9197 self .syntaxerror_callback = None
@@ -98,15 +104,55 @@ def reset_running_time(self):
98104 self .running_time = 0
99105
100106 def runsource (self , source , filename = None , symbol = 'single' ,
101- encode = True ):
107+ encode = 'auto' ):
102108 """Execute Python code.
103109
104110 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
110156 if filename is None :
111157 filename = filename_for_console_input (source )
112158 with self .timer :
@@ -132,11 +178,11 @@ def showsyntaxerror(self, filename=None):
132178 pass
133179 else :
134180 # Stuff in the right filename and right lineno
135- if not py3 :
136- lineno -= 2
137181 # strip linecache line number
138182 if re .match (r'<bpython-input-\d+>' , filename ):
139183 filename = '<input>'
184+ if filename == '<input>' and not py3 :
185+ lineno -= 2
140186 value = SyntaxError (msg , (filename , lineno , offset , line ))
141187 sys .last_value = value
142188 list = traceback .format_exception_only (type , value )
@@ -160,8 +206,7 @@ def showtraceback(self):
160206 fname = '<input>'
161207 tblist [i ] = (fname , lineno , module , something )
162208 # 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 :
165210 tblist [i ] = (fname , lineno - 2 , module , something )
166211
167212 l = traceback .format_list (tblist )
0 commit comments