##// END OF EJS Templates
Update irunner to work in Python 3.
Thomas Kluyver -
Show More
@@ -1,440 +1,442 b''
1 1 #!/usr/bin/env python
2 2 """Module for interactively running scripts.
3 3
4 4 This module implements classes for interactively running scripts written for
5 5 any system with a prompt which can be matched by a regexp suitable for
6 6 pexpect. It can be used to run as if they had been typed up interactively, an
7 7 arbitrary series of commands for the target system.
8 8
9 9 The module includes classes ready for IPython (with the default prompts),
10 10 plain Python and SAGE, but making a new one is trivial. To see how to use it,
11 11 simply run the module as a script:
12 12
13 13 ./irunner.py --help
14 14
15 15
16 16 This is an extension of Ken Schutte <kschutte-AT-csail.mit.edu>'s script
17 17 contributed on the ipython-user list:
18 18
19 19 http://mail.scipy.org/pipermail/ipython-user/2006-May/003539.html
20 20
21 21
22 22 NOTES:
23 23
24 24 - This module requires pexpect, available in most linux distros, or which can
25 25 be downloaded from
26 26
27 27 http://pexpect.sourceforge.net
28 28
29 29 - Because pexpect only works under Unix or Windows-Cygwin, this has the same
30 30 limitations. This means that it will NOT work under native windows Python.
31 31 """
32 32
33 33 # Stdlib imports
34 34 import optparse
35 35 import os
36 36 import sys
37 37
38 38 # Third-party modules: we carry a copy of pexpect to reduce the need for
39 39 # external dependencies, but our import checks for a system version first.
40 40 from IPython.external import pexpect
41 from IPython.utils import py3compat
41 42
42 43 # Global usage strings, to avoid indentation issues when typing it below.
43 44 USAGE = """
44 45 Interactive script runner, type: %s
45 46
46 47 runner [opts] script_name
47 48 """
48 49
49 50 def pexpect_monkeypatch():
50 51 """Patch pexpect to prevent unhandled exceptions at VM teardown.
51 52
52 53 Calling this function will monkeypatch the pexpect.spawn class and modify
53 54 its __del__ method to make it more robust in the face of failures that can
54 55 occur if it is called when the Python VM is shutting down.
55 56
56 57 Since Python may fire __del__ methods arbitrarily late, it's possible for
57 58 them to execute during the teardown of the Python VM itself. At this
58 59 point, various builtin modules have been reset to None. Thus, the call to
59 60 self.close() will trigger an exception because it tries to call os.close(),
60 61 and os is now None.
61 62 """
62 63
63 64 if pexpect.__version__[:3] >= '2.2':
64 65 # No need to patch, fix is already the upstream version.
65 66 return
66 67
67 68 def __del__(self):
68 69 """This makes sure that no system resources are left open.
69 70 Python only garbage collects Python objects. OS file descriptors
70 71 are not Python objects, so they must be handled explicitly.
71 72 If the child file descriptor was opened outside of this class
72 73 (passed to the constructor) then this does not close it.
73 74 """
74 75 if not self.closed:
75 76 try:
76 77 self.close()
77 78 except AttributeError:
78 79 pass
79 80
80 81 pexpect.spawn.__del__ = __del__
81 82
82 83 pexpect_monkeypatch()
83 84
84 85 # The generic runner class
85 86 class InteractiveRunner(object):
86 87 """Class to run a sequence of commands through an interactive program."""
87 88
88 89 def __init__(self,program,prompts,args=None,out=sys.stdout,echo=True):
89 90 """Construct a runner.
90 91
91 92 Inputs:
92 93
93 94 - program: command to execute the given program.
94 95
95 96 - prompts: a list of patterns to match as valid prompts, in the
96 97 format used by pexpect. This basically means that it can be either
97 98 a string (to be compiled as a regular expression) or a list of such
98 99 (it must be a true list, as pexpect does type checks).
99 100
100 101 If more than one prompt is given, the first is treated as the main
101 102 program prompt and the others as 'continuation' prompts, like
102 103 python's. This means that blank lines in the input source are
103 104 ommitted when the first prompt is matched, but are NOT ommitted when
104 105 the continuation one matches, since this is how python signals the
105 106 end of multiline input interactively.
106 107
107 108 Optional inputs:
108 109
109 110 - args(None): optional list of strings to pass as arguments to the
110 111 child program.
111 112
112 113 - out(sys.stdout): if given, an output stream to be used when writing
113 114 output. The only requirement is that it must have a .write() method.
114 115
115 116 Public members not parameterized in the constructor:
116 117
117 118 - delaybeforesend(0): Newer versions of pexpect have a delay before
118 119 sending each new input. For our purposes here, it's typically best
119 120 to just set this to zero, but if you encounter reliability problems
120 121 or want an interactive run to pause briefly at each prompt, just
121 122 increase this value (it is measured in seconds). Note that this
122 123 variable is not honored at all by older versions of pexpect.
123 124 """
124 125
125 126 self.program = program
126 127 self.prompts = prompts
127 128 if args is None: args = []
128 129 self.args = args
129 130 self.out = out
130 131 self.echo = echo
131 132 # Other public members which we don't make as parameters, but which
132 133 # users may occasionally want to tweak
133 134 self.delaybeforesend = 0
134 135
135 136 # Create child process and hold on to it so we don't have to re-create
136 137 # for every single execution call
137 138 c = self.child = pexpect.spawn(self.program,self.args,timeout=None)
138 139 c.delaybeforesend = self.delaybeforesend
139 140 # pexpect hard-codes the terminal size as (24,80) (rows,columns).
140 141 # This causes problems because any line longer than 80 characters gets
141 142 # completely overwrapped on the printed outptut (even though
142 143 # internally the code runs fine). We reset this to 99 rows X 200
143 144 # columns (arbitrarily chosen), which should avoid problems in all
144 145 # reasonable cases.
145 146 c.setwinsize(99,200)
146 147
147 148 def close(self):
148 149 """close child process"""
149 150
150 151 self.child.close()
151 152
152 153 def run_file(self,fname,interact=False,get_output=False):
153 154 """Run the given file interactively.
154 155
155 156 Inputs:
156 157
157 158 -fname: name of the file to execute.
158 159
159 160 See the run_source docstring for the meaning of the optional
160 161 arguments."""
161 162
162 163 fobj = open(fname,'r')
163 164 try:
164 165 out = self.run_source(fobj,interact,get_output)
165 166 finally:
166 167 fobj.close()
167 168 if get_output:
168 169 return out
169 170
170 171 def run_source(self,source,interact=False,get_output=False):
171 172 """Run the given source code interactively.
172 173
173 174 Inputs:
174 175
175 176 - source: a string of code to be executed, or an open file object we
176 177 can iterate over.
177 178
178 179 Optional inputs:
179 180
180 181 - interact(False): if true, start to interact with the running
181 182 program at the end of the script. Otherwise, just exit.
182 183
183 184 - get_output(False): if true, capture the output of the child process
184 185 (filtering the input commands out) and return it as a string.
185 186
186 187 Returns:
187 188 A string containing the process output, but only if requested.
188 189 """
189 190
190 191 # if the source is a string, chop it up in lines so we can iterate
191 192 # over it just as if it were an open file.
192 193 if isinstance(source, basestring):
193 194 source = source.splitlines(True)
194 195
195 196 if self.echo:
196 197 # normalize all strings we write to use the native OS line
197 198 # separators.
198 199 linesep = os.linesep
199 200 stdwrite = self.out.write
200 201 write = lambda s: stdwrite(s.replace('\r\n',linesep))
201 202 else:
202 203 # Quiet mode, all writes are no-ops
203 204 write = lambda s: None
204 205
205 206 c = self.child
206 207 prompts = c.compile_pattern_list(self.prompts)
207 208 prompt_idx = c.expect_list(prompts)
208 209
209 210 # Flag whether the script ends normally or not, to know whether we can
210 211 # do anything further with the underlying process.
211 212 end_normal = True
212 213
213 214 # If the output was requested, store it in a list for return at the end
214 215 if get_output:
215 216 output = []
216 217 store_output = output.append
217 218
218 219 for cmd in source:
219 220 # skip blank lines for all matches to the 'main' prompt, while the
220 221 # secondary prompts do not
221 222 if prompt_idx==0 and \
222 223 (cmd.isspace() or cmd.lstrip().startswith('#')):
223 224 write(cmd)
224 225 continue
225 226
226 227 # write('AFTER: '+c.after) # dbg
227 228 write(c.after)
228 229 c.send(cmd)
229 230 try:
230 231 prompt_idx = c.expect_list(prompts)
231 232 except pexpect.EOF:
232 233 # this will happen if the child dies unexpectedly
233 234 write(c.before)
234 235 end_normal = False
235 236 break
236 237
237 238 write(c.before)
238 239
239 240 # With an echoing process, the output we get in c.before contains
240 241 # the command sent, a newline, and then the actual process output
241 242 if get_output:
242 243 store_output(c.before[len(cmd+'\n'):])
243 244 #write('CMD: <<%s>>' % cmd) # dbg
244 245 #write('OUTPUT: <<%s>>' % output[-1]) # dbg
245 246
246 247 self.out.flush()
247 248 if end_normal:
248 249 if interact:
249 250 c.send('\n')
250 251 print '<< Starting interactive mode >>',
251 252 try:
252 253 c.interact()
253 254 except OSError:
254 255 # This is what fires when the child stops. Simply print a
255 256 # newline so the system prompt is aligned. The extra
256 257 # space is there to make sure it gets printed, otherwise
257 258 # OS buffering sometimes just suppresses it.
258 259 write(' \n')
259 260 self.out.flush()
260 261 else:
261 262 if interact:
262 263 e="Further interaction is not possible: child process is dead."
263 264 print >> sys.stderr, e
264 265
265 266 # Leave the child ready for more input later on, otherwise select just
266 267 # hangs on the second invocation.
267 268 if c.isalive():
268 269 c.send('\n')
269 270
270 271 # Return any requested output
271 272 if get_output:
272 273 return ''.join(output)
273 274
274 275 def main(self,argv=None):
275 276 """Run as a command-line script."""
276 277
277 278 parser = optparse.OptionParser(usage=USAGE % self.__class__.__name__)
278 279 newopt = parser.add_option
279 280 newopt('-i','--interact',action='store_true',default=False,
280 281 help='Interact with the program after the script is run.')
281 282
282 283 opts,args = parser.parse_args(argv)
283 284
284 285 if len(args) != 1:
285 286 print >> sys.stderr,"You must supply exactly one file to run."
286 287 sys.exit(1)
287 288
288 289 self.run_file(args[0],opts.interact)
289 290
291 _ipython_cmd = "ipython3" if py3compat.PY3 else "ipython"
290 292
291 293 # Specific runners for particular programs
292 294 class IPythonRunner(InteractiveRunner):
293 295 """Interactive IPython runner.
294 296
295 297 This initalizes IPython in 'nocolor' mode for simplicity. This lets us
296 298 avoid having to write a regexp that matches ANSI sequences, though pexpect
297 299 does support them. If anyone contributes patches for ANSI color support,
298 300 they will be welcome.
299 301
300 302 It also sets the prompts manually, since the prompt regexps for
301 303 pexpect need to be matched to the actual prompts, so user-customized
302 304 prompts would break this.
303 305 """
304 306
305 def __init__(self,program = 'ipython',args=None,out=sys.stdout,echo=True):
307 def __init__(self,program = _ipython_cmd, args=None, out=sys.stdout, echo=True):
306 308 """New runner, optionally passing the ipython command to use."""
307 309 args0 = ['--colors=NoColor',
308 310 '--no-term-title',
309 311 '--no-autoindent',
310 312 # '--quick' is important, to prevent loading default config:
311 313 '--quick']
312 314 if args is None: args = args0
313 315 else: args = args0 + args
314 316 prompts = [r'In \[\d+\]: ',r' \.*: ']
315 317 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
316 318
317 319
318 320 class PythonRunner(InteractiveRunner):
319 321 """Interactive Python runner."""
320 322
321 def __init__(self,program='python',args=None,out=sys.stdout,echo=True):
323 def __init__(self,program=sys.executable, args=None, out=sys.stdout, echo=True):
322 324 """New runner, optionally passing the python command to use."""
323 325
324 326 prompts = [r'>>> ',r'\.\.\. ']
325 327 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
326 328
327 329
328 330 class SAGERunner(InteractiveRunner):
329 331 """Interactive SAGE runner.
330 332
331 333 WARNING: this runner only works if you manually adjust your SAGE
332 334 configuration so that the 'color' option in the configuration file is set to
333 335 'NoColor', because currently the prompt matching regexp does not identify
334 336 color sequences."""
335 337
336 338 def __init__(self,program='sage',args=None,out=sys.stdout,echo=True):
337 339 """New runner, optionally passing the sage command to use."""
338 340
339 341 prompts = ['sage: ',r'\s*\.\.\. ']
340 342 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
341 343
342 344
343 345 class RunnerFactory(object):
344 346 """Code runner factory.
345 347
346 348 This class provides an IPython code runner, but enforces that only one
347 349 runner is ever instantiated. The runner is created based on the extension
348 350 of the first file to run, and it raises an exception if a runner is later
349 351 requested for a different extension type.
350 352
351 353 This ensures that we don't generate example files for doctest with a mix of
352 354 python and ipython syntax.
353 355 """
354 356
355 357 def __init__(self,out=sys.stdout):
356 358 """Instantiate a code runner."""
357 359
358 360 self.out = out
359 361 self.runner = None
360 362 self.runnerClass = None
361 363
362 364 def _makeRunner(self,runnerClass):
363 365 self.runnerClass = runnerClass
364 366 self.runner = runnerClass(out=self.out)
365 367 return self.runner
366 368
367 369 def __call__(self,fname):
368 370 """Return a runner for the given filename."""
369 371
370 372 if fname.endswith('.py'):
371 373 runnerClass = PythonRunner
372 374 elif fname.endswith('.ipy'):
373 375 runnerClass = IPythonRunner
374 376 else:
375 377 raise ValueError('Unknown file type for Runner: %r' % fname)
376 378
377 379 if self.runner is None:
378 380 return self._makeRunner(runnerClass)
379 381 else:
380 382 if runnerClass==self.runnerClass:
381 383 return self.runner
382 384 else:
383 385 e='A runner of type %r can not run file %r' % \
384 386 (self.runnerClass,fname)
385 387 raise ValueError(e)
386 388
387 389
388 390 # Global usage string, to avoid indentation issues if typed in a function def.
389 391 MAIN_USAGE = """
390 392 %prog [options] file_to_run
391 393
392 394 This is an interface to the various interactive runners available in this
393 395 module. If you want to pass specific options to one of the runners, you need
394 396 to first terminate the main options with a '--', and then provide the runner's
395 397 options. For example:
396 398
397 399 irunner.py --python -- --help
398 400
399 401 will pass --help to the python runner. Similarly,
400 402
401 403 irunner.py --ipython -- --interact script.ipy
402 404
403 405 will run the script.ipy file under the IPython runner, and then will start to
404 406 interact with IPython at the end of the script (instead of exiting).
405 407
406 408 The already implemented runners are listed below; adding one for a new program
407 409 is a trivial task, see the source for examples.
408 410 """
409 411
410 412 def main():
411 413 """Run as a command-line script."""
412 414
413 415 parser = optparse.OptionParser(usage=MAIN_USAGE)
414 416 newopt = parser.add_option
415 417 newopt('--ipython',action='store_const',dest='mode',const='ipython',
416 418 help='IPython interactive runner (default).')
417 419 newopt('--python',action='store_const',dest='mode',const='python',
418 420 help='Python interactive runner.')
419 421 newopt('--sage',action='store_const',dest='mode',const='sage',
420 422 help='SAGE interactive runner.')
421 423
422 424 opts,args = parser.parse_args()
423 425 runners = dict(ipython=IPythonRunner,
424 426 python=PythonRunner,
425 427 sage=SAGERunner)
426 428
427 429 try:
428 430 ext = os.path.splitext(args[0])[-1]
429 431 except IndexError:
430 432 ext = ''
431 433 modes = {'.ipy':'ipython',
432 434 '.py':'python',
433 435 '.sage':'sage'}
434 436 mode = modes.get(ext,"ipython")
435 437 if opts.mode:
436 438 mode = opts.mode
437 439 runners[mode]().main(args)
438 440
439 441 if __name__ == '__main__':
440 442 main()
@@ -1,174 +1,182 b''
1 1 """Test suite for the irunner module.
2 2
3 3 Not the most elegant or fine-grained, but it does cover at least the bulk
4 4 functionality."""
5 5
6 6 # Global to make tests extra verbose and help debugging
7 7 VERBOSE = True
8 8
9 9 # stdlib imports
10 10 import StringIO
11 11 import sys
12 12 import unittest
13 13
14 14 # IPython imports
15 15 from IPython.lib import irunner
16 16 from IPython.testing.decorators import known_failure_py3
17 from IPython.utils.py3compat import doctest_refactor_print
17 18
18 19 # Testing code begins
19 20 class RunnerTestCase(unittest.TestCase):
20 21
21 22 def setUp(self):
22 23 self.out = StringIO.StringIO()
23 24 #self.out = sys.stdout
24 25
25 26 def _test_runner(self,runner,source,output):
26 27 """Test that a given runner's input/output match."""
27 28
28 29 runner.run_source(source)
29 30 out = self.out.getvalue()
30 31 #out = ''
31 32 # this output contains nasty \r\n lineends, and the initial ipython
32 33 # banner. clean it up for comparison, removing lines of whitespace
33 34 output_l = [l for l in output.splitlines() if l and not l.isspace()]
34 35 out_l = [l for l in out.splitlines() if l and not l.isspace()]
35 36 mismatch = 0
36 37 if len(output_l) != len(out_l):
37 38 message = ("Mismatch in number of lines\n\n"
38 39 "Expected:\n"
39 40 "~~~~~~~~~\n"
40 41 "%s\n\n"
41 42 "Got:\n"
42 43 "~~~~~~~~~\n"
43 44 "%s"
44 45 ) % ("\n".join(output_l), "\n".join(out_l))
45 46 self.fail(message)
46 47 for n in range(len(output_l)):
47 48 # Do a line-by-line comparison
48 49 ol1 = output_l[n].strip()
49 50 ol2 = out_l[n].strip()
50 51 if ol1 != ol2:
51 52 mismatch += 1
52 53 if VERBOSE:
53 54 print '<<< line %s does not match:' % n
54 55 print repr(ol1)
55 56 print repr(ol2)
56 57 print '>>>'
57 58 self.assert_(mismatch==0,'Number of mismatched lines: %s' %
58 59 mismatch)
59 60
60 # irunner isn't working on Python 3 (due to pexpect)
61 # The SyntaxError appears differently in Python 3, for some reason.
61 62 @known_failure_py3
62 63 def testIPython(self):
63 64 """Test the IPython runner."""
64 source = """
65 source = doctest_refactor_print("""
65 66 print 'hello, this is python'
66 67 # some more code
67 68 x=1;y=2
68 69 x+y**2
69 70
70 71 # An example of autocall functionality
71 72 from math import *
72 73 autocall 1
73 74 cos pi
74 75 autocall 0
75 76 cos pi
76 77 cos(pi)
77 78
78 79 for i in range(5):
79 print i,
80 print i
80 81
81 82 print "that's all folks!"
82 83
83 84 exit
84 """
85 output = """\
85 """)
86 output = doctest_refactor_print("""\
86 87 In [1]: print 'hello, this is python'
87 88 hello, this is python
88 89
89 90
90 91 # some more code
91 92 In [2]: x=1;y=2
92 93
93 94 In [3]: x+y**2
94 95 Out[3]: 5
95 96
96 97
97 98 # An example of autocall functionality
98 99 In [4]: from math import *
99 100
100 101 In [5]: autocall 1
101 102 Automatic calling is: Smart
102 103
103 104 In [6]: cos pi
104 105 ------> cos(pi)
105 106 Out[6]: -1.0
106 107
107 108 In [7]: autocall 0
108 109 Automatic calling is: OFF
109 110
110 111 In [8]: cos pi
111 112 File "<ipython-input-8-6bd7313dd9a9>", line 1
112 113 cos pi
113 114 ^
114 115 SyntaxError: invalid syntax
115 116
116 117
117 118 In [9]: cos(pi)
118 119 Out[9]: -1.0
119 120
120 121
121 122 In [10]: for i in range(5):
122 ....: print i,
123 ....: print i
123 124 ....:
124 0 1 2 3 4
125 0
126 1
127 2
128 3
129 4
125 130
126 131 In [11]: print "that's all folks!"
127 132 that's all folks!
128 133
129 134
130 135 In [12]: exit
131 """
136 """)
132 137 runner = irunner.IPythonRunner(out=self.out)
133 138 self._test_runner(runner,source,output)
134 139
135 @known_failure_py3
136 140 def testPython(self):
137 141 """Test the Python runner."""
138 142 runner = irunner.PythonRunner(out=self.out)
139 source = """
143 source = doctest_refactor_print("""
140 144 print 'hello, this is python'
141 145
142 146 # some more code
143 147 x=1;y=2
144 148 x+y**2
145 149
146 150 from math import *
147 151 cos(pi)
148 152
149 153 for i in range(5):
150 print i,
154 print i
151 155
152 156 print "that's all folks!"
153 """
154 output = """\
157 """)
158 output = doctest_refactor_print("""\
155 159 >>> print 'hello, this is python'
156 160 hello, this is python
157 161
158 162 # some more code
159 163 >>> x=1;y=2
160 164 >>> x+y**2
161 165 5
162 166
163 167 >>> from math import *
164 168 >>> cos(pi)
165 169 -1.0
166 170
167 171 >>> for i in range(5):
168 ... print i,
172 ... print i
169 173 ...
170 0 1 2 3 4
174 0
175 1
176 2
177 3
178 4
171 179 >>> print "that's all folks!"
172 180 that's all folks!
173 """
181 """)
174 182 self._test_runner(runner,source,output)
@@ -1,110 +1,108 b''
1 1 """Test suite for pylab_import_all magic
2 2 Modified from the irunner module but using regex.
3 3 """
4 4
5 5 # Global to make tests extra verbose and help debugging
6 6 VERBOSE = True
7 7
8 8 # stdlib imports
9 9 import StringIO
10 10 import sys
11 11 import unittest
12 12 import re
13 13
14 14 # IPython imports
15 15 from IPython.lib import irunner
16 16 from IPython.testing import decorators
17 17
18 18 # Testing code begins
19 19 class RunnerTestCase(unittest.TestCase):
20 20
21 21 def setUp(self):
22 22 self.out = StringIO.StringIO()
23 23 #self.out = sys.stdout
24 24
25 @decorators.known_failure_py3
26 25 def _test_runner(self,runner,source,output):
27 26 """Test that a given runner's input/output match."""
28 27
29 28 runner.run_source(source)
30 29 out = self.out.getvalue()
31 30 #out = ''
32 31 # this output contains nasty \r\n lineends, and the initial ipython
33 32 # banner. clean it up for comparison, removing lines of whitespace
34 33 output_l = [l for l in output.splitlines() if l and not l.isspace()]
35 34 out_l = [l for l in out.splitlines() if l and not l.isspace()]
36 35 mismatch = 0
37 36 if len(output_l) != len(out_l):
38 37 message = ("Mismatch in number of lines\n\n"
39 38 "Expected:\n"
40 39 "~~~~~~~~~\n"
41 40 "%s\n\n"
42 41 "Got:\n"
43 42 "~~~~~~~~~\n"
44 43 "%s"
45 44 ) % ("\n".join(output_l), "\n".join(out_l))
46 45 self.fail(message)
47 46 for n in range(len(output_l)):
48 47 # Do a line-by-line comparison
49 48 ol1 = output_l[n].strip()
50 49 ol2 = out_l[n].strip()
51 50 if not re.match(ol1,ol2):
52 51 mismatch += 1
53 52 if VERBOSE:
54 53 print '<<< line %s does not match:' % n
55 54 print repr(ol1)
56 55 print repr(ol2)
57 56 print '>>>'
58 57 self.assert_(mismatch==0,'Number of mismatched lines: %s' %
59 58 mismatch)
60 59
61 60 @decorators.skipif_not_matplotlib
62 61 def test_pylab_import_all_enabled(self):
63 62 "Verify that plot is available when pylab_import_all = True"
64 63 source = """
65 64 from IPython.config.application import Application
66 65 app = Application.instance()
67 66 app.pylab_import_all = True
68 67 pylab
69 68 ip=get_ipython()
70 69 'plot' in ip.user_ns
71 70 """
72 71 output = """
73 72 In \[1\]: from IPython\.config\.application import Application
74 73 In \[2\]: app = Application\.instance\(\)
75 74 In \[3\]: app\.pylab_import_all = True
76 75 In \[4\]: pylab
77 76 ^Welcome to pylab, a matplotlib-based Python environment
78 77 For more information, type 'help\(pylab\)'\.
79 78 In \[5\]: ip=get_ipython\(\)
80 79 In \[6\]: \'plot\' in ip\.user_ns
81 80 Out\[6\]: True
82 81 """
83 82 runner = irunner.IPythonRunner(out=self.out)
84 83 self._test_runner(runner,source,output)
85 84
86 @decorators.known_failure_py3
87 85 @decorators.skipif_not_matplotlib
88 86 def test_pylab_import_all_disabled(self):
89 87 "Verify that plot is not available when pylab_import_all = False"
90 88 source = """
91 89 from IPython.config.application import Application
92 90 app = Application.instance()
93 91 app.pylab_import_all = False
94 92 pylab
95 93 ip=get_ipython()
96 94 'plot' in ip.user_ns
97 95 """
98 96 output = """
99 97 In \[1\]: from IPython\.config\.application import Application
100 98 In \[2\]: app = Application\.instance\(\)
101 99 In \[3\]: app\.pylab_import_all = False
102 100 In \[4\]: pylab
103 101 ^Welcome to pylab, a matplotlib-based Python environment
104 102 For more information, type 'help\(pylab\)'\.
105 103 In \[5\]: ip=get_ipython\(\)
106 104 In \[6\]: \'plot\' in ip\.user_ns
107 105 Out\[6\]: False
108 106 """
109 107 runner = irunner.IPythonRunner(out=self.out)
110 108 self._test_runner(runner,source,output)
General Comments 0
You need to be logged in to leave comments. Login now