diff --git a/IPython/Extensions/ipy_pydb.py b/IPython/Extensions/ipy_pydb.py old mode 100755 new mode 100644 diff --git a/IPython/Extensions/ipy_stock_completers.py b/IPython/Extensions/ipy_stock_completers.py old mode 100755 new mode 100644 diff --git a/IPython/Extensions/jobctrl.py b/IPython/Extensions/jobctrl.py old mode 100755 new mode 100644 diff --git a/IPython/Extensions/ledit.py b/IPython/Extensions/ledit.py old mode 100755 new mode 100644 diff --git a/IPython/PyColorize.py b/IPython/PyColorize.py old mode 100755 new mode 100644 diff --git a/IPython/completer.py b/IPython/completer.py index 3647da2..52df78e 100644 --- a/IPython/completer.py +++ b/IPython/completer.py @@ -314,7 +314,10 @@ class IPCompleter(Completer): # don't want to treat as delimiters in filename matching # when escaped with backslash - protectables = ' ' + if sys.platform == 'win32': + protectables = ' ' + else: + protectables = ' ()' if text.startswith('!'): text = text[1:] diff --git a/IPython/frontend/asyncfrontendbase.py b/IPython/frontend/asyncfrontendbase.py index 3662351..a35366f 100644 --- a/IPython/frontend/asyncfrontendbase.py +++ b/IPython/frontend/asyncfrontendbase.py @@ -16,28 +16,12 @@ __docformat__ = "restructuredtext en" #------------------------------------------------------------------------------- import uuid -try: - from zope.interface import Interface, Attribute, implements, classProvides -except ImportError, e: - e.message = """%s -________________________________________________________________________________ -zope.interface is required to run asynchronous frontends.""" % e.message - e.args = (e.message, ) + e.args[1:] -from frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory - -from IPython.kernel.engineservice import IEngineCore +from zope.interface import Interface, Attribute, implements, classProvides +from twisted.python.failure import Failure +from IPython.frontend.frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory from IPython.kernel.core.history import FrontEndHistory - -try: - from twisted.python.failure import Failure -except ImportError, e: - e.message = """%s -________________________________________________________________________________ -twisted is required to run asynchronous frontends.""" % e.message - e.args = (e.message, ) + e.args[1:] - - +from IPython.kernel.engineservice import IEngineCore class AsyncFrontEndBase(FrontEndBase): diff --git a/IPython/frontend/cocoa/tests/test_cocoa_frontend.py b/IPython/frontend/cocoa/tests/test_cocoa_frontend.py index d85728d..eb4dae2 100644 --- a/IPython/frontend/cocoa/tests/test_cocoa_frontend.py +++ b/IPython/frontend/cocoa/tests/test_cocoa_frontend.py @@ -14,28 +14,31 @@ __docformat__ = "restructuredtext en" #--------------------------------------------------------------------------- # Imports #--------------------------------------------------------------------------- -from IPython.kernel.core.interpreter import Interpreter -import IPython.kernel.engineservice as es -from IPython.testing.util import DeferredTestCase -from twisted.internet.defer import succeed -from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController - -from Foundation import NSMakeRect -from AppKit import NSTextView, NSScrollView + +try: + from IPython.kernel.core.interpreter import Interpreter + import IPython.kernel.engineservice as es + from IPython.testing.util import DeferredTestCase + from twisted.internet.defer import succeed + from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController + from Foundation import NSMakeRect + from AppKit import NSTextView, NSScrollView +except ImportError: + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC") class TestIPythonCocoaControler(DeferredTestCase): """Tests for IPythonCocoaController""" - + def setUp(self): self.controller = IPythonCocoaController.alloc().init() self.engine = es.EngineService() self.engine.startService() - - + def tearDown(self): self.controller = None self.engine.stopService() - + def testControllerExecutesCode(self): code ="""5+5""" expected = Interpreter().execute(code) @@ -47,45 +50,45 @@ class TestIPythonCocoaControler(DeferredTestCase): self.assertDeferredEquals( self.controller.execute(code).addCallback(removeNumberAndID), expected) - + def testControllerMirrorsUserNSWithValuesAsStrings(self): code = """userns1=1;userns2=2""" def testControllerUserNS(result): self.assertEquals(self.controller.userNS['userns1'], 1) self.assertEquals(self.controller.userNS['userns2'], 2) - + self.controller.execute(code).addCallback(testControllerUserNS) - - + + def testControllerInstantiatesIEngine(self): self.assert_(es.IEngineBase.providedBy(self.controller.engine)) - + def testControllerCompletesToken(self): code = """longNameVariable=10""" def testCompletes(result): self.assert_("longNameVariable" in result) - + def testCompleteToken(result): self.controller.complete("longNa").addCallback(testCompletes) - + self.controller.execute(code).addCallback(testCompletes) - - + + def testCurrentIndent(self): """test that current_indent_string returns current indent or None. Uses _indent_for_block for direct unit testing. """ - + self.controller.tabUsesSpaces = True self.assert_(self.controller._indent_for_block("""a=3""") == None) self.assert_(self.controller._indent_for_block("") == None) block = """def test():\n a=3""" self.assert_(self.controller._indent_for_block(block) == \ ' ' * self.controller.tabSpaces) - + block = """if(True):\n%sif(False):\n%spass""" % \ (' '*self.controller.tabSpaces, 2*' '*self.controller.tabSpaces) self.assert_(self.controller._indent_for_block(block) == \ 2*(' '*self.controller.tabSpaces)) - + diff --git a/IPython/frontend/frontendbase.py b/IPython/frontend/frontendbase.py index 7012ba8..9f98dcf 100644 --- a/IPython/frontend/frontendbase.py +++ b/IPython/frontend/frontendbase.py @@ -24,11 +24,14 @@ import string import uuid import _ast -from zopeinterface import Interface, Attribute, implements, classProvides - +from IPython.frontend.zopeinterface import ( + Interface, + Attribute, + implements, + classProvides +) from IPython.kernel.core.history import FrontEndHistory from IPython.kernel.core.util import Bunch -from IPython.kernel.engineservice import IEngineCore ############################################################################## # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or diff --git a/IPython/frontend/tests/test_frontendbase.py b/IPython/frontend/tests/test_frontendbase.py index 42d3856..c89af0b 100644 --- a/IPython/frontend/tests/test_frontendbase.py +++ b/IPython/frontend/tests/test_frontendbase.py @@ -16,9 +16,14 @@ __docformat__ = "restructuredtext en" #--------------------------------------------------------------------------- import unittest -from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase -from IPython.frontend import frontendbase -from IPython.kernel.engineservice import EngineService + +try: + from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase + from IPython.frontend import frontendbase + from IPython.kernel.engineservice import EngineService +except ImportError: + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") class FrontEndCallbackChecker(AsyncFrontEndBase): """FrontEndBase subclass for checking callbacks""" @@ -28,11 +33,11 @@ class FrontEndCallbackChecker(AsyncFrontEndBase): self.updateCalled = False self.renderResultCalled = False self.renderErrorCalled = False - + def update_cell_prompt(self, result, blockID=None): self.updateCalled = True return result - + def render_result(self, result): self.renderResultCalled = True return result diff --git a/IPython/gui/wx/wxIPython.py b/IPython/gui/wx/wxIPython.py old mode 100755 new mode 100644 diff --git a/IPython/irunner.py b/IPython/irunner.py old mode 100755 new mode 100644 diff --git a/IPython/kernel/core/shell.py b/IPython/kernel/core/shell.py deleted file mode 100644 index eb266ae..0000000 --- a/IPython/kernel/core/shell.py +++ /dev/null @@ -1,357 +0,0 @@ -# encoding: utf-8 -# -*- test-case-name: IPython.test.test_shell -*- - -"""The core IPython Shell""" - -__docformat__ = "restructuredtext en" - -#------------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# Imports -#------------------------------------------------------------------------------- - -import pprint -import signal -import sys -import threading -import time - -from code import InteractiveConsole, softspace -from StringIO import StringIO - -from IPython.OutputTrap import OutputTrap -from IPython import ultraTB - -from IPython.kernel.error import NotDefined - - -class InteractiveShell(InteractiveConsole): - """The Basic IPython Shell class. - - This class provides the basic capabilities of IPython. Currently - this class does not do anything IPython specific. That is, it is - just a python shell. - - It is modelled on code.InteractiveConsole, but adds additional - capabilities. These additional capabilities are what give IPython - its power. - - The current version of this class is meant to be a prototype that guides - the future design of the IPython core. This class must not use Twisted - in any way, but it must be designed in a way that makes it easy to - incorporate into Twisted and hook network protocols up to. - - Some of the methods of this class comprise the official IPython core - interface. These methods must be tread safe and they must return types - that can be easily serialized by protocols such as PB, XML-RPC and SOAP. - Locks have been provided for making the methods thread safe, but additional - locks can be added as needed. - - Any method that is meant to be a part of the official interface must also - be declared in the kernel.coreservice.ICoreService interface. Eventually - all other methods should have single leading underscores to note that they - are not designed to be 'public.' Currently, because this class inherits - from code.InteractiveConsole there are many private methods w/o leading - underscores. The interface should be as simple as possible and methods - should not be added to the interface unless they really need to be there. - - Note: - - - For now I am using methods named put/get to move objects in/out of the - users namespace. Originally, I was calling these methods push/pull, but - because code.InteractiveConsole already has a push method, I had to use - something different. Eventually, we probably won't subclass this class - so we can call these methods whatever we want. So, what do we want to - call them? - - We need a way of running the trapping of stdout/stderr in different ways. - We should be able to i) trap, ii) not trap at all or iii) trap and echo - things to stdout and stderr. - - How should errors be handled? Should exceptions be raised? - - What should methods that don't compute anything return? The default of - None? - """ - - def __init__(self, locals=None, filename=""): - """Creates a new TrappingInteractiveConsole object.""" - InteractiveConsole.__init__(self,locals,filename) - self._trap = OutputTrap(debug=0) - self._stdin = [] - self._stdout = [] - self._stderr = [] - self._last_type = self._last_traceback = self._last_value = None - #self._namespace_lock = threading.Lock() - #self._command_lock = threading.Lock() - self.lastCommandIndex = -1 - # I am using this user defined signal to interrupt the currently - # running command. I am not sure if this is the best way, but - # it is working! - # This doesn't work on Windows as it doesn't have this signal. - #signal.signal(signal.SIGUSR1, self._handleSIGUSR1) - - # An exception handler. Experimental: later we need to make the - # modes/colors available to user configuration, etc. - self.tbHandler = ultraTB.FormattedTB(color_scheme='NoColor', - mode='Context', - tb_offset=2) - - def _handleSIGUSR1(self, signum, frame): - """Handle the SIGUSR1 signal by printing to stderr.""" - print>>sys.stderr, "Command stopped." - - def _prefilter(self, line, more): - return line - - def _trapRunlines(self, lines): - """ - This executes the python source code, source, in the - self.locals namespace and traps stdout and stderr. Upon - exiting, self.out and self.err contain the values of - stdout and stderr for the last executed command only. - """ - - # Execute the code - #self._namespace_lock.acquire() - self._trap.flush() - self._trap.trap() - self._runlines(lines) - self.lastCommandIndex += 1 - self._trap.release() - #self._namespace_lock.release() - - # Save stdin, stdout and stderr to lists - #self._command_lock.acquire() - self._stdin.append(lines) - self._stdout.append(self.prune_output(self._trap.out.getvalue())) - self._stderr.append(self.prune_output(self._trap.err.getvalue())) - #self._command_lock.release() - - def prune_output(self, s): - """Only return the first and last 1600 chars of stdout and stderr. - - Something like this is required to make sure that the engine and - controller don't become overwhelmed by the size of stdout/stderr. - """ - if len(s) > 3200: - return s[:1600] + '\n............\n' + s[-1600:] - else: - return s - - # Lifted from iplib.InteractiveShell - def _runlines(self,lines): - """Run a string of one or more lines of source. - - This method is capable of running a string containing multiple source - lines, as if they had been entered at the IPython prompt. Since it - exposes IPython's processing machinery, the given strings can contain - magic calls (%magic), special shell access (!cmd), etc.""" - - # We must start with a clean buffer, in case this is run from an - # interactive IPython session (via a magic, for example). - self.resetbuffer() - lines = lines.split('\n') - more = 0 - for line in lines: - # skip blank lines so we don't mess up the prompt counter, but do - # NOT skip even a blank line if we are in a code block (more is - # true) - if line or more: - more = self.push((self._prefilter(line,more))) - # IPython's runsource returns None if there was an error - # compiling the code. This allows us to stop processing right - # away, so the user gets the error message at the right place. - if more is None: - break - # final newline in case the input didn't have it, so that the code - # actually does get executed - if more: - self.push('\n') - - def runcode(self, code): - """Execute a code object. - - When an exception occurs, self.showtraceback() is called to - display a traceback. All exceptions are caught except - SystemExit, which is reraised. - - A note about KeyboardInterrupt: this exception may occur - elsewhere in this code, and may not always be caught. The - caller should be prepared to deal with it. - - """ - - self._last_type = self._last_traceback = self._last_value = None - try: - exec code in self.locals - except: - # Since the exception info may need to travel across the wire, we - # pack it in right away. Note that we are abusing the exception - # value to store a fully formatted traceback, since the stack can - # not be serialized for network transmission. - et,ev,tb = sys.exc_info() - self._last_type = et - self._last_traceback = tb - tbinfo = self.tbHandler.text(et,ev,tb) - # Construct a meaningful traceback message for shipping over the - # wire. - buf = pprint.pformat(self.buffer) - try: - ename = et.__name__ - except: - ename = et - msg = """\ -%(ev)s -*************************************************************************** -An exception occurred in an IPython engine while executing user code. - -Current execution buffer (lines being run): -%(buf)s - -A full traceback from the actual engine: -%(tbinfo)s -*************************************************************************** - """ % locals() - self._last_value = msg - else: - if softspace(sys.stdout, 0): - print - - ################################################################## - # Methods that are a part of the official interface - # - # These methods should also be put in the - # kernel.coreservice.ICoreService interface. - # - # These methods must conform to certain restrictions that allow - # them to be exposed to various network protocols: - # - # - As much as possible, these methods must return types that can be - # serialized by PB, XML-RPC and SOAP. None is OK. - # - Every method must be thread safe. There are some locks provided - # for this purpose, but new, specialized locks can be added to the - # class. - ################################################################## - - # Methods for running code - - def exc_info(self): - """Return exception information much like sys.exc_info(). - - This method returns the same (etype,evalue,tb) tuple as sys.exc_info, - but from the last time that the engine had an exception fire.""" - - return self._last_type,self._last_value,self._last_traceback - - def execute(self, lines): - self._trapRunlines(lines) - if self._last_type is None: - return self.getCommand() - else: - raise self._last_type(self._last_value) - - # Methods for working with the namespace - - def put(self, key, value): - """Put value into locals namespace with name key. - - I have often called this push(), but in this case the - InteractiveConsole class already defines a push() method that - is different. - """ - - if not isinstance(key, str): - raise TypeError, "Objects must be keyed by strings." - self.update({key:value}) - - def get(self, key): - """Gets an item out of the self.locals dict by key. - - Raise NameError if the object doesn't exist. - - I have often called this pull(). I still like that better. - """ - - class NotDefined(object): - """A class to signify an objects that is not in the users ns.""" - pass - - if not isinstance(key, str): - raise TypeError, "Objects must be keyed by strings." - result = self.locals.get(key, NotDefined()) - if isinstance(result, NotDefined): - raise NameError('name %s is not defined' % key) - else: - return result - - - def update(self, dictOfData): - """Loads a dict of key value pairs into the self.locals namespace.""" - if not isinstance(dictOfData, dict): - raise TypeError, "update() takes a dict object." - #self._namespace_lock.acquire() - self.locals.update(dictOfData) - #self._namespace_lock.release() - - # Methods for getting stdout/stderr/stdin - - def reset(self): - """Reset the InteractiveShell.""" - - #self._command_lock.acquire() - self._stdin = [] - self._stdout = [] - self._stderr = [] - self.lastCommandIndex = -1 - #self._command_lock.release() - - #self._namespace_lock.acquire() - # preserve id, mpi objects - mpi = self.locals.get('mpi', None) - id = self.locals.get('id', None) - del self.locals - self.locals = {'mpi': mpi, 'id': id} - #self._namespace_lock.release() - - def getCommand(self,i=None): - """Get the stdin/stdout/stderr of command i.""" - - #self._command_lock.acquire() - - - if i is not None and not isinstance(i, int): - raise TypeError("Command index not an int: " + str(i)) - - if i in range(self.lastCommandIndex + 1): - inResult = self._stdin[i] - outResult = self._stdout[i] - errResult = self._stderr[i] - cmdNum = i - elif i is None and self.lastCommandIndex >= 0: - inResult = self._stdin[self.lastCommandIndex] - outResult = self._stdout[self.lastCommandIndex] - errResult = self._stderr[self.lastCommandIndex] - cmdNum = self.lastCommandIndex - else: - inResult = None - outResult = None - errResult = None - - #self._command_lock.release() - - if inResult is not None: - return dict(commandIndex=cmdNum, stdin=inResult, stdout=outResult, stderr=errResult) - else: - raise IndexError("Command with index %s does not exist" % str(i)) - - def getLastCommandIndex(self): - """Get the index of the last command.""" - #self._command_lock.acquire() - ind = self.lastCommandIndex - #self._command_lock.release() - return ind - diff --git a/IPython/kernel/core/tests/test_shell.py b/IPython/kernel/core/tests/test_shell.py deleted file mode 100644 index 87d7ee2..0000000 --- a/IPython/kernel/core/tests/test_shell.py +++ /dev/null @@ -1,67 +0,0 @@ -# encoding: utf-8 - -"""This file contains unittests for the shell.py module.""" - -__docformat__ = "restructuredtext en" - -#------------------------------------------------------------------------------- -# Copyright (C) 2008 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING, distributed as part of this software. -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# Imports -#------------------------------------------------------------------------------- - -import unittest -from IPython.kernel.core import shell - -resultKeys = ('commandIndex', 'stdin', 'stdout', 'stderr') - -class BasicShellTest(unittest.TestCase): - - def setUp(self): - self.s = shell.InteractiveShell() - - def testExecute(self): - commands = [(0,"a = 5","",""), - (1,"b = 10","",""), - (2,"c = a + b","",""), - (3,"print c","15\n",""), - (4,"import math","",""), - (5,"2.0*math.pi","6.2831853071795862\n","")] - for c in commands: - result = self.s.execute(c[1]) - self.assertEquals(result, dict(zip(resultKeys,c))) - - def testPutGet(self): - objs = [10,"hi there",1.2342354,{"p":(1,2)}] - for o in objs: - self.s.put("key",o) - value = self.s.get("key") - self.assertEquals(value,o) - self.assertRaises(TypeError, self.s.put,10) - self.assertRaises(TypeError, self.s.get,10) - self.s.reset() - self.assertRaises(NameError, self.s.get, 'a') - - def testUpdate(self): - d = {"a": 10, "b": 34.3434, "c": "hi there"} - self.s.update(d) - for k in d.keys(): - value = self.s.get(k) - self.assertEquals(value, d[k]) - self.assertRaises(TypeError, self.s.update, [1,2,2]) - - def testCommand(self): - self.assertRaises(IndexError,self.s.getCommand) - self.s.execute("a = 5") - self.assertEquals(self.s.getCommand(), dict(zip(resultKeys, (0,"a = 5","","")))) - self.assertEquals(self.s.getCommand(0), dict(zip(resultKeys, (0,"a = 5","","")))) - self.s.reset() - self.assertEquals(self.s.getLastCommandIndex(),-1) - self.assertRaises(IndexError,self.s.getCommand) - - \ No newline at end of file diff --git a/IPython/kernel/scripts/ipcluster.py b/IPython/kernel/scripts/ipcluster.py old mode 100755 new mode 100644 diff --git a/IPython/kernel/scripts/ipcontroller.py b/IPython/kernel/scripts/ipcontroller.py old mode 100755 new mode 100644 diff --git a/IPython/kernel/scripts/ipengine.py b/IPython/kernel/scripts/ipengine.py old mode 100755 new mode 100644 diff --git a/IPython/kernel/tests/multienginetest.py b/IPython/kernel/tests/multienginetest.py index 914c4a8..39fa2c0 100644 --- a/IPython/kernel/tests/multienginetest.py +++ b/IPython/kernel/tests/multienginetest.py @@ -20,7 +20,6 @@ from twisted.internet import defer from IPython.kernel import engineservice as es from IPython.kernel import multiengine as me from IPython.kernel import newserialized -from IPython.kernel.error import NotDefined from IPython.testing import util from IPython.testing.parametric import parametric, Parametric from IPython.kernel import newserialized diff --git a/IPython/kernel/tests/test_controllerservice.py b/IPython/kernel/tests/test_controllerservice.py index 58e27f2..21f30b3 100644 --- a/IPython/kernel/tests/test_controllerservice.py +++ b/IPython/kernel/tests/test_controllerservice.py @@ -30,14 +30,15 @@ try: from controllertest import IControllerCoreTestCase from IPython.testing.util import DeferredTestCase except ImportError: - pass -else: - class BasicControllerServiceTest(DeferredTestCase, - IControllerCoreTestCase): - - def setUp(self): - self.controller = ControllerService() - self.controller.startService() - - def tearDown(self): - self.controller.stopService() + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") + +class BasicControllerServiceTest(DeferredTestCase, + IControllerCoreTestCase): + + def setUp(self): + self.controller = ControllerService() + self.controller.startService() + + def tearDown(self): + self.controller.stopService() diff --git a/IPython/kernel/tests/test_enginefc.py b/IPython/kernel/tests/test_enginefc.py index 7f482cf..b8d0caf 100644 --- a/IPython/kernel/tests/test_enginefc.py +++ b/IPython/kernel/tests/test_enginefc.py @@ -37,56 +37,57 @@ try: IEngineSerializedTestCase, \ IEngineQueuedTestCase except ImportError: - print "we got an error!!!" - raise -else: - class EngineFCTest(DeferredTestCase, - IEngineCoreTestCase, - IEngineSerializedTestCase, - IEngineQueuedTestCase - ): - - zi.implements(IControllerBase) - - def setUp(self): - - # Start a server and append to self.servers - self.controller_reference = FCRemoteEngineRefFromService(self) - self.controller_tub = Tub() - self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1') - self.controller_tub.setLocation('127.0.0.1:10105') - - furl = self.controller_tub.registerReference(self.controller_reference) - self.controller_tub.startService() - - # Start an EngineService and append to services/client - self.engine_service = es.EngineService() - self.engine_service.startService() - self.engine_tub = Tub() - self.engine_tub.startService() - engine_connector = EngineConnector(self.engine_tub) - d = engine_connector.connect_to_controller(self.engine_service, furl) - # This deferred doesn't fire until after register_engine has returned and - # thus, self.engine has been defined and the tets can proceed. - return d - - def tearDown(self): - dlist = [] - # Shut down the engine - d = self.engine_tub.stopService() - dlist.append(d) - # Shut down the controller - d = self.controller_tub.stopService() - dlist.append(d) - return defer.DeferredList(dlist) - - #--------------------------------------------------------------------------- - # Make me look like a basic controller - #--------------------------------------------------------------------------- - - def register_engine(self, engine_ref, id=None, ip=None, port=None, pid=None): - self.engine = IEngineQueued(IEngineBase(engine_ref)) - return {'id':id} - - def unregister_engine(self, id): - pass \ No newline at end of file + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") + + +class EngineFCTest(DeferredTestCase, + IEngineCoreTestCase, + IEngineSerializedTestCase, + IEngineQueuedTestCase + ): + + zi.implements(IControllerBase) + + def setUp(self): + + # Start a server and append to self.servers + self.controller_reference = FCRemoteEngineRefFromService(self) + self.controller_tub = Tub() + self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1') + self.controller_tub.setLocation('127.0.0.1:10105') + + furl = self.controller_tub.registerReference(self.controller_reference) + self.controller_tub.startService() + + # Start an EngineService and append to services/client + self.engine_service = es.EngineService() + self.engine_service.startService() + self.engine_tub = Tub() + self.engine_tub.startService() + engine_connector = EngineConnector(self.engine_tub) + d = engine_connector.connect_to_controller(self.engine_service, furl) + # This deferred doesn't fire until after register_engine has returned and + # thus, self.engine has been defined and the tets can proceed. + return d + + def tearDown(self): + dlist = [] + # Shut down the engine + d = self.engine_tub.stopService() + dlist.append(d) + # Shut down the controller + d = self.controller_tub.stopService() + dlist.append(d) + return defer.DeferredList(dlist) + + #--------------------------------------------------------------------------- + # Make me look like a basic controller + #--------------------------------------------------------------------------- + + def register_engine(self, engine_ref, id=None, ip=None, port=None, pid=None): + self.engine = IEngineQueued(IEngineBase(engine_ref)) + return {'id':id} + + def unregister_engine(self, id): + pass \ No newline at end of file diff --git a/IPython/kernel/tests/test_engineservice.py b/IPython/kernel/tests/test_engineservice.py index 15c80a4..22a47eb 100644 --- a/IPython/kernel/tests/test_engineservice.py +++ b/IPython/kernel/tests/test_engineservice.py @@ -35,44 +35,46 @@ try: IEngineQueuedTestCase, \ IEnginePropertiesTestCase except ImportError: - pass -else: - class BasicEngineServiceTest(DeferredTestCase, - IEngineCoreTestCase, - IEngineSerializedTestCase, - IEnginePropertiesTestCase): - - def setUp(self): - self.engine = es.EngineService() - self.engine.startService() - - def tearDown(self): - return self.engine.stopService() - - class ThreadedEngineServiceTest(DeferredTestCase, - IEngineCoreTestCase, - IEngineSerializedTestCase, - IEnginePropertiesTestCase): - - def setUp(self): - self.engine = es.ThreadedEngineService() - self.engine.startService() + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") + + +class BasicEngineServiceTest(DeferredTestCase, + IEngineCoreTestCase, + IEngineSerializedTestCase, + IEnginePropertiesTestCase): + + def setUp(self): + self.engine = es.EngineService() + self.engine.startService() + + def tearDown(self): + return self.engine.stopService() + +class ThreadedEngineServiceTest(DeferredTestCase, + IEngineCoreTestCase, + IEngineSerializedTestCase, + IEnginePropertiesTestCase): + + def setUp(self): + self.engine = es.ThreadedEngineService() + self.engine.startService() + + def tearDown(self): + return self.engine.stopService() + +class QueuedEngineServiceTest(DeferredTestCase, + IEngineCoreTestCase, + IEngineSerializedTestCase, + IEnginePropertiesTestCase, + IEngineQueuedTestCase): + + def setUp(self): + self.rawEngine = es.EngineService() + self.rawEngine.startService() + self.engine = es.IEngineQueued(self.rawEngine) - def tearDown(self): - return self.engine.stopService() - - class QueuedEngineServiceTest(DeferredTestCase, - IEngineCoreTestCase, - IEngineSerializedTestCase, - IEnginePropertiesTestCase, - IEngineQueuedTestCase): - - def setUp(self): - self.rawEngine = es.EngineService() - self.rawEngine.startService() - self.engine = es.IEngineQueued(self.rawEngine) - - def tearDown(self): - return self.rawEngine.stopService() - - + def tearDown(self): + return self.rawEngine.stopService() + + diff --git a/IPython/kernel/tests/test_multiengine.py b/IPython/kernel/tests/test_multiengine.py index 97510f2..82bf41b 100644 --- a/IPython/kernel/tests/test_multiengine.py +++ b/IPython/kernel/tests/test_multiengine.py @@ -23,32 +23,34 @@ try: from IPython.kernel.tests.multienginetest import (IMultiEngineTestCase, ISynchronousMultiEngineTestCase) except ImportError: - pass -else: - class BasicMultiEngineTestCase(DeferredTestCase, IMultiEngineTestCase): + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") + + +class BasicMultiEngineTestCase(DeferredTestCase, IMultiEngineTestCase): + + def setUp(self): + self.controller = ControllerService() + self.controller.startService() + self.multiengine = me.IMultiEngine(self.controller) + self.engines = [] - def setUp(self): - self.controller = ControllerService() - self.controller.startService() - self.multiengine = me.IMultiEngine(self.controller) - self.engines = [] - - def tearDown(self): - self.controller.stopService() - for e in self.engines: - e.stopService() - - - class SynchronousMultiEngineTestCase(DeferredTestCase, ISynchronousMultiEngineTestCase): + def tearDown(self): + self.controller.stopService() + for e in self.engines: + e.stopService() + + +class SynchronousMultiEngineTestCase(DeferredTestCase, ISynchronousMultiEngineTestCase): + + def setUp(self): + self.controller = ControllerService() + self.controller.startService() + self.multiengine = me.ISynchronousMultiEngine(me.IMultiEngine(self.controller)) + self.engines = [] - def setUp(self): - self.controller = ControllerService() - self.controller.startService() - self.multiengine = me.ISynchronousMultiEngine(me.IMultiEngine(self.controller)) - self.engines = [] - - def tearDown(self): - self.controller.stopService() - for e in self.engines: - e.stopService() + def tearDown(self): + self.controller.stopService() + for e in self.engines: + e.stopService() diff --git a/IPython/kernel/tests/test_multienginefc.py b/IPython/kernel/tests/test_multienginefc.py index f390992..de24c4c 100644 --- a/IPython/kernel/tests/test_multienginefc.py +++ b/IPython/kernel/tests/test_multienginefc.py @@ -30,115 +30,115 @@ try: from IPython.kernel.error import CompositeError from IPython.kernel.util import printer except ImportError: - pass -else: + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") - def _raise_it(f): - try: - f.raiseException() - except CompositeError, e: - e.raise_exception() +def _raise_it(f): + try: + f.raiseException() + except CompositeError, e: + e.raise_exception() + + +class FullSynchronousMultiEngineTestCase(DeferredTestCase, IFullSynchronousMultiEngineTestCase): + + def setUp(self): + self.engines = [] + + self.controller = ControllerService() + self.controller.startService() + self.imultiengine = IMultiEngine(self.controller) + self.mec_referenceable = IFCSynchronousMultiEngine(self.imultiengine) + + self.controller_tub = Tub() + self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1') + self.controller_tub.setLocation('127.0.0.1:10105') - class FullSynchronousMultiEngineTestCase(DeferredTestCase, IFullSynchronousMultiEngineTestCase): + furl = self.controller_tub.registerReference(self.mec_referenceable) + self.controller_tub.startService() - def setUp(self): - - self.engines = [] - - self.controller = ControllerService() - self.controller.startService() - self.imultiengine = IMultiEngine(self.controller) - self.mec_referenceable = IFCSynchronousMultiEngine(self.imultiengine) - - self.controller_tub = Tub() - self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1') - self.controller_tub.setLocation('127.0.0.1:10105') - - furl = self.controller_tub.registerReference(self.mec_referenceable) - self.controller_tub.startService() - - self.client_tub = ClientConnector() - d = self.client_tub.get_multiengine_client(furl) - d.addCallback(self.handle_got_client) - return d - - def handle_got_client(self, client): - self.multiengine = client + self.client_tub = ClientConnector() + d = self.client_tub.get_multiengine_client(furl) + d.addCallback(self.handle_got_client) + return d - def tearDown(self): - dlist = [] - # Shut down the multiengine client - d = self.client_tub.tub.stopService() - dlist.append(d) - # Shut down the engines - for e in self.engines: - e.stopService() - # Shut down the controller - d = self.controller_tub.stopService() - d.addBoth(lambda _: self.controller.stopService()) - dlist.append(d) - return defer.DeferredList(dlist) + def handle_got_client(self, client): + self.multiengine = client + + def tearDown(self): + dlist = [] + # Shut down the multiengine client + d = self.client_tub.tub.stopService() + dlist.append(d) + # Shut down the engines + for e in self.engines: + e.stopService() + # Shut down the controller + d = self.controller_tub.stopService() + d.addBoth(lambda _: self.controller.stopService()) + dlist.append(d) + return defer.DeferredList(dlist) - def test_mapper(self): - self.addEngine(4) - m = self.multiengine.mapper() - self.assertEquals(m.multiengine,self.multiengine) - self.assertEquals(m.dist,'b') - self.assertEquals(m.targets,'all') - self.assertEquals(m.block,True) - - def test_map_default(self): - self.addEngine(4) - m = self.multiengine.mapper() - d = m.map(lambda x: 2*x, range(10)) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - d.addCallback(lambda _: self.multiengine.map(lambda x: 2*x, range(10))) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - return d - - def test_map_noblock(self): - self.addEngine(4) - m = self.multiengine.mapper(block=False) - d = m.map(lambda x: 2*x, range(10)) - d.addCallback(lambda did: self.multiengine.get_pending_deferred(did, True)) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - return d - - def test_mapper_fail(self): - self.addEngine(4) - m = self.multiengine.mapper() - d = m.map(lambda x: 1/0, range(10)) - d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) - return d - - def test_parallel(self): - self.addEngine(4) - p = self.multiengine.parallel() - self.assert_(isinstance(p, ParallelFunction)) - @p - def f(x): return 2*x - d = f(range(10)) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - return d - - def test_parallel_noblock(self): - self.addEngine(1) - p = self.multiengine.parallel(block=False) - self.assert_(isinstance(p, ParallelFunction)) - @p - def f(x): return 2*x - d = f(range(10)) - d.addCallback(lambda did: self.multiengine.get_pending_deferred(did, True)) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - return d - - def test_parallel_fail(self): - self.addEngine(4) - p = self.multiengine.parallel() - self.assert_(isinstance(p, ParallelFunction)) - @p - def f(x): return 1/0 - d = f(range(10)) - d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) - return d \ No newline at end of file + def test_mapper(self): + self.addEngine(4) + m = self.multiengine.mapper() + self.assertEquals(m.multiengine,self.multiengine) + self.assertEquals(m.dist,'b') + self.assertEquals(m.targets,'all') + self.assertEquals(m.block,True) + + def test_map_default(self): + self.addEngine(4) + m = self.multiengine.mapper() + d = m.map(lambda x: 2*x, range(10)) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + d.addCallback(lambda _: self.multiengine.map(lambda x: 2*x, range(10))) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + return d + + def test_map_noblock(self): + self.addEngine(4) + m = self.multiengine.mapper(block=False) + d = m.map(lambda x: 2*x, range(10)) + d.addCallback(lambda did: self.multiengine.get_pending_deferred(did, True)) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + return d + + def test_mapper_fail(self): + self.addEngine(4) + m = self.multiengine.mapper() + d = m.map(lambda x: 1/0, range(10)) + d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) + return d + + def test_parallel(self): + self.addEngine(4) + p = self.multiengine.parallel() + self.assert_(isinstance(p, ParallelFunction)) + @p + def f(x): return 2*x + d = f(range(10)) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + return d + + def test_parallel_noblock(self): + self.addEngine(1) + p = self.multiengine.parallel(block=False) + self.assert_(isinstance(p, ParallelFunction)) + @p + def f(x): return 2*x + d = f(range(10)) + d.addCallback(lambda did: self.multiengine.get_pending_deferred(did, True)) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + return d + + def test_parallel_fail(self): + self.addEngine(4) + p = self.multiengine.parallel() + self.assert_(isinstance(p, ParallelFunction)) + @p + def f(x): return 1/0 + d = f(range(10)) + d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) + return d \ No newline at end of file diff --git a/IPython/kernel/tests/test_newserialized.py b/IPython/kernel/tests/test_newserialized.py index 09de5a6..747b694 100644 --- a/IPython/kernel/tests/test_newserialized.py +++ b/IPython/kernel/tests/test_newserialized.py @@ -28,75 +28,75 @@ try: SerializeIt, \ UnSerializeIt except ImportError: - pass -else: - #------------------------------------------------------------------------------- - # Tests - #------------------------------------------------------------------------------- + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") + +#------------------------------------------------------------------------------- +# Tests +#------------------------------------------------------------------------------- + +class SerializedTestCase(unittest.TestCase): + + def setUp(self): + pass - class SerializedTestCase(unittest.TestCase): + def tearDown(self): + pass - def setUp(self): - pass - - def tearDown(self): - pass - - def testSerializedInterfaces(self): + def testSerializedInterfaces(self): - us = UnSerialized({'a':10, 'b':range(10)}) - s = ISerialized(us) - uss = IUnSerialized(s) - self.assert_(ISerialized.providedBy(s)) - self.assert_(IUnSerialized.providedBy(us)) - self.assert_(IUnSerialized.providedBy(uss)) - for m in list(ISerialized): - self.assert_(hasattr(s, m)) - for m in list(IUnSerialized): - self.assert_(hasattr(us, m)) - for m in list(IUnSerialized): - self.assert_(hasattr(uss, m)) + us = UnSerialized({'a':10, 'b':range(10)}) + s = ISerialized(us) + uss = IUnSerialized(s) + self.assert_(ISerialized.providedBy(s)) + self.assert_(IUnSerialized.providedBy(us)) + self.assert_(IUnSerialized.providedBy(uss)) + for m in list(ISerialized): + self.assert_(hasattr(s, m)) + for m in list(IUnSerialized): + self.assert_(hasattr(us, m)) + for m in list(IUnSerialized): + self.assert_(hasattr(uss, m)) - def testPickleSerialized(self): - obj = {'a':1.45345, 'b':'asdfsdf', 'c':10000L} - original = UnSerialized(obj) - originalSer = ISerialized(original) - firstData = originalSer.getData() - firstTD = originalSer.getTypeDescriptor() - firstMD = originalSer.getMetadata() - self.assert_(firstTD == 'pickle') - self.assert_(firstMD == {}) - unSerialized = IUnSerialized(originalSer) - secondObj = unSerialized.getObject() - for k, v in secondObj.iteritems(): - self.assert_(obj[k] == v) - secondSer = ISerialized(UnSerialized(secondObj)) - self.assert_(firstData == secondSer.getData()) - self.assert_(firstTD == secondSer.getTypeDescriptor() ) - self.assert_(firstMD == secondSer.getMetadata()) + def testPickleSerialized(self): + obj = {'a':1.45345, 'b':'asdfsdf', 'c':10000L} + original = UnSerialized(obj) + originalSer = ISerialized(original) + firstData = originalSer.getData() + firstTD = originalSer.getTypeDescriptor() + firstMD = originalSer.getMetadata() + self.assert_(firstTD == 'pickle') + self.assert_(firstMD == {}) + unSerialized = IUnSerialized(originalSer) + secondObj = unSerialized.getObject() + for k, v in secondObj.iteritems(): + self.assert_(obj[k] == v) + secondSer = ISerialized(UnSerialized(secondObj)) + self.assert_(firstData == secondSer.getData()) + self.assert_(firstTD == secondSer.getTypeDescriptor() ) + self.assert_(firstMD == secondSer.getMetadata()) + + def testNDArraySerialized(self): + try: + import numpy + except ImportError: + pass + else: + a = numpy.linspace(0.0, 1.0, 1000) + unSer1 = UnSerialized(a) + ser1 = ISerialized(unSer1) + td = ser1.getTypeDescriptor() + self.assert_(td == 'ndarray') + md = ser1.getMetadata() + self.assert_(md['shape'] == a.shape) + self.assert_(md['dtype'] == a.dtype.str) + buff = ser1.getData() + self.assert_(buff == numpy.getbuffer(a)) + s = Serialized(buff, td, md) + us = IUnSerialized(s) + final = us.getObject() + self.assert_(numpy.getbuffer(a) == numpy.getbuffer(final)) + self.assert_(a.dtype.str == final.dtype.str) + self.assert_(a.shape == final.shape) + - def testNDArraySerialized(self): - try: - import numpy - except ImportError: - pass - else: - a = numpy.linspace(0.0, 1.0, 1000) - unSer1 = UnSerialized(a) - ser1 = ISerialized(unSer1) - td = ser1.getTypeDescriptor() - self.assert_(td == 'ndarray') - md = ser1.getMetadata() - self.assert_(md['shape'] == a.shape) - self.assert_(md['dtype'] == a.dtype.str) - buff = ser1.getData() - self.assert_(buff == numpy.getbuffer(a)) - s = Serialized(buff, td, md) - us = IUnSerialized(s) - final = us.getObject() - self.assert_(numpy.getbuffer(a) == numpy.getbuffer(final)) - self.assert_(a.dtype.str == final.dtype.str) - self.assert_(a.shape == final.shape) - - - \ No newline at end of file diff --git a/IPython/kernel/tests/test_pendingdeferred.py b/IPython/kernel/tests/test_pendingdeferred.py index 2ac9bda..73d3b84 100644 --- a/IPython/kernel/tests/test_pendingdeferred.py +++ b/IPython/kernel/tests/test_pendingdeferred.py @@ -25,162 +25,162 @@ try: from IPython.kernel import error from IPython.kernel.util import printer except ImportError: - pass -else: + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") - class Foo(object): - - def bar(self, bahz): - return defer.succeed('blahblah: %s' % bahz) +class Foo(object): - class TwoPhaseFoo(pd.PendingDeferredManager): - - def __init__(self, foo): - self.foo = foo - pd.PendingDeferredManager.__init__(self) + def bar(self, bahz): + return defer.succeed('blahblah: %s' % bahz) - @pd.two_phase - def bar(self, bahz): - return self.foo.bar(bahz) +class TwoPhaseFoo(pd.PendingDeferredManager): - class PendingDeferredManagerTest(DeferredTestCase): - - def setUp(self): - self.pdm = pd.PendingDeferredManager() - - def tearDown(self): - pass - - def testBasic(self): - dDict = {} - # Create 10 deferreds and save them - for i in range(10): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - dDict[did] = d - # Make sure they are begin saved - for k in dDict.keys(): - self.assert_(self.pdm.quick_has_id(k)) - # Get the pending deferred (block=True), then callback with 'foo' and compare - for did in dDict.keys()[0:5]: - d = self.pdm.get_pending_deferred(did,block=True) - dDict[did].callback('foo') - d.addCallback(lambda r: self.assert_(r=='foo')) - # Get the pending deferreds with (block=False) and make sure ResultNotCompleted is raised - for did in dDict.keys()[5:10]: - d = self.pdm.get_pending_deferred(did,block=False) - d.addErrback(lambda f: self.assertRaises(error.ResultNotCompleted, f.raiseException)) - # Now callback the last 5, get them and compare. - for did in dDict.keys()[5:10]: - dDict[did].callback('foo') - d = self.pdm.get_pending_deferred(did,block=False) - d.addCallback(lambda r: self.assert_(r=='foo')) - - def test_save_then_delete(self): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - self.assert_(self.pdm.quick_has_id(did)) - self.pdm.delete_pending_deferred(did) - self.assert_(not self.pdm.quick_has_id(did)) - - def test_save_get_delete(self): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d2.addErrback(lambda f: self.assertRaises(error.AbortedPendingDeferredError, f.raiseException)) - self.pdm.delete_pending_deferred(did) - return d2 - - def test_double_get(self): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d3 = self.pdm.get_pending_deferred(did,True) - d3.addErrback(lambda f: self.assertRaises(error.InvalidDeferredID, f.raiseException)) - - def test_get_after_callback(self): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d.callback('foo') - d2 = self.pdm.get_pending_deferred(did,True) - d2.addCallback(lambda r: self.assertEquals(r,'foo')) - self.assert_(not self.pdm.quick_has_id(did)) + def __init__(self, foo): + self.foo = foo + pd.PendingDeferredManager.__init__(self) - def test_get_before_callback(self): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d.callback('foo') - d2.addCallback(lambda r: self.assertEquals(r,'foo')) - self.assert_(not self.pdm.quick_has_id(did)) - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d2.addCallback(lambda r: self.assertEquals(r,'foo')) - d.callback('foo') - self.assert_(not self.pdm.quick_has_id(did)) - - def test_get_after_errback(self): - class MyError(Exception): - pass - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d.errback(failure.Failure(MyError('foo'))) - d2 = self.pdm.get_pending_deferred(did,True) - d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) - self.assert_(not self.pdm.quick_has_id(did)) - - def test_get_before_errback(self): - class MyError(Exception): - pass - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d.errback(failure.Failure(MyError('foo'))) - d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) - self.assert_(not self.pdm.quick_has_id(did)) - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) - d.errback(failure.Failure(MyError('foo'))) - self.assert_(not self.pdm.quick_has_id(did)) - - def test_noresult_noblock(self): - d = defer.Deferred() - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,False) - d2.addErrback(lambda f: self.assertRaises(error.ResultNotCompleted, f.raiseException)) + @pd.two_phase + def bar(self, bahz): + return self.foo.bar(bahz) - def test_with_callbacks(self): - d = defer.Deferred() - d.addCallback(lambda r: r+' foo') - d.addCallback(lambda r: r+' bar') - did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d.callback('bam') - d2.addCallback(lambda r: self.assertEquals(r,'bam foo bar')) +class PendingDeferredManagerTest(DeferredTestCase): + + def setUp(self): + self.pdm = pd.PendingDeferredManager() - def test_with_errbacks(self): - class MyError(Exception): - pass + def tearDown(self): + pass + + def testBasic(self): + dDict = {} + # Create 10 deferreds and save them + for i in range(10): d = defer.Deferred() - d.addCallback(lambda r: 'foo') - d.addErrback(lambda f: 'caught error') did = self.pdm.save_pending_deferred(d) - d2 = self.pdm.get_pending_deferred(did,True) - d.errback(failure.Failure(MyError('bam'))) - d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) + dDict[did] = d + # Make sure they are begin saved + for k in dDict.keys(): + self.assert_(self.pdm.quick_has_id(k)) + # Get the pending deferred (block=True), then callback with 'foo' and compare + for did in dDict.keys()[0:5]: + d = self.pdm.get_pending_deferred(did,block=True) + dDict[did].callback('foo') + d.addCallback(lambda r: self.assert_(r=='foo')) + # Get the pending deferreds with (block=False) and make sure ResultNotCompleted is raised + for did in dDict.keys()[5:10]: + d = self.pdm.get_pending_deferred(did,block=False) + d.addErrback(lambda f: self.assertRaises(error.ResultNotCompleted, f.raiseException)) + # Now callback the last 5, get them and compare. + for did in dDict.keys()[5:10]: + dDict[did].callback('foo') + d = self.pdm.get_pending_deferred(did,block=False) + d.addCallback(lambda r: self.assert_(r=='foo')) + + def test_save_then_delete(self): + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + self.assert_(self.pdm.quick_has_id(did)) + self.pdm.delete_pending_deferred(did) + self.assert_(not self.pdm.quick_has_id(did)) + + def test_save_get_delete(self): + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d2.addErrback(lambda f: self.assertRaises(error.AbortedPendingDeferredError, f.raiseException)) + self.pdm.delete_pending_deferred(did) + return d2 + + def test_double_get(self): + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d3 = self.pdm.get_pending_deferred(did,True) + d3.addErrback(lambda f: self.assertRaises(error.InvalidDeferredID, f.raiseException)) + + def test_get_after_callback(self): + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d.callback('foo') + d2 = self.pdm.get_pending_deferred(did,True) + d2.addCallback(lambda r: self.assertEquals(r,'foo')) + self.assert_(not self.pdm.quick_has_id(did)) + + def test_get_before_callback(self): + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d.callback('foo') + d2.addCallback(lambda r: self.assertEquals(r,'foo')) + self.assert_(not self.pdm.quick_has_id(did)) + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d2.addCallback(lambda r: self.assertEquals(r,'foo')) + d.callback('foo') + self.assert_(not self.pdm.quick_has_id(did)) + + def test_get_after_errback(self): + class MyError(Exception): + pass + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d.errback(failure.Failure(MyError('foo'))) + d2 = self.pdm.get_pending_deferred(did,True) + d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) + self.assert_(not self.pdm.quick_has_id(did)) + + def test_get_before_errback(self): + class MyError(Exception): + pass + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d.errback(failure.Failure(MyError('foo'))) + d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) + self.assert_(not self.pdm.quick_has_id(did)) + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) + d.errback(failure.Failure(MyError('foo'))) + self.assert_(not self.pdm.quick_has_id(did)) - def test_nested_deferreds(self): - d = defer.Deferred() - d2 = defer.Deferred() - d.addCallback(lambda r: d2) - did = self.pdm.save_pending_deferred(d) - d.callback('foo') - d3 = self.pdm.get_pending_deferred(did,False) - d3.addErrback(lambda f: self.assertRaises(error.ResultNotCompleted, f.raiseException)) - d2.callback('bar') - d3 = self.pdm.get_pending_deferred(did,False) - d3.addCallback(lambda r: self.assertEquals(r,'bar')) + def test_noresult_noblock(self): + d = defer.Deferred() + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,False) + d2.addErrback(lambda f: self.assertRaises(error.ResultNotCompleted, f.raiseException)) + + def test_with_callbacks(self): + d = defer.Deferred() + d.addCallback(lambda r: r+' foo') + d.addCallback(lambda r: r+' bar') + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d.callback('bam') + d2.addCallback(lambda r: self.assertEquals(r,'bam foo bar')) + + def test_with_errbacks(self): + class MyError(Exception): + pass + d = defer.Deferred() + d.addCallback(lambda r: 'foo') + d.addErrback(lambda f: 'caught error') + did = self.pdm.save_pending_deferred(d) + d2 = self.pdm.get_pending_deferred(did,True) + d.errback(failure.Failure(MyError('bam'))) + d2.addErrback(lambda f: self.assertRaises(MyError, f.raiseException)) + + def test_nested_deferreds(self): + d = defer.Deferred() + d2 = defer.Deferred() + d.addCallback(lambda r: d2) + did = self.pdm.save_pending_deferred(d) + d.callback('foo') + d3 = self.pdm.get_pending_deferred(did,False) + d3.addErrback(lambda f: self.assertRaises(error.ResultNotCompleted, f.raiseException)) + d2.callback('bar') + d3 = self.pdm.get_pending_deferred(did,False) + d3.addCallback(lambda r: self.assertEquals(r,'bar')) diff --git a/IPython/kernel/tests/test_task.py b/IPython/kernel/tests/test_task.py index f957504..face815 100644 --- a/IPython/kernel/tests/test_task.py +++ b/IPython/kernel/tests/test_task.py @@ -26,25 +26,26 @@ try: from IPython.testing.util import DeferredTestCase from IPython.kernel.tests.tasktest import ITaskControllerTestCase except ImportError: - pass -else: - #------------------------------------------------------------------------------- - # Tests - #------------------------------------------------------------------------------- + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") - class BasicTaskControllerTestCase(DeferredTestCase, ITaskControllerTestCase): +#------------------------------------------------------------------------------- +# Tests +#------------------------------------------------------------------------------- + +class BasicTaskControllerTestCase(DeferredTestCase, ITaskControllerTestCase): + + def setUp(self): + self.controller = cs.ControllerService() + self.controller.startService() + self.multiengine = IMultiEngine(self.controller) + self.tc = task.ITaskController(self.controller) + self.tc.failurePenalty = 0 + self.engines=[] - def setUp(self): - self.controller = cs.ControllerService() - self.controller.startService() - self.multiengine = IMultiEngine(self.controller) - self.tc = task.ITaskController(self.controller) - self.tc.failurePenalty = 0 - self.engines=[] - - def tearDown(self): - self.controller.stopService() - for e in self.engines: - e.stopService() + def tearDown(self): + self.controller.stopService() + for e in self.engines: + e.stopService() diff --git a/IPython/kernel/tests/test_taskfc.py b/IPython/kernel/tests/test_taskfc.py index e2b4122..266c7fa 100644 --- a/IPython/kernel/tests/test_taskfc.py +++ b/IPython/kernel/tests/test_taskfc.py @@ -33,129 +33,130 @@ try: from IPython.kernel.error import CompositeError from IPython.kernel.parallelfunction import ParallelFunction except ImportError: - pass -else: + import nose + raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap") - #------------------------------------------------------------------------------- - # Tests - #------------------------------------------------------------------------------- - def _raise_it(f): - try: - f.raiseException() - except CompositeError, e: - e.raise_exception() +#------------------------------------------------------------------------------- +# Tests +#------------------------------------------------------------------------------- - class TaskTest(DeferredTestCase, ITaskControllerTestCase): +def _raise_it(f): + try: + f.raiseException() + except CompositeError, e: + e.raise_exception() - def setUp(self): - - self.engines = [] - - self.controller = cs.ControllerService() - self.controller.startService() - self.imultiengine = me.IMultiEngine(self.controller) - self.itc = taskmodule.ITaskController(self.controller) - self.itc.failurePenalty = 0 - - self.mec_referenceable = IFCSynchronousMultiEngine(self.imultiengine) - self.tc_referenceable = IFCTaskController(self.itc) - - self.controller_tub = Tub() - self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1') - self.controller_tub.setLocation('127.0.0.1:10105') - - mec_furl = self.controller_tub.registerReference(self.mec_referenceable) - tc_furl = self.controller_tub.registerReference(self.tc_referenceable) - self.controller_tub.startService() - - self.client_tub = ClientConnector() - d = self.client_tub.get_multiengine_client(mec_furl) - d.addCallback(self.handle_mec_client) - d.addCallback(lambda _: self.client_tub.get_task_client(tc_furl)) - d.addCallback(self.handle_tc_client) - return d - - def handle_mec_client(self, client): - self.multiengine = client +class TaskTest(DeferredTestCase, ITaskControllerTestCase): + + def setUp(self): + + self.engines = [] + + self.controller = cs.ControllerService() + self.controller.startService() + self.imultiengine = me.IMultiEngine(self.controller) + self.itc = taskmodule.ITaskController(self.controller) + self.itc.failurePenalty = 0 + + self.mec_referenceable = IFCSynchronousMultiEngine(self.imultiengine) + self.tc_referenceable = IFCTaskController(self.itc) + + self.controller_tub = Tub() + self.controller_tub.listenOn('tcp:10105:interface=127.0.0.1') + self.controller_tub.setLocation('127.0.0.1:10105') + + mec_furl = self.controller_tub.registerReference(self.mec_referenceable) + tc_furl = self.controller_tub.registerReference(self.tc_referenceable) + self.controller_tub.startService() + + self.client_tub = ClientConnector() + d = self.client_tub.get_multiengine_client(mec_furl) + d.addCallback(self.handle_mec_client) + d.addCallback(lambda _: self.client_tub.get_task_client(tc_furl)) + d.addCallback(self.handle_tc_client) + return d + + def handle_mec_client(self, client): + self.multiengine = client + + def handle_tc_client(self, client): + self.tc = client + + def tearDown(self): + dlist = [] + # Shut down the multiengine client + d = self.client_tub.tub.stopService() + dlist.append(d) + # Shut down the engines + for e in self.engines: + e.stopService() + # Shut down the controller + d = self.controller_tub.stopService() + d.addBoth(lambda _: self.controller.stopService()) + dlist.append(d) + return defer.DeferredList(dlist) + + def test_mapper(self): + self.addEngine(1) + m = self.tc.mapper() + self.assertEquals(m.task_controller,self.tc) + self.assertEquals(m.clear_before,False) + self.assertEquals(m.clear_after,False) + self.assertEquals(m.retries,0) + self.assertEquals(m.recovery_task,None) + self.assertEquals(m.depend,None) + self.assertEquals(m.block,True) + + def test_map_default(self): + self.addEngine(1) + m = self.tc.mapper() + d = m.map(lambda x: 2*x, range(10)) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + d.addCallback(lambda _: self.tc.map(lambda x: 2*x, range(10))) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + return d + + def test_map_noblock(self): + self.addEngine(1) + m = self.tc.mapper(block=False) + d = m.map(lambda x: 2*x, range(10)) + d.addCallback(lambda r: self.assertEquals(r,[x for x in range(10)])) + return d + + def test_mapper_fail(self): + self.addEngine(1) + m = self.tc.mapper() + d = m.map(lambda x: 1/0, range(10)) + d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) + return d + + def test_parallel(self): + self.addEngine(1) + p = self.tc.parallel() + self.assert_(isinstance(p, ParallelFunction)) + @p + def f(x): return 2*x + d = f(range(10)) + d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) + return d - def handle_tc_client(self, client): - self.tc = client + def test_parallel_noblock(self): + self.addEngine(1) + p = self.tc.parallel(block=False) + self.assert_(isinstance(p, ParallelFunction)) + @p + def f(x): return 2*x + d = f(range(10)) + d.addCallback(lambda r: self.assertEquals(r,[x for x in range(10)])) + return d - def tearDown(self): - dlist = [] - # Shut down the multiengine client - d = self.client_tub.tub.stopService() - dlist.append(d) - # Shut down the engines - for e in self.engines: - e.stopService() - # Shut down the controller - d = self.controller_tub.stopService() - d.addBoth(lambda _: self.controller.stopService()) - dlist.append(d) - return defer.DeferredList(dlist) - - def test_mapper(self): - self.addEngine(1) - m = self.tc.mapper() - self.assertEquals(m.task_controller,self.tc) - self.assertEquals(m.clear_before,False) - self.assertEquals(m.clear_after,False) - self.assertEquals(m.retries,0) - self.assertEquals(m.recovery_task,None) - self.assertEquals(m.depend,None) - self.assertEquals(m.block,True) - - def test_map_default(self): - self.addEngine(1) - m = self.tc.mapper() - d = m.map(lambda x: 2*x, range(10)) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - d.addCallback(lambda _: self.tc.map(lambda x: 2*x, range(10))) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - return d - - def test_map_noblock(self): - self.addEngine(1) - m = self.tc.mapper(block=False) - d = m.map(lambda x: 2*x, range(10)) - d.addCallback(lambda r: self.assertEquals(r,[x for x in range(10)])) - return d - - def test_mapper_fail(self): - self.addEngine(1) - m = self.tc.mapper() - d = m.map(lambda x: 1/0, range(10)) - d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) - return d - - def test_parallel(self): - self.addEngine(1) - p = self.tc.parallel() - self.assert_(isinstance(p, ParallelFunction)) - @p - def f(x): return 2*x - d = f(range(10)) - d.addCallback(lambda r: self.assertEquals(r,[2*x for x in range(10)])) - return d - - def test_parallel_noblock(self): - self.addEngine(1) - p = self.tc.parallel(block=False) - self.assert_(isinstance(p, ParallelFunction)) - @p - def f(x): return 2*x - d = f(range(10)) - d.addCallback(lambda r: self.assertEquals(r,[x for x in range(10)])) - return d - - def test_parallel_fail(self): - self.addEngine(1) - p = self.tc.parallel() - self.assert_(isinstance(p, ParallelFunction)) - @p - def f(x): return 1/0 - d = f(range(10)) - d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) - return d \ No newline at end of file + def test_parallel_fail(self): + self.addEngine(1) + p = self.tc.parallel() + self.assert_(isinstance(p, ParallelFunction)) + @p + def f(x): return 1/0 + d = f(range(10)) + d.addBoth(lambda f: self.assertRaises(ZeroDivisionError, _raise_it, f)) + return d \ No newline at end of file diff --git a/IPython/testing/mkdoctests.py b/IPython/testing/mkdoctests.py old mode 100755 new mode 100644 diff --git a/docs/source/development/development.txt b/docs/source/development/development.txt index 375ae23..e4bc727 100644 --- a/docs/source/development/development.txt +++ b/docs/source/development/development.txt @@ -93,28 +93,28 @@ Specific subpackages -------------------- ``core`` - This is the core functionality of IPython that is independent of the - terminal, network and GUIs. Most of the code that is in the current - IPython trunk will be refactored, cleaned up and moved here. + This is the core functionality of IPython that is independent of the + terminal, network and GUIs. Most of the code that is in the current + IPython trunk will be refactored, cleaned up and moved here. ``kernel`` - The enables the IPython core to be expose to a the network. This is - also where all of the parallel computing capabilities are to be found. - + The enables the IPython core to be expose to a the network. This is + also where all of the parallel computing capabilities are to be found. + ``config`` - The configuration package used by IPython. + The configuration package used by IPython. ``frontends`` - The various frontends for IPython. A frontend is the end-user application - that exposes the capabilities of IPython to the user. The most basic frontend - will simply be a terminal based application that looks just like today 's - IPython. Other frontends will likely be more powerful and based on GUI toolkits. + The various frontends for IPython. A frontend is the end-user application + that exposes the capabilities of IPython to the user. The most basic frontend + will simply be a terminal based application that looks just like today 's + IPython. Other frontends will likely be more powerful and based on GUI toolkits. ``notebook`` - An application that allows users to work with IPython notebooks. + An application that allows users to work with IPython notebooks. ``tools`` - This is where general utilities go. + This is where general utilities go. Version control @@ -125,17 +125,17 @@ to contribute code to IPython. Here is a sketch of how to use Bazaar for IPytho development. First, you should install Bazaar. After you have done that, make sure that it is working by getting the latest main branch of IPython:: - $ bzr branch lp:ipython + $ bzr branch lp:ipython Now you can create a new branch for you to do your work in:: - $ bzr branch ipython ipython-mybranch + $ bzr branch ipython ipython-mybranch The typical work cycle in this branch will be to make changes in `ipython-mybranch` and then commit those changes using the commit command:: - $ ...do work in ipython-mybranch... - $ bzr ci -m "the commit message goes here" + $ ...do work in ipython-mybranch... + $ bzr ci -m "the commit message goes here" Please note that since we now don't use an old-style linear ChangeLog (that tends to cause problems with distributed version control @@ -156,26 +156,26 @@ the project, and the `--short` log option becomes a nice summary. While working with this branch, it is a good idea to merge in changes that have been made upstream in the parent branch. This can be done by doing:: - $ bzr pull - + $ bzr pull + If this command shows that the branches have diverged, then you should do a merge instead:: - $ bzr merge lp:ipython + $ bzr merge lp:ipython If you want others to be able to see your branch, you can create an account with launchpad and push the branch to your own workspace:: - $ bzr push bzr+ssh://@bazaar.launchpad.net/~/+junk/ipython-mybranch + $ bzr push bzr+ssh://@bazaar.launchpad.net/~/+junk/ipython-mybranch Finally, once the work in your branch is done, you can merge your changes back into the `ipython` branch by using merge:: - $ cd ipython - $ merge ../ipython-mybranch - [resolve any conflicts] - $ bzr ci -m "Fixing that bug" - $ bzr push + $ cd ipython + $ merge ../ipython-mybranch + [resolve any conflicts] + $ bzr ci -m "Fixing that bug" + $ bzr push But this will require you to have write permissions to the `ipython` branch. It you don't you can tell one of the IPython devs about your branch and they can do the merge for you. @@ -349,6 +349,37 @@ IPython. The current prototype of ``tconfig`` is located in the IPython sandbox. .. _ConfigObj: http://www.voidspace.org.uk/python/configobj.html .. _Traits: http://code.enthought.com/traits/ +Installation and testing scenarios +================================== + +This section outlines the various scenarios that we need to test before we release an IPython version. These scenarios represent different ways of installing IPython and its dependencies. + +Installation scenarios +---------------------- + + 1. Install from tarball using `python setup.py install`. + a. With only readline+nose dependencies installed. + b. With all dependencies installed (readline, zope.interface, + Twisted, foolscap, Sphinx, nose, pyOpenSSL). + 2. Install using easy_install. + a. With only readline+nose dependencies installed. + i. Default dependencies: `easy_install ipython-0.9.beta3-py2.5.egg` + ii. Optional dependency sets: `easy_install -f ipython-0.9.beta3-py2.5.egg IPython[kernel,doc,test,security]` + b. With all dependencies already installed. + + +Tests to run for these scenarios +-------------------------------- + + 1. Run the full test suite. + 2. Start a controller and engines and try a few things by hand. + a. Using ipcluster. + b. Using ipcontroller/ipengine by hand. + 3. Run a few of the parallel examples. + 4. Try the kernel with and without security with and without PyOpenSSL + installed. + 5. Beat on the IPython terminal a bunch. + 6. Make sure that furl files are being put in proper locations. diff --git a/docs/source/install/basic.txt b/docs/source/install/basic.txt index fbf2f3a..bf3298e 100644 --- a/docs/source/install/basic.txt +++ b/docs/source/install/basic.txt @@ -68,29 +68,25 @@ Mac OSX information ------------------- Under OSX, there is a choice you need to make. Apple ships its own build -of Python, which lives in the core OSX filesystem hierarchy. You can +of Python, which lives in the core OSX filesystem hierarchy (/System/Library/Frameworks/Python.framework). You can also manually install a separate Python, either purely by hand -(typically in /usr/local) or by using Fink, which puts everything under -/sw. Which route to follow is a matter of personal preference, as I've -seen users who favor each of the approaches. Here I will simply list the -known installation issues under OSX, along with their solutions. +(typically in /usr/local), by using Fink or DarwinPorts, which put everything under /sw or /opt respectively, or using the python.org "Framework" python, which installs a framework similar to the system python in /Library/Frameworks. The Enthought Python Distribution (http://www.enthought.com/products/epd.php), uses the python.org "Framework" python and thus also installs into /Library/Frameworks. Which route to follow is a matter of personal preference, as I've seen users who favor each of the approaches. + +For users of OS X 10.5 (Leopard), the system python installation contains support for `DTrace`_, a kernel-level profiling system integrated into OS X 10.5. This facility provides significant advantage to developers and users interested in high-performance computing by using the system python. + +.. _DTrace: http://www.apple.com/macosx/technology/unix.html + +IPython is known to work with all the above installation options. As such, we do not endorse one choice over the others. Here we will simply list the known installation issues under OSX, along with their solutions. This page: http://geosci.uchicago.edu/~tobis/pylab.html contains information on this topic, with additional details on how to make IPython and matplotlib play nicely under OSX. -To run IPython and readline on OSX "Leopard" system python, see the -wiki page at http://ipython.scipy.org/moin/InstallationOSXLeopard - -GUI problems ------------- +GUI problems (older versions of OS X) +------------------------------------- -The following instructions apply to an install of IPython under OSX from -unpacking the .tar.gz distribution and installing it for the default -Python interpreter shipped by Apple. If you are using a fink install, -fink will take care of these details for you, by installing IPython -against fink's Python. +The following instructions apply to an install of IPython under OSX before OS X 10.5 (users of OS X 10.5 see [#]_ ) by unpacking the .tar.gz distribution and installing it for the default Python interpreter shipped by Apple. If you are using a fink or DarwinPorts install, they will take care of these details for you, by installing IPython against their Python. IPython offers various forms of support for interacting with graphical applications from the command line, from simple Tk apps (which are in @@ -103,7 +99,7 @@ So when installing under OSX, it is best to use the following command:: $ sudo pythonw setup.py install --install-scripts=/usr/local/bin -or +or:: $ sudo pythonw setup.py install --install-scripts=/usr/bin @@ -124,12 +120,14 @@ scripts in an internal directory not available by default at the command line (if you use /usr/local/bin, you need to make sure this is in your $PATH, which may not be true by default). +.. [#] Users of OS X 10.5 who choose to use the system-installed python should install IPython using ``sudo python setupegg.py install`` from the IPython source directory or from `PyPI`_ using ``sudo easy_install ipython``. + +.. _PyPI: http://pypi.python.org/pypi Readline problems ----------------- -By default, the Python version shipped by Apple does not include the -readline library, so central to IPython's behavior. If you install +By default, the Python version shipped by Apple before OS X 10.5 does not include the readline library, so central to IPython's behavior. If you install IPython against Apple's Python, you will not have arrow keys, tab completion, etc. For Mac OSX 10.3 (Panther), you can find a prebuilt readline library here: @@ -142,9 +140,25 @@ need to either: /Library/Python/2.3/site-packages, or 2. install http://pythonmac.org/packages/TigerPython23Compat.pkg.zip -Users installing against Fink's Python or a properly hand-built one -should not have this problem. +Beginning with OS X 10.5, Apple's python installation uses libedit, a BSD-licensed not-quite-compatible readline replacement. As of IPython 0.9, many of the issues related to the differences between readline and libedit have been resolved. If you find that you are experiencing readline-related issues (e.g. problems with tab-completion, history movement, or line editing), you can install Ludwig Schwartz's readline package which effectively replaces libedit with readline for packages installed via setuptools. If you installed IPython from the source directory using:: + + sudo python setupegg.py + +or from PyPI with:: + + sudo easy_install ipython + +then you can install the readline egg via [#]_:: + + sudo easy_install readline + +If needed, the readline egg can be build and installed from source (see the +wiki page at http://ipython.scipy.org/moin/InstallationOSXLeopard). + +Users installing against Fink or DarwinPorts's Python or a properly hand-built python installation should not have this problem. + +.. [#] If you have installed SVN 1.5, you will also to install a patch to setuptools before installing the readline egg. Use ``sudo easy_install http://www.jaraco.com/ASP/eggs/setuptools-0.6c8_svn15fix.egg``. DarwinPorts -----------