##// END OF EJS Templates
Merge pull request #5571 from minrk/readline-deps...
Thomas Kluyver -
r16387:8a98cfed merge
parent child Browse files
Show More
@@ -1,344 +1,347 b''
1 1 #!/usr/bin/env python
2 2 # -*- coding: utf-8 -*-
3 3 """Setup script for IPython.
4 4
5 5 Under Posix environments it works like a typical setup.py script.
6 6 Under Windows, the command sdist is not supported, since IPython
7 7 requires utilities which are not available under Windows."""
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (c) 2008-2011, IPython Development Team.
11 11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.rst, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Minimal Python version sanity check
22 22 #-----------------------------------------------------------------------------
23 23 from __future__ import print_function
24 24
25 25 import sys
26 26
27 27 # This check is also made in IPython/__init__, don't forget to update both when
28 28 # changing Python version requirements.
29 29 v = sys.version_info
30 30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
31 31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
32 32 print(error, file=sys.stderr)
33 33 sys.exit(1)
34 34
35 35 PY3 = (sys.version_info[0] >= 3)
36 36
37 37 # At least we're on the python version we need, move on.
38 38
39 39 #-------------------------------------------------------------------------------
40 40 # Imports
41 41 #-------------------------------------------------------------------------------
42 42
43 43 # Stdlib imports
44 44 import os
45 45 import shutil
46 46
47 47 from glob import glob
48 48
49 49 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
50 50 # update it when the contents of directories change.
51 51 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
52 52
53 53 from distutils.core import setup
54 54
55 55 # Our own imports
56 56 from setupbase import target_update
57 57
58 58 from setupbase import (
59 59 setup_args,
60 60 find_packages,
61 61 find_package_data,
62 62 check_package_data_first,
63 63 find_entry_points,
64 64 build_scripts_entrypt,
65 65 find_data_files,
66 66 check_for_dependencies,
67 67 git_prebuild,
68 68 check_submodule_status,
69 69 update_submodules,
70 70 require_submodules,
71 71 UpdateSubmodules,
72 72 get_bdist_wheel,
73 73 CompileCSS,
74 74 JavascriptVersion,
75 75 install_symlinked,
76 76 install_lib_symlink,
77 77 install_scripts_for_symlink,
78 78 unsymlink,
79 79 )
80 80 from setupext import setupext
81 81
82 82 isfile = os.path.isfile
83 83 pjoin = os.path.join
84 84
85 85 #-----------------------------------------------------------------------------
86 86 # Function definitions
87 87 #-----------------------------------------------------------------------------
88 88
89 89 def cleanup():
90 90 """Clean up the junk left around by the build process"""
91 91 if "develop" not in sys.argv and "egg_info" not in sys.argv:
92 92 try:
93 93 shutil.rmtree('ipython.egg-info')
94 94 except:
95 95 try:
96 96 os.unlink('ipython.egg-info')
97 97 except:
98 98 pass
99 99
100 100 #-------------------------------------------------------------------------------
101 101 # Handle OS specific things
102 102 #-------------------------------------------------------------------------------
103 103
104 104 if os.name in ('nt','dos'):
105 105 os_name = 'windows'
106 106 else:
107 107 os_name = os.name
108 108
109 109 # Under Windows, 'sdist' has not been supported. Now that the docs build with
110 110 # Sphinx it might work, but let's not turn it on until someone confirms that it
111 111 # actually works.
112 112 if os_name == 'windows' and 'sdist' in sys.argv:
113 113 print('The sdist command is not available under Windows. Exiting.')
114 114 sys.exit(1)
115 115
116 116 #-------------------------------------------------------------------------------
117 117 # Make sure we aren't trying to run without submodules
118 118 #-------------------------------------------------------------------------------
119 119 here = os.path.abspath(os.path.dirname(__file__))
120 120
121 121 def require_clean_submodules():
122 122 """Check on git submodules before distutils can do anything
123 123
124 124 Since distutils cannot be trusted to update the tree
125 125 after everything has been set in motion,
126 126 this is not a distutils command.
127 127 """
128 128 # PACKAGERS: Add a return here to skip checks for git submodules
129 129
130 130 # don't do anything if nothing is actually supposed to happen
131 131 for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
132 132 if do_nothing in sys.argv:
133 133 return
134 134
135 135 status = check_submodule_status(here)
136 136
137 137 if status == "missing":
138 138 print("checking out submodules for the first time")
139 139 update_submodules(here)
140 140 elif status == "unclean":
141 141 print('\n'.join([
142 142 "Cannot build / install IPython with unclean submodules",
143 143 "Please update submodules with",
144 144 " python setup.py submodule",
145 145 "or",
146 146 " git submodule update",
147 147 "or commit any submodule changes you have made."
148 148 ]))
149 149 sys.exit(1)
150 150
151 151 require_clean_submodules()
152 152
153 153 #-------------------------------------------------------------------------------
154 154 # Things related to the IPython documentation
155 155 #-------------------------------------------------------------------------------
156 156
157 157 # update the manuals when building a source dist
158 158 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
159 159
160 160 # List of things to be updated. Each entry is a triplet of args for
161 161 # target_update()
162 162 to_update = [
163 163 # FIXME - Disabled for now: we need to redo an automatic way
164 164 # of generating the magic info inside the rst.
165 165 #('docs/magic.tex',
166 166 #['IPython/Magic.py'],
167 167 #"cd doc && ./update_magic.sh" ),
168 168
169 169 ('docs/man/ipcluster.1.gz',
170 170 ['docs/man/ipcluster.1'],
171 171 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
172 172
173 173 ('docs/man/ipcontroller.1.gz',
174 174 ['docs/man/ipcontroller.1'],
175 175 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
176 176
177 177 ('docs/man/ipengine.1.gz',
178 178 ['docs/man/ipengine.1'],
179 179 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
180 180
181 181 ('docs/man/ipython.1.gz',
182 182 ['docs/man/ipython.1'],
183 183 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
184 184
185 185 ]
186 186
187 187
188 188 [ target_update(*t) for t in to_update ]
189 189
190 190 #---------------------------------------------------------------------------
191 191 # Find all the packages, package data, and data_files
192 192 #---------------------------------------------------------------------------
193 193
194 194 packages = find_packages()
195 195 package_data = find_package_data()
196 196
197 197 data_files = find_data_files()
198 198
199 199 setup_args['packages'] = packages
200 200 setup_args['package_data'] = package_data
201 201 setup_args['data_files'] = data_files
202 202
203 203 #---------------------------------------------------------------------------
204 204 # custom distutils commands
205 205 #---------------------------------------------------------------------------
206 206 # imports here, so they are after setuptools import if there was one
207 207 from distutils.command.sdist import sdist
208 208 from distutils.command.upload import upload
209 209
210 210 class UploadWindowsInstallers(upload):
211 211
212 212 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
213 213 user_options = upload.user_options + [
214 214 ('files=', 'f', 'exe file (or glob) to upload')
215 215 ]
216 216 def initialize_options(self):
217 217 upload.initialize_options(self)
218 218 meta = self.distribution.metadata
219 219 base = '{name}-{version}'.format(
220 220 name=meta.get_name(),
221 221 version=meta.get_version()
222 222 )
223 223 self.files = os.path.join('dist', '%s.*.exe' % base)
224 224
225 225 def run(self):
226 226 for dist_file in glob(self.files):
227 227 self.upload_file('bdist_wininst', 'any', dist_file)
228 228
229 229 setup_args['cmdclass'] = {
230 230 'build_py': check_package_data_first(git_prebuild('IPython')),
231 231 'sdist' : git_prebuild('IPython', sdist),
232 232 'upload_wininst' : UploadWindowsInstallers,
233 233 'submodule' : UpdateSubmodules,
234 234 'css' : CompileCSS,
235 235 'symlink': install_symlinked,
236 236 'install_lib_symlink': install_lib_symlink,
237 237 'install_scripts_sym': install_scripts_for_symlink,
238 238 'unsymlink': unsymlink,
239 239 'jsversion' : JavascriptVersion,
240 240 }
241 241
242 242 #---------------------------------------------------------------------------
243 243 # Handle scripts, dependencies, and setuptools specific things
244 244 #---------------------------------------------------------------------------
245 245
246 246 # For some commands, use setuptools. Note that we do NOT list install here!
247 247 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
248 248 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
249 249 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
250 250 'egg_info', 'easy_install', 'upload', 'install_egg_info',
251 251 ))
252 252 if sys.platform == 'win32':
253 253 # Depend on setuptools for install on *Windows only*
254 254 # If we get script-installation working without setuptools,
255 255 # then we can back off, but until then use it.
256 256 # See Issue #369 on GitHub for more
257 257 needs_setuptools.add('install')
258 258
259 259 if len(needs_setuptools.intersection(sys.argv)) > 0:
260 260 import setuptools
261 261
262 262 # This dict is used for passing extra arguments that are setuptools
263 263 # specific to setup
264 264 setuptools_extra_args = {}
265 265
266 266 # setuptools requirements
267 267
268 268 extras_require = dict(
269 269 parallel = ['pyzmq>=2.1.11'],
270 270 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
271 271 zmq = ['pyzmq>=2.1.11'],
272 272 doc = ['Sphinx>=1.1', 'numpydoc'],
273 273 test = ['nose>=0.10.1'],
274 terminal = [],
274 275 notebook = ['tornado>=3.1', 'pyzmq>=2.1.11', 'jinja2'],
275 276 nbconvert = ['pygments', 'jinja2', 'Sphinx>=0.3']
276 277 )
277 278 if sys.version_info < (3, 3):
278 279 extras_require['test'].append('mock')
279 280
280 281 everything = set()
281 282 for deps in extras_require.values():
282 283 everything.update(deps)
283 284 extras_require['all'] = everything
284 285
285 286 install_requires = []
287
288 # add readline
286 289 if sys.platform == 'darwin':
287 290 if any(arg.startswith('bdist') for arg in sys.argv) or not setupext.check_for_readline():
288 291 install_requires.append('gnureadline')
289 292 elif sys.platform.startswith('win'):
290 # Pyreadline has unicode and Python 3 fixes in 2.0
291 install_requires.append('pyreadline>=2.0')
293 extras_require['terminal'].append('pyreadline>=2.0')
294
292 295
293 296 if 'setuptools' in sys.modules:
294 297 # setup.py develop should check for submodules
295 298 from setuptools.command.develop import develop
296 299 setup_args['cmdclass']['develop'] = require_submodules(develop)
297 300 setup_args['cmdclass']['bdist_wheel'] = get_bdist_wheel()
298 301
299 302 setuptools_extra_args['zip_safe'] = False
300 303 setuptools_extra_args['entry_points'] = {'console_scripts':find_entry_points()}
301 304 setup_args['extras_require'] = extras_require
302 305 requires = setup_args['install_requires'] = install_requires
303 306
304 307 # Script to be run by the windows binary installer after the default setup
305 308 # routine, to add shortcuts and similar windows-only things. Windows
306 309 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
307 310 # doesn't find them.
308 311 if 'bdist_wininst' in sys.argv:
309 312 if len(sys.argv) > 2 and \
310 313 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
311 314 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
312 315 sys.exit(1)
313 316 setup_args['data_files'].append(
314 317 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
315 318 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
316 319 setup_args['options'] = {"bdist_wininst":
317 320 {"install_script":
318 321 "ipython_win_post_install.py"}}
319 322
320 323 else:
321 324 # If we are installing without setuptools, call this function which will
322 325 # check for dependencies an inform the user what is needed. This is
323 326 # just to make life easy for users.
324 327 for install_cmd in ('install', 'symlink'):
325 328 if install_cmd in sys.argv:
326 329 check_for_dependencies()
327 330 break
328 331 # scripts has to be a non-empty list, or install_scripts isn't called
329 332 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
330 333
331 334 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
332 335
333 336 #---------------------------------------------------------------------------
334 337 # Do the actual setup now
335 338 #---------------------------------------------------------------------------
336 339
337 340 setup_args.update(setuptools_extra_args)
338 341
339 342 def main():
340 343 setup(**setup_args)
341 344 cleanup()
342 345
343 346 if __name__ == '__main__':
344 347 main()
@@ -1,701 +1,696 b''
1 1 # encoding: utf-8
2 2 """
3 3 This module defines the things that are used in setup.py for building IPython
4 4
5 5 This includes:
6 6
7 7 * The basic arguments to setup
8 8 * Functions for finding things like packages, package data, etc.
9 9 * A function for checking dependencies.
10 10 """
11 from __future__ import print_function
12 11
13 #-------------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
15 #
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
18 #-------------------------------------------------------------------------------
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
14
15 from __future__ import print_function
19 16
20 #-------------------------------------------------------------------------------
21 # Imports
22 #-------------------------------------------------------------------------------
23 17 import errno
24 18 import os
25 19 import sys
26 20
27 21 from distutils.command.build_py import build_py
28 22 from distutils.command.build_scripts import build_scripts
29 23 from distutils.command.install import install
30 24 from distutils.command.install_scripts import install_scripts
31 25 from distutils.cmd import Command
32 26 from fnmatch import fnmatch
33 27 from glob import glob
34 28 from subprocess import call
35 29
36 30 from setupext import install_data_ext
37 31
38 32 #-------------------------------------------------------------------------------
39 33 # Useful globals and utility functions
40 34 #-------------------------------------------------------------------------------
41 35
42 36 # A few handy globals
43 37 isfile = os.path.isfile
44 38 pjoin = os.path.join
45 39 repo_root = os.path.dirname(os.path.abspath(__file__))
46 40
47 41 def oscmd(s):
48 42 print(">", s)
49 43 os.system(s)
50 44
51 45 # Py3 compatibility hacks, without assuming IPython itself is installed with
52 46 # the full py3compat machinery.
53 47
54 48 try:
55 49 execfile
56 50 except NameError:
57 51 def execfile(fname, globs, locs=None):
58 52 locs = locs or globs
59 53 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
60 54
61 55 # A little utility we'll need below, since glob() does NOT allow you to do
62 56 # exclusion on multiple endings!
63 57 def file_doesnt_endwith(test,endings):
64 58 """Return true if test is a file and its name does NOT end with any
65 59 of the strings listed in endings."""
66 60 if not isfile(test):
67 61 return False
68 62 for e in endings:
69 63 if test.endswith(e):
70 64 return False
71 65 return True
72 66
73 67 #---------------------------------------------------------------------------
74 68 # Basic project information
75 69 #---------------------------------------------------------------------------
76 70
77 71 # release.py contains version, authors, license, url, keywords, etc.
78 72 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
79 73
80 74 # Create a dict with the basic information
81 75 # This dict is eventually passed to setup after additional keys are added.
82 76 setup_args = dict(
83 77 name = name,
84 78 version = version,
85 79 description = description,
86 80 long_description = long_description,
87 81 author = author,
88 82 author_email = author_email,
89 83 url = url,
90 84 download_url = download_url,
91 85 license = license,
92 86 platforms = platforms,
93 87 keywords = keywords,
94 88 classifiers = classifiers,
95 89 cmdclass = {'install_data': install_data_ext},
96 90 )
97 91
98 92
99 93 #---------------------------------------------------------------------------
100 94 # Find packages
101 95 #---------------------------------------------------------------------------
102 96
103 97 def find_packages():
104 98 """
105 99 Find all of IPython's packages.
106 100 """
107 101 excludes = ['deathrow', 'quarantine']
108 102 packages = []
109 103 for dir,subdirs,files in os.walk('IPython'):
110 104 package = dir.replace(os.path.sep, '.')
111 105 if any(package.startswith('IPython.'+exc) for exc in excludes):
112 106 # package is to be excluded (e.g. deathrow)
113 107 continue
114 108 if '__init__.py' not in files:
115 109 # not a package
116 110 continue
117 111 packages.append(package)
118 112 return packages
119 113
120 114 #---------------------------------------------------------------------------
121 115 # Find package data
122 116 #---------------------------------------------------------------------------
123 117
124 118 def find_package_data():
125 119 """
126 120 Find IPython's package_data.
127 121 """
128 122 # This is not enough for these things to appear in an sdist.
129 123 # We need to muck with the MANIFEST to get this to work
130 124
131 125 # exclude components and less from the walk;
132 126 # we will build the components separately
133 127 excludes = [
134 128 pjoin('static', 'components'),
135 129 pjoin('static', '*', 'less'),
136 130 ]
137 131
138 132 # walk notebook resources:
139 133 cwd = os.getcwd()
140 134 os.chdir(os.path.join('IPython', 'html'))
141 135 static_data = []
142 136 for parent, dirs, files in os.walk('static'):
143 137 if any(fnmatch(parent, pat) for pat in excludes):
144 138 # prevent descending into subdirs
145 139 dirs[:] = []
146 140 continue
147 141 for f in files:
148 142 static_data.append(pjoin(parent, f))
149 143
150 144 components = pjoin("static", "components")
151 145 # select the components we actually need to install
152 146 # (there are lots of resources we bundle for sdist-reasons that we don't actually use)
153 147 static_data.extend([
154 148 pjoin(components, "backbone", "backbone-min.js"),
155 149 pjoin(components, "bootstrap", "bootstrap", "js", "bootstrap.min.js"),
156 150 pjoin(components, "bootstrap-tour", "build", "css", "bootstrap-tour.min.css"),
157 151 pjoin(components, "bootstrap-tour", "build", "js", "bootstrap-tour.min.js"),
158 152 pjoin(components, "font-awesome", "font", "*.*"),
159 153 pjoin(components, "google-caja", "html-css-sanitizer-minified.js"),
160 154 pjoin(components, "highlight.js", "build", "highlight.pack.js"),
161 155 pjoin(components, "jquery", "jquery.min.js"),
162 156 pjoin(components, "jquery-ui", "ui", "minified", "jquery-ui.min.js"),
163 157 pjoin(components, "jquery-ui", "themes", "smoothness", "jquery-ui.min.css"),
164 158 pjoin(components, "jquery-ui", "themes", "smoothness", "images", "*"),
165 159 pjoin(components, "marked", "lib", "marked.js"),
166 160 pjoin(components, "requirejs", "require.js"),
167 161 pjoin(components, "underscore", "underscore-min.js"),
168 162 ])
169 163
170 164 # Ship all of Codemirror's CSS and JS
171 165 for parent, dirs, files in os.walk(pjoin(components, 'codemirror')):
172 166 for f in files:
173 167 if f.endswith(('.js', '.css')):
174 168 static_data.append(pjoin(parent, f))
175 169
176 170 os.chdir(os.path.join('tests',))
177 171 js_tests = glob('*.js') + glob('*/*.js')
178 172
179 173 os.chdir(os.path.join(cwd, 'IPython', 'nbconvert'))
180 174 nbconvert_templates = [os.path.join(dirpath, '*.*')
181 175 for dirpath, _, _ in os.walk('templates')]
182 176
183 177 os.chdir(cwd)
184 178
185 179 package_data = {
186 180 'IPython.config.profile' : ['README*', '*/*.py'],
187 181 'IPython.core.tests' : ['*.png', '*.jpg'],
188 182 'IPython.lib.tests' : ['*.wav'],
189 183 'IPython.testing.plugin' : ['*.txt'],
190 184 'IPython.html' : ['templates/*'] + static_data,
191 185 'IPython.html.tests' : js_tests,
192 186 'IPython.qt.console' : ['resources/icon/*.svg'],
193 187 'IPython.nbconvert' : nbconvert_templates +
194 188 ['tests/files/*.*', 'exporters/tests/files/*.*'],
195 189 'IPython.nbconvert.filters' : ['marked.js'],
196 190 'IPython.nbformat' : ['tests/*.ipynb']
197 191 }
198 192
199 193 return package_data
200 194
201 195
202 196 def check_package_data(package_data):
203 197 """verify that package_data globs make sense"""
204 198 print("checking package data")
205 199 for pkg, data in package_data.items():
206 200 pkg_root = pjoin(*pkg.split('.'))
207 201 for d in data:
208 202 path = pjoin(pkg_root, d)
209 203 if '*' in path:
210 204 assert len(glob(path)) > 0, "No files match pattern %s" % path
211 205 else:
212 206 assert os.path.exists(path), "Missing package data: %s" % path
213 207
214 208
215 209 def check_package_data_first(command):
216 210 """decorator for checking package_data before running a given command
217 211
218 212 Probably only needs to wrap build_py
219 213 """
220 214 class DecoratedCommand(command):
221 215 def run(self):
222 216 check_package_data(self.package_data)
223 217 command.run(self)
224 218 return DecoratedCommand
225 219
226 220
227 221 #---------------------------------------------------------------------------
228 222 # Find data files
229 223 #---------------------------------------------------------------------------
230 224
231 225 def make_dir_struct(tag,base,out_base):
232 226 """Make the directory structure of all files below a starting dir.
233 227
234 228 This is just a convenience routine to help build a nested directory
235 229 hierarchy because distutils is too stupid to do this by itself.
236 230
237 231 XXX - this needs a proper docstring!
238 232 """
239 233
240 234 # we'll use these a lot below
241 235 lbase = len(base)
242 236 pathsep = os.path.sep
243 237 lpathsep = len(pathsep)
244 238
245 239 out = []
246 240 for (dirpath,dirnames,filenames) in os.walk(base):
247 241 # we need to strip out the dirpath from the base to map it to the
248 242 # output (installation) path. This requires possibly stripping the
249 243 # path separator, because otherwise pjoin will not work correctly
250 244 # (pjoin('foo/','/bar') returns '/bar').
251 245
252 246 dp_eff = dirpath[lbase:]
253 247 if dp_eff.startswith(pathsep):
254 248 dp_eff = dp_eff[lpathsep:]
255 249 # The output path must be anchored at the out_base marker
256 250 out_path = pjoin(out_base,dp_eff)
257 251 # Now we can generate the final filenames. Since os.walk only produces
258 252 # filenames, we must join back with the dirpath to get full valid file
259 253 # paths:
260 254 pfiles = [pjoin(dirpath,f) for f in filenames]
261 255 # Finally, generate the entry we need, which is a pari of (output
262 256 # path, files) for use as a data_files parameter in install_data.
263 257 out.append((out_path, pfiles))
264 258
265 259 return out
266 260
267 261
268 262 def find_data_files():
269 263 """
270 264 Find IPython's data_files.
271 265
272 266 Just man pages at this point.
273 267 """
274 268
275 269 manpagebase = pjoin('share', 'man', 'man1')
276 270
277 271 # Simple file lists can be made by hand
278 272 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
279 273 if not manpages:
280 274 # When running from a source tree, the manpages aren't gzipped
281 275 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
282 276
283 277 # And assemble the entire output list
284 278 data_files = [ (manpagebase, manpages) ]
285 279
286 280 return data_files
287 281
288 282
289 283 def make_man_update_target(manpage):
290 284 """Return a target_update-compliant tuple for the given manpage.
291 285
292 286 Parameters
293 287 ----------
294 288 manpage : string
295 289 Name of the manpage, must include the section number (trailing number).
296 290
297 291 Example
298 292 -------
299 293
300 294 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
301 295 ('docs/man/ipython.1.gz',
302 296 ['docs/man/ipython.1'],
303 297 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
304 298 """
305 299 man_dir = pjoin('docs', 'man')
306 300 manpage_gz = manpage + '.gz'
307 301 manpath = pjoin(man_dir, manpage)
308 302 manpath_gz = pjoin(man_dir, manpage_gz)
309 303 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
310 304 locals() )
311 305 return (manpath_gz, [manpath], gz_cmd)
312 306
313 307 # The two functions below are copied from IPython.utils.path, so we don't need
314 308 # to import IPython during setup, which fails on Python 3.
315 309
316 310 def target_outdated(target,deps):
317 311 """Determine whether a target is out of date.
318 312
319 313 target_outdated(target,deps) -> 1/0
320 314
321 315 deps: list of filenames which MUST exist.
322 316 target: single filename which may or may not exist.
323 317
324 318 If target doesn't exist or is older than any file listed in deps, return
325 319 true, otherwise return false.
326 320 """
327 321 try:
328 322 target_time = os.path.getmtime(target)
329 323 except os.error:
330 324 return 1
331 325 for dep in deps:
332 326 dep_time = os.path.getmtime(dep)
333 327 if dep_time > target_time:
334 328 #print "For target",target,"Dep failed:",dep # dbg
335 329 #print "times (dep,tar):",dep_time,target_time # dbg
336 330 return 1
337 331 return 0
338 332
339 333
340 334 def target_update(target,deps,cmd):
341 335 """Update a target with a given command given a list of dependencies.
342 336
343 337 target_update(target,deps,cmd) -> runs cmd if target is outdated.
344 338
345 339 This is just a wrapper around target_outdated() which calls the given
346 340 command if target is outdated."""
347 341
348 342 if target_outdated(target,deps):
349 343 os.system(cmd)
350 344
351 345 #---------------------------------------------------------------------------
352 346 # Find scripts
353 347 #---------------------------------------------------------------------------
354 348
355 349 def find_entry_points():
356 350 """Find IPython's scripts.
357 351
358 352 if entry_points is True:
359 353 return setuptools entry_point-style definitions
360 354 else:
361 355 return file paths of plain scripts [default]
362 356
363 357 suffix is appended to script names if entry_points is True, so that the
364 358 Python 3 scripts get named "ipython3" etc.
365 359 """
366 360 ep = [
367 361 'ipython%s = IPython:start_ipython',
368 362 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
369 363 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
370 364 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
371 365 'iptest%s = IPython.testing.iptestcontroller:main',
372 366 ]
373 367 suffix = str(sys.version_info[0])
374 368 return [e % '' for e in ep] + [e % suffix for e in ep]
375 369
376 370 script_src = """#!{executable}
377 371 # This script was automatically generated by setup.py
378 372 if __name__ == '__main__':
379 373 from {mod} import {func}
380 374 {func}()
381 375 """
382 376
383 377 class build_scripts_entrypt(build_scripts):
384 378 def run(self):
385 379 self.mkpath(self.build_dir)
386 380 outfiles = []
387 381 for script in find_entry_points():
388 382 name, entrypt = script.split('=')
389 383 name = name.strip()
390 384 entrypt = entrypt.strip()
391 385 outfile = os.path.join(self.build_dir, name)
392 386 outfiles.append(outfile)
393 387 print('Writing script to', outfile)
394 388
395 389 mod, func = entrypt.split(':')
396 390 with open(outfile, 'w') as f:
397 391 f.write(script_src.format(executable=sys.executable,
398 392 mod=mod, func=func))
399 393
400 394 return outfiles, outfiles
401 395
402 396 class install_lib_symlink(Command):
403 397 user_options = [
404 398 ('install-dir=', 'd', "directory to install to"),
405 399 ]
406 400
407 401 def initialize_options(self):
408 402 self.install_dir = None
409 403
410 404 def finalize_options(self):
411 405 self.set_undefined_options('symlink',
412 406 ('install_lib', 'install_dir'),
413 407 )
414 408
415 409 def run(self):
416 410 if sys.platform == 'win32':
417 411 raise Exception("This doesn't work on Windows.")
418 412 pkg = os.path.join(os.getcwd(), 'IPython')
419 413 dest = os.path.join(self.install_dir, 'IPython')
420 414 if os.path.islink(dest):
421 415 print('removing existing symlink at %s' % dest)
422 416 os.unlink(dest)
423 417 print('symlinking %s -> %s' % (pkg, dest))
424 418 os.symlink(pkg, dest)
425 419
426 420 class unsymlink(install):
427 421 def run(self):
428 422 dest = os.path.join(self.install_lib, 'IPython')
429 423 if os.path.islink(dest):
430 424 print('removing symlink at %s' % dest)
431 425 os.unlink(dest)
432 426 else:
433 427 print('No symlink exists at %s' % dest)
434 428
435 429 class install_symlinked(install):
436 430 def run(self):
437 431 if sys.platform == 'win32':
438 432 raise Exception("This doesn't work on Windows.")
439 433
440 434 # Run all sub-commands (at least those that need to be run)
441 435 for cmd_name in self.get_sub_commands():
442 436 self.run_command(cmd_name)
443 437
444 438 # 'sub_commands': a list of commands this command might have to run to
445 439 # get its work done. See cmd.py for more info.
446 440 sub_commands = [('install_lib_symlink', lambda self:True),
447 441 ('install_scripts_sym', lambda self:True),
448 442 ]
449 443
450 444 class install_scripts_for_symlink(install_scripts):
451 445 """Redefined to get options from 'symlink' instead of 'install'.
452 446
453 447 I love distutils almost as much as I love setuptools.
454 448 """
455 449 def finalize_options(self):
456 450 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
457 451 self.set_undefined_options('symlink',
458 452 ('install_scripts', 'install_dir'),
459 453 ('force', 'force'),
460 454 ('skip_build', 'skip_build'),
461 455 )
462 456
463 457 #---------------------------------------------------------------------------
464 458 # Verify all dependencies
465 459 #---------------------------------------------------------------------------
466 460
467 461 def check_for_dependencies():
468 462 """Check for IPython's dependencies.
469 463
470 464 This function should NOT be called if running under setuptools!
471 465 """
472 466 from setupext.setupext import (
473 467 print_line, print_raw, print_status,
474 468 check_for_sphinx, check_for_pygments,
475 469 check_for_nose, check_for_pexpect,
476 470 check_for_pyzmq, check_for_readline,
477 471 check_for_jinja2, check_for_tornado
478 472 )
479 473 print_line()
480 474 print_raw("BUILDING IPYTHON")
481 475 print_status('python', sys.version)
482 476 print_status('platform', sys.platform)
483 477 if sys.platform == 'win32':
484 478 print_status('Windows version', sys.getwindowsversion())
485 479
486 480 print_raw("")
487 481 print_raw("OPTIONAL DEPENDENCIES")
488 482
489 483 check_for_sphinx()
490 484 check_for_pygments()
491 485 check_for_nose()
492 486 if os.name == 'posix':
493 487 check_for_pexpect()
494 488 check_for_pyzmq()
495 489 check_for_tornado()
496 490 check_for_readline()
497 491 check_for_jinja2()
498 492
499 493 #---------------------------------------------------------------------------
500 494 # VCS related
501 495 #---------------------------------------------------------------------------
502 496
503 497 # utils.submodule has checks for submodule status
504 498 execfile(pjoin('IPython','utils','submodule.py'), globals())
505 499
506 500 class UpdateSubmodules(Command):
507 501 """Update git submodules
508 502
509 503 IPython's external javascript dependencies live in a separate repo.
510 504 """
511 505 description = "Update git submodules"
512 506 user_options = []
513 507
514 508 def initialize_options(self):
515 509 pass
516 510
517 511 def finalize_options(self):
518 512 pass
519 513
520 514 def run(self):
521 515 failure = False
522 516 try:
523 517 self.spawn('git submodule init'.split())
524 518 self.spawn('git submodule update --recursive'.split())
525 519 except Exception as e:
526 520 failure = e
527 521 print(e)
528 522
529 523 if not check_submodule_status(repo_root) == 'clean':
530 524 print("submodules could not be checked out")
531 525 sys.exit(1)
532 526
533 527
534 528 def git_prebuild(pkg_dir, build_cmd=build_py):
535 529 """Return extended build or sdist command class for recording commit
536 530
537 531 records git commit in IPython.utils._sysinfo.commit
538 532
539 533 for use in IPython.utils.sysinfo.sys_info() calls after installation.
540 534
541 535 Also ensures that submodules exist prior to running
542 536 """
543 537
544 538 class MyBuildPy(build_cmd):
545 539 ''' Subclass to write commit data into installation tree '''
546 540 def run(self):
547 541 build_cmd.run(self)
548 542 # this one will only fire for build commands
549 543 if hasattr(self, 'build_lib'):
550 544 self._record_commit(self.build_lib)
551 545
552 546 def make_release_tree(self, base_dir, files):
553 547 # this one will fire for sdist
554 548 build_cmd.make_release_tree(self, base_dir, files)
555 549 self._record_commit(base_dir)
556 550
557 551 def _record_commit(self, base_dir):
558 552 import subprocess
559 553 proc = subprocess.Popen('git rev-parse --short HEAD',
560 554 stdout=subprocess.PIPE,
561 555 stderr=subprocess.PIPE,
562 556 shell=True)
563 557 repo_commit, _ = proc.communicate()
564 558 repo_commit = repo_commit.strip().decode("ascii")
565 559
566 560 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
567 561 if os.path.isfile(out_pth) and not repo_commit:
568 562 # nothing to write, don't clobber
569 563 return
570 564
571 565 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
572 566
573 567 # remove to avoid overwriting original via hard link
574 568 try:
575 569 os.remove(out_pth)
576 570 except (IOError, OSError):
577 571 pass
578 572 with open(out_pth, 'w') as out_file:
579 573 out_file.writelines([
580 574 '# GENERATED BY setup.py\n',
581 575 'commit = "%s"\n' % repo_commit,
582 576 ])
583 577 return require_submodules(MyBuildPy)
584 578
585 579
586 580 def require_submodules(command):
587 581 """decorator for instructing a command to check for submodules before running"""
588 582 class DecoratedCommand(command):
589 583 def run(self):
590 584 if not check_submodule_status(repo_root) == 'clean':
591 585 print("submodules missing! Run `setup.py submodule` and try again")
592 586 sys.exit(1)
593 587 command.run(self)
594 588 return DecoratedCommand
595 589
596 590 #---------------------------------------------------------------------------
597 591 # bdist related
598 592 #---------------------------------------------------------------------------
599 593
600 594 def get_bdist_wheel():
601 595 """Construct bdist_wheel command for building wheels
602 596
603 597 Constructs py2-none-any tag, instead of py2.7-none-any
604 598 """
605 599 class RequiresWheel(Command):
606 600 description = "Dummy command for missing bdist_wheel"
607 601 user_options = []
608 602
609 603 def initialize_options(self):
610 604 pass
611 605
612 606 def finalize_options(self):
613 607 pass
614 608
615 609 def run(self):
616 610 print("bdist_wheel requires the wheel package")
617 611 sys.exit(1)
618 612
619 613 if 'setuptools' not in sys.modules:
620 614 return RequiresWheel
621 615 else:
622 616 try:
623 617 from wheel.bdist_wheel import bdist_wheel, read_pkg_info, write_pkg_info
624 618 except ImportError:
625 619 return RequiresWheel
626 620
627 621 class bdist_wheel_tag(bdist_wheel):
628 622
629 623 def add_requirements(self, metadata_path):
630 624 """transform platform-dependent requirements"""
631 625 pkg_info = read_pkg_info(metadata_path)
632 626 # pkg_info is an email.Message object (?!)
633 627 # we have to remove the unconditional 'readline' and/or 'pyreadline' entries
634 628 # and transform them to conditionals
635 629 requires = pkg_info.get_all('Requires-Dist')
636 630 del pkg_info['Requires-Dist']
637 631 def _remove_startswith(lis, prefix):
638 632 """like list.remove, but with startswith instead of =="""
639 633 found = False
640 634 for idx, item in enumerate(lis):
641 635 if item.startswith(prefix):
642 636 found = True
643 637 break
644 638 if found:
645 639 lis.pop(idx)
646 640
647 641 for pkg in ("gnureadline", "pyreadline", "mock"):
648 642 _remove_startswith(requires, pkg)
649 643 requires.append("gnureadline; sys.platform == 'darwin' and platform.python_implementation == 'CPython'")
650 requires.append("pyreadline (>=2.0); sys.platform == 'win32' and platform.python_implementation == 'CPython'")
644 requires.append("pyreadline (>=2.0); extra == 'terminal' and sys.platform == 'win32' and platform.python_implementation == 'CPython'")
645 requires.append("pyreadline (>=2.0); extra == 'all' and sys.platform == 'win32' and platform.python_implementation == 'CPython'")
651 646 requires.append("mock; extra == 'test' and python_version < '3.3'")
652 647 for r in requires:
653 648 pkg_info['Requires-Dist'] = r
654 649 write_pkg_info(metadata_path, pkg_info)
655 650
656 651 return bdist_wheel_tag
657 652
658 653 #---------------------------------------------------------------------------
659 654 # Notebook related
660 655 #---------------------------------------------------------------------------
661 656
662 657 class CompileCSS(Command):
663 658 """Recompile Notebook CSS
664 659
665 660 Regenerate the compiled CSS from LESS sources.
666 661
667 662 Requires various dev dependencies, such as fabric and lessc.
668 663 """
669 664 description = "Recompile Notebook CSS"
670 665 user_options = []
671 666
672 667 def initialize_options(self):
673 668 pass
674 669
675 670 def finalize_options(self):
676 671 pass
677 672
678 673 def run(self):
679 674 call("fab css", shell=True, cwd=pjoin(repo_root, "IPython", "html"))
680 675
681 676 class JavascriptVersion(Command):
682 677 """write the javascript version to notebook javascript"""
683 678 description = "Write IPython version to javascript"
684 679 user_options = []
685 680
686 681 def initialize_options(self):
687 682 pass
688 683
689 684 def finalize_options(self):
690 685 pass
691 686
692 687 def run(self):
693 688 nsfile = pjoin(repo_root, "IPython", "html", "static", "base", "js", "namespace.js")
694 689 with open(nsfile) as f:
695 690 lines = f.readlines()
696 691 with open(nsfile, 'w') as f:
697 692 for line in lines:
698 693 if line.startswith("IPython.version"):
699 694 line = 'IPython.version = "{0}";\n'.format(version)
700 695 f.write(line)
701 696
General Comments 0
You need to be logged in to leave comments. Login now