##// END OF EJS Templates
Merge upstream
Fernando Perez -
r1145:f7f6f379 merge
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,73 b''
1 """ Debug a script (like %run -d) in IPython process, Using WinPdb
2
3 Usage:
4
5 %wdb test.py
6 run test.py, with a winpdb breakpoint at start of the file
7
8 %wdb pass
9 Change the password (e.g. if you have forgotten the old one)
10 """
11
12 import os
13
14 import IPython.ipapi
15 import rpdb2
16
17 ip = IPython.ipapi.get()
18
19 rpdb_started = False
20
21 def wdb_f(self, arg):
22 """ Debug a script (like %run -d) in IPython process, Using WinPdb
23
24 Usage:
25
26 %wdb test.py
27 run test.py, with a winpdb breakpoint at start of the file
28
29 %wdb pass
30 Change the password (e.g. if you have forgotten the old one)
31
32 Note that after the script has been run, you need to do "Go" (f5)
33 in WinPdb to resume normal IPython operation.
34 """
35
36 global rpdb_started
37 if not arg.strip():
38 print __doc__
39 return
40
41 if arg.strip() == 'pass':
42 passwd = raw_input('Enter new winpdb session password: ')
43 ip.db['winpdb_pass'] = passwd
44 print "Winpdb password changed"
45 if rpdb_started:
46 print "You need to restart IPython to use the new password"
47 return
48
49 path = os.path.abspath(arg)
50 if not os.path.isfile(path):
51 raise IPython.ipapi.UsageError("%%wdb: file %s does not exist" % path)
52 if not rpdb_started:
53 passwd = ip.db.get('winpdb_pass', None)
54 if passwd is None:
55 import textwrap
56 print textwrap.dedent("""\
57 Winpdb sessions need a password that you use for attaching the external
58 winpdb session. IPython will remember this. You can change the password later
59 by '%wpdb pass'
60 """)
61 passwd = raw_input('Enter new winpdb session password: ')
62 ip.db['winpdb_pass'] = passwd
63
64 print "Starting rpdb2 in IPython process"
65 rpdb2.start_embedded_debugger(passwd, timeout = 0)
66 rpdb_started = True
67
68 rpdb2.set_temp_breakpoint(path)
69 print 'It is time to attach with WinPdb (launch WinPdb if needed, File -> Attach)'
70 ip.magic('%run ' + arg)
71
72
73 ip.expose_magic('wdb', wdb_f)
@@ -0,0 +1,436 b''
1 #!/usr/bin/python
2 # -*- coding: iso-8859-15 -*-
3 '''
4 Provides IPython remote instance.
5
6 @author: Laurent Dufrechou
7 laurent.dufrechou _at_ gmail.com
8 @license: BSD
9
10 All rights reserved. This program and the accompanying materials are made
11 available under the terms of the BSD which accompanies this distribution, and
12 is available at U{http://www.opensource.org/licenses/bsd-license.php}
13 '''
14
15 __version__ = 0.9
16 __author__ = "Laurent Dufrechou"
17 __email__ = "laurent.dufrechou _at_ gmail.com"
18 __license__ = "BSD"
19
20 import re
21 import sys
22 import os
23 import locale
24 import time
25 import pydoc,__builtin__,site
26 from thread_ex import ThreadEx
27 from StringIO import StringIO
28
29 try:
30 import IPython
31 except Exception,e:
32 raise "Error importing IPython (%s)" % str(e)
33
34 ##############################################################################
35 class _Helper(object):
36 """Redefine the built-in 'help'.
37 This is a wrapper around pydoc.help (with a twist).
38 """
39
40 def __init__(self,pager):
41 self._pager = pager
42
43 def __repr__(self):
44 return "Type help() for interactive help, " \
45 "or help(object) for help about object."
46
47 def __call__(self, *args, **kwds):
48 class DummyWriter(object):
49 def __init__(self,pager):
50 self._pager = pager
51
52 def write(self,data):
53 self._pager(data)
54
55 import pydoc
56 pydoc.help.output = DummyWriter(self._pager)
57 pydoc.help.interact = lambda :1
58
59 return pydoc.help(*args, **kwds)
60
61
62 ##############################################################################
63 class _CodeExecutor(ThreadEx):
64
65 def __init__(self, instance, after):
66 ThreadEx.__init__(self)
67 self.instance = instance
68 self._afterExecute=after
69
70 def run(self):
71 try:
72 self.instance._doc_text = None
73 self.instance._help_text = None
74 self.instance._execute()
75 # used for uper class to generate event after execution
76 self._afterExecute()
77
78 except KeyboardInterrupt:
79 pass
80
81
82 ##############################################################################
83 class NonBlockingIPShell(object):
84 '''
85 Create an IPython instance, running the commands in a separate,
86 non-blocking thread.
87 This allows embedding in any GUI without blockage.
88
89 Note: The ThreadEx class supports asynchroneous function call
90 via raise_exc()
91 '''
92
93 def __init__(self,argv=[],user_ns={},user_global_ns=None,
94 cin=None, cout=None, cerr=None,
95 ask_exit_handler=None, rawinput=None):
96 '''
97 @param argv: Command line options for IPython
98 @type argv: list
99 @param user_ns: User namespace.
100 @type user_ns: dictionary
101 @param user_global_ns: User global namespace.
102 @type user_global_ns: dictionary.
103 @param cin: Console standard input.
104 @type cin: IO stream
105 @param cout: Console standard output.
106 @type cout: IO stream
107 @param cerr: Console standard error.
108 @type cerr: IO stream
109 @param exit_handler: Replacement for builtin exit() function
110 @type exit_handler: function
111 @param time_loop: Define the sleep time between two thread's loop
112 @type int
113 '''
114 #ipython0 initialisation
115 self.initIpython0(argv, user_ns, user_global_ns,
116 cin, cout, cerr,
117 ask_exit_handler, rawinput)
118
119 #vars used by _execute
120 self._iter_more = 0
121 self._history_level = 0
122 self._complete_sep = re.compile('[\s\{\}\[\]\(\)]')
123 self._prompt = str(self._IP.outputcache.prompt1).strip()
124
125 #thread working vars
126 self._line_to_execute = ''
127
128 #vars that will be checked by GUI loop to handle thread states...
129 #will be replaced later by PostEvent GUI funtions...
130 self._doc_text = None
131 self._help_text = None
132 self._add_button = None
133
134 def initIpython0(self, argv=[], user_ns={}, user_global_ns=None,
135 cin=None, cout=None, cerr=None,
136 ask_exit_handler=None, rawinput=None):
137 #first we redefine in/out/error functions of IPython
138 if cin:
139 IPython.Shell.Term.cin = cin
140 if cout:
141 IPython.Shell.Term.cout = cout
142 if cerr:
143 IPython.Shell.Term.cerr = cerr
144
145 # This is to get rid of the blockage that accurs during
146 # IPython.Shell.InteractiveShell.user_setup()
147 IPython.iplib.raw_input = lambda x: None
148
149 self._term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr)
150
151 excepthook = sys.excepthook
152
153 self._IP = IPython.Shell.make_IPython(
154 argv,user_ns=user_ns,
155 user_global_ns=user_global_ns,
156 embedded=True,
157 shell_class=IPython.Shell.InteractiveShell)
158
159 #we replace IPython default encoding by wx locale encoding
160 loc = locale.getpreferredencoding()
161 if loc:
162 self._IP.stdin_encoding = loc
163 #we replace the ipython default pager by our pager
164 self._IP.set_hook('show_in_pager',self._pager)
165
166 #we replace the ipython default shell command caller by our shell handler
167 self._IP.set_hook('shell_hook',self._shell)
168
169 #we replace the ipython default input command caller by our method
170 IPython.iplib.raw_input_original = rawinput
171
172 #we replace the ipython default exit command by our method
173 self._IP.exit = ask_exit_handler
174 #we replace the help command
175 self._IP.user_ns['help'] = _Helper(self._pager_help)
176
177 sys.excepthook = excepthook
178
179 #----------------------- Thread management section ----------------------
180 def doExecute(self,line):
181 """
182 Tell the thread to process the 'line' command
183 """
184
185 self._line_to_execute = line
186 #we launch the ipython line execution in a thread to make it interruptible
187 self.ce = _CodeExecutor(self,self._afterExecute)
188 self.ce.start()
189
190 #----------------------- IPython management section ----------------------
191 def getDocText(self):
192 """
193 Returns the output of the processing that need to be paged (if any)
194
195 @return: The std output string.
196 @rtype: string
197 """
198 return self._doc_text
199
200 def getHelpText(self):
201 """
202 Returns the output of the processing that need to be paged via help pager(if any)
203
204 @return: The std output string.
205 @rtype: string
206 """
207 return self._help_text
208
209 def getBanner(self):
210 """
211 Returns the IPython banner for useful info on IPython instance
212
213 @return: The banner string.
214 @rtype: string
215 """
216 return self._IP.BANNER
217
218 def getPromptCount(self):
219 """
220 Returns the prompt number.
221 Each time a user execute a line in the IPython shell the prompt count is increased
222
223 @return: The prompt number
224 @rtype: int
225 """
226 return self._IP.outputcache.prompt_count
227
228 def getPrompt(self):
229 """
230 Returns current prompt inside IPython instance
231 (Can be In [...]: ot ...:)
232
233 @return: The current prompt.
234 @rtype: string
235 """
236 return self._prompt
237
238 def getIndentation(self):
239 """
240 Returns the current indentation level
241 Usefull to put the caret at the good start position if we want to do autoindentation.
242
243 @return: The indentation level.
244 @rtype: int
245 """
246 return self._IP.indent_current_nsp
247
248 def updateNamespace(self, ns_dict):
249 '''
250 Add the current dictionary to the shell namespace.
251
252 @param ns_dict: A dictionary of symbol-values.
253 @type ns_dict: dictionary
254 '''
255 self._IP.user_ns.update(ns_dict)
256
257 def complete(self, line):
258 '''
259 Returns an auto completed line and/or posibilities for completion.
260
261 @param line: Given line so far.
262 @type line: string
263
264 @return: Line completed as for as possible,
265 and possible further completions.
266 @rtype: tuple
267 '''
268 split_line = self._complete_sep.split(line)
269 possibilities = self._IP.complete(split_line[-1])
270 if possibilities:
271
272 def _commonPrefix(str1, str2):
273 '''
274 Reduction function. returns common prefix of two given strings.
275
276 @param str1: First string.
277 @type str1: string
278 @param str2: Second string
279 @type str2: string
280
281 @return: Common prefix to both strings.
282 @rtype: string
283 '''
284 for i in range(len(str1)):
285 if not str2.startswith(str1[:i+1]):
286 return str1[:i]
287 return str1
288 common_prefix = reduce(_commonPrefix, possibilities)
289 completed = line[:-len(split_line[-1])]+common_prefix
290 else:
291 completed = line
292 return completed, possibilities
293
294 def historyBack(self):
295 '''
296 Provides one history command back.
297
298 @return: The command string.
299 @rtype: string
300 '''
301 history = ''
302 #the below while loop is used to suppress empty history lines
303 while((history == '' or history == '\n') and self._history_level >0):
304 if self._history_level>=1:
305 self._history_level -= 1
306 history = self._getHistory()
307 return history
308
309 def historyForward(self):
310 '''
311 Provides one history command forward.
312
313 @return: The command string.
314 @rtype: string
315 '''
316 history = ''
317 #the below while loop is used to suppress empty history lines
318 while((history == '' or history == '\n') and self._history_level <= self._getHistoryMaxIndex()):
319 if self._history_level < self._getHistoryMaxIndex():
320 self._history_level += 1
321 history = self._getHistory()
322 else:
323 if self._history_level == self._getHistoryMaxIndex():
324 history = self._getHistory()
325 self._history_level += 1
326 else:
327 history = ''
328 return history
329
330 def initHistoryIndex(self):
331 '''
332 set history to last command entered
333 '''
334 self._history_level = self._getHistoryMaxIndex()+1
335
336 #----------------------- IPython PRIVATE management section --------------
337 def _afterExecute(self):
338 '''
339 Can be redefined to generate post event after excution is done
340 '''
341 pass
342
343 def _getHistoryMaxIndex(self):
344 '''
345 returns the max length of the history buffer
346
347 @return: history length
348 @rtype: int
349 '''
350 return len(self._IP.input_hist_raw)-1
351
352 def _getHistory(self):
353 '''
354 Get's the command string of the current history level.
355
356 @return: Historic command stri
357 @rtype: string
358 '''
359 rv = self._IP.input_hist_raw[self._history_level].strip('\n')
360 return rv
361
362 def _pager_help(self,text):
363 '''
364 This function is used as a callback replacment to IPython help pager function
365
366 It puts the 'text' value inside the self._help_text string that can be retrived via getHelpText
367 function.
368 '''
369 if self._help_text == None:
370 self._help_text = text
371 else:
372 self._help_text += text
373
374 def _pager(self,IP,text):
375 '''
376 This function is used as a callback replacment to IPython pager function
377
378 It puts the 'text' value inside the self._doc_text string that can be retrived via getDocText
379 function.
380 '''
381 self._doc_text = text
382
383 def _execute(self):
384 '''
385 Executes the current line provided by the shell object.
386 '''
387 orig_stdout = sys.stdout
388 sys.stdout = IPython.Shell.Term.cout
389
390 try:
391 line = self._IP.raw_input(None, self._iter_more)
392 if self._IP.autoindent:
393 self._IP.readline_startup_hook(None)
394
395 except KeyboardInterrupt:
396 self._IP.write('\nKeyboardInterrupt\n')
397 self._IP.resetbuffer()
398 # keep cache in sync with the prompt counter:
399 self._IP.outputcache.prompt_count -= 1
400
401 if self._IP.autoindent:
402 self._IP.indent_current_nsp = 0
403 self._iter_more = 0
404 except:
405 self._IP.showtraceback()
406 else:
407 self._iter_more = self._IP.push(line)
408 if (self._IP.SyntaxTB.last_syntax_error and
409 self._IP.rc.autoedit_syntax):
410 self._IP.edit_syntax_error()
411 if self._iter_more:
412 self._prompt = str(self._IP.outputcache.prompt2).strip()
413 if self._IP.autoindent:
414 self._IP.readline_startup_hook(self._IP.pre_readline)
415 else:
416 self._prompt = str(self._IP.outputcache.prompt1).strip()
417 self._IP.indent_current_nsp = 0 #we set indentation to 0
418 sys.stdout = orig_stdout
419
420 def _shell(self, ip, cmd):
421 '''
422 Replacement method to allow shell commands without them blocking.
423
424 @param ip: Ipython instance, same as self._IP
425 @type cmd: Ipython instance
426 @param cmd: Shell command to execute.
427 @type cmd: string
428 '''
429 stdin, stdout = os.popen4(cmd)
430 result = stdout.read().decode('cp437').encode(locale.getpreferredencoding())
431 #we use print command because the shell command is called inside IPython instance and thus is
432 #redirected to thread cout
433 #"\x01\x1b[1;36m\x02" <-- add colour to the text...
434 print "\x01\x1b[1;36m\x02"+result
435 stdout.close()
436 stdin.close()
@@ -0,0 +1,4 b''
1 import os
2 def oscmd(c):
3 os.system(c)
4 oscmd('sphinx-build -d build/doctrees source build/html') No newline at end of file
@@ -0,0 +1,132 b''
1 # -*- coding: utf-8 -*-
2 #
3 # IPython documentation build configuration file, created by
4 # sphinx-quickstart.py on Sat Mar 29 15:36:13 2008.
5 #
6 # This file is execfile()d with the current directory set to its containing dir.
7 #
8 # The contents of this file are pickled, so don't put values in the namespace
9 # that aren't pickleable (module imports are okay, they're removed automatically).
10 #
11 # All configuration values have a default value; values that are commented out
12 # serve to show the default value.
13
14 import sys
15
16 # If your extensions are in another directory, add it here.
17 #sys.path.append('some/directory')
18
19 # General configuration
20 # ---------------------
21
22 # Add any Sphinx extension module names here, as strings. They can be extensions
23 # coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
24 #extensions = []
25
26 # Add any paths that contain templates here, relative to this directory.
27 templates_path = ['_templates']
28
29 # The suffix of source filenames.
30 source_suffix = '.rst'
31
32 # The master toctree document.
33 master_doc = 'ipython'
34
35 # General substitutions.
36 project = 'IPython'
37 copyright = '2008, IPython team'
38
39 # The default replacements for |version| and |release|, also used in various
40 # other places throughout the built documents.
41 #
42 # The short X.Y version.
43 version = '0.8.3'
44 # The full version, including alpha/beta/rc tags.
45 release = '0.8.3'
46
47 # There are two options for replacing |today|: either, you set today to some
48 # non-false value, then it is used:
49 #today = ''
50 # Else, today_fmt is used as the format for a strftime call.
51 today_fmt = '%B %d, %Y'
52
53 # List of documents that shouldn't be included in the build.
54 #unused_docs = []
55
56 # If true, '()' will be appended to :func: etc. cross-reference text.
57 #add_function_parentheses = True
58
59 # If true, the current module name will be prepended to all description
60 # unit titles (such as .. function::).
61 #add_module_names = True
62
63 # If true, sectionauthor and moduleauthor directives will be shown in the
64 # output. They are ignored by default.
65 #show_authors = False
66
67 # The name of the Pygments (syntax highlighting) style to use.
68 pygments_style = 'sphinx'
69
70
71 # Options for HTML output
72 # -----------------------
73
74 # The style sheet to use for HTML and HTML Help pages. A file of that name
75 # must exist either in Sphinx' static/ path, or in one of the custom paths
76 # given in html_static_path.
77 html_style = 'default.css'
78
79 # Add any paths that contain custom static files (such as style sheets) here,
80 # relative to this directory. They are copied after the builtin static files,
81 # so a file named "default.css" will overwrite the builtin "default.css".
82 html_static_path = ['_static']
83
84 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
85 # using the given strftime format.
86 html_last_updated_fmt = '%b %d, %Y'
87
88 # If true, SmartyPants will be used to convert quotes and dashes to
89 # typographically correct entities.
90 #html_use_smartypants = True
91
92 # Content template for the index page.
93 #html_index = ''
94
95 # Custom sidebar templates, maps document names to template names.
96 #html_sidebars = {}
97
98 # Additional templates that should be rendered to pages, maps page names to
99 # template names.
100 #html_additional_pages = {}
101
102 # If false, no module index is generated.
103 #html_use_modindex = True
104
105 # If true, the reST sources are included in the HTML build as _sources/<name>.
106 #html_copy_source = True
107
108 # Output file base name for HTML help builder.
109 htmlhelp_basename = 'IPythondoc'
110
111
112 # Options for LaTeX output
113 # ------------------------
114
115 # The paper size ('letter' or 'a4').
116 #latex_paper_size = 'letter'
117
118 # The font size ('10pt', '11pt' or '12pt').
119 #latex_font_size = '10pt'
120
121 # Grouping the document tree into LaTeX files. List of tuples
122 # (source start file, target name, title, author, document class [howto/manual]).
123 #latex_documents = []
124
125 # Additional stuff for the LaTeX preamble.
126 #latex_preamble = ''
127
128 # Documents to append as an appendix to all manuals.
129 #latex_appendices = []
130
131 # If false, no module index is generated.
132 #latex_use_modindex = True
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,1 +1,2 b''
1 [LF]
1 *.py
2 *.py
@@ -373,8 +373,7 b' def push_ipython_script(node):'
373 ohist = ip.IP.output_hist
373 ohist = ip.IP.output_hist
374 hstart = len(ip.IP.input_hist)
374 hstart = len(ip.IP.input_hist)
375 script = node.script()
375 script = node.script()
376
376
377 script = g.splitLines(script + '\n')
378 ip.user_ns['_p'] = node
377 ip.user_ns['_p'] = node
379 ip.runlines(script)
378 ip.runlines(script)
380 ip.user_ns.pop('_p',None)
379 ip.user_ns.pop('_p',None)
@@ -189,7 +189,7 b' def magic_kill(self,line):'
189 magic_tasks(self,line)
189 magic_tasks(self,line)
190
190
191 if sys.platform == 'win32':
191 if sys.platform == 'win32':
192 shell_internal_commands = 'break chcp cls copy ctty date del erase dir md mkdir path prompt rd rmdir time type ver vol'.split()
192 shell_internal_commands = 'break chcp cls copy ctty date del erase dir md mkdir path prompt rd rmdir start time type ver vol'.split()
193 else:
193 else:
194 # todo linux commands
194 # todo linux commands
195 shell_internal_commands = []
195 shell_internal_commands = []
@@ -72,6 +72,22 b' def main():'
72 #o.autoexec.append('%colors NoColor')
72 #o.autoexec.append('%colors NoColor')
73 #o.autoexec.append('%colors Linux')
73 #o.autoexec.append('%colors Linux')
74
74
75 # for sane integer division that converts to float (1/2 == 0.5)
76 #o.autoexec.append('from __future__ import division')
77
78 # For %tasks and %kill
79 #import jobctrl
80
81 # For autoreloading of modules (%autoreload, %aimport)
82 #import ipy_autoreload
83
84 # For winpdb support (%wdb)
85 #import ipy_winpdb
86
87 # For bzr completer, requires bzrlib (the python installation of bzr)
88 #import ipy_bzr
89
90
75
91
76 # some config helper functions you can use
92 # some config helper functions you can use
77 def import_all(modules):
93 def import_all(modules):
@@ -70,8 +70,8 b' class IPythonHistoryPanel(wx.Panel):'
70 add = False
70 add = False
71 if self.filter_magic.GetValue() == True and history_line[0] == '%':
71 if self.filter_magic.GetValue() == True and history_line[0] == '%':
72 add = False
72 add = False
73 if add:
73 if add:
74 self.text_ctrl.AppendText(history_line+'\n')
74 self.text_ctrl.AppendText(history_line+'\n')
75
75
76
76
77 #----------------------------------------------------------------------
77 #----------------------------------------------------------------------
This diff has been collapsed as it changes many lines, (811 lines changed) Show them Hide them
@@ -1,7 +1,7 b''
1 #!/usr/bin/python
1 #!/usr/bin/python
2 # -*- coding: iso-8859-15 -*-
2 # -*- coding: iso-8859-15 -*-
3 '''
3 '''
4 Provides IPython WX console widget.
4 Provides IPython WX console widgets.
5
5
6 @author: Laurent Dufrechou
6 @author: Laurent Dufrechou
7 laurent.dufrechou _at_ gmail.com
7 laurent.dufrechou _at_ gmail.com
@@ -30,428 +30,86 b' import wx.lib.newevent'
30
30
31 import re
31 import re
32 import sys
32 import sys
33 import os
34 import locale
33 import locale
35 import time
36 from ThreadEx import Thread
37 from StringIO import StringIO
34 from StringIO import StringIO
38
39 try:
35 try:
40 import IPython
36 import IPython
41 except Exception,e:
37 except Exception,e:
42 raise "Error importing IPython (%s)" % str(e)
38 raise "Error importing IPython (%s)" % str(e)
43
39
44 class IterableIPShell(Thread):
40 from ipshell_nonblocking import NonBlockingIPShell
41
42
43 class WxNonBlockingIPShell(NonBlockingIPShell):
45 '''
44 '''
46 Create an IPython instance inside a dedicated thread.
45 An NonBlockingIPShell Thread that is WX dependent.
47 Does not start a blocking event loop, instead allow single iterations.
48 This allows embedding in any GUI without blockage.
49 The thread is a slave one, in that it doesn't interact directly with the GUI.
50 Note Thread class comes from ThreadEx that supports asynchroneous function call
51 via raise_exc()
52 '''
46 '''
53
47 def __init__(self, parent,
54 def __init__(self,argv=[],user_ns=None,user_global_ns=None,
48 argv=[],user_ns={},user_global_ns=None,
55 cin=None, cout=None, cerr=None,
49 cin=None, cout=None, cerr=None,
56 exit_handler=None,time_loop = 0.1):
50 ask_exit_handler=None, rawinput=None):
57 '''
58 @param argv: Command line options for IPython
59 @type argv: list
60 @param user_ns: User namespace.
61 @type user_ns: dictionary
62 @param user_global_ns: User global namespace.
63 @type user_global_ns: dictionary.
64 @param cin: Console standard input.
65 @type cin: IO stream
66 @param cout: Console standard output.
67 @type cout: IO stream
68 @param cerr: Console standard error.
69 @type cerr: IO stream
70 @param exit_handler: Replacement for builtin exit() function
71 @type exit_handler: function
72 @param time_loop: Define the sleep time between two thread's loop
73 @type int
74 '''
75 Thread.__init__(self)
76
77 #first we redefine in/out/error functions of IPython
78 if cin:
79 IPython.Shell.Term.cin = cin
80 if cout:
81 IPython.Shell.Term.cout = cout
82 if cerr:
83 IPython.Shell.Term.cerr = cerr
84
85 # This is to get rid of the blockage that accurs during
86 # IPython.Shell.InteractiveShell.user_setup()
87 IPython.iplib.raw_input = lambda x: None
88
89 self._term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr)
90
91 excepthook = sys.excepthook
92 self._IP = IPython.Shell.make_IPython(
93 argv,user_ns=user_ns,
94 user_global_ns=user_global_ns,
95 embedded=True,
96 shell_class=IPython.Shell.InteractiveShell)
97
98 #we replace IPython default encoding by wx locale encoding
99 loc = locale.getpreferredencoding()
100 if loc:
101 self._IP.stdin_encoding = loc
102 #we replace the ipython default pager by our pager
103 self._IP.set_hook('show_in_pager',self._pager)
104
51
105 #we replace the ipython default shell command caller by our shell handler
52 NonBlockingIPShell.__init__(self,argv,user_ns,user_global_ns,
106 self._IP.set_hook('shell_hook',self._shell)
53 cin, cout, cerr,
107
54 ask_exit_handler,
108 #we replace the ipython default input command caller by our method
55 rawinput)
109 IPython.iplib.raw_input_original = self._raw_input
110 #we replace the ipython default exit command by our method
111 self._IP.exit = self._setAskExit
112
113 sys.excepthook = excepthook
114
115 self._iter_more = 0
116 self._history_level = 0
117 self._complete_sep = re.compile('[\s\{\}\[\]\(\)]')
118 self._prompt = str(self._IP.outputcache.prompt1).strip()
119
120 #thread working vars
121 self._terminate = False
122 self._time_loop = time_loop
123 self._has_doc = False
124 self._do_execute = False
125 self._line_to_execute = ''
126 self._doc_text = None
127 self._ask_exit = False
128
129 #----------------------- Thread management section ----------------------
130 def run (self):
131 """
132 Thread main loop
133 The thread will run until self._terminate will be set to True via shutdown() function
134 Command processing can be interrupted with Instance.raise_exc(KeyboardInterrupt) call in the
135 GUI thread.
136 """
137 while(not self._terminate):
138 try:
139 if self._do_execute:
140 self._doc_text = None
141 self._execute()
142 self._do_execute = False
143
144 except KeyboardInterrupt:
145 pass
146
56
147 time.sleep(self._time_loop)
57 self.parent = parent
148
149 def shutdown(self):
150 """
151 Shutdown the tread
152 """
153 self._terminate = True
154
155 def doExecute(self,line):
156 """
157 Tell the thread to process the 'line' command
158 """
159 self._do_execute = True
160 self._line_to_execute = line
161
162 def isExecuteDone(self):
163 """
164 Returns the processing state
165 """
166 return not self._do_execute
167
168 #----------------------- IPython management section ----------------------
169 def getAskExit(self):
170 '''
171 returns the _ask_exit variable that can be checked by GUI to see if
172 IPython request an exit handling
173 '''
174 return self._ask_exit
175
58
176 def clearAskExit(self):
59 self.ask_exit_callback = ask_exit_handler
177 '''
60 self._IP.exit = self._askExit
178 clear the _ask_exit var when GUI as handled the request.
179 '''
180 self._ask_exit = False
181
182 def getDocText(self):
183 """
184 Returns the output of the processing that need to be paged (if any)
185
186 @return: The std output string.
187 @rtype: string
188 """
189 return self._doc_text
190
191 def getBanner(self):
192 """
193 Returns the IPython banner for useful info on IPython instance
194
195 @return: The banner string.
196 @rtype: string
197 """
198 return self._IP.BANNER
199
200 def getPromptCount(self):
201 """
202 Returns the prompt number.
203 Each time a user execute a line in the IPython shell the prompt count is increased
204
205 @return: The prompt number
206 @rtype: int
207 """
208 return self._IP.outputcache.prompt_count
209
210 def getPrompt(self):
211 """
212 Returns current prompt inside IPython instance
213 (Can be In [...]: ot ...:)
214
215 @return: The current prompt.
216 @rtype: string
217 """
218 return self._prompt
219
220 def getIndentation(self):
221 """
222 Returns the current indentation level
223 Usefull to put the caret at the good start position if we want to do autoindentation.
224
225 @return: The indentation level.
226 @rtype: int
227 """
228 return self._IP.indent_current_nsp
229
230 def updateNamespace(self, ns_dict):
231 '''
232 Add the current dictionary to the shell namespace.
233
234 @param ns_dict: A dictionary of symbol-values.
235 @type ns_dict: dictionary
236 '''
237 self._IP.user_ns.update(ns_dict)
238
61
239 def complete(self, line):
62 def addGUIShortcut(self,text,func):
240 '''
63 wx.CallAfter(self.parent.add_button_handler,
241 Returns an auto completed line and/or posibilities for completion.
64 button_info={ 'text':text,
242
65 'func':self.parent.doExecuteLine(func)})
243 @param line: Given line so far.
244 @type line: string
245
66
246 @return: Line completed as for as possible,
67 def _askExit(self):
247 and possible further completions.
68 wx.CallAfter(self.ask_exit_callback, ())
248 @rtype: tuple
249 '''
250 split_line = self._complete_sep.split(line)
251 possibilities = self._IP.complete(split_line[-1])
252 if possibilities:
253
254 def _commonPrefix(str1, str2):
255 '''
256 Reduction function. returns common prefix of two given strings.
257
258 @param str1: First string.
259 @type str1: string
260 @param str2: Second string
261 @type str2: string
262
263 @return: Common prefix to both strings.
264 @rtype: string
265 '''
266 for i in range(len(str1)):
267 if not str2.startswith(str1[:i+1]):
268 return str1[:i]
269 return str1
270 common_prefix = reduce(_commonPrefix, possibilities)
271 completed = line[:-len(split_line[-1])]+common_prefix
272 else:
273 completed = line
274 return completed, possibilities
275
69
276 def historyBack(self):
70 def _afterExecute(self):
277 '''
71 wx.CallAfter(self.parent.evtStateExecuteDone, ())
278 Provides one history command back.
279
280 @return: The command string.
281 @rtype: string
282 '''
283 history = ''
284 #the below while loop is used to suppress empty history lines
285 while((history == '' or history == '\n') and self._history_level >0):
286 if self._history_level>=1:
287 self._history_level -= 1
288 history = self._getHistory()
289 return history
290
291 def historyForward(self):
292 '''
293 Provides one history command forward.
294
295 @return: The command string.
296 @rtype: string
297 '''
298 history = ''
299 #the below while loop is used to suppress empty history lines
300 while((history == '' or history == '\n') and self._history_level <= self._getHistoryMaxIndex()):
301 if self._history_level < self._getHistoryMaxIndex():
302 self._history_level += 1
303 history = self._getHistory()
304 else:
305 if self._history_level == self._getHistoryMaxIndex():
306 history = self._getHistory()
307 self._history_level += 1
308 else:
309 history = ''
310 return history
311
312 def initHistoryIndex(self):
313 '''
314 set history to last command entered
315 '''
316 self._history_level = self._getHistoryMaxIndex()+1
317
318 #----------------------- IPython PRIVATE management section ----------------------
319 def _setAskExit(self):
320 '''
321 set the _ask_exit variable that can be cjhecked by GUI to see if
322 IPython request an exit handling
323 '''
324 self._ask_exit = True
325
326 def _getHistoryMaxIndex(self):
327 '''
328 returns the max length of the history buffer
329
330 @return: history length
331 @rtype: int
332 '''
333 return len(self._IP.input_hist_raw)-1
334
335 def _getHistory(self):
336 '''
337 Get's the command string of the current history level.
338
339 @return: Historic command string.
340 @rtype: string
341 '''
342 rv = self._IP.input_hist_raw[self._history_level].strip('\n')
343 return rv
344
345 def _pager(self,IP,text):
346 '''
347 This function is used as a callback replacment to IPython pager function
348
349 It puts the 'text' value inside the self._doc_text string that can be retrived via getDocText
350 function.
351 '''
352 self._doc_text = text
353
354 def _raw_input(self, prompt=''):
355 '''
356 Custom raw_input() replacement. Get's current line from console buffer.
357
358 @param prompt: Prompt to print. Here for compatability as replacement.
359 @type prompt: string
360
361 @return: The current command line text.
362 @rtype: string
363 '''
364 return self._line_to_execute
365
72
366 def _execute(self):
367 '''
368 Executes the current line provided by the shell object.
369 '''
370 orig_stdout = sys.stdout
371 sys.stdout = IPython.Shell.Term.cout
372
73
373 try:
374 line = self._IP.raw_input(None, self._iter_more)
375 if self._IP.autoindent:
376 self._IP.readline_startup_hook(None)
377
378 except KeyboardInterrupt:
379 self._IP.write('\nKeyboardInterrupt\n')
380 self._IP.resetbuffer()
381 # keep cache in sync with the prompt counter:
382 self._IP.outputcache.prompt_count -= 1
383
384 if self._IP.autoindent:
385 self._IP.indent_current_nsp = 0
386 self._iter_more = 0
387 except:
388 self._IP.showtraceback()
389 else:
390 self._iter_more = self._IP.push(line)
391 if (self._IP.SyntaxTB.last_syntax_error and
392 self._IP.rc.autoedit_syntax):
393 self._IP.edit_syntax_error()
394 if self._iter_more:
395 self._prompt = str(self._IP.outputcache.prompt2).strip()
396 if self._IP.autoindent:
397 self._IP.readline_startup_hook(self._IP.pre_readline)
398 else:
399 self._prompt = str(self._IP.outputcache.prompt1).strip()
400 self._IP.indent_current_nsp = 0 #we set indentation to 0
401 sys.stdout = orig_stdout
402
403 def _shell(self, ip, cmd):
404 '''
405 Replacement method to allow shell commands without them blocking.
406
407 @param ip: Ipython instance, same as self._IP
408 @type cmd: Ipython instance
409 @param cmd: Shell command to execute.
410 @type cmd: string
411 '''
412 stdin, stdout = os.popen4(cmd)
413 result = stdout.read().decode('cp437').encode(locale.getpreferredencoding())
414 #we use print command because the shell command is called inside IPython instance and thus is
415 #redirected to thread cout
416 #"\x01\x1b[1;36m\x02" <-- add colour to the text...
417 print "\x01\x1b[1;36m\x02"+result
418 stdout.close()
419 stdin.close()
420
421 class WxConsoleView(stc.StyledTextCtrl):
74 class WxConsoleView(stc.StyledTextCtrl):
422 '''
75 '''
423 Specialized styled text control view for console-like workflow.
76 Specialized styled text control view for console-like workflow.
424 We use here a scintilla frontend thus it can be reused in any GUI taht supports
77 We use here a scintilla frontend thus it can be reused in any GUI that
425 scintilla with less work.
78 supports scintilla with less work.
426
79
427 @cvar ANSI_COLORS_BLACK: Mapping of terminal colors to X11 names.(with Black background)
80 @cvar ANSI_COLORS_BLACK: Mapping of terminal colors to X11 names.
81 (with Black background)
428 @type ANSI_COLORS_BLACK: dictionary
82 @type ANSI_COLORS_BLACK: dictionary
429
83
430 @cvar ANSI_COLORS_WHITE: Mapping of terminal colors to X11 names.(with White background)
84 @cvar ANSI_COLORS_WHITE: Mapping of terminal colors to X11 names.
85 (with White background)
431 @type ANSI_COLORS_WHITE: dictionary
86 @type ANSI_COLORS_WHITE: dictionary
432
87
433 @ivar color_pat: Regex of terminal color pattern
88 @ivar color_pat: Regex of terminal color pattern
434 @type color_pat: _sre.SRE_Pattern
89 @type color_pat: _sre.SRE_Pattern
435 '''
90 '''
436 ANSI_STYLES_BLACK ={'0;30': [0,'WHITE'], '0;31': [1,'RED'],
91 ANSI_STYLES_BLACK={'0;30': [0,'WHITE'], '0;31': [1,'RED'],
437 '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
92 '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
438 '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
93 '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
439 '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
94 '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
440 '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
95 '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
441 '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
96 '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
442 '1;34': [12,'LIGHT BLUE'], '1;35': [13,'MEDIUM VIOLET RED'],
97 '1;34': [12,'LIGHT BLUE'], '1;35':
443 '1;36': [14,'LIGHT STEEL BLUE'], '1;37': [15,'YELLOW']}
98 [13,'MEDIUM VIOLET RED'],
444
99 '1;36': [14,'LIGHT STEEL BLUE'],'1;37': [15,'YELLOW']}
445 ANSI_STYLES_WHITE ={'0;30': [0,'BLACK'], '0;31': [1,'RED'],
100
446 '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
101 ANSI_STYLES_WHITE={'0;30': [0,'BLACK'], '0;31': [1,'RED'],
447 '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
102 '0;32': [2,'GREEN'], '0;33': [3,'BROWN'],
448 '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
103 '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'],
449 '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
104 '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'],
450 '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
105 '1;30': [8,'DARK GREY'], '1;31': [9,'RED'],
451 '1;34': [12,'LIGHT BLUE'], '1;35': [13,'MEDIUM VIOLET RED'],
106 '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'],
452 '1;36': [14,'LIGHT STEEL BLUE'], '1;37': [15,'YELLOW']}
107 '1;34': [12,'LIGHT BLUE'], '1;35':
453
108 [13,'MEDIUM VIOLET RED'],
454 def __init__(self,parent,prompt,intro="",background_color="BLACK",pos=wx.DefaultPosition, ID = -1, size=wx.DefaultSize,
109 '1;36': [14,'LIGHT STEEL BLUE'],'1;37': [15,'YELLOW']}
110
111 def __init__(self,parent,prompt,intro="",background_color="BLACK",
112 pos=wx.DefaultPosition, ID = -1, size=wx.DefaultSize,
455 style=0):
113 style=0):
456 '''
114 '''
457 Initialize console view.
115 Initialize console view.
@@ -467,9 +125,10 b' class WxConsoleView(stc.StyledTextCtrl):'
467 '''
125 '''
468 stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
126 stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
469
127
470 ####### Scintilla configuration ##################################################
128 ####### Scintilla configuration ###################################
471
129
472 # Ctrl + B or Ctrl + N can be used to zoomin/zoomout the text inside the widget
130 # Ctrl + B or Ctrl + N can be used to zoomin/zoomout the text inside
131 # the widget
473 self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
132 self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
474 self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
133 self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
475
134
@@ -531,12 +190,16 b' class WxConsoleView(stc.StyledTextCtrl):'
531 self.SetCaretForeground("WHITE")
190 self.SetCaretForeground("WHITE")
532 self.ANSI_STYLES = self.ANSI_STYLES_BLACK
191 self.ANSI_STYLES = self.ANSI_STYLES_BLACK
533
192
534 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%s,back:%s,size:%d,face:%s" % (self.ANSI_STYLES['0;30'][1],
193 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
535 self.background_color,
194 "fore:%s,back:%s,size:%d,face:%s"
536 faces['size'], faces['mono']))
195 % (self.ANSI_STYLES['0;30'][1],
196 self.background_color,
197 faces['size'], faces['mono']))
537 self.StyleClearAll()
198 self.StyleClearAll()
538 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FF0000,back:#0000FF,bold")
199 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
539 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
200 "fore:#FF0000,back:#0000FF,bold")
201 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
202 "fore:#000000,back:#FF0000,bold")
540
203
541 for style in self.ANSI_STYLES.values():
204 for style in self.ANSI_STYLES.values():
542 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
205 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
@@ -552,7 +215,6 b' class WxConsoleView(stc.StyledTextCtrl):'
552 self.showPrompt()
215 self.showPrompt()
553
216
554 self.Bind(wx.EVT_KEY_DOWN, self._onKeypress, self)
217 self.Bind(wx.EVT_KEY_DOWN, self._onKeypress, self)
555 #self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
556
218
557 def write(self, text):
219 def write(self, text):
558 '''
220 '''
@@ -641,18 +303,6 b' class WxConsoleView(stc.StyledTextCtrl):'
641 return self.GetTextRange(self.getCurrentPromptStart(),
303 return self.GetTextRange(self.getCurrentPromptStart(),
642 self.getCurrentLineEnd())
304 self.getCurrentLineEnd())
643
305
644 def showReturned(self, text):
645 '''
646 Show returned text from last command and print new prompt.
647
648 @param text: Text to show.
649 @type text: string
650 '''
651 self.write('\n'+text)
652 if text:
653 self.write('\n')
654 self.showPrompt()
655
656 def moveCursorOnNewValidKey(self):
306 def moveCursorOnNewValidKey(self):
657 #If cursor is at wrong position put it at last line...
307 #If cursor is at wrong position put it at last line...
658 if self.GetCurrentPos() < self.getCurrentPromptStart():
308 if self.GetCurrentPos() < self.getCurrentPromptStart():
@@ -720,7 +370,7 b' class WxConsoleView(stc.StyledTextCtrl):'
720 @return: Return True if event as been catched.
370 @return: Return True if event as been catched.
721 @rtype: boolean
371 @rtype: boolean
722 '''
372 '''
723
373
724 if event.GetKeyCode() == wx.WXK_HOME:
374 if event.GetKeyCode() == wx.WXK_HOME:
725 if event.Modifiers == wx.MOD_NONE:
375 if event.Modifiers == wx.MOD_NONE:
726 self.moveCursorOnNewValidKey()
376 self.moveCursorOnNewValidKey()
@@ -744,9 +394,9 b' class WxConsoleView(stc.StyledTextCtrl):'
744
394
745 elif event.GetKeyCode() == wx.WXK_BACK:
395 elif event.GetKeyCode() == wx.WXK_BACK:
746 self.moveCursorOnNewValidKey()
396 self.moveCursorOnNewValidKey()
747 if self.getCursorPos() > self.getCurrentPromptStart():
397 if self.getCursorPos() > self.getCurrentPromptStart():
748 self.removeFromTo(self.getCursorPos()-1,self.getCursorPos())
398 event.Skip()
749 return True
399 return True
750
400
751 if skip:
401 if skip:
752 if event.GetKeyCode() not in [wx.WXK_PAGEUP,wx.WXK_PAGEDOWN] and event.Modifiers == wx.MOD_NONE:
402 if event.GetKeyCode() not in [wx.WXK_PAGEUP,wx.WXK_PAGEDOWN] and event.Modifiers == wx.MOD_NONE:
@@ -791,15 +441,20 b' class WxConsoleView(stc.StyledTextCtrl):'
791 #print pt
441 #print pt
792 #self.Refresh(False)
442 #self.Refresh(False)
793
443
794 class WxIPythonViewPanel(wx.Panel):
444 class IPShellWidget(wx.Panel):
795 '''
445 '''
796 This is wx.Panel that embbed the IPython Thread and the wx.StyledTextControl
446 This is wx.Panel that embbed the IPython Thread and the wx.StyledTextControl
797 If you want to port this to any other GUI toolkit, just replace the WxConsoleView
447 If you want to port this to any other GUI toolkit, just replace the
798 by YOURGUIConsoleView and make YOURGUIIPythonView derivate from whatever container you want.
448 WxConsoleView by YOURGUIConsoleView and make YOURGUIIPythonView derivate
799 I've choosed to derivate from a wx.Panel because it seems to be ore usefull
449 from whatever container you want. I've choosed to derivate from a wx.Panel
800 Any idea to make it more 'genric' welcomed.
450 because it seems to be more useful
451 Any idea to make it more 'generic' welcomed.
801 '''
452 '''
802 def __init__(self,parent,exit_handler=None,intro=None,background_color="BLACK"):
453
454 def __init__(self, parent, intro=None,
455 background_color="BLACK", add_button_handler=None,
456 wx_ip_shell=None,
457 ):
803 '''
458 '''
804 Initialize.
459 Initialize.
805 Instanciate an IPython thread.
460 Instanciate an IPython thread.
@@ -808,29 +463,39 b' class WxIPythonViewPanel(wx.Panel):'
808 '''
463 '''
809 wx.Panel.__init__(self,parent,-1)
464 wx.Panel.__init__(self,parent,-1)
810
465
811 ### IPython thread instanciation ###
466 ### IPython non blocking shell instanciation ###
812 self.cout = StringIO()
467 self.cout = StringIO()
813 self.IP = IterableIPShell(cout=self.cout,cerr=self.cout,
468 self.add_button_handler = add_button_handler
814 exit_handler = exit_handler,
469
815 time_loop = 0.1)
470 if wx_ip_shell is not None:
816 self.IP.start()
471 self.IP = wx_ip_shell
817
472 else:
473 self.IP = WxNonBlockingIPShell(self,
474 cout = self.cout, cerr = self.cout,
475 ask_exit_handler = self.askExitCallback,
476 rawinput = self.rawInput)
477
818 ### IPython wx console view instanciation ###
478 ### IPython wx console view instanciation ###
819 #If user didn't defined an intro text, we create one for him
479 #If user didn't defined an intro text, we create one for him
820 #If you really wnat an empty intrp just call wxIPythonViewPanel with intro=''
480 #If you really wnat an empty intrp just call wxIPythonViewPanel
821 if intro == None:
481 #with intro=''
482 if intro is None:
822 welcome_text = "Welcome to WxIPython Shell.\n\n"
483 welcome_text = "Welcome to WxIPython Shell.\n\n"
823 welcome_text+= self.IP.getBanner()
484 welcome_text+= self.IP.getBanner()
824 welcome_text+= "!command -> Execute command in shell\n"
485 welcome_text+= "!command -> Execute command in shell\n"
825 welcome_text+= "TAB -> Autocompletion\n"
486 welcome_text+= "TAB -> Autocompletion\n"
487 else:
488 welcome_text = intro
826
489
827 self.text_ctrl = WxConsoleView(self,
490 self.text_ctrl = WxConsoleView(self,
828 self.IP.getPrompt(),
491 self.IP.getPrompt(),
829 intro=welcome_text,
492 intro=welcome_text,
830 background_color=background_color)
493 background_color=background_color)
494
495 self.cout.write = self.text_ctrl.write
831
496
832 self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress, self.text_ctrl)
497 self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress, self.text_ctrl)
833
498
834 ### making the layout of the panel ###
499 ### making the layout of the panel ###
835 sizer = wx.BoxSizer(wx.VERTICAL)
500 sizer = wx.BoxSizer(wx.VERTICAL)
836 sizer.Add(self.text_ctrl, 1, wx.EXPAND)
501 sizer.Add(self.text_ctrl, 1, wx.EXPAND)
@@ -841,158 +506,151 b' class WxIPythonViewPanel(wx.Panel):'
841 #and we focus on the widget :)
506 #and we focus on the widget :)
842 self.SetFocus()
507 self.SetFocus()
843
508
844 ### below are the thread communication variable ###
509 #widget state management (for key handling different cases)
845 # the IPython thread is managed via unidirectional communication.
510 self.setCurrentState('IDLE')
846 # It's a thread slave that can't interact by itself with the GUI.
511 self.pager_state = 'DONE'
847 # When the GUI event loop is done runStateMachine() is called and the thread sate is then
512
848 # managed.
513 def askExitCallback(self, event):
849
514 self.askExitHandler(event)
850 #Initialize the state machine #kept for information
515
851 #self.states = ['IDLE',
516 #---------------------- IPython Thread Management ------------------------
852 # 'DO_EXECUTE_LINE',
517 def stateDoExecuteLine(self):
853 # 'WAIT_END_OF_EXECUTION',
518 #print >>sys.__stdout__,"command:",self.getCurrentLine()
854 # 'SHOW_DOC',
519 lines=self.text_ctrl.getCurrentLine()
855 # 'SHOW_PROMPT']
520 self.text_ctrl.write('\n')
856
521 for line in lines.split('\n'):
857 self.cur_state = 'IDLE'
522 self.IP.doExecute((line.replace('\t',' '*4)).encode('cp1252'))
858 self.pager_state = 'DONE'
523 self.updateHistoryTracker(self.text_ctrl.getCurrentLine())
859 #wx.CallAfter(self.runStateMachine)
524 self.setCurrentState('WAIT_END_OF_EXECUTION')
860
525
861 # This creates a new Event class and a EVT binder function
526 def evtStateExecuteDone(self,evt):
862 (self.AskExitEvent, EVT_ASK_EXIT) = wx.lib.newevent.NewEvent()
527 self.doc = self.IP.getDocText()
863
528 self.help = self.IP.getHelpText()
864 self.Bind(wx.EVT_IDLE, self.runStateMachine)
529 if self.doc:
865 self.Bind(EVT_ASK_EXIT, exit_handler)
530 self.pager_lines = self.doc[7:].split('\n')
866
531 self.pager_state = 'INIT'
867 def __del__(self):
532 self.setCurrentState('SHOW_DOC')
868 self.IP.shutdown()
533 self.pager(self.doc)
869 self.IP.join()
534 elif self.help:
870 WxConsoleView.__del__()
535 self.pager_lines = self.help.split('\n')
871
536 self.pager_state = 'INIT'
872 #---------------------------- IPython Thread Management ---------------------------------------
537 self.setCurrentState('SHOW_DOC')
873 def runStateMachine(self,event):
538 self.pager(self.help)
874 #print >>self.sys_stdout,"state:",self.cur_state
539 else:
540 self.stateShowPrompt()
541
542 def stateShowPrompt(self):
543 self.setCurrentState('SHOW_PROMPT')
544 self.text_ctrl.setPrompt(self.IP.getPrompt())
545 self.text_ctrl.setIndentation(self.IP.getIndentation())
546 self.text_ctrl.setPromptCount(self.IP.getPromptCount())
547 self.text_ctrl.showPrompt()
548 self.IP.initHistoryIndex()
549 self.setCurrentState('IDLE')
550
551 def setCurrentState(self, state):
552 self.cur_state = state
875 self.updateStatusTracker(self.cur_state)
553 self.updateStatusTracker(self.cur_state)
876
554 #---------------------------- Ipython raw_input -----------------------------------
877 if self.cur_state == 'DO_EXECUTE_LINE':
555 def rawInput(self, prompt=''):
878 #print >>self.sys_stdout,"command:",self.getCurrentLine()
556 self.setCurrentState('WAITING_USER_INPUT')
879 self.IP.doExecute(self.text_ctrl.getCurrentLine().replace('\t',' '*4))
557 while self.cur_state != 'WAIT_END_OF_EXECUTION':
880 self.updateHistoryTracker(self.text_ctrl.getCurrentLine())
558 pass
881 self.cur_state = 'WAIT_END_OF_EXECUTION'
559 line = self.text_ctrl.getCurrentLine()
882
560 line = line.split('\n')
883 if self.cur_state == 'WAIT_END_OF_EXECUTION':
561 return line[-2]
884 if self.IP.isExecuteDone():
885 self.doc = self.IP.getDocText()
886 if self.IP.getAskExit():
887 evt = self.AskExitEvent()
888 wx.PostEvent(self, evt)
889 self.IP.clearAskExit()
890 if self.doc:
891 self.pager_state = 'INIT'
892 self.cur_state = 'SHOW_DOC'
893 else:
894 self.cur_state = 'SHOW_PROMPT'
895
896 if self.cur_state == 'SHOW_PROMPT':
897 self.text_ctrl.setPrompt(self.IP.getPrompt())
898 self.text_ctrl.setIndentation(self.IP.getIndentation())
899 self.text_ctrl.setPromptCount(self.IP.getPromptCount())
900 rv = self.cout.getvalue()
901 if rv: rv = rv.strip('\n')
902 self.text_ctrl.showReturned(rv)
903 self.cout.truncate(0)
904 self.IP.initHistoryIndex()
905 self.cur_state = 'IDLE'
906
562
907 if self.cur_state == 'SHOW_DOC':
908 self.pager(self.doc)
909 if self.pager_state == 'DONE':
910 self.cur_state = 'SHOW_PROMPT'
911
912 event.Skip()
913
914 #---------------------------- IPython pager ---------------------------------------
563 #---------------------------- IPython pager ---------------------------------------
915 def pager(self,text):#,start=0,screen_lines=0,pager_cmd = None):
564 def pager(self,text):
916 if self.pager_state == 'WAITING':
565
917 #print >>self.sys_stdout,"PAGER waiting"
566 if self.pager_state == 'INIT':
918 return
567 #print >>sys.__stdout__,"PAGER state:",self.pager_state
919
568 self.pager_nb_lines = len(self.pager_lines)
920 if self.pager_state == 'INIT':
569 self.pager_index = 0
921 #print >>self.sys_stdout,"PAGER state:",self.pager_state
570 self.pager_do_remove = False
922 self.pager_lines = text[7:].split('\n')
571 self.text_ctrl.write('\n')
923 self.pager_nb_lines = len(self.pager_lines)
572 self.pager_state = 'PROCESS_LINES'
924 self.pager_index = 0
573
925 self.pager_do_remove = False
574 if self.pager_state == 'PROCESS_LINES':
926 self.text_ctrl.write('\n')
575 #print >>sys.__stdout__,"PAGER state:",self.pager_state
927 self.pager_state = 'PROCESS_LINES'
576 if self.pager_do_remove == True:
928
577 self.text_ctrl.removeCurrentLine()
929 if self.pager_state == 'PROCESS_LINES':
578 self.pager_do_remove = False
930 #print >>self.sys_stdout,"PAGER state:",self.pager_state
579
931 if self.pager_do_remove == True:
580 if self.pager_nb_lines > 10:
932 self.text_ctrl.removeCurrentLine()
581 #print >>sys.__stdout__,"PAGER processing 10 lines"
933 self.pager_do_remove = False
582 if self.pager_index > 0:
934
583 self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
935 if self.pager_nb_lines > 10:
584 else:
936 #print >>self.sys_stdout,"PAGER processing 10 lines"
585 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
937 if self.pager_index > 0:
586
938 self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
587 for line in self.pager_lines[self.pager_index+1:self.pager_index+9]:
939 else:
588 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
940 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
589 self.pager_index += 10
941
590 self.pager_nb_lines -= 10
942 for line in self.pager_lines[self.pager_index+1:self.pager_index+9]:
591 self.text_ctrl.write("--- Push Enter to continue or 'Q' to quit---")
943 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
592 self.pager_do_remove = True
944 self.pager_index += 10
593 self.pager_state = 'WAITING'
945 self.pager_nb_lines -= 10
594 return
946 self.text_ctrl.write("--- Push Enter to continue or 'Q' to quit---")
595 else:
947 self.pager_do_remove = True
596 #print >>sys.__stdout__,"PAGER processing last lines"
948 self.pager_state = 'WAITING'
597 if self.pager_nb_lines > 0:
949 return
598 if self.pager_index > 0:
950 else:
599 self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
951 #print >>self.sys_stdout,"PAGER processing last lines"
600 else:
952 if self.pager_nb_lines > 0:
601 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
953 if self.pager_index > 0:
602
954 self.text_ctrl.write(">\x01\x1b[1;36m\x02"+self.pager_lines[self.pager_index]+'\n')
603 self.pager_index += 1
955 else:
956 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+self.pager_lines[self.pager_index]+'\n')
957
958 self.pager_index += 1
959 self.pager_nb_lines -= 1
604 self.pager_nb_lines -= 1
960 if self.pager_nb_lines > 0:
605 if self.pager_nb_lines > 0:
961 for line in self.pager_lines[self.pager_index:]:
606 for line in self.pager_lines[self.pager_index:]:
962 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
607 self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n')
963 self.pager_nb_lines = 0
608 self.pager_nb_lines = 0
964 self.pager_state = 'DONE'
609 self.pager_state = 'DONE'
610 self.stateShowPrompt()
965
611
966 #---------------------------- Key Handler --------------------------------------------
612 #------------------------ Key Handler ------------------------------------
967 def keyPress(self, event):
613 def keyPress(self, event):
968 '''
614 '''
969 Key press callback with plenty of shell goodness, like history,
615 Key press callback with plenty of shell goodness, like history,
970 autocompletions, etc.
616 autocompletions, etc.
971 '''
617 '''
972
618
973 if event.GetKeyCode() == ord('C'):
619 if event.GetKeyCode() == ord('C'):
974 if event.Modifiers == wx.MOD_CONTROL:
620 if event.Modifiers == wx.MOD_CONTROL:
975 if self.cur_state == 'WAIT_END_OF_EXECUTION':
621 if self.cur_state == 'WAIT_END_OF_EXECUTION':
976 #we raise an exception inside the IPython thread container
622 #we raise an exception inside the IPython thread container
977 self.IP.raise_exc(KeyboardInterrupt)
623 self.IP.ce.raise_exc(KeyboardInterrupt)
978 return
624 return
979
625
980 if event.KeyCode == wx.WXK_RETURN:
626 if event.KeyCode == wx.WXK_RETURN:
981 if self.cur_state == 'IDLE':
627 if self.cur_state == 'IDLE':
982 #we change the state ot the state machine
628 #we change the state ot the state machine
983 self.cur_state = 'DO_EXECUTE_LINE'
629 self.setCurrentState('DO_EXECUTE_LINE')
630 self.stateDoExecuteLine()
984 return
631 return
985 if self.pager_state == 'WAITING':
632 if self.pager_state == 'WAITING':
986 self.pager_state = 'PROCESS_LINES'
633 self.pager_state = 'PROCESS_LINES'
634 self.pager(self.doc)
987 return
635 return
988
636
637 if self.cur_state == 'WAITING_USER_INPUT':
638 line=self.text_ctrl.getCurrentLine()
639 self.text_ctrl.write('\n')
640 self.setCurrentState('WAIT_END_OF_EXECUTION')
641 return
642
989 if event.GetKeyCode() in [ord('q'),ord('Q')]:
643 if event.GetKeyCode() in [ord('q'),ord('Q')]:
990 if self.pager_state == 'WAITING':
644 if self.pager_state == 'WAITING':
991 self.pager_state = 'DONE'
645 self.pager_state = 'DONE'
646 self.text_ctrl.write('\n')
647 self.stateShowPrompt()
992 return
648 return
993
649
994 #scroll_position = self.text_ctrl.GetScrollPos(wx.VERTICAL)
650 if self.cur_state == 'WAITING_USER_INPUT':
995 if self.cur_state == 'IDLE':
651 event.Skip()
652
653 if self.cur_state == 'IDLE':
996 if event.KeyCode == wx.WXK_UP:
654 if event.KeyCode == wx.WXK_UP:
997 history = self.IP.historyBack()
655 history = self.IP.historyBack()
998 self.text_ctrl.writeHistory(history)
656 self.text_ctrl.writeHistory(history)
@@ -1019,8 +677,8 b' class WxIPythonViewPanel(wx.Panel):'
1019
677
1020 return
678 return
1021 event.Skip()
679 event.Skip()
1022
680
1023 #---------------------------- Hook Section --------------------------------------------
681 #------------------------ Hook Section -----------------------------------
1024 def updateHistoryTracker(self,command_line):
682 def updateHistoryTracker(self,command_line):
1025 '''
683 '''
1026 Default history tracker (does nothing)
684 Default history tracker (does nothing)
@@ -1032,6 +690,7 b' class WxIPythonViewPanel(wx.Panel):'
1032 Define a new history tracker
690 Define a new history tracker
1033 '''
691 '''
1034 self.updateHistoryTracker = func
692 self.updateHistoryTracker = func
693
1035 def updateStatusTracker(self,status):
694 def updateStatusTracker(self,status):
1036 '''
695 '''
1037 Default status tracker (does nothing)
696 Default status tracker (does nothing)
@@ -1043,4 +702,36 b' class WxIPythonViewPanel(wx.Panel):'
1043 Define a new status tracker
702 Define a new status tracker
1044 '''
703 '''
1045 self.updateStatusTracker = func
704 self.updateStatusTracker = func
1046
705
706 def askExitHandler(self, event):
707 '''
708 Default exit handler
709 '''
710 self.text_ctrl.write('\nExit callback has not been set.')
711
712 def setAskExitHandler(self, func):
713 '''
714 Define an exit handler
715 '''
716 self.askExitHandler = func
717
718 if __name__ == '__main__':
719 # Some simple code to test the shell widget.
720 class MainWindow(wx.Frame):
721 def __init__(self, parent, id, title):
722 wx.Frame.__init__(self, parent, id, title, size=(300,250))
723 self._sizer = wx.BoxSizer(wx.VERTICAL)
724 self.shell = IPShellWidget(self)
725 self._sizer.Add(self.shell, 1, wx.EXPAND)
726 self.SetSizer(self._sizer)
727 self.SetAutoLayout(1)
728 self.Show(True)
729
730 app = wx.PySimpleApp()
731 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
732 frame.SetSize((780, 460))
733 shell = frame.shell
734
735 app.MainLoop()
736
737
@@ -1,3 +1,8 b''
1 """
2 Thread subclass that can deal with asynchronously function calls via
3 raise_exc.
4 """
5
1 import threading
6 import threading
2 import inspect
7 import inspect
3 import ctypes
8 import ctypes
@@ -17,7 +22,7 b' def _async_raise(tid, exctype):'
17 raise SystemError("PyThreadState_SetAsyncExc failed")
22 raise SystemError("PyThreadState_SetAsyncExc failed")
18
23
19
24
20 class Thread(threading.Thread):
25 class ThreadEx(threading.Thread):
21 def _get_my_tid(self):
26 def _get_my_tid(self):
22 """determines this (self's) thread id"""
27 """determines this (self's) thread id"""
23 if not self.isAlive():
28 if not self.isAlive():
@@ -2,11 +2,13 b''
2 # -*- coding: iso-8859-15 -*-
2 # -*- coding: iso-8859-15 -*-
3
3
4 import wx.aui
4 import wx.aui
5 import wx.py
5
6 #used for about dialog
6 from wx.lib.wordwrap import wordwrap
7 from wx.lib.wordwrap import wordwrap
7
8
8 from ipython_view import *
9 #used for ipython GUI objects
9 from ipython_history import *
10 from IPython.gui.wx.ipython_view import IPShellWidget
11 from IPython.gui.wx.ipython_history import IPythonHistoryPanel
10
12
11 __version__ = 0.8
13 __version__ = 0.8
12 __author__ = "Laurent Dufrechou"
14 __author__ = "Laurent Dufrechou"
@@ -20,7 +22,8 b' __license__ = "BSD"'
20 class MyFrame(wx.Frame):
22 class MyFrame(wx.Frame):
21 """Creating one main frame for our
23 """Creating one main frame for our
22 application with movables windows"""
24 application with movables windows"""
23 def __init__(self, parent=None, id=-1, title="WxIPython", pos=wx.DefaultPosition,
25 def __init__(self, parent=None, id=-1, title="WxIPython",
26 pos=wx.DefaultPosition,
24 size=(800, 600), style=wx.DEFAULT_FRAME_STYLE):
27 size=(800, 600), style=wx.DEFAULT_FRAME_STYLE):
25 wx.Frame.__init__(self, parent, id, title, pos, size, style)
28 wx.Frame.__init__(self, parent, id, title, pos, size, style)
26 self._mgr = wx.aui.AuiManager()
29 self._mgr = wx.aui.AuiManager()
@@ -31,15 +34,14 b' class MyFrame(wx.Frame):'
31 #create differents panels and make them persistant
34 #create differents panels and make them persistant
32 self.history_panel = IPythonHistoryPanel(self)
35 self.history_panel = IPythonHistoryPanel(self)
33
36
34 self.ipython_panel = WxIPythonViewPanel(self,self.OnExitDlg,
37 self.ipython_panel = IPShellWidget(self,background_color = "BLACK")
35 background_color = "BLACK")
36
37 #self.ipython_panel = WxIPythonViewPanel(self,self.OnExitDlg,
38 # background_color = "WHITE")
39
38
39 #self.ipython_panel = IPShellWidget(self,background_color = "WHITE")
40
40 self.ipython_panel.setHistoryTrackerHook(self.history_panel.write)
41 self.ipython_panel.setHistoryTrackerHook(self.history_panel.write)
41 self.ipython_panel.setStatusTrackerHook(self.updateStatus)
42 self.ipython_panel.setStatusTrackerHook(self.updateStatus)
42
43 self.ipython_panel.setAskExitHandler(self.OnExitDlg)
44
43 self.statusbar = self.createStatus()
45 self.statusbar = self.createStatus()
44 self.createMenu()
46 self.createMenu()
45
47
@@ -48,13 +50,11 b' class MyFrame(wx.Frame):'
48 # main panels
50 # main panels
49 self._mgr.AddPane(self.ipython_panel , wx.CENTER, "IPython Shell")
51 self._mgr.AddPane(self.ipython_panel , wx.CENTER, "IPython Shell")
50 self._mgr.AddPane(self.history_panel , wx.RIGHT, "IPython history")
52 self._mgr.AddPane(self.history_panel , wx.RIGHT, "IPython history")
51
53
52 # now we specify some panel characteristics
54 # now we specify some panel characteristics
53 self._mgr.GetPane(self.ipython_panel).CaptionVisible(True);
55 self._mgr.GetPane(self.ipython_panel).CaptionVisible(True);
54 self._mgr.GetPane(self.history_panel).CaptionVisible(True);
56 self._mgr.GetPane(self.history_panel).CaptionVisible(True);
55 self._mgr.GetPane(self.history_panel).MinSize((200,400));
57 self._mgr.GetPane(self.history_panel).MinSize((200,400));
56
57
58
58
59 # tell the manager to "commit" all the changes just made
59 # tell the manager to "commit" all the changes just made
60 self._mgr.Update()
60 self._mgr.Update()
@@ -121,6 +121,7 b' class MyFrame(wx.Frame):'
121 states = {'IDLE':'Idle',
121 states = {'IDLE':'Idle',
122 'DO_EXECUTE_LINE':'Send command',
122 'DO_EXECUTE_LINE':'Send command',
123 'WAIT_END_OF_EXECUTION':'Running command',
123 'WAIT_END_OF_EXECUTION':'Running command',
124 'WAITING_USER_INPUT':'Waiting user input',
124 'SHOW_DOC':'Showing doc',
125 'SHOW_DOC':'Showing doc',
125 'SHOW_PROMPT':'Showing prompt'}
126 'SHOW_PROMPT':'Showing prompt'}
126 self.statusbar.SetStatusText(states[text], 0)
127 self.statusbar.SetStatusText(states[text], 0)
@@ -273,16 +273,27 b' class IPApi:'
273 """
273 """
274 res = []
274 res = []
275 lines = script.splitlines()
275 lines = script.splitlines()
276
276 level = 0
277 level = 0
277 for l in lines:
278 for l in lines:
278 lstripped = l.lstrip()
279 lstripped = l.lstrip()
279 stripped = l.strip()
280 stripped = l.strip()
280 if not stripped:
281 if not stripped:
281 continue
282 continue
282 newlevel = len(l) - len(lstripped)
283 newlevel = len(l) - len(lstripped)
283 if level > 0 and newlevel == 0 and not stripped.endswith(':'):
284 def is_secondary_block_start(s):
285 if not s.endswith(':'):
286 return False
287 if (s.startswith('elif') or
288 s.startswith('else') or
289 s.startswith('except') or
290 s.startswith('finally')):
291 return True
292
293 if level > 0 and newlevel == 0 and not is_secondary_block_start(stripped):
284 # add empty line
294 # add empty line
285 res.append('')
295 res.append('')
296
286 res.append(l)
297 res.append(l)
287 level = newlevel
298 level = newlevel
288 return '\n'.join(res) + '\n'
299 return '\n'.join(res) + '\n'
@@ -292,7 +303,7 b' class IPApi:'
292 else:
303 else:
293 script = '\n'.join(lines)
304 script = '\n'.join(lines)
294 clean=cleanup_ipy_script(script)
305 clean=cleanup_ipy_script(script)
295
306 # print "_ip.runlines() script:\n",clean #dbg
296 self.IP.runlines(clean)
307 self.IP.runlines(clean)
297 def to_user_ns(self,vars, interactive = True):
308 def to_user_ns(self,vars, interactive = True):
298 """Inject a group of variables into the IPython user namespace.
309 """Inject a group of variables into the IPython user namespace.
@@ -210,7 +210,7 b" object? -> Details about 'object'. ?object also works, ?? prints more."
210 editor = '0',
210 editor = '0',
211 gthread = 0,
211 gthread = 0,
212 help = 0,
212 help = 0,
213 interact = 1,
213 interact = 0,
214 ipythondir = ipythondir_def,
214 ipythondir = ipythondir_def,
215 log = 0,
215 log = 0,
216 logfile = '',
216 logfile = '',
@@ -1,5 +1,116 b''
1 2008-04-02 Ville Vainio <vivainio@gmail.com>
2
3 * ipy_winpdb.py: New extension for winpdb integration. %wdb
4 test.py is winpdb equivalent of %run -d test.py. winpdb is a
5 crossplatform remote GUI debugger based on wxpython.
6
7 2008-03-29 Ville Vainio <vivainio@gmail.com>
8
9 * ipython.rst, do_sphinx.py: New documentation base, based on
10 reStucturedText and Sphinx (html/pdf generation). The old Lyx
11 based documentation will not be updated anymore.
12
13 * jobctrl.py: Use shell in Popen for 'start' command (in windows).
14
15 2008-03-24 Ville Vainio <vivainio@gmail.com>
16
17 * ipython.rst, do_sphinx.py: New documentation base, based on
18 reStucturedText and Sphinx (html/pdf generation). The old Lyx
19 based documentation will not be updated anymore.
20
21 ipython.rst has up to date documentation on matters that were not
22 documented at all, and it also removes various
23 misdocumented/deprecated features.
24
25 2008-03-22 Ville Vainio <vivainio@gmail.com>
26
27 * Shell.py: Merge mtexp branch:
28 https://code.launchpad.net/~ipython/ipython/mtexp
29
30 Privides simpler and more robust MTInteractiveShell that won't
31 deadlock, even when the worker thread (GUI) stops doing runcode()
32 regularly. r71.
33
34 2008-03-20 Ville Vainio <vivainio@gmail.com>
35
36 * twshell.py: New shell that runs IPython code in Twisted reactor.
37 Launch by doing ipython -twisted. r67.
38
39 2008-03-19 Ville Vainio <vivainio@gmail.com>
40
41 * Magic.py: %rehashx works correctly when shadowed system commands
42 have upper case characters (e.g. Print.exe). r64.
43
44 * ipy_bzr.py, ipy_app_completers.py: new bzr completer that also
45 knows options to commands, based on bzrtools. Uses bzrlib
46 directly. r66.
47
48 2008-03-16 Ville Vainio <vivainio@gmail.com>
49
50 * make_tarball.py: Fixed for bzr.
51
52 * ipapi.py: Better _ip.runlines() script cleanup. r56,r79.
53
54 * ipy_vimserver.py, ipy.vim: New extension for vim server mode,
55 by Erich Heine.
56
57 2008-03-12 Ville Vainio <vivainio@gmail.com>
58
59 * ipmaker.py: Force (reload?) import of ipy_user_conf and
60 ipy_profile_foo, so that embedded instances can be relaunched and
61 configuration is still done. r50
62
63 * ipapi.py, test_embed.py: Allow specifying shell class in
64 launch_new_instance & make_new instance. Use this in
65 test_embed.py. r51.
66
67 test_embed.py is also a good and simple demo of embedding IPython.
68
69
70 2008-03-10 Ville Vainio <vivainio@gmail.com>
71
72 * tool/update_revnum.py: Change to bzr revisioning scheme in
73 revision numbers.
74
75 * Shell.py: Threading improvements:
76
77 In multithreaded shells, do not hang on macros and o.autoexec
78 commands (or anything executed with _ip.runlines()) anymore. Allow
79 recursive execution of IPython code in
80 MTInteractiveShell.runsource by checking if we are already in
81 worker thread, and execute code directly if we are. r48.
82
83 MTInteractiveShell.runsource: execute code directly if worker
84 thread is not running yet (this is the case in config files). r49.
85
86 2008-03-09 Ville Vainio <vivainio@gmail.com>
87
88 * ipy_profile_sh.py: You can now use $LA or LA() to refer to last
89 argument of previous command in sh profile. Similar to bash '!$'.
90 LA(3) or $LA(3) stands for last argument of input history command
91 3.
92
93 * Shell.py: -pylab names don't clutter %whos listing.
94
95 2008-03-07 Ville Vainio <vivainio@gmail.com>
96
97 * ipy_autoreload.py: new extension (by Pauli Virtanen) for
98 autoreloading modules; try %autoreload and %aimport. Close #154.
99 Uses the new pre_runcode_hook.
100
101 2008-02-24 Ville Vainio <vivainio@gmail.com>
102
103 * platutils_posix.py: freeze_term_title works
104
105 2008-02-21 Ville Vainio <vivainio@gmail.com>
106
107 * Magic.py: %quickref does not crash with empty docstring
108
1 2008-02-20 Ville Vainio <vivainio@gmail.com>
109 2008-02-20 Ville Vainio <vivainio@gmail.com>
2
110
111 * completer.py: do not treat [](){} as protectable chars anymore,
112 close #233.
113
3 * completer.py: do not treat [](){} as protectable chars anymore
114 * completer.py: do not treat [](){} as protectable chars anymore
4
115
5 * magic.py, test_cpaste.py: Allow different prefix for pasting
116 * magic.py, test_cpaste.py: Allow different prefix for pasting
@@ -3,7 +3,7 b''
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="180" left="223" height="627" width="1280"/>
6 <global_window_position top="257" left="131" 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/>
@@ -38,18 +38,18 b''
38 <v t="vivainio.20080219230342"><vh>slist to leo</vh></v>
38 <v t="vivainio.20080219230342"><vh>slist to leo</vh></v>
39 </v>
39 </v>
40 </v>
40 </v>
41 <v t="vivainio.20080218195413"><vh>Class tests</vh>
41 <v t="vivainio.20080218195413" a="E"><vh>Class tests</vh>
42 <v t="vivainio.20080218200509"><vh>csvr</vh></v>
42 <v t="vivainio.20080218200509"><vh>csvr</vh></v>
43 <v t="vivainio.20080218191007"><vh>tempfile</vh></v>
43 <v t="vivainio.20080218191007"><vh>tempfile</vh></v>
44 <v t="vivainio.20080218195413.1"><vh>rfile</vh></v>
44 <v t="vivainio.20080218195413.1"><vh>rfile</vh></v>
45 <v t="vivainio.20080219225804"><vh>strlist</vh></v>
45 <v t="vivainio.20080219225804"><vh>strlist</vh></v>
46 </v>
46 </v>
47 <v t="vivainio.20080222201226" a="V"><vh>IPython script push tests</vh></v>
47 <v t="vivainio.20080218201219" a="E"><vh>Direct variables</vh>
48 <v t="vivainio.20080218201219" a="E"><vh>Direct variables</vh>
48 <v t="vivainio.20080222201226"><vh>NewHeadline</vh></v>
49 <v t="vivainio.20080218201219.2"><vh>bar</vh></v>
49 <v t="vivainio.20080218201219.2"><vh>bar</vh></v>
50 </v>
50 </v>
51 <v t="vivainio.20080316144536" a="E"><vh>pylab tests</vh>
51 <v t="vivainio.20080316144536" a="E"><vh>pylab tests</vh>
52 <v t="vivainio.20080316145539.2" a="TV"><vh>Generate testarr</vh></v>
52 <v t="vivainio.20080316145539.2"><vh>Generate testarr</vh></v>
53 <v t="vivainio.20080316085925"><vh>testarr</vh></v>
53 <v t="vivainio.20080316085925"><vh>testarr</vh></v>
54 <v t="vivainio.20080316085950"><vh>Call plotter on testarr</vh></v>
54 <v t="vivainio.20080316085950"><vh>Call plotter on testarr</vh></v>
55 </v>
55 </v>
@@ -128,21 +128,45 b' def format_slist(obj):'
128 <t tx="vivainio.20080222193236">?</t>
128 <t tx="vivainio.20080222193236">?</t>
129 <t tx="vivainio.20080222193236.1">@wrap
129 <t tx="vivainio.20080222193236.1">@wrap
130 @nocolor</t>
130 @nocolor</t>
131 <t tx="vivainio.20080222201226">1+2
131 <t tx="vivainio.20080222201226"># test ipython script 'cleanup' with complex blocks
132 1+2
132 print "hello"
133 print "hello"
133 3+4
134 3+4
134
135
135 def f(x):
136 def f(x):
136 return x.upper()
137 return x.upper()
137
138
138 f('hello world')
139
139
140 if 0:
140 if 0:
141 print "foo"
141 print "foo"
142 else:
142 else:
143 print "bar"
143 print "bar"
144
144
145 </t>
145 def g():
146 pass
147
148 g()
149
150 if 1:
151 if 1:
152 print "hello"
153
154 print "world"
155
156 if 1:
157 print "hello"
158
159 print "word"
160 else:
161 print "foo"
162
163 print "bar"
164 print "baz"
165
166 try:
167 raise Exception
168 except:
169 print "exc ok"</t>
146 <t tx="vivainio.20080222202211"></t>
170 <t tx="vivainio.20080222202211"></t>
147 <t tx="vivainio.20080222202211.1" ipython="7d71005506636f6f7264737101284b0c4bde747102732e">@cl rfile
171 <t tx="vivainio.20080222202211.1" ipython="7d71005506636f6f7264737101284b0c4bde747102732e">@cl rfile
148 hello
172 hello
@@ -170,7 +170,7 b' setup(name = name,'
170 license = license,
170 license = license,
171 platforms = platforms,
171 platforms = platforms,
172 keywords = keywords,
172 keywords = keywords,
173 packages = ['IPython', 'IPython.Extensions', 'IPython.external'],
173 packages = ['IPython', 'IPython.Extensions', 'IPython.external', 'IPython.gui', 'IPython.gui.wx'],
174 scripts = scriptfiles,
174 scripts = scriptfiles,
175
175
176 cmdclass = {'install_data': install_data_ext},
176 cmdclass = {'install_data': install_data_ext},
General Comments 0
You need to be logged in to leave comments. Login now