##// END OF EJS Templates
merge
vivainio2 -
r1077:c10b8067 merge
parent child Browse files
Show More
@@ -0,0 +1,239
1 """ Integration with gvim, by Erich Heine
2
3 Provides a %vim magic command, and reuses the same vim session. Uses
4 unix domain sockets for communication between vim and IPython. ipy.vim is
5 available in doc/examples of the IPython distribution.
6
7 Slightly touched up email announcement (and description how to use it) by
8 Erich Heine is here:
9
10 Ive recently been playing with ipython, and like it quite a bit. I did
11 however discover a bit of frustration, namely with editor interaction.
12 I am a gvim user, and using the command edit on a new file causes
13 ipython to try and run that file as soon as the text editor opens
14 up. The -x command of course fixes this, but its still a bit annoying,
15 switching windows to do a run file, then back to the text
16 editor. Being a heavy tab user in gvim, another annoyance is not being
17 able to specify weather a new tab is how I choose to open the file.
18
19 Not being one to shirk my open source duties (and seeing this as a
20 good excuse to poke around ipython internals), Ive created a script
21 for having gvim and ipython work very nicely together. Ive attached
22 both to this email (hoping of course that the mailing list allows such
23 things).
24
25 There are 2 files:
26
27 ipy_vimserver.py -- this file contains the ipython stuff
28 ipy.vim -- this file contains the gvim stuff
29
30 In combination they allow for a few functionalities:
31
32 #1. the vim magic command. This is a fancy wrapper around the edit
33 magic, that allows for a new option, -t, which opens the text in a new
34 gvim tab. Otherwise it works the same as edit -x. (it internally
35 calls edit -x). This magic command also juggles vim server management,
36 so when it is called when there is not a gvim running, it creates a
37 new gvim instance, named after the ipython session name. Once such a
38 gvim instance is running, it will be used for subsequent uses of the
39 vim command.
40
41 #2. ipython - gvim interaction. Once a file has been opened with the
42 vim magic (and a session set up, see below), pressing the F5 key in
43 vim will cause the calling ipython instance to execute run
44 filename.py. (if you typo like I do, this is very useful)
45
46 #3. ipython server - this is a thread wich listens on a unix domain
47 socket, and runs commands sent to that socket.
48
49 Note, this only works on POSIX systems, that allow for AF_UNIX type
50 sockets. It has only been tested on linux (a fairly recent debian
51 testing distro).
52
53 To install it put, the ipserver.py in your favorite locaion for
54 sourcing ipython scripts. I put the ipy.vim in
55 ~/.vim/after/ftplugin/python/.
56
57 To use (this can be scripted im sure, but i usually have 2 or 3
58 ipythons and corresponding gvims open):
59
60 import ipy_vimserver
61 ipy_vimserver.setup('sessionname')
62
63 (Editors note - you can probably add these to your ipy_user_conf.py)
64
65 Then use ipython as you normally would, until you need to edit
66 something. Instead of edit, use the vim magic. Thats it!
67
68 """
69
70 import IPython.ipapi
71 #import ipythonhooks
72 import socket, select
73 import os, threading, subprocess
74 import re
75
76 ERRCONDS = select.POLLHUP|select.POLLERR
77 SERVER = None
78 ip = IPython.ipapi.get()
79
80 # this listens to a unix domain socket in a separate thread, so that comms
81 # between a vim instance and ipython can happen in a fun and productive way
82 class IpyServer(threading.Thread):
83 def __init__(self, sname):
84 super(IpyServer, self).__init__()
85 self.keep_running = True
86 self.__sname = sname
87 self.socket = socket.socket(socket.AF_UNIX)
88 self.poller = select.poll()
89 self.current_conns = dict()
90 self.setDaemon(True)
91
92 def listen(self):
93 self.socket.bind(self.__sname)
94 self.socket.listen(1)
95
96 def __handle_error(self, socket):
97 if socket == self.socket.fileno():
98 self.keep_running = False
99 for a in self.current_conns.values():
100 a.close()
101 return False
102 else:
103 y = self.current_conns[socket]
104 del self.current_conns[socket]
105 y.close()
106 self.poller.unregister(socket)
107
108 def serve_me(self):
109 self.listen()
110 self.poller.register(self.socket,select.POLLIN|ERRCONDS)
111
112 while self.keep_running:
113 try:
114 avail = self.poller.poll(1)
115 except:
116 continue
117
118 if not avail: continue
119
120 for sock, conds in avail:
121 if conds & (ERRCONDS):
122 if self.__handle_error(sock): continue
123 else: break
124
125 if sock == self.socket.fileno():
126 y = self.socket.accept()[0]
127 self.poller.register(y, select.POLLIN|ERRCONDS)
128 self.current_conns[y.fileno()] = y
129 else: y = self.current_conns.get(sock)
130
131 self.handle_request(y)
132
133 os.remove(self.__sname)
134
135 run = serve_me
136
137 def stop(self):
138 self.keep_running = False
139
140 def handle_request(self,sock):
141 sock.settimeout(1)
142 while self.keep_running:
143 try:
144 x = sock.recv(4096)
145 except socket.timeout:
146 pass
147 else:
148 break
149 self.do_it(x)
150
151 def do_it(self, data):
152 data = data.split('\n')
153 cmds = list()
154 for line in data:
155 cmds.append(line)
156 ip.runlines(cmds)
157
158
159 # try to help ensure that the unix domain socket is cleaned up proper
160 def shutdown_server(self):
161 if SERVER:
162 SERVER.stop()
163 SERVER.join(3)
164 raise IPython.ipapi.TryNext
165
166 ip.set_hook('shutdown_hook', shutdown_server, 10)
167
168 # this fun function exists to make setup easier for all, and makes the
169 # vimhook function ready for instance specific communication
170 def setup(sessionname='',socketdir=os.path.expanduser('~/.ipython/')):
171 global SERVER
172
173 if sessionname:
174 session = sessionname
175 elif os.environ.get('IPY_SESSION'):
176 session = os.environ.get('IPY_SESSION')
177 else:
178 session = 'IPYS'
179 vimhook.vimserver=session
180 vimhook.ipyserver = os.path.join(socketdir, session)
181 if not SERVER:
182 SERVER = IpyServer(vimhook.ipyserver)
183 SERVER.start()
184
185
186
187 # calls gvim, with all ops happening on the correct gvim instance for this
188 # ipython instance. it then calls edit -x (since gvim will return right away)
189 # things of note: it sets up a special environment, so that the ipy.vim script
190 # can connect back to the ipython instance and do fun things, like run the file
191 def vimhook(self, fname, line):
192 env = os.environ.copy()
193 vserver = vimhook.vimserver.upper()
194 check = subprocess.Popen('gvim --serverlist', stdout = subprocess.PIPE,
195 shell=True)
196 check.wait()
197 cval = [l for l in check.stdout.readlines() if vserver in l]
198
199 if cval:
200 vimargs = '--remote%s' % (vimhook.extras,)
201 else:
202 vimargs = ''
203 vimhook.extras = ''
204
205 env['IPY_SESSION'] = vimhook.vimserver
206 env['IPY_SERVER'] = vimhook.ipyserver
207
208 if line is None: line = ''
209 else: line = '+' + line
210 vim_cmd = 'gvim --servername %s %s %s %s' % (vimhook.vimserver, vimargs,
211 line, fname)
212 subprocess.call(vim_cmd, env=env, shell=True)
213
214
215 #default values to keep it sane...
216 vimhook.vimserver = ''
217 vimhook.ipyserver = ''
218
219 ip.set_hook('editor',vimhook)
220
221 # this is set up so more vim specific commands can be added, instead of just
222 # the current -t. all thats required is a compiled regex, a call to do_arg(pat)
223 # and the logic to deal with the new feature
224 newtab = re.compile(r'-t(?:\s|$)')
225 def vim(self, argstr):
226 def do_arg(pat, rarg):
227 x = len(pat.findall(argstr))
228 if x:
229 a = pat.sub('',argstr)
230 return rarg, a
231 else: return '', argstr
232
233 t, argstr = do_arg(newtab, '-tab')
234 vimhook.extras = t
235 argstr = 'edit -x ' + argstr
236 ip.magic(argstr)
237
238 ip.expose_magic('vim', vim)
239
@@ -0,0 +1,67
1 if !exists("$IPY_SESSION")
2 finish
3 endif
4
5 " set up the python interpreter within vim, to have all the right modules
6 " imported, as well as certain useful globals set
7 python import socket
8 python import os
9 python import vim
10 python IPYSERVER = None
11
12 python << EOF
13 # do we have a connection to the ipython instance?
14 def check_server():
15 global IPYSERVER
16 if IPYSERVER:
17 return True
18 else:
19 return False
20
21 # connect to the ipython server, if we need to
22 def connect():
23 global IPYSERVER
24 if check_server():
25 return
26 try:
27 IPYSERVER = socket.socket(socket.AF_UNIX)
28 IPYSERVER.connect(os.environ.get('IPY_SERVER'))
29 except:
30 IPYSERVER = None
31
32 def disconnect():
33 if IPYSERVER:
34 IPYSERVER.close()
35
36 def send(cmd):
37 x = 0
38 while True:
39 x += IPYSERVER.send(cmd)
40 if x < len(cmd):
41 cmd = cmd[x:]
42 else:
43 break
44
45 def run_this_file():
46 if check_server():
47 send('run %s' % (vim.current.buffer.name,))
48 else:
49 raise Exception, "Not connected to an IPython server"
50 EOF
51
52 fun! <SID>toggle_send_on_save()
53 if exists("s:ssos") && s:ssos == 1
54 let s:ssos = 0
55 au! BufWritePost *.py :py run_this_file()
56 echo "Autosend Off"
57 else
58 let s:ssos = 1
59 au BufWritePost *.py :py run_this_file()
60 echo "Autowsend On"
61 endif
62 endfun
63
64 map <silent> <F5> :python run_this_file()<CR>
65 imap <silent> <C-F5> <ESC><F5>a
66 map <F7> :call <SID>toggle_send_on_save()<CR>
67 py connect()
@@ -1,354 +1,359
1 1 #!/usr/bin/env python
2 2
3 3 """ Implementations for various useful completers
4 4
5 5 See Extensions/ipy_stock_completers.py on examples of how to enable a completer,
6 6 but the basic idea is to do:
7 7
8 8 ip.set_hook('complete_command', svn_completer, str_key = 'svn')
9 9
10 10 """
11 11 import IPython.ipapi
12 12 import glob,os,shlex,sys
13 13 import inspect
14 14 from time import time
15 15 ip = IPython.ipapi.get()
16 16
17 17 try:
18 18 set
19 19 except:
20 20 from sets import Set as set
21 21
22 22 TIMEOUT_STORAGE = 3 #Time in seconds after which the rootmodules will be stored
23 23 TIMEOUT_GIVEUP = 20 #Time in seconds after which we give up
24 24
25 25 def quick_completer(cmd, completions):
26 26 """ Easily create a trivial completer for a command.
27 27
28 28 Takes either a list of completions, or all completions in string
29 29 (that will be split on whitespace)
30 30
31 31 Example::
32 32
33 33 [d:\ipython]|1> import ipy_completers
34 34 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
35 35 [d:\ipython]|3> foo b<TAB>
36 36 bar baz
37 37 [d:\ipython]|3> foo ba
38 38 """
39 39 if isinstance(completions, basestring):
40 40
41 41 completions = completions.split()
42 42 def do_complete(self,event):
43 43 return completions
44 44
45 45 ip.set_hook('complete_command',do_complete, str_key = cmd)
46 46
47 47 def getRootModules():
48 48 """
49 49 Returns a list containing the names of all the modules available in the
50 50 folders of the pythonpath.
51 51 """
52 52 modules = []
53 53 if ip.db.has_key('rootmodules'):
54 54 return ip.db['rootmodules']
55 55 t = time()
56 56 store = False
57 57 for path in sys.path:
58 58 modules += moduleList(path)
59 59 if time() - t >= TIMEOUT_STORAGE and not store:
60 60 store = True
61 61 print "\nCaching the list of root modules, please wait!"
62 62 print "(This will only be done once - type '%rehashx' to " + \
63 63 "reset cache!)"
64 64 print
65 65 if time() - t > TIMEOUT_GIVEUP:
66 66 print "This is taking too long, we give up."
67 67 print
68 68 ip.db['rootmodules'] = []
69 69 return []
70 70
71 71 modules += sys.builtin_module_names
72 72
73 73 modules = list(set(modules))
74 74 if '__init__' in modules:
75 75 modules.remove('__init__')
76 76 modules = list(set(modules))
77 77 if store:
78 78 ip.db['rootmodules'] = modules
79 79 return modules
80 80
81 81 def moduleList(path):
82 82 """
83 83 Return the list containing the names of the modules available in the given
84 84 folder.
85 85 """
86 86
87 87 if os.path.isdir(path):
88 88 folder_list = os.listdir(path)
89 89 else:
90 90 folder_list = []
91 91 #folder_list = glob.glob(os.path.join(path,'*'))
92 92 folder_list = [p for p in folder_list \
93 93 if os.path.exists(os.path.join(path, p,'__init__.py'))\
94 94 or p[-3:] in ('.py','.so')\
95 95 or p[-4:] in ('.pyc','.pyo')]
96 96
97 97 folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
98 98 return folder_list
99 99
100 100 def moduleCompletion(line):
101 101 """
102 102 Returns a list containing the completion possibilities for an import line.
103 103 The line looks like this :
104 104 'import xml.d'
105 105 'from xml.dom import'
106 106 """
107 107 def tryImport(mod, only_modules=False):
108 108 def isImportable(module, attr):
109 109 if only_modules:
110 110 return inspect.ismodule(getattr(module, attr))
111 111 else:
112 112 return not(attr[:2] == '__' and attr[-2:] == '__')
113 113 try:
114 114 m = __import__(mod)
115 115 except:
116 116 return []
117 117 mods = mod.split('.')
118 118 for module in mods[1:]:
119 119 m = getattr(m,module)
120 120 if (not hasattr(m, '__file__')) or (not only_modules) or\
121 121 (hasattr(m, '__file__') and '__init__' in m.__file__):
122 122 completion_list = [attr for attr in dir(m) if isImportable(m, attr)]
123 123 completion_list.extend(getattr(m,'__all__',[]))
124 124 if hasattr(m, '__file__') and '__init__' in m.__file__:
125 125 completion_list.extend(moduleList(os.path.dirname(m.__file__)))
126 126 completion_list = list(set(completion_list))
127 127 if '__init__' in completion_list:
128 128 completion_list.remove('__init__')
129 129 return completion_list
130 130
131 131 words = line.split(' ')
132 132 if len(words) == 3 and words[0] == 'from':
133 133 return ['import ']
134 134 if len(words) < 3 and (words[0] in ['import','from']) :
135 135 if len(words) == 1:
136 136 return getRootModules()
137 137 mod = words[1].split('.')
138 138 if len(mod) < 2:
139 139 return getRootModules()
140 140 completion_list = tryImport('.'.join(mod[:-1]), True)
141 141 completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
142 142 return completion_list
143 143 if len(words) >= 3 and words[0] == 'from':
144 144 mod = words[1]
145 145 return tryImport(mod)
146 146
147 147 def vcs_completer(commands, event):
148 148 """ utility to make writing typical version control app completers easier
149 149
150 150 VCS command line apps typically have the format:
151 151
152 152 [sudo ]PROGNAME [help] [command] file file...
153 153
154 154 """
155 155
156 156
157 157 cmd_param = event.line.split()
158 158 if event.line.endswith(' '):
159 159 cmd_param.append('')
160 160
161 161 if cmd_param[0] == 'sudo':
162 162 cmd_param = cmd_param[1:]
163 163
164 164 if len(cmd_param) == 2 or 'help' in cmd_param:
165 165 return commands.split()
166 166
167 167 return ip.IP.Completer.file_matches(event.symbol)
168 168
169 169
170 170 pkg_cache = None
171 171
172 172 def module_completer(self,event):
173 173 """ Give completions after user has typed 'import ...' or 'from ...'"""
174 174
175 175 # This works in all versions of python. While 2.5 has
176 176 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
177 177 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
178 178 # of possibly problematic side effects.
179 179 # This search the folders in the sys.path for available modules.
180 180
181 181 return moduleCompletion(event.line)
182 182
183 183
184 184 svn_commands = """\
185 185 add blame praise annotate ann cat checkout co cleanup commit ci copy
186 186 cp delete del remove rm diff di export help ? h import info list ls
187 187 lock log merge mkdir move mv rename ren propdel pdel pd propedit pedit
188 188 pe propget pget pg proplist plist pl propset pset ps resolved revert
189 189 status stat st switch sw unlock update
190 190 """
191 191
192 192 def svn_completer(self,event):
193 193 return vcs_completer(svn_commands, event)
194 194
195 195
196 196 hg_commands = """
197 197 add addremove annotate archive backout branch branches bundle cat
198 198 clone commit copy diff export grep heads help identify import incoming
199 199 init locate log manifest merge outgoing parents paths pull push
200 200 qapplied qclone qcommit qdelete qdiff qfold qguard qheader qimport
201 201 qinit qnew qnext qpop qprev qpush qrefresh qrename qrestore qsave
202 202 qselect qseries qtop qunapplied recover remove rename revert rollback
203 203 root serve showconfig status strip tag tags tip unbundle update verify
204 204 version
205 205 """
206 206
207 207 def hg_completer(self,event):
208 208 """ Completer for mercurial commands """
209 209
210 210 return vcs_completer(hg_commands, event)
211 211
212 212
213 213
214 __bzr_commands = None
215
214 216 def bzr_commands():
217 global __bzr_commands
218 if __bzr_commands is not None:
219 return __bzr_commands
215 220 out = os.popen('bzr help commands')
216 return [l.split()[0] for l in out]
217
221 __bzr_commands = [l.split()[0] for l in out]
222 return __bzr_commands
218 223
219 224 def bzr_completer(self,event):
220 225 """ Completer for bazaar commands """
221 226 cmd_param = event.line.split()
222 227 if event.line.endswith(' '):
223 228 cmd_param.append('')
224 229
225 230 if len(cmd_param) > 2:
226 231 cmd = cmd_param[1]
227 232 param = cmd_param[-1]
228 233 output_file = (param == '--output=')
229 234 if cmd == 'help':
230 235 return bzr_commands()
231 236 elif cmd in ['bundle-revisions','conflicts',
232 237 'deleted','nick','register-branch',
233 238 'serve','unbind','upgrade','version',
234 239 'whoami'] and not output_file:
235 240 return []
236 241 else:
237 242 # the rest are probably file names
238 243 return ip.IP.Completer.file_matches(event.symbol)
239 244
240 245 return bzr_commands()
241 246
242 247
243 248 def shlex_split(x):
244 249 """Helper function to split lines into segments."""
245 250 #shlex.split raise exception if syntax error in sh syntax
246 251 #for example if no closing " is found. This function keeps dropping
247 252 #the last character of the line until shlex.split does not raise
248 253 #exception. Adds end of the line to the result of shlex.split
249 254 #example: %run "c:/python -> ['%run','"c:/python']
250 255 endofline=[]
251 256 while x!="":
252 257 try:
253 258 comps=shlex.split(x)
254 259 if len(endofline)>=1:
255 260 comps.append("".join(endofline))
256 261 return comps
257 262 except ValueError:
258 263 endofline=[x[-1:]]+endofline
259 264 x=x[:-1]
260 265 return ["".join(endofline)]
261 266
262 267 def runlistpy(self, event):
263 268 comps = shlex_split(event.line)
264 269 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
265 270
266 271 #print "\nev=",event # dbg
267 272 #print "rp=",relpath # dbg
268 273 #print 'comps=',comps # dbg
269 274
270 275 lglob = glob.glob
271 276 isdir = os.path.isdir
272 277 if relpath.startswith('~'):
273 278 relpath = os.path.expanduser(relpath)
274 279 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*')
275 280 if isdir(f)]
276 281
277 282 # Find if the user has already typed the first filename, after which we
278 283 # should complete on all files, since after the first one other files may
279 284 # be arguments to the input script.
280 285 #filter(
281 286 if filter(lambda f: f.endswith('.py') or f.endswith('.ipy') or
282 287 f.endswith('.pyw'),comps):
283 288 pys = [f.replace('\\','/') for f in lglob('*')]
284 289 else:
285 290 pys = [f.replace('\\','/')
286 291 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
287 292 lglob(relpath + '*.pyw')]
288 293 return dirs + pys
289 294
290 295
291 296 def cd_completer(self, event):
292 297 relpath = event.symbol
293 298 #print event # dbg
294 299 if '-b' in event.line:
295 300 # return only bookmark completions
296 301 bkms = self.db.get('bookmarks',{})
297 302 return bkms.keys()
298 303
299 304
300 305 if event.symbol == '-':
301 306 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
302 307 # jump in directory history by number
303 308 fmt = '-%0' + width_dh +'d [%s]'
304 309 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
305 310 if len(ents) > 1:
306 311 return ents
307 312 return []
308 313
309 314 if relpath.startswith('~'):
310 315 relpath = os.path.expanduser(relpath).replace('\\','/')
311 316 found = []
312 317 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
313 318 if os.path.isdir(f)]:
314 319 if ' ' in d:
315 320 # we don't want to deal with any of that, complex code
316 321 # for this is elsewhere
317 322 raise IPython.ipapi.TryNext
318 323 found.append( d )
319 324
320 325 if not found:
321 326 if os.path.isdir(relpath):
322 327 return [relpath]
323 328 raise IPython.ipapi.TryNext
324 329 return found
325 330
326 331 def apt_get_packages(prefix):
327 332 out = os.popen('apt-cache pkgnames')
328 333 for p in out:
329 334 if p.startswith(prefix):
330 335 yield p.rstrip()
331 336
332 337
333 338 apt_commands = """\
334 339 update upgrade install remove purge source build-dep dist-upgrade
335 340 dselect-upgrade clean autoclean check"""
336 341
337 342 def apt_completer(self, event):
338 343 """ Completer for apt-get (uses apt-cache internally)
339 344
340 345 """
341 346
342 347
343 348 cmd_param = event.line.split()
344 349 if event.line.endswith(' '):
345 350 cmd_param.append('')
346 351
347 352 if cmd_param[0] == 'sudo':
348 353 cmd_param = cmd_param[1:]
349 354
350 355 if len(cmd_param) == 2 or 'help' in cmd_param:
351 356 return apt_commands.split()
352 357
353 358 return list(apt_get_packages(event.symbol))
354 359
@@ -1,575 +1,577
1 1 """ ILeo - Leo plugin for IPython
2 2
3 3
4 4 """
5 5 import IPython.ipapi
6 6 import IPython.genutils
7 7 import IPython.generics
8 8 from IPython.hooks import CommandChainDispatcher
9 9 import re
10 10 import UserDict
11 11 from IPython.ipapi import TryNext
12 12 import IPython.macro
13 import IPython.Shell
13 14
14 15 def init_ipython(ipy):
15 16 """ This will be run by _ip.load('ipy_leo')
16 17
17 18 Leo still needs to run update_commander() after this.
18 19
19 20 """
20 21 global ip
21 22 ip = ipy
23 IPython.Shell.hijack_tk()
22 24 ip.set_hook('complete_command', mb_completer, str_key = '%mb')
23 25 ip.expose_magic('mb',mb_f)
24 26 ip.expose_magic('lee',lee_f)
25 27 ip.expose_magic('leoref',leoref_f)
26 28 expose_ileo_push(push_cl_node,100)
27 29 # this should be the LAST one that will be executed, and it will never raise TryNext
28 30 expose_ileo_push(push_ipython_script, 1000)
29 31 expose_ileo_push(push_plain_python, 100)
30 32 expose_ileo_push(push_ev_node, 100)
31 33 global wb
32 34 wb = LeoWorkbook()
33 35 ip.user_ns['wb'] = wb
34 36
35 37 show_welcome()
36 38
37 39
38 40 def update_commander(new_leox):
39 41 """ Set the Leo commander to use
40 42
41 43 This will be run every time Leo does ipython-launch; basically,
42 44 when the user switches the document he is focusing on, he should do
43 45 ipython-launch to tell ILeo what document the commands apply to.
44 46
45 47 """
46 48
47 49 global c,g
48 50 c,g = new_leox.c, new_leox.g
49 51 print "Set Leo Commander:",c.frame.getTitle()
50 52
51 53 # will probably be overwritten by user, but handy for experimentation early on
52 54 ip.user_ns['c'] = c
53 55 ip.user_ns['g'] = g
54 56 ip.user_ns['_leo'] = new_leox
55 57
56 58 new_leox.push = push_position_from_leo
57 59 run_leo_startup_node()
58 60
59 61 from IPython.external.simplegeneric import generic
60 62 import pprint
61 63
62 64 def es(s):
63 65 g.es(s, tabName = 'IPython')
64 66 pass
65 67
66 68 @generic
67 69 def format_for_leo(obj):
68 70 """ Convert obj to string representiation (for editing in Leo)"""
69 71 return pprint.pformat(obj)
70 72
71 73 @format_for_leo.when_type(list)
72 74 def format_list(obj):
73 75 return "\n".join(str(s) for s in obj)
74 76
75 77
76 78 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
77 79 def valid_attribute(s):
78 80 return attribute_re.match(s)
79 81
80 82 _rootnode = None
81 83 def rootnode():
82 84 """ Get ileo root node (@ipy-root)
83 85
84 86 if node has become invalid or has not been set, return None
85 87
86 88 Note that the root is the *first* @ipy-root item found
87 89 """
88 90 global _rootnode
89 91 if _rootnode is None:
90 92 return None
91 93 if c.positionExists(_rootnode.p):
92 94 return _rootnode
93 95 _rootnode = None
94 96 return None
95 97
96 98 def all_cells():
97 99 global _rootnode
98 100 d = {}
99 101 r = rootnode()
100 102 if r is not None:
101 103 nodes = r.p.children_iter()
102 104 else:
103 105 nodes = c.allNodes_iter()
104 106
105 107 for p in nodes:
106 108 h = p.headString()
107 109 if h.strip() == '@ipy-root':
108 110 # update root node (found it for the first time)
109 111 _rootnode = LeoNode(p)
110 112 # the next recursive call will use the children of new root
111 113 return all_cells()
112 114
113 115 if h.startswith('@a '):
114 116 d[h.lstrip('@a ').strip()] = p.parent().copy()
115 117 elif not valid_attribute(h):
116 118 continue
117 119 d[h] = p.copy()
118 120 return d
119 121
120 122 def eval_node(n):
121 123 body = n.b
122 124 if not body.startswith('@cl'):
123 125 # plain python repr node, just eval it
124 126 return ip.ev(n.b)
125 127 # @cl nodes deserve special treatment - first eval the first line (minus cl), then use it to call the rest of body
126 128 first, rest = body.split('\n',1)
127 129 tup = first.split(None, 1)
128 130 # @cl alone SPECIAL USE-> dump var to user_ns
129 131 if len(tup) == 1:
130 132 val = ip.ev(rest)
131 133 ip.user_ns[n.h] = val
132 134 es("%s = %s" % (n.h, repr(val)[:20] ))
133 135 return val
134 136
135 137 cl, hd = tup
136 138
137 139 xformer = ip.ev(hd.strip())
138 140 es('Transform w/ %s' % repr(xformer))
139 141 return xformer(rest, n)
140 142
141 143 class LeoNode(object, UserDict.DictMixin):
142 144 """ Node in Leo outline
143 145
144 146 Most important attributes (getters/setters available:
145 147 .v - evaluate node, can also be alligned
146 148 .b, .h - body string, headline string
147 149 .l - value as string list
148 150
149 151 Also supports iteration,
150 152
151 153 setitem / getitem (indexing):
152 154 wb.foo['key'] = 12
153 155 assert wb.foo['key'].v == 12
154 156
155 157 Note the asymmetry on setitem and getitem! Also other
156 158 dict methods are available.
157 159
158 160 .ipush() - run push-to-ipython
159 161
160 162 Minibuffer command access (tab completion works):
161 163
162 164 mb save-to-file
163 165
164 166 """
165 167 def __init__(self,p):
166 168 self.p = p.copy()
167 169
168 170 def __str__(self):
169 171 return "<LeoNode %s>" % str(self.p)
170 172
171 173 __repr__ = __str__
172 174
173 175 def __get_h(self): return self.p.headString()
174 176 def __set_h(self,val):
175 177 print "set head",val
176 178 c.beginUpdate()
177 179 try:
178 180 c.setHeadString(self.p,val)
179 181 finally:
180 182 c.endUpdate()
181 183
182 184 h = property( __get_h, __set_h, doc = "Node headline string")
183 185
184 186 def __get_b(self): return self.p.bodyString()
185 187 def __set_b(self,val):
186 188 print "set body",val
187 189 c.beginUpdate()
188 190 try:
189 191 c.setBodyString(self.p, val)
190 192 finally:
191 193 c.endUpdate()
192 194
193 195 b = property(__get_b, __set_b, doc = "Nody body string")
194 196
195 197 def __set_val(self, val):
196 198 self.b = format_for_leo(val)
197 199
198 200 v = property(lambda self: eval_node(self), __set_val, doc = "Node evaluated value")
199 201
200 202 def __set_l(self,val):
201 203 self.b = '\n'.join(val )
202 204 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
203 205 __set_l, doc = "Node value as string list")
204 206
205 207 def __iter__(self):
206 208 """ Iterate through nodes direct children """
207 209
208 210 return (LeoNode(p) for p in self.p.children_iter())
209 211
210 212 def __children(self):
211 213 d = {}
212 214 for child in self:
213 215 head = child.h
214 216 tup = head.split(None,1)
215 217 if len(tup) > 1 and tup[0] == '@k':
216 218 d[tup[1]] = child
217 219 continue
218 220
219 221 if not valid_attribute(head):
220 222 d[head] = child
221 223 continue
222 224 return d
223 225 def keys(self):
224 226 d = self.__children()
225 227 return d.keys()
226 228 def __getitem__(self, key):
227 229 """ wb.foo['Some stuff'] Return a child node with headline 'Some stuff'
228 230
229 231 If key is a valid python name (e.g. 'foo'), look for headline '@k foo' as well
230 232 """
231 233 key = str(key)
232 234 d = self.__children()
233 235 return d[key]
234 236 def __setitem__(self, key, val):
235 237 """ You can do wb.foo['My Stuff'] = 12 to create children
236 238
237 239 This will create 'My Stuff' as a child of foo (if it does not exist), and
238 240 do .v = 12 assignment.
239 241
240 242 Exception:
241 243
242 244 wb.foo['bar'] = 12
243 245
244 246 will create a child with headline '@k bar', because bar is a valid python name
245 247 and we don't want to crowd the WorkBook namespace with (possibly numerous) entries
246 248 """
247 249 key = str(key)
248 250 d = self.__children()
249 251 if key in d:
250 252 d[key].v = val
251 253 return
252 254
253 255 if not valid_attribute(key):
254 256 head = key
255 257 else:
256 258 head = '@k ' + key
257 259 p = c.createLastChildNode(self.p, head, '')
258 260 LeoNode(p).v = val
259 261
260 262 def ipush(self):
261 263 """ Does push-to-ipython on the node """
262 264 push_from_leo(self)
263 265
264 266 def go(self):
265 267 """ Set node as current node (to quickly see it in Outline) """
266 268 c.beginUpdate()
267 269 try:
268 270 c.setCurrentPosition(self.p)
269 271 finally:
270 272 c.endUpdate()
271 273
272 274 def script(self):
273 275 """ Method to get the 'tangled' contents of the node
274 276
275 277 (parse @others, << section >> references etc.)
276 278 """
277 279 return g.getScript(c,self.p,useSelectedText=False,useSentinels=False)
278 280
279 281 def __get_uA(self):
280 282 p = self.p
281 283 # Create the uA if necessary.
282 284 if not hasattr(p.v.t,'unknownAttributes'):
283 285 p.v.t.unknownAttributes = {}
284 286
285 287 d = p.v.t.unknownAttributes.setdefault('ipython', {})
286 288 return d
287 289
288 290 uA = property(__get_uA, doc = "Access persistent unknownAttributes of node")
289 291
290 292
291 293 class LeoWorkbook:
292 294 """ class for 'advanced' node access
293 295
294 296 Has attributes for all "discoverable" nodes. Node is discoverable if it
295 297 either
296 298
297 299 - has a valid python name (Foo, bar_12)
298 300 - is a parent of an anchor node (if it has a child '@a foo', it is visible as foo)
299 301
300 302 """
301 303 def __getattr__(self, key):
302 304 if key.startswith('_') or key == 'trait_names' or not valid_attribute(key):
303 305 raise AttributeError
304 306 cells = all_cells()
305 307 p = cells.get(key, None)
306 308 if p is None:
307 309 return add_var(key)
308 310
309 311 return LeoNode(p)
310 312
311 313 def __str__(self):
312 314 return "<LeoWorkbook>"
313 315 def __setattr__(self,key, val):
314 316 raise AttributeError("Direct assignment to workbook denied, try wb.%s.v = %s" % (key,val))
315 317
316 318 __repr__ = __str__
317 319
318 320 def __iter__(self):
319 321 """ Iterate all (even non-exposed) nodes """
320 322 cells = all_cells()
321 323 return (LeoNode(p) for p in c.allNodes_iter())
322 324
323 325 current = property(lambda self: LeoNode(c.currentPosition()), doc = "Currently selected node")
324 326
325 327 def match_h(self, regex):
326 328 cmp = re.compile(regex)
327 329 for node in self:
328 330 if re.match(cmp, node.h, re.IGNORECASE):
329 331 yield node
330 332 return
331 333
332 334 @IPython.generics.complete_object.when_type(LeoWorkbook)
333 335 def workbook_complete(obj, prev):
334 336 return all_cells().keys() + [s for s in prev if not s.startswith('_')]
335 337
336 338
337 339 def add_var(varname):
338 340 c.beginUpdate()
339 341 r = rootnode()
340 342 try:
341 343 if r is None:
342 344 p2 = g.findNodeAnywhere(c,varname)
343 345 else:
344 346 p2 = g.findNodeInChildren(c, r.p, varname)
345 347 if p2:
346 348 return LeoNode(p2)
347 349
348 350 if r is not None:
349 351 p2 = r.p.insertAsLastChild()
350 352
351 353 else:
352 354 p2 = c.currentPosition().insertAfter()
353 355
354 356 c.setHeadString(p2,varname)
355 357 return LeoNode(p2)
356 358 finally:
357 359 c.endUpdate()
358 360
359 361 def add_file(self,fname):
360 362 p2 = c.currentPosition().insertAfter()
361 363
362 364 push_from_leo = CommandChainDispatcher()
363 365
364 366 def expose_ileo_push(f, prio = 0):
365 367 push_from_leo.add(f, prio)
366 368
367 369 def push_ipython_script(node):
368 370 """ Execute the node body in IPython, as if it was entered in interactive prompt """
369 371 c.beginUpdate()
370 372 try:
371 373 ohist = ip.IP.output_hist
372 374 hstart = len(ip.IP.input_hist)
373 375 script = node.script()
374 376
375 377 script = g.splitLines(script + '\n')
376 378 ip.user_ns['_p'] = node
377 379 ip.runlines(script)
378 380 ip.user_ns.pop('_p',None)
379 381
380 382 has_output = False
381 383 for idx in range(hstart,len(ip.IP.input_hist)):
382 384 val = ohist.get(idx,None)
383 385 if val is None:
384 386 continue
385 387 has_output = True
386 388 inp = ip.IP.input_hist[idx]
387 389 if inp.strip():
388 390 es('In: %s' % (inp[:40], ))
389 391
390 392 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
391 393
392 394 if not has_output:
393 395 es('ipy run: %s (%d LL)' %( node.h,len(script)))
394 396 finally:
395 397 c.endUpdate()
396 398
397 399
398 400 def eval_body(body):
399 401 try:
400 402 val = ip.ev(body)
401 403 except:
402 404 # just use stringlist if it's not completely legal python expression
403 405 val = IPython.genutils.SList(body.splitlines())
404 406 return val
405 407
406 408 def push_plain_python(node):
407 409 if not node.h.endswith('P'):
408 410 raise TryNext
409 411 script = node.script()
410 412 lines = script.count('\n')
411 413 try:
412 414 exec script in ip.user_ns
413 415 except:
414 416 print " -- Exception in script:\n"+script + "\n --"
415 417 raise
416 418 es('ipy plain: %s (%d LL)' % (node.h,lines))
417 419
418 420
419 421 def push_cl_node(node):
420 422 """ If node starts with @cl, eval it
421 423
422 424 The result is put as last child of @ipy-results node, if it exists
423 425 """
424 426 if not node.b.startswith('@cl'):
425 427 raise TryNext
426 428
427 429 p2 = g.findNodeAnywhere(c,'@ipy-results')
428 430 val = node.v
429 431 if p2:
430 432 es("=> @ipy-results")
431 433 LeoNode(p2).v = val
432 434 es(val)
433 435
434 436 def push_ev_node(node):
435 437 """ If headline starts with @ev, eval it and put result in body """
436 438 if not node.h.startswith('@ev '):
437 439 raise TryNext
438 440 expr = node.h.lstrip('@ev ')
439 441 es('ipy eval ' + expr)
440 442 res = ip.ev(expr)
441 443 node.v = res
442 444
443 445
444 446 def push_position_from_leo(p):
445 447 push_from_leo(LeoNode(p))
446 448
447 449 @generic
448 450 def edit_object_in_leo(obj, varname):
449 451 """ Make it @cl node so it can be pushed back directly by alt+I """
450 452 node = add_var(varname)
451 453 formatted = format_for_leo(obj)
452 454 if not formatted.startswith('@cl'):
453 455 formatted = '@cl\n' + formatted
454 456 node.b = formatted
455 457 node.go()
456 458
457 459 @edit_object_in_leo.when_type(IPython.macro.Macro)
458 460 def edit_macro(obj,varname):
459 461 bod = '_ip.defmacro("""\\\n' + obj.value + '""")'
460 462 node = add_var('Macro_' + varname)
461 463 node.b = bod
462 464 node.go()
463 465
464 466 def get_history(hstart = 0):
465 467 res = []
466 468 ohist = ip.IP.output_hist
467 469
468 470 for idx in range(hstart, len(ip.IP.input_hist)):
469 471 val = ohist.get(idx,None)
470 472 has_output = True
471 473 inp = ip.IP.input_hist_raw[idx]
472 474 if inp.strip():
473 475 res.append('In [%d]: %s' % (idx, inp))
474 476 if val:
475 477 res.append(pprint.pformat(val))
476 478 res.append('\n')
477 479 return ''.join(res)
478 480
479 481
480 482 def lee_f(self,s):
481 483 """ Open file(s)/objects in Leo
482 484
483 485 - %lee hist -> open full session history in leo
484 486 - Takes an object
485 487 - Takes an mglob pattern, e.g. '%lee *.cpp' or %leo 'rec:*.cpp'
486 488 """
487 489 import os
488 490
489 491 c.beginUpdate()
490 492 try:
491 493 if s == 'hist':
492 494 wb.ipython_history.b = get_history()
493 495 wb.ipython_history.go()
494 496 return
495 497
496 498
497 499
498 500 # try editing the object directly
499 501 obj = ip.user_ns.get(s, None)
500 502 if obj is not None:
501 503 edit_object_in_leo(obj,s)
502 504 return
503 505
504 506 # if it's not object, it's a file name / mglob pattern
505 507 from IPython.external import mglob
506 508
507 509 files = (os.path.abspath(f) for f in mglob.expand(s))
508 510 for fname in files:
509 511 p = g.findNodeAnywhere(c,'@auto ' + fname)
510 512 if not p:
511 513 p = c.currentPosition().insertAfter()
512 514
513 515 p.setHeadString('@auto ' + fname)
514 516 if os.path.isfile(fname):
515 517 c.setBodyString(p,open(fname).read())
516 518 c.selectPosition(p)
517 519 print "Editing file(s), press ctrl+shift+w in Leo to write @auto nodes"
518 520 finally:
519 521 c.endUpdate()
520 522
521 523
522 524
523 525 def leoref_f(self,s):
524 526 """ Quick reference for ILeo """
525 527 import textwrap
526 528 print textwrap.dedent("""\
527 529 %leoe file/object - open file / object in leo
528 530 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
529 531 wb.foo.v = 12 - assign to body of node foo
530 532 wb.foo.b - read or write the body of node foo
531 533 wb.foo.l - body of node foo as string list
532 534
533 535 for el in wb.foo:
534 536 print el.v
535 537
536 538 """
537 539 )
538 540
539 541
540 542
541 543 def mb_f(self, arg):
542 544 """ Execute leo minibuffer commands
543 545
544 546 Example:
545 547 mb save-to-file
546 548 """
547 549 c.executeMinibufferCommand(arg)
548 550
549 551 def mb_completer(self,event):
550 552 """ Custom completer for minibuffer """
551 553 cmd_param = event.line.split()
552 554 if event.line.endswith(' '):
553 555 cmd_param.append('')
554 556 if len(cmd_param) > 2:
555 557 return ip.IP.Completer.file_matches(event.symbol)
556 558 cmds = c.commandsDict.keys()
557 559 cmds.sort()
558 560 return cmds
559 561
560 562 def show_welcome():
561 563 print "------------------"
562 564 print "Welcome to Leo-enabled IPython session!"
563 565 print "Try %leoref for quick reference."
564 566 import IPython.platutils
565 567 IPython.platutils.set_term_title('ILeo')
566 568 IPython.platutils.freeze_term_title()
567 569
568 570 def run_leo_startup_node():
569 571 p = g.findNodeAnywhere(c,'@ipy-startup')
570 572 if p:
571 573 print "Running @ipy-startup nodes"
572 574 for n in LeoNode(p):
573 575 push_from_leo(n)
574 576
575 577
@@ -1,83 +1,87
1 1 # -*- coding: utf-8 -*-
2 2 """Release data for the IPython project.
3 3
4 4 $Id: Release.py 3002 2008-02-01 07:17:00Z fperez $"""
5 5
6 6 #*****************************************************************************
7 7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 8 #
9 9 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
10 10 # <n8gray@caltech.edu>
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #*****************************************************************************
15 15
16 16 # Name of the package for release purposes. This is the name which labels
17 17 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
18 18 name = 'ipython'
19 19
20 20 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
21 21 # the new substring. We have to avoid using either dashes or underscores,
22 22 # because bdist_rpm does not accept dashes (an RPM) convention, and
23 23 # bdist_deb does not accept underscores (a Debian convention).
24 24
25 revision = '46'
25 revision = '57'
26 branch = 'ipython'
26 27
27 version = '0.8.3.bzr.r' + revision
28 if branch == 'ipython':
29 version = '0.8.3.bzr.r' + revision
30 else:
31 version = '0.8.3.bzr.r%s.%s' % (revision,branch)
28 32
29 33 description = "An enhanced interactive Python shell."
30 34
31 35 long_description = \
32 36 """
33 37 IPython provides a replacement for the interactive Python interpreter with
34 38 extra functionality.
35 39
36 40 Main features:
37 41
38 42 * Comprehensive object introspection.
39 43
40 44 * Input history, persistent across sessions.
41 45
42 46 * Caching of output results during a session with automatically generated
43 47 references.
44 48
45 49 * Readline based name completion.
46 50
47 51 * Extensible system of 'magic' commands for controlling the environment and
48 52 performing many tasks related either to IPython or the operating system.
49 53
50 54 * Configuration system with easy switching between different setups (simpler
51 55 than changing $PYTHONSTARTUP environment variables every time).
52 56
53 57 * Session logging and reloading.
54 58
55 59 * Extensible syntax processing for special purpose situations.
56 60
57 61 * Access to the system shell with user-extensible alias system.
58 62
59 63 * Easily embeddable in other Python programs.
60 64
61 65 * Integrated access to the pdb debugger and the Python profiler.
62 66
63 67 The latest development version is always available at the IPython subversion
64 68 repository_.
65 69
66 70 .. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev
67 71 """
68 72
69 73 license = 'BSD'
70 74
71 75 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
72 76 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
73 77 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
74 78 'Ville' : ('Ville Vainio','vivainio@gmail.com')
75 79 }
76 80
77 81 url = 'http://ipython.scipy.org'
78 82
79 83 download_url = 'http://ipython.scipy.org/dist'
80 84
81 85 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
82 86
83 87 keywords = ['Interactive','Interpreter','Shell']
@@ -1,596 +1,597
1 1 ''' IPython customization API
2 2
3 3 Your one-stop module for configuring & extending ipython
4 4
5 5 The API will probably break when ipython 1.0 is released, but so
6 6 will the other configuration method (rc files).
7 7
8 8 All names prefixed by underscores are for internal use, not part
9 9 of the public api.
10 10
11 11 Below is an example that you can just put to a module and import from ipython.
12 12
13 13 A good practice is to install the config script below as e.g.
14 14
15 15 ~/.ipython/my_private_conf.py
16 16
17 17 And do
18 18
19 19 import_mod my_private_conf
20 20
21 21 in ~/.ipython/ipythonrc
22 22
23 23 That way the module is imported at startup and you can have all your
24 24 personal configuration (as opposed to boilerplate ipythonrc-PROFILENAME
25 25 stuff) in there.
26 26
27 27 -----------------------------------------------
28 28 import IPython.ipapi
29 29 ip = IPython.ipapi.get()
30 30
31 31 def ankka_f(self, arg):
32 32 print "Ankka",self,"says uppercase:",arg.upper()
33 33
34 34 ip.expose_magic("ankka",ankka_f)
35 35
36 36 ip.magic('alias sayhi echo "Testing, hi ok"')
37 37 ip.magic('alias helloworld echo "Hello world"')
38 38 ip.system('pwd')
39 39
40 40 ip.ex('import re')
41 41 ip.ex("""
42 42 def funcci(a,b):
43 43 print a+b
44 44 print funcci(3,4)
45 45 """)
46 46 ip.ex("funcci(348,9)")
47 47
48 48 def jed_editor(self,filename, linenum=None):
49 49 print "Calling my own editor, jed ... via hook!"
50 50 import os
51 51 if linenum is None: linenum = 0
52 52 os.system('jed +%d %s' % (linenum, filename))
53 53 print "exiting jed"
54 54
55 55 ip.set_hook('editor',jed_editor)
56 56
57 57 o = ip.options
58 58 o.autocall = 2 # FULL autocall mode
59 59
60 60 print "done!"
61 61 '''
62 62
63 63 # stdlib imports
64 64 import __builtin__
65 65 import sys
66 66
67 67 try: # Python 2.3 compatibility
68 68 set
69 69 except NameError:
70 70 import sets
71 71 set = sets.Set
72 72
73 73 # our own
74 74 #from IPython.genutils import warn,error
75 75
76 76 class TryNext(Exception):
77 77 """Try next hook exception.
78 78
79 79 Raise this in your hook function to indicate that the next hook handler
80 80 should be used to handle the operation. If you pass arguments to the
81 81 constructor those arguments will be used by the next hook instead of the
82 82 original ones.
83 83 """
84 84
85 85 def __init__(self, *args, **kwargs):
86 86 self.args = args
87 87 self.kwargs = kwargs
88 88
89 89 class UsageError(Exception):
90 90 """ Error in magic function arguments, etc.
91 91
92 92 Something that probably won't warrant a full traceback, but should
93 93 nevertheless interrupt a macro / batch file.
94 94 """
95 95
96 96 class IPyAutocall:
97 97 """ Instances of this class are always autocalled
98 98
99 99 This happens regardless of 'autocall' variable state. Use this to
100 100 develop macro-like mechanisms.
101 101 """
102 102
103 103 def set_ip(self,ip):
104 104 """ Will be used to set _ip point to current ipython instance b/f call
105 105
106 106 Override this method if you don't want this to happen.
107 107
108 108 """
109 109 self._ip = ip
110 110
111 111
112 112 # contains the most recently instantiated IPApi
113 113
114 114 class IPythonNotRunning:
115 115 """Dummy do-nothing class.
116 116
117 117 Instances of this class return a dummy attribute on all accesses, which
118 118 can be called and warns. This makes it easier to write scripts which use
119 119 the ipapi.get() object for informational purposes to operate both with and
120 120 without ipython. Obviously code which uses the ipython object for
121 121 computations will not work, but this allows a wider range of code to
122 122 transparently work whether ipython is being used or not."""
123 123
124 124 def __init__(self,warn=True):
125 125 if warn:
126 126 self.dummy = self._dummy_warn
127 127 else:
128 128 self.dummy = self._dummy_silent
129 129
130 130 def __str__(self):
131 131 return "<IPythonNotRunning>"
132 132
133 133 __repr__ = __str__
134 134
135 135 def __getattr__(self,name):
136 136 return self.dummy
137 137
138 138 def _dummy_warn(self,*args,**kw):
139 139 """Dummy function, which doesn't do anything but warn."""
140 140
141 141 print ("IPython is not running, this is a dummy no-op function")
142 142
143 143 def _dummy_silent(self,*args,**kw):
144 144 """Dummy function, which doesn't do anything and emits no warnings."""
145 145 pass
146 146
147 147 _recent = None
148 148
149 149
150 150 def get(allow_dummy=False,dummy_warn=True):
151 151 """Get an IPApi object.
152 152
153 153 If allow_dummy is true, returns an instance of IPythonNotRunning
154 154 instead of None if not running under IPython.
155 155
156 156 If dummy_warn is false, the dummy instance will be completely silent.
157 157
158 158 Running this should be the first thing you do when writing extensions that
159 159 can be imported as normal modules. You can then direct all the
160 160 configuration operations against the returned object.
161 161 """
162 162 global _recent
163 163 if allow_dummy and not _recent:
164 164 _recent = IPythonNotRunning(dummy_warn)
165 165 return _recent
166 166
167 167 class IPApi:
168 168 """ The actual API class for configuring IPython
169 169
170 170 You should do all of the IPython configuration by getting an IPApi object
171 171 with IPython.ipapi.get() and using the attributes and methods of the
172 172 returned object."""
173 173
174 174 def __init__(self,ip):
175 175
176 176 # All attributes exposed here are considered to be the public API of
177 177 # IPython. As needs dictate, some of these may be wrapped as
178 178 # properties.
179 179
180 180 self.magic = ip.ipmagic
181 181
182 182 self.system = ip.system
183 183
184 184 self.set_hook = ip.set_hook
185 185
186 186 self.set_custom_exc = ip.set_custom_exc
187 187
188 188 self.user_ns = ip.user_ns
189 189 self.user_ns['_ip'] = self
190 190
191 191 self.set_crash_handler = ip.set_crash_handler
192 192
193 193 # Session-specific data store, which can be used to store
194 194 # data that should persist through the ipython session.
195 195 self.meta = ip.meta
196 196
197 197 # The ipython instance provided
198 198 self.IP = ip
199 199
200 200 self.extensions = {}
201 201
202 202 self.dbg = DebugTools(self)
203 203
204 204 global _recent
205 205 _recent = self
206 206
207 207 # Use a property for some things which are added to the instance very
208 208 # late. I don't have time right now to disentangle the initialization
209 209 # order issues, so a property lets us delay item extraction while
210 210 # providing a normal attribute API.
211 211 def get_db(self):
212 212 """A handle to persistent dict-like database (a PickleShareDB object)"""
213 213 return self.IP.db
214 214
215 215 db = property(get_db,None,None,get_db.__doc__)
216 216
217 217 def get_options(self):
218 218 """All configurable variables."""
219 219
220 220 # catch typos by disabling new attribute creation. If new attr creation
221 221 # is in fact wanted (e.g. when exposing new options), do allow_new_attr(True)
222 222 # for the received rc struct.
223 223
224 224 self.IP.rc.allow_new_attr(False)
225 225 return self.IP.rc
226 226
227 227 options = property(get_options,None,None,get_options.__doc__)
228 228
229 229 def expose_magic(self,magicname, func):
230 230 ''' Expose own function as magic function for ipython
231 231
232 232 def foo_impl(self,parameter_s=''):
233 233 """My very own magic!. (Use docstrings, IPython reads them)."""
234 234 print 'Magic function. Passed parameter is between < >: <'+parameter_s+'>'
235 235 print 'The self object is:',self
236 236
237 237 ipapi.expose_magic("foo",foo_impl)
238 238 '''
239 239
240 240 import new
241 241 im = new.instancemethod(func,self.IP, self.IP.__class__)
242 242 old = getattr(self.IP, "magic_" + magicname, None)
243 243 if old:
244 244 self.dbg.debug_stack("Magic redefinition '%s', old %s" % (magicname,
245 245 old))
246 246
247 247 setattr(self.IP, "magic_" + magicname, im)
248 248
249 249 def ex(self,cmd):
250 250 """ Execute a normal python statement in user namespace """
251 251 exec cmd in self.user_ns
252 252
253 253 def ev(self,expr):
254 254 """ Evaluate python expression expr in user namespace
255 255
256 256 Returns the result of evaluation"""
257 257 return eval(expr,self.user_ns)
258 258
259 259 def runlines(self,lines):
260 260 """ Run the specified lines in interpreter, honoring ipython directives.
261 261
262 262 This allows %magic and !shell escape notations.
263 263
264 264 Takes either all lines in one string or list of lines.
265 265 """
266 266
267 267 def cleanup_ipy_script(script):
268 268 """ Make a script safe for _ip.runlines()
269 269
270 270 - Removes empty lines
271 271 - Suffixes all indented blocks that end with unindented lines with empty lines
272 272
273 273 """
274 274 res = []
275 275 lines = script.splitlines()
276 276 level = 0
277 277 for l in lines:
278 stripped = l.lstrip()
279 if not l.strip():
278 lstripped = l.lstrip()
279 stripped = l.strip()
280 if not stripped:
280 281 continue
281 newlevel = len(l) - len(stripped)
282 if level > 0 and newlevel == 0:
282 newlevel = len(l) - len(lstripped)
283 if level > 0 and newlevel == 0 and not stripped.endswith(':'):
283 284 # add empty line
284 285 res.append('')
285 286 res.append(l)
286 287 level = newlevel
287 288 return '\n'.join(res) + '\n'
288 289
289 290 if isinstance(lines,basestring):
290 291 script = lines
291 292 else:
292 293 script = '\n'.join(lines)
293 294 clean=cleanup_ipy_script(script)
294 295
295 296 self.IP.runlines(clean)
296 297 def to_user_ns(self,vars, interactive = True):
297 298 """Inject a group of variables into the IPython user namespace.
298 299
299 300 Inputs:
300 301
301 302 - vars: string with variable names separated by whitespace, or a
302 303 dict with name/value pairs.
303 304
304 305 - interactive: if True (default), the var will be listed with
305 306 %whos et. al.
306 307
307 308 This utility routine is meant to ease interactive debugging work,
308 309 where you want to easily propagate some internal variable in your code
309 310 up to the interactive namespace for further exploration.
310 311
311 312 When you run code via %run, globals in your script become visible at
312 313 the interactive prompt, but this doesn't happen for locals inside your
313 314 own functions and methods. Yet when debugging, it is common to want
314 315 to explore some internal variables further at the interactive propmt.
315 316
316 317 Examples:
317 318
318 319 To use this, you first must obtain a handle on the ipython object as
319 320 indicated above, via:
320 321
321 322 import IPython.ipapi
322 323 ip = IPython.ipapi.get()
323 324
324 325 Once this is done, inside a routine foo() where you want to expose
325 326 variables x and y, you do the following:
326 327
327 328 def foo():
328 329 ...
329 330 x = your_computation()
330 331 y = something_else()
331 332
332 333 # This pushes x and y to the interactive prompt immediately, even
333 334 # if this routine crashes on the next line after:
334 335 ip.to_user_ns('x y')
335 336 ...
336 337
337 338 # To expose *ALL* the local variables from the function, use:
338 339 ip.to_user_ns(locals())
339 340
340 341 ...
341 342 # return
342 343
343 344
344 345 If you need to rename variables, the dict input makes it easy. For
345 346 example, this call exposes variables 'foo' as 'x' and 'bar' as 'y'
346 347 in IPython user namespace:
347 348
348 349 ip.to_user_ns(dict(x=foo,y=bar))
349 350 """
350 351
351 352 # print 'vars given:',vars # dbg
352 353
353 354 # We need a dict of name/value pairs to do namespace updates.
354 355 if isinstance(vars,dict):
355 356 # If a dict was given, no need to change anything.
356 357 vdict = vars
357 358 elif isinstance(vars,basestring):
358 359 # If a string with names was given, get the caller's frame to
359 360 # evaluate the given names in
360 361 cf = sys._getframe(1)
361 362 vdict = {}
362 363 for name in vars.split():
363 364 try:
364 365 vdict[name] = eval(name,cf.f_globals,cf.f_locals)
365 366 except:
366 367 print ('could not get var. %s from %s' %
367 368 (name,cf.f_code.co_name))
368 369 else:
369 370 raise ValueError('vars must be a string or a dict')
370 371
371 372 # Propagate variables to user namespace
372 373 self.user_ns.update(vdict)
373 374
374 375 # And configure interactive visibility
375 376 config_ns = self.IP.user_config_ns
376 377 if interactive:
377 378 for name,val in vdict.iteritems():
378 379 config_ns.pop(name,None)
379 380 else:
380 381 for name,val in vdict.iteritems():
381 382 config_ns[name] = val
382 383
383 384
384 385 def expand_alias(self,line):
385 386 """ Expand an alias in the command line
386 387
387 388 Returns the provided command line, possibly with the first word
388 389 (command) translated according to alias expansion rules.
389 390
390 391 [ipython]|16> _ip.expand_aliases("np myfile.txt")
391 392 <16> 'q:/opt/np/notepad++.exe myfile.txt'
392 393 """
393 394
394 395 pre,fn,rest = self.IP.split_user_input(line)
395 396 res = pre + self.IP.expand_aliases(fn,rest)
396 397 return res
397 398
398 399 def itpl(self, s, depth = 1):
399 400 """ Expand Itpl format string s.
400 401
401 402 Only callable from command line (i.e. prefilter results);
402 403 If you use in your scripts, you need to use a bigger depth!
403 404 """
404 405 return self.IP.var_expand(s, depth)
405 406
406 407 def defalias(self, name, cmd):
407 408 """ Define a new alias
408 409
409 410 _ip.defalias('bb','bldmake bldfiles')
410 411
411 412 Creates a new alias named 'bb' in ipython user namespace
412 413 """
413 414
414 415 self.dbg.check_hotname(name)
415 416
416 417
417 418 if name in self.IP.alias_table:
418 419 self.dbg.debug_stack("Alias redefinition: '%s' => '%s' (old '%s')" %
419 420 (name, cmd, self.IP.alias_table[name]))
420 421
421 422
422 423 if callable(cmd):
423 424 self.IP.alias_table[name] = cmd
424 425 import IPython.shadowns
425 426 setattr(IPython.shadowns, name,cmd)
426 427 return
427 428
428 429 if isinstance(cmd,basestring):
429 430 nargs = cmd.count('%s')
430 431 if nargs>0 and cmd.find('%l')>=0:
431 432 raise Exception('The %s and %l specifiers are mutually exclusive '
432 433 'in alias definitions.')
433 434
434 435 self.IP.alias_table[name] = (nargs,cmd)
435 436 return
436 437
437 438 # just put it in - it's probably (0,'foo')
438 439 self.IP.alias_table[name] = cmd
439 440
440 441 def defmacro(self, *args):
441 442 """ Define a new macro
442 443
443 444 2 forms of calling:
444 445
445 446 mac = _ip.defmacro('print "hello"\nprint "world"')
446 447
447 448 (doesn't put the created macro on user namespace)
448 449
449 450 _ip.defmacro('build', 'bldmake bldfiles\nabld build winscw udeb')
450 451
451 452 (creates a macro named 'build' in user namespace)
452 453 """
453 454
454 455 import IPython.macro
455 456
456 457 if len(args) == 1:
457 458 return IPython.macro.Macro(args[0])
458 459 elif len(args) == 2:
459 460 self.user_ns[args[0]] = IPython.macro.Macro(args[1])
460 461 else:
461 462 return Exception("_ip.defmacro must be called with 1 or 2 arguments")
462 463
463 464 def set_next_input(self, s):
464 465 """ Sets the 'default' input string for the next command line.
465 466
466 467 Requires readline.
467 468
468 469 Example:
469 470
470 471 [D:\ipython]|1> _ip.set_next_input("Hello Word")
471 472 [D:\ipython]|2> Hello Word_ # cursor is here
472 473 """
473 474
474 475 self.IP.rl_next_input = s
475 476
476 477 def load(self, mod):
477 478 """ Load an extension.
478 479
479 480 Some modules should (or must) be 'load()':ed, rather than just imported.
480 481
481 482 Loading will do:
482 483
483 484 - run init_ipython(ip)
484 485 - run ipython_firstrun(ip)
485 486
486 487 """
487 488 if mod in self.extensions:
488 489 # just to make sure we don't init it twice
489 490 # note that if you 'load' a module that has already been
490 491 # imported, init_ipython gets run anyway
491 492
492 493 return self.extensions[mod]
493 494 __import__(mod)
494 495 m = sys.modules[mod]
495 496 if hasattr(m,'init_ipython'):
496 497 m.init_ipython(self)
497 498
498 499 if hasattr(m,'ipython_firstrun'):
499 500 already_loaded = self.db.get('firstrun_done', set())
500 501 if mod not in already_loaded:
501 502 m.ipython_firstrun(self)
502 503 already_loaded.add(mod)
503 504 self.db['firstrun_done'] = already_loaded
504 505
505 506 self.extensions[mod] = m
506 507 return m
507 508
508 509
509 510 class DebugTools:
510 511 """ Used for debugging mishaps in api usage
511 512
512 513 So far, tracing redefinitions is supported.
513 514 """
514 515
515 516 def __init__(self, ip):
516 517 self.ip = ip
517 518 self.debugmode = False
518 519 self.hotnames = set()
519 520
520 521 def hotname(self, name_to_catch):
521 522 self.hotnames.add(name_to_catch)
522 523
523 524 def debug_stack(self, msg = None):
524 525 if not self.debugmode:
525 526 return
526 527
527 528 import traceback
528 529 if msg is not None:
529 530 print '====== %s ========' % msg
530 531 traceback.print_stack()
531 532
532 533 def check_hotname(self,name):
533 534 if name in self.hotnames:
534 535 self.debug_stack( "HotName '%s' caught" % name)
535 536
536 537 def launch_new_instance(user_ns = None,shellclass = None):
537 538 """ Make and start a new ipython instance.
538 539
539 540 This can be called even without having an already initialized
540 541 ipython session running.
541 542
542 543 This is also used as the egg entry point for the 'ipython' script.
543 544
544 545 """
545 546 ses = make_session(user_ns,shellclass)
546 547 ses.mainloop()
547 548
548 549
549 550 def make_user_ns(user_ns = None):
550 551 """Return a valid user interactive namespace.
551 552
552 553 This builds a dict with the minimal information needed to operate as a
553 554 valid IPython user namespace, which you can pass to the various embedding
554 555 classes in ipython.
555 556 """
556 557
557 558 if user_ns is None:
558 559 # Set __name__ to __main__ to better match the behavior of the
559 560 # normal interpreter.
560 561 user_ns = {'__name__' :'__main__',
561 562 '__builtins__' : __builtin__,
562 563 }
563 564 else:
564 565 user_ns.setdefault('__name__','__main__')
565 566 user_ns.setdefault('__builtins__',__builtin__)
566 567
567 568 return user_ns
568 569
569 570
570 571 def make_user_global_ns(ns = None):
571 572 """Return a valid user global namespace.
572 573
573 574 Similar to make_user_ns(), but global namespaces are really only needed in
574 575 embedded applications, where there is a distinction between the user's
575 576 interactive namespace and the global one where ipython is running."""
576 577
577 578 if ns is None: ns = {}
578 579 return ns
579 580
580 581
581 582 def make_session(user_ns = None, shellclass = None):
582 583 """Makes, but does not launch an IPython session.
583 584
584 585 Later on you can call obj.mainloop() on the returned object.
585 586
586 587 Inputs:
587 588
588 589 - user_ns(None): a dict to be used as the user's namespace with initial
589 590 data.
590 591
591 592 WARNING: This should *not* be run when a session exists already."""
592 593
593 594 import IPython.Shell
594 595 if shellclass is None:
595 596 return IPython.Shell.start(user_ns)
596 597 return shellclass(user_ns = user_ns)
@@ -1,499 +1,528
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <?xml-stylesheet ekr_test?>
3 3 <leo_file>
4 4 <leo_header file_format="2" tnodes="0" max_tnode_index="0" clone_windows="0"/>
5 5 <globals body_outline_ratio="0.307814992026">
6 <global_window_position top="122" left="624" height="627" width="1280"/>
6 <global_window_position top="180" left="223" height="627" width="1280"/>
7 7 <global_log_window_position top="0" left="0" height="0" width="0"/>
8 8 </globals>
9 9 <preferences/>
10 10 <find_panel_settings/>
11 11 <vnodes>
12 12 <v t="vivainio.20080222193236" a="E"><vh>Documentation</vh>
13 13 <v t="vivainio.20080223121915" tnodeList="vivainio.20080223121915,vivainio.20080222193236.1,vivainio.20080223133858,vivainio.20080223133922,vivainio.20080223133947,vivainio.20080223134018,vivainio.20080223134100,vivainio.20080223134118,vivainio.20080223134433,vivainio.20080223142207,vivainio.20080223134136"><vh>@nosent ILeo_doc.txt</vh>
14 14 <v t="vivainio.20080222193236.1"><vh>Documentation</vh>
15 15 <v t="vivainio.20080223133858"><vh>Introduction</vh></v>
16 16 <v t="vivainio.20080223133922"><vh>Installation</vh></v>
17 17 <v t="vivainio.20080223133947"><vh>Accessing IPython from Leo</vh></v>
18 18 <v t="vivainio.20080223134018"><vh>Accessing Leo nodes from IPython</vh></v>
19 19 <v t="vivainio.20080223134100"><vh>Cl definitions</vh></v>
20 20 <v t="vivainio.20080223134118"><vh>Special node types</vh></v>
21 21 <v t="vivainio.20080223134433"><vh>Custom push</vh></v>
22 22 <v t="vivainio.20080223142207" a="E"><vh>Code snippets</vh></v>
23 23 <v t="vivainio.20080223134136"><vh>Acknowledgements and history</vh></v>
24 24 </v>
25 25 </v>
26 26 </v>
27 27 <v t="vivainio.20080218184525"><vh>@chapters</vh></v>
28 <v t="vivainio.20080223133721"><vh>@settings</vh>
28 <v t="vivainio.20080223133721" a="E"><vh>@settings</vh>
29 <v t="vivainio.20080316092617"><vh>@@string ipython_argv = ipython -pylab</vh></v>
29 30 <v t="vivainio.20080223133721.1"><vh>@enabled-plugins</vh></v>
30 31 </v>
31 32 <v t="vivainio.20080218184540"><vh>@ipy-startup</vh>
32 33 <v t="vivainio.20080218184613.1"><vh>b</vh></v>
33 34 <v t="vivainio.20080218200031"><vh>Some classes P</vh>
34 35 <v t="vivainio.20080218190816"><vh>File-like access</vh></v>
35 36 <v t="vivainio.20080218200106"><vh>csv data</vh></v>
36 37 <v t="vivainio.20080219225120"><vh>String list</vh></v>
37 38 <v t="vivainio.20080219230342"><vh>slist to leo</vh></v>
38 39 </v>
39 40 </v>
40 41 <v t="vivainio.20080218195413"><vh>Class tests</vh>
41 42 <v t="vivainio.20080218200509"><vh>csvr</vh></v>
42 43 <v t="vivainio.20080218191007"><vh>tempfile</vh></v>
43 44 <v t="vivainio.20080218195413.1"><vh>rfile</vh></v>
44 45 <v t="vivainio.20080219225804"><vh>strlist</vh></v>
45 46 </v>
46 47 <v t="vivainio.20080218201219" a="E"><vh>Direct variables</vh>
47 48 <v t="vivainio.20080222201226"><vh>NewHeadline</vh></v>
48 49 <v t="vivainio.20080218201219.2"><vh>bar</vh></v>
49 50 </v>
51 <v t="vivainio.20080316144536" a="E"><vh>pylab tests</vh>
52 <v t="vivainio.20080316145539.2" a="TV"><vh>Generate testarr</vh></v>
53 <v t="vivainio.20080316085925"><vh>testarr</vh></v>
54 <v t="vivainio.20080316085950"><vh>Call plotter on testarr</vh></v>
55 </v>
50 56 <v t="vivainio.20080222202211"><vh>test stuff</vh></v>
51 <v t="vivainio.20080223142403" a="E"><vh>@ipy-results</vh>
57 <v t="vivainio.20080223142403"><vh>@ipy-results</vh>
52 58 <v t="vivainio.20080223142403.1"><vh>foo</vh></v>
53 59 </v>
54 <v t="vivainio.20080222202211.1" a="ETV"><vh>spam</vh></v>
60 <v t="vivainio.20080222202211.1" a="E"><vh>spam</vh></v>
55 61 </vnodes>
56 62 <tnodes>
57 63 <t tx="vivainio.20080218184525">?</t>
58 64 <t tx="vivainio.20080218184540">?Direct children of this node will be pushed at ipython bridge startup
59 65
60 66 This node itself will *not* be pushed</t>
61 67 <t tx="vivainio.20080218184613.1">print "world"</t>
62 68 <t tx="vivainio.20080218190816">def rfile(body,n):
63 69 """ @cl rfile
64 70
65 71 produces a StringIO (file like obj of the rest of the body) """
66 72
67 73 import StringIO
68 74 return StringIO.StringIO(body)
69 75
70 76 def tmpfile(body,n):
71 77 """ @cl tmpfile
72 78
73 79 Produces a temporary file, with node body as contents
74 80
75 81 """
76 82 import tempfile
77 83 h, fname = tempfile.mkstemp()
78 84 f = open(fname,'w')
79 85 f.write(body)
80 86 f.close()
81 87 return fname
82 88 </t>
83 89 <t tx="vivainio.20080218191007">@cl tmpfile
84 90
85 91 Hello</t>
86 92 <t tx="vivainio.20080218195413">?</t>
87 93 <t tx="vivainio.20080218195413.1">@cl rfile
88 94 These
89 95 lines
90 96 should
91 97 be
92 98 readable </t>
93 99 <t tx="vivainio.20080218200031">@others</t>
94 100 <t tx="vivainio.20080218200106">def csvdata(body,n):
95 101 import csv
96 102 d = csv.Sniffer().sniff(body)
97 103 reader = csv.reader(body.splitlines(), dialect = d)
98 104 return reader</t>
99 105 <t tx="vivainio.20080218200509">@cl csvdata
100 106
101 107 a,b,b
102 108 1,2,2</t>
103 109 <t tx="vivainio.20080218201219"></t>
104 110 <t tx="vivainio.20080218201219.2">@cl
105 111 "hello world"</t>
106 112 <t tx="vivainio.20080219225120">import IPython.genutils
107 113 def slist(body,n):
108 114 return IPython.genutils.SList(body.splitlines())
109 115 </t>
110 116 <t tx="vivainio.20080219225804">@cl slist
111 117 hello
112 118 world
113 119 on
114 120 many
115 121 lines
116 122 </t>
117 123 <t tx="vivainio.20080219230342">import ipy_leo
118 124 @ipy_leo.format_for_leo.when_type(IPython.genutils.SList)
119 125 def format_slist(obj):
120 126 return "@cl slist\n" + obj.n
121 127 </t>
122 128 <t tx="vivainio.20080222193236">?</t>
123 129 <t tx="vivainio.20080222193236.1">@wrap
124 130 @nocolor</t>
125 131 <t tx="vivainio.20080222201226">1+2
126 132 print "hello"
127 133 3+4
128 134
129 135 def f(x):
130 136 return x.upper()
131 137
132 f('hello world')</t>
138 f('hello world')
139
140 if 0:
141 print "foo"
142 else:
143 print "bar"
144
145 </t>
133 146 <t tx="vivainio.20080222202211"></t>
134 147 <t tx="vivainio.20080222202211.1" ipython="7d71005506636f6f7264737101284b0c4bde747102732e">@cl rfile
135 148 hello
136 149 world
137 150 and whatever</t>
138 151 <t tx="vivainio.20080223121915">@others
139 152 </t>
140 153 <t tx="vivainio.20080223133721"></t>
141 154 <t tx="vivainio.20080223133721.1">ipython.py</t>
142 155 <t tx="vivainio.20080223133858">
143 156 Introduction
144 157 ============
145 158
146 159 The purpose of ILeo, or leo-ipython bridge, is being a two-way communication
147 160 channel between Leo and IPython. The level of integration is much deeper than
148 161 conventional integration in IDEs; most notably, you are able to store *data* in
149 162 Leo nodes, in addition to mere program code. The possibilities of this are
150 163 endless, and this degree of integration has not been seen previously in the python
151 164 world.
152 165
153 166 IPython users are accustomed to using things like %edit to produce non-trivial
154 167 functions/classes (i.e. something that they don't want to enter directly on the
155 168 interactive prompt, but creating a proper script/module involves too much
156 169 overhead). In ILeo, this task consists just going to the Leo window, creating a node
157 170 and writing the code there, and pressing alt+I (push-to-ipython).
158 171
159 172 Obviously, you can save the Leo document as usual - this is a great advantage
160 173 of ILeo over using %edit, you can save your experimental scripts all at one
161 174 time, without having to organize them into script/module files (before you
162 175 really want to, of course!)
163 176 </t>
164 177 <t tx="vivainio.20080223133922">
165 178 Installation
166 179 ============
167 180
168 181 You need at least Leo 4.4.7, and the development version of IPython (ILeo
169 182 will be incorporated to IPython 0.8.3).
170 183
171 184 You can get IPython from Launchpad by installing bzr and doing
172 185
173 186 bzr branch lp:ipython
174 187
175 188 and running "setup.py install".
176 189
177 190 You need to enable the 'ipython.py' plugin in Leo:
178 191
179 192 - Help -&gt; Open LeoSettings.leo
180 193
181 194 - Edit @settings--&gt;Plugins--&gt;@enabled-plugins, add/uncomment 'ipython.py'
182 195
183 196 - Alternatively, you can add @settings--&gt;@enabled-plugins with body ipython.py to your leo document.
184 197
185 198 - Restart Leo. Be sure that you have the console window open (start leo.py from console, or double-click leo.py on windows)
186 199
187 200 - Press alt+5 OR alt-x start-ipython to launch IPython in the console that
188 201 started leo. You can start entering IPython commands normally, and Leo will keep
189 202 running at the same time.
190 203 </t>
191 204 <t tx="vivainio.20080223133947">
192 205 Accessing IPython from Leo
193 206 ==========================
194 207
195 208 IPython code
196 209 ------------
197 210
198 211 Just enter IPython commands on a Leo node and press alt-I to execute
199 212 push-to-ipython in order to execute the script in IPython. 'commands' is
200 213 interpreted loosely here - you can enter function and class definitions, in
201 214 addition to the things you would usually enter at IPython prompt - calculations,
202 215 system commands etc.
203 216
204 217 Everything that would be legal to enter on IPython prompt is legal to execute
205 218 from ILeo.
206 219
207 220 Results will be shows in Leo log window for convenience, in addition to the console.
208 221
209 222 Suppose that a node had the following contents:
210 223 {{{
211 224 1+2
212 225 print "hello"
213 226 3+4
214 227
215 228 def f(x):
216 229 return x.upper()
217 230
218 231 f('hello world')
219 232 }}}
220 233
221 234 If you press alt+I on that node, you will see the following in Leo log window (IPython tab):
222 235
223 236 {{{
224 237 In: 1+2
225 238 &lt;2&gt; 3
226 239 In: 3+4
227 240 &lt;4&gt; 7
228 241 In: f('hello world')
229 242 &lt;6&gt; 'HELLO WORLD'
230 243 }}}
231 244
232 245 (numbers like &lt;6&gt; mean IPython output history indices; the actual object can be
233 246 referenced with _6 as usual in IPython).
234 247
235 248
236 249 Plain Python code
237 250 -----------------
238 251
239 252 If the headline of the node ends with capital P, alt-I will not run the code
240 253 through IPython translation mechanism but use the direct python 'exec' statement
241 254 (in IPython user namespace) to execute the code. It wont be shown in IPython
242 255 history, and sometimes it is safer (and more efficient) to execute things as
243 256 plain Python statements. Large class definitions are good candidates for P
244 257 nodes.
245 258 </t>
246 259 <t tx="vivainio.20080223134018">
247 260 Accessing Leo nodes from IPython
248 261 ================================
249 262
250 263 The real fun starts when you start entering text to leo nodes, and are using
251 264 that as data (input/output) for your IPython work.
252 265
253 266 Accessing Leo nodes happens through the variable 'wb' (short for "WorkBook")
254 267 that exist in the IPython user namespace. Nodes that are directly accessible are
255 268 the ones that have simple names which could also be Python variable names;
256 269 'foo_1' will be accessible directly from IPython, whereas 'my scripts' will not.
257 270 If you want to access a node with arbitrary headline, add a child node '@a foo'
258 271 (@a stands for 'anchor'). Then, the parent of '@a foo' is accessible through
259 272 'wb.foo'.
260 273
261 274 You can see what nodes are accessible be entering (in IPython) wb.&lt;TAB&gt;. Example:
262 275
263 276 [C:leo/src]|12&gt; wb.
264 277 wb.b wb.tempfile wb.rfile wb.NewHeadline
265 278 wb.bar wb.Docs wb.strlist wb.csvr
266 279 [C:leo/src]|12&gt; wb.tempfile
267 280 &lt;12&gt; &lt;ipy_leo.LeoNode object at 0x044B6D90&gt;
268 281
269 282 So here, we meet the 'LeoNode' class that is your key to manipulating Leo
270 283 content from IPython!
271 284
272 285 LeoNode
273 286 -------
274 287
275 288 Suppose that we had a node with headline 'spam' and body:
276 289
277 290 ['12',2222+32]
278 291
279 292 we can access it from IPython (or from scripts entered into other Leo nodes!) by doing:
280 293
281 294 C:leo/src]|19&gt; wb.spam.v
282 295 &lt;19&gt; ['12', 2254]
283 296
284 297 'v' attribute stands for 'value', which means the node contents will be run
285 298 through 'eval' and everything you would be able to enter into IPython prompt
286 299 will be converted to objects. This mechanism can be extended far beyond direct
287 300 evaluation (see '@cl definitions').
288 301
289 302 'v' attribute also has a setter, i.e. you can do:
290 303
291 304 wb.spam.v = "mystring"
292 305
293 306 Which will result in the node 'spam' having the following text:
294 307
295 308 'mystring'
296 309
297 310 What assignment to 'v' does can be configured through generic functions
298 311 ('simplegeneric' module, will be explained later).
299 312
300 313 Besides v, you can set the body text directly through
301 314
302 315 wb.spam.b = "some\nstring",
303 316
304 317 headline by
305 318
306 319 wb.spam.h = 'new_headline'
307 320
308 321 (obviously you must access the node through wb.new_headline from that point
309 322 onwards), and access the contents as string list (IPython SList) through
310 323 'wb.spam.l'.
311 324
312 325 If you do 'wb.foo.v = 12' when node named 'foo' does not exist, the node titled
313 326 'foo' will be automatically created and assigned body 12.
314 327
315 328 LeoNode also supports go() that focuses the node in the Leo window, and ipush()
316 329 that simulates pressing alt+I on the node.
317 330
318 331 You can access unknownAttributes by .uA property dictionary. Unknown attributes
319 332 allow you to store arbitrary (pickleable) python objects in the Leo nodes; the
320 333 attributes are stored when you save the .leo document, and recreated when you
321 334 open the document again. The attributes are not visible anywhere, but can be
322 335 used for domain-specific metatada. Example:
323 336
324 337 [C:leo/src]|12&gt; wb.spam.uA['coords'] = (12,222)
325 338 [C:leo/src]|13&gt; wb.spam.uA
326 339 &lt;13&gt; {'coords': (12, 222)}
327 340
328 341 Accessing children with iteration and dict notation
329 342 ---------------------------------------------------
330 343
331 344 Sometimes, you may want to treat a node as a 'database', where the nodes
332 345 children represent elements in the database. You can create a new child node for
333 346 node 'spam', with headline 'foo bar' like this:
334 347
335 348 wb.spam['foo bar'] = "Hello"
336 349
337 350 And assign a new value for it by doing
338 351
339 352 wb.spam['foo bar'].v = "Hello again"
340 353
341 354 Note how you can't use .v when you first create the node - i.e. the node needs
342 355 to be initialized by simple assignment, that will be interpreted as assignment
343 356 to '.v'. This is a conscious design choice.
344 357
345 358 If you try to do wb.spam['bar'] = 'Hello', ILeo will assign '@k bar' as the
346 359 headline for the child instead, because 'bar' is a legal python name (and as
347 360 such would be incorporated in the workbook namespace). This is done to avoid
348 361 crowding the workbook namespace with extraneous items. The item will still be
349 362 accessible as wb.spam['bar']
350 363
351 364 LeoNodes are iterable, so to see the headlines of all the children of 'spam' do:
352 365
353 366 for n in wb.spam:
354 367 print n.h
355 368 </t>
356 369 <t tx="vivainio.20080223134100">
357 370 @cl definitions
358 371 ===============
359 372
360 373 If the first line in the body text is of the form '@cl sometext', IPython will
361 374 evaluate 'sometext' and call the result with the rest of the body when you do
362 375 'wb.foo.v'. An example is in place here. Suppose that we have defined a class (I
363 376 use the term class in a non-python sense here)
364 377
365 378 {{{
366 379 def rfile(body,node):
367 380 """ @cl rfile
368 381
369 382 produces a StringIO (file like obj) of the rest of the body """
370 383
371 384 import StringIO
372 385 return StringIO.StringIO(body)
373 386 }}}
374 387
375 388 (note that node is ignored here - but it could be used to access headline,
376 389 children etc.),
377 390
378 391 Now, let's say you have node 'spam' with text
379 392
380 393 {{{
381 394 @cl rfile
382 395 hello
383 396 world
384 397 and whatever
385 398 }}}
386 399
387 400 Now, in IPython, we can do this:
388 401
389 402 {{{
390 403 [C:leo/src]|22&gt; f = wb.spam.v
391 404 [C:leo/src]|23&gt; f
392 405 &lt;23&gt; &lt;StringIO.StringIO instance at 0x04E7E490&gt;
393 406 [C:leo/src]|24&gt; f.readline()
394 407 &lt;24&gt; u'hello\n'
395 408 [C:leo/src]|25&gt; f.readline()
396 409 &lt;25&gt; u'world\n'
397 410 [C:leo/src]|26&gt; f.readline()
398 411 &lt;26&gt; u'and whatever'
399 412 [C:leo/src]|27&gt; f.readline()
400 413 &lt;27&gt; u''
401 414 }}}
402 415
403 416 You should declare new @cl types to make ILeo as convenient your problem domain
404 417 as possible. For example, a "@cl etree" could return the elementtree object for
405 418 xml content.
406 419 </t>
407 420 <t tx="vivainio.20080223134118">
408 421 Special node types
409 422 ==================
410 423
411 424 @ipy-startup
412 425 ------------
413 426
414 427 If this node exist, the *direct children* of this will be pushed to IPython when
415 428 ILeo is started (you press alt+5). Use it to push your own @cl definitions etc.
416 429 The contents of of the node itself will be ignored.
417 430
418 431 @ipy-results
419 432 ------------
420 433
421 434 When you create a new node (wb.foo.v = 'stuff'), the node foo will be created as
422 435 a child of this node. If @ipy-results does not exist, the new node will be created after the currently selected node.
423 436
424 437 @a nodes
425 438 --------
426 439
427 440 You can attach these as children of existing nodes to provide a way to access
428 441 nodes with arbitrary headlines, or to provide aliases to other nodes. If
429 442 multiple @a nodes are attached as children of a node, all the names can be used
430 443 to access the same object.
431 444 </t>
432 445 <t tx="vivainio.20080223134136">
433 446 Acknowledgements &amp; History
434 447 ==========================
435 448
436 449 This idea got started when I (Ville) saw this post by Edward Ream (the author of
437 450 Leo) on IPython developer mailing list:
438 451
439 452 http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html
440 453
441 454 I was using FreeMind as mind mapping software, and so I had an immediate use
442 455 case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The
443 456 wheels started rolling, I got obsessed with the power of this concept
444 457 (everything clicked together), and Edwards excitement paralleled mine.
445 458 Everything was mind-bogglingly easy/trivial, something that is typical of all
446 459 revolutionary technologies (think Python here).
447 460
448 461 The discussion that "built" ILeo is here:
449 462 http://sourceforge.net/forum/forum.php?thread_id=1911662&amp;forum_id=10226
450 463
451 464 ?</t>
452 465 <t tx="vivainio.20080223134433">
453 466 Declaring custom push-to-ipython handlers
454 467 =========================================
455 468
456 469 Sometimes, you might want to configure what alt+I on a node does. You can do
457 470 that by creating your own push function and expose it using
458 471 ipy_leo.expose_ileo_push(f, priority). The function should check whether the
459 472 node should by handled by the function and raise IPython.ipapi.TryNext if it
460 473 will not do the handling, giving the next function in the chain a chance to see
461 474 whether it should handle the push.
462 475
463 476 This example would print an uppercase version of node body if the node headline ends
464 477 with U (yes, this is completely useless!):
465 478
466 479 {{{
467 480 def push_upcase(node):
468 481 if not node.h.endswith('U'):
469 482 raise TryNext
470 483 print node.b.upper()
471 484
472 485 ipy_leo.expose_ileo_push(push_upcase, 12)
473 486 }}}
474 487
475 488 (the priority should be between 0-100 - typically, you don't need to care about
476 489 it and can usually omit the argument altogether)
477 490 </t>
478 491 <t tx="vivainio.20080223142207">
479 492 Example code snippets
480 493 =====================
481 494
482 495 Get list of all headlines of all the nodes in leo:
483 496
484 497 [node.h for node in wb]
485 498
486 499 Create node with headline 'baz', empty body:
487 500 wb.baz
488 501
489 502 Create 10 child nodes for baz, where i is headline and 'Hello ' + i is body:
490 503
491 504 for i in range(10):
492 505 wb.baz[i] = 'Hello %d' % i
493 506
494 507
495 508 </t>
496 509 <t tx="vivainio.20080223142403"></t>
497 510 <t tx="vivainio.20080223142403.1">12</t>
511 <t tx="vivainio.20080316085925">array([[ 0, 1, 2],
512 [ 3, 4, 5],
513 [ 6, 7, 8],
514 [ 9, 10, 11]])</t>
515 <t tx="vivainio.20080316085950"># press alt+i here to plot testarr
516
517 plot(wb.testarr.v)</t>
518 <t tx="vivainio.20080316092617"></t>
519 <t tx="vivainio.20080316144536">Quickstart:
520 easy_install numpy
521 easy_install matplotlib
522
523 Make sure you have '@string ipython-argv = ipython -pylab' in @settings. We currently recommend using TkAgg as the backend (it's also the default)</t>
524 <t tx="vivainio.20080316145539.2">#press alt+i here to generate an array for plotter
525
526 wb.testarr.v = arange(12).reshape(4,3)</t>
498 527 </tnodes>
499 528 </leo_file>
@@ -1,42 +1,48
1 1 """ An example of one way to embed IPython in your own application
2 2
3 3 This basically means starting up IPython with some of your programs objects visible in the IPython
4 4 user namespace.
5 5
6 6 """
7 7
8 8 import sys
9 9 sys.path.insert(1,'..')
10 10
11 11 import IPython.ipapi
12 12
13 13
14 14
15 15 def test_session(shellclass):
16 16 print "*****************\nLaunch shell for",shellclass
17 17 my_ns = dict(a=10)
18 ses = IPython.ipapi.make_session(my_ns)
18 ses = IPython.ipapi.make_session(my_ns, shellclass=shellclass)
19 19
20 20 # Now get the ipapi instance, to be stored somewhere in your program for manipulation of the running
21 21 # IPython session. See http://ipython.scipy.org/moin/IpythonExtensionApi
22 22
23 23 ip = ses.IP.getapi()
24 24
25 25 # let's play with the ipapi a bit, creating a magic function for a soon-to-be-started IPython
26 26 def mymagic_f(self,s):
27 27 print "mymagic says",s
28 28
29 29 ip.expose_magic("mymagic",mymagic_f)
30 30
31 31 # And finally, start the IPython interaction! This will block until you say Exit.
32 32
33 33 ses.mainloop()
34 34
35 35 print "IPython session for shell ",shellclass," finished! namespace content:"
36 36 for k,v in my_ns.items():
37 37 print k,':',str(v)[:80].rstrip()
38 38
39 39 import IPython.Shell
40 40
41 test_session(shellclass = None)
42 test_session(IPython.Shell._select_shell(['ipython', '-q4thread']))
41 def do_test(arg_line):
42 test_session(IPython.Shell._select_shell(arg_line.split()))
43
44 do_test('')
45 do_test('ipython -gthread')
46 do_test('ipython -q4thread')
47 do_test('ipython -pylab')
48 do_test('ipython -pylab -gthread') No newline at end of file
@@ -1,28 +1,32
1 1 import os,sys,shutil
2 2
3 repo = "http://ipython.scipy.org/svn/ipython/ipython/branches/0.7.3"
4 basename = 'ipython'
5 workdir = './mkdist'
6
7 workdir = os.path.abspath(workdir)
3 basever = '0.8.3'
8 4
9 print "working at",workdir
10 5 def oscmd(c):
11 6 print ">",c
12 7 s = os.system(c)
13 8 if s:
14 9 print "Error",s
15 10 sys.exit(s)
16 11
12 def verinfo():
13
14 out = os.popen('bzr version-info')
15 pairs = (l.split(':',1) for l in out)
16 d = dict(((k,v.strip()) for (k,v) in pairs))
17 return d
18
19 basename = 'ipython'
20
21 #tarname = '%s.r%s.tgz' % (basename, ver)
22 oscmd('update_revnum.py')
23
24 ver = verinfo()
17 25
18 assert not os.path.isdir(workdir)
19 os.mkdir(workdir)
20 os.chdir(workdir)
26 if ver['branch-nick'] == 'ipython':
27 tarname = 'ipython-%s.bzr.r%s.tgz' % (basever, ver['revno'])
28 else:
29 tarname = 'ipython-%s.bzr.r%s.%s.tgz' % (basever, ver['revno'], ver['branch-nick'])
30
31 oscmd('bzr export ' + tarname)
21 32
22 oscmd('svn export %s %s' % (repo,basename))
23 ver = os.popen('svnversion ../..').read().strip()
24 tarname = '%s.r%s.tgz' % (basename, ver)
25 oscmd('tar czvf ../%s %s' % (tarname, basename))
26 print "Produced: ",os.path.abspath('../' + tarname)
27 os.chdir('/')
28 shutil.rmtree(workdir)
@@ -1,14 +1,23
1 1 #!/usr/bin/env python
2 2 """ Change the revision number in Release.py """
3 3
4 4 import os
5 import re
5 import re,pprint
6 6
7 rev = os.popen('bzr revno').read().strip()
7 def verinfo():
8
9 out = os.popen('bzr version-info')
10 pairs = (l.split(':',1) for l in out)
11 d = dict(((k,v.strip()) for (k,v) in pairs))
12 return d
8 13
9 print "current rev is",rev
10 assert ':' not in rev
14 ver = verinfo()
15
16 pprint.pprint(ver)
11 17
12 18 rfile = open('../IPython/Release.py','rb').read()
13 newcont = re.sub(r'revision\s*=.*', "revision = '%s'" % rev, rfile)
19 newcont = re.sub(r'revision\s*=.*', "revision = '%s'" % ver['revno'], rfile)
20
21 newcont = re.sub(r'^branch\s*=[^=].*', "branch = '%s'" % ver['branch-nick'], newcont )
22
14 23 open('../IPython/Release.py','wb').write(newcont)
General Comments 0
You need to be logged in to leave comments. Login now