Merge lp:~ellisonbg/ipython/bugfixes0411409 into lp:ipython/0.11

Proposed by Brian Granger
Status: Merged
Merged at revision: not available
Proposed branch: lp:~ellisonbg/ipython/bugfixes0411409
Merge into: lp:ipython/0.11
Diff against target: None lines
To merge this branch: bzr merge lp:~ellisonbg/ipython/bugfixes0411409
Reviewer Review Type Date Requested Status
Fernando Perez Needs Fixing
Review via email: mp+5716@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Brian Granger (ellisonbg) wrote :

This has a number of bug fixes that are targeted for the 0.10 release. Many of the bug fixes are trivial, but a few are quite subtle and need to be carefully reviewed.

1176. By Brian Granger

Adding test_twistedutil.py.

1177. By Brian Granger

Merged Gael's ipython-sync-frontend branch with important mods.

This branch showed conflicts with recent changes I made to:

IPython.kernel.core.interpreter
IPython.kernel.core.tests.test_interpreter

I resolved these conflicts and closed a ticket that Gael fixed in his
branch. BUT, there is a related ticket that I opened. Furthermore,
Gael was using nose in test_interpreter, but we need to keep things in
IPython.kernel free of nose!

1178. By Brian Granger

Merging in Jorgen's changes to iplib.py for ticket 315392.

1179. By Brian Granger

Closing invalid ticket 364347.

This ticket is invalid (thanks to R. Kern) and I have changed the test
to test the correct thing.

1180. By Brian Granger

Initial refactor of task dependency system.

We are thinking about refactoring the task dependency system. Currently
is is based on engine properties and a function sent with each task.

In this commit, I have added a TaskRejectError that tasks can raise to
indicate that the engine doesn't have the required dependencies. For
now I have not removed any of the old stuff, but I have added warnings
that we might remove the older *_prop* methods in IMultiEngine.

See this ticket for more info: https://bugs.launchpad.net/bugs/361419

Revision history for this message
Fernando Perez (fdo.perez) wrote :

Not done with the review yet, but in the meantime, please merge the fixes I put in:

https://code.launchpad.net/~fdo.perez/ipython/brian-bugfixes

This fixes one of the broken tests. There's another one that I don't know how to fix, so I'll mention that in the actual review.

Revision history for this message
Fernando Perez (fdo.perez) wrote :

- The cocoa tests currently fail if I try to run the suite with Trial, because they use the nose skiptest form. I'm not sure if trial has a way to spell that out. After merging my fix (see previous comment) I get with

trial IPython

...

===============================================================================
[ERROR]: IPython.frontend.cocoa.tests.test_cocoa_frontend

Traceback (most recent call last):
  File "/usr/lib/python2.5/site-packages/twisted/trial/runner.py", line 547, in loadPackage
    module = modinfo.load()
  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 380, in load
    return self.pathEntry.pythonPath.moduleLoader(self.name)
  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 618, in moduleLoader
    return self._moduleLoader(modname)
  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 426, in namedAny
    topLevelPackage = _importAndCheckStack(trialname)
  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 377, in _importAndCheckStack
    return __import__(importName)
  File "/home/fperez/usr/lib/python2.5/site-packages/IPython/frontend/cocoa/tests/test_cocoa_frontend.py", line 28, in <module>
    raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
nose.plugins.skip.SkipTest: This test requires zope.interface, Twisted, Foolscap and PyObjC
-------------------------------------------------------------------------------
Ran 387 tests in 40.094s

FAILED (errors=1, successes=387)

Since it seems we'll be moving towards using trial for the twisted-using parts, I guess we'll need to mark these skips in a trial-compliant way, but I don't know if twisted has support for that out of the box. You may know...

More to come...

review: Needs Fixing
Revision history for this message
Brian Granger (ellisonbg) wrote :

I don't see any commits to your branch, should there be any?

On Tue, Apr 21, 2009 at 11:07 PM, Fernando Perez <email address hidden> wrote:
> Not done with the review yet, but in the meantime, please merge the fixes I put in:
>
> https://code.launchpad.net/~fdo.perez/ipython/brian-bugfixes
>
> This fixes one of the broken tests.  There's another one that I don't know how to fix, so I'll mention that in the actual review.
> --
> https://code.launchpad.net/~ellisonbg/ipython/bugfixes0411409/+merge/5716
> You are subscribed to branch lp:ipython.
>

--
Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
<email address hidden>
<email address hidden>

Revision history for this message
Brian Granger (ellisonbg) wrote :

Yes, I think there is a way of getting twisted to skip tests, I will
look into this.

Brian

On Tue, Apr 21, 2009 at 11:11 PM, Fernando Perez <email address hidden> wrote:
> Review: Needs Fixing
> - The cocoa tests currently fail if I try to run the suite with Trial, because they use the nose skiptest form.  I'm not sure if trial has a way to spell that  out.  After merging my fix (see previous comment) I get with
>
> trial IPython
>
> ...
>
> ===============================================================================
> [ERROR]: IPython.frontend.cocoa.tests.test_cocoa_frontend
>
> Traceback (most recent call last):
>  File "/usr/lib/python2.5/site-packages/twisted/trial/runner.py", line 547, in loadPackage
>    module = modinfo.load()
>  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 380, in load
>    return self.pathEntry.pythonPath.moduleLoader(self.name)
>  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 618, in moduleLoader
>    return self._moduleLoader(modname)
>  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 426, in namedAny
>    topLevelPackage = _importAndCheckStack(trialname)
>  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 377, in _importAndCheckStack
>    return __import__(importName)
>  File "/home/fperez/usr/lib/python2.5/site-packages/IPython/frontend/cocoa/tests/test_cocoa_frontend.py", line 28, in <module>
>    raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
> nose.plugins.skip.SkipTest: This test requires zope.interface, Twisted, Foolscap and PyObjC
> -------------------------------------------------------------------------------
> Ran 387 tests in 40.094s
>
> FAILED (errors=1, successes=387)
>
>
> Since it seems we'll be moving towards using trial for the twisted-using parts, I guess we'll need to mark these skips in a trial-compliant way,  but I don't know if twisted has support for that out of the box.  You may know...
>
> More to come...
> --
> https://code.launchpad.net/~ellisonbg/ipython/bugfixes0411409/+merge/5716
> You are subscribed to branch lp:ipython.
>

--
Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
<email address hidden>
<email address hidden>

Revision history for this message
Fernando Perez (fdo.perez) wrote :

- ultraTB problems: I'm OK with the fixes in place now, I made a ticket:

  https://bugs.launchpad.net/ipython/+bug/364994

  so we fix this the right way once we're done with 0.10.

  Please just make 'XXX' marks in those __IPYTHON__ sections so they stand out when I search for problems in the merge.

- in ipcluster.py, rather than
428 +from IPython.genutils import get_ipython_dir, get_log_dir, get_security_dir
429 +from IPython.genutils import num_cpus

I'd just use

 +from IPython.genutils import ( get_ipython_dir, get_log_dir, get_security_dir,
 + num_cpus )

since now python allows that syntax (as of 2.4).

- We probably should refactor the entire ipython directory tree creation into a single get_ipython_dirs() function that makes them all and returns a dict. But that can be done later, just an idea for now...

- No docstrings in _err_and_stop and _delay_start. Even if they are private, they should have a docstring so others (like me :) actually know what they are meant to do. For private functions like this a more terse docstring is OK, but at least it should be enough so anyone reading the code has some idea of what's going on.

- In ipcontroller:

589 import sys, time, os
590 +import tempfile

I think we're now using the style of one import per line, sorted alphabetically. This makes it also easier to spot unneded imports via pyflakes and remove them by just nuking the line.

