##// END OF EJS Templates
Fix references to raw_input()
Thomas Kluyver -
Show More
@@ -1,215 +1,216 b''
1 1 # encoding: utf-8
2 2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian E. Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21 from __future__ import print_function
22 22
23 23 import os
24 24 import sys
25 25 import traceback
26 26 from pprint import pformat
27 27
28 28 from IPython.core import ultratb
29 29 from IPython.core.release import author_email
30 30 from IPython.utils.sysinfo import sys_info
31 from IPython.utils.py3compat import input
31 32
32 33 #-----------------------------------------------------------------------------
33 34 # Code
34 35 #-----------------------------------------------------------------------------
35 36
36 37 # Template for the user message.
37 38 _default_message_template = """\
38 39 Oops, {app_name} crashed. We do our best to make it stable, but...
39 40
40 41 A crash report was automatically generated with the following information:
41 42 - A verbatim copy of the crash traceback.
42 43 - A copy of your input history during this session.
43 44 - Data on your current {app_name} configuration.
44 45
45 46 It was left in the file named:
46 47 \t'{crash_report_fname}'
47 48 If you can email this file to the developers, the information in it will help
48 49 them in understanding and correcting the problem.
49 50
50 51 You can mail it to: {contact_name} at {contact_email}
51 52 with the subject '{app_name} Crash Report'.
52 53
53 54 If you want to do it now, the following command will work (under Unix):
54 55 mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
55 56
56 57 To ensure accurate tracking of this issue, please file a report about it at:
57 58 {bug_tracker}
58 59 """
59 60
60 61 _lite_message_template = """
61 62 If you suspect this is an IPython bug, please report it at:
62 63 https://github.com/ipython/ipython/issues
63 64 or send an email to the mailing list at {email}
64 65
65 66 You can print a more detailed traceback right now with "%tb", or use "%debug"
66 67 to interactively debug it.
67 68
68 69 Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
69 70 {config}Application.verbose_crash=True
70 71 """
71 72
72 73
73 74 class CrashHandler(object):
74 75 """Customizable crash handlers for IPython applications.
75 76
76 77 Instances of this class provide a :meth:`__call__` method which can be
77 78 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
78 79
79 80 def __call__(self, etype, evalue, etb)
80 81 """
81 82
82 83 message_template = _default_message_template
83 84 section_sep = '\n\n'+'*'*75+'\n\n'
84 85
85 86 def __init__(self, app, contact_name=None, contact_email=None,
86 87 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
87 88 """Create a new crash handler
88 89
89 90 Parameters
90 91 ----------
91 92 app : Application
92 93 A running :class:`Application` instance, which will be queried at
93 94 crash time for internal information.
94 95
95 96 contact_name : str
96 97 A string with the name of the person to contact.
97 98
98 99 contact_email : str
99 100 A string with the email address of the contact.
100 101
101 102 bug_tracker : str
102 103 A string with the URL for your project's bug tracker.
103 104
104 105 show_crash_traceback : bool
105 106 If false, don't print the crash traceback on stderr, only generate
106 107 the on-disk report
107 108
108 109 Non-argument instance attributes:
109 110
110 111 These instances contain some non-argument attributes which allow for
111 112 further customization of the crash handler's behavior. Please see the
112 113 source for further details.
113 114 """
114 115 self.crash_report_fname = "Crash_report_%s.txt" % app.name
115 116 self.app = app
116 117 self.call_pdb = call_pdb
117 118 #self.call_pdb = True # dbg
118 119 self.show_crash_traceback = show_crash_traceback
119 120 self.info = dict(app_name = app.name,
120 121 contact_name = contact_name,
121 122 contact_email = contact_email,
122 123 bug_tracker = bug_tracker,
123 124 crash_report_fname = self.crash_report_fname)
124 125
125 126
126 127 def __call__(self, etype, evalue, etb):
127 128 """Handle an exception, call for compatible with sys.excepthook"""
128 129
129 130 # do not allow the crash handler to be called twice without reinstalling it
130 131 # this prevents unlikely errors in the crash handling from entering an
131 132 # infinite loop.
132 133 sys.excepthook = sys.__excepthook__
133 134
134 135 # Report tracebacks shouldn't use color in general (safer for users)
135 136 color_scheme = 'NoColor'
136 137
137 138 # Use this ONLY for developer debugging (keep commented out for release)
138 139 #color_scheme = 'Linux' # dbg
139 140 try:
140 141 rptdir = self.app.ipython_dir
141 142 except:
142 143 rptdir = os.getcwdu()
143 144 if rptdir is None or not os.path.isdir(rptdir):
144 145 rptdir = os.getcwdu()
145 146 report_name = os.path.join(rptdir,self.crash_report_fname)
146 147 # write the report filename into the instance dict so it can get
147 148 # properly expanded out in the user message template
148 149 self.crash_report_fname = report_name
149 150 self.info['crash_report_fname'] = report_name
150 151 TBhandler = ultratb.VerboseTB(
151 152 color_scheme=color_scheme,
152 153 long_header=1,
153 154 call_pdb=self.call_pdb,
154 155 )
155 156 if self.call_pdb:
156 157 TBhandler(etype,evalue,etb)
157 158 return
158 159 else:
159 160 traceback = TBhandler.text(etype,evalue,etb,context=31)
160 161
161 162 # print traceback to screen
162 163 if self.show_crash_traceback:
163 164 print(traceback, file=sys.stderr)
164 165
165 166 # and generate a complete report on disk
166 167 try:
167 168 report = open(report_name,'w')
168 169 except:
169 170 print('Could not create crash report on disk.', file=sys.stderr)
170 171 return
171 172
172 173 # Inform user on stderr of what happened
173 174 print('\n'+'*'*70+'\n', file=sys.stderr)
174 175 print(self.message_template.format(**self.info), file=sys.stderr)
175 176
176 177 # Construct report on disk
177 178 report.write(self.make_report(traceback))
178 179 report.close()
179 raw_input("Hit <Enter> to quit (your terminal may close):")
180 input("Hit <Enter> to quit (your terminal may close):")
180 181
181 182 def make_report(self,traceback):
182 183 """Return a string containing a crash report."""
183 184
184 185 sec_sep = self.section_sep
185 186
186 187 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
187 188 rpt_add = report.append
188 189 rpt_add(sys_info())
189 190
190 191 try:
191 192 config = pformat(self.app.config)
192 193 rpt_add(sec_sep)
193 194 rpt_add('Application name: %s\n\n' % self.app_name)
194 195 rpt_add('Current user configuration structure:\n\n')
195 196 rpt_add(config)
196 197 except:
197 198 pass
198 199 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
199 200
200 201 return ''.join(report)
201 202
202 203
203 204 def crash_handler_lite(etype, evalue, tb):
204 205 """a light excepthook, adding a small message to the usual traceback"""
205 206 traceback.print_exception(etype, evalue, tb)
206 207
207 208 from IPython.core.interactiveshell import InteractiveShell
208 209 if InteractiveShell.initialized():
209 210 # we are in a Shell environment, give %magic example
210 211 config = "%config "
211 212 else:
212 213 # we are not in a shell, show generic config
213 214 config = "c."
214 215 print(_lite_message_template.format(email=author_email, config=config), file=sys.stderr)
215 216
@@ -1,350 +1,350 b''
1 1 # encoding: utf-8
2 2 """
3 3 Paging capabilities for IPython.core
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Fernando Perez
9 9
10 10 Notes
11 11 -----
12 12
13 13 For now this uses ipapi, so it can't be in IPython.utils. If we can get
14 14 rid of that dependency, we could move it there.
15 15 -----
16 16 """
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Copyright (C) 2008-2011 The IPython Development Team
20 20 #
21 21 # Distributed under the terms of the BSD License. The full license is in
22 22 # the file COPYING, distributed as part of this software.
23 23 #-----------------------------------------------------------------------------
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Imports
27 27 #-----------------------------------------------------------------------------
28 28 from __future__ import print_function
29 29
30 30 import os
31 31 import re
32 32 import sys
33 33 import tempfile
34 34
35 35 from io import UnsupportedOperation
36 36
37 37 from IPython import get_ipython
38 38 from IPython.core.error import TryNext
39 39 from IPython.utils.data import chop
40 40 from IPython.utils import io
41 41 from IPython.utils.process import system
42 42 from IPython.utils.terminal import get_terminal_size
43 43 from IPython.utils import py3compat
44 44
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Classes and functions
48 48 #-----------------------------------------------------------------------------
49 49
50 50 esc_re = re.compile(r"(\x1b[^m]+m)")
51 51
52 52 def page_dumb(strng, start=0, screen_lines=25):
53 53 """Very dumb 'pager' in Python, for when nothing else works.
54 54
55 55 Only moves forward, same interface as page(), except for pager_cmd and
56 56 mode."""
57 57
58 58 out_ln = strng.splitlines()[start:]
59 59 screens = chop(out_ln,screen_lines-1)
60 60 if len(screens) == 1:
61 61 print(os.linesep.join(screens[0]), file=io.stdout)
62 62 else:
63 63 last_escape = ""
64 64 for scr in screens[0:-1]:
65 65 hunk = os.linesep.join(scr)
66 66 print(last_escape + hunk, file=io.stdout)
67 67 if not page_more():
68 68 return
69 69 esc_list = esc_re.findall(hunk)
70 70 if len(esc_list) > 0:
71 71 last_escape = esc_list[-1]
72 72 print(last_escape + os.linesep.join(screens[-1]), file=io.stdout)
73 73
74 74 def _detect_screen_size(screen_lines_def):
75 75 """Attempt to work out the number of lines on the screen.
76 76
77 77 This is called by page(). It can raise an error (e.g. when run in the
78 78 test suite), so it's separated out so it can easily be called in a try block.
79 79 """
80 80 TERM = os.environ.get('TERM',None)
81 81 if not((TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5'):
82 82 # curses causes problems on many terminals other than xterm, and
83 83 # some termios calls lock up on Sun OS5.
84 84 return screen_lines_def
85 85
86 86 try:
87 87 import termios
88 88 import curses
89 89 except ImportError:
90 90 return screen_lines_def
91 91
92 92 # There is a bug in curses, where *sometimes* it fails to properly
93 93 # initialize, and then after the endwin() call is made, the
94 94 # terminal is left in an unusable state. Rather than trying to
95 95 # check everytime for this (by requesting and comparing termios
96 96 # flags each time), we just save the initial terminal state and
97 97 # unconditionally reset it every time. It's cheaper than making
98 98 # the checks.
99 99 term_flags = termios.tcgetattr(sys.stdout)
100 100
101 101 # Curses modifies the stdout buffer size by default, which messes
102 102 # up Python's normal stdout buffering. This would manifest itself
103 103 # to IPython users as delayed printing on stdout after having used
104 104 # the pager.
105 105 #
106 106 # We can prevent this by manually setting the NCURSES_NO_SETBUF
107 107 # environment variable. For more details, see:
108 108 # http://bugs.python.org/issue10144
109 109 NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
110 110 os.environ['NCURSES_NO_SETBUF'] = ''
111 111
112 112 # Proceed with curses initialization
113 113 try:
114 114 scr = curses.initscr()
115 115 except AttributeError:
116 116 # Curses on Solaris may not be complete, so we can't use it there
117 117 return screen_lines_def
118 118
119 119 screen_lines_real,screen_cols = scr.getmaxyx()
120 120 curses.endwin()
121 121
122 122 # Restore environment
123 123 if NCURSES_NO_SETBUF is None:
124 124 del os.environ['NCURSES_NO_SETBUF']
125 125 else:
126 126 os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF
127 127
128 128 # Restore terminal state in case endwin() didn't.
129 129 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
130 130 # Now we have what we needed: the screen size in rows/columns
131 131 return screen_lines_real
132 132 #print '***Screen size:',screen_lines_real,'lines x',\
133 133 #screen_cols,'columns.' # dbg
134 134
135 135 def page(strng, start=0, screen_lines=0, pager_cmd=None):
136 136 """Print a string, piping through a pager after a certain length.
137 137
138 138 The screen_lines parameter specifies the number of *usable* lines of your
139 139 terminal screen (total lines minus lines you need to reserve to show other
140 140 information).
141 141
142 142 If you set screen_lines to a number <=0, page() will try to auto-determine
143 143 your screen size and will only use up to (screen_size+screen_lines) for
144 144 printing, paging after that. That is, if you want auto-detection but need
145 145 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
146 146 auto-detection without any lines reserved simply use screen_lines = 0.
147 147
148 148 If a string won't fit in the allowed lines, it is sent through the
149 149 specified pager command. If none given, look for PAGER in the environment,
150 150 and ultimately default to less.
151 151
152 152 If no system pager works, the string is sent through a 'dumb pager'
153 153 written in python, very simplistic.
154 154 """
155 155
156 156 # Some routines may auto-compute start offsets incorrectly and pass a
157 157 # negative value. Offset to 0 for robustness.
158 158 start = max(0, start)
159 159
160 160 # first, try the hook
161 161 ip = get_ipython()
162 162 if ip:
163 163 try:
164 164 ip.hooks.show_in_pager(strng)
165 165 return
166 166 except TryNext:
167 167 pass
168 168
169 169 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
170 170 TERM = os.environ.get('TERM','dumb')
171 171 if TERM in ['dumb','emacs'] and os.name != 'nt':
172 172 print(strng)
173 173 return
174 174 # chop off the topmost part of the string we don't want to see
175 175 str_lines = strng.splitlines()[start:]
176 176 str_toprint = os.linesep.join(str_lines)
177 177 num_newlines = len(str_lines)
178 178 len_str = len(str_toprint)
179 179
180 180 # Dumb heuristics to guesstimate number of on-screen lines the string
181 181 # takes. Very basic, but good enough for docstrings in reasonable
182 182 # terminals. If someone later feels like refining it, it's not hard.
183 183 numlines = max(num_newlines,int(len_str/80)+1)
184 184
185 185 screen_lines_def = get_terminal_size()[1]
186 186
187 187 # auto-determine screen size
188 188 if screen_lines <= 0:
189 189 try:
190 190 screen_lines += _detect_screen_size(screen_lines_def)
191 191 except (TypeError, UnsupportedOperation):
192 192 print(str_toprint, file=io.stdout)
193 193 return
194 194
195 195 #print 'numlines',numlines,'screenlines',screen_lines # dbg
196 196 if numlines <= screen_lines :
197 197 #print '*** normal print' # dbg
198 198 print(str_toprint, file=io.stdout)
199 199 else:
200 200 # Try to open pager and default to internal one if that fails.
201 201 # All failure modes are tagged as 'retval=1', to match the return
202 202 # value of a failed system command. If any intermediate attempt
203 203 # sets retval to 1, at the end we resort to our own page_dumb() pager.
204 204 pager_cmd = get_pager_cmd(pager_cmd)
205 205 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
206 206 if os.name == 'nt':
207 207 if pager_cmd.startswith('type'):
208 208 # The default WinXP 'type' command is failing on complex strings.
209 209 retval = 1
210 210 else:
211 211 tmpname = tempfile.mktemp('.txt')
212 212 tmpfile = open(tmpname,'wt')
213 213 tmpfile.write(strng)
214 214 tmpfile.close()
215 215 cmd = "%s < %s" % (pager_cmd,tmpname)
216 216 if os.system(cmd):
217 217 retval = 1
218 218 else:
219 219 retval = None
220 220 os.remove(tmpname)
221 221 else:
222 222 try:
223 223 retval = None
224 224 # if I use popen4, things hang. No idea why.
225 225 #pager,shell_out = os.popen4(pager_cmd)
226 226 pager = os.popen(pager_cmd, 'w')
227 227 try:
228 228 pager_encoding = pager.encoding or sys.stdout.encoding
229 229 pager.write(py3compat.cast_bytes_py2(
230 230 strng, encoding=pager_encoding))
231 231 finally:
232 232 retval = pager.close()
233 233 except IOError as msg: # broken pipe when user quits
234 234 if msg.args == (32, 'Broken pipe'):
235 235 retval = None
236 236 else:
237 237 retval = 1
238 238 except OSError:
239 239 # Other strange problems, sometimes seen in Win2k/cygwin
240 240 retval = 1
241 241 if retval is not None:
242 242 page_dumb(strng,screen_lines=screen_lines)
243 243
244 244
245 245 def page_file(fname, start=0, pager_cmd=None):
246 246 """Page a file, using an optional pager command and starting line.
247 247 """
248 248
249 249 pager_cmd = get_pager_cmd(pager_cmd)
250 250 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
251 251
252 252 try:
253 253 if os.environ['TERM'] in ['emacs','dumb']:
254 254 raise EnvironmentError
255 255 system(pager_cmd + ' ' + fname)
256 256 except:
257 257 try:
258 258 if start > 0:
259 259 start -= 1
260 260 page(open(fname).read(),start)
261 261 except:
262 262 print('Unable to show file',repr(fname))
263 263
264 264
265 265 def get_pager_cmd(pager_cmd=None):
266 266 """Return a pager command.
267 267
268 268 Makes some attempts at finding an OS-correct one.
269 269 """
270 270 if os.name == 'posix':
271 271 default_pager_cmd = 'less -r' # -r for color control sequences
272 272 elif os.name in ['nt','dos']:
273 273 default_pager_cmd = 'type'
274 274
275 275 if pager_cmd is None:
276 276 try:
277 277 pager_cmd = os.environ['PAGER']
278 278 except:
279 279 pager_cmd = default_pager_cmd
280 280 return pager_cmd
281 281
282 282
283 283 def get_pager_start(pager, start):
284 284 """Return the string for paging files with an offset.
285 285
286 286 This is the '+N' argument which less and more (under Unix) accept.
287 287 """
288 288
289 289 if pager in ['less','more']:
290 290 if start:
291 291 start_string = '+' + str(start)
292 292 else:
293 293 start_string = ''
294 294 else:
295 295 start_string = ''
296 296 return start_string
297 297
298 298
299 299 # (X)emacs on win32 doesn't like to be bypassed with msvcrt.getch()
300 300 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
301 301 import msvcrt
302 302 def page_more():
303 303 """ Smart pausing between pages
304 304
305 305 @return: True if need print more lines, False if quit
306 306 """
307 307 io.stdout.write('---Return to continue, q to quit--- ')
308 308 ans = msvcrt.getwch()
309 309 if ans in ("q", "Q"):
310 310 result = False
311 311 else:
312 312 result = True
313 313 io.stdout.write("\b"*37 + " "*37 + "\b"*37)
314 314 return result
315 315 else:
316 316 def page_more():
317 ans = raw_input('---Return to continue, q to quit--- ')
317 ans = py3compat.input('---Return to continue, q to quit--- ')
318 318 if ans.lower().startswith('q'):
319 319 return False
320 320 else:
321 321 return True
322 322
323 323
324 324 def snip_print(str,width = 75,print_full = 0,header = ''):
325 325 """Print a string snipping the midsection to fit in width.
326 326
327 327 print_full: mode control:
328 328
329 329 - 0: only snip long strings
330 330 - 1: send to page() directly.
331 331 - 2: snip long strings and ask for full length viewing with page()
332 332
333 333 Return 1 if snipping was necessary, 0 otherwise."""
334 334
335 335 if print_full == 1:
336 336 page(header+str)
337 337 return 0
338 338
339 339 print(header, end=' ')
340 340 if len(str) < width:
341 341 print(str)
342 342 snip = 0
343 343 else:
344 344 whalf = int((width -5)/2)
345 345 print(str[:whalf] + ' <...> ' + str[-whalf:])
346 346 snip = 1
347 347 if snip and print_full == 2:
348 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
348 if py3compat.input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
349 349 page(str)
350 350 return snip
@@ -1,584 +1,584 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the inputsplitter module.
3 3
4 4 Authors
5 5 -------
6 6 * Fernando Perez
7 7 * Robert Kern
8 8 """
9 9 from __future__ import print_function
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2010-2011 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20 # stdlib
21 21 import unittest
22 22 import sys
23 23
24 24 # Third party
25 25 import nose.tools as nt
26 26
27 27 # Our own
28 28 from IPython.core import inputsplitter as isp
29 29 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
30 30 from IPython.testing import tools as tt
31 31 from IPython.utils import py3compat
32 from IPython.utils.py3compat import string_types
32 from IPython.utils.py3compat import string_types, input
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Semi-complete examples (also used as tests)
36 36 #-----------------------------------------------------------------------------
37 37
38 38 # Note: at the bottom, there's a slightly more complete version of this that
39 39 # can be useful during development of code here.
40 40
41 41 def mini_interactive_loop(input_func):
42 42 """Minimal example of the logic of an interactive interpreter loop.
43 43
44 44 This serves as an example, and it is used by the test system with a fake
45 45 raw_input that simulates interactive input."""
46 46
47 47 from IPython.core.inputsplitter import InputSplitter
48 48
49 49 isp = InputSplitter()
50 50 # In practice, this input loop would be wrapped in an outside loop to read
51 51 # input indefinitely, until some exit/quit command was issued. Here we
52 52 # only illustrate the basic inner loop.
53 53 while isp.push_accepts_more():
54 54 indent = ' '*isp.indent_spaces
55 55 prompt = '>>> ' + indent
56 56 line = indent + input_func(prompt)
57 57 isp.push(line)
58 58
59 59 # Here we just return input so we can use it in a test suite, but a real
60 60 # interpreter would instead send it for execution somewhere.
61 61 src = isp.source_reset()
62 62 #print 'Input source was:\n', src # dbg
63 63 return src
64 64
65 65 #-----------------------------------------------------------------------------
66 66 # Test utilities, just for local use
67 67 #-----------------------------------------------------------------------------
68 68
69 69 def assemble(block):
70 70 """Assemble a block into multi-line sub-blocks."""
71 71 return ['\n'.join(sub_block)+'\n' for sub_block in block]
72 72
73 73
74 74 def pseudo_input(lines):
75 75 """Return a function that acts like raw_input but feeds the input list."""
76 76 ilines = iter(lines)
77 77 def raw_in(prompt):
78 78 try:
79 79 return next(ilines)
80 80 except StopIteration:
81 81 return ''
82 82 return raw_in
83 83
84 84 #-----------------------------------------------------------------------------
85 85 # Tests
86 86 #-----------------------------------------------------------------------------
87 87 def test_spaces():
88 88 tests = [('', 0),
89 89 (' ', 1),
90 90 ('\n', 0),
91 91 (' \n', 1),
92 92 ('x', 0),
93 93 (' x', 1),
94 94 (' x',2),
95 95 (' x',4),
96 96 # Note: tabs are counted as a single whitespace!
97 97 ('\tx', 1),
98 98 ('\t x', 2),
99 99 ]
100 100 tt.check_pairs(isp.num_ini_spaces, tests)
101 101
102 102
103 103 def test_remove_comments():
104 104 tests = [('text', 'text'),
105 105 ('text # comment', 'text '),
106 106 ('text # comment\n', 'text \n'),
107 107 ('text # comment \n', 'text \n'),
108 108 ('line # c \nline\n','line \nline\n'),
109 109 ('line # c \nline#c2 \nline\nline #c\n\n',
110 110 'line \nline\nline\nline \n\n'),
111 111 ]
112 112 tt.check_pairs(isp.remove_comments, tests)
113 113
114 114
115 115 def test_get_input_encoding():
116 116 encoding = isp.get_input_encoding()
117 117 nt.assert_true(isinstance(encoding, string_types))
118 118 # simple-minded check that at least encoding a simple string works with the
119 119 # encoding we got.
120 120 nt.assert_equal(u'test'.encode(encoding), b'test')
121 121
122 122
123 123 class NoInputEncodingTestCase(unittest.TestCase):
124 124 def setUp(self):
125 125 self.old_stdin = sys.stdin
126 126 class X: pass
127 127 fake_stdin = X()
128 128 sys.stdin = fake_stdin
129 129
130 130 def test(self):
131 131 # Verify that if sys.stdin has no 'encoding' attribute we do the right
132 132 # thing
133 133 enc = isp.get_input_encoding()
134 134 self.assertEqual(enc, 'ascii')
135 135
136 136 def tearDown(self):
137 137 sys.stdin = self.old_stdin
138 138
139 139
140 140 class InputSplitterTestCase(unittest.TestCase):
141 141 def setUp(self):
142 142 self.isp = isp.InputSplitter()
143 143
144 144 def test_reset(self):
145 145 isp = self.isp
146 146 isp.push('x=1')
147 147 isp.reset()
148 148 self.assertEqual(isp._buffer, [])
149 149 self.assertEqual(isp.indent_spaces, 0)
150 150 self.assertEqual(isp.source, '')
151 151 self.assertEqual(isp.code, None)
152 152 self.assertEqual(isp._is_complete, False)
153 153
154 154 def test_source(self):
155 155 self.isp._store('1')
156 156 self.isp._store('2')
157 157 self.assertEqual(self.isp.source, '1\n2\n')
158 158 self.assertTrue(len(self.isp._buffer)>0)
159 159 self.assertEqual(self.isp.source_reset(), '1\n2\n')
160 160 self.assertEqual(self.isp._buffer, [])
161 161 self.assertEqual(self.isp.source, '')
162 162
163 163 def test_indent(self):
164 164 isp = self.isp # shorthand
165 165 isp.push('x=1')
166 166 self.assertEqual(isp.indent_spaces, 0)
167 167 isp.push('if 1:\n x=1')
168 168 self.assertEqual(isp.indent_spaces, 4)
169 169 isp.push('y=2\n')
170 170 self.assertEqual(isp.indent_spaces, 0)
171 171
172 172 def test_indent2(self):
173 173 isp = self.isp
174 174 isp.push('if 1:')
175 175 self.assertEqual(isp.indent_spaces, 4)
176 176 isp.push(' x=1')
177 177 self.assertEqual(isp.indent_spaces, 4)
178 178 # Blank lines shouldn't change the indent level
179 179 isp.push(' '*2)
180 180 self.assertEqual(isp.indent_spaces, 4)
181 181
182 182 def test_indent3(self):
183 183 isp = self.isp
184 184 # When a multiline statement contains parens or multiline strings, we
185 185 # shouldn't get confused.
186 186 isp.push("if 1:")
187 187 isp.push(" x = (1+\n 2)")
188 188 self.assertEqual(isp.indent_spaces, 4)
189 189
190 190 def test_indent4(self):
191 191 isp = self.isp
192 192 # whitespace after ':' should not screw up indent level
193 193 isp.push('if 1: \n x=1')
194 194 self.assertEqual(isp.indent_spaces, 4)
195 195 isp.push('y=2\n')
196 196 self.assertEqual(isp.indent_spaces, 0)
197 197 isp.push('if 1:\t\n x=1')
198 198 self.assertEqual(isp.indent_spaces, 4)
199 199 isp.push('y=2\n')
200 200 self.assertEqual(isp.indent_spaces, 0)
201 201
202 202 def test_dedent_pass(self):
203 203 isp = self.isp # shorthand
204 204 # should NOT cause dedent
205 205 isp.push('if 1:\n passes = 5')
206 206 self.assertEqual(isp.indent_spaces, 4)
207 207 isp.push('if 1:\n pass')
208 208 self.assertEqual(isp.indent_spaces, 0)
209 209 isp.push('if 1:\n pass ')
210 210 self.assertEqual(isp.indent_spaces, 0)
211 211
212 212 def test_dedent_break(self):
213 213 isp = self.isp # shorthand
214 214 # should NOT cause dedent
215 215 isp.push('while 1:\n breaks = 5')
216 216 self.assertEqual(isp.indent_spaces, 4)
217 217 isp.push('while 1:\n break')
218 218 self.assertEqual(isp.indent_spaces, 0)
219 219 isp.push('while 1:\n break ')
220 220 self.assertEqual(isp.indent_spaces, 0)
221 221
222 222 def test_dedent_continue(self):
223 223 isp = self.isp # shorthand
224 224 # should NOT cause dedent
225 225 isp.push('while 1:\n continues = 5')
226 226 self.assertEqual(isp.indent_spaces, 4)
227 227 isp.push('while 1:\n continue')
228 228 self.assertEqual(isp.indent_spaces, 0)
229 229 isp.push('while 1:\n continue ')
230 230 self.assertEqual(isp.indent_spaces, 0)
231 231
232 232 def test_dedent_raise(self):
233 233 isp = self.isp # shorthand
234 234 # should NOT cause dedent
235 235 isp.push('if 1:\n raised = 4')
236 236 self.assertEqual(isp.indent_spaces, 4)
237 237 isp.push('if 1:\n raise TypeError()')
238 238 self.assertEqual(isp.indent_spaces, 0)
239 239 isp.push('if 1:\n raise')
240 240 self.assertEqual(isp.indent_spaces, 0)
241 241 isp.push('if 1:\n raise ')
242 242 self.assertEqual(isp.indent_spaces, 0)
243 243
244 244 def test_dedent_return(self):
245 245 isp = self.isp # shorthand
246 246 # should NOT cause dedent
247 247 isp.push('if 1:\n returning = 4')
248 248 self.assertEqual(isp.indent_spaces, 4)
249 249 isp.push('if 1:\n return 5 + 493')
250 250 self.assertEqual(isp.indent_spaces, 0)
251 251 isp.push('if 1:\n return')
252 252 self.assertEqual(isp.indent_spaces, 0)
253 253 isp.push('if 1:\n return ')
254 254 self.assertEqual(isp.indent_spaces, 0)
255 255 isp.push('if 1:\n return(0)')
256 256 self.assertEqual(isp.indent_spaces, 0)
257 257
258 258 def test_push(self):
259 259 isp = self.isp
260 260 self.assertTrue(isp.push('x=1'))
261 261
262 262 def test_push2(self):
263 263 isp = self.isp
264 264 self.assertFalse(isp.push('if 1:'))
265 265 for line in [' x=1', '# a comment', ' y=2']:
266 266 print(line)
267 267 self.assertTrue(isp.push(line))
268 268
269 269 def test_push3(self):
270 270 isp = self.isp
271 271 isp.push('if True:')
272 272 isp.push(' a = 1')
273 273 self.assertFalse(isp.push('b = [1,'))
274 274
275 275 def test_push_accepts_more(self):
276 276 isp = self.isp
277 277 isp.push('x=1')
278 278 self.assertFalse(isp.push_accepts_more())
279 279
280 280 def test_push_accepts_more2(self):
281 281 isp = self.isp
282 282 isp.push('if 1:')
283 283 self.assertTrue(isp.push_accepts_more())
284 284 isp.push(' x=1')
285 285 self.assertTrue(isp.push_accepts_more())
286 286 isp.push('')
287 287 self.assertFalse(isp.push_accepts_more())
288 288
289 289 def test_push_accepts_more3(self):
290 290 isp = self.isp
291 291 isp.push("x = (2+\n3)")
292 292 self.assertFalse(isp.push_accepts_more())
293 293
294 294 def test_push_accepts_more4(self):
295 295 isp = self.isp
296 296 # When a multiline statement contains parens or multiline strings, we
297 297 # shouldn't get confused.
298 298 # FIXME: we should be able to better handle de-dents in statements like
299 299 # multiline strings and multiline expressions (continued with \ or
300 300 # parens). Right now we aren't handling the indentation tracking quite
301 301 # correctly with this, though in practice it may not be too much of a
302 302 # problem. We'll need to see.
303 303 isp.push("if 1:")
304 304 isp.push(" x = (2+")
305 305 isp.push(" 3)")
306 306 self.assertTrue(isp.push_accepts_more())
307 307 isp.push(" y = 3")
308 308 self.assertTrue(isp.push_accepts_more())
309 309 isp.push('')
310 310 self.assertFalse(isp.push_accepts_more())
311 311
312 312 def test_push_accepts_more5(self):
313 313 isp = self.isp
314 314 isp.push('try:')
315 315 isp.push(' a = 5')
316 316 isp.push('except:')
317 317 isp.push(' raise')
318 318 # We want to be able to add an else: block at this point, so it should
319 319 # wait for a blank line.
320 320 self.assertTrue(isp.push_accepts_more())
321 321
322 322 def test_continuation(self):
323 323 isp = self.isp
324 324 isp.push("import os, \\")
325 325 self.assertTrue(isp.push_accepts_more())
326 326 isp.push("sys")
327 327 self.assertFalse(isp.push_accepts_more())
328 328
329 329 def test_syntax_error(self):
330 330 isp = self.isp
331 331 # Syntax errors immediately produce a 'ready' block, so the invalid
332 332 # Python can be sent to the kernel for evaluation with possible ipython
333 333 # special-syntax conversion.
334 334 isp.push('run foo')
335 335 self.assertFalse(isp.push_accepts_more())
336 336
337 337 def test_unicode(self):
338 338 self.isp.push(u"PΓ©rez")
339 339 self.isp.push(u'\xc3\xa9')
340 340 self.isp.push(u"u'\xc3\xa9'")
341 341
342 342 def test_line_continuation(self):
343 343 """ Test issue #2108."""
344 344 isp = self.isp
345 345 # A blank line after a line continuation should not accept more
346 346 isp.push("1 \\\n\n")
347 347 self.assertFalse(isp.push_accepts_more())
348 348 # Whitespace after a \ is a SyntaxError. The only way to test that
349 349 # here is to test that push doesn't accept more (as with
350 350 # test_syntax_error() above).
351 351 isp.push(r"1 \ ")
352 352 self.assertFalse(isp.push_accepts_more())
353 353 # Even if the line is continuable (c.f. the regular Python
354 354 # interpreter)
355 355 isp.push(r"(1 \ ")
356 356 self.assertFalse(isp.push_accepts_more())
357 357
358 358 class InteractiveLoopTestCase(unittest.TestCase):
359 359 """Tests for an interactive loop like a python shell.
360 360 """
361 361 def check_ns(self, lines, ns):
362 362 """Validate that the given input lines produce the resulting namespace.
363 363
364 364 Note: the input lines are given exactly as they would be typed in an
365 365 auto-indenting environment, as mini_interactive_loop above already does
366 366 auto-indenting and prepends spaces to the input.
367 367 """
368 368 src = mini_interactive_loop(pseudo_input(lines))
369 369 test_ns = {}
370 370 exec(src, test_ns)
371 371 # We can't check that the provided ns is identical to the test_ns,
372 372 # because Python fills test_ns with extra keys (copyright, etc). But
373 373 # we can check that the given dict is *contained* in test_ns
374 374 for k,v in ns.iteritems():
375 375 self.assertEqual(test_ns[k], v)
376 376
377 377 def test_simple(self):
378 378 self.check_ns(['x=1'], dict(x=1))
379 379
380 380 def test_simple2(self):
381 381 self.check_ns(['if 1:', 'x=2'], dict(x=2))
382 382
383 383 def test_xy(self):
384 384 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
385 385
386 386 def test_abc(self):
387 387 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
388 388
389 389 def test_multi(self):
390 390 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
391 391
392 392
393 393 class IPythonInputTestCase(InputSplitterTestCase):
394 394 """By just creating a new class whose .isp is a different instance, we
395 395 re-run the same test battery on the new input splitter.
396 396
397 397 In addition, this runs the tests over the syntax and syntax_ml dicts that
398 398 were tested by individual functions, as part of the OO interface.
399 399
400 400 It also makes some checks on the raw buffer storage.
401 401 """
402 402
403 403 def setUp(self):
404 404 self.isp = isp.IPythonInputSplitter()
405 405
406 406 def test_syntax(self):
407 407 """Call all single-line syntax tests from the main object"""
408 408 isp = self.isp
409 409 for example in syntax.itervalues():
410 410 for raw, out_t in example:
411 411 if raw.startswith(' '):
412 412 continue
413 413
414 414 isp.push(raw+'\n')
415 415 out, out_raw = isp.source_raw_reset()
416 416 self.assertEqual(out.rstrip(), out_t,
417 417 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
418 418 self.assertEqual(out_raw.rstrip(), raw.rstrip())
419 419
420 420 def test_syntax_multiline(self):
421 421 isp = self.isp
422 422 for example in syntax_ml.itervalues():
423 423 for line_pairs in example:
424 424 out_t_parts = []
425 425 raw_parts = []
426 426 for lraw, out_t_part in line_pairs:
427 427 if out_t_part is not None:
428 428 out_t_parts.append(out_t_part)
429 429
430 430 if lraw is not None:
431 431 isp.push(lraw)
432 432 raw_parts.append(lraw)
433 433
434 434 out, out_raw = isp.source_raw_reset()
435 435 out_t = '\n'.join(out_t_parts).rstrip()
436 436 raw = '\n'.join(raw_parts).rstrip()
437 437 self.assertEqual(out.rstrip(), out_t)
438 438 self.assertEqual(out_raw.rstrip(), raw)
439 439
440 440 def test_syntax_multiline_cell(self):
441 441 isp = self.isp
442 442 for example in syntax_ml.itervalues():
443 443
444 444 out_t_parts = []
445 445 for line_pairs in example:
446 446 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
447 447 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
448 448 out = isp.transform_cell(raw)
449 449 # Match ignoring trailing whitespace
450 450 self.assertEqual(out.rstrip(), out_t.rstrip())
451 451
452 452 def test_cellmagic_preempt(self):
453 453 isp = self.isp
454 454 for raw, name, line, cell in [
455 455 ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
456 456 ("%%cellm \nline\n>>>hi", u'cellm', u'', u'line\n>>>hi'),
457 457 (">>>%%cellm \nline\n>>>hi", u'cellm', u'', u'line\nhi'),
458 458 ("%%cellm \n>>>hi", u'cellm', u'', u'hi'),
459 459 ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
460 460 ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
461 461 ]:
462 462 expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
463 463 name, line, cell
464 464 )
465 465 out = isp.transform_cell(raw)
466 466 self.assertEqual(out.rstrip(), expected.rstrip())
467 467
468 468
469 469
470 470 #-----------------------------------------------------------------------------
471 471 # Main - use as a script, mostly for developer experiments
472 472 #-----------------------------------------------------------------------------
473 473
474 474 if __name__ == '__main__':
475 475 # A simple demo for interactive experimentation. This code will not get
476 476 # picked up by any test suite.
477 477 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
478 478
479 479 # configure here the syntax to use, prompt and whether to autoindent
480 480 #isp, start_prompt = InputSplitter(), '>>> '
481 481 isp, start_prompt = IPythonInputSplitter(), 'In> '
482 482
483 483 autoindent = True
484 484 #autoindent = False
485 485
486 486 try:
487 487 while True:
488 488 prompt = start_prompt
489 489 while isp.push_accepts_more():
490 490 indent = ' '*isp.indent_spaces
491 491 if autoindent:
492 line = indent + raw_input(prompt+indent)
492 line = indent + input(prompt+indent)
493 493 else:
494 line = raw_input(prompt)
494 line = input(prompt)
495 495 isp.push(line)
496 496 prompt = '... '
497 497
498 498 # Here we just return input so we can use it in a test suite, but a
499 499 # real interpreter would instead send it for execution somewhere.
500 500 #src = isp.source; raise EOFError # dbg
501 501 src, raw = isp.source_raw_reset()
502 502 print('Input source was:\n', src)
503 503 print('Raw source was:\n', raw)
504 504 except EOFError:
505 505 print('Bye')
506 506
507 507 # Tests for cell magics support
508 508
509 509 def test_last_blank():
510 510 nt.assert_false(isp.last_blank(''))
511 511 nt.assert_false(isp.last_blank('abc'))
512 512 nt.assert_false(isp.last_blank('abc\n'))
513 513 nt.assert_false(isp.last_blank('abc\na'))
514 514
515 515 nt.assert_true(isp.last_blank('\n'))
516 516 nt.assert_true(isp.last_blank('\n '))
517 517 nt.assert_true(isp.last_blank('abc\n '))
518 518 nt.assert_true(isp.last_blank('abc\n\n'))
519 519 nt.assert_true(isp.last_blank('abc\nd\n\n'))
520 520 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
521 521 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
522 522
523 523
524 524 def test_last_two_blanks():
525 525 nt.assert_false(isp.last_two_blanks(''))
526 526 nt.assert_false(isp.last_two_blanks('abc'))
527 527 nt.assert_false(isp.last_two_blanks('abc\n'))
528 528 nt.assert_false(isp.last_two_blanks('abc\n\na'))
529 529 nt.assert_false(isp.last_two_blanks('abc\n \n'))
530 530 nt.assert_false(isp.last_two_blanks('abc\n\n'))
531 531
532 532 nt.assert_true(isp.last_two_blanks('\n\n'))
533 533 nt.assert_true(isp.last_two_blanks('\n\n '))
534 534 nt.assert_true(isp.last_two_blanks('\n \n'))
535 535 nt.assert_true(isp.last_two_blanks('abc\n\n '))
536 536 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
537 537 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
538 538 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
539 539 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
540 540 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
541 541 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
542 542
543 543
544 544 class CellMagicsCommon(object):
545 545
546 546 def test_whole_cell(self):
547 547 src = "%%cellm line\nbody\n"
548 548 sp = self.sp
549 549 sp.push(src)
550 550 out = sp.source_reset()
551 551 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
552 552 nt.assert_equal(out, py3compat.u_format(ref))
553 553
554 554 def test_cellmagic_help(self):
555 555 self.sp.push('%%cellm?')
556 556 nt.assert_false(self.sp.push_accepts_more())
557 557
558 558 def tearDown(self):
559 559 self.sp.reset()
560 560
561 561
562 562 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
563 563 sp = isp.IPythonInputSplitter(line_input_checker=False)
564 564
565 565 def test_incremental(self):
566 566 sp = self.sp
567 567 sp.push('%%cellm firstline\n')
568 568 nt.assert_true(sp.push_accepts_more()) #1
569 569 sp.push('line2\n')
570 570 nt.assert_true(sp.push_accepts_more()) #2
571 571 sp.push('\n')
572 572 # This should accept a blank line and carry on until the cell is reset
573 573 nt.assert_true(sp.push_accepts_more()) #3
574 574
575 575 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
576 576 sp = isp.IPythonInputSplitter(line_input_checker=True)
577 577
578 578 def test_incremental(self):
579 579 sp = self.sp
580 580 sp.push('%%cellm line2\n')
581 581 nt.assert_true(sp.push_accepts_more()) #1
582 582 sp.push('\n')
583 583 # In this case, a blank line should end the cell magic
584 584 nt.assert_false(sp.push_accepts_more()) #2
@@ -1,582 +1,583 b''
1 1 """Module for interactive demos using IPython.
2 2
3 3 This module implements a few classes for running Python scripts interactively
4 4 in IPython for demonstrations. With very simple markup (a few tags in
5 5 comments), you can control points where the script stops executing and returns
6 6 control to IPython.
7 7
8 8
9 9 Provided classes
10 10 ----------------
11 11
12 12 The classes are (see their docstrings for further details):
13 13
14 14 - Demo: pure python demos
15 15
16 16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 17 typed interactively (so magics work, as well as any other special syntax you
18 18 may have added via input prefilters).
19 19
20 20 - LineDemo: single-line version of the Demo class. These demos are executed
21 21 one line at a time, and require no markup.
22 22
23 23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 24 executed a line at a time, but processed via IPython).
25 25
26 26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 27 declares an empty marquee and a pre_cmd that clears the screen before each
28 28 block (see Subclassing below).
29 29
30 30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 31 classes.
32 32
33 33 Inheritance diagram:
34 34
35 35 .. inheritance-diagram:: IPython.lib.demo
36 36 :parts: 3
37 37
38 38 Subclassing
39 39 -----------
40 40
41 41 The classes here all include a few methods meant to make customization by
42 42 subclassing more convenient. Their docstrings below have some more details:
43 43
44 44 - marquee(): generates a marquee to provide visible on-screen markers at each
45 45 block start and end.
46 46
47 47 - pre_cmd(): run right before the execution of each block.
48 48
49 49 - post_cmd(): run right after the execution of each block. If the block
50 50 raises an exception, this is NOT called.
51 51
52 52
53 53 Operation
54 54 ---------
55 55
56 56 The file is run in its own empty namespace (though you can pass it a string of
57 57 arguments as if in a command line environment, and it will see those as
58 58 sys.argv). But at each stop, the global IPython namespace is updated with the
59 59 current internal demo namespace, so you can work interactively with the data
60 60 accumulated so far.
61 61
62 62 By default, each block of code is printed (with syntax highlighting) before
63 63 executing it and you have to confirm execution. This is intended to show the
64 64 code to an audience first so you can discuss it, and only proceed with
65 65 execution once you agree. There are a few tags which allow you to modify this
66 66 behavior.
67 67
68 68 The supported tags are:
69 69
70 70 # <demo> stop
71 71
72 72 Defines block boundaries, the points where IPython stops execution of the
73 73 file and returns to the interactive prompt.
74 74
75 75 You can optionally mark the stop tag with extra dashes before and after the
76 76 word 'stop', to help visually distinguish the blocks in a text editor:
77 77
78 78 # <demo> --- stop ---
79 79
80 80
81 81 # <demo> silent
82 82
83 83 Make a block execute silently (and hence automatically). Typically used in
84 84 cases where you have some boilerplate or initialization code which you need
85 85 executed but do not want to be seen in the demo.
86 86
87 87 # <demo> auto
88 88
89 89 Make a block execute automatically, but still being printed. Useful for
90 90 simple code which does not warrant discussion, since it avoids the extra
91 91 manual confirmation.
92 92
93 93 # <demo> auto_all
94 94
95 95 This tag can _only_ be in the first block, and if given it overrides the
96 96 individual auto tags to make the whole demo fully automatic (no block asks
97 97 for confirmation). It can also be given at creation time (or the attribute
98 98 set later) to override what's in the file.
99 99
100 100 While _any_ python file can be run as a Demo instance, if there are no stop
101 101 tags the whole file will run in a single block (no different that calling
102 102 first %pycat and then %run). The minimal markup to make this useful is to
103 103 place a set of stop tags; the other tags are only there to let you fine-tune
104 104 the execution.
105 105
106 106 This is probably best explained with the simple example file below. You can
107 107 copy this into a file named ex_demo.py, and try running it via::
108 108
109 109 from IPython.demo import Demo
110 110 d = Demo('ex_demo.py')
111 111 d()
112 112
113 113 Each time you call the demo object, it runs the next block. The demo object
114 114 has a few useful methods for navigation, like again(), edit(), jump(), seek()
115 115 and back(). It can be reset for a new run via reset() or reloaded from disk
116 116 (in case you've edited the source) via reload(). See their docstrings below.
117 117
118 118 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
119 119 been added to the "docs/examples/core" directory. Just cd to this directory in
120 120 an IPython session, and type::
121 121
122 122 %run demo-exercizer.py
123 123
124 124 and then follow the directions.
125 125
126 126 Example
127 127 -------
128 128
129 129 The following is a very simple example of a valid demo file.
130 130
131 131 ::
132 132
133 133 #################### EXAMPLE DEMO <ex_demo.py> ###############################
134 134 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
135 135
136 136 print 'Hello, welcome to an interactive IPython demo.'
137 137
138 138 # The mark below defines a block boundary, which is a point where IPython will
139 139 # stop execution and return to the interactive prompt. The dashes are actually
140 140 # optional and used only as a visual aid to clearly separate blocks while
141 141 # editing the demo code.
142 142 # <demo> stop
143 143
144 144 x = 1
145 145 y = 2
146 146
147 147 # <demo> stop
148 148
149 149 # the mark below makes this block as silent
150 150 # <demo> silent
151 151
152 152 print 'This is a silent block, which gets executed but not printed.'
153 153
154 154 # <demo> stop
155 155 # <demo> auto
156 156 print 'This is an automatic block.'
157 157 print 'It is executed without asking for confirmation, but printed.'
158 158 z = x+y
159 159
160 160 print 'z=',x
161 161
162 162 # <demo> stop
163 163 # This is just another normal block.
164 164 print 'z is now:', z
165 165
166 166 print 'bye!'
167 167 ################### END EXAMPLE DEMO <ex_demo.py> ############################
168 168 """
169 169
170 170 from __future__ import unicode_literals
171 171
172 172 #*****************************************************************************
173 173 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
174 174 #
175 175 # Distributed under the terms of the BSD License. The full license is in
176 176 # the file COPYING, distributed as part of this software.
177 177 #
178 178 #*****************************************************************************
179 179 from __future__ import print_function
180 180
181 181 import os
182 182 import re
183 183 import shlex
184 184 import sys
185 185
186 186 from IPython.utils import io
187 187 from IPython.utils.text import marquee
188 188 from IPython.utils import openpy
189 from IPython.utils import py3compat
189 190 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
190 191
191 192 class DemoError(Exception): pass
192 193
193 194 def re_mark(mark):
194 195 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
195 196
196 197 class Demo(object):
197 198
198 199 re_stop = re_mark('-*\s?stop\s?-*')
199 200 re_silent = re_mark('silent')
200 201 re_auto = re_mark('auto')
201 202 re_auto_all = re_mark('auto_all')
202 203
203 204 def __init__(self,src,title='',arg_str='',auto_all=None):
204 205 """Make a new demo object. To run the demo, simply call the object.
205 206
206 207 See the module docstring for full details and an example (you can use
207 208 IPython.Demo? in IPython to see it).
208 209
209 210 Inputs:
210 211
211 212 - src is either a file, or file-like object, or a
212 213 string that can be resolved to a filename.
213 214
214 215 Optional inputs:
215 216
216 217 - title: a string to use as the demo name. Of most use when the demo
217 218 you are making comes from an object that has no filename, or if you
218 219 want an alternate denotation distinct from the filename.
219 220
220 221 - arg_str(''): a string of arguments, internally converted to a list
221 222 just like sys.argv, so the demo script can see a similar
222 223 environment.
223 224
224 225 - auto_all(None): global flag to run all blocks automatically without
225 226 confirmation. This attribute overrides the block-level tags and
226 227 applies to the whole demo. It is an attribute of the object, and
227 228 can be changed at runtime simply by reassigning it to a boolean
228 229 value.
229 230 """
230 231 if hasattr(src, "read"):
231 232 # It seems to be a file or a file-like object
232 233 self.fname = "from a file-like object"
233 234 if title == '':
234 235 self.title = "from a file-like object"
235 236 else:
236 237 self.title = title
237 238 else:
238 239 # Assume it's a string or something that can be converted to one
239 240 self.fname = src
240 241 if title == '':
241 242 (filepath, filename) = os.path.split(src)
242 243 self.title = filename
243 244 else:
244 245 self.title = title
245 246 self.sys_argv = [src] + shlex.split(arg_str)
246 247 self.auto_all = auto_all
247 248 self.src = src
248 249
249 250 # get a few things from ipython. While it's a bit ugly design-wise,
250 251 # it ensures that things like color scheme and the like are always in
251 252 # sync with the ipython mode being used. This class is only meant to
252 253 # be used inside ipython anyways, so it's OK.
253 254 ip = get_ipython() # this is in builtins whenever IPython is running
254 255 self.ip_ns = ip.user_ns
255 256 self.ip_colorize = ip.pycolorize
256 257 self.ip_showtb = ip.showtraceback
257 258 self.ip_run_cell = ip.run_cell
258 259 self.shell = ip
259 260
260 261 # load user data and initialize data structures
261 262 self.reload()
262 263
263 264 def fload(self):
264 265 """Load file object."""
265 266 # read data and parse into blocks
266 267 if hasattr(self, 'fobj') and self.fobj is not None:
267 268 self.fobj.close()
268 269 if hasattr(self.src, "read"):
269 270 # It seems to be a file or a file-like object
270 271 self.fobj = self.src
271 272 else:
272 273 # Assume it's a string or something that can be converted to one
273 274 self.fobj = openpy.open(self.fname)
274 275
275 276 def reload(self):
276 277 """Reload source from disk and initialize state."""
277 278 self.fload()
278 279
279 280 self.src = "".join(openpy.strip_encoding_cookie(self.fobj))
280 281 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
281 282 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
282 283 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
283 284
284 285 # if auto_all is not given (def. None), we read it from the file
285 286 if self.auto_all is None:
286 287 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
287 288 else:
288 289 self.auto_all = bool(self.auto_all)
289 290
290 291 # Clean the sources from all markup so it doesn't get displayed when
291 292 # running the demo
292 293 src_blocks = []
293 294 auto_strip = lambda s: self.re_auto.sub('',s)
294 295 for i,b in enumerate(src_b):
295 296 if self._auto[i]:
296 297 src_blocks.append(auto_strip(b))
297 298 else:
298 299 src_blocks.append(b)
299 300 # remove the auto_all marker
300 301 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
301 302
302 303 self.nblocks = len(src_blocks)
303 304 self.src_blocks = src_blocks
304 305
305 306 # also build syntax-highlighted source
306 307 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
307 308
308 309 # ensure clean namespace and seek offset
309 310 self.reset()
310 311
311 312 def reset(self):
312 313 """Reset the namespace and seek pointer to restart the demo"""
313 314 self.user_ns = {}
314 315 self.finished = False
315 316 self.block_index = 0
316 317
317 318 def _validate_index(self,index):
318 319 if index<0 or index>=self.nblocks:
319 320 raise ValueError('invalid block index %s' % index)
320 321
321 322 def _get_index(self,index):
322 323 """Get the current block index, validating and checking status.
323 324
324 325 Returns None if the demo is finished"""
325 326
326 327 if index is None:
327 328 if self.finished:
328 329 print('Demo finished. Use <demo_name>.reset() if you want to rerun it.', file=io.stdout)
329 330 return None
330 331 index = self.block_index
331 332 else:
332 333 self._validate_index(index)
333 334 return index
334 335
335 336 def seek(self,index):
336 337 """Move the current seek pointer to the given block.
337 338
338 339 You can use negative indices to seek from the end, with identical
339 340 semantics to those of Python lists."""
340 341 if index<0:
341 342 index = self.nblocks + index
342 343 self._validate_index(index)
343 344 self.block_index = index
344 345 self.finished = False
345 346
346 347 def back(self,num=1):
347 348 """Move the seek pointer back num blocks (default is 1)."""
348 349 self.seek(self.block_index-num)
349 350
350 351 def jump(self,num=1):
351 352 """Jump a given number of blocks relative to the current one.
352 353
353 354 The offset can be positive or negative, defaults to 1."""
354 355 self.seek(self.block_index+num)
355 356
356 357 def again(self):
357 358 """Move the seek pointer back one block and re-execute."""
358 359 self.back(1)
359 360 self()
360 361
361 362 def edit(self,index=None):
362 363 """Edit a block.
363 364
364 365 If no number is given, use the last block executed.
365 366
366 367 This edits the in-memory copy of the demo, it does NOT modify the
367 368 original source file. If you want to do that, simply open the file in
368 369 an editor and use reload() when you make changes to the file. This
369 370 method is meant to let you change a block during a demonstration for
370 371 explanatory purposes, without damaging your original script."""
371 372
372 373 index = self._get_index(index)
373 374 if index is None:
374 375 return
375 376 # decrease the index by one (unless we're at the very beginning), so
376 377 # that the default demo.edit() call opens up the sblock we've last run
377 378 if index>0:
378 379 index -= 1
379 380
380 381 filename = self.shell.mktempfile(self.src_blocks[index])
381 382 self.shell.hooks.editor(filename,1)
382 383 with open(filename, 'r') as f:
383 384 new_block = f.read()
384 385 # update the source and colored block
385 386 self.src_blocks[index] = new_block
386 387 self.src_blocks_colored[index] = self.ip_colorize(new_block)
387 388 self.block_index = index
388 389 # call to run with the newly edited index
389 390 self()
390 391
391 392 def show(self,index=None):
392 393 """Show a single block on screen"""
393 394
394 395 index = self._get_index(index)
395 396 if index is None:
396 397 return
397 398
398 399 print(self.marquee('<%s> block # %s (%s remaining)' %
399 400 (self.title,index,self.nblocks-index-1)), file=io.stdout)
400 401 print((self.src_blocks_colored[index]), file=io.stdout)
401 402 sys.stdout.flush()
402 403
403 404 def show_all(self):
404 405 """Show entire demo on screen, block by block"""
405 406
406 407 fname = self.title
407 408 title = self.title
408 409 nblocks = self.nblocks
409 410 silent = self._silent
410 411 marquee = self.marquee
411 412 for index,block in enumerate(self.src_blocks_colored):
412 413 if silent[index]:
413 414 print(marquee('<%s> SILENT block # %s (%s remaining)' %
414 415 (title,index,nblocks-index-1)), file=io.stdout)
415 416 else:
416 417 print(marquee('<%s> block # %s (%s remaining)' %
417 418 (title,index,nblocks-index-1)), file=io.stdout)
418 419 print(block, end=' ', file=io.stdout)
419 420 sys.stdout.flush()
420 421
421 422 def run_cell(self,source):
422 423 """Execute a string with one or more lines of code"""
423 424
424 425 exec(source, self.user_ns)
425 426
426 427 def __call__(self,index=None):
427 428 """run a block of the demo.
428 429
429 430 If index is given, it should be an integer >=1 and <= nblocks. This
430 431 means that the calling convention is one off from typical Python
431 432 lists. The reason for the inconsistency is that the demo always
432 433 prints 'Block n/N, and N is the total, so it would be very odd to use
433 434 zero-indexing here."""
434 435
435 436 index = self._get_index(index)
436 437 if index is None:
437 438 return
438 439 try:
439 440 marquee = self.marquee
440 441 next_block = self.src_blocks[index]
441 442 self.block_index += 1
442 443 if self._silent[index]:
443 444 print(marquee('Executing silent block # %s (%s remaining)' %
444 445 (index,self.nblocks-index-1)), file=io.stdout)
445 446 else:
446 447 self.pre_cmd()
447 448 self.show(index)
448 449 if self.auto_all or self._auto[index]:
449 450 print(marquee('output:'), file=io.stdout)
450 451 else:
451 452 print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ', file=io.stdout)
452 ans = raw_input().strip()
453 ans = py3compat.input().strip()
453 454 if ans:
454 455 print(marquee('Block NOT executed'), file=io.stdout)
455 456 return
456 457 try:
457 458 save_argv = sys.argv
458 459 sys.argv = self.sys_argv
459 460 self.run_cell(next_block)
460 461 self.post_cmd()
461 462 finally:
462 463 sys.argv = save_argv
463 464
464 465 except:
465 466 self.ip_showtb(filename=self.fname)
466 467 else:
467 468 self.ip_ns.update(self.user_ns)
468 469
469 470 if self.block_index == self.nblocks:
470 471 mq1 = self.marquee('END OF DEMO')
471 472 if mq1:
472 473 # avoid spurious print >>io.stdout,s if empty marquees are used
473 474 print(file=io.stdout)
474 475 print(mq1, file=io.stdout)
475 476 print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'), file=io.stdout)
476 477 self.finished = True
477 478
478 479 # These methods are meant to be overridden by subclasses who may wish to
479 480 # customize the behavior of of their demos.
480 481 def marquee(self,txt='',width=78,mark='*'):
481 482 """Return the input string centered in a 'marquee'."""
482 483 return marquee(txt,width,mark)
483 484
484 485 def pre_cmd(self):
485 486 """Method called before executing each block."""
486 487 pass
487 488
488 489 def post_cmd(self):
489 490 """Method called after executing each block."""
490 491 pass
491 492
492 493
493 494 class IPythonDemo(Demo):
494 495 """Class for interactive demos with IPython's input processing applied.
495 496
496 497 This subclasses Demo, but instead of executing each block by the Python
497 498 interpreter (via exec), it actually calls IPython on it, so that any input
498 499 filters which may be in place are applied to the input block.
499 500
500 501 If you have an interactive environment which exposes special input
501 502 processing, you can use this class instead to write demo scripts which
502 503 operate exactly as if you had typed them interactively. The default Demo
503 504 class requires the input to be valid, pure Python code.
504 505 """
505 506
506 507 def run_cell(self,source):
507 508 """Execute a string with one or more lines of code"""
508 509
509 510 self.shell.run_cell(source)
510 511
511 512 class LineDemo(Demo):
512 513 """Demo where each line is executed as a separate block.
513 514
514 515 The input script should be valid Python code.
515 516
516 517 This class doesn't require any markup at all, and it's meant for simple
517 518 scripts (with no nesting or any kind of indentation) which consist of
518 519 multiple lines of input to be executed, one at a time, as if they had been
519 520 typed in the interactive prompt.
520 521
521 522 Note: the input can not have *any* indentation, which means that only
522 523 single-lines of input are accepted, not even function definitions are
523 524 valid."""
524 525
525 526 def reload(self):
526 527 """Reload source from disk and initialize state."""
527 528 # read data and parse into blocks
528 529 self.fload()
529 530 lines = self.fobj.readlines()
530 531 src_b = [l for l in lines if l.strip()]
531 532 nblocks = len(src_b)
532 533 self.src = ''.join(lines)
533 534 self._silent = [False]*nblocks
534 535 self._auto = [True]*nblocks
535 536 self.auto_all = True
536 537 self.nblocks = nblocks
537 538 self.src_blocks = src_b
538 539
539 540 # also build syntax-highlighted source
540 541 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
541 542
542 543 # ensure clean namespace and seek offset
543 544 self.reset()
544 545
545 546
546 547 class IPythonLineDemo(IPythonDemo,LineDemo):
547 548 """Variant of the LineDemo class whose input is processed by IPython."""
548 549 pass
549 550
550 551
551 552 class ClearMixin(object):
552 553 """Use this mixin to make Demo classes with less visual clutter.
553 554
554 555 Demos using this mixin will clear the screen before every block and use
555 556 blank marquees.
556 557
557 558 Note that in order for the methods defined here to actually override those
558 559 of the classes it's mixed with, it must go /first/ in the inheritance
559 560 tree. For example:
560 561
561 562 class ClearIPDemo(ClearMixin,IPythonDemo): pass
562 563
563 564 will provide an IPythonDemo class with the mixin's features.
564 565 """
565 566
566 567 def marquee(self,txt='',width=78,mark='*'):
567 568 """Blank marquee that returns '' no matter what the input."""
568 569 return ''
569 570
570 571 def pre_cmd(self):
571 572 """Method called before executing each block.
572 573
573 574 This one simply clears the screen."""
574 575 from IPython.utils.terminal import term_clear
575 576 term_clear()
576 577
577 578 class ClearDemo(ClearMixin,Demo):
578 579 pass
579 580
580 581
581 582 class ClearIPDemo(ClearMixin,IPythonDemo):
582 583 pass
@@ -1,123 +1,124 b''
1 1 """ 'editor' hooks for common editors that work well with ipython
2 2
3 3 They should honor the line number argument, at least.
4 4
5 5 Contributions are *very* welcome.
6 6 """
7 7 from __future__ import print_function
8 8
9 9 import os
10 10 import pipes
11 11 import subprocess
12 12
13 13 from IPython import get_ipython
14 14 from IPython.core.error import TryNext
15 from IPython.utils import py3compat
15 16
16 17
17 18 def install_editor(template, wait=False):
18 19 """Installs the editor that is called by IPython for the %edit magic.
19 20
20 21 This overrides the default editor, which is generally set by your EDITOR
21 22 environment variable or is notepad (windows) or vi (linux). By supplying a
22 23 template string `run_template`, you can control how the editor is invoked
23 24 by IPython -- (e.g. the format in which it accepts command line options)
24 25
25 26 Parameters
26 27 ----------
27 28 template : basestring
28 29 run_template acts as a template for how your editor is invoked by
29 30 the shell. It should contain '{filename}', which will be replaced on
30 31 invokation with the file name, and '{line}', $line by line number
31 32 (or 0) to invoke the file with.
32 33 wait : bool
33 34 If `wait` is true, wait until the user presses enter before returning,
34 35 to facilitate non-blocking editors that exit immediately after
35 36 the call.
36 37 """
37 38
38 39 # not all editors support $line, so we'll leave out this check
39 40 # for substitution in ['$file', '$line']:
40 41 # if not substitution in run_template:
41 42 # raise ValueError(('run_template should contain %s'
42 43 # ' for string substitution. You supplied "%s"' % (substitution,
43 44 # run_template)))
44 45
45 46 def call_editor(self, filename, line=0):
46 47 if line is None:
47 48 line = 0
48 49 cmd = template.format(filename=pipes.quote(filename), line=line)
49 50 print(">", cmd)
50 51 proc = subprocess.Popen(cmd, shell=True)
51 52 if wait and proc.wait() != 0:
52 53 raise TryNext()
53 54 if wait:
54 raw_input("Press Enter when done editing:")
55 py3compat.input("Press Enter when done editing:")
55 56
56 57 get_ipython().set_hook('editor', call_editor)
57 58 get_ipython().editor = template
58 59
59 60
60 61 # in these, exe is always the path/name of the executable. Useful
61 62 # if you don't have the editor directory in your path
62 63 def komodo(exe=u'komodo'):
63 64 """ Activestate Komodo [Edit] """
64 65 install_editor(exe + u' -l {line} {filename}', wait=True)
65 66
66 67
67 68 def scite(exe=u"scite"):
68 69 """ SciTE or Sc1 """
69 70 install_editor(exe + u' {filename} -goto:{line}')
70 71
71 72
72 73 def notepadplusplus(exe=u'notepad++'):
73 74 """ Notepad++ http://notepad-plus.sourceforge.net """
74 75 install_editor(exe + u' -n{line} {filename}')
75 76
76 77
77 78 def jed(exe=u'jed'):
78 79 """ JED, the lightweight emacsish editor """
79 80 install_editor(exe + u' +{line} {filename}')
80 81
81 82
82 83 def idle(exe=u'idle'):
83 84 """ Idle, the editor bundled with python
84 85
85 86 Parameters
86 87 ----------
87 88 exe : str, None
88 89 If none, should be pretty smart about finding the executable.
89 90 """
90 91 if exe is None:
91 92 import idlelib
92 93 p = os.path.dirname(idlelib.__filename__)
93 94 # i'm not sure if this actually works. Is this idle.py script
94 95 # guarenteed to be executable?
95 96 exe = os.path.join(p, 'idle.py')
96 97 install_editor(exe + u' {filename}')
97 98
98 99
99 100 def mate(exe=u'mate'):
100 101 """ TextMate, the missing editor"""
101 102 # wait=True is not required since we're using the -w flag to mate
102 103 install_editor(exe + u' -w -l {line} {filename}')
103 104
104 105
105 106 # ##########################################
106 107 # these are untested, report any problems
107 108 # ##########################################
108 109
109 110
110 111 def emacs(exe=u'emacs'):
111 112 install_editor(exe + u' +{line} {filename}')
112 113
113 114
114 115 def gnuclient(exe=u'gnuclient'):
115 116 install_editor(exe + u' -nw +{line} {filename}')
116 117
117 118
118 119 def crimson_editor(exe=u'cedt.exe'):
119 120 install_editor(exe + u' /L:{line} {filename}')
120 121
121 122
122 123 def kate(exe=u'kate'):
123 124 install_editor(exe + u' -u -l {line} {filename}')
@@ -1,492 +1,492 b''
1 1 # -*- coding: utf-8 -*-
2 2 """terminal client to the IPython kernel
3 3
4 4 """
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2013 The IPython Development Team
7 7 #
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING, distributed as part of this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15 from __future__ import print_function
16 16
17 17 import bdb
18 18 import signal
19 19 import os
20 20 import sys
21 21 import time
22 22 import subprocess
23 23 from io import BytesIO
24 24 import base64
25 25
26 26 try:
27 27 from queue import Empty # Py 3
28 28 except ImportError:
29 29 from Queue import Empty # Py 2
30 30
31 31 from IPython.core import page
32 32 from IPython.utils.warn import warn, error
33 33 from IPython.utils import io
34 from IPython.utils.py3compat import string_types
34 from IPython.utils.py3compat import string_types, input
35 35 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode, Float
36 36 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
37 37
38 38 from IPython.terminal.interactiveshell import TerminalInteractiveShell
39 39 from IPython.terminal.console.completer import ZMQCompleter
40 40
41 41
42 42 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
43 43 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
44 44 _executing = False
45 45 _execution_state = Unicode('')
46 46 kernel_timeout = Float(60, config=True,
47 47 help="""Timeout for giving up on a kernel (in seconds).
48 48
49 49 On first connect and restart, the console tests whether the
50 50 kernel is running and responsive by sending kernel_info_requests.
51 51 This sets the timeout in seconds for how long the kernel can take
52 52 before being presumed dead.
53 53 """
54 54 )
55 55
56 56 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
57 57 config=True, help=
58 58 """
59 59 Handler for image type output. This is useful, for example,
60 60 when connecting to the kernel in which pylab inline backend is
61 61 activated. There are four handlers defined. 'PIL': Use
62 62 Python Imaging Library to popup image; 'stream': Use an
63 63 external program to show the image. Image will be fed into
64 64 the STDIN of the program. You will need to configure
65 65 `stream_image_handler`; 'tempfile': Use an external program to
66 66 show the image. Image will be saved in a temporally file and
67 67 the program is called with the temporally file. You will need
68 68 to configure `tempfile_image_handler`; 'callable': You can set
69 69 any Python callable which is called with the image data. You
70 70 will need to configure `callable_image_handler`.
71 71 """
72 72 )
73 73
74 74 stream_image_handler = List(config=True, help=
75 75 """
76 76 Command to invoke an image viewer program when you are using
77 77 'stream' image handler. This option is a list of string where
78 78 the first element is the command itself and reminders are the
79 79 options for the command. Raw image data is given as STDIN to
80 80 the program.
81 81 """
82 82 )
83 83
84 84 tempfile_image_handler = List(config=True, help=
85 85 """
86 86 Command to invoke an image viewer program when you are using
87 87 'tempfile' image handler. This option is a list of string
88 88 where the first element is the command itself and reminders
89 89 are the options for the command. You can use {file} and
90 90 {format} in the string to represent the location of the
91 91 generated image file and image format.
92 92 """
93 93 )
94 94
95 95 callable_image_handler = Any(config=True, help=
96 96 """
97 97 Callable object called via 'callable' image handler with one
98 98 argument, `data`, which is `msg["content"]["data"]` where
99 99 `msg` is the message from iopub channel. For exmaple, you can
100 100 find base64 encoded PNG data as `data['image/png']`.
101 101 """
102 102 )
103 103
104 104 mime_preference = List(
105 105 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
106 106 config=True, allow_none=False, help=
107 107 """
108 108 Preferred object representation MIME type in order. First
109 109 matched MIME type will be used.
110 110 """
111 111 )
112 112
113 113 manager = Instance('IPython.kernel.KernelManager')
114 114 client = Instance('IPython.kernel.KernelClient')
115 115 def _client_changed(self, name, old, new):
116 116 self.session_id = new.session.session
117 117 session_id = Unicode()
118 118
119 119 def init_completer(self):
120 120 """Initialize the completion machinery.
121 121
122 122 This creates completion machinery that can be used by client code,
123 123 either interactively in-process (typically triggered by the readline
124 124 library), programatically (such as in test suites) or out-of-prcess
125 125 (typically over the network by remote frontends).
126 126 """
127 127 from IPython.core.completerlib import (module_completer,
128 128 magic_run_completer, cd_completer)
129 129
130 130 self.Completer = ZMQCompleter(self, self.client, config=self.config)
131 131
132 132
133 133 self.set_hook('complete_command', module_completer, str_key = 'import')
134 134 self.set_hook('complete_command', module_completer, str_key = 'from')
135 135 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
136 136 self.set_hook('complete_command', cd_completer, str_key = '%cd')
137 137
138 138 # Only configure readline if we truly are using readline. IPython can
139 139 # do tab-completion over the network, in GUIs, etc, where readline
140 140 # itself may be absent
141 141 if self.has_readline:
142 142 self.set_readline_completer()
143 143
144 144 def run_cell(self, cell, store_history=True):
145 145 """Run a complete IPython cell.
146 146
147 147 Parameters
148 148 ----------
149 149 cell : str
150 150 The code (including IPython code such as %magic functions) to run.
151 151 store_history : bool
152 152 If True, the raw and translated cell will be stored in IPython's
153 153 history. For user code calling back into IPython's machinery, this
154 154 should be set to False.
155 155 """
156 156 if (not cell) or cell.isspace():
157 157 return
158 158
159 159 if cell.strip() == 'exit':
160 160 # explicitly handle 'exit' command
161 161 return self.ask_exit()
162 162
163 163 # flush stale replies, which could have been ignored, due to missed heartbeats
164 164 while self.client.shell_channel.msg_ready():
165 165 self.client.shell_channel.get_msg()
166 166 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
167 167 msg_id = self.client.shell_channel.execute(cell, not store_history)
168 168
169 169 # first thing is wait for any side effects (output, stdin, etc.)
170 170 self._executing = True
171 171 self._execution_state = "busy"
172 172 while self._execution_state != 'idle' and self.client.is_alive():
173 173 try:
174 174 self.handle_stdin_request(msg_id, timeout=0.05)
175 175 except Empty:
176 176 # display intermediate print statements, etc.
177 177 self.handle_iopub(msg_id)
178 178 pass
179 179
180 180 # after all of that is done, wait for the execute reply
181 181 while self.client.is_alive():
182 182 try:
183 183 self.handle_execute_reply(msg_id, timeout=0.05)
184 184 except Empty:
185 185 pass
186 186 else:
187 187 break
188 188 self._executing = False
189 189
190 190 #-----------------
191 191 # message handlers
192 192 #-----------------
193 193
194 194 def handle_execute_reply(self, msg_id, timeout=None):
195 195 msg = self.client.shell_channel.get_msg(block=False, timeout=timeout)
196 196 if msg["parent_header"].get("msg_id", None) == msg_id:
197 197
198 198 self.handle_iopub(msg_id)
199 199
200 200 content = msg["content"]
201 201 status = content['status']
202 202
203 203 if status == 'aborted':
204 204 self.write('Aborted\n')
205 205 return
206 206 elif status == 'ok':
207 207 # print execution payloads as well:
208 208 for item in content["payload"]:
209 209 text = item.get('text', None)
210 210 if text:
211 211 page.page(text)
212 212
213 213 elif status == 'error':
214 214 for frame in content["traceback"]:
215 215 print(frame, file=io.stderr)
216 216
217 217 self.execution_count = int(content["execution_count"] + 1)
218 218
219 219
220 220 def handle_iopub(self, msg_id):
221 221 """ Method to process subscribe channel's messages
222 222
223 223 This method consumes and processes messages on the IOPub channel,
224 224 such as stdout, stderr, pyout and status.
225 225
226 226 It only displays output that is caused by the given msg_id
227 227 """
228 228 while self.client.iopub_channel.msg_ready():
229 229 sub_msg = self.client.iopub_channel.get_msg()
230 230 msg_type = sub_msg['header']['msg_type']
231 231 parent = sub_msg["parent_header"]
232 232 if (not parent) or msg_id == parent['msg_id']:
233 233 if msg_type == 'status':
234 234 state = self._execution_state = sub_msg["content"]["execution_state"]
235 235 # idle messages mean an individual sequence is complete,
236 236 # so break out of consumption to allow other things to take over.
237 237 if state == 'idle':
238 238 break
239 239
240 240 elif msg_type == 'stream':
241 241 if sub_msg["content"]["name"] == "stdout":
242 242 print(sub_msg["content"]["data"], file=io.stdout, end="")
243 243 io.stdout.flush()
244 244 elif sub_msg["content"]["name"] == "stderr" :
245 245 print(sub_msg["content"]["data"], file=io.stderr, end="")
246 246 io.stderr.flush()
247 247
248 248 elif msg_type == 'pyout':
249 249 self.execution_count = int(sub_msg["content"]["execution_count"])
250 250 format_dict = sub_msg["content"]["data"]
251 251 self.handle_rich_data(format_dict)
252 252 # taken from DisplayHook.__call__:
253 253 hook = self.displayhook
254 254 hook.start_displayhook()
255 255 hook.write_output_prompt()
256 256 hook.write_format_data(format_dict)
257 257 hook.log_output(format_dict)
258 258 hook.finish_displayhook()
259 259
260 260 elif msg_type == 'display_data':
261 261 self.handle_rich_data(sub_msg["content"]["data"])
262 262
263 263
264 264 _imagemime = {
265 265 'image/png': 'png',
266 266 'image/jpeg': 'jpeg',
267 267 'image/svg+xml': 'svg',
268 268 }
269 269
270 270 def handle_rich_data(self, data):
271 271 for mime in self.mime_preference:
272 272 if mime in data and mime in self._imagemime:
273 273 self.handle_image(data, mime)
274 274 return
275 275
276 276 def handle_image(self, data, mime):
277 277 handler = getattr(
278 278 self, 'handle_image_{0}'.format(self.image_handler), None)
279 279 if handler:
280 280 handler(data, mime)
281 281
282 282 def handle_image_PIL(self, data, mime):
283 283 if mime not in ('image/png', 'image/jpeg'):
284 284 return
285 285 import PIL.Image
286 286 raw = base64.decodestring(data[mime].encode('ascii'))
287 287 img = PIL.Image.open(BytesIO(raw))
288 288 img.show()
289 289
290 290 def handle_image_stream(self, data, mime):
291 291 raw = base64.decodestring(data[mime].encode('ascii'))
292 292 imageformat = self._imagemime[mime]
293 293 fmt = dict(format=imageformat)
294 294 args = [s.format(**fmt) for s in self.stream_image_handler]
295 295 with open(os.devnull, 'w') as devnull:
296 296 proc = subprocess.Popen(
297 297 args, stdin=subprocess.PIPE,
298 298 stdout=devnull, stderr=devnull)
299 299 proc.communicate(raw)
300 300
301 301 def handle_image_tempfile(self, data, mime):
302 302 raw = base64.decodestring(data[mime].encode('ascii'))
303 303 imageformat = self._imagemime[mime]
304 304 filename = 'tmp.{0}'.format(imageformat)
305 305 with NamedFileInTemporaryDirectory(filename) as f, \
306 306 open(os.devnull, 'w') as devnull:
307 307 f.write(raw)
308 308 f.flush()
309 309 fmt = dict(file=f.name, format=imageformat)
310 310 args = [s.format(**fmt) for s in self.tempfile_image_handler]
311 311 subprocess.call(args, stdout=devnull, stderr=devnull)
312 312
313 313 def handle_image_callable(self, data, mime):
314 314 self.callable_image_handler(data)
315 315
316 316 def handle_stdin_request(self, msg_id, timeout=0.1):
317 317 """ Method to capture raw_input
318 318 """
319 319 msg_rep = self.client.stdin_channel.get_msg(timeout=timeout)
320 320 # in case any iopub came while we were waiting:
321 321 self.handle_iopub(msg_id)
322 322 if msg_id == msg_rep["parent_header"].get("msg_id"):
323 323 # wrap SIGINT handler
324 324 real_handler = signal.getsignal(signal.SIGINT)
325 325 def double_int(sig,frame):
326 326 # call real handler (forwards sigint to kernel),
327 327 # then raise local interrupt, stopping local raw_input
328 328 real_handler(sig,frame)
329 329 raise KeyboardInterrupt
330 330 signal.signal(signal.SIGINT, double_int)
331 331
332 332 try:
333 raw_data = raw_input(msg_rep["content"]["prompt"])
333 raw_data = input(msg_rep["content"]["prompt"])
334 334 except EOFError:
335 335 # turn EOFError into EOF character
336 336 raw_data = '\x04'
337 337 except KeyboardInterrupt:
338 338 sys.stdout.write('\n')
339 339 return
340 340 finally:
341 341 # restore SIGINT handler
342 342 signal.signal(signal.SIGINT, real_handler)
343 343
344 344 # only send stdin reply if there *was not* another request
345 345 # or execution finished while we were reading.
346 346 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
347 347 self.client.stdin_channel.input(raw_data)
348 348
349 349 def mainloop(self, display_banner=False):
350 350 while True:
351 351 try:
352 352 self.interact(display_banner=display_banner)
353 353 #self.interact_with_readline()
354 354 # XXX for testing of a readline-decoupled repl loop, call
355 355 # interact_with_readline above
356 356 break
357 357 except KeyboardInterrupt:
358 358 # this should not be necessary, but KeyboardInterrupt
359 359 # handling seems rather unpredictable...
360 360 self.write("\nKeyboardInterrupt in interact()\n")
361 361
362 362 def wait_for_kernel(self, timeout=None):
363 363 """method to wait for a kernel to be ready"""
364 364 tic = time.time()
365 365 self.client.hb_channel.unpause()
366 366 while True:
367 367 msg_id = self.client.kernel_info()
368 368 reply = None
369 369 while True:
370 370 try:
371 371 reply = self.client.get_shell_msg(timeout=1)
372 372 except Empty:
373 373 break
374 374 else:
375 375 if reply['parent_header'].get('msg_id') == msg_id:
376 376 return True
377 377 if timeout is not None \
378 378 and (time.time() - tic) > timeout \
379 379 and not self.client.hb_channel.is_beating():
380 380 # heart failed
381 381 return False
382 382 return True
383 383
384 384 def interact(self, display_banner=None):
385 385 """Closely emulate the interactive Python console."""
386 386
387 387 # batch run -> do not interact
388 388 if self.exit_now:
389 389 return
390 390
391 391 if display_banner is None:
392 392 display_banner = self.display_banner
393 393
394 394 if isinstance(display_banner, string_types):
395 395 self.show_banner(display_banner)
396 396 elif display_banner:
397 397 self.show_banner()
398 398
399 399 more = False
400 400
401 401 # run a non-empty no-op, so that we don't get a prompt until
402 402 # we know the kernel is ready. This keeps the connection
403 403 # message above the first prompt.
404 404 if not self.wait_for_kernel(self.kernel_timeout):
405 405 error("Kernel did not respond\n")
406 406 return
407 407
408 408 if self.has_readline:
409 409 self.readline_startup_hook(self.pre_readline)
410 410 hlen_b4_cell = self.readline.get_current_history_length()
411 411 else:
412 412 hlen_b4_cell = 0
413 413 # exit_now is set by a call to %Exit or %Quit, through the
414 414 # ask_exit callback.
415 415
416 416 while not self.exit_now:
417 417 if not self.client.is_alive():
418 418 # kernel died, prompt for action or exit
419 419
420 420 action = "restart" if self.manager else "wait for restart"
421 421 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
422 422 if ans:
423 423 if self.manager:
424 424 self.manager.restart_kernel(True)
425 425 self.wait_for_kernel(self.kernel_timeout)
426 426 else:
427 427 self.exit_now = True
428 428 continue
429 429 try:
430 430 # protect prompt block from KeyboardInterrupt
431 431 # when sitting on ctrl-C
432 432 self.hooks.pre_prompt_hook()
433 433 if more:
434 434 try:
435 435 prompt = self.prompt_manager.render('in2')
436 436 except Exception:
437 437 self.showtraceback()
438 438 if self.autoindent:
439 439 self.rl_do_indent = True
440 440
441 441 else:
442 442 try:
443 443 prompt = self.separate_in + self.prompt_manager.render('in')
444 444 except Exception:
445 445 self.showtraceback()
446 446
447 447 line = self.raw_input(prompt)
448 448 if self.exit_now:
449 449 # quick exit on sys.std[in|out] close
450 450 break
451 451 if self.autoindent:
452 452 self.rl_do_indent = False
453 453
454 454 except KeyboardInterrupt:
455 455 #double-guard against keyboardinterrupts during kbdint handling
456 456 try:
457 457 self.write('\nKeyboardInterrupt\n')
458 458 source_raw = self.input_splitter.source_raw_reset()[1]
459 459 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
460 460 more = False
461 461 except KeyboardInterrupt:
462 462 pass
463 463 except EOFError:
464 464 if self.autoindent:
465 465 self.rl_do_indent = False
466 466 if self.has_readline:
467 467 self.readline_startup_hook(None)
468 468 self.write('\n')
469 469 self.exit()
470 470 except bdb.BdbQuit:
471 471 warn('The Python debugger has exited with a BdbQuit exception.\n'
472 472 'Because of how pdb handles the stack, it is impossible\n'
473 473 'for IPython to properly format this particular exception.\n'
474 474 'IPython will resume normal operation.')
475 475 except:
476 476 # exceptions here are VERY RARE, but they can be triggered
477 477 # asynchronously by signal handlers, for example.
478 478 self.showtraceback()
479 479 else:
480 480 self.input_splitter.push(line)
481 481 more = self.input_splitter.push_accepts_more()
482 482 if (self.SyntaxTB.last_syntax_error and
483 483 self.autoedit_syntax):
484 484 self.edit_syntax_error()
485 485 if not more:
486 486 source_raw = self.input_splitter.source_raw_reset()[1]
487 487 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
488 488 self.run_cell(source_raw)
489 489
490 490
491 491 # Turn off the exit flag, so the mainloop can be restarted if desired
492 492 self.exit_now = False
@@ -1,229 +1,229 b''
1 1 # encoding: utf-8
2 2 """
3 3 IO related utilities.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12 from __future__ import print_function
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 import os
18 18 import sys
19 19 import tempfile
20 20 from .capture import CapturedIO, capture_output
21 from .py3compat import string_types
21 from .py3compat import string_types, input
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Code
25 25 #-----------------------------------------------------------------------------
26 26
27 27
28 28 class IOStream:
29 29
30 30 def __init__(self,stream, fallback=None):
31 31 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
32 32 if fallback is not None:
33 33 stream = fallback
34 34 else:
35 35 raise ValueError("fallback required, but not specified")
36 36 self.stream = stream
37 37 self._swrite = stream.write
38 38
39 39 # clone all methods not overridden:
40 40 def clone(meth):
41 41 return not hasattr(self, meth) and not meth.startswith('_')
42 42 for meth in filter(clone, dir(stream)):
43 43 setattr(self, meth, getattr(stream, meth))
44 44
45 45 def write(self,data):
46 46 try:
47 47 self._swrite(data)
48 48 except:
49 49 try:
50 50 # print handles some unicode issues which may trip a plain
51 51 # write() call. Emulate write() by using an empty end
52 52 # argument.
53 53 print(data, end='', file=self.stream)
54 54 except:
55 55 # if we get here, something is seriously broken.
56 56 print('ERROR - failed to write data to stream:', self.stream,
57 57 file=sys.stderr)
58 58
59 59 def writelines(self, lines):
60 60 if isinstance(lines, string_types):
61 61 lines = [lines]
62 62 for line in lines:
63 63 self.write(line)
64 64
65 65 # This class used to have a writeln method, but regular files and streams
66 66 # in Python don't have this method. We need to keep this completely
67 67 # compatible so we removed it.
68 68
69 69 @property
70 70 def closed(self):
71 71 return self.stream.closed
72 72
73 73 def close(self):
74 74 pass
75 75
76 76 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
77 77 devnull = open(os.devnull, 'a')
78 78 stdin = IOStream(sys.stdin, fallback=devnull)
79 79 stdout = IOStream(sys.stdout, fallback=devnull)
80 80 stderr = IOStream(sys.stderr, fallback=devnull)
81 81
82 82 class IOTerm:
83 83 """ Term holds the file or file-like objects for handling I/O operations.
84 84
85 85 These are normally just sys.stdin, sys.stdout and sys.stderr but for
86 86 Windows they can can replaced to allow editing the strings before they are
87 87 displayed."""
88 88
89 89 # In the future, having IPython channel all its I/O operations through
90 90 # this class will make it easier to embed it into other environments which
91 91 # are not a normal terminal (such as a GUI-based shell)
92 92 def __init__(self, stdin=None, stdout=None, stderr=None):
93 93 mymodule = sys.modules[__name__]
94 94 self.stdin = IOStream(stdin, mymodule.stdin)
95 95 self.stdout = IOStream(stdout, mymodule.stdout)
96 96 self.stderr = IOStream(stderr, mymodule.stderr)
97 97
98 98
99 99 class Tee(object):
100 100 """A class to duplicate an output stream to stdout/err.
101 101
102 102 This works in a manner very similar to the Unix 'tee' command.
103 103
104 104 When the object is closed or deleted, it closes the original file given to
105 105 it for duplication.
106 106 """
107 107 # Inspired by:
108 108 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
109 109
110 110 def __init__(self, file_or_name, mode="w", channel='stdout'):
111 111 """Construct a new Tee object.
112 112
113 113 Parameters
114 114 ----------
115 115 file_or_name : filename or open filehandle (writable)
116 116 File that will be duplicated
117 117
118 118 mode : optional, valid mode for open().
119 119 If a filename was give, open with this mode.
120 120
121 121 channel : str, one of ['stdout', 'stderr']
122 122 """
123 123 if channel not in ['stdout', 'stderr']:
124 124 raise ValueError('Invalid channel spec %s' % channel)
125 125
126 126 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
127 127 self.file = file_or_name
128 128 else:
129 129 self.file = open(file_or_name, mode)
130 130 self.channel = channel
131 131 self.ostream = getattr(sys, channel)
132 132 setattr(sys, channel, self)
133 133 self._closed = False
134 134
135 135 def close(self):
136 136 """Close the file and restore the channel."""
137 137 self.flush()
138 138 setattr(sys, self.channel, self.ostream)
139 139 self.file.close()
140 140 self._closed = True
141 141
142 142 def write(self, data):
143 143 """Write data to both channels."""
144 144 self.file.write(data)
145 145 self.ostream.write(data)
146 146 self.ostream.flush()
147 147
148 148 def flush(self):
149 149 """Flush both channels."""
150 150 self.file.flush()
151 151 self.ostream.flush()
152 152
153 153 def __del__(self):
154 154 if not self._closed:
155 155 self.close()
156 156
157 157
158 158 def ask_yes_no(prompt,default=None):
159 159 """Asks a question and returns a boolean (y/n) answer.
160 160
161 161 If default is given (one of 'y','n'), it is used if the user input is
162 162 empty. Otherwise the question is repeated until an answer is given.
163 163
164 164 An EOF is treated as the default answer. If there is no default, an
165 165 exception is raised to prevent infinite loops.
166 166
167 167 Valid answers are: y/yes/n/no (match is not case sensitive)."""
168 168
169 169 answers = {'y':True,'n':False,'yes':True,'no':False}
170 170 ans = None
171 171 while ans not in answers.keys():
172 172 try:
173 ans = raw_input(prompt+' ').lower()
173 ans = input(prompt+' ').lower()
174 174 if not ans: # response was an empty string
175 175 ans = default
176 176 except KeyboardInterrupt:
177 177 pass
178 178 except EOFError:
179 179 if default in answers.keys():
180 180 ans = default
181 181 print()
182 182 else:
183 183 raise
184 184
185 185 return answers[ans]
186 186
187 187
188 188 def temp_pyfile(src, ext='.py'):
189 189 """Make a temporary python file, return filename and filehandle.
190 190
191 191 Parameters
192 192 ----------
193 193 src : string or list of strings (no need for ending newlines if list)
194 194 Source code to be written to the file.
195 195
196 196 ext : optional, string
197 197 Extension for the generated file.
198 198
199 199 Returns
200 200 -------
201 201 (filename, open filehandle)
202 202 It is the caller's responsibility to close the open file and unlink it.
203 203 """
204 204 fname = tempfile.mkstemp(ext)[1]
205 205 f = open(fname,'w')
206 206 f.write(src)
207 207 f.flush()
208 208 return fname, f
209 209
210 210
211 211 def raw_print(*args, **kw):
212 212 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
213 213
214 214 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
215 215 file=sys.__stdout__)
216 216 sys.__stdout__.flush()
217 217
218 218
219 219 def raw_print_err(*args, **kw):
220 220 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
221 221
222 222 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
223 223 file=sys.__stderr__)
224 224 sys.__stderr__.flush()
225 225
226 226
227 227 # Short aliases for quick debugging, do NOT use these in production code.
228 228 rprint = raw_print
229 229 rprinte = raw_print_err
General Comments 0
You need to be logged in to leave comments. Login now