##// END OF EJS Templates
merge from trunk
Ville M. Vainio -
r1734:9e481613 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,26 b''
1 # encoding: utf-8
2
3 """This file contains unittests for the interpreter.py 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 from IPython.kernel.core.interpreter import Interpreter
19
20 def test_unicode():
21 """ Test unicode handling with the interpreter.
22 """
23 i = Interpreter()
24 i.execute_python(u'print "ù"')
25 i.execute_python('print "ù"')
26
@@ -0,0 +1,161 b''
1 """Tests for the decorators we've created for IPython.
2 """
3
4 # Module imports
5 # Std lib
6 import inspect
7 import sys
8
9 # Third party
10 import nose.tools as nt
11
12 # Our own
13 from IPython.testing import decorators as dec
14
15
16 #-----------------------------------------------------------------------------
17 # Utilities
18
19 # Note: copied from OInspect, kept here so the testing stuff doesn't create
20 # circular dependencies and is easier to reuse.
21 def getargspec(obj):
22 """Get the names and default values of a function's arguments.
23
24 A tuple of four things is returned: (args, varargs, varkw, defaults).
25 'args' is a list of the argument names (it may contain nested lists).
26 'varargs' and 'varkw' are the names of the * and ** arguments or None.
27 'defaults' is an n-tuple of the default values of the last n arguments.
28
29 Modified version of inspect.getargspec from the Python Standard
30 Library."""
31
32 if inspect.isfunction(obj):
33 func_obj = obj
34 elif inspect.ismethod(obj):
35 func_obj = obj.im_func
36 else:
37 raise TypeError, 'arg is not a Python function'
38 args, varargs, varkw = inspect.getargs(func_obj.func_code)
39 return args, varargs, varkw, func_obj.func_defaults
40
41 #-----------------------------------------------------------------------------
42 # Testing functions
43
44 @dec.skip
45 def test_deliberately_broken():
46 """A deliberately broken test - we want to skip this one."""
47 1/0
48
49 @dec.skip('foo')
50 def test_deliberately_broken2():
51 """Another deliberately broken test - we want to skip this one."""
52 1/0
53
54
55 # Verify that we can correctly skip the doctest for a function at will, but
56 # that the docstring itself is NOT destroyed by the decorator.
57 @dec.skip_doctest
58 def doctest_bad(x,y=1,**k):
59 """A function whose doctest we need to skip.
60
61 >>> 1+1
62 3
63 """
64 print 'x:',x
65 print 'y:',y
66 print 'k:',k
67
68
69 def call_doctest_bad():
70 """Check that we can still call the decorated functions.
71
72 >>> doctest_bad(3,y=4)
73 x: 3
74 y: 4
75 k: {}
76 """
77 pass
78
79
80 def test_skip_dt_decorator():
81 """Doctest-skipping decorator should preserve the docstring.
82 """
83 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
84 check = """A function whose doctest we need to skip.
85
86 >>> 1+1
87 3
88 """
89 # Fetch the docstring from doctest_bad after decoration.
90 val = doctest_bad.__doc__
91
92 assert check==val,"doctest_bad docstrings don't match"
93
94 # Doctest skipping should work for class methods too
95 class foo(object):
96 """Foo
97
98 Example:
99
100 >>> 1+1
101 2
102 """
103
104 @dec.skip_doctest
105 def __init__(self,x):
106 """Make a foo.
107
108 Example:
109
110 >>> f = foo(3)
111 junk
112 """
113 print 'Making a foo.'
114 self.x = x
115
116 @dec.skip_doctest
117 def bar(self,y):
118 """Example:
119
120 >>> f = foo(3)
121 >>> f.bar(0)
122 boom!
123 >>> 1/0
124 bam!
125 """
126 return 1/y
127
128 def baz(self,y):
129 """Example:
130
131 >>> f = foo(3)
132 Making a foo.
133 >>> f.baz(3)
134 True
135 """
136 return self.x==y
137
138
139
140 def test_skip_dt_decorator2():
141 """Doctest-skipping decorator should preserve function signature.
142 """
143 # Hardcoded correct answer
144 dtargs = (['x', 'y'], None, 'k', (1,))
145 # Introspect out the value
146 dtargsr = getargspec(doctest_bad)
147 assert dtargsr==dtargs, \
148 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
149
150
151 @dec.skip_linux
152 def test_linux():
153 nt.assert_not_equals(sys.platform,'linux2',"This test can't run under linux")
154
155 @dec.skip_win32
156 def test_win32():
157 nt.assert_not_equals(sys.platform,'win32',"This test can't run under windows")
158
159 @dec.skip_osx
160 def test_osx():
161 nt.assert_not_equals(sys.platform,'darwin',"This test can't run under osx")
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
@@ -0,0 +1,32 b''
1 # encoding: utf-8
2
3 """Tests for genutils.py"""
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 from IPython import genutils
19
20
21 def test_get_home_dir():
22 """Make sure we can get the home directory."""
23 home_dir = genutils.get_home_dir()
24
25 def test_get_ipython_dir():
26 """Make sure we can get the ipython directory."""
27 ipdir = genutils.get_ipython_dir()
28
29 def test_get_security_dir():
30 """Make sure we can get the ipython/security directory."""
31 sdir = genutils.get_security_dir()
32 No newline at end of file
@@ -0,0 +1,240 b''
1 .. _paralleltask:
2
3 ==========================
4 The IPython task interface
5 ==========================
6
7 .. contents::
8
9 The ``Task`` interface to the controller presents the engines as a fault tolerant, dynamic load-balanced system or workers. Unlike the ``MultiEngine`` interface, in the ``Task`` interface, the user have no direct access to individual engines. In some ways, this interface is simpler, but in other ways it is more powerful. Best of all the user can use both of these interfaces at the same time to take advantage or both of their strengths. When the user can break up the user's work into segments that do not depend on previous execution, the ``Task`` interface is ideal. But it also has more power and flexibility, allowing the user to guide the distribution of jobs, without having to assign Tasks to engines explicitly.
10
11 Starting the IPython controller and engines
12 ===========================================
13
14 To follow along with this tutorial, the user will need to start the IPython
15 controller and four IPython engines. The simplest way of doing this is to
16 use the ``ipcluster`` command::
17
18 $ ipcluster -n 4
19
20 For more detailed information about starting the controller and engines, see our :ref:`introduction <ip1par>` to using IPython for parallel computing.
21
22 The magic here is that this single controller and set of engines is running both the MultiEngine and ``Task`` interfaces simultaneously.
23
24 QuickStart Task Farming
25 =======================
26
27 First, a quick example of how to start running the most basic Tasks.
28 The first step is to import the IPython ``client`` module and then create a ``TaskClient`` instance::
29
30 In [1]: from IPython.kernel import client
31
32 In [2]: tc = client.TaskClient()
33
34 Then the user wrap the commands the user want to run in Tasks::
35
36 In [3]: tasklist = []
37 In [4]: for n in range(1000):
38 ... tasklist.append(client.Task("a = %i"%n, pull="a"))
39
40 The first argument of the ``Task`` constructor is a string, the command to be executed. The most important optional keyword argument is ``pull``, which can be a string or list of strings, and it specifies the variable names to be saved as results of the ``Task``.
41
42 Next, the user need to submit the Tasks to the ``TaskController`` with the ``TaskClient``::
43
44 In [5]: taskids = [ tc.run(t) for t in tasklist ]
45
46 This will give the user a list of the TaskIDs used by the controller to keep track of the Tasks and their results. Now at some point the user are going to want to get those results back. The ``barrier`` method allows the user to wait for the Tasks to finish running::
47
48 In [6]: tc.barrier(taskids)
49
50 This command will block until all the Tasks in ``taskids`` have finished. Now, the user probably want to look at the user's results::
51
52 In [7]: task_results = [ tc.get_task_result(taskid) for taskid in taskids ]
53
54 Now the user have a list of ``TaskResult`` objects, which have the actual result as a dictionary, but also keep track of some useful metadata about the ``Task``::
55
56 In [8]: tr = ``Task``_results[73]
57
58 In [9]: tr
59 Out[9]: ``TaskResult``[ID:73]:{'a':73}
60
61 In [10]: tr.engineid
62 Out[10]: 1
63
64 In [11]: tr.submitted, tr.completed, tr.duration
65 Out[11]: ("2008/03/08 03:41:42", "2008/03/08 03:41:44", 2.12345)
66
67 The actual results are stored in a dictionary, ``tr.results``, and a namespace object ``tr.ns`` which accesses the result keys by attribute::
68
69 In [12]: tr.results['a']
70 Out[12]: 73
71
72 In [13]: tr.ns.a
73 Out[13]: 73
74
75 That should cover the basics of running simple Tasks. There are several more powerful things the user can do with Tasks covered later. The most useful probably being using a ``MutiEngineClient`` interface to initialize all the engines with the import dependencies necessary to run the user's Tasks.
76
77 There are many options for running and managing Tasks. The best way to learn further about the ``Task`` interface is to study the examples in ``docs/examples``. If the user do so and learn a lots about this interface, we encourage the user to expand this documentation about the ``Task`` system.
78
79 Overview of the Task System
80 ===========================
81
82 The user's view of the ``Task`` system has three basic objects: The ``TaskClient``, the ``Task``, and the ``TaskResult``. The names of these three objects well indicate their role.
83
84 The ``TaskClient`` is the user's ``Task`` farming connection to the IPython cluster. Unlike the ``MultiEngineClient``, the ``TaskControler`` handles all the scheduling and distribution of work, so the ``TaskClient`` has no notion of engines, it just submits Tasks and requests their results. The Tasks are described as ``Task`` objects, and their results are wrapped in ``TaskResult`` objects. Thus, there are very few necessary methods for the user to manage.
85
86 Inside the task system is a Scheduler object, which assigns tasks to workers. The default scheduler is a simple FIFO queue. Subclassing the Scheduler should be easy, just implementing your own priority system.
87
88 The TaskClient
89 ==============
90
91 The ``TaskClient`` is the object the user use to connect to the ``Controller`` that is managing the user's Tasks. It is the analog of the ``MultiEngineClient`` for the standard IPython multiplexing interface. As with all client interfaces, the first step is to import the IPython Client Module::
92
93 In [1]: from IPython.kernel import client
94
95 Just as with the ``MultiEngineClient``, the user create the ``TaskClient`` with a tuple, containing the ip-address and port of the ``Controller``. the ``client`` module conveniently has the default address of the ``Task`` interface of the controller. Creating a default ``TaskClient`` object would be done with this::
96
97 In [2]: tc = client.TaskClient(client.default_task_address)
98
99 or, if the user want to specify a non default location of the ``Controller``, the user can specify explicitly::
100
101 In [3]: tc = client.TaskClient(("192.168.1.1", 10113))
102
103 As discussed earlier, the ``TaskClient`` only has a few basic methods.
104
105 * ``tc.run(task)``
106 ``run`` is the method by which the user submits Tasks. It takes exactly one argument, a ``Task`` object. All the advanced control of ``Task`` behavior is handled by properties of the ``Task`` object, rather than the submission command, so they will be discussed later in the `Task`_ section. ``run`` returns an integer, the ``Task``ID by which the ``Task`` and its results can be tracked and retrieved::
107
108 In [4]: ``Task``ID = tc.run(``Task``)
109
110 * ``tc.get_task_result(taskid, block=``False``)``
111 ``get_task_result`` is the method by which results are retrieved. It takes a single integer argument, the ``Task``ID`` of the result the user wish to retrieve. ``get_task_result`` also takes a keyword argument ``block``. ``block`` specifies whether the user actually want to wait for the result. If ``block`` is false, as it is by default, ``get_task_result`` will return immediately. If the ``Task`` has completed, it will return the ``TaskResult`` object for that ``Task``. But if the ``Task`` has not completed, it will return ``None``. If the user specify ``block=``True``, then ``get_task_result`` will wait for the ``Task`` to complete, and always return the ``TaskResult`` for the requested ``Task``.
112 * ``tc.barrier(taskid(s))``
113 ``barrier`` is a synchronization method. It takes exactly one argument, a ``Task``ID or list of taskIDs. ``barrier`` will block until all the specified Tasks have completed. In practice, a barrier is often called between the ``Task`` submission section of the code and the result gathering section::
114
115 In [5]: taskIDs = [ tc.run(``Task``) for ``Task`` in myTasks ]
116
117 In [6]: tc.get_task_result(taskIDs[-1]) is None
118 Out[6]: ``True``
119
120 In [7]: tc.barrier(``Task``ID)
121
122 In [8]: results = [ tc.get_task_result(tid) for tid in taskIDs ]
123
124 * ``tc.queue_status(verbose=``False``)``
125 ``queue_status`` is a method for querying the state of the ``TaskControler``. ``queue_status`` returns a dict of the form::
126
127 {'scheduled': Tasks that have been submitted but yet run
128 'pending' : Tasks that are currently running
129 'succeeded': Tasks that have completed successfully
130 'failed' : Tasks that have finished with a failure
131 }
132
133 if @verbose is not specified (or is ``False``), then the values of the dict are integers - the number of Tasks in each state. if @verbose is ``True``, then each element in the dict is a list of the taskIDs in that state::
134
135 In [8]: tc.queue_status()
136 Out[8]: {'scheduled': 4,
137 'pending' : 2,
138 'succeeded': 5,
139 'failed' : 1
140 }
141
142 In [9]: tc.queue_status(verbose=True)
143 Out[9]: {'scheduled': [8,9,10,11],
144 'pending' : [6,7],
145 'succeeded': [0,1,2,4,5],
146 'failed' : [3]
147 }
148
149 * ``tc.abort(taskid)``
150 ``abort`` allows the user to abort Tasks that have already been submitted. ``abort`` will always return immediately. If the ``Task`` has completed, ``abort`` will raise an ``IndexError ``Task`` Already Completed``. An obvious case for ``abort`` would be where the user submits a long-running ``Task`` with a number of retries (see ``Task``_ section for how to specify retries) in an interactive session, but realizes there has been a typo. The user can then abort the ``Task``, preventing certain failures from cluttering up the queue. It can also be used for parallel search-type problems, where only one ``Task`` will give the solution, so once the user find the solution, the user would want to abort all remaining Tasks to prevent wasted work.
151 * ``tc.spin()``
152 ``spin`` simply triggers the scheduler in the ``TaskControler``. Under most normal circumstances, this will do nothing. The primary known usage case involves the ``Task`` dependency (see `Dependencies`_). The dependency is a function of an Engine's ``properties``, but changing the ``properties`` via the ``MutliEngineClient`` does not trigger a reschedule event. The main example case for this requires the following event sequence:
153 * ``engine`` is available, ``Task`` is submitted, but ``engine`` does not have ``Task``'s dependencies.
154 * ``engine`` gets necessary dependencies while no new Tasks are submitted or completed.
155 * now ``engine`` can run ``Task``, but a ``Task`` event is required for the ``TaskControler`` to try scheduling ``Task`` again.
156
157 ``spin`` is just an empty ping method to ensure that the Controller has scheduled all available Tasks, and should not be needed under most normal circumstances.
158
159 That covers the ``TaskClient``, a simple interface to the cluster. With this, the user can submit jobs (and abort if necessary), request their results, synchronize on arbitrary subsets of jobs.
160
161 .. _task: The Task Object
162
163 The Task Object
164 ===============
165
166 The ``Task`` is the basic object for describing a job. It can be used in a very simple manner, where the user just specifies a command string to be executed as the ``Task``. The usage of this first argument is exactly the same as the ``execute`` method of the ``MultiEngine`` (in fact, ``execute`` is called to run the code)::
167
168 In [1]: t = client.Task("a = str(id)")
169
170 This ``Task`` would run, and store the string representation of the ``id`` element in ``a`` in each worker's namespace, but it is fairly useless because the user does not know anything about the state of the ``worker`` on which it ran at the time of retrieving results. It is important that each ``Task`` not expect the state of the ``worker`` to persist after the ``Task`` is completed.
171 There are many different situations for using ``Task`` Farming, and the ``Task`` object has many attributes for use in customizing the ``Task`` behavior. All of a ``Task``'s attributes may be specified in the constructor, through keyword arguments, or after ``Task`` construction through attribute assignment.
172
173 Data Attributes
174 ***************
175 It is likely that the user may want to move data around before or after executing the ``Task``. We provide methods of sending data to initialize the worker's namespace, and specifying what data to bring back as the ``Task``'s results.
176
177 * pull = []
178 The obvious case is as above, where ``t`` would execute and store the result of ``myfunc`` in ``a``, it is likely that the user would want to bring ``a`` back to their namespace. This is done through the ``pull`` attribute. ``pull`` can be a string or list of strings, and it specifies the names of variables to be retrieved. The ``TaskResult`` object retrieved by ``get_task_result`` will have a dictionary of keys and values, and the ``Task``'s ``pull`` attribute determines what goes into it::
179
180 In [2]: t = client.Task("a = str(id)", pull = "a")
181
182 In [3]: t = client.Task("a = str(id)", pull = ["a", "id"])
183
184 * push = {}
185 A user might also want to initialize some data into the namespace before the code part of the ``Task`` is run. Enter ``push``. ``push`` is a dictionary of key/value pairs to be loaded from the user's namespace into the worker's immediately before execution::
186
187 In [4]: t = client.Task("a = f(submitted)", push=dict(submitted=time.time()), pull="a")
188
189 push and pull result directly in calling an ``engine``'s ``push`` and ``pull`` methods before and after ``Task`` execution respectively, and thus their api is the same.
190
191 Namespace Cleaning
192 ******************
193 When a user is running a large number of Tasks, it is likely that the namespace of the worker's could become cluttered. Some Tasks might be sensitive to clutter, while others might be known to cause namespace pollution. For these reasons, Tasks have two boolean attributes for cleaning up the namespace.
194
195 * ``clear_after``
196 if clear_after is specified ``True``, the worker on which the ``Task`` was run will be reset (via ``engine.reset``) upon completion of the ``Task``. This can be useful for both Tasks that produce clutter or Tasks whose intermediate data one might wish to be kept private::
197
198 In [5]: t = client.Task("a = range(1e10)", pull = "a",clear_after=True)
199
200
201 * ``clear_before``
202 as one might guess, clear_before is identical to ``clear_after``, but it takes place before the ``Task`` is run. This ensures that the ``Task`` runs on a fresh worker::
203
204 In [6]: t = client.Task("a = globals()", pull = "a",clear_before=True)
205
206 Of course, a user can both at the same time, ensuring that all workers are clear except when they are currently running a job. Both of these default to ``False``.
207
208 Fault Tolerance
209 ***************
210 It is possible that Tasks might fail, and there are a variety of reasons this could happen. One might be that the worker it was running on disconnected, and there was nothing wrong with the ``Task`` itself. With the fault tolerance attributes of the ``Task``, the user can specify how many times to resubmit the ``Task``, and what to do if it never succeeds.
211
212 * ``retries``
213 ``retries`` is an integer, specifying the number of times a ``Task`` is to be retried. It defaults to zero. It is often a good idea for this number to be 1 or 2, to protect the ``Task`` from disconnecting engines, but not a large number. If a ``Task`` is failing 100 times, there is probably something wrong with the ``Task``. The canonical bad example:
214
215 In [7]: t = client.Task("os.kill(os.getpid(), 9)", retries=99)
216
217 This would actually take down 100 workers.
218
219 * ``recovery_task``
220 ``recovery_task`` is another ``Task`` object, to be run in the event of the original ``Task`` still failing after running out of retries. Since ``recovery_task`` is another ``Task`` object, it can have its own ``recovery_task``. The chain of Tasks is limitless, except loops are not allowed (that would be bad!).
221
222 Dependencies
223 ************
224 Dependencies are the most powerful part of the ``Task`` farming system, because it allows the user to do some classification of the workers, and guide the ``Task`` distribution without meddling with the controller directly. It makes use of two objects - the ``Task``'s ``depend`` attribute, and the engine's ``properties``. See the `MultiEngine`_ reference for how to use engine properties. The engine properties api exists for extending IPython, allowing conditional execution and new controllers that make decisions based on properties of its engines. Currently the ``Task`` dependency is the only internal use of the properties api.
225
226 .. _MultiEngine: ./parallel_multiengine
227
228 The ``depend`` attribute of a ``Task`` must be a function of exactly one argument, the worker's properties dictionary, and it should return ``True`` if the ``Task`` should be allowed to run on the worker and ``False`` if not. The usage in the controller is fault tolerant, so exceptions raised by ``Task.depend`` will be ignored and functionally equivalent to always returning ``False``. Tasks`` with invalid ``depend`` functions will never be assigned to a worker::
229
230 In [8]: def dep(properties):
231 ... return properties["RAM"] > 2**32 # have at least 4GB
232 In [9]: t = client.Task("a = bigfunc()", depend=dep)
233
234 It is important to note that assignment of values to the properties dict is done entirely by the user, either locally (in the engine) using the EngineAPI, or remotely, through the ``MultiEngineClient``'s get/set_properties methods.
235
236
237
238
239
240
@@ -0,0 +1,191 b''
1 Overview
2 ========
3
4 This document describes the steps required to install IPython. IPython is organized into a number of subpackages, each of which has its own dependencies. All of the subpackages come with IPython, so you don't need to download and install them separately. However, to use a given subpackage, you will need to install all of its dependencies.
5
6
7 Please let us know if you have problems installing IPython or any of its
8 dependencies. IPython requires Python version 2.4 or greater. We have not tested
9 IPython with the upcoming 2.6 or 3.0 versions.
10
11 .. warning::
12
13 IPython will not work with Python 2.3 or below.
14
15 Some of the installation approaches use the :mod:`setuptools` package and its :command:`easy_install` command line program. In many scenarios, this provides the most simple method of installing IPython and its dependencies. It is not required though. More information about :mod:`setuptools` can be found on its website.
16
17 More general information about installing Python packages can be found in Python's documentation at http://www.python.org/doc/.
18
19 Installing IPython itself
20 =========================
21
22 Given a properly built Python, the basic interactive IPython shell will work with no external dependencies. However, some Python distributions (particularly on Windows and OS X), don't come with a working :mod:`readline` module. The IPython shell will work without :mod:`readline`, but will lack many features that users depend on, such as tab completion and command line editing. See below for details of how to make sure you have a working :mod:`readline`.
23
24 Installation using easy_install
25 -------------------------------
26
27 If you have :mod:`setuptools` installed, the easiest way of getting IPython is to simple use :command:`easy_install`::
28
29 $ easy_install IPython
30
31 That's it.
32
33 Installation from source
34 ------------------------
35
36 If you don't want to use :command:`easy_install`, or don't have it installed, just grab the latest stable build of IPython from `here <http://ipython.scipy.org/dist/>`_. Then do the following::
37
38 $ tar -xzf ipython.tar.gz
39 $ cd ipython
40 $ python setup.py install
41
42 If you are installing to a location (like ``/usr/local``) that requires higher permissions, you may need to run the last command with :command:`sudo`.
43
44 Windows
45 -------
46
47 There are a few caveats for Windows users. The main issue is that a basic ``python setup.py install`` approach won't create ``.bat`` file or Start Menu shortcuts, which most users want. To get an installation with these, there are two choices:
48
49 1. Install using :command:`easy_install`.
50
51 2. Install using our binary ``.exe`` Windows installer, which can be found at `here <http://ipython.scipy.org/dist/>`_
52
53 3. Install from source, but using :mod:`setuptools` (``python setupegg.py install``).
54
55 Installing the development version
56 ----------------------------------
57
58 It is also possible to install the development version of IPython from our `Bazaar <http://bazaar-vcs.org/>`_ source code
59 repository. To do this you will need to have Bazaar installed on your system. Then just do::
60
61 $ bzr branch lp:ipython
62 $ cd ipython
63 $ python setup.py install
64
65 Again, this last step on Windows won't create ``.bat`` files or Start Menu shortcuts, so you will have to use one of the other approaches listed above.
66
67 Some users want to be able to follow the development branch as it changes. If you have :mod:`setuptools` installed, this is easy. Simply replace the last step by::
68
69 $ python setupegg.py develop
70
71 This creates links in the right places and installs the command line script to the appropriate places. Then, if you want to update your IPython at any time, just do::
72
73 $ bzr pull
74
75 Basic optional dependencies
76 ===========================
77
78 There are a number of basic optional dependencies that most users will want to get. These are:
79
80 * readline (for command line editing, tab completion, etc.)
81 * nose (to run the IPython test suite)
82 * pexpect (to use things like irunner)
83
84 If you are comfortable installing these things yourself, have at it, otherwise read on for more details.
85
86 readline
87 --------
88
89 In principle, all Python distributions should come with a working :mod:`readline` module. But, reality is not quite that simple. There are two common situations where you won't have a working :mod:`readline` module:
90
91 * If you are using the built-in Python on Mac OS X.
92
93 * If you are running Windows, which doesn't have a :mod:`readline` module.
94
95 On OS X, the built-in Python doesn't not have :mod:`readline` because of license issues. Starting with OS X 10.5 (Leopard), Apple's built-in Python has a BSD-licensed not-quite-compatible readline replacement. As of IPython 0.9, many of the issues related to the differences between readline and libedit have been resolved. For many users, libedit may be sufficient.
96
97 Most users on OS X will want to get the full :mod:`readline` module. To get a working :mod:`readline` module, just do (with :mod:`setuptools` installed)::
98
99 $ easy_install readline
100
101 .. note:
102
103 Other Python distributions on OS X (such as fink, MacPorts and the
104 official python.org binaries) already have readline installed so
105 you don't have to do this step.
106
107 If needed, the readline egg can be build and installed from source (see the wiki page at http://ipython.scipy.org/moin/InstallationOSXLeopard).
108
109 On Windows, you will need the PyReadline module. PyReadline is a separate, Windows only implementation of readline that uses native Windows calls through :mod:`ctypes`. The easiest way of installing PyReadline is you use the binary installer available `here <http://ipython.scipy.org/dist/>`_. The :mod:`ctypes` module, which comes with Python 2.5 and greater, is required by PyReadline. It is available for Python 2.4 at http://python.net/crew/theller/ctypes.
110
111 nose
112 ----
113
114 To run the IPython test suite you will need the :mod:`nose` package. Nose provides a great way of sniffing out and running all of the IPython tests. The simplest way of getting nose, is to use :command:`easy_install`::
115
116 $ easy_install nose
117
118 Another way of getting this is to do::
119
120 $ easy_install IPython[test]
121
122 For more installation options, see the `nose website <http://somethingaboutorange.com/mrl/projects/nose/>`_. Once you have nose installed, you can run IPython's test suite using the iptest command::
123
124 $ iptest
125
126
127 pexpect
128 -------
129
130 The `pexpect <http://www.noah.org/wiki/Pexpect>`_ package is used in IPython's :command:`irunner` script. On Unix platforms (including OS X), just do::
131
132 $ easy_install pexpect
133
134 Windows users are out of luck as pexpect does not run there.
135
136 Dependencies for IPython.kernel (parallel computing)
137 ====================================================
138
139 The IPython kernel provides a nice architecture for parallel computing. The main focus of this architecture is on interactive parallel computing. These features require a number of additional packages:
140
141 * zope.interface (yep, we use interfaces)
142 * Twisted (asynchronous networking framework)
143 * Foolscap (a nice, secure network protocol)
144 * pyOpenSSL (security for network connections)
145
146 On a Unix style platform (including OS X), if you want to use :mod:`setuptools`, you can just do::
147
148 $ easy_install IPython[kernel] # the first three
149 $ easy_install IPython[security] # pyOpenSSL
150
151 zope.interface and Twisted
152 --------------------------
153
154 On Unix style platforms (including OS X), the simplest way of getting the these is to use :command:`easy_install`::
155
156 $ easy_install zope.interface
157 $ easy_install Twisted
158
159 Of course, you can also download the source tarballs from the `Twisted website <twistedmatrix.org>`_ and the `zope.interface page at PyPI <http://pypi.python.org/pypi/zope.interface>`_ and do the usual ``python setup.py install`` if you prefer.
160
161 Windows is a bit different. For zope.interface and Twisted, simply get the latest binary ``.exe`` installer from the Twisted website. This installer includes both zope.interface and Twisted and should just work.
162
163 Foolscap
164 --------
165
166 Foolscap uses Twisted to provide a very nice secure RPC protocol that we use to implement our parallel computing features.
167
168 On all platforms a simple::
169
170 $ easy_install foolscap
171
172 should work. You can also download the source tarballs from the `Foolscap website <http://foolscap.lothar.com/trac>`_ and do ``python setup.py install`` if you prefer.
173
174 pyOpenSSL
175 ---------
176
177 IPython requires an older version of pyOpenSSL (0.6 rather than the current 0.7). There are a couple of options for getting this:
178
179 1. Most Linux distributions have packages for pyOpenSSL.
180 2. The built-in Python 2.5 on OS X 10.5 already has it installed.
181 3. There are source tarballs on the pyOpenSSL website. On Unix-like
182 platforms, these can be built using ``python seutp.py install``.
183 4. There is also a binary ``.exe`` Windows installer on the `pyOpenSSL website <http://pyopenssl.sourceforge.net/>`_.
184
185 Dependencies for IPython.frontend (the IPython GUI)
186 ===================================================
187
188 wxPython
189 --------
190
191 Starting with IPython 0.9, IPython has a new IPython.frontend package that has a nice wxPython based IPython GUI. As you would expect, this GUI requires wxPython. Most Linux distributions have wxPython packages available and the built-in Python on OS X comes with wxPython preinstalled. For Windows, a binary installer is available on the `wxPython website <http://www.wxpython.org/>`_. No newline at end of file
@@ -0,0 +1,423 b''
1 """
2 Defines a docutils directive for inserting inheritance diagrams.
3
4 Provide the directive with one or more classes or modules (separated
5 by whitespace). For modules, all of the classes in that module will
6 be used.
7
8 Example::
9
10 Given the following classes:
11
12 class A: pass
13 class B(A): pass
14 class C(A): pass
15 class D(B, C): pass
16 class E(B): pass
17
18 .. inheritance-diagram: D E
19
20 Produces a graph like the following:
21
22 A
23 / \
24 B C
25 / \ /
26 E D
27
28 The graph is inserted as a PNG+image map into HTML and a PDF in
29 LaTeX.
30 """
31
32 import inspect
33 import os
34 import re
35 import subprocess
36 try:
37 from hashlib import md5
38 except ImportError:
39 from md5 import md5
40
41 from docutils.nodes import Body, Element
42 from docutils.writers.html4css1 import HTMLTranslator
43 from sphinx.latexwriter import LaTeXTranslator
44 from docutils.parsers.rst import directives
45 from sphinx.roles import xfileref_role
46
47 class DotException(Exception):
48 pass
49
50 class InheritanceGraph(object):
51 """
52 Given a list of classes, determines the set of classes that
53 they inherit from all the way to the root "object", and then
54 is able to generate a graphviz dot graph from them.
55 """
56 def __init__(self, class_names, show_builtins=False):
57 """
58 *class_names* is a list of child classes to show bases from.
59
60 If *show_builtins* is True, then Python builtins will be shown
61 in the graph.
62 """
63 self.class_names = class_names
64 self.classes = self._import_classes(class_names)
65 self.all_classes = self._all_classes(self.classes)
66 if len(self.all_classes) == 0:
67 raise ValueError("No classes found for inheritance diagram")
68 self.show_builtins = show_builtins
69
70 py_sig_re = re.compile(r'''^([\w.]*\.)? # class names
71 (\w+) \s* $ # optionally arguments
72 ''', re.VERBOSE)
73
74 def _import_class_or_module(self, name):
75 """
76 Import a class using its fully-qualified *name*.
77 """
78 try:
79 path, base = self.py_sig_re.match(name).groups()
80 except:
81 raise ValueError(
82 "Invalid class or module '%s' specified for inheritance diagram" % name)
83 fullname = (path or '') + base
84 path = (path and path.rstrip('.'))
85 if not path:
86 path = base
87 if not path:
88 raise ValueError(
89 "Invalid class or module '%s' specified for inheritance diagram" % name)
90 try:
91 module = __import__(path, None, None, [])
92 except ImportError:
93 raise ValueError(
94 "Could not import class or module '%s' specified for inheritance diagram" % name)
95
96 try:
97 todoc = module
98 for comp in fullname.split('.')[1:]:
99 todoc = getattr(todoc, comp)
100 except AttributeError:
101 raise ValueError(
102 "Could not find class or module '%s' specified for inheritance diagram" % name)
103
104 # If a class, just return it
105 if inspect.isclass(todoc):
106 return [todoc]
107 elif inspect.ismodule(todoc):
108 classes = []
109 for cls in todoc.__dict__.values():
110 if inspect.isclass(cls) and cls.__module__ == todoc.__name__:
111 classes.append(cls)
112 return classes
113 raise ValueError(
114 "'%s' does not resolve to a class or module" % name)
115
116 def _import_classes(self, class_names):
117 """
118 Import a list of classes.
119 """
120 classes = []
121 for name in class_names:
122 classes.extend(self._import_class_or_module(name))
123 return classes
124
125 def _all_classes(self, classes):
126 """
127 Return a list of all classes that are ancestors of *classes*.
128 """
129 all_classes = {}
130
131 def recurse(cls):
132 all_classes[cls] = None
133 for c in cls.__bases__:
134 if c not in all_classes:
135 recurse(c)
136
137 for cls in classes:
138 recurse(cls)
139
140 return all_classes.keys()
141
142 def class_name(self, cls, parts=0):
143 """
144 Given a class object, return a fully-qualified name. This
145 works for things I've tested in matplotlib so far, but may not
146 be completely general.
147 """
148 module = cls.__module__
149 if module == '__builtin__':
150 fullname = cls.__name__
151 else:
152 fullname = "%s.%s" % (module, cls.__name__)
153 if parts == 0:
154 return fullname
155 name_parts = fullname.split('.')
156 return '.'.join(name_parts[-parts:])
157
158 def get_all_class_names(self):
159 """
160 Get all of the class names involved in the graph.
161 """
162 return [self.class_name(x) for x in self.all_classes]
163
164 # These are the default options for graphviz
165 default_graph_options = {
166 "rankdir": "LR",
167 "size": '"8.0, 12.0"'
168 }
169 default_node_options = {
170 "shape": "box",
171 "fontsize": 10,
172 "height": 0.25,
173 "fontname": "Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",
174 "style": '"setlinewidth(0.5)"'
175 }
176 default_edge_options = {
177 "arrowsize": 0.5,
178 "style": '"setlinewidth(0.5)"'
179 }
180
181 def _format_node_options(self, options):
182 return ','.join(["%s=%s" % x for x in options.items()])
183 def _format_graph_options(self, options):
184 return ''.join(["%s=%s;\n" % x for x in options.items()])
185
186 def generate_dot(self, fd, name, parts=0, urls={},
187 graph_options={}, node_options={},
188 edge_options={}):
189 """
190 Generate a graphviz dot graph from the classes that
191 were passed in to __init__.
192
193 *fd* is a Python file-like object to write to.
194
195 *name* is the name of the graph
196
197 *urls* is a dictionary mapping class names to http urls
198
199 *graph_options*, *node_options*, *edge_options* are
200 dictionaries containing key/value pairs to pass on as graphviz
201 properties.
202 """
203 g_options = self.default_graph_options.copy()
204 g_options.update(graph_options)
205 n_options = self.default_node_options.copy()
206 n_options.update(node_options)
207 e_options = self.default_edge_options.copy()
208 e_options.update(edge_options)
209
210 fd.write('digraph %s {\n' % name)
211 fd.write(self._format_graph_options(g_options))
212
213 for cls in self.all_classes:
214 if not self.show_builtins and cls in __builtins__.values():
215 continue
216
217 name = self.class_name(cls, parts)
218
219 # Write the node
220 this_node_options = n_options.copy()
221 url = urls.get(self.class_name(cls))
222 if url is not None:
223 this_node_options['URL'] = '"%s"' % url
224 fd.write(' "%s" [%s];\n' %
225 (name, self._format_node_options(this_node_options)))
226
227 # Write the edges
228 for base in cls.__bases__:
229 if not self.show_builtins and base in __builtins__.values():
230 continue
231
232 base_name = self.class_name(base, parts)
233 fd.write(' "%s" -> "%s" [%s];\n' %
234 (base_name, name,
235 self._format_node_options(e_options)))
236 fd.write('}\n')
237
238 def run_dot(self, args, name, parts=0, urls={},
239 graph_options={}, node_options={}, edge_options={}):
240 """
241 Run graphviz 'dot' over this graph, returning whatever 'dot'
242 writes to stdout.
243
244 *args* will be passed along as commandline arguments.
245
246 *name* is the name of the graph
247
248 *urls* is a dictionary mapping class names to http urls
249
250 Raises DotException for any of the many os and
251 installation-related errors that may occur.
252 """
253 try:
254 dot = subprocess.Popen(['dot'] + list(args),
255 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
256 close_fds=True)
257 except OSError:
258 raise DotException("Could not execute 'dot'. Are you sure you have 'graphviz' installed?")
259 except ValueError:
260 raise DotException("'dot' called with invalid arguments")
261 except:
262 raise DotException("Unexpected error calling 'dot'")
263
264 self.generate_dot(dot.stdin, name, parts, urls, graph_options,
265 node_options, edge_options)
266 dot.stdin.close()
267 result = dot.stdout.read()
268 returncode = dot.wait()
269 if returncode != 0:
270 raise DotException("'dot' returned the errorcode %d" % returncode)
271 return result
272
273 class inheritance_diagram(Body, Element):
274 """
275 A docutils node to use as a placeholder for the inheritance
276 diagram.
277 """
278 pass
279
280 def inheritance_diagram_directive_run(class_names, options, state):
281 """
282 Run when the inheritance_diagram directive is first encountered.
283 """
284 node = inheritance_diagram()
285
286 # Create a graph starting with the list of classes
287 graph = InheritanceGraph(class_names)
288
289 # Create xref nodes for each target of the graph's image map and
290 # add them to the doc tree so that Sphinx can resolve the
291 # references to real URLs later. These nodes will eventually be
292 # removed from the doctree after we're done with them.
293 for name in graph.get_all_class_names():
294 refnodes, x = xfileref_role(
295 'class', ':class:`%s`' % name, name, 0, state)
296 node.extend(refnodes)
297 # Store the graph object so we can use it to generate the
298 # dot file later
299 node['graph'] = graph
300 # Store the original content for use as a hash
301 node['parts'] = options.get('parts', 0)
302 node['content'] = " ".join(class_names)
303 return [node]
304
305 def get_graph_hash(node):
306 return md5(node['content'] + str(node['parts'])).hexdigest()[-10:]
307
308 def html_output_graph(self, node):
309 """
310 Output the graph for HTML. This will insert a PNG with clickable
311 image map.
312 """
313 graph = node['graph']
314 parts = node['parts']
315
316 graph_hash = get_graph_hash(node)
317 name = "inheritance%s" % graph_hash
318 png_path = os.path.join('_static', name + ".png")
319
320 path = '_static'
321 source = self.document.attributes['source']
322 count = source.split('/doc/')[-1].count('/')
323 for i in range(count):
324 if os.path.exists(path): break
325 path = '../'+path
326 path = '../'+path #specifically added for matplotlib
327
328 # Create a mapping from fully-qualified class names to URLs.
329 urls = {}
330 for child in node:
331 if child.get('refuri') is not None:
332 urls[child['reftitle']] = child.get('refuri')
333 elif child.get('refid') is not None:
334 urls[child['reftitle']] = '#' + child.get('refid')
335
336 # These arguments to dot will save a PNG file to disk and write
337 # an HTML image map to stdout.
338 image_map = graph.run_dot(['-Tpng', '-o%s' % png_path, '-Tcmapx'],
339 name, parts, urls)
340 return ('<img src="%s/%s.png" usemap="#%s" class="inheritance"/>%s' %
341 (path, name, name, image_map))
342
343 def latex_output_graph(self, node):
344 """
345 Output the graph for LaTeX. This will insert a PDF.
346 """
347 graph = node['graph']
348 parts = node['parts']
349
350 graph_hash = get_graph_hash(node)
351 name = "inheritance%s" % graph_hash
352 pdf_path = os.path.join('_static', name + ".pdf")
353
354 graph.run_dot(['-Tpdf', '-o%s' % pdf_path],
355 name, parts, graph_options={'size': '"6.0,6.0"'})
356 return '\\includegraphics{../../%s}' % pdf_path
357
358 def visit_inheritance_diagram(inner_func):
359 """
360 This is just a wrapper around html/latex_output_graph to make it
361 easier to handle errors and insert warnings.
362 """
363 def visitor(self, node):
364 try:
365 content = inner_func(self, node)
366 except DotException, e:
367 # Insert the exception as a warning in the document
368 warning = self.document.reporter.warning(str(e), line=node.line)
369 warning.parent = node
370 node.children = [warning]
371 else:
372 source = self.document.attributes['source']
373 self.body.append(content)
374 node.children = []
375 return visitor
376
377 def do_nothing(self, node):
378 pass
379
380 options_spec = {
381 'parts': directives.nonnegative_int
382 }
383
384 # Deal with the old and new way of registering directives
385 try:
386 from docutils.parsers.rst import Directive
387 except ImportError:
388 from docutils.parsers.rst.directives import _directives
389 def inheritance_diagram_directive(name, arguments, options, content, lineno,
390 content_offset, block_text, state,
391 state_machine):
392 return inheritance_diagram_directive_run(arguments, options, state)
393 inheritance_diagram_directive.__doc__ = __doc__
394 inheritance_diagram_directive.arguments = (1, 100, 0)
395 inheritance_diagram_directive.options = options_spec
396 inheritance_diagram_directive.content = 0
397 _directives['inheritance-diagram'] = inheritance_diagram_directive
398 else:
399 class inheritance_diagram_directive(Directive):
400 has_content = False
401 required_arguments = 1
402 optional_arguments = 100
403 final_argument_whitespace = False
404 option_spec = options_spec
405
406 def run(self):
407 return inheritance_diagram_directive_run(
408 self.arguments, self.options, self.state)
409 inheritance_diagram_directive.__doc__ = __doc__
410
411 directives.register_directive('inheritance-diagram',
412 inheritance_diagram_directive)
413
414 def setup(app):
415 app.add_node(inheritance_diagram)
416
417 HTMLTranslator.visit_inheritance_diagram = \
418 visit_inheritance_diagram(html_output_graph)
419 HTMLTranslator.depart_inheritance_diagram = do_nothing
420
421 LaTeXTranslator.visit_inheritance_diagram = \
422 visit_inheritance_diagram(latex_output_graph)
423 LaTeXTranslator.depart_inheritance_diagram = do_nothing
@@ -0,0 +1,75 b''
1 from pygments.lexer import Lexer, do_insertions
2 from pygments.lexers.agile import PythonConsoleLexer, PythonLexer, \
3 PythonTracebackLexer
4 from pygments.token import Comment, Generic
5 from sphinx import highlighting
6 import re
7
8 line_re = re.compile('.*?\n')
9
10 class IPythonConsoleLexer(Lexer):
11 """
12 For IPython console output or doctests, such as:
13
14 Tracebacks are not currently supported.
15
16 .. sourcecode:: ipython
17
18 In [1]: a = 'foo'
19
20 In [2]: a
21 Out[2]: 'foo'
22
23 In [3]: print a
24 foo
25
26 In [4]: 1 / 0
27 """
28 name = 'IPython console session'
29 aliases = ['ipython']
30 mimetypes = ['text/x-ipython-console']
31 input_prompt = re.compile("(In \[[0-9]+\]: )|( \.\.\.+:)")
32 output_prompt = re.compile("(Out\[[0-9]+\]: )|( \.\.\.+:)")
33 continue_prompt = re.compile(" \.\.\.+:")
34 tb_start = re.compile("\-+")
35
36 def get_tokens_unprocessed(self, text):
37 pylexer = PythonLexer(**self.options)
38 tblexer = PythonTracebackLexer(**self.options)
39
40 curcode = ''
41 insertions = []
42 for match in line_re.finditer(text):
43 line = match.group()
44 input_prompt = self.input_prompt.match(line)
45 continue_prompt = self.continue_prompt.match(line.rstrip())
46 output_prompt = self.output_prompt.match(line)
47 if line.startswith("#"):
48 insertions.append((len(curcode),
49 [(0, Comment, line)]))
50 elif input_prompt is not None:
51 insertions.append((len(curcode),
52 [(0, Generic.Prompt, input_prompt.group())]))
53 curcode += line[input_prompt.end():]
54 elif continue_prompt is not None:
55 insertions.append((len(curcode),
56 [(0, Generic.Prompt, continue_prompt.group())]))
57 curcode += line[continue_prompt.end():]
58 elif output_prompt is not None:
59 insertions.append((len(curcode),
60 [(0, Generic.Output, output_prompt.group())]))
61 curcode += line[output_prompt.end():]
62 else:
63 if curcode:
64 for item in do_insertions(insertions,
65 pylexer.get_tokens_unprocessed(curcode)):
66 yield item
67 curcode = ''
68 insertions = []
69 yield match.start(), Generic.Output, line
70 if curcode:
71 for item in do_insertions(insertions,
72 pylexer.get_tokens_unprocessed(curcode)):
73 yield item
74
75 highlighting.lexers['ipython'] = IPythonConsoleLexer()
@@ -0,0 +1,87 b''
1 #
2 # A pair of directives for inserting content that will only appear in
3 # either html or latex.
4 #
5
6 from docutils.nodes import Body, Element
7 from docutils.writers.html4css1 import HTMLTranslator
8 from sphinx.latexwriter import LaTeXTranslator
9 from docutils.parsers.rst import directives
10
11 class html_only(Body, Element):
12 pass
13
14 class latex_only(Body, Element):
15 pass
16
17 def run(content, node_class, state, content_offset):
18 text = '\n'.join(content)
19 node = node_class(text)
20 state.nested_parse(content, content_offset, node)
21 return [node]
22
23 try:
24 from docutils.parsers.rst import Directive
25 except ImportError:
26 from docutils.parsers.rst.directives import _directives
27
28 def html_only_directive(name, arguments, options, content, lineno,
29 content_offset, block_text, state, state_machine):
30 return run(content, html_only, state, content_offset)
31
32 def latex_only_directive(name, arguments, options, content, lineno,
33 content_offset, block_text, state, state_machine):
34 return run(content, latex_only, state, content_offset)
35
36 for func in (html_only_directive, latex_only_directive):
37 func.content = 1
38 func.options = {}
39 func.arguments = None
40
41 _directives['htmlonly'] = html_only_directive
42 _directives['latexonly'] = latex_only_directive
43 else:
44 class OnlyDirective(Directive):
45 has_content = True
46 required_arguments = 0
47 optional_arguments = 0
48 final_argument_whitespace = True
49 option_spec = {}
50
51 def run(self):
52 self.assert_has_content()
53 return run(self.content, self.node_class,
54 self.state, self.content_offset)
55
56 class HtmlOnlyDirective(OnlyDirective):
57 node_class = html_only
58
59 class LatexOnlyDirective(OnlyDirective):
60 node_class = latex_only
61
62 directives.register_directive('htmlonly', HtmlOnlyDirective)
63 directives.register_directive('latexonly', LatexOnlyDirective)
64
65 def setup(app):
66 app.add_node(html_only)
67 app.add_node(latex_only)
68
69 # Add visit/depart methods to HTML-Translator:
70 def visit_perform(self, node):
71 pass
72 def depart_perform(self, node):
73 pass
74 def visit_ignore(self, node):
75 node.children = []
76 def depart_ignore(self, node):
77 node.children = []
78
79 HTMLTranslator.visit_html_only = visit_perform
80 HTMLTranslator.depart_html_only = depart_perform
81 HTMLTranslator.visit_latex_only = visit_ignore
82 HTMLTranslator.depart_latex_only = depart_ignore
83
84 LaTeXTranslator.visit_html_only = visit_ignore
85 LaTeXTranslator.depart_html_only = depart_ignore
86 LaTeXTranslator.visit_latex_only = visit_perform
87 LaTeXTranslator.depart_latex_only = depart_perform
@@ -0,0 +1,155 b''
1 """A special directive for including a matplotlib plot.
2
3 Given a path to a .py file, it includes the source code inline, then:
4
5 - On HTML, will include a .png with a link to a high-res .png.
6
7 - On LaTeX, will include a .pdf
8
9 This directive supports all of the options of the `image` directive,
10 except for `target` (since plot will add its own target).
11
12 Additionally, if the :include-source: option is provided, the literal
13 source will be included inline, as well as a link to the source.
14 """
15
16 import sys, os, glob, shutil
17 from docutils.parsers.rst import directives
18
19 try:
20 # docutils 0.4
21 from docutils.parsers.rst.directives.images import align
22 except ImportError:
23 # docutils 0.5
24 from docutils.parsers.rst.directives.images import Image
25 align = Image.align
26
27
28 import matplotlib
29 import IPython.Shell
30 matplotlib.use('Agg')
31 import matplotlib.pyplot as plt
32
33 mplshell = IPython.Shell.MatplotlibShell('mpl')
34
35 options = {'alt': directives.unchanged,
36 'height': directives.length_or_unitless,
37 'width': directives.length_or_percentage_or_unitless,
38 'scale': directives.nonnegative_int,
39 'align': align,
40 'class': directives.class_option,
41 'include-source': directives.flag }
42
43 template = """
44 .. htmlonly::
45
46 [`source code <../%(srcdir)s/%(basename)s.py>`__,
47 `png <../%(srcdir)s/%(basename)s.hires.png>`__,
48 `pdf <../%(srcdir)s/%(basename)s.pdf>`__]
49
50 .. image:: ../%(srcdir)s/%(basename)s.png
51 %(options)s
52
53 .. latexonly::
54 .. image:: ../%(srcdir)s/%(basename)s.pdf
55 %(options)s
56
57 """
58
59 def makefig(fullpath, outdir):
60 """
61 run a pyplot script and save the low and high res PNGs and a PDF in _static
62 """
63
64 fullpath = str(fullpath) # todo, why is unicode breaking this
65 formats = [('png', 100),
66 ('hires.png', 200),
67 ('pdf', 72),
68 ]
69
70 basedir, fname = os.path.split(fullpath)
71 basename, ext = os.path.splitext(fname)
72 all_exists = True
73
74 if basedir != outdir:
75 shutil.copyfile(fullpath, os.path.join(outdir, fname))
76
77 for format, dpi in formats:
78 outname = os.path.join(outdir, '%s.%s' % (basename, format))
79 if not os.path.exists(outname):
80 all_exists = False
81 break
82
83 if all_exists:
84 print ' already have %s'%fullpath
85 return
86
87 print ' building %s'%fullpath
88 plt.close('all') # we need to clear between runs
89 matplotlib.rcdefaults()
90
91 mplshell.magic_run(fullpath)
92 for format, dpi in formats:
93 outname = os.path.join(outdir, '%s.%s' % (basename, format))
94 if os.path.exists(outname): continue
95 plt.savefig(outname, dpi=dpi)
96
97 def run(arguments, options, state_machine, lineno):
98 reference = directives.uri(arguments[0])
99 basedir, fname = os.path.split(reference)
100 basename, ext = os.path.splitext(fname)
101
102 # todo - should we be using the _static dir for the outdir, I am
103 # not sure we want to corrupt that dir with autogenerated files
104 # since it also has permanent files in it which makes it difficult
105 # to clean (save an rm -rf followed by and svn up)
106 srcdir = 'pyplots'
107
108 makefig(os.path.join(srcdir, reference), srcdir)
109
110 # todo: it is not great design to assume the makefile is putting
111 # the figs into the right place, so we may want to do that here instead.
112
113 if options.has_key('include-source'):
114 lines = ['.. literalinclude:: ../pyplots/%(reference)s' % locals()]
115 del options['include-source']
116 else:
117 lines = []
118
119 options = [' :%s: %s' % (key, val) for key, val in
120 options.items()]
121 options = "\n".join(options)
122
123 lines.extend((template % locals()).split('\n'))
124
125 state_machine.insert_input(
126 lines, state_machine.input_lines.source(0))
127 return []
128
129
130 try:
131 from docutils.parsers.rst import Directive
132 except ImportError:
133 from docutils.parsers.rst.directives import _directives
134
135 def plot_directive(name, arguments, options, content, lineno,
136 content_offset, block_text, state, state_machine):
137 return run(arguments, options, state_machine, lineno)
138 plot_directive.__doc__ = __doc__
139 plot_directive.arguments = (1, 0, 1)
140 plot_directive.options = options
141
142 _directives['plot'] = plot_directive
143 else:
144 class plot_directive(Directive):
145 required_arguments = 1
146 optional_arguments = 0
147 final_argument_whitespace = True
148 option_spec = options
149 def run(self):
150 return run(self.arguments, self.options,
151 self.state_machine, self.lineno)
152 plot_directive.__doc__ = __doc__
153
154 directives.register_directive('plot', plot_directive)
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)
@@ -1,7 +1,5 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project.
2 """Release data for the IPython project."""
3
4 $Id: Release.py 3002 2008-02-01 07:17:00Z fperez $"""
5
3
6 #*****************************************************************************
4 #*****************************************************************************
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
5 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
@@ -23,9 +21,9 b" name = 'ipython'"
23 # bdist_deb does not accept underscores (a Debian convention).
21 # bdist_deb does not accept underscores (a Debian convention).
24
22
25 development = False # change this to False to do a release
23 development = False # change this to False to do a release
26 version_base = '0.9.rc1'
24 version_base = '0.9.1'
27 branch = 'ipython'
25 branch = 'ipython'
28 revision = '1124'
26 revision = '1143'
29
27
30 if development:
28 if development:
31 if branch == 'ipython':
29 if branch == 'ipython':
@@ -36,45 +34,69 b' else:'
36 version = version_base
34 version = version_base
37
35
38
36
39 description = "Tools for interactive development in Python."
37 description = "An interactive computing environment for Python"
40
38
41 long_description = \
39 long_description = \
42 """
40 """
43 IPython provides a replacement for the interactive Python interpreter with
41 The goal of IPython is to create a comprehensive environment for
44 extra functionality.
42 interactive and exploratory computing. To support this goal, IPython
43 has two main components:
44
45 * An enhanced interactive Python shell.
46
47 * An architecture for interactive parallel computing.
48
49 The enhanced interactive Python shell has the following main features:
50
51 * Comprehensive object introspection.
52
53 * Input history, persistent across sessions.
45
54
46 Main features:
55 * Caching of output results during a session with automatically generated
56 references.
47
57
48 * Comprehensive object introspection.
58 * Readline based name completion.
49
59
50 * Input history, persistent across sessions.
60 * Extensible system of 'magic' commands for controlling the environment and
61 performing many tasks related either to IPython or the operating system.
51
62
52 * Caching of output results during a session with automatically generated
63 * Configuration system with easy switching between different setups (simpler
53 references.
64 than changing $PYTHONSTARTUP environment variables every time).
54
65
55 * Readline based name completion.
66 * Session logging and reloading.
56
67
57 * Extensible system of 'magic' commands for controlling the environment and
68 * Extensible syntax processing for special purpose situations.
58 performing many tasks related either to IPython or the operating system.
59
69
60 * Configuration system with easy switching between different setups (simpler
70 * Access to the system shell with user-extensible alias system.
61 than changing $PYTHONSTARTUP environment variables every time).
62
71
63 * Session logging and reloading.
72 * Easily embeddable in other Python programs and wxPython GUIs.
64
73
65 * Extensible syntax processing for special purpose situations.
74 * Integrated access to the pdb debugger and the Python profiler.
66
75
67 * Access to the system shell with user-extensible alias system.
76 The parallel computing architecture has the following main features:
68
77
69 * Easily embeddable in other Python programs.
78 * Quickly parallelize Python code from an interactive Python/IPython session.
70
79
71 * Integrated access to the pdb debugger and the Python profiler.
80 * A flexible and dynamic process model that be deployed on anything from
81 multicore workstations to supercomputers.
72
82
73 The latest development version is always available at the IPython subversion
83 * An architecture that supports many different styles of parallelism, from
74 repository_.
84 message passing to task farming.
75
85
76 .. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev
86 * Both blocking and fully asynchronous interfaces.
77 """
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 """
78
100
79 license = 'BSD'
101 license = 'BSD'
80
102
@@ -16,13 +16,11 b' __docformat__ = "restructuredtext en"'
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 import os
18 import os
19 from IPython.config.cutils import get_home_dir, get_ipython_dir
19 from os.path import join as pjoin
20
21 from IPython.genutils import get_home_dir, get_ipython_dir
20 from IPython.external.configobj import ConfigObj
22 from IPython.external.configobj import ConfigObj
21
23
22 # Traitlets config imports
23 from IPython.config import traitlets
24 from IPython.config.config import *
25 from traitlets import *
26
24
27 class ConfigObjManager(object):
25 class ConfigObjManager(object):
28
26
@@ -53,7 +51,7 b' class ConfigObjManager(object):'
53
51
54 def write_default_config_file(self):
52 def write_default_config_file(self):
55 ipdir = get_ipython_dir()
53 ipdir = get_ipython_dir()
56 fname = ipdir + '/' + self.filename
54 fname = pjoin(ipdir, self.filename)
57 if not os.path.isfile(fname):
55 if not os.path.isfile(fname):
58 print "Writing the configuration file to: " + fname
56 print "Writing the configuration file to: " + fname
59 self.write_config_obj_to_file(fname)
57 self.write_config_obj_to_file(fname)
@@ -87,11 +85,11 b' class ConfigObjManager(object):'
87
85
88 # In ipythondir if it is set
86 # In ipythondir if it is set
89 if ipythondir is not None:
87 if ipythondir is not None:
90 trythis = ipythondir + '/' + filename
88 trythis = pjoin(ipythondir, filename)
91 if os.path.isfile(trythis):
89 if os.path.isfile(trythis):
92 return trythis
90 return trythis
93
91
94 trythis = get_ipython_dir() + '/' + filename
92 trythis = pjoin(get_ipython_dir(), filename)
95 if os.path.isfile(trythis):
93 if os.path.isfile(trythis):
96 return trythis
94 return trythis
97
95
@@ -22,71 +22,6 b' import sys'
22 # Normal code begins
22 # Normal code begins
23 #---------------------------------------------------------------------------
23 #---------------------------------------------------------------------------
24
24
25 class HomeDirError(Exception):
26 pass
27
28 def get_home_dir():
29 """Return the closest possible equivalent to a 'home' directory.
30
31 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
32
33 Currently only Posix and NT are implemented, a HomeDirError exception is
34 raised for all other OSes. """
35
36 isdir = os.path.isdir
37 env = os.environ
38 try:
39 homedir = env['HOME']
40 if not isdir(homedir):
41 # in case a user stuck some string which does NOT resolve to a
42 # valid path, it's as good as if we hadn't foud it
43 raise KeyError
44 return homedir
45 except KeyError:
46 if os.name == 'posix':
47 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
48 elif os.name == 'nt':
49 # For some strange reason, win9x returns 'nt' for os.name.
50 try:
51 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
52 if not isdir(homedir):
53 homedir = os.path.join(env['USERPROFILE'])
54 if not isdir(homedir):
55 raise HomeDirError
56 return homedir
57 except:
58 try:
59 # Use the registry to get the 'My Documents' folder.
60 import _winreg as wreg
61 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
62 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
63 homedir = wreg.QueryValueEx(key,'Personal')[0]
64 key.Close()
65 if not isdir(homedir):
66 e = ('Invalid "Personal" folder registry key '
67 'typically "My Documents".\n'
68 'Value: %s\n'
69 'This is not a valid directory on your system.' %
70 homedir)
71 raise HomeDirError(e)
72 return homedir
73 except HomeDirError:
74 raise
75 except:
76 return 'C:\\'
77 elif os.name == 'dos':
78 # Desperate, may do absurd things in classic MacOS. May work under DOS.
79 return 'C:\\'
80 else:
81 raise HomeDirError,'support for your operating system not implemented.'
82
83 def get_ipython_dir():
84 ipdir_def = '.ipython'
85 home_dir = get_home_dir()
86 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
87 os.path.join(home_dir,ipdir_def)))
88 return ipdir
89
90 def import_item(key):
25 def import_item(key):
91 """
26 """
92 Import and return bar given the string foo.bar.
27 Import and return bar given the string foo.bar.
@@ -50,7 +50,6 b' import subprocess'
50 from subprocess import PIPE
50 from subprocess import PIPE
51 import sys
51 import sys
52 import os
52 import os
53 import time
54 import types
53 import types
55
54
56 try:
55 try:
@@ -69,8 +68,16 b' except ImportError:'
69
68
70 mswindows = (sys.platform == "win32")
69 mswindows = (sys.platform == "win32")
71
70
71 skip = False
72
72 if mswindows:
73 if mswindows:
73 import winprocess
74 import platform
75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
76 # Killable process does not work under vista when starting for
77 # something else than cmd.
78 skip = True
79 else:
80 import winprocess
74 else:
81 else:
75 import signal
82 import signal
76
83
@@ -78,7 +85,11 b' if not mswindows:'
78 def DoNothing(*args):
85 def DoNothing(*args):
79 pass
86 pass
80
87
81 class Popen(subprocess.Popen):
88
89 if skip:
90 Popen = subprocess.Popen
91 else:
92 class Popen(subprocess.Popen):
82 if not mswindows:
93 if not mswindows:
83 # Override __init__ to set a preexec_fn
94 # Override __init__ to set a preexec_fn
84 def __init__(self, *args, **kwargs):
95 def __init__(self, *args, **kwargs):
@@ -50,7 +50,7 b' class PipedProcess(Thread):'
50 """
50 """
51 env = os.environ
51 env = os.environ
52 env['TERM'] = 'xterm'
52 env['TERM'] = 'xterm'
53 process = Popen((self.command_string + ' 2>&1', ), shell=True,
53 process = Popen(self.command_string + ' 2>&1', shell=True,
54 env=env,
54 env=env,
55 universal_newlines=True,
55 universal_newlines=True,
56 stdout=PIPE, stdin=PIPE, )
56 stdout=PIPE, stdin=PIPE, )
@@ -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,14 +21,13 b' __docformat__ = "restructuredtext en"'
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import string
23 import string
24 import uuid
24 import codeop
25 import _ast
25 from IPython.external import guid
26
26
27
27 from IPython.frontend.zopeinterface import (
28 from IPython.frontend.zopeinterface import (
28 Interface,
29 Interface,
29 Attribute,
30 Attribute,
30 implements,
31 classProvides
32 )
31 )
33 from IPython.kernel.core.history import FrontEndHistory
32 from IPython.kernel.core.history import FrontEndHistory
34 from IPython.kernel.core.util import Bunch
33 from IPython.kernel.core.util import Bunch
@@ -134,11 +133,7 b' class IFrontEnd(Interface):'
134
133
135 pass
134 pass
136
135
137 def compile_ast(block):
136
138 """Compiles block to an _ast.AST"""
139
140 pass
141
142 def get_history_previous(current_block):
137 def get_history_previous(current_block):
143 """Returns the block previous in the history. Saves currentBlock if
138 """Returns the block previous in the history. Saves currentBlock if
144 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"""
@@ -220,28 +215,14 b' class FrontEndBase(object):'
220 """
215 """
221
216
222 try:
217 try:
223 ast = self.compile_ast(block)
218 is_complete = codeop.compile_command(block.rstrip() + '\n\n',
219 "<string>", "exec")
224 except:
220 except:
225 return False
221 return False
226
222
227 lines = block.split('\n')
223 lines = block.split('\n')
228 return (len(lines)==1 or str(lines[-1])=='')
224 return ((is_complete is not None)
229
225 and (len(lines)==1 or str(lines[-1])==''))
230
231 def compile_ast(self, block):
232 """Compile block to an AST
233
234 Parameters:
235 block : str
236
237 Result:
238 AST
239
240 Throws:
241 Exception if block cannot be compiled
242 """
243
244 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
245
226
246
227
247 def execute(self, block, blockID=None):
228 def execute(self, block, blockID=None):
@@ -261,7 +242,7 b' class FrontEndBase(object):'
261 raise Exception("Block is not compilable")
242 raise Exception("Block is not compilable")
262
243
263 if(blockID == None):
244 if(blockID == None):
264 blockID = uuid.uuid4() #random UUID
245 blockID = guid.generate()
265
246
266 try:
247 try:
267 result = self.shell.execute(block)
248 result = self.shell.execute(block)
@@ -20,6 +20,8 b' import re'
20
20
21 import IPython
21 import IPython
22 import sys
22 import sys
23 import codeop
24 import traceback
23
25
24 from frontendbase import FrontEndBase
26 from frontendbase import FrontEndBase
25 from IPython.kernel.core.interpreter import Interpreter
27 from IPython.kernel.core.interpreter import Interpreter
@@ -76,6 +78,11 b' class LineFrontEndBase(FrontEndBase):'
76
78
77 if banner is not None:
79 if banner is not None:
78 self.banner = banner
80 self.banner = banner
81
82 def start(self):
83 """ Put the frontend in a state where it is ready for user
84 interaction.
85 """
79 if self.banner is not None:
86 if self.banner is not None:
80 self.write(self.banner, refresh=False)
87 self.write(self.banner, refresh=False)
81
88
@@ -141,9 +148,18 b' class LineFrontEndBase(FrontEndBase):'
141 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
148 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
142 return False
149 return False
143 else:
150 else:
144 # Add line returns here, to make sure that the statement is
151 self.capture_output()
145 # complete.
152 try:
146 return FrontEndBase.is_complete(self, string.rstrip() + '\n\n')
153 # Add line returns here, to make sure that the statement is
154 # complete.
155 is_complete = codeop.compile_command(string.rstrip() + '\n\n',
156 "<string>", "exec")
157 self.release_output()
158 except Exception, e:
159 # XXX: Hack: return True so that the
160 # code gets executed and the error captured.
161 is_complete = True
162 return is_complete
147
163
148
164
149 def write(self, string, refresh=True):
165 def write(self, string, refresh=True):
@@ -166,22 +182,35 b' class LineFrontEndBase(FrontEndBase):'
166 raw_string = python_string
182 raw_string = python_string
167 # Create a false result, in case there is an exception
183 # Create a false result, in case there is an exception
168 self.last_result = dict(number=self.prompt_number)
184 self.last_result = dict(number=self.prompt_number)
185
186 ## try:
187 ## self.history.input_cache[-1] = raw_string.rstrip()
188 ## result = self.shell.execute(python_string)
189 ## self.last_result = result
190 ## self.render_result(result)
191 ## except:
192 ## self.show_traceback()
193 ## finally:
194 ## self.after_execute()
195
169 try:
196 try:
170 self.history.input_cache[-1] = raw_string.rstrip()
197 try:
171 result = self.shell.execute(python_string)
198 self.history.input_cache[-1] = raw_string.rstrip()
172 self.last_result = result
199 result = self.shell.execute(python_string)
173 self.render_result(result)
200 self.last_result = result
174 except:
201 self.render_result(result)
175 self.show_traceback()
202 except:
203 self.show_traceback()
176 finally:
204 finally:
177 self.after_execute()
205 self.after_execute()
178
206
207
179 #--------------------------------------------------------------------------
208 #--------------------------------------------------------------------------
180 # LineFrontEndBase interface
209 # LineFrontEndBase interface
181 #--------------------------------------------------------------------------
210 #--------------------------------------------------------------------------
182
211
183 def prefilter_input(self, string):
212 def prefilter_input(self, string):
184 """ Priflter the input to turn it in valid python.
213 """ Prefilter the input to turn it in valid python.
185 """
214 """
186 string = string.replace('\r\n', '\n')
215 string = string.replace('\r\n', '\n')
187 string = string.replace('\t', 4*' ')
216 string = string.replace('\t', 4*' ')
@@ -210,9 +239,12 b' class LineFrontEndBase(FrontEndBase):'
210 line = self.input_buffer
239 line = self.input_buffer
211 new_line, completions = self.complete(line)
240 new_line, completions = self.complete(line)
212 if len(completions)>1:
241 if len(completions)>1:
213 self.write_completion(completions)
242 self.write_completion(completions, new_line=new_line)
214 self.input_buffer = new_line
243 elif not line == new_line:
244 self.input_buffer = new_line
215 if self.debug:
245 if self.debug:
246 print >>sys.__stdout__, 'line', line
247 print >>sys.__stdout__, 'new_line', new_line
216 print >>sys.__stdout__, completions
248 print >>sys.__stdout__, completions
217
249
218
250
@@ -222,10 +254,15 b' class LineFrontEndBase(FrontEndBase):'
222 return 80
254 return 80
223
255
224
256
225 def write_completion(self, possibilities):
257 def write_completion(self, possibilities, new_line=None):
226 """ Write the list of possible completions.
258 """ Write the list of possible completions.
259
260 new_line is the completed input line that should be displayed
261 after the completion are writen. If None, the input_buffer
262 before the completion is used.
227 """
263 """
228 current_buffer = self.input_buffer
264 if new_line is None:
265 new_line = self.input_buffer
229
266
230 self.write('\n')
267 self.write('\n')
231 max_len = len(max(possibilities, key=len)) + 1
268 max_len = len(max(possibilities, key=len)) + 1
@@ -246,7 +283,7 b' class LineFrontEndBase(FrontEndBase):'
246 self.write(''.join(buf))
283 self.write(''.join(buf))
247 self.new_prompt(self.input_prompt_template.substitute(
284 self.new_prompt(self.input_prompt_template.substitute(
248 number=self.last_result['number'] + 1))
285 number=self.last_result['number'] + 1))
249 self.input_buffer = current_buffer
286 self.input_buffer = new_line
250
287
251
288
252 def new_prompt(self, prompt):
289 def new_prompt(self, prompt):
@@ -275,6 +312,8 b' class LineFrontEndBase(FrontEndBase):'
275 else:
312 else:
276 self.input_buffer += self._get_indent_string(
313 self.input_buffer += self._get_indent_string(
277 current_buffer[:-1])
314 current_buffer[:-1])
315 if len(current_buffer.split('\n')) == 2:
316 self.input_buffer += '\t\t'
278 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
317 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
279 self.input_buffer += '\t'
318 self.input_buffer += '\t'
280
319
@@ -24,6 +24,7 b' __docformat__ = "restructuredtext en"'
24 import sys
24 import sys
25
25
26 from linefrontendbase import LineFrontEndBase, common_prefix
26 from linefrontendbase import LineFrontEndBase, common_prefix
27 from frontendbase import FrontEndBase
27
28
28 from IPython.ipmaker import make_IPython
29 from IPython.ipmaker import make_IPython
29 from IPython.ipapi import IPApi
30 from IPython.ipapi import IPApi
@@ -34,6 +35,7 b' from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap'
34 from IPython.genutils import Term
35 from IPython.genutils import Term
35 import pydoc
36 import pydoc
36 import os
37 import os
38 import sys
37
39
38
40
39 def mk_system_call(system_call_function, command):
41 def mk_system_call(system_call_function, command):
@@ -57,6 +59,8 b' class PrefilterFrontEnd(LineFrontEndBase):'
57 to execute the statements and the ipython0 used for code
59 to execute the statements and the ipython0 used for code
58 completion...
60 completion...
59 """
61 """
62
63 debug = False
60
64
61 def __init__(self, ipython0=None, *args, **kwargs):
65 def __init__(self, ipython0=None, *args, **kwargs):
62 """ Parameters:
66 """ Parameters:
@@ -65,12 +69,24 b' class PrefilterFrontEnd(LineFrontEndBase):'
65 ipython0: an optional ipython0 instance to use for command
69 ipython0: an optional ipython0 instance to use for command
66 prefiltering and completion.
70 prefiltering and completion.
67 """
71 """
72 LineFrontEndBase.__init__(self, *args, **kwargs)
73 self.shell.output_trap = RedirectorOutputTrap(
74 out_callback=self.write,
75 err_callback=self.write,
76 )
77 self.shell.traceback_trap = SyncTracebackTrap(
78 formatters=self.shell.traceback_trap.formatters,
79 )
80
81 # Start the ipython0 instance:
68 self.save_output_hooks()
82 self.save_output_hooks()
69 if ipython0 is None:
83 if ipython0 is None:
70 # Instanciate an IPython0 interpreter to be able to use the
84 # Instanciate an IPython0 interpreter to be able to use the
71 # prefiltering.
85 # prefiltering.
72 # XXX: argv=[] is a bit bold.
86 # XXX: argv=[] is a bit bold.
73 ipython0 = make_IPython(argv=[])
87 ipython0 = make_IPython(argv=[],
88 user_ns=self.shell.user_ns,
89 user_global_ns=self.shell.user_global_ns)
74 self.ipython0 = ipython0
90 self.ipython0 = ipython0
75 # Set the pager:
91 # Set the pager:
76 self.ipython0.set_hook('show_in_pager',
92 self.ipython0.set_hook('show_in_pager',
@@ -86,24 +102,13 b' class PrefilterFrontEnd(LineFrontEndBase):'
86 'ls -CF')
102 'ls -CF')
87 # And now clean up the mess created by ipython0
103 # And now clean up the mess created by ipython0
88 self.release_output()
104 self.release_output()
105
106
89 if not 'banner' in kwargs and self.banner is None:
107 if not 'banner' in kwargs and self.banner is None:
90 kwargs['banner'] = self.ipython0.BANNER + """
108 self.banner = self.ipython0.BANNER + """
91 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
109 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
92
110
93 LineFrontEndBase.__init__(self, *args, **kwargs)
111 self.start()
94 # XXX: Hack: mix the two namespaces
95 self.shell.user_ns.update(self.ipython0.user_ns)
96 self.ipython0.user_ns = self.shell.user_ns
97 self.shell.user_global_ns.update(self.ipython0.user_global_ns)
98 self.ipython0.user_global_ns = self.shell.user_global_ns
99
100 self.shell.output_trap = RedirectorOutputTrap(
101 out_callback=self.write,
102 err_callback=self.write,
103 )
104 self.shell.traceback_trap = SyncTracebackTrap(
105 formatters=self.shell.traceback_trap.formatters,
106 )
107
112
108 #--------------------------------------------------------------------------
113 #--------------------------------------------------------------------------
109 # FrontEndBase interface
114 # FrontEndBase interface
@@ -113,7 +118,7 b' This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""'
113 """ Use ipython0 to capture the last traceback and display it.
118 """ Use ipython0 to capture the last traceback and display it.
114 """
119 """
115 self.capture_output()
120 self.capture_output()
116 self.ipython0.showtraceback()
121 self.ipython0.showtraceback(tb_offset=-1)
117 self.release_output()
122 self.release_output()
118
123
119
124
@@ -164,6 +169,8 b' This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""'
164
169
165
170
166 def complete(self, line):
171 def complete(self, line):
172 # FIXME: This should be factored out in the linefrontendbase
173 # method.
167 word = line.split('\n')[-1].split(' ')[-1]
174 word = line.split('\n')[-1].split(' ')[-1]
168 completions = self.ipython0.complete(word)
175 completions = self.ipython0.complete(word)
169 # FIXME: The proper sort should be done in the complete method.
176 # FIXME: The proper sort should be done in the complete method.
@@ -189,17 +196,33 b' This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""'
189 # capture it.
196 # capture it.
190 self.capture_output()
197 self.capture_output()
191 self.last_result = dict(number=self.prompt_number)
198 self.last_result = dict(number=self.prompt_number)
199
200 ## try:
201 ## for line in input_string.split('\n'):
202 ## filtered_lines.append(
203 ## self.ipython0.prefilter(line, False).rstrip())
204 ## except:
205 ## # XXX: probably not the right thing to do.
206 ## self.ipython0.showsyntaxerror()
207 ## self.after_execute()
208 ## finally:
209 ## self.release_output()
210
211
192 try:
212 try:
193 for line in input_string.split('\n'):
213 try:
194 filtered_lines.append(
214 for line in input_string.split('\n'):
195 self.ipython0.prefilter(line, False).rstrip())
215 filtered_lines.append(
196 except:
216 self.ipython0.prefilter(line, False).rstrip())
197 # XXX: probably not the right thing to do.
217 except:
198 self.ipython0.showsyntaxerror()
218 # XXX: probably not the right thing to do.
199 self.after_execute()
219 self.ipython0.showsyntaxerror()
220 self.after_execute()
200 finally:
221 finally:
201 self.release_output()
222 self.release_output()
202
223
224
225
203 # Clean up the trailing whitespace, to avoid indentation errors
226 # Clean up the trailing whitespace, to avoid indentation errors
204 filtered_string = '\n'.join(filtered_lines)
227 filtered_string = '\n'.join(filtered_lines)
205 return filtered_string
228 return filtered_string
@@ -1,157 +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 class FrontEndCallbackChecker(AsyncFrontEndBase):
29
29 """FrontEndBase subclass for checking callbacks"""
30 if __name__ == '__main__':
30 def __init__(self, engine=None, history=None):
31 test_iscomplete()
31 super(FrontEndCallbackChecker, self).__init__(engine=engine,
32 history=history)
33 self.updateCalled = False
34 self.renderResultCalled = False
35 self.renderErrorCalled = False
36
37 def update_cell_prompt(self, result, blockID=None):
38 self.updateCalled = True
39 return result
40
41 def render_result(self, result):
42 self.renderResultCalled = True
43 return result
44
45
46 def render_error(self, failure):
47 self.renderErrorCalled = True
48 return failure
49
50
51
32
52
53 class TestAsyncFrontendBase(unittest.TestCase):
54 def setUp(self):
55 """Setup the EngineService and FrontEndBase"""
56
57 self.fb = FrontEndCallbackChecker(engine=EngineService())
58
59
60 def test_implements_IFrontEnd(self):
61 assert(frontendbase.IFrontEnd.implementedBy(
62 AsyncFrontEndBase))
63
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
84 def test_blockID_added_to_result(self):
85 block = """3+3"""
86
87 d = self.fb.execute(block, blockID='TEST_ID')
88
89 d.addCallback(self.checkBlockID, expected='TEST_ID')
90
91 def test_blockID_added_to_failure(self):
92 block = "raise Exception()"
93
94 d = self.fb.execute(block,blockID='TEST_ID')
95 d.addErrback(self.checkFailureID, expected='TEST_ID')
96
97 def checkBlockID(self, result, expected=""):
98 assert(result['blockID'] == expected)
99
100
101 def checkFailureID(self, failure, expected=""):
102 assert(failure.blockID == expected)
103
104
105 def test_callbacks_added_to_execute(self):
106 """test that
107 update_cell_prompt
108 render_result
109
110 are added to execute request
111 """
112
113 d = self.fb.execute("10+10")
114 d.addCallback(self.checkCallbacks)
115
116
117 def checkCallbacks(self, result):
118 assert(self.fb.updateCalled)
119 assert(self.fb.renderResultCalled)
120
121
122 def test_error_callback_added_to_execute(self):
123 """test that render_error called on execution error"""
124
125 d = self.fb.execute("raise Exception()")
126 d.addCallback(self.checkRenderError)
127
128 def checkRenderError(self, result):
129 assert(self.fb.renderErrorCalled)
130
131 def test_history_returns_expected_block(self):
132 """Make sure history browsing doesn't fail"""
133
134 blocks = ["a=1","a=2","a=3"]
135 for b in blocks:
136 d = self.fb.execute(b)
137
138 # d is now the deferred for the last executed block
139 d.addCallback(self.historyTests, blocks)
140
141
142 def historyTests(self, result, blocks):
143 """historyTests"""
144
145 assert(len(blocks) >= 3)
146 assert(self.fb.get_history_previous("") == blocks[-2])
147 assert(self.fb.get_history_previous("") == blocks[-3])
148 assert(self.fb.get_history_next() == blocks[-2])
149
150
151 def test_history_returns_none_at_startup(self):
152 """test_history_returns_none_at_startup"""
153
154 assert(self.fb.get_history_previous("")==None)
155 assert(self.fb.get_history_next()==None)
156
157
@@ -19,6 +19,7 b' import sys'
19 from IPython.frontend._process import PipedProcess
19 from IPython.frontend._process import PipedProcess
20 from IPython.testing import decorators as testdec
20 from IPython.testing import decorators as testdec
21
21
22
22 def test_capture_out():
23 def test_capture_out():
23 """ A simple test to see if we can execute a process and get the output.
24 """ A simple test to see if we can execute a process and get the output.
24 """
25 """
@@ -29,8 +30,7 b' def test_capture_out():'
29 result = s.getvalue().rstrip()
30 result = s.getvalue().rstrip()
30 assert result == '1'
31 assert result == '1'
31
32
32 # FIXME
33
33 @testdec.skip("This doesn't work under Windows")
34 def test_io():
34 def test_io():
35 """ Checks that we can send characters on stdin to the process.
35 """ Checks that we can send characters on stdin to the process.
36 """
36 """
@@ -23,6 +23,7 b' import wx'
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
25 from wx.py import editwindow
26 import time
26 import sys
27 import sys
27 LINESEP = '\n'
28 LINESEP = '\n'
28 if sys.platform == 'win32':
29 if sys.platform == 'win32':
@@ -35,7 +36,7 b' import re'
35
36
36 _DEFAULT_SIZE = 10
37 _DEFAULT_SIZE = 10
37 if sys.platform == 'darwin':
38 if sys.platform == 'darwin':
38 _DEFAULT_STYLE = 12
39 _DEFAULT_SIZE = 12
39
40
40 _DEFAULT_STYLE = {
41 _DEFAULT_STYLE = {
41 'stdout' : 'fore:#0000FF',
42 'stdout' : 'fore:#0000FF',
@@ -115,12 +116,15 b' class ConsoleWidget(editwindow.EditWindow):'
115 # The color of the carret (call _apply_style() after setting)
116 # The color of the carret (call _apply_style() after setting)
116 carret_color = 'BLACK'
117 carret_color = 'BLACK'
117
118
119 # Store the last time a refresh was done
120 _last_refresh_time = 0
121
118 #--------------------------------------------------------------------------
122 #--------------------------------------------------------------------------
119 # Public API
123 # Public API
120 #--------------------------------------------------------------------------
124 #--------------------------------------------------------------------------
121
125
122 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
126 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
123 size=wx.DefaultSize, style=0, ):
127 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
124 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
128 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
125 self._configure_scintilla()
129 self._configure_scintilla()
126
130
@@ -168,9 +172,14 b' class ConsoleWidget(editwindow.EditWindow):'
168
172
169 self.GotoPos(self.GetLength())
173 self.GotoPos(self.GetLength())
170 if refresh:
174 if refresh:
171 # Maybe this is faster than wx.Yield()
175 current_time = time.time()
172 self.ProcessEvent(wx.PaintEvent())
176 if current_time - self._last_refresh_time > 0.03:
173 #wx.Yield()
177 if sys.platform == 'win32':
178 wx.SafeYield()
179 else:
180 wx.Yield()
181 # self.ProcessEvent(wx.PaintEvent())
182 self._last_refresh_time = current_time
174
183
175
184
176 def new_prompt(self, prompt):
185 def new_prompt(self, prompt):
@@ -183,7 +192,6 b' class ConsoleWidget(editwindow.EditWindow):'
183 # now we update our cursor giving end of prompt
192 # now we update our cursor giving end of prompt
184 self.current_prompt_pos = self.GetLength()
193 self.current_prompt_pos = self.GetLength()
185 self.current_prompt_line = self.GetCurrentLine()
194 self.current_prompt_line = self.GetCurrentLine()
186 wx.Yield()
187 self.EnsureCaretVisible()
195 self.EnsureCaretVisible()
188
196
189
197
@@ -128,6 +128,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
128 # while it is being swapped
128 # while it is being swapped
129 _out_buffer_lock = Lock()
129 _out_buffer_lock = Lock()
130
130
131 # The different line markers used to higlight the prompts.
131 _markers = dict()
132 _markers = dict()
132
133
133 #--------------------------------------------------------------------------
134 #--------------------------------------------------------------------------
@@ -135,12 +136,16 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
135 #--------------------------------------------------------------------------
136 #--------------------------------------------------------------------------
136
137
137 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
138 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
138 size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
139 size=wx.DefaultSize,
140 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
139 *args, **kwds):
141 *args, **kwds):
140 """ Create Shell instance.
142 """ Create Shell instance.
141 """
143 """
142 ConsoleWidget.__init__(self, parent, id, pos, size, style)
144 ConsoleWidget.__init__(self, parent, id, pos, size, style)
143 PrefilterFrontEnd.__init__(self, **kwds)
145 PrefilterFrontEnd.__init__(self, **kwds)
146
147 # Stick in our own raw_input:
148 self.ipython0.raw_input = self.raw_input
144
149
145 # Marker for complete buffer.
150 # Marker for complete buffer.
146 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
151 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
@@ -164,9 +169,11 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
164 # Inject self in namespace, for debug
169 # Inject self in namespace, for debug
165 if self.debug:
170 if self.debug:
166 self.shell.user_ns['self'] = self
171 self.shell.user_ns['self'] = self
172 # Inject our own raw_input in namespace
173 self.shell.user_ns['raw_input'] = self.raw_input
167
174
168
175
169 def raw_input(self, prompt):
176 def raw_input(self, prompt=''):
170 """ A replacement from python's raw_input.
177 """ A replacement from python's raw_input.
171 """
178 """
172 self.new_prompt(prompt)
179 self.new_prompt(prompt)
@@ -174,15 +181,13 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
174 if hasattr(self, '_cursor'):
181 if hasattr(self, '_cursor'):
175 del self._cursor
182 del self._cursor
176 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
183 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
177 self.waiting = True
178 self.__old_on_enter = self._on_enter
184 self.__old_on_enter = self._on_enter
185 event_loop = wx.EventLoop()
179 def my_on_enter():
186 def my_on_enter():
180 self.waiting = False
187 event_loop.Exit()
181 self._on_enter = my_on_enter
188 self._on_enter = my_on_enter
182 # XXX: Busy waiting, ugly.
189 # XXX: Running a separate event_loop. Ugly.
183 while self.waiting:
190 event_loop.Run()
184 wx.Yield()
185 sleep(0.1)
186 self._on_enter = self.__old_on_enter
191 self._on_enter = self.__old_on_enter
187 self._input_state = 'buffering'
192 self._input_state = 'buffering'
188 self._cursor = wx.BusyCursor()
193 self._cursor = wx.BusyCursor()
@@ -191,16 +196,18 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
191
196
192 def system_call(self, command_string):
197 def system_call(self, command_string):
193 self._input_state = 'subprocess'
198 self._input_state = 'subprocess'
199 event_loop = wx.EventLoop()
200 def _end_system_call():
201 self._input_state = 'buffering'
202 self._running_process = False
203 event_loop.Exit()
204
194 self._running_process = PipedProcess(command_string,
205 self._running_process = PipedProcess(command_string,
195 out_callback=self.buffered_write,
206 out_callback=self.buffered_write,
196 end_callback = self._end_system_call)
207 end_callback = _end_system_call)
197 self._running_process.start()
208 self._running_process.start()
198 # XXX: another one of these polling loops to have a blocking
209 # XXX: Running a separate event_loop. Ugly.
199 # call
210 event_loop.Run()
200 wx.Yield()
201 while self._running_process:
202 wx.Yield()
203 sleep(0.1)
204 # Be sure to flush the buffer.
211 # Be sure to flush the buffer.
205 self._buffer_flush(event=None)
212 self._buffer_flush(event=None)
206
213
@@ -226,8 +233,9 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
226 for name in symbol_string.split('.')[1:] + ['__doc__']:
233 for name in symbol_string.split('.')[1:] + ['__doc__']:
227 symbol = getattr(symbol, name)
234 symbol = getattr(symbol, name)
228 self.AutoCompCancel()
235 self.AutoCompCancel()
229 wx.Yield()
236 # Check that the symbol can indeed be converted to a string:
230 self.CallTipShow(self.GetCurrentPos(), symbol)
237 symbol += ''
238 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
231 except:
239 except:
232 # The retrieve symbol couldn't be converted to a string
240 # The retrieve symbol couldn't be converted to a string
233 pass
241 pass
@@ -238,9 +246,9 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
238 true, open the menu.
246 true, open the menu.
239 """
247 """
240 if self.debug:
248 if self.debug:
241 print >>sys.__stdout__, "_popup_completion",
249 print >>sys.__stdout__, "_popup_completion"
242 line = self.input_buffer
250 line = self.input_buffer
243 if (self.AutoCompActive() and not line[-1] == '.') \
251 if (self.AutoCompActive() and line and not line[-1] == '.') \
244 or create==True:
252 or create==True:
245 suggestion, completions = self.complete(line)
253 suggestion, completions = self.complete(line)
246 offset=0
254 offset=0
@@ -284,19 +292,21 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
284 if i in self._markers:
292 if i in self._markers:
285 self.MarkerDeleteHandle(self._markers[i])
293 self.MarkerDeleteHandle(self._markers[i])
286 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
294 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
287 # Update the display:
295 # Use a callafter to update the display robustly under windows
288 wx.Yield()
296 def callback():
289 self.GotoPos(self.GetLength())
297 self.GotoPos(self.GetLength())
290 PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string)
298 PrefilterFrontEnd.execute(self, python_string,
299 raw_string=raw_string)
300 wx.CallAfter(callback)
291
301
292 def save_output_hooks(self):
302 def save_output_hooks(self):
293 self.__old_raw_input = __builtin__.raw_input
303 self.__old_raw_input = __builtin__.raw_input
294 PrefilterFrontEnd.save_output_hooks(self)
304 PrefilterFrontEnd.save_output_hooks(self)
295
305
296 def capture_output(self):
306 def capture_output(self):
297 __builtin__.raw_input = self.raw_input
298 self.SetLexer(stc.STC_LEX_NULL)
307 self.SetLexer(stc.STC_LEX_NULL)
299 PrefilterFrontEnd.capture_output(self)
308 PrefilterFrontEnd.capture_output(self)
309 __builtin__.raw_input = self.raw_input
300
310
301
311
302 def release_output(self):
312 def release_output(self):
@@ -316,12 +326,24 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
316 def show_traceback(self):
326 def show_traceback(self):
317 start_line = self.GetCurrentLine()
327 start_line = self.GetCurrentLine()
318 PrefilterFrontEnd.show_traceback(self)
328 PrefilterFrontEnd.show_traceback(self)
319 wx.Yield()
329 self.ProcessEvent(wx.PaintEvent())
330 #wx.Yield()
320 for i in range(start_line, self.GetCurrentLine()):
331 for i in range(start_line, self.GetCurrentLine()):
321 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
332 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
322
333
323
334
324 #--------------------------------------------------------------------------
335 #--------------------------------------------------------------------------
336 # FrontEndBase interface
337 #--------------------------------------------------------------------------
338
339 def render_error(self, e):
340 start_line = self.GetCurrentLine()
341 self.write('\n' + e + '\n')
342 for i in range(start_line, self.GetCurrentLine()):
343 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
344
345
346 #--------------------------------------------------------------------------
325 # ConsoleWidget interface
347 # ConsoleWidget interface
326 #--------------------------------------------------------------------------
348 #--------------------------------------------------------------------------
327
349
@@ -351,7 +373,8 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
351 if self._input_state == 'subprocess':
373 if self._input_state == 'subprocess':
352 if self.debug:
374 if self.debug:
353 print >>sys.__stderr__, 'Killing running process'
375 print >>sys.__stderr__, 'Killing running process'
354 self._running_process.process.kill()
376 if hasattr(self._running_process, 'process'):
377 self._running_process.process.kill()
355 elif self._input_state == 'buffering':
378 elif self._input_state == 'buffering':
356 if self.debug:
379 if self.debug:
357 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
380 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
@@ -376,7 +399,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
376 char = '\04'
399 char = '\04'
377 self._running_process.process.stdin.write(char)
400 self._running_process.process.stdin.write(char)
378 self._running_process.process.stdin.flush()
401 self._running_process.process.stdin.flush()
379 elif event.KeyCode in (ord('('), 57):
402 elif event.KeyCode in (ord('('), 57, 53):
380 # Calltips
403 # Calltips
381 event.Skip()
404 event.Skip()
382 self.do_calltip()
405 self.do_calltip()
@@ -410,8 +433,8 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
410 self.input_buffer = new_buffer
433 self.input_buffer = new_buffer
411 # Tab-completion
434 # Tab-completion
412 elif event.KeyCode == ord('\t'):
435 elif event.KeyCode == ord('\t'):
413 last_line = self.input_buffer.split('\n')[-1]
436 current_line, current_line_number = self.CurLine
414 if not re.match(r'^\s*$', last_line):
437 if not re.match(r'^\s*$', current_line):
415 self.complete_current_input()
438 self.complete_current_input()
416 if self.AutoCompActive():
439 if self.AutoCompActive():
417 wx.CallAfter(self._popup_completion, create=True)
440 wx.CallAfter(self._popup_completion, create=True)
@@ -427,7 +450,7 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
427 if event.KeyCode in (59, ord('.')):
450 if event.KeyCode in (59, ord('.')):
428 # Intercepting '.'
451 # Intercepting '.'
429 event.Skip()
452 event.Skip()
430 self._popup_completion(create=True)
453 wx.CallAfter(self._popup_completion, create=True)
431 else:
454 else:
432 ConsoleWidget._on_key_up(self, event, skip=skip)
455 ConsoleWidget._on_key_up(self, event, skip=skip)
433
456
@@ -456,13 +479,6 b' class WxController(ConsoleWidget, PrefilterFrontEnd):'
456 # Private API
479 # Private API
457 #--------------------------------------------------------------------------
480 #--------------------------------------------------------------------------
458
481
459 def _end_system_call(self):
460 """ Called at the end of a system call.
461 """
462 self._input_state = 'buffering'
463 self._running_process = False
464
465
466 def _buffer_flush(self, event):
482 def _buffer_flush(self, event):
467 """ Called by the timer to flush the write buffer.
483 """ Called by the timer to flush the write buffer.
468
484
@@ -16,13 +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 import string
23 import uuid
24 import _ast
25
26 try:
19 try:
27 from zope.interface import Interface, Attribute, implements, classProvides
20 from zope.interface import Interface, Attribute, implements, classProvides
28 except ImportError:
21 except ImportError:
@@ -979,6 +979,38 b' def get_home_dir():'
979 else:
979 else:
980 raise HomeDirError,'support for your operating system not implemented.'
980 raise HomeDirError,'support for your operating system not implemented.'
981
981
982
983 def get_ipython_dir():
984 """Get the IPython directory for this platform and user.
985
986 This uses the logic in `get_home_dir` to find the home directory
987 and the adds either .ipython or _ipython to the end of the path.
988 """
989 if os.name == 'posix':
990 ipdir_def = '.ipython'
991 else:
992 ipdir_def = '_ipython'
993 home_dir = get_home_dir()
994 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
995 os.path.join(home_dir,ipdir_def)))
996 return ipdir
997
998 def get_security_dir():
999 """Get the IPython security directory.
1000
1001 This directory is the default location for all security related files,
1002 including SSL/TLS certificates and FURL files.
1003
1004 If the directory does not exist, it is created with 0700 permissions.
1005 If it exists, permissions are set to 0700.
1006 """
1007 security_dir = os.path.join(get_ipython_dir(), 'security')
1008 if not os.path.isdir(security_dir):
1009 os.mkdir(security_dir, 0700)
1010 else:
1011 os.chmod(security_dir, 0700)
1012 return security_dir
1013
982 #****************************************************************************
1014 #****************************************************************************
983 # strings and text
1015 # strings and text
984
1016
@@ -15,17 +15,15 b' __docformat__ = "restructuredtext en"'
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 from os.path import join as pjoin
19
18 from IPython.external.configobj import ConfigObj
20 from IPython.external.configobj import ConfigObj
19 from IPython.config.api import ConfigObjManager
21 from IPython.config.api import ConfigObjManager
20 from IPython.config.cutils import get_ipython_dir
22 from IPython.genutils import get_ipython_dir, get_security_dir
21
23
22 default_kernel_config = ConfigObj()
24 default_kernel_config = ConfigObj()
23
25
24 try:
26 security_dir = get_security_dir()
25 ipython_dir = get_ipython_dir() + '/'
26 except:
27 # This will defaults to the cwd
28 ipython_dir = ''
29
27
30 #-------------------------------------------------------------------------------
28 #-------------------------------------------------------------------------------
31 # Engine Configuration
29 # Engine Configuration
@@ -33,7 +31,7 b' except:'
33
31
34 engine_config = dict(
32 engine_config = dict(
35 logfile = '', # Empty means log to stdout
33 logfile = '', # Empty means log to stdout
36 furl_file = ipython_dir + 'ipcontroller-engine.furl'
34 furl_file = pjoin(security_dir, 'ipcontroller-engine.furl')
37 )
35 )
38
36
39 #-------------------------------------------------------------------------------
37 #-------------------------------------------------------------------------------
@@ -69,10 +67,10 b' controller_config = dict('
69 port = 0, # 0 means pick a port for me
67 port = 0, # 0 means pick a port for me
70 location = '', # Empty string means try to set automatically
68 location = '', # Empty string means try to set automatically
71 secure = True,
69 secure = True,
72 cert_file = ipython_dir + 'ipcontroller-engine.pem',
70 cert_file = pjoin(security_dir, 'ipcontroller-engine.pem'),
73 ),
71 ),
74 engine_fc_interface = 'IPython.kernel.enginefc.IFCControllerBase',
72 engine_fc_interface = 'IPython.kernel.enginefc.IFCControllerBase',
75 engine_furl_file = ipython_dir + 'ipcontroller-engine.furl',
73 engine_furl_file = pjoin(security_dir, 'ipcontroller-engine.furl'),
76
74
77 controller_interfaces = dict(
75 controller_interfaces = dict(
78 # multiengine = dict(
76 # multiengine = dict(
@@ -83,12 +81,12 b' controller_config = dict('
83 task = dict(
81 task = dict(
84 controller_interface = 'IPython.kernel.task.ITaskController',
82 controller_interface = 'IPython.kernel.task.ITaskController',
85 fc_interface = 'IPython.kernel.taskfc.IFCTaskController',
83 fc_interface = 'IPython.kernel.taskfc.IFCTaskController',
86 furl_file = ipython_dir + 'ipcontroller-tc.furl'
84 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
87 ),
85 ),
88 multiengine = dict(
86 multiengine = dict(
89 controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
87 controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
90 fc_interface = 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine',
88 fc_interface = 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine',
91 furl_file = ipython_dir + 'ipcontroller-mec.furl'
89 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
92 )
90 )
93 ),
91 ),
94
92
@@ -97,7 +95,7 b' controller_config = dict('
97 port = 0, # 0 means pick a port for me
95 port = 0, # 0 means pick a port for me
98 location = '', # Empty string means try to set automatically
96 location = '', # Empty string means try to set automatically
99 secure = True,
97 secure = True,
100 cert_file = ipython_dir + 'ipcontroller-client.pem'
98 cert_file = pjoin(security_dir, 'ipcontroller-client.pem')
101 )
99 )
102 )
100 )
103
101
@@ -108,10 +106,10 b' controller_config = dict('
108 client_config = dict(
106 client_config = dict(
109 client_interfaces = dict(
107 client_interfaces = dict(
110 task = dict(
108 task = dict(
111 furl_file = ipython_dir + 'ipcontroller-tc.furl'
109 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
112 ),
110 ),
113 multiengine = dict(
111 multiengine = dict(
114 furl_file = ipython_dir + 'ipcontroller-mec.furl'
112 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
115 )
113 )
116 )
114 )
117 )
115 )
@@ -8,8 +8,6 b' which can also be useful as templates for writing new, application-specific'
8 managers.
8 managers.
9 """
9 """
10
10
11 from __future__ import with_statement
12
13 __docformat__ = "restructuredtext en"
11 __docformat__ = "restructuredtext en"
14
12
15 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
@@ -50,7 +50,7 b' from IPython.kernel.engineservice import \\'
50 IEngineSerialized, \
50 IEngineSerialized, \
51 IEngineQueued
51 IEngineQueued
52
52
53 from IPython.config import cutils
53 from IPython.genutils import get_ipython_dir
54 from IPython.kernel import codeutil
54 from IPython.kernel import codeutil
55
55
56 #-------------------------------------------------------------------------------
56 #-------------------------------------------------------------------------------
@@ -170,7 +170,7 b' class ControllerService(object, service.Service):'
170
170
171 def _getEngineInfoLogFile(self):
171 def _getEngineInfoLogFile(self):
172 # Store all logs inside the ipython directory
172 # Store all logs inside the ipython directory
173 ipdir = cutils.get_ipython_dir()
173 ipdir = get_ipython_dir()
174 pjoin = os.path.join
174 pjoin = os.path.join
175 logdir_base = pjoin(ipdir,'log')
175 logdir_base = pjoin(ipdir,'log')
176 if not os.path.isdir(logdir_base):
176 if not os.path.isdir(logdir_base):
@@ -680,6 +680,13 b' class Interpreter(object):'
680 # how trailing whitespace is handled, but this seems to work.
680 # how trailing whitespace is handled, but this seems to work.
681 python = python.strip()
681 python = python.strip()
682
682
683 # The compiler module does not like unicode. We need to convert
684 # it encode it:
685 if isinstance(python, unicode):
686 # Use the utf-8-sig BOM so the compiler detects this a UTF-8
687 # encode string.
688 python = '\xef\xbb\xbf' + python.encode('utf-8')
689
683 # The compiler module will parse the code into an abstract syntax tree.
690 # The compiler module will parse the code into an abstract syntax tree.
684 ast = compiler.parse(python)
691 ast = compiler.parse(python)
685
692
@@ -13,13 +13,17 b' __docformat__ = "restructuredtext en"'
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15
15
16 # Stdlib imports
16 import os
17 import os
17 from cStringIO import StringIO
18 from cStringIO import StringIO
18
19
19 from IPython.testing import decorators as testdec
20 # Our own imports
21 from IPython.testing import decorators as dec
20
22
21 # FIXME
23 #-----------------------------------------------------------------------------
22 @testdec.skip("This doesn't work under Windows")
24 # Test functions
25
26 @dec.skip_win32
23 def test_redirector():
27 def test_redirector():
24 """ Checks that the redirector can be used to do synchronous capture.
28 """ Checks that the redirector can be used to do synchronous capture.
25 """
29 """
@@ -40,8 +44,8 b' def test_redirector():'
40 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
44 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
41 assert result1 == result2
45 assert result1 == result2
42
46
43 # FIXME
47
44 @testdec.skip("This doesn't work under Windows")
48 @dec.skip_win32
45 def test_redirector_output_trap():
49 def test_redirector_output_trap():
46 """ This test check not only that the redirector_output_trap does
50 """ 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
51 trap the output, but also that it does it in a gready way, that
@@ -63,6 +67,4 b' def test_redirector_output_trap():'
63 result1 = out.getvalue()
67 result1 = out.getvalue()
64 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
68 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
65 assert result1 == result2
69 assert result1 == result2
66
67
70
68
@@ -93,7 +93,7 b' from subprocess import Popen,call'
93 # IPython imports
93 # IPython imports
94 #---------------------------------------------------------------------------
94 #---------------------------------------------------------------------------
95 from IPython.tools import utils
95 from IPython.tools import utils
96 from IPython.config import cutils
96 from IPython.genutils import get_ipython_dir
97
97
98 #---------------------------------------------------------------------------
98 #---------------------------------------------------------------------------
99 # Normal code begins
99 # Normal code begins
@@ -180,7 +180,7 b' def clusterLocal(opt,arg):'
180 """Start a cluster on the local machine."""
180 """Start a cluster on the local machine."""
181
181
182 # Store all logs inside the ipython directory
182 # Store all logs inside the ipython directory
183 ipdir = cutils.get_ipython_dir()
183 ipdir = get_ipython_dir()
184 pjoin = os.path.join
184 pjoin = os.path.join
185
185
186 logfile = opt.logfile
186 logfile = opt.logfile
@@ -256,6 +256,24 b' def clusterLocal(opt,arg):'
256 def clusterRemote(opt,arg):
256 def clusterRemote(opt,arg):
257 """Start a remote cluster over SSH"""
257 """Start a remote cluster over SSH"""
258
258
259 # B. Granger, 9/3/08
260 # The launching of a remote cluster using SSH and a clusterfile
261 # is broken. Because it won't be fixed before the 0.9 release,
262 # we are removing it. For now, we just print a message to the
263 # user and abort.
264
265 print """The launching of a remote IPython cluster using SSL
266 and a clusterfile has been removed in this release.
267 It has been broken for a while and we are in the process
268 of building a new process management system that will be
269 used to provide a more robust way of starting an IPython
270 cluster.
271
272 For now remote clusters have to be launched using ipcontroller
273 and ipengine separately.
274 """
275 sys.exit(1)
276
259 # Load the remote cluster configuration
277 # Load the remote cluster configuration
260 clConfig = {}
278 clConfig = {}
261 execfile(opt.clusterfile,clConfig)
279 execfile(opt.clusterfile,clConfig)
@@ -265,7 +283,7 b' def clusterRemote(opt,arg):'
265 sshx = clConfig.get('sshx',os.environ.get('IPYTHON_SSHX','sshx'))
283 sshx = clConfig.get('sshx',os.environ.get('IPYTHON_SSHX','sshx'))
266
284
267 # Store all logs inside the ipython directory
285 # Store all logs inside the ipython directory
268 ipdir = cutils.get_ipython_dir()
286 ipdir = get_ipython_dir()
269 pjoin = os.path.join
287 pjoin = os.path.join
270
288
271 logfile = opt.logfile
289 logfile = opt.logfile
@@ -311,6 +329,11 b' def clusterRemote(opt,arg):'
311 def main():
329 def main():
312 """Main driver for the two big options: local or remote cluster."""
330 """Main driver for the two big options: local or remote cluster."""
313
331
332 if sys.platform=='win32':
333 print """ipcluster does not work on Microsoft Windows. Please start
334 your IPython cluster using the ipcontroller and ipengine scripts."""
335 sys.exit(1)
336
314 opt,arg = parse_args()
337 opt,arg = parse_args()
315
338
316 clusterfile = opt.clusterfile
339 clusterfile = opt.clusterfile
@@ -105,6 +105,7 b' def start_engine():'
105 # register_engine to tell the controller we are ready to do work
105 # register_engine to tell the controller we are ready to do work
106 engine_connector = EngineConnector(tub_service)
106 engine_connector = EngineConnector(tub_service)
107 furl_file = kernel_config['engine']['furl_file']
107 furl_file = kernel_config['engine']['furl_file']
108 log.msg("Using furl file: %s" % furl_file)
108 d = engine_connector.connect_to_controller(engine_service, furl_file)
109 d = engine_connector.connect_to_controller(engine_service, furl_file)
109 d.addErrback(lambda _: reactor.stop())
110 d.addErrback(lambda _: reactor.stop())
110
111
@@ -245,7 +245,7 b' class IEngineSerializedTestCase(object):'
245 self.assert_(es.IEngineSerialized.providedBy(self.engine))
245 self.assert_(es.IEngineSerialized.providedBy(self.engine))
246
246
247 def testIEngineSerializedInterfaceMethods(self):
247 def testIEngineSerializedInterfaceMethods(self):
248 """Does self.engine have the methods and attributes in IEngireCore."""
248 """Does self.engine have the methods and attributes in IEngineCore."""
249 for m in list(es.IEngineSerialized):
249 for m in list(es.IEngineSerialized):
250 self.assert_(hasattr(self.engine, m))
250 self.assert_(hasattr(self.engine, m))
251
251
@@ -288,7 +288,7 b' class IEngineQueuedTestCase(object):'
288 self.assert_(es.IEngineQueued.providedBy(self.engine))
288 self.assert_(es.IEngineQueued.providedBy(self.engine))
289
289
290 def testIEngineQueuedInterfaceMethods(self):
290 def testIEngineQueuedInterfaceMethods(self):
291 """Does self.engine have the methods and attributes in IEngireQueued."""
291 """Does self.engine have the methods and attributes in IEngineQueued."""
292 for m in list(es.IEngineQueued):
292 for m in list(es.IEngineQueued):
293 self.assert_(hasattr(self.engine, m))
293 self.assert_(hasattr(self.engine, m))
294
294
@@ -326,7 +326,7 b' class IEnginePropertiesTestCase(object):'
326 self.assert_(es.IEngineProperties.providedBy(self.engine))
326 self.assert_(es.IEngineProperties.providedBy(self.engine))
327
327
328 def testIEnginePropertiesInterfaceMethods(self):
328 def testIEnginePropertiesInterfaceMethods(self):
329 """Does self.engine have the methods and attributes in IEngireProperties."""
329 """Does self.engine have the methods and attributes in IEngineProperties."""
330 for m in list(es.IEngineProperties):
330 for m in list(es.IEngineProperties):
331 self.assert_(hasattr(self.engine, m))
331 self.assert_(hasattr(self.engine, m))
332
332
@@ -1,4 +1,6 b''
1 from __future__ import with_statement
1 #from __future__ import with_statement
2
3 # XXX This file is currently disabled to preserve 2.4 compatibility.
2
4
3 #def test_simple():
5 #def test_simple():
4 if 0:
6 if 0:
@@ -25,17 +27,17 b' if 0:'
25
27
26 mec.pushAll()
28 mec.pushAll()
27
29
28 with parallel as pr:
30 ## with parallel as pr:
29 # A comment
31 ## # A comment
30 remote() # this means the code below only runs remotely
32 ## remote() # this means the code below only runs remotely
31 print 'Hello remote world'
33 ## print 'Hello remote world'
32 x = range(10)
34 ## x = range(10)
33 # Comments are OK
35 ## # Comments are OK
34 # Even misindented.
36 ## # Even misindented.
35 y = x+1
37 ## y = x+1
36
38
37
39
38 with pfor('i',sequence) as pr:
40 ## with pfor('i',sequence) as pr:
39 print x[i]
41 ## print x[i]
40
42
41 print pr.x + pr.y
43 print pr.x + pr.y
@@ -8,6 +8,10 b' the decorator, in order to preserve metadata such as function name,'
8 setup and teardown functions and so on - see nose.tools for more
8 setup and teardown functions and so on - see nose.tools for more
9 information.
9 information.
10
10
11 This module provides a set of useful decorators meant to be ready to use in
12 your own tests. See the bottom of the file for the ready-made ones, and if you
13 find yourself writing a new one that may be of generic use, add it here.
14
11 NOTE: This file contains IPython-specific decorators and imports the
15 NOTE: This file contains IPython-specific decorators and imports the
12 numpy.testing.decorators file, which we've copied verbatim. Any of our own
16 numpy.testing.decorators file, which we've copied verbatim. Any of our own
13 code will be added at the bottom if we end up extending this.
17 code will be added at the bottom if we end up extending this.
@@ -15,6 +19,7 b' code will be added at the bottom if we end up extending this.'
15
19
16 # Stdlib imports
20 # Stdlib imports
17 import inspect
21 import inspect
22 import sys
18
23
19 # Third-party imports
24 # Third-party imports
20
25
@@ -123,6 +128,9 b" skip_doctest = make_label_dec('skip_doctest',"
123 def skip(msg=''):
128 def skip(msg=''):
124 """Decorator - mark a test function for skipping from test suite.
129 """Decorator - mark a test function for skipping from test suite.
125
130
131 This function *is* already a decorator, it is not a factory like
132 make_label_dec or some of those in decorators_numpy.
133
126 :Parameters:
134 :Parameters:
127
135
128 func : function
136 func : function
@@ -145,3 +153,8 b" def skip(msg=''):"
145 return apply_wrapper(wrapper,func)
153 return apply_wrapper(wrapper,func)
146
154
147 return inner
155 return inner
156
157 # Decorators to skip certain tests on specific platforms.
158 skip_win32 = skipif(sys.platform=='win32',"This test does not run under Windows")
159 skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux")
160 skip_osx = skipif(sys.platform=='darwin',"This test does not run under OSX")
@@ -1,6 +1,5 b''
1 # Set this prefix to where you want to install the plugin
1 # Set this prefix to where you want to install the plugin
2 PREFIX=~/usr/local
2 PREFIX=/usr/local
3 PREFIX=~/tmp/local
4
3
5 NOSE0=nosetests -vs --with-doctest --doctest-tests --detailed-errors
4 NOSE0=nosetests -vs --with-doctest --doctest-tests --detailed-errors
6 NOSE=nosetests -vvs --with-ipdoctest --doctest-tests --doctest-extension=txt \
5 NOSE=nosetests -vvs --with-ipdoctest --doctest-tests --doctest-extension=txt \
@@ -1,152 +1,19 b''
1 """Some simple tests for the plugin while running scripts.
2 """
1 # Module imports
3 # Module imports
2 # Std lib
4 # Std lib
3 import inspect
5 import inspect
4
6
5 # Third party
6
7 # Our own
7 # Our own
8 from IPython.testing import decorators as dec
8 from IPython.testing import decorators as dec
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Utilities
12
13 # Note: copied from OInspect, kept here so the testing stuff doesn't create
14 # circular dependencies and is easier to reuse.
15 def getargspec(obj):
16 """Get the names and default values of a function's arguments.
17
18 A tuple of four things is returned: (args, varargs, varkw, defaults).
19 'args' is a list of the argument names (it may contain nested lists).
20 'varargs' and 'varkw' are the names of the * and ** arguments or None.
21 'defaults' is an n-tuple of the default values of the last n arguments.
22
23 Modified version of inspect.getargspec from the Python Standard
24 Library."""
25
26 if inspect.isfunction(obj):
27 func_obj = obj
28 elif inspect.ismethod(obj):
29 func_obj = obj.im_func
30 else:
31 raise TypeError, 'arg is not a Python function'
32 args, varargs, varkw = inspect.getargs(func_obj.func_code)
33 return args, varargs, varkw, func_obj.func_defaults
34
35 #-----------------------------------------------------------------------------
36 # Testing functions
11 # Testing functions
37
12
38 def test_trivial():
13 def test_trivial():
39 """A trivial passing test."""
14 """A trivial passing test."""
40 pass
15 pass
41
16
42
43 @dec.skip
44 def test_deliberately_broken():
45 """A deliberately broken test - we want to skip this one."""
46 1/0
47
48 @dec.skip('foo')
49 def test_deliberately_broken2():
50 """Another deliberately broken test - we want to skip this one."""
51 1/0
52
53
54 # Verify that we can correctly skip the doctest for a function at will, but
55 # that the docstring itself is NOT destroyed by the decorator.
56 @dec.skip_doctest
57 def doctest_bad(x,y=1,**k):
58 """A function whose doctest we need to skip.
59
60 >>> 1+1
61 3
62 """
63 print 'x:',x
64 print 'y:',y
65 print 'k:',k
66
67
68 def call_doctest_bad():
69 """Check that we can still call the decorated functions.
70
71 >>> doctest_bad(3,y=4)
72 x: 3
73 y: 4
74 k: {}
75 """
76 pass
77
78
79 # Doctest skipping should work for class methods too
80 class foo(object):
81 """Foo
82
83 Example:
84
85 >>> 1+1
86 2
87 """
88
89 @dec.skip_doctest
90 def __init__(self,x):
91 """Make a foo.
92
93 Example:
94
95 >>> f = foo(3)
96 junk
97 """
98 print 'Making a foo.'
99 self.x = x
100
101 @dec.skip_doctest
102 def bar(self,y):
103 """Example:
104
105 >>> f = foo(3)
106 >>> f.bar(0)
107 boom!
108 >>> 1/0
109 bam!
110 """
111 return 1/y
112
113 def baz(self,y):
114 """Example:
115
116 >>> f = foo(3)
117 Making a foo.
118 >>> f.baz(3)
119 True
120 """
121 return self.x==y
122
123
124 def test_skip_dt_decorator():
125 """Doctest-skipping decorator should preserve the docstring.
126 """
127 # Careful: 'check' must be a *verbatim* copy of the doctest_bad docstring!
128 check = """A function whose doctest we need to skip.
129
130 >>> 1+1
131 3
132 """
133 # Fetch the docstring from doctest_bad after decoration.
134 val = doctest_bad.__doc__
135
136 assert check==val,"doctest_bad docstrings don't match"
137
138
139 def test_skip_dt_decorator2():
140 """Doctest-skipping decorator should preserve function signature.
141 """
142 # Hardcoded correct answer
143 dtargs = (['x', 'y'], None, 'k', (1,))
144 # Introspect out the value
145 dtargsr = getargspec(doctest_bad)
146 assert dtargsr==dtargs, \
147 "Incorrectly reconstructed args for doctest_bad: %s" % (dtargsr,)
148
149
150 def doctest_run():
17 def doctest_run():
151 """Test running a trivial script.
18 """Test running a trivial script.
152
19
@@ -154,7 +21,6 b' def doctest_run():'
154 x is: 1
21 x is: 1
155 """
22 """
156
23
157 #@dec.skip_doctest
158 def doctest_runvars():
24 def doctest_runvars():
159 """Test that variables defined in scripts get loaded correcly via %run.
25 """Test that variables defined in scripts get loaded correcly via %run.
160
26
@@ -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
@@ -45,7 +45,10 b' def mergesort(list_of_lists, key=None):'
45 for i, itr in enumerate(iter(pl) for pl in list_of_lists):
45 for i, itr in enumerate(iter(pl) for pl in list_of_lists):
46 try:
46 try:
47 item = itr.next()
47 item = itr.next()
48 toadd = (key(item), i, item, itr) if key else (item, i, itr)
48 if key:
49 toadd = (key(item), i, item, itr)
50 else:
51 toadd = (item, i, itr)
49 heap.append(toadd)
52 heap.append(toadd)
50 except StopIteration:
53 except StopIteration:
51 pass
54 pass
@@ -1,7 +1,6 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 #
2 #
3 # IPython documentation build configuration file, created by
3 # IPython documentation build configuration file.
4 # sphinx-quickstart on Thu May 8 16:45:02 2008.
5
4
6 # NOTE: This file has been edited manually from the auto-generated one from
5 # NOTE: This file has been edited manually from the auto-generated one from
7 # sphinx. Do NOT delete and re-generate. If any changes from sphinx are
6 # sphinx. Do NOT delete and re-generate. If any changes from sphinx are
@@ -21,7 +20,11 b' import sys, os'
21 # If your extensions are in another directory, add it here. If the directory
20 # If your extensions are in another directory, add it here. If the directory
22 # is relative to the documentation root, use os.path.abspath to make it
21 # is relative to the documentation root, use os.path.abspath to make it
23 # absolute, like shown here.
22 # absolute, like shown here.
24 #sys.path.append(os.path.abspath('some/directory'))
23 sys.path.append(os.path.abspath('../sphinxext'))
24
25 # Import support for ipython console session syntax highlighting (lives
26 # in the sphinxext directory defined above)
27 import ipython_console_highlighting
25
28
26 # We load the ipython release info into a dict by explicit execution
29 # We load the ipython release info into a dict by explicit execution
27 iprelease = {}
30 iprelease = {}
@@ -32,7 +35,11 b" execfile('../../IPython/Release.py',iprelease)"
32
35
33 # Add any Sphinx extension module names here, as strings. They can be extensions
36 # Add any Sphinx extension module names here, as strings. They can be extensions
34 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
37 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
35 #extensions = []
38 extensions = ['sphinx.ext.autodoc',
39 'inheritance_diagram', 'only_directives',
40 'ipython_console_highlighting',
41 # 'plot_directive', # disabled for now, needs matplotlib
42 ]
36
43
37 # Add any paths that contain templates here, relative to this directory.
44 # Add any paths that contain templates here, relative to this directory.
38 templates_path = ['_templates']
45 templates_path = ['_templates']
@@ -67,7 +74,7 b" today_fmt = '%B %d, %Y'"
67
74
68 # List of directories, relative to source directories, that shouldn't be searched
75 # List of directories, relative to source directories, that shouldn't be searched
69 # for source files.
76 # for source files.
70 #exclude_dirs = []
77 exclude_dirs = ['attic']
71
78
72 # If true, '()' will be appended to :func: etc. cross-reference text.
79 # If true, '()' will be appended to :func: etc. cross-reference text.
73 #add_function_parentheses = True
80 #add_function_parentheses = True
@@ -135,7 +142,7 b" html_last_updated_fmt = '%b %d, %Y'"
135 #html_file_suffix = ''
142 #html_file_suffix = ''
136
143
137 # Output file base name for HTML help builder.
144 # Output file base name for HTML help builder.
138 htmlhelp_basename = 'IPythondoc'
145 htmlhelp_basename = 'ipythondoc'
139
146
140
147
141 # Options for LaTeX output
148 # Options for LaTeX output
@@ -151,10 +158,7 b" latex_font_size = '11pt'"
151 # (source start file, target name, title, author, document class [howto/manual]).
158 # (source start file, target name, title, author, document class [howto/manual]).
152
159
153 latex_documents = [ ('index', 'ipython.tex', 'IPython Documentation',
160 latex_documents = [ ('index', 'ipython.tex', 'IPython Documentation',
154 ur"""Brian Granger, Fernando Pérez and Ville Vainio\\
161 ur"""The IPython Development Team""",
155 \ \\
156 With contributions from:\\
157 Benjamin Ragan-Kelley and Barry Wark.""",
158 'manual'),
162 'manual'),
159 ]
163 ]
160
164
@@ -176,5 +180,8 b" latex_documents = [ ('index', 'ipython.tex', 'IPython Documentation',"
176 #latex_use_modindex = True
180 #latex_use_modindex = True
177
181
178
182
179 # Cleanup: delete release info to avoid pickling errors from sphinx
183 # Cleanup
184 # -------
185 # delete release info to avoid pickling errors from sphinx
186
180 del iprelease
187 del iprelease
@@ -18,6 +18,8 b' time. A hybrid approach of specifying a few options in ipythonrc and'
18 doing the more advanced configuration in ipy_user_conf.py is also
18 doing the more advanced configuration in ipy_user_conf.py is also
19 possible.
19 possible.
20
20
21 .. _ipythonrc:
22
21 The ipythonrc approach
23 The ipythonrc approach
22 ======================
24 ======================
23
25
@@ -36,11 +38,11 b' fairly primitive). Note that these are not python files, and this is'
36 deliberate, because it allows us to do some things which would be quite
38 deliberate, because it allows us to do some things which would be quite
37 tricky to implement if they were normal python files.
39 tricky to implement if they were normal python files.
38
40
39 First, an rcfile can contain permanent default values for almost all
41 First, an rcfile can contain permanent default values for almost all command
40 command line options (except things like -help or -Version). Sec
42 line options (except things like -help or -Version). :ref:`This section
41 `command line options`_ contains a description of all command-line
43 <command_line_options>` contains a description of all command-line
42 options. However, values you explicitly specify at the command line
44 options. However, values you explicitly specify at the command line override
43 override the values defined in the rcfile.
45 the values defined in the rcfile.
44
46
45 Besides command line option values, the rcfile can specify values for
47 Besides command line option values, the rcfile can specify values for
46 certain extra special options which are not available at the command
48 certain extra special options which are not available at the command
@@ -266,13 +268,13 b' which look like this::'
266 IPython profiles
268 IPython profiles
267 ================
269 ================
268
270
269 As we already mentioned, IPython supports the -profile command-line
271 As we already mentioned, IPython supports the -profile command-line option (see
270 option (see sec. `command line options`_). A profile is nothing more
272 :ref:`here <command_line_options>`). A profile is nothing more than a
271 than a particular configuration file like your basic ipythonrc one,
273 particular configuration file like your basic ipythonrc one, but with
272 but with particular customizations for a specific purpose. When you
274 particular customizations for a specific purpose. When you start IPython with
273 start IPython with 'ipython -profile <name>', it assumes that in your
275 'ipython -profile <name>', it assumes that in your IPYTHONDIR there is a file
274 IPYTHONDIR there is a file called ipythonrc-<name> or
276 called ipythonrc-<name> or ipy_profile_<name>.py, and loads it instead of the
275 ipy_profile_<name>.py, and loads it instead of the normal ipythonrc.
277 normal ipythonrc.
276
278
277 This system allows you to maintain multiple configurations which load
279 This system allows you to maintain multiple configurations which load
278 modules, set options, define functions, etc. suitable for different
280 modules, set options, define functions, etc. suitable for different
@@ -11,28 +11,27 b' in a directory named by default $HOME/.ipython. You can change this by'
11 defining the environment variable IPYTHONDIR, or at runtime with the
11 defining the environment variable IPYTHONDIR, or at runtime with the
12 command line option -ipythondir.
12 command line option -ipythondir.
13
13
14 If all goes well, the first time you run IPython it should
14 If all goes well, the first time you run IPython it should automatically create
15 automatically create a user copy of the config directory for you,
15 a user copy of the config directory for you, based on its builtin defaults. You
16 based on its builtin defaults. You can look at the files it creates to
16 can look at the files it creates to learn more about configuring the
17 learn more about configuring the system. The main file you will modify
17 system. The main file you will modify to configure IPython's behavior is called
18 to configure IPython's behavior is called ipythonrc (with a .ini
18 ipythonrc (with a .ini extension under Windows), included for reference
19 extension under Windows), included for reference in `ipythonrc`_
19 :ref:`here <ipythonrc>`. This file is very commented and has many variables you
20 section. This file is very commented and has many variables you can
20 can change to suit your taste, you can find more details :ref:`here
21 change to suit your taste, you can find more details in
21 <customization>`. Here we discuss the basic things you will want to make sure
22 Sec. customization_. Here we discuss the basic things you will want to
22 things are working properly from the beginning.
23 make sure things are working properly from the beginning.
24
23
25
24
26 .. _Accessing help:
25 .. _accessing_help:
27
26
28 Access to the Python help system
27 Access to the Python help system
29 ================================
28 ================================
30
29
31 This is true for Python in general (not just for IPython): you should
30 This is true for Python in general (not just for IPython): you should have an
32 have an environment variable called PYTHONDOCS pointing to the directory
31 environment variable called PYTHONDOCS pointing to the directory where your
33 where your HTML Python documentation lives. In my system it's
32 HTML Python documentation lives. In my system it's
34 /usr/share/doc/python-docs-2.3.4/html, check your local details or ask
33 :file:`/usr/share/doc/python-doc/html`, check your local details or ask your
35 your systems administrator.
34 systems administrator.
36
35
37 This is the directory which holds the HTML version of the Python
36 This is the directory which holds the HTML version of the Python
38 manuals. Unfortunately it seems that different Linux distributions
37 manuals. Unfortunately it seems that different Linux distributions
@@ -40,8 +39,9 b' package these files differently, so you may have to look around a bit.'
40 Below I show the contents of this directory on my system for reference::
39 Below I show the contents of this directory on my system for reference::
41
40
42 [html]> ls
41 [html]> ls
43 about.dat acks.html dist/ ext/ index.html lib/ modindex.html
42 about.html dist/ icons/ lib/ python2.5.devhelp.gz whatsnew/
44 stdabout.dat tut/ about.html api/ doc/ icons/ inst/ mac/ ref/ style.css
43 acks.html doc/ index.html mac/ ref/
44 api/ ext/ inst/ modindex.html tut/
45
45
46 You should really make sure this variable is correctly set so that
46 You should really make sure this variable is correctly set so that
47 Python's pydoc-based help system works. It is a powerful and convenient
47 Python's pydoc-based help system works. It is a powerful and convenient
@@ -108,6 +108,8 b' The following terminals seem to handle the color sequences fine:'
108 support under cygwin, please post to the IPython mailing list so
108 support under cygwin, please post to the IPython mailing list so
109 this issue can be resolved for all users.
109 this issue can be resolved for all users.
110
110
111 .. _pyreadline: https://code.launchpad.net/pyreadline
112
111 These have shown problems:
113 These have shown problems:
112
114
113 * Windows command prompt in WinXP/2k logged into a Linux machine via
115 * Windows command prompt in WinXP/2k logged into a Linux machine via
@@ -157,13 +159,12 b' $HOME/.ipython/ipythonrc and set the colors option to the desired value.'
157 Object details (types, docstrings, source code, etc.)
159 Object details (types, docstrings, source code, etc.)
158 =====================================================
160 =====================================================
159
161
160 IPython has a set of special functions for studying the objects you
162 IPython has a set of special functions for studying the objects you are working
161 are working with, discussed in detail in Sec. `dynamic object
163 with, discussed in detail :ref:`here <dynamic_object_info>`. But this system
162 information`_. But this system relies on passing information which is
164 relies on passing information which is longer than your screen through a data
163 longer than your screen through a data pager, such as the common Unix
165 pager, such as the common Unix less and more programs. In order to be able to
164 less and more programs. In order to be able to see this information in
166 see this information in color, your pager needs to be properly configured. I
165 color, your pager needs to be properly configured. I strongly
167 strongly recommend using less instead of more, as it seems that more simply can
166 recommend using less instead of more, as it seems that more simply can
167 not understand colored text correctly.
168 not understand colored text correctly.
168
169
169 In order to configure less as your default pager, do the following:
170 In order to configure less as your default pager, do the following:
@@ -4,24 +4,39 b''
4 Credits
4 Credits
5 =======
5 =======
6
6
7 IPython is mainly developed by Fernando Pérez
7 IPython is led by Fernando Pérez.
8 <Fernando.Perez@colorado.edu>, but the project was born from mixing in
8
9 Fernando's code with the IPP project by Janko Hauser
9 As of this writing, the following developers have joined the core team:
10 <jhauser-AT-zscout.de> and LazyPython by Nathan Gray
10
11 <n8gray-AT-caltech.edu>. For all IPython-related requests, please
11 * [Robert Kern] <rkern-AT-enthought.com>: co-mentored the 2005
12 contact Fernando.
12 Google Summer of Code project to develop python interactive
13
13 notebooks (XML documents) and graphical interface. This project
14 As of early 2006, the following developers have joined the core team:
14 was awarded to the students Tzanko Matev <tsanko-AT-gmail.com> and
15
15 Toni Alatalo <antont-AT-an.org>.
16 * [Robert Kern] <rkern-AT-enthought.com>: co-mentored the 2005
16
17 Google Summer of Code project to develop python interactive
17 * [Brian Granger] <ellisonbg-AT-gmail.com>: extending IPython to allow
18 notebooks (XML documents) and graphical interface. This project
18 support for interactive parallel computing.
19 was awarded to the students Tzanko Matev <tsanko-AT-gmail.com> and
19
20 Toni Alatalo <antont-AT-an.org>
20 * [Benjamin (Min) Ragan-Kelley]: key work on IPython's parallel
21 * [Brian Granger] <bgranger-AT-scu.edu>: extending IPython to allow
21 computing infrastructure.
22 support for interactive parallel computing.
22
23 * [Ville Vainio] <vivainio-AT-gmail.com>: Ville is the new
23 * [Ville Vainio] <vivainio-AT-gmail.com>: Ville has made many improvements
24 maintainer for the main trunk of IPython after version 0.7.1.
24 to the core of IPython and was the maintainer of the main IPython
25 trunk from version 0.7.1 to 0.8.4.
26
27 * [Gael Varoquaux] <gael.varoquaux-AT-normalesup.org>: work on the merged
28 architecture for the interpreter as of version 0.9, implementing a new WX GUI
29 based on this system.
30
31 * [Barry Wark] <barrywark-AT-gmail.com>: implementing a new Cocoa GUI, as well
32 as work on the new interpreter architecture and Twisted support.
33
34 * [Laurent Dufrechou] <laurent.dufrechou-AT-gmail.com>: development of the WX
35 GUI support.
36
37 * [Jörgen Stenarson] <jorgen.stenarson-AT-bostream.nu>: maintainer of the
38 PyReadline project, necessary for IPython under windows.
39
25
40
26 The IPython project is also very grateful to:
41 The IPython project is also very grateful to:
27
42
@@ -50,90 +65,143 b" an O'Reilly Python editor. His Oct/11/2001 article about IPP and"
50 LazyPython, was what got this project started. You can read it at:
65 LazyPython, was what got this project started. You can read it at:
51 http://www.onlamp.com/pub/a/python/2001/10/11/pythonnews.html.
66 http://www.onlamp.com/pub/a/python/2001/10/11/pythonnews.html.
52
67
53 And last but not least, all the kind IPython users who have emailed new
68 And last but not least, all the kind IPython users who have emailed new code,
54 code, bug reports, fixes, comments and ideas. A brief list follows,
69 bug reports, fixes, comments and ideas. A brief list follows, please let us
55 please let me know if I have ommitted your name by accident:
70 know if we have ommitted your name by accident:
56
71
57 * [Jack Moffit] <jack-AT-xiph.org> Bug fixes, including the infamous
72 * Dan Milstein <danmil-AT-comcast.net>. A bold refactoring of the
58 color problem. This bug alone caused many lost hours and
73 core prefilter stuff in the IPython interpreter.
59 frustration, many thanks to him for the fix. I've always been a
74
60 fan of Ogg & friends, now I have one more reason to like these folks.
75 * [Jack Moffit] <jack-AT-xiph.org> Bug fixes, including the infamous
61 Jack is also contributing with Debian packaging and many other
76 color problem. This bug alone caused many lost hours and
62 things.
77 frustration, many thanks to him for the fix. I've always been a
63 * [Alexander Schmolck] <a.schmolck-AT-gmx.net> Emacs work, bug
78 fan of Ogg & friends, now I have one more reason to like these folks.
64 reports, bug fixes, ideas, lots more. The ipython.el mode for
79 Jack is also contributing with Debian packaging and many other
65 (X)Emacs is Alex's code, providing full support for IPython under
80 things.
66 (X)Emacs.
81
67 * [Andrea Riciputi] <andrea.riciputi-AT-libero.it> Mac OSX
82 * [Alexander Schmolck] <a.schmolck-AT-gmx.net> Emacs work, bug
68 information, Fink package management.
83 reports, bug fixes, ideas, lots more. The ipython.el mode for
69 * [Gary Bishop] <gb-AT-cs.unc.edu> Bug reports, and patches to work
84 (X)Emacs is Alex's code, providing full support for IPython under
70 around the exception handling idiosyncracies of WxPython. Readline
85 (X)Emacs.
71 and color support for Windows.
86
72 * [Jeffrey Collins] <Jeff.Collins-AT-vexcel.com> Bug reports. Much
87 * [Andrea Riciputi] <andrea.riciputi-AT-libero.it> Mac OSX
73 improved readline support, including fixes for Python 2.3.
88 information, Fink package management.
74 * [Dryice Liu] <dryice-AT-liu.com.cn> FreeBSD port.
89
75 * [Mike Heeter] <korora-AT-SDF.LONESTAR.ORG>
90 * [Gary Bishop] <gb-AT-cs.unc.edu> Bug reports, and patches to work
76 * [Christopher Hart] <hart-AT-caltech.edu> PDB integration.
91 around the exception handling idiosyncracies of WxPython. Readline
77 * [Milan Zamazal] <pdm-AT-zamazal.org> Emacs info.
92 and color support for Windows.
78 * [Philip Hisley] <compsys-AT-starpower.net>
93
79 * [Holger Krekel] <pyth-AT-devel.trillke.net> Tab completion, lots
94 * [Jeffrey Collins] <Jeff.Collins-AT-vexcel.com> Bug reports. Much
80 more.
95 improved readline support, including fixes for Python 2.3.
81 * [Robin Siebler] <robinsiebler-AT-starband.net>
96
82 * [Ralf Ahlbrink] <ralf_ahlbrink-AT-web.de>
97 * [Dryice Liu] <dryice-AT-liu.com.cn> FreeBSD port.
83 * [Thorsten Kampe] <thorsten-AT-thorstenkampe.de>
98
84 * [Fredrik Kant] <fredrik.kant-AT-front.com> Windows setup.
99 * [Mike Heeter] <korora-AT-SDF.LONESTAR.ORG>
85 * [Syver Enstad] <syver-en-AT-online.no> Windows setup.
100
86 * [Richard] <rxe-AT-renre-europe.com> Global embedding.
101 * [Christopher Hart] <hart-AT-caltech.edu> PDB integration.
87 * [Hayden Callow] <h.callow-AT-elec.canterbury.ac.nz> Gnuplot.py 1.6
102
88 compatibility.
103 * [Milan Zamazal] <pdm-AT-zamazal.org> Emacs info.
89 * [Leonardo Santagada] <retype-AT-terra.com.br> Fixes for Windows
104
90 installation.
105 * [Philip Hisley] <compsys-AT-starpower.net>
91 * [Christopher Armstrong] <radix-AT-twistedmatrix.com> Bugfixes.
106
92 * [Francois Pinard] <pinard-AT-iro.umontreal.ca> Code and
107 * [Holger Krekel] <pyth-AT-devel.trillke.net> Tab completion, lots
93 documentation fixes.
108 more.
94 * [Cory Dodt] <cdodt-AT-fcoe.k12.ca.us> Bug reports and Windows
109
95 ideas. Patches for Windows installer.
110 * [Robin Siebler] <robinsiebler-AT-starband.net>
96 * [Olivier Aubert] <oaubert-AT-bat710.univ-lyon1.fr> New magics.
111
97 * [King C. Shu] <kingshu-AT-myrealbox.com> Autoindent patch.
112 * [Ralf Ahlbrink] <ralf_ahlbrink-AT-web.de>
98 * [Chris Drexler] <chris-AT-ac-drexler.de> Readline packages for
113
99 Win32/CygWin.
114 * [Thorsten Kampe] <thorsten-AT-thorstenkampe.de>
100 * [Gustavo Cordova Avila] <gcordova-AT-sismex.com> EvalDict code for
115
101 nice, lightweight string interpolation.
116 * [Fredrik Kant] <fredrik.kant-AT-front.com> Windows setup.
102 * [Kasper Souren] <Kasper.Souren-AT-ircam.fr> Bug reports, ideas.
117
103 * [Gever Tulley] <gever-AT-helium.com> Code contributions.
118 * [Syver Enstad] <syver-en-AT-online.no> Windows setup.
104 * [Ralf Schmitt] <ralf-AT-brainbot.com> Bug reports & fixes.
119
105 * [Oliver Sander] <osander-AT-gmx.de> Bug reports.
120 * [Richard] <rxe-AT-renre-europe.com> Global embedding.
106 * [Rod Holland] <rhh-AT-structurelabs.com> Bug reports and fixes to
121
107 logging module.
122 * [Hayden Callow] <h.callow-AT-elec.canterbury.ac.nz> Gnuplot.py 1.6
108 * [Daniel 'Dang' Griffith] <pythondev-dang-AT-lazytwinacres.net>
123 compatibility.
109 Fixes, enhancement suggestions for system shell use.
124
110 * [Viktor Ransmayr] <viktor.ransmayr-AT-t-online.de> Tests and
125 * [Leonardo Santagada] <retype-AT-terra.com.br> Fixes for Windows
111 reports on Windows installation issues. Contributed a true Windows
126 installation.
112 binary installer.
127
113 * [Mike Salib] <msalib-AT-mit.edu> Help fixing a subtle bug related
128 * [Christopher Armstrong] <radix-AT-twistedmatrix.com> Bugfixes.
114 to traceback printing.
129
115 * [W.J. van der Laan] <gnufnork-AT-hetdigitalegat.nl> Bash-like
130 * [Francois Pinard] <pinard-AT-iro.umontreal.ca> Code and
116 prompt specials.
131 documentation fixes.
117 * [Antoon Pardon] <Antoon.Pardon-AT-rece.vub.ac.be> Critical fix for
132
118 the multithreaded IPython.
133 * [Cory Dodt] <cdodt-AT-fcoe.k12.ca.us> Bug reports and Windows
119 * [John Hunter] <jdhunter-AT-nitace.bsd.uchicago.edu> Matplotlib
134 ideas. Patches for Windows installer.
120 author, helped with all the development of support for matplotlib
135
121 in IPyhton, including making necessary changes to matplotlib itself.
136 * [Olivier Aubert] <oaubert-AT-bat710.univ-lyon1.fr> New magics.
122 * [Matthew Arnison] <maffew-AT-cat.org.au> Bug reports, '%run -d' idea.
137
123 * [Prabhu Ramachandran] <prabhu_r-AT-users.sourceforge.net> Help
138 * [King C. Shu] <kingshu-AT-myrealbox.com> Autoindent patch.
124 with (X)Emacs support, threading patches, ideas...
139
125 * [Norbert Tretkowski] <tretkowski-AT-inittab.de> help with Debian
140 * [Chris Drexler] <chris-AT-ac-drexler.de> Readline packages for
126 packaging and distribution.
141 Win32/CygWin.
127 * [George Sakkis] <gsakkis-AT-eden.rutgers.edu> New matcher for
142
128 tab-completing named arguments of user-defined functions.
143 * [Gustavo Cordova Avila] <gcordova-AT-sismex.com> EvalDict code for
129 * [Jörgen Stenarson] <jorgen.stenarson-AT-bostream.nu> Wildcard
144 nice, lightweight string interpolation.
130 support implementation for searching namespaces.
145
131 * [Vivian De Smedt] <vivian-AT-vdesmedt.com> Debugger enhancements,
146 * [Kasper Souren] <Kasper.Souren-AT-ircam.fr> Bug reports, ideas.
132 so that when pdb is activated from within IPython, coloring, tab
147
133 completion and other features continue to work seamlessly.
148 * [Gever Tulley] <gever-AT-helium.com> Code contributions.
134 * [Scott Tsai] <scottt958-AT-yahoo.com.tw> Support for automatic
149
135 editor invocation on syntax errors (see
150 * [Ralf Schmitt] <ralf-AT-brainbot.com> Bug reports & fixes.
136 http://www.scipy.net/roundup/ipython/issue36).
151
137 * [Alexander Belchenko] <bialix-AT-ukr.net> Improvements for win32
152 * [Oliver Sander] <osander-AT-gmx.de> Bug reports.
138 paging system.
153
139 * [Will Maier] <willmaier-AT-ml1.net> Official OpenBSD port. No newline at end of file
154 * [Rod Holland] <rhh-AT-structurelabs.com> Bug reports and fixes to
155 logging module.
156
157 * [Daniel 'Dang' Griffith] <pythondev-dang-AT-lazytwinacres.net>
158 Fixes, enhancement suggestions for system shell use.
159
160 * [Viktor Ransmayr] <viktor.ransmayr-AT-t-online.de> Tests and
161 reports on Windows installation issues. Contributed a true Windows
162 binary installer.
163
164 * [Mike Salib] <msalib-AT-mit.edu> Help fixing a subtle bug related
165 to traceback printing.
166
167 * [W.J. van der Laan] <gnufnork-AT-hetdigitalegat.nl> Bash-like
168 prompt specials.
169
170 * [Antoon Pardon] <Antoon.Pardon-AT-rece.vub.ac.be> Critical fix for
171 the multithreaded IPython.
172
173 * [John Hunter] <jdhunter-AT-nitace.bsd.uchicago.edu> Matplotlib
174 author, helped with all the development of support for matplotlib
175 in IPyhton, including making necessary changes to matplotlib itself.
176
177 * [Matthew Arnison] <maffew-AT-cat.org.au> Bug reports, '%run -d' idea.
178
179 * [Prabhu Ramachandran] <prabhu_r-AT-users.sourceforge.net> Help
180 with (X)Emacs support, threading patches, ideas...
181
182 * [Norbert Tretkowski] <tretkowski-AT-inittab.de> help with Debian
183 packaging and distribution.
184
185 * [George Sakkis] <gsakkis-AT-eden.rutgers.edu> New matcher for
186 tab-completing named arguments of user-defined functions.
187
188 * [Jörgen Stenarson] <jorgen.stenarson-AT-bostream.nu> Wildcard
189 support implementation for searching namespaces.
190
191 * [Vivian De Smedt] <vivian-AT-vdesmedt.com> Debugger enhancements,
192 so that when pdb is activated from within IPython, coloring, tab
193 completion and other features continue to work seamlessly.
194
195 * [Scott Tsai] <scottt958-AT-yahoo.com.tw> Support for automatic
196 editor invocation on syntax errors (see
197 http://www.scipy.net/roundup/ipython/issue36).
198
199 * [Alexander Belchenko] <bialix-AT-ukr.net> Improvements for win32
200 paging system.
201
202 * [Will Maier] <willmaier-AT-ml1.net> Official OpenBSD port.
203
204 * [Ondrej Certik] <ondrej-AT-certik.cz>: set up the IPython docs to use the new
205 Sphinx system used by Python, Matplotlib and many more projects.
206
207 * [Stefan van der Walt] <stefan-AT-sun.ac.za>: support for the new config system.
@@ -1,10 +1,8 b''
1 .. _development:
1 .. _development:
2
2
3 ==================================
3 ==============================
4 IPython development guidelines
4 IPython development guidelines
5 ==================================
5 ==============================
6
7 .. contents::
8
6
9
7
10 Overview
8 Overview
@@ -24,11 +22,11 b' There are two, no three, main goals of the IPython effort:'
24 to be used from within a variety of GUI applications.
22 to be used from within a variety of GUI applications.
25 3. Implement a system for interactive parallel computing.
23 3. Implement a system for interactive parallel computing.
26
24
27 While the third goal may seem a bit unrelated to the main focus of IPython, it turns
25 While the third goal may seem a bit unrelated to the main focus of IPython, it
28 out that the technologies required for this goal are nearly identical with those
26 turns out that the technologies required for this goal are nearly identical
29 required for goal two. This is the main reason the interactive parallel computing
27 with those required for goal two. This is the main reason the interactive
30 capabilities are being put into IPython proper. Currently the third of these goals is
28 parallel computing capabilities are being put into IPython proper. Currently
31 furthest along.
29 the third of these goals is furthest along.
32
30
33 This document describes IPython from the perspective of developers.
31 This document describes IPython from the perspective of developers.
34
32
@@ -39,51 +37,59 b' Project organization'
39 Subpackages
37 Subpackages
40 -----------
38 -----------
41
39
42 IPython is organized into semi self-contained subpackages. Each of the subpackages will have its own:
40 IPython is organized into semi self-contained subpackages. Each of the
41 subpackages will have its own:
43
42
44 - **Dependencies**. One of the most important things to keep in mind in
43 - **Dependencies**. One of the most important things to keep in mind in
45 partitioning code amongst subpackages, is that they should be used to cleanly
44 partitioning code amongst subpackages, is that they should be used to cleanly
46 encapsulate dependencies.
45 encapsulate dependencies.
46
47 - **Tests**. Each subpackage shoud have its own ``tests`` subdirectory that
47 - **Tests**. Each subpackage shoud have its own ``tests`` subdirectory that
48 contains all of the tests for that package. For information about writing tests
48 contains all of the tests for that package. For information about writing
49 for IPython, see the `Testing System`_ section of this document.
49 tests for IPython, see the `Testing System`_ section of this document.
50 - **Configuration**. Each subpackage should have its own ``config`` subdirectory
50
51 that contains the configuration information for the components of the
51 - **Configuration**. Each subpackage should have its own ``config``
52 subpackage. For information about how the IPython configuration system
52 subdirectory that contains the configuration information for the components
53 works, see the `Configuration System`_ section of this document.
53 of the subpackage. For information about how the IPython configuration
54 - **Scripts**. Each subpackage should have its own ``scripts`` subdirectory that
54 system works, see the `Configuration System`_ section of this document.
55 contains all of the command line scripts associated with the subpackage.
55
56 - **Scripts**. Each subpackage should have its own ``scripts`` subdirectory
57 that contains all of the command line scripts associated with the subpackage.
56
58
57 Installation and dependencies
59 Installation and dependencies
58 -----------------------------
60 -----------------------------
59
61
60 IPython will not use `setuptools`_ for installation. Instead, we will use standard
62 IPython will not use `setuptools`_ for installation. Instead, we will use
61 ``setup.py`` scripts that use `distutils`_. While there are a number a extremely nice
63 standard ``setup.py`` scripts that use `distutils`_. While there are a number a
62 features that `setuptools`_ has (like namespace packages), the current implementation
64 extremely nice features that `setuptools`_ has (like namespace packages), the
63 of `setuptools`_ has performance problems, particularly on shared file systems. In
65 current implementation of `setuptools`_ has performance problems, particularly
64 particular, when Python packages are installed on NSF file systems, import times
66 on shared file systems. In particular, when Python packages are installed on
65 become much too long (up towards 10 seconds).
67 NSF file systems, import times become much too long (up towards 10 seconds).
66
68
67 Because IPython is being used extensively in the context of high performance
69 Because IPython is being used extensively in the context of high performance
68 computing, where performance is critical but shared file systems are common, we feel
70 computing, where performance is critical but shared file systems are common, we
69 these performance hits are not acceptable. Thus, until the performance problems
71 feel these performance hits are not acceptable. Thus, until the performance
70 associated with `setuptools`_ are addressed, we will stick with plain `distutils`_. We
72 problems associated with `setuptools`_ are addressed, we will stick with plain
71 are hopeful that these problems will be addressed and that we will eventually begin
73 `distutils`_. We are hopeful that these problems will be addressed and that we
72 using `setuptools`_. Because of this, we are trying to organize IPython in a way that
74 will eventually begin using `setuptools`_. Because of this, we are trying to
73 will make the eventual transition to `setuptools`_ as painless as possible.
75 organize IPython in a way that will make the eventual transition to
74
76 `setuptools`_ as painless as possible.
75 Because we will be using `distutils`_, there will be no method for automatically installing dependencies. Instead, we are following the approach of `Matplotlib`_ which can be summarized as follows:
77
78 Because we will be using `distutils`_, there will be no method for
79 automatically installing dependencies. Instead, we are following the approach
80 of `Matplotlib`_ which can be summarized as follows:
76
81
77 - Distinguish between required and optional dependencies. However, the required
82 - Distinguish between required and optional dependencies. However, the required
78 dependencies for IPython should be only the Python standard library.
83 dependencies for IPython should be only the Python standard library.
79 - Upon installation check to see which optional dependencies are present and tell
84
80 the user which parts of IPython need which optional dependencies.
85 - Upon installation check to see which optional dependencies are present and
86 tell the user which parts of IPython need which optional dependencies.
81
87
82 It is absolutely critical that each subpackage of IPython has a clearly specified set
88 It is absolutely critical that each subpackage of IPython has a clearly
83 of dependencies and that dependencies are not carelessly inherited from other IPython
89 specified set of dependencies and that dependencies are not carelessly
84 subpackages. Furthermore, tests that have certain dependencies should not fail if
90 inherited from other IPython subpackages. Furthermore, tests that have certain
85 those dependencies are not present. Instead they should be skipped and print a
91 dependencies should not fail if those dependencies are not present. Instead
86 message.
92 they should be skipped and print a message.
87
93
88 .. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
94 .. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
89 .. _distutils: http://docs.python.org/lib/module-distutils.html
95 .. _distutils: http://docs.python.org/lib/module-distutils.html
@@ -106,9 +112,10 b' Specific subpackages'
106
112
107 ``frontends``
113 ``frontends``
108 The various frontends for IPython. A frontend is the end-user application
114 The various frontends for IPython. A frontend is the end-user application
109 that exposes the capabilities of IPython to the user. The most basic frontend
115 that exposes the capabilities of IPython to the user. The most basic
110 will simply be a terminal based application that looks just like today 's
116 frontend will simply be a terminal based application that looks just like
111 IPython. Other frontends will likely be more powerful and based on GUI toolkits.
117 today 's IPython. Other frontends will likely be more powerful and based
118 on GUI toolkits.
112
119
113 ``notebook``
120 ``notebook``
114 An application that allows users to work with IPython notebooks.
121 An application that allows users to work with IPython notebooks.
@@ -120,10 +127,12 b' Specific subpackages'
120 Version control
127 Version control
121 ===============
128 ===============
122
129
123 In the past, IPython development has been done using `Subversion`__. Recently, we made the transition to using `Bazaar`__ and `Launchpad`__. This makes it much easier for people
130 In the past, IPython development has been done using `Subversion`__. Recently,
124 to contribute code to IPython. Here is a sketch of how to use Bazaar for IPython
131 we made the transition to using `Bazaar`__ and `Launchpad`__. This makes it
125 development. First, you should install Bazaar. After you have done that, make
132 much easier for people to contribute code to IPython. Here is a sketch of how
126 sure that it is working by getting the latest main branch of IPython::
133 to use Bazaar for IPython development. First, you should install Bazaar.
134 After you have done that, make sure that it is working by getting the latest
135 main branch of IPython::
127
136
128 $ bzr branch lp:ipython
137 $ bzr branch lp:ipython
129
138
@@ -131,17 +140,17 b' Now you can create a new branch for you to do your work in::'
131
140
132 $ bzr branch ipython ipython-mybranch
141 $ bzr branch ipython ipython-mybranch
133
142
134 The typical work cycle in this branch will be to make changes in `ipython-mybranch`
143 The typical work cycle in this branch will be to make changes in
135 and then commit those changes using the commit command::
144 ``ipython-mybranch`` and then commit those changes using the commit command::
136
145
137 $ ...do work in ipython-mybranch...
146 $ ...do work in ipython-mybranch...
138 $ bzr ci -m "the commit message goes here"
147 $ bzr ci -m "the commit message goes here"
139
148
140 Please note that since we now don't use an old-style linear ChangeLog
149 Please note that since we now don't use an old-style linear ChangeLog (that
141 (that tends to cause problems with distributed version control
150 tends to cause problems with distributed version control systems), you should
142 systems), you should ensure that your log messages are reasonably
151 ensure that your log messages are reasonably detailed. Use a docstring-like
143 detailed. Use a docstring-like approach in the commit messages
152 approach in the commit messages (including the second line being left
144 (including the second line being left *blank*)::
153 *blank*)::
145
154
146 Single line summary of changes being committed.
155 Single line summary of changes being committed.
147
156
@@ -149,27 +158,27 b' detailed. Use a docstring-like approach in the commit messages'
149 - including crediting outside contributors if they sent the
158 - including crediting outside contributors if they sent the
150 code/bug/idea!
159 code/bug/idea!
151
160
152 If we couple this with a policy of making single commits for each
161 If we couple this with a policy of making single commits for each reasonably
153 reasonably atomic change, the bzr log should give an excellent view of
162 atomic change, the bzr log should give an excellent view of the project, and
154 the project, and the `--short` log option becomes a nice summary.
163 the `--short` log option becomes a nice summary.
155
164
156 While working with this branch, it is a good idea to merge in changes that have been
165 While working with this branch, it is a good idea to merge in changes that have
157 made upstream in the parent branch. This can be done by doing::
166 been made upstream in the parent branch. This can be done by doing::
158
167
159 $ bzr pull
168 $ bzr pull
160
169
161 If this command shows that the branches have diverged, then you should do a merge
170 If this command shows that the branches have diverged, then you should do a
162 instead::
171 merge instead::
163
172
164 $ bzr merge lp:ipython
173 $ bzr merge lp:ipython
165
174
166 If you want others to be able to see your branch, you can create an account with
175 If you want others to be able to see your branch, you can create an account
167 launchpad and push the branch to your own workspace::
176 with launchpad and push the branch to your own workspace::
168
177
169 $ bzr push bzr+ssh://<me>@bazaar.launchpad.net/~<me>/+junk/ipython-mybranch
178 $ bzr push bzr+ssh://<me>@bazaar.launchpad.net/~<me>/+junk/ipython-mybranch
170
179
171 Finally, once the work in your branch is done, you can merge your changes back into
180 Finally, once the work in your branch is done, you can merge your changes back
172 the `ipython` branch by using merge::
181 into the `ipython` branch by using merge::
173
182
174 $ cd ipython
183 $ cd ipython
175 $ merge ../ipython-mybranch
184 $ merge ../ipython-mybranch
@@ -177,8 +186,9 b' the `ipython` branch by using merge::'
177 $ bzr ci -m "Fixing that bug"
186 $ bzr ci -m "Fixing that bug"
178 $ bzr push
187 $ bzr push
179
188
180 But this will require you to have write permissions to the `ipython` branch. It you don't
189 But this will require you to have write permissions to the `ipython` branch.
181 you can tell one of the IPython devs about your branch and they can do the merge for you.
190 It you don't you can tell one of the IPython devs about your branch and they
191 can do the merge for you.
182
192
183 More information about Bazaar workflows can be found `here`__.
193 More information about Bazaar workflows can be found `here`__.
184
194
@@ -193,27 +203,29 b' Documentation'
193 Standalone documentation
203 Standalone documentation
194 ------------------------
204 ------------------------
195
205
196 All standalone documentation should be written in plain text (``.txt``) files using
206 All standalone documentation should be written in plain text (``.txt``) files
197 `reStructuredText`_ for markup and formatting. All such documentation should be placed
207 using `reStructuredText`_ for markup and formatting. All such documentation
198 in the top level directory ``docs`` of the IPython source tree. Or, when appropriate,
208 should be placed in the top level directory ``docs`` of the IPython source
199 a suitably named subdirectory should be used. The documentation in this location will
209 tree. Or, when appropriate, a suitably named subdirectory should be used. The
200 serve as the main source for IPython documentation and all existing documentation
210 documentation in this location will serve as the main source for IPython
201 should be converted to this format.
211 documentation and all existing documentation should be converted to this
212 format.
202
213
203 In the future, the text files in the ``docs`` directory will be used to generate all
214 In the future, the text files in the ``docs`` directory will be used to
204 forms of documentation for IPython. This include documentation on the IPython website
215 generate all forms of documentation for IPython. This include documentation on
205 as well as *pdf* documentation.
216 the IPython website as well as *pdf* documentation.
206
217
207 .. _reStructuredText: http://docutils.sourceforge.net/rst.html
218 .. _reStructuredText: http://docutils.sourceforge.net/rst.html
208
219
209 Docstring format
220 Docstring format
210 ----------------
221 ----------------
211
222
212 Good docstrings are very important. All new code will use `Epydoc`_ for generating API
223 Good docstrings are very important. All new code will use `Epydoc`_ for
213 docs, so we will follow the `Epydoc`_ conventions. More specifically, we will use
224 generating API docs, so we will follow the `Epydoc`_ conventions. More
214 `reStructuredText`_ for markup and formatting, since it is understood by a wide
225 specifically, we will use `reStructuredText`_ for markup and formatting, since
215 variety of tools. This means that if in the future we have any reason to change from
226 it is understood by a wide variety of tools. This means that if in the future
216 `Epydoc`_ to something else, we'll have fewer transition pains.
227 we have any reason to change from `Epydoc`_ to something else, we'll have fewer
228 transition pains.
217
229
218 Details about using `reStructuredText`_ for docstrings can be found `here
230 Details about using `reStructuredText`_ for docstrings can be found `here
219 <http://epydoc.sourceforge.net/manual-othermarkup.html>`_.
231 <http://epydoc.sourceforge.net/manual-othermarkup.html>`_.
@@ -233,7 +245,8 b' Coding conventions'
233 General
245 General
234 -------
246 -------
235
247
236 In general, we'll try to follow the standard Python style conventions as described here:
248 In general, we'll try to follow the standard Python style conventions as
249 described here:
237
250
238 - `Style Guide for Python Code <http://www.python.org/peps/pep-0008.html>`_
251 - `Style Guide for Python Code <http://www.python.org/peps/pep-0008.html>`_
239
252
@@ -250,8 +263,8 b' Other comments:'
250 Naming conventions
263 Naming conventions
251 ------------------
264 ------------------
252
265
253 In terms of naming conventions, we'll follow the guidelines from the `Style Guide for
266 In terms of naming conventions, we'll follow the guidelines from the `Style
254 Python Code`_.
267 Guide for Python Code`_.
255
268
256 For all new IPython code (and much existing code is being refactored), we'll use:
269 For all new IPython code (and much existing code is being refactored), we'll use:
257
270
@@ -259,67 +272,81 b" For all new IPython code (and much existing code is being refactored), we'll use"
259
272
260 - ``CamelCase`` for class names.
273 - ``CamelCase`` for class names.
261
274
262 - ``lowercase_with_underscores`` for methods, functions, variables and attributes.
275 - ``lowercase_with_underscores`` for methods, functions, variables and
276 attributes.
263
277
264 This may be confusing as most of the existing IPython codebase uses a different convention (``lowerCamelCase`` for methods and attributes). Slowly, we will move IPython over to the new
278 This may be confusing as most of the existing IPython codebase uses a different
265 convention, providing shadow names for backward compatibility in public interfaces.
279 convention (``lowerCamelCase`` for methods and attributes). Slowly, we will
280 move IPython over to the new convention, providing shadow names for backward
281 compatibility in public interfaces.
266
282
267 There are, however, some important exceptions to these rules. In some cases, IPython
283 There are, however, some important exceptions to these rules. In some cases,
268 code will interface with packages (Twisted, Wx, Qt) that use other conventions. At some level this makes it impossible to adhere to our own standards at all times. In particular, when subclassing classes that use other naming conventions, you must follow their naming conventions. To deal with cases like this, we propose the following policy:
284 IPython code will interface with packages (Twisted, Wx, Qt) that use other
285 conventions. At some level this makes it impossible to adhere to our own
286 standards at all times. In particular, when subclassing classes that use other
287 naming conventions, you must follow their naming conventions. To deal with
288 cases like this, we propose the following policy:
269
289
270 - If you are subclassing a class that uses different conventions, use its
290 - If you are subclassing a class that uses different conventions, use its
271 naming conventions throughout your subclass. Thus, if you are creating a
291 naming conventions throughout your subclass. Thus, if you are creating a
272 Twisted Protocol class, used Twisted's ``namingSchemeForMethodsAndAttributes.``
292 Twisted Protocol class, used Twisted's
273
293 ``namingSchemeForMethodsAndAttributes.``
274 - All IPython's official interfaces should use our conventions. In some cases
294
275 this will mean that you need to provide shadow names (first implement ``fooBar``
295 - All IPython's official interfaces should use our conventions. In some cases
276 and then ``foo_bar = fooBar``). We want to avoid this at all costs, but it
296 this will mean that you need to provide shadow names (first implement
277 will probably be necessary at times. But, please use this sparingly!
297 ``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all
278
298 costs, but it will probably be necessary at times. But, please use this
279 Implementation-specific *private* methods will use ``_single_underscore_prefix``.
299 sparingly!
280 Names with a leading double underscore will *only* be used in special cases, as they
300
281 makes subclassing difficult (such names are not easily seen by child classes).
301 Implementation-specific *private* methods will use
282
302 ``_single_underscore_prefix``. Names with a leading double underscore will
283 Occasionally some run-in lowercase names are used, but mostly for very short names or
303 *only* be used in special cases, as they makes subclassing difficult (such
284 where we are implementing methods very similar to existing ones in a base class (like
304 names are not easily seen by child classes).
285 ``runlines()`` where ``runsource()`` and ``runcode()`` had established precedent).
305
306 Occasionally some run-in lowercase names are used, but mostly for very short
307 names or where we are implementing methods very similar to existing ones in a
308 base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had
309 established precedent).
286
310
287 The old IPython codebase has a big mix of classes and modules prefixed with an
311 The old IPython codebase has a big mix of classes and modules prefixed with an
288 explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned upon, as
312 explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned
289 namespaces offer cleaner prefixing. The only case where this approach is justified is
313 upon, as namespaces offer cleaner prefixing. The only case where this approach
290 for classes which are expected to be imported into external namespaces and a very
314 is justified is for classes which are expected to be imported into external
291 generic name (like Shell) is too likely to clash with something else. We'll need to
315 namespaces and a very generic name (like Shell) is too likely to clash with
292 revisit this issue as we clean up and refactor the code, but in general we should
316 something else. We'll need to revisit this issue as we clean up and refactor
293 remove as many unnecessary ``IP``/``ip`` prefixes as possible. However, if a prefix
317 the code, but in general we should remove as many unnecessary ``IP``/``ip``
294 seems absolutely necessary the more specific ``IPY`` or ``ipy`` are preferred.
318 prefixes as possible. However, if a prefix seems absolutely necessary the more
319 specific ``IPY`` or ``ipy`` are preferred.
295
320
296 .. _devel_testing:
321 .. _devel_testing:
297
322
298 Testing system
323 Testing system
299 ==============
324 ==============
300
325
301 It is extremely important that all code contributed to IPython has tests. Tests should
326 It is extremely important that all code contributed to IPython has tests. Tests
302 be written as unittests, doctests or as entities that the `Nose`_ testing package will
327 should be written as unittests, doctests or as entities that the `Nose`_
303 find. Regardless of how the tests are written, we will use `Nose`_ for discovering and
328 testing package will find. Regardless of how the tests are written, we will use
304 running the tests. `Nose`_ will be required to run the IPython test suite, but will
329 `Nose`_ for discovering and running the tests. `Nose`_ will be required to run
305 not be required to simply use IPython.
330 the IPython test suite, but will not be required to simply use IPython.
306
331
307 .. _Nose: http://code.google.com/p/python-nose/
332 .. _Nose: http://code.google.com/p/python-nose/
308
333
309 Tests of `Twisted`__ using code should be written by subclassing the ``TestCase`` class
334 Tests of `Twisted`__ using code should be written by subclassing the
310 that comes with ``twisted.trial.unittest``. When this is done, `Nose`_ will be able to
335 ``TestCase`` class that comes with ``twisted.trial.unittest``. When this is
311 run the tests and the twisted reactor will be handled correctly.
336 done, `Nose`_ will be able to run the tests and the twisted reactor will be
337 handled correctly.
312
338
313 .. __: http://www.twistedmatrix.com
339 .. __: http://www.twistedmatrix.com
314
340
315 Each subpackage in IPython should have its own ``tests`` directory that contains all
341 Each subpackage in IPython should have its own ``tests`` directory that
316 of the tests for that subpackage. This allows each subpackage to be self-contained. If
342 contains all of the tests for that subpackage. This allows each subpackage to
317 a subpackage has any dependencies beyond the Python standard library, the tests for
343 be self-contained. If a subpackage has any dependencies beyond the Python
318 that subpackage should be skipped if the dependencies are not found. This is very
344 standard library, the tests for that subpackage should be skipped if the
319 important so users don't get tests failing simply because they don't have dependencies.
345 dependencies are not found. This is very important so users don't get tests
346 failing simply because they don't have dependencies.
320
347
321 We also need to look into use Noses ability to tag tests to allow a more modular
348 We also need to look into use Noses ability to tag tests to allow a more
322 approach of running tests.
349 modular approach of running tests.
323
350
324 .. _devel_config:
351 .. _devel_config:
325
352
@@ -327,45 +354,54 b' Configuration system'
327 ====================
354 ====================
328
355
329 IPython uses `.ini`_ files for configuration purposes. This represents a huge
356 IPython uses `.ini`_ files for configuration purposes. This represents a huge
330 improvement over the configuration system used in IPython. IPython works with these
357 improvement over the configuration system used in IPython. IPython works with
331 files using the `ConfigObj`_ package, which IPython includes as
358 these files using the `ConfigObj`_ package, which IPython includes as
332 ``ipython1/external/configobj.py``.
359 ``ipython1/external/configobj.py``.
333
360
334 Currently, we are using raw `ConfigObj`_ objects themselves. Each subpackage of IPython
361 Currently, we are using raw `ConfigObj`_ objects themselves. Each subpackage of
335 should contain a ``config`` subdirectory that contains all of the configuration
362 IPython should contain a ``config`` subdirectory that contains all of the
336 information for the subpackage. To see how configuration information is defined (along
363 configuration information for the subpackage. To see how configuration
337 with defaults) see at the examples in ``ipython1/kernel/config`` and
364 information is defined (along with defaults) see at the examples in
338 ``ipython1/core/config``. Likewise, to see how the configuration information is used,
365 ``ipython1/kernel/config`` and ``ipython1/core/config``. Likewise, to see how
339 see examples in ``ipython1/kernel/scripts/ipengine.py``.
366 the configuration information is used, see examples in
340
367 ``ipython1/kernel/scripts/ipengine.py``.
341 Eventually, we will add a new layer on top of the raw `ConfigObj`_ objects. We are
368
342 calling this new layer, ``tconfig``, as it will use a `Traits`_-like validation model.
369 Eventually, we will add a new layer on top of the raw `ConfigObj`_ objects. We
343 We won't actually use `Traits`_, but will implement something similar in pure Python.
370 are calling this new layer, ``tconfig``, as it will use a `Traits`_-like
344 But, even in this new system, we will still use `ConfigObj`_ and `.ini`_ files
371 validation model. We won't actually use `Traits`_, but will implement
345 underneath the hood. Talk to Fernando if you are interested in working on this part of
372 something similar in pure Python. But, even in this new system, we will still
346 IPython. The current prototype of ``tconfig`` is located in the IPython sandbox.
373 use `ConfigObj`_ and `.ini`_ files underneath the hood. Talk to Fernando if you
374 are interested in working on this part of IPython. The current prototype of
375 ``tconfig`` is located in the IPython sandbox.
347
376
348 .. _.ini: http://docs.python.org/lib/module-ConfigParser.html
377 .. _.ini: http://docs.python.org/lib/module-ConfigParser.html
349 .. _ConfigObj: http://www.voidspace.org.uk/python/configobj.html
378 .. _ConfigObj: http://www.voidspace.org.uk/python/configobj.html
350 .. _Traits: http://code.enthought.com/traits/
379 .. _Traits: http://code.enthought.com/traits/
351
380
381
352 Installation and testing scenarios
382 Installation and testing scenarios
353 ==================================
383 ==================================
354
384
355 This section outlines the various scenarios that we need to test before we release an IPython version. These scenarios represent different ways of installing IPython and its dependencies.
385 This section outlines the various scenarios that we need to test before we
386 release an IPython version. These scenarios represent different ways of
387 installing IPython and its dependencies.
356
388
357 Installation scenarios under Linux and OS X
389 Installation scenarios under Linux and OS X
358 -------------------------------------------
390 -------------------------------------------
359
391
360 1. Install from tarball using `python setup.py install`.
392 1. Install from tarball using ``python setup.py install``.
361 a. With only readline+nose dependencies installed.
393 a. With only readline+nose dependencies installed.
362 b. With all dependencies installed (readline, zope.interface,
394 b. With all dependencies installed (readline, zope.interface, Twisted,
363 Twisted, foolscap, Sphinx, nose, pyOpenSSL).
395 foolscap, Sphinx, nose, pyOpenSSL).
396
364 2. Install using easy_install.
397 2. Install using easy_install.
398
365 a. With only readline+nose dependencies installed.
399 a. With only readline+nose dependencies installed.
366 i. Default dependencies: `easy_install ipython-0.9.beta3-py2.5.egg`
400 i. Default dependencies: ``easy_install ipython-0.9.beta3-py2.5.egg``
367 ii. Optional dependency sets: `easy_install -f ipython-0.9.beta3-py2.5.egg IPython[kernel,doc,test,security]`
401 ii. Optional dependency sets: ``easy_install -f ipython-0.9.beta3-py2.5.egg IPython[kernel,doc,test,security]``
402
368 b. With all dependencies already installed.
403 b. With all dependencies already installed.
404
369
405
370 Installation scenarios under Win32
406 Installation scenarios under Win32
371 ----------------------------------
407 ----------------------------------
@@ -381,6 +417,7 b' Tests to run for these scenarios'
381 2. Start a controller and engines and try a few things by hand.
417 2. Start a controller and engines and try a few things by hand.
382 a. Using ipcluster.
418 a. Using ipcluster.
383 b. Using ipcontroller/ipengine by hand.
419 b. Using ipcontroller/ipengine by hand.
420
384 3. Run a few of the parallel examples.
421 3. Run a few of the parallel examples.
385 4. Try the kernel with and without security with and without PyOpenSSL
422 4. Try the kernel with and without security with and without PyOpenSSL
386 installed.
423 installed.
@@ -388,10 +425,22 b' Tests to run for these scenarios'
388 6. Make sure that furl files are being put in proper locations.
425 6. Make sure that furl files are being put in proper locations.
389
426
390
427
428 Release checklist
429 =================
391
430
431 Most of the release process is automated by the :file:`release` script in the
432 :file:`tools` directory. This is just a handy reminder for the release manager.
392
433
434 #. Run the release script, which makes the tar.gz, eggs and Win32 .exe
435 installer. It posts them to the site and registers the release with PyPI.
393
436
437 #. Updating the website with announcements and links to the updated changes.txt
438 in html form. Remember to put a short note both on the news page of the site
439 and on launcphad.
394
440
441 #. Drafting a short release announcement with i) highlights and ii) a link to
442 the html changes.txt.
395
443
444 #. Make sure that the released version of the docs is live on the site.
396
445
397
446 #. Celebrate!
@@ -7,3 +7,4 b' Development'
7
7
8 development.txt
8 development.txt
9 roadmap.txt
9 roadmap.txt
10 notification_blueprint.txt
@@ -1,4 +1,4 b''
1 .. Notification:
1 .. _notification:
2
2
3 ==========================================
3 ==========================================
4 IPython.kernel.core.notification blueprint
4 IPython.kernel.core.notification blueprint
@@ -11,37 +11,39 b' The :mod:`IPython.kernel.core.notification` module will provide a simple impleme'
11 Functional Requirements
11 Functional Requirements
12 =======================
12 =======================
13 The notification center must:
13 The notification center must:
14 * Provide synchronous notification of events to all registered observers.
14 * Provide synchronous notification of events to all registered observers.
15 * Provide typed or labeled notification types
15 * Provide typed or labeled notification types
16 * Allow observers to register callbacks for individual or all notification types
16 * Allow observers to register callbacks for individual or all notification types
17 * Allow observers to register callbacks for events from individual or all notifying objects
17 * Allow observers to register callbacks for events from individual or all notifying objects
18 * Notification to the observer consists of the notification type, notifying object and user-supplied extra information [implementation: as keyword parameters to the registered callback]
18 * Notification to the observer consists of the notification type, notifying object and user-supplied extra information [implementation: as keyword parameters to the registered callback]
19 * Perform as O(1) in the case of no registered observers.
19 * Perform as O(1) in the case of no registered observers.
20 * Permit out-of-process or cross-network extension.
20 * Permit out-of-process or cross-network extension.
21
21
22 What's not included
22 What's not included
23 ==============================================================
23 ==============================================================
24 As written, the :mod:`IPython.kernel.core.notificaiton` module does not:
24 As written, the :mod:`IPython.kernel.core.notificaiton` module does not:
25 * Provide out-of-process or network notifications [these should be handled by a separate, Twisted aware module in :mod:`IPython.kernel`].
25 * Provide out-of-process or network notifications [these should be handled by a separate, Twisted aware module in :mod:`IPython.kernel`].
26 * Provide zope.interface-style interfaces for the notification system [these should also be provided by the :mod:`IPython.kernel` module]
26 * Provide zope.interface-style interfaces for the notification system [these should also be provided by the :mod:`IPython.kernel` module]
27
27
28 Use Cases
28 Use Cases
29 =========
29 =========
30 The following use cases describe the main intended uses of the notificaiton module and illustrate the main success scenario for each use case:
30 The following use cases describe the main intended uses of the notificaiton module and illustrate the main success scenario for each use case:
31
31
32 1. Dwight Schroot is writing a frontend for the IPython project. His frontend is stuck in the stone age and must communicate synchronously with an IPython.kernel.core.Interpreter instance. Because code is executed in blocks by the Interpreter, Dwight's UI freezes every time he executes a long block of code. To keep track of the progress of his long running block, Dwight adds the following code to his frontend's set-up code::
32 1. Dwight Schroot is writing a frontend for the IPython project. His frontend is stuck in the stone age and must communicate synchronously with an IPython.kernel.core.Interpreter instance. Because code is executed in blocks by the Interpreter, Dwight's UI freezes every time he executes a long block of code. To keep track of the progress of his long running block, Dwight adds the following code to his frontend's set-up code::
33 from IPython.kernel.core.notification import NotificationCenter
33
34 center = NotificationCenter.sharedNotificationCenter
34 from IPython.kernel.core.notification import NotificationCenter
35 center.registerObserver(self, type=IPython.kernel.core.Interpreter.STDOUT_NOTIFICATION_TYPE, notifying_object=self.interpreter, callback=self.stdout_notification)
35 center = NotificationCenter.sharedNotificationCenter
36
36 center.registerObserver(self, type=IPython.kernel.core.Interpreter.STDOUT_NOTIFICATION_TYPE, notifying_object=self.interpreter, callback=self.stdout_notification)
37 and elsewhere in his front end::
37
38 def stdout_notification(self, type, notifying_object, out_string=None):
38 and elsewhere in his front end::
39 self.writeStdOut(out_string)
39
40
40 def stdout_notification(self, type, notifying_object, out_string=None):
41 If everything works, the Interpreter will (according to its published API) fire a notification via the :data:`IPython.kernel.core.notification.sharedCenter` of type :const:`STD_OUT_NOTIFICATION_TYPE` before writing anything to stdout [it's up to the Intereter implementation to figure out when to do this]. The notificaiton center will then call the registered callbacks for that event type (in this case, Dwight's frontend's stdout_notification method). Again, according to its API, the Interpreter provides an additional keyword argument when firing the notificaiton of out_string, a copy of the string it will write to stdout.
41 self.writeStdOut(out_string)
42
42
43 Like magic, Dwight's frontend is able to provide output, even during long-running calculations. Now if Jim could just convince Dwight to use Twisted...
43 If everything works, the Interpreter will (according to its published API) fire a notification via the :data:`IPython.kernel.core.notification.sharedCenter` of type :const:`STD_OUT_NOTIFICATION_TYPE` before writing anything to stdout [it's up to the Intereter implementation to figure out when to do this]. The notificaiton center will then call the registered callbacks for that event type (in this case, Dwight's frontend's stdout_notification method). Again, according to its API, the Interpreter provides an additional keyword argument when firing the notificaiton of out_string, a copy of the string it will write to stdout.
44
44
45 2. Boss Hog is writing a frontend for the IPython project. Because Boss Hog is stuck in the stone age, his frontend will be written in a new Fortran-like dialect of python and will run only from the command line. Because he doesn't need any fancy notification system and is used to worrying about every cycle on his rat-wheel powered mini, Boss Hog is adamant that the new notification system not produce any performance penalty. As they say in Hazard county, there's no such thing as a free lunch. If he wanted zero overhead, he should have kept using IPython 0.8. Instead, those tricky Duke boys slide in a suped-up bridge-out jumpin' awkwardly confederate-lovin' notification module that imparts only a constant (and small) performance penalty when the Interpreter (or any other object) fires an event for which there are no registered observers. Of course, the same notificaiton-enabled Interpreter can then be used in frontends that require notifications, thus saving the IPython project from a nasty civil war.
45 Like magic, Dwight's frontend is able to provide output, even during long-running calculations. Now if Jim could just convince Dwight to use Twisted...
46
46
47 3. Barry is wrting a frontend for the IPython project. Because Barry's front end is the *new hotness*, it uses an asynchronous event model to communicate with a Twisted :mod:`~IPython.kernel.engineservice` that communicates with the IPython :class:`~IPython.kernel.core.interpreter.Interpreter`. Using the :mod:`IPython.kernel.notification` module, an asynchronous wrapper on the :mod:`IPython.kernel.core.notification` module, Barry's frontend can register for notifications from the interpreter that are delivered asynchronously. Even if Barry's frontend is running on a separate process or even host from the Interpreter, the notifications are delivered, as if by dark and twisted magic. Just like Dwight's frontend, Barry's frontend can now recieve notifications of e.g. writing to stdout/stderr, opening/closing an external file, an exception in the executing code, etc. No newline at end of file
47 2. Boss Hog is writing a frontend for the IPython project. Because Boss Hog is stuck in the stone age, his frontend will be written in a new Fortran-like dialect of python and will run only from the command line. Because he doesn't need any fancy notification system and is used to worrying about every cycle on his rat-wheel powered mini, Boss Hog is adamant that the new notification system not produce any performance penalty. As they say in Hazard county, there's no such thing as a free lunch. If he wanted zero overhead, he should have kept using IPython 0.8. Instead, those tricky Duke boys slide in a suped-up bridge-out jumpin' awkwardly confederate-lovin' notification module that imparts only a constant (and small) performance penalty when the Interpreter (or any other object) fires an event for which there are no registered observers. Of course, the same notificaiton-enabled Interpreter can then be used in frontends that require notifications, thus saving the IPython project from a nasty civil war.
48
49 3. Barry is wrting a frontend for the IPython project. Because Barry's front end is the *new hotness*, it uses an asynchronous event model to communicate with a Twisted :mod:`~IPython.kernel.engineservice` that communicates with the IPython :class:`~IPython.kernel.core.interpreter.Interpreter`. Using the :mod:`IPython.kernel.notification` module, an asynchronous wrapper on the :mod:`IPython.kernel.core.notification` module, Barry's frontend can register for notifications from the interpreter that are delivered asynchronously. Even if Barry's frontend is running on a separate process or even host from the Interpreter, the notifications are delivered, as if by dark and twisted magic. Just like Dwight's frontend, Barry's frontend can now recieve notifications of e.g. writing to stdout/stderr, opening/closing an external file, an exception in the executing code, etc. No newline at end of file
@@ -32,16 +32,21 b' IPython is implemented using a distributed set of processes that communicate usi'
32
32
33 We need to build a system that makes it trivial for users to start and manage IPython processes. This system should have the following properties:
33 We need to build a system that makes it trivial for users to start and manage IPython processes. This system should have the following properties:
34
34
35 * It should possible to do everything through an extremely simple API that users
35 * It should possible to do everything through an extremely simple API that users
36 can call from their own Python script. No shell commands should be needed.
36 can call from their own Python script. No shell commands should be needed.
37 * This simple API should be configured using standard .ini files.
37
38 * The system should make it possible to start processes using a number of different
38 * This simple API should be configured using standard .ini files.
39 approaches: SSH, PBS/Torque, Xgrid, Windows Server, mpirun, etc.
39
40 * The controller and engine processes should each have a daemon for monitoring,
40 * The system should make it possible to start processes using a number of different
41 signaling and clean up.
41 approaches: SSH, PBS/Torque, Xgrid, Windows Server, mpirun, etc.
42 * The system should be secure.
42
43 * The system should work under all the major operating systems, including
43 * The controller and engine processes should each have a daemon for monitoring,
44 Windows.
44 signaling and clean up.
45
46 * The system should be secure.
47
48 * The system should work under all the major operating systems, including
49 Windows.
45
50
46 Initial work has begun on the daemon infrastructure, and some of the needed logic is contained in the ipcluster script.
51 Initial work has begun on the daemon infrastructure, and some of the needed logic is contained in the ipcluster script.
47
52
@@ -57,12 +62,15 b' Security'
57
62
58 Currently, IPython has no built in security or security model. Because we would like IPython to be usable on public computer systems and over wide area networks, we need to come up with a robust solution for security. Here are some of the specific things that need to be included:
63 Currently, IPython has no built in security or security model. Because we would like IPython to be usable on public computer systems and over wide area networks, we need to come up with a robust solution for security. Here are some of the specific things that need to be included:
59
64
60 * User authentication between all processes (engines, controller and clients).
65 * User authentication between all processes (engines, controller and clients).
61 * Optional TSL/SSL based encryption of all communication channels.
66
62 * A good way of picking network ports so multiple users on the same system can
67 * Optional TSL/SSL based encryption of all communication channels.
63 run their own controller and engines without interfering with those of others.
68
64 * A clear model for security that enables users to evaluate the security risks
69 * A good way of picking network ports so multiple users on the same system can
65 associated with using IPython in various manners.
70 run their own controller and engines without interfering with those of others.
71
72 * A clear model for security that enables users to evaluate the security risks
73 associated with using IPython in various manners.
66
74
67 For the implementation of this, we plan on using Twisted's support for SSL and authentication. One things that we really should look at is the `Foolscap`_ network protocol, which provides many of these things out of the box.
75 For the implementation of this, we plan on using Twisted's support for SSL and authentication. One things that we really should look at is the `Foolscap`_ network protocol, which provides many of these things out of the box.
68
76
@@ -70,6 +78,9 b" For the implementation of this, we plan on using Twisted's support for SSL and a"
70
78
71 The security work needs to be done in conjunction with other network protocol stuff.
79 The security work needs to be done in conjunction with other network protocol stuff.
72
80
81 As of the 0.9 release of IPython, we are using Foolscap and we have implemented
82 a full security model.
83
73 Latent performance issues
84 Latent performance issues
74 -------------------------
85 -------------------------
75
86
@@ -82,7 +93,7 b' Currently, we have a number of performance issues that are waiting to bite users'
82 * Currently, the client to controller connections are done through XML-RPC using
93 * Currently, the client to controller connections are done through XML-RPC using
83 HTTP 1.0. This is very inefficient as XML-RPC is a very verbose protocol and
94 HTTP 1.0. This is very inefficient as XML-RPC is a very verbose protocol and
84 each request must be handled with a new connection. We need to move these network
95 each request must be handled with a new connection. We need to move these network
85 connections over to PB or Foolscap.
96 connections over to PB or Foolscap. Done!
86 * We currently don't have a good way of handling large objects in the controller.
97 * We currently don't have a good way of handling large objects in the controller.
87 The biggest problem is that because we don't have any way of streaming objects,
98 The biggest problem is that because we don't have any way of streaming objects,
88 we get lots of temporary copies in the low-level buffers. We need to implement
99 we get lots of temporary copies in the low-level buffers. We need to implement
@@ -16,10 +16,13 b' Will IPython speed my Python code up?'
16 Yes and no. When converting a serial code to run in parallel, there often many
16 Yes and no. When converting a serial code to run in parallel, there often many
17 difficulty questions that need to be answered, such as:
17 difficulty questions that need to be answered, such as:
18
18
19 * How should data be decomposed onto the set of processors?
19 * How should data be decomposed onto the set of processors?
20 * What are the data movement patterns?
20
21 * Can the algorithm be structured to minimize data movement?
21 * What are the data movement patterns?
22 * Is dynamic load balancing important?
22
23 * Can the algorithm be structured to minimize data movement?
24
25 * Is dynamic load balancing important?
23
26
24 We can't answer such questions for you. This is the hard (but fun) work of parallel
27 We can't answer such questions for you. This is the hard (but fun) work of parallel
25 computing. But, once you understand these things IPython will make it easier for you to
28 computing. But, once you understand these things IPython will make it easier for you to
@@ -28,9 +31,7 b' resulting parallel code interactively.'
28
31
29 With that said, if your problem is trivial to parallelize, IPython has a number of
32 With that said, if your problem is trivial to parallelize, IPython has a number of
30 different interfaces that will enable you to parallelize things is almost no time at
33 different interfaces that will enable you to parallelize things is almost no time at
31 all. A good place to start is the ``map`` method of our `multiengine interface`_.
34 all. A good place to start is the ``map`` method of our :class:`MultiEngineClient`.
32
33 .. _multiengine interface: ./parallel_multiengine
34
35
35 What is the best way to use MPI from Python?
36 What is the best way to use MPI from Python?
36 --------------------------------------------
37 --------------------------------------------
@@ -40,26 +41,33 b' What about all the other parallel computing packages in Python?'
40
41
41 Some of the unique characteristic of IPython are:
42 Some of the unique characteristic of IPython are:
42
43
43 * IPython is the only architecture that abstracts out the notion of a
44 * IPython is the only architecture that abstracts out the notion of a
44 parallel computation in such a way that new models of parallel computing
45 parallel computation in such a way that new models of parallel computing
45 can be explored quickly and easily. If you don't like the models we
46 can be explored quickly and easily. If you don't like the models we
46 provide, you can simply create your own using the capabilities we provide.
47 provide, you can simply create your own using the capabilities we provide.
47 * IPython is asynchronous from the ground up (we use `Twisted`_).
48
48 * IPython's architecture is designed to avoid subtle problems
49 * IPython is asynchronous from the ground up (we use `Twisted`_).
49 that emerge because of Python's global interpreter lock (GIL).
50
50 * While IPython'1 architecture is designed to support a wide range
51 * IPython's architecture is designed to avoid subtle problems
51 of novel parallel computing models, it is fully interoperable with
52 that emerge because of Python's global interpreter lock (GIL).
52 traditional MPI applications.
53
53 * IPython has been used and tested extensively on modern supercomputers.
54 * While IPython's architecture is designed to support a wide range
54 * IPython's networking layers are completely modular. Thus, is
55 of novel parallel computing models, it is fully interoperable with
55 straightforward to replace our existing network protocols with
56 traditional MPI applications.
56 high performance alternatives (ones based upon Myranet/Infiniband).
57
57 * IPython is designed from the ground up to support collaborative
58 * IPython has been used and tested extensively on modern supercomputers.
58 parallel computing. This enables multiple users to actively develop
59
59 and run the *same* parallel computation.
60 * IPython's networking layers are completely modular. Thus, is
60 * Interactivity is a central goal for us. While IPython does not have
61 straightforward to replace our existing network protocols with
61 to be used interactivly, is can be.
62 high performance alternatives (ones based upon Myranet/Infiniband).
62
63
64 * IPython is designed from the ground up to support collaborative
65 parallel computing. This enables multiple users to actively develop
66 and run the *same* parallel computation.
67
68 * Interactivity is a central goal for us. While IPython does not have
69 to be used interactivly, it can be.
70
63 .. _Twisted: http://www.twistedmatrix.com
71 .. _Twisted: http://www.twistedmatrix.com
64
72
65 Why The IPython controller a bottleneck in my parallel calculation?
73 Why The IPython controller a bottleneck in my parallel calculation?
@@ -71,13 +79,17 b' too much data is being pushed and pulled to and from the engines. If your algori'
71 is structured in this way, you really should think about alternative ways of
79 is structured in this way, you really should think about alternative ways of
72 handling the data movement. Here are some ideas:
80 handling the data movement. Here are some ideas:
73
81
74 1. Have the engines write data to files on the locals disks of the engines.
82 1. Have the engines write data to files on the locals disks of the engines.
75 2. Have the engines write data to files on a file system that is shared by
83
76 the engines.
84 2. Have the engines write data to files on a file system that is shared by
77 3. Have the engines write data to a database that is shared by the engines.
85 the engines.
78 4. Simply keep data in the persistent memory of the engines and move the
86
79 computation to the data (rather than the data to the computation).
87 3. Have the engines write data to a database that is shared by the engines.
80 5. See if you can pass data directly between engines using MPI.
88
89 4. Simply keep data in the persistent memory of the engines and move the
90 computation to the data (rather than the data to the computation).
91
92 5. See if you can pass data directly between engines using MPI.
81
93
82 Isn't Python slow to be used for high-performance parallel computing?
94 Isn't Python slow to be used for high-performance parallel computing?
83 ---------------------------------------------------------------------
95 ---------------------------------------------------------------------
@@ -7,50 +7,32 b' History'
7 Origins
7 Origins
8 =======
8 =======
9
9
10 The current IPython system grew out of the following three projects:
10 IPython was starting in 2001 by Fernando Perez. IPython as we know it
11
11 today grew out of the following three projects:
12 * [ipython] by Fernando Pérez. I was working on adding
12
13 Mathematica-type prompts and a flexible configuration system
13 * ipython by Fernando Pérez. I was working on adding
14 (something better than $PYTHONSTARTUP) to the standard Python
14 Mathematica-type prompts and a flexible configuration system
15 interactive interpreter.
15 (something better than $PYTHONSTARTUP) to the standard Python
16 * [IPP] by Janko Hauser. Very well organized, great usability. Had
16 interactive interpreter.
17 an old help system. IPP was used as the 'container' code into
17 * IPP by Janko Hauser. Very well organized, great usability. Had
18 which I added the functionality from ipython and LazyPython.
18 an old help system. IPP was used as the 'container' code into
19 * [LazyPython] by Nathan Gray. Simple but very powerful. The quick
19 which I added the functionality from ipython and LazyPython.
20 syntax (auto parens, auto quotes) and verbose/colored tracebacks
20 * LazyPython by Nathan Gray. Simple but very powerful. The quick
21 were all taken from here.
21 syntax (auto parens, auto quotes) and verbose/colored tracebacks
22
22 were all taken from here.
23 When I found out about IPP and LazyPython I tried to join all three
23
24 into a unified system. I thought this could provide a very nice
24 Here is how Fernando describes it:
25 working environment, both for regular programming and scientific
25
26 computing: shell-like features, IDL/Matlab numerics, Mathematica-type
26 When I found out about IPP and LazyPython I tried to join all three
27 prompt history and great object introspection and help facilities. I
27 into a unified system. I thought this could provide a very nice
28 think it worked reasonably well, though it was a lot more work than I
28 working environment, both for regular programming and scientific
29 had initially planned.
29 computing: shell-like features, IDL/Matlab numerics, Mathematica-type
30
30 prompt history and great object introspection and help facilities. I
31
31 think it worked reasonably well, though it was a lot more work than I
32 Current status
32 had initially planned.
33 ==============
33
34
34 Today and how we got here
35 The above listed features work, and quite well for the most part. But
35 =========================
36 until a major internal restructuring is done (see below), only bug
36
37 fixing will be done, no other features will be added (unless very minor
37 This needs to be filled in.
38 and well localized in the cleaner parts of the code).
38
39
40 IPython consists of some 18000 lines of pure python code, of which
41 roughly two thirds is reasonably clean. The rest is, messy code which
42 needs a massive restructuring before any further major work is done.
43 Even the messy code is fairly well documented though, and most of the
44 problems in the (non-existent) class design are well pointed to by a
45 PyChecker run. So the rewriting work isn't that bad, it will just be
46 time-consuming.
47
48
49 Future
50 ------
51
52 See the separate new_design document for details. Ultimately, I would
53 like to see IPython become part of the standard Python distribution as a
54 'big brother with batteries' to the standard Python interactive
55 interpreter. But that will never happen with the current state of the
56 code, so all contributions are welcome. No newline at end of file
@@ -2,11 +2,15 b''
2 IPython Documentation
2 IPython Documentation
3 =====================
3 =====================
4
4
5 Contents
5 .. htmlonly::
6 ========
6
7 :Release: |release|
8 :Date: |today|
9
10 Contents:
7
11
8 .. toctree::
12 .. toctree::
9 :maxdepth: 1
13 :maxdepth: 2
10
14
11 overview.txt
15 overview.txt
12 install/index.txt
16 install/index.txt
@@ -20,9 +24,9 b' Contents'
20 license_and_copyright.txt
24 license_and_copyright.txt
21 credits.txt
25 credits.txt
22
26
23 Indices and tables
24 ==================
25
27
26 * :ref:`genindex`
28 .. htmlonly::
27 * :ref:`modindex`
29
28 * :ref:`search` No newline at end of file
30 * :ref:`genindex`
31 * :ref:`modindex`
32 * :ref:`search`
@@ -7,5 +7,4 b' Installation'
7 .. toctree::
7 .. toctree::
8 :maxdepth: 2
8 :maxdepth: 2
9
9
10 basic.txt
10 install.txt
11 advanced.txt
@@ -8,7 +8,7 b' IPython reference'
8
8
9 .. contents::
9 .. contents::
10
10
11 .. _Command line options:
11 .. _command_line_options:
12
12
13 Command-line usage
13 Command-line usage
14 ==================
14 ==================
@@ -288,12 +288,13 b' All options with a [no] prepended can be specified in negated form'
288 recursive inclusions.
288 recursive inclusions.
289
289
290 -prompt_in1, pi1 <string>
290 -prompt_in1, pi1 <string>
291 Specify the string used for input prompts. Note that if you
291
292 are using numbered prompts, the number is represented with a
292 Specify the string used for input prompts. Note that if you are using
293 '\#' in the string. Don't forget to quote strings with spaces
293 numbered prompts, the number is represented with a '\#' in the
294 embedded in them. Default: 'In [\#]:'. Sec. Prompts_
294 string. Don't forget to quote strings with spaces embedded in
295 discusses in detail all the available escapes to customize
295 them. Default: 'In [\#]:'. The :ref:`prompts section <prompts>`
296 your prompts.
296 discusses in detail all the available escapes to customize your
297 prompts.
297
298
298 -prompt_in2, pi2 <string>
299 -prompt_in2, pi2 <string>
299 Similar to the previous option, but used for the continuation
300 Similar to the previous option, but used for the continuation
@@ -2077,13 +2078,14 b' customizations.'
2077 Access to the standard Python help
2078 Access to the standard Python help
2078 ----------------------------------
2079 ----------------------------------
2079
2080
2080 As of Python 2.1, a help system is available with access to object
2081 As of Python 2.1, a help system is available with access to object docstrings
2081 docstrings and the Python manuals. Simply type 'help' (no quotes) to
2082 and the Python manuals. Simply type 'help' (no quotes) to access it. You can
2082 access it. You can also type help(object) to obtain information about a
2083 also type help(object) to obtain information about a given object, and
2083 given object, and help('keyword') for information on a keyword. As noted
2084 help('keyword') for information on a keyword. As noted :ref:`here
2084 in sec. `accessing help`_, you need to properly configure
2085 <accessing_help>`, you need to properly configure your environment variable
2085 your environment variable PYTHONDOCS for this feature to work correctly.
2086 PYTHONDOCS for this feature to work correctly.
2086
2087
2088 .. _dynamic_object_info:
2087
2089
2088 Dynamic object information
2090 Dynamic object information
2089 --------------------------
2091 --------------------------
@@ -2126,7 +2128,7 b' are not really defined as separate identifiers. Try for example typing'
2126 {}.get? or after doing import os, type os.path.abspath??.
2128 {}.get? or after doing import os, type os.path.abspath??.
2127
2129
2128
2130
2129 .. _Readline:
2131 .. _readline:
2130
2132
2131 Readline-based features
2133 Readline-based features
2132 -----------------------
2134 -----------------------
@@ -2240,10 +2242,9 b' explanation in your ipythonrc file.'
2240 Session logging and restoring
2242 Session logging and restoring
2241 -----------------------------
2243 -----------------------------
2242
2244
2243 You can log all input from a session either by starting IPython with
2245 You can log all input from a session either by starting IPython with the
2244 the command line switches -log or -logfile (see sec. `command line
2246 command line switches -log or -logfile (see :ref:`here <command_line_options>`)
2245 options`_) or by activating the logging at any moment with the magic
2247 or by activating the logging at any moment with the magic function %logstart.
2246 function %logstart.
2247
2248
2248 Log files can later be reloaded with the -logplay option and IPython
2249 Log files can later be reloaded with the -logplay option and IPython
2249 will attempt to 'replay' the log by executing all the lines in it, thus
2250 will attempt to 'replay' the log by executing all the lines in it, thus
@@ -2279,6 +2280,8 b' resume logging to a file which had previously been started with'
2279 %logstart. They will fail (with an explanation) if you try to use them
2280 %logstart. They will fail (with an explanation) if you try to use them
2280 before logging has been started.
2281 before logging has been started.
2281
2282
2283 .. _system_shell_access:
2284
2282 System shell access
2285 System shell access
2283 -------------------
2286 -------------------
2284
2287
@@ -2389,7 +2392,7 b" These features are basically a terminal version of Ka-Ping Yee's cgitb"
2389 module, now part of the standard Python library.
2392 module, now part of the standard Python library.
2390
2393
2391
2394
2392 .. _Input caching:
2395 .. _input_caching:
2393
2396
2394 Input caching system
2397 Input caching system
2395 --------------------
2398 --------------------
@@ -2429,7 +2432,7 b' sec. 6.2 <#sec:magic> for more details on the macro system.'
2429 A history function %hist allows you to see any part of your input
2432 A history function %hist allows you to see any part of your input
2430 history by printing a range of the _i variables.
2433 history by printing a range of the _i variables.
2431
2434
2432 .. _Output caching:
2435 .. _output_caching:
2433
2436
2434 Output caching system
2437 Output caching system
2435 ---------------------
2438 ---------------------
@@ -3034,7 +3037,7 b' which is being shared by the interactive IPython loop and your GUI'
3034 thread, you should really handle it with thread locking and
3037 thread, you should really handle it with thread locking and
3035 syncrhonization properties. The Python documentation discusses these.
3038 syncrhonization properties. The Python documentation discusses these.
3036
3039
3037 .. _Interactive demos:
3040 .. _interactive_demos:
3038
3041
3039 Interactive demos with IPython
3042 Interactive demos with IPython
3040 ==============================
3043 ==============================
@@ -3143,21 +3146,17 b' toolkits, including Tk, GTK and WXPython. It also provides a number of'
3143 commands useful for scientific computing, all with a syntax compatible
3146 commands useful for scientific computing, all with a syntax compatible
3144 with that of the popular Matlab program.
3147 with that of the popular Matlab program.
3145
3148
3146 IPython accepts the special option -pylab (Sec. `Command line
3149 IPython accepts the special option -pylab (see :ref:`here
3147 options`_). This configures it to support matplotlib, honoring the
3150 <command_line_options>`). This configures it to support matplotlib, honoring
3148 settings in the .matplotlibrc file. IPython will detect the user's
3151 the settings in the .matplotlibrc file. IPython will detect the user's choice
3149 choice of matplotlib GUI backend, and automatically select the proper
3152 of matplotlib GUI backend, and automatically select the proper threading model
3150 threading model to prevent blocking. It also sets matplotlib in
3153 to prevent blocking. It also sets matplotlib in interactive mode and modifies
3151 interactive mode and modifies %run slightly, so that any
3154 %run slightly, so that any matplotlib-based script can be executed using %run
3152 matplotlib-based script can be executed using %run and the final
3155 and the final show() command does not block the interactive shell.
3153 show() command does not block the interactive shell.
3156
3154
3157 The -pylab option must be given first in order for IPython to configure its
3155 The -pylab option must be given first in order for IPython to
3158 threading mode. However, you can still issue other options afterwards. This
3156 configure its threading mode. However, you can still issue other
3159 allows you to have a matplotlib-based environment customized with additional
3157 options afterwards. This allows you to have a matplotlib-based
3160 modules using the standard IPython profile mechanism (see :ref:`here
3158 environment customized with additional modules using the standard
3161 <profiles>`): ``ipython -pylab -p myprofile`` will load the profile defined in
3159 IPython profile mechanism (Sec. Profiles_): ''ipython -pylab -p
3162 ipythonrc-myprofile after configuring matplotlib.
3160 myprofile'' will load the profile defined in ipythonrc-myprofile after
3161 configuring matplotlib.
3162
3163
@@ -24,11 +24,11 b' Tab completion'
24 --------------
24 --------------
25
25
26 TAB-completion, especially for attributes, is a convenient way to explore the
26 TAB-completion, especially for attributes, is a convenient way to explore the
27 structure of any object you're dealing with. Simply type object_name.<TAB>
27 structure of any object you're dealing with. Simply type object_name.<TAB> and
28 and a list of the object's attributes will be printed (see readline_ for
28 a list of the object's attributes will be printed (see :ref:`the readline
29 more). Tab completion also works on file and directory names, which combined
29 section <readline>` for more). Tab completion also works on file and directory
30 with IPython's alias system allows you to do from within IPython many of the
30 names, which combined with IPython's alias system allows you to do from within
31 things you normally would need the system shell for.
31 IPython many of the things you normally would need the system shell for.
32
32
33 Explore your objects
33 Explore your objects
34 --------------------
34 --------------------
@@ -39,18 +39,18 b' constructor details for classes. The magic commands %pdoc, %pdef, %psource'
39 and %pfile will respectively print the docstring, function definition line,
39 and %pfile will respectively print the docstring, function definition line,
40 full source code and the complete file for any object (when they can be
40 full source code and the complete file for any object (when they can be
41 found). If automagic is on (it is by default), you don't need to type the '%'
41 found). If automagic is on (it is by default), you don't need to type the '%'
42 explicitly. See sec. `dynamic object information`_ for more.
42 explicitly. See :ref:`this section <dynamic_object_info>` for more.
43
43
44 The `%run` magic command
44 The `%run` magic command
45 ------------------------
45 ------------------------
46
46
47 The %run magic command allows you to run any python script and load all of
47 The %run magic command allows you to run any python script and load all of its
48 its data directly into the interactive namespace. Since the file is re-read
48 data directly into the interactive namespace. Since the file is re-read from
49 from disk each time, changes you make to it are reflected immediately (in
49 disk each time, changes you make to it are reflected immediately (in contrast
50 contrast to the behavior of import). I rarely use import for code I am
50 to the behavior of import). I rarely use import for code I am testing, relying
51 testing, relying on %run instead. See magic_ section for more on this and
51 on %run instead. See :ref:`this section <magic>` for more on this and other
52 other magic commands, or type the name of any magic command and ? to get
52 magic commands, or type the name of any magic command and ? to get details on
53 details on it. See also sec. dreload_ for a recursive reload command. %run
53 it. See also :ref:`this section <dreload>` for a recursive reload command. %run
54 also has special flags for timing the execution of your scripts (-t) and for
54 also has special flags for timing the execution of your scripts (-t) and for
55 executing them under the control of either Python's pdb debugger (-d) or
55 executing them under the control of either Python's pdb debugger (-d) or
56 profiler (-p). With all of these, %run can be used as the main tool for
56 profiler (-p). With all of these, %run can be used as the main tool for
@@ -60,21 +60,21 b' choice.'
60 Debug a Python script
60 Debug a Python script
61 ---------------------
61 ---------------------
62
62
63 Use the Python debugger, pdb. The %pdb command allows you to toggle on and
63 Use the Python debugger, pdb. The %pdb command allows you to toggle on and off
64 off the automatic invocation of an IPython-enhanced pdb debugger (with
64 the automatic invocation of an IPython-enhanced pdb debugger (with coloring,
65 coloring, tab completion and more) at any uncaught exception. The advantage
65 tab completion and more) at any uncaught exception. The advantage of this is
66 of this is that pdb starts inside the function where the exception occurred,
66 that pdb starts inside the function where the exception occurred, with all data
67 with all data still available. You can print variables, see code, execute
67 still available. You can print variables, see code, execute statements and even
68 statements and even walk up and down the call stack to track down the true
68 walk up and down the call stack to track down the true source of the problem
69 source of the problem (which often is many layers in the stack above where
69 (which often is many layers in the stack above where the exception gets
70 the exception gets triggered). Running programs with %run and pdb active can
70 triggered). Running programs with %run and pdb active can be an efficient to
71 be an efficient to develop and debug code, in many cases eliminating the need
71 develop and debug code, in many cases eliminating the need for print statements
72 for print statements or external debugging tools. I often simply put a 1/0 in
72 or external debugging tools. I often simply put a 1/0 in a place where I want
73 a place where I want to take a look so that pdb gets called, quickly view
73 to take a look so that pdb gets called, quickly view whatever variables I need
74 whatever variables I need to or test various pieces of code and then remove
74 to or test various pieces of code and then remove the 1/0. Note also that '%run
75 the 1/0. Note also that '%run -d' activates pdb and automatically sets
75 -d' activates pdb and automatically sets initial breakpoints for you to step
76 initial breakpoints for you to step through your code, watch variables, etc.
76 through your code, watch variables, etc. The :ref:`output caching section
77 See Sec. `Output caching`_ for details.
77 <output_caching>` has more details.
78
78
79 Use the output cache
79 Use the output cache
80 --------------------
80 --------------------
@@ -84,7 +84,8 b' and variables named _1, _2, etc. alias them. For example, the result of input'
84 line 4 is available either as Out[4] or as _4. Additionally, three variables
84 line 4 is available either as Out[4] or as _4. Additionally, three variables
85 named _, __ and ___ are always kept updated with the for the last three
85 named _, __ and ___ are always kept updated with the for the last three
86 results. This allows you to recall any previous result and further use it for
86 results. This allows you to recall any previous result and further use it for
87 new calculations. See Sec. `Output caching`_ for more.
87 new calculations. See :ref:`the output caching section <output_caching>` for
88 more.
88
89
89 Suppress output
90 Suppress output
90 ---------------
91 ---------------
@@ -102,7 +103,7 b' A similar system exists for caching input. All input is stored in a global'
102 list called In , so you can re-execute lines 22 through 28 plus line 34 by
103 list called In , so you can re-execute lines 22 through 28 plus line 34 by
103 typing 'exec In[22:29]+In[34]' (using Python slicing notation). If you need
104 typing 'exec In[22:29]+In[34]' (using Python slicing notation). If you need
104 to execute the same set of lines often, you can assign them to a macro with
105 to execute the same set of lines often, you can assign them to a macro with
105 the %macro function. See sec. `Input caching`_ for more.
106 the %macro function. See :ref:`here <input_caching>` for more.
106
107
107 Use your input history
108 Use your input history
108 ----------------------
109 ----------------------
@@ -134,17 +135,18 b' into Python variables.'
134 Use Python variables when calling the shell
135 Use Python variables when calling the shell
135 -------------------------------------------
136 -------------------------------------------
136
137
137 Expand python variables when calling the shell (either via '!' and '!!' or
138 Expand python variables when calling the shell (either via '!' and '!!' or via
138 via aliases) by prepending a $ in front of them. You can also expand complete
139 aliases) by prepending a $ in front of them. You can also expand complete
139 python expressions. See `System shell access`_ for more.
140 python expressions. See :ref:`our shell section <system_shell_access>` for
141 more details.
140
142
141 Use profiles
143 Use profiles
142 ------------
144 ------------
143
145
144 Use profiles to maintain different configurations (modules to load, function
146 Use profiles to maintain different configurations (modules to load, function
145 definitions, option settings) for particular tasks. You can then have
147 definitions, option settings) for particular tasks. You can then have
146 customized versions of IPython for specific purposes. See sec. profiles_ for
148 customized versions of IPython for specific purposes. :ref:`This section
147 more.
149 <profiles>` has more details.
148
150
149
151
150 Embed IPython in your programs
152 Embed IPython in your programs
@@ -152,7 +154,7 b' Embed IPython in your programs'
152
154
153 A few lines of code are enough to load a complete IPython inside your own
155 A few lines of code are enough to load a complete IPython inside your own
154 programs, giving you the ability to work with your data interactively after
156 programs, giving you the ability to work with your data interactively after
155 automatic processing has been completed. See sec. embedding_ for more.
157 automatic processing has been completed. See :ref:`here <embedding>` for more.
156
158
157 Use the Python profiler
159 Use the Python profiler
158 -----------------------
160 -----------------------
@@ -166,8 +168,8 b' Use IPython to present interactive demos'
166 ----------------------------------------
168 ----------------------------------------
167
169
168 Use the IPython.demo.Demo class to load any Python script as an interactive
170 Use the IPython.demo.Demo class to load any Python script as an interactive
169 demo. With a minimal amount of simple markup, you can control the execution
171 demo. With a minimal amount of simple markup, you can control the execution of
170 of the script, stopping as needed. See sec. `interactive demos`_ for more.
172 the script, stopping as needed. See :ref:`here <interactive_demos>` for more.
171
173
172 Run doctests
174 Run doctests
173 ------------
175 ------------
@@ -1,56 +1,82 b''
1 .. _license:
1 .. _license:
2
2
3 =============================
3 =====================
4 License and Copyright
4 License and Copyright
5 =============================
5 =====================
6
6
7 This files needs to be updated to reflect what the new COPYING.txt files says about our license and copyright!
7 License
8 =======
8
9
9 IPython is released under the terms of the BSD license, whose general
10 IPython is licensed under the terms of the new or revised BSD license, as follows::
10 form can be found at: http://www.opensource.org/licenses/bsd-license.php. The full text of the
11 IPython license is reproduced below::
12
11
13 IPython is released under a BSD-type license.
12 Copyright (c) 2008, IPython Development Team
14
13
15 Copyright (c) 2001, 2002, 2003, 2004 Fernando Perez
14 All rights reserved.
16 <fperez@colorado.edu>.
17
15
18 Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and
16 Redistribution and use in source and binary forms, with or without modification,
19 Nathaniel Gray <n8gray@caltech.edu>.
17 are permitted provided that the following conditions are met:
20
18
21 All rights reserved.
19 Redistributions of source code must retain the above copyright notice, this list of
20 conditions and the following disclaimer.
21
22 Redistributions in binary form must reproduce the above copyright notice, this list
23 of conditions and the following disclaimer in the documentation and/or other
24 materials provided with the distribution.
25
26 Neither the name of the IPython Development Team nor the names of its contributors
27 may be used to endorse or promote products derived from this software without
28 specific prior written permission.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
31 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
40
41 About the IPython Development Team
42 ==================================
43
44 Fernando Perez began IPython in 2001 based on code from Janko Hauser <jhauser@zscout.de>
45 and Nathaniel Gray <n8gray@caltech.edu>. Fernando is still the project lead.
46
47 The IPython Development Team is the set of all contributors to the IPython project.
48 This includes all of the IPython subprojects. Here is a list of the currently active contributors:
49
50 * Matthieu Brucher
51 * Ondrej Certik
52 * Laurent Dufrechou
53 * Robert Kern
54 * Brian E. Granger
55 * Fernando Perez (project leader)
56 * Benjamin Ragan-Kelley
57 * Ville M. Vainio
58 * Gael Varoququx
59 * Stefan van der Walt
60 * Tech-X Corporation
61 * Barry Wark
62
63 If your name is missing, please add it.
64
65 Our Copyright Policy
66 ====================
67
68 IPython uses a shared copyright model. Each contributor maintains copyright over
69 their contributions to IPython. But, it is important to note that these
70 contributions are typically only changes to the repositories. Thus, the IPython
71 source code, in its entirety is not the copyright of any single person or
72 institution. Instead, it is the collective copyright of the entire IPython
73 Development Team. If individual contributors want to maintain a record of what
74 changes/contributions they have specific copyright on, they should indicate their
75 copyright in the commit message of the change, when they commit the change to
76 one of the IPython repositories.
22
77
23 Redistribution and use in source and binary forms, with or without
78 Miscellaneous
24 modification, are permitted provided that the following conditions
79 =============
25 are met:
26
27 a. Redistributions of source code must retain the above copyright
28 notice, this list of conditions and the following disclaimer.
29
30 b. Redistributions in binary form must reproduce the above copyright
31 notice, this list of conditions and the following disclaimer in the
32 documentation and/or other materials provided with the distribution.
33
34 c. Neither the name of the copyright holders nor the names of any
35 contributors to this software may be used to endorse or promote
36 products derived from this software without specific prior written
37 permission.
38
39 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
41 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
42 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
43 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
44 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
45 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
47 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
49 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
50 POSSIBILITY OF SUCH DAMAGE.
51
52 Individual authors are the holders of the copyright for their code and
53 are listed in each file.
54
80
55 Some files (DPyGetOpt.py, for example) may be licensed under different
81 Some files (DPyGetOpt.py, for example) may be licensed under different
56 conditions. Ultimately each file indicates clearly the conditions under
82 conditions. Ultimately each file indicates clearly the conditions under
@@ -14,136 +14,164 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.
21 * An architecture for interactive parallel computing.
21 * An architecture for interactive parallel computing.
22
22
23 All of IPython is open source (released under the revised BSD license).
23 All of IPython is open source (released under the revised BSD license).
24
24
25 Enhanced interactive Python shell
25 Enhanced interactive Python shell
26 =================================
26 =================================
27
27
28 IPython's interactive shell (`ipython`), has the following goals:
28 IPython's interactive shell (:command:`ipython`), has the following goals,
29
29 amongst others:
30 1. Provide an interactive shell superior to Python's default. IPython
30
31 has many features for object introspection, system shell access,
31 1. Provide an interactive shell superior to Python's default. IPython
32 and its own special command system for adding functionality when
32 has many features for object introspection, system shell access,
33 working interactively. It tries to be a very efficient environment
33 and its own special command system for adding functionality when
34 both for Python code development and for exploration of problems
34 working interactively. It tries to be a very efficient environment
35 using Python objects (in situations like data analysis).
35 both for Python code development and for exploration of problems
36 2. Serve as an embeddable, ready to use interpreter for your own
36 using Python objects (in situations like data analysis).
37 programs. IPython can be started with a single call from inside
37
38 another program, providing access to the current namespace. This
38 2. Serve as an embeddable, ready to use interpreter for your own
39 can be very useful both for debugging purposes and for situations
39 programs. IPython can be started with a single call from inside
40 where a blend of batch-processing and interactive exploration are
40 another program, providing access to the current namespace. This
41 needed.
41 can be very useful both for debugging purposes and for situations
42 3. Offer a flexible framework which can be used as the base
42 where a blend of batch-processing and interactive exploration are
43 environment for other systems with Python as the underlying
43 needed. New in the 0.9 version of IPython is a reusable wxPython
44 language. Specifically scientific environments like Mathematica,
44 based IPython widget.
45 IDL and Matlab inspired its design, but similar ideas can be
45
46 useful in many fields.
46 3. Offer a flexible framework which can be used as the base
47 4. Allow interactive testing of threaded graphical toolkits. IPython
47 environment for other systems with Python as the underlying
48 has support for interactive, non-blocking control of GTK, Qt and
48 language. Specifically scientific environments like Mathematica,
49 WX applications via special threading flags. The normal Python
49 IDL and Matlab inspired its design, but similar ideas can be
50 shell can only do this for Tkinter applications.
50 useful in many fields.
51
52 4. Allow interactive testing of threaded graphical toolkits. IPython
53 has support for interactive, non-blocking control of GTK, Qt and
54 WX applications via special threading flags. The normal Python
55 shell can only do this for Tkinter applications.
51
56
52 Main features of the interactive shell
57 Main features of the interactive shell
53 --------------------------------------
58 --------------------------------------
54
59
55 * Dynamic object introspection. One can access docstrings, function
60 * Dynamic object introspection. One can access docstrings, function
56 definition prototypes, source code, source files and other details
61 definition prototypes, source code, source files and other details
57 of any object accessible to the interpreter with a single
62 of any object accessible to the interpreter with a single
58 keystroke (:samp:`?`, and using :samp:`??` provides additional detail).
63 keystroke (:samp:`?`, and using :samp:`??` provides additional detail).
59 * Searching through modules and namespaces with :samp:`*` wildcards, both
64
60 when using the :samp:`?` system and via the :samp:`%psearch` command.
65 * Searching through modules and namespaces with :samp:`*` wildcards, both
61 * Completion in the local namespace, by typing :kbd:`TAB` at the prompt.
66 when using the :samp:`?` system and via the :samp:`%psearch` command.
62 This works for keywords, modules, methods, variables and files in the
67
63 current directory. This is supported via the readline library, and
68 * Completion in the local namespace, by typing :kbd:`TAB` at the prompt.
64 full access to configuring readline's behavior is provided.
69 This works for keywords, modules, methods, variables and files in the
65 Custom completers can be implemented easily for different purposes
70 current directory. This is supported via the readline library, and
66 (system commands, magic arguments etc.)
71 full access to configuring readline's behavior is provided.
67 * Numbered input/output prompts with command history (persistent
72 Custom completers can be implemented easily for different purposes
68 across sessions and tied to each profile), full searching in this
73 (system commands, magic arguments etc.)
69 history and caching of all input and output.
74
70 * User-extensible 'magic' commands. A set of commands prefixed with
75 * Numbered input/output prompts with command history (persistent
71 :samp:`%` is available for controlling IPython itself and provides
76 across sessions and tied to each profile), full searching in this
72 directory control, namespace information and many aliases to
77 history and caching of all input and output.
73 common system shell commands.
78
74 * Alias facility for defining your own system aliases.
79 * User-extensible 'magic' commands. A set of commands prefixed with
75 * Complete system shell access. Lines starting with :samp:`!` are passed
80 :samp:`%` is available for controlling IPython itself and provides
76 directly to the system shell, and using :samp:`!!` or :samp:`var = !cmd`
81 directory control, namespace information and many aliases to
77 captures shell output into python variables for further use.
82 common system shell commands.
78 * Background execution of Python commands in a separate thread.
83
79 IPython has an internal job manager called jobs, and a
84 * Alias facility for defining your own system aliases.
80 conveninence backgrounding magic function called :samp:`%bg`.
85
81 * The ability to expand python variables when calling the system
86 * Complete system shell access. Lines starting with :samp:`!` are passed
82 shell. In a shell command, any python variable prefixed with :samp:`$` is
87 directly to the system shell, and using :samp:`!!` or :samp:`var = !cmd`
83 expanded. A double :samp:`$$` allows passing a literal :samp:`$` to the shell (for
88 captures shell output into python variables for further use.
84 access to shell and environment variables like :envvar:`PATH`).
89
85 * Filesystem navigation, via a magic :samp:`%cd` command, along with a
90 * Background execution of Python commands in a separate thread.
86 persistent bookmark system (using :samp:`%bookmark`) for fast access to
91 IPython has an internal job manager called jobs, and a
87 frequently visited directories.
92 convenience backgrounding magic function called :samp:`%bg`.
88 * A lightweight persistence framework via the :samp:`%store` command, which
93
89 allows you to save arbitrary Python variables. These get restored
94 * The ability to expand python variables when calling the system
90 automatically when your session restarts.
95 shell. In a shell command, any python variable prefixed with :samp:`$` is
91 * Automatic indentation (optional) of code as you type (through the
96 expanded. A double :samp:`$$` allows passing a literal :samp:`$` to the shell (for
92 readline library).
97 access to shell and environment variables like :envvar:`PATH`).
93 * Macro system for quickly re-executing multiple lines of previous
98
94 input with a single name. Macros can be stored persistently via
99 * Filesystem navigation, via a magic :samp:`%cd` command, along with a
95 :samp:`%store` and edited via :samp:`%edit`.
100 persistent bookmark system (using :samp:`%bookmark`) for fast access to
96 * Session logging (you can then later use these logs as code in your
101 frequently visited directories.
97 programs). Logs can optionally timestamp all input, and also store
102
98 session output (marked as comments, so the log remains valid
103 * A lightweight persistence framework via the :samp:`%store` command, which
99 Python source code).
104 allows you to save arbitrary Python variables. These get restored
100 * Session restoring: logs can be replayed to restore a previous
105 automatically when your session restarts.
101 session to the state where you left it.
106
102 * Verbose and colored exception traceback printouts. Easier to parse
107 * Automatic indentation (optional) of code as you type (through the
103 visually, and in verbose mode they produce a lot of useful
108 readline library).
104 debugging information (basically a terminal version of the cgitb
109
105 module).
110 * Macro system for quickly re-executing multiple lines of previous
106 * Auto-parentheses: callable objects can be executed without
111 input with a single name. Macros can be stored persistently via
107 parentheses: :samp:`sin 3` is automatically converted to :samp:`sin(3)`.
112 :samp:`%store` and edited via :samp:`%edit`.
108 * Auto-quoting: using :samp:`,`, or :samp:`;` as the first character forces
113
109 auto-quoting of the rest of the line: :samp:`,my_function a b` becomes
114 * Session logging (you can then later use these logs as code in your
110 automatically :samp:`my_function("a","b")`, while :samp:`;my_function a b`
115 programs). Logs can optionally timestamp all input, and also store
111 becomes :samp:`my_function("a b")`.
116 session output (marked as comments, so the log remains valid
112 * Extensible input syntax. You can define filters that pre-process
117 Python source code).
113 user input to simplify input in special situations. This allows
118
114 for example pasting multi-line code fragments which start with
119 * Session restoring: logs can be replayed to restore a previous
115 :samp:`>>>` or :samp:`...` such as those from other python sessions or the
120 session to the state where you left it.
116 standard Python documentation.
121
117 * Flexible configuration system. It uses a configuration file which
122 * Verbose and colored exception traceback printouts. Easier to parse
118 allows permanent setting of all command-line options, module
123 visually, and in verbose mode they produce a lot of useful
119 loading, code and file execution. The system allows recursive file
124 debugging information (basically a terminal version of the cgitb
120 inclusion, so you can have a base file with defaults and layers
125 module).
121 which load other customizations for particular projects.
126
122 * Embeddable. You can call IPython as a python shell inside your own
127 * Auto-parentheses: callable objects can be executed without
123 python programs. This can be used both for debugging code or for
128 parentheses: :samp:`sin 3` is automatically converted to :samp:`sin(3)`.
124 providing interactive abilities to your programs with knowledge
129
125 about the local namespaces (very useful in debugging and data
130 * Auto-quoting: using :samp:`,`, or :samp:`;` as the first character forces
126 analysis situations).
131 auto-quoting of the rest of the line: :samp:`,my_function a b` becomes
127 * Easy debugger access. You can set IPython to call up an enhanced
132 automatically :samp:`my_function("a","b")`, while :samp:`;my_function a b`
128 version of the Python debugger (pdb) every time there is an
133 becomes :samp:`my_function("a b")`.
129 uncaught exception. This drops you inside the code which triggered
134
130 the exception with all the data live and it is possible to
135 * Extensible input syntax. You can define filters that pre-process
131 navigate the stack to rapidly isolate the source of a bug. The
136 user input to simplify input in special situations. This allows
132 :samp:`%run` magic command (with the :samp:`-d` option) can run any script under
137 for example pasting multi-line code fragments which start with
133 pdb's control, automatically setting initial breakpoints for you.
138 :samp:`>>>` or :samp:`...` such as those from other python sessions or the
134 This version of pdb has IPython-specific improvements, including
139 standard Python documentation.
135 tab-completion and traceback coloring support. For even easier
140
136 debugger access, try :samp:`%debug` after seeing an exception. winpdb is
141 * Flexible configuration system. It uses a configuration file which
137 also supported, see ipy_winpdb extension.
142 allows permanent setting of all command-line options, module
138 * Profiler support. You can run single statements (similar to
143 loading, code and file execution. The system allows recursive file
139 :samp:`profile.run()`) or complete programs under the profiler's control.
144 inclusion, so you can have a base file with defaults and layers
140 While this is possible with standard cProfile or profile modules,
145 which load other customizations for particular projects.
141 IPython wraps this functionality with magic commands (see :samp:`%prun`
146
142 and :samp:`%run -p`) convenient for rapid interactive work.
147 * Embeddable. You can call IPython as a python shell inside your own
143 * Doctest support. The special :samp:`%doctest_mode` command toggles a mode
148 python programs. This can be used both for debugging code or for
144 that allows you to paste existing doctests (with leading :samp:`>>>`
149 providing interactive abilities to your programs with knowledge
145 prompts and whitespace) and uses doctest-compatible prompts and
150 about the local namespaces (very useful in debugging and data
146 output, so you can use IPython sessions as doctest code.
151 analysis situations).
152
153 * Easy debugger access. You can set IPython to call up an enhanced
154 version of the Python debugger (pdb) every time there is an
155 uncaught exception. This drops you inside the code which triggered
156 the exception with all the data live and it is possible to
157 navigate the stack to rapidly isolate the source of a bug. The
158 :samp:`%run` magic command (with the :samp:`-d` option) can run any script under
159 pdb's control, automatically setting initial breakpoints for you.
160 This version of pdb has IPython-specific improvements, including
161 tab-completion and traceback coloring support. For even easier
162 debugger access, try :samp:`%debug` after seeing an exception. winpdb is
163 also supported, see ipy_winpdb extension.
164
165 * Profiler support. You can run single statements (similar to
166 :samp:`profile.run()`) or complete programs under the profiler's control.
167 While this is possible with standard cProfile or profile modules,
168 IPython wraps this functionality with magic commands (see :samp:`%prun`
169 and :samp:`%run -p`) convenient for rapid interactive work.
170
171 * Doctest support. The special :samp:`%doctest_mode` command toggles a mode
172 that allows you to paste existing doctests (with leading :samp:`>>>`
173 prompts and whitespace) and uses doctest-compatible prompts and
174 output, so you can use IPython sessions as doctest code.
147
175
148 Interactive parallel computing
176 Interactive parallel computing
149 ==============================
177 ==============================
@@ -153,6 +181,37 b' architecture within IPython that allows such hardware to be used quickly and eas'
153 from Python. Moreover, this architecture is designed to support interactive and
181 from Python. Moreover, this architecture is designed to support interactive and
154 collaborative parallel computing.
182 collaborative parallel computing.
155
183
184 The main features of this system are:
185
186 * Quickly parallelize Python code from an interactive Python/IPython session.
187
188 * A flexible and dynamic process model that be deployed on anything from
189 multicore workstations to supercomputers.
190
191 * An architecture that supports many different styles of parallelism, from
192 message passing to task farming. And all of these styles can be handled
193 interactively.
194
195 * Both blocking and fully asynchronous interfaces.
196
197 * High level APIs that enable many things to be parallelized in a few lines
198 of code.
199
200 * Write parallel code that will run unchanged on everything from multicore
201 workstations to supercomputers.
202
203 * Full integration with Message Passing libraries (MPI).
204
205 * Capabilities based security model with full encryption of network connections.
206
207 * Share live parallel jobs with other users securely. We call this collaborative
208 parallel computing.
209
210 * Dynamically load balanced task farming system.
211
212 * Robust error handling. Python exceptions raised in parallel execution are
213 gathered and presented to the top-level code.
214
156 For more information, see our :ref:`overview <parallel_index>` of using IPython for
215 For more information, see our :ref:`overview <parallel_index>` of using IPython for
157 parallel computing.
216 parallel computing.
158
217
@@ -1,12 +1,9 b''
1 .. _parallel_index:
1 .. _parallel_index:
2
2
3 ====================================
3 ====================================
4 Using IPython for Parallel computing
4 Using IPython for parallel computing
5 ====================================
5 ====================================
6
6
7 User Documentation
8 ==================
9
10 .. toctree::
7 .. toctree::
11 :maxdepth: 2
8 :maxdepth: 2
12
9
@@ -1,57 +1,68 b''
1 .. _ip1par:
1 .. _ip1par:
2
2
3 ======================================
3 ============================
4 Using IPython for parallel computing
4 Overview and getting started
5 ======================================
5 ============================
6
6
7 .. contents::
7 .. contents::
8
8
9 Introduction
9 Introduction
10 ============
10 ============
11
11
12 This file gives an overview of IPython. IPython has a sophisticated and
12 This file gives an overview of IPython's sophisticated and
13 powerful architecture for parallel and distributed computing. This
13 powerful architecture for parallel and distributed computing. This
14 architecture abstracts out parallelism in a very general way, which
14 architecture abstracts out parallelism in a very general way, which
15 enables IPython to support many different styles of parallelism
15 enables IPython to support many different styles of parallelism
16 including:
16 including:
17
17
18 * Single program, multiple data (SPMD) parallelism.
18 * Single program, multiple data (SPMD) parallelism.
19 * Multiple program, multiple data (MPMD) parallelism.
19 * Multiple program, multiple data (MPMD) parallelism.
20 * Message passing using ``MPI``.
20 * Message passing using ``MPI``.
21 * Task farming.
21 * Task farming.
22 * Data parallel.
22 * Data parallel.
23 * Combinations of these approaches.
23 * Combinations of these approaches.
24 * Custom user defined approaches.
24 * Custom user defined approaches.
25
25
26 Most importantly, IPython enables all types of parallel applications to
26 Most importantly, IPython enables all types of parallel applications to
27 be developed, executed, debugged and monitored *interactively*. Hence,
27 be developed, executed, debugged and monitored *interactively*. Hence,
28 the ``I`` in IPython. The following are some example usage cases for IPython:
28 the ``I`` in IPython. The following are some example usage cases for IPython:
29
29
30 * Quickly parallelize algorithms that are embarrassingly parallel
30 * Quickly parallelize algorithms that are embarrassingly parallel
31 using a number of simple approaches. Many simple things can be
31 using a number of simple approaches. Many simple things can be
32 parallelized interactively in one or two lines of code.
32 parallelized interactively in one or two lines of code.
33 * Steer traditional MPI applications on a supercomputer from an
33
34 IPython session on your laptop.
34 * Steer traditional MPI applications on a supercomputer from an
35 * Analyze and visualize large datasets (that could be remote and/or
35 IPython session on your laptop.
36 distributed) interactively using IPython and tools like
36
37 matplotlib/TVTK.
37 * Analyze and visualize large datasets (that could be remote and/or
38 * Develop, test and debug new parallel algorithms
38 distributed) interactively using IPython and tools like
39 (that may use MPI) interactively.
39 matplotlib/TVTK.
40 * Tie together multiple MPI jobs running on different systems into
40
41 one giant distributed and parallel system.
41 * Develop, test and debug new parallel algorithms
42 * Start a parallel job on your cluster and then have a remote
42 (that may use MPI) interactively.
43 collaborator connect to it and pull back data into their
43
44 local IPython session for plotting and analysis.
44 * Tie together multiple MPI jobs running on different systems into
45 * Run a set of tasks on a set of CPUs using dynamic load balancing.
45 one giant distributed and parallel system.
46
47 * Start a parallel job on your cluster and then have a remote
48 collaborator connect to it and pull back data into their
49 local IPython session for plotting and analysis.
50
51 * Run a set of tasks on a set of CPUs using dynamic load balancing.
46
52
47 Architecture overview
53 Architecture overview
48 =====================
54 =====================
49
55
50 The IPython architecture consists of three components:
56 The IPython architecture consists of three components:
51
57
52 * The IPython engine.
58 * The IPython engine.
53 * The IPython controller.
59 * The IPython controller.
54 * Various controller Clients.
60 * Various controller clients.
61
62 These components live in the :mod:`IPython.kernel` package and are
63 installed with IPython. They do, however, have additional dependencies
64 that must be installed. For more information, see our
65 :ref:`installation documentation <install_index>`.
55
66
56 IPython engine
67 IPython engine
57 ---------------
68 ---------------
@@ -75,16 +86,21 b' IPython engines can connect. For each connected engine, the controller'
75 manages a queue. All actions that can be performed on the engine go
86 manages a queue. All actions that can be performed on the engine go
76 through this queue. While the engines themselves block when user code is
87 through this queue. While the engines themselves block when user code is
77 run, the controller hides that from the user to provide a fully
88 run, the controller hides that from the user to provide a fully
78 asynchronous interface to a set of engines. Because the controller
89 asynchronous interface to a set of engines.
79 listens on a network port for engines to connect to it, it must be
90
80 started before any engines are started.
91 .. note::
92
93 Because the controller listens on a network port for engines to
94 connect to it, it must be started *before* any engines are started.
81
95
82 The controller also provides a single point of contact for users who wish
96 The controller also provides a single point of contact for users who wish
83 to utilize the engines connected to the controller. There are different
97 to utilize the engines connected to the controller. There are different
84 ways of working with a controller. In IPython these ways correspond to different interfaces that the controller is adapted to. Currently we have two default interfaces to the controller:
98 ways of working with a controller. In IPython these ways correspond to different interfaces that the controller is adapted to. Currently we have two default interfaces to the controller:
85
99
86 * The MultiEngine interface.
100 * The MultiEngine interface, which provides the simplest possible way of working
87 * The Task interface.
101 with engines interactively.
102 * The Task interface, which provides presents the engines as a load balanced
103 task farming system.
88
104
89 Advanced users can easily add new custom interfaces to enable other
105 Advanced users can easily add new custom interfaces to enable other
90 styles of parallelism.
106 styles of parallelism.
@@ -100,18 +116,37 b' Controller clients'
100
116
101 For each controller interface, there is a corresponding client. These
117 For each controller interface, there is a corresponding client. These
102 clients allow users to interact with a set of engines through the
118 clients allow users to interact with a set of engines through the
103 interface.
119 interface. Here are the two default clients:
120
121 * The :class:`MultiEngineClient` class.
122 * The :class:`TaskClient` class.
104
123
105 Security
124 Security
106 --------
125 --------
107
126
108 By default (as long as `pyOpenSSL` is installed) all network connections between the controller and engines and the controller and clients are secure. What does this mean? First of all, all of the connections will be encrypted using SSL. Second, the connections are authenticated. We handle authentication in a `capabilities`__ based security model. In this model, a "capability (known in some systems as a key) is a communicable, unforgeable token of authority". Put simply, a capability is like a key to your house. If you have the key to your house, you can get in, if not you can't.
127 By default (as long as `pyOpenSSL` is installed) all network connections between the controller and engines and the controller and clients are secure. What does this mean? First of all, all of the connections will be encrypted using SSL. Second, the connections are authenticated. We handle authentication in a `capabilities`__ based security model. In this model, a "capability (known in some systems as a key) is a communicable, unforgeable token of authority". Put simply, a capability is like a key to your house. If you have the key to your house, you can get in. If not, you can't.
109
128
110 .. __: http://en.wikipedia.org/wiki/Capability-based_security
129 .. __: http://en.wikipedia.org/wiki/Capability-based_security
111
130
112 In our architecture, the controller is the only process that listens on network ports, and is thus responsible to creating these keys. In IPython, these keys are known as Foolscap URLs, or FURLs, because of the underlying network protocol we are using. As a user, you don't need to know anything about the details of these FURLs, other than that when the controller starts, it saves a set of FURLs to files named something.furl. The default location of these files is your ~./ipython directory.
131 In our architecture, the controller is the only process that listens on network ports, and is thus responsible to creating these keys. In IPython, these keys are known as Foolscap URLs, or FURLs, because of the underlying network protocol we are using. As a user, you don't need to know anything about the details of these FURLs, other than that when the controller starts, it saves a set of FURLs to files named :file:`something.furl`. The default location of these files is the :file:`~./ipython/security` directory.
113
132
114 To connect and authenticate to the controller an engine or client simply needs to present an appropriate furl (that was originally created by the controller) to the controller. Thus, the .furl files need to be copied to a location where the clients and engines can find them. Typically, this is the ~./ipython directory on the host where the client/engine is running (which could be a different host than the controller). Once the .furl files are copied over, everything should work fine.
133 To connect and authenticate to the controller an engine or client simply needs to present an appropriate furl (that was originally created by the controller) to the controller. Thus, the .furl files need to be copied to a location where the clients and engines can find them. Typically, this is the :file:`~./ipython/security` directory on the host where the client/engine is running (which could be a different host than the controller). Once the .furl files are copied over, everything should work fine.
134
135 Currently, there are three .furl files that the controller creates:
136
137 ipcontroller-engine.furl
138 This ``.furl`` file is the key that gives an engine the ability to connect
139 to a controller.
140
141 ipcontroller-tc.furl
142 This ``.furl`` file is the key that a :class:`TaskClient` must use to
143 connect to the task interface of a controller.
144
145 ipcontroller-mec.furl
146 This ``.furl`` file is the key that a :class:`MultiEngineClient` must use to
147 connect to the multiengine interface of a controller.
148
149 More details of how these ``.furl`` files are used are given below.
115
150
116 Getting Started
151 Getting Started
117 ===============
152 ===============
@@ -127,28 +162,40 b' Starting the controller and engine on your local machine'
127
162
128 This is the simplest configuration that can be used and is useful for
163 This is the simplest configuration that can be used and is useful for
129 testing the system and on machines that have multiple cores and/or
164 testing the system and on machines that have multiple cores and/or
130 multple CPUs. The easiest way of doing this is using the ``ipcluster``
165 multple CPUs. The easiest way of getting started is to use the :command:`ipcluster`
131 command::
166 command::
132
167
133 $ ipcluster -n 4
168 $ ipcluster -n 4
134
169
135 This will start an IPython controller and then 4 engines that connect to
170 This will start an IPython controller and then 4 engines that connect to
136 the controller. Lastly, the script will print out the Python commands
171 the controller. Lastly, the script will print out the Python commands
137 that you can use to connect to the controller. It is that easy.
172 that you can use to connect to the controller. It is that easy.
138
173
139 Underneath the hood, the ``ipcluster`` script uses two other top-level
174 .. warning::
175
176 The :command:`ipcluster` does not currently work on Windows. We are
177 working on it though.
178
179 Underneath the hood, the controller creates ``.furl`` files in the
180 :file:`~./ipython/security` directory. Because the engines are on the
181 same host, they automatically find the needed :file:`ipcontroller-engine.furl`
182 there and use it to connect to the controller.
183
184 The :command:`ipcluster` script uses two other top-level
140 scripts that you can also use yourself. These scripts are
185 scripts that you can also use yourself. These scripts are
141 ``ipcontroller``, which starts the controller and ``ipengine`` which
186 :command:`ipcontroller`, which starts the controller and :command:`ipengine` which
142 starts one engine. To use these scripts to start things on your local
187 starts one engine. To use these scripts to start things on your local
143 machine, do the following.
188 machine, do the following.
144
189
145 First start the controller::
190 First start the controller::
146
191
147 $ ipcontroller &
192 $ ipcontroller
148
193
149 Next, start however many instances of the engine you want using (repeatedly) the command::
194 Next, start however many instances of the engine you want using (repeatedly) the command::
150
195
151 $ ipengine &
196 $ ipengine
197
198 The engines should start and automatically connect to the controller using the ``.furl`` files in :file:`~./ipython/security`. You are now ready to use the controller and engines from IPython.
152
199
153 .. warning::
200 .. warning::
154
201
@@ -156,47 +203,71 b' Next, start however many instances of the engine you want using (repeatedly) the'
156 start the controller before the engines, since the engines connect
203 start the controller before the engines, since the engines connect
157 to the controller as they get started.
204 to the controller as they get started.
158
205
159 On some platforms you may need to give these commands in the form
206 .. note::
160 ``(ipcontroller &)`` and ``(ipengine &)`` for them to work properly. The
161 engines should start and automatically connect to the controller on the
162 default ports, which are chosen for this type of setup. You are now ready
163 to use the controller and engines from IPython.
164
207
165 Starting the controller and engines on different machines
208 On some platforms (OS X), to put the controller and engine into the background
166 ---------------------------------------------------------
209 you may need to give these commands in the form ``(ipcontroller &)``
210 and ``(ipengine &)`` (with the parentheses) for them to work properly.
167
211
168 This section needs to be updated to reflect the new Foolscap capabilities based
169 model.
170
212
171 Using ``ipcluster`` with ``ssh``
213 Starting the controller and engines on different hosts
172 --------------------------------
214 ------------------------------------------------------
173
215
174 The ``ipcluster`` command can also start a controller and engines using
216 When the controller and engines are running on different hosts, things are
175 ``ssh``. We need more documentation on this, but for now here is any
217 slightly more complicated, but the underlying ideas are the same:
176 example startup script::
177
218
178 controller = dict(host='myhost',
219 1. Start the controller on a host using :command:`ipcontroler`.
179 engine_port=None, # default is 10105
220 2. Copy :file:`ipcontroller-engine.furl` from :file:`~./ipython/security` on the controller's host to the host where the engines will run.
180 control_port=None,
221 3. Use :command:`ipengine` on the engine's hosts to start the engines.
181 )
182
222
183 # keys are hostnames, values are the number of engine on that host
223 The only thing you have to be careful of is to tell :command:`ipengine` where the :file:`ipcontroller-engine.furl` file is located. There are two ways you can do this:
184 engines = dict(node1=2,
224
185 node2=2,
225 * Put :file:`ipcontroller-engine.furl` in the :file:`~./ipython/security` directory
186 node3=2,
226 on the engine's host, where it will be found automatically.
187 node3=2,
227 * Call :command:`ipengine` with the ``--furl-file=full_path_to_the_file`` flag.
188 )
228
229 The ``--furl-file`` flag works like this::
230
231 $ ipengine --furl-file=/path/to/my/ipcontroller-engine.furl
232
233 .. note::
234
235 If the controller's and engine's hosts all have a shared file system
236 (:file:`~./ipython/security` is the same on all of them), then things
237 will just work!
238
239 Make .furl files persistent
240 ---------------------------
241
242 At fist glance it may seem that that managing the ``.furl`` files is a bit annoying. Going back to the house and key analogy, copying the ``.furl`` around each time you start the controller is like having to make a new key everytime you want to unlock the door and enter your house. As with your house, you want to be able to create the key (or ``.furl`` file) once, and then simply use it at any point in the future.
243
244 This is possible. The only thing you have to do is decide what ports the controller will listen on for the engines and clients. This is done as follows::
245
246 $ ipcontroller --client-port=10101 --engine-port=10102
247
248 Then, just copy the furl files over the first time and you are set. You can start and stop the controller and engines any many times as you want in the future, just make sure to tell the controller to use the *same* ports.
249
250 .. note::
251
252 You may ask the question: what ports does the controller listen on if you
253 don't tell is to use specific ones? The default is to use high random port
254 numbers. We do this for two reasons: i) to increase security through obcurity
255 and ii) to multiple controllers on a given host to start and automatically
256 use different ports.
189
257
190 Starting engines using ``mpirun``
258 Starting engines using ``mpirun``
191 ---------------------------------
259 ---------------------------------
192
260
193 The IPython engines can be started using ``mpirun``/``mpiexec``, even if
261 The IPython engines can be started using ``mpirun``/``mpiexec``, even if
194 the engines don't call MPI_Init() or use the MPI API in any way. This is
262 the engines don't call ``MPI_Init()`` or use the MPI API in any way. This is
195 supported on modern MPI implementations like `Open MPI`_.. This provides
263 supported on modern MPI implementations like `Open MPI`_.. This provides
196 an really nice way of starting a bunch of engine. On a system with MPI
264 an really nice way of starting a bunch of engine. On a system with MPI
197 installed you can do::
265 installed you can do::
198
266
199 mpirun -n 4 ipengine --controller-port=10000 --controller-ip=host0
267 mpirun -n 4 ipengine
268
269 to start 4 engine on a cluster. This works even if you don't have any
270 Python-MPI bindings installed.
200
271
201 .. _Open MPI: http://www.open-mpi.org/
272 .. _Open MPI: http://www.open-mpi.org/
202
273
@@ -214,12 +285,12 b' Next Steps'
214 ==========
285 ==========
215
286
216 Once you have started the IPython controller and one or more engines, you
287 Once you have started the IPython controller and one or more engines, you
217 are ready to use the engines to do somnething useful. To make sure
288 are ready to use the engines to do something useful. To make sure
218 everything is working correctly, try the following commands::
289 everything is working correctly, try the following commands::
219
290
220 In [1]: from IPython.kernel import client
291 In [1]: from IPython.kernel import client
221
292
222 In [2]: mec = client.MultiEngineClient() # This looks for .furl files in ~./ipython
293 In [2]: mec = client.MultiEngineClient()
223
294
224 In [4]: mec.get_ids()
295 In [4]: mec.get_ids()
225 Out[4]: [0, 1, 2, 3]
296 Out[4]: [0, 1, 2, 3]
@@ -239,4 +310,18 b' everything is working correctly, try the following commands::'
239 [3] In [1]: print "Hello World"
310 [3] In [1]: print "Hello World"
240 [3] Out[1]: Hello World
311 [3] Out[1]: Hello World
241
312
242 If this works, you are ready to learn more about the :ref:`MultiEngine <parallelmultiengine>` and :ref:`Task <paralleltask>` interfaces to the controller.
313 Remember, a client also needs to present a ``.furl`` file to the controller. How does this happen? When a multiengine client is created with no arguments, the client tries to find the corresponding ``.furl`` file in the local :file:`~./ipython/security` directory. If it finds it, you are set. If you have put the ``.furl`` file in a different location or it has a different name, create the client like this::
314
315 mec = client.MultiEngineClient('/path/to/my/ipcontroller-mec.furl')
316
317 Same thing hold true of creating a task client::
318
319 tc = client.TaskClient('/path/to/my/ipcontroller-tc.furl')
320
321 You are now ready to learn more about the :ref:`MultiEngine <parallelmultiengine>` and :ref:`Task <paralleltask>` interfaces to the controller.
322
323 .. note::
324
325 Don't forget that the engine, multiengine client and task client all have
326 *different* furl files. You must move *each* of these around to an appropriate
327 location so that the engines and clients can use them to connect to the controller.
@@ -1,57 +1,115 b''
1 .. _parallelmultiengine:
1 .. _parallelmultiengine:
2
2
3 =================================
3 ===============================
4 IPython's MultiEngine interface
4 IPython's multiengine interface
5 =================================
5 ===============================
6
6
7 .. contents::
7 .. contents::
8
8
9 The MultiEngine interface represents one possible way of working with a
9 The multiengine interface represents one possible way of working with a set of
10 set of IPython engines. The basic idea behind the MultiEngine interface is
10 IPython engines. The basic idea behind the multiengine interface is that the
11 that the capabilities of each engine are explicitly exposed to the user.
11 capabilities of each engine are directly and explicitly exposed to the user.
12 Thus, in the MultiEngine interface, each engine is given an id that is
12 Thus, in the multiengine interface, each engine is given an id that is used to
13 used to identify the engine and give it work to do. This interface is very
13 identify the engine and give it work to do. This interface is very intuitive
14 intuitive and is designed with interactive usage in mind, and is thus the
14 and is designed with interactive usage in mind, and is thus the best place for
15 best place for new users of IPython to begin.
15 new users of IPython to begin.
16
16
17 Starting the IPython controller and engines
17 Starting the IPython controller and engines
18 ===========================================
18 ===========================================
19
19
20 To follow along with this tutorial, you will need to start the IPython
20 To follow along with this tutorial, you will need to start the IPython
21 controller and four IPython engines. The simplest way of doing this is to
21 controller and four IPython engines. The simplest way of doing this is to use
22 use the ``ipcluster`` command::
22 the :command:`ipcluster` command::
23
23
24 $ ipcluster -n 4
24 $ ipcluster -n 4
25
25
26 For more detailed information about starting the controller and engines, see our :ref:`introduction <ip1par>` to using IPython for parallel computing.
26 For more detailed information about starting the controller and engines, see
27 our :ref:`introduction <ip1par>` to using IPython for parallel computing.
27
28
28 Creating a ``MultiEngineClient`` instance
29 Creating a ``MultiEngineClient`` instance
29 =========================================
30 =========================================
30
31
31 The first step is to import the IPython ``client`` module and then create a ``MultiEngineClient`` instance::
32 The first step is to import the IPython :mod:`IPython.kernel.client` module
33 and then create a :class:`MultiEngineClient` instance::
32
34
33 In [1]: from IPython.kernel import client
35 In [1]: from IPython.kernel import client
34
36
35 In [2]: mec = client.MultiEngineClient()
37 In [2]: mec = client.MultiEngineClient()
36
38
37 To make sure there are engines connected to the controller, use can get a list of engine ids::
39 This form assumes that the :file:`ipcontroller-mec.furl` is in the
40 :file:`~./ipython/security` directory on the client's host. If not, the
41 location of the ``.furl`` file must be given as an argument to the
42 constructor::
43
44 In[2]: mec = client.MultiEngineClient('/path/to/my/ipcontroller-mec.furl')
45
46 To make sure there are engines connected to the controller, use can get a list
47 of engine ids::
38
48
39 In [3]: mec.get_ids()
49 In [3]: mec.get_ids()
40 Out[3]: [0, 1, 2, 3]
50 Out[3]: [0, 1, 2, 3]
41
51
42 Here we see that there are four engines ready to do work for us.
52 Here we see that there are four engines ready to do work for us.
43
53
54 Quick and easy parallelism
55 ==========================
56
57 In many cases, you simply want to apply a Python function to a sequence of objects, but *in parallel*. The multiengine interface provides two simple ways of accomplishing this: a parallel version of :func:`map` and ``@parallel`` function decorator.
58
59 Parallel map
60 ------------
61
62 Python's builtin :func:`map` functions allows a function to be applied to a
63 sequence element-by-element. This type of code is typically trivial to
64 parallelize. In fact, the multiengine interface in IPython already has a
65 parallel version of :meth:`map` that works just like its serial counterpart::
66
67 In [63]: serial_result = map(lambda x:x**10, range(32))
68
69 In [64]: parallel_result = mec.map(lambda x:x**10, range(32))
70
71 In [65]: serial_result==parallel_result
72 Out[65]: True
73
74 .. note::
75
76 The multiengine interface version of :meth:`map` does not do any load
77 balancing. For a load balanced version, see the task interface.
78
79 .. seealso::
80
81 The :meth:`map` method has a number of options that can be controlled by
82 the :meth:`mapper` method. See its docstring for more information.
83
84 Parallel function decorator
85 ---------------------------
86
87 Parallel functions are just like normal function, but they can be called on sequences and *in parallel*. The multiengine interface provides a decorator that turns any Python function into a parallel function::
88
89 In [10]: @mec.parallel()
90 ....: def f(x):
91 ....: return 10.0*x**4
92 ....:
93
94 In [11]: f(range(32)) # this is done in parallel
95 Out[11]:
96 [0.0,10.0,160.0,...]
97
98 See the docstring for the :meth:`parallel` decorator for options.
99
44 Running Python commands
100 Running Python commands
45 =======================
101 =======================
46
102
47 The most basic type of operation that can be performed on the engines is to execute Python code. Executing Python code can be done in blocking or non-blocking mode (blocking is default) using the ``execute`` method.
103 The most basic type of operation that can be performed on the engines is to
104 execute Python code. Executing Python code can be done in blocking or
105 non-blocking mode (blocking is default) using the :meth:`execute` method.
48
106
49 Blocking execution
107 Blocking execution
50 ------------------
108 ------------------
51
109
52 In blocking mode, the ``MultiEngineClient`` object (called ``mec`` in
110 In blocking mode, the :class:`MultiEngineClient` object (called ``mec`` in
53 these examples) submits the command to the controller, which places the
111 these examples) submits the command to the controller, which places the
54 command in the engines' queues for execution. The ``execute`` call then
112 command in the engines' queues for execution. The :meth:`execute` call then
55 blocks until the engines are done executing the command::
113 blocks until the engines are done executing the command::
56
114
57 # The default is to run on all engines
115 # The default is to run on all engines
@@ -71,7 +129,8 b' blocks until the engines are done executing the command::'
71 [2] In [2]: b=10
129 [2] In [2]: b=10
72 [3] In [2]: b=10
130 [3] In [2]: b=10
73
131
74 Python commands can be executed on specific engines by calling execute using the ``targets`` keyword argument::
132 Python commands can be executed on specific engines by calling execute using
133 the ``targets`` keyword argument::
75
134
76 In [6]: mec.execute('c=a+b',targets=[0,2])
135 In [6]: mec.execute('c=a+b',targets=[0,2])
77 Out[6]:
136 Out[6]:
@@ -102,7 +161,9 b' Python commands can be executed on specific engines by calling execute using the'
102 [3] In [4]: print c
161 [3] In [4]: print c
103 [3] Out[4]: -5
162 [3] Out[4]: -5
104
163
105 This example also shows one of the most important things about the IPython engines: they have a persistent user namespaces. The ``execute`` method returns a Python ``dict`` that contains useful information::
164 This example also shows one of the most important things about the IPython
165 engines: they have a persistent user namespaces. The :meth:`execute` method
166 returns a Python ``dict`` that contains useful information::
106
167
107 In [9]: result_dict = mec.execute('d=10; print d')
168 In [9]: result_dict = mec.execute('d=10; print d')
108
169
@@ -118,10 +179,12 b' This example also shows one of the most important things about the IPython engin'
118 Non-blocking execution
179 Non-blocking execution
119 ----------------------
180 ----------------------
120
181
121 In non-blocking mode, ``execute`` submits the command to be executed and then returns a
182 In non-blocking mode, :meth:`execute` submits the command to be executed and
122 ``PendingResult`` object immediately. The ``PendingResult`` object gives you a way of getting a
183 then returns a :class:`PendingResult` object immediately. The
123 result at a later time through its ``get_result`` method or ``r`` attribute. This allows you to
184 :class:`PendingResult` object gives you a way of getting a result at a later
124 quickly submit long running commands without blocking your local Python/IPython session::
185 time through its :meth:`get_result` method or :attr:`r` attribute. This allows
186 you to quickly submit long running commands without blocking your local
187 Python/IPython session::
125
188
126 # In blocking mode
189 # In blocking mode
127 In [6]: mec.execute('import time')
190 In [6]: mec.execute('import time')
@@ -159,7 +222,10 b' quickly submit long running commands without blocking your local Python/IPython '
159 [2] In [3]: time.sleep(10)
222 [2] In [3]: time.sleep(10)
160 [3] In [3]: time.sleep(10)
223 [3] In [3]: time.sleep(10)
161
224
162 Often, it is desirable to wait until a set of ``PendingResult`` objects are done. For this, there is a the method ``barrier``. This method takes a tuple of ``PendingResult`` objects and blocks until all of the associated results are ready::
225 Often, it is desirable to wait until a set of :class:`PendingResult` objects
226 are done. For this, there is a the method :meth:`barrier`. This method takes a
227 tuple of :class:`PendingResult` objects and blocks until all of the associated
228 results are ready::
163
229
164 In [72]: mec.block=False
230 In [72]: mec.block=False
165
231
@@ -182,14 +248,16 b' Often, it is desirable to wait until a set of ``PendingResult`` objects are done'
182 The ``block`` and ``targets`` keyword arguments and attributes
248 The ``block`` and ``targets`` keyword arguments and attributes
183 --------------------------------------------------------------
249 --------------------------------------------------------------
184
250
185 Most commands in the multiengine interface (like ``execute``) accept ``block`` and ``targets``
251 Most methods in the multiengine interface (like :meth:`execute`) accept
186 as keyword arguments. As we have seen above, these keyword arguments control the blocking mode
252 ``block`` and ``targets`` as keyword arguments. As we have seen above, these
187 and which engines the command is applied to. The ``MultiEngineClient`` class also has ``block``
253 keyword arguments control the blocking mode and which engines the command is
188 and ``targets`` attributes that control the default behavior when the keyword arguments are not
254 applied to. The :class:`MultiEngineClient` class also has :attr:`block` and
189 provided. Thus the following logic is used for ``block`` and ``targets``:
255 :attr:`targets` attributes that control the default behavior when the keyword
256 arguments are not provided. Thus the following logic is used for :attr:`block`
257 and :attr:`targets`:
190
258
191 * If no keyword argument is provided, the instance attributes are used.
259 * If no keyword argument is provided, the instance attributes are used.
192 * Keyword argument, if provided override the instance attributes.
260 * Keyword argument, if provided override the instance attributes.
193
261
194 The following examples demonstrate how to use the instance attributes::
262 The following examples demonstrate how to use the instance attributes::
195
263
@@ -225,14 +293,19 b' The following examples demonstrate how to use the instance attributes::'
225 [3] In [6]: b=10; print b
293 [3] In [6]: b=10; print b
226 [3] Out[6]: 10
294 [3] Out[6]: 10
227
295
228 The ``block`` and ``targets`` instance attributes also determine the behavior of the parallel
296 The :attr:`block` and :attr:`targets` instance attributes also determine the
229 magic commands...
297 behavior of the parallel magic commands.
230
298
231
299
232 Parallel magic commands
300 Parallel magic commands
233 -----------------------
301 -----------------------
234
302
235 We provide a few IPython magic commands (``%px``, ``%autopx`` and ``%result``) that make it more pleasant to execute Python commands on the engines interactively. These are simply shortcuts to ``execute`` and ``get_result``. The ``%px`` magic executes a single Python command on the engines specified by the `magicTargets``targets` attribute of the ``MultiEngineClient`` instance (by default this is 'all')::
303 We provide a few IPython magic commands (``%px``, ``%autopx`` and ``%result``)
304 that make it more pleasant to execute Python commands on the engines
305 interactively. These are simply shortcuts to :meth:`execute` and
306 :meth:`get_result`. The ``%px`` magic executes a single Python command on the
307 engines specified by the :attr:`targets` attribute of the
308 :class:`MultiEngineClient` instance (by default this is ``'all'``)::
236
309
237 # Make this MultiEngineClient active for parallel magic commands
310 # Make this MultiEngineClient active for parallel magic commands
238 In [23]: mec.activate()
311 In [23]: mec.activate()
@@ -277,7 +350,9 b' We provide a few IPython magic commands (``%px``, ``%autopx`` and ``%result``) t'
277 [3] In [9]: print numpy.linalg.eigvals(a)
350 [3] In [9]: print numpy.linalg.eigvals(a)
278 [3] Out[9]: [ 0.83664764 -0.25602658]
351 [3] Out[9]: [ 0.83664764 -0.25602658]
279
352
280 The ``%result`` magic gets and prints the stdin/stdout/stderr of the last command executed on each engine. It is simply a shortcut to the ``get_result`` method::
353 The ``%result`` magic gets and prints the stdin/stdout/stderr of the last
354 command executed on each engine. It is simply a shortcut to the
355 :meth:`get_result` method::
281
356
282 In [29]: %result
357 In [29]: %result
283 Out[29]:
358 Out[29]:
@@ -294,7 +369,8 b' The ``%result`` magic gets and prints the stdin/stdout/stderr of the last comman'
294 [3] In [9]: print numpy.linalg.eigvals(a)
369 [3] In [9]: print numpy.linalg.eigvals(a)
295 [3] Out[9]: [ 0.83664764 -0.25602658]
370 [3] Out[9]: [ 0.83664764 -0.25602658]
296
371
297 The ``%autopx`` magic switches to a mode where everything you type is executed on the engines given by the ``targets`` attribute::
372 The ``%autopx`` magic switches to a mode where everything you type is executed
373 on the engines given by the :attr:`targets` attribute::
298
374
299 In [30]: mec.block=False
375 In [30]: mec.block=False
300
376
@@ -335,51 +411,19 b' The ``%autopx`` magic switches to a mode where everything you type is executed o'
335 [3] In [12]: print "Average max eigenvalue is: ", sum(max_evals)/len(max_evals)
411 [3] In [12]: print "Average max eigenvalue is: ", sum(max_evals)/len(max_evals)
336 [3] Out[12]: Average max eigenvalue is: 10.1158837784
412 [3] Out[12]: Average max eigenvalue is: 10.1158837784
337
413
338 Using the ``with`` statement of Python 2.5
339 ------------------------------------------
340
414
341 Python 2.5 introduced the ``with`` statement. The ``MultiEngineClient`` can be used with the ``with`` statement to execute a block of code on the engines indicated by the ``targets`` attribute::
415 Moving Python objects around
416 ============================
342
417
343 In [3]: with mec:
418 In addition to executing code on engines, you can transfer Python objects to
344 ...: client.remote() # Required so the following code is not run locally
419 and from your IPython session and the engines. In IPython, these operations
345 ...: a = 10
420 are called :meth:`push` (sending an object to the engines) and :meth:`pull`
346 ...: b = 30
421 (getting an object from the engines).
347 ...: c = a+b
348 ...:
349 ...:
350
351 In [4]: mec.get_result()
352 Out[4]:
353 <Results List>
354 [0] In [1]: a = 10
355 b = 30
356 c = a+b
357
358 [1] In [1]: a = 10
359 b = 30
360 c = a+b
361
362 [2] In [1]: a = 10
363 b = 30
364 c = a+b
365
366 [3] In [1]: a = 10
367 b = 30
368 c = a+b
369
370 This is basically another way of calling execute, but one with allows you to avoid writing code in strings. When used in this way, the attributes ``targets`` and ``block`` are used to control how the code is executed. For now, if you run code in non-blocking mode you won't have access to the ``PendingResult``.
371
372 Moving Python object around
373 ===========================
374
375 In addition to executing code on engines, you can transfer Python objects to and from your
376 IPython session and the engines. In IPython, these operations are called ``push`` (sending an
377 object to the engines) and ``pull`` (getting an object from the engines).
378
422
379 Basic push and pull
423 Basic push and pull
380 -------------------
424 -------------------
381
425
382 Here are some examples of how you use ``push`` and ``pull``::
426 Here are some examples of how you use :meth:`push` and :meth:`pull`::
383
427
384 In [38]: mec.push(dict(a=1.03234,b=3453))
428 In [38]: mec.push(dict(a=1.03234,b=3453))
385 Out[38]: [None, None, None, None]
429 Out[38]: [None, None, None, None]
@@ -415,7 +459,8 b' Here are some examples of how you use ``push`` and ``pull``::'
415 [3] In [13]: print c
459 [3] In [13]: print c
416 [3] Out[13]: speed
460 [3] Out[13]: speed
417
461
418 In non-blocking mode ``push`` and ``pull`` also return ``PendingResult`` objects::
462 In non-blocking mode :meth:`push` and :meth:`pull` also return
463 :class:`PendingResult` objects::
419
464
420 In [47]: mec.block=False
465 In [47]: mec.block=False
421
466
@@ -428,7 +473,11 b' In non-blocking mode ``push`` and ``pull`` also return ``PendingResult`` objects'
428 Push and pull for functions
473 Push and pull for functions
429 ---------------------------
474 ---------------------------
430
475
431 Functions can also be pushed and pulled using ``push_function`` and ``pull_function``::
476 Functions can also be pushed and pulled using :meth:`push_function` and
477 :meth:`pull_function`::
478
479
480 In [52]: mec.block=True
432
481
433 In [53]: def f(x):
482 In [53]: def f(x):
434 ....: return 2.0*x**4
483 ....: return 2.0*x**4
@@ -466,7 +515,10 b' Functions can also be pushed and pulled using ``push_function`` and ``pull_funct'
466 Dictionary interface
515 Dictionary interface
467 --------------------
516 --------------------
468
517
469 As a shorthand to ``push`` and ``pull``, the ``MultiEngineClient`` class implements some of the Python dictionary interface. This make the remote namespaces of the engines appear as a local dictionary. Underneath, this uses ``push`` and ``pull``::
518 As a shorthand to :meth:`push` and :meth:`pull`, the
519 :class:`MultiEngineClient` class implements some of the Python dictionary
520 interface. This make the remote namespaces of the engines appear as a local
521 dictionary. Underneath, this uses :meth:`push` and :meth:`pull`::
470
522
471 In [50]: mec.block=True
523 In [50]: mec.block=True
472
524
@@ -478,11 +530,13 b' As a shorthand to ``push`` and ``pull``, the ``MultiEngineClient`` class impleme'
478 Scatter and gather
530 Scatter and gather
479 ------------------
531 ------------------
480
532
481 Sometimes it is useful to partition a sequence and push the partitions to different engines. In
533 Sometimes it is useful to partition a sequence and push the partitions to
482 MPI language, this is know as scatter/gather and we follow that terminology. However, it is
534 different engines. In MPI language, this is know as scatter/gather and we
483 important to remember that in IPython ``scatter`` is from the interactive IPython session to
535 follow that terminology. However, it is important to remember that in
484 the engines and ``gather`` is from the engines back to the interactive IPython session. For
536 IPython's :class:`MultiEngineClient` class, :meth:`scatter` is from the
485 scatter/gather operations between engines, MPI should be used::
537 interactive IPython session to the engines and :meth:`gather` is from the
538 engines back to the interactive IPython session. For scatter/gather operations
539 between engines, MPI should be used::
486
540
487 In [58]: mec.scatter('a',range(16))
541 In [58]: mec.scatter('a',range(16))
488 Out[58]: [None, None, None, None]
542 Out[58]: [None, None, None, None]
@@ -510,24 +564,12 b' scatter/gather operations between engines, MPI should be used::'
510 Other things to look at
564 Other things to look at
511 =======================
565 =======================
512
566
513 Parallel map
514 ------------
515
516 Python's builtin ``map`` functions allows a function to be applied to a sequence element-by-element. This type of code is typically trivial to parallelize. In fact, the MultiEngine interface in IPython already has a parallel version of ``map`` that works just like its serial counterpart::
517
518 In [63]: serial_result = map(lambda x:x**10, range(32))
519
520 In [64]: parallel_result = mec.map(lambda x:x**10, range(32))
521
522 In [65]: serial_result==parallel_result
523 Out[65]: True
524
525 As you would expect, the parallel version of ``map`` is also influenced by the ``block`` and ``targets`` keyword arguments and attributes.
526
527 How to do parallel list comprehensions
567 How to do parallel list comprehensions
528 --------------------------------------
568 --------------------------------------
529
569
530 In many cases list comprehensions are nicer than using the map function. While we don't have fully parallel list comprehensions, it is simple to get the basic effect using ``scatter`` and ``gather``::
570 In many cases list comprehensions are nicer than using the map function. While
571 we don't have fully parallel list comprehensions, it is simple to get the
572 basic effect using :meth:`scatter` and :meth:`gather`::
531
573
532 In [66]: mec.scatter('x',range(64))
574 In [66]: mec.scatter('x',range(64))
533 Out[66]: [None, None, None, None]
575 Out[66]: [None, None, None, None]
@@ -547,10 +589,16 b' In many cases list comprehensions are nicer than using the map function. While '
547 In [69]: print y
589 In [69]: print y
548 [0, 1, 1024, 59049, 1048576, 9765625, 60466176, 282475249, 1073741824,...]
590 [0, 1, 1024, 59049, 1048576, 9765625, 60466176, 282475249, 1073741824,...]
549
591
550 Parallel Exceptions
592 Parallel exceptions
551 -------------------
593 -------------------
552
594
553 In the MultiEngine interface, parallel commands can raise Python exceptions, just like serial commands. But, it is a little subtle, because a single parallel command can actually raise multiple exceptions (one for each engine the command was run on). To express this idea, the MultiEngine interface has a ``CompositeError`` exception class that will be raised in most cases. The ``CompositeError`` class is a special type of exception that wraps one or more other types of exceptions. Here is how it works::
595 In the multiengine interface, parallel commands can raise Python exceptions,
596 just like serial commands. But, it is a little subtle, because a single
597 parallel command can actually raise multiple exceptions (one for each engine
598 the command was run on). To express this idea, the MultiEngine interface has a
599 :exc:`CompositeError` exception class that will be raised in most cases. The
600 :exc:`CompositeError` class is a special type of exception that wraps one or
601 more other types of exceptions. Here is how it works::
554
602
555 In [76]: mec.block=True
603 In [76]: mec.block=True
556
604
@@ -580,7 +628,7 b' In the MultiEngine interface, parallel commands can raise Python exceptions, jus'
580 [2:execute]: ZeroDivisionError: integer division or modulo by zero
628 [2:execute]: ZeroDivisionError: integer division or modulo by zero
581 [3:execute]: ZeroDivisionError: integer division or modulo by zero
629 [3:execute]: ZeroDivisionError: integer division or modulo by zero
582
630
583 Notice how the error message printed when ``CompositeError`` is raised has information about the individual exceptions that were raised on each engine. If you want, you can even raise one of these original exceptions::
631 Notice how the error message printed when :exc:`CompositeError` is raised has information about the individual exceptions that were raised on each engine. If you want, you can even raise one of these original exceptions::
584
632
585 In [80]: try:
633 In [80]: try:
586 ....: mec.execute('1/0')
634 ....: mec.execute('1/0')
@@ -602,7 +650,9 b' Notice how the error message printed when ``CompositeError`` is raised has infor'
602
650
603 ZeroDivisionError: integer division or modulo by zero
651 ZeroDivisionError: integer division or modulo by zero
604
652
605 If you are working in IPython, you can simple type ``%debug`` after one of these ``CompositeError`` is raised, and inspect the exception instance::
653 If you are working in IPython, you can simple type ``%debug`` after one of
654 these :exc:`CompositeError` exceptions is raised, and inspect the exception
655 instance::
606
656
607 In [81]: mec.execute('1/0')
657 In [81]: mec.execute('1/0')
608 ---------------------------------------------------------------------------
658 ---------------------------------------------------------------------------
@@ -679,6 +729,11 b' If you are working in IPython, you can simple type ``%debug`` after one of these'
679
729
680 ZeroDivisionError: integer division or modulo by zero
730 ZeroDivisionError: integer division or modulo by zero
681
731
732 .. note::
733
734 The above example appears to be broken right now because of a change in
735 how we are using Twisted.
736
682 All of this same error handling magic even works in non-blocking mode::
737 All of this same error handling magic even works in non-blocking mode::
683
738
684 In [83]: mec.block=False
739 In [83]: mec.block=False
@@ -1,240 +1,93 b''
1 .. _paralleltask:
1 .. _paralleltask:
2
2
3 =================================
3 ==========================
4 The IPython Task interface
4 The IPython task interface
5 =================================
5 ==========================
6
6
7 .. contents::
7 .. contents::
8
8
9 The ``Task`` interface to the controller presents the engines as a fault tolerant, dynamic load-balanced system or workers. Unlike the ``MultiEngine`` interface, in the ``Task`` interface, the user have no direct access to individual engines. In some ways, this interface is simpler, but in other ways it is more powerful. Best of all the user can use both of these interfaces at the same time to take advantage or both of their strengths. When the user can break up the user's work into segments that do not depend on previous execution, the ``Task`` interface is ideal. But it also has more power and flexibility, allowing the user to guide the distribution of jobs, without having to assign Tasks to engines explicitly.
9 The task interface to the controller presents the engines as a fault tolerant, dynamic load-balanced system or workers. Unlike the multiengine interface, in the task interface, the user have no direct access to individual engines. In some ways, this interface is simpler, but in other ways it is more powerful.
10
11 Best of all the user can use both of these interfaces running at the same time to take advantage or both of their strengths. When the user can break up the user's work into segments that do not depend on previous execution, the task interface is ideal. But it also has more power and flexibility, allowing the user to guide the distribution of jobs, without having to assign tasks to engines explicitly.
10
12
11 Starting the IPython controller and engines
13 Starting the IPython controller and engines
12 ===========================================
14 ===========================================
13
15
14 To follow along with this tutorial, the user will need to start the IPython
16 To follow along with this tutorial, you will need to start the IPython
15 controller and four IPython engines. The simplest way of doing this is to
17 controller and four IPython engines. The simplest way of doing this is to use
16 use the ``ipcluster`` command::
18 the :command:`ipcluster` command::
17
19
18 $ ipcluster -n 4
20 $ ipcluster -n 4
19
21
20 For more detailed information about starting the controller and engines, see our :ref:`introduction <ip1par>` to using IPython for parallel computing.
22 For more detailed information about starting the controller and engines, see
23 our :ref:`introduction <ip1par>` to using IPython for parallel computing.
24
25 Creating a ``TaskClient`` instance
26 =========================================
27
28 The first step is to import the IPython :mod:`IPython.kernel.client` module
29 and then create a :class:`TaskClient` instance::
30
31 In [1]: from IPython.kernel import client
32
33 In [2]: tc = client.TaskClient()
34
35 This form assumes that the :file:`ipcontroller-tc.furl` is in the
36 :file:`~./ipython/security` directory on the client's host. If not, the
37 location of the ``.furl`` file must be given as an argument to the
38 constructor::
39
40 In[2]: mec = client.TaskClient('/path/to/my/ipcontroller-tc.furl')
41
42 Quick and easy parallelism
43 ==========================
44
45 In many cases, you simply want to apply a Python function to a sequence of objects, but *in parallel*. Like the multiengine interface, the task interface provides two simple ways of accomplishing this: a parallel version of :func:`map` and ``@parallel`` function decorator. However, the verions in the task interface have one important difference: they are dynamically load balanced. Thus, if the execution time per item varies significantly, you should use the versions in the task interface.
46
47 Parallel map
48 ------------
49
50 The parallel :meth:`map` in the task interface is similar to that in the multiengine interface::
51
52 In [63]: serial_result = map(lambda x:x**10, range(32))
53
54 In [64]: parallel_result = tc.map(lambda x:x**10, range(32))
55
56 In [65]: serial_result==parallel_result
57 Out[65]: True
58
59 Parallel function decorator
60 ---------------------------
61
62 Parallel functions are just like normal function, but they can be called on sequences and *in parallel*. The multiengine interface provides a decorator that turns any Python function into a parallel function::
21
63
22 The magic here is that this single controller and set of engines is running both the MultiEngine and ``Task`` interfaces simultaneously.
64 In [10]: @tc.parallel()
65 ....: def f(x):
66 ....: return 10.0*x**4
67 ....:
23
68
24 QuickStart Task Farming
69 In [11]: f(range(32)) # this is done in parallel
25 =======================
70 Out[11]:
71 [0.0,10.0,160.0,...]
26
72
27 First, a quick example of how to start running the most basic Tasks.
73 More details
28 The first step is to import the IPython ``client`` module and then create a ``TaskClient`` instance::
74 ============
29
30 In [1]: from IPython.kernel import client
31
32 In [2]: tc = client.TaskClient()
33
75
34 Then the user wrap the commands the user want to run in Tasks::
76 The :class:`TaskClient` has many more powerful features that allow quite a bit of flexibility in how tasks are defined and run. The next places to look are in the following classes:
35
77
36 In [3]: tasklist = []
78 * :class:`IPython.kernel.client.TaskClient`
37 In [4]: for n in range(1000):
79 * :class:`IPython.kernel.client.StringTask`
38 ... tasklist.append(client.Task("a = %i"%n, pull="a"))
80 * :class:`IPython.kernel.client.MapTask`
39
81
40 The first argument of the ``Task`` constructor is a string, the command to be executed. The most important optional keyword argument is ``pull``, which can be a string or list of strings, and it specifies the variable names to be saved as results of the ``Task``.
82 The following is an overview of how to use these classes together:
41
83
42 Next, the user need to submit the Tasks to the ``TaskController`` with the ``TaskClient``::
84 1. Create a :class:`TaskClient`.
85 2. Create one or more instances of :class:`StringTask` or :class:`MapTask`
86 to define your tasks.
87 3. Submit your tasks to using the :meth:`run` method of your
88 :class:`TaskClient` instance.
89 4. Use :meth:`TaskClient.get_task_result` to get the results of the
90 tasks.
43
91
44 In [5]: taskids = [ tc.run(t) for t in tasklist ]
92 We are in the process of developing more detailed information about the task interface. For now, the docstrings of the :class:`TaskClient`, :class:`StringTask` and :class:`MapTask` classes should be consulted.
45
93
46 This will give the user a list of the TaskIDs used by the controller to keep track of the Tasks and their results. Now at some point the user are going to want to get those results back. The ``barrier`` method allows the user to wait for the Tasks to finish running::
47
48 In [6]: tc.barrier(taskids)
49
50 This command will block until all the Tasks in ``taskids`` have finished. Now, the user probably want to look at the user's results::
51
52 In [7]: task_results = [ tc.get_task_result(taskid) for taskid in taskids ]
53
54 Now the user have a list of ``TaskResult`` objects, which have the actual result as a dictionary, but also keep track of some useful metadata about the ``Task``::
55
56 In [8]: tr = ``Task``_results[73]
57
58 In [9]: tr
59 Out[9]: ``TaskResult``[ID:73]:{'a':73}
60
61 In [10]: tr.engineid
62 Out[10]: 1
63
64 In [11]: tr.submitted, tr.completed, tr.duration
65 Out[11]: ("2008/03/08 03:41:42", "2008/03/08 03:41:44", 2.12345)
66
67 The actual results are stored in a dictionary, ``tr.results``, and a namespace object ``tr.ns`` which accesses the result keys by attribute::
68
69 In [12]: tr.results['a']
70 Out[12]: 73
71
72 In [13]: tr.ns.a
73 Out[13]: 73
74
75 That should cover the basics of running simple Tasks. There are several more powerful things the user can do with Tasks covered later. The most useful probably being using a ``MutiEngineClient`` interface to initialize all the engines with the import dependencies necessary to run the user's Tasks.
76
77 There are many options for running and managing Tasks. The best way to learn further about the ``Task`` interface is to study the examples in ``docs/examples``. If the user do so and learn a lots about this interface, we encourage the user to expand this documentation about the ``Task`` system.
78
79 Overview of the Task System
80 ===========================
81
82 The user's view of the ``Task`` system has three basic objects: The ``TaskClient``, the ``Task``, and the ``TaskResult``. The names of these three objects well indicate their role.
83
84 The ``TaskClient`` is the user's ``Task`` farming connection to the IPython cluster. Unlike the ``MultiEngineClient``, the ``TaskControler`` handles all the scheduling and distribution of work, so the ``TaskClient`` has no notion of engines, it just submits Tasks and requests their results. The Tasks are described as ``Task`` objects, and their results are wrapped in ``TaskResult`` objects. Thus, there are very few necessary methods for the user to manage.
85
86 Inside the task system is a Scheduler object, which assigns tasks to workers. The default scheduler is a simple FIFO queue. Subclassing the Scheduler should be easy, just implementing your own priority system.
87
88 The TaskClient
89 ==============
90
91 The ``TaskClient`` is the object the user use to connect to the ``Controller`` that is managing the user's Tasks. It is the analog of the ``MultiEngineClient`` for the standard IPython multiplexing interface. As with all client interfaces, the first step is to import the IPython Client Module::
92
93 In [1]: from IPython.kernel import client
94
95 Just as with the ``MultiEngineClient``, the user create the ``TaskClient`` with a tuple, containing the ip-address and port of the ``Controller``. the ``client`` module conveniently has the default address of the ``Task`` interface of the controller. Creating a default ``TaskClient`` object would be done with this::
96
97 In [2]: tc = client.TaskClient(client.default_task_address)
98
99 or, if the user want to specify a non default location of the ``Controller``, the user can specify explicitly::
100
101 In [3]: tc = client.TaskClient(("192.168.1.1", 10113))
102
103 As discussed earlier, the ``TaskClient`` only has a few basic methods.
104
105 * ``tc.run(task)``
106 ``run`` is the method by which the user submits Tasks. It takes exactly one argument, a ``Task`` object. All the advanced control of ``Task`` behavior is handled by properties of the ``Task`` object, rather than the submission command, so they will be discussed later in the `Task`_ section. ``run`` returns an integer, the ``Task``ID by which the ``Task`` and its results can be tracked and retrieved::
107
108 In [4]: ``Task``ID = tc.run(``Task``)
109
110 * ``tc.get_task_result(taskid, block=``False``)``
111 ``get_task_result`` is the method by which results are retrieved. It takes a single integer argument, the ``Task``ID`` of the result the user wish to retrieve. ``get_task_result`` also takes a keyword argument ``block``. ``block`` specifies whether the user actually want to wait for the result. If ``block`` is false, as it is by default, ``get_task_result`` will return immediately. If the ``Task`` has completed, it will return the ``TaskResult`` object for that ``Task``. But if the ``Task`` has not completed, it will return ``None``. If the user specify ``block=``True``, then ``get_task_result`` will wait for the ``Task`` to complete, and always return the ``TaskResult`` for the requested ``Task``.
112 * ``tc.barrier(taskid(s))``
113 ``barrier`` is a synchronization method. It takes exactly one argument, a ``Task``ID or list of taskIDs. ``barrier`` will block until all the specified Tasks have completed. In practice, a barrier is often called between the ``Task`` submission section of the code and the result gathering section::
114
115 In [5]: taskIDs = [ tc.run(``Task``) for ``Task`` in myTasks ]
116
117 In [6]: tc.get_task_result(taskIDs[-1]) is None
118 Out[6]: ``True``
119
120 In [7]: tc.barrier(``Task``ID)
121
122 In [8]: results = [ tc.get_task_result(tid) for tid in taskIDs ]
123
124 * ``tc.queue_status(verbose=``False``)``
125 ``queue_status`` is a method for querying the state of the ``TaskControler``. ``queue_status`` returns a dict of the form::
126
127 {'scheduled': Tasks that have been submitted but yet run
128 'pending' : Tasks that are currently running
129 'succeeded': Tasks that have completed successfully
130 'failed' : Tasks that have finished with a failure
131 }
132
133 if @verbose is not specified (or is ``False``), then the values of the dict are integers - the number of Tasks in each state. if @verbose is ``True``, then each element in the dict is a list of the taskIDs in that state::
134
135 In [8]: tc.queue_status()
136 Out[8]: {'scheduled': 4,
137 'pending' : 2,
138 'succeeded': 5,
139 'failed' : 1
140 }
141
142 In [9]: tc.queue_status(verbose=True)
143 Out[9]: {'scheduled': [8,9,10,11],
144 'pending' : [6,7],
145 'succeeded': [0,1,2,4,5],
146 'failed' : [3]
147 }
148
149 * ``tc.abort(taskid)``
150 ``abort`` allows the user to abort Tasks that have already been submitted. ``abort`` will always return immediately. If the ``Task`` has completed, ``abort`` will raise an ``IndexError ``Task`` Already Completed``. An obvious case for ``abort`` would be where the user submits a long-running ``Task`` with a number of retries (see ``Task``_ section for how to specify retries) in an interactive session, but realizes there has been a typo. The user can then abort the ``Task``, preventing certain failures from cluttering up the queue. It can also be used for parallel search-type problems, where only one ``Task`` will give the solution, so once the user find the solution, the user would want to abort all remaining Tasks to prevent wasted work.
151 * ``tc.spin()``
152 ``spin`` simply triggers the scheduler in the ``TaskControler``. Under most normal circumstances, this will do nothing. The primary known usage case involves the ``Task`` dependency (see `Dependencies`_). The dependency is a function of an Engine's ``properties``, but changing the ``properties`` via the ``MutliEngineClient`` does not trigger a reschedule event. The main example case for this requires the following event sequence:
153 * ``engine`` is available, ``Task`` is submitted, but ``engine`` does not have ``Task``'s dependencies.
154 * ``engine`` gets necessary dependencies while no new Tasks are submitted or completed.
155 * now ``engine`` can run ``Task``, but a ``Task`` event is required for the ``TaskControler`` to try scheduling ``Task`` again.
156
157 ``spin`` is just an empty ping method to ensure that the Controller has scheduled all available Tasks, and should not be needed under most normal circumstances.
158
159 That covers the ``TaskClient``, a simple interface to the cluster. With this, the user can submit jobs (and abort if necessary), request their results, synchronize on arbitrary subsets of jobs.
160
161 .. _task: The Task Object
162
163 The Task Object
164 ===============
165
166 The ``Task`` is the basic object for describing a job. It can be used in a very simple manner, where the user just specifies a command string to be executed as the ``Task``. The usage of this first argument is exactly the same as the ``execute`` method of the ``MultiEngine`` (in fact, ``execute`` is called to run the code)::
167
168 In [1]: t = client.Task("a = str(id)")
169
170 This ``Task`` would run, and store the string representation of the ``id`` element in ``a`` in each worker's namespace, but it is fairly useless because the user does not know anything about the state of the ``worker`` on which it ran at the time of retrieving results. It is important that each ``Task`` not expect the state of the ``worker`` to persist after the ``Task`` is completed.
171 There are many different situations for using ``Task`` Farming, and the ``Task`` object has many attributes for use in customizing the ``Task`` behavior. All of a ``Task``'s attributes may be specified in the constructor, through keyword arguments, or after ``Task`` construction through attribute assignment.
172
173 Data Attributes
174 ***************
175 It is likely that the user may want to move data around before or after executing the ``Task``. We provide methods of sending data to initialize the worker's namespace, and specifying what data to bring back as the ``Task``'s results.
176
177 * pull = []
178 The obvious case is as above, where ``t`` would execute and store the result of ``myfunc`` in ``a``, it is likely that the user would want to bring ``a`` back to their namespace. This is done through the ``pull`` attribute. ``pull`` can be a string or list of strings, and it specifies the names of variables to be retrieved. The ``TaskResult`` object retrieved by ``get_task_result`` will have a dictionary of keys and values, and the ``Task``'s ``pull`` attribute determines what goes into it::
179
180 In [2]: t = client.Task("a = str(id)", pull = "a")
181
182 In [3]: t = client.Task("a = str(id)", pull = ["a", "id"])
183
184 * push = {}
185 A user might also want to initialize some data into the namespace before the code part of the ``Task`` is run. Enter ``push``. ``push`` is a dictionary of key/value pairs to be loaded from the user's namespace into the worker's immediately before execution::
186
187 In [4]: t = client.Task("a = f(submitted)", push=dict(submitted=time.time()), pull="a")
188
189 push and pull result directly in calling an ``engine``'s ``push`` and ``pull`` methods before and after ``Task`` execution respectively, and thus their api is the same.
190
191 Namespace Cleaning
192 ******************
193 When a user is running a large number of Tasks, it is likely that the namespace of the worker's could become cluttered. Some Tasks might be sensitive to clutter, while others might be known to cause namespace pollution. For these reasons, Tasks have two boolean attributes for cleaning up the namespace.
194
195 * ``clear_after``
196 if clear_after is specified ``True``, the worker on which the ``Task`` was run will be reset (via ``engine.reset``) upon completion of the ``Task``. This can be useful for both Tasks that produce clutter or Tasks whose intermediate data one might wish to be kept private::
197
198 In [5]: t = client.Task("a = range(1e10)", pull = "a",clear_after=True)
199
200
201 * ``clear_before``
202 as one might guess, clear_before is identical to ``clear_after``, but it takes place before the ``Task`` is run. This ensures that the ``Task`` runs on a fresh worker::
203
204 In [6]: t = client.Task("a = globals()", pull = "a",clear_before=True)
205
206 Of course, a user can both at the same time, ensuring that all workers are clear except when they are currently running a job. Both of these default to ``False``.
207
208 Fault Tolerance
209 ***************
210 It is possible that Tasks might fail, and there are a variety of reasons this could happen. One might be that the worker it was running on disconnected, and there was nothing wrong with the ``Task`` itself. With the fault tolerance attributes of the ``Task``, the user can specify how many times to resubmit the ``Task``, and what to do if it never succeeds.
211
212 * ``retries``
213 ``retries`` is an integer, specifying the number of times a ``Task`` is to be retried. It defaults to zero. It is often a good idea for this number to be 1 or 2, to protect the ``Task`` from disconnecting engines, but not a large number. If a ``Task`` is failing 100 times, there is probably something wrong with the ``Task``. The canonical bad example:
214
215 In [7]: t = client.Task("os.kill(os.getpid(), 9)", retries=99)
216
217 This would actually take down 100 workers.
218
219 * ``recovery_task``
220 ``recovery_task`` is another ``Task`` object, to be run in the event of the original ``Task`` still failing after running out of retries. Since ``recovery_task`` is another ``Task`` object, it can have its own ``recovery_task``. The chain of Tasks is limitless, except loops are not allowed (that would be bad!).
221
222 Dependencies
223 ************
224 Dependencies are the most powerful part of the ``Task`` farming system, because it allows the user to do some classification of the workers, and guide the ``Task`` distribution without meddling with the controller directly. It makes use of two objects - the ``Task``'s ``depend`` attribute, and the engine's ``properties``. See the `MultiEngine`_ reference for how to use engine properties. The engine properties api exists for extending IPython, allowing conditional execution and new controllers that make decisions based on properties of its engines. Currently the ``Task`` dependency is the only internal use of the properties api.
225
226 .. _MultiEngine: ./parallel_multiengine
227
228 The ``depend`` attribute of a ``Task`` must be a function of exactly one argument, the worker's properties dictionary, and it should return ``True`` if the ``Task`` should be allowed to run on the worker and ``False`` if not. The usage in the controller is fault tolerant, so exceptions raised by ``Task.depend`` will be ignored and functionally equivalent to always returning ``False``. Tasks`` with invalid ``depend`` functions will never be assigned to a worker::
229
230 In [8]: def dep(properties):
231 ... return properties["RAM"] > 2**32 # have at least 4GB
232 In [9]: t = client.Task("a = bigfunc()", depend=dep)
233
234 It is important to note that assignment of values to the properties dict is done entirely by the user, either locally (in the engine) using the EngineAPI, or remotely, through the ``MultiEngineClient``'s get/set_properties methods.
235
236
237
238
239
240
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
@@ -2,6 +2,7 b''
2 """Windows-specific part of the installation"""
2 """Windows-specific part of the installation"""
3
3
4 import os, sys, shutil
4 import os, sys, shutil
5 pjoin = os.path.join
5
6
6 def mkshortcut(target,description,link_file,*args,**kw):
7 def mkshortcut(target,description,link_file,*args,**kw):
7 """make a shortcut if it doesn't exist, and register its creation"""
8 """make a shortcut if it doesn't exist, and register its creation"""
@@ -11,69 +12,85 b' def mkshortcut(target,description,link_file,*args,**kw):'
11
12
12 def install():
13 def install():
13 """Routine to be run by the win32 installer with the -install switch."""
14 """Routine to be run by the win32 installer with the -install switch."""
14
15
15 from IPython.Release import version
16 from IPython.Release import version
16
17
17 # Get some system constants
18 # Get some system constants
18 prefix = sys.prefix
19 prefix = sys.prefix
19 python = prefix + r'\python.exe'
20 python = pjoin(prefix, 'python.exe')
20 # Lookup path to common startmenu ...
21 ip_dir = get_special_folder_path('CSIDL_COMMON_PROGRAMS') + r'\IPython'
22
21
23 # Some usability warnings at installation time. I don't want them at the
22 # Lookup path to common startmenu ...
24 # top-level, so they don't appear if the user is uninstalling.
23 ip_start_menu = pjoin(get_special_folder_path('CSIDL_COMMON_PROGRAMS'), 'IPython')
25 try:
26 import ctypes
27 except ImportError:
28 print ('To take full advantage of IPython, you need ctypes from:\n'
29 'http://sourceforge.net/projects/ctypes')
30
31 try:
32 import win32con
33 except ImportError:
34 print ('To take full advantage of IPython, you need pywin32 from:\n'
35 'http://starship.python.net/crew/mhammond/win32/Downloads.html')
36
37 try:
38 import readline
39 except ImportError:
40 print ('To take full advantage of IPython, you need readline from:\n'
41 'https://launchpad.net/pyreadline')
42
43 ipybase = '"' + prefix + r'\scripts\ipython"'
44 # Create IPython entry ...
24 # Create IPython entry ...
45 if not os.path.isdir(ip_dir):
25 if not os.path.isdir(ip_start_menu):
46 os.mkdir(ip_dir)
26 os.mkdir(ip_start_menu)
47 directory_created(ip_dir)
27 directory_created(ip_start_menu)
48
28
49 # Create program shortcuts ...
29 # Create .py and .bat files to make things available from
50 f = ip_dir + r'\IPython.lnk'
30 # the Windows command line. Thanks to the Twisted project
51 a = ipybase
31 # for this logic!
52 mkshortcut(python,'IPython',f,a)
32 programs = [
53
33 'ipython',
54 f = ip_dir + r'\pysh.lnk'
34 'iptest',
55 a = ipybase+' -p sh'
35 'ipcontroller',
56 mkshortcut(python,'IPython (command prompt mode)',f,a)
36 'ipengine',
57
37 'ipcluster',
58 f = ip_dir + r'\pylab.lnk'
38 'ipythonx',
59 a = ipybase+' -pylab'
39 'ipython-wx',
60 mkshortcut(python,'IPython (PyLab mode)',f,a)
40 'irunner'
61
41 ]
62 f = ip_dir + r'\scipy.lnk'
42 scripts = pjoin(prefix,'scripts')
63 a = ipybase+' -pylab -p scipy'
43 for program in programs:
64 mkshortcut(python,'IPython (scipy profile)',f,a)
44 raw = pjoin(scripts, program)
65
45 bat = raw + '.bat'
46 py = raw + '.py'
47 # Create .py versions of the scripts
48 shutil.copy(raw, py)
49 # Create .bat files for each of the scripts
50 bat_file = file(bat,'w')
51 bat_file.write("@%s %s %%*" % (python, py))
52 bat_file.close()
53
54 # Now move onto setting the Start Menu up
55 ipybase = pjoin(scripts, 'ipython')
56
57 link = pjoin(ip_start_menu, 'IPython.lnk')
58 cmd = '"%s"' % ipybase
59 mkshortcut(python,'IPython',link,cmd)
60
61 link = pjoin(ip_start_menu, 'pysh.lnk')
62 cmd = '"%s" -p sh' % ipybase
63 mkshortcut(python,'IPython (command prompt mode)',link,cmd)
64
65 link = pjoin(ip_start_menu, 'pylab.lnk')
66 cmd = '"%s" -pylab' % ipybase
67 mkshortcut(python,'IPython (PyLab mode)',link,cmd)
68
69 link = pjoin(ip_start_menu, 'scipy.lnk')
70 cmd = '"%s" -pylab -p scipy' % ipybase
71 mkshortcut(python,'IPython (scipy profile)',link,cmd)
72
73 link = pjoin(ip_start_menu, 'IPython test suite.lnk')
74 cmd = '"%s" -vv' % pjoin(scripts, 'iptest')
75 mkshortcut(python,'Run the IPython test suite',link,cmd)
76
77 link = pjoin(ip_start_menu, 'ipcontroller.lnk')
78 cmd = '"%s" -xy' % pjoin(scripts, 'ipcontroller')
79 mkshortcut(python,'IPython controller',link,cmd)
80
81 link = pjoin(ip_start_menu, 'ipengine.lnk')
82 cmd = '"%s"' % pjoin(scripts, 'ipengine')
83 mkshortcut(python,'IPython engine',link,cmd)
84
66 # Create documentation shortcuts ...
85 # Create documentation shortcuts ...
67 t = prefix + r'\share\doc\ipython\manual\ipython.pdf'
86 t = prefix + r'\share\doc\ipython\manual\ipython.pdf'
68 f = ip_dir + r'\Manual in PDF.lnk'
87 f = ip_start_menu + r'\Manual in PDF.lnk'
69 mkshortcut(t,r'IPython Manual - PDF-Format',f)
88 mkshortcut(t,r'IPython Manual - PDF-Format',f)
70
89
71 t = prefix + r'\share\doc\ipython\manual\html\index.html'
90 t = prefix + r'\share\doc\ipython\manual\html\index.html'
72 f = ip_dir + r'\Manual in HTML.lnk'
91 f = ip_start_menu + r'\Manual in HTML.lnk'
73 mkshortcut(t,'IPython Manual - HTML-Format',f)
92 mkshortcut(t,'IPython Manual - HTML-Format',f)
74
93
75 # make ipython.py
76 shutil.copy(prefix + r'\scripts\ipython', prefix + r'\scripts\ipython.py')
77
94
78 def remove():
95 def remove():
79 """Routine to be run by the win32 installer with the -remove switch."""
96 """Routine to be run by the win32 installer with the -remove switch."""
@@ -115,6 +115,7 b' def find_packages():'
115 add_package(packages, 'kernel', config=True, tests=True, scripts=True)
115 add_package(packages, 'kernel', config=True, tests=True, scripts=True)
116 add_package(packages, 'kernel.core', config=True, tests=True)
116 add_package(packages, 'kernel.core', config=True, tests=True)
117 add_package(packages, 'testing', tests=True)
117 add_package(packages, 'testing', tests=True)
118 add_package(packages, 'tests')
118 add_package(packages, 'testing.plugin', tests=False)
119 add_package(packages, 'testing.plugin', tests=False)
119 add_package(packages, 'tools', tests=True)
120 add_package(packages, 'tools', tests=True)
120 add_package(packages, 'UserConfig')
121 add_package(packages, 'UserConfig')
@@ -1,14 +1,8 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """Wrapper to run setup.py using setuptools."""
2 """Wrapper to run setup.py using setuptools."""
3
3
4 import os
5 import sys
4 import sys
6
5
7 # Add my local path to sys.path
8 home = os.environ['HOME']
9 sys.path.insert(0,'%s/usr/local/lib/python%s/site-packages' %
10 (home,sys.version[:3]))
11
12 # now, import setuptools and call the actual setup
6 # now, import setuptools and call the actual setup
13 import setuptools
7 import setuptools
14 # print sys.argv
8 # print sys.argv
@@ -10,17 +10,15 b' echo'
10 echo "Releasing IPython version $version"
10 echo "Releasing IPython version $version"
11 echo "=================================="
11 echo "=================================="
12
12
13 echo "Marking ChangeLog with release information and making NEWS file..."
14
15 # Clean up build/dist directories
16 rm -rf $ipdir/build/*
17 rm -rf $ipdir/dist/*
18
19 # Perform local backup
13 # Perform local backup
20 cd $ipdir/tools
14 cd $ipdir/tools
21 ./make_tarball.py
15 ./make_tarball.py
22 mv ipython-*.tgz $ipbackupdir
16 mv ipython-*.tgz $ipbackupdir
23
17
18 # Clean up build/dist directories
19 rm -rf $ipdir/build/*
20 rm -rf $ipdir/dist/*
21
24 # Build source and binary distros
22 # Build source and binary distros
25 cd $ipdir
23 cd $ipdir
26 ./setup.py sdist --formats=gztar
24 ./setup.py sdist --formats=gztar
@@ -28,8 +26,8 b' cd $ipdir'
28 # Build version-specific RPMs, where we must use the --python option to ensure
26 # Build version-specific RPMs, where we must use the --python option to ensure
29 # that the resulting RPM is really built with the requested python version (so
27 # that the resulting RPM is really built with the requested python version (so
30 # things go to lib/python2.X/...)
28 # things go to lib/python2.X/...)
31 python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4
29 #python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4
32 python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5
30 #python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5
33
31
34 # Build eggs
32 # Build eggs
35 python2.4 ./setup_bdist_egg.py
33 python2.4 ./setup_bdist_egg.py
@@ -15,8 +15,8 b' cd $ipdir'
15 ./setup.py sdist --formats=gztar
15 ./setup.py sdist --formats=gztar
16
16
17 # Build rpms
17 # Build rpms
18 #python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4
18 python2.4 ./setup.py bdist_rpm --binary-only --release=py24 --python=/usr/bin/python2.4
19 #python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5
19 python2.5 ./setup.py bdist_rpm --binary-only --release=py25 --python=/usr/bin/python2.5
20
20
21 # Build eggs
21 # Build eggs
22 python2.4 ./setup_bdist_egg.py
22 python2.4 ./setup_bdist_egg.py
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
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