Show More
@@ -0,0 +1,155 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.error import UsageError | |
|
23 | from IPython.core.magic import ( | |
|
24 | Magics, magics_class, line_magic, cell_magic | |
|
25 | ) | |
|
26 | from IPython.testing.skipdoctest import skip_doctest | |
|
27 | from IPython.utils.process import find_cmd, FindCmdError | |
|
28 | from IPython.utils.traitlets import List, Dict | |
|
29 | ||
|
30 | #----------------------------------------------------------------------------- | |
|
31 | # Magic implementation classes | |
|
32 | #----------------------------------------------------------------------------- | |
|
33 | ||
|
34 | @magics_class | |
|
35 | class ScriptMagics(Magics, Configurable): | |
|
36 | """Magics for talking to scripts | |
|
37 | ||
|
38 | This defines a base `%%script` cell magic for running a cell | |
|
39 | with a program in a subprocess, and registers a few top-level | |
|
40 | magics that call %%script with common interpreters. | |
|
41 | """ | |
|
42 | script_magics = List(config=True, | |
|
43 | help="""Extra script cell magics to define | |
|
44 | ||
|
45 | This generates simple wrappers of `%%script foo` as `%%foo`. | |
|
46 | ||
|
47 | If you want to add script magics that aren't on your path, | |
|
48 | specify them in script_paths | |
|
49 | """, | |
|
50 | ) | |
|
51 | def _script_magics_default(self): | |
|
52 | """default to a common list of programs if we find them""" | |
|
53 | ||
|
54 | defaults = [] | |
|
55 | to_try = [] | |
|
56 | if os.name == 'nt': | |
|
57 | defaults.append('cmd') | |
|
58 | to_try.append('powershell') | |
|
59 | to_try.extend([ | |
|
60 | 'sh', | |
|
61 | 'bash', | |
|
62 | 'perl', | |
|
63 | 'ruby', | |
|
64 | 'python3', | |
|
65 | 'pypy', | |
|
66 | ]) | |
|
67 | ||
|
68 | for cmd in to_try: | |
|
69 | if cmd in self.script_paths: | |
|
70 | defaults.append(cmd) | |
|
71 | else: | |
|
72 | try: | |
|
73 | find_cmd(cmd) | |
|
74 | except FindCmdError: | |
|
75 | # command not found, ignore it | |
|
76 | pass | |
|
77 | except ImportError: | |
|
78 | # Windows without pywin32, find_cmd doesn't work | |
|
79 | pass | |
|
80 | else: | |
|
81 | defaults.append(cmd) | |
|
82 | return defaults | |
|
83 | ||
|
84 | script_paths = Dict(config=True, | |
|
85 | help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby' | |
|
86 | ||
|
87 | Only necessary for items in script_magics where the default path will not | |
|
88 | find the right interpreter. | |
|
89 | """ | |
|
90 | ) | |
|
91 | ||
|
92 | def __init__(self, shell=None): | |
|
93 | Configurable.__init__(self, config=shell.config) | |
|
94 | self._generate_script_magics() | |
|
95 | Magics.__init__(self, shell=shell) | |
|
96 | ||
|
97 | def _generate_script_magics(self): | |
|
98 | cell_magics = self.magics['cell'] | |
|
99 | for name in self.script_magics: | |
|
100 | cell_magics[name] = self._make_script_magic(name) | |
|
101 | ||
|
102 | def _make_script_magic(self, name): | |
|
103 | """make a named magic, that calls %%script with a particular program""" | |
|
104 | # expand to explicit path if necessary: | |
|
105 | script = self.script_paths.get(name, name) | |
|
106 | ||
|
107 | def named_script_magic(line, cell): | |
|
108 | # if line, add it as cl-flags | |
|
109 | if line: | |
|
110 | line = "%s %s" % (script, line) | |
|
111 | else: | |
|
112 | line = script | |
|
113 | return self.shebang(line, cell) | |
|
114 | ||
|
115 | # write a basic docstring: | |
|
116 | named_script_magic.__doc__ = \ | |
|
117 | """%%{name} script magic | |
|
118 | ||
|
119 | Run cells with {script} in a subprocess. | |
|
120 | ||
|
121 | This is a shortcut for `%%script {script}` | |
|
122 | """.format(**locals()) | |
|
123 | ||
|
124 | return named_script_magic | |
|
125 | ||
|
126 | @cell_magic("script") | |
|
127 | def shebang(self, line, cell): | |
|
128 | """Run a cell via a shell command | |
|
129 | ||
|
130 | The `%%script` line is like the #! line of script, | |
|
131 | specifying a program (bash, perl, ruby, etc.) with which to run. | |
|
132 | ||
|
133 | The rest of the cell is run by that program. | |
|
134 | ||
|
135 | Examples | |
|
136 | -------- | |
|
137 | :: | |
|
138 | ||
|
139 | In [1]: %%script bash | |
|
140 | ...: for i in 1 2 3; do | |
|
141 | ...: echo $i | |
|
142 | ...: done | |
|
143 | 1 | |
|
144 | 2 | |
|
145 | 3 | |
|
146 | """ | |
|
147 | p = Popen(line, stdout=PIPE, stderr=PIPE, stdin=PIPE) | |
|
148 | out,err = p.communicate(cell) | |
|
149 | sys.stdout.write(out) | |
|
150 | sys.stdout.flush() | |
|
151 | sys.stderr.write(err) | |
|
152 | sys.stderr.flush() | |
|
153 | ||
|
154 | # expose %%script as %%! | |
|
155 | cell_magic('!')(shebang) |
@@ -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 |
@@ -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 |
General Comments 0
You need to be logged in to leave comments.
Login now