##// END OF EJS Templates
sh profile: ./foo runs 'foo' directly as system command
Ville M. Vainio -
Show More
@@ -1,251 +1,258 b''
1 1 """Shell mode for IPython.
2 2
3 3 Start ipython in shell mode by invoking "ipython -p sh"
4 4
5 5 (the old version, "ipython -p pysh" still works but this is the more "modern"
6 6 shell mode and is recommended for users who don't care about pysh-mode
7 7 compatibility)
8 8 """
9 9
10 10 from IPython import ipapi
11 11 import os,textwrap
12 12
13 13 # The import below effectively obsoletes your old-style ipythonrc[.ini],
14 14 # so consider yourself warned!
15 15
16 16 import ipy_defaults
17 17
18 18 def main():
19 19 ip = ipapi.get()
20 20 o = ip.options
21 21 # autocall to "full" mode (smart mode is default, I like full mode)
22 22
23 23 o.autocall = 2
24 24
25 25 # Jason Orendorff's path class is handy to have in user namespace
26 26 # if you are doing shell-like stuff
27 27 try:
28 28 ip.ex("from IPython.external.path import path" )
29 29 except ImportError:
30 30 pass
31 31
32 32 # beefed up %env is handy in shell mode
33 33 import envpersist
34 34
35 35 # To see where mycmd resides (in path/aliases), do %which mycmd
36 36 import ipy_which
37 37
38 38 # tab completers for hg, svn, ...
39 39 import ipy_app_completers
40 40
41 41 # To make executables foo and bar in mybin usable without PATH change, do:
42 42 # %rehashdir c:/mybin
43 43 # %store foo
44 44 # %store bar
45 45 import ipy_rehashdir
46 46
47 47 # does not work without subprocess module!
48 48 #import ipy_signals
49 49
50 50 ip.ex('import os')
51 51 ip.ex("def up(): os.chdir('..')")
52 52 ip.user_ns['LA'] = LastArgFinder()
53 53 # Nice prompt
54 54
55 55 o.prompt_in1= r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
56 56 o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> '
57 57 o.prompt_out= '<\#> '
58 58
59 59 from IPython import Release
60 60
61 61 import sys
62 62 # Non-chatty banner
63 63 o.banner = "IPython %s [on Py %s]\n" % (Release.version,sys.version.split(None,1)[0])
64 64
65 65
66 66 ip.IP.default_option('cd','-q')
67 67 ip.IP.default_option('macro', '-r')
68 68 # If you only rarely want to execute the things you %edit...
69 69 #ip.IP.default_option('edit','-x')
70 70
71 71
72 72 o.prompts_pad_left="1"
73 73 # Remove all blank lines in between prompts, like a normal shell.
74 74 o.separate_in="0"
75 75 o.separate_out="0"
76 76 o.separate_out2="0"
77 77
78 78 # now alias all syscommands
79 79
80 80 db = ip.db
81 81
82 82 syscmds = db.get("syscmdlist",[] )
83 83 if not syscmds:
84 84 print textwrap.dedent("""
85 85 System command list not initialized, probably the first run...
86 86 running %rehashx to refresh the command list. Run %rehashx
87 87 again to refresh command list (after installing new software etc.)
88 88 """)
89 89 ip.magic('rehashx')
90 90 syscmds = db.get("syscmdlist")
91 91
92 92 # lowcase aliases on win32 only
93 93 if os.name == 'posix':
94 94 mapper = lambda s:s
95 95 else:
96 96 def mapper(s): return s.lower()
97 97
98 98 for cmd in syscmds:
99 99 # print "sys",cmd #dbg
100 100 noext, ext = os.path.splitext(cmd)
101 101 key = mapper(noext)
102 102 if key not in ip.IP.alias_table:
103 103 ip.defalias(key, cmd)
104 104
105 105 # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more
106 106 ip.load("IPython.external.mglob")
107 107
108 108 # win32 is crippled w/o cygwin, try to help it a little bit
109 109 if sys.platform == 'win32':
110 110 if 'cygwin' in os.environ['PATH'].lower():
111 111 # use the colors of cygwin ls (recommended)
112 112 ip.defalias('d', 'ls -F --color=auto')
113 113 else:
114 114 # get icp, imv, imkdir, igrep, irm,...
115 115 ip.load('ipy_fsops')
116 116
117 117 # and the next best thing to real 'ls -F'
118 118 ip.defalias('d','dir /w /og /on')
119 119
120 ip.set_hook('input_prefilter', dotslash_prefilter_f)
120 121 extend_shell_behavior(ip)
121 122
122 123 class LastArgFinder:
123 124 """ Allow $LA to work as "last argument of previous command", like $! in bash
124 125
125 126 To call this in normal IPython code, do LA()
126 127 """
127 128 def __call__(self, hist_idx = None):
128 129 ip = ipapi.get()
129 130 if hist_idx is None:
130 131 return str(self)
131 132 return ip.IP.input_hist_raw[hist_idx].strip().split()[-1]
132 133 def __str__(self):
133 134 ip = ipapi.get()
134 135 for cmd in reversed(ip.IP.input_hist_raw):
135 136 parts = cmd.strip().split()
136 137 if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']:
137 138 continue
138 139 return parts[-1]
139 140 return ""
140 141
141
142
143
142 def dotslash_prefilter_f(self,line):
143 """ ./foo now runs foo as system command
144
145 Removes the need for doing !./foo
146 """
147 import IPython.genutils
148 if line.startswith("./"):
149 return "_ip.system(" + IPython.genutils.make_quoted_expr(line)+")"
150 raise ipapi.TryNext
144 151
145 152 # XXX You do not need to understand the next function!
146 153 # This should probably be moved out of profile
147 154
148 155 def extend_shell_behavior(ip):
149 156
150 157 # Instead of making signature a global variable tie it to IPSHELL.
151 158 # In future if it is required to distinguish between different
152 159 # shells we can assign a signature per shell basis
153 160 ip.IP.__sig__ = 0xa005
154 161 # mark the IPSHELL with this signature
155 162 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
156 163
157 164 from IPython.Itpl import ItplNS
158 165 from IPython.genutils import shell
159 166 # utility to expand user variables via Itpl
160 167 # xxx do something sensible with depth?
161 168 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
162 169 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
163 170
164 171 def get_locals():
165 172 """ Substituting a variable through Itpl deep inside the IPSHELL stack
166 173 requires the knowledge of all the variables in scope upto the last
167 174 IPSHELL frame. This routine simply merges all the local variables
168 175 on the IPSHELL stack without worrying about their scope rules
169 176 """
170 177 import sys
171 178 # note lambda expression constitues a function call
172 179 # hence fno should be incremented by one
173 180 getsig = lambda fno: sys._getframe(fno+1).f_globals \
174 181 ['__builtins__'].__dict__['__sig__']
175 182 getlvars = lambda fno: sys._getframe(fno+1).f_locals
176 183 # trackback until we enter the IPSHELL
177 184 frame_no = 1
178 185 sig = ip.IP.__sig__
179 186 fsig = ~sig
180 187 while fsig != sig :
181 188 try:
182 189 fsig = getsig(frame_no)
183 190 except (AttributeError, KeyError):
184 191 frame_no += 1
185 192 except ValueError:
186 193 # stack is depleted
187 194 # call did not originate from IPSHELL
188 195 return {}
189 196 first_frame = frame_no
190 197 # walk further back until we exit from IPSHELL or deplete stack
191 198 try:
192 199 while(sig == getsig(frame_no+1)):
193 200 frame_no += 1
194 201 except (AttributeError, KeyError, ValueError):
195 202 pass
196 203 # merge the locals from top down hence overriding
197 204 # any re-definitions of variables, functions etc.
198 205 lvars = {}
199 206 for fno in range(frame_no, first_frame-1, -1):
200 207 lvars.update(getlvars(fno))
201 208 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
202 209 return lvars
203 210
204 211 def _runlines(lines):
205 212 """Run a string of one or more lines of source.
206 213
207 214 This method is capable of running a string containing multiple source
208 215 lines, as if they had been entered at the IPython prompt. Since it
209 216 exposes IPython's processing machinery, the given strings can contain
210 217 magic calls (%magic), special shell access (!cmd), etc."""
211 218
212 219 # We must start with a clean buffer, in case this is run from an
213 220 # interactive IPython session (via a magic, for example).
214 221 ip.IP.resetbuffer()
215 222 lines = lines.split('\n')
216 223 more = 0
217 224 command = ''
218 225 for line in lines:
219 226 # skip blank lines so we don't mess up the prompt counter, but do
220 227 # NOT skip even a blank line if we are in a code block (more is
221 228 # true)
222 229 # if command is not empty trim the line
223 230 if command != '' :
224 231 line = line.strip()
225 232 # add the broken line to the command
226 233 if line and line[-1] == '\\' :
227 234 command += line[0:-1] + ' '
228 235 more = True
229 236 continue
230 237 else :
231 238 # add the last (current) line to the command
232 239 command += line
233 240 if command or more:
234 241 # push to raw history, so hist line numbers stay in sync
235 242 ip.IP.input_hist_raw.append("# " + command + "\n")
236 243
237 244 more = ip.IP.push(ip.IP.prefilter(command,more))
238 245 command = ''
239 246 # IPython's runsource returns None if there was an error
240 247 # compiling the code. This allows us to stop processing right
241 248 # away, so the user gets the error message at the right place.
242 249 if more is None:
243 250 break
244 251 # final newline in case the input didn't have it, so that the code
245 252 # actually does get executed
246 253 if more:
247 254 ip.IP.push('\n')
248 255
249 256 ip.IP.runlines = _runlines
250 257
251 258 main()
@@ -1,161 +1,162 b''
1 1 .. _changes:
2 2
3 3 ==========
4 4 What's new
5 5 ==========
6 6
7 7 .. contents::
8 8
9 9 Release 0.9
10 10 ===========
11 11
12 12 New features
13 13 ------------
14 14
15 15 * All of the parallel computing capabilities from `ipython1-dev` have been merged into
16 16 IPython proper. This resulted in the following new subpackages:
17 17 :mod:`IPython.kernel`, :mod:`IPython.kernel.core`, :mod:`IPython.config`,
18 18 :mod:`IPython.tools` and :mod:`IPython.testing`.
19 19 * As part of merging in the `ipython1-dev` stuff, the `setup.py` script and friends
20 20 have been completely refactored. Now we are checking for dependencies using
21 21 the approach that matplotlib uses.
22 22 * The documentation has been completely reorganized to accept the documentation
23 23 from `ipython1-dev`.
24 24 * We have switched to using Foolscap for all of our network protocols in
25 25 :mod:`IPython.kernel`. This gives us secure connections that are both encrypted
26 26 and authenticated.
27 27 * We have a brand new `COPYING.txt` files that describes the IPython license
28 28 and copyright. The biggest change is that we are putting "The IPython
29 29 Development Team" as the copyright holder. We give more details about exactly
30 30 what this means in this file. All developer should read this and use the new
31 31 banner in all IPython source code files.
32 * sh profile: ./foo runs foo as system command, no need to do !./foo anymore
32 33
33 34 Bug fixes
34 35 ---------
35 36
36 37 * A few subpackages has missing `__init__.py` files.
37 38 * The documentation is only created is Sphinx is found. Previously, the `setup.py`
38 39 script would fail if it was missing.
39 40
40 41 Backwards incompatible changes
41 42 ------------------------------
42 43
43 44 * IPython has a larger set of dependencies if you want all of its capabilities.
44 45 See the `setup.py` script for details.
45 46 * The constructors for :class:`IPython.kernel.client.MultiEngineClient` and
46 47 :class:`IPython.kernel.client.TaskClient` no longer take the (ip,port) tuple.
47 48 Instead they take the filename of a file that contains the FURL for that
48 49 client. If the FURL file is in your IPYTHONDIR, it will be found automatically
49 50 and the constructor can be left empty.
50 51 * The asynchronous clients in :mod:`IPython.kernel.asyncclient` are now created
51 52 using the factory functions :func:`get_multiengine_client` and
52 53 :func:`get_task_client`. These return a `Deferred` to the actual client.
53 54 * The command line options to `ipcontroller` and `ipengine` have changed to
54 55 reflect the new Foolscap network protocol and the FURL files. Please see the
55 56 help for these scripts for details.
56 57 * The configuration files for the kernel have changed because of the Foolscap stuff.
57 58 If you were using custom config files before, you should delete them and regenerate
58 59 new ones.
59 60
60 61 Changes merged in from IPython1
61 62 -------------------------------
62 63
63 64 New features
64 65 ............
65 66
66 67 * Much improved ``setup.py`` and ``setupegg.py`` scripts. Because Twisted
67 68 and zope.interface are now easy installable, we can declare them as dependencies
68 69 in our setupegg.py script.
69 70 * IPython is now compatible with Twisted 2.5.0 and 8.x.
70 71 * Added a new example of how to use :mod:`ipython1.kernel.asynclient`.
71 72 * Initial draft of a process daemon in :mod:`ipython1.daemon`. This has not
72 73 been merged into IPython and is still in `ipython1-dev`.
73 74 * The ``TaskController`` now has methods for getting the queue status.
74 75 * The ``TaskResult`` objects not have information about how long the task
75 76 took to run.
76 77 * We are attaching additional attributes to exceptions ``(_ipython_*)`` that
77 78 we use to carry additional info around.
78 79 * New top-level module :mod:`asyncclient` that has asynchronous versions (that
79 80 return deferreds) of the client classes. This is designed to users who want
80 81 to run their own Twisted reactor
81 82 * All the clients in :mod:`client` are now based on Twisted. This is done by
82 83 running the Twisted reactor in a separate thread and using the
83 84 :func:`blockingCallFromThread` function that is in recent versions of Twisted.
84 85 * Functions can now be pushed/pulled to/from engines using
85 86 :meth:`MultiEngineClient.push_function` and :meth:`MultiEngineClient.pull_function`.
86 87 * Gather/scatter are now implemented in the client to reduce the work load
87 88 of the controller and improve performance.
88 89 * Complete rewrite of the IPython docuementation. All of the documentation
89 90 from the IPython website has been moved into docs/source as restructured
90 91 text documents. PDF and HTML documentation are being generated using
91 92 Sphinx.
92 93 * New developer oriented documentation: development guidelines and roadmap.
93 94 * Traditional ``ChangeLog`` has been changed to a more useful ``changes.txt`` file
94 95 that is organized by release and is meant to provide something more relevant
95 96 for users.
96 97
97 98 Bug fixes
98 99 .........
99 100
100 101 * Created a proper ``MANIFEST.in`` file to create source distributions.
101 102 * Fixed a bug in the ``MultiEngine`` interface. Previously, multi-engine
102 103 actions were being collected with a :class:`DeferredList` with
103 104 ``fireononeerrback=1``. This meant that methods were returning
104 105 before all engines had given their results. This was causing extremely odd
105 106 bugs in certain cases. To fix this problem, we have 1) set
106 107 ``fireononeerrback=0`` to make sure all results (or exceptions) are in
107 108 before returning and 2) introduced a :exc:`CompositeError` exception
108 109 that wraps all of the engine exceptions. This is a huge change as it means
109 110 that users will have to catch :exc:`CompositeError` rather than the actual
110 111 exception.
111 112
112 113 Backwards incompatible changes
113 114 ..............................
114 115
115 116 * All names have been renamed to conform to the lowercase_with_underscore
116 117 convention. This will require users to change references to all names like
117 118 ``queueStatus`` to ``queue_status``.
118 119 * Previously, methods like :meth:`MultiEngineClient.push` and
119 120 :meth:`MultiEngineClient.push` used ``*args`` and ``**kwargs``. This was
120 121 becoming a problem as we weren't able to introduce new keyword arguments into
121 122 the API. Now these methods simple take a dict or sequence. This has also allowed
122 123 us to get rid of the ``*All`` methods like :meth:`pushAll` and :meth:`pullAll`.
123 124 These things are now handled with the ``targets`` keyword argument that defaults
124 125 to ``'all'``.
125 126 * The :attr:`MultiEngineClient.magicTargets` has been renamed to
126 127 :attr:`MultiEngineClient.targets`.
127 128 * All methods in the MultiEngine interface now accept the optional keyword argument
128 129 ``block``.
129 130 * Renamed :class:`RemoteController` to :class:`MultiEngineClient` and
130 131 :class:`TaskController` to :class:`TaskClient`.
131 132 * Renamed the top-level module from :mod:`api` to :mod:`client`.
132 133 * Most methods in the multiengine interface now raise a :exc:`CompositeError` exception
133 134 that wraps the user's exceptions, rather than just raising the raw user's exception.
134 135 * Changed the ``setupNS`` and ``resultNames`` in the ``Task`` class to ``push``
135 136 and ``pull``.
136 137
137 138 Release 0.8.4
138 139 =============
139 140
140 141 Someone needs to describe what went into 0.8.4.
141 142
142 143 Release 0.8.2
143 144 =============
144 145
145 146 * %pushd/%popd behave differently; now "pushd /foo" pushes CURRENT directory
146 147 and jumps to /foo. The current behaviour is closer to the documented
147 148 behaviour, and should not trip anyone.
148 149
149 150 Release 0.8.3
150 151 =============
151 152
152 153 * pydb is now disabled by default (due to %run -d problems). You can enable
153 154 it by passing -pydb command line argument to IPython. Note that setting
154 155 it in config file won't work.
155 156
156 157 Older releases
157 158 ==============
158 159
159 160 Changes in earlier releases of IPython are described in the older file ``ChangeLog``.
160 161 Please refer to this document for details.
161 162
General Comments 0
You need to be logged in to leave comments. Login now