##// END OF EJS Templates
pep8 compliance, first pass
Barry Wark -
Show More
@@ -1,27 +1,28 b''
1 1 # encoding: utf-8
2 # -*- test-case-name: ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
2 # -*- test-case-name: IPython.frontend.cocoa.tests.test_cocoa_frontend -*-
3 3
4 """PyObjC classes to provide a Cocoa frontend to the ipython1.kernel.engineservice.EngineService.
4 """PyObjC classes to provide a Cocoa frontend to the
5 IPython.kernel.engineservice.EngineService.
5 6
6 The Cocoa frontend is divided into two classes:
7 - IPythonCocoaController
8 - IPythonCLITextViewDelegate
7 To add an IPython interpreter to a cocoa app, instantiate an
8 IPythonCocoaController in a XIB and connect its textView outlet to an
9 NSTextView instance in your UI. That's it.
9 10
10 To add an IPython interpreter to a cocoa app, instantiate both of these classes in an XIB...[FINISH]
11 Author: Barry Wark
11 12 """
12 13
13 14 __docformat__ = "restructuredtext en"
14 15
15 #-------------------------------------------------------------------------------
16 # Copyright (C) 2008 Barry Wark <barrywark@gmail.com>
16 #-----------------------------------------------------------------------------
17 # Copyright (C) 2008 The IPython Development Team
17 18 #
18 19 # Distributed under the terms of the BSD License. The full license is in
19 20 # the file COPYING, distributed as part of this software.
20 #-------------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
21 22
22 #-------------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
23 24 # Imports
24 #-------------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
25 26
26 27 import objc
27 28 import uuid
@@ -42,12 +43,13 b' from IPython.frontend.frontendbase import FrontEndBase'
42 43 from twisted.internet.threads import blockingCallFromThread
43 44 from twisted.python.failure import Failure
44 45
45 #-------------------------------------------------------------------------------
46 #------------------------------------------------------------------------------
46 47 # Classes to implement the Cocoa frontend
47 #-------------------------------------------------------------------------------
48 #------------------------------------------------------------------------------
48 49
49 50 # TODO:
50 # 1. use MultiEngineClient and out-of-process engine rather than ThreadedEngineService?
51 # 1. use MultiEngineClient and out-of-process engine rather than
52 # ThreadedEngineService?
51 53 # 2. integrate Xgrid launching of engines
52 54
53 55
@@ -89,7 +91,8 b' class IPythonCocoaController(NSObject, FrontEndBase):'
89 91 NSLog('IPython engine started')
90 92
91 93 # Register for app termination
92 NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(self,
94 NSNotificationCenter.defaultCenter().addObserver_selector_name_object_(
95 self,
93 96 'appWillTerminate:',
94 97 NSApplicationWillTerminateNotification,
95 98 None)
@@ -163,7 +166,8 b' class IPythonCocoaController(NSObject, FrontEndBase):'
163 166 def startCLIForTextView(self):
164 167 """Print banner"""
165 168
166 banner = """IPython1 %s -- An enhanced Interactive Python.""" % IPython.__version__
169 banner = """IPython1 %s -- An enhanced Interactive Python.""" % \
170 IPython.__version__
167 171
168 172 self.insert_text(banner + '\n\n')
169 173
@@ -206,14 +210,18 b' class IPythonCocoaController(NSObject, FrontEndBase):'
206 210 return True
207 211
208 212 elif(selector == 'moveToBeginningOfParagraph:'):
209 textView.setSelectedRange_(NSMakeRange(self.currentBlockRange().location, 0))
213 textView.setSelectedRange_(NSMakeRange(
214 self.currentBlockRange().location,
215 0))
210 216 return True
211 217 elif(selector == 'moveToEndOfParagraph:'):
212 textView.setSelectedRange_(NSMakeRange(self.currentBlockRange().location + \
218 textView.setSelectedRange_(NSMakeRange(
219 self.currentBlockRange().location + \
213 220 self.currentBlockRange().length, 0))
214 221 return True
215 222 elif(selector == 'deleteToEndOfParagraph:'):
216 if(textView.selectedRange().location <= self.currentBlockRange().location):
223 if(textView.selectedRange().location <= \
224 self.currentBlockRange().location):
217 225 # Intersect the selected range with the current line range
218 226 if(self.currentBlockRange().length < 0):
219 227 self.blockRanges[self.currentBlockID].length = 0
@@ -235,7 +243,8 b' class IPythonCocoaController(NSObject, FrontEndBase):'
235 243
236 244 elif(selector == 'deleteBackward:'):
237 245 #if we're at the beginning of the current block, ignore
238 if(textView.selectedRange().location == self.currentBlockRange().location):
246 if(textView.selectedRange().location == \
247 self.currentBlockRange().location):
239 248 return True
240 249 else:
241 250 self.currentBlockRange().length-=1
@@ -243,14 +252,15 b' class IPythonCocoaController(NSObject, FrontEndBase):'
243 252 return False
244 253
245 254
246 def textView_shouldChangeTextInRanges_replacementStrings_(self, textView, ranges, replacementStrings):
255 def textView_shouldChangeTextInRanges_replacementStrings_(self,
256 textView, ranges, replacementStrings):
247 257 """
248 258 Delegate method for NSTextView.
249 259
250 Refuse change text in ranges not at end, but make those changes at end.
260 Refuse change text in ranges not at end, but make those changes at
261 end.
251 262 """
252 263
253 #print 'textView_shouldChangeTextInRanges_replacementStrings_:',ranges,replacementStrings
254 264 assert(len(ranges) == len(replacementStrings))
255 265 allow = True
256 266 for r,s in zip(ranges, replacementStrings):
@@ -261,13 +271,17 b' class IPythonCocoaController(NSObject, FrontEndBase):'
261 271 allow = False
262 272
263 273
264 self.blockRanges.setdefault(self.currentBlockID, self.currentBlockRange()).length += len(s)
274 self.blockRanges.setdefault(self.currentBlockID,
275 self.currentBlockRange()).length +=\
276 len(s)
265 277
266 278 return allow
267 279
268 def textView_completions_forPartialWordRange_indexOfSelectedItem_(self, textView, words, charRange, index):
280 def textView_completions_forPartialWordRange_indexOfSelectedItem_(self,
281 textView, words, charRange, index):
269 282 try:
270 token = textView.textStorage().string().substringWithRange_(charRange)
283 ts = textView.textStorage()
284 token = ts.string().substringWithRange_(charRange)
271 285 completions = blockingCallFromThread(self.complete, token)
272 286 except:
273 287 completions = objc.nil
@@ -288,7 +302,9 b' class IPythonCocoaController(NSObject, FrontEndBase):'
288 302 return uuid.uuid4()
289 303
290 304 def currentBlockRange(self):
291 return self.blockRanges.get(self.currentBlockID, NSMakeRange(self.textView.textStorage().length(), 0))
305 return self.blockRanges.get(self.currentBlockID,
306 NSMakeRange(self.textView.textStorage().length(),
307 0))
292 308
293 309 def currentBlock(self):
294 310 """The current block's text"""
@@ -298,7 +314,8 b' class IPythonCocoaController(NSObject, FrontEndBase):'
298 314 def textForRange(self, textRange):
299 315 """textForRange"""
300 316
301 return self.textView.textStorage().string().substringWithRange_(textRange)
317 ts = self.textView.textStorage()
318 return ts.string().substringWithRange_(textRange)
302 319
303 320 def currentLine(self):
304 321 block = self.textForRange(self.currentBlockRange())
@@ -330,7 +347,8 b' class IPythonCocoaController(NSObject, FrontEndBase):'
330 347 self.output_prompt(result) +
331 348 result.get('display',{}).get('pprint','') +
332 349 '\n\n',
333 textRange=NSMakeRange(inputRange.location+inputRange.length, 0))
350 textRange=NSMakeRange(inputRange.location+inputRange.length,
351 0))
334 352 return result
335 353
336 354
@@ -341,7 +359,9 b' class IPythonCocoaController(NSObject, FrontEndBase):'
341 359
342 360
343 361 def insert_text(self, string=None, textRange=None, scrollToVisible=True):
344 """Insert text into textView at textRange, updating blockRanges as necessary"""
362 """Insert text into textView at textRange, updating blockRanges
363 as necessary
364 """
345 365
346 366 if(textRange == None):
347 367 textRange = NSMakeRange(self.textView.textStorage().length(), 0) #range for end of text
@@ -1,26 +1,19 b''
1 1 # encoding: utf-8
2 """This file contains unittests for the ipython1.frontend.cocoa.cocoa_frontend module.
3
4 Things that should be tested:
5
6 - IPythonCocoaController instantiates an IEngineInteractive
7 - IPythonCocoaController executes code on the engine
8 - IPythonCocoaController mirrors engine's user_ns
2 """This file contains unittests for the
3 IPython.frontend.cocoa.cocoa_frontend module.
9 4 """
10 5 __docformat__ = "restructuredtext en"
11 6
12 #-------------------------------------------------------------------------------
13 # Copyright (C) 2005 Fernando Perez <fperez@colorado.edu>
14 # Brian E Granger <ellisonbg@gmail.com>
15 # Benjamin Ragan-Kelley <benjaminrk@gmail.com>
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2005 The IPython Development Team
16 9 #
17 10 # Distributed under the terms of the BSD License. The full license is in
18 11 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
20 13
21 #-------------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
22 15 # Imports
23 #-------------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
24 17 from IPython.kernel.core.interpreter import Interpreter
25 18 import IPython.kernel.engineservice as es
26 19 from IPython.testing.util import DeferredTestCase
@@ -51,7 +44,9 b' class TestIPythonCocoaControler(DeferredTestCase):'
51 44 del result['number']
52 45 del result['id']
53 46 return result
54 self.assertDeferredEquals(self.controller.execute(code).addCallback(removeNumberAndID), expected)
47 self.assertDeferredEquals(
48 self.controller.execute(code).addCallback(removeNumberAndID),
49 expected)
55 50
56 51 def testControllerMirrorsUserNSWithValuesAsStrings(self):
57 52 code = """userns1=1;userns2=2"""
@@ -1,6 +1,8 b''
1 1 # encoding: utf-8
2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
2 3 """
3 frontendbase provides an interface and base class for GUI frontends for IPython.kernel/IPython.kernel.core.
4 frontendbase provides an interface and base class for GUI frontends for
5 IPython.kernel/IPython.kernel.core.
4 6
5 7 Frontend implementations will likely want to subclass FrontEndBase.
6 8
@@ -57,20 +59,26 b' class IFrontEndFactory(zi.Interface):'
57 59 class IFrontEnd(zi.Interface):
58 60 """Interface for frontends. All methods return t.i.d.Deferred"""
59 61
60 zi.Attribute("input_prompt_template", "string.Template instance substituteable with execute result.")
61 zi.Attribute("output_prompt_template", "string.Template instance substituteable with execute result.")
62 zi.Attribute("continuation_prompt_template", "string.Template instance substituteable with execute result.")
62 zi.Attribute("input_prompt_template", "string.Template instance\
63 substituteable with execute result.")
64 zi.Attribute("output_prompt_template", "string.Template instance\
65 substituteable with execute result.")
66 zi.Attribute("continuation_prompt_template", "string.Template instance\
67 substituteable with execute result.")
63 68
64 69 def update_cell_prompt(self, result):
65 70 """Subclass may override to update the input prompt for a block.
66 Since this method will be called as a twisted.internet.defer.Deferred's callback,
71 Since this method will be called as a
72 twisted.internet.defer.Deferred's callback,
67 73 implementations should return result when finished."""
68 74
69 75 pass
70 76
71 77 def render_result(self, result):
72 """Render the result of an execute call. Implementors may choose the method of rendering.
73 For example, a notebook-style frontend might render a Chaco plot inline.
78 """Render the result of an execute call. Implementors may choose the
79 method of rendering.
80 For example, a notebook-style frontend might render a Chaco plot
81 inline.
74 82
75 83 Parameters:
76 84 result : dict (result of IEngineBase.execute )
@@ -82,24 +90,31 b' class IFrontEnd(zi.Interface):'
82 90 pass
83 91
84 92 def render_error(self, failure):
85 """Subclasses must override to render the failure. Since this method will be called as a
86 twisted.internet.defer.Deferred's callback, implementations should return result
87 when finished."""
93 """Subclasses must override to render the failure. Since this method
94 ill be called as a twisted.internet.defer.Deferred's callback,
95 implementations should return result when finished.
96 """
88 97
89 98 pass
90 99
91 100
92 101 def input_prompt(result={}):
93 """Returns the input prompt by subsituting into self.input_prompt_template"""
102 """Returns the input prompt by subsituting into
103 self.input_prompt_template
104 """
94 105 pass
95 106
96 107 def output_prompt(result):
97 """Returns the output prompt by subsituting into self.output_prompt_template"""
108 """Returns the output prompt by subsituting into
109 self.output_prompt_template
110 """
98 111
99 112 pass
100 113
101 114 def continuation_prompt():
102 """Returns the continuation prompt by subsituting into self.continuation_prompt_template"""
115 """Returns the continuation prompt by subsituting into
116 self.continuation_prompt_template
117 """
103 118
104 119 pass
105 120
@@ -221,7 +236,8 b' class FrontEndBase(object):'
221 236 Parameters:
222 237 block : {str, AST}
223 238 blockID : any
224 Caller may provide an ID to identify this block. result['blockID'] := blockID
239 Caller may provide an ID to identify this block.
240 result['blockID'] := blockID
225 241
226 242 Result:
227 243 Deferred result of self.interpreter.execute
@@ -243,8 +259,8 b' class FrontEndBase(object):'
243 259
244 260
245 261 def _add_block_id(self, result, blockID):
246 """Add the blockID to result or failure. Unfortunatley, we have to treat failures
247 differently than result dicts
262 """Add the blockID to result or failure. Unfortunatley, we have to
263 treat failures differently than result dicts.
248 264 """
249 265
250 266 if(isinstance(result, Failure)):
@@ -291,11 +307,12 b' class FrontEndBase(object):'
291 307
292 308 def update_cell_prompt(self, result):
293 309 """Subclass may override to update the input prompt for a block.
294 Since this method will be called as a twisted.internet.defer.Deferred's callback,
295 implementations should return result when finished.
310 Since this method will be called as a
311 twisted.internet.defer.Deferred's callback, implementations should
312 return result when finished.
296 313
297 NP: result is a failure if the execute returned a failre. To get the blockID, you should
298 do something like::
314 NP: result is a failure if the execute returned a failre.
315 To get the blockID, you should do something like::
299 316 if(isinstance(result, twisted.python.failure.Failure)):
300 317 blockID = result.blockID
301 318 else:
@@ -308,17 +325,18 b' class FrontEndBase(object):'
308 325
309 326
310 327 def render_result(self, result):
311 """Subclasses must override to render result. Since this method will be called as a
312 twisted.internet.defer.Deferred's callback, implementations should return result
313 when finished."""
328 """Subclasses must override to render result. Since this method will
329 be called as a twisted.internet.defer.Deferred's callback,
330 implementations should return result when finished.
331 """
314 332
315 333 return result
316 334
317 335
318 336 def render_error(self, failure):
319 """Subclasses must override to render the failure. Since this method will be called as a
320 twisted.internet.defer.Deferred's callback, implementations should return result
321 when finished."""
337 """Subclasses must override to render the failure. Since this method
338 will be called as a twisted.internet.defer.Deferred's callback,
339 implementations should return result when finished."""
322 340
323 341 return failure
324 342
@@ -4,16 +4,16 b''
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 #-------------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13 13
14 #-------------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 15 # Imports
16 #-------------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17 17
18 18 import unittest
19 19 from IPython.frontend import frontendbase
@@ -22,7 +22,8 b' from IPython.kernel.engineservice import EngineService'
22 22 class FrontEndCallbackChecker(frontendbase.FrontEndBase):
23 23 """FrontEndBase subclass for checking callbacks"""
24 24 def __init__(self, engine=None, history=None):
25 super(FrontEndCallbackChecker, self).__init__(engine=engine, history=history)
25 super(FrontEndCallbackChecker, self).__init__(engine=engine,
26 history=history)
26 27 self.updateCalled = False
27 28 self.renderResultCalled = False
28 29 self.renderErrorCalled = False
@@ -51,7 +52,8 b' class TestFrontendBase(unittest.TestCase):'
51 52
52 53
53 54 def test_implements_IFrontEnd(self):
54 assert(frontendbase.IFrontEnd.implementedBy(frontendbase.FrontEndBase))
55 assert(frontendbase.IFrontEnd.implementedBy(
56 frontendbase.FrontEndBase))
55 57
56 58
57 59 def test_is_complete_returns_False_for_incomplete_block(self):
@@ -847,11 +847,13 b' class Command(object):'
847 847 self.deferred.errback(reason)
848 848
849 849 class ThreadedEngineService(EngineService):
850 """An EngineService subclass that defers execute commands to a separate thread.
850 """An EngineService subclass that defers execute commands to a separate
851 thread.
851 852
852 ThreadedEngineService uses twisted.internet.threads.deferToThread to defer execute
853 requests to a separate thread. GUI frontends may want to use ThreadedEngineService as
854 the engine in an IPython.frontend.frontendbase.FrontEndBase subclass to prevent
853 ThreadedEngineService uses twisted.internet.threads.deferToThread to
854 defer execute requests to a separate thread. GUI frontends may want to
855 use ThreadedEngineService as the engine in an
856 IPython.frontend.frontendbase.FrontEndBase subclass to prevent
855 857 block execution from blocking the GUI thread.
856 858 """
857 859
General Comments 0
You need to be logged in to leave comments. Login now