##// END OF EJS Templates
Backport PR #2068: record sysinfo in sdist...
MinRK -
Show More
@@ -1,285 +1,290 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 from distutils.command.upload import upload
56
55
57 # 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
58 if PY3:
57 if PY3:
59 import setuptools
58 import setuptools
60
59
61 # Our own imports
60 # Our own imports
62 from setupbase import target_update
61 from setupbase import target_update
63
62
64 from setupbase import (
63 from setupbase import (
65 setup_args,
64 setup_args,
66 find_packages,
65 find_packages,
67 find_package_data,
66 find_package_data,
68 find_scripts,
67 find_scripts,
69 find_data_files,
68 find_data_files,
70 check_for_dependencies,
69 check_for_dependencies,
71 record_commit_info,
70 record_commit_info,
72 )
71 )
73 from setupext import setupext
72 from setupext import setupext
74
73
75 isfile = os.path.isfile
74 isfile = os.path.isfile
76 pjoin = os.path.join
75 pjoin = os.path.join
77
76
78 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
79 # Function definitions
78 # Function definitions
80 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
81
80
82 def cleanup():
81 def cleanup():
83 """Clean up the junk left around by the build process"""
82 """Clean up the junk left around by the build process"""
84 if "develop" not in sys.argv:
83 if "develop" not in sys.argv:
85 try:
84 try:
86 shutil.rmtree('ipython.egg-info')
85 shutil.rmtree('ipython.egg-info')
87 except:
86 except:
88 try:
87 try:
89 os.unlink('ipython.egg-info')
88 os.unlink('ipython.egg-info')
90 except:
89 except:
91 pass
90 pass
92
91
93 #-------------------------------------------------------------------------------
92 #-------------------------------------------------------------------------------
94 # Handle OS specific things
93 # Handle OS specific things
95 #-------------------------------------------------------------------------------
94 #-------------------------------------------------------------------------------
96
95
97 if os.name == 'posix':
96 if os.name == 'posix':
98 os_name = 'posix'
97 os_name = 'posix'
99 elif os.name in ['nt','dos']:
98 elif os.name in ['nt','dos']:
100 os_name = 'windows'
99 os_name = 'windows'
101 else:
100 else:
102 print('Unsupported operating system:',os.name)
101 print('Unsupported operating system:',os.name)
103 sys.exit(1)
102 sys.exit(1)
104
103
105 # 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
106 # 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
107 # actually works.
106 # actually works.
108 if os_name == 'windows' and 'sdist' in sys.argv:
107 if os_name == 'windows' and 'sdist' in sys.argv:
109 print('The sdist command is not available under Windows. Exiting.')
108 print('The sdist command is not available under Windows. Exiting.')
110 sys.exit(1)
109 sys.exit(1)
111
110
112 #-------------------------------------------------------------------------------
111 #-------------------------------------------------------------------------------
113 # Things related to the IPython documentation
112 # Things related to the IPython documentation
114 #-------------------------------------------------------------------------------
113 #-------------------------------------------------------------------------------
115
114
116 # update the manuals when building a source dist
115 # update the manuals when building a source dist
117 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'):
118 import textwrap
117 import textwrap
119
118
120 # 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
121 # target_update()
120 # target_update()
122 to_update = [
121 to_update = [
123 # FIXME - Disabled for now: we need to redo an automatic way
122 # FIXME - Disabled for now: we need to redo an automatic way
124 # of generating the magic info inside the rst.
123 # of generating the magic info inside the rst.
125 #('docs/magic.tex',
124 #('docs/magic.tex',
126 #['IPython/Magic.py'],
125 #['IPython/Magic.py'],
127 #"cd doc && ./update_magic.sh" ),
126 #"cd doc && ./update_magic.sh" ),
128
127
129 ('docs/man/ipcluster.1.gz',
128 ('docs/man/ipcluster.1.gz',
130 ['docs/man/ipcluster.1'],
129 ['docs/man/ipcluster.1'],
131 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
130 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
132
131
133 ('docs/man/ipcontroller.1.gz',
132 ('docs/man/ipcontroller.1.gz',
134 ['docs/man/ipcontroller.1'],
133 ['docs/man/ipcontroller.1'],
135 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
134 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
136
135
137 ('docs/man/ipengine.1.gz',
136 ('docs/man/ipengine.1.gz',
138 ['docs/man/ipengine.1'],
137 ['docs/man/ipengine.1'],
139 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
138 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
140
139
141 ('docs/man/iplogger.1.gz',
140 ('docs/man/iplogger.1.gz',
142 ['docs/man/iplogger.1'],
141 ['docs/man/iplogger.1'],
143 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
142 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
144
143
145 ('docs/man/ipython.1.gz',
144 ('docs/man/ipython.1.gz',
146 ['docs/man/ipython.1'],
145 ['docs/man/ipython.1'],
147 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
146 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
148
147
149 ('docs/man/irunner.1.gz',
148 ('docs/man/irunner.1.gz',
150 ['docs/man/irunner.1'],
149 ['docs/man/irunner.1'],
151 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
150 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
152
151
153 ('docs/man/pycolor.1.gz',
152 ('docs/man/pycolor.1.gz',
154 ['docs/man/pycolor.1'],
153 ['docs/man/pycolor.1'],
155 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
154 'cd docs/man && gzip -9c pycolor.1 > pycolor.1.gz'),
156 ]
155 ]
157
156
158
157
159 [ target_update(*t) for t in to_update ]
158 [ target_update(*t) for t in to_update ]
160
159
161 #---------------------------------------------------------------------------
160 #---------------------------------------------------------------------------
162 # Find all the packages, package data, and data_files
161 # Find all the packages, package data, and data_files
163 #---------------------------------------------------------------------------
162 #---------------------------------------------------------------------------
164
163
165 packages = find_packages()
164 packages = find_packages()
166 package_data = find_package_data()
165 package_data = find_package_data()
167 data_files = find_data_files()
166 data_files = find_data_files()
168
167
169 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython')}
170 setup_args['packages'] = packages
168 setup_args['packages'] = packages
171 setup_args['package_data'] = package_data
169 setup_args['package_data'] = package_data
172 setup_args['data_files'] = data_files
170 setup_args['data_files'] = data_files
173
171
174 #---------------------------------------------------------------------------
172 #---------------------------------------------------------------------------
175 # custom upload_wininst command
173 # custom distutils commands
176 #---------------------------------------------------------------------------
174 #---------------------------------------------------------------------------
175 # imports here, so they are after setuptools import if there was one
176 from distutils.command.sdist import sdist
177 from distutils.command.upload import upload
177
178
178 class UploadWindowsInstallers(upload):
179 class UploadWindowsInstallers(upload):
179
180
180 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)"
181 user_options = upload.user_options + [
182 user_options = upload.user_options + [
182 ('files=', 'f', 'exe file (or glob) to upload')
183 ('files=', 'f', 'exe file (or glob) to upload')
183 ]
184 ]
184 def initialize_options(self):
185 def initialize_options(self):
185 upload.initialize_options(self)
186 upload.initialize_options(self)
186 meta = self.distribution.metadata
187 meta = self.distribution.metadata
187 base = '{name}-{version}'.format(
188 base = '{name}-{version}'.format(
188 name=meta.get_name(),
189 name=meta.get_name(),
189 version=meta.get_version()
190 version=meta.get_version()
190 )
191 )
191 self.files = os.path.join('dist', '%s.*.exe' % base)
192 self.files = os.path.join('dist', '%s.*.exe' % base)
192
193
193 def run(self):
194 def run(self):
194 for dist_file in glob(self.files):
195 for dist_file in glob(self.files):
195 self.upload_file('bdist_wininst', 'any', dist_file)
196 self.upload_file('bdist_wininst', 'any', dist_file)
196
197
197 setup_args['cmdclass']['upload_wininst'] = UploadWindowsInstallers
198 setup_args['cmdclass'] = {
199 'build_py': record_commit_info('IPython'),
200 'sdist' : record_commit_info('IPython', sdist),
201 'upload_wininst' : UploadWindowsInstallers,
202 }
198
203
199 #---------------------------------------------------------------------------
204 #---------------------------------------------------------------------------
200 # Handle scripts, dependencies, and setuptools specific things
205 # Handle scripts, dependencies, and setuptools specific things
201 #---------------------------------------------------------------------------
206 #---------------------------------------------------------------------------
202
207
203 # 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!
204 # 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'
205 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
210 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
206 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
211 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
207 'egg_info', 'easy_install', 'upload',
212 'egg_info', 'easy_install', 'upload',
208 ))
213 ))
209 if sys.platform == 'win32':
214 if sys.platform == 'win32':
210 # Depend on setuptools for install on *Windows only*
215 # Depend on setuptools for install on *Windows only*
211 # If we get script-installation working without setuptools,
216 # If we get script-installation working without setuptools,
212 # then we can back off, but until then use it.
217 # then we can back off, but until then use it.
213 # See Issue #369 on GitHub for more
218 # See Issue #369 on GitHub for more
214 needs_setuptools.add('install')
219 needs_setuptools.add('install')
215
220
216 if len(needs_setuptools.intersection(sys.argv)) > 0:
221 if len(needs_setuptools.intersection(sys.argv)) > 0:
217 import setuptools
222 import setuptools
218
223
219 # This dict is used for passing extra arguments that are setuptools
224 # This dict is used for passing extra arguments that are setuptools
220 # specific to setup
225 # specific to setup
221 setuptools_extra_args = {}
226 setuptools_extra_args = {}
222
227
223 if 'setuptools' in sys.modules:
228 if 'setuptools' in sys.modules:
224 setuptools_extra_args['zip_safe'] = False
229 setuptools_extra_args['zip_safe'] = False
225 setuptools_extra_args['entry_points'] = find_scripts(True)
230 setuptools_extra_args['entry_points'] = find_scripts(True)
226 setup_args['extras_require'] = dict(
231 setup_args['extras_require'] = dict(
227 parallel = 'pyzmq>=2.1.4',
232 parallel = 'pyzmq>=2.1.4',
228 zmq = 'pyzmq>=2.1.4',
233 zmq = 'pyzmq>=2.1.4',
229 doc = 'Sphinx>=0.3',
234 doc = 'Sphinx>=0.3',
230 test = 'nose>=0.10.1',
235 test = 'nose>=0.10.1',
231 notebook = 'tornado>=2.0'
236 notebook = 'tornado>=2.0'
232 )
237 )
233 requires = setup_args.setdefault('install_requires', [])
238 requires = setup_args.setdefault('install_requires', [])
234 setupext.display_status = False
239 setupext.display_status = False
235 if not setupext.check_for_readline():
240 if not setupext.check_for_readline():
236 if sys.platform == 'darwin':
241 if sys.platform == 'darwin':
237 requires.append('readline')
242 requires.append('readline')
238 elif sys.platform.startswith('win'):
243 elif sys.platform.startswith('win'):
239 # Pyreadline 64 bit windows issue solved in versions >=1.7.1
244 # Pyreadline 64 bit windows issue solved in versions >=1.7.1
240 # Also solves issues with some older versions of pyreadline that
245 # Also solves issues with some older versions of pyreadline that
241 # satisfy the unconstrained depdendency.
246 # satisfy the unconstrained depdendency.
242 requires.append('pyreadline>=1.7.1')
247 requires.append('pyreadline>=1.7.1')
243 else:
248 else:
244 pass
249 pass
245 # do we want to install readline here?
250 # do we want to install readline here?
246
251
247 # Script to be run by the windows binary installer after the default setup
252 # Script to be run by the windows binary installer after the default setup
248 # routine, to add shortcuts and similar windows-only things. Windows
253 # routine, to add shortcuts and similar windows-only things. Windows
249 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
254 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
250 # doesn't find them.
255 # doesn't find them.
251 if 'bdist_wininst' in sys.argv:
256 if 'bdist_wininst' in sys.argv:
252 if len(sys.argv) > 2 and \
257 if len(sys.argv) > 2 and \
253 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
258 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
254 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
259 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
255 sys.exit(1)
260 sys.exit(1)
256 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
261 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
257 setup_args['options'] = {"bdist_wininst":
262 setup_args['options'] = {"bdist_wininst":
258 {"install_script":
263 {"install_script":
259 "ipython_win_post_install.py"}}
264 "ipython_win_post_install.py"}}
260
265
261 if PY3:
266 if PY3:
262 setuptools_extra_args['use_2to3'] = True
267 setuptools_extra_args['use_2to3'] = True
263 from setuptools.command.build_py import build_py
268 from setuptools.command.build_py import build_py
264 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython', build_cmd=build_py)}
269 setup_args['cmdclass'] = {'build_py': record_commit_info('IPython', build_cmd=build_py)}
265 setuptools_extra_args['entry_points'] = find_scripts(True, suffix='3')
270 setuptools_extra_args['entry_points'] = find_scripts(True, suffix='3')
266 setuptools._dont_write_bytecode = True
271 setuptools._dont_write_bytecode = True
267 else:
272 else:
268 # If we are running without setuptools, call this function which will
273 # If we are running without setuptools, call this function which will
269 # check for dependencies an inform the user what is needed. This is
274 # check for dependencies an inform the user what is needed. This is
270 # just to make life easy for users.
275 # just to make life easy for users.
271 check_for_dependencies()
276 check_for_dependencies()
272 setup_args['scripts'] = find_scripts(False)
277 setup_args['scripts'] = find_scripts(False)
273
278
274 #---------------------------------------------------------------------------
279 #---------------------------------------------------------------------------
275 # Do the actual setup now
280 # Do the actual setup now
276 #---------------------------------------------------------------------------
281 #---------------------------------------------------------------------------
277
282
278 setup_args.update(setuptools_extra_args)
283 setup_args.update(setuptools_extra_args)
279
284
280 def main():
285 def main():
281 setup(**setup_args)
286 setup(**setup_args)
282 cleanup()
287 cleanup()
283
288
284 if __name__ == '__main__':
289 if __name__ == '__main__':
285 main()
290 main()
@@ -1,397 +1,419 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 # Py3 compatibility hacks, without assuming IPython itself is installed with
47 # Py3 compatibility hacks, without assuming IPython itself is installed with
48 # the full py3compat machinery.
48 # the full py3compat machinery.
49
49
50 try:
50 try:
51 execfile
51 execfile
52 except NameError:
52 except NameError:
53 def execfile(fname, globs, locs=None):
53 def execfile(fname, globs, locs=None):
54 locs = locs or globs
54 locs = locs or globs
55 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
55 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
56
56
57 # A little utility we'll need below, since glob() does NOT allow you to do
57 # A little utility we'll need below, since glob() does NOT allow you to do
58 # exclusion on multiple endings!
58 # exclusion on multiple endings!
59 def file_doesnt_endwith(test,endings):
59 def file_doesnt_endwith(test,endings):
60 """Return true if test is a file and its name does NOT end with any
60 """Return true if test is a file and its name does NOT end with any
61 of the strings listed in endings."""
61 of the strings listed in endings."""
62 if not isfile(test):
62 if not isfile(test):
63 return False
63 return False
64 for e in endings:
64 for e in endings:
65 if test.endswith(e):
65 if test.endswith(e):
66 return False
66 return False
67 return True
67 return True
68
68
69 #---------------------------------------------------------------------------
69 #---------------------------------------------------------------------------
70 # Basic project information
70 # Basic project information
71 #---------------------------------------------------------------------------
71 #---------------------------------------------------------------------------
72
72
73 # release.py contains version, authors, license, url, keywords, etc.
73 # release.py contains version, authors, license, url, keywords, etc.
74 execfile(pjoin('IPython','core','release.py'), globals())
74 execfile(pjoin('IPython','core','release.py'), globals())
75
75
76 # Create a dict with the basic information
76 # Create a dict with the basic information
77 # This dict is eventually passed to setup after additional keys are added.
77 # This dict is eventually passed to setup after additional keys are added.
78 setup_args = dict(
78 setup_args = dict(
79 name = name,
79 name = name,
80 version = version,
80 version = version,
81 description = description,
81 description = description,
82 long_description = long_description,
82 long_description = long_description,
83 author = author,
83 author = author,
84 author_email = author_email,
84 author_email = author_email,
85 url = url,
85 url = url,
86 download_url = download_url,
86 download_url = download_url,
87 license = license,
87 license = license,
88 platforms = platforms,
88 platforms = platforms,
89 keywords = keywords,
89 keywords = keywords,
90 classifiers = classifiers,
90 classifiers = classifiers,
91 cmdclass = {'install_data': install_data_ext},
91 cmdclass = {'install_data': install_data_ext},
92 )
92 )
93
93
94
94
95 #---------------------------------------------------------------------------
95 #---------------------------------------------------------------------------
96 # Find packages
96 # Find packages
97 #---------------------------------------------------------------------------
97 #---------------------------------------------------------------------------
98
98
99 def find_packages():
99 def find_packages():
100 """
100 """
101 Find all of IPython's packages.
101 Find all of IPython's packages.
102 """
102 """
103 excludes = ['deathrow', 'quarantine']
103 excludes = ['deathrow', 'quarantine']
104 packages = []
104 packages = []
105 for dir,subdirs,files in os.walk('IPython'):
105 for dir,subdirs,files in os.walk('IPython'):
106 package = dir.replace(os.path.sep, '.')
106 package = dir.replace(os.path.sep, '.')
107 if any(package.startswith('IPython.'+exc) for exc in excludes):
107 if any(package.startswith('IPython.'+exc) for exc in excludes):
108 # package is to be excluded (e.g. deathrow)
108 # package is to be excluded (e.g. deathrow)
109 continue
109 continue
110 if '__init__.py' not in files:
110 if '__init__.py' not in files:
111 # not a package
111 # not a package
112 continue
112 continue
113 packages.append(package)
113 packages.append(package)
114 return packages
114 return packages
115
115
116 #---------------------------------------------------------------------------
116 #---------------------------------------------------------------------------
117 # Find package data
117 # Find package data
118 #---------------------------------------------------------------------------
118 #---------------------------------------------------------------------------
119
119
120 def find_package_data():
120 def find_package_data():
121 """
121 """
122 Find IPython's package_data.
122 Find IPython's package_data.
123 """
123 """
124 # This is not enough for these things to appear in an sdist.
124 # This is not enough for these things to appear in an sdist.
125 # We need to muck with the MANIFEST to get this to work
125 # We need to muck with the MANIFEST to get this to work
126
126
127 # exclude static things that we don't ship (e.g. mathjax)
127 # exclude static things that we don't ship (e.g. mathjax)
128 excludes = ['mathjax']
128 excludes = ['mathjax']
129
129
130 # add 'static/' prefix to exclusions, and tuplify for use in startswith
130 # add 'static/' prefix to exclusions, and tuplify for use in startswith
131 excludes = tuple([os.path.join('static', ex) for ex in excludes])
131 excludes = tuple([os.path.join('static', ex) for ex in excludes])
132
132
133 # walk notebook resources:
133 # walk notebook resources:
134 cwd = os.getcwd()
134 cwd = os.getcwd()
135 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
135 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
136 static_walk = list(os.walk('static'))
136 static_walk = list(os.walk('static'))
137 os.chdir(cwd)
137 os.chdir(cwd)
138 static_data = []
138 static_data = []
139 for parent, dirs, files in static_walk:
139 for parent, dirs, files in static_walk:
140 if parent.startswith(excludes):
140 if parent.startswith(excludes):
141 continue
141 continue
142 for f in files:
142 for f in files:
143 static_data.append(os.path.join(parent, f))
143 static_data.append(os.path.join(parent, f))
144
144
145 package_data = {
145 package_data = {
146 'IPython.config.profile' : ['README*', '*/*.py'],
146 'IPython.config.profile' : ['README*', '*/*.py'],
147 'IPython.testing' : ['*.txt'],
147 'IPython.testing' : ['*.txt'],
148 'IPython.testing.plugin' : ['*.txt'],
148 'IPython.testing.plugin' : ['*.txt'],
149 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
149 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
150 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
150 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
151 }
151 }
152 return package_data
152 return package_data
153
153
154
154
155 #---------------------------------------------------------------------------
155 #---------------------------------------------------------------------------
156 # Find data files
156 # Find data files
157 #---------------------------------------------------------------------------
157 #---------------------------------------------------------------------------
158
158
159 def make_dir_struct(tag,base,out_base):
159 def make_dir_struct(tag,base,out_base):
160 """Make the directory structure of all files below a starting dir.
160 """Make the directory structure of all files below a starting dir.
161
161
162 This is just a convenience routine to help build a nested directory
162 This is just a convenience routine to help build a nested directory
163 hierarchy because distutils is too stupid to do this by itself.
163 hierarchy because distutils is too stupid to do this by itself.
164
164
165 XXX - this needs a proper docstring!
165 XXX - this needs a proper docstring!
166 """
166 """
167
167
168 # we'll use these a lot below
168 # we'll use these a lot below
169 lbase = len(base)
169 lbase = len(base)
170 pathsep = os.path.sep
170 pathsep = os.path.sep
171 lpathsep = len(pathsep)
171 lpathsep = len(pathsep)
172
172
173 out = []
173 out = []
174 for (dirpath,dirnames,filenames) in os.walk(base):
174 for (dirpath,dirnames,filenames) in os.walk(base):
175 # we need to strip out the dirpath from the base to map it to the
175 # we need to strip out the dirpath from the base to map it to the
176 # output (installation) path. This requires possibly stripping the
176 # output (installation) path. This requires possibly stripping the
177 # path separator, because otherwise pjoin will not work correctly
177 # path separator, because otherwise pjoin will not work correctly
178 # (pjoin('foo/','/bar') returns '/bar').
178 # (pjoin('foo/','/bar') returns '/bar').
179
179
180 dp_eff = dirpath[lbase:]
180 dp_eff = dirpath[lbase:]
181 if dp_eff.startswith(pathsep):
181 if dp_eff.startswith(pathsep):
182 dp_eff = dp_eff[lpathsep:]
182 dp_eff = dp_eff[lpathsep:]
183 # The output path must be anchored at the out_base marker
183 # The output path must be anchored at the out_base marker
184 out_path = pjoin(out_base,dp_eff)
184 out_path = pjoin(out_base,dp_eff)
185 # Now we can generate the final filenames. Since os.walk only produces
185 # Now we can generate the final filenames. Since os.walk only produces
186 # filenames, we must join back with the dirpath to get full valid file
186 # filenames, we must join back with the dirpath to get full valid file
187 # paths:
187 # paths:
188 pfiles = [pjoin(dirpath,f) for f in filenames]
188 pfiles = [pjoin(dirpath,f) for f in filenames]
189 # Finally, generate the entry we need, which is a pari of (output
189 # Finally, generate the entry we need, which is a pari of (output
190 # path, files) for use as a data_files parameter in install_data.
190 # path, files) for use as a data_files parameter in install_data.
191 out.append((out_path, pfiles))
191 out.append((out_path, pfiles))
192
192
193 return out
193 return out
194
194
195
195
196 def find_data_files():
196 def find_data_files():
197 """
197 """
198 Find IPython's data_files.
198 Find IPython's data_files.
199
199
200 Most of these are docs.
200 Most of these are docs.
201 """
201 """
202
202
203 docdirbase = pjoin('share', 'doc', 'ipython')
203 docdirbase = pjoin('share', 'doc', 'ipython')
204 manpagebase = pjoin('share', 'man', 'man1')
204 manpagebase = pjoin('share', 'man', 'man1')
205
205
206 # Simple file lists can be made by hand
206 # Simple file lists can be made by hand
207 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
207 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
208 if not manpages:
208 if not manpages:
209 # When running from a source tree, the manpages aren't gzipped
209 # When running from a source tree, the manpages aren't gzipped
210 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
210 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
211 igridhelpfiles = filter(isfile,
211 igridhelpfiles = filter(isfile,
212 glob(pjoin('IPython','extensions','igrid_help.*')))
212 glob(pjoin('IPython','extensions','igrid_help.*')))
213
213
214 # For nested structures, use the utility above
214 # For nested structures, use the utility above
215 example_files = make_dir_struct(
215 example_files = make_dir_struct(
216 'data',
216 'data',
217 pjoin('docs','examples'),
217 pjoin('docs','examples'),
218 pjoin(docdirbase,'examples')
218 pjoin(docdirbase,'examples')
219 )
219 )
220 manual_files = make_dir_struct(
220 manual_files = make_dir_struct(
221 'data',
221 'data',
222 pjoin('docs','html'),
222 pjoin('docs','html'),
223 pjoin(docdirbase,'manual')
223 pjoin(docdirbase,'manual')
224 )
224 )
225
225
226 # And assemble the entire output list
226 # And assemble the entire output list
227 data_files = [ (manpagebase, manpages),
227 data_files = [ (manpagebase, manpages),
228 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
228 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
229 ] + manual_files + example_files
229 ] + manual_files + example_files
230
230
231 return data_files
231 return data_files
232
232
233
233
234 def make_man_update_target(manpage):
234 def make_man_update_target(manpage):
235 """Return a target_update-compliant tuple for the given manpage.
235 """Return a target_update-compliant tuple for the given manpage.
236
236
237 Parameters
237 Parameters
238 ----------
238 ----------
239 manpage : string
239 manpage : string
240 Name of the manpage, must include the section number (trailing number).
240 Name of the manpage, must include the section number (trailing number).
241
241
242 Example
242 Example
243 -------
243 -------
244
244
245 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
245 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
246 ('docs/man/ipython.1.gz',
246 ('docs/man/ipython.1.gz',
247 ['docs/man/ipython.1'],
247 ['docs/man/ipython.1'],
248 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
248 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
249 """
249 """
250 man_dir = pjoin('docs', 'man')
250 man_dir = pjoin('docs', 'man')
251 manpage_gz = manpage + '.gz'
251 manpage_gz = manpage + '.gz'
252 manpath = pjoin(man_dir, manpage)
252 manpath = pjoin(man_dir, manpage)
253 manpath_gz = pjoin(man_dir, manpage_gz)
253 manpath_gz = pjoin(man_dir, manpage_gz)
254 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
254 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
255 locals() )
255 locals() )
256 return (manpath_gz, [manpath], gz_cmd)
256 return (manpath_gz, [manpath], gz_cmd)
257
257
258 # The two functions below are copied from IPython.utils.path, so we don't need
258 # The two functions below are copied from IPython.utils.path, so we don't need
259 # to import IPython during setup, which fails on Python 3.
259 # to import IPython during setup, which fails on Python 3.
260
260
261 def target_outdated(target,deps):
261 def target_outdated(target,deps):
262 """Determine whether a target is out of date.
262 """Determine whether a target is out of date.
263
263
264 target_outdated(target,deps) -> 1/0
264 target_outdated(target,deps) -> 1/0
265
265
266 deps: list of filenames which MUST exist.
266 deps: list of filenames which MUST exist.
267 target: single filename which may or may not exist.
267 target: single filename which may or may not exist.
268
268
269 If target doesn't exist or is older than any file listed in deps, return
269 If target doesn't exist or is older than any file listed in deps, return
270 true, otherwise return false.
270 true, otherwise return false.
271 """
271 """
272 try:
272 try:
273 target_time = os.path.getmtime(target)
273 target_time = os.path.getmtime(target)
274 except os.error:
274 except os.error:
275 return 1
275 return 1
276 for dep in deps:
276 for dep in deps:
277 dep_time = os.path.getmtime(dep)
277 dep_time = os.path.getmtime(dep)
278 if dep_time > target_time:
278 if dep_time > target_time:
279 #print "For target",target,"Dep failed:",dep # dbg
279 #print "For target",target,"Dep failed:",dep # dbg
280 #print "times (dep,tar):",dep_time,target_time # dbg
280 #print "times (dep,tar):",dep_time,target_time # dbg
281 return 1
281 return 1
282 return 0
282 return 0
283
283
284
284
285 def target_update(target,deps,cmd):
285 def target_update(target,deps,cmd):
286 """Update a target with a given command given a list of dependencies.
286 """Update a target with a given command given a list of dependencies.
287
287
288 target_update(target,deps,cmd) -> runs cmd if target is outdated.
288 target_update(target,deps,cmd) -> runs cmd if target is outdated.
289
289
290 This is just a wrapper around target_outdated() which calls the given
290 This is just a wrapper around target_outdated() which calls the given
291 command if target is outdated."""
291 command if target is outdated."""
292
292
293 if target_outdated(target,deps):
293 if target_outdated(target,deps):
294 os.system(cmd)
294 os.system(cmd)
295
295
296 #---------------------------------------------------------------------------
296 #---------------------------------------------------------------------------
297 # Find scripts
297 # Find scripts
298 #---------------------------------------------------------------------------
298 #---------------------------------------------------------------------------
299
299
300 def find_scripts(entry_points=False, suffix=''):
300 def find_scripts(entry_points=False, suffix=''):
301 """Find IPython's scripts.
301 """Find IPython's scripts.
302
302
303 if entry_points is True:
303 if entry_points is True:
304 return setuptools entry_point-style definitions
304 return setuptools entry_point-style definitions
305 else:
305 else:
306 return file paths of plain scripts [default]
306 return file paths of plain scripts [default]
307
307
308 suffix is appended to script names if entry_points is True, so that the
308 suffix is appended to script names if entry_points is True, so that the
309 Python 3 scripts get named "ipython3" etc.
309 Python 3 scripts get named "ipython3" etc.
310 """
310 """
311 if entry_points:
311 if entry_points:
312 console_scripts = [s % suffix for s in [
312 console_scripts = [s % suffix for s in [
313 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
313 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
314 'pycolor%s = IPython.utils.PyColorize:main',
314 'pycolor%s = IPython.utils.PyColorize:main',
315 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
315 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
316 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
316 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
317 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
317 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
318 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
318 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
319 'iptest%s = IPython.testing.iptest:main',
319 'iptest%s = IPython.testing.iptest:main',
320 'irunner%s = IPython.lib.irunner:main'
320 'irunner%s = IPython.lib.irunner:main'
321 ]]
321 ]]
322 gui_scripts = []
322 gui_scripts = []
323 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
323 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
324 else:
324 else:
325 parallel_scripts = pjoin('IPython','parallel','scripts')
325 parallel_scripts = pjoin('IPython','parallel','scripts')
326 main_scripts = pjoin('IPython','scripts')
326 main_scripts = pjoin('IPython','scripts')
327 scripts = [
327 scripts = [
328 pjoin(parallel_scripts, 'ipengine'),
328 pjoin(parallel_scripts, 'ipengine'),
329 pjoin(parallel_scripts, 'ipcontroller'),
329 pjoin(parallel_scripts, 'ipcontroller'),
330 pjoin(parallel_scripts, 'ipcluster'),
330 pjoin(parallel_scripts, 'ipcluster'),
331 pjoin(parallel_scripts, 'iplogger'),
331 pjoin(parallel_scripts, 'iplogger'),
332 pjoin(main_scripts, 'ipython'),
332 pjoin(main_scripts, 'ipython'),
333 pjoin(main_scripts, 'pycolor'),
333 pjoin(main_scripts, 'pycolor'),
334 pjoin(main_scripts, 'irunner'),
334 pjoin(main_scripts, 'irunner'),
335 pjoin(main_scripts, 'iptest')
335 pjoin(main_scripts, 'iptest')
336 ]
336 ]
337 return scripts
337 return scripts
338
338
339 #---------------------------------------------------------------------------
339 #---------------------------------------------------------------------------
340 # Verify all dependencies
340 # Verify all dependencies
341 #---------------------------------------------------------------------------
341 #---------------------------------------------------------------------------
342
342
343 def check_for_dependencies():
343 def check_for_dependencies():
344 """Check for IPython's dependencies.
344 """Check for IPython's dependencies.
345
345
346 This function should NOT be called if running under setuptools!
346 This function should NOT be called if running under setuptools!
347 """
347 """
348 from setupext.setupext import (
348 from setupext.setupext import (
349 print_line, print_raw, print_status,
349 print_line, print_raw, print_status,
350 check_for_sphinx, check_for_pygments,
350 check_for_sphinx, check_for_pygments,
351 check_for_nose, check_for_pexpect,
351 check_for_nose, check_for_pexpect,
352 check_for_pyzmq, check_for_readline
352 check_for_pyzmq, check_for_readline
353 )
353 )
354 print_line()
354 print_line()
355 print_raw("BUILDING IPYTHON")
355 print_raw("BUILDING IPYTHON")
356 print_status('python', sys.version)
356 print_status('python', sys.version)
357 print_status('platform', sys.platform)
357 print_status('platform', sys.platform)
358 if sys.platform == 'win32':
358 if sys.platform == 'win32':
359 print_status('Windows version', sys.getwindowsversion())
359 print_status('Windows version', sys.getwindowsversion())
360
360
361 print_raw("")
361 print_raw("")
362 print_raw("OPTIONAL DEPENDENCIES")
362 print_raw("OPTIONAL DEPENDENCIES")
363
363
364 check_for_sphinx()
364 check_for_sphinx()
365 check_for_pygments()
365 check_for_pygments()
366 check_for_nose()
366 check_for_nose()
367 check_for_pexpect()
367 check_for_pexpect()
368 check_for_pyzmq()
368 check_for_pyzmq()
369 check_for_readline()
369 check_for_readline()
370
370
371 def record_commit_info(pkg_dir, build_cmd=build_py):
371 def record_commit_info(pkg_dir, build_cmd=build_py):
372 """ Return extended build command class for recording commit
372 """ Return extended build or sdist command class for recording commit
373
373
374 records git commit in IPython.utils._sysinfo.commit
374 records git commit in IPython.utils._sysinfo.commit
375
375
376 for use in IPython.utils.sysinfo.sys_info() calls after installation.
376 for use in IPython.utils.sysinfo.sys_info() calls after installation.
377 """
377 """
378
378
379 class MyBuildPy(build_cmd):
379 class MyBuildPy(build_cmd):
380 ''' Subclass to write commit data into installation tree '''
380 ''' Subclass to write commit data into installation tree '''
381 def run(self):
381 def run(self):
382 build_cmd.run(self)
382 build_cmd.run(self)
383 # this one will only fire for build commands
384 if hasattr(self, 'build_lib'):
385 self._record_commit(self.build_lib)
386
387 def make_release_tree(self, base_dir, files):
388 # this one will fire for sdist
389 build_cmd.make_release_tree(self, base_dir, files)
390 self._record_commit(base_dir)
391
392 def _record_commit(self, base_dir):
383 import subprocess
393 import subprocess
384 proc = subprocess.Popen('git rev-parse --short HEAD',
394 proc = subprocess.Popen('git rev-parse --short HEAD',
385 stdout=subprocess.PIPE,
395 stdout=subprocess.PIPE,
386 stderr=subprocess.PIPE,
396 stderr=subprocess.PIPE,
387 shell=True)
397 shell=True)
388 repo_commit, _ = proc.communicate()
398 repo_commit, _ = proc.communicate()
389 repo_commit = repo_commit.strip()
399 repo_commit = repo_commit.strip().decode("ascii")
390 # We write the installation commit even if it's empty
400
391 out_pth = pjoin(self.build_lib, pkg_dir, 'utils', '_sysinfo.py')
401 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
402 if os.path.isfile(out_pth) and not repo_commit:
403 # nothing to write, don't clobber
404 return
405
406 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
407
408 # remove to avoid overwriting original via hard link
409 try:
410 os.remove(out_pth)
411 except (IOError, OSError):
412 pass
413 print (out_pth, file=sys.stderr)
392 with open(out_pth, 'w') as out_file:
414 with open(out_pth, 'w') as out_file:
393 out_file.writelines([
415 out_file.writelines([
394 '# GENERATED BY setup.py\n',
416 '# GENERATED BY setup.py\n',
395 'commit = "%s"\n' % repo_commit.decode('ascii'),
417 'commit = "%s"\n' % repo_commit,
396 ])
418 ])
397 return MyBuildPy
419 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now