- In the docs:
930 +This is possible. but before you do this, you **must** remove any old FURL

should read:
930 +This is possible, but before you do this, you **must** remove any old FURL

- Overall, the changes look great. Once these minor things are fixed, and the Cocoa/trial skip problem referred in my previous message is addressed, as well as merging that fix I made for test_iplib, this has my approval.

Thanks a lot for all this work, it's excellent and gets us much closer to 0.10!

review: Needs Fixing
Revision history for this message
Fernando Perez (fdo.perez) wrote :

> I don't see any commits to your branch, should there be any?

Oops, forgot to push. There now:

http://bazaar.launchpad.net/~fdo.perez/ipython/brian-bugfixes/revision/1181

Sorry 'bout that :)

f

Revision history for this message
Vishal Vatsa (vvatsa) wrote :

I downloaded and ran trial also, I have one other test failure:

[ERROR]: IPython.tests.test_iplib

Traceback (most recent call last):
  File "/usr/lib/python2.5/site-packages/twisted/trial/runner.py", line 547, in loadPackage
    module = modinfo.load()
  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 380, in load
    return self.pathEntry.pythonPath.moduleLoader(self.name)
  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 618, in moduleLoader
    return self._moduleLoader(modname)
  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 426, in namedAny
    topLevelPackage = _importAndCheckStack(trialname)
  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 377, in _importAndCheckStack
    return __import__(importName)
  File "/home/vva/src/tmp/for_review/IPython/tests/test_iplib.py", line 31, in <module>
    ip = _ip # This is the ipapi instance
exceptions.NameError: name '_ip' is not defined

=======================================================================================
Did you guys also get this?

Revision history for this message
Vishal Vatsa (vvatsa) wrote :

Hey,

Another thing, I see that you are removing the --ipythondir option,
since it did not work any way thats fine.
But could we make the IPYTHONDIR environmental var. more obvious in the docs.

-v

Revision history for this message
Brian Granger (ellisonbg) wrote :

Thanks for the review. I will fix all these things and merge in the
next few hours.

On Tue, Apr 21, 2009 at 11:35 PM, Fernando Perez <email address hidden> wrote:
> Review: Needs Fixing
> - ultraTB problems: I'm OK with the fixes in place now, I made a ticket:
>
>  https://bugs.launchpad.net/ipython/+bug/364994
>
>  so we fix this the right way once we're done with 0.10.
>
>  Please just make 'XXX' marks in those __IPYTHON__ sections so they stand out when I search for problems in the merge.
>
> - in ipcluster.py, rather than
> 428     +from IPython.genutils import get_ipython_dir, get_log_dir, get_security_dir
> 429     +from IPython.genutils import num_cpus
>
> I'd just use
>
>        +from IPython.genutils import ( get_ipython_dir, get_log_dir, get_security_dir,
>        +                               num_cpus )
>
> since now python allows that syntax (as of 2.4).
>
>
> - We probably should refactor the entire ipython directory tree creation into a single get_ipython_dirs() function that makes them all and returns a dict.  But that can be done later, just an idea for now...
>
>
> - No docstrings in _err_and_stop and _delay_start.  Even if they are private, they should have a docstring so others (like me :) actually know what they are meant to do.  For private functions like this a more terse docstring is OK, but at least it should be enough so anyone reading the code has some idea of what's going on.
>
>
> - In ipcontroller:
>
> 589      import sys, time, os
> 590     +import tempfile
>
> I think we're now using the style of one import per line, sorted alphabetically.  This makes it also easier to spot unneded imports via pyflakes and remove them by just nuking the line.
>
>
> - In the docs:
> 930     +This is possible. but before you do this, you **must** remove any old FURL
>
> should read:
> 930     +This is possible, but before you do this, you **must** remove any old FURL
>
>
> - Overall, the changes look great.  Once these minor things are fixed, and the Cocoa/trial skip problem referred in my previous message is addressed, as well as merging that fix I made for test_iplib, this has my approval.
>
>
> Thanks a lot for all this work, it's excellent and gets us much closer to 0.10!
> --
> https://code.launchpad.net/~ellisonbg/ipython/bugfixes0411409/+merge/5716
> You are subscribed to branch lp:ipython.
>

--
Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
<email address hidden>
<email address hidden>

Revision history for this message
Brian Granger (ellisonbg) wrote :

This fails because this test needs to be run using nosetests rather
than trial. We are still trying to figure out the best way of running
the test suite, but for now, just do:

trial IPython.kernel

Fernando and I are putting some flags in place that will make all of
this work better though. This should be in place by the end of the
day today.

Cheers,

Brian

On Wed, Apr 22, 2009 at 2:08 AM, Vishal Vatsa <email address hidden> wrote:
> I downloaded and ran trial also, I have one other test failure:
>
> [ERROR]: IPython.tests.test_iplib
>
> Traceback (most recent call last):
>  File "/usr/lib/python2.5/site-packages/twisted/trial/runner.py", line 547, in loadPackage
>    module = modinfo.load()
>  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 380, in load
>    return self.pathEntry.pythonPath.moduleLoader(self.name)
>  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 618, in moduleLoader
>    return self._moduleLoader(modname)
>  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 426, in namedAny
>    topLevelPackage = _importAndCheckStack(trialname)
>  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 377, in _importAndCheckStack
>    return __import__(importName)
>  File "/home/vva/src/tmp/for_review/IPython/tests/test_iplib.py", line 31, in <module>
>    ip = _ip    # This is the ipapi instance
> exceptions.NameError: name '_ip' is not defined
>
> =======================================================================================
> Did you guys also get this?
> --
> https://code.launchpad.net/~ellisonbg/ipython/bugfixes0411409/+merge/5716
> You are subscribed to branch lp:ipython.
>

--
Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
<email address hidden>
<email address hidden>

Revision history for this message
Fernando Perez (fdo.perez) wrote :

On Wed, Apr 22, 2009 at 2:08 AM, Vishal Vatsa <email address hidden> wrote:
> I downloaded and ran trial also, I have one other test failure:
>
> [ERROR]: IPython.tests.test_iplib

> Did you guys also get this?

Yes, but there's a fix for it in my copy of Brian's branch that he can
pull in before merging, so this one will be fine. The one about nose
vs trial will take a little more work, but we should have it sorted
out later.

Thanks!

f

1181. By Brian Granger

Merging Fernando's fixes to test_iplib.py.

Revision history for this message
Brian Granger (ellisonbg) wrote :
Download full text (3.3 KiB)

In trial, any module, TestCase or TestCase method that has a skip
attribute=True will be skipped. However, we need to think more
carefully about exactly what logic needs to be in place in these
situations that takes into account all of the following:

* Is nose installed
* Is Twisted installed
* Is nose or trial running the test suite
* Are the other deps installed (PyObjC, Wx, etc.)

The current logic in our test files looks like this:

try:
    from IPython.kernel.core.interpreter import Interpreter
    import IPython.kernel.engineservice as es
    from IPython.testing.util import DeferredTestCase
    from twisted.internet.defer import succeed
    from IPython.frontend.cocoa.cocoa_frontend import
IPythonCocoaController
    from Foundation import NSMakeRect
    from AppKit import NSTextView, NSScrollView
