From d8f2aac45135b669e9c5d5eac3be0d8480acb19a 2008-08-23 21:18:02 From: Brian Granger Date: 2008-08-23 21:18:02 Subject: [PATCH] Fixing small bugs for the release. * Fixing imports in tests when deps are not present. * Removed shell.py and test_shell.py as they are old. * Adding notes about installation and testing. --- diff --git a/IPython/frontend/cocoa/tests/test_cocoa_frontend.py b/IPython/frontend/cocoa/tests/test_cocoa_frontend.py index d85728d..8ba73b2 100644 --- a/IPython/frontend/cocoa/tests/test_cocoa_frontend.py +++ b/IPython/frontend/cocoa/tests/test_cocoa_frontend.py @@ -18,74 +18,75 @@ 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 -class TestIPythonCocoaControler(DeferredTestCase): - """Tests for IPythonCocoaController""" +try: + from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController + from Foundation import NSMakeRect + from AppKit import NSTextView, NSScrollView +except ImportError: + class TestIPythonCocoaControler(DeferredTestCase): + """Tests for IPythonCocoaController""" - def setUp(self): - self.controller = IPythonCocoaController.alloc().init() - self.engine = es.EngineService() - self.engine.startService() + 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 tearDown(self): + self.controller = None + self.engine.stopService() - def testControllerExecutesCode(self): - code ="""5+5""" - expected = Interpreter().execute(code) - del expected['number'] - def removeNumberAndID(result): - del result['number'] - del result['id'] - return result - self.assertDeferredEquals( - self.controller.execute(code).addCallback(removeNumberAndID), - expected) + def testControllerExecutesCode(self): + code ="""5+5""" + expected = Interpreter().execute(code) + del expected['number'] + def removeNumberAndID(result): + del result['number'] + del result['id'] + return result + 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) + 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) + self.controller.execute(code).addCallback(testControllerUserNS) - def testControllerInstantiatesIEngine(self): - self.assert_(es.IEngineBase.providedBy(self.controller.engine)) + 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 testControllerCompletesToken(self): + code = """longNameVariable=10""" + def testCompletes(result): + self.assert_("longNameVariable" in result) - def testCompleteToken(result): - self.controller.complete("longNa").addCallback(testCompletes) + def testCompleteToken(result): + self.controller.complete("longNa").addCallback(testCompletes) - self.controller.execute(code).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. - """ + 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) + 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)) + 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/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/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/docs/source/development/development.txt b/docs/source/development/development.txt index 375ae23..877f0b0 100644 --- a/docs/source/development/development.txt +++ b/docs/source/development/development.txt @@ -349,6 +349,39 @@ 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 (test1) + b. With all dependencies installed (readline, zope.interface, + Twisted, foolscap, Sphinx, nose, pyOpenSSL) (test2) + 2. Install using easy_install. + a. With only readline+nose dependencies installed (test3) + i. Default dependencies. + ii. Optional dependency sets (kernel, doc, test, security) + easy_install -f ipython-0.9.beta3-py2.5.egg IPython[kernel,doc,test,security] + + b. With all dependencies already installed (test2) + + +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.