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 | #----------------------------------------------------------------------------- | |
@@ -30,5 +31,4 b' class StdoutWriter(WriterBase):' | |||||
30 |
|
31 | |||
31 | See base for more... |
|
32 | See base for more... | |
32 | """ |
|
33 | """ | |
33 |
|
34 | io.unicode_std_stream().write(output) | ||
34 | print(output) |
|
@@ -1,3 +1,4 b'' | |||||
|
1 | # coding: utf-8 | |||
1 | """ |
|
2 | """ | |
2 | Module with tests for stdout |
|
3 | Module with tests for stdout | |
3 | """ |
|
4 | """ | |
@@ -43,9 +44,11 b' class TestStdout(TestsBase):' | |||||
43 |
|
44 | |||
44 | # Create stdout writer, test output |
|
45 | # Create stdout writer, test output | |
45 | writer = StdoutWriter() |
|
46 | writer = StdoutWriter() | |
46 | writer.write('a', {'b': 'c'}) |
|
47 | writer.write(u'a×', {'b': 'c'}) | |
47 | output = stream.getvalue() |
|
48 | output = stream.getvalue() | |
48 | self.fuzzy_compare(output, 'a') |
|
49 | if not PY3: | |
|
50 | output = output.decode('utf-8') | |||
|
51 | self.fuzzy_compare(output, u'a×') | |||
49 |
|
52 | |||
50 | # Revert stdout |
|
53 | # Revert stdout | |
51 | sys.stdout = stdout No newline at end of file |
|
54 | sys.stdout = stdout |
@@ -10,15 +10,17 b' IO related utilities.' | |||||
10 | # the file COPYING, distributed as part of this software. |
|
10 | # the file COPYING, distributed as part of this software. | |
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 | from __future__ import print_function |
|
12 | from __future__ import print_function | |
|
13 | from __future__ import absolute_import | |||
13 |
|
14 | |||
14 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
15 | # Imports |
|
16 | # Imports | |
16 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
|
18 | import codecs | |||
17 | import os |
|
19 | import os | |
18 | import sys |
|
20 | import sys | |
19 | import tempfile |
|
21 | import tempfile | |
20 | from .capture import CapturedIO, capture_output |
|
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 | # Code |
|
26 | # Code | |
@@ -230,3 +232,26 b' def raw_print_err(*args, **kw):' | |||||
230 | # Short aliases for quick debugging, do NOT use these in production code. |
|
232 | # Short aliases for quick debugging, do NOT use these in production code. | |
231 | rprint = raw_print |
|
233 | rprint = raw_print | |
232 | rprinte = raw_print_err |
|
234 | rprinte = raw_print_err | |
|
235 | ||||
|
236 | def unicode_std_stream(stream='stdout'): | |||
|
237 | """Get a wrapper to write unicode to stdout/stderr as UTF-8. | |||
|
238 | ||||
|
239 | This ignores environment variables and default encodings, to reliably write | |||
|
240 | unicode to stdout or stderr. | |||
|
241 | ||||
|
242 | :: | |||
|
243 | ||||
|
244 | unicode_std_stream().write(u'ł@e¶ŧ←') | |||
|
245 | """ | |||
|
246 | assert stream in ('stdout', 'stderr') | |||
|
247 | stream = getattr(sys, stream) | |||
|
248 | if PY3: | |||
|
249 | try: | |||
|
250 | stream_b = stream.buffer | |||
|
251 | except AttributeError: | |||
|
252 | # sys.stdout has been replaced - use it directly | |||
|
253 | return stream | |||
|
254 | else: | |||
|
255 | stream_b = stream | |||
|
256 | ||||
|
257 | 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 subprocess import Popen, PIPE |
|
20 | from subprocess import Popen, PIPE | |
@@ -20,7 +22,8 b' import unittest' | |||||
20 |
|
22 | |||
21 | import nose.tools as nt |
|
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 | from IPython.utils.py3compat import doctest_refactor_print, PY3 |
|
27 | from IPython.utils.py3compat import doctest_refactor_print, PY3 | |
25 |
|
28 | |||
26 | if PY3: |
|
29 | if PY3: | |
@@ -88,3 +91,34 b' def test_capture_output():' | |||||
88 |
|
91 | |||
89 | nt.assert_equal(io.stdout, 'hi, stdout\n') |
|
92 | nt.assert_equal(io.stdout, 'hi, stdout\n') | |
90 | nt.assert_equal(io.stderr, 'hi, stderr\n') |
|
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