Show More
@@ -13,6 +13,7 b' Contains Stdout writer' | |||||
13 | # Imports |
|
13 | # Imports | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 |
|
15 | |||
|
16 | from IPython.utils import io | |||
16 | from .base import WriterBase |
|
17 | from .base import WriterBase | |
17 |
|
18 | |||
18 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
@@ -31,4 +32,4 b' class StdoutWriter(WriterBase):' | |||||
31 | See base for more... |
|
32 | See base for more... | |
32 | """ |
|
33 | """ | |
33 |
|
34 | |||
34 | print(output) |
|
35 | io.unicode_std_stream().write(output) |
@@ -14,10 +14,12 b' from __future__ import print_function' | |||||
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 | # Imports |
|
15 | # Imports | |
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
|
17 | import codecs | |||
17 | import os |
|
18 | import os | |
18 | import sys |
|
19 | import sys | |
19 | import tempfile |
|
20 | import tempfile | |
20 | from StringIO import StringIO |
|
21 | from StringIO import StringIO | |
|
22 | from .py3compat import PY3 | |||
21 |
|
23 | |||
22 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
23 | # Code |
|
25 | # Code | |
@@ -285,4 +287,25 b' class capture_output(object):' | |||||
285 | sys.stdout = self.sys_stdout |
|
287 | sys.stdout = self.sys_stdout | |
286 | sys.stderr = self.sys_stderr |
|
288 | sys.stderr = self.sys_stderr | |
287 |
|
289 | |||
|
290 | def unicode_std_stream(stream='stdout'): | |||
|
291 | """Get a wrapper to write unicode to stdout/stderr as UTF-8. | |||
288 |
|
|
292 | ||
|
293 | This ignores environment variables and default encodings, to reliably write | |||
|
294 | unicode to stdout or stderr. | |||
|
295 | ||||
|
296 | :: | |||
|
297 | ||||
|
298 | unicode_std_stream().write(u'ł@e¶ŧ←') | |||
|
299 | """ | |||
|
300 | assert stream in ('stdout', 'stderr') | |||
|
301 | stream = getattr(sys, stream) | |||
|
302 | if PY3: | |||
|
303 | try: | |||
|
304 | stream_b = stream.buffer | |||
|
305 | except AttributeError: | |||
|
306 | # sys.stdout has been replaced - use it directly | |||
|
307 | return stream | |||
|
308 | else: | |||
|
309 | stream_b = stream | |||
|
310 | ||||
|
311 | return codecs.getwriter('utf-8')(stream_b) |
@@ -12,7 +12,9 b'' | |||||
12 | # Imports |
|
12 | # Imports | |
13 | #----------------------------------------------------------------------------- |
|
13 | #----------------------------------------------------------------------------- | |
14 | from __future__ import print_function |
|
14 | from __future__ import print_function | |
|
15 | from __future__ import absolute_import | |||
15 |
|
16 | |||
|
17 | import io as stdlib_io | |||
16 | import sys |
|
18 | import sys | |
17 |
|
19 | |||
18 | from StringIO import StringIO |
|
20 | from StringIO import StringIO | |
@@ -21,8 +23,9 b' from subprocess import Popen, PIPE' | |||||
21 | import nose.tools as nt |
|
23 | import nose.tools as nt | |
22 |
|
24 | |||
23 | from IPython.testing.ipunittest import ParametricTestCase |
|
25 | from IPython.testing.ipunittest import ParametricTestCase | |
24 | from IPython.utils.io import Tee, capture_output |
|
26 | from IPython.testing.decorators import skipif | |
25 | from IPython.utils.py3compat import doctest_refactor_print |
|
27 | from IPython.utils.io import Tee, capture_output, unicode_std_stream | |
|
28 | from IPython.utils.py3compat import doctest_refactor_print, PY3 | |||
26 |
|
29 | |||
27 | #----------------------------------------------------------------------------- |
|
30 | #----------------------------------------------------------------------------- | |
28 | # Tests |
|
31 | # Tests | |
@@ -84,3 +87,34 b' def test_capture_output():' | |||||
84 |
|
87 | |||
85 | nt.assert_equal(io.stdout, 'hi, stdout\n') |
|
88 | nt.assert_equal(io.stdout, 'hi, stdout\n') | |
86 | nt.assert_equal(io.stderr, 'hi, stderr\n') |
|
89 | nt.assert_equal(io.stderr, 'hi, stderr\n') | |
|
90 | ||||
|
91 | def test_UnicodeStdStream(): | |||
|
92 | # Test wrapping a bytes-level stdout | |||
|
93 | if PY3: | |||
|
94 | stdoutb = stdlib_io.BytesIO() | |||
|
95 | stdout = stdlib_io.TextIOWrapper(stdoutb, encoding='ascii') | |||
|
96 | else: | |||
|
97 | stdout = stdoutb = stdlib_io.BytesIO() | |||
|
98 | ||||
|
99 | orig_stdout = sys.stdout | |||
|
100 | sys.stdout = stdout | |||
|
101 | try: | |||
|
102 | sample = u"@łe¶ŧ←" | |||
|
103 | unicode_std_stream().write(sample) | |||
|
104 | ||||
|
105 | output = stdoutb.getvalue().decode('utf-8') | |||
|
106 | nt.assert_equal(output, sample) | |||
|
107 | assert not stdout.closed | |||
|
108 | finally: | |||
|
109 | sys.stdout = orig_stdout | |||
|
110 | ||||
|
111 | @skipif(not PY3, "Not applicable on Python 2") | |||
|
112 | def test_UnicodeStdStream_nowrap(): | |||
|
113 | # If we replace stdout with a StringIO, it shouldn't get wrapped. | |||
|
114 | orig_stdout = sys.stdout | |||
|
115 | sys.stdout = StringIO() | |||
|
116 | try: | |||
|
117 | nt.assert_is(unicode_std_stream(), sys.stdout) | |||
|
118 | assert not sys.stdout.closed | |||
|
119 | finally: | |||
|
120 | sys.stdout = orig_stdout No newline at end of file |
General Comments 0
You need to be logged in to leave comments.
Login now