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 | 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 |
@@ -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 |
General Comments 0
You need to be logged in to leave comments.
Login now