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 |
@@ -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 |
|
|
73 | if add: | |
74 |
|
|
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 |
|
|
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, |
|
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 |
|
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 t |
|
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. |
|
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. |
|
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 |
|
91 | ANSI_STYLES_BLACK={'0;30': [0,'WHITE'], '0;31': [1,'RED'], | |
437 |
|
|
92 | '0;32': [2,'GREEN'], '0;33': [3,'BROWN'], | |
438 |
|
|
93 | '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'], | |
439 |
|
|
94 | '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'], | |
440 |
|
|
95 | '1;30': [8,'DARK GREY'], '1;31': [9,'RED'], | |
441 |
|
|
96 | '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'], | |
442 |
|
|
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 |
|
|
102 | '0;32': [2,'GREEN'], '0;33': [3,'BROWN'], | |
448 |
|
|
103 | '0;34': [4,'BLUE'], '0;35': [5,'PURPLE'], | |
449 |
|
|
104 | '0;36': [6,'CYAN'], '0;37': [7,'LIGHT GREY'], | |
450 |
|
|
105 | '1;30': [8,'DARK GREY'], '1;31': [9,'RED'], | |
451 |
|
|
106 | '1;32': [10,'SEA GREEN'], '1;33': [11,'YELLOW'], | |
452 |
|
|
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 |
|
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, |
|
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, |
|
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 |
|
|
397 | if self.getCursorPos() > self.getCurrentPromptStart(): | |
748 | self.removeFromTo(self.getCursorPos()-1,self.getCursorPos()) |
|
398 | event.Skip() | |
749 |
|
|
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 |
|
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 |
|
447 | If you want to port this to any other GUI toolkit, just replace the | |
798 |
by YOURGUIConsoleView and make YOURGUIIPythonView derivate |
|
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 |
|
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 |
|
480 | #If you really wnat an empty intrp just call wxIPythonViewPanel | |
821 |
|
|
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 |
|
|
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 |
|
|
605 | if self.pager_nb_lines > 0: | |
961 |
|
|
606 | for line in self.pager_lines[self.pager_index:]: | |
962 |
|
|
607 | self.text_ctrl.write("\x01\x1b[1;36m\x02 "+line+'\n') | |
963 |
|
|
608 | self.pager_nb_lines = 0 | |
964 | self.pager_state = 'DONE' |
|
609 | self.pager_state = 'DONE' | |
|
610 | self.stateShowPrompt() | |||
965 |
|
611 | |||
966 |
#------------------------ |
|
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. |
|
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 |
#------------------------ |
|
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", |
|
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 = |
|
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=" |
|
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" |
|
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