Show More
@@ -0,0 +1,45 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 | import sys | |||
|
9 | ||||
|
10 | from IPython.utils import py3compat | |||
|
11 | from IPython.utils import openpy | |||
|
12 | ||||
|
13 | if py3compat.PY3: | |||
|
14 | getline = linecache.getline | |||
|
15 | ||||
|
16 | # getlines has to be looked up at runtime, because doctests monkeypatch it. | |||
|
17 | @functools.wraps(linecache.getlines) | |||
|
18 | def getlines(filename, module_globals=None): | |||
|
19 | return linecache.getlines(filename, module_globals=module_globals) | |||
|
20 | ||||
|
21 | else: | |||
|
22 | def getlines(filename, module_globals=None): | |||
|
23 | """Get the lines (as unicode) for a file from the cache. | |||
|
24 | Update the cache if it doesn't contain an entry for this file already.""" | |||
|
25 | filename = py3compat.cast_bytes(filename, sys.getfilesystemencoding()) | |||
|
26 | lines = linecache.getlines(filename, module_globals=module_globals) | |||
|
27 | ||||
|
28 | # The bits we cache ourselves can be unicode. | |||
|
29 | if (not lines) or isinstance(lines[0], unicode): | |||
|
30 | return lines | |||
|
31 | ||||
|
32 | readline = openpy._list_readline(lines) | |||
|
33 | try: | |||
|
34 | encoding, _ = openpy.detect_encoding(readline) | |||
|
35 | except SyntaxError: | |||
|
36 | encoding = 'ascii' | |||
|
37 | return [l.decode(encoding, 'replace') for l in lines] | |||
|
38 | ||||
|
39 | # This is a straight copy of linecache.getline | |||
|
40 | def getline(filename, lineno, module_globals=None): | |||
|
41 | lines = getlines(filename, module_globals) | |||
|
42 | if 1 <= lineno <= len(lines): | |||
|
43 | return lines[lineno-1] | |||
|
44 | else: | |||
|
45 | return '' |
@@ -30,9 +30,9 b' import bdb' | |||||
30 | import linecache |
|
30 | import linecache | |
31 | import sys |
|
31 | import sys | |
32 |
|
32 | |||
33 | from IPython.utils import PyColorize |
|
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 |
|
35 | from IPython.utils import coloransi, io, openpy, py3compat | |
36 | from IPython.core.excolors import exception_colors |
|
36 | from IPython.core.excolors import exception_colors | |
37 |
|
37 | |||
38 | # See if we can use pydb. |
|
38 | # See if we can use pydb. | |
@@ -304,16 +304,16 b' class Pdb(OldPdb):' | |||||
304 | # vds: << |
|
304 | # vds: << | |
305 |
|
305 | |||
306 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): |
|
306 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): | |
307 |
import |
|
307 | import repr | |
308 |
|
308 | |||
309 | ret = [] |
|
309 | ret = [] | |
310 |
|
310 | |||
311 | Colors = self.color_scheme_table.active_colors |
|
311 | Colors = self.color_scheme_table.active_colors | |
312 | ColorsNormal = Colors.Normal |
|
312 | ColorsNormal = Colors.Normal | |
313 | tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal) |
|
313 | tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal) | |
314 | tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) |
|
314 | tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal) | |
315 | tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) |
|
315 | tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) | |
316 | tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, |
|
316 | tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, | |
317 | ColorsNormal) |
|
317 | ColorsNormal) | |
318 |
|
318 | |||
319 | frame, lineno = frame_lineno |
|
319 | frame, lineno = frame_lineno | |
@@ -327,7 +327,7 b' class Pdb(OldPdb):' | |||||
327 |
|
327 | |||
328 | #s = filename + '(' + `lineno` + ')' |
|
328 | #s = filename + '(' + `lineno` + ')' | |
329 | filename = self.canonic(frame.f_code.co_filename) |
|
329 | filename = self.canonic(frame.f_code.co_filename) | |
330 | link = tpl_link % filename |
|
330 | link = tpl_link % py3compat.cast_unicode(filename) | |
331 |
|
331 | |||
332 | if frame.f_code.co_name: |
|
332 | if frame.f_code.co_name: | |
333 | func = frame.f_code.co_name |
|
333 | func = frame.f_code.co_name | |
@@ -348,10 +348,10 b' class Pdb(OldPdb):' | |||||
348 | ret.append('> ') |
|
348 | ret.append('> ') | |
349 | else: |
|
349 | else: | |
350 | ret.append(' ') |
|
350 | ret.append(' ') | |
351 | ret.append('%s(%s)%s\n' % (link,lineno,call)) |
|
351 | ret.append(u'%s(%s)%s\n' % (link,lineno,call)) | |
352 |
|
352 | |||
353 | start = lineno - 1 - context//2 |
|
353 | start = lineno - 1 - context//2 | |
354 | lines = linecache.getlines(filename) |
|
354 | lines = ulinecache.getlines(filename) | |
355 | start = max(start, 0) |
|
355 | start = max(start, 0) | |
356 | start = min(start, len(lines) - context) |
|
356 | start = min(start, len(lines) - context) | |
357 | lines = lines[start : start + context] |
|
357 | lines = lines[start : start + context] | |
@@ -364,7 +364,6 b' class Pdb(OldPdb):' | |||||
364 | ret.append(self.__format_line(linetpl, filename, |
|
364 | ret.append(self.__format_line(linetpl, filename, | |
365 | start + 1 + i, line, |
|
365 | start + 1 + i, line, | |
366 | arrow = show_arrow) ) |
|
366 | arrow = show_arrow) ) | |
367 |
|
||||
368 | return ''.join(ret) |
|
367 | return ''.join(ret) | |
369 |
|
368 | |||
370 | def __format_line(self, tpl_line, filename, lineno, line, arrow = False): |
|
369 | def __format_line(self, tpl_line, filename, lineno, line, arrow = False): | |
@@ -422,8 +421,11 b' class Pdb(OldPdb):' | |||||
422 | tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) |
|
421 | tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal) | |
423 | 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) | |
424 | src = [] |
|
423 | src = [] | |
|
424 | if filename == "<string>" and hasattr(self, "_exec_filename"): | |||
|
425 | filename = self._exec_filename | |||
|
426 | ||||
425 | for lineno in range(first, last+1): |
|
427 | for lineno in range(first, last+1): | |
426 | line = linecache.getline(filename, lineno) |
|
428 | line = ulinecache.getline(filename, lineno) | |
427 | if not line: |
|
429 | if not line: | |
428 | break |
|
430 | break | |
429 |
|
431 |
@@ -2908,7 +2908,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2908 | lines = self.history_manager.get_range_by_str(range_str, raw=raw) |
|
2908 | lines = self.history_manager.get_range_by_str(range_str, raw=raw) | |
2909 | return "\n".join(x for _, _, x in lines) |
|
2909 | return "\n".join(x for _, _, x in lines) | |
2910 |
|
2910 | |||
2911 | def find_user_code(self, target, raw=True, py_only=False): |
|
2911 | def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True): | |
2912 | """Get a code string from history, file, url, or a string or macro. |
|
2912 | """Get a code string from history, file, url, or a string or macro. | |
2913 |
|
2913 | |||
2914 | This is mainly used by magic functions. |
|
2914 | This is mainly used by magic functions. | |
@@ -2945,7 +2945,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2945 | utarget = unquote_filename(target) |
|
2945 | utarget = unquote_filename(target) | |
2946 | try: |
|
2946 | try: | |
2947 | if utarget.startswith(('http://', 'https://')): |
|
2947 | if utarget.startswith(('http://', 'https://')): | |
2948 |
return openpy.read_py_url(utarget, skip_encoding_cookie= |
|
2948 | return openpy.read_py_url(utarget, skip_encoding_cookie=skip_encoding_cookie) | |
2949 | except UnicodeDecodeError: |
|
2949 | except UnicodeDecodeError: | |
2950 | if not py_only : |
|
2950 | if not py_only : | |
2951 | response = urllib.urlopen(target) |
|
2951 | response = urllib.urlopen(target) | |
@@ -2961,7 +2961,7 b' class InteractiveShell(SingletonConfigurable):' | |||||
2961 | for tgt in potential_target : |
|
2961 | for tgt in potential_target : | |
2962 | if os.path.isfile(tgt): # Read file |
|
2962 | if os.path.isfile(tgt): # Read file | |
2963 | try : |
|
2963 | try : | |
2964 |
return openpy.read_py_file(tgt, skip_encoding_cookie= |
|
2964 | return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie) | |
2965 | except UnicodeDecodeError : |
|
2965 | except UnicodeDecodeError : | |
2966 | if not py_only : |
|
2966 | if not py_only : | |
2967 | with io_open(tgt,'r', encoding='latin1') as f : |
|
2967 | with io_open(tgt,'r', encoding='latin1') as f : |
@@ -554,6 +554,8 b' python-profiler package from non-free.""")' | |||||
554 | print "%s prompt to start your script." % deb.prompt |
|
554 | print "%s prompt to start your script." % deb.prompt | |
555 | ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns} |
|
555 | ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns} | |
556 | try: |
|
556 | try: | |
|
557 | #save filename so it can be used by methods on the deb object | |||
|
558 | deb._exec_filename = filename | |||
557 | deb.run('execfile("%s", prog_ns)' % filename, ns) |
|
559 | deb.run('execfile("%s", prog_ns)' % filename, ns) | |
558 |
|
560 | |||
559 | except: |
|
561 | except: |
@@ -23,6 +23,7 b' from IPython.core.error import StdinNotImplementedError, UsageError' | |||||
23 | from IPython.core.magic import Magics, magics_class, line_magic |
|
23 | from IPython.core.magic import Magics, magics_class, line_magic | |
24 | from IPython.testing.skipdoctest import skip_doctest |
|
24 | from IPython.testing.skipdoctest import skip_doctest | |
25 | from IPython.utils.encoding import DEFAULT_ENCODING |
|
25 | from IPython.utils.encoding import DEFAULT_ENCODING | |
|
26 | from IPython.utils.openpy import read_py_file | |||
26 | from IPython.utils.path import get_py_filename |
|
27 | from IPython.utils.path import get_py_filename | |
27 |
|
28 | |||
28 | #----------------------------------------------------------------------------- |
|
29 | #----------------------------------------------------------------------------- | |
@@ -118,7 +119,7 b' class NamespaceMagics(Magics):' | |||||
118 | except IOError as msg: |
|
119 | except IOError as msg: | |
119 | print msg |
|
120 | print msg | |
120 | return |
|
121 | return | |
121 |
page.page(self.shell. |
|
122 | page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False))) | |
122 |
|
123 | |||
123 | @line_magic |
|
124 | @line_magic | |
124 | def psearch(self, parameter_s=''): |
|
125 | def psearch(self, parameter_s=''): |
@@ -32,6 +32,7 b' from IPython.core.magic import (' | |||||
32 | ) |
|
32 | ) | |
33 | from IPython.testing.skipdoctest import skip_doctest |
|
33 | from IPython.testing.skipdoctest import skip_doctest | |
34 | from IPython.utils.io import file_read, nlprint |
|
34 | from IPython.utils.io import file_read, nlprint | |
|
35 | from IPython.utils.openpy import source_to_unicode | |||
35 | from IPython.utils.path import get_py_filename, unquote_filename |
|
36 | from IPython.utils.path import get_py_filename, unquote_filename | |
36 | from IPython.utils.process import abbrev_cwd |
|
37 | from IPython.utils.process import abbrev_cwd | |
37 | from IPython.utils.terminal import set_term_title |
|
38 | from IPython.utils.terminal import set_term_title | |
@@ -686,12 +687,12 b' class OSMagics(Magics):' | |||||
686 | 'or macro.') |
|
687 | 'or macro.') | |
687 |
|
688 | |||
688 | try : |
|
689 | try : | |
689 | cont = self.shell.find_user_code(parameter_s) |
|
690 | cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False) | |
690 | except (ValueError, IOError): |
|
691 | except (ValueError, IOError): | |
691 | print "Error: no such file, variable, URL, history range or macro" |
|
692 | print "Error: no such file, variable, URL, history range or macro" | |
692 | return |
|
693 | return | |
693 |
|
694 | |||
694 | page.page(self.shell.pycolorize(cont)) |
|
695 | page.page(self.shell.pycolorize(source_to_unicode(cont))) | |
695 |
|
696 | |||
696 | @magic_arguments.magic_arguments() |
|
697 | @magic_arguments.magic_arguments() | |
697 | @magic_arguments.argument( |
|
698 | @magic_arguments.argument( |
@@ -24,6 +24,8 b' import linecache' | |||||
24 | import os |
|
24 | import os | |
25 | import sys |
|
25 | import sys | |
26 | import types |
|
26 | import types | |
|
27 | import io as stdlib_io | |||
|
28 | ||||
27 | from collections import namedtuple |
|
29 | from collections import namedtuple | |
28 | try: |
|
30 | try: | |
29 | from itertools import izip_longest |
|
31 | from itertools import izip_longest | |
@@ -35,10 +37,12 b' from IPython.core import page' | |||||
35 | from IPython.testing.skipdoctest import skip_doctest_py3 |
|
37 | from IPython.testing.skipdoctest import skip_doctest_py3 | |
36 | from IPython.utils import PyColorize |
|
38 | from IPython.utils import PyColorize | |
37 | from IPython.utils import io |
|
39 | from IPython.utils import io | |
|
40 | from IPython.utils import openpy | |||
38 | from IPython.utils import py3compat |
|
41 | from IPython.utils import py3compat | |
39 | from IPython.utils.text import indent |
|
42 | from IPython.utils.text import indent | |
40 | from IPython.utils.wildcard import list_namespace |
|
43 | from IPython.utils.wildcard import list_namespace | |
41 | from IPython.utils.coloransi import * |
|
44 | from IPython.utils.coloransi import * | |
|
45 | from IPython.utils.py3compat import cast_unicode | |||
42 |
|
46 | |||
43 | #**************************************************************************** |
|
47 | #**************************************************************************** | |
44 | # Builtin color schemes |
|
48 | # Builtin color schemes | |
@@ -90,6 +94,29 b' def object_info(**kw):' | |||||
90 | return infodict |
|
94 | return infodict | |
91 |
|
95 | |||
92 |
|
96 | |||
|
97 | def get_encoding(obj): | |||
|
98 | """Get encoding for python source file defining obj | |||
|
99 | ||||
|
100 | Returns None if obj is not defined in a sourcefile. | |||
|
101 | """ | |||
|
102 | ofile = find_file(obj) | |||
|
103 | # run contents of file through pager starting at line where the object | |||
|
104 | # is defined, as long as the file isn't binary and is actually on the | |||
|
105 | # filesystem. | |||
|
106 | if ofile is None: | |||
|
107 | return None | |||
|
108 | elif ofile.endswith(('.so', '.dll', '.pyd')): | |||
|
109 | return None | |||
|
110 | elif not os.path.isfile(ofile): | |||
|
111 | return None | |||
|
112 | else: | |||
|
113 | # Print only text files, not extension binaries. Note that | |||
|
114 | # getsourcelines returns lineno with 1-offset and page() uses | |||
|
115 | # 0-offset, so we must adjust. | |||
|
116 | buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2 | |||
|
117 | encoding, lines = openpy.detect_encoding(buffer.readline) | |||
|
118 | return encoding | |||
|
119 | ||||
93 | def getdoc(obj): |
|
120 | def getdoc(obj): | |
94 | """Stable wrapper around inspect.getdoc. |
|
121 | """Stable wrapper around inspect.getdoc. | |
95 |
|
122 | |||
@@ -109,10 +136,13 b' def getdoc(obj):' | |||||
109 | return inspect.cleandoc(ds) |
|
136 | return inspect.cleandoc(ds) | |
110 |
|
137 | |||
111 | try: |
|
138 | try: | |
112 |
|
|
139 | docstr = inspect.getdoc(obj) | |
|
140 | encoding = get_encoding(obj) | |||
|
141 | return py3compat.cast_unicode(docstr, encoding=encoding) | |||
113 | except Exception: |
|
142 | except Exception: | |
114 | # Harden against an inspect failure, which can occur with |
|
143 | # Harden against an inspect failure, which can occur with | |
115 | # SWIG-wrapped extensions. |
|
144 | # SWIG-wrapped extensions. | |
|
145 | raise | |||
116 | return None |
|
146 | return None | |
117 |
|
147 | |||
118 |
|
148 | |||
@@ -143,7 +173,8 b' def getsource(obj,is_binary=False):' | |||||
143 | except TypeError: |
|
173 | except TypeError: | |
144 | if hasattr(obj,'__class__'): |
|
174 | if hasattr(obj,'__class__'): | |
145 | src = inspect.getsource(obj.__class__) |
|
175 | src = inspect.getsource(obj.__class__) | |
146 | return src |
|
176 | encoding = get_encoding(obj) | |
|
177 | return cast_unicode(src, encoding=encoding) | |||
147 |
|
178 | |||
148 | def getargspec(obj): |
|
179 | def getargspec(obj): | |
149 | """Get the names and default values of a function's arguments. |
|
180 | """Get the names and default values of a function's arguments. | |
@@ -319,9 +350,8 b' class Inspector:' | |||||
319 | exception is suppressed.""" |
|
350 | exception is suppressed.""" | |
320 |
|
351 | |||
321 | try: |
|
352 | try: | |
322 | # We need a plain string here, NOT unicode! |
|
|||
323 | hdef = oname + inspect.formatargspec(*getargspec(obj)) |
|
353 | hdef = oname + inspect.formatargspec(*getargspec(obj)) | |
324 |
return |
|
354 | return cast_unicode(hdef) | |
325 | except: |
|
355 | except: | |
326 | return None |
|
356 | return None | |
327 |
|
357 | |||
@@ -435,7 +465,7 b' class Inspector:' | |||||
435 | except: |
|
465 | except: | |
436 | self.noinfo('source',oname) |
|
466 | self.noinfo('source',oname) | |
437 | else: |
|
467 | else: | |
438 |
page.page(self.format( |
|
468 | page.page(self.format(src)) | |
439 |
|
469 | |||
440 | def pfile(self, obj, oname=''): |
|
470 | def pfile(self, obj, oname=''): | |
441 | """Show the whole file where an object was defined.""" |
|
471 | """Show the whole file where an object was defined.""" | |
@@ -457,7 +487,7 b' class Inspector:' | |||||
457 | # Print only text files, not extension binaries. Note that |
|
487 | # Print only text files, not extension binaries. Note that | |
458 | # getsourcelines returns lineno with 1-offset and page() uses |
|
488 | # getsourcelines returns lineno with 1-offset and page() uses | |
459 | # 0-offset, so we must adjust. |
|
489 | # 0-offset, so we must adjust. | |
460 |
page.page(self.format(open(ofile |
|
490 | page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1) | |
461 |
|
491 | |||
462 | def _format_fields(self, fields, title_width=12): |
|
492 | def _format_fields(self, fields, title_width=12): | |
463 | """Formats a list of fields for display. |
|
493 | """Formats a list of fields for display. | |
@@ -476,7 +506,7 b' class Inspector:' | |||||
476 | title = header(title + ":") + "\n" |
|
506 | title = header(title + ":") + "\n" | |
477 | else: |
|
507 | else: | |
478 | title = header((title+":").ljust(title_width)) |
|
508 | title = header((title+":").ljust(title_width)) | |
479 | out.append(title + content) |
|
509 | out.append(cast_unicode(title) + cast_unicode(content)) | |
480 | return "\n".join(out) |
|
510 | return "\n".join(out) | |
481 |
|
511 | |||
482 | # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict) |
|
512 | # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict) | |
@@ -536,7 +566,8 b' class Inspector:' | |||||
536 | # Source or docstring, depending on detail level and whether |
|
566 | # Source or docstring, depending on detail level and whether | |
537 | # source found. |
|
567 | # source found. | |
538 | if detail_level > 0 and info['source'] is not None: |
|
568 | if detail_level > 0 and info['source'] is not None: | |
539 |
displayfields.append(("Source", |
|
569 | displayfields.append(("Source", | |
|
570 | self.format(cast_unicode(info['source'])))) | |||
540 | elif info['docstring'] is not None: |
|
571 | elif info['docstring'] is not None: | |
541 | displayfields.append(("Docstring", info["docstring"])) |
|
572 | displayfields.append(("Docstring", info["docstring"])) | |
542 |
|
573 |
@@ -1,6 +1,7 b'' | |||||
|
1 | # encoding: utf-8 | |||
1 | """Tests for IPython.core.ultratb |
|
2 | """Tests for IPython.core.ultratb | |
2 | """ |
|
3 | """ | |
3 |
|
4 | import io | ||
4 | import os.path |
|
5 | import os.path | |
5 | import unittest |
|
6 | import unittest | |
6 |
|
7 | |||
@@ -49,3 +50,26 b' class ChangedPyFileTest(unittest.TestCase):' | |||||
49 | ip.run_cell("foo.f()") |
|
50 | ip.run_cell("foo.f()") | |
50 | with tt.AssertPrints("ZeroDivisionError"): |
|
51 | with tt.AssertPrints("ZeroDivisionError"): | |
51 | ip.run_cell("foo.f()") |
|
52 | ip.run_cell("foo.f()") | |
|
53 | ||||
|
54 | iso_8859_5_file = u'''# coding: iso-8859-5 | |||
|
55 | ||||
|
56 | def fail(): | |||
|
57 | """дбИЖ""" | |||
|
58 | 1/0 # дбИЖ | |||
|
59 | ''' | |||
|
60 | ||||
|
61 | class NonAsciiTest(unittest.TestCase): | |||
|
62 | def test_iso8859_5(self): | |||
|
63 | # Non-ascii directory name as well. | |||
|
64 | with TemporaryDirectory(suffix=u'é') as td: | |||
|
65 | fname = os.path.join(td, 'dfghjkl.py') | |||
|
66 | ||||
|
67 | with io.open(fname, 'w', encoding='iso-8859-5') as f: | |||
|
68 | f.write(iso_8859_5_file) | |||
|
69 | ||||
|
70 | with prepended_to_syspath(td): | |||
|
71 | ip.run_cell("from dfghjkl import fail") | |||
|
72 | ||||
|
73 | with tt.AssertPrints("ZeroDivisionError"): | |||
|
74 | with tt.AssertPrints(u'дбИЖ', suppress=False): | |||
|
75 | ip.run_cell('fail()') |
@@ -69,7 +69,7 b' possible inclusion in future releases.' | |||||
69 | # the file COPYING, distributed as part of this software. |
|
69 | # the file COPYING, distributed as part of this software. | |
70 | #***************************************************************************** |
|
70 | #***************************************************************************** | |
71 |
|
71 | |||
72 |
from __future__ import |
|
72 | from __future__ import unicode_literals | |
73 |
|
73 | |||
74 | import inspect |
|
74 | import inspect | |
75 | import keyword |
|
75 | import keyword | |
@@ -99,9 +99,12 b' from IPython.core.display_trap import DisplayTrap' | |||||
99 | from IPython.core.excolors import exception_colors |
|
99 | from IPython.core.excolors import exception_colors | |
100 | from IPython.utils import PyColorize |
|
100 | from IPython.utils import PyColorize | |
101 | from IPython.utils import io |
|
101 | from IPython.utils import io | |
|
102 | from IPython.utils import path as util_path | |||
102 | from IPython.utils import py3compat |
|
103 | from IPython.utils import py3compat | |
103 | from IPython.utils import pyfile |
|
104 | from IPython.utils import pyfile | |
|
105 | from IPython.utils import ulinecache | |||
104 | from IPython.utils.data import uniq_stable |
|
106 | from IPython.utils.data import uniq_stable | |
|
107 | from IPython.utils.openpy import read_py_file | |||
105 | from IPython.utils.warn import info, error |
|
108 | from IPython.utils.warn import info, error | |
106 |
|
109 | |||
107 | # Globals |
|
110 | # Globals | |
@@ -229,7 +232,6 b' def fix_frame_records_filenames(records):' | |||||
229 |
|
232 | |||
230 |
|
233 | |||
231 | def _fixed_getinnerframes(etb, context=1,tb_offset=0): |
|
234 | def _fixed_getinnerframes(etb, context=1,tb_offset=0): | |
232 | import linecache |
|
|||
233 | LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 |
|
235 | LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5 | |
234 |
|
236 | |||
235 | records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) |
|
237 | records = fix_frame_records_filenames(inspect.getinnerframes(etb, context)) | |
@@ -251,7 +253,7 b' def _fixed_getinnerframes(etb, context=1,tb_offset=0):' | |||||
251 | maybeStart = lnum-1 - context//2 |
|
253 | maybeStart = lnum-1 - context//2 | |
252 | start = max(maybeStart, 0) |
|
254 | start = max(maybeStart, 0) | |
253 | end = start + context |
|
255 | end = start + context | |
254 | lines = linecache.getlines(file)[start:end] |
|
256 | lines = ulinecache.getlines(file)[start:end] | |
255 | buf = list(records[i]) |
|
257 | buf = list(records[i]) | |
256 | buf[LNUM_POS] = lnum |
|
258 | buf[LNUM_POS] = lnum | |
257 | buf[INDEX_POS] = lnum - 1 - start |
|
259 | buf[INDEX_POS] = lnum - 1 - start | |
@@ -282,12 +284,7 b' def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):' | |||||
282 | _line_format = _parser.format2 |
|
284 | _line_format = _parser.format2 | |
283 |
|
285 | |||
284 | for line in lines: |
|
286 | for line in lines: | |
285 | # FIXME: we need to ensure the source is a pure string at this point, |
|
287 | line = py3compat.cast_unicode(line) | |
286 | # else the coloring code makes a royal mess. This is in need of a |
|
|||
287 | # serious refactoring, so that all of the ultratb and PyColorize code |
|
|||
288 | # is unicode-safe. So for now this is rather an ugly hack, but |
|
|||
289 | # necessary to at least have readable tracebacks. Improvements welcome! |
|
|||
290 | line = py3compat.cast_bytes_py2(line, 'utf-8') |
|
|||
291 |
|
288 | |||
292 | new_line, err = _line_format(line, 'str', scheme) |
|
289 | new_line, err = _line_format(line, 'str', scheme) | |
293 | if not err: line = new_line |
|
290 | if not err: line = new_line | |
@@ -547,14 +544,13 b' class ListTB(TBTools):' | |||||
547 |
|
544 | |||
548 | Also lifted nearly verbatim from traceback.py |
|
545 | Also lifted nearly verbatim from traceback.py | |
549 | """ |
|
546 | """ | |
550 |
|
||||
551 | have_filedata = False |
|
547 | have_filedata = False | |
552 | Colors = self.Colors |
|
548 | Colors = self.Colors | |
553 | list = [] |
|
549 | list = [] | |
554 | stype = Colors.excName + etype.__name__ + Colors.Normal |
|
550 | stype = Colors.excName + etype.__name__ + Colors.Normal | |
555 | if value is None: |
|
551 | if value is None: | |
556 | # Not sure if this can still happen in Python 2.6 and above |
|
552 | # Not sure if this can still happen in Python 2.6 and above | |
557 |
list.append( |
|
553 | list.append( py3compat.cast_unicode(stype) + '\n') | |
558 | else: |
|
554 | else: | |
559 | if etype is SyntaxError: |
|
555 | if etype is SyntaxError: | |
560 | have_filedata = True |
|
556 | have_filedata = True | |
@@ -562,18 +558,22 b' class ListTB(TBTools):' | |||||
562 | if not value.filename: value.filename = "<string>" |
|
558 | if not value.filename: value.filename = "<string>" | |
563 | list.append('%s File %s"%s"%s, line %s%d%s\n' % \ |
|
559 | list.append('%s File %s"%s"%s, line %s%d%s\n' % \ | |
564 | (Colors.normalEm, |
|
560 | (Colors.normalEm, | |
565 | Colors.filenameEm, value.filename, Colors.normalEm, |
|
561 | Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm, | |
566 | Colors.linenoEm, value.lineno, Colors.Normal )) |
|
562 | Colors.linenoEm, value.lineno, Colors.Normal )) | |
567 | if value.text is not None: |
|
563 | textline = ulinecache.getline(value.filename, value.lineno) | |
|
564 | if textline == '': | |||
|
565 | textline = py3compat.cast_unicode(value.text, "utf-8") | |||
|
566 | ||||
|
567 | if textline is not None: | |||
568 | i = 0 |
|
568 | i = 0 | |
569 |
while i < len( |
|
569 | while i < len(textline) and textline[i].isspace(): | |
570 | i += 1 |
|
570 | i += 1 | |
571 | list.append('%s %s%s\n' % (Colors.line, |
|
571 | list.append('%s %s%s\n' % (Colors.line, | |
572 |
|
|
572 | textline.strip(), | |
573 | Colors.Normal)) |
|
573 | Colors.Normal)) | |
574 | if value.offset is not None: |
|
574 | if value.offset is not None: | |
575 | s = ' ' |
|
575 | s = ' ' | |
576 |
for c in |
|
576 | for c in textline[i:value.offset-1]: | |
577 | if c.isspace(): |
|
577 | if c.isspace(): | |
578 | s += c |
|
578 | s += c | |
579 | else: |
|
579 | else: | |
@@ -779,10 +779,9 b' class VerboseTB(TBTools):' | |||||
779 | abspath = os.path.abspath |
|
779 | abspath = os.path.abspath | |
780 | for frame, file, lnum, func, lines, index in records: |
|
780 | for frame, file, lnum, func, lines, index in records: | |
781 | #print '*** record:',file,lnum,func,lines,index # dbg |
|
781 | #print '*** record:',file,lnum,func,lines,index # dbg | |
782 |
|
||||
783 | if not file: |
|
782 | if not file: | |
784 | file = '?' |
|
783 | file = '?' | |
785 | elif not(file.startswith("<") and file.endswith(">")): |
|
784 | elif not(file.startswith(str("<")) and file.endswith(str(">"))): | |
786 | # Guess that filenames like <string> aren't real filenames, so |
|
785 | # Guess that filenames like <string> aren't real filenames, so | |
787 | # don't call abspath on them. |
|
786 | # don't call abspath on them. | |
788 | try: |
|
787 | try: | |
@@ -791,7 +790,7 b' class VerboseTB(TBTools):' | |||||
791 | # Not sure if this can still happen: abspath now works with |
|
790 | # Not sure if this can still happen: abspath now works with | |
792 | # file names like <string> |
|
791 | # file names like <string> | |
793 | pass |
|
792 | pass | |
794 |
|
793 | file = py3compat.cast_unicode(file, util_path.fs_encoding) | ||
795 | link = tpl_link % file |
|
794 | link = tpl_link % file | |
796 | args, varargs, varkw, locals = inspect.getargvalues(frame) |
|
795 | args, varargs, varkw, locals = inspect.getargvalues(frame) | |
797 |
|
796 | |||
@@ -831,7 +830,7 b' class VerboseTB(TBTools):' | |||||
831 | # Look up the corresponding source file. |
|
830 | # Look up the corresponding source file. | |
832 | file = pyfile.source_from_cache(file) |
|
831 | file = pyfile.source_from_cache(file) | |
833 |
|
832 | |||
834 | def linereader(file=file, lnum=[lnum], getline=linecache.getline): |
|
833 | def linereader(file=file, lnum=[lnum], getline=ulinecache.getline): | |
835 | line = getline(file, lnum[0]) |
|
834 | line = getline(file, lnum[0]) | |
836 | lnum[0] += 1 |
|
835 | lnum[0] += 1 | |
837 | return line |
|
836 | return line | |
@@ -926,7 +925,7 b' class VerboseTB(TBTools):' | |||||
926 | etype_str,evalue_str = map(str,(etype,evalue)) |
|
925 | etype_str,evalue_str = map(str,(etype,evalue)) | |
927 | # ... and format it |
|
926 | # ... and format it | |
928 | exception = ['%s%s%s: %s' % (Colors.excName, etype_str, |
|
927 | exception = ['%s%s%s: %s' % (Colors.excName, etype_str, | |
929 | ColorsNormal, evalue_str)] |
|
928 | ColorsNormal, py3compat.cast_unicode(evalue_str))] | |
930 | if (not py3compat.PY3) and type(evalue) is types.InstanceType: |
|
929 | if (not py3compat.PY3) and type(evalue) is types.InstanceType: | |
931 | try: |
|
930 | try: | |
932 | names = [w for w in dir(evalue) if isinstance(w, basestring)] |
|
931 | names = [w for w in dir(evalue) if isinstance(w, basestring)] | |
@@ -938,7 +937,7 b' class VerboseTB(TBTools):' | |||||
938 | exception.append(_m % (Colors.excName,ColorsNormal)) |
|
937 | exception.append(_m % (Colors.excName,ColorsNormal)) | |
939 | etype_str,evalue_str = map(str,sys.exc_info()[:2]) |
|
938 | etype_str,evalue_str = map(str,sys.exc_info()[:2]) | |
940 | exception.append('%s%s%s: %s' % (Colors.excName,etype_str, |
|
939 | exception.append('%s%s%s: %s' % (Colors.excName,etype_str, | |
941 | ColorsNormal, evalue_str)) |
|
940 | ColorsNormal, py3compat.cast_unicode(evalue_str))) | |
942 | names = [] |
|
941 | names = [] | |
943 | for name in names: |
|
942 | for name in names: | |
944 | value = text_repr(getattr(evalue, name)) |
|
943 | value = text_repr(getattr(evalue, name)) |
@@ -5,7 +5,7 b' import subprocess' | |||||
5 | import sys |
|
5 | import sys | |
6 |
|
6 | |||
7 | from IPython.core.error import TryNext |
|
7 | from IPython.core.error import TryNext | |
8 |
|
8 | import IPython.utils.py3compat as py3compat | ||
9 |
|
9 | |||
10 | def win32_clipboard_get(): |
|
10 | def win32_clipboard_get(): | |
11 | """ Get the current clipboard's text on Windows. |
|
11 | """ Get the current clipboard's text on Windows. | |
@@ -31,6 +31,7 b' def osx_clipboard_get():' | |||||
31 | text, stderr = p.communicate() |
|
31 | text, stderr = p.communicate() | |
32 | # Text comes in with old Mac \r line endings. Change them to \n. |
|
32 | # Text comes in with old Mac \r line endings. Change them to \n. | |
33 | text = text.replace('\r', '\n') |
|
33 | text = text.replace('\r', '\n') | |
|
34 | text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) | |||
34 | return text |
|
35 | return text | |
35 |
|
36 | |||
36 | def tkinter_clipboard_get(): |
|
37 | def tkinter_clipboard_get(): | |
@@ -49,6 +50,7 b' def tkinter_clipboard_get():' | |||||
49 | root.withdraw() |
|
50 | root.withdraw() | |
50 | text = root.clipboard_get() |
|
51 | text = root.clipboard_get() | |
51 | root.destroy() |
|
52 | root.destroy() | |
|
53 | text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) | |||
52 | return text |
|
54 | return text | |
53 |
|
55 | |||
54 |
|
56 |
@@ -1,3 +1,6 b'' | |||||
|
1 | from __future__ import unicode_literals | |||
|
2 | ||||
|
3 | ||||
1 | """Module for interactive demos using IPython. |
|
4 | """Module for interactive demos using IPython. | |
2 |
|
5 | |||
3 | This module implements a few classes for running Python scripts interactively |
|
6 | This module implements a few classes for running Python scripts interactively | |
@@ -179,7 +182,7 b' from IPython.utils.PyColorize import Parser' | |||||
179 | from IPython.utils import io |
|
182 | from IPython.utils import io | |
180 | from IPython.utils.io import file_read, file_readlines |
|
183 | from IPython.utils.io import file_read, file_readlines | |
181 | from IPython.utils.text import marquee |
|
184 | from IPython.utils.text import marquee | |
182 |
|
185 | from IPython.utils import openpy | ||
183 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] |
|
186 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] | |
184 |
|
187 | |||
185 | class DemoError(Exception): pass |
|
188 | class DemoError(Exception): pass | |
@@ -264,13 +267,13 b' class Demo(object):' | |||||
264 | self.fobj = self.src |
|
267 | self.fobj = self.src | |
265 | else: |
|
268 | else: | |
266 | # Assume it's a string or something that can be converted to one |
|
269 | # Assume it's a string or something that can be converted to one | |
267 | self.fobj = open(self.fname) |
|
270 | self.fobj = openpy.open(self.fname) | |
268 |
|
271 | |||
269 | def reload(self): |
|
272 | def reload(self): | |
270 | """Reload source from disk and initialize state.""" |
|
273 | """Reload source from disk and initialize state.""" | |
271 | self.fload() |
|
274 | self.fload() | |
272 |
|
275 | |||
273 |
self.src = self.fobj |
|
276 | self.src = "".join(openpy.strip_encoding_cookie(self.fobj)) | |
274 | src_b = [b.strip() for b in self.re_stop.split(self.src) if b] |
|
277 | src_b = [b.strip() for b in self.re_stop.split(self.src) if b] | |
275 | self._silent = [bool(self.re_silent.findall(b)) for b in src_b] |
|
278 | self._silent = [bool(self.re_silent.findall(b)) for b in src_b] | |
276 | self._auto = [bool(self.re_auto.findall(b)) for b in src_b] |
|
279 | self._auto = [bool(self.re_auto.findall(b)) for b in src_b] |
@@ -30,6 +30,8 b' formatting (which is the hard part).' | |||||
30 | """ |
|
30 | """ | |
31 | from __future__ import print_function |
|
31 | from __future__ import print_function | |
32 |
|
32 | |||
|
33 | from __future__ import unicode_literals | |||
|
34 | ||||
33 | __all__ = ['ANSICodeColors','Parser'] |
|
35 | __all__ = ['ANSICodeColors','Parser'] | |
34 |
|
36 | |||
35 | _scheme_default = 'Linux' |
|
37 | _scheme_default = 'Linux' |
@@ -7,7 +7,7 b' Much of the code is taken from the tokenize module in Python 3.2.' | |||||
7 | from __future__ import absolute_import |
|
7 | from __future__ import absolute_import | |
8 |
|
8 | |||
9 | import io |
|
9 | import io | |
10 | from io import TextIOWrapper |
|
10 | from io import TextIOWrapper, BytesIO | |
11 | import re |
|
11 | import re | |
12 | import urllib |
|
12 | import urllib | |
13 |
|
13 | |||
@@ -120,6 +120,32 b' except ImportError:' | |||||
120 | text.mode = 'r' |
|
120 | text.mode = 'r' | |
121 | return text |
|
121 | return text | |
122 |
|
122 | |||
|
123 | def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True): | |||
|
124 | """Converts a bytes string with python source code to unicode. | |||
|
125 | ||||
|
126 | Unicode strings are passed through unchanged. Byte strings are checked | |||
|
127 | for the python source file encoding cookie to determine encoding. | |||
|
128 | txt can be either a bytes buffer or a string containing the source | |||
|
129 | code. | |||
|
130 | """ | |||
|
131 | if isinstance(txt, unicode): | |||
|
132 | return txt | |||
|
133 | if isinstance(txt, bytes): | |||
|
134 | buffer = BytesIO(txt) | |||
|
135 | else: | |||
|
136 | buffer = txt | |||
|
137 | try: | |||
|
138 | encoding, _ = detect_encoding(buffer.readline) | |||
|
139 | except SyntaxError: | |||
|
140 | encoding = "ascii" | |||
|
141 | buffer.seek(0) | |||
|
142 | text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True) | |||
|
143 | text.mode = 'r' | |||
|
144 | if skip_encoding_cookie: | |||
|
145 | return u"".join(strip_encoding_cookie(text)) | |||
|
146 | else: | |||
|
147 | return text.read() | |||
|
148 | ||||
123 | def strip_encoding_cookie(filelike): |
|
149 | def strip_encoding_cookie(filelike): | |
124 | """Generator to pull lines from a text-mode file, skipping the encoding |
|
150 | """Generator to pull lines from a text-mode file, skipping the encoding | |
125 | cookie if it is found in the first two lines. |
|
151 | cookie if it is found in the first two lines. | |
@@ -181,12 +207,13 b" def read_py_url(url, errors='replace', skip_encoding_cookie=True):" | |||||
181 | """ |
|
207 | """ | |
182 | response = urllib.urlopen(url) |
|
208 | response = urllib.urlopen(url) | |
183 | buffer = io.BytesIO(response.read()) |
|
209 | buffer = io.BytesIO(response.read()) | |
184 | encoding, lines = detect_encoding(buffer.readline) |
|
210 | return source_to_unicode(buffer, errors, skip_encoding_cookie) | |
185 | buffer.seek(0) |
|
|||
186 | text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True) |
|
|||
187 | text.mode = 'r' |
|
|||
188 | if skip_encoding_cookie: |
|
|||
189 | return "".join(strip_encoding_cookie(text)) |
|
|||
190 | else: |
|
|||
191 | return text.read() |
|
|||
192 |
|
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 |
@@ -38,7 +38,7 b' from IPython.lib.kernel import (' | |||||
38 | get_connection_file, get_connection_info, connect_qtconsole |
|
38 | get_connection_file, get_connection_info, connect_qtconsole | |
39 | ) |
|
39 | ) | |
40 | from IPython.testing.skipdoctest import skip_doctest |
|
40 | from IPython.testing.skipdoctest import skip_doctest | |
41 | from IPython.utils import io |
|
41 | from IPython.utils import io, openpy | |
42 | from IPython.utils.jsonutil import json_clean, encode_images |
|
42 | from IPython.utils.jsonutil import json_clean, encode_images | |
43 | from IPython.utils.process import arg_split |
|
43 | from IPython.utils.process import arg_split | |
44 | from IPython.utils import py3compat |
|
44 | from IPython.utils import py3compat | |
@@ -355,7 +355,9 b' class KernelMagics(Magics):' | |||||
355 |
|
355 | |||
356 | cont = open(arg_s).read() |
|
356 | cont = open(arg_s).read() | |
357 | if arg_s.endswith('.py'): |
|
357 | if arg_s.endswith('.py'): | |
358 |
cont = self.shell.pycolorize( |
|
358 | cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False)) | |
|
359 | else: | |||
|
360 | cont = open(arg_s).read() | |||
359 | page.page(cont) |
|
361 | page.page(cont) | |
360 |
|
362 | |||
361 | more = line_magic('more')(less) |
|
363 | more = line_magic('more')(less) |
@@ -1,9 +1,12 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
1 | """A simple interactive demo to illustrate the use of IPython's Demo class. |
|
2 | """A simple interactive demo to illustrate the use of IPython's Demo class. | |
2 |
|
3 | |||
3 | Any python script can be run as a demo, but that does little more than showing |
|
4 | Any python script can be run as a demo, but that does little more than showing | |
4 | it on-screen, syntax-highlighted in one shot. If you add a little simple |
|
5 | it on-screen, syntax-highlighted in one shot. If you add a little simple | |
5 | markup, you can stop at specified intervals and return to the ipython prompt, |
|
6 | markup, you can stop at specified intervals and return to the ipython prompt, | |
6 | resuming execution later. |
|
7 | resuming execution later. | |
|
8 | ||||
|
9 | This is a unicode test, åäö | |||
7 | """ |
|
10 | """ | |
8 | from __future__ import print_function |
|
11 | from __future__ import print_function | |
9 |
|
12 |
General Comments 0
You need to be logged in to leave comments.
Login now