##// END OF EJS Templates
Changed a bunch of modules to NOT have the x permission bit set.
Brian Granger -
Show More
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -1,92 +1,94 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """This file contains unittests for the
2 """This file contains unittests for the
3 IPython.frontend.cocoa.cocoa_frontend module.
3 IPython.frontend.cocoa.cocoa_frontend module.
4 """
4 """
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #---------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2005 The IPython Development Team
8 # Copyright (C) 2005 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13
13
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #---------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17 from IPython.kernel.core.interpreter import Interpreter
18 import IPython.kernel.engineservice as es
19 from IPython.testing.util import DeferredTestCase
20 from twisted.internet.defer import succeed
21
17
22 try:
18 try:
19 from IPython.kernel.core.interpreter import Interpreter
20 import IPython.kernel.engineservice as es
21 from IPython.testing.util import DeferredTestCase
22 from twisted.internet.defer import succeed
23 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
23 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
24 from Foundation import NSMakeRect
24 from Foundation import NSMakeRect
25 from AppKit import NSTextView, NSScrollView
25 from AppKit import NSTextView, NSScrollView
26 except ImportError:
26 except ImportError:
27 pass
28 else:
27 class TestIPythonCocoaControler(DeferredTestCase):
29 class TestIPythonCocoaControler(DeferredTestCase):
28 """Tests for IPythonCocoaController"""
30 """Tests for IPythonCocoaController"""
29
31
30 def setUp(self):
32 def setUp(self):
31 self.controller = IPythonCocoaController.alloc().init()
33 self.controller = IPythonCocoaController.alloc().init()
32 self.engine = es.EngineService()
34 self.engine = es.EngineService()
33 self.engine.startService()
35 self.engine.startService()
34
36
35
37
36 def tearDown(self):
38 def tearDown(self):
37 self.controller = None
39 self.controller = None
38 self.engine.stopService()
40 self.engine.stopService()
39
41
40 def testControllerExecutesCode(self):
42 def testControllerExecutesCode(self):
41 code ="""5+5"""
43 code ="""5+5"""
42 expected = Interpreter().execute(code)
44 expected = Interpreter().execute(code)
43 del expected['number']
45 del expected['number']
44 def removeNumberAndID(result):
46 def removeNumberAndID(result):
45 del result['number']
47 del result['number']
46 del result['id']
48 del result['id']
47 return result
49 return result
48 self.assertDeferredEquals(
50 self.assertDeferredEquals(
49 self.controller.execute(code).addCallback(removeNumberAndID),
51 self.controller.execute(code).addCallback(removeNumberAndID),
50 expected)
52 expected)
51
53
52 def testControllerMirrorsUserNSWithValuesAsStrings(self):
54 def testControllerMirrorsUserNSWithValuesAsStrings(self):
53 code = """userns1=1;userns2=2"""
55 code = """userns1=1;userns2=2"""
54 def testControllerUserNS(result):
56 def testControllerUserNS(result):
55 self.assertEquals(self.controller.userNS['userns1'], 1)
57 self.assertEquals(self.controller.userNS['userns1'], 1)
56 self.assertEquals(self.controller.userNS['userns2'], 2)
58 self.assertEquals(self.controller.userNS['userns2'], 2)
57
59
58 self.controller.execute(code).addCallback(testControllerUserNS)
60 self.controller.execute(code).addCallback(testControllerUserNS)
59
61
60
62
61 def testControllerInstantiatesIEngine(self):
63 def testControllerInstantiatesIEngine(self):
62 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
64 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
63
65
64 def testControllerCompletesToken(self):
66 def testControllerCompletesToken(self):
65 code = """longNameVariable=10"""
67 code = """longNameVariable=10"""
66 def testCompletes(result):
68 def testCompletes(result):
67 self.assert_("longNameVariable" in result)
69 self.assert_("longNameVariable" in result)
68
70
69 def testCompleteToken(result):
71 def testCompleteToken(result):
70 self.controller.complete("longNa").addCallback(testCompletes)
72 self.controller.complete("longNa").addCallback(testCompletes)
71
73
72 self.controller.execute(code).addCallback(testCompletes)
74 self.controller.execute(code).addCallback(testCompletes)
73
75
74
76
75 def testCurrentIndent(self):
77 def testCurrentIndent(self):
76 """test that current_indent_string returns current indent or None.
78 """test that current_indent_string returns current indent or None.
77 Uses _indent_for_block for direct unit testing.
79 Uses _indent_for_block for direct unit testing.
78 """
80 """
79
81
80 self.controller.tabUsesSpaces = True
82 self.controller.tabUsesSpaces = True
81 self.assert_(self.controller._indent_for_block("""a=3""") == None)
83 self.assert_(self.controller._indent_for_block("""a=3""") == None)
82 self.assert_(self.controller._indent_for_block("") == None)
84 self.assert_(self.controller._indent_for_block("") == None)
83 block = """def test():\n a=3"""
85 block = """def test():\n a=3"""
84 self.assert_(self.controller._indent_for_block(block) == \
86 self.assert_(self.controller._indent_for_block(block) == \
85 ' ' * self.controller.tabSpaces)
87 ' ' * self.controller.tabSpaces)
86
88
87 block = """if(True):\n%sif(False):\n%spass""" % \
89 block = """if(True):\n%sif(False):\n%spass""" % \
88 (' '*self.controller.tabSpaces,
90 (' '*self.controller.tabSpaces,
89 2*' '*self.controller.tabSpaces)
91 2*' '*self.controller.tabSpaces)
90 self.assert_(self.controller._indent_for_block(block) == \
92 self.assert_(self.controller._indent_for_block(block) == \
91 2*(' '*self.controller.tabSpaces))
93 2*(' '*self.controller.tabSpaces))
92
94
@@ -1,359 +1,358 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
3 """
3 """
4 frontendbase provides an interface and base class for GUI frontends for
4 frontendbase provides an interface and base class for GUI frontends for
5 IPython.kernel/IPython.kernel.core.
5 IPython.kernel/IPython.kernel.core.
6
6
7 Frontend implementations will likely want to subclass FrontEndBase.
7 Frontend implementations will likely want to subclass FrontEndBase.
8
8
9 Author: Barry Wark
9 Author: Barry Wark
10 """
10 """
11 __docformat__ = "restructuredtext en"
11 __docformat__ = "restructuredtext en"
12
12
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19
19
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import string
23 import string
24 import uuid
24 import uuid
25 import _ast
25 import _ast
26
26
27 from zopeinterface import Interface, Attribute, implements, classProvides
27 from zopeinterface import Interface, Attribute, implements, classProvides
28
28
29 from IPython.kernel.core.history import FrontEndHistory
29 from IPython.kernel.core.history import FrontEndHistory
30 from IPython.kernel.core.util import Bunch
30 from IPython.kernel.core.util import Bunch
31 from IPython.kernel.engineservice import IEngineCore
32
31
33 ##############################################################################
32 ##############################################################################
34 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
33 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
35 # not
34 # not
36
35
37 rc = Bunch()
36 rc = Bunch()
38 rc.prompt_in1 = r'In [$number]: '
37 rc.prompt_in1 = r'In [$number]: '
39 rc.prompt_in2 = r'...'
38 rc.prompt_in2 = r'...'
40 rc.prompt_out = r'Out [$number]: '
39 rc.prompt_out = r'Out [$number]: '
41
40
42 ##############################################################################
41 ##############################################################################
43 # Interface definitions
42 # Interface definitions
44 ##############################################################################
43 ##############################################################################
45
44
46 class IFrontEndFactory(Interface):
45 class IFrontEndFactory(Interface):
47 """Factory interface for frontends."""
46 """Factory interface for frontends."""
48
47
49 def __call__(engine=None, history=None):
48 def __call__(engine=None, history=None):
50 """
49 """
51 Parameters:
50 Parameters:
52 interpreter : IPython.kernel.engineservice.IEngineCore
51 interpreter : IPython.kernel.engineservice.IEngineCore
53 """
52 """
54
53
55 pass
54 pass
56
55
57
56
58 class IFrontEnd(Interface):
57 class IFrontEnd(Interface):
59 """Interface for frontends. All methods return t.i.d.Deferred"""
58 """Interface for frontends. All methods return t.i.d.Deferred"""
60
59
61 Attribute("input_prompt_template", "string.Template instance\
60 Attribute("input_prompt_template", "string.Template instance\
62 substituteable with execute result.")
61 substituteable with execute result.")
63 Attribute("output_prompt_template", "string.Template instance\
62 Attribute("output_prompt_template", "string.Template instance\
64 substituteable with execute result.")
63 substituteable with execute result.")
65 Attribute("continuation_prompt_template", "string.Template instance\
64 Attribute("continuation_prompt_template", "string.Template instance\
66 substituteable with execute result.")
65 substituteable with execute result.")
67
66
68 def update_cell_prompt(result, blockID=None):
67 def update_cell_prompt(result, blockID=None):
69 """Subclass may override to update the input prompt for a block.
68 """Subclass may override to update the input prompt for a block.
70
69
71 In asynchronous frontends, this method will be called as a
70 In asynchronous frontends, this method will be called as a
72 twisted.internet.defer.Deferred's callback/errback.
71 twisted.internet.defer.Deferred's callback/errback.
73 Implementations should thus return result when finished.
72 Implementations should thus return result when finished.
74
73
75 Result is a result dict in case of success, and a
74 Result is a result dict in case of success, and a
76 twisted.python.util.failure.Failure in case of an error
75 twisted.python.util.failure.Failure in case of an error
77 """
76 """
78
77
79 pass
78 pass
80
79
81 def render_result(result):
80 def render_result(result):
82 """Render the result of an execute call. Implementors may choose the
81 """Render the result of an execute call. Implementors may choose the
83 method of rendering.
82 method of rendering.
84 For example, a notebook-style frontend might render a Chaco plot
83 For example, a notebook-style frontend might render a Chaco plot
85 inline.
84 inline.
86
85
87 Parameters:
86 Parameters:
88 result : dict (result of IEngineBase.execute )
87 result : dict (result of IEngineBase.execute )
89 blockID = result['blockID']
88 blockID = result['blockID']
90
89
91 Result:
90 Result:
92 Output of frontend rendering
91 Output of frontend rendering
93 """
92 """
94
93
95 pass
94 pass
96
95
97 def render_error(failure):
96 def render_error(failure):
98 """Subclasses must override to render the failure.
97 """Subclasses must override to render the failure.
99
98
100 In asynchronous frontend, since this method will be called as a
99 In asynchronous frontend, since this method will be called as a
101 twisted.internet.defer.Deferred's callback. Implementations
100 twisted.internet.defer.Deferred's callback. Implementations
102 should thus return result when finished.
101 should thus return result when finished.
103
102
104 blockID = failure.blockID
103 blockID = failure.blockID
105 """
104 """
106
105
107 pass
106 pass
108
107
109 def input_prompt(number=''):
108 def input_prompt(number=''):
110 """Returns the input prompt by subsituting into
109 """Returns the input prompt by subsituting into
111 self.input_prompt_template
110 self.input_prompt_template
112 """
111 """
113 pass
112 pass
114
113
115 def output_prompt(number=''):
114 def output_prompt(number=''):
116 """Returns the output prompt by subsituting into
115 """Returns the output prompt by subsituting into
117 self.output_prompt_template
116 self.output_prompt_template
118 """
117 """
119
118
120 pass
119 pass
121
120
122 def continuation_prompt():
121 def continuation_prompt():
123 """Returns the continuation prompt by subsituting into
122 """Returns the continuation prompt by subsituting into
124 self.continuation_prompt_template
123 self.continuation_prompt_template
125 """
124 """
126
125
127 pass
126 pass
128
127
129 def is_complete(block):
128 def is_complete(block):
130 """Returns True if block is complete, False otherwise."""
129 """Returns True if block is complete, False otherwise."""
131
130
132 pass
131 pass
133
132
134 def compile_ast(block):
133 def compile_ast(block):
135 """Compiles block to an _ast.AST"""
134 """Compiles block to an _ast.AST"""
136
135
137 pass
136 pass
138
137
139 def get_history_previous(current_block):
138 def get_history_previous(current_block):
140 """Returns the block previous in the history. Saves currentBlock if
139 """Returns the block previous in the history. Saves currentBlock if
141 the history_cursor is currently at the end of the input history"""
140 the history_cursor is currently at the end of the input history"""
142 pass
141 pass
143
142
144 def get_history_next():
143 def get_history_next():
145 """Returns the next block in the history."""
144 """Returns the next block in the history."""
146
145
147 pass
146 pass
148
147
149 def complete(self, line):
148 def complete(self, line):
150 """Returns the list of possible completions, and the completed
149 """Returns the list of possible completions, and the completed
151 line.
150 line.
152
151
153 The input argument is the full line to be completed. This method
152 The input argument is the full line to be completed. This method
154 returns both the line completed as much as possible, and the list
153 returns both the line completed as much as possible, and the list
155 of further possible completions (full words).
154 of further possible completions (full words).
156 """
155 """
157 pass
156 pass
158
157
159
158
160 ##############################################################################
159 ##############################################################################
161 # Base class for all the frontends.
160 # Base class for all the frontends.
162 ##############################################################################
161 ##############################################################################
163
162
164 class FrontEndBase(object):
163 class FrontEndBase(object):
165 """
164 """
166 FrontEndBase manages the state tasks for a CLI frontend:
165 FrontEndBase manages the state tasks for a CLI frontend:
167 - Input and output history management
166 - Input and output history management
168 - Input/continuation and output prompt generation
167 - Input/continuation and output prompt generation
169
168
170 Some issues (due to possibly unavailable engine):
169 Some issues (due to possibly unavailable engine):
171 - How do we get the current cell number for the engine?
170 - How do we get the current cell number for the engine?
172 - How do we handle completions?
171 - How do we handle completions?
173 """
172 """
174
173
175 history_cursor = 0
174 history_cursor = 0
176
175
177 input_prompt_template = string.Template(rc.prompt_in1)
176 input_prompt_template = string.Template(rc.prompt_in1)
178 output_prompt_template = string.Template(rc.prompt_out)
177 output_prompt_template = string.Template(rc.prompt_out)
179 continuation_prompt_template = string.Template(rc.prompt_in2)
178 continuation_prompt_template = string.Template(rc.prompt_in2)
180
179
181 def __init__(self, shell=None, history=None):
180 def __init__(self, shell=None, history=None):
182 self.shell = shell
181 self.shell = shell
183 if history is None:
182 if history is None:
184 self.history = FrontEndHistory(input_cache=[''])
183 self.history = FrontEndHistory(input_cache=[''])
185 else:
184 else:
186 self.history = history
185 self.history = history
187
186
188
187
189 def input_prompt(self, number=''):
188 def input_prompt(self, number=''):
190 """Returns the current input prompt
189 """Returns the current input prompt
191
190
192 It would be great to use ipython1.core.prompts.Prompt1 here
191 It would be great to use ipython1.core.prompts.Prompt1 here
193 """
192 """
194 return self.input_prompt_template.safe_substitute({'number':number})
193 return self.input_prompt_template.safe_substitute({'number':number})
195
194
196
195
197 def continuation_prompt(self):
196 def continuation_prompt(self):
198 """Returns the current continuation prompt"""
197 """Returns the current continuation prompt"""
199
198
200 return self.continuation_prompt_template.safe_substitute()
199 return self.continuation_prompt_template.safe_substitute()
201
200
202 def output_prompt(self, number=''):
201 def output_prompt(self, number=''):
203 """Returns the output prompt for result"""
202 """Returns the output prompt for result"""
204
203
205 return self.output_prompt_template.safe_substitute({'number':number})
204 return self.output_prompt_template.safe_substitute({'number':number})
206
205
207
206
208 def is_complete(self, block):
207 def is_complete(self, block):
209 """Determine if block is complete.
208 """Determine if block is complete.
210
209
211 Parameters
210 Parameters
212 block : string
211 block : string
213
212
214 Result
213 Result
215 True if block can be sent to the engine without compile errors.
214 True if block can be sent to the engine without compile errors.
216 False otherwise.
215 False otherwise.
217 """
216 """
218
217
219 try:
218 try:
220 ast = self.compile_ast(block)
219 ast = self.compile_ast(block)
221 except:
220 except:
222 return False
221 return False
223
222
224 lines = block.split('\n')
223 lines = block.split('\n')
225 return (len(lines)==1 or str(lines[-1])=='')
224 return (len(lines)==1 or str(lines[-1])=='')
226
225
227
226
228 def compile_ast(self, block):
227 def compile_ast(self, block):
229 """Compile block to an AST
228 """Compile block to an AST
230
229
231 Parameters:
230 Parameters:
232 block : str
231 block : str
233
232
234 Result:
233 Result:
235 AST
234 AST
236
235
237 Throws:
236 Throws:
238 Exception if block cannot be compiled
237 Exception if block cannot be compiled
239 """
238 """
240
239
241 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
240 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
242
241
243
242
244 def execute(self, block, blockID=None):
243 def execute(self, block, blockID=None):
245 """Execute the block and return the result.
244 """Execute the block and return the result.
246
245
247 Parameters:
246 Parameters:
248 block : {str, AST}
247 block : {str, AST}
249 blockID : any
248 blockID : any
250 Caller may provide an ID to identify this block.
249 Caller may provide an ID to identify this block.
251 result['blockID'] := blockID
250 result['blockID'] := blockID
252
251
253 Result:
252 Result:
254 Deferred result of self.interpreter.execute
253 Deferred result of self.interpreter.execute
255 """
254 """
256
255
257 if(not self.is_complete(block)):
256 if(not self.is_complete(block)):
258 raise Exception("Block is not compilable")
257 raise Exception("Block is not compilable")
259
258
260 if(blockID == None):
259 if(blockID == None):
261 blockID = uuid.uuid4() #random UUID
260 blockID = uuid.uuid4() #random UUID
262
261
263 try:
262 try:
264 result = self.shell.execute(block)
263 result = self.shell.execute(block)
265 except Exception,e:
264 except Exception,e:
266 e = self._add_block_id_for_failure(e, blockID=blockID)
265 e = self._add_block_id_for_failure(e, blockID=blockID)
267 e = self.update_cell_prompt(e, blockID=blockID)
266 e = self.update_cell_prompt(e, blockID=blockID)
268 e = self.render_error(e)
267 e = self.render_error(e)
269 else:
268 else:
270 result = self._add_block_id_for_result(result, blockID=blockID)
269 result = self._add_block_id_for_result(result, blockID=blockID)
271 result = self.update_cell_prompt(result, blockID=blockID)
270 result = self.update_cell_prompt(result, blockID=blockID)
272 result = self.render_result(result)
271 result = self.render_result(result)
273
272
274 return result
273 return result
275
274
276
275
277 def _add_block_id_for_result(self, result, blockID):
276 def _add_block_id_for_result(self, result, blockID):
278 """Add the blockID to result or failure. Unfortunatley, we have to
277 """Add the blockID to result or failure. Unfortunatley, we have to
279 treat failures differently than result dicts.
278 treat failures differently than result dicts.
280 """
279 """
281
280
282 result['blockID'] = blockID
281 result['blockID'] = blockID
283
282
284 return result
283 return result
285
284
286 def _add_block_id_for_failure(self, failure, blockID):
285 def _add_block_id_for_failure(self, failure, blockID):
287 """_add_block_id_for_failure"""
286 """_add_block_id_for_failure"""
288 failure.blockID = blockID
287 failure.blockID = blockID
289 return failure
288 return failure
290
289
291
290
292 def _add_history(self, result, block=None):
291 def _add_history(self, result, block=None):
293 """Add block to the history"""
292 """Add block to the history"""
294
293
295 assert(block != None)
294 assert(block != None)
296 self.history.add_items([block])
295 self.history.add_items([block])
297 self.history_cursor += 1
296 self.history_cursor += 1
298
297
299 return result
298 return result
300
299
301
300
302 def get_history_previous(self, current_block):
301 def get_history_previous(self, current_block):
303 """ Returns previous history string and decrement history cursor.
302 """ Returns previous history string and decrement history cursor.
304 """
303 """
305 command = self.history.get_history_item(self.history_cursor - 1)
304 command = self.history.get_history_item(self.history_cursor - 1)
306
305
307 if command is not None:
306 if command is not None:
308 if(self.history_cursor+1 == len(self.history.input_cache)):
307 if(self.history_cursor+1 == len(self.history.input_cache)):
309 self.history.input_cache[self.history_cursor] = current_block
308 self.history.input_cache[self.history_cursor] = current_block
310 self.history_cursor -= 1
309 self.history_cursor -= 1
311 return command
310 return command
312
311
313
312
314 def get_history_next(self):
313 def get_history_next(self):
315 """ Returns next history string and increment history cursor.
314 """ Returns next history string and increment history cursor.
316 """
315 """
317 command = self.history.get_history_item(self.history_cursor+1)
316 command = self.history.get_history_item(self.history_cursor+1)
318
317
319 if command is not None:
318 if command is not None:
320 self.history_cursor += 1
319 self.history_cursor += 1
321 return command
320 return command
322
321
323 ###
322 ###
324 # Subclasses probably want to override these methods...
323 # Subclasses probably want to override these methods...
325 ###
324 ###
326
325
327 def update_cell_prompt(self, result, blockID=None):
326 def update_cell_prompt(self, result, blockID=None):
328 """Subclass may override to update the input prompt for a block.
327 """Subclass may override to update the input prompt for a block.
329
328
330 This method only really makes sens in asyncrhonous frontend.
329 This method only really makes sens in asyncrhonous frontend.
331 Since this method will be called as a
330 Since this method will be called as a
332 twisted.internet.defer.Deferred's callback, implementations should
331 twisted.internet.defer.Deferred's callback, implementations should
333 return result when finished.
332 return result when finished.
334 """
333 """
335
334
336 raise NotImplementedError
335 raise NotImplementedError
337
336
338
337
339 def render_result(self, result):
338 def render_result(self, result):
340 """Subclasses must override to render result.
339 """Subclasses must override to render result.
341
340
342 In asynchronous frontends, this method will be called as a
341 In asynchronous frontends, this method will be called as a
343 twisted.internet.defer.Deferred's callback. Implementations
342 twisted.internet.defer.Deferred's callback. Implementations
344 should thus return result when finished.
343 should thus return result when finished.
345 """
344 """
346
345
347 raise NotImplementedError
346 raise NotImplementedError
348
347
349
348
350 def render_error(self, failure):
349 def render_error(self, failure):
351 """Subclasses must override to render the failure.
350 """Subclasses must override to render the failure.
352
351
353 In asynchronous frontends, this method will be called as a
352 In asynchronous frontends, this method will be called as a
354 twisted.internet.defer.Deferred's callback. Implementations
353 twisted.internet.defer.Deferred's callback. Implementations
355 should thus return result when finished.
354 should thus return result when finished.
356 """
355 """
357
356
358 raise NotImplementedError
357 raise NotImplementedError
359
358
@@ -1,152 +1,157 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """This file contains unittests for the frontendbase module."""
3 """This file contains unittests for the frontendbase module."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #---------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13
13
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #---------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17
17
18 import unittest
18 import unittest
19 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
19
20 from IPython.frontend import frontendbase
20 try:
21 from IPython.kernel.engineservice import EngineService
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService
24 except ImportError:
25 import nose
26 raise nose.SkipTest("This test requires zope.interface and Twisted")
22
27
23 class FrontEndCallbackChecker(AsyncFrontEndBase):
28 class FrontEndCallbackChecker(AsyncFrontEndBase):
24 """FrontEndBase subclass for checking callbacks"""
29 """FrontEndBase subclass for checking callbacks"""
25 def __init__(self, engine=None, history=None):
30 def __init__(self, engine=None, history=None):
26 super(FrontEndCallbackChecker, self).__init__(engine=engine,
31 super(FrontEndCallbackChecker, self).__init__(engine=engine,
27 history=history)
32 history=history)
28 self.updateCalled = False
33 self.updateCalled = False
29 self.renderResultCalled = False
34 self.renderResultCalled = False
30 self.renderErrorCalled = False
35 self.renderErrorCalled = False
31
36
32 def update_cell_prompt(self, result, blockID=None):
37 def update_cell_prompt(self, result, blockID=None):
33 self.updateCalled = True
38 self.updateCalled = True
34 return result
39 return result
35
40
36 def render_result(self, result):
41 def render_result(self, result):
37 self.renderResultCalled = True
42 self.renderResultCalled = True
38 return result
43 return result
39
44
40
45
41 def render_error(self, failure):
46 def render_error(self, failure):
42 self.renderErrorCalled = True
47 self.renderErrorCalled = True
43 return failure
48 return failure
44
49
45
50
46
51
47
52
48 class TestAsyncFrontendBase(unittest.TestCase):
53 class TestAsyncFrontendBase(unittest.TestCase):
49 def setUp(self):
54 def setUp(self):
50 """Setup the EngineService and FrontEndBase"""
55 """Setup the EngineService and FrontEndBase"""
51
56
52 self.fb = FrontEndCallbackChecker(engine=EngineService())
57 self.fb = FrontEndCallbackChecker(engine=EngineService())
53
58
54
59
55 def test_implements_IFrontEnd(self):
60 def test_implements_IFrontEnd(self):
56 assert(frontendbase.IFrontEnd.implementedBy(
61 assert(frontendbase.IFrontEnd.implementedBy(
57 AsyncFrontEndBase))
62 AsyncFrontEndBase))
58
63
59
64
60 def test_is_complete_returns_False_for_incomplete_block(self):
65 def test_is_complete_returns_False_for_incomplete_block(self):
61 """"""
66 """"""
62
67
63 block = """def test(a):"""
68 block = """def test(a):"""
64
69
65 assert(self.fb.is_complete(block) == False)
70 assert(self.fb.is_complete(block) == False)
66
71
67 def test_is_complete_returns_True_for_complete_block(self):
72 def test_is_complete_returns_True_for_complete_block(self):
68 """"""
73 """"""
69
74
70 block = """def test(a): pass"""
75 block = """def test(a): pass"""
71
76
72 assert(self.fb.is_complete(block))
77 assert(self.fb.is_complete(block))
73
78
74 block = """a=3"""
79 block = """a=3"""
75
80
76 assert(self.fb.is_complete(block))
81 assert(self.fb.is_complete(block))
77
82
78
83
79 def test_blockID_added_to_result(self):
84 def test_blockID_added_to_result(self):
80 block = """3+3"""
85 block = """3+3"""
81
86
82 d = self.fb.execute(block, blockID='TEST_ID')
87 d = self.fb.execute(block, blockID='TEST_ID')
83
88
84 d.addCallback(self.checkBlockID, expected='TEST_ID')
89 d.addCallback(self.checkBlockID, expected='TEST_ID')
85
90
86 def test_blockID_added_to_failure(self):
91 def test_blockID_added_to_failure(self):
87 block = "raise Exception()"
92 block = "raise Exception()"
88
93
89 d = self.fb.execute(block,blockID='TEST_ID')
94 d = self.fb.execute(block,blockID='TEST_ID')
90 d.addErrback(self.checkFailureID, expected='TEST_ID')
95 d.addErrback(self.checkFailureID, expected='TEST_ID')
91
96
92 def checkBlockID(self, result, expected=""):
97 def checkBlockID(self, result, expected=""):
93 assert(result['blockID'] == expected)
98 assert(result['blockID'] == expected)
94
99
95
100
96 def checkFailureID(self, failure, expected=""):
101 def checkFailureID(self, failure, expected=""):
97 assert(failure.blockID == expected)
102 assert(failure.blockID == expected)
98
103
99
104
100 def test_callbacks_added_to_execute(self):
105 def test_callbacks_added_to_execute(self):
101 """test that
106 """test that
102 update_cell_prompt
107 update_cell_prompt
103 render_result
108 render_result
104
109
105 are added to execute request
110 are added to execute request
106 """
111 """
107
112
108 d = self.fb.execute("10+10")
113 d = self.fb.execute("10+10")
109 d.addCallback(self.checkCallbacks)
114 d.addCallback(self.checkCallbacks)
110
115
111
116
112 def checkCallbacks(self, result):
117 def checkCallbacks(self, result):
113 assert(self.fb.updateCalled)
118 assert(self.fb.updateCalled)
114 assert(self.fb.renderResultCalled)
119 assert(self.fb.renderResultCalled)
115
120
116
121
117 def test_error_callback_added_to_execute(self):
122 def test_error_callback_added_to_execute(self):
118 """test that render_error called on execution error"""
123 """test that render_error called on execution error"""
119
124
120 d = self.fb.execute("raise Exception()")
125 d = self.fb.execute("raise Exception()")
121 d.addCallback(self.checkRenderError)
126 d.addCallback(self.checkRenderError)
122
127
123 def checkRenderError(self, result):
128 def checkRenderError(self, result):
124 assert(self.fb.renderErrorCalled)
129 assert(self.fb.renderErrorCalled)
125
130
126 def test_history_returns_expected_block(self):
131 def test_history_returns_expected_block(self):
127 """Make sure history browsing doesn't fail"""
132 """Make sure history browsing doesn't fail"""
128
133
129 blocks = ["a=1","a=2","a=3"]
134 blocks = ["a=1","a=2","a=3"]
130 for b in blocks:
135 for b in blocks:
131 d = self.fb.execute(b)
136 d = self.fb.execute(b)
132
137
133 # d is now the deferred for the last executed block
138 # d is now the deferred for the last executed block
134 d.addCallback(self.historyTests, blocks)
139 d.addCallback(self.historyTests, blocks)
135
140
136
141
137 def historyTests(self, result, blocks):
142 def historyTests(self, result, blocks):
138 """historyTests"""
143 """historyTests"""
139
144
140 assert(len(blocks) >= 3)
145 assert(len(blocks) >= 3)
141 assert(self.fb.get_history_previous("") == blocks[-2])
146 assert(self.fb.get_history_previous("") == blocks[-2])
142 assert(self.fb.get_history_previous("") == blocks[-3])
147 assert(self.fb.get_history_previous("") == blocks[-3])
143 assert(self.fb.get_history_next() == blocks[-2])
148 assert(self.fb.get_history_next() == blocks[-2])
144
149
145
150
146 def test_history_returns_none_at_startup(self):
151 def test_history_returns_none_at_startup(self):
147 """test_history_returns_none_at_startup"""
152 """test_history_returns_none_at_startup"""
148
153
149 assert(self.fb.get_history_previous("")==None)
154 assert(self.fb.get_history_previous("")==None)
150 assert(self.fb.get_history_next()==None)
155 assert(self.fb.get_history_next()==None)
151
156
152
157
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
@@ -1,92 +1,91 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """This file contains unittests for the enginepb.py module."""
3 """This file contains unittests for the enginepb.py module."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 try:
18 try:
19 from twisted.python import components
19 from twisted.python import components
20 from twisted.internet import reactor, defer
20 from twisted.internet import reactor, defer
21 from twisted.spread import pb
21 from twisted.spread import pb
22 from twisted.internet.base import DelayedCall
22 from twisted.internet.base import DelayedCall
23 DelayedCall.debug = True
23 DelayedCall.debug = True
24
24
25 import zope.interface as zi
25 import zope.interface as zi
26
26
27 from IPython.kernel.fcutil import Tub, UnauthenticatedTub
27 from IPython.kernel.fcutil import Tub, UnauthenticatedTub
28 from IPython.kernel import engineservice as es
28 from IPython.kernel import engineservice as es
29 from IPython.testing.util import DeferredTestCase
29 from IPython.testing.util import DeferredTestCase
30 from IPython.kernel.controllerservice import IControllerBase
30 from IPython.kernel.controllerservice import IControllerBase
31 from IPython.kernel.enginefc import FCRemoteEngineRefFromService, IEngineBase
31 from IPython.kernel.enginefc import FCRemoteEngineRefFromService, IEngineBase
32 from IPython.kernel.engineservice import IEngineQueued
32 from IPython.kernel.engineservice import IEngineQueued
33 from IPython.kernel.engineconnector import EngineConnector
33 from IPython.kernel.engineconnector import EngineConnector
34
34
35 from IPython.kernel.tests.engineservicetest import \
35 from IPython.kernel.tests.engineservicetest import \
36 IEngineCoreTestCase, \
36 IEngineCoreTestCase, \
37 IEngineSerializedTestCase, \
37 IEngineSerializedTestCase, \
38 IEngineQueuedTestCase
38 IEngineQueuedTestCase
39 except ImportError:
39 except ImportError:
40 print "we got an error!!!"
40 pass
41 raise
42 else:
41 else:
43 class EngineFCTest(DeferredTestCase,
42 class EngineFCTest(DeferredTestCase,
44 IEngineCoreTestCase,
43 IEngineCoreTestCase,
45 IEngineSerializedTestCase,
44 IEngineSerializedTestCase,
46 IEngineQueuedTestCase
45 IEngineQueuedTestCase
47 ):
46 ):
48
47
49 zi.implements(IControllerBase)
48 zi.implements(IControllerBase)
50
49
51 def setUp(self):
50 def setUp(self):
52
51
53 # Start a server and append to self.servers
52 # Start a server and append to self.servers
54 self.controller_reference = FCRemoteEngineRefFromService(self)
53 self.controller_reference = FCRemoteEngineRefFromService(self)
55 self.controller_tub = Tub()
54 self.controller_tub = Tub()
56 self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1')
55 self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1')
57 self.controller_tub.setLocation('127.0.0.1:10105')
56 self.controller_tub.setLocation('127.0.0.1:10105')
58
57
59 furl = self.controller_tub.registerReference(self.controller_reference)
58 furl = self.controller_tub.registerReference(self.controller_reference)
60 self.controller_tub.startService()
59 self.controller_tub.startService()
61
60
62 # Start an EngineService and append to services/client
61 # Start an EngineService and append to services/client
63 self.engine_service = es.EngineService()
62 self.engine_service = es.EngineService()
64 self.engine_service.startService()
63 self.engine_service.startService()
65 self.engine_tub = Tub()
64 self.engine_tub = Tub()
66 self.engine_tub.startService()
65 self.engine_tub.startService()
67 engine_connector = EngineConnector(self.engine_tub)
66 engine_connector = EngineConnector(self.engine_tub)
68 d = engine_connector.connect_to_controller(self.engine_service, furl)
67 d = engine_connector.connect_to_controller(self.engine_service, furl)
69 # This deferred doesn't fire until after register_engine has returned and
68 # This deferred doesn't fire until after register_engine has returned and
70 # thus, self.engine has been defined and the tets can proceed.
69 # thus, self.engine has been defined and the tets can proceed.
71 return d
70 return d
72
71
73 def tearDown(self):
72 def tearDown(self):
74 dlist = []
73 dlist = []
75 # Shut down the engine
74 # Shut down the engine
76 d = self.engine_tub.stopService()
75 d = self.engine_tub.stopService()
77 dlist.append(d)
76 dlist.append(d)
78 # Shut down the controller
77 # Shut down the controller
79 d = self.controller_tub.stopService()
78 d = self.controller_tub.stopService()
80 dlist.append(d)
79 dlist.append(d)
81 return defer.DeferredList(dlist)
80 return defer.DeferredList(dlist)
82
81
83 #---------------------------------------------------------------------------
82 #---------------------------------------------------------------------------
84 # Make me look like a basic controller
83 # Make me look like a basic controller
85 #---------------------------------------------------------------------------
84 #---------------------------------------------------------------------------
86
85
87 def register_engine(self, engine_ref, id=None, ip=None, port=None, pid=None):
86 def register_engine(self, engine_ref, id=None, ip=None, port=None, pid=None):
88 self.engine = IEngineQueued(IEngineBase(engine_ref))
87 self.engine = IEngineQueued(IEngineBase(engine_ref))
89 return {'id':id}
88 return {'id':id}
90
89
91 def unregister_engine(self, id):
90 def unregister_engine(self, id):
92 pass No newline at end of file
91 pass
1 NO CONTENT: modified file chmod 100755 => 100644
NO CONTENT: modified file chmod 100755 => 100644
General Comments 0
You need to be logged in to leave comments. Login now