##// END OF EJS Templates
Fix getting unicode lines in IPython.core.debugger.
Thomas Kluyver -
Show More
@@ -0,0 +1,38 b''
1 """Wrapper around linecache which decodes files to unicode according to PEP 263.
2
3 This is only needed for Python 2 - linecache in Python 3 does the same thing
4 itself.
5 """
6 import functools
7 import linecache
8
9 from IPython.utils import py3compat
10 from IPython.utils import openpy
11
12 if py3compat.PY3:
13 getline = linecache.getline
14
15 # getlines has to be looked up at runtime, because doctests monkeypatch it.
16 @functools.wraps(linecache.getlines)
17 def getlines(filename, module_globals=None):
18 return linecache.getlines(filename, module_globals=module_globals)
19
20 else:
21 def getlines(filename, module_globals=None):
22 """Get the lines (as unicode) for a file from the cache.
23 Update the cache if it doesn't contain an entry for this file already."""
24 linesb = linecache.getlines(filename, module_globals=module_globals)
25 readline = openpy._list_readline(linesb)
26 try:
27 encoding, _ = openpy.detect_encoding(readline)
28 except SyntaxError:
29 encoding = 'ascii'
30 return [l.decode(encoding, 'replace') for l in linesb]
31
32 # This is a straight copy of linecache.getline
33 def getline(filename, lineno, module_globals=None):
34 lines = getlines(filename, module_globals)
35 if 1 <= lineno <= len(lines):
36 return lines[lineno-1]
37 else:
38 return ''
@@ -30,7 +30,7 b' import bdb'
30 import linecache
30 import linecache
31 import sys
31 import sys
32
32
33 from IPython.utils import PyColorize, py3compat
33 from IPython.utils import PyColorize, ulinecache
34 from IPython.core import ipapi
34 from IPython.core import ipapi
35 from IPython.utils import coloransi, io, openpy
35 from IPython.utils import coloransi, io, openpy
36 from IPython.core.excolors import exception_colors
36 from IPython.core.excolors import exception_colors
@@ -179,22 +179,6 b' def _file_lines(fname):'
179 return out
179 return out
180
180
181
181
182 def _readline(x):
183 """helper to pop elements off list of string
184
185 call with list of strings, return readline function that will pop
186 one line off the beginning of a copy of the list with each call.
187 raise StopIteration when empty or on third call
188 """
189 x = x[:2]
190 def readline():
191 if x:
192 return x.pop(0)
193 else:
194 raise StopIteration
195 return readline
196
197
198 class Pdb(OldPdb):
182 class Pdb(OldPdb):
199 """Modified Pdb class, does not load readline."""
183 """Modified Pdb class, does not load readline."""
200
184
@@ -320,7 +304,7 b' class Pdb(OldPdb):'
320 # vds: <<
304 # vds: <<
321
305
322 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
306 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
323 import linecache, repr
307 import repr
324
308
325 ret = []
309 ret = []
326
310
@@ -367,11 +351,7 b' class Pdb(OldPdb):'
367 ret.append('%s(%s)%s\n' % (link,lineno,call))
351 ret.append('%s(%s)%s\n' % (link,lineno,call))
368
352
369 start = lineno - 1 - context//2
353 start = lineno - 1 - context//2
370 lines = linecache.getlines(filename)
354 lines = ulinecache.getlines(filename)
371 try:
372 encoding, _ = openpy.detect_encoding(_readline(lines))
373 except SyntaxError:
374 encoding = "ascii"
375 start = max(start, 0)
355 start = max(start, 0)
376 start = min(start, len(lines) - context)
356 start = min(start, len(lines) - context)
377 lines = lines[start : start + context]
357 lines = lines[start : start + context]
@@ -382,7 +362,7 b' class Pdb(OldPdb):'
382 and tpl_line_em \
362 and tpl_line_em \
383 or tpl_line
363 or tpl_line
384 ret.append(self.__format_line(linetpl, filename,
364 ret.append(self.__format_line(linetpl, filename,
385 start + 1 + i, py3compat.cast_unicode(line),
365 start + 1 + i, line,
386 arrow = show_arrow) )
366 arrow = show_arrow) )
387 return ''.join(ret)
367 return ''.join(ret)
388
368
@@ -442,18 +422,10 b' class Pdb(OldPdb):'
442 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
422 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
443 src = []
423 src = []
444 if filename == "<string>" and hasattr(self, "_exec_filename"):
424 if filename == "<string>" and hasattr(self, "_exec_filename"):
445 lines = list(open(self._exec_filename))
425 filename = self._exec_filename
446 else:
426
447 lines = linecache.getlines(filename)
448 try:
449 encoding, _ = openpy.detect_encoding(_readline(lines))
450 except SyntaxError:
451 encoding = "ascii"
452 if not lines:
453 print >>io.stdout, "No src could be located using filename: %r"%filename
454 return #Bailing out, there is nothing to see here
455 for lineno in range(first, last+1):
427 for lineno in range(first, last+1):
456 line = py3compat.cast_unicode(lines[lineno])
428 ulinecache.getline(filename, lineno)
457 if not line:
429 if not line:
458 break
430 break
459
431
@@ -208,3 +208,12 b" def read_py_url(url, errors='replace', skip_encoding_cookie=True):"
208 response = urllib.urlopen(url)
208 response = urllib.urlopen(url)
209 buffer = io.BytesIO(response.read())
209 buffer = io.BytesIO(response.read())
210 return source_to_unicode(buffer, errors, skip_encoding_cookie)
210 return source_to_unicode(buffer, errors, skip_encoding_cookie)
211
212 def _list_readline(x):
213 """Given a list, returns a readline() function that returns the next element
214 with each call.
215 """
216 x = iter(x)
217 def readline():
218 return next(x)
219 return readline
General Comments 0
You need to be logged in to leave comments. Login now