##// END OF EJS Templates
Make single setup script work on Python 2 and Python 3.
Thomas Kluyver -
Show More
@@ -1,272 +1,286 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
24
24 import sys
25 import sys
25
26
26 # 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
27 # changing Python version requirements.
28 # changing Python version requirements.
28 if sys.version[0:3] < '2.6':
29 #~ if sys.version[0:3] < '2.6':
29 error = """\
30 #~ error = """\
30 ERROR: 'IPython requires Python Version 2.6 or above.'
31 #~ ERROR: 'IPython requires Python Version 2.6 or above.'
31 Exiting."""
32 #~ Exiting."""
32 print >> sys.stderr, error
33 #~ print >> sys.stderr, error
33 sys.exit(1)
34 #~ sys.exit(1)
35
36 PY3 = (sys.version_info[0] >= 3)
34
37
35 # 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.
36
39
37 #-------------------------------------------------------------------------------
40 #-------------------------------------------------------------------------------
38 # Imports
41 # Imports
39 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
40
43
41 # Stdlib imports
44 # Stdlib imports
42 import os
45 import os
43 import shutil
46 import shutil
44
47
45 from glob import glob
48 from glob import glob
46
49
47 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
50 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
48 # update it when the contents of directories change.
51 # update it when the contents of directories change.
49 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
52 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
50
53
51 from distutils.core import setup
54 from distutils.core import setup
52
55
56 # On Python 3, we need distribute (new setuptools) to do the 2to3 conversion
57 if PY3:
58 import setuptools
59
53 # Our own imports
60 # Our own imports
54 from IPython.utils.path import target_update
61 from setupbase import target_update
55
62
56 from setupbase import (
63 from setupbase import (
57 setup_args,
64 setup_args,
58 find_packages,
65 find_packages,
59 find_package_data,
66 find_package_data,
60 find_scripts,
67 find_scripts,
61 find_data_files,
68 find_data_files,
62 check_for_dependencies,
69 check_for_dependencies,
63 record_commit_info,
70 record_commit_info,
64 )
71 )
65 from setupext import setupext
72 from setupext import setupext
66
73
67 isfile = os.path.isfile
74 isfile = os.path.isfile
68 pjoin = os.path.join
75 pjoin = os.path.join
69
76
70 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
71 # Function definitions
78 # Function definitions
72 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
73
80
74 def cleanup():
81 def cleanup():
75 """Clean up the junk left around by the build process"""
82 """Clean up the junk left around by the build process"""
76 if "develop" not in sys.argv:
83 if "develop" not in sys.argv:
77 try:
84 try:
78 shutil.rmtree('ipython.egg-info')
85 shutil.rmtree('ipython.egg-info')
79 except:
86 except:
80 try:
87 try:
81 os.unlink('ipython.egg-info')
88 os.unlink('ipython.egg-info')
82 except:
89 except:
83 pass
90 pass
84
91
85 #-------------------------------------------------------------------------------
92 #-------------------------------------------------------------------------------
86 # Handle OS specific things
93 # Handle OS specific things
87 #-------------------------------------------------------------------------------
94 #-------------------------------------------------------------------------------
88
95
89 if os.name == 'posix':
96 if os.name == 'posix':
90 os_name = 'posix'
97 os_name = 'posix'
91 elif os.name in ['nt','dos']:
98 elif os.name in ['nt','dos']:
92 os_name = 'windows'
99 os_name = 'windows'
93 else:
100 else:
94 print 'Unsupported operating system:',os.name
101 print('Unsupported operating system:',os.name)
95 sys.exit(1)
102 sys.exit(1)
96
103
97 # 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
98 # 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
99 # actually works.
106 # actually works.
100 if os_name == 'windows' and 'sdist' in sys.argv:
107 if os_name == 'windows' and 'sdist' in sys.argv:
101 print 'The sdist command is not available under Windows. Exiting.'
108 print('The sdist command is not available under Windows. Exiting.')
102 sys.exit(1)
109 sys.exit(1)
103
110
104 #-------------------------------------------------------------------------------
111 #-------------------------------------------------------------------------------
105 # Things related to the IPython documentation
112 # Things related to the IPython documentation
106 #-------------------------------------------------------------------------------
113 #-------------------------------------------------------------------------------
107
114
108 # update the manuals when building a source dist
115 # update the manuals when building a source dist
109 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'):
110 import textwrap
117 import textwrap
111
118
112 # 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
113 # target_update()
120 # target_update()
114 to_update = [
121 to_update = [
115 # FIXME - Disabled for now: we need to redo an automatic way
122 # FIXME - Disabled for now: we need to redo an automatic way
116 # of generating the magic info inside the rst.
123 # of generating the magic info inside the rst.
117 #('docs/magic.tex',
124 #('docs/magic.tex',
118 #['IPython/Magic.py'],
125 #['IPython/Magic.py'],
119 #"cd doc && ./update_magic.sh" ),
126 #"cd doc && ./update_magic.sh" ),
120
127
121 ('docs/man/ipcluster.1.gz',
128 ('docs/man/ipcluster.1.gz',
122 ['docs/man/ipcluster.1'],
129 ['docs/man/ipcluster.1'],
123 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
130 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
124
131
125 ('docs/man/ipcontroller.1.gz',
132 ('docs/man/ipcontroller.1.gz',
126 ['docs/man/ipcontroller.1'],
133 ['docs/man/ipcontroller.1'],
127 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
134 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
128
135
129 ('docs/man/ipengine.1.gz',
136 ('docs/man/ipengine.1.gz',
130 ['docs/man/ipengine.1'],
137 ['docs/man/ipengine.1'],
131 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
138 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
132
139
133 ('docs/man/iplogger.1.gz',
140 ('docs/man/iplogger.1.gz',
134 ['docs/man/iplogger.1'],
141 ['docs/man/iplogger.1'],
135 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
142 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
136
143
137 ('docs/man/ipython.1.gz',
144 ('docs/man/ipython.1.gz',
138 ['docs/man/ipython.1'],
145 ['docs/man/ipython.1'],
139 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
146 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
140
147
141 ('docs/man/irunner.1.gz',
148 ('docs/man/irunner.1.gz',
142 ['docs/man/irunner.1'],
149 ['docs/man/irunner.1'],
143 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
150 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
144
151
145 ('docs/man/pycolor.1.gz',
152 ('docs/man/pycolor.1.gz',
146 ['docs/man/pycolor.1'],
153 ['docs/man/pycolor.1'],
147 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
154 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
148 ]
155 ]
149
156
150 # Only build the docs if sphinx is present
157 # Only build the docs if sphinx is present
151 try:
158 try:
152 import sphinx
159 import sphinx
153 except ImportError:
160 except ImportError:
154 pass
161 pass
155 else:
162 else:
156 # The Makefile calls the do_sphinx scripts to build html and pdf, so
163 # The Makefile calls the do_sphinx scripts to build html and pdf, so
157 # just one target is enough to cover all manual generation
164 # just one target is enough to cover all manual generation
158
165
159 # First, compute all the dependencies that can force us to rebuild the
166 # First, compute all the dependencies that can force us to rebuild the
160 # docs. Start with the main release file that contains metadata
167 # docs. Start with the main release file that contains metadata
161 docdeps = ['IPython/core/release.py']
168 docdeps = ['IPython/core/release.py']
162 # Inculde all the reST sources
169 # Inculde all the reST sources
163 pjoin = os.path.join
170 pjoin = os.path.join
164 for dirpath,dirnames,filenames in os.walk('docs/source'):
171 for dirpath,dirnames,filenames in os.walk('docs/source'):
165 if dirpath in ['_static','_templates']:
172 if dirpath in ['_static','_templates']:
166 continue
173 continue
167 docdeps += [ pjoin(dirpath,f) for f in filenames
174 docdeps += [ pjoin(dirpath,f) for f in filenames
168 if f.endswith('.txt') ]
175 if f.endswith('.txt') ]
169 # and the examples
176 # and the examples
170 for dirpath,dirnames,filenames in os.walk('docs/example'):
177 for dirpath,dirnames,filenames in os.walk('docs/example'):
171 docdeps += [ pjoin(dirpath,f) for f in filenames
178 docdeps += [ pjoin(dirpath,f) for f in filenames
172 if not f.endswith('~') ]
179 if not f.endswith('~') ]
173 # then, make them all dependencies for the main html docs
180 # then, make them all dependencies for the main html docs
174 to_update.append(
181 to_update.append(
175 ('docs/dist/index.html',
182 ('docs/dist/index.html',
176 docdeps,
183 docdeps,
177 "cd docs && make dist")
184 "cd docs && make dist")
178 )
185 )
179
186
180 [ target_update(*t) for t in to_update ]
187 [ target_update(*t) for t in to_update ]
181
188
182 #---------------------------------------------------------------------------
189 #---------------------------------------------------------------------------
183 # Find all the packages, package data, and data_files
190 # Find all the packages, package data, and data_files
184 #---------------------------------------------------------------------------
191 #---------------------------------------------------------------------------
185
192
186 packages = find_packages()
193 packages = find_packages()
187 package_data = find_package_data()
194 package_data = find_package_data()
188 data_files = find_data_files()
195 data_files = find_data_files()
189
196
197 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython')}
198 setup_args['packages'] = packages
199 setup_args['package_data'] = package_data
200 setup_args['data_files'] = data_files
201
190 #---------------------------------------------------------------------------
202 #---------------------------------------------------------------------------
191 # Handle scripts, dependencies, and setuptools specific things
203 # Handle scripts, dependencies, and setuptools specific things
192 #---------------------------------------------------------------------------
204 #---------------------------------------------------------------------------
193
205
194 # For some commands, use setuptools. Note that we do NOT list install here!
206 # For some commands, use setuptools. Note that we do NOT list install here!
195 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
207 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
196 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
208 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
197 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
209 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
198 'egg_info', 'easy_install', 'upload',
210 'egg_info', 'easy_install', 'upload',
199 ))
211 ))
200 if sys.platform == 'win32':
212 if sys.platform == 'win32':
201 # Depend on setuptools for install on *Windows only*
213 # Depend on setuptools for install on *Windows only*
202 # If we get script-installation working without setuptools,
214 # If we get script-installation working without setuptools,
203 # then we can back off, but until then use it.
215 # then we can back off, but until then use it.
204 # See Issue #369 on GitHub for more
216 # See Issue #369 on GitHub for more
205 needs_setuptools.add('install')
217 needs_setuptools.add('install')
206
218
207 if len(needs_setuptools.intersection(sys.argv)) > 0:
219 if len(needs_setuptools.intersection(sys.argv)) > 0:
208 import setuptools
220 import setuptools
209
221
210 # This dict is used for passing extra arguments that are setuptools
222 # This dict is used for passing extra arguments that are setuptools
211 # specific to setup
223 # specific to setup
212 setuptools_extra_args = {}
224 setuptools_extra_args = {}
213
225
214 if 'setuptools' in sys.modules:
226 if 'setuptools' in sys.modules:
215 setuptools_extra_args['zip_safe'] = False
227 setuptools_extra_args['zip_safe'] = False
216 setuptools_extra_args['entry_points'] = find_scripts(True)
228 setuptools_extra_args['entry_points'] = find_scripts(True)
217 setup_args['extras_require'] = dict(
229 setup_args['extras_require'] = dict(
218 parallel = 'pyzmq>=2.1.4',
230 parallel = 'pyzmq>=2.1.4',
219 zmq = 'pyzmq>=2.1.4',
231 zmq = 'pyzmq>=2.1.4',
220 doc = 'Sphinx>=0.3',
232 doc = 'Sphinx>=0.3',
221 test = 'nose>=0.10.1',
233 test = 'nose>=0.10.1',
222 notebook = 'tornado>=2.0'
234 notebook = 'tornado>=2.0'
223 )
235 )
224 requires = setup_args.setdefault('install_requires', [])
236 requires = setup_args.setdefault('install_requires', [])
225 setupext.display_status = False
237 setupext.display_status = False
226 if not setupext.check_for_readline():
238 if not setupext.check_for_readline():
227 if sys.platform == 'darwin':
239 if sys.platform == 'darwin':
228 requires.append('readline')
240 requires.append('readline')
229 elif sys.platform.startswith('win') and sys.maxsize < 2**32:
241 elif sys.platform.startswith('win') and sys.maxsize < 2**32:
230 # only require pyreadline on 32b Windows, due to 64b bug in pyreadline:
242 # only require pyreadline on 32b Windows, due to 64b bug in pyreadline:
231 # https://bugs.launchpad.net/pyreadline/+bug/787574
243 # https://bugs.launchpad.net/pyreadline/+bug/787574
232 requires.append('pyreadline')
244 requires.append('pyreadline')
233 else:
245 else:
234 pass
246 pass
235 # do we want to install readline here?
247 # do we want to install readline here?
236
248
237 # Script to be run by the windows binary installer after the default setup
249 # Script to be run by the windows binary installer after the default setup
238 # routine, to add shortcuts and similar windows-only things. Windows
250 # routine, to add shortcuts and similar windows-only things. Windows
239 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
251 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
240 # doesn't find them.
252 # doesn't find them.
241 if 'bdist_wininst' in sys.argv:
253 if 'bdist_wininst' in sys.argv:
242 if len(sys.argv) > 2 and \
254 if len(sys.argv) > 2 and \
243 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
255 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
244 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
256 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
245 sys.exit(1)
257 sys.exit(1)
246 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
258 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
247 setup_args['options'] = {"bdist_wininst":
259 setup_args['options'] = {"bdist_wininst":
248 {"install_script":
260 {"install_script":
249 "ipython_win_post_install.py"}}
261 "ipython_win_post_install.py"}}
262
263 if PY3:
264 setuptools_extra_args['use_2to3'] = True
265 from setuptools.command.build_py import build_py
266 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython', build_cmd=build_py)}
267 setuptools_extra_args['entry_points'] = find_scripts(True, suffix='3')
250 else:
268 else:
251 # If we are running without setuptools, call this function which will
269 # If we are running without setuptools, call this function which will
252 # check for dependencies an inform the user what is needed. This is
270 # check for dependencies an inform the user what is needed. This is
253 # just to make life easy for users.
271 # just to make life easy for users.
254 check_for_dependencies()
272 check_for_dependencies()
255 setup_args['scripts'] = find_scripts(False)
273 setup_args['scripts'] = find_scripts(False)
256
274
257 #---------------------------------------------------------------------------
275 #---------------------------------------------------------------------------
258 # Do the actual setup now
276 # Do the actual setup now
259 #---------------------------------------------------------------------------
277 #---------------------------------------------------------------------------
260
278
261 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython')}
262 setup_args['packages'] = packages
263 setup_args['package_data'] = package_data
264 setup_args['data_files'] = data_files
265 setup_args.update(setuptools_extra_args)
279 setup_args.update(setuptools_extra_args)
266
280
267 def main():
281 def main():
268 setup(**setup_args)
282 setup(**setup_args)
269 cleanup()
283 cleanup()
270
284
271 if __name__ == '__main__':
285 if __name__ == '__main__':
272 main()
286 main()
@@ -1,390 +1,428 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 This module defines the things that are used in setup.py for building IPython
3 This module defines the things that are used in setup.py for building IPython
4
4
5 This includes:
5 This includes:
6
6
7 * The basic arguments to setup
7 * The basic arguments to setup
8 * Functions for finding things like packages, package data, etc.
8 * Functions for finding things like packages, package data, etc.
9 * A function for checking dependencies.
9 * A function for checking dependencies.
10 """
10 """
11 from __future__ import print_function
11 from __future__ import print_function
12
12
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19
19
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import os
23 import os
24 import sys
24 import sys
25
25
26 try:
26 try:
27 from configparser import ConfigParser
27 from configparser import ConfigParser
28 except:
28 except:
29 from ConfigParser import ConfigParser
29 from ConfigParser import ConfigParser
30 from distutils.command.build_py import build_py
30 from distutils.command.build_py import build_py
31 from glob import glob
31 from glob import glob
32
32
33 from setupext import install_data_ext
33 from setupext import install_data_ext
34
34
35 #-------------------------------------------------------------------------------
35 #-------------------------------------------------------------------------------
36 # Useful globals and utility functions
36 # Useful globals and utility functions
37 #-------------------------------------------------------------------------------
37 #-------------------------------------------------------------------------------
38
38
39 # A few handy globals
39 # A few handy globals
40 isfile = os.path.isfile
40 isfile = os.path.isfile
41 pjoin = os.path.join
41 pjoin = os.path.join
42
42
43 def oscmd(s):
43 def oscmd(s):
44 print(">", s)
44 print(">", s)
45 os.system(s)
45 os.system(s)
46
46
47 try:
47 try:
48 execfile
48 execfile
49 except NameError:
49 except NameError:
50 def execfile(fname, globs, locs=None):
50 def execfile(fname, globs, locs=None):
51 locs = locs or globs
51 locs = locs or globs
52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
53
53
54 # A little utility we'll need below, since glob() does NOT allow you to do
54 # A little utility we'll need below, since glob() does NOT allow you to do
55 # exclusion on multiple endings!
55 # exclusion on multiple endings!
56 def file_doesnt_endwith(test,endings):
56 def file_doesnt_endwith(test,endings):
57 """Return true if test is a file and its name does NOT end with any
57 """Return true if test is a file and its name does NOT end with any
58 of the strings listed in endings."""
58 of the strings listed in endings."""
59 if not isfile(test):
59 if not isfile(test):
60 return False
60 return False
61 for e in endings:
61 for e in endings:
62 if test.endswith(e):
62 if test.endswith(e):
63 return False
63 return False
64 return True
64 return True
65
65
66 #---------------------------------------------------------------------------
66 #---------------------------------------------------------------------------
67 # Basic project information
67 # Basic project information
68 #---------------------------------------------------------------------------
68 #---------------------------------------------------------------------------
69
69
70 # release.py contains version, authors, license, url, keywords, etc.
70 # release.py contains version, authors, license, url, keywords, etc.
71 execfile(pjoin('IPython','core','release.py'), globals())
71 execfile(pjoin('IPython','core','release.py'), globals())
72
72
73 # Create a dict with the basic information
73 # Create a dict with the basic information
74 # This dict is eventually passed to setup after additional keys are added.
74 # This dict is eventually passed to setup after additional keys are added.
75 setup_args = dict(
75 setup_args = dict(
76 name = name,
76 name = name,
77 version = version,
77 version = version,
78 description = description,
78 description = description,
79 long_description = long_description,
79 long_description = long_description,
80 author = author,
80 author = author,
81 author_email = author_email,
81 author_email = author_email,
82 url = url,
82 url = url,
83 download_url = download_url,
83 download_url = download_url,
84 license = license,
84 license = license,
85 platforms = platforms,
85 platforms = platforms,
86 keywords = keywords,
86 keywords = keywords,
87 classifiers = classifiers,
87 classifiers = classifiers,
88 cmdclass = {'install_data': install_data_ext},
88 cmdclass = {'install_data': install_data_ext},
89 )
89 )
90
90
91
91
92 #---------------------------------------------------------------------------
92 #---------------------------------------------------------------------------
93 # Find packages
93 # Find packages
94 #---------------------------------------------------------------------------
94 #---------------------------------------------------------------------------
95
95
96 def find_packages():
96 def find_packages():
97 """
97 """
98 Find all of IPython's packages.
98 Find all of IPython's packages.
99 """
99 """
100 excludes = ['deathrow']
100 excludes = ['deathrow']
101 packages = []
101 packages = []
102 for dir,subdirs,files in os.walk('IPython'):
102 for dir,subdirs,files in os.walk('IPython'):
103 package = dir.replace(os.path.sep, '.')
103 package = dir.replace(os.path.sep, '.')
104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
105 # package is to be excluded (e.g. deathrow)
105 # package is to be excluded (e.g. deathrow)
106 continue
106 continue
107 if '__init__.py' not in files:
107 if '__init__.py' not in files:
108 # not a package
108 # not a package
109 continue
109 continue
110 packages.append(package)
110 packages.append(package)
111 return packages
111 return packages
112
112
113 #---------------------------------------------------------------------------
113 #---------------------------------------------------------------------------
114 # Find package data
114 # Find package data
115 #---------------------------------------------------------------------------
115 #---------------------------------------------------------------------------
116
116
117 def find_package_data():
117 def find_package_data():
118 """
118 """
119 Find IPython's package_data.
119 Find IPython's package_data.
120 """
120 """
121 # This is not enough for these things to appear in an sdist.
121 # This is not enough for these things to appear in an sdist.
122 # We need to muck with the MANIFEST to get this to work
122 # We need to muck with the MANIFEST to get this to work
123
123
124 # exclude static things that we don't ship (e.g. mathjax)
124 # exclude static things that we don't ship (e.g. mathjax)
125 excludes = ['mathjax']
125 excludes = ['mathjax']
126
126
127 # add 'static/' prefix to exclusions, and tuplify for use in startswith
127 # add 'static/' prefix to exclusions, and tuplify for use in startswith
128 excludes = tuple([os.path.join('static', ex) for ex in excludes])
128 excludes = tuple([os.path.join('static', ex) for ex in excludes])
129
129
130 # walk notebook resources:
130 # walk notebook resources:
131 cwd = os.getcwd()
131 cwd = os.getcwd()
132 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
132 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
133 static_walk = list(os.walk('static'))
133 static_walk = list(os.walk('static'))
134 os.chdir(cwd)
134 os.chdir(cwd)
135 static_data = []
135 static_data = []
136 for parent, dirs, files in static_walk:
136 for parent, dirs, files in static_walk:
137 if parent.startswith(excludes):
137 if parent.startswith(excludes):
138 continue
138 continue
139 for f in files:
139 for f in files:
140 static_data.append(os.path.join(parent, f))
140 static_data.append(os.path.join(parent, f))
141
141
142 package_data = {
142 package_data = {
143 'IPython.config.profile' : ['README*', '*/*.py'],
143 'IPython.config.profile' : ['README*', '*/*.py'],
144 'IPython.testing' : ['*.txt'],
144 'IPython.testing' : ['*.txt'],
145 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
145 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
146 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
146 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
147 }
147 }
148 return package_data
148 return package_data
149
149
150
150
151 #---------------------------------------------------------------------------
151 #---------------------------------------------------------------------------
152 # Find data files
152 # Find data files
153 #---------------------------------------------------------------------------
153 #---------------------------------------------------------------------------
154
154
155 def make_dir_struct(tag,base,out_base):
155 def make_dir_struct(tag,base,out_base):
156 """Make the directory structure of all files below a starting dir.
156 """Make the directory structure of all files below a starting dir.
157
157
158 This is just a convenience routine to help build a nested directory
158 This is just a convenience routine to help build a nested directory
159 hierarchy because distutils is too stupid to do this by itself.
159 hierarchy because distutils is too stupid to do this by itself.
160
160
161 XXX - this needs a proper docstring!
161 XXX - this needs a proper docstring!
162 """
162 """
163
163
164 # we'll use these a lot below
164 # we'll use these a lot below
165 lbase = len(base)
165 lbase = len(base)
166 pathsep = os.path.sep
166 pathsep = os.path.sep
167 lpathsep = len(pathsep)
167 lpathsep = len(pathsep)
168
168
169 out = []
169 out = []
170 for (dirpath,dirnames,filenames) in os.walk(base):
170 for (dirpath,dirnames,filenames) in os.walk(base):
171 # we need to strip out the dirpath from the base to map it to the
171 # we need to strip out the dirpath from the base to map it to the
172 # output (installation) path. This requires possibly stripping the
172 # output (installation) path. This requires possibly stripping the
173 # path separator, because otherwise pjoin will not work correctly
173 # path separator, because otherwise pjoin will not work correctly
174 # (pjoin('foo/','/bar') returns '/bar').
174 # (pjoin('foo/','/bar') returns '/bar').
175
175
176 dp_eff = dirpath[lbase:]
176 dp_eff = dirpath[lbase:]
177 if dp_eff.startswith(pathsep):
177 if dp_eff.startswith(pathsep):
178 dp_eff = dp_eff[lpathsep:]
178 dp_eff = dp_eff[lpathsep:]
179 # The output path must be anchored at the out_base marker
179 # The output path must be anchored at the out_base marker
180 out_path = pjoin(out_base,dp_eff)
180 out_path = pjoin(out_base,dp_eff)
181 # Now we can generate the final filenames. Since os.walk only produces
181 # Now we can generate the final filenames. Since os.walk only produces
182 # filenames, we must join back with the dirpath to get full valid file
182 # filenames, we must join back with the dirpath to get full valid file
183 # paths:
183 # paths:
184 pfiles = [pjoin(dirpath,f) for f in filenames]
184 pfiles = [pjoin(dirpath,f) for f in filenames]
185 # Finally, generate the entry we need, which is a pari of (output
185 # Finally, generate the entry we need, which is a pari of (output
186 # path, files) for use as a data_files parameter in install_data.
186 # path, files) for use as a data_files parameter in install_data.
187 out.append((out_path, pfiles))
187 out.append((out_path, pfiles))
188
188
189 return out
189 return out
190
190
191
191
192 def find_data_files():
192 def find_data_files():
193 """
193 """
194 Find IPython's data_files.
194 Find IPython's data_files.
195
195
196 Most of these are docs.
196 Most of these are docs.
197 """
197 """
198
198
199 docdirbase = pjoin('share', 'doc', 'ipython')
199 docdirbase = pjoin('share', 'doc', 'ipython')
200 manpagebase = pjoin('share', 'man', 'man1')
200 manpagebase = pjoin('share', 'man', 'man1')
201
201
202 # Simple file lists can be made by hand
202 # Simple file lists can be made by hand
203 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
203 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
204 if not manpages:
204 if not manpages:
205 # When running from a source tree, the manpages aren't gzipped
205 # When running from a source tree, the manpages aren't gzipped
206 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
206 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
207 igridhelpfiles = filter(isfile,
207 igridhelpfiles = filter(isfile,
208 glob(pjoin('IPython','extensions','igrid_help.*')))
208 glob(pjoin('IPython','extensions','igrid_help.*')))
209
209
210 # For nested structures, use the utility above
210 # For nested structures, use the utility above
211 example_files = make_dir_struct(
211 example_files = make_dir_struct(
212 'data',
212 'data',
213 pjoin('docs','examples'),
213 pjoin('docs','examples'),
214 pjoin(docdirbase,'examples')
214 pjoin(docdirbase,'examples')
215 )
215 )
216 manual_files = make_dir_struct(
216 manual_files = make_dir_struct(
217 'data',
217 'data',
218 pjoin('docs','html'),
218 pjoin('docs','html'),
219 pjoin(docdirbase,'manual')
219 pjoin(docdirbase,'manual')
220 )
220 )
221
221
222 # And assemble the entire output list
222 # And assemble the entire output list
223 data_files = [ (manpagebase, manpages),
223 data_files = [ (manpagebase, manpages),
224 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
224 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
225 ] + manual_files + example_files
225 ] + manual_files + example_files
226
226
227 return data_files
227 return data_files
228
228
229
229
230 def make_man_update_target(manpage):
230 def make_man_update_target(manpage):
231 """Return a target_update-compliant tuple for the given manpage.
231 """Return a target_update-compliant tuple for the given manpage.
232
232
233 Parameters
233 Parameters
234 ----------
234 ----------
235 manpage : string
235 manpage : string
236 Name of the manpage, must include the section number (trailing number).
236 Name of the manpage, must include the section number (trailing number).
237
237
238 Example
238 Example
239 -------
239 -------
240
240
241 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
241 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
242 ('docs/man/ipython.1.gz',
242 ('docs/man/ipython.1.gz',
243 ['docs/man/ipython.1'],
243 ['docs/man/ipython.1'],
244 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
244 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
245 """
245 """
246 man_dir = pjoin('docs', 'man')
246 man_dir = pjoin('docs', 'man')
247 manpage_gz = manpage + '.gz'
247 manpage_gz = manpage + '.gz'
248 manpath = pjoin(man_dir, manpage)
248 manpath = pjoin(man_dir, manpage)
249 manpath_gz = pjoin(man_dir, manpage_gz)
249 manpath_gz = pjoin(man_dir, manpage_gz)
250 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
250 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
251 locals() )
251 locals() )
252 return (manpath_gz, [manpath], gz_cmd)
252 return (manpath_gz, [manpath], gz_cmd)
253
253
254 # The two functions below are copied from IPython.utils.path, so we don't need
255 # to import IPython during setup, which fails on Python 3.
256
257 def target_outdated(target,deps):
258 """Determine whether a target is out of date.
259
260 target_outdated(target,deps) -> 1/0
261
262 deps: list of filenames which MUST exist.
263 target: single filename which may or may not exist.
264
265 If target doesn't exist or is older than any file listed in deps, return
266 true, otherwise return false.
267 """
268 try:
269 target_time = os.path.getmtime(target)
270 except os.error:
271 return 1
272 for dep in deps:
273 dep_time = os.path.getmtime(dep)
274 if dep_time > target_time:
275 #print "For target",target,"Dep failed:",dep # dbg
276 #print "times (dep,tar):",dep_time,target_time # dbg
277 return 1
278 return 0
279
280
281 def target_update(target,deps,cmd):
282 """Update a target with a given command given a list of dependencies.
283
284 target_update(target,deps,cmd) -> runs cmd if target is outdated.
285
286 This is just a wrapper around target_outdated() which calls the given
287 command if target is outdated."""
288
289 if target_outdated(target,deps):
290 system(cmd)
291
254 #---------------------------------------------------------------------------
292 #---------------------------------------------------------------------------
255 # Find scripts
293 # Find scripts
256 #---------------------------------------------------------------------------
294 #---------------------------------------------------------------------------
257
295
258 def find_scripts(entry_points=False, suffix=''):
296 def find_scripts(entry_points=False, suffix=''):
259 """Find IPython's scripts.
297 """Find IPython's scripts.
260
298
261 if entry_points is True:
299 if entry_points is True:
262 return setuptools entry_point-style definitions
300 return setuptools entry_point-style definitions
263 else:
301 else:
264 return file paths of plain scripts [default]
302 return file paths of plain scripts [default]
265
303
266 suffix is appended to script names if entry_points is True, so that the
304 suffix is appended to script names if entry_points is True, so that the
267 Python 3 scripts get named "ipython3" etc.
305 Python 3 scripts get named "ipython3" etc.
268 """
306 """
269 if entry_points:
307 if entry_points:
270 console_scripts = [s % suffix for s in [
308 console_scripts = [s % suffix for s in [
271 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
309 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
272 'pycolor%s = IPython.utils.PyColorize:main',
310 'pycolor%s = IPython.utils.PyColorize:main',
273 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
311 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
274 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
312 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
275 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
313 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
276 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
314 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
277 'iptest%s = IPython.testing.iptest:main',
315 'iptest%s = IPython.testing.iptest:main',
278 'irunner%s = IPython.lib.irunner:main'
316 'irunner%s = IPython.lib.irunner:main'
279 ]]
317 ]]
280 gui_scripts = [s % suffix for s in [
318 gui_scripts = [s % suffix for s in [
281 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
319 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
282 ]]
320 ]]
283 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
321 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
284 else:
322 else:
285 parallel_scripts = pjoin('IPython','parallel','scripts')
323 parallel_scripts = pjoin('IPython','parallel','scripts')
286 main_scripts = pjoin('IPython','scripts')
324 main_scripts = pjoin('IPython','scripts')
287 scripts = [
325 scripts = [
288 pjoin(parallel_scripts, 'ipengine'),
326 pjoin(parallel_scripts, 'ipengine'),
289 pjoin(parallel_scripts, 'ipcontroller'),
327 pjoin(parallel_scripts, 'ipcontroller'),
290 pjoin(parallel_scripts, 'ipcluster'),
328 pjoin(parallel_scripts, 'ipcluster'),
291 pjoin(parallel_scripts, 'iplogger'),
329 pjoin(parallel_scripts, 'iplogger'),
292 pjoin(main_scripts, 'ipython'),
330 pjoin(main_scripts, 'ipython'),
293 pjoin(main_scripts, 'pycolor'),
331 pjoin(main_scripts, 'pycolor'),
294 pjoin(main_scripts, 'irunner'),
332 pjoin(main_scripts, 'irunner'),
295 pjoin(main_scripts, 'iptest')
333 pjoin(main_scripts, 'iptest')
296 ]
334 ]
297 return scripts
335 return scripts
298
336
299 #---------------------------------------------------------------------------
337 #---------------------------------------------------------------------------
300 # Verify all dependencies
338 # Verify all dependencies
301 #---------------------------------------------------------------------------
339 #---------------------------------------------------------------------------
302
340
303 def check_for_dependencies():
341 def check_for_dependencies():
304 """Check for IPython's dependencies.
342 """Check for IPython's dependencies.
305
343
306 This function should NOT be called if running under setuptools!
344 This function should NOT be called if running under setuptools!
307 """
345 """
308 from setupext.setupext import (
346 from setupext.setupext import (
309 print_line, print_raw, print_status,
347 print_line, print_raw, print_status,
310 check_for_sphinx, check_for_pygments,
348 check_for_sphinx, check_for_pygments,
311 check_for_nose, check_for_pexpect,
349 check_for_nose, check_for_pexpect,
312 check_for_pyzmq, check_for_readline
350 check_for_pyzmq, check_for_readline
313 )
351 )
314 print_line()
352 print_line()
315 print_raw("BUILDING IPYTHON")
353 print_raw("BUILDING IPYTHON")
316 print_status('python', sys.version)
354 print_status('python', sys.version)
317 print_status('platform', sys.platform)
355 print_status('platform', sys.platform)
318 if sys.platform == 'win32':
356 if sys.platform == 'win32':
319 print_status('Windows version', sys.getwindowsversion())
357 print_status('Windows version', sys.getwindowsversion())
320
358
321 print_raw("")
359 print_raw("")
322 print_raw("OPTIONAL DEPENDENCIES")
360 print_raw("OPTIONAL DEPENDENCIES")
323
361
324 check_for_sphinx()
362 check_for_sphinx()
325 check_for_pygments()
363 check_for_pygments()
326 check_for_nose()
364 check_for_nose()
327 check_for_pexpect()
365 check_for_pexpect()
328 check_for_pyzmq()
366 check_for_pyzmq()
329 check_for_readline()
367 check_for_readline()
330
368
331 def record_commit_info(pkg_dir, build_cmd=build_py):
369 def record_commit_info(pkg_dir, build_cmd=build_py):
332 """ Return extended build command class for recording commit
370 """ Return extended build command class for recording commit
333
371
334 The extended command tries to run git to find the current commit, getting
372 The extended command tries to run git to find the current commit, getting
335 the empty string if it fails. It then writes the commit hash into a file
373 the empty string if it fails. It then writes the commit hash into a file
336 in the `pkg_dir` path, named ``.git_commit_info.ini``.
374 in the `pkg_dir` path, named ``.git_commit_info.ini``.
337
375
338 In due course this information can be used by the package after it is
376 In due course this information can be used by the package after it is
339 installed, to tell you what commit it was installed from if known.
377 installed, to tell you what commit it was installed from if known.
340
378
341 To make use of this system, you need a package with a .git_commit_info.ini
379 To make use of this system, you need a package with a .git_commit_info.ini
342 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
380 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
343 this::
381 this::
344
382
345 # This is an ini file that may contain information about the code state
383 # This is an ini file that may contain information about the code state
346 [commit hash]
384 [commit hash]
347 # The line below may contain a valid hash if it has been substituted
385 # The line below may contain a valid hash if it has been substituted
348 # during 'git archive'
386 # during 'git archive'
349 archive_subst_hash=$Format:%h$
387 archive_subst_hash=$Format:%h$
350 # This line may be modified by the install process
388 # This line may be modified by the install process
351 install_hash=
389 install_hash=
352
390
353 The .git_commit_info file above is also designed to be used with git
391 The .git_commit_info file above is also designed to be used with git
354 substitution - so you probably also want a ``.gitattributes`` file in the
392 substitution - so you probably also want a ``.gitattributes`` file in the
355 root directory of your working tree that contains something like this::
393 root directory of your working tree that contains something like this::
356
394
357 myproject/.git_commit_info.ini export-subst
395 myproject/.git_commit_info.ini export-subst
358
396
359 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
397 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
360 archive`` - useful in case someone makes such an archive - for example with
398 archive`` - useful in case someone makes such an archive - for example with
361 via the github 'download source' button.
399 via the github 'download source' button.
362
400
363 Although all the above will work as is, you might consider having something
401 Although all the above will work as is, you might consider having something
364 like a ``get_info()`` function in your package to display the commit
402 like a ``get_info()`` function in your package to display the commit
365 information at the terminal. See the ``pkg_info.py`` module in the nipy
403 information at the terminal. See the ``pkg_info.py`` module in the nipy
366 package for an example.
404 package for an example.
367 """
405 """
368 class MyBuildPy(build_cmd):
406 class MyBuildPy(build_cmd):
369 ''' Subclass to write commit data into installation tree '''
407 ''' Subclass to write commit data into installation tree '''
370 def run(self):
408 def run(self):
371 build_cmd.run(self)
409 build_cmd.run(self)
372 import subprocess
410 import subprocess
373 proc = subprocess.Popen('git rev-parse --short HEAD',
411 proc = subprocess.Popen('git rev-parse --short HEAD',
374 stdout=subprocess.PIPE,
412 stdout=subprocess.PIPE,
375 stderr=subprocess.PIPE,
413 stderr=subprocess.PIPE,
376 shell=True)
414 shell=True)
377 repo_commit, _ = proc.communicate()
415 repo_commit, _ = proc.communicate()
378 # We write the installation commit even if it's empty
416 # We write the installation commit even if it's empty
379 cfg_parser = ConfigParser()
417 cfg_parser = ConfigParser()
380 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
418 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
381 if not cfg_parser.has_section('commit hash'):
419 if not cfg_parser.has_section('commit hash'):
382 # just in case the ini file is empty or doesn't exist, somehow
420 # just in case the ini file is empty or doesn't exist, somehow
383 # we don't want the next line to raise
421 # we don't want the next line to raise
384 cfg_parser.add_section('commit hash')
422 cfg_parser.add_section('commit hash')
385 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
423 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
386 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
424 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
387 out_file = open(out_pth, 'wt')
425 out_file = open(out_pth, 'wt')
388 cfg_parser.write(out_file)
426 cfg_parser.write(out_file)
389 out_file.close()
427 out_file.close()
390 return MyBuildPy
428 return MyBuildPy
@@ -1,176 +1,177 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 from __future__ import print_function
2
3
3 __docformat__ = "restructuredtext en"
4 __docformat__ = "restructuredtext en"
4
5
5 #-------------------------------------------------------------------------------
6 #-------------------------------------------------------------------------------
6 # Copyright (C) 2008 The IPython Development Team
7 # Copyright (C) 2008 The IPython Development Team
7 #
8 #
8 # 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
9 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
10 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
11
12
12 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
13 # Imports
14 # Imports
14 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
15
16
16 import sys, os
17 import sys, os
17 from textwrap import fill
18 from textwrap import fill
18
19
19 display_status=True
20 display_status=True
20
21
21 def check_display(f):
22 def check_display(f):
22 """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"""
23 def maybe_display(*args, **kwargs):
24 def maybe_display(*args, **kwargs):
24 if display_status:
25 if display_status:
25 return f(*args, **kwargs)
26 return f(*args, **kwargs)
26 return maybe_display
27 return maybe_display
27
28
28 @check_display
29 @check_display
29 def print_line(char='='):
30 def print_line(char='='):
30 print char * 76
31 print(char * 76)
31
32
32 @check_display
33 @check_display
33 def print_status(package, status):
34 def print_status(package, status):
34 initial_indent = "%22s: " % package
35 initial_indent = "%22s: " % package
35 indent = ' ' * 24
36 indent = ' ' * 24
36 print fill(str(status), width=76,
37 print(fill(str(status), width=76,
37 initial_indent=initial_indent,
38 initial_indent=initial_indent,
38 subsequent_indent=indent)
39 subsequent_indent=indent))
39
40
40 @check_display
41 @check_display
41 def print_message(message):
42 def print_message(message):
42 indent = ' ' * 24 + "* "
43 indent = ' ' * 24 + "* "
43 print fill(str(message), width=76,
44 print(fill(str(message), width=76,
44 initial_indent=indent,
45 initial_indent=indent,
45 subsequent_indent=indent)
46 subsequent_indent=indent))
46
47
47 @check_display
48 @check_display
48 def print_raw(section):
49 def print_raw(section):
49 print section
50 print(section)
50
51
51 #-------------------------------------------------------------------------------
52 #-------------------------------------------------------------------------------
52 # Tests for specific packages
53 # Tests for specific packages
53 #-------------------------------------------------------------------------------
54 #-------------------------------------------------------------------------------
54
55
55 def check_for_ipython():
56 def check_for_ipython():
56 try:
57 try:
57 import IPython
58 import IPython
58 except ImportError:
59 except ImportError:
59 print_status("IPython", "Not found")
60 print_status("IPython", "Not found")
60 return False
61 return False
61 else:
62 else:
62 print_status("IPython", IPython.__version__)
63 print_status("IPython", IPython.__version__)
63 return True
64 return True
64
65
65 def check_for_sphinx():
66 def check_for_sphinx():
66 try:
67 try:
67 import sphinx
68 import sphinx
68 except ImportError:
69 except ImportError:
69 print_status('sphinx', "Not found (required for building documentation)")
70 print_status('sphinx', "Not found (required for building documentation)")
70 return False
71 return False
71 else:
72 else:
72 print_status('sphinx', sphinx.__version__)
73 print_status('sphinx', sphinx.__version__)
73 return True
74 return True
74
75
75 def check_for_pygments():
76 def check_for_pygments():
76 try:
77 try:
77 import pygments
78 import pygments
78 except ImportError:
79 except ImportError:
79 print_status('pygments', "Not found (required for syntax highlighting documentation)")
80 print_status('pygments', "Not found (required for syntax highlighting documentation)")
80 return False
81 return False
81 else:
82 else:
82 print_status('pygments', pygments.__version__)
83 print_status('pygments', pygments.__version__)
83 return True
84 return True
84
85
85 def check_for_nose():
86 def check_for_nose():
86 try:
87 try:
87 import nose
88 import nose
88 except ImportError:
89 except ImportError:
89 print_status('nose', "Not found (required for running the test suite)")
90 print_status('nose', "Not found (required for running the test suite)")
90 return False
91 return False
91 else:
92 else:
92 print_status('nose', nose.__version__)
93 print_status('nose', nose.__version__)
93 return True
94 return True
94
95
95 def check_for_pexpect():
96 def check_for_pexpect():
96 try:
97 try:
97 import pexpect
98 import pexpect
98 except ImportError:
99 except ImportError:
99 print_status("pexpect", "no (required for running standalone doctests)")
100 print_status("pexpect", "no (required for running standalone doctests)")
100 return False
101 return False
101 else:
102 else:
102 print_status("pexpect", pexpect.__version__)
103 print_status("pexpect", pexpect.__version__)
103 return True
104 return True
104
105
105 def check_for_httplib2():
106 def check_for_httplib2():
106 try:
107 try:
107 import httplib2
108 import httplib2
108 except ImportError:
109 except ImportError:
109 print_status("httplib2", "no (required for blocking http clients)")
110 print_status("httplib2", "no (required for blocking http clients)")
110 return False
111 return False
111 else:
112 else:
112 print_status("httplib2","yes")
113 print_status("httplib2","yes")
113 return True
114 return True
114
115
115 def check_for_sqlalchemy():
116 def check_for_sqlalchemy():
116 try:
117 try:
117 import sqlalchemy
118 import sqlalchemy
118 except ImportError:
119 except ImportError:
119 print_status("sqlalchemy", "no (required for the ipython1 notebook)")
120 print_status("sqlalchemy", "no (required for the ipython1 notebook)")
120 return False
121 return False
121 else:
122 else:
122 print_status("sqlalchemy","yes")
123 print_status("sqlalchemy","yes")
123 return True
124 return True
124
125
125 def check_for_simplejson():
126 def check_for_simplejson():
126 try:
127 try:
127 import simplejson
128 import simplejson
128 except ImportError:
129 except ImportError:
129 print_status("simplejson", "no (required for the ipython1 notebook)")
130 print_status("simplejson", "no (required for the ipython1 notebook)")
130 return False
131 return False
131 else:
132 else:
132 print_status("simplejson","yes")
133 print_status("simplejson","yes")
133 return True
134 return True
134
135
135 def check_for_pyzmq():
136 def check_for_pyzmq():
136 try:
137 try:
137 import zmq
138 import zmq
138 except ImportError:
139 except ImportError:
139 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)")
140 return False
141 return False
141 else:
142 else:
142 # pyzmq 2.1.10 adds pyzmq_version_info funtion for returning
143 # pyzmq 2.1.10 adds pyzmq_version_info funtion for returning
143 # version as a tuple
144 # version as a tuple
144 if hasattr(zmq, 'pyzmq_version_info'):
145 if hasattr(zmq, 'pyzmq_version_info'):
145 if zmq.pyzmq_version_info() >= (2,1,4):
146 if zmq.pyzmq_version_info() >= (2,1,4):
146 print_status("pyzmq", zmq.__version__)
147 print_status("pyzmq", zmq.__version__)
147 return True
148 return True
148 else:
149 else:
149 # this branch can never occur, at least until we update our
150 # this branch can never occur, at least until we update our
150 # pyzmq dependency beyond 2.1.10
151 # pyzmq dependency beyond 2.1.10
151 return False
152 return False
152 # this is necessarily earlier than 2.1.10, so string comparison is
153 # this is necessarily earlier than 2.1.10, so string comparison is
153 # okay
154 # okay
154 if zmq.__version__ < '2.1.4':
155 if zmq.__version__ < '2.1.4':
155 print_status('pyzmq', "no (have %s, but require >= 2.1.4 for"
156 print_status('pyzmq', "no (have %s, but require >= 2.1.4 for"
156 " qtconsole and parallel computing capabilities)"%zmq.__version__)
157 " qtconsole and parallel computing capabilities)"%zmq.__version__)
157 return False
158 return False
158 else:
159 else:
159 print_status("pyzmq", zmq.__version__)
160 print_status("pyzmq", zmq.__version__)
160 return True
161 return True
161
162
162 def check_for_readline():
163 def check_for_readline():
163 try:
164 try:
164 import readline
165 import readline
165 except ImportError:
166 except ImportError:
166 try:
167 try:
167 import pyreadline
168 import pyreadline
168 except ImportError:
169 except ImportError:
169 print_status('readline', "no (required for good interactive behavior)")
170 print_status('readline', "no (required for good interactive behavior)")
170 return False
171 return False
171 else:
172 else:
172 print_status('readline', "yes pyreadline-"+pyreadline.release.version)
173 print_status('readline', "yes pyreadline-"+pyreadline.release.version)
173 return True
174 return True
174 else:
175 else:
175 print_status('readline', "yes")
176 print_status('readline', "yes")
176 return True
177 return True
General Comments 0
You need to be logged in to leave comments. Login now