##// END OF EJS Templates
Merge pull request #8240 from minrk/split-io...
Thomas Kluyver -
r21119:a229520a merge
parent child Browse files
Show More
@@ -0,0 +1,131 b''
1 # encoding: utf-8
2 """Tests for file IO"""
3
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import io as stdlib_io
8 import os.path
9 import stat
10
11 import nose.tools as nt
12
13 from IPython.testing.decorators import skip_win32
14 from ..fileio import atomic_writing
15
16 from IPython.utils.tempdir import TemporaryDirectory
17
18 umask = 0
19
20 def test_atomic_writing():
21 class CustomExc(Exception): pass
22
23 with TemporaryDirectory() as td:
24 f1 = os.path.join(td, 'penguin')
25 with stdlib_io.open(f1, 'w') as f:
26 f.write(u'Before')
27
28 if os.name != 'nt':
29 os.chmod(f1, 0o701)
30 orig_mode = stat.S_IMODE(os.stat(f1).st_mode)
31
32 f2 = os.path.join(td, 'flamingo')
33 try:
34 os.symlink(f1, f2)
35 have_symlink = True
36 except (AttributeError, NotImplementedError, OSError):
37 # AttributeError: Python doesn't support it
38 # NotImplementedError: The system doesn't support it
39 # OSError: The user lacks the privilege (Windows)
40 have_symlink = False
41
42 with nt.assert_raises(CustomExc):
43 with atomic_writing(f1) as f:
44 f.write(u'Failing write')
45 raise CustomExc
46
47 # Because of the exception, the file should not have been modified
48 with stdlib_io.open(f1, 'r') as f:
49 nt.assert_equal(f.read(), u'Before')
50
51 with atomic_writing(f1) as f:
52 f.write(u'Overwritten')
53
54 with stdlib_io.open(f1, 'r') as f:
55 nt.assert_equal(f.read(), u'Overwritten')
56
57 if os.name != 'nt':
58 mode = stat.S_IMODE(os.stat(f1).st_mode)
59 nt.assert_equal(mode, orig_mode)
60
61 if have_symlink:
62 # Check that writing over a file preserves a symlink
63 with atomic_writing(f2) as f:
64 f.write(u'written from symlink')
65
66 with stdlib_io.open(f1, 'r') as f:
67 nt.assert_equal(f.read(), u'written from symlink')
68
69 def _save_umask():
70 global umask
71 umask = os.umask(0)
72 os.umask(umask)
73
74 def _restore_umask():
75 os.umask(umask)
76
77 @skip_win32
78 @nt.with_setup(_save_umask, _restore_umask)
79 def test_atomic_writing_umask():
80 with TemporaryDirectory() as td:
81 os.umask(0o022)
82 f1 = os.path.join(td, '1')
83 with atomic_writing(f1) as f:
84 f.write(u'1')
85 mode = stat.S_IMODE(os.stat(f1).st_mode)
86 nt.assert_equal(mode, 0o644, '{:o} != 644'.format(mode))
87
88 os.umask(0o057)
89 f2 = os.path.join(td, '2')
90 with atomic_writing(f2) as f:
91 f.write(u'2')
92 mode = stat.S_IMODE(os.stat(f2).st_mode)
93 nt.assert_equal(mode, 0o620, '{:o} != 620'.format(mode))
94
95
96 def test_atomic_writing_newlines():
97 with TemporaryDirectory() as td:
98 path = os.path.join(td, 'testfile')
99
100 lf = u'a\nb\nc\n'
101 plat = lf.replace(u'\n', os.linesep)
102 crlf = lf.replace(u'\n', u'\r\n')
103
104 # test default
105 with stdlib_io.open(path, 'w') as f:
106 f.write(lf)
107 with stdlib_io.open(path, 'r', newline='') as f:
108 read = f.read()
109 nt.assert_equal(read, plat)
110
111 # test newline=LF
112 with stdlib_io.open(path, 'w', newline='\n') as f:
113 f.write(lf)
114 with stdlib_io.open(path, 'r', newline='') as f:
115 read = f.read()
116 nt.assert_equal(read, lf)
117
118 # test newline=CRLF
119 with atomic_writing(path, newline='\r\n') as f:
120 f.write(lf)
121 with stdlib_io.open(path, 'r', newline='') as f:
122 read = f.read()
123 nt.assert_equal(read, crlf)
124
125 # test newline=no convert
126 text = u'crlf\r\ncr\rlf\n'
127 with atomic_writing(path, newline='') as f:
128 f.write(text)
129 with stdlib_io.open(path, 'r', newline='') as f:
130 read = f.read()
131 nt.assert_equal(read, text)
@@ -0,0 +1,33 b''
1 # coding: utf-8
2 """io-related utilities"""
3
4 # Copyright (c) Jupyter Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import codecs
8 import sys
9 from IPython.utils.py3compat import PY3
10
11
12 def unicode_std_stream(stream='stdout'):
13 u"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
14
15 This ignores environment variables and default encodings, to reliably write
16 unicode to stdout or stderr.
17
18 ::
19
20 unicode_std_stream().write(u'ł@e¶ŧ←')
21 """
22 assert stream in ('stdout', 'stderr')
23 stream = getattr(sys, stream)
24 if PY3:
25 try:
26 stream_b = stream.buffer
27 except AttributeError:
28 # sys.stdout has been replaced - use it directly
29 return stream
30 else:
31 stream_b = stream
32
33 return codecs.getwriter('utf-8')(stream_b)
@@ -0,0 +1,50 b''
1 # encoding: utf-8
2 """Tests for utils.io"""
3
4 # Copyright (c) Jupyter Development Team.
5 # Distributed under the terms of the Modified BSD License.
6
7 import io as stdlib_io
8 import sys
9
10 import nose.tools as nt
11
12 from IPython.testing.decorators import skipif
13 from ..io import unicode_std_stream
14 from IPython.utils.py3compat import PY3
15
16 if PY3:
17 from io import StringIO
18 else:
19 from StringIO import StringIO
20
21 def test_UnicodeStdStream():
22 # Test wrapping a bytes-level stdout
23 if PY3:
24 stdoutb = stdlib_io.BytesIO()
25 stdout = stdlib_io.TextIOWrapper(stdoutb, encoding='ascii')
26 else:
27 stdout = stdoutb = stdlib_io.BytesIO()
28
29 orig_stdout = sys.stdout
30 sys.stdout = stdout
31 try:
32 sample = u"@łe¶ŧ←"
33 unicode_std_stream().write(sample)
34
35 output = stdoutb.getvalue().decode('utf-8')
36 nt.assert_equal(output, sample)
37 assert not stdout.closed
38 finally:
39 sys.stdout = orig_stdout
40
41 @skipif(not PY3, "Not applicable on Python 2")
42 def test_UnicodeStdStream_nowrap():
43 # If we replace stdout with a StringIO, it shouldn't get wrapped.
44 orig_stdout = sys.stdout
45 sys.stdout = StringIO()
46 try:
47 nt.assert_is(unicode_std_stream(), sys.stdout)
48 assert not sys.stdout.closed
49 finally:
50 sys.stdout = orig_stdout
@@ -11,6 +11,7 b' import errno'
11 import io
11 import io
12 import os
12 import os
13 import shutil
13 import shutil
14 import tempfile
14
15
15 from tornado.web import HTTPError
16 from tornado.web import HTTPError
16
17
@@ -19,10 +20,91 b' from IPython.html.utils import ('
19 to_os_path,
20 to_os_path,
20 )
21 )
21 from IPython import nbformat
22 from IPython import nbformat
22 from IPython.utils.io import atomic_writing
23 from IPython.utils.py3compat import str_to_unicode
23 from IPython.utils.py3compat import str_to_unicode
24
24
25
25
26 def _copy_metadata(src, dst):
27 """Copy the set of metadata we want for atomic_writing.
28
29 Permission bits and flags. We'd like to copy file ownership as well, but we
30 can't do that.
31 """
32 shutil.copymode(src, dst)
33 st = os.stat(src)
34 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
35 os.chflags(dst, st.st_flags)
36
37 @contextmanager
38 def atomic_writing(path, text=True, encoding='utf-8', **kwargs):
39 """Context manager to write to a file only if the entire write is successful.
40
41 This works by creating a temporary file in the same directory, and renaming
42 it over the old file if the context is exited without an error. If other
43 file names are hard linked to the target file, this relationship will not be
44 preserved.
45
46 On Windows, there is a small chink in the atomicity: the target file is
47 deleted before renaming the temporary file over it. This appears to be
48 unavoidable.
49
50 Parameters
51 ----------
52 path : str
53 The target file to write to.
54
55 text : bool, optional
56 Whether to open the file in text mode (i.e. to write unicode). Default is
57 True.
58
59 encoding : str, optional
60 The encoding to use for files opened in text mode. Default is UTF-8.
61
62 **kwargs
63 Passed to :func:`io.open`.
64 """
65 # realpath doesn't work on Windows: http://bugs.python.org/issue9949
66 # Luckily, we only need to resolve the file itself being a symlink, not
67 # any of its directories, so this will suffice:
68 if os.path.islink(path):
69 path = os.path.join(os.path.dirname(path), os.readlink(path))
70
71 dirname, basename = os.path.split(path)
72 tmp_dir = tempfile.mkdtemp(prefix=basename, dir=dirname)
73 tmp_path = os.path.join(tmp_dir, basename)
74 if text:
75 fileobj = io.open(tmp_path, 'w', encoding=encoding, **kwargs)
76 else:
77 fileobj = io.open(tmp_path, 'wb', **kwargs)
78
79 try:
80 yield fileobj
81 except:
82 fileobj.close()
83 shutil.rmtree(tmp_dir)
84 raise
85
86 # Flush to disk
87 fileobj.flush()
88 os.fsync(fileobj.fileno())
89
90 # Written successfully, now rename it
91 fileobj.close()
92
93 # Copy permission bits, access time, etc.
94 try:
95 _copy_metadata(path, tmp_path)
96 except OSError:
97 # e.g. the file didn't already exist. Ignore any failure to copy metadata
98 pass
99
100 if os.name == 'nt' and os.path.exists(path):
101 # Rename over existing file doesn't work on Windows
102 os.remove(path)
103
104 os.rename(tmp_path, path)
105 shutil.rmtree(tmp_dir)
106
107
26 class FileManagerMixin(object):
108 class FileManagerMixin(object):
27 """
109 """
28 Mixin for ContentsAPI classes that interact with the filesystem.
110 Mixin for ContentsAPI classes that interact with the filesystem.
@@ -3,33 +3,24 b''
3 IO related utilities.
3 IO related utilities.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 # Copyright (c) IPython Development Team.
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Distributed under the terms of the Modified BSD License.
8 #
8
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12 from __future__ import print_function
9 from __future__ import print_function
13 from __future__ import absolute_import
10 from __future__ import absolute_import
14
11
15 #-----------------------------------------------------------------------------
12
16 # Imports
17 #-----------------------------------------------------------------------------
18 import codecs
13 import codecs
19 from contextlib import contextmanager
14 from contextlib import contextmanager
20 import io
15 import io
21 import os
16 import os
22 import shutil
17 import shutil
23 import stat
24 import sys
18 import sys
25 import tempfile
19 import tempfile
20 import warnings
26 from .capture import CapturedIO, capture_output
21 from .capture import CapturedIO, capture_output
27 from .py3compat import string_types, input, PY3
22 from .py3compat import string_types, input, PY3
28
23
29 #-----------------------------------------------------------------------------
30 # Code
31 #-----------------------------------------------------------------------------
32
33
24
34 class IOStream:
25 class IOStream:
35
26
@@ -221,87 +212,11 b" def temp_pyfile(src, ext='.py'):"
221 f.flush()
212 f.flush()
222 return fname, f
213 return fname, f
223
214
224 def _copy_metadata(src, dst):
215 def atomic_writing(*args, **kwargs):
225 """Copy the set of metadata we want for atomic_writing.
216 """DEPRECATED: moved to IPython.html.services.contents.fileio"""
226
217 warn("IPython.utils.io.atomic_writing has moved to IPython.html.services.contents.fileio")
227 Permission bits and flags. We'd like to copy file ownership as well, but we
218 from IPython.html.services.contents.fileio import atomic_writing
228 can't do that.
219 return atomic_writing(*args, **kwargs)
229 """
230 shutil.copymode(src, dst)
231 st = os.stat(src)
232 if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
233 os.chflags(dst, st.st_flags)
234
235 @contextmanager
236 def atomic_writing(path, text=True, encoding='utf-8', **kwargs):
237 """Context manager to write to a file only if the entire write is successful.
238
239 This works by creating a temporary file in the same directory, and renaming
240 it over the old file if the context is exited without an error. If other
241 file names are hard linked to the target file, this relationship will not be
242 preserved.
243
244 On Windows, there is a small chink in the atomicity: the target file is
245 deleted before renaming the temporary file over it. This appears to be
246 unavoidable.
247
248 Parameters
249 ----------
250 path : str
251 The target file to write to.
252
253 text : bool, optional
254 Whether to open the file in text mode (i.e. to write unicode). Default is
255 True.
256
257 encoding : str, optional
258 The encoding to use for files opened in text mode. Default is UTF-8.
259
260 **kwargs
261 Passed to :func:`io.open`.
262 """
263 # realpath doesn't work on Windows: http://bugs.python.org/issue9949
264 # Luckily, we only need to resolve the file itself being a symlink, not
265 # any of its directories, so this will suffice:
266 if os.path.islink(path):
267 path = os.path.join(os.path.dirname(path), os.readlink(path))
268
269 dirname, basename = os.path.split(path)
270 tmp_dir = tempfile.mkdtemp(prefix=basename, dir=dirname)
271 tmp_path = os.path.join(tmp_dir, basename)
272 if text:
273 fileobj = io.open(tmp_path, 'w', encoding=encoding, **kwargs)
274 else:
275 fileobj = io.open(tmp_path, 'wb', **kwargs)
276
277 try:
278 yield fileobj
279 except:
280 fileobj.close()
281 shutil.rmtree(tmp_dir)
282 raise
283
284 # Flush to disk
285 fileobj.flush()
286 os.fsync(fileobj.fileno())
287
288 # Written successfully, now rename it
289 fileobj.close()
290
291 # Copy permission bits, access time, etc.
292 try:
293 _copy_metadata(path, tmp_path)
294 except OSError:
295 # e.g. the file didn't already exist. Ignore any failure to copy metadata
296 pass
297
298 if os.name == 'nt' and os.path.exists(path):
299 # Rename over existing file doesn't work on Windows
300 os.remove(path)
301
302 os.rename(tmp_path, path)
303 shutil.rmtree(tmp_dir)
304
305
220
306 def raw_print(*args, **kw):
221 def raw_print(*args, **kw):
307 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
222 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
@@ -323,25 +238,9 b' def raw_print_err(*args, **kw):'
323 rprint = raw_print
238 rprint = raw_print
324 rprinte = raw_print_err
239 rprinte = raw_print_err
325
240
326 def unicode_std_stream(stream='stdout'):
327 u"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
328
329 This ignores environment variables and default encodings, to reliably write
330 unicode to stdout or stderr.
331
241
332 ::
242 def unicode_std_stream(stream='stdout'):
333
243 """DEPRECATED, moved to jupyter_nbconvert.utils.io"""
334 unicode_std_stream().write(u'ł@e¶ŧ←')
244 warn("IPython.utils.io.unicode_std_stream has moved to jupyter_nbconvert.utils.io")
335 """
245 from jupyter_nbconvert.utils.io import unicode_std_stream
336 assert stream in ('stdout', 'stderr')
246 return unicode_std_stream(stream)
337 stream = getattr(sys, stream)
338 if PY3:
339 try:
340 stream_b = stream.buffer
341 except AttributeError:
342 # sys.stdout has been replaced - use it directly
343 return stream
344 else:
345 stream_b = stream
346
347 return codecs.getwriter('utf-8')(stream_b)
@@ -18,9 +18,7 b' import unittest'
18 import nose.tools as nt
18 import nose.tools as nt
19
19
20 from IPython.testing.decorators import skipif, skip_win32
20 from IPython.testing.decorators import skipif, skip_win32
21 from IPython.utils.io import (Tee, capture_output, unicode_std_stream,
21 from IPython.utils.io import Tee, capture_output
22 atomic_writing,
23 )
24 from IPython.utils.py3compat import doctest_refactor_print, PY3
22 from IPython.utils.py3compat import doctest_refactor_print, PY3
25 from IPython.utils.tempdir import TemporaryDirectory
23 from IPython.utils.tempdir import TemporaryDirectory
26
24
@@ -86,146 +84,4 b' def test_capture_output():'
86 nt.assert_equal(io.stdout, 'hi, stdout\n')
84 nt.assert_equal(io.stdout, 'hi, stdout\n')
87 nt.assert_equal(io.stderr, 'hi, stderr\n')
85 nt.assert_equal(io.stderr, 'hi, stderr\n')
88
86
89 def test_UnicodeStdStream():
87
90 # Test wrapping a bytes-level stdout
91 if PY3:
92 stdoutb = stdlib_io.BytesIO()
93 stdout = stdlib_io.TextIOWrapper(stdoutb, encoding='ascii')
94 else:
95 stdout = stdoutb = stdlib_io.BytesIO()
96
97 orig_stdout = sys.stdout
98 sys.stdout = stdout
99 try:
100 sample = u"@łe¶ŧ←"
101 unicode_std_stream().write(sample)
102
103 output = stdoutb.getvalue().decode('utf-8')
104 nt.assert_equal(output, sample)
105 assert not stdout.closed
106 finally:
107 sys.stdout = orig_stdout
108
109 @skipif(not PY3, "Not applicable on Python 2")
110 def test_UnicodeStdStream_nowrap():
111 # If we replace stdout with a StringIO, it shouldn't get wrapped.
112 orig_stdout = sys.stdout
113 sys.stdout = StringIO()
114 try:
115 nt.assert_is(unicode_std_stream(), sys.stdout)
116 assert not sys.stdout.closed
117 finally:
118 sys.stdout = orig_stdout
119
120 def test_atomic_writing():
121 class CustomExc(Exception): pass
122
123 with TemporaryDirectory() as td:
124 f1 = os.path.join(td, 'penguin')
125 with stdlib_io.open(f1, 'w') as f:
126 f.write(u'Before')
127
128 if os.name != 'nt':
129 os.chmod(f1, 0o701)
130 orig_mode = stat.S_IMODE(os.stat(f1).st_mode)
131
132 f2 = os.path.join(td, 'flamingo')
133 try:
134 os.symlink(f1, f2)
135 have_symlink = True
136 except (AttributeError, NotImplementedError, OSError):
137 # AttributeError: Python doesn't support it
138 # NotImplementedError: The system doesn't support it
139 # OSError: The user lacks the privilege (Windows)
140 have_symlink = False
141
142 with nt.assert_raises(CustomExc):
143 with atomic_writing(f1) as f:
144 f.write(u'Failing write')
145 raise CustomExc
146
147 # Because of the exception, the file should not have been modified
148 with stdlib_io.open(f1, 'r') as f:
149 nt.assert_equal(f.read(), u'Before')
150
151 with atomic_writing(f1) as f:
152 f.write(u'Overwritten')
153
154 with stdlib_io.open(f1, 'r') as f:
155 nt.assert_equal(f.read(), u'Overwritten')
156
157 if os.name != 'nt':
158 mode = stat.S_IMODE(os.stat(f1).st_mode)
159 nt.assert_equal(mode, orig_mode)
160
161 if have_symlink:
162 # Check that writing over a file preserves a symlink
163 with atomic_writing(f2) as f:
164 f.write(u'written from symlink')
165
166 with stdlib_io.open(f1, 'r') as f:
167 nt.assert_equal(f.read(), u'written from symlink')
168
169 def _save_umask():
170 global umask
171 umask = os.umask(0)
172 os.umask(umask)
173
174 def _restore_umask():
175 os.umask(umask)
176
177 @skip_win32
178 @nt.with_setup(_save_umask, _restore_umask)
179 def test_atomic_writing_umask():
180 with TemporaryDirectory() as td:
181 os.umask(0o022)
182 f1 = os.path.join(td, '1')
183 with atomic_writing(f1) as f:
184 f.write(u'1')
185 mode = stat.S_IMODE(os.stat(f1).st_mode)
186 nt.assert_equal(mode, 0o644, '{:o} != 644'.format(mode))
187
188 os.umask(0o057)
189 f2 = os.path.join(td, '2')
190 with atomic_writing(f2) as f:
191 f.write(u'2')
192 mode = stat.S_IMODE(os.stat(f2).st_mode)
193 nt.assert_equal(mode, 0o620, '{:o} != 620'.format(mode))
194
195
196 def test_atomic_writing_newlines():
197 with TemporaryDirectory() as td:
198 path = os.path.join(td, 'testfile')
199
200 lf = u'a\nb\nc\n'
201 plat = lf.replace(u'\n', os.linesep)
202 crlf = lf.replace(u'\n', u'\r\n')
203
204 # test default
205 with stdlib_io.open(path, 'w') as f:
206 f.write(lf)
207 with stdlib_io.open(path, 'r', newline='') as f:
208 read = f.read()
209 nt.assert_equal(read, plat)
210
211 # test newline=LF
212 with stdlib_io.open(path, 'w', newline='\n') as f:
213 f.write(lf)
214 with stdlib_io.open(path, 'r', newline='') as f:
215 read = f.read()
216 nt.assert_equal(read, lf)
217
218 # test newline=CRLF
219 with atomic_writing(path, newline='\r\n') as f:
220 f.write(lf)
221 with stdlib_io.open(path, 'r', newline='') as f:
222 read = f.read()
223 nt.assert_equal(read, crlf)
224
225 # test newline=no convert
226 text = u'crlf\r\ncr\rlf\n'
227 with atomic_writing(path, newline='') as f:
228 f.write(text)
229 with stdlib_io.open(path, 'r', newline='') as f:
230 read = f.read()
231 nt.assert_equal(read, text)
@@ -49,7 +49,6 b' from zmq.eventloop.zmqstream import ZMQStream'
49
49
50 from IPython.core.release import kernel_protocol_version
50 from IPython.core.release import kernel_protocol_version
51 from IPython.config.configurable import Configurable, LoggingConfigurable
51 from IPython.config.configurable import Configurable, LoggingConfigurable
52 from IPython.utils import io
53 from IPython.utils.importstring import import_item
52 from IPython.utils.importstring import import_item
54 from jupyter_client.jsonutil import extract_dates, squash_dates, date_default
53 from jupyter_client.jsonutil import extract_dates, squash_dates, date_default
55 from IPython.utils.py3compat import (str_to_bytes, str_to_unicode, unicode_type,
54 from IPython.utils.py3compat import (str_to_bytes, str_to_unicode, unicode_type,
@@ -59,6 +58,8 b' from IPython.utils.traitlets import (CBytes, Unicode, Bool, Any, Instance, Set,'
59 TraitError,
58 TraitError,
60 )
59 )
61 from jupyter_client.adapter import adapt
60 from jupyter_client.adapter import adapt
61 from traitlets.log import get_logger
62
62
63
63 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
64 # utility functions
65 # utility functions
@@ -653,8 +654,9 b' class Session(Configurable):'
653 msg = self.msg(msg_or_type, content=content, parent=parent,
654 msg = self.msg(msg_or_type, content=content, parent=parent,
654 header=header, metadata=metadata)
655 header=header, metadata=metadata)
655 if not os.getpid() == self.pid:
656 if not os.getpid() == self.pid:
656 io.rprint("WARNING: attempted to send message from fork")
657 get_logger().warn("WARNING: attempted to send message from fork\n%s",
657 io.rprint(msg)
658 msg
659 )
658 return
660 return
659 buffers = [] if buffers is None else buffers
661 buffers = [] if buffers is None else buffers
660 if self.adapt_version:
662 if self.adapt_version:
@@ -1,33 +1,20 b''
1 """Utility for calling pandoc"""
1 """Utility for calling pandoc"""
2 #-----------------------------------------------------------------------------
2 # Copyright (c) IPython Development Team.
3 # Copyright (c) 2014 the IPython Development Team.
4 #
5 # Distributed under the terms of the Modified BSD License.
3 # Distributed under the terms of the Modified BSD License.
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
9
4
10 #-----------------------------------------------------------------------------
5 from __future__ import print_function, absolute_import
11 # Imports
12 #-----------------------------------------------------------------------------
13 from __future__ import print_function
14
6
15 # Stdlib imports
16 import subprocess
7 import subprocess
17 import warnings
8 import warnings
18 import re
9 import re
19 from io import TextIOWrapper, BytesIO
10 from io import TextIOWrapper, BytesIO
20
11
21 # IPython imports
22 from IPython.utils.py3compat import cast_bytes
12 from IPython.utils.py3compat import cast_bytes
23 from IPython.utils.version import check_version
13 from IPython.utils.version import check_version
24 from IPython.utils.process import is_cmd_found, FindCmdError
14 from IPython.utils.process import is_cmd_found, FindCmdError
25
15
26 from .exceptions import ConversionException
16 from .exceptions import ConversionException
27
17
28 #-----------------------------------------------------------------------------
29 # Classes and functions
30 #-----------------------------------------------------------------------------
31 _minimal_version = "1.12.1"
18 _minimal_version = "1.12.1"
32
19
33 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
20 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
@@ -1,24 +1,13 b''
1 """
1 """
2 Contains Stdout writer
2 Contains Stdout writer
3 """
3 """
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
6 #
7 #Distributed under the terms of the Modified BSD License.
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
4
12 #-----------------------------------------------------------------------------
5 # Copyright (c) Jupyter Development Team.
13 # Imports
6 # Distributed under the terms of the Modified BSD License.
14 #-----------------------------------------------------------------------------
15
7
16 from IPython.utils import io
8 from jupyter_nbconvert.utils import io
17 from .base import WriterBase
9 from .base import WriterBase
18
10
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
22
11
23 class StdoutWriter(WriterBase):
12 class StdoutWriter(WriterBase):
24 """Consumes output from nbconvert export...() methods and writes to the
13 """Consumes output from nbconvert export...() methods and writes to the
General Comments 0
You need to be logged in to leave comments. Login now