##// END OF EJS Templates
Merging in Brian's branch (also pulls Gael's work)....
Fernando Perez -
r1720:a2890974 merge
parent child Browse files
Show More
@@ -0,0 +1,155 b''
1 # encoding: utf-8
2
3 """This file contains unittests for the frontendbase module."""
4
5 __docformat__ = "restructuredtext en"
6
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
13
14 #---------------------------------------------------------------------------
15 # Imports
16 #---------------------------------------------------------------------------
17
18 import unittest
19
20 try:
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService
24 except ImportError:
25 import nose
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
27
28 from IPython.testing.decorators import skip
29
30 class FrontEndCallbackChecker(AsyncFrontEndBase):
31 """FrontEndBase subclass for checking callbacks"""
32 def __init__(self, engine=None, history=None):
33 super(FrontEndCallbackChecker, self).__init__(engine=engine,
34 history=history)
35 self.updateCalled = False
36 self.renderResultCalled = False
37 self.renderErrorCalled = False
38
39 def update_cell_prompt(self, result, blockID=None):
40 self.updateCalled = True
41 return result
42
43 def render_result(self, result):
44 self.renderResultCalled = True
45 return result
46
47
48 def render_error(self, failure):
49 self.renderErrorCalled = True
50 return failure
51
52
53
54
55 class TestAsyncFrontendBase(unittest.TestCase):
56 def setUp(self):
57 """Setup the EngineService and FrontEndBase"""
58
59 self.fb = FrontEndCallbackChecker(engine=EngineService())
60
61 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(
63 AsyncFrontEndBase))
64
65 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 block = """def test(a):"""
69
70 assert(self.fb.is_complete(block) == False)
71
72 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 block = """def test(a): pass"""
76
77 assert(self.fb.is_complete(block))
78
79 block = """a=3"""
80
81 assert(self.fb.is_complete(block))
82
83 def test_blockID_added_to_result(self):
84 block = """3+3"""
85
86 d = self.fb.execute(block, blockID='TEST_ID')
87
88 d.addCallback(self.checkBlockID, expected='TEST_ID')
89
90 def test_blockID_added_to_failure(self):
91 block = "raise Exception()"
92
93 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')
95
96 def checkBlockID(self, result, expected=""):
97 assert(result['blockID'] == expected)
98
99
100 def checkFailureID(self, failure, expected=""):
101 assert(failure.blockID == expected)
102
103
104 def test_callbacks_added_to_execute(self):
105 """test that
106 update_cell_prompt
107 render_result
108
109 are added to execute request
110 """
111
112 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)
114
115 def checkCallbacks(self, result):
116 assert(self.fb.updateCalled)
117 assert(self.fb.renderResultCalled)
118
119 @skip("This test fails and lead to an unhandled error in a Deferred.")
120 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""
122
123 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)
125
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
128
129 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""
131
132 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:
134 d = self.fb.execute(b)
135
136 # d is now the deferred for the last executed block
137 d.addCallback(self.historyTests, blocks)
138
139
140 def historyTests(self, result, blocks):
141 """historyTests"""
142
143 assert(len(blocks) >= 3)
144 assert(self.fb.get_history_previous("") == blocks[-2])
145 assert(self.fb.get_history_previous("") == blocks[-3])
146 assert(self.fb.get_history_next() == blocks[-2])
147
148
149 def test_history_returns_none_at_startup(self):
150 """test_history_returns_none_at_startup"""
151
152 assert(self.fb.get_history_previous("")==None)
153 assert(self.fb.get_history_next()==None)
154
155
@@ -0,0 +1,20 b''
1 #!/usr/bin/env python
2 """Call the compile script to check that all code we ship compiles correctly.
3 """
4
5 import os
6 import sys
7
8
9 vstr = '.'.join(map(str,sys.version_info[:2]))
10
11 stat = os.system('python %s/lib/python%s/compileall.py .' % (sys.prefix,vstr))
12
13 print
14 if stat:
15 print '*** THERE WAS AN ERROR! ***'
16 print 'See messages above for the actual file that produced it.'
17 else:
18 print 'OK'
19
20 sys.exit(stat)
@@ -34,45 +34,69 b' else:'
34 version = version_base
34 version = version_base
35
35
36
36
37 description = "Tools for interactive development in Python."
37 description = "An interactive computing environment for Python"
38
38
39 long_description = \
39 long_description = \
40 """
40 """
41 IPython provides a replacement for the interactive Python interpreter with
41 The goal of IPython is to create a comprehensive environment for
42 extra functionality.
42 interactive and exploratory computing. To support this goal, IPython
43 has two main components:
43
44
44 Main features:
45 * An enhanced interactive Python shell.
45
46
46 * Comprehensive object introspection.
47 * An architecture for interactive parallel computing.
47
48
48 * Input history, persistent across sessions.
49 The enhanced interactive Python shell has the following main features:
49
50
50 * Caching of output results during a session with automatically generated
51 * Comprehensive object introspection.
51 references.
52
52
53 * Readline based name completion.
53 * Input history, persistent across sessions.
54
54
55 * Extensible system of 'magic' commands for controlling the environment and
55 * Caching of output results during a session with automatically generated
56 performing many tasks related either to IPython or the operating system.
56 references.
57
57
58 * Configuration system with easy switching between different setups (simpler
58 * Readline based name completion.
59 than changing $PYTHONSTARTUP environment variables every time).
60
59
61 * Session logging and reloading.
60 * Extensible system of 'magic' commands for controlling the environment and
61 performing many tasks related either to IPython or the operating system.
62
62
63 * Extensible syntax processing for special purpose situations.
63 * Configuration system with easy switching between different setups (simpler
64 than changing $PYTHONSTARTUP environment variables every time).
64
65
65 * Access to the system shell with user-extensible alias system.
66 * Session logging and reloading.
66
67
67 * Easily embeddable in other Python programs.
68 * Extensible syntax processing for special purpose situations.
68
69
69 * Integrated access to the pdb debugger and the Python profiler.
70 * Access to the system shell with user-extensible alias system.
70
71
71 The latest development version is always available at the IPython subversion
72 * Easily embeddable in other Python programs and wxPython GUIs.
72 repository_.
73
73
74 .. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev
74 * Integrated access to the pdb debugger and the Python profiler.
75 """
75
76 The parallel computing architecture has the following main features:
77
78 * Quickly parallelize Python code from an interactive Python/IPython session.
79
80 * A flexible and dynamic process model that be deployed on anything from
81 multicore workstations to supercomputers.
82
83 * An architecture that supports many different styles of parallelism, from
84 message passing to task farming.
85
86 * Both blocking and fully asynchronous interfaces.
87
88 * High level APIs that enable many things to be parallelized in a few lines
89 of code.
90
91 * Share live parallel jobs with other users securely.
92
93 * Dynamically load balanced task farming system.
94
95 * Robust error handling in parallel code.
96
97 The latest development version is always available from IPython's `Launchpad
98 site <http://launchpad.net/ipython>`_.
99 """
76
100
77 license = 'BSD'
101 license = 'BSD'
78
102
@@ -21,10 +21,6 b' from os.path import join as pjoin'
21 from IPython.genutils import get_home_dir, get_ipython_dir
21 from IPython.genutils import get_home_dir, get_ipython_dir
22 from IPython.external.configobj import ConfigObj
22 from IPython.external.configobj import ConfigObj
23
23
24 # Traitlets config imports
25 from IPython.config import traitlets
26 from IPython.config.config import *
27 from traitlets import *
28
24
29 class ConfigObjManager(object):
25 class ConfigObjManager(object):
30
26
@@ -14,7 +14,7 b' __docformat__ = "restructuredtext en"'
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17 import uuid
17 from IPython.external import guid
18
18
19
19
20 from zope.interface import Interface, Attribute, implements, classProvides
20 from zope.interface import Interface, Attribute, implements, classProvides
@@ -59,7 +59,7 b' class AsyncFrontEndBase(FrontEndBase):'
59 return Failure(Exception("Block is not compilable"))
59 return Failure(Exception("Block is not compilable"))
60
60
61 if(blockID == None):
61 if(blockID == None):
62 blockID = uuid.uuid4() #random UUID
62 blockID = guid.generate()
63
63
64 d = self.engine.execute(block)
64 d = self.engine.execute(block)
65 d.addCallback(self._add_history, block=block)
65 d.addCallback(self._add_history, block=block)
@@ -26,7 +26,7 b' __docformat__ = "restructuredtext en"'
26
26
27 import sys
27 import sys
28 import objc
28 import objc
29 import uuid
29 from IPython.external import guid
30
30
31 from Foundation import NSObject, NSMutableArray, NSMutableDictionary,\
31 from Foundation import NSObject, NSMutableArray, NSMutableDictionary,\
32 NSLog, NSNotificationCenter, NSMakeRange,\
32 NSLog, NSNotificationCenter, NSMakeRange,\
@@ -361,7 +361,7 b' class IPythonCocoaController(NSObject, AsyncFrontEndBase):'
361
361
362 def next_block_ID(self):
362 def next_block_ID(self):
363
363
364 return uuid.uuid4()
364 return guid.generate()
365
365
366 def new_cell_block(self):
366 def new_cell_block(self):
367 """A new CellBlock at the end of self.textView.textStorage()"""
367 """A new CellBlock at the end of self.textView.textStorage()"""
@@ -21,83 +21,13 b' __docformat__ = "restructuredtext en"'
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import string
23 import string
24
24 import codeop
25 try:
25 from IPython.external import guid
26 import _ast
27 except ImportError:
28 # Python 2.4 hackish workaround.
29 class bunch: pass
30 _ast = bunch()
31 _ast.PyCF_ONLY_AST = 1024
32
33
34
35 try:
36 import uuid
37 except ImportError:
38 # Python 2.4 hackish workaround.
39 class UUID:
40 def __init__(self,bytes):
41 version = 4
42 int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
43 # Set the variant to RFC 4122.
44 int &= ~(0xc000 << 48L)
45 int |= 0x8000 << 48L
46 # Set the version number.
47 int &= ~(0xf000 << 64L)
48 int |= version << 76L
49 self.__dict__['int'] = int
50
51 def __cmp__(self, other):
52 if isinstance(other, UUID):
53 return cmp(self.int, other.int)
54 return NotImplemented
55
56 def __hash__(self):
57 return hash(self.int)
58
59 def __int__(self):
60 return self.int
61
62 def __repr__(self):
63 return 'UUID(%r)' % str(self)
64
65 def __setattr__(self, name, value):
66 raise TypeError('UUID objects are immutable')
67
68 def __str__(self):
69 hex = '%032x' % self.int
70 return '%s-%s-%s-%s-%s' % (
71 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
72
73 def get_bytes(self):
74 bytes = ''
75 for shift in range(0, 128, 8):
76 bytes = chr((self.int >> shift) & 0xff) + bytes
77 return bytes
78
79 bytes = property(get_bytes)
80
81
82 def _u4():
83 "Fake random uuid"
84
85 import random
86 bytes = [chr(random.randrange(256)) for i in range(16)]
87 return UUID(bytes)
88
89 class bunch: pass
90 uuid = bunch()
91 uuid.uuid4 = _u4
92 del _u4
93
94
26
95
27
96 from IPython.frontend.zopeinterface import (
28 from IPython.frontend.zopeinterface import (
97 Interface,
29 Interface,
98 Attribute,
30 Attribute,
99 implements,
100 classProvides
101 )
31 )
102 from IPython.kernel.core.history import FrontEndHistory
32 from IPython.kernel.core.history import FrontEndHistory
103 from IPython.kernel.core.util import Bunch
33 from IPython.kernel.core.util import Bunch
@@ -203,11 +133,7 b' class IFrontEnd(Interface):'
203
133
204 pass
134 pass
205
135
206 def compile_ast(block):
136
207 """Compiles block to an _ast.AST"""
208
209 pass
210
211 def get_history_previous(current_block):
137 def get_history_previous(current_block):
212 """Returns the block previous in the history. Saves currentBlock if
138 """Returns the block previous in the history. Saves currentBlock if
213 the history_cursor is currently at the end of the input history"""
139 the history_cursor is currently at the end of the input history"""
@@ -289,28 +215,14 b' class FrontEndBase(object):'
289 """
215 """
290
216
291 try:
217 try:
292 ast = self.compile_ast(block)
218 is_complete = codeop.compile_command(block.rstrip() + '\n\n',
219 "<string>", "exec")
293 except:
220 except:
294 return False
221 return False
295
222
296 lines = block.split('\n')
223 lines = block.split('\n')
297 return (len(lines)==1 or str(lines[-1])=='')
224 return ((is_complete is not None)
298
225 and (len(lines)==1 or str(lines[-1])==''))
299
300 def compile_ast(self, block):
301 """Compile block to an AST
302
303 Parameters:
304 block : str
305
306 Result:
307 AST
308
309 Throws:
310 Exception if block cannot be compiled
311 """
312
313 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
314
226
315
227
316 def execute(self, block, blockID=None):
228 def execute(self, block, blockID=None):
@@ -330,7 +242,7 b' class FrontEndBase(object):'
330 raise Exception("Block is not compilable")
242 raise Exception("Block is not compilable")
331
243
332 if(blockID == None):
244 if(blockID == None):
333 blockID = uuid.uuid4() #random UUID
245 blockID = guid.generate()
334
246
335 try:
247 try:
336 result = self.shell.execute(block)
248 result = self.shell.execute(block)
@@ -1,155 +1,32 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2 """
3 """This file contains unittests for the frontendbase module."""
3 Test the basic functionality of frontendbase.
4 """
4
5
5 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
6
7
7 #---------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
9 #
10 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is
11 # the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
13
14
14 #---------------------------------------------------------------------------
15 from IPython.frontend.frontendbase import FrontEndBase
15 # Imports
16
16 #---------------------------------------------------------------------------
17 def test_iscomplete():
17
18 """ Check that is_complete works.
18 import unittest
19 """
19
20 f = FrontEndBase()
20 try:
21 assert f.is_complete('(a + a)')
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 assert not f.is_complete('(a + a')
22 from IPython.frontend import frontendbase
23 assert f.is_complete('1')
23 from IPython.kernel.engineservice import EngineService
24 assert not f.is_complete('1 + ')
24 except ImportError:
25 assert not f.is_complete('1 + \n\n')
25 import nose
26 assert f.is_complete('if True:\n print 1\n')
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
27 assert not f.is_complete('if True:\n print 1')
27
28 assert f.is_complete('def f():\n print 1\n')
28 from IPython.testing.decorators import skip
29
29
30 if __name__ == '__main__':
30 class FrontEndCallbackChecker(AsyncFrontEndBase):
31 test_iscomplete()
31 """FrontEndBase subclass for checking callbacks"""
32 def __init__(self, engine=None, history=None):
33 super(FrontEndCallbackChecker, self).__init__(engine=engine,
34 history=history)
35 self.updateCalled = False
36 self.renderResultCalled = False
37 self.renderErrorCalled = False
38
39 def update_cell_prompt(self, result, blockID=None):
40 self.updateCalled = True
41 return result
42
43 def render_result(self, result):
44 self.renderResultCalled = True
45 return result
46
47
48 def render_error(self, failure):
49 self.renderErrorCalled = True
50 return failure
51
52
53
32
54
55 class TestAsyncFrontendBase(unittest.TestCase):
56 def setUp(self):
57 """Setup the EngineService and FrontEndBase"""
58
59 self.fb = FrontEndCallbackChecker(engine=EngineService())
60
61 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(
63 AsyncFrontEndBase))
64
65 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 block = """def test(a):"""
69
70 assert(self.fb.is_complete(block) == False)
71
72 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 block = """def test(a): pass"""
76
77 assert(self.fb.is_complete(block))
78
79 block = """a=3"""
80
81 assert(self.fb.is_complete(block))
82
83 def test_blockID_added_to_result(self):
84 block = """3+3"""
85
86 d = self.fb.execute(block, blockID='TEST_ID')
87
88 d.addCallback(self.checkBlockID, expected='TEST_ID')
89
90 def test_blockID_added_to_failure(self):
91 block = "raise Exception()"
92
93 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')
95
96 def checkBlockID(self, result, expected=""):
97 assert(result['blockID'] == expected)
98
99
100 def checkFailureID(self, failure, expected=""):
101 assert(failure.blockID == expected)
102
103
104 def test_callbacks_added_to_execute(self):
105 """test that
106 update_cell_prompt
107 render_result
108
109 are added to execute request
110 """
111
112 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)
114
115 def checkCallbacks(self, result):
116 assert(self.fb.updateCalled)
117 assert(self.fb.renderResultCalled)
118
119 @skip("This test fails and lead to an unhandled error in a Deferred.")
120 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""
122
123 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)
125
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
128
129 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""
131
132 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:
134 d = self.fb.execute(b)
135
136 # d is now the deferred for the last executed block
137 d.addCallback(self.historyTests, blocks)
138
139
140 def historyTests(self, result, blocks):
141 """historyTests"""
142
143 assert(len(blocks) >= 3)
144 assert(self.fb.get_history_previous("") == blocks[-2])
145 assert(self.fb.get_history_previous("") == blocks[-3])
146 assert(self.fb.get_history_next() == blocks[-2])
147
148
149 def test_history_returns_none_at_startup(self):
150 """test_history_returns_none_at_startup"""
151
152 assert(self.fb.get_history_previous("")==None)
153 assert(self.fb.get_history_next()==None)
154
155
@@ -16,9 +16,6 b' __docformat__ = "restructuredtext en"'
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18
18
19 #-------------------------------------------------------------------------------
20 # Imports
21 #-------------------------------------------------------------------------------
22 try:
19 try:
23 from zope.interface import Interface, Attribute, implements, classProvides
20 from zope.interface import Interface, Attribute, implements, classProvides
24 except ImportError:
21 except ImportError:
@@ -16,10 +16,12 b' __docformat__ = "restructuredtext en"'
16 import os
16 import os
17 from cStringIO import StringIO
17 from cStringIO import StringIO
18
18
19 from IPython.testing import decorators as testdec
19 # FIXME:
20 import nose
21 import sys
22 if sys.platform == 'win32':
23 raise nose.SkipTest("These tests are not reliable under windows")
20
24
21 # FIXME
22 @testdec.skip("This doesn't work under Windows")
23 def test_redirector():
25 def test_redirector():
24 """ Checks that the redirector can be used to do synchronous capture.
26 """ Checks that the redirector can be used to do synchronous capture.
25 """
27 """
@@ -40,8 +42,6 b' def test_redirector():'
40 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
42 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
41 assert result1 == result2
43 assert result1 == result2
42
44
43 # FIXME
44 @testdec.skip("This doesn't work under Windows")
45 def test_redirector_output_trap():
45 def test_redirector_output_trap():
46 """ This test check not only that the redirector_output_trap does
46 """ This test check not only that the redirector_output_trap does
47 trap the output, but also that it does it in a gready way, that
47 trap the output, but also that it does it in a gready way, that
@@ -1,11 +1,11 b''
1 ===============
1 ==============
2 IPython1 README
2 IPython README
3 ===============
3 ==============
4
5 .. contents::
6
4
7 Overview
5 Overview
8 ========
6 ========
9
7
10 Welcome to IPython. New users should consult our documentation, which can be found
8 Welcome to IPython. Our documentation can be found in the docs/source
11 in the docs/source subdirectory.
9 subdirectory. We also have ``.html`` and ``.pdf`` versions of this
10 documentation available on the IPython `website <http://ipython.scipy.org>`_.
11
@@ -14,7 +14,7 b' However, the interpreter supplied with the standard Python distribution'
14 is somewhat limited for extended interactive use.
14 is somewhat limited for extended interactive use.
15
15
16 The goal of IPython is to create a comprehensive environment for
16 The goal of IPython is to create a comprehensive environment for
17 interactive and exploratory computing. To support, this goal, IPython
17 interactive and exploratory computing. To support this goal, IPython
18 has two main components:
18 has two main components:
19
19
20 * An enhanced interactive Python shell.
20 * An enhanced interactive Python shell.
1 NO CONTENT: file renamed from IPython/config/config.py to sandbox/config.py
NO CONTENT: file renamed from IPython/config/config.py to sandbox/config.py
1 NO CONTENT: file renamed from IPython/config/tests/sample_config.py to sandbox/sample_config.py
NO CONTENT: file renamed from IPython/config/tests/sample_config.py to sandbox/sample_config.py
1 NO CONTENT: file renamed from IPython/config/tests/test_config.py to sandbox/test_config.py
NO CONTENT: file renamed from IPython/config/tests/test_config.py to sandbox/test_config.py
1 NO CONTENT: file renamed from IPython/config/traitlets.py to sandbox/traitlets.py
NO CONTENT: file renamed from IPython/config/traitlets.py to sandbox/traitlets.py
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now