Show More
@@ -1,512 +1,532 b'' | |||||
1 | #!/usr/bin/python |
|
1 | #!/usr/bin/python | |
2 | # -*- coding: iso-8859-15 -*- |
|
2 | # -*- coding: iso-8859-15 -*- | |
3 | ''' |
|
3 | ''' | |
4 | Provides IPython remote instance. |
|
4 | Provides IPython remote instance. | |
5 |
|
5 | |||
6 | @author: Laurent Dufrechou |
|
6 | @author: Laurent Dufrechou | |
7 | laurent.dufrechou _at_ gmail.com |
|
7 | laurent.dufrechou _at_ gmail.com | |
8 | @license: BSD |
|
8 | @license: BSD | |
9 |
|
9 | |||
10 | All rights reserved. This program and the accompanying materials are made |
|
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 |
|
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} |
|
12 | is available at U{http://www.opensource.org/licenses/bsd-license.php} | |
13 | ''' |
|
13 | ''' | |
14 |
|
14 | |||
15 | __version__ = 0.9 |
|
15 | __version__ = 0.9 | |
16 | __author__ = "Laurent Dufrechou" |
|
16 | __author__ = "Laurent Dufrechou" | |
17 | __email__ = "laurent.dufrechou _at_ gmail.com" |
|
17 | __email__ = "laurent.dufrechou _at_ gmail.com" | |
18 | __license__ = "BSD" |
|
18 | __license__ = "BSD" | |
19 |
|
19 | |||
20 | import re |
|
20 | import re | |
21 | import sys |
|
21 | import sys | |
22 | import os |
|
22 | import os | |
23 | import locale |
|
23 | import locale | |
24 | from thread_ex import ThreadEx |
|
24 | from thread_ex import ThreadEx | |
25 |
|
25 | |||
26 | try: |
|
26 | try: | |
27 | import IPython |
|
27 | import IPython | |
28 | except Exception,e: |
|
28 | except Exception,e: | |
29 | print "Error importing IPython (%s)" % str(e) |
|
29 | print "Error importing IPython (%s)" % str(e) | |
30 | raise Exception, e |
|
30 | raise Exception, e | |
31 |
|
31 | |||
32 | ############################################################################## |
|
32 | ############################################################################## | |
33 | class _Helper(object): |
|
33 | class _Helper(object): | |
34 | """Redefine the built-in 'help'. |
|
34 | """Redefine the built-in 'help'. | |
35 | This is a wrapper around pydoc.help (with a twist). |
|
35 | This is a wrapper around pydoc.help (with a twist). | |
36 | """ |
|
36 | """ | |
37 |
|
37 | |||
38 | def __init__(self, pager): |
|
38 | def __init__(self, pager): | |
39 | self._pager = pager |
|
39 | self._pager = pager | |
40 |
|
40 | |||
41 | def __repr__(self): |
|
41 | def __repr__(self): | |
42 | return "Type help() for interactive help, " \ |
|
42 | return "Type help() for interactive help, " \ | |
43 | "or help(object) for help about object." |
|
43 | "or help(object) for help about object." | |
44 |
|
44 | |||
45 | def __call__(self, *args, **kwds): |
|
45 | def __call__(self, *args, **kwds): | |
46 | class DummyWriter(object): |
|
46 | class DummyWriter(object): | |
47 | '''Dumy class to handle help output''' |
|
47 | '''Dumy class to handle help output''' | |
48 | def __init__(self, pager): |
|
48 | def __init__(self, pager): | |
49 | self._pager = pager |
|
49 | self._pager = pager | |
50 |
|
50 | |||
51 | def write(self, data): |
|
51 | def write(self, data): | |
52 | '''hook to fill self._pager''' |
|
52 | '''hook to fill self._pager''' | |
53 | self._pager(data) |
|
53 | self._pager(data) | |
54 |
|
54 | |||
55 | import pydoc |
|
55 | import pydoc | |
56 | pydoc.help.output = DummyWriter(self._pager) |
|
56 | pydoc.help.output = DummyWriter(self._pager) | |
57 | pydoc.help.interact = lambda :1 |
|
57 | pydoc.help.interact = lambda :1 | |
58 |
|
58 | |||
59 | return pydoc.help(*args, **kwds) |
|
59 | return pydoc.help(*args, **kwds) | |
60 |
|
60 | |||
61 |
|
61 | |||
62 | ############################################################################## |
|
62 | ############################################################################## | |
63 | class _CodeExecutor(ThreadEx): |
|
63 | class _CodeExecutor(ThreadEx): | |
64 | ''' Thread that execute ipython code ''' |
|
64 | ''' Thread that execute ipython code ''' | |
65 | def __init__(self, instance): |
|
65 | def __init__(self, instance): | |
66 | ThreadEx.__init__(self) |
|
66 | ThreadEx.__init__(self) | |
67 | self.instance = instance |
|
67 | self.instance = instance | |
68 |
|
68 | |||
69 | def run(self): |
|
69 | def run(self): | |
70 | '''Thread main loop''' |
|
70 | '''Thread main loop''' | |
71 | try: |
|
71 | try: | |
72 | self.instance._doc_text = None |
|
72 | self.instance._doc_text = None | |
73 | self.instance._help_text = None |
|
73 | self.instance._help_text = None | |
74 | self.instance._execute() |
|
74 | self.instance._execute() | |
75 | # used for uper class to generate event after execution |
|
75 | # used for uper class to generate event after execution | |
76 | self.instance._afterExecute() |
|
76 | self.instance._afterExecute() | |
77 |
|
77 | |||
78 | except KeyboardInterrupt: |
|
78 | except KeyboardInterrupt: | |
79 | pass |
|
79 | pass | |
80 |
|
80 | |||
81 |
|
81 | |||
82 | ############################################################################## |
|
82 | ############################################################################## | |
83 | class NonBlockingIPShell(object): |
|
83 | class NonBlockingIPShell(object): | |
84 | ''' |
|
84 | ''' | |
85 | Create an IPython instance, running the commands in a separate, |
|
85 | Create an IPython instance, running the commands in a separate, | |
86 | non-blocking thread. |
|
86 | non-blocking thread. | |
87 | This allows embedding in any GUI without blockage. |
|
87 | This allows embedding in any GUI without blockage. | |
88 |
|
88 | |||
89 | Note: The ThreadEx class supports asynchroneous function call |
|
89 | Note: The ThreadEx class supports asynchroneous function call | |
90 | via raise_exc() |
|
90 | via raise_exc() | |
91 | ''' |
|
91 | ''' | |
92 |
|
92 | |||
93 | def __init__(self, argv=[], user_ns={}, user_global_ns=None, |
|
93 | def __init__(self, argv=[], user_ns={}, user_global_ns=None, | |
94 | cin=None, cout=None, cerr=None, |
|
94 | cin=None, cout=None, cerr=None, | |
95 | ask_exit_handler=None): |
|
95 | ask_exit_handler=None): | |
96 | ''' |
|
96 | ''' | |
97 | @param argv: Command line options for IPython |
|
97 | @param argv: Command line options for IPython | |
98 | @type argv: list |
|
98 | @type argv: list | |
99 | @param user_ns: User namespace. |
|
99 | @param user_ns: User namespace. | |
100 | @type user_ns: dictionary |
|
100 | @type user_ns: dictionary | |
101 | @param user_global_ns: User global namespace. |
|
101 | @param user_global_ns: User global namespace. | |
102 | @type user_global_ns: dictionary. |
|
102 | @type user_global_ns: dictionary. | |
103 | @param cin: Console standard input. |
|
103 | @param cin: Console standard input. | |
104 | @type cin: IO stream |
|
104 | @type cin: IO stream | |
105 | @param cout: Console standard output. |
|
105 | @param cout: Console standard output. | |
106 | @type cout: IO stream |
|
106 | @type cout: IO stream | |
107 | @param cerr: Console standard error. |
|
107 | @param cerr: Console standard error. | |
108 | @type cerr: IO stream |
|
108 | @type cerr: IO stream | |
109 | @param exit_handler: Replacement for builtin exit() function |
|
109 | @param exit_handler: Replacement for builtin exit() function | |
110 | @type exit_handler: function |
|
110 | @type exit_handler: function | |
111 | @param time_loop: Define the sleep time between two thread's loop |
|
111 | @param time_loop: Define the sleep time between two thread's loop | |
112 | @type int |
|
112 | @type int | |
113 | ''' |
|
113 | ''' | |
114 | #ipython0 initialisation |
|
114 | #ipython0 initialisation | |
115 | self._IP = None |
|
115 | self._IP = None | |
116 | self.initIpython0(argv, user_ns, user_global_ns, |
|
116 | self.initIpython0(argv, user_ns, user_global_ns, | |
117 | cin, cout, cerr, |
|
117 | cin, cout, cerr, | |
118 | ask_exit_handler) |
|
118 | ask_exit_handler) | |
119 |
|
119 | |||
120 | #vars used by _execute |
|
120 | #vars used by _execute | |
121 | self._iter_more = 0 |
|
121 | self._iter_more = 0 | |
122 | self._history_level = 0 |
|
122 | self._history_level = 0 | |
123 | self._complete_sep = re.compile('[\s\{\}\[\]\(\)\=]') |
|
123 | self._complete_sep = re.compile('[\s\{\}\[\]\(\)\=]') | |
124 | self._prompt = str(self._IP.outputcache.prompt1).strip() |
|
124 | self._prompt = str(self._IP.outputcache.prompt1).strip() | |
125 |
|
125 | |||
126 | #thread working vars |
|
126 | #thread working vars | |
127 | self._line_to_execute = '' |
|
127 | self._line_to_execute = '' | |
128 | self._threading = True |
|
128 | self._threading = True | |
129 |
|
129 | |||
130 | #vars that will be checked by GUI loop to handle thread states... |
|
130 | #vars that will be checked by GUI loop to handle thread states... | |
131 | #will be replaced later by PostEvent GUI funtions... |
|
131 | #will be replaced later by PostEvent GUI funtions... | |
132 | self._doc_text = None |
|
132 | self._doc_text = None | |
133 | self._help_text = None |
|
133 | self._help_text = None | |
134 | self._add_button = None |
|
134 | self._add_button = None | |
135 |
|
135 | |||
136 | def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, |
|
136 | def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, | |
137 | cin=None, cout=None, cerr=None, |
|
137 | cin=None, cout=None, cerr=None, | |
138 | ask_exit_handler=None): |
|
138 | ask_exit_handler=None): | |
139 | ''' Initialize an ipython0 instance ''' |
|
139 | ''' Initialize an ipython0 instance ''' | |
140 |
|
140 | |||
141 | #first we redefine in/out/error functions of IPython |
|
141 | #first we redefine in/out/error functions of IPython | |
142 | #BUG: we've got a limitation form ipython0 there |
|
142 | #BUG: we've got a limitation form ipython0 there | |
143 | #only one instance can be instanciated else tehre will be |
|
143 | #only one instance can be instanciated else tehre will be | |
144 | #cin/cout/cerr clash... |
|
144 | #cin/cout/cerr clash... | |
145 | if cin: |
|
145 | if cin: | |
146 | IPython.genutils.Term.cin = cin |
|
146 | IPython.genutils.Term.cin = cin | |
147 | if cout: |
|
147 | if cout: | |
148 | IPython.genutils.Term.cout = cout |
|
148 | IPython.genutils.Term.cout = cout | |
149 | if cerr: |
|
149 | if cerr: | |
150 | IPython.genutils.Term.cerr = cerr |
|
150 | IPython.genutils.Term.cerr = cerr | |
151 |
|
151 | |||
152 | excepthook = sys.excepthook |
|
152 | excepthook = sys.excepthook | |
153 |
|
153 | |||
154 | #Hack to save sys.displayhook, because ipython seems to overwrite it... |
|
154 | #Hack to save sys.displayhook, because ipython seems to overwrite it... | |
155 | self.sys_displayhook_ori = sys.displayhook |
|
155 | self.sys_displayhook_ori = sys.displayhook | |
156 |
|
156 | |||
157 | self._IP = IPython.Shell.make_IPython( |
|
157 | self._IP = IPython.Shell.make_IPython( | |
158 | argv,user_ns=user_ns, |
|
158 | argv,user_ns=user_ns, | |
159 | user_global_ns=user_global_ns, |
|
159 | user_global_ns=user_global_ns, | |
160 | embedded=True, |
|
160 | embedded=True, | |
161 | shell_class=IPython.Shell.InteractiveShell) |
|
161 | shell_class=IPython.Shell.InteractiveShell) | |
162 |
|
162 | |||
163 | #we save ipython0 displayhook and we restore sys.displayhook |
|
163 | #we save ipython0 displayhook and we restore sys.displayhook | |
164 | self.displayhook = sys.displayhook |
|
164 | self.displayhook = sys.displayhook | |
165 | sys.displayhook = self.sys_displayhook_ori |
|
165 | sys.displayhook = self.sys_displayhook_ori | |
166 |
|
166 | |||
167 | #we replace IPython default encoding by wx locale encoding |
|
167 | #we replace IPython default encoding by wx locale encoding | |
168 | loc = locale.getpreferredencoding() |
|
168 | loc = locale.getpreferredencoding() | |
169 | if loc: |
|
169 | if loc: | |
170 | self._IP.stdin_encoding = loc |
|
170 | self._IP.stdin_encoding = loc | |
171 | #we replace the ipython default pager by our pager |
|
171 | #we replace the ipython default pager by our pager | |
172 | self._IP.set_hook('show_in_pager', self._pager) |
|
172 | self._IP.set_hook('show_in_pager', self._pager) | |
173 |
|
173 | |||
174 | #we replace the ipython default shell command caller by our shell handler |
|
174 | #we replace the ipython default shell command caller by our shell handler | |
175 | self._IP.set_hook('shell_hook', self._shell) |
|
175 | self._IP.set_hook('shell_hook', self._shell) | |
176 |
|
176 | |||
177 | #we replace the ipython default input command caller by our method |
|
177 | #we replace the ipython default input command caller by our method | |
178 | IPython.iplib.raw_input_original = self._raw_input |
|
178 | IPython.iplib.raw_input_original = self._raw_input | |
179 | #we replace the ipython default exit command by our method |
|
179 | #we replace the ipython default exit command by our method | |
180 | self._IP.exit = ask_exit_handler |
|
180 | self._IP.exit = ask_exit_handler | |
181 | #we replace the help command |
|
181 | #we replace the help command | |
182 | self._IP.user_ns['help'] = _Helper(self._pager_help) |
|
182 | self._IP.user_ns['help'] = _Helper(self._pager_help) | |
183 |
|
183 | |||
184 | #we disable cpase magic... until we found a way to use it properly. |
|
184 | #we disable cpase magic... until we found a way to use it properly. | |
185 | #import IPython.ipapi |
|
185 | #import IPython.ipapi | |
186 | ip = IPython.ipapi.get() |
|
186 | ip = IPython.ipapi.get() | |
187 | def bypassMagic(self, arg): |
|
187 | def bypassMagic(self, arg): | |
188 | print '%this magic is currently disabled.' |
|
188 | print '%this magic is currently disabled.' | |
189 | ip.expose_magic('cpaste', bypassMagic) |
|
189 | ip.expose_magic('cpaste', bypassMagic) | |
190 |
|
190 | |||
|
191 | def resetMagic(self, arg): | |||
|
192 | """Resets the namespace by removing all names defined by the user. | |||
|
193 | ||||
|
194 | Input/Output history are left around in case you need them.""" | |||
|
195 | ||||
|
196 | ans = True ##todo find away to ask the user... | |||
|
197 | ##seems hard to do it cleanly... | |||
|
198 | if not ans: | |||
|
199 | print 'Nothing done.' | |||
|
200 | return | |||
|
201 | user_ns = self.shell.user_ns | |||
|
202 | for i in self.magic_who_ls(): | |||
|
203 | del(user_ns[i]) | |||
|
204 | ||||
|
205 | # Also flush the private list of module references kept for script | |||
|
206 | # execution protection | |||
|
207 | self.shell._user_main_modules[:] = [] | |||
|
208 | ||||
|
209 | ip.expose_magic('reset', resetMagic) | |||
|
210 | ||||
191 | sys.excepthook = excepthook |
|
211 | sys.excepthook = excepthook | |
192 |
|
212 | |||
193 | #----------------------- Thread management section ---------------------- |
|
213 | #----------------------- Thread management section ---------------------- | |
194 | def doExecute(self, line): |
|
214 | def doExecute(self, line): | |
195 | """ |
|
215 | """ | |
196 | Tell the thread to process the 'line' command |
|
216 | Tell the thread to process the 'line' command | |
197 | """ |
|
217 | """ | |
198 |
|
218 | |||
199 | self._line_to_execute = line |
|
219 | self._line_to_execute = line | |
200 |
|
220 | |||
201 | if self._threading: |
|
221 | if self._threading: | |
202 | #we launch the ipython line execution in a thread to make it interruptible |
|
222 | #we launch the ipython line execution in a thread to make it interruptible | |
203 | #with include it in self namespace to be able to call ce.raise_exc(KeyboardInterrupt) |
|
223 | #with include it in self namespace to be able to call ce.raise_exc(KeyboardInterrupt) | |
204 | self.ce = _CodeExecutor(self) |
|
224 | self.ce = _CodeExecutor(self) | |
205 | self.ce.start() |
|
225 | self.ce.start() | |
206 | else: |
|
226 | else: | |
207 | try: |
|
227 | try: | |
208 | self._doc_text = None |
|
228 | self._doc_text = None | |
209 | self._help_text = None |
|
229 | self._help_text = None | |
210 | self._execute() |
|
230 | self._execute() | |
211 | # used for uper class to generate event after execution |
|
231 | # used for uper class to generate event after execution | |
212 | self._afterExecute() |
|
232 | self._afterExecute() | |
213 |
|
233 | |||
214 | except KeyboardInterrupt: |
|
234 | except KeyboardInterrupt: | |
215 | pass |
|
235 | pass | |
216 |
|
236 | |||
217 | #----------------------- IPython management section ---------------------- |
|
237 | #----------------------- IPython management section ---------------------- | |
218 | def getThreading(self): |
|
238 | def getThreading(self): | |
219 | """ |
|
239 | """ | |
220 | Returns threading status, is set to True, then each command sent to |
|
240 | Returns threading status, is set to True, then each command sent to | |
221 | the interpreter will be executed in a separated thread allowing, |
|
241 | the interpreter will be executed in a separated thread allowing, | |
222 | for example, breaking a long running commands. |
|
242 | for example, breaking a long running commands. | |
223 | Disallowing it, permits better compatibilty with instance that is embedding |
|
243 | Disallowing it, permits better compatibilty with instance that is embedding | |
224 | IPython instance. |
|
244 | IPython instance. | |
225 |
|
245 | |||
226 | @return: Execution method |
|
246 | @return: Execution method | |
227 | @rtype: bool |
|
247 | @rtype: bool | |
228 | """ |
|
248 | """ | |
229 | return self._threading |
|
249 | return self._threading | |
230 |
|
250 | |||
231 | def setThreading(self, state): |
|
251 | def setThreading(self, state): | |
232 | """ |
|
252 | """ | |
233 | Sets threading state, if set to True, then each command sent to |
|
253 | Sets threading state, if set to True, then each command sent to | |
234 | the interpreter will be executed in a separated thread allowing, |
|
254 | the interpreter will be executed in a separated thread allowing, | |
235 | for example, breaking a long running commands. |
|
255 | for example, breaking a long running commands. | |
236 | Disallowing it, permits better compatibilty with instance that is embedding |
|
256 | Disallowing it, permits better compatibilty with instance that is embedding | |
237 | IPython instance. |
|
257 | IPython instance. | |
238 |
|
258 | |||
239 | @param state: Sets threading state |
|
259 | @param state: Sets threading state | |
240 | @type bool |
|
260 | @type bool | |
241 | """ |
|
261 | """ | |
242 | self._threading = state |
|
262 | self._threading = state | |
243 |
|
263 | |||
244 | def getDocText(self): |
|
264 | def getDocText(self): | |
245 | """ |
|
265 | """ | |
246 | Returns the output of the processing that need to be paged (if any) |
|
266 | Returns the output of the processing that need to be paged (if any) | |
247 |
|
267 | |||
248 | @return: The std output string. |
|
268 | @return: The std output string. | |
249 | @rtype: string |
|
269 | @rtype: string | |
250 | """ |
|
270 | """ | |
251 | return self._doc_text |
|
271 | return self._doc_text | |
252 |
|
272 | |||
253 | def getHelpText(self): |
|
273 | def getHelpText(self): | |
254 | """ |
|
274 | """ | |
255 | Returns the output of the processing that need to be paged via help pager(if any) |
|
275 | Returns the output of the processing that need to be paged via help pager(if any) | |
256 |
|
276 | |||
257 | @return: The std output string. |
|
277 | @return: The std output string. | |
258 | @rtype: string |
|
278 | @rtype: string | |
259 | """ |
|
279 | """ | |
260 | return self._help_text |
|
280 | return self._help_text | |
261 |
|
281 | |||
262 | def getBanner(self): |
|
282 | def getBanner(self): | |
263 | """ |
|
283 | """ | |
264 | Returns the IPython banner for useful info on IPython instance |
|
284 | Returns the IPython banner for useful info on IPython instance | |
265 |
|
285 | |||
266 | @return: The banner string. |
|
286 | @return: The banner string. | |
267 | @rtype: string |
|
287 | @rtype: string | |
268 | """ |
|
288 | """ | |
269 | return self._IP.BANNER |
|
289 | return self._IP.BANNER | |
270 |
|
290 | |||
271 | def getPromptCount(self): |
|
291 | def getPromptCount(self): | |
272 | """ |
|
292 | """ | |
273 | Returns the prompt number. |
|
293 | Returns the prompt number. | |
274 | Each time a user execute a line in the IPython shell the prompt count is increased |
|
294 | Each time a user execute a line in the IPython shell the prompt count is increased | |
275 |
|
295 | |||
276 | @return: The prompt number |
|
296 | @return: The prompt number | |
277 | @rtype: int |
|
297 | @rtype: int | |
278 | """ |
|
298 | """ | |
279 | return self._IP.outputcache.prompt_count |
|
299 | return self._IP.outputcache.prompt_count | |
280 |
|
300 | |||
281 | def getPrompt(self): |
|
301 | def getPrompt(self): | |
282 | """ |
|
302 | """ | |
283 | Returns current prompt inside IPython instance |
|
303 | Returns current prompt inside IPython instance | |
284 | (Can be In [...]: ot ...:) |
|
304 | (Can be In [...]: ot ...:) | |
285 |
|
305 | |||
286 | @return: The current prompt. |
|
306 | @return: The current prompt. | |
287 | @rtype: string |
|
307 | @rtype: string | |
288 | """ |
|
308 | """ | |
289 | return self._prompt |
|
309 | return self._prompt | |
290 |
|
310 | |||
291 | def getIndentation(self): |
|
311 | def getIndentation(self): | |
292 | """ |
|
312 | """ | |
293 | Returns the current indentation level |
|
313 | Returns the current indentation level | |
294 | Usefull to put the caret at the good start position if we want to do autoindentation. |
|
314 | Usefull to put the caret at the good start position if we want to do autoindentation. | |
295 |
|
315 | |||
296 | @return: The indentation level. |
|
316 | @return: The indentation level. | |
297 | @rtype: int |
|
317 | @rtype: int | |
298 | """ |
|
318 | """ | |
299 | return self._IP.indent_current_nsp |
|
319 | return self._IP.indent_current_nsp | |
300 |
|
320 | |||
301 | def updateNamespace(self, ns_dict): |
|
321 | def updateNamespace(self, ns_dict): | |
302 | ''' |
|
322 | ''' | |
303 | Add the current dictionary to the shell namespace. |
|
323 | Add the current dictionary to the shell namespace. | |
304 |
|
324 | |||
305 | @param ns_dict: A dictionary of symbol-values. |
|
325 | @param ns_dict: A dictionary of symbol-values. | |
306 | @type ns_dict: dictionary |
|
326 | @type ns_dict: dictionary | |
307 | ''' |
|
327 | ''' | |
308 | self._IP.user_ns.update(ns_dict) |
|
328 | self._IP.user_ns.update(ns_dict) | |
309 |
|
329 | |||
310 | def complete(self, line): |
|
330 | def complete(self, line): | |
311 | ''' |
|
331 | ''' | |
312 | Returns an auto completed line and/or posibilities for completion. |
|
332 | Returns an auto completed line and/or posibilities for completion. | |
313 |
|
333 | |||
314 | @param line: Given line so far. |
|
334 | @param line: Given line so far. | |
315 | @type line: string |
|
335 | @type line: string | |
316 |
|
336 | |||
317 | @return: Line completed as for as possible, |
|
337 | @return: Line completed as for as possible, | |
318 | and possible further completions. |
|
338 | and possible further completions. | |
319 | @rtype: tuple |
|
339 | @rtype: tuple | |
320 | ''' |
|
340 | ''' | |
321 | split_line = self._complete_sep.split(line) |
|
341 | split_line = self._complete_sep.split(line) | |
322 | possibilities = self._IP.complete(split_line[-1]) |
|
342 | possibilities = self._IP.complete(split_line[-1]) | |
323 | if possibilities: |
|
343 | if possibilities: | |
324 |
|
344 | |||
325 | def _commonPrefix(str1, str2): |
|
345 | def _commonPrefix(str1, str2): | |
326 | ''' |
|
346 | ''' | |
327 | Reduction function. returns common prefix of two given strings. |
|
347 | Reduction function. returns common prefix of two given strings. | |
328 |
|
348 | |||
329 | @param str1: First string. |
|
349 | @param str1: First string. | |
330 | @type str1: string |
|
350 | @type str1: string | |
331 | @param str2: Second string |
|
351 | @param str2: Second string | |
332 | @type str2: string |
|
352 | @type str2: string | |
333 |
|
353 | |||
334 | @return: Common prefix to both strings. |
|
354 | @return: Common prefix to both strings. | |
335 | @rtype: string |
|
355 | @rtype: string | |
336 | ''' |
|
356 | ''' | |
337 | for i in range(len(str1)): |
|
357 | for i in range(len(str1)): | |
338 | if not str2.startswith(str1[:i+1]): |
|
358 | if not str2.startswith(str1[:i+1]): | |
339 | return str1[:i] |
|
359 | return str1[:i] | |
340 | return str1 |
|
360 | return str1 | |
341 | common_prefix = reduce(_commonPrefix, possibilities) |
|
361 | common_prefix = reduce(_commonPrefix, possibilities) | |
342 | completed = line[:-len(split_line[-1])]+common_prefix |
|
362 | completed = line[:-len(split_line[-1])]+common_prefix | |
343 | else: |
|
363 | else: | |
344 | completed = line |
|
364 | completed = line | |
345 | return completed, possibilities |
|
365 | return completed, possibilities | |
346 |
|
366 | |||
347 | def historyBack(self): |
|
367 | def historyBack(self): | |
348 | ''' |
|
368 | ''' | |
349 | Provides one history command back. |
|
369 | Provides one history command back. | |
350 |
|
370 | |||
351 | @return: The command string. |
|
371 | @return: The command string. | |
352 | @rtype: string |
|
372 | @rtype: string | |
353 | ''' |
|
373 | ''' | |
354 | history = '' |
|
374 | history = '' | |
355 | #the below while loop is used to suppress empty history lines |
|
375 | #the below while loop is used to suppress empty history lines | |
356 | while((history == '' or history == '\n') and self._history_level >0): |
|
376 | while((history == '' or history == '\n') and self._history_level >0): | |
357 | if self._history_level >= 1: |
|
377 | if self._history_level >= 1: | |
358 | self._history_level -= 1 |
|
378 | self._history_level -= 1 | |
359 | history = self._getHistory() |
|
379 | history = self._getHistory() | |
360 | return history |
|
380 | return history | |
361 |
|
381 | |||
362 | def historyForward(self): |
|
382 | def historyForward(self): | |
363 | ''' |
|
383 | ''' | |
364 | Provides one history command forward. |
|
384 | Provides one history command forward. | |
365 |
|
385 | |||
366 | @return: The command string. |
|
386 | @return: The command string. | |
367 | @rtype: string |
|
387 | @rtype: string | |
368 | ''' |
|
388 | ''' | |
369 | history = '' |
|
389 | history = '' | |
370 | #the below while loop is used to suppress empty history lines |
|
390 | #the below while loop is used to suppress empty history lines | |
371 | while((history == '' or history == '\n') \ |
|
391 | while((history == '' or history == '\n') \ | |
372 | and self._history_level <= self._getHistoryMaxIndex()): |
|
392 | and self._history_level <= self._getHistoryMaxIndex()): | |
373 | if self._history_level < self._getHistoryMaxIndex(): |
|
393 | if self._history_level < self._getHistoryMaxIndex(): | |
374 | self._history_level += 1 |
|
394 | self._history_level += 1 | |
375 | history = self._getHistory() |
|
395 | history = self._getHistory() | |
376 | else: |
|
396 | else: | |
377 | if self._history_level == self._getHistoryMaxIndex(): |
|
397 | if self._history_level == self._getHistoryMaxIndex(): | |
378 | history = self._getHistory() |
|
398 | history = self._getHistory() | |
379 | self._history_level += 1 |
|
399 | self._history_level += 1 | |
380 | else: |
|
400 | else: | |
381 | history = '' |
|
401 | history = '' | |
382 | return history |
|
402 | return history | |
383 |
|
403 | |||
384 | def initHistoryIndex(self): |
|
404 | def initHistoryIndex(self): | |
385 | ''' |
|
405 | ''' | |
386 | set history to last command entered |
|
406 | set history to last command entered | |
387 | ''' |
|
407 | ''' | |
388 | self._history_level = self._getHistoryMaxIndex()+1 |
|
408 | self._history_level = self._getHistoryMaxIndex()+1 | |
389 |
|
409 | |||
390 | #----------------------- IPython PRIVATE management section -------------- |
|
410 | #----------------------- IPython PRIVATE management section -------------- | |
391 | def _afterExecute(self): |
|
411 | def _afterExecute(self): | |
392 | ''' |
|
412 | ''' | |
393 | Can be redefined to generate post event after excution is done |
|
413 | Can be redefined to generate post event after excution is done | |
394 | ''' |
|
414 | ''' | |
395 | pass |
|
415 | pass | |
396 |
|
416 | |||
397 | #def _askExit(self): |
|
417 | #def _askExit(self): | |
398 | # ''' |
|
418 | # ''' | |
399 | # Can be redefined to generate post event to exit the Ipython shell |
|
419 | # Can be redefined to generate post event to exit the Ipython shell | |
400 | # ''' |
|
420 | # ''' | |
401 | # pass |
|
421 | # pass | |
402 |
|
422 | |||
403 | def _getHistoryMaxIndex(self): |
|
423 | def _getHistoryMaxIndex(self): | |
404 | ''' |
|
424 | ''' | |
405 | returns the max length of the history buffer |
|
425 | returns the max length of the history buffer | |
406 |
|
426 | |||
407 | @return: history length |
|
427 | @return: history length | |
408 | @rtype: int |
|
428 | @rtype: int | |
409 | ''' |
|
429 | ''' | |
410 | return len(self._IP.input_hist_raw)-1 |
|
430 | return len(self._IP.input_hist_raw)-1 | |
411 |
|
431 | |||
412 | def _getHistory(self): |
|
432 | def _getHistory(self): | |
413 | ''' |
|
433 | ''' | |
414 | Get's the command string of the current history level. |
|
434 | Get's the command string of the current history level. | |
415 |
|
435 | |||
416 | @return: Historic command stri |
|
436 | @return: Historic command stri | |
417 | @rtype: string |
|
437 | @rtype: string | |
418 | ''' |
|
438 | ''' | |
419 | rv = self._IP.input_hist_raw[self._history_level].strip('\n') |
|
439 | rv = self._IP.input_hist_raw[self._history_level].strip('\n') | |
420 | return rv |
|
440 | return rv | |
421 |
|
441 | |||
422 | def _pager_help(self, text): |
|
442 | def _pager_help(self, text): | |
423 | ''' |
|
443 | ''' | |
424 | This function is used as a callback replacment to IPython help pager function |
|
444 | This function is used as a callback replacment to IPython help pager function | |
425 |
|
445 | |||
426 | It puts the 'text' value inside the self._help_text string that can be retrived via |
|
446 | It puts the 'text' value inside the self._help_text string that can be retrived via | |
427 | getHelpText function. |
|
447 | getHelpText function. | |
428 | ''' |
|
448 | ''' | |
429 | if self._help_text == None: |
|
449 | if self._help_text == None: | |
430 | self._help_text = text |
|
450 | self._help_text = text | |
431 | else: |
|
451 | else: | |
432 | self._help_text += text |
|
452 | self._help_text += text | |
433 |
|
453 | |||
434 | def _pager(self, IP, text): |
|
454 | def _pager(self, IP, text): | |
435 | ''' |
|
455 | ''' | |
436 | This function is used as a callback replacment to IPython pager function |
|
456 | This function is used as a callback replacment to IPython pager function | |
437 |
|
457 | |||
438 | It puts the 'text' value inside the self._doc_text string that can be retrived via |
|
458 | It puts the 'text' value inside the self._doc_text string that can be retrived via | |
439 | getDocText function. |
|
459 | getDocText function. | |
440 | ''' |
|
460 | ''' | |
441 | self._doc_text = text |
|
461 | self._doc_text = text | |
442 |
|
462 | |||
443 | def _raw_input(self, prompt=''): |
|
463 | def _raw_input(self, prompt=''): | |
444 | ''' |
|
464 | ''' | |
445 | Custom raw_input() replacement. Get's current line from console buffer. |
|
465 | Custom raw_input() replacement. Get's current line from console buffer. | |
446 |
|
466 | |||
447 | @param prompt: Prompt to print. Here for compatability as replacement. |
|
467 | @param prompt: Prompt to print. Here for compatability as replacement. | |
448 | @type prompt: string |
|
468 | @type prompt: string | |
449 |
|
469 | |||
450 | @return: The current command line text. |
|
470 | @return: The current command line text. | |
451 | @rtype: string |
|
471 | @rtype: string | |
452 | ''' |
|
472 | ''' | |
453 | return self._line_to_execute |
|
473 | return self._line_to_execute | |
454 |
|
474 | |||
455 | def _execute(self): |
|
475 | def _execute(self): | |
456 | ''' |
|
476 | ''' | |
457 | Executes the current line provided by the shell object. |
|
477 | Executes the current line provided by the shell object. | |
458 | ''' |
|
478 | ''' | |
459 |
|
479 | |||
460 | orig_stdout = sys.stdout |
|
480 | orig_stdout = sys.stdout | |
461 | sys.stdout = IPython.Shell.Term.cout |
|
481 | sys.stdout = IPython.Shell.Term.cout | |
462 | #self.sys_displayhook_ori = sys.displayhook |
|
482 | #self.sys_displayhook_ori = sys.displayhook | |
463 | #sys.displayhook = self.displayhook |
|
483 | #sys.displayhook = self.displayhook | |
464 |
|
484 | |||
465 | try: |
|
485 | try: | |
466 | line = self._IP.raw_input(None, self._iter_more) |
|
486 | line = self._IP.raw_input(None, self._iter_more) | |
467 | if self._IP.autoindent: |
|
487 | if self._IP.autoindent: | |
468 | self._IP.readline_startup_hook(None) |
|
488 | self._IP.readline_startup_hook(None) | |
469 |
|
489 | |||
470 | except KeyboardInterrupt: |
|
490 | except KeyboardInterrupt: | |
471 | self._IP.write('\nKeyboardInterrupt\n') |
|
491 | self._IP.write('\nKeyboardInterrupt\n') | |
472 | self._IP.resetbuffer() |
|
492 | self._IP.resetbuffer() | |
473 | # keep cache in sync with the prompt counter: |
|
493 | # keep cache in sync with the prompt counter: | |
474 | self._IP.outputcache.prompt_count -= 1 |
|
494 | self._IP.outputcache.prompt_count -= 1 | |
475 |
|
495 | |||
476 | if self._IP.autoindent: |
|
496 | if self._IP.autoindent: | |
477 | self._IP.indent_current_nsp = 0 |
|
497 | self._IP.indent_current_nsp = 0 | |
478 | self._iter_more = 0 |
|
498 | self._iter_more = 0 | |
479 | except: |
|
499 | except: | |
480 | self._IP.showtraceback() |
|
500 | self._IP.showtraceback() | |
481 | else: |
|
501 | else: | |
482 | self._iter_more = self._IP.push(line) |
|
502 | self._iter_more = self._IP.push(line) | |
483 | if (self._IP.SyntaxTB.last_syntax_error and self._IP.rc.autoedit_syntax): |
|
503 | if (self._IP.SyntaxTB.last_syntax_error and self._IP.rc.autoedit_syntax): | |
484 | self._IP.edit_syntax_error() |
|
504 | self._IP.edit_syntax_error() | |
485 | if self._iter_more: |
|
505 | if self._iter_more: | |
486 | self._prompt = str(self._IP.outputcache.prompt2).strip() |
|
506 | self._prompt = str(self._IP.outputcache.prompt2).strip() | |
487 | if self._IP.autoindent: |
|
507 | if self._IP.autoindent: | |
488 | self._IP.readline_startup_hook(self._IP.pre_readline) |
|
508 | self._IP.readline_startup_hook(self._IP.pre_readline) | |
489 | else: |
|
509 | else: | |
490 | self._prompt = str(self._IP.outputcache.prompt1).strip() |
|
510 | self._prompt = str(self._IP.outputcache.prompt1).strip() | |
491 | self._IP.indent_current_nsp = 0 #we set indentation to 0 |
|
511 | self._IP.indent_current_nsp = 0 #we set indentation to 0 | |
492 |
|
512 | |||
493 | sys.stdout = orig_stdout |
|
513 | sys.stdout = orig_stdout | |
494 | #sys.displayhook = self.sys_displayhook_ori |
|
514 | #sys.displayhook = self.sys_displayhook_ori | |
495 |
|
515 | |||
496 | def _shell(self, ip, cmd): |
|
516 | def _shell(self, ip, cmd): | |
497 | ''' |
|
517 | ''' | |
498 | Replacement method to allow shell commands without them blocking. |
|
518 | Replacement method to allow shell commands without them blocking. | |
499 |
|
519 | |||
500 | @param ip: Ipython instance, same as self._IP |
|
520 | @param ip: Ipython instance, same as self._IP | |
501 | @type cmd: Ipython instance |
|
521 | @type cmd: Ipython instance | |
502 | @param cmd: Shell command to execute. |
|
522 | @param cmd: Shell command to execute. | |
503 | @type cmd: string |
|
523 | @type cmd: string | |
504 | ''' |
|
524 | ''' | |
505 | stdin, stdout = os.popen4(cmd) |
|
525 | stdin, stdout = os.popen4(cmd) | |
506 | result = stdout.read().decode('cp437').encode(locale.getpreferredencoding()) |
|
526 | result = stdout.read().decode('cp437').encode(locale.getpreferredencoding()) | |
507 | #we use print command because the shell command is called |
|
527 | #we use print command because the shell command is called | |
508 | #inside IPython instance and thus is redirected to thread cout |
|
528 | #inside IPython instance and thus is redirected to thread cout | |
509 | #"\x01\x1b[1;36m\x02" <-- add colour to the text... |
|
529 | #"\x01\x1b[1;36m\x02" <-- add colour to the text... | |
510 | print "\x01\x1b[1;36m\x02"+result |
|
530 | print "\x01\x1b[1;36m\x02"+result | |
511 | stdout.close() |
|
531 | stdout.close() | |
512 | stdin.close() |
|
532 | stdin.close() |
General Comments 0
You need to be logged in to leave comments.
Login now