##// 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 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2017 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2018 m.ConfigMagics, m.DeprecatedMagics, m.ExecutionMagics,
2018 m.ConfigMagics, m.DeprecatedMagics, m.ExecutionMagics,
2019 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
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 # FIXME: Move the color initialization to the DisplayHook, which
2023 # FIXME: Move the color initialization to the DisplayHook, which
2023 # should be split into a prompt manager and displayhook. We probably
2024 # should be split into a prompt manager and displayhook. We probably
@@ -30,7 +30,7 b' from IPython.external.decorator import decorator'
30 from IPython.utils.ipstruct import Struct
30 from IPython.utils.ipstruct import Struct
31 from IPython.utils.process import arg_split
31 from IPython.utils.process import arg_split
32 from IPython.utils.text import dedent
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 from IPython.utils.warn import error, warn
34 from IPython.utils.warn import error, warn
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
@@ -365,10 +365,10 b' class MagicsManager(Configurable):'
365 for m in magic_objects:
365 for m in magic_objects:
366 if not m.registered:
366 if not m.registered:
367 raise ValueError("Class of magics %r was constructed without "
367 raise ValueError("Class of magics %r was constructed without "
368 "the @register_macics class decorator")
368 "the @register_magics class decorator")
369 if type(m) is type:
369 if type(m) in (type, MetaHasTraits):
370 # If we're given an uninstantiated class
370 # If we're given an uninstantiated class
371 m = m(self.shell)
371 m = m(shell=self.shell)
372
372
373 # Now that we have an instance, we can register it and update the
373 # Now that we have an instance, we can register it and update the
374 # table of callables
374 # table of callables
@@ -25,6 +25,7 b' from .logging import LoggingMagics'
25 from .namespace import NamespaceMagics
25 from .namespace import NamespaceMagics
26 from .osm import OSMagics
26 from .osm import OSMagics
27 from .pylab import PylabMagics
27 from .pylab import PylabMagics
28 from .script import ScriptMagics
28
29
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30 # Magic implementation classes
31 # Magic implementation classes
@@ -16,17 +16,20 b' builtin.'
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Stdlib
18 # Stdlib
19 import io
19 import os
20 import os
20 import re
21 import re
21 import sys
22 import sys
22 from pprint import pformat
23 from pprint import pformat
23
24
24 # Our own packages
25 # Our own packages
26 from IPython.core import magic_arguments
25 from IPython.core import oinspect
27 from IPython.core import oinspect
26 from IPython.core import page
28 from IPython.core import page
27 from IPython.core.error import UsageError
29 from IPython.core.error import UsageError, StdinNotImplementedError
28 from IPython.core.magic import (Magics, compress_dhist, magics_class,
30 from IPython.core.magic import (
29 line_magic)
31 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
32 )
30 from IPython.testing.skipdoctest import skip_doctest
33 from IPython.testing.skipdoctest import skip_doctest
31 from IPython.utils.io import file_read, nlprint
34 from IPython.utils.io import file_read, nlprint
32 from IPython.utils.path import get_py_filename, unquote_filename
35 from IPython.utils.path import get_py_filename, unquote_filename
@@ -432,7 +435,7 b' class OSMagics(Magics):'
432 @skip_doctest
435 @skip_doctest
433 @line_magic
436 @line_magic
434 def sc(self, parameter_s=''):
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 DEPRECATED. Suboptimal, retained for backwards compatibility.
440 DEPRECATED. Suboptimal, retained for backwards compatibility.
438
441
@@ -545,9 +548,9 b' class OSMagics(Magics):'
545 else:
548 else:
546 return out
549 return out
547
550
548 @line_magic
551 @line_cell_magic
549 def sx(self, parameter_s=''):
552 def sx(self, line='', cell=None):
550 """Shell execute - run a shell command and capture its output.
553 """Shell execute - run shell command and capture output (!! is short-hand).
551
554
552 %sx command
555 %sx command
553
556
@@ -586,10 +589,21 b' class OSMagics(Magics):'
586
589
587 This is very useful when trying to use such lists as arguments to
590 This is very useful when trying to use such lists as arguments to
588 system commands."""
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:
605 system = line_cell_magic('system')(sx)
591 return self.shell.getoutput(parameter_s)
606 bang = cell_magic('!')(sx)
592
593
607
594 @line_magic
608 @line_magic
595 def bookmark(self, parameter_s=''):
609 def bookmark(self, parameter_s=''):
@@ -675,3 +689,33 b' class OSMagics(Magics):'
675 return
689 return
676
690
677 page.page(self.shell.pycolorize(cont))
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 cell_magic, line_cell_magic,
28 cell_magic, line_cell_magic,
29 register_line_magic, register_cell_magic,
29 register_line_magic, register_cell_magic,
30 register_line_cell_magic)
30 register_line_cell_magic)
31 from IPython.core.magics import execution
31 from IPython.core.magics import execution, script
32 from IPython.nbformat.v3.tests.nbexamples import nb0
32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 from IPython.nbformat import current
33 from IPython.nbformat import current
34 from IPython.testing import decorators as dec
34 from IPython.testing import decorators as dec
35 from IPython.testing import tools as tt
35 from IPython.testing import tools as tt
36 from IPython.utils import py3compat
36 from IPython.utils import py3compat
37 from IPython.utils.tempdir import TemporaryDirectory
37 from IPython.utils.tempdir import TemporaryDirectory
38 from IPython.utils.process import find_cmd
38
39
39 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
40 # Test functions begin
41 # Test functions begin
@@ -560,4 +561,104 b' class CellMagicTestCase(TestCase):'
560 # Check that nothing is registered as 'cellm33'
561 # Check that nothing is registered as 'cellm33'
561 c33 = _ip.find_cell_magic('cellm33')
562 c33 = _ip.find_cell_magic('cellm33')
562 nt.assert_equals(c33, None)
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