##// END OF EJS Templates
Merge pull request #1855 from minrk/moremagics...
Fernando Perez -
r7413:18f728c8 merge
parent child Browse files
Show More
@@ -0,0 +1,215 b''
1 """Magic functions for running cells in various scripts."""
2 #-----------------------------------------------------------------------------
3 # Copyright (c) 2012 The IPython Development Team.
4 #
5 # Distributed under the terms of the Modified BSD License.
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
9
10 #-----------------------------------------------------------------------------
11 # Imports
12 #-----------------------------------------------------------------------------
13
14 # Stdlib
15 import os
16 import re
17 import sys
18 from subprocess import Popen, PIPE
19
20 # Our own packages
21 from IPython.config.configurable import Configurable
22 from IPython.core import magic_arguments
23 from IPython.core.error import UsageError
24 from IPython.core.magic import (
25 Magics, magics_class, line_magic, cell_magic
26 )
27 from IPython.lib.backgroundjobs import BackgroundJobManager
28 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.utils import py3compat
30 from IPython.utils.process import find_cmd, FindCmdError, arg_split
31 from IPython.utils.traitlets import List, Dict
32
33 #-----------------------------------------------------------------------------
34 # Magic implementation classes
35 #-----------------------------------------------------------------------------
36
37 def script_args(f):
38 """single decorator for adding script args"""
39 args = [
40 magic_arguments.argument(
41 '--out', type=str,
42 help="""The variable in which to store stdout from the script.
43 If the script is backgrounded, this will be the stdout *pipe*,
44 instead of the stderr text itself.
45 """
46 ),
47 magic_arguments.argument(
48 '--err', type=str,
49 help="""The variable in which to store stderr from the script.
50 If the script is backgrounded, this will be the stderr *pipe*,
51 instead of the stderr text itself.
52 """
53 ),
54 magic_arguments.argument(
55 '--bg', action="store_true",
56 help="""Whether to run the script in the background.
57 If given, the only way to see the output of the command is
58 with --out/err.
59 """
60 ),
61 ]
62 for arg in args:
63 f = arg(f)
64 return f
65
66 @magics_class
67 class ScriptMagics(Magics, Configurable):
68 """Magics for talking to scripts
69
70 This defines a base `%%script` cell magic for running a cell
71 with a program in a subprocess, and registers a few top-level
72 magics that call %%script with common interpreters.
73 """
74 script_magics = List(config=True,
75 help="""Extra script cell magics to define
76
77 This generates simple wrappers of `%%script foo` as `%%foo`.
78
79 If you want to add script magics that aren't on your path,
80 specify them in script_paths
81 """,
82 )
83 def _script_magics_default(self):
84 """default to a common list of programs if we find them"""
85
86 defaults = []
87 to_try = []
88 if os.name == 'nt':
89 defaults.append('cmd')
90 to_try.append('powershell')
91 to_try.extend([
92 'sh',
93 'bash',
94 'perl',
95 'ruby',
96 'python3',
97 'pypy',
98 ])
99
100 for cmd in to_try:
101 if cmd in self.script_paths:
102 defaults.append(cmd)
103 else:
104 try:
105 find_cmd(cmd)
106 except FindCmdError:
107 # command not found, ignore it
108 pass
109 except ImportError:
110 # Windows without pywin32, find_cmd doesn't work
111 pass
112 else:
113 defaults.append(cmd)
114 return defaults
115
116 script_paths = Dict(config=True,
117 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
118
119 Only necessary for items in script_magics where the default path will not
120 find the right interpreter.
121 """
122 )
123
124 def __init__(self, shell=None):
125 Configurable.__init__(self, config=shell.config)
126 self._generate_script_magics()
127 Magics.__init__(self, shell=shell)
128 self.job_manager = BackgroundJobManager()
129
130 def _generate_script_magics(self):
131 cell_magics = self.magics['cell']
132 for name in self.script_magics:
133 cell_magics[name] = self._make_script_magic(name)
134
135 def _make_script_magic(self, name):
136 """make a named magic, that calls %%script with a particular program"""
137 # expand to explicit path if necessary:
138 script = self.script_paths.get(name, name)
139
140 @magic_arguments.magic_arguments()
141 @script_args
142 def named_script_magic(line, cell):
143 # if line, add it as cl-flags
144 if line:
145 line = "%s %s" % (script, line)
146 else:
147 line = script
148 return self.shebang(line, cell)
149
150 # write a basic docstring:
151 named_script_magic.__doc__ = \
152 """%%{name} script magic
153
154 Run cells with {script} in a subprocess.
155
156 This is a shortcut for `%%script {script}`
157 """.format(**locals())
158
159 return named_script_magic
160
161 @magic_arguments.magic_arguments()
162 @script_args
163 @cell_magic("script")
164 def shebang(self, line, cell):
165 """Run a cell via a shell command
166
167 The `%%script` line is like the #! line of script,
168 specifying a program (bash, perl, ruby, etc.) with which to run.
169
170 The rest of the cell is run by that program.
171
172 Examples
173 --------
174 ::
175
176 In [1]: %%script bash
177 ...: for i in 1 2 3; do
178 ...: echo $i
179 ...: done
180 1
181 2
182 3
183 """
184 argv = arg_split(line, posix = not sys.platform.startswith('win'))
185 args, cmd = self.shebang.parser.parse_known_args(argv)
186
187 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
188
189 if args.bg:
190 if args.out:
191 self.shell.user_ns[args.out] = p.stdout
192 if args.err:
193 self.shell.user_ns[args.err] = p.stderr
194 self.job_manager.new(self._run_script, p, cell)
195 return
196
197 out, err = p.communicate(cell)
198 out = py3compat.bytes_to_str(out)
199 err = py3compat.bytes_to_str(err)
200 if args.out:
201 self.shell.user_ns[args.out] = out
202 else:
203 sys.stdout.write(out)
204 sys.stdout.flush()
205 if args.err:
206 self.shell.user_ns[args.err] = err
207 else:
208 sys.stderr.write(err)
209 sys.stderr.flush()
210
211 def _run_script(self, p, cell):
212 """callback for running the script in the background"""
213 p.stdin.write(cell)
214 p.stdin.close()
215 p.wait()
@@ -0,0 +1,448 b''
1 {
2 "metadata": {
3 "name": "Script Magics"
4 },
5 "nbformat": 3,
6 "worksheets": [
7 {
8 "cells": [
9 {
10 "cell_type": "heading",
11 "level": 1,
12 "source": [
13 "Running Scripts from IPython"
14 ]
15 },
16 {
17 "cell_type": "markdown",
18 "source": [
19 "IPython has a `%%script` cell magic, which lets you run a cell in",
20 "a subprocess of any interpreter on your system, such as: bash, ruby, perl, zsh, R, etc.",
21 "",
22 "It can even be a script of your own, which expects input on stdin."
23 ]
24 },
25 {
26 "cell_type": "code",
27 "input": [
28 "import sys"
29 ],
30 "language": "python",
31 "outputs": [],
32 "prompt_number": 1
33 },
34 {
35 "cell_type": "markdown",
36 "source": [
37 "To use it, simply pass a path or shell command to the program you want to run on the `%%script` line,",
38 "and the rest of the cell will be run by that script, and stdout/err from the subprocess are captured and displayed."
39 ]
40 },
41 {
42 "cell_type": "code",
43 "input": [
44 "%%script python",
45 "import sys",
46 "print 'hello from Python %s' % sys.version"
47 ],
48 "language": "python",
49 "outputs": [
50 {
51 "output_type": "stream",
52 "stream": "stdout",
53 "text": [
54 "hello from Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) ",
55 "[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)]",
56 ""
57 ]
58 }
59 ],
60 "prompt_number": 2
61 },
62 {
63 "cell_type": "code",
64 "input": [
65 "%%script python3",
66 "import sys",
67 "print('hello from Python: %s' % sys.version)"
68 ],
69 "language": "python",
70 "outputs": [
71 {
72 "output_type": "stream",
73 "stream": "stdout",
74 "text": [
75 "hello from Python: 3.2.3 (v3.2.3:3d0686d90f55, Apr 10 2012, 11:25:50) ",
76 "[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]",
77 ""
78 ]
79 }
80 ],
81 "prompt_number": 3
82 },
83 {
84 "cell_type": "markdown",
85 "source": [
86 "IPython also creates aliases for a few common interpreters, such as bash, ruby, perl, etc.",
87 "",
88 "These are all equivalent to `%%script <name>`"
89 ]
90 },
91 {
92 "cell_type": "code",
93 "input": [
94 "%%ruby",
95 "puts \"Hello from Ruby #{RUBY_VERSION}\""
96 ],
97 "language": "python",
98 "outputs": [
99 {
100 "output_type": "stream",
101 "stream": "stdout",
102 "text": [
103 "Hello from Ruby 1.8.7",
104 ""
105 ]
106 }
107 ],
108 "prompt_number": 4
109 },
110 {
111 "cell_type": "code",
112 "input": [
113 "%%bash",
114 "echo \"hello from $BASH\""
115 ],
116 "language": "python",
117 "outputs": [
118 {
119 "output_type": "stream",
120 "stream": "stdout",
121 "text": [
122 "hello from /usr/local/bin/bash",
123 ""
124 ]
125 }
126 ],
127 "prompt_number": 5
128 },
129 {
130 "cell_type": "heading",
131 "level": 2,
132 "source": [
133 "Capturing output"
134 ]
135 },
136 {
137 "cell_type": "markdown",
138 "source": [
139 "You can also capture stdout/err from these subprocesses into Python variables, instead of letting them go directly to stdout/err"
140 ]
141 },
142 {
143 "cell_type": "code",
144 "input": [
145 "%%bash",
146 "echo \"hi, stdout\"",
147 "echo \"hello, stderr\" >&2",
148 ""
149 ],
150 "language": "python",
151 "outputs": [
152 {
153 "output_type": "stream",
154 "stream": "stdout",
155 "text": [
156 "hi, stdout",
157 ""
158 ]
159 },
160 {
161 "output_type": "stream",
162 "stream": "stderr",
163 "text": [
164 "hello, stderr",
165 ""
166 ]
167 }
168 ],
169 "prompt_number": 6
170 },
171 {
172 "cell_type": "code",
173 "input": [
174 "%%bash --out output --err error",
175 "echo \"hi, stdout\"",
176 "echo \"hello, stderr\" >&2"
177 ],
178 "language": "python",
179 "outputs": [],
180 "prompt_number": 7
181 },
182 {
183 "cell_type": "code",
184 "input": [
185 "print error",
186 "print output"
187 ],
188 "language": "python",
189 "outputs": [
190 {
191 "output_type": "stream",
192 "stream": "stdout",
193 "text": [
194 "hello, stderr",
195 "",
196 "hi, stdout",
197 "",
198 ""
199 ]
200 }
201 ],
202 "prompt_number": 8
203 },
204 {
205 "cell_type": "heading",
206 "level": 2,
207 "source": [
208 "Background Scripts"
209 ]
210 },
211 {
212 "cell_type": "markdown",
213 "source": [
214 "These scripts can be run in the background, by adding the `--bg` flag.",
215 "",
216 "When you do this, output is discarded unless you use the `--out/err`",
217 "flags to store output as above."
218 ]
219 },
220 {
221 "cell_type": "code",
222 "input": [
223 "%%ruby --bg --out ruby_lines",
224 "for n in 1...10",
225 " sleep 1",
226 " puts \"line #{n}\"",
227 " STDOUT.flush",
228 "end"
229 ],
230 "language": "python",
231 "outputs": [
232 {
233 "output_type": "stream",
234 "stream": "stdout",
235 "text": [
236 "Starting job # 0 in a separate thread.",
237 ""
238 ]
239 }
240 ],
241 "prompt_number": 9
242 },
243 {
244 "cell_type": "markdown",
245 "source": [
246 "When you do store output of a background thread, these are the stdout/err *pipes*,",
247 "rather than the text of the output."
248 ]
249 },
250 {
251 "cell_type": "code",
252 "input": [
253 "ruby_lines"
254 ],
255 "language": "python",
256 "outputs": [
257 {
258 "output_type": "pyout",
259 "prompt_number": 10,
260 "text": [
261 "<open file '<fdopen>', mode 'rb' at 0x10dc651e0>"
262 ]
263 }
264 ],
265 "prompt_number": 10
266 },
267 {
268 "cell_type": "code",
269 "input": [
270 "print ruby_lines.read()"
271 ],
272 "language": "python",
273 "outputs": [
274 {
275 "output_type": "stream",
276 "stream": "stdout",
277 "text": [
278 "line 1",
279 "line 2",
280 "line 3",
281 "line 4",
282 "line 5",
283 "line 6",
284 "line 7",
285 "line 8",
286 "line 9",
287 "",
288 ""
289 ]
290 }
291 ],
292 "prompt_number": 11
293 },
294 {
295 "cell_type": "heading",
296 "level": 2,
297 "source": [
298 "Arguments to subcommand"
299 ]
300 },
301 {
302 "cell_type": "markdown",
303 "source": [
304 "You can pass arguments the subcommand as well,",
305 "such as this example instructing Python to use integer division from Python 3:"
306 ]
307 },
308 {
309 "cell_type": "code",
310 "input": [
311 "%%script python -Qnew",
312 "print 1/3"
313 ],
314 "language": "python",
315 "outputs": [
316 {
317 "output_type": "stream",
318 "stream": "stdout",
319 "text": [
320 "0.333333333333",
321 ""
322 ]
323 }
324 ],
325 "prompt_number": 12
326 },
327 {
328 "cell_type": "markdown",
329 "source": [
330 "You can really specify *any* program for `%%script`,",
331 "for instance here is a 'program' that echos the lines of stdin, with delays between each line."
332 ]
333 },
334 {
335 "cell_type": "code",
336 "input": [
337 "%%script --bg --out bashout bash -c \"while read line; do echo $line; sleep 1; done\"",
338 "line 1",
339 "line 2",
340 "line 3",
341 "line 4",
342 "line 5",
343 ""
344 ],
345 "language": "python",
346 "outputs": [
347 {
348 "output_type": "stream",
349 "stream": "stdout",
350 "text": [
351 "Starting job # 2 in a separate thread.",
352 ""
353 ]
354 }
355 ],
356 "prompt_number": 13
357 },
358 {
359 "cell_type": "markdown",
360 "source": [
361 "Remember, since the output of a background script is just the stdout pipe,",
362 "you can read it as lines become available:"
363 ]
364 },
365 {
366 "cell_type": "code",
367 "input": [
368 "import time",
369 "tic = time.time()",
370 "line = True",
371 "while True:",
372 " line = bashout.readline()",
373 " if not line:",
374 " break",
375 " sys.stdout.write(\"%.1fs: %s\" %(time.time()-tic, line))",
376 " sys.stdout.flush()",
377 ""
378 ],
379 "language": "python",
380 "outputs": [
381 {
382 "output_type": "stream",
383 "stream": "stdout",
384 "text": [
385 "0.0s: line 1",
386 ""
387 ]
388 },
389 {
390 "output_type": "stream",
391 "stream": "stdout",
392 "text": [
393 "1.0s: line 2",
394 ""
395 ]
396 },
397 {
398 "output_type": "stream",
399 "stream": "stdout",
400 "text": [
401 "2.0s: line 3",
402 ""
403 ]
404 },
405 {
406 "output_type": "stream",
407 "stream": "stdout",
408 "text": [
409 "3.0s: line 4",
410 ""
411 ]
412 },
413 {
414 "output_type": "stream",
415 "stream": "stdout",
416 "text": [
417 "4.0s: line 5",
418 ""
419 ]
420 }
421 ],
422 "prompt_number": 14
423 },
424 {
425 "cell_type": "heading",
426 "level": 2,
427 "source": [
428 "Configuring the default ScriptMagics"
429 ]
430 },
431 {
432 "cell_type": "markdown",
433 "source": [
434 "The list of aliased script magics is configurable.",
435 "",
436 "The default is to pick from a few common interpreters, and use them if found, but you can specify your own in ipython_config.py:",
437 "",
438 " c.ScriptMagics.scripts = ['R', 'pypy', 'myprogram']",
439 "",
440 "And if any of these programs do not apear on your default PATH, then you would also need to specify their location with:",
441 "",
442 " c.ScriptMagics.script_paths = {'myprogram': '/opt/path/to/myprogram'}"
443 ]
444 }
445 ]
446 }
447 ]
448 } No newline at end of file
@@ -2017,7 +2017,8 b' class InteractiveShell(SingletonConfigurable):'
2017 2017 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2018 2018 m.ConfigMagics, m.DeprecatedMagics, m.ExecutionMagics,
2019 2019 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2020 m.NamespaceMagics, m.OSMagics, m.PylabMagics )
2020 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2021 )
2021 2022
2022 2023 # FIXME: Move the color initialization to the DisplayHook, which
2023 2024 # should be split into a prompt manager and displayhook. We probably
@@ -30,7 +30,7 b' from IPython.external.decorator import decorator'
30 30 from IPython.utils.ipstruct import Struct
31 31 from IPython.utils.process import arg_split
32 32 from IPython.utils.text import dedent
33 from IPython.utils.traitlets import Bool, Dict, Instance
33 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
34 34 from IPython.utils.warn import error, warn
35 35
36 36 #-----------------------------------------------------------------------------
@@ -365,10 +365,10 b' class MagicsManager(Configurable):'
365 365 for m in magic_objects:
366 366 if not m.registered:
367 367 raise ValueError("Class of magics %r was constructed without "
368 "the @register_macics class decorator")
369 if type(m) is type:
368 "the @register_magics class decorator")
369 if type(m) in (type, MetaHasTraits):
370 370 # If we're given an uninstantiated class
371 m = m(self.shell)
371 m = m(shell=self.shell)
372 372
373 373 # Now that we have an instance, we can register it and update the
374 374 # table of callables
@@ -25,6 +25,7 b' from .logging import LoggingMagics'
25 25 from .namespace import NamespaceMagics
26 26 from .osm import OSMagics
27 27 from .pylab import PylabMagics
28 from .script import ScriptMagics
28 29
29 30 #-----------------------------------------------------------------------------
30 31 # Magic implementation classes
@@ -16,17 +16,20 b' builtin.'
16 16 #-----------------------------------------------------------------------------
17 17
18 18 # Stdlib
19 import io
19 20 import os
20 21 import re
21 22 import sys
22 23 from pprint import pformat
23 24
24 25 # Our own packages
26 from IPython.core import magic_arguments
25 27 from IPython.core import oinspect
26 28 from IPython.core import page
27 from IPython.core.error import UsageError
28 from IPython.core.magic import (Magics, compress_dhist, magics_class,
29 line_magic)
29 from IPython.core.error import UsageError, StdinNotImplementedError
30 from IPython.core.magic import (
31 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
32 )
30 33 from IPython.testing.skipdoctest import skip_doctest
31 34 from IPython.utils.io import file_read, nlprint
32 35 from IPython.utils.path import get_py_filename, unquote_filename
@@ -432,7 +435,7 b' class OSMagics(Magics):'
432 435 @skip_doctest
433 436 @line_magic
434 437 def sc(self, parameter_s=''):
435 """Shell capture - execute a shell command and capture its output.
438 """Shell capture - run shell command and capture output (DEPRECATED use !).
436 439
437 440 DEPRECATED. Suboptimal, retained for backwards compatibility.
438 441
@@ -545,9 +548,9 b' class OSMagics(Magics):'
545 548 else:
546 549 return out
547 550
548 @line_magic
549 def sx(self, parameter_s=''):
550 """Shell execute - run a shell command and capture its output.
551 @line_cell_magic
552 def sx(self, line='', cell=None):
553 """Shell execute - run shell command and capture output (!! is short-hand).
551 554
552 555 %sx command
553 556
@@ -586,10 +589,21 b' class OSMagics(Magics):'
586 589
587 590 This is very useful when trying to use such lists as arguments to
588 591 system commands."""
592
593 if cell is None:
594 # line magic
595 return self.shell.getoutput(line)
596 else:
597 opts,args = self.parse_options(line, '', 'out=')
598 output = self.shell.getoutput(cell)
599 out_name = opts.get('out', opts.get('o'))
600 if out_name:
601 self.shell.user_ns[out_name] = output
602 else:
603 return output
589 604
590 if parameter_s:
591 return self.shell.getoutput(parameter_s)
592
605 system = line_cell_magic('system')(sx)
606 bang = cell_magic('!')(sx)
593 607
594 608 @line_magic
595 609 def bookmark(self, parameter_s=''):
@@ -675,3 +689,33 b' class OSMagics(Magics):'
675 689 return
676 690
677 691 page.page(self.shell.pycolorize(cont))
692
693 @magic_arguments.magic_arguments()
694 @magic_arguments.argument(
695 '-a', '--amend', action='store_true', default=False,
696 help='Open file for amending if it exists'
697 )
698 @magic_arguments.argument(
699 'filename', type=unicode,
700 help='file to write'
701 )
702 @cell_magic
703 def file(self, line, cell):
704 """Write the contents of the cell to a file.
705
706 For frontends that do not support stdin (Notebook), -f is implied.
707 """
708 args = magic_arguments.parse_argstring(self.file, line)
709 filename = unquote_filename(args.filename)
710
711 if os.path.exists(filename):
712 if args.amend:
713 print "Amending to %s" % filename
714 else:
715 print "Overwriting %s" % filename
716 else:
717 print "Writing %s" % filename
718
719 mode = 'a' if args.amend else 'w'
720 with io.open(filename, mode, encoding='utf-8') as f:
721 f.write(cell)
@@ -28,13 +28,14 b' from IPython.core.magic import (Magics, magics_class, line_magic,'
28 28 cell_magic, line_cell_magic,
29 29 register_line_magic, register_cell_magic,
30 30 register_line_cell_magic)
31 from IPython.core.magics import execution
31 from IPython.core.magics import execution, script
32 32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 33 from IPython.nbformat import current
34 34 from IPython.testing import decorators as dec
35 35 from IPython.testing import tools as tt
36 36 from IPython.utils import py3compat
37 37 from IPython.utils.tempdir import TemporaryDirectory
38 from IPython.utils.process import find_cmd
38 39
39 40 #-----------------------------------------------------------------------------
40 41 # Test functions begin
@@ -560,4 +561,104 b' class CellMagicTestCase(TestCase):'
560 561 # Check that nothing is registered as 'cellm33'
561 562 c33 = _ip.find_cell_magic('cellm33')
562 563 nt.assert_equals(c33, None)
564
565 def test_file():
566 """Basic %%file"""
567 ip = get_ipython()
568 with TemporaryDirectory() as td:
569 fname = os.path.join(td, 'file1')
570 ip.run_cell_magic("file", fname, u'\n'.join([
571 'line1',
572 'line2',
573 ]))
574 with open(fname) as f:
575 s = f.read()
576 nt.assert_in('line1\n', s)
577 nt.assert_in('line2', s)
578
579 def test_file_unicode():
580 """%%file with unicode cell"""
581 ip = get_ipython()
582 with TemporaryDirectory() as td:
583 fname = os.path.join(td, 'file1')
584 ip.run_cell_magic("file", fname, u'\n'.join([
585 u'linΓ©1',
586 u'linΓ©2',
587 ]))
588 with io.open(fname, encoding='utf-8') as f:
589 s = f.read()
590 nt.assert_in(u'linΓ©1\n', s)
591 nt.assert_in(u'linΓ©2', s)
592
593 def test_file_amend():
594 """%%file -a amends files"""
595 ip = get_ipython()
596 with TemporaryDirectory() as td:
597 fname = os.path.join(td, 'file2')
598 ip.run_cell_magic("file", fname, u'\n'.join([
599 'line1',
600 'line2',
601 ]))
602 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
603 'line3',
604 'line4',
605 ]))
606 with open(fname) as f:
607 s = f.read()
608 nt.assert_in('line1\n', s)
609 nt.assert_in('line3\n', s)
610
563 611
612 def test_script_config():
613 ip = get_ipython()
614 ip.config.ScriptMagics.script_magics = ['whoda']
615 sm = script.ScriptMagics(shell=ip)
616 nt.assert_in('whoda', sm.magics['cell'])
617
618 @dec.skip_win32
619 def test_script_out():
620 ip = get_ipython()
621 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
622 nt.assert_equals(ip.user_ns['output'], 'hi\n')
623
624 @dec.skip_win32
625 def test_script_err():
626 ip = get_ipython()
627 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
628 nt.assert_equals(ip.user_ns['error'], 'hello\n')
629
630 @dec.skip_win32
631 def test_script_out_err():
632 ip = get_ipython()
633 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
634 nt.assert_equals(ip.user_ns['output'], 'hi\n')
635 nt.assert_equals(ip.user_ns['error'], 'hello\n')
636
637 @dec.skip_win32
638 def test_script_bg_out():
639 ip = get_ipython()
640 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
641 nt.assert_equals(ip.user_ns['output'].read(), 'hi\n')
642
643 @dec.skip_win32
644 def test_script_bg_err():
645 ip = get_ipython()
646 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
647 nt.assert_equals(ip.user_ns['error'].read(), 'hello\n')
648
649 @dec.skip_win32
650 def test_script_bg_out_err():
651 ip = get_ipython()
652 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
653 nt.assert_equals(ip.user_ns['output'].read(), 'hi\n')
654 nt.assert_equals(ip.user_ns['error'].read(), 'hello\n')
655
656 def test_script_defaults():
657 ip = get_ipython()
658 for cmd in ['sh', 'bash', 'perl', 'ruby']:
659 try:
660 find_cmd(cmd)
661 except Exception:
662 pass
663 else:
664 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
General Comments 0
You need to be logged in to leave comments. Login now