Show More
@@ -1,465 +1,471 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, after): |
|
65 | def __init__(self, instance, after): | |
66 | ThreadEx.__init__(self) |
|
66 | ThreadEx.__init__(self) | |
67 | self.instance = instance |
|
67 | self.instance = instance | |
68 | self._afterExecute = after |
|
68 | self._afterExecute = after | |
69 |
|
69 | |||
70 | def run(self): |
|
70 | def run(self): | |
71 | '''Thread main loop''' |
|
71 | '''Thread main loop''' | |
72 | try: |
|
72 | try: | |
73 | self.instance._doc_text = None |
|
73 | self.instance._doc_text = None | |
74 | self.instance._help_text = None |
|
74 | self.instance._help_text = None | |
75 | self.instance._execute() |
|
75 | self.instance._execute() | |
76 | # used for uper class to generate event after execution |
|
76 | # used for uper class to generate event after execution | |
77 | self._afterExecute() |
|
77 | self._afterExecute() | |
78 |
|
78 | |||
79 | except KeyboardInterrupt: |
|
79 | except KeyboardInterrupt: | |
80 | pass |
|
80 | pass | |
81 |
|
81 | |||
82 |
|
82 | |||
83 | ############################################################################## |
|
83 | ############################################################################## | |
84 | class NonBlockingIPShell(object): |
|
84 | class NonBlockingIPShell(object): | |
85 | ''' |
|
85 | ''' | |
86 | Create an IPython instance, running the commands in a separate, |
|
86 | Create an IPython instance, running the commands in a separate, | |
87 | non-blocking thread. |
|
87 | non-blocking thread. | |
88 | This allows embedding in any GUI without blockage. |
|
88 | This allows embedding in any GUI without blockage. | |
89 |
|
89 | |||
90 | Note: The ThreadEx class supports asynchroneous function call |
|
90 | Note: The ThreadEx class supports asynchroneous function call | |
91 | via raise_exc() |
|
91 | via raise_exc() | |
92 | ''' |
|
92 | ''' | |
93 |
|
93 | |||
94 | def __init__(self, argv=[], user_ns={}, user_global_ns=None, |
|
94 | def __init__(self, argv=[], user_ns={}, user_global_ns=None, | |
95 | cin=None, cout=None, cerr=None, |
|
95 | cin=None, cout=None, cerr=None, | |
96 | ask_exit_handler=None): |
|
96 | ask_exit_handler=None): | |
97 | ''' |
|
97 | ''' | |
98 | @param argv: Command line options for IPython |
|
98 | @param argv: Command line options for IPython | |
99 | @type argv: list |
|
99 | @type argv: list | |
100 | @param user_ns: User namespace. |
|
100 | @param user_ns: User namespace. | |
101 | @type user_ns: dictionary |
|
101 | @type user_ns: dictionary | |
102 | @param user_global_ns: User global namespace. |
|
102 | @param user_global_ns: User global namespace. | |
103 | @type user_global_ns: dictionary. |
|
103 | @type user_global_ns: dictionary. | |
104 | @param cin: Console standard input. |
|
104 | @param cin: Console standard input. | |
105 | @type cin: IO stream |
|
105 | @type cin: IO stream | |
106 | @param cout: Console standard output. |
|
106 | @param cout: Console standard output. | |
107 | @type cout: IO stream |
|
107 | @type cout: IO stream | |
108 | @param cerr: Console standard error. |
|
108 | @param cerr: Console standard error. | |
109 | @type cerr: IO stream |
|
109 | @type cerr: IO stream | |
110 | @param exit_handler: Replacement for builtin exit() function |
|
110 | @param exit_handler: Replacement for builtin exit() function | |
111 | @type exit_handler: function |
|
111 | @type exit_handler: function | |
112 | @param time_loop: Define the sleep time between two thread's loop |
|
112 | @param time_loop: Define the sleep time between two thread's loop | |
113 | @type int |
|
113 | @type int | |
114 | ''' |
|
114 | ''' | |
115 | #ipython0 initialisation |
|
115 | #ipython0 initialisation | |
116 | self._IP = None |
|
116 | self._IP = None | |
117 | self._term = None |
|
117 | self._term = None | |
118 | self.initIpython0(argv, user_ns, user_global_ns, |
|
118 | self.initIpython0(argv, user_ns, user_global_ns, | |
119 | cin, cout, cerr, |
|
119 | cin, cout, cerr, | |
120 | ask_exit_handler) |
|
120 | ask_exit_handler) | |
121 |
|
121 | |||
122 | #vars used by _execute |
|
122 | #vars used by _execute | |
123 | self._iter_more = 0 |
|
123 | self._iter_more = 0 | |
124 | self._history_level = 0 |
|
124 | self._history_level = 0 | |
125 | self._complete_sep = re.compile('[\s\{\}\[\]\(\)\=]') |
|
125 | self._complete_sep = re.compile('[\s\{\}\[\]\(\)\=]') | |
126 | self._prompt = str(self._IP.outputcache.prompt1).strip() |
|
126 | self._prompt = str(self._IP.outputcache.prompt1).strip() | |
127 |
|
127 | |||
128 | #thread working vars |
|
128 | #thread working vars | |
129 | self._line_to_execute = '' |
|
129 | self._line_to_execute = '' | |
130 |
|
130 | |||
131 | #vars that will be checked by GUI loop to handle thread states... |
|
131 | #vars that will be checked by GUI loop to handle thread states... | |
132 | #will be replaced later by PostEvent GUI funtions... |
|
132 | #will be replaced later by PostEvent GUI funtions... | |
133 | self._doc_text = None |
|
133 | self._doc_text = None | |
134 | self._help_text = None |
|
134 | self._help_text = None | |
135 | self._add_button = None |
|
135 | self._add_button = None | |
136 |
|
136 | |||
137 | def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, |
|
137 | def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, | |
138 | cin=None, cout=None, cerr=None, |
|
138 | cin=None, cout=None, cerr=None, | |
139 | ask_exit_handler=None): |
|
139 | ask_exit_handler=None): | |
140 | ''' Initialize an ithon0 instance ''' |
|
140 | ''' Initialize an ithon0 instance ''' | |
141 |
|
141 | |||
142 | #first we redefine in/out/error functions of IPython |
|
142 | #first we redefine in/out/error functions of IPython | |
143 | if cin: |
|
143 | if cin: | |
144 | IPython.Shell.Term.cin = cin |
|
144 | IPython.Shell.Term.cin = cin | |
145 | if cout: |
|
145 | if cout: | |
146 | IPython.Shell.Term.cout = cout |
|
146 | IPython.Shell.Term.cout = cout | |
147 | if cerr: |
|
147 | if cerr: | |
148 | IPython.Shell.Term.cerr = cerr |
|
148 | IPython.Shell.Term.cerr = cerr | |
149 |
|
149 | |||
150 | # This is to get rid of the blockage that accurs during |
|
150 | # This is to get rid of the blockage that accurs during | |
151 | # IPython.Shell.InteractiveShell.user_setup() |
|
151 | # IPython.Shell.InteractiveShell.user_setup() | |
152 | IPython.iplib.raw_input = lambda x: None |
|
152 | IPython.iplib.raw_input = lambda x: None | |
153 |
|
153 | |||
154 | self._term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr) |
|
154 | self._term = IPython.genutils.IOTerm(cin=cin, cout=cout, cerr=cerr) | |
155 |
|
155 | |||
156 | excepthook = sys.excepthook |
|
156 | excepthook = sys.excepthook | |
157 |
|
157 | #Hack to save sys.displayhook, because ipython seems to overwrite it... | ||
|
158 | self.sys_displayhook_ori = sys.displayhook | |||
|
159 | ||||
158 | self._IP = IPython.Shell.make_IPython( |
|
160 | self._IP = IPython.Shell.make_IPython( | |
159 | argv,user_ns=user_ns, |
|
161 | argv,user_ns=user_ns, | |
160 | user_global_ns=user_global_ns, |
|
162 | user_global_ns=user_global_ns, | |
161 | embedded=True, |
|
163 | embedded=True, | |
162 | shell_class=IPython.Shell.InteractiveShell) |
|
164 | shell_class=IPython.Shell.InteractiveShell) | |
163 |
|
165 | |||
|
166 | #we restore sys.displayhook | |||
|
167 | sys.displayhook = self.sys_displayhook_ori | |||
|
168 | ||||
164 | #we replace IPython default encoding by wx locale encoding |
|
169 | #we replace IPython default encoding by wx locale encoding | |
165 | loc = locale.getpreferredencoding() |
|
170 | loc = locale.getpreferredencoding() | |
166 | if loc: |
|
171 | if loc: | |
167 | self._IP.stdin_encoding = loc |
|
172 | self._IP.stdin_encoding = loc | |
168 | #we replace the ipython default pager by our pager |
|
173 | #we replace the ipython default pager by our pager | |
169 | self._IP.set_hook('show_in_pager', self._pager) |
|
174 | self._IP.set_hook('show_in_pager', self._pager) | |
170 |
|
175 | |||
171 | #we replace the ipython default shell command caller by our shell handler |
|
176 | #we replace the ipython default shell command caller by our shell handler | |
172 | self._IP.set_hook('shell_hook', self._shell) |
|
177 | self._IP.set_hook('shell_hook', self._shell) | |
173 |
|
178 | |||
174 | #we replace the ipython default input command caller by our method |
|
179 | #we replace the ipython default input command caller by our method | |
175 | IPython.iplib.raw_input_original = self._raw_input |
|
180 | IPython.iplib.raw_input_original = self._raw_input | |
176 | #we replace the ipython default exit command by our method |
|
181 | #we replace the ipython default exit command by our method | |
177 | self._IP.exit = ask_exit_handler |
|
182 | self._IP.exit = ask_exit_handler | |
178 | #we replace the help command |
|
183 | #we replace the help command | |
179 | self._IP.user_ns['help'] = _Helper(self._pager_help) |
|
184 | self._IP.user_ns['help'] = _Helper(self._pager_help) | |
180 |
|
185 | |||
181 | #we disable cpase magic... until we found a way to use it properly. |
|
186 | #we disable cpase magic... until we found a way to use it properly. | |
182 | #import IPython.ipapi |
|
187 | #import IPython.ipapi | |
183 | ip = IPython.ipapi.get() |
|
188 | ip = IPython.ipapi.get() | |
184 | def bypassMagic(self, arg): |
|
189 | def bypassMagic(self, arg): | |
185 | print '%this magic is currently disabled.' |
|
190 | print '%this magic is currently disabled.' | |
186 | ip.expose_magic('cpaste', bypassMagic) |
|
191 | ip.expose_magic('cpaste', bypassMagic) | |
187 |
|
192 | |||
188 | sys.excepthook = excepthook |
|
193 | sys.excepthook = excepthook | |
189 |
|
194 | |||
190 | #----------------------- Thread management section ---------------------- |
|
195 | #----------------------- Thread management section ---------------------- | |
191 | def doExecute(self, line): |
|
196 | def doExecute(self, line): | |
192 | """ |
|
197 | """ | |
193 | Tell the thread to process the 'line' command |
|
198 | Tell the thread to process the 'line' command | |
194 | """ |
|
199 | """ | |
195 |
|
200 | |||
196 | self._line_to_execute = line |
|
201 | self._line_to_execute = line | |
197 | #we launch the ipython line execution in a thread to make it interruptible |
|
202 | #we launch the ipython line execution in a thread to make it interruptible | |
198 | ce = _CodeExecutor(self, self._afterExecute) |
|
203 | #with include it in self namespace to be able to call ce.raise_exc(KeyboardInterrupt) | |
199 | ce.start() |
|
204 | self.ce = _CodeExecutor(self, self._afterExecute) | |
|
205 | self.ce.start() | |||
200 |
|
206 | |||
201 | #----------------------- IPython management section ---------------------- |
|
207 | #----------------------- IPython management section ---------------------- | |
202 | def getDocText(self): |
|
208 | def getDocText(self): | |
203 | """ |
|
209 | """ | |
204 | Returns the output of the processing that need to be paged (if any) |
|
210 | Returns the output of the processing that need to be paged (if any) | |
205 |
|
211 | |||
206 | @return: The std output string. |
|
212 | @return: The std output string. | |
207 | @rtype: string |
|
213 | @rtype: string | |
208 | """ |
|
214 | """ | |
209 | return self._doc_text |
|
215 | return self._doc_text | |
210 |
|
216 | |||
211 | def getHelpText(self): |
|
217 | def getHelpText(self): | |
212 | """ |
|
218 | """ | |
213 | Returns the output of the processing that need to be paged via help pager(if any) |
|
219 | Returns the output of the processing that need to be paged via help pager(if any) | |
214 |
|
220 | |||
215 | @return: The std output string. |
|
221 | @return: The std output string. | |
216 | @rtype: string |
|
222 | @rtype: string | |
217 | """ |
|
223 | """ | |
218 | return self._help_text |
|
224 | return self._help_text | |
219 |
|
225 | |||
220 | def getBanner(self): |
|
226 | def getBanner(self): | |
221 | """ |
|
227 | """ | |
222 | Returns the IPython banner for useful info on IPython instance |
|
228 | Returns the IPython banner for useful info on IPython instance | |
223 |
|
229 | |||
224 | @return: The banner string. |
|
230 | @return: The banner string. | |
225 | @rtype: string |
|
231 | @rtype: string | |
226 | """ |
|
232 | """ | |
227 | return self._IP.BANNER |
|
233 | return self._IP.BANNER | |
228 |
|
234 | |||
229 | def getPromptCount(self): |
|
235 | def getPromptCount(self): | |
230 | """ |
|
236 | """ | |
231 | Returns the prompt number. |
|
237 | Returns the prompt number. | |
232 | Each time a user execute a line in the IPython shell the prompt count is increased |
|
238 | Each time a user execute a line in the IPython shell the prompt count is increased | |
233 |
|
239 | |||
234 | @return: The prompt number |
|
240 | @return: The prompt number | |
235 | @rtype: int |
|
241 | @rtype: int | |
236 | """ |
|
242 | """ | |
237 | return self._IP.outputcache.prompt_count |
|
243 | return self._IP.outputcache.prompt_count | |
238 |
|
244 | |||
239 | def getPrompt(self): |
|
245 | def getPrompt(self): | |
240 | """ |
|
246 | """ | |
241 | Returns current prompt inside IPython instance |
|
247 | Returns current prompt inside IPython instance | |
242 | (Can be In [...]: ot ...:) |
|
248 | (Can be In [...]: ot ...:) | |
243 |
|
249 | |||
244 | @return: The current prompt. |
|
250 | @return: The current prompt. | |
245 | @rtype: string |
|
251 | @rtype: string | |
246 | """ |
|
252 | """ | |
247 | return self._prompt |
|
253 | return self._prompt | |
248 |
|
254 | |||
249 | def getIndentation(self): |
|
255 | def getIndentation(self): | |
250 | """ |
|
256 | """ | |
251 | Returns the current indentation level |
|
257 | Returns the current indentation level | |
252 | Usefull to put the caret at the good start position if we want to do autoindentation. |
|
258 | Usefull to put the caret at the good start position if we want to do autoindentation. | |
253 |
|
259 | |||
254 | @return: The indentation level. |
|
260 | @return: The indentation level. | |
255 | @rtype: int |
|
261 | @rtype: int | |
256 | """ |
|
262 | """ | |
257 | return self._IP.indent_current_nsp |
|
263 | return self._IP.indent_current_nsp | |
258 |
|
264 | |||
259 | def updateNamespace(self, ns_dict): |
|
265 | def updateNamespace(self, ns_dict): | |
260 | ''' |
|
266 | ''' | |
261 | Add the current dictionary to the shell namespace. |
|
267 | Add the current dictionary to the shell namespace. | |
262 |
|
268 | |||
263 | @param ns_dict: A dictionary of symbol-values. |
|
269 | @param ns_dict: A dictionary of symbol-values. | |
264 | @type ns_dict: dictionary |
|
270 | @type ns_dict: dictionary | |
265 | ''' |
|
271 | ''' | |
266 | self._IP.user_ns.update(ns_dict) |
|
272 | self._IP.user_ns.update(ns_dict) | |
267 |
|
273 | |||
268 | def complete(self, line): |
|
274 | def complete(self, line): | |
269 | ''' |
|
275 | ''' | |
270 | Returns an auto completed line and/or posibilities for completion. |
|
276 | Returns an auto completed line and/or posibilities for completion. | |
271 |
|
277 | |||
272 | @param line: Given line so far. |
|
278 | @param line: Given line so far. | |
273 | @type line: string |
|
279 | @type line: string | |
274 |
|
280 | |||
275 | @return: Line completed as for as possible, |
|
281 | @return: Line completed as for as possible, | |
276 | and possible further completions. |
|
282 | and possible further completions. | |
277 | @rtype: tuple |
|
283 | @rtype: tuple | |
278 | ''' |
|
284 | ''' | |
279 | split_line = self._complete_sep.split(line) |
|
285 | split_line = self._complete_sep.split(line) | |
280 | possibilities = self._IP.complete(split_line[-1]) |
|
286 | possibilities = self._IP.complete(split_line[-1]) | |
281 | if possibilities: |
|
287 | if possibilities: | |
282 |
|
288 | |||
283 | def _commonPrefix(str1, str2): |
|
289 | def _commonPrefix(str1, str2): | |
284 | ''' |
|
290 | ''' | |
285 | Reduction function. returns common prefix of two given strings. |
|
291 | Reduction function. returns common prefix of two given strings. | |
286 |
|
292 | |||
287 | @param str1: First string. |
|
293 | @param str1: First string. | |
288 | @type str1: string |
|
294 | @type str1: string | |
289 | @param str2: Second string |
|
295 | @param str2: Second string | |
290 | @type str2: string |
|
296 | @type str2: string | |
291 |
|
297 | |||
292 | @return: Common prefix to both strings. |
|
298 | @return: Common prefix to both strings. | |
293 | @rtype: string |
|
299 | @rtype: string | |
294 | ''' |
|
300 | ''' | |
295 | for i in range(len(str1)): |
|
301 | for i in range(len(str1)): | |
296 | if not str2.startswith(str1[:i+1]): |
|
302 | if not str2.startswith(str1[:i+1]): | |
297 | return str1[:i] |
|
303 | return str1[:i] | |
298 | return str1 |
|
304 | return str1 | |
299 | common_prefix = reduce(_commonPrefix, possibilities) |
|
305 | common_prefix = reduce(_commonPrefix, possibilities) | |
300 | completed = line[:-len(split_line[-1])]+common_prefix |
|
306 | completed = line[:-len(split_line[-1])]+common_prefix | |
301 | else: |
|
307 | else: | |
302 | completed = line |
|
308 | completed = line | |
303 | return completed, possibilities |
|
309 | return completed, possibilities | |
304 |
|
310 | |||
305 | def historyBack(self): |
|
311 | def historyBack(self): | |
306 | ''' |
|
312 | ''' | |
307 | Provides one history command back. |
|
313 | Provides one history command back. | |
308 |
|
314 | |||
309 | @return: The command string. |
|
315 | @return: The command string. | |
310 | @rtype: string |
|
316 | @rtype: string | |
311 | ''' |
|
317 | ''' | |
312 | history = '' |
|
318 | history = '' | |
313 | #the below while loop is used to suppress empty history lines |
|
319 | #the below while loop is used to suppress empty history lines | |
314 | while((history == '' or history == '\n') and self._history_level >0): |
|
320 | while((history == '' or history == '\n') and self._history_level >0): | |
315 | if self._history_level >= 1: |
|
321 | if self._history_level >= 1: | |
316 | self._history_level -= 1 |
|
322 | self._history_level -= 1 | |
317 | history = self._getHistory() |
|
323 | history = self._getHistory() | |
318 | return history |
|
324 | return history | |
319 |
|
325 | |||
320 | def historyForward(self): |
|
326 | def historyForward(self): | |
321 | ''' |
|
327 | ''' | |
322 | Provides one history command forward. |
|
328 | Provides one history command forward. | |
323 |
|
329 | |||
324 | @return: The command string. |
|
330 | @return: The command string. | |
325 | @rtype: string |
|
331 | @rtype: string | |
326 | ''' |
|
332 | ''' | |
327 | history = '' |
|
333 | history = '' | |
328 | #the below while loop is used to suppress empty history lines |
|
334 | #the below while loop is used to suppress empty history lines | |
329 | while((history == '' or history == '\n') \ |
|
335 | while((history == '' or history == '\n') \ | |
330 | and self._history_level <= self._getHistoryMaxIndex()): |
|
336 | and self._history_level <= self._getHistoryMaxIndex()): | |
331 | if self._history_level < self._getHistoryMaxIndex(): |
|
337 | if self._history_level < self._getHistoryMaxIndex(): | |
332 | self._history_level += 1 |
|
338 | self._history_level += 1 | |
333 | history = self._getHistory() |
|
339 | history = self._getHistory() | |
334 | else: |
|
340 | else: | |
335 | if self._history_level == self._getHistoryMaxIndex(): |
|
341 | if self._history_level == self._getHistoryMaxIndex(): | |
336 | history = self._getHistory() |
|
342 | history = self._getHistory() | |
337 | self._history_level += 1 |
|
343 | self._history_level += 1 | |
338 | else: |
|
344 | else: | |
339 | history = '' |
|
345 | history = '' | |
340 | return history |
|
346 | return history | |
341 |
|
347 | |||
342 | def initHistoryIndex(self): |
|
348 | def initHistoryIndex(self): | |
343 | ''' |
|
349 | ''' | |
344 | set history to last command entered |
|
350 | set history to last command entered | |
345 | ''' |
|
351 | ''' | |
346 | self._history_level = self._getHistoryMaxIndex()+1 |
|
352 | self._history_level = self._getHistoryMaxIndex()+1 | |
347 |
|
353 | |||
348 | #----------------------- IPython PRIVATE management section -------------- |
|
354 | #----------------------- IPython PRIVATE management section -------------- | |
349 | def _afterExecute(self): |
|
355 | def _afterExecute(self): | |
350 | ''' |
|
356 | ''' | |
351 | Can be redefined to generate post event after excution is done |
|
357 | Can be redefined to generate post event after excution is done | |
352 | ''' |
|
358 | ''' | |
353 | pass |
|
359 | pass | |
354 |
|
360 | |||
355 | #def _askExit(self): |
|
361 | #def _askExit(self): | |
356 | # ''' |
|
362 | # ''' | |
357 | # Can be redefined to generate post event to exit the Ipython shell |
|
363 | # Can be redefined to generate post event to exit the Ipython shell | |
358 | # ''' |
|
364 | # ''' | |
359 | # pass |
|
365 | # pass | |
360 |
|
366 | |||
361 | def _getHistoryMaxIndex(self): |
|
367 | def _getHistoryMaxIndex(self): | |
362 | ''' |
|
368 | ''' | |
363 | returns the max length of the history buffer |
|
369 | returns the max length of the history buffer | |
364 |
|
370 | |||
365 | @return: history length |
|
371 | @return: history length | |
366 | @rtype: int |
|
372 | @rtype: int | |
367 | ''' |
|
373 | ''' | |
368 | return len(self._IP.input_hist_raw)-1 |
|
374 | return len(self._IP.input_hist_raw)-1 | |
369 |
|
375 | |||
370 | def _getHistory(self): |
|
376 | def _getHistory(self): | |
371 | ''' |
|
377 | ''' | |
372 | Get's the command string of the current history level. |
|
378 | Get's the command string of the current history level. | |
373 |
|
379 | |||
374 | @return: Historic command stri |
|
380 | @return: Historic command stri | |
375 | @rtype: string |
|
381 | @rtype: string | |
376 | ''' |
|
382 | ''' | |
377 | rv = self._IP.input_hist_raw[self._history_level].strip('\n') |
|
383 | rv = self._IP.input_hist_raw[self._history_level].strip('\n') | |
378 | return rv |
|
384 | return rv | |
379 |
|
385 | |||
380 | def _pager_help(self, text): |
|
386 | def _pager_help(self, text): | |
381 | ''' |
|
387 | ''' | |
382 | This function is used as a callback replacment to IPython help pager function |
|
388 | This function is used as a callback replacment to IPython help pager function | |
383 |
|
389 | |||
384 | It puts the 'text' value inside the self._help_text string that can be retrived via |
|
390 | It puts the 'text' value inside the self._help_text string that can be retrived via | |
385 | getHelpText function. |
|
391 | getHelpText function. | |
386 | ''' |
|
392 | ''' | |
387 | if self._help_text == None: |
|
393 | if self._help_text == None: | |
388 | self._help_text = text |
|
394 | self._help_text = text | |
389 | else: |
|
395 | else: | |
390 | self._help_text += text |
|
396 | self._help_text += text | |
391 |
|
397 | |||
392 | def _pager(self, IP, text): |
|
398 | def _pager(self, IP, text): | |
393 | ''' |
|
399 | ''' | |
394 | This function is used as a callback replacment to IPython pager function |
|
400 | This function is used as a callback replacment to IPython pager function | |
395 |
|
401 | |||
396 | It puts the 'text' value inside the self._doc_text string that can be retrived via |
|
402 | It puts the 'text' value inside the self._doc_text string that can be retrived via | |
397 | getDocText function. |
|
403 | getDocText function. | |
398 | ''' |
|
404 | ''' | |
399 | self._doc_text = text |
|
405 | self._doc_text = text | |
400 |
|
406 | |||
401 | def _raw_input(self, prompt=''): |
|
407 | def _raw_input(self, prompt=''): | |
402 | ''' |
|
408 | ''' | |
403 | Custom raw_input() replacement. Get's current line from console buffer. |
|
409 | Custom raw_input() replacement. Get's current line from console buffer. | |
404 |
|
410 | |||
405 | @param prompt: Prompt to print. Here for compatability as replacement. |
|
411 | @param prompt: Prompt to print. Here for compatability as replacement. | |
406 | @type prompt: string |
|
412 | @type prompt: string | |
407 |
|
413 | |||
408 | @return: The current command line text. |
|
414 | @return: The current command line text. | |
409 | @rtype: string |
|
415 | @rtype: string | |
410 | ''' |
|
416 | ''' | |
411 | return self._line_to_execute |
|
417 | return self._line_to_execute | |
412 |
|
418 | |||
413 | def _execute(self): |
|
419 | def _execute(self): | |
414 | ''' |
|
420 | ''' | |
415 | Executes the current line provided by the shell object. |
|
421 | Executes the current line provided by the shell object. | |
416 | ''' |
|
422 | ''' | |
417 | orig_stdout = sys.stdout |
|
423 | orig_stdout = sys.stdout | |
418 | sys.stdout = IPython.Shell.Term.cout |
|
424 | sys.stdout = IPython.Shell.Term.cout | |
419 |
|
425 | |||
420 | try: |
|
426 | try: | |
421 | line = self._IP.raw_input(None, self._iter_more) |
|
427 | line = self._IP.raw_input(None, self._iter_more) | |
422 | if self._IP.autoindent: |
|
428 | if self._IP.autoindent: | |
423 | self._IP.readline_startup_hook(None) |
|
429 | self._IP.readline_startup_hook(None) | |
424 |
|
430 | |||
425 | except KeyboardInterrupt: |
|
431 | except KeyboardInterrupt: | |
426 | self._IP.write('\nKeyboardInterrupt\n') |
|
432 | self._IP.write('\nKeyboardInterrupt\n') | |
427 | self._IP.resetbuffer() |
|
433 | self._IP.resetbuffer() | |
428 | # keep cache in sync with the prompt counter: |
|
434 | # keep cache in sync with the prompt counter: | |
429 | self._IP.outputcache.prompt_count -= 1 |
|
435 | self._IP.outputcache.prompt_count -= 1 | |
430 |
|
436 | |||
431 | if self._IP.autoindent: |
|
437 | if self._IP.autoindent: | |
432 | self._IP.indent_current_nsp = 0 |
|
438 | self._IP.indent_current_nsp = 0 | |
433 | self._iter_more = 0 |
|
439 | self._iter_more = 0 | |
434 | except: |
|
440 | except: | |
435 | self._IP.showtraceback() |
|
441 | self._IP.showtraceback() | |
436 | else: |
|
442 | else: | |
437 | self._iter_more = self._IP.push(line) |
|
443 | self._iter_more = self._IP.push(line) | |
438 | if (self._IP.SyntaxTB.last_syntax_error and self._IP.rc.autoedit_syntax): |
|
444 | if (self._IP.SyntaxTB.last_syntax_error and self._IP.rc.autoedit_syntax): | |
439 | self._IP.edit_syntax_error() |
|
445 | self._IP.edit_syntax_error() | |
440 | if self._iter_more: |
|
446 | if self._iter_more: | |
441 | self._prompt = str(self._IP.outputcache.prompt2).strip() |
|
447 | self._prompt = str(self._IP.outputcache.prompt2).strip() | |
442 | if self._IP.autoindent: |
|
448 | if self._IP.autoindent: | |
443 | self._IP.readline_startup_hook(self._IP.pre_readline) |
|
449 | self._IP.readline_startup_hook(self._IP.pre_readline) | |
444 | else: |
|
450 | else: | |
445 | self._prompt = str(self._IP.outputcache.prompt1).strip() |
|
451 | self._prompt = str(self._IP.outputcache.prompt1).strip() | |
446 | self._IP.indent_current_nsp = 0 #we set indentation to 0 |
|
452 | self._IP.indent_current_nsp = 0 #we set indentation to 0 | |
447 | sys.stdout = orig_stdout |
|
453 | sys.stdout = orig_stdout | |
448 |
|
454 | |||
449 | def _shell(self, ip, cmd): |
|
455 | def _shell(self, ip, cmd): | |
450 | ''' |
|
456 | ''' | |
451 | Replacement method to allow shell commands without them blocking. |
|
457 | Replacement method to allow shell commands without them blocking. | |
452 |
|
458 | |||
453 | @param ip: Ipython instance, same as self._IP |
|
459 | @param ip: Ipython instance, same as self._IP | |
454 | @type cmd: Ipython instance |
|
460 | @type cmd: Ipython instance | |
455 | @param cmd: Shell command to execute. |
|
461 | @param cmd: Shell command to execute. | |
456 | @type cmd: string |
|
462 | @type cmd: string | |
457 | ''' |
|
463 | ''' | |
458 | stdin, stdout = os.popen4(cmd) |
|
464 | stdin, stdout = os.popen4(cmd) | |
459 | result = stdout.read().decode('cp437').encode(locale.getpreferredencoding()) |
|
465 | result = stdout.read().decode('cp437').encode(locale.getpreferredencoding()) | |
460 | #we use print command because the shell command is called |
|
466 | #we use print command because the shell command is called | |
461 | #inside IPython instance and thus is redirected to thread cout |
|
467 | #inside IPython instance and thus is redirected to thread cout | |
462 | #"\x01\x1b[1;36m\x02" <-- add colour to the text... |
|
468 | #"\x01\x1b[1;36m\x02" <-- add colour to the text... | |
463 | print "\x01\x1b[1;36m\x02"+result |
|
469 | print "\x01\x1b[1;36m\x02"+result | |
464 | stdout.close() |
|
470 | stdout.close() | |
465 | stdin.close() |
|
471 | stdin.close() |
General Comments 0
You need to be logged in to leave comments.
Login now