##// END OF EJS Templates
re-add the rprint and rprinte alias....
Matthias Bussonnier -
Show More
@@ -1,243 +1,248 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IO related utilities.
3 IO related utilities.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9
9
10
10
11 import atexit
11 import atexit
12 import os
12 import os
13 import sys
13 import sys
14 import tempfile
14 import tempfile
15 import warnings
15 import warnings
16 from warnings import warn
16 from warnings import warn
17
17
18 from IPython.utils.decorators import undoc
18 from IPython.utils.decorators import undoc
19 from .capture import CapturedIO, capture_output
19 from .capture import CapturedIO, capture_output
20
20
21 @undoc
21 @undoc
22 class IOStream:
22 class IOStream:
23
23
24 def __init__(self, stream, fallback=None):
24 def __init__(self, stream, fallback=None):
25 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
25 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
26 DeprecationWarning, stacklevel=2)
26 DeprecationWarning, stacklevel=2)
27 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
27 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
28 if fallback is not None:
28 if fallback is not None:
29 stream = fallback
29 stream = fallback
30 else:
30 else:
31 raise ValueError("fallback required, but not specified")
31 raise ValueError("fallback required, but not specified")
32 self.stream = stream
32 self.stream = stream
33 self._swrite = stream.write
33 self._swrite = stream.write
34
34
35 # clone all methods not overridden:
35 # clone all methods not overridden:
36 def clone(meth):
36 def clone(meth):
37 return not hasattr(self, meth) and not meth.startswith('_')
37 return not hasattr(self, meth) and not meth.startswith('_')
38 for meth in filter(clone, dir(stream)):
38 for meth in filter(clone, dir(stream)):
39 try:
39 try:
40 val = getattr(stream, meth)
40 val = getattr(stream, meth)
41 except AttributeError:
41 except AttributeError:
42 pass
42 pass
43 else:
43 else:
44 setattr(self, meth, val)
44 setattr(self, meth, val)
45
45
46 def __repr__(self):
46 def __repr__(self):
47 cls = self.__class__
47 cls = self.__class__
48 tpl = '{mod}.{cls}({args})'
48 tpl = '{mod}.{cls}({args})'
49 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
49 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
50
50
51 def write(self,data):
51 def write(self,data):
52 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
52 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
53 DeprecationWarning, stacklevel=2)
53 DeprecationWarning, stacklevel=2)
54 try:
54 try:
55 self._swrite(data)
55 self._swrite(data)
56 except:
56 except:
57 try:
57 try:
58 # print handles some unicode issues which may trip a plain
58 # print handles some unicode issues which may trip a plain
59 # write() call. Emulate write() by using an empty end
59 # write() call. Emulate write() by using an empty end
60 # argument.
60 # argument.
61 print(data, end='', file=self.stream)
61 print(data, end='', file=self.stream)
62 except:
62 except:
63 # if we get here, something is seriously broken.
63 # if we get here, something is seriously broken.
64 print('ERROR - failed to write data to stream:', self.stream,
64 print('ERROR - failed to write data to stream:', self.stream,
65 file=sys.stderr)
65 file=sys.stderr)
66
66
67 def writelines(self, lines):
67 def writelines(self, lines):
68 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
68 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
69 DeprecationWarning, stacklevel=2)
69 DeprecationWarning, stacklevel=2)
70 if isinstance(lines, str):
70 if isinstance(lines, str):
71 lines = [lines]
71 lines = [lines]
72 for line in lines:
72 for line in lines:
73 self.write(line)
73 self.write(line)
74
74
75 # This class used to have a writeln method, but regular files and streams
75 # This class used to have a writeln method, but regular files and streams
76 # in Python don't have this method. We need to keep this completely
76 # in Python don't have this method. We need to keep this completely
77 # compatible so we removed it.
77 # compatible so we removed it.
78
78
79 @property
79 @property
80 def closed(self):
80 def closed(self):
81 return self.stream.closed
81 return self.stream.closed
82
82
83 def close(self):
83 def close(self):
84 pass
84 pass
85
85
86 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
86 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
87 devnull = open(os.devnull, 'w')
87 devnull = open(os.devnull, 'w')
88 atexit.register(devnull.close)
88 atexit.register(devnull.close)
89
89
90 # io.std* are deprecated, but don't show our own deprecation warnings
90 # io.std* are deprecated, but don't show our own deprecation warnings
91 # during initialization of the deprecated API.
91 # during initialization of the deprecated API.
92 with warnings.catch_warnings():
92 with warnings.catch_warnings():
93 warnings.simplefilter('ignore', DeprecationWarning)
93 warnings.simplefilter('ignore', DeprecationWarning)
94 stdin = IOStream(sys.stdin, fallback=devnull)
94 stdin = IOStream(sys.stdin, fallback=devnull)
95 stdout = IOStream(sys.stdout, fallback=devnull)
95 stdout = IOStream(sys.stdout, fallback=devnull)
96 stderr = IOStream(sys.stderr, fallback=devnull)
96 stderr = IOStream(sys.stderr, fallback=devnull)
97
97
98 class Tee(object):
98 class Tee(object):
99 """A class to duplicate an output stream to stdout/err.
99 """A class to duplicate an output stream to stdout/err.
100
100
101 This works in a manner very similar to the Unix 'tee' command.
101 This works in a manner very similar to the Unix 'tee' command.
102
102
103 When the object is closed or deleted, it closes the original file given to
103 When the object is closed or deleted, it closes the original file given to
104 it for duplication.
104 it for duplication.
105 """
105 """
106 # Inspired by:
106 # Inspired by:
107 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
107 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
108
108
109 def __init__(self, file_or_name, mode="w", channel='stdout'):
109 def __init__(self, file_or_name, mode="w", channel='stdout'):
110 """Construct a new Tee object.
110 """Construct a new Tee object.
111
111
112 Parameters
112 Parameters
113 ----------
113 ----------
114 file_or_name : filename or open filehandle (writable)
114 file_or_name : filename or open filehandle (writable)
115 File that will be duplicated
115 File that will be duplicated
116
116
117 mode : optional, valid mode for open().
117 mode : optional, valid mode for open().
118 If a filename was give, open with this mode.
118 If a filename was give, open with this mode.
119
119
120 channel : str, one of ['stdout', 'stderr']
120 channel : str, one of ['stdout', 'stderr']
121 """
121 """
122 if channel not in ['stdout', 'stderr']:
122 if channel not in ['stdout', 'stderr']:
123 raise ValueError('Invalid channel spec %s' % channel)
123 raise ValueError('Invalid channel spec %s' % channel)
124
124
125 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
125 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
126 self.file = file_or_name
126 self.file = file_or_name
127 else:
127 else:
128 self.file = open(file_or_name, mode)
128 self.file = open(file_or_name, mode)
129 self.channel = channel
129 self.channel = channel
130 self.ostream = getattr(sys, channel)
130 self.ostream = getattr(sys, channel)
131 setattr(sys, channel, self)
131 setattr(sys, channel, self)
132 self._closed = False
132 self._closed = False
133
133
134 def close(self):
134 def close(self):
135 """Close the file and restore the channel."""
135 """Close the file and restore the channel."""
136 self.flush()
136 self.flush()
137 setattr(sys, self.channel, self.ostream)
137 setattr(sys, self.channel, self.ostream)
138 self.file.close()
138 self.file.close()
139 self._closed = True
139 self._closed = True
140
140
141 def write(self, data):
141 def write(self, data):
142 """Write data to both channels."""
142 """Write data to both channels."""
143 self.file.write(data)
143 self.file.write(data)
144 self.ostream.write(data)
144 self.ostream.write(data)
145 self.ostream.flush()
145 self.ostream.flush()
146
146
147 def flush(self):
147 def flush(self):
148 """Flush both channels."""
148 """Flush both channels."""
149 self.file.flush()
149 self.file.flush()
150 self.ostream.flush()
150 self.ostream.flush()
151
151
152 def __del__(self):
152 def __del__(self):
153 if not self._closed:
153 if not self._closed:
154 self.close()
154 self.close()
155
155
156
156
157 def ask_yes_no(prompt, default=None, interrupt=None):
157 def ask_yes_no(prompt, default=None, interrupt=None):
158 """Asks a question and returns a boolean (y/n) answer.
158 """Asks a question and returns a boolean (y/n) answer.
159
159
160 If default is given (one of 'y','n'), it is used if the user input is
160 If default is given (one of 'y','n'), it is used if the user input is
161 empty. If interrupt is given (one of 'y','n'), it is used if the user
161 empty. If interrupt is given (one of 'y','n'), it is used if the user
162 presses Ctrl-C. Otherwise the question is repeated until an answer is
162 presses Ctrl-C. Otherwise the question is repeated until an answer is
163 given.
163 given.
164
164
165 An EOF is treated as the default answer. If there is no default, an
165 An EOF is treated as the default answer. If there is no default, an
166 exception is raised to prevent infinite loops.
166 exception is raised to prevent infinite loops.
167
167
168 Valid answers are: y/yes/n/no (match is not case sensitive)."""
168 Valid answers are: y/yes/n/no (match is not case sensitive)."""
169
169
170 answers = {'y':True,'n':False,'yes':True,'no':False}
170 answers = {'y':True,'n':False,'yes':True,'no':False}
171 ans = None
171 ans = None
172 while ans not in answers.keys():
172 while ans not in answers.keys():
173 try:
173 try:
174 ans = input(prompt+' ').lower()
174 ans = input(prompt+' ').lower()
175 if not ans: # response was an empty string
175 if not ans: # response was an empty string
176 ans = default
176 ans = default
177 except KeyboardInterrupt:
177 except KeyboardInterrupt:
178 if interrupt:
178 if interrupt:
179 ans = interrupt
179 ans = interrupt
180 print("\r")
180 print("\r")
181 except EOFError:
181 except EOFError:
182 if default in answers.keys():
182 if default in answers.keys():
183 ans = default
183 ans = default
184 print()
184 print()
185 else:
185 else:
186 raise
186 raise
187
187
188 return answers[ans]
188 return answers[ans]
189
189
190
190
191 def temp_pyfile(src, ext='.py'):
191 def temp_pyfile(src, ext='.py'):
192 """Make a temporary python file, return filename and filehandle.
192 """Make a temporary python file, return filename and filehandle.
193
193
194 Parameters
194 Parameters
195 ----------
195 ----------
196 src : string or list of strings (no need for ending newlines if list)
196 src : string or list of strings (no need for ending newlines if list)
197 Source code to be written to the file.
197 Source code to be written to the file.
198
198
199 ext : optional, string
199 ext : optional, string
200 Extension for the generated file.
200 Extension for the generated file.
201
201
202 Returns
202 Returns
203 -------
203 -------
204 (filename, open filehandle)
204 (filename, open filehandle)
205 It is the caller's responsibility to close the open file and unlink it.
205 It is the caller's responsibility to close the open file and unlink it.
206 """
206 """
207 fname = tempfile.mkstemp(ext)[1]
207 fname = tempfile.mkstemp(ext)[1]
208 f = open(fname,'w')
208 f = open(fname,'w')
209 f.write(src)
209 f.write(src)
210 f.flush()
210 f.flush()
211 return fname, f
211 return fname, f
212
212
213 @undoc
213 @undoc
214 def atomic_writing(*args, **kwargs):
214 def atomic_writing(*args, **kwargs):
215 """DEPRECATED: moved to notebook.services.contents.fileio"""
215 """DEPRECATED: moved to notebook.services.contents.fileio"""
216 warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio since IPython 4.0", DeprecationWarning, stacklevel=2)
216 warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio since IPython 4.0", DeprecationWarning, stacklevel=2)
217 from notebook.services.contents.fileio import atomic_writing
217 from notebook.services.contents.fileio import atomic_writing
218 return atomic_writing(*args, **kwargs)
218 return atomic_writing(*args, **kwargs)
219
219
220 @undoc
220 @undoc
221 def raw_print(*args, **kw):
221 def raw_print(*args, **kw):
222 """DEPRECATED: Raw print to sys.__stdout__, otherwise identical interface to print()."""
222 """DEPRECATED: Raw print to sys.__stdout__, otherwise identical interface to print()."""
223 warn("IPython.utils.io.raw_print has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2)
223 warn("IPython.utils.io.raw_print has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2)
224
224
225 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
225 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
226 file=sys.__stdout__)
226 file=sys.__stdout__)
227 sys.__stdout__.flush()
227 sys.__stdout__.flush()
228
228
229 @undoc
229 @undoc
230 def raw_print_err(*args, **kw):
230 def raw_print_err(*args, **kw):
231 """DEPRECATED: Raw print to sys.__stderr__, otherwise identical interface to print()."""
231 """DEPRECATED: Raw print to sys.__stderr__, otherwise identical interface to print()."""
232 warn("IPython.utils.io.raw_print_err has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2)
232 warn("IPython.utils.io.raw_print_err has been deprecated since IPython 7.0", DeprecationWarning, stacklevel=2)
233
233
234 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
234 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
235 file=sys.__stderr__)
235 file=sys.__stderr__)
236 sys.__stderr__.flush()
236 sys.__stderr__.flush()
237
237
238 # used by IPykernel <- 4.9. Removed during IPython 7-dev period and re-added
239 # Keep for a version or two then should remove
240 rprint = raw_print
241 rprinte = raw_print_err
242
238 @undoc
243 @undoc
239 def unicode_std_stream(stream='stdout'):
244 def unicode_std_stream(stream='stdout'):
240 """DEPRECATED, moved to nbconvert.utils.io"""
245 """DEPRECATED, moved to nbconvert.utils.io"""
241 warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io since IPython 4.0", DeprecationWarning, stacklevel=2)
246 warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io since IPython 4.0", DeprecationWarning, stacklevel=2)
242 from nbconvert.utils.io import unicode_std_stream
247 from nbconvert.utils.io import unicode_std_stream
243 return unicode_std_stream(stream)
248 return unicode_std_stream(stream)
General Comments 0
You need to be logged in to leave comments. Login now