##// END OF EJS Templates
Split the frontend base class in different files and add a base class...
Gael Varoquaux -
Show More
@@ -0,0 +1,93 b''
1 """
2 Base front end class for all async frontends.
3 """
4 __docformat__ = "restructuredtext en"
5
6 #-------------------------------------------------------------------------------
7 # Copyright (C) 2008 The IPython Development Team
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-------------------------------------------------------------------------------
12
13
14 #-------------------------------------------------------------------------------
15 # Imports
16 #-------------------------------------------------------------------------------
17 import uuid
18
19 try:
20 from zope.interface import Interface, Attribute, implements, classProvides
21 except ImportError:
22 #zope.interface is not available
23 Interface = object
24 def Attribute(name, doc): pass
25 def implements(interface): pass
26 def classProvides(interface): pass
27
28
29
30 from frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory
31
32 from IPython.kernel.engineservice import IEngineCore
33 from IPython.kernel.core.history import FrontEndHistory
34
35 try:
36 from twisted.python.failure import Failure
37 except ImportError:
38 #Twisted not available
39 Failure = Exception
40
41
42
43
44 class AsyncFrontEndBase(FrontEndBase):
45 """
46 Overrides FrontEndBase to wrap execute in a deferred result.
47 All callbacks are made as callbacks on the deferred result.
48 """
49
50 implements(IFrontEnd)
51 classProvides(IFrontEndFactory)
52
53 def __init__(self, engine=None, history=None):
54 assert(engine==None or IEngineCore.providedBy(engine))
55 self.engine = IEngineCore(engine)
56 if history is None:
57 self.history = FrontEndHistory(input_cache=[''])
58 else:
59 self.history = history
60
61
62 def execute(self, block, blockID=None):
63 """Execute the block and return the deferred result.
64
65 Parameters:
66 block : {str, AST}
67 blockID : any
68 Caller may provide an ID to identify this block.
69 result['blockID'] := blockID
70
71 Result:
72 Deferred result of self.interpreter.execute
73 """
74
75 if(not self.is_complete(block)):
76 return Failure(Exception("Block is not compilable"))
77
78 if(blockID == None):
79 blockID = uuid.uuid4() #random UUID
80
81 d = self.engine.execute(block)
82 d.addCallback(self._add_history, block=block)
83 d.addCallbacks(self._add_block_id_for_result,
84 errback=self._add_block_id_for_failure,
85 callbackArgs=(blockID,),
86 errbackArgs=(blockID,))
87 d.addBoth(self.update_cell_prompt, blockID=blockID)
88 d.addCallbacks(self.render_result,
89 errback=self.render_error)
90
91 return d
92
93
@@ -0,0 +1,123 b''
1 """
2 Base front end class for all line-oriented frontends.
3
4 Currently this focuses on synchronous frontends.
5 """
6 __docformat__ = "restructuredtext en"
7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
14
15 #-------------------------------------------------------------------------------
16 # Imports
17 #-------------------------------------------------------------------------------
18 import re
19
20 import IPython
21
22
23 from frontendbase import FrontEndBase
24 from IPython.kernel.core.interpreter import Interpreter
25
26 #-------------------------------------------------------------------------------
27 # Base class for the line-oriented front ends
28 #-------------------------------------------------------------------------------
29 class LineFrontEndBase(FrontEndBase):
30
31 # Are we entering multi line input?
32 multi_line_input = False
33
34 # The added tab stop to the string. It may, for instance, come from
35 # copy and pasting something with tabs.
36 tab_stop = 0
37 # FIXME: We still have to deal with this.
38
39 #--------------------------------------------------------------------------
40 # Public API
41 #--------------------------------------------------------------------------
42
43 def __init__(self, shell=None, history=None):
44 if shell is None:
45 shell = Interpreter()
46 FrontEndBase.__init__(self, shell=shell, history=history)
47
48 #FIXME: print banner.
49 banner = """IPython1 %s -- An enhanced Interactive Python.""" \
50 % IPython.__version__
51
52
53 def complete(self, token):
54 """Complete token in engine's user_ns
55
56 Parameters
57 ----------
58 token : string
59
60 Result
61 ------
62 Deferred result of
63 IPython.kernel.engineservice.IEngineBase.complete
64 """
65
66 return self.shell.complete(token)
67
68
69 def render_result(self, result):
70 if 'stdout' in result and result['stdout']:
71 self.write('\n' + result['stdout'])
72 if 'display' in result and result['display']:
73 self.write("%s%s\n" % (
74 self.output_prompt % result['number'],
75 result['display']['pprint']
76 ) )
77
78
79 def render_error(self, failure):
80 self.insert_text('\n\n'+str(failure)+'\n\n')
81 return failure
82
83
84 def on_enter(self):
85 """ Called when the return key is pressed in a line editing
86 buffer.
87 """
88 current_buffer = self.get_current_edit_buffer()
89 current_buffer = current_buffer.replace('\r\n', '\n')
90 current_buffer = current_buffer.replace('\t', 4*' ')
91 cleaned_buffer = '\n'.join(l.rstrip()
92 for l in current_buffer.split('\n'))
93 if ( not self.multi_line_input
94 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
95 if self.is_complete(cleaned_buffer):
96 self._add_history(None, cleaned_buffer.rstrip())
97 result = self.shell.execute(cleaned_buffer)
98 self.render_result(result)
99 self.new_prompt(self.prompt % (result['number'] + 1))
100 self.multi_line_input = False
101 else:
102 if self.multi_line_input:
103 self.write('\n' + self._get_indent_string(current_buffer))
104 else:
105 self.multi_line_input = True
106 self.write('\n\t')
107 else:
108 self.write('\n'+self._get_indent_string(current_buffer))
109
110
111 #--------------------------------------------------------------------------
112 # Private API
113 #--------------------------------------------------------------------------
114
115 def _get_indent_string(self, string):
116 string = string.split('\n')[-1]
117 indent_chars = len(string) - len(string.lstrip())
118 indent_string = '\t'*(indent_chars // 4) + \
119 ' '*(indent_chars % 4)
120
121 return indent_string
122
123
@@ -40,7 +40,7 b' from pprint import saferepr'
40 40
41 41 import IPython
42 42 from IPython.kernel.engineservice import ThreadedEngineService
43 from IPython.frontend.frontendbase import AsyncFrontEndBase
43 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
44 44
45 45 from twisted.internet.threads import blockingCallFromThread
46 46 from twisted.python.failure import Failure
@@ -37,12 +37,6 b' from IPython.kernel.core.history import FrontEndHistory'
37 37 from IPython.kernel.core.util import Bunch
38 38 from IPython.kernel.engineservice import IEngineCore
39 39
40 try:
41 from twisted.python.failure import Failure
42 except ImportError:
43 #Twisted not available
44 Failure = Exception
45
46 40 ##############################################################################
47 41 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
48 42 # not
@@ -355,53 +349,4 b' class FrontEndBase(object):'
355 349
356 350
357 351
358 class AsyncFrontEndBase(FrontEndBase):
359 """
360 Overrides FrontEndBase to wrap execute in a deferred result.
361 All callbacks are made as callbacks on the deferred result.
362 """
363
364 implements(IFrontEnd)
365 classProvides(IFrontEndFactory)
366
367 def __init__(self, engine=None, history=None):
368 assert(engine==None or IEngineCore.providedBy(engine))
369 self.engine = IEngineCore(engine)
370 if history is None:
371 self.history = FrontEndHistory(input_cache=[''])
372 else:
373 self.history = history
374
375
376 def execute(self, block, blockID=None):
377 """Execute the block and return the deferred result.
378
379 Parameters:
380 block : {str, AST}
381 blockID : any
382 Caller may provide an ID to identify this block.
383 result['blockID'] := blockID
384
385 Result:
386 Deferred result of self.interpreter.execute
387 """
388
389 if(not self.is_complete(block)):
390 return Failure(Exception("Block is not compilable"))
391
392 if(blockID == None):
393 blockID = uuid.uuid4() #random UUID
394
395 d = self.engine.execute(block)
396 d.addCallback(self._add_history, block=block)
397 d.addCallbacks(self._add_block_id_for_result,
398 errback=self._add_block_id_for_failure,
399 callbackArgs=(blockID,),
400 errbackArgs=(blockID,))
401 d.addBoth(self.update_cell_prompt, blockID=blockID)
402 d.addCallbacks(self.render_result,
403 errback=self.render_error)
404
405 return d
406
407 352
@@ -23,11 +23,8 b' __docformat__ = "restructuredtext en"'
23 23
24 24 import wx
25 25 from console_widget import ConsoleWidget
26 import re
27 26
28 import IPython
29 from IPython.kernel.engineservice import EngineService
30 from IPython.frontend.frontendbase import FrontEndBase
27 from IPython.frontend.linefrontendbase import LineFrontEndBase
31 28
32 29 #-------------------------------------------------------------------------------
33 30 # Classes to implement the Wx frontend
@@ -36,19 +33,11 b' from IPython.frontend.frontendbase import FrontEndBase'
36 33
37 34
38 35
39 class IPythonWxController(FrontEndBase, ConsoleWidget):
36 class IPythonWxController(LineFrontEndBase, ConsoleWidget):
40 37
41 38 output_prompt = \
42 39 '\n\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
43 40
44 # Are we entering multi line input?
45 multi_line_input = False
46
47 # The added tab stop to the string. It may, for instance, come from
48 # copy and pasting something with tabs.
49 tab_stop = 0
50 # FIXME: We still have to deal with this.
51
52 41 #--------------------------------------------------------------------------
53 42 # Public API
54 43 #--------------------------------------------------------------------------
@@ -59,61 +48,11 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
59 48 """ Create Shell instance.
60 49 """
61 50 ConsoleWidget.__init__(self, parent, id, pos, size, style)
62 FrontEndBase.__init__(self, engine=EngineService(),
63 )
64
65 # FIXME: Something is wrong with the history, I instanciate it
66 # with an empty cache, but this is not the way to do.
67 self.lines = {}
68
69 # Start the IPython engine
70 self.engine.startService()
51 LineFrontEndBase.__init__(self)
71 52
72 53 # Capture Character keys
73 54 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
74 55
75 #FIXME: print banner.
76 banner = """IPython1 %s -- An enhanced Interactive Python.""" \
77 % IPython.__version__
78
79
80 def appWillTerminate_(self, notification):
81 """appWillTerminate"""
82
83 self.engine.stopService()
84
85
86 def complete(self, token):
87 """Complete token in engine's user_ns
88
89 Parameters
90 ----------
91 token : string
92
93 Result
94 ------
95 Deferred result of
96 IPython.kernel.engineservice.IEngineBase.complete
97 """
98
99 return self.engine.complete(token)
100
101
102 def render_result(self, result):
103 if 'stdout' in result and result['stdout']:
104 self.write('\n' + result['stdout'])
105 if 'display' in result and result['display']:
106 self.write("%s%s\n" % (
107 self.output_prompt % result['number'],
108 result['display']['pprint']
109 ) )
110
111
112 def render_error(self, failure):
113 self.insert_text('\n\n'+str(failure)+'\n\n')
114 return failure
115
116
117 56 #--------------------------------------------------------------------------
118 57 # Private API
119 58 #--------------------------------------------------------------------------
@@ -127,7 +66,7 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
127 66 # Capture enter
128 67 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
129 68 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
130 self._on_enter()
69 self.on_enter()
131 70 # Up history
132 71 elif event.KeyCode == wx.WXK_UP and (
133 72 ( current_line_number == self.current_prompt_line and
@@ -149,41 +88,6 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
149 88 ConsoleWidget._on_key_down(self, event, skip=True)
150 89
151 90
152 def _on_enter(self):
153 """ Called when the return key is pressed in a line editing
154 buffer.
155 """
156 current_buffer = self.get_current_edit_buffer()
157 current_buffer = current_buffer.replace('\r\n', '\n')
158 current_buffer = current_buffer.replace('\t', 4*' ')
159 cleaned_buffer = '\n'.join(l.rstrip()
160 for l in current_buffer.split('\n'))
161 if ( not self.multi_line_input
162 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
163 if self.is_complete(cleaned_buffer):
164 self._add_history(None, cleaned_buffer.rstrip())
165 result = self.engine.shell.execute(cleaned_buffer)
166 self.render_result(result)
167 self.new_prompt(self.prompt % (result['number'] + 1))
168 self.multi_line_input = False
169 else:
170 if self.multi_line_input:
171 self.write('\n' + self._get_indent_string(current_buffer))
172 else:
173 self.multi_line_input = True
174 self.write('\n\t')
175 else:
176 self.write('\n'+self._get_indent_string(current_buffer))
177
178
179 def _get_indent_string(self, string):
180 string = string.split('\n')[-1]
181 indent_chars = len(string) - len(string.lstrip())
182 indent_string = '\t'*(indent_chars // 4) + \
183 ' '*(indent_chars % 4)
184
185 return indent_string
186
187 91
188 92
189 93 if __name__ == '__main__':
General Comments 0
You need to be logged in to leave comments. Login now