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 | ||||
|
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 = " |
|
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 = |
|
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 |
|
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 |
|
|
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 = |
|
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 |
|
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 |
IPython |
|
2 | IPython README | |
3 |
============== |
|
3 | ============== | |
4 |
|
||||
5 | .. contents:: |
|
|||
6 |
|
4 | |||
7 | Overview |
|
5 | Overview | |
8 | ======== |
|
6 | ======== | |
9 |
|
7 | |||
10 |
Welcome to IPython. |
|
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 |
|
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