diff --git a/IPython/Release.py b/IPython/Release.py index 3cc40eb..d2e3bf5 100644 --- a/IPython/Release.py +++ b/IPython/Release.py @@ -21,7 +21,7 @@ name = 'ipython' # bdist_deb does not accept underscores (a Debian convention). development = False # change this to False to do a release -version_base = '0.9' +version_base = '0.9.1' branch = 'ipython' revision = '1143' @@ -34,45 +34,69 @@ else: version = version_base -description = "Tools for interactive development in Python." +description = "An interactive computing environment for Python" long_description = \ """ -IPython provides a replacement for the interactive Python interpreter with -extra functionality. +The goal of IPython is to create a comprehensive environment for +interactive and exploratory computing. To support this goal, IPython +has two main components: -Main features: +* An enhanced interactive Python shell. - * Comprehensive object introspection. +* An architecture for interactive parallel computing. - * Input history, persistent across sessions. +The enhanced interactive Python shell has the following main features: - * Caching of output results during a session with automatically generated - references. +* Comprehensive object introspection. - * Readline based name completion. +* Input history, persistent across sessions. - * Extensible system of 'magic' commands for controlling the environment and - performing many tasks related either to IPython or the operating system. +* Caching of output results during a session with automatically generated + references. - * Configuration system with easy switching between different setups (simpler - than changing $PYTHONSTARTUP environment variables every time). +* Readline based name completion. - * Session logging and reloading. +* Extensible system of 'magic' commands for controlling the environment and + performing many tasks related either to IPython or the operating system. - * Extensible syntax processing for special purpose situations. +* Configuration system with easy switching between different setups (simpler + than changing $PYTHONSTARTUP environment variables every time). - * Access to the system shell with user-extensible alias system. +* Session logging and reloading. - * Easily embeddable in other Python programs. +* Extensible syntax processing for special purpose situations. - * Integrated access to the pdb debugger and the Python profiler. +* Access to the system shell with user-extensible alias system. - The latest development version is always available at the IPython subversion - repository_. +* Easily embeddable in other Python programs and wxPython GUIs. -.. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev - """ +* Integrated access to the pdb debugger and the Python profiler. + +The parallel computing architecture has the following main features: + +* Quickly parallelize Python code from an interactive Python/IPython session. + +* A flexible and dynamic process model that be deployed on anything from + multicore workstations to supercomputers. + +* An architecture that supports many different styles of parallelism, from + message passing to task farming. + +* Both blocking and fully asynchronous interfaces. + +* High level APIs that enable many things to be parallelized in a few lines + of code. + +* Share live parallel jobs with other users securely. + +* Dynamically load balanced task farming system. + +* Robust error handling in parallel code. + +The latest development version is always available from IPython's `Launchpad +site `_. +""" license = 'BSD' diff --git a/IPython/config/api.py b/IPython/config/api.py index d394098..6de3d3e 100644 --- a/IPython/config/api.py +++ b/IPython/config/api.py @@ -21,10 +21,6 @@ from os.path import join as pjoin from IPython.genutils import get_home_dir, get_ipython_dir from IPython.external.configobj import ConfigObj -# Traitlets config imports -from IPython.config import traitlets -from IPython.config.config import * -from traitlets import * class ConfigObjManager(object): diff --git a/IPython/frontend/asyncfrontendbase.py b/IPython/frontend/asyncfrontendbase.py index a35366f..78afa18 100644 --- a/IPython/frontend/asyncfrontendbase.py +++ b/IPython/frontend/asyncfrontendbase.py @@ -14,7 +14,7 @@ __docformat__ = "restructuredtext en" #------------------------------------------------------------------------------- # Imports #------------------------------------------------------------------------------- -import uuid +from IPython.external import guid from zope.interface import Interface, Attribute, implements, classProvides @@ -59,7 +59,7 @@ class AsyncFrontEndBase(FrontEndBase): return Failure(Exception("Block is not compilable")) if(blockID == None): - blockID = uuid.uuid4() #random UUID + blockID = guid.generate() d = self.engine.execute(block) d.addCallback(self._add_history, block=block) diff --git a/IPython/frontend/cocoa/cocoa_frontend.py b/IPython/frontend/cocoa/cocoa_frontend.py index 63b765c..349e794 100644 --- a/IPython/frontend/cocoa/cocoa_frontend.py +++ b/IPython/frontend/cocoa/cocoa_frontend.py @@ -26,7 +26,7 @@ __docformat__ = "restructuredtext en" import sys import objc -import uuid +from IPython.external import guid from Foundation import NSObject, NSMutableArray, NSMutableDictionary,\ NSLog, NSNotificationCenter, NSMakeRange,\ @@ -361,7 +361,7 @@ class IPythonCocoaController(NSObject, AsyncFrontEndBase): def next_block_ID(self): - return uuid.uuid4() + return guid.generate() def new_cell_block(self): """A new CellBlock at the end of self.textView.textStorage()""" diff --git a/IPython/frontend/frontendbase.py b/IPython/frontend/frontendbase.py index 9f98dcf..3ae6e78 100644 --- a/IPython/frontend/frontendbase.py +++ b/IPython/frontend/frontendbase.py @@ -21,14 +21,13 @@ __docformat__ = "restructuredtext en" # Imports #------------------------------------------------------------------------------- import string -import uuid -import _ast +import codeop +from IPython.external import guid + from IPython.frontend.zopeinterface import ( Interface, Attribute, - implements, - classProvides ) from IPython.kernel.core.history import FrontEndHistory from IPython.kernel.core.util import Bunch @@ -134,11 +133,7 @@ class IFrontEnd(Interface): pass - def compile_ast(block): - """Compiles block to an _ast.AST""" - - pass - + def get_history_previous(current_block): """Returns the block previous in the history. Saves currentBlock if the history_cursor is currently at the end of the input history""" @@ -220,28 +215,14 @@ class FrontEndBase(object): """ try: - ast = self.compile_ast(block) + is_complete = codeop.compile_command(block.rstrip() + '\n\n', + "", "exec") except: return False lines = block.split('\n') - return (len(lines)==1 or str(lines[-1])=='') - - - def compile_ast(self, block): - """Compile block to an AST - - Parameters: - block : str - - Result: - AST - - Throws: - Exception if block cannot be compiled - """ - - return compile(block, "", "exec", _ast.PyCF_ONLY_AST) + return ((is_complete is not None) + and (len(lines)==1 or str(lines[-1])=='')) def execute(self, block, blockID=None): @@ -261,7 +242,7 @@ class FrontEndBase(object): raise Exception("Block is not compilable") if(blockID == None): - blockID = uuid.uuid4() #random UUID + blockID = guid.generate() try: result = self.shell.execute(block) diff --git a/IPython/frontend/linefrontendbase.py b/IPython/frontend/linefrontendbase.py index 494fc71..a154e13 100644 --- a/IPython/frontend/linefrontendbase.py +++ b/IPython/frontend/linefrontendbase.py @@ -182,16 +182,29 @@ class LineFrontEndBase(FrontEndBase): raw_string = python_string # Create a false result, in case there is an exception self.last_result = dict(number=self.prompt_number) + + ## try: + ## self.history.input_cache[-1] = raw_string.rstrip() + ## result = self.shell.execute(python_string) + ## self.last_result = result + ## self.render_result(result) + ## except: + ## self.show_traceback() + ## finally: + ## self.after_execute() + try: - self.history.input_cache[-1] = raw_string.rstrip() - result = self.shell.execute(python_string) - self.last_result = result - self.render_result(result) - except: - self.show_traceback() + try: + self.history.input_cache[-1] = raw_string.rstrip() + result = self.shell.execute(python_string) + self.last_result = result + self.render_result(result) + except: + self.show_traceback() finally: self.after_execute() + #-------------------------------------------------------------------------- # LineFrontEndBase interface #-------------------------------------------------------------------------- diff --git a/IPython/frontend/prefilterfrontend.py b/IPython/frontend/prefilterfrontend.py index ad6ce13..440d3e2 100644 --- a/IPython/frontend/prefilterfrontend.py +++ b/IPython/frontend/prefilterfrontend.py @@ -196,17 +196,33 @@ This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code.""" # capture it. self.capture_output() self.last_result = dict(number=self.prompt_number) + + ## try: + ## for line in input_string.split('\n'): + ## filtered_lines.append( + ## self.ipython0.prefilter(line, False).rstrip()) + ## except: + ## # XXX: probably not the right thing to do. + ## self.ipython0.showsyntaxerror() + ## self.after_execute() + ## finally: + ## self.release_output() + + try: - for line in input_string.split('\n'): - filtered_lines.append( - self.ipython0.prefilter(line, False).rstrip()) - except: - # XXX: probably not the right thing to do. - self.ipython0.showsyntaxerror() - self.after_execute() + try: + for line in input_string.split('\n'): + filtered_lines.append( + self.ipython0.prefilter(line, False).rstrip()) + except: + # XXX: probably not the right thing to do. + self.ipython0.showsyntaxerror() + self.after_execute() finally: self.release_output() + + # Clean up the trailing whitespace, to avoid indentation errors filtered_string = '\n'.join(filtered_lines) return filtered_string diff --git a/IPython/frontend/tests/test_asyncfrontendbase.py b/IPython/frontend/tests/test_asyncfrontendbase.py new file mode 100644 index 0000000..617456e --- /dev/null +++ b/IPython/frontend/tests/test_asyncfrontendbase.py @@ -0,0 +1,155 @@ +# encoding: utf-8 + +"""This file contains unittests for the frontendbase 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 + +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") + +from IPython.testing.decorators import skip + +class FrontEndCallbackChecker(AsyncFrontEndBase): + """FrontEndBase subclass for checking callbacks""" + def __init__(self, engine=None, history=None): + super(FrontEndCallbackChecker, self).__init__(engine=engine, + history=history) + 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 + + + def render_error(self, failure): + self.renderErrorCalled = True + return failure + + + + +class TestAsyncFrontendBase(unittest.TestCase): + def setUp(self): + """Setup the EngineService and FrontEndBase""" + + self.fb = FrontEndCallbackChecker(engine=EngineService()) + + def test_implements_IFrontEnd(self): + assert(frontendbase.IFrontEnd.implementedBy( + AsyncFrontEndBase)) + + def test_is_complete_returns_False_for_incomplete_block(self): + """""" + + block = """def test(a):""" + + assert(self.fb.is_complete(block) == False) + + def test_is_complete_returns_True_for_complete_block(self): + """""" + + block = """def test(a): pass""" + + assert(self.fb.is_complete(block)) + + block = """a=3""" + + assert(self.fb.is_complete(block)) + + def test_blockID_added_to_result(self): + block = """3+3""" + + d = self.fb.execute(block, blockID='TEST_ID') + + d.addCallback(self.checkBlockID, expected='TEST_ID') + + def test_blockID_added_to_failure(self): + block = "raise Exception()" + + d = self.fb.execute(block,blockID='TEST_ID') + d.addErrback(self.checkFailureID, expected='TEST_ID') + + def checkBlockID(self, result, expected=""): + assert(result['blockID'] == expected) + + + def checkFailureID(self, failure, expected=""): + assert(failure.blockID == expected) + + + def test_callbacks_added_to_execute(self): + """test that + update_cell_prompt + render_result + + are added to execute request + """ + + d = self.fb.execute("10+10") + d.addCallback(self.checkCallbacks) + + def checkCallbacks(self, result): + assert(self.fb.updateCalled) + assert(self.fb.renderResultCalled) + + @skip("This test fails and lead to an unhandled error in a Deferred.") + def test_error_callback_added_to_execute(self): + """test that render_error called on execution error""" + + d = self.fb.execute("raise Exception()") + d.addCallback(self.checkRenderError) + + def checkRenderError(self, result): + assert(self.fb.renderErrorCalled) + + def test_history_returns_expected_block(self): + """Make sure history browsing doesn't fail""" + + blocks = ["a=1","a=2","a=3"] + for b in blocks: + d = self.fb.execute(b) + + # d is now the deferred for the last executed block + d.addCallback(self.historyTests, blocks) + + + def historyTests(self, result, blocks): + """historyTests""" + + assert(len(blocks) >= 3) + assert(self.fb.get_history_previous("") == blocks[-2]) + assert(self.fb.get_history_previous("") == blocks[-3]) + assert(self.fb.get_history_next() == blocks[-2]) + + + def test_history_returns_none_at_startup(self): + """test_history_returns_none_at_startup""" + + assert(self.fb.get_history_previous("")==None) + assert(self.fb.get_history_next()==None) + + diff --git a/IPython/frontend/tests/test_frontendbase.py b/IPython/frontend/tests/test_frontendbase.py index 617456e..f3f4e5a 100644 --- a/IPython/frontend/tests/test_frontendbase.py +++ b/IPython/frontend/tests/test_frontendbase.py @@ -1,155 +1,32 @@ # encoding: utf-8 - -"""This file contains unittests for the frontendbase module.""" +""" +Test the basic functionality of frontendbase. +""" __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 - -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") - -from IPython.testing.decorators import skip - -class FrontEndCallbackChecker(AsyncFrontEndBase): - """FrontEndBase subclass for checking callbacks""" - def __init__(self, engine=None, history=None): - super(FrontEndCallbackChecker, self).__init__(engine=engine, - history=history) - 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 - - - def render_error(self, failure): - self.renderErrorCalled = True - return failure - - +#------------------------------------------------------------------------------- +# 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. +#------------------------------------------------------------------------------- + +from IPython.frontend.frontendbase import FrontEndBase + +def test_iscomplete(): + """ Check that is_complete works. + """ + f = FrontEndBase() + assert f.is_complete('(a + a)') + assert not f.is_complete('(a + a') + assert f.is_complete('1') + assert not f.is_complete('1 + ') + assert not f.is_complete('1 + \n\n') + assert f.is_complete('if True:\n print 1\n') + assert not f.is_complete('if True:\n print 1') + assert f.is_complete('def f():\n print 1\n') + +if __name__ == '__main__': + test_iscomplete() - -class TestAsyncFrontendBase(unittest.TestCase): - def setUp(self): - """Setup the EngineService and FrontEndBase""" - - self.fb = FrontEndCallbackChecker(engine=EngineService()) - - def test_implements_IFrontEnd(self): - assert(frontendbase.IFrontEnd.implementedBy( - AsyncFrontEndBase)) - - def test_is_complete_returns_False_for_incomplete_block(self): - """""" - - block = """def test(a):""" - - assert(self.fb.is_complete(block) == False) - - def test_is_complete_returns_True_for_complete_block(self): - """""" - - block = """def test(a): pass""" - - assert(self.fb.is_complete(block)) - - block = """a=3""" - - assert(self.fb.is_complete(block)) - - def test_blockID_added_to_result(self): - block = """3+3""" - - d = self.fb.execute(block, blockID='TEST_ID') - - d.addCallback(self.checkBlockID, expected='TEST_ID') - - def test_blockID_added_to_failure(self): - block = "raise Exception()" - - d = self.fb.execute(block,blockID='TEST_ID') - d.addErrback(self.checkFailureID, expected='TEST_ID') - - def checkBlockID(self, result, expected=""): - assert(result['blockID'] == expected) - - - def checkFailureID(self, failure, expected=""): - assert(failure.blockID == expected) - - - def test_callbacks_added_to_execute(self): - """test that - update_cell_prompt - render_result - - are added to execute request - """ - - d = self.fb.execute("10+10") - d.addCallback(self.checkCallbacks) - - def checkCallbacks(self, result): - assert(self.fb.updateCalled) - assert(self.fb.renderResultCalled) - - @skip("This test fails and lead to an unhandled error in a Deferred.") - def test_error_callback_added_to_execute(self): - """test that render_error called on execution error""" - - d = self.fb.execute("raise Exception()") - d.addCallback(self.checkRenderError) - - def checkRenderError(self, result): - assert(self.fb.renderErrorCalled) - - def test_history_returns_expected_block(self): - """Make sure history browsing doesn't fail""" - - blocks = ["a=1","a=2","a=3"] - for b in blocks: - d = self.fb.execute(b) - - # d is now the deferred for the last executed block - d.addCallback(self.historyTests, blocks) - - - def historyTests(self, result, blocks): - """historyTests""" - - assert(len(blocks) >= 3) - assert(self.fb.get_history_previous("") == blocks[-2]) - assert(self.fb.get_history_previous("") == blocks[-3]) - assert(self.fb.get_history_next() == blocks[-2]) - - - def test_history_returns_none_at_startup(self): - """test_history_returns_none_at_startup""" - - assert(self.fb.get_history_previous("")==None) - assert(self.fb.get_history_next()==None) - - diff --git a/IPython/frontend/zopeinterface.py b/IPython/frontend/zopeinterface.py index fd37101..2081be3 100644 --- a/IPython/frontend/zopeinterface.py +++ b/IPython/frontend/zopeinterface.py @@ -16,13 +16,6 @@ __docformat__ = "restructuredtext en" # the file COPYING, distributed as part of this software. #------------------------------------------------------------------------------- -#------------------------------------------------------------------------------- -# Imports -#------------------------------------------------------------------------------- -import string -import uuid -import _ast - try: from zope.interface import Interface, Attribute, implements, classProvides except ImportError: diff --git a/IPython/kernel/contexts.py b/IPython/kernel/contexts.py index 553f140..949688e 100644 --- a/IPython/kernel/contexts.py +++ b/IPython/kernel/contexts.py @@ -8,8 +8,6 @@ which can also be useful as templates for writing new, application-specific managers. """ -from __future__ import with_statement - __docformat__ = "restructuredtext en" #------------------------------------------------------------------------------- diff --git a/IPython/kernel/core/tests/test_redirectors.py b/IPython/kernel/core/tests/test_redirectors.py index f9e57f5..81aa0ba 100644 --- a/IPython/kernel/core/tests/test_redirectors.py +++ b/IPython/kernel/core/tests/test_redirectors.py @@ -13,13 +13,17 @@ __docformat__ = "restructuredtext en" #------------------------------------------------------------------------------- +# Stdlib imports import os from cStringIO import StringIO -from IPython.testing import decorators as testdec +# Our own imports +from IPython.testing import decorators as dec -# FIXME -@testdec.skip("This doesn't work under Windows") +#----------------------------------------------------------------------------- +# Test functions + +@dec.skip_win32 def test_redirector(): """ Checks that the redirector can be used to do synchronous capture. """ @@ -40,8 +44,8 @@ def test_redirector(): result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10)) assert result1 == result2 -# FIXME -@testdec.skip("This doesn't work under Windows") + +@dec.skip_win32 def test_redirector_output_trap(): """ This test check not only that the redirector_output_trap does trap the output, but also that it does it in a gready way, that @@ -63,6 +67,4 @@ def test_redirector_output_trap(): result1 = out.getvalue() result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10)) assert result1 == result2 - - diff --git a/IPython/kernel/tests/test_contexts.py b/IPython/kernel/tests/test_contexts.py index 22590d0..2ef2dec 100644 --- a/IPython/kernel/tests/test_contexts.py +++ b/IPython/kernel/tests/test_contexts.py @@ -1,4 +1,6 @@ -from __future__ import with_statement +#from __future__ import with_statement + +# XXX This file is currently disabled to preserve 2.4 compatibility. #def test_simple(): if 0: @@ -25,17 +27,17 @@ if 0: mec.pushAll() - with parallel as pr: - # A comment - remote() # this means the code below only runs remotely - print 'Hello remote world' - x = range(10) - # Comments are OK - # Even misindented. - y = x+1 + ## with parallel as pr: + ## # A comment + ## remote() # this means the code below only runs remotely + ## print 'Hello remote world' + ## x = range(10) + ## # Comments are OK + ## # Even misindented. + ## y = x+1 - with pfor('i',sequence) as pr: - print x[i] + ## with pfor('i',sequence) as pr: + ## print x[i] print pr.x + pr.y diff --git a/IPython/testing/decorators.py b/IPython/testing/decorators.py index 78b6840..6cbe0a7 100644 --- a/IPython/testing/decorators.py +++ b/IPython/testing/decorators.py @@ -8,6 +8,10 @@ the decorator, in order to preserve metadata such as function name, setup and teardown functions and so on - see nose.tools for more information. +This module provides a set of useful decorators meant to be ready to use in +your own tests. See the bottom of the file for the ready-made ones, and if you +find yourself writing a new one that may be of generic use, add it here. + NOTE: This file contains IPython-specific decorators and imports the numpy.testing.decorators file, which we've copied verbatim. Any of our own code will be added at the bottom if we end up extending this. @@ -15,6 +19,7 @@ code will be added at the bottom if we end up extending this. # Stdlib imports import inspect +import sys # Third-party imports @@ -123,6 +128,9 @@ skip_doctest = make_label_dec('skip_doctest', def skip(msg=''): """Decorator - mark a test function for skipping from test suite. + This function *is* already a decorator, it is not a factory like + make_label_dec or some of those in decorators_numpy. + :Parameters: func : function @@ -145,3 +153,8 @@ def skip(msg=''): return apply_wrapper(wrapper,func) return inner + +# Decorators to skip certain tests on specific platforms. +skip_win32 = skipif(sys.platform=='win32',"This test does not run under Windows") +skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux") +skip_osx = skipif(sys.platform=='darwin',"This test does not run under OSX") diff --git a/IPython/testing/plugin/test_refs.py b/IPython/testing/plugin/test_refs.py index fc7e6f0..ae9ba41 100644 --- a/IPython/testing/plugin/test_refs.py +++ b/IPython/testing/plugin/test_refs.py @@ -1,152 +1,19 @@ +"""Some simple tests for the plugin while running scripts. +""" # Module imports # Std lib import inspect -# Third party - # Our own from IPython.testing import decorators as dec #----------------------------------------------------------------------------- -# Utilities - -# Note: copied from OInspect, kept here so the testing stuff doesn't create -# circular dependencies and is easier to reuse. -def getargspec(obj): - """Get the names and default values of a function's arguments. - - A tuple of four things is returned: (args, varargs, varkw, defaults). - 'args' is a list of the argument names (it may contain nested lists). - 'varargs' and 'varkw' are the names of the * and ** arguments or None. - 'defaults' is an n-tuple of the default values of the last n arguments. - - Modified version of inspect.getargspec from the Python Standard - Library.""" - - if inspect.isfunction(obj): - func_obj = obj - elif inspect.ismethod(obj): - func_obj = obj.im_func - else: - raise TypeError, 'arg is not a Python function' - args, varargs, varkw = inspect.getargs(func_obj.func_code) - return args, varargs, varkw, func_obj.func_defaults - -#----------------------------------------------------------------------------- # Testing functions def test_trivial(): """A trivial passing test.""" pass - -@dec.skip -def test_deliberately_broken(): - """A deliberately broken test - we want to skip this one.""" - 1/0 - -@dec.skip('foo') -def test_deliberately_broken2(): - """Another deliberately broken test - we want to skip this one.""" - 1/0 - - -# Verify that we can correctly skip the doctest for a function at will, but -# that the docstring itself is NOT destroyed by the decorator. -@dec.skip_doctest -def doctest_bad(x,y=1,**k): - """A function whose doctest we need to skip. - - >>> 1+1 - 3 - """ - print 'x:',x - print 'y:',y - print 'k:',k - - -def call_doctest_bad(): - """Check that we can still call the decorated functions. - - >>> doctest_bad(3,y=4) - x: 3 - y: 4 - k: {} - """ - pass - - -# Doctest skipping should work for class methods too -class foo(object): - """Foo - - Example: - - >>> 1+1 - 2 - """ - - @dec.skip_doctest - def __init__(self,x): - """Make a foo. - - Example: - - >>> f = foo(3) - junk - """ - print 'Making a foo.' - self.x = x - - @dec.skip_doctest - def bar(self,y): - """Example: - - >>> f = foo(3) - >>> f.bar(0) - boom! - >>> 1/0 - bam! - """ - return 1/y - - def baz(self,y): - """Example: - - >>> f = foo(3) - Making a foo. - >>> f.baz(3) - True - """ - return self.x==y - - -def test_skip_dt_decorator(): - """Doctest-skipping decorator should preserve the docstring. - """ - # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring! - check = """A function whose doctest we need to skip. - - >>> 1+1 - 3 - """ - # Fetch the docstring from doctest_bad after decoration. - val = doctest_bad.__doc__ - - assert check==val,"doctest_bad docstrings don't match" - - -def test_skip_dt_decorator2(): - """Doctest-skipping decorator should preserve function signature. - """ - # Hardcoded correct answer - dtargs = (['x', 'y'], None, 'k', (1,)) - # Introspect out the value - dtargsr = getargspec(doctest_bad) - assert dtargsr==dtargs, \ - "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,) - - def doctest_run(): """Test running a trivial script. @@ -154,7 +21,6 @@ def doctest_run(): x is: 1 """ -#@dec.skip_doctest def doctest_runvars(): """Test that variables defined in scripts get loaded correcly via %run. diff --git a/IPython/testing/tests/test_decorators.py b/IPython/testing/tests/test_decorators.py new file mode 100644 index 0000000..e91ec73 --- /dev/null +++ b/IPython/testing/tests/test_decorators.py @@ -0,0 +1,161 @@ +"""Tests for the decorators we've created for IPython. +""" + +# Module imports +# Std lib +import inspect +import sys + +# Third party +import nose.tools as nt + +# Our own +from IPython.testing import decorators as dec + + +#----------------------------------------------------------------------------- +# Utilities + +# Note: copied from OInspect, kept here so the testing stuff doesn't create +# circular dependencies and is easier to reuse. +def getargspec(obj): + """Get the names and default values of a function's arguments. + + A tuple of four things is returned: (args, varargs, varkw, defaults). + 'args' is a list of the argument names (it may contain nested lists). + 'varargs' and 'varkw' are the names of the * and ** arguments or None. + 'defaults' is an n-tuple of the default values of the last n arguments. + + Modified version of inspect.getargspec from the Python Standard + Library.""" + + if inspect.isfunction(obj): + func_obj = obj + elif inspect.ismethod(obj): + func_obj = obj.im_func + else: + raise TypeError, 'arg is not a Python function' + args, varargs, varkw = inspect.getargs(func_obj.func_code) + return args, varargs, varkw, func_obj.func_defaults + +#----------------------------------------------------------------------------- +# Testing functions + +@dec.skip +def test_deliberately_broken(): + """A deliberately broken test - we want to skip this one.""" + 1/0 + +@dec.skip('foo') +def test_deliberately_broken2(): + """Another deliberately broken test - we want to skip this one.""" + 1/0 + + +# Verify that we can correctly skip the doctest for a function at will, but +# that the docstring itself is NOT destroyed by the decorator. +@dec.skip_doctest +def doctest_bad(x,y=1,**k): + """A function whose doctest we need to skip. + + >>> 1+1 + 3 + """ + print 'x:',x + print 'y:',y + print 'k:',k + + +def call_doctest_bad(): + """Check that we can still call the decorated functions. + + >>> doctest_bad(3,y=4) + x: 3 + y: 4 + k: {} + """ + pass + + +def test_skip_dt_decorator(): + """Doctest-skipping decorator should preserve the docstring. + """ + # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring! + check = """A function whose doctest we need to skip. + + >>> 1+1 + 3 + """ + # Fetch the docstring from doctest_bad after decoration. + val = doctest_bad.__doc__ + + assert check==val,"doctest_bad docstrings don't match" + +# Doctest skipping should work for class methods too +class foo(object): + """Foo + + Example: + + >>> 1+1 + 2 + """ + + @dec.skip_doctest + def __init__(self,x): + """Make a foo. + + Example: + + >>> f = foo(3) + junk + """ + print 'Making a foo.' + self.x = x + + @dec.skip_doctest + def bar(self,y): + """Example: + + >>> f = foo(3) + >>> f.bar(0) + boom! + >>> 1/0 + bam! + """ + return 1/y + + def baz(self,y): + """Example: + + >>> f = foo(3) + Making a foo. + >>> f.baz(3) + True + """ + return self.x==y + + + +def test_skip_dt_decorator2(): + """Doctest-skipping decorator should preserve function signature. + """ + # Hardcoded correct answer + dtargs = (['x', 'y'], None, 'k', (1,)) + # Introspect out the value + dtargsr = getargspec(doctest_bad) + assert dtargsr==dtargs, \ + "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,) + + +@dec.skip_linux +def test_linux(): + nt.assert_not_equals(sys.platform,'linux2',"This test can't run under linux") + +@dec.skip_win32 +def test_win32(): + nt.assert_not_equals(sys.platform,'win32',"This test can't run under windows") + +@dec.skip_osx +def test_osx(): + nt.assert_not_equals(sys.platform,'darwin',"This test can't run under osx") diff --git a/README.txt b/README.txt index a46aaeb..dcda9ef 100644 --- a/README.txt +++ b/README.txt @@ -1,11 +1,11 @@ -=============== -IPython1 README -=============== - -.. contents:: +============== +IPython README +============== Overview ======== -Welcome to IPython. New users should consult our documentation, which can be found -in the docs/source subdirectory. +Welcome to IPython. Our documentation can be found in the docs/source +subdirectory. We also have ``.html`` and ``.pdf`` versions of this +documentation available on the IPython `website `_. + diff --git a/README_Windows.txt b/README_Windows.txt deleted file mode 100644 index 0ad13a7..0000000 --- a/README_Windows.txt +++ /dev/null @@ -1,50 +0,0 @@ -Notes for Windows Users -======================= - -See http://ipython.scipy.org/moin/IpythonOnWindows for up-to-date information -about running IPython on Windows. - - -Requirements ------------- - -IPython runs under (as far as the Windows family is concerned): - -- Windows XP, 2000 (and probably WinNT): works well. It needs: - - * PyWin32: http://sourceforge.net/projects/pywin32/ - - * PyReadline: http://ipython.scipy.org/moin/PyReadline/Intro - - * If you are using Python2.4, this in turn requires Tomas Heller's ctypes - from: http://starship.python.net/crew/theller/ctypes (not needed for Python - 2.5 users, since 2.5 already ships with ctypes). - -- Windows 95/98/ME: I have no idea. It should work, but I can't test. - -- CygWin environments should work, they are basically Posix. - -It needs Python 2.3 or newer. - - -Installation ------------- - -Double-click the supplied .exe installer file. If all goes well, that's all -you need to do. You should now have an IPython entry in your Start Menu. - - -Installation from source distribution -------------------------------------- - -In case the automatic installer does not work for some reason, you can -download the ipython-XXX.tar.gz file, which contains the full IPython source -distribution (the popular WinZip can read .tar.gz files). - -After uncompressing the archive, you can install it at a command terminal just -like any other Python module, by using python setup.py install'. After this -completes, you can run the supplied win32_manual_post_install.py script which -will add the relevant shortcuts to your startup menu. - -Optionally, you may skip installation altogether and just launch "ipython.py" -from the root folder of the extracted source distribution. diff --git a/docs/examples/kernel/nwmerge.py b/docs/examples/kernel/nwmerge.py index 32447a2..4723501 100644 --- a/docs/examples/kernel/nwmerge.py +++ b/docs/examples/kernel/nwmerge.py @@ -45,7 +45,10 @@ def mergesort(list_of_lists, key=None): for i, itr in enumerate(iter(pl) for pl in list_of_lists): try: item = itr.next() - toadd = (key(item), i, item, itr) if key else (item, i, itr) + if key: + toadd = (key(item), i, item, itr) + else: + toadd = (item, i, itr) heap.append(toadd) except StopIteration: pass diff --git a/docs/source/overview.txt b/docs/source/overview.txt index 6ac308d..9ee38cb 100644 --- a/docs/source/overview.txt +++ b/docs/source/overview.txt @@ -14,7 +14,7 @@ However, the interpreter supplied with the standard Python distribution is somewhat limited for extended interactive use. The goal of IPython is to create a comprehensive environment for -interactive and exploratory computing. To support, this goal, IPython +interactive and exploratory computing. To support this goal, IPython has two main components: * An enhanced interactive Python shell. diff --git a/IPython/config/config.py b/sandbox/config.py similarity index 100% rename from IPython/config/config.py rename to sandbox/config.py diff --git a/IPython/config/tests/sample_config.py b/sandbox/sample_config.py similarity index 100% rename from IPython/config/tests/sample_config.py rename to sandbox/sample_config.py diff --git a/IPython/config/tests/test_config.py b/sandbox/test_config.py similarity index 100% rename from IPython/config/tests/test_config.py rename to sandbox/test_config.py diff --git a/IPython/config/traitlets.py b/sandbox/traitlets.py similarity index 100% rename from IPython/config/traitlets.py rename to sandbox/traitlets.py diff --git a/tools/compile.py b/tools/compile.py new file mode 100644 index 0000000..4a08400 --- /dev/null +++ b/tools/compile.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +"""Call the compile script to check that all code we ship compiles correctly. +""" + +import os +import sys + + +vstr = '.'.join(map(str,sys.version_info[:2])) + +stat = os.system('python %s/lib/python%s/compileall.py .' % (sys.prefix,vstr)) + +print +if stat: + print '*** THERE WAS AN ERROR! ***' + print 'See messages above for the actual file that produced it.' +else: + print 'OK' + +sys.exit(stat) diff --git a/tools/testrel b/tools/testrel index 3ead49f..b6901e2 100755 --- a/tools/testrel +++ b/tools/testrel @@ -15,8 +15,8 @@ cd $ipdir ./setup.py sdist --formats=gztar # Build rpms -#python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4 -#python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5 +python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4 +python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5 # Build eggs python2.4 ./setup_bdist_egg.py