Show More
@@ -10,15 +10,17 b' IO related utilities.' | |||
|
10 | 10 | # the file COPYING, distributed as part of this software. |
|
11 | 11 | #----------------------------------------------------------------------------- |
|
12 | 12 | from __future__ import print_function |
|
13 | from __future__ import absolute_import | |
|
13 | 14 | |
|
14 | 15 | #----------------------------------------------------------------------------- |
|
15 | 16 | # Imports |
|
16 | 17 | #----------------------------------------------------------------------------- |
|
18 | import codecs | |
|
17 | 19 | import os |
|
18 | 20 | import sys |
|
19 | 21 | import tempfile |
|
20 | 22 | from .capture import CapturedIO, capture_output |
|
21 | from .py3compat import string_types, input | |
|
23 | from .py3compat import string_types, input, PY3 | |
|
22 | 24 | |
|
23 | 25 | #----------------------------------------------------------------------------- |
|
24 | 26 | # Code |
@@ -227,3 +229,26 b' def raw_print_err(*args, **kw):' | |||
|
227 | 229 | # Short aliases for quick debugging, do NOT use these in production code. |
|
228 | 230 | rprint = raw_print |
|
229 | 231 | rprinte = raw_print_err |
|
232 | ||
|
233 | def unicode_std_stream(stream='stdout'): | |
|
234 | """Get a wrapper to write unicode to stdout/stderr as UTF-8. | |
|
235 | ||
|
236 | This ignores environment variables and default encodings, to reliably write | |
|
237 | unicode to stdout or stderr. | |
|
238 | ||
|
239 | :: | |
|
240 | ||
|
241 | unicode_std_stream().write(u'ł@e¶ŧ←') | |
|
242 | """ | |
|
243 | assert stream in ('stdout', 'stderr') | |
|
244 | stream = getattr(sys, stream) | |
|
245 | if PY3: | |
|
246 | try: | |
|
247 | stream_b = stream.buffer | |
|
248 | except AttributeError: | |
|
249 | # sys.stdout has been replaced - use it directly | |
|
250 | return stream | |
|
251 | else: | |
|
252 | stream_b = stream | |
|
253 | ||
|
254 | return codecs.getwriter('utf-8')(stream_b) |
@@ -12,7 +12,9 b'' | |||
|
12 | 12 | # Imports |
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | from __future__ import print_function |
|
15 | from __future__ import absolute_import | |
|
15 | 16 | |
|
17 | import io as stdlib_io | |
|
16 | 18 | import sys |
|
17 | 19 | |
|
18 | 20 | from subprocess import Popen, PIPE |
@@ -20,7 +22,8 b' import unittest' | |||
|
20 | 22 | |
|
21 | 23 | import nose.tools as nt |
|
22 | 24 | |
|
23 | from IPython.utils.io import Tee, capture_output | |
|
25 | from IPython.testing.decorators import skipif | |
|
26 | from IPython.utils.io import Tee, capture_output, unicode_std_stream | |
|
24 | 27 | from IPython.utils.py3compat import doctest_refactor_print, PY3 |
|
25 | 28 | |
|
26 | 29 | if PY3: |
@@ -88,3 +91,34 b' def test_capture_output():' | |||
|
88 | 91 | |
|
89 | 92 | nt.assert_equal(io.stdout, 'hi, stdout\n') |
|
90 | 93 | nt.assert_equal(io.stderr, 'hi, stderr\n') |
|
94 | ||
|
95 | def test_UnicodeStdStream(): | |
|
96 | # Test wrapping a bytes-level stdout | |
|
97 | if PY3: | |
|
98 | stdoutb = stdlib_io.BytesIO() | |
|
99 | stdout = stdlib_io.TextIOWrapper(stdoutb, encoding='ascii') | |
|
100 | else: | |
|
101 | stdout = stdoutb = stdlib_io.BytesIO() | |
|
102 | ||
|
103 | orig_stdout = sys.stdout | |
|
104 | sys.stdout = stdout | |
|
105 | try: | |
|
106 | sample = u"@łe¶ŧ←" | |
|
107 | unicode_std_stream().write(sample) | |
|
108 | ||
|
109 | output = stdoutb.getvalue().decode('utf-8') | |
|
110 | nt.assert_equal(output, sample) | |
|
111 | assert not stdout.closed | |
|
112 | finally: | |
|
113 | sys.stdout = orig_stdout | |
|
114 | ||
|
115 | @skipif(not PY3, "Not applicable on Python 2") | |
|
116 | def test_UnicodeStdStream_nowrap(): | |
|
117 | # If we replace stdout with a StringIO, it shouldn't get wrapped. | |
|
118 | orig_stdout = sys.stdout | |
|
119 | sys.stdout = StringIO() | |
|
120 | try: | |
|
121 | nt.assert_is(unicode_std_stream(), sys.stdout) | |
|
122 | assert not sys.stdout.closed | |
|
123 | finally: | |
|
124 | sys.stdout = orig_stdout No newline at end of file |
General Comments 0
You need to be logged in to leave comments.
Login now