##// END OF EJS Templates
bump minimum pyzmq version to 2.1.11...
MinRK -
Show More
@@ -1,75 +1,72 b''
1 """The IPython ZMQ-based parallel computing interface.
1 """The IPython ZMQ-based parallel computing interface.
2
2
3 Authors:
3 Authors:
4
4
5 * MinRK
5 * MinRK
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2011 The IPython Development Team
8 # Copyright (C) 2011 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # 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 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 import os
18 import os
19 import warnings
19 import warnings
20
20
21 import zmq
21 import zmq
22
22
23 from IPython.config.configurable import MultipleInstanceError
23 from IPython.config.configurable import MultipleInstanceError
24 from IPython.zmq import check_for_zmq
24 from IPython.zmq import check_for_zmq
25
25
26 if os.name == 'nt':
26 min_pyzmq = '2.1.11'
27 min_pyzmq = '2.1.7'
28 else:
29 min_pyzmq = '2.1.4'
30
27
31 check_for_zmq(min_pyzmq, 'IPython.parallel')
28 check_for_zmq(min_pyzmq, 'IPython.parallel')
32
29
33 from IPython.utils.pickleutil import Reference
30 from IPython.utils.pickleutil import Reference
34
31
35 from .client.asyncresult import *
32 from .client.asyncresult import *
36 from .client.client import Client
33 from .client.client import Client
37 from .client.remotefunction import *
34 from .client.remotefunction import *
38 from .client.view import *
35 from .client.view import *
39 from .controller.dependency import *
36 from .controller.dependency import *
40 from .error import *
37 from .error import *
41 from .util import interactive
38 from .util import interactive
42
39
43 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
44 # Functions
41 # Functions
45 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
46
43
47
44
48 def bind_kernel(**kwargs):
45 def bind_kernel(**kwargs):
49 """Bind an Engine's Kernel to be used as a full IPython kernel.
46 """Bind an Engine's Kernel to be used as a full IPython kernel.
50
47
51 This allows a running Engine to be used simultaneously as a full IPython kernel
48 This allows a running Engine to be used simultaneously as a full IPython kernel
52 with the QtConsole or other frontends.
49 with the QtConsole or other frontends.
53
50
54 This function returns immediately.
51 This function returns immediately.
55 """
52 """
56 from IPython.zmq.ipkernel import IPKernelApp
53 from IPython.zmq.ipkernel import IPKernelApp
57 from IPython.parallel.apps.ipengineapp import IPEngineApp
54 from IPython.parallel.apps.ipengineapp import IPEngineApp
58
55
59 # first check for IPKernelApp, in which case this should be a no-op
56 # first check for IPKernelApp, in which case this should be a no-op
60 # because there is already a bound kernel
57 # because there is already a bound kernel
61 if IPKernelApp.initialized() and isinstance(IPKernelApp._instance, IPKernelApp):
58 if IPKernelApp.initialized() and isinstance(IPKernelApp._instance, IPKernelApp):
62 return
59 return
63
60
64 if IPEngineApp.initialized():
61 if IPEngineApp.initialized():
65 try:
62 try:
66 app = IPEngineApp.instance()
63 app = IPEngineApp.instance()
67 except MultipleInstanceError:
64 except MultipleInstanceError:
68 pass
65 pass
69 else:
66 else:
70 return app.bind_kernel(**kwargs)
67 return app.bind_kernel(**kwargs)
71
68
72 raise RuntimeError("bind_kernel be called from an IPEngineApp instance")
69 raise RuntimeError("bind_kernel be called from an IPEngineApp instance")
73
70
74
71
75
72
@@ -1,608 +1,598 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Test Suite Runner.
2 """IPython Test Suite Runner.
3
3
4 This module provides a main entry point to a user script to test IPython
4 This module provides a main entry point to a user script to test IPython
5 itself from the command line. There are two ways of running this script:
5 itself from the command line. There are two ways of running this script:
6
6
7 1. With the syntax `iptest all`. This runs our entire test suite by
7 1. With the syntax `iptest all`. This runs our entire test suite by
8 calling this script (with different arguments) recursively. This
8 calling this script (with different arguments) recursively. This
9 causes modules and package to be tested in different processes, using nose
9 causes modules and package to be tested in different processes, using nose
10 or trial where appropriate.
10 or trial where appropriate.
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 the script simply calls nose, but with special command line flags and
12 the script simply calls nose, but with special command line flags and
13 plugins loaded.
13 plugins loaded.
14
14
15 """
15 """
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Copyright (C) 2009-2011 The IPython Development Team
18 # Copyright (C) 2009-2011 The IPython Development Team
19 #
19 #
20 # Distributed under the terms of the BSD License. The full license is in
20 # Distributed under the terms of the BSD License. The full license is in
21 # the file COPYING, distributed as part of this software.
21 # the file COPYING, distributed as part of this software.
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Imports
25 # Imports
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 from __future__ import print_function
27 from __future__ import print_function
28
28
29 # Stdlib
29 # Stdlib
30 import glob
30 import glob
31 import os
31 import os
32 import os.path as path
32 import os.path as path
33 import signal
33 import signal
34 import sys
34 import sys
35 import subprocess
35 import subprocess
36 import tempfile
36 import tempfile
37 import time
37 import time
38 import warnings
38 import warnings
39
39
40 # Note: monkeypatch!
40 # Note: monkeypatch!
41 # We need to monkeypatch a small problem in nose itself first, before importing
41 # We need to monkeypatch a small problem in nose itself first, before importing
42 # it for actual use. This should get into nose upstream, but its release cycle
42 # it for actual use. This should get into nose upstream, but its release cycle
43 # is slow and we need it for our parametric tests to work correctly.
43 # is slow and we need it for our parametric tests to work correctly.
44 from IPython.testing import nosepatch
44 from IPython.testing import nosepatch
45
45
46 # Monkeypatch extra assert methods into nose.tools if they're not already there.
46 # Monkeypatch extra assert methods into nose.tools if they're not already there.
47 # This can be dropped once we no longer test on Python 2.6
47 # This can be dropped once we no longer test on Python 2.6
48 from IPython.testing import nose_assert_methods
48 from IPython.testing import nose_assert_methods
49
49
50 # Now, proceed to import nose itself
50 # Now, proceed to import nose itself
51 import nose.plugins.builtin
51 import nose.plugins.builtin
52 from nose.plugins.xunit import Xunit
52 from nose.plugins.xunit import Xunit
53 from nose import SkipTest
53 from nose import SkipTest
54 from nose.core import TestProgram
54 from nose.core import TestProgram
55
55
56 # Our own imports
56 # Our own imports
57 from IPython.utils import py3compat
57 from IPython.utils import py3compat
58 from IPython.utils.importstring import import_item
58 from IPython.utils.importstring import import_item
59 from IPython.utils.path import get_ipython_module_path, get_ipython_package_dir
59 from IPython.utils.path import get_ipython_module_path, get_ipython_package_dir
60 from IPython.utils.process import find_cmd, pycmd2argv
60 from IPython.utils.process import find_cmd, pycmd2argv
61 from IPython.utils.sysinfo import sys_info
61 from IPython.utils.sysinfo import sys_info
62 from IPython.utils.tempdir import TemporaryDirectory
62 from IPython.utils.tempdir import TemporaryDirectory
63 from IPython.utils.warn import warn
63 from IPython.utils.warn import warn
64
64
65 from IPython.testing import globalipapp
65 from IPython.testing import globalipapp
66 from IPython.testing.plugin.ipdoctest import IPythonDoctest
66 from IPython.testing.plugin.ipdoctest import IPythonDoctest
67 from IPython.external.decorators import KnownFailure, knownfailureif
67 from IPython.external.decorators import KnownFailure, knownfailureif
68
68
69 pjoin = path.join
69 pjoin = path.join
70
70
71
71
72 #-----------------------------------------------------------------------------
72 #-----------------------------------------------------------------------------
73 # Globals
73 # Globals
74 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
75
75
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Warnings control
78 # Warnings control
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81 # Twisted generates annoying warnings with Python 2.6, as will do other code
81 # Twisted generates annoying warnings with Python 2.6, as will do other code
82 # that imports 'sets' as of today
82 # that imports 'sets' as of today
83 warnings.filterwarnings('ignore', 'the sets module is deprecated',
83 warnings.filterwarnings('ignore', 'the sets module is deprecated',
84 DeprecationWarning )
84 DeprecationWarning )
85
85
86 # This one also comes from Twisted
86 # This one also comes from Twisted
87 warnings.filterwarnings('ignore', 'the sha module is deprecated',
87 warnings.filterwarnings('ignore', 'the sha module is deprecated',
88 DeprecationWarning)
88 DeprecationWarning)
89
89
90 # Wx on Fedora11 spits these out
90 # Wx on Fedora11 spits these out
91 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
91 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
92 UserWarning)
92 UserWarning)
93
93
94 # ------------------------------------------------------------------------------
94 # ------------------------------------------------------------------------------
95 # Monkeypatch Xunit to count known failures as skipped.
95 # Monkeypatch Xunit to count known failures as skipped.
96 # ------------------------------------------------------------------------------
96 # ------------------------------------------------------------------------------
97 def monkeypatch_xunit():
97 def monkeypatch_xunit():
98 try:
98 try:
99 knownfailureif(True)(lambda: None)()
99 knownfailureif(True)(lambda: None)()
100 except Exception as e:
100 except Exception as e:
101 KnownFailureTest = type(e)
101 KnownFailureTest = type(e)
102
102
103 def addError(self, test, err, capt=None):
103 def addError(self, test, err, capt=None):
104 if issubclass(err[0], KnownFailureTest):
104 if issubclass(err[0], KnownFailureTest):
105 err = (SkipTest,) + err[1:]
105 err = (SkipTest,) + err[1:]
106 return self.orig_addError(test, err, capt)
106 return self.orig_addError(test, err, capt)
107
107
108 Xunit.orig_addError = Xunit.addError
108 Xunit.orig_addError = Xunit.addError
109 Xunit.addError = addError
109 Xunit.addError = addError
110
110
111 #-----------------------------------------------------------------------------
111 #-----------------------------------------------------------------------------
112 # Logic for skipping doctests
112 # Logic for skipping doctests
113 #-----------------------------------------------------------------------------
113 #-----------------------------------------------------------------------------
114 def extract_version(mod):
114 def extract_version(mod):
115 return mod.__version__
115 return mod.__version__
116
116
117 def test_for(item, min_version=None, callback=extract_version):
117 def test_for(item, min_version=None, callback=extract_version):
118 """Test to see if item is importable, and optionally check against a minimum
118 """Test to see if item is importable, and optionally check against a minimum
119 version.
119 version.
120
120
121 If min_version is given, the default behavior is to check against the
121 If min_version is given, the default behavior is to check against the
122 `__version__` attribute of the item, but specifying `callback` allows you to
122 `__version__` attribute of the item, but specifying `callback` allows you to
123 extract the value you are interested in. e.g::
123 extract the value you are interested in. e.g::
124
124
125 In [1]: import sys
125 In [1]: import sys
126
126
127 In [2]: from IPython.testing.iptest import test_for
127 In [2]: from IPython.testing.iptest import test_for
128
128
129 In [3]: test_for('sys', (2,6), callback=lambda sys: sys.version_info)
129 In [3]: test_for('sys', (2,6), callback=lambda sys: sys.version_info)
130 Out[3]: True
130 Out[3]: True
131
131
132 """
132 """
133 try:
133 try:
134 check = import_item(item)
134 check = import_item(item)
135 except (ImportError, RuntimeError):
135 except (ImportError, RuntimeError):
136 # GTK reports Runtime error if it can't be initialized even if it's
136 # GTK reports Runtime error if it can't be initialized even if it's
137 # importable.
137 # importable.
138 return False
138 return False
139 else:
139 else:
140 if min_version:
140 if min_version:
141 if callback:
141 if callback:
142 # extra processing step to get version to compare
142 # extra processing step to get version to compare
143 check = callback(check)
143 check = callback(check)
144
144
145 return check >= min_version
145 return check >= min_version
146 else:
146 else:
147 return True
147 return True
148
148
149 # Global dict where we can store information on what we have and what we don't
149 # Global dict where we can store information on what we have and what we don't
150 # have available at test run time
150 # have available at test run time
151 have = {}
151 have = {}
152
152
153 have['curses'] = test_for('_curses')
153 have['curses'] = test_for('_curses')
154 have['matplotlib'] = test_for('matplotlib')
154 have['matplotlib'] = test_for('matplotlib')
155 have['numpy'] = test_for('numpy')
155 have['numpy'] = test_for('numpy')
156 have['pexpect'] = test_for('IPython.external.pexpect')
156 have['pexpect'] = test_for('IPython.external.pexpect')
157 have['pymongo'] = test_for('pymongo')
157 have['pymongo'] = test_for('pymongo')
158 have['pygments'] = test_for('pygments')
158 have['pygments'] = test_for('pygments')
159 have['qt'] = test_for('IPython.external.qt')
159 have['qt'] = test_for('IPython.external.qt')
160 have['rpy2'] = test_for('rpy2')
160 have['rpy2'] = test_for('rpy2')
161 have['sqlite3'] = test_for('sqlite3')
161 have['sqlite3'] = test_for('sqlite3')
162 have['cython'] = test_for('Cython')
162 have['cython'] = test_for('Cython')
163 have['oct2py'] = test_for('oct2py')
163 have['oct2py'] = test_for('oct2py')
164 have['tornado'] = test_for('tornado.version_info', (2,1,0), callback=None)
164 have['tornado'] = test_for('tornado.version_info', (2,1,0), callback=None)
165 have['jinja2'] = test_for('jinja2')
165 have['jinja2'] = test_for('jinja2')
166 have['wx'] = test_for('wx')
166 have['wx'] = test_for('wx')
167 have['wx.aui'] = test_for('wx.aui')
167 have['wx.aui'] = test_for('wx.aui')
168 have['azure'] = test_for('azure')
168 have['azure'] = test_for('azure')
169
169
170 if os.name == 'nt':
170 min_zmq = (2,1,11)
171 min_zmq = (2,1,7)
171
172 else:
172 have['zmq'] = test_for('zmq.pyzmq_version_info', min_zmq)
173 min_zmq = (2,1,4)
174
175 def version_tuple(mod):
176 "turn '2.1.9' into (2,1,9), and '2.1dev' into (2,1,999)"
177 # turn 'dev' into 999, because Python3 rejects str-int comparisons
178 vs = mod.__version__.replace('dev', '.999')
179 tup = tuple([int(v) for v in vs.split('.') ])
180 return tup
181
182 have['zmq'] = test_for('zmq', min_zmq, version_tuple)
183
173
184 #-----------------------------------------------------------------------------
174 #-----------------------------------------------------------------------------
185 # Functions and classes
175 # Functions and classes
186 #-----------------------------------------------------------------------------
176 #-----------------------------------------------------------------------------
187
177
188 def report():
178 def report():
189 """Return a string with a summary report of test-related variables."""
179 """Return a string with a summary report of test-related variables."""
190
180
191 out = [ sys_info(), '\n']
181 out = [ sys_info(), '\n']
192
182
193 avail = []
183 avail = []
194 not_avail = []
184 not_avail = []
195
185
196 for k, is_avail in have.items():
186 for k, is_avail in have.items():
197 if is_avail:
187 if is_avail:
198 avail.append(k)
188 avail.append(k)
199 else:
189 else:
200 not_avail.append(k)
190 not_avail.append(k)
201
191
202 if avail:
192 if avail:
203 out.append('\nTools and libraries available at test time:\n')
193 out.append('\nTools and libraries available at test time:\n')
204 avail.sort()
194 avail.sort()
205 out.append(' ' + ' '.join(avail)+'\n')
195 out.append(' ' + ' '.join(avail)+'\n')
206
196
207 if not_avail:
197 if not_avail:
208 out.append('\nTools and libraries NOT available at test time:\n')
198 out.append('\nTools and libraries NOT available at test time:\n')
209 not_avail.sort()
199 not_avail.sort()
210 out.append(' ' + ' '.join(not_avail)+'\n')
200 out.append(' ' + ' '.join(not_avail)+'\n')
211
201
212 return ''.join(out)
202 return ''.join(out)
213
203
214
204
215 def make_exclude():
205 def make_exclude():
216 """Make patterns of modules and packages to exclude from testing.
206 """Make patterns of modules and packages to exclude from testing.
217
207
218 For the IPythonDoctest plugin, we need to exclude certain patterns that
208 For the IPythonDoctest plugin, we need to exclude certain patterns that
219 cause testing problems. We should strive to minimize the number of
209 cause testing problems. We should strive to minimize the number of
220 skipped modules, since this means untested code.
210 skipped modules, since this means untested code.
221
211
222 These modules and packages will NOT get scanned by nose at all for tests.
212 These modules and packages will NOT get scanned by nose at all for tests.
223 """
213 """
224 # Simple utility to make IPython paths more readably, we need a lot of
214 # Simple utility to make IPython paths more readably, we need a lot of
225 # these below
215 # these below
226 ipjoin = lambda *paths: pjoin('IPython', *paths)
216 ipjoin = lambda *paths: pjoin('IPython', *paths)
227
217
228 exclusions = [ipjoin('external'),
218 exclusions = [ipjoin('external'),
229 ipjoin('quarantine'),
219 ipjoin('quarantine'),
230 ipjoin('deathrow'),
220 ipjoin('deathrow'),
231 # This guy is probably attic material
221 # This guy is probably attic material
232 ipjoin('testing', 'mkdoctests'),
222 ipjoin('testing', 'mkdoctests'),
233 # Testing inputhook will need a lot of thought, to figure out
223 # Testing inputhook will need a lot of thought, to figure out
234 # how to have tests that don't lock up with the gui event
224 # how to have tests that don't lock up with the gui event
235 # loops in the picture
225 # loops in the picture
236 ipjoin('lib', 'inputhook'),
226 ipjoin('lib', 'inputhook'),
237 # Config files aren't really importable stand-alone
227 # Config files aren't really importable stand-alone
238 ipjoin('config', 'profile'),
228 ipjoin('config', 'profile'),
239 # The notebook 'static' directory contains JS, css and other
229 # The notebook 'static' directory contains JS, css and other
240 # files for web serving. Occasionally projects may put a .py
230 # files for web serving. Occasionally projects may put a .py
241 # file in there (MathJax ships a conf.py), so we might as
231 # file in there (MathJax ships a conf.py), so we might as
242 # well play it safe and skip the whole thing.
232 # well play it safe and skip the whole thing.
243 ipjoin('frontend', 'html', 'notebook', 'static')
233 ipjoin('frontend', 'html', 'notebook', 'static')
244 ]
234 ]
245 if not have['sqlite3']:
235 if not have['sqlite3']:
246 exclusions.append(ipjoin('core', 'tests', 'test_history'))
236 exclusions.append(ipjoin('core', 'tests', 'test_history'))
247 exclusions.append(ipjoin('core', 'history'))
237 exclusions.append(ipjoin('core', 'history'))
248 if not have['wx']:
238 if not have['wx']:
249 exclusions.append(ipjoin('lib', 'inputhookwx'))
239 exclusions.append(ipjoin('lib', 'inputhookwx'))
250
240
251 # FIXME: temporarily disable autoreload tests, as they can produce
241 # FIXME: temporarily disable autoreload tests, as they can produce
252 # spurious failures in subsequent tests (cythonmagic).
242 # spurious failures in subsequent tests (cythonmagic).
253 exclusions.append(ipjoin('extensions', 'autoreload'))
243 exclusions.append(ipjoin('extensions', 'autoreload'))
254 exclusions.append(ipjoin('extensions', 'tests', 'test_autoreload'))
244 exclusions.append(ipjoin('extensions', 'tests', 'test_autoreload'))
255
245
256 # We do this unconditionally, so that the test suite doesn't import
246 # We do this unconditionally, so that the test suite doesn't import
257 # gtk, changing the default encoding and masking some unicode bugs.
247 # gtk, changing the default encoding and masking some unicode bugs.
258 exclusions.append(ipjoin('lib', 'inputhookgtk'))
248 exclusions.append(ipjoin('lib', 'inputhookgtk'))
259 exclusions.append(ipjoin('zmq', 'gui', 'gtkembed'))
249 exclusions.append(ipjoin('zmq', 'gui', 'gtkembed'))
260
250
261 # These have to be skipped on win32 because the use echo, rm, cd, etc.
251 # These have to be skipped on win32 because the use echo, rm, cd, etc.
262 # See ticket https://github.com/ipython/ipython/issues/87
252 # See ticket https://github.com/ipython/ipython/issues/87
263 if sys.platform == 'win32':
253 if sys.platform == 'win32':
264 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
254 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
265 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
255 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
266
256
267 if not have['pexpect']:
257 if not have['pexpect']:
268 exclusions.extend([ipjoin('lib', 'irunner'),
258 exclusions.extend([ipjoin('lib', 'irunner'),
269 ipjoin('lib', 'tests', 'test_irunner'),
259 ipjoin('lib', 'tests', 'test_irunner'),
270 ipjoin('frontend', 'terminal', 'console'),
260 ipjoin('frontend', 'terminal', 'console'),
271 ])
261 ])
272
262
273 if not have['zmq']:
263 if not have['zmq']:
274 exclusions.append(ipjoin('zmq'))
264 exclusions.append(ipjoin('zmq'))
275 exclusions.append(ipjoin('frontend', 'qt'))
265 exclusions.append(ipjoin('frontend', 'qt'))
276 exclusions.append(ipjoin('frontend', 'html'))
266 exclusions.append(ipjoin('frontend', 'html'))
277 exclusions.append(ipjoin('frontend', 'consoleapp.py'))
267 exclusions.append(ipjoin('frontend', 'consoleapp.py'))
278 exclusions.append(ipjoin('frontend', 'terminal', 'console'))
268 exclusions.append(ipjoin('frontend', 'terminal', 'console'))
279 exclusions.append(ipjoin('parallel'))
269 exclusions.append(ipjoin('parallel'))
280 elif not have['qt'] or not have['pygments']:
270 elif not have['qt'] or not have['pygments']:
281 exclusions.append(ipjoin('frontend', 'qt'))
271 exclusions.append(ipjoin('frontend', 'qt'))
282
272
283 if not have['pymongo']:
273 if not have['pymongo']:
284 exclusions.append(ipjoin('parallel', 'controller', 'mongodb'))
274 exclusions.append(ipjoin('parallel', 'controller', 'mongodb'))
285 exclusions.append(ipjoin('parallel', 'tests', 'test_mongodb'))
275 exclusions.append(ipjoin('parallel', 'tests', 'test_mongodb'))
286
276
287 if not have['matplotlib']:
277 if not have['matplotlib']:
288 exclusions.extend([ipjoin('core', 'pylabtools'),
278 exclusions.extend([ipjoin('core', 'pylabtools'),
289 ipjoin('core', 'tests', 'test_pylabtools'),
279 ipjoin('core', 'tests', 'test_pylabtools'),
290 ipjoin('zmq', 'pylab'),
280 ipjoin('zmq', 'pylab'),
291 ])
281 ])
292
282
293 if not have['cython']:
283 if not have['cython']:
294 exclusions.extend([ipjoin('extensions', 'cythonmagic')])
284 exclusions.extend([ipjoin('extensions', 'cythonmagic')])
295 exclusions.extend([ipjoin('extensions', 'tests', 'test_cythonmagic')])
285 exclusions.extend([ipjoin('extensions', 'tests', 'test_cythonmagic')])
296
286
297 if not have['oct2py']:
287 if not have['oct2py']:
298 exclusions.extend([ipjoin('extensions', 'octavemagic')])
288 exclusions.extend([ipjoin('extensions', 'octavemagic')])
299 exclusions.extend([ipjoin('extensions', 'tests', 'test_octavemagic')])
289 exclusions.extend([ipjoin('extensions', 'tests', 'test_octavemagic')])
300
290
301 if not have['tornado']:
291 if not have['tornado']:
302 exclusions.append(ipjoin('frontend', 'html'))
292 exclusions.append(ipjoin('frontend', 'html'))
303
293
304 if not have['jinja2']:
294 if not have['jinja2']:
305 exclusions.append(ipjoin('frontend', 'html', 'notebook', 'notebookapp'))
295 exclusions.append(ipjoin('frontend', 'html', 'notebook', 'notebookapp'))
306
296
307 if not have['rpy2'] or not have['numpy']:
297 if not have['rpy2'] or not have['numpy']:
308 exclusions.append(ipjoin('extensions', 'rmagic'))
298 exclusions.append(ipjoin('extensions', 'rmagic'))
309 exclusions.append(ipjoin('extensions', 'tests', 'test_rmagic'))
299 exclusions.append(ipjoin('extensions', 'tests', 'test_rmagic'))
310
300
311 if not have['azure']:
301 if not have['azure']:
312 exclusions.append(ipjoin('frontend', 'html', 'notebook', 'azurenbmanager'))
302 exclusions.append(ipjoin('frontend', 'html', 'notebook', 'azurenbmanager'))
313
303
314 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
304 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
315 if sys.platform == 'win32':
305 if sys.platform == 'win32':
316 exclusions = [s.replace('\\','\\\\') for s in exclusions]
306 exclusions = [s.replace('\\','\\\\') for s in exclusions]
317
307
318 # check for any exclusions that don't seem to exist:
308 # check for any exclusions that don't seem to exist:
319 parent, _ = os.path.split(get_ipython_package_dir())
309 parent, _ = os.path.split(get_ipython_package_dir())
320 for exclusion in exclusions:
310 for exclusion in exclusions:
321 if exclusion.endswith(('deathrow', 'quarantine')):
311 if exclusion.endswith(('deathrow', 'quarantine')):
322 # ignore deathrow/quarantine, which exist in dev, but not install
312 # ignore deathrow/quarantine, which exist in dev, but not install
323 continue
313 continue
324 fullpath = pjoin(parent, exclusion)
314 fullpath = pjoin(parent, exclusion)
325 if not os.path.exists(fullpath) and not glob.glob(fullpath + '.*'):
315 if not os.path.exists(fullpath) and not glob.glob(fullpath + '.*'):
326 warn("Excluding nonexistent file: %r" % exclusion)
316 warn("Excluding nonexistent file: %r" % exclusion)
327
317
328 return exclusions
318 return exclusions
329
319
330
320
331 class IPTester(object):
321 class IPTester(object):
332 """Call that calls iptest or trial in a subprocess.
322 """Call that calls iptest or trial in a subprocess.
333 """
323 """
334 #: string, name of test runner that will be called
324 #: string, name of test runner that will be called
335 runner = None
325 runner = None
336 #: list, parameters for test runner
326 #: list, parameters for test runner
337 params = None
327 params = None
338 #: list, arguments of system call to be made to call test runner
328 #: list, arguments of system call to be made to call test runner
339 call_args = None
329 call_args = None
340 #: list, subprocesses we start (for cleanup)
330 #: list, subprocesses we start (for cleanup)
341 processes = None
331 processes = None
342 #: str, coverage xml output file
332 #: str, coverage xml output file
343 coverage_xml = None
333 coverage_xml = None
344
334
345 def __init__(self, runner='iptest', params=None):
335 def __init__(self, runner='iptest', params=None):
346 """Create new test runner."""
336 """Create new test runner."""
347 p = os.path
337 p = os.path
348 if runner == 'iptest':
338 if runner == 'iptest':
349 iptest_app = get_ipython_module_path('IPython.testing.iptest')
339 iptest_app = get_ipython_module_path('IPython.testing.iptest')
350 self.runner = pycmd2argv(iptest_app) + sys.argv[1:]
340 self.runner = pycmd2argv(iptest_app) + sys.argv[1:]
351 else:
341 else:
352 raise Exception('Not a valid test runner: %s' % repr(runner))
342 raise Exception('Not a valid test runner: %s' % repr(runner))
353 if params is None:
343 if params is None:
354 params = []
344 params = []
355 if isinstance(params, str):
345 if isinstance(params, str):
356 params = [params]
346 params = [params]
357 self.params = params
347 self.params = params
358
348
359 # Assemble call
349 # Assemble call
360 self.call_args = self.runner+self.params
350 self.call_args = self.runner+self.params
361
351
362 # Find the section we're testing (IPython.foo)
352 # Find the section we're testing (IPython.foo)
363 for sect in self.params:
353 for sect in self.params:
364 if sect.startswith('IPython'): break
354 if sect.startswith('IPython'): break
365 else:
355 else:
366 raise ValueError("Section not found", self.params)
356 raise ValueError("Section not found", self.params)
367
357
368 if '--with-xunit' in self.call_args:
358 if '--with-xunit' in self.call_args:
369
359
370 self.call_args.append('--xunit-file')
360 self.call_args.append('--xunit-file')
371 # FIXME: when Windows uses subprocess.call, these extra quotes are unnecessary:
361 # FIXME: when Windows uses subprocess.call, these extra quotes are unnecessary:
372 xunit_file = path.abspath(sect+'.xunit.xml')
362 xunit_file = path.abspath(sect+'.xunit.xml')
373 if sys.platform == 'win32':
363 if sys.platform == 'win32':
374 xunit_file = '"%s"' % xunit_file
364 xunit_file = '"%s"' % xunit_file
375 self.call_args.append(xunit_file)
365 self.call_args.append(xunit_file)
376
366
377 if '--with-xml-coverage' in self.call_args:
367 if '--with-xml-coverage' in self.call_args:
378 self.coverage_xml = path.abspath(sect+".coverage.xml")
368 self.coverage_xml = path.abspath(sect+".coverage.xml")
379 self.call_args.remove('--with-xml-coverage')
369 self.call_args.remove('--with-xml-coverage')
380 self.call_args = ["coverage", "run", "--source="+sect] + self.call_args[1:]
370 self.call_args = ["coverage", "run", "--source="+sect] + self.call_args[1:]
381
371
382 # Store anything we start to clean up on deletion
372 # Store anything we start to clean up on deletion
383 self.processes = []
373 self.processes = []
384
374
385 def _run_cmd(self):
375 def _run_cmd(self):
386 with TemporaryDirectory() as IPYTHONDIR:
376 with TemporaryDirectory() as IPYTHONDIR:
387 env = os.environ.copy()
377 env = os.environ.copy()
388 env['IPYTHONDIR'] = IPYTHONDIR
378 env['IPYTHONDIR'] = IPYTHONDIR
389 # print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
379 # print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
390 subp = subprocess.Popen(self.call_args, env=env)
380 subp = subprocess.Popen(self.call_args, env=env)
391 self.processes.append(subp)
381 self.processes.append(subp)
392 # If this fails, the process will be left in self.processes and
382 # If this fails, the process will be left in self.processes and
393 # cleaned up later, but if the wait call succeeds, then we can
383 # cleaned up later, but if the wait call succeeds, then we can
394 # clear the stored process.
384 # clear the stored process.
395 retcode = subp.wait()
385 retcode = subp.wait()
396 self.processes.pop()
386 self.processes.pop()
397 return retcode
387 return retcode
398
388
399 def run(self):
389 def run(self):
400 """Run the stored commands"""
390 """Run the stored commands"""
401 try:
391 try:
402 retcode = self._run_cmd()
392 retcode = self._run_cmd()
403 except KeyboardInterrupt:
393 except KeyboardInterrupt:
404 return -signal.SIGINT
394 return -signal.SIGINT
405 except:
395 except:
406 import traceback
396 import traceback
407 traceback.print_exc()
397 traceback.print_exc()
408 return 1 # signal failure
398 return 1 # signal failure
409
399
410 if self.coverage_xml:
400 if self.coverage_xml:
411 subprocess.call(["coverage", "xml", "-o", self.coverage_xml])
401 subprocess.call(["coverage", "xml", "-o", self.coverage_xml])
412 return retcode
402 return retcode
413
403
414 def __del__(self):
404 def __del__(self):
415 """Cleanup on exit by killing any leftover processes."""
405 """Cleanup on exit by killing any leftover processes."""
416 for subp in self.processes:
406 for subp in self.processes:
417 if subp.poll() is not None:
407 if subp.poll() is not None:
418 continue # process is already dead
408 continue # process is already dead
419
409
420 try:
410 try:
421 print('Cleaning up stale PID: %d' % subp.pid)
411 print('Cleaning up stale PID: %d' % subp.pid)
422 subp.kill()
412 subp.kill()
423 except: # (OSError, WindowsError) ?
413 except: # (OSError, WindowsError) ?
424 # This is just a best effort, if we fail or the process was
414 # This is just a best effort, if we fail or the process was
425 # really gone, ignore it.
415 # really gone, ignore it.
426 pass
416 pass
427 else:
417 else:
428 for i in range(10):
418 for i in range(10):
429 if subp.poll() is None:
419 if subp.poll() is None:
430 time.sleep(0.1)
420 time.sleep(0.1)
431 else:
421 else:
432 break
422 break
433
423
434 if subp.poll() is None:
424 if subp.poll() is None:
435 # The process did not die...
425 # The process did not die...
436 print('... failed. Manual cleanup may be required.')
426 print('... failed. Manual cleanup may be required.')
437
427
438 def make_runners(inc_slow=False):
428 def make_runners(inc_slow=False):
439 """Define the top-level packages that need to be tested.
429 """Define the top-level packages that need to be tested.
440 """
430 """
441
431
442 # Packages to be tested via nose, that only depend on the stdlib
432 # Packages to be tested via nose, that only depend on the stdlib
443 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
433 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
444 'testing', 'utils', 'nbformat', 'inprocess' ]
434 'testing', 'utils', 'nbformat', 'inprocess' ]
445
435
446 if have['zmq']:
436 if have['zmq']:
447 nose_pkg_names.append('zmq')
437 nose_pkg_names.append('zmq')
448 if inc_slow:
438 if inc_slow:
449 nose_pkg_names.append('parallel')
439 nose_pkg_names.append('parallel')
450
440
451 # For debugging this code, only load quick stuff
441 # For debugging this code, only load quick stuff
452 #nose_pkg_names = ['core', 'extensions'] # dbg
442 #nose_pkg_names = ['core', 'extensions'] # dbg
453
443
454 # Make fully qualified package names prepending 'IPython.' to our name lists
444 # Make fully qualified package names prepending 'IPython.' to our name lists
455 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
445 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
456
446
457 # Make runners
447 # Make runners
458 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
448 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
459
449
460 return runners
450 return runners
461
451
462
452
463 def run_iptest():
453 def run_iptest():
464 """Run the IPython test suite using nose.
454 """Run the IPython test suite using nose.
465
455
466 This function is called when this script is **not** called with the form
456 This function is called when this script is **not** called with the form
467 `iptest all`. It simply calls nose with appropriate command line flags
457 `iptest all`. It simply calls nose with appropriate command line flags
468 and accepts all of the standard nose arguments.
458 and accepts all of the standard nose arguments.
469 """
459 """
470 # Apply our monkeypatch to Xunit
460 # Apply our monkeypatch to Xunit
471 if '--with-xunit' in sys.argv and not hasattr(Xunit, 'orig_addError'):
461 if '--with-xunit' in sys.argv and not hasattr(Xunit, 'orig_addError'):
472 monkeypatch_xunit()
462 monkeypatch_xunit()
473
463
474 warnings.filterwarnings('ignore',
464 warnings.filterwarnings('ignore',
475 'This will be removed soon. Use IPython.testing.util instead')
465 'This will be removed soon. Use IPython.testing.util instead')
476
466
477 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
467 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
478
468
479 '--with-ipdoctest',
469 '--with-ipdoctest',
480 '--ipdoctest-tests','--ipdoctest-extension=txt',
470 '--ipdoctest-tests','--ipdoctest-extension=txt',
481
471
482 # We add --exe because of setuptools' imbecility (it
472 # We add --exe because of setuptools' imbecility (it
483 # blindly does chmod +x on ALL files). Nose does the
473 # blindly does chmod +x on ALL files). Nose does the
484 # right thing and it tries to avoid executables,
474 # right thing and it tries to avoid executables,
485 # setuptools unfortunately forces our hand here. This
475 # setuptools unfortunately forces our hand here. This
486 # has been discussed on the distutils list and the
476 # has been discussed on the distutils list and the
487 # setuptools devs refuse to fix this problem!
477 # setuptools devs refuse to fix this problem!
488 '--exe',
478 '--exe',
489 ]
479 ]
490 if '-a' not in argv and '-A' not in argv:
480 if '-a' not in argv and '-A' not in argv:
491 argv = argv + ['-a', '!crash']
481 argv = argv + ['-a', '!crash']
492
482
493 if nose.__version__ >= '0.11':
483 if nose.__version__ >= '0.11':
494 # I don't fully understand why we need this one, but depending on what
484 # I don't fully understand why we need this one, but depending on what
495 # directory the test suite is run from, if we don't give it, 0 tests
485 # directory the test suite is run from, if we don't give it, 0 tests
496 # get run. Specifically, if the test suite is run from the source dir
486 # get run. Specifically, if the test suite is run from the source dir
497 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
487 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
498 # even if the same call done in this directory works fine). It appears
488 # even if the same call done in this directory works fine). It appears
499 # that if the requested package is in the current dir, nose bails early
489 # that if the requested package is in the current dir, nose bails early
500 # by default. Since it's otherwise harmless, leave it in by default
490 # by default. Since it's otherwise harmless, leave it in by default
501 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
491 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
502 argv.append('--traverse-namespace')
492 argv.append('--traverse-namespace')
503
493
504 # use our plugin for doctesting. It will remove the standard doctest plugin
494 # use our plugin for doctesting. It will remove the standard doctest plugin
505 # if it finds it enabled
495 # if it finds it enabled
506 plugins = [IPythonDoctest(make_exclude()), KnownFailure()]
496 plugins = [IPythonDoctest(make_exclude()), KnownFailure()]
507
497
508 # We need a global ipython running in this process, but the special
498 # We need a global ipython running in this process, but the special
509 # in-process group spawns its own IPython kernels, so for *that* group we
499 # in-process group spawns its own IPython kernels, so for *that* group we
510 # must avoid also opening the global one (otherwise there's a conflict of
500 # must avoid also opening the global one (otherwise there's a conflict of
511 # singletons). Ultimately the solution to this problem is to refactor our
501 # singletons). Ultimately the solution to this problem is to refactor our
512 # assumptions about what needs to be a singleton and what doesn't (app
502 # assumptions about what needs to be a singleton and what doesn't (app
513 # objects should, individual shells shouldn't). But for now, this
503 # objects should, individual shells shouldn't). But for now, this
514 # workaround allows the test suite for the inprocess module to complete.
504 # workaround allows the test suite for the inprocess module to complete.
515 if not 'IPython.inprocess' in sys.argv:
505 if not 'IPython.inprocess' in sys.argv:
516 globalipapp.start_ipython()
506 globalipapp.start_ipython()
517
507
518 # Now nose can run
508 # Now nose can run
519 TestProgram(argv=argv, addplugins=plugins)
509 TestProgram(argv=argv, addplugins=plugins)
520
510
521
511
522 def run_iptestall(inc_slow=False):
512 def run_iptestall(inc_slow=False):
523 """Run the entire IPython test suite by calling nose and trial.
513 """Run the entire IPython test suite by calling nose and trial.
524
514
525 This function constructs :class:`IPTester` instances for all IPython
515 This function constructs :class:`IPTester` instances for all IPython
526 modules and package and then runs each of them. This causes the modules
516 modules and package and then runs each of them. This causes the modules
527 and packages of IPython to be tested each in their own subprocess using
517 and packages of IPython to be tested each in their own subprocess using
528 nose.
518 nose.
529
519
530 Parameters
520 Parameters
531 ----------
521 ----------
532
522
533 inc_slow : bool, optional
523 inc_slow : bool, optional
534 Include slow tests, like IPython.parallel. By default, these tests aren't
524 Include slow tests, like IPython.parallel. By default, these tests aren't
535 run.
525 run.
536 """
526 """
537
527
538 runners = make_runners(inc_slow=inc_slow)
528 runners = make_runners(inc_slow=inc_slow)
539
529
540 # Run the test runners in a temporary dir so we can nuke it when finished
530 # Run the test runners in a temporary dir so we can nuke it when finished
541 # to clean up any junk files left over by accident. This also makes it
531 # to clean up any junk files left over by accident. This also makes it
542 # robust against being run in non-writeable directories by mistake, as the
532 # robust against being run in non-writeable directories by mistake, as the
543 # temp dir will always be user-writeable.
533 # temp dir will always be user-writeable.
544 curdir = os.getcwdu()
534 curdir = os.getcwdu()
545 testdir = tempfile.gettempdir()
535 testdir = tempfile.gettempdir()
546 os.chdir(testdir)
536 os.chdir(testdir)
547
537
548 # Run all test runners, tracking execution time
538 # Run all test runners, tracking execution time
549 failed = []
539 failed = []
550 t_start = time.time()
540 t_start = time.time()
551 try:
541 try:
552 for (name, runner) in runners:
542 for (name, runner) in runners:
553 print('*'*70)
543 print('*'*70)
554 print('IPython test group:',name)
544 print('IPython test group:',name)
555 res = runner.run()
545 res = runner.run()
556 if res:
546 if res:
557 failed.append( (name, runner) )
547 failed.append( (name, runner) )
558 if res == -signal.SIGINT:
548 if res == -signal.SIGINT:
559 print("Interrupted")
549 print("Interrupted")
560 break
550 break
561 finally:
551 finally:
562 os.chdir(curdir)
552 os.chdir(curdir)
563 t_end = time.time()
553 t_end = time.time()
564 t_tests = t_end - t_start
554 t_tests = t_end - t_start
565 nrunners = len(runners)
555 nrunners = len(runners)
566 nfail = len(failed)
556 nfail = len(failed)
567 # summarize results
557 # summarize results
568 print()
558 print()
569 print('*'*70)
559 print('*'*70)
570 print('Test suite completed for system with the following information:')
560 print('Test suite completed for system with the following information:')
571 print(report())
561 print(report())
572 print('Ran %s test groups in %.3fs' % (nrunners, t_tests))
562 print('Ran %s test groups in %.3fs' % (nrunners, t_tests))
573 print()
563 print()
574 print('Status:')
564 print('Status:')
575 if not failed:
565 if not failed:
576 print('OK')
566 print('OK')
577 else:
567 else:
578 # If anything went wrong, point out what command to rerun manually to
568 # If anything went wrong, point out what command to rerun manually to
579 # see the actual errors and individual summary
569 # see the actual errors and individual summary
580 print('ERROR - %s out of %s test groups failed.' % (nfail, nrunners))
570 print('ERROR - %s out of %s test groups failed.' % (nfail, nrunners))
581 for name, failed_runner in failed:
571 for name, failed_runner in failed:
582 print('-'*40)
572 print('-'*40)
583 print('Runner failed:',name)
573 print('Runner failed:',name)
584 print('You may wish to rerun this one individually, with:')
574 print('You may wish to rerun this one individually, with:')
585 failed_call_args = [py3compat.cast_unicode(x) for x in failed_runner.call_args]
575 failed_call_args = [py3compat.cast_unicode(x) for x in failed_runner.call_args]
586 print(u' '.join(failed_call_args))
576 print(u' '.join(failed_call_args))
587 print()
577 print()
588 # Ensure that our exit code indicates failure
578 # Ensure that our exit code indicates failure
589 sys.exit(1)
579 sys.exit(1)
590
580
591
581
592 def main():
582 def main():
593 for arg in sys.argv[1:]:
583 for arg in sys.argv[1:]:
594 if arg.startswith('IPython'):
584 if arg.startswith('IPython'):
595 # This is in-process
585 # This is in-process
596 run_iptest()
586 run_iptest()
597 else:
587 else:
598 if "--all" in sys.argv:
588 if "--all" in sys.argv:
599 sys.argv.remove("--all")
589 sys.argv.remove("--all")
600 inc_slow = True
590 inc_slow = True
601 else:
591 else:
602 inc_slow = False
592 inc_slow = False
603 # This starts subprocesses
593 # This starts subprocesses
604 run_iptestall(inc_slow=inc_slow)
594 run_iptestall(inc_slow=inc_slow)
605
595
606
596
607 if __name__ == '__main__':
597 if __name__ == '__main__':
608 main()
598 main()
@@ -1,73 +1,51 b''
1 #-----------------------------------------------------------------------------
1 #-----------------------------------------------------------------------------
2 # Copyright (C) 2010 The IPython Development Team
2 # Copyright (C) 2010 The IPython Development Team
3 #
3 #
4 # Distributed under the terms of the BSD License. The full license is in
4 # Distributed under the terms of the BSD License. The full license is in
5 # the file COPYING.txt, distributed as part of this software.
5 # the file COPYING.txt, distributed as part of this software.
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Verify zmq version dependency >= 2.1.4
9 # Verify zmq version dependency >= 2.1.11
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import warnings
12 import warnings
13 from distutils.version import LooseVersion as V
13 from IPython.utils.version import check_version
14
14
15
15
16 def patch_pyzmq():
16 def patch_pyzmq():
17 """backport a few patches from newer pyzmq
17 """backport a few patches from newer pyzmq
18
18
19 These can be removed as we bump our minimum pyzmq version
19 These can be removed as we bump our minimum pyzmq version
20 """
20 """
21
21
22 import zmq
22 import zmq
23
23
24 # ioloop.install, introduced in pyzmq 2.1.7
25 from zmq.eventloop import ioloop
26
27 def install():
28 import tornado.ioloop
29 tornado.ioloop.IOLoop = ioloop.IOLoop
30
31 if not hasattr(ioloop, 'install'):
32 ioloop.install = install
33
34 # fix missing DEALER/ROUTER aliases in pyzmq < 2.1.9
35 if not hasattr(zmq, 'DEALER'):
36 zmq.DEALER = zmq.XREQ
37 if not hasattr(zmq, 'ROUTER'):
38 zmq.ROUTER = zmq.XREP
39
40 # fallback on stdlib json if jsonlib is selected, because jsonlib breaks things.
24 # fallback on stdlib json if jsonlib is selected, because jsonlib breaks things.
41 # jsonlib support is removed from pyzmq >= 2.2.0
25 # jsonlib support is removed from pyzmq >= 2.2.0
42
26
43 from zmq.utils import jsonapi
27 from zmq.utils import jsonapi
44 if jsonapi.jsonmod.__name__ == 'jsonlib':
28 if jsonapi.jsonmod.__name__ == 'jsonlib':
45 import json
29 import json
46 jsonapi.jsonmod = json
30 jsonapi.jsonmod = json
47
31
48
32
49 def check_for_zmq(minimum_version, module='IPython.zmq'):
33 def check_for_zmq(minimum_version, module='IPython.zmq'):
50 try:
34 try:
51 import zmq
35 import zmq
52 except ImportError:
36 except ImportError:
53 raise ImportError("%s requires pyzmq >= %s"%(module, minimum_version))
37 raise ImportError("%s requires pyzmq >= %s"%(module, minimum_version))
54
38
55 pyzmq_version = zmq.__version__
39 pyzmq_version = zmq.__version__
56
40
57 if 'dev' not in pyzmq_version and V(pyzmq_version) < V(minimum_version):
41 if not check_version(pyzmq_version, minimum_version):
58 raise ImportError("%s requires pyzmq >= %s, but you have %s"%(
42 raise ImportError("%s requires pyzmq >= %s, but you have %s"%(
59 module, minimum_version, pyzmq_version))
43 module, minimum_version, pyzmq_version))
60
44
61 if V(zmq.zmq_version()) >= V('4.0.0'):
45 check_for_zmq('2.1.11')
62 warnings.warn("""libzmq 4 detected.
63 It is unlikely that IPython's zmq code will work properly.
64 Please install libzmq stable, which is 2.1.x or 2.2.x""",
65 RuntimeWarning)
66
67 check_for_zmq('2.1.4')
68 patch_pyzmq()
46 patch_pyzmq()
69
47
70 from .blockingkernelmanager import BlockingKernelManager
48 from .blockingkernelmanager import BlockingKernelManager
71 from .kernelmanager import *
49 from .kernelmanager import *
72 from .session import Session
50 from .session import Session
73
51
@@ -1,302 +1,302 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """Setup script for IPython.
3 """Setup script for IPython.
4
4
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (c) 2008-2011, IPython Development Team.
10 # Copyright (c) 2008-2011, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.txt, distributed with this software.
17 # The full license is in the file COPYING.txt, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Minimal Python version sanity check
21 # Minimal Python version sanity check
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 from __future__ import print_function
23 from __future__ import print_function
24
24
25 import sys
25 import sys
26
26
27 # This check is also made in IPython/__init__, don't forget to update both when
27 # This check is also made in IPython/__init__, don't forget to update both when
28 # changing Python version requirements.
28 # changing Python version requirements.
29 #~ if sys.version[0:3] < '2.6':
29 #~ if sys.version[0:3] < '2.6':
30 #~ error = """\
30 #~ error = """\
31 #~ ERROR: 'IPython requires Python Version 2.6 or above.'
31 #~ ERROR: 'IPython requires Python Version 2.6 or above.'
32 #~ Exiting."""
32 #~ Exiting."""
33 #~ print >> sys.stderr, error
33 #~ print >> sys.stderr, error
34 #~ sys.exit(1)
34 #~ sys.exit(1)
35
35
36 PY3 = (sys.version_info[0] >= 3)
36 PY3 = (sys.version_info[0] >= 3)
37
37
38 # At least we're on the python version we need, move on.
38 # At least we're on the python version we need, move on.
39
39
40 #-------------------------------------------------------------------------------
40 #-------------------------------------------------------------------------------
41 # Imports
41 # Imports
42 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
43
43
44 # Stdlib imports
44 # Stdlib imports
45 import os
45 import os
46 import shutil
46 import shutil
47
47
48 from glob import glob
48 from glob import glob
49
49
50 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
50 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
51 # update it when the contents of directories change.
51 # update it when the contents of directories change.
52 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
52 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
53
53
54 from distutils.core import setup
54 from distutils.core import setup
55
55
56 # On Python 3, we need distribute (new setuptools) to do the 2to3 conversion
56 # On Python 3, we need distribute (new setuptools) to do the 2to3 conversion
57 if PY3:
57 if PY3:
58 import setuptools
58 import setuptools
59
59
60 # Our own imports
60 # Our own imports
61 from setupbase import target_update
61 from setupbase import target_update
62
62
63 from setupbase import (
63 from setupbase import (
64 setup_args,
64 setup_args,
65 find_packages,
65 find_packages,
66 find_package_data,
66 find_package_data,
67 find_scripts,
67 find_scripts,
68 find_data_files,
68 find_data_files,
69 check_for_dependencies,
69 check_for_dependencies,
70 record_commit_info,
70 record_commit_info,
71 )
71 )
72 from setupext import setupext
72 from setupext import setupext
73
73
74 isfile = os.path.isfile
74 isfile = os.path.isfile
75 pjoin = os.path.join
75 pjoin = os.path.join
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Function definitions
78 # Function definitions
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81 def cleanup():
81 def cleanup():
82 """Clean up the junk left around by the build process"""
82 """Clean up the junk left around by the build process"""
83 if "develop" not in sys.argv and "egg_info" not in sys.argv:
83 if "develop" not in sys.argv and "egg_info" not in sys.argv:
84 try:
84 try:
85 shutil.rmtree('ipython.egg-info')
85 shutil.rmtree('ipython.egg-info')
86 except:
86 except:
87 try:
87 try:
88 os.unlink('ipython.egg-info')
88 os.unlink('ipython.egg-info')
89 except:
89 except:
90 pass
90 pass
91
91
92 #-------------------------------------------------------------------------------
92 #-------------------------------------------------------------------------------
93 # Handle OS specific things
93 # Handle OS specific things
94 #-------------------------------------------------------------------------------
94 #-------------------------------------------------------------------------------
95
95
96 if os.name == 'posix':
96 if os.name == 'posix':
97 os_name = 'posix'
97 os_name = 'posix'
98 elif os.name in ['nt','dos']:
98 elif os.name in ['nt','dos']:
99 os_name = 'windows'
99 os_name = 'windows'
100 else:
100 else:
101 print('Unsupported operating system:',os.name)
101 print('Unsupported operating system:',os.name)
102 sys.exit(1)
102 sys.exit(1)
103
103
104 # Under Windows, 'sdist' has not been supported. Now that the docs build with
104 # Under Windows, 'sdist' has not been supported. Now that the docs build with
105 # Sphinx it might work, but let's not turn it on until someone confirms that it
105 # Sphinx it might work, but let's not turn it on until someone confirms that it
106 # actually works.
106 # actually works.
107 if os_name == 'windows' and 'sdist' in sys.argv:
107 if os_name == 'windows' and 'sdist' in sys.argv:
108 print('The sdist command is not available under Windows. Exiting.')
108 print('The sdist command is not available under Windows. Exiting.')
109 sys.exit(1)
109 sys.exit(1)
110
110
111 #-------------------------------------------------------------------------------
111 #-------------------------------------------------------------------------------
112 # Things related to the IPython documentation
112 # Things related to the IPython documentation
113 #-------------------------------------------------------------------------------
113 #-------------------------------------------------------------------------------
114
114
115 # update the manuals when building a source dist
115 # update the manuals when building a source dist
116 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
116 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
117 import textwrap
117 import textwrap
118
118
119 # List of things to be updated. Each entry is a triplet of args for
119 # List of things to be updated. Each entry is a triplet of args for
120 # target_update()
120 # target_update()
121 to_update = [
121 to_update = [
122 # FIXME - Disabled for now: we need to redo an automatic way
122 # FIXME - Disabled for now: we need to redo an automatic way
123 # of generating the magic info inside the rst.
123 # of generating the magic info inside the rst.
124 #('docs/magic.tex',
124 #('docs/magic.tex',
125 #['IPython/Magic.py'],
125 #['IPython/Magic.py'],
126 #"cd doc && ./update_magic.sh" ),
126 #"cd doc && ./update_magic.sh" ),
127
127
128 ('docs/man/ipcluster.1.gz',
128 ('docs/man/ipcluster.1.gz',
129 ['docs/man/ipcluster.1'],
129 ['docs/man/ipcluster.1'],
130 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
130 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
131
131
132 ('docs/man/ipcontroller.1.gz',
132 ('docs/man/ipcontroller.1.gz',
133 ['docs/man/ipcontroller.1'],
133 ['docs/man/ipcontroller.1'],
134 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
134 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
135
135
136 ('docs/man/ipengine.1.gz',
136 ('docs/man/ipengine.1.gz',
137 ['docs/man/ipengine.1'],
137 ['docs/man/ipengine.1'],
138 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
138 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
139
139
140 ('docs/man/iplogger.1.gz',
140 ('docs/man/iplogger.1.gz',
141 ['docs/man/iplogger.1'],
141 ['docs/man/iplogger.1'],
142 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
142 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
143
143
144 ('docs/man/ipython.1.gz',
144 ('docs/man/ipython.1.gz',
145 ['docs/man/ipython.1'],
145 ['docs/man/ipython.1'],
146 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
146 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
147
147
148 ('docs/man/irunner.1.gz',
148 ('docs/man/irunner.1.gz',
149 ['docs/man/irunner.1'],
149 ['docs/man/irunner.1'],
150 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
150 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
151
151
152 ('docs/man/pycolor.1.gz',
152 ('docs/man/pycolor.1.gz',
153 ['docs/man/pycolor.1'],
153 ['docs/man/pycolor.1'],
154 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
154 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
155 ]
155 ]
156
156
157
157
158 [ target_update(*t) for t in to_update ]
158 [ target_update(*t) for t in to_update ]
159
159
160 #---------------------------------------------------------------------------
160 #---------------------------------------------------------------------------
161 # Find all the packages, package data, and data_files
161 # Find all the packages, package data, and data_files
162 #---------------------------------------------------------------------------
162 #---------------------------------------------------------------------------
163
163
164 packages = find_packages()
164 packages = find_packages()
165 package_data = find_package_data()
165 package_data = find_package_data()
166 data_files = find_data_files()
166 data_files = find_data_files()
167
167
168 setup_args['packages'] = packages
168 setup_args['packages'] = packages
169 setup_args['package_data'] = package_data
169 setup_args['package_data'] = package_data
170 setup_args['data_files'] = data_files
170 setup_args['data_files'] = data_files
171
171
172 #---------------------------------------------------------------------------
172 #---------------------------------------------------------------------------
173 # custom distutils commands
173 # custom distutils commands
174 #---------------------------------------------------------------------------
174 #---------------------------------------------------------------------------
175 # imports here, so they are after setuptools import if there was one
175 # imports here, so they are after setuptools import if there was one
176 from distutils.command.sdist import sdist
176 from distutils.command.sdist import sdist
177 from distutils.command.upload import upload
177 from distutils.command.upload import upload
178
178
179 class UploadWindowsInstallers(upload):
179 class UploadWindowsInstallers(upload):
180
180
181 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
181 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
182 user_options = upload.user_options + [
182 user_options = upload.user_options + [
183 ('files=', 'f', 'exe file (or glob) to upload')
183 ('files=', 'f', 'exe file (or glob) to upload')
184 ]
184 ]
185 def initialize_options(self):
185 def initialize_options(self):
186 upload.initialize_options(self)
186 upload.initialize_options(self)
187 meta = self.distribution.metadata
187 meta = self.distribution.metadata
188 base = '{name}-{version}'.format(
188 base = '{name}-{version}'.format(
189 name=meta.get_name(),
189 name=meta.get_name(),
190 version=meta.get_version()
190 version=meta.get_version()
191 )
191 )
192 self.files = os.path.join('dist', '%s.*.exe' % base)
192 self.files = os.path.join('dist', '%s.*.exe' % base)
193
193
194 def run(self):
194 def run(self):
195 for dist_file in glob(self.files):
195 for dist_file in glob(self.files):
196 self.upload_file('bdist_wininst', 'any', dist_file)
196 self.upload_file('bdist_wininst', 'any', dist_file)
197
197
198 setup_args['cmdclass'] = {
198 setup_args['cmdclass'] = {
199 'build_py': record_commit_info('IPython'),
199 'build_py': record_commit_info('IPython'),
200 'sdist' : record_commit_info('IPython', sdist),
200 'sdist' : record_commit_info('IPython', sdist),
201 'upload_wininst' : UploadWindowsInstallers,
201 'upload_wininst' : UploadWindowsInstallers,
202 }
202 }
203
203
204 #---------------------------------------------------------------------------
204 #---------------------------------------------------------------------------
205 # Handle scripts, dependencies, and setuptools specific things
205 # Handle scripts, dependencies, and setuptools specific things
206 #---------------------------------------------------------------------------
206 #---------------------------------------------------------------------------
207
207
208 # For some commands, use setuptools. Note that we do NOT list install here!
208 # For some commands, use setuptools. Note that we do NOT list install here!
209 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
209 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
210 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
210 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
211 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
211 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
212 'egg_info', 'easy_install', 'upload',
212 'egg_info', 'easy_install', 'upload',
213 ))
213 ))
214 if sys.platform == 'win32':
214 if sys.platform == 'win32':
215 # Depend on setuptools for install on *Windows only*
215 # Depend on setuptools for install on *Windows only*
216 # If we get script-installation working without setuptools,
216 # If we get script-installation working without setuptools,
217 # then we can back off, but until then use it.
217 # then we can back off, but until then use it.
218 # See Issue #369 on GitHub for more
218 # See Issue #369 on GitHub for more
219 needs_setuptools.add('install')
219 needs_setuptools.add('install')
220
220
221 if len(needs_setuptools.intersection(sys.argv)) > 0:
221 if len(needs_setuptools.intersection(sys.argv)) > 0:
222 import setuptools
222 import setuptools
223
223
224 # This dict is used for passing extra arguments that are setuptools
224 # This dict is used for passing extra arguments that are setuptools
225 # specific to setup
225 # specific to setup
226 setuptools_extra_args = {}
226 setuptools_extra_args = {}
227
227
228 if 'setuptools' in sys.modules:
228 if 'setuptools' in sys.modules:
229 setuptools_extra_args['zip_safe'] = False
229 setuptools_extra_args['zip_safe'] = False
230 setuptools_extra_args['entry_points'] = find_scripts(True)
230 setuptools_extra_args['entry_points'] = find_scripts(True)
231 setup_args['extras_require'] = dict(
231 setup_args['extras_require'] = dict(
232 parallel = 'pyzmq>=2.1.4',
232 parallel = 'pyzmq>=2.1.11',
233 qtconsole = ['pyzmq>=2.1.4', 'pygments'],
233 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
234 zmq = 'pyzmq>=2.1.4',
234 zmq = 'pyzmq>=2.1.11',
235 doc = 'Sphinx>=0.3',
235 doc = 'Sphinx>=0.3',
236 test = 'nose>=0.10.1',
236 test = 'nose>=0.10.1',
237 notebook = ['tornado>=2.0', 'pyzmq>=2.1.4', 'jinja2'],
237 notebook = ['tornado>=2.0', 'pyzmq>=2.1.11', 'jinja2'],
238 )
238 )
239 requires = setup_args.setdefault('install_requires', [])
239 requires = setup_args.setdefault('install_requires', [])
240 setupext.display_status = False
240 setupext.display_status = False
241 if not setupext.check_for_readline():
241 if not setupext.check_for_readline():
242 if sys.platform == 'darwin':
242 if sys.platform == 'darwin':
243 requires.append('readline')
243 requires.append('readline')
244 elif sys.platform.startswith('win'):
244 elif sys.platform.startswith('win'):
245 # Pyreadline 64 bit windows issue solved in versions >=1.7.1
245 # Pyreadline 64 bit windows issue solved in versions >=1.7.1
246 # Also solves issues with some older versions of pyreadline that
246 # Also solves issues with some older versions of pyreadline that
247 # satisfy the unconstrained depdendency.
247 # satisfy the unconstrained depdendency.
248 requires.append('pyreadline>=1.7.1')
248 requires.append('pyreadline>=1.7.1')
249 else:
249 else:
250 pass
250 pass
251 # do we want to install readline here?
251 # do we want to install readline here?
252
252
253 # Script to be run by the windows binary installer after the default setup
253 # Script to be run by the windows binary installer after the default setup
254 # routine, to add shortcuts and similar windows-only things. Windows
254 # routine, to add shortcuts and similar windows-only things. Windows
255 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
255 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
256 # doesn't find them.
256 # doesn't find them.
257 if 'bdist_wininst' in sys.argv:
257 if 'bdist_wininst' in sys.argv:
258 if len(sys.argv) > 2 and \
258 if len(sys.argv) > 2 and \
259 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
259 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
260 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
260 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
261 sys.exit(1)
261 sys.exit(1)
262 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
262 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
263 setup_args['options'] = {"bdist_wininst":
263 setup_args['options'] = {"bdist_wininst":
264 {"install_script":
264 {"install_script":
265 "ipython_win_post_install.py"}}
265 "ipython_win_post_install.py"}}
266
266
267 if PY3:
267 if PY3:
268 setuptools_extra_args['use_2to3'] = True
268 setuptools_extra_args['use_2to3'] = True
269 # we try to make a 2.6, 2.7, and 3.1 to 3.3 python compatible code
269 # we try to make a 2.6, 2.7, and 3.1 to 3.3 python compatible code
270 # so we explicitly disable some 2to3 fixes to be sure we aren't forgetting
270 # so we explicitly disable some 2to3 fixes to be sure we aren't forgetting
271 # anything.
271 # anything.
272 setuptools_extra_args['use_2to3_exclude_fixers'] = [
272 setuptools_extra_args['use_2to3_exclude_fixers'] = [
273 'lib2to3.fixes.fix_apply',
273 'lib2to3.fixes.fix_apply',
274 'lib2to3.fixes.fix_except',
274 'lib2to3.fixes.fix_except',
275 'lib2to3.fixes.fix_has_key',
275 'lib2to3.fixes.fix_has_key',
276 'lib2to3.fixes.fix_next',
276 'lib2to3.fixes.fix_next',
277 'lib2to3.fixes.fix_repr',
277 'lib2to3.fixes.fix_repr',
278 'lib2to3.fixes.fix_tuple_params',
278 'lib2to3.fixes.fix_tuple_params',
279 ]
279 ]
280 from setuptools.command.build_py import build_py
280 from setuptools.command.build_py import build_py
281 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython', build_cmd=build_py)}
281 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython', build_cmd=build_py)}
282 setuptools_extra_args['entry_points'] = find_scripts(True, suffix='3')
282 setuptools_extra_args['entry_points'] = find_scripts(True, suffix='3')
283 setuptools._dont_write_bytecode = True
283 setuptools._dont_write_bytecode = True
284 else:
284 else:
285 # If we are running without setuptools, call this function which will
285 # If we are running without setuptools, call this function which will
286 # check for dependencies an inform the user what is needed. This is
286 # check for dependencies an inform the user what is needed. This is
287 # just to make life easy for users.
287 # just to make life easy for users.
288 check_for_dependencies()
288 check_for_dependencies()
289 setup_args['scripts'] = find_scripts(False)
289 setup_args['scripts'] = find_scripts(False)
290
290
291 #---------------------------------------------------------------------------
291 #---------------------------------------------------------------------------
292 # Do the actual setup now
292 # Do the actual setup now
293 #---------------------------------------------------------------------------
293 #---------------------------------------------------------------------------
294
294
295 setup_args.update(setuptools_extra_args)
295 setup_args.update(setuptools_extra_args)
296
296
297 def main():
297 def main():
298 setup(**setup_args)
298 setup(**setup_args)
299 cleanup()
299 cleanup()
300
300
301 if __name__ == '__main__':
301 if __name__ == '__main__':
302 main()
302 main()
@@ -1,182 +1,172 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 from __future__ import print_function
2 from __future__ import print_function
3
3
4 __docformat__ = "restructuredtext en"
4 __docformat__ = "restructuredtext en"
5
5
6 #-------------------------------------------------------------------------------
6 #-------------------------------------------------------------------------------
7 # Copyright (C) 2008 The IPython Development Team
7 # Copyright (C) 2008 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12
12
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
16
16
17 import sys, os
17 import sys, os
18 from textwrap import fill
18 from textwrap import fill
19
19
20 display_status=True
20 display_status=True
21
21
22 def check_display(f):
22 def check_display(f):
23 """decorator to allow display methods to be muted by mod.display_status"""
23 """decorator to allow display methods to be muted by mod.display_status"""
24 def maybe_display(*args, **kwargs):
24 def maybe_display(*args, **kwargs):
25 if display_status:
25 if display_status:
26 return f(*args, **kwargs)
26 return f(*args, **kwargs)
27 return maybe_display
27 return maybe_display
28
28
29 @check_display
29 @check_display
30 def print_line(char='='):
30 def print_line(char='='):
31 print(char * 76)
31 print(char * 76)
32
32
33 @check_display
33 @check_display
34 def print_status(package, status):
34 def print_status(package, status):
35 initial_indent = "%22s: " % package
35 initial_indent = "%22s: " % package
36 indent = ' ' * 24
36 indent = ' ' * 24
37 print(fill(str(status), width=76,
37 print(fill(str(status), width=76,
38 initial_indent=initial_indent,
38 initial_indent=initial_indent,
39 subsequent_indent=indent))
39 subsequent_indent=indent))
40
40
41 @check_display
41 @check_display
42 def print_message(message):
42 def print_message(message):
43 indent = ' ' * 24 + "* "
43 indent = ' ' * 24 + "* "
44 print(fill(str(message), width=76,
44 print(fill(str(message), width=76,
45 initial_indent=indent,
45 initial_indent=indent,
46 subsequent_indent=indent))
46 subsequent_indent=indent))
47
47
48 @check_display
48 @check_display
49 def print_raw(section):
49 def print_raw(section):
50 print(section)
50 print(section)
51
51
52 #-------------------------------------------------------------------------------
52 #-------------------------------------------------------------------------------
53 # Tests for specific packages
53 # Tests for specific packages
54 #-------------------------------------------------------------------------------
54 #-------------------------------------------------------------------------------
55
55
56 def check_for_ipython():
56 def check_for_ipython():
57 try:
57 try:
58 import IPython
58 import IPython
59 except ImportError:
59 except ImportError:
60 print_status("IPython", "Not found")
60 print_status("IPython", "Not found")
61 return False
61 return False
62 else:
62 else:
63 print_status("IPython", IPython.__version__)
63 print_status("IPython", IPython.__version__)
64 return True
64 return True
65
65
66 def check_for_sphinx():
66 def check_for_sphinx():
67 try:
67 try:
68 import sphinx
68 import sphinx
69 except ImportError:
69 except ImportError:
70 print_status('sphinx', "Not found (required for building documentation)")
70 print_status('sphinx', "Not found (required for building documentation)")
71 return False
71 return False
72 else:
72 else:
73 print_status('sphinx', sphinx.__version__)
73 print_status('sphinx', sphinx.__version__)
74 return True
74 return True
75
75
76 def check_for_pygments():
76 def check_for_pygments():
77 try:
77 try:
78 import pygments
78 import pygments
79 except ImportError:
79 except ImportError:
80 print_status('pygments', "Not found (required for syntax highlighting documentation)")
80 print_status('pygments', "Not found (required for syntax highlighting documentation)")
81 return False
81 return False
82 else:
82 else:
83 print_status('pygments', pygments.__version__)
83 print_status('pygments', pygments.__version__)
84 return True
84 return True
85
85
86 def check_for_nose():
86 def check_for_nose():
87 try:
87 try:
88 import nose
88 import nose
89 except ImportError:
89 except ImportError:
90 print_status('nose', "Not found (required for running the test suite)")
90 print_status('nose', "Not found (required for running the test suite)")
91 return False
91 return False
92 else:
92 else:
93 print_status('nose', nose.__version__)
93 print_status('nose', nose.__version__)
94 return True
94 return True
95
95
96 def check_for_pexpect():
96 def check_for_pexpect():
97 try:
97 try:
98 import pexpect
98 import pexpect
99 except ImportError:
99 except ImportError:
100 print_status("pexpect", "no (required for running standalone doctests)")
100 print_status("pexpect", "no (required for running standalone doctests)")
101 return False
101 return False
102 else:
102 else:
103 print_status("pexpect", pexpect.__version__)
103 print_status("pexpect", pexpect.__version__)
104 return True
104 return True
105
105
106 def check_for_httplib2():
106 def check_for_httplib2():
107 try:
107 try:
108 import httplib2
108 import httplib2
109 except ImportError:
109 except ImportError:
110 print_status("httplib2", "no (required for blocking http clients)")
110 print_status("httplib2", "no (required for blocking http clients)")
111 return False
111 return False
112 else:
112 else:
113 print_status("httplib2","yes")
113 print_status("httplib2","yes")
114 return True
114 return True
115
115
116 def check_for_sqlalchemy():
116 def check_for_sqlalchemy():
117 try:
117 try:
118 import sqlalchemy
118 import sqlalchemy
119 except ImportError:
119 except ImportError:
120 print_status("sqlalchemy", "no (required for the ipython1 notebook)")
120 print_status("sqlalchemy", "no (required for the ipython1 notebook)")
121 return False
121 return False
122 else:
122 else:
123 print_status("sqlalchemy","yes")
123 print_status("sqlalchemy","yes")
124 return True
124 return True
125
125
126 def check_for_simplejson():
126 def check_for_simplejson():
127 try:
127 try:
128 import simplejson
128 import simplejson
129 except ImportError:
129 except ImportError:
130 print_status("simplejson", "no (required for the ipython1 notebook)")
130 print_status("simplejson", "no (required for the ipython1 notebook)")
131 return False
131 return False
132 else:
132 else:
133 print_status("simplejson","yes")
133 print_status("simplejson","yes")
134 return True
134 return True
135
135
136 def check_for_pyzmq():
136 def check_for_pyzmq():
137 try:
137 try:
138 import zmq
138 import zmq
139 except ImportError:
139 except ImportError:
140 print_status('pyzmq', "no (required for qtconsole, notebook, and parallel computing capabilities)")
140 print_status('pyzmq', "no (required for qtconsole, notebook, and parallel computing capabilities)")
141 return False
141 return False
142 else:
142 else:
143 # pyzmq 2.1.10 adds pyzmq_version_info funtion for returning
143 # pyzmq 2.1.10 adds pyzmq_version_info funtion for returning
144 # version as a tuple
144 # version as a tuple
145 if hasattr(zmq, 'pyzmq_version_info'):
145 if hasattr(zmq, 'pyzmq_version_info') and zmq.pyzmq_version_info() >= (2,1,11):
146 if zmq.pyzmq_version_info() >= (2,1,4):
147 print_status("pyzmq", zmq.__version__)
146 print_status("pyzmq", zmq.__version__)
148 return True
147 return True
149 else:
150 # this branch can never occur, at least until we update our
151 # pyzmq dependency beyond 2.1.10
152 return False
153 # this is necessarily earlier than 2.1.10, so string comparison is
154 # okay
155 if zmq.__version__ < '2.1.4':
156 print_status('pyzmq', "no (have %s, but require >= 2.1.4 for"
157 " qtconsole and parallel computing capabilities)"%zmq.__version__)
158 return False
159 else:
148 else:
160 print_status("pyzmq", zmq.__version__)
149 print_status('pyzmq', "no (have %s, but require >= 2.1.11 for"
161 return True
150 " qtconsole, notebook, and parallel computing capabilities)" % zmq.__version__)
151 return False
162
152
163 def check_for_readline():
153 def check_for_readline():
164 from distutils.version import LooseVersion
154 from distutils.version import LooseVersion
165 try:
155 try:
166 import readline
156 import readline
167 except ImportError:
157 except ImportError:
168 try:
158 try:
169 import pyreadline
159 import pyreadline
170 vs = pyreadline.release.version
160 vs = pyreadline.release.version
171 except (ImportError, AttributeError):
161 except (ImportError, AttributeError):
172 print_status('readline', "no (required for good interactive behavior)")
162 print_status('readline', "no (required for good interactive behavior)")
173 return False
163 return False
174 if LooseVersion(vs).version >= [1,7,1]:
164 if LooseVersion(vs).version >= [1,7,1]:
175 print_status('readline', "yes pyreadline-" + vs)
165 print_status('readline', "yes pyreadline-" + vs)
176 return True
166 return True
177 else:
167 else:
178 print_status('readline', "no pyreadline-%s < 1.7.1" % vs)
168 print_status('readline', "no pyreadline-%s < 1.7.1" % vs)
179 return False
169 return False
180 else:
170 else:
181 print_status('readline', "yes")
171 print_status('readline', "yes")
182 return True
172 return True
General Comments 0
You need to be logged in to leave comments. Login now