except ImportError:
    import nose
    raise nose.SkipTest("This test requires zope.interface, Twisted,
Foolscap and PyObjC")

Is simply not sufficient to properly handle all the various
possibilities. We need to think more carefully about the logic that
is needed. Honestly, I have a feeling that we are simply going to get
rid off all this logic and put it into our test runner.

On Tue, Apr 21, 2009 at 11:11 PM, Fernando Perez <email address hidden> wrote:
> Review: Needs Fixing
> - The cocoa tests currently fail if I try to run the suite with Trial, because they use the nose skiptest form.  I'm not sure if trial has a way to spell that  out.  After merging my fix (see previous comment) I get with
>
> trial IPython
>
> ...
>
> ===============================================================================
> [ERROR]: IPython.frontend.cocoa.tests.test_cocoa_frontend
>
> Traceback (most recent call last):
>  File "/usr/lib/python2.5/site-packages/twisted/trial/runner.py", line 547, in loadPackage
>    module = modinfo.load()
>  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 380, in load
>    return self.pathEntry.pythonPath.moduleLoader(self.name)
>  File "/usr/lib/python2.5/site-packages/twisted/python/modules.py", line 618, in moduleLoader
>    return self._moduleLoader(modname)
>  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 426, in namedAny
>    topLevelPackage = _importAndCheckStack(trialname)
>  File "/usr/lib/python2.5/site-packages/twisted/python/reflect.py", line 377, in _importAndCheckStack
>    return __import__(importName)
>  File "/home/fperez/usr/lib/python2.5/site-packages/IPython/frontend/cocoa/tests/test_cocoa_frontend.py", line 28, in <module>
>    raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
> nose.plugins.skip.SkipTest: This test requires zope.interface, Twisted, Foolscap and PyObjC
> -------------------------------------------------------------------------------
> Ran 387 tests in 40.094s
>
> FAILED (errors=1, successes=387)
>
>
> Since it seems we'll be moving towards using trial for the twisted-using parts, I guess we'll need to mark these skips in a trial-compliant way,  but I don't know if twisted has support for that out of the box.  You may know...
>
> More to come...
> --
> https://code.launchpad.net/~ellisonbg/ipython...

Read more...

1182. By Brian Granger

Addressing various review comments.

1183. By Brian Granger

Adding information about IPYTHONDIR to usage of ipcluster and friends.

1184. By Brian Granger

Fixing misc testing related things.

1185. By Brian Granger

Commiting fixes for running our test suite using trial and nose.

We are moving towards a model that allows trial and nose to each run
different parts of our test suite. I have added __test__ = {} to
modules that nose should skip. I have added new decorators that trial
can use to skip tests. See this ticket for more information:

https://bugs.launchpad.net/bugs/362142

1186. By Brian Granger

Fix for ticket https://bugs.launchpad.net/bugs/362458

Python 2.4 does not support a try/finally with a yield in the try. I
have changed this to a try with an empty except, followed by the
statement that was in the finally.

1187. By Brian Granger

Merging fixes from Fernando's branch.

1188. By Brian Granger

Refactored iptest to include the iptestall capabilities.

We not have a test suite that can be run with `iptest all`. Give it a
shot!

1189. By Brian Granger

Merging Fernando's fixes from his trunk-dev and fixing testing things.

I have merged his changes with a few modifications. I have also
removed IPython.kernel from the list of packages that nose will test.

1190. By Brian Granger

Run the top level module tests in a single process.

1191. By Brian Granger

Moving find_exe -> platutils.find_cmd and making is cross platform.

The find_cmd function used to be in ipcluster.py to find executables
on win32. We need this on all platforms and now we have it!

1192. By Brian Granger

Adding test_platutils.py.

1193. By Administrator <Administrator@brian-cda46cdbf>

Adding new tests for test_magic for win32.

1194. By Brian Granger

Fixing ticket https://bugs.launchpad.net/bugs/366334

Now we find ipython using platutils.find_cmd

1195. By Brian Granger

Making the doctest exclude paths os independent.

1196. By Administrator <Administrator@brian-cda46cdbf>

Fixing doctest EXCLUDES in iptest on win32.

The regular expressions we were using on win32 were not matching. The
trick is to construct the regular expression with double \\ like this::

    re.compile('foo\\\\bar')

Arggg!!

1197. By Administrator <Administrator@brian-cda46cdbf>

Fixing bugs with the testing system.

1198. By Brian Granger

Fixing tests in IPython.testing.

1199. By Brian Granger

Adding test_tools.py

1200. By Administrator <Administrator@brian-cda46cdbf>

More fixes for testing on win32.

1201. By Administrator <Administrator@brian-cda46cdbf>

Added platutils.get_long_path_name to expand paths with "~" on win32.

This might be needed to fix ticket https://bugs.launchpad.net/bugs/366353
But, there are still problems with Magic.parse_options

1202. By Administrator <Administrator@brian-cda46cdbf>

Merging changes from above.

1203. By Administrator <Administrator@brian-cda46cdbf>

Changing comment in test_magic to reflect bug status.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'IPython/frontend/tests/test_asyncfrontendbase.py'
--- IPython/frontend/tests/test_asyncfrontendbase.py 2008-09-14 22:13:51 +0000
+++ IPython/frontend/tests/test_asyncfrontendbase.py 2009-04-16 05:08:03 +0000
@@ -1,6 +1,6 @@
1# encoding: utf-81# encoding: utf-8
22
3"""This file contains unittests for the frontendbase module."""3"""This file contains unittests for the asyncfrontendbase module."""
44
5__docformat__ = "restructuredtext en"5__docformat__ = "restructuredtext en"
66
@@ -15,17 +15,17 @@
15# Imports 15# Imports
16#---------------------------------------------------------------------------16#---------------------------------------------------------------------------
1717
18import unittest
1918
20try:19try:
20 from twisted.trial import unittest
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase 22 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService23 from IPython.kernel.engineservice import EngineService
24 from IPython.testing.parametric import Parametric, parametric
24except ImportError:25except ImportError:
25 import nose26 import nose
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")27 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
2728
28from IPython.testing.decorators import skip
2929
30class FrontEndCallbackChecker(AsyncFrontEndBase):30class FrontEndCallbackChecker(AsyncFrontEndBase):
31 """FrontEndBase subclass for checking callbacks"""31 """FrontEndBase subclass for checking callbacks"""
@@ -44,14 +44,11 @@
44 self.renderResultCalled = True44 self.renderResultCalled = True
45 return result45 return result
46 46
47
48 def render_error(self, failure):47 def render_error(self, failure):
49 self.renderErrorCalled = True48 self.renderErrorCalled = True
50 return failure49 return failure
51 50
5251
53
54
55class TestAsyncFrontendBase(unittest.TestCase):52class TestAsyncFrontendBase(unittest.TestCase):
56 def setUp(self):53 def setUp(self):
57 """Setup the EngineService and FrontEndBase"""54 """Setup the EngineService and FrontEndBase"""
@@ -59,97 +56,56 @@
59 self.fb = FrontEndCallbackChecker(engine=EngineService())56 self.fb = FrontEndCallbackChecker(engine=EngineService())
60 57
61 def test_implements_IFrontEnd(self):58 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(59 self.assert_(frontendbase.IFrontEnd.implementedBy(
63 AsyncFrontEndBase))60 AsyncFrontEndBase))
64 61
65 def test_is_complete_returns_False_for_incomplete_block(self):62 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 block = """def test(a):"""63 block = """def test(a):"""
69 64 self.assert_(self.fb.is_complete(block) == False)
70 assert(self.fb.is_complete(block) == False)
71 65
72 def test_is_complete_returns_True_for_complete_block(self):66 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 block = """def test(a): pass"""67 block = """def test(a): pass"""
76 68 self.assert_(self.fb.is_complete(block))
77 assert(self.fb.is_complete(block))
78
79 block = """a=3"""69 block = """a=3"""
80 70 self.assert_(self.fb.is_complete(block))
81 assert(self.fb.is_complete(block))
82 71
83 def test_blockID_added_to_result(self):72 def test_blockID_added_to_result(self):
84 block = """3+3"""73 block = """3+3"""
85
86 d = self.fb.execute(block, blockID='TEST_ID')74 d = self.fb.execute(block, blockID='TEST_ID')
87 75 d.addCallback(lambda r: self.assert_(r['blockID']=='TEST_ID'))
88 d.addCallback(self.checkBlockID, expected='TEST_ID')76 return d
89 77
90 def test_blockID_added_to_failure(self):78 def test_blockID_added_to_failure(self):
91 block = "raise Exception()"79 block = "raise Exception()"
92
93 d = self.fb.execute(block,blockID='TEST_ID')80 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')81 d.addErrback(lambda f: self.assert_(f.blockID=='TEST_ID'))
95 82 return d
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 83
104 def test_callbacks_added_to_execute(self):84 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")85 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)86 d.addCallback(lambda r: self.assert_(self.fb.updateCalled and self.fb.renderResultCalled))
114 87 return d
115 def checkCallbacks(self, result):88
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):89 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""90 """Test that render_error called on execution error."""
122 91
123 d = self.fb.execute("raise Exception()")92 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)93 d.addErrback(lambda f: self.assert_(self.fb.renderErrorCalled))
125 94 return d
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
128 95
129 def test_history_returns_expected_block(self):96 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""97 """Make sure history browsing doesn't fail."""
131 98
132 blocks = ["a=1","a=2","a=3"]99 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:100 d = self.fb.execute(blocks[0])
134 d = self.fb.execute(b)101 d.addCallback(lambda _: self.fb.execute(blocks[1]))
135 102 d.addCallback(lambda _: self.fb.execute(blocks[2]))
136 # d is now the deferred for the last executed block103 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-2]))
137 d.addCallback(self.historyTests, blocks)104 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-3]))
138 105 d.addCallback(lambda _: self.assert_(self.fb.get_history_next()==blocks[-2]))
139 106 return d
140 def historyTests(self, result, blocks):107
141 """historyTests"""108 def test_history_returns_none_at_startup(self):
142 109 self.assert_(self.fb.get_history_previous("")==None)
143 assert(len(blocks) >= 3)110 self.assert_(self.fb.get_history_next()==None)
144 assert(self.fb.get_history_previous("") == blocks[-2])111
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
156112
=== modified file 'IPython/genutils.py'
--- IPython/genutils.py 2009-03-16 23:58:42 +0000
+++ IPython/genutils.py 2009-04-18 23:24:22 +0000
@@ -1007,7 +1007,17 @@
1007 else:1007 else:
1008 os.chmod(security_dir, 0700)1008 os.chmod(security_dir, 0700)
1009 return security_dir1009 return security_dir
1010 1010
1011def get_log_dir():
1012 """Get the IPython log directory.
1013
1014 If the log directory does not exist, it is created.
1015 """
1016 log_dir = os.path.join(get_ipython_dir(), 'log')
1017 if not os.path.isdir(log_dir):
1018 os.mkdir(log_dir, 0777)
1019 return log_dir
1020
1011#****************************************************************************1021#****************************************************************************
1012# strings and text1022# strings and text
10131023
10141024
=== modified file 'IPython/kernel/__init__.py'
--- IPython/kernel/__init__.py 2008-06-08 22:25:02 +0000
+++ IPython/kernel/__init__.py 2009-04-18 23:24:22 +0000
@@ -15,10 +15,9 @@
15deferred/Twisted using clients.15deferred/Twisted using clients.
16"""16"""
17__docformat__ = "restructuredtext en"17__docformat__ = "restructuredtext en"
18#-------------------------------------------------------------------------------18#-----------------------------------------------------------------------------
19# Copyright (C) 2008 The IPython Development Team19# Copyright (C) 2008 The IPython Development Team
20#20#
21# Distributed under the terms of the BSD License. The full license is in21# Distributed under the terms of the BSD License. The full license is in
22# the file COPYING, distributed as part of this software.22# the file COPYING, distributed as part of this software.
23#-------------------------------------------------------------------------------
24
25\ No newline at end of file23\ No newline at end of file
24#-----------------------------------------------------------------------------
26\ No newline at end of file25\ No newline at end of file
2726
=== modified file 'IPython/kernel/config/__init__.py'
--- IPython/kernel/config/__init__.py 2008-11-14 23:27:13 +0000
+++ IPython/kernel/config/__init__.py 2009-04-18 23:24:22 +0000
@@ -15,6 +15,7 @@
15# Imports15# Imports
16#-------------------------------------------------------------------------------16#-------------------------------------------------------------------------------
1717
18import os, sys
18from os.path import join as pjoin19from os.path import join as pjoin
1920
20from IPython.external.configobj import ConfigObj21from IPython.external.configobj import ConfigObj
@@ -23,6 +24,7 @@
2324
24default_kernel_config = ConfigObj()25default_kernel_config = ConfigObj()
2526
27# This will raise OSError if ipythondir doesn't exist.
26security_dir = get_security_dir()28security_dir = get_security_dir()
2729
28#-------------------------------------------------------------------------------30#-------------------------------------------------------------------------------
2931
=== modified file 'IPython/kernel/core/interpreter.py'
--- IPython/kernel/core/interpreter.py 2008-09-06 02:26:28 +0000
+++ IPython/kernel/core/interpreter.py 2009-04-19 00:13:57 +0000
@@ -679,21 +679,22 @@
679 # to exec will fail however. There seems to be some inconsistency in679 # to exec will fail however. There seems to be some inconsistency in
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()
682682
683 # The compiler module does not like unicode. We need to convert683 # The compiler module does not like unicode. We need to convert
684 # it encode it:684 # it encode it:
685 if isinstance(python, unicode):685 if isinstance(python, unicode):
686 # Use the utf-8-sig BOM so the compiler detects this a UTF-8686 # Use the utf-8-sig BOM so the compiler detects this a UTF-8
687 # encode string.687 # encode string.
688 python = '\xef\xbb\xbf' + python.encode('utf-8')688 python = '\xef\xbb\xbf' + python.encode('utf-8')
689689
690 # 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.
691 # This has a bug with str("a\nb"), but not str("""a\nb""")!!!
691 ast = compiler.parse(python)692 ast = compiler.parse(python)
692693
693 # Uncomment to help debug the ast tree694 # Uncomment to help debug the ast tree
694 # for n in ast.node:695 # for n in ast.node:
695 # print n.lineno,'->',n696 # print n.lineno,'->',n
696 697
697 # Each separate command is available by iterating over ast.node. The698 # Each separate command is available by iterating over ast.node. The
698 # lineno attribute is the line number (1-indexed) beginning the commands699 # lineno attribute is the line number (1-indexed) beginning the commands
699 # suite.700 # suite.
@@ -703,20 +704,23 @@
703 # We might eventually discover other cases where lineno is None and have704 # We might eventually discover other cases where lineno is None and have
704 # to put in a more sophisticated test.705 # to put in a more sophisticated test.
705 linenos = [x.lineno-1 for x in ast.node if x.lineno is not None]706 linenos = [x.lineno-1 for x in ast.node if x.lineno is not None]
706707
707 # When we finally get the slices, we will need to slice all the way to708 # When we finally get the slices, we will need to slice all the way to
708 # the end even though we don't have a line number for it. Fortunately,709 # the end even though we don't have a line number for it. Fortunately,
709 # None does the job nicely.710 # None does the job nicely.
710 linenos.append(None)711 linenos.append(None)
712
713 # This is causing problems with commands that have a \n embedded in
714 # a string, such as str("""a\nb""")
711 lines = python.splitlines()715 lines = python.splitlines()
712716
713 # Create a list of atomic commands.717 # Create a list of atomic commands.
714 cmds = []718 cmds = []
715 for i, j in zip(linenos[:-1], linenos[1:]):719 for i, j in zip(linenos[:-1], linenos[1:]):
716 cmd = lines[i:j]720 cmd = lines[i:j]
717 if cmd:721 if cmd:
718 cmds.append('\n'.join(cmd)+'\n')722 cmds.append('\n'.join(cmd)+'\n')
719723
720 return cmds724 return cmds
721725
722 def error(self, text):726 def error(self, text):
723727
=== modified file 'IPython/kernel/core/tests/test_interpreter.py'
--- IPython/kernel/core/tests/test_interpreter.py 2008-09-06 03:26:50 +0000
+++ IPython/kernel/core/tests/test_interpreter.py 2009-04-19 00:13:57 +0000
@@ -15,12 +15,22 @@
15# Imports 15# Imports
16#-----------------------------------------------------------------------------16#-----------------------------------------------------------------------------
1717
18import unittest
18from IPython.kernel.core.interpreter import Interpreter19from IPython.kernel.core.interpreter import Interpreter
1920
20def test_unicode():21class TestInterpreter(unittest.TestCase):
21 """ Test unicode handling with the interpreter.22
22 """23 def test_unicode(self):
23 i = Interpreter()24 """ Test unicode handling with the interpreter.
24 i.execute_python(u'print "ù"')25 """
25 i.execute_python('print "ù"')26 i = Interpreter()
27 i.execute_python(u'print "ù"')
28 i.execute_python('print "ù"')
29
30 def test_ticket266993_1(self):
31 i = Interpreter()
32 i.execute('str("""a\nb""")')
2633
34 def test_ticket266993_2(self):
35 i = Interpreter()
36 i.execute('str("a\nb")')
27\ No newline at end of file37\ No newline at end of file
2838
=== modified file 'IPython/kernel/core/ultraTB.py'
--- IPython/kernel/core/ultraTB.py 2009-03-11 06:53:19 +0000
+++ IPython/kernel/core/ultraTB.py 2009-04-16 05:22:09 +0000
@@ -487,10 +487,14 @@
487 else:487 else:
488 list.append('%s\n' % str(stype))488 list.append('%s\n' % str(stype))
489489
490 # vds:>>490 # This is being commented out for now as the __IPYTHON__ variable
491 if have_filedata:491 # referenced here is not resolved and causes massive test failures
492 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)492 # and errors. B. Granger, 04/2009.
493 # vds:<<493 # See https://bugs.launchpad.net/bugs/362137
494 # # vds:>>
495 # if have_filedata:
496 # __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
497 # # vds:<<
494498
495 return list499 return list
496500
@@ -804,13 +808,17 @@
804 value = text_repr(getattr(evalue, name))808 value = text_repr(getattr(evalue, name))
805 exception.append('\n%s%s = %s' % (indent, name, value))809 exception.append('\n%s%s = %s' % (indent, name, value))
806810
807 # vds: >>811 # This is being commented out for now as the __IPYTHON__ variable
808 if records:812 # referenced here is not resolved and causes massive test failures
809 filepath, lnum = records[-1][1:3]813 # and errors. B. Granger, 04/2009.
810 #print "file:", str(file), "linenb", str(lnum) # dbg814 # See https://bugs.launchpad.net/bugs/362137
811 filepath = os.path.abspath(filepath)815 # # vds: >>
812 __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)816 # if records:
813 # vds: <<817 # filepath, lnum = records[-1][1:3]
818 # #print "file:", str(file), "linenb", str(lnum) # dbg
819 # filepath = os.path.abspath(filepath)
820 # __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
821 # # vds: <<
814 822
815 # return all our info assembled as a single string823 # return all our info assembled as a single string
816 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )824 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
817825
=== modified file 'IPython/kernel/engineconnector.py'
--- IPython/kernel/engineconnector.py 2008-11-14 23:27:13 +0000
+++ IPython/kernel/engineconnector.py 2009-04-18 21:53:37 +0000
@@ -67,10 +67,10 @@
67 self.furl = find_furl(furl_or_file)67 self.furl = find_furl(furl_or_file)
68 except ValueError:68 except ValueError:
69 return defer.fail(failure.Failure())69 return defer.fail(failure.Failure())
70 # return defer.fail(failure.Failure(ValueError('not a valid furl or furl file: %r' % furl_or_file)))70 else:
71 d = self.tub.getReference(self.furl)71 d = self.tub.getReference(self.furl)
72 d.addCallbacks(self._register, self._log_failure)72 d.addCallbacks(self._register, self._log_failure)
73 return d73 return d
74 74
75 def _log_failure(self, reason):75 def _log_failure(self, reason):
76 log.err('EngineConnector: engine registration failed:')76 log.err('EngineConnector: engine registration failed:')
7777
=== modified file 'IPython/kernel/error.py'
--- IPython/kernel/error.py 2008-06-06 19:41:55 +0000
+++ IPython/kernel/error.py 2009-04-18 21:53:37 +0000
@@ -104,6 +104,9 @@
104class SecurityError(KernelError):104class SecurityError(KernelError):
105 pass105 pass
106106
107class FileTimeoutError(KernelError):
108 pass
109
107class CompositeError(KernelError):110class CompositeError(KernelError):
108 def __init__(self, message, elist):111 def __init__(self, message, elist):
109 Exception.__init__(self, *(message, elist))112 Exception.__init__(self, *(message, elist))
110113
=== modified file 'IPython/kernel/scripts/ipcluster.py'
--- IPython/kernel/scripts/ipcluster.py 2009-03-23 15:54:00 +0000
+++ IPython/kernel/scripts/ipcluster.py 2009-04-18 23:24:22 +0000
@@ -1,4 +1,4 @@
1#!/usr/bin/env python1 #!/usr/bin/env python
2# encoding: utf-82# encoding: utf-8
33
4"""Start an IPython cluster = (controller + engines)."""4"""Start an IPython cluster = (controller + engines)."""
@@ -29,11 +29,25 @@
2929
30from IPython.external import argparse30from IPython.external import argparse
31from IPython.external import Itpl31from IPython.external import Itpl
32from IPython.genutils import get_ipython_dir, num_cpus32from IPython.genutils import get_ipython_dir, get_log_dir, get_security_dir
33from IPython.kernel.fcutil import have_crypto33from IPython.genutils import num_cpus
34from IPython.kernel.error import SecurityError34from IPython.kernel.fcutil import have_crypto
35from IPython.kernel.fcutil import have_crypto35
36from IPython.kernel.twistedutil import gatherBoth36# Create various ipython directories if they don't exist.
37# This must be done before IPython.kernel.config is imported.
38from IPython.iplib import user_setup
39if os.name == 'posix':
40 rc_suffix = ''
41else:
42 rc_suffix = '.ini'
43user_setup(get_ipython_dir(), rc_suffix, mode='install', interactive=False)
44get_log_dir()
45get_security_dir()
46
47from IPython.kernel.config import config_manager as kernel_config_manager
48from IPython.kernel.error import SecurityError, FileTimeoutError
49from IPython.kernel.fcutil import have_crypto
50from IPython.kernel.twistedutil import gatherBoth, wait_for_file
37from IPython.kernel.util import printer51from IPython.kernel.util import printer
3852
3953
@@ -184,8 +198,10 @@
184 from IPython.kernel.scripts import ipcontroller198 from IPython.kernel.scripts import ipcontroller
185 script_location = ipcontroller.__file__.replace('.pyc', '.py')199 script_location = ipcontroller.__file__.replace('.pyc', '.py')
186 # The -u option here turns on unbuffered output, which is required200 # The -u option here turns on unbuffered output, which is required
187 # on Win32 to prevent wierd conflict and problems with Twisted201 # on Win32 to prevent wierd conflict and problems with Twisted.
188 args = [find_exe('python'), '-u', script_location]202 # Also, use sys.executable to make sure we are picking up the
203 # right python exe.
204 args = [sys.executable, '-u', script_location]
189 else:205 else:
190 args = ['ipcontroller']206 args = ['ipcontroller']
191 self.extra_args = extra_args207 self.extra_args = extra_args
@@ -204,8 +220,10 @@
204 from IPython.kernel.scripts import ipengine220 from IPython.kernel.scripts import ipengine
205 script_location = ipengine.__file__.replace('.pyc', '.py')221 script_location = ipengine.__file__.replace('.pyc', '.py')
206 # The -u option here turns on unbuffered output, which is required222 # The -u option here turns on unbuffered output, which is required
207 # on Win32 to prevent wierd conflict and problems with Twisted223 # on Win32 to prevent wierd conflict and problems with Twisted.
208 args = [find_exe('python'), '-u', script_location]224 # Also, use sys.executable to make sure we are picking up the
225 # right python exe.
226 args = [sys.executable, '-u', script_location]
209 else:227 else:
210 args = ['ipengine']228 args = ['ipengine']
211 self.extra_args = extra_args229 self.extra_args = extra_args
@@ -465,6 +483,7 @@
465# The main functions should then just parse the command line arguments, create483# The main functions should then just parse the command line arguments, create
466# the appropriate class and call a 'start' method.484# the appropriate class and call a 'start' method.
467485
486
468def check_security(args, cont_args):487def check_security(args, cont_args):
469 if (not args.x or not args.y) and not have_crypto:488 if (not args.x or not args.y) and not have_crypto:
470 log.err("""489 log.err("""
@@ -478,6 +497,7 @@
478 cont_args.append('-y')497 cont_args.append('-y')
479 return True498 return True
480499
500
481def check_reuse(args, cont_args):501def check_reuse(args, cont_args):
482 if args.r:502 if args.r:
483 cont_args.append('-r')503 cont_args.append('-r')
@@ -491,6 +511,23 @@
491 cont_args.append('--engine-port=%i' % args.engine_port)511 cont_args.append('--engine-port=%i' % args.engine_port)
492 return True512 return True
493513
514
515def _err_and_stop(f):
516 log.err(f)
517 reactor.stop()
518
519
520def _delay_start(cont_pid, start_engines, furl_file, reuse):
521 if not reuse:
522 if os.path.isfile(furl_file):
523 os.unlink(furl_file)
524 log.msg('Waiting for controller to finish starting...')
525 d = wait_for_file(furl_file, delay=0.2, max_tries=50)
526 d.addCallback(lambda _: log.msg('Controller started'))
527 d.addCallback(lambda _: start_engines(cont_pid))
528 return d
529
530
494def main_local(args):531def main_local(args):
495 cont_args = []532 cont_args = []
496 cont_args.append('--logfile=%s' % pjoin(args.logdir,'ipcontroller'))533 cont_args.append('--logfile=%s' % pjoin(args.logdir,'ipcontroller'))
@@ -520,13 +557,10 @@
520 signal.signal(signal.SIGINT,shutdown)557 signal.signal(signal.SIGINT,shutdown)
521 d = eset.start(args.n)558 d = eset.start(args.n)
522 return d559 return d
523 def delay_start(cont_pid):560 config = kernel_config_manager.get_config_obj()
524 # This is needed because the controller doesn't start listening561 furl_file = config['controller']['engine_furl_file']
525 # right when it starts and the controller needs to write562 dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
526 # furl files for the engine to pick up563 dstart.addErrback(_err_and_stop)
527 reactor.callLater(1.0, start_engines, cont_pid)
528 dstart.addCallback(delay_start)
529 dstart.addErrback(lambda f: f.raiseException())
530564
531565
532def main_mpi(args):566def main_mpi(args):
@@ -562,13 +596,10 @@
562 signal.signal(signal.SIGINT,shutdown)596 signal.signal(signal.SIGINT,shutdown)
563 d = eset.start()597 d = eset.start()
564 return d598 return d
565 def delay_start(cont_pid):599 config = kernel_config_manager.get_config_obj()
566 # This is needed because the controller doesn't start listening600 furl_file = config['controller']['engine_furl_file']
567 # right when it starts and the controller needs to write601 dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
568 # furl files for the engine to pick up602 dstart.addErrback(_err_and_stop)
569 reactor.callLater(1.0, start_engines, cont_pid)
570 dstart.addCallback(delay_start)
571 dstart.addErrback(lambda f: f.raiseException())
572603
573604
574def main_pbs(args):605def main_pbs(args):
@@ -595,8 +626,10 @@
595 signal.signal(signal.SIGINT,shutdown)626 signal.signal(signal.SIGINT,shutdown)
596 d = pbs_set.start(args.n)627 d = pbs_set.start(args.n)
597 return d628 return d
598 dstart.addCallback(start_engines)629 config = kernel_config_manager.get_config_obj()
599 dstart.addErrback(lambda f: f.raiseException())630 furl_file = config['controller']['engine_furl_file']
631 dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
632 dstart.addErrback(_err_and_stop)
600633
601634
602def main_ssh(args):635def main_ssh(args):
@@ -637,12 +670,10 @@
637 signal.signal(signal.SIGINT,shutdown)670 signal.signal(signal.SIGINT,shutdown)
638 d = ssh_set.start(clusterfile['send_furl'])671 d = ssh_set.start(clusterfile['send_furl'])
639 return d672 return d
640 673 config = kernel_config_manager.get_config_obj()
641 def delay_start(cont_pid):674 furl_file = config['controller']['engine_furl_file']
642 reactor.callLater(1.0, start_engines, cont_pid)675 dstart.addCallback(_delay_start, start_engines, furl_file, args.r)
643 676 dstart.addErrback(_err_and_stop)
644 dstart.addCallback(delay_start)
645 dstart.addErrback(lambda f: f.raiseException())
646677
647678
648def get_args():679def get_args():
649680
=== modified file 'IPython/kernel/scripts/ipcontroller.py'
--- IPython/kernel/scripts/ipcontroller.py 2009-03-15 01:38:00 +0000
+++ IPython/kernel/scripts/ipcontroller.py 2009-04-18 23:24:22 +0000
@@ -22,6 +22,7 @@
22sys.path.insert(0, '')22sys.path.insert(0, '')
2323
24import sys, time, os24import sys, time, os
25import tempfile
25from optparse import OptionParser26from optparse import OptionParser
2627
27from twisted.application import internet, service28from twisted.application import internet, service
@@ -37,6 +38,18 @@
37from IPython.kernel import controllerservice38from IPython.kernel import controllerservice
38from IPython.kernel.fcutil import check_furl_file_security39from IPython.kernel.fcutil import check_furl_file_security
3940
41# Create various ipython directories if they don't exist.
42# This must be done before IPython.kernel.config is imported.
43from IPython.iplib import user_setup
44from IPython.genutils import get_ipython_dir, get_log_dir, get_security_dir
45if os.name == 'posix':
46 rc_suffix = ''
47else:
48 rc_suffix = '.ini'
49user_setup(get_ipython_dir(), rc_suffix, mode='install', interactive=False)
50get_log_dir()
51get_security_dir()
52
40from IPython.kernel.config import config_manager as kernel_config_manager53from IPython.kernel.config import config_manager as kernel_config_manager
41from IPython.config.cutils import import_item54from IPython.config.cutils import import_item
4255
@@ -45,6 +58,10 @@
45# Code58# Code
46#-------------------------------------------------------------------------------59#-------------------------------------------------------------------------------
4760
61def get_temp_furlfile(filename):
62 return tempfile.mktemp(dir=os.path.dirname(filename),
63 prefix=os.path.basename(filename))
64
48def make_tub(ip, port, secure, cert_file):65def make_tub(ip, port, secure, cert_file):
49 """66 """
50 Create a listening tub given an ip, port, and cert_file location.67 Create a listening tub given an ip, port, and cert_file location.
@@ -107,13 +124,18 @@
107 """Set the location for the tub and return a deferred."""124 """Set the location for the tub and return a deferred."""
108125
109 def register(empty, ref, furl_file):126 def register(empty, ref, furl_file):
110 client_tub.registerReference(ref, furlFile=furl_file)127 # We create and then move to make sure that when the file
128 # appears to other processes, the buffer has the flushed
129 # and the file has been closed
130 temp_furl_file = get_temp_furlfile(furl_file)
131 client_tub.registerReference(ref, furlFile=temp_furl_file)
132 os.rename(temp_furl_file, furl_file)
111 133
112 if location == '':134 if location == '':
113 d = client_tub.setLocationAutomatically()135 d = client_tub.setLocationAutomatically()
114 else:136 else:
115 d = defer.maybeDeferred(client_tub.setLocation, "%s:%i" % (location, client_listener.getPortnum()))137 d = defer.maybeDeferred(client_tub.setLocation, "%s:%i" % (location, client_listener.getPortnum()))
116 138
117 for ciname, ci in config['controller']['controller_interfaces'].iteritems():139 for ciname, ci in config['controller']['controller_interfaces'].iteritems():
118 log.msg("Adapting Controller to interface: %s" % ciname)140 log.msg("Adapting Controller to interface: %s" % ciname)
119 furl_file = ci['furl_file']141 furl_file = ci['furl_file']
@@ -154,7 +176,12 @@
154 """Set the location for the tub and return a deferred."""176 """Set the location for the tub and return a deferred."""
155177
156 def register(empty, ref, furl_file):178 def register(empty, ref, furl_file):
157 engine_tub.registerReference(ref, furlFile=furl_file)179 # We create and then move to make sure that when the file
180 # appears to other processes, the buffer has the flushed
181 # and the file has been closed
182 temp_furl_file = get_temp_furlfile(furl_file)
183 engine_tub.registerReference(ref, furlFile=temp_furl_file)
184 os.rename(temp_furl_file, furl_file)
158 185
159 if location == '':186 if location == '':
160 d = engine_tub.setLocationAutomatically()187 d = engine_tub.setLocationAutomatically()
@@ -325,12 +352,6 @@
325 help="log file name (default is stdout)"352 help="log file name (default is stdout)"
326 )353 )
327 parser.add_option(354 parser.add_option(
328 "--ipythondir",
329 type="string",
330 dest="ipythondir",
331 help="look for config files and profiles in this directory"
332 )
333 parser.add_option(
334 "-r",355 "-r",
335 action="store_true",356 action="store_true",
336 dest="reuse_furls",357 dest="reuse_furls",
@@ -339,7 +360,6 @@
339 360
340 (options, args) = parser.parse_args()361 (options, args) = parser.parse_args()
341 362
342 kernel_config_manager.update_config_obj_from_default_file(options.ipythondir)
343 config = kernel_config_manager.get_config_obj()363 config = kernel_config_manager.get_config_obj()
344 364
345 # Update with command line options365 # Update with command line options
346366
=== modified file 'IPython/kernel/scripts/ipengine.py'
--- IPython/kernel/scripts/ipengine.py 2009-03-15 01:38:00 +0000
+++ IPython/kernel/scripts/ipengine.py 2009-04-18 23:24:22 +0000
@@ -33,6 +33,19 @@
33from IPython.kernel.core.config import config_manager as core_config_manager33from IPython.kernel.core.config import config_manager as core_config_manager
34from IPython.config.cutils import import_item34from IPython.config.cutils import import_item
35from IPython.kernel.engineservice import EngineService35from IPython.kernel.engineservice import EngineService
36
37# Create various ipython directories if they don't exist.
38# This must be done before IPython.kernel.config is imported.
39from IPython.iplib import user_setup
40from IPython.genutils import get_ipython_dir, get_log_dir, get_security_dir
41if os.name == 'posix':
42 rc_suffix = ''
43else:
44 rc_suffix = '.ini'
45user_setup(get_ipython_dir(), rc_suffix, mode='install', interactive=False)
46get_log_dir()
47get_security_dir()
48
36from IPython.kernel.config import config_manager as kernel_config_manager49from IPython.kernel.config import config_manager as kernel_config_manager
37from IPython.kernel.engineconnector import EngineConnector50from IPython.kernel.engineconnector import EngineConnector
3851
@@ -106,13 +119,19 @@
106 engine_connector = EngineConnector(tub_service)119 engine_connector = EngineConnector(tub_service)
107 furl_file = kernel_config['engine']['furl_file']120 furl_file = kernel_config['engine']['furl_file']
108 log.msg("Using furl file: %s" % furl_file)121 log.msg("Using furl file: %s" % furl_file)
109 d = engine_connector.connect_to_controller(engine_service, furl_file)122
110 def handle_error(f):123 def call_connect(engine_service, furl_file):
111 log.err(f)124 d = engine_connector.connect_to_controller(engine_service, furl_file)
112 if reactor.running:125 def handle_error(f):
113 reactor.stop()126 # If this print statement is replaced by a log.err(f) I get
114 d.addErrback(handle_error)127 # an unhandled error, which makes no sense. I shouldn't have
115 128 # to use a print statement here. My only thought is that
129 # at the beginning of the process the logging is still starting up
130 print "error connecting to controller:", f.getErrorMessage()
131 reactor.callLater(0.1, reactor.stop)
132 d.addErrback(handle_error)
133
134 reactor.callWhenRunning(call_connect, engine_service, furl_file)
116 reactor.run()135 reactor.run()
117136
118137
@@ -142,18 +161,9 @@
142 dest="logfile",161 dest="logfile",
143 help="log file name (default is stdout)"162 help="log file name (default is stdout)"
144 )163 )
145 parser.add_option(
146 "--ipythondir",
147 type="string",
148 dest="ipythondir",
149 help="look for config files and profiles in this directory"
150 )
151 164
152 (options, args) = parser.parse_args()165 (options, args) = parser.parse_args()
153 166
154 kernel_config_manager.update_config_obj_from_default_file(options.ipythondir)
155 core_config_manager.update_config_obj_from_default_file(options.ipythondir)
156
157 kernel_config = kernel_config_manager.get_config_obj()167 kernel_config = kernel_config_manager.get_config_obj()
158 # Now override with command line options168 # Now override with command line options
159 if options.furl_file is not None:169 if options.furl_file is not None:
160170
=== modified file 'IPython/kernel/tests/test_multiengine.py'
--- IPython/kernel/tests/test_multiengine.py 2008-08-23 23:06:36 +0000
+++ IPython/kernel/tests/test_multiengine.py 2009-04-18 21:53:37 +0000
@@ -4,16 +4,16 @@
44
5__docformat__ = "restructuredtext en"5__docformat__ = "restructuredtext en"
66
7#-------------------------------------------------------------------------------7#-----------------------------------------------------------------------------
8# Copyright (C) 2008 The IPython Development Team8# Copyright (C) 2008 The IPython Development Team
9#9#
10# Distributed under the terms of the BSD License. The full license is in10# Distributed under the terms of the BSD License. The full license is in
11# the file COPYING, distributed as part of this software.11# the file COPYING, distributed as part of this software.
12#-------------------------------------------------------------------------------12#-----------------------------------------------------------------------------
1313
14#-------------------------------------------------------------------------------14#-----------------------------------------------------------------------------
15# Imports15# Imports
16#-------------------------------------------------------------------------------16#-----------------------------------------------------------------------------
1717
18try:18try:
19 from twisted.internet import defer19 from twisted.internet import defer
2020
=== modified file 'IPython/kernel/tests/test_newserialized.py'
--- IPython/kernel/tests/test_newserialized.py 2008-08-23 23:06:36 +0000
+++ IPython/kernel/tests/test_newserialized.py 2009-04-18 21:53:37 +0000
@@ -4,16 +4,16 @@
44
5__docformat__ = "restructuredtext en"5__docformat__ = "restructuredtext en"
66
7#-------------------------------------------------------------------------------7#-----------------------------------------------------------------------------
8# Copyright (C) 2008 The IPython Development Team8# Copyright (C) 2008 The IPython Development Team
9#9#
10# Distributed under the terms of the BSD License. The full license is in10# Distributed under the terms of the BSD License. The full license is in
11# the file COPYING, distributed as part of this software.11# the file COPYING, distributed as part of this software.
12#-------------------------------------------------------------------------------12#-----------------------------------------------------------------------------
1313
14#-------------------------------------------------------------------------------14#-----------------------------------------------------------------------------
15# Imports15# Imports
16#-------------------------------------------------------------------------------16#-----------------------------------------------------------------------------
1717
18try:18try:
19 import zope.interface as zi19 import zope.interface as zi
@@ -31,9 +31,9 @@
31 import nose31 import nose
32 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")32 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
3333
34#-------------------------------------------------------------------------------34#-----------------------------------------------------------------------------
35# Tests35# Tests
36#-------------------------------------------------------------------------------36#-----------------------------------------------------------------------------
3737
38class SerializedTestCase(unittest.TestCase):38class SerializedTestCase(unittest.TestCase):
3939
4040
=== modified file 'IPython/kernel/twistedutil.py'
--- IPython/kernel/twistedutil.py 2008-06-06 19:41:55 +0000
+++ IPython/kernel/twistedutil.py 2009-04-18 21:53:37 +0000
@@ -16,12 +16,15 @@
16# Imports16# Imports
17#-------------------------------------------------------------------------------17#-------------------------------------------------------------------------------
1818
19import os, sys
19import threading, Queue, atexit20import threading, Queue, atexit
21
20import twisted22import twisted
21
22from twisted.internet import defer, reactor23from twisted.internet import defer, reactor
23from twisted.python import log, failure24from twisted.python import log, failure
2425
26from IPython.kernel.error import FileTimeoutError
27
25#-------------------------------------------------------------------------------28#-------------------------------------------------------------------------------
26# Classes related to twisted and threads29# Classes related to twisted and threads
27#-------------------------------------------------------------------------------30#-------------------------------------------------------------------------------
@@ -204,3 +207,43 @@
204 result = None207 result = None
205208
206 return result209 return result
210
211
212def wait_for_file(filename, delay=0.1, max_tries=10):
213 """Wait (poll) for a file to be created.
214
215 This method returns a Deferred that will fire when a file exists. It
216 works by polling os.path.isfile in time intervals specified by the
217 delay argument. If `max_tries` is reached, it will errback with a
218 `FileTimeoutError`.
219
220 Parameters
221 ----------
222 filename : str
223 The name of the file to wait for.
224 delay : float
225 The time to wait between polls.
226 max_tries : int
227 The max number of attempts before raising `FileTimeoutError`
228
229 Returns
230 -------
231 d : Deferred
232 A Deferred instance that will fire when the file exists.
233 """
234
235 d = defer.Deferred()
236
237 def _test_for_file(filename, attempt=0):
238 if attempt >= max_tries:
239 d.errback(FileTimeoutError(
240 'timeout waiting for file to be created: %s' % filename
241 ))
242 else:
243 if os.path.isfile(filename):
244 d.callback(True)
245 else:
246 reactor.callLater(delay, _test_for_file, filename, attempt+1)
247
248 _test_for_file(filename)
249 return d
207250
=== modified file 'IPython/tests/test_genutils.py'
--- IPython/tests/test_genutils.py 2009-03-11 17:44:53 +0000
+++ IPython/tests/test_genutils.py 2009-04-18 23:24:22 +0000
@@ -210,7 +210,6 @@
210 home_dir = genutils.get_home_dir()210 home_dir = genutils.get_home_dir()
211 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))211 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
212212
213
214#213#
215# Tests for get_ipython_dir214# Tests for get_ipython_dir
216#215#
@@ -239,7 +238,6 @@
239 ipdir = genutils.get_ipython_dir()238 ipdir = genutils.get_ipython_dir()
240 nt.assert_equal(ipdir, os.path.abspath(os.path.join("someplace", "_ipython")))239 nt.assert_equal(ipdir, os.path.abspath(os.path.join("someplace", "_ipython")))
241240
242
243#241#
244# Tests for get_security_dir242# Tests for get_security_dir
245#243#
@@ -249,6 +247,14 @@
249 """Testcase to see if we can call get_security_dir without Exceptions."""247 """Testcase to see if we can call get_security_dir without Exceptions."""
250 sdir = genutils.get_security_dir()248 sdir = genutils.get_security_dir()
251249
250#
251# Tests for get_log_dir
252#
253
254@with_enivronment
255def test_get_log_dir():
256 """Testcase to see if we can call get_log_dir without Exceptions."""
257 sdir = genutils.get_log_dir()
252258
253#259#
254# Tests for popkey260# Tests for popkey
255261
=== modified file 'docs/source/parallel/parallel_process.txt'
--- docs/source/parallel/parallel_process.txt 2009-03-18 18:45:20 +0000
+++ docs/source/parallel/parallel_process.txt 2009-04-18 21:53:37 +0000
@@ -302,18 +302,33 @@
302Make FURL files persistent302Make FURL files persistent
303---------------------------303---------------------------
304304
305At 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 every time 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.305At fist glance it may seem that that managing the FURL files is a bit
306306annoying. Going back to the house and key analogy, copying the FURL around
307This 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::307each time you start the controller is like having to make a new key every time
308you want to unlock the door and enter your house. As with your house, you want
309to be able to create the key (or FURL file) once, and then simply use it at
310any point in the future.
311
312This is possible. but before you do this, you **must** remove any old FURL
313files in the :file:`~/.ipython/security` directory.
314
315.. warning::
316
317 You **must** remove old FURL files before using persistent FURL files.
318
319Then, The only thing you have to do is decide what ports the controller will
320listen on for the engines and clients. This is done as follows::
308321
309 $ ipcontroller -r --client-port=10101 --engine-port=10102322 $ ipcontroller -r --client-port=10101 --engine-port=10102
310323
311These options also work with all of the various modes of 324These options also work with all of the various modes of
312:command:`ipcluster`::325:command:`ipcluster`::
313326
314 $ ipcluster local -n 2 -r --client-port=10101 --engine-port=10102327 $ ipcluster local -n 2 -r --client-port=10101 --engine-port=10102
315328
316Then, 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.329Then, just copy the furl files over the first time and you are set. You can
330start and stop the controller and engines any many times as you want in the
331future, just make sure to tell the controller to use the *same* ports.
317332
318.. note::333.. note::
319334

Subscribers

People subscribed via source and target branches