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