##// END OF EJS Templates
add ipython[terminal] dependency group...
MinRK -
Show More
@@ -1,341 +1,346 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 if sys.version_info[:2] < (2,7):
30 30 error = "ERROR: IPython requires Python Version 2.7 or above."
31 31 print(error, file=sys.stderr)
32 32 sys.exit(1)
33 33
34 34 PY3 = (sys.version_info[0] >= 3)
35 35
36 36 # At least we're on the python version we need, move on.
37 37
38 38 #-------------------------------------------------------------------------------
39 39 # Imports
40 40 #-------------------------------------------------------------------------------
41 41
42 42 # Stdlib imports
43 43 import os
44 44 import shutil
45 45
46 46 from glob import glob
47 47
48 48 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
49 49 # update it when the contents of directories change.
50 50 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
51 51
52 52 from distutils.core import setup
53 53
54 54 # Our own imports
55 55 from setupbase import target_update
56 56
57 57 from setupbase import (
58 58 setup_args,
59 59 find_packages,
60 60 find_package_data,
61 61 check_package_data_first,
62 62 find_entry_points,
63 63 build_scripts_entrypt,
64 64 find_data_files,
65 65 check_for_dependencies,
66 66 git_prebuild,
67 67 check_submodule_status,
68 68 update_submodules,
69 69 require_submodules,
70 70 UpdateSubmodules,
71 71 get_bdist_wheel,
72 72 CompileCSS,
73 73 JavascriptVersion,
74 74 install_symlinked,
75 75 install_lib_symlink,
76 76 install_scripts_for_symlink,
77 77 unsymlink,
78 78 )
79 79 from setupext import setupext
80 80
81 81 isfile = os.path.isfile
82 82 pjoin = os.path.join
83 83
84 84 #-----------------------------------------------------------------------------
85 85 # Function definitions
86 86 #-----------------------------------------------------------------------------
87 87
88 88 def cleanup():
89 89 """Clean up the junk left around by the build process"""
90 90 if "develop" not in sys.argv and "egg_info" not in sys.argv:
91 91 try:
92 92 shutil.rmtree('ipython.egg-info')
93 93 except:
94 94 try:
95 95 os.unlink('ipython.egg-info')
96 96 except:
97 97 pass
98 98
99 99 #-------------------------------------------------------------------------------
100 100 # Handle OS specific things
101 101 #-------------------------------------------------------------------------------
102 102
103 103 if os.name in ('nt','dos'):
104 104 os_name = 'windows'
105 105 else:
106 106 os_name = os.name
107 107
108 108 # Under Windows, 'sdist' has not been supported. Now that the docs build with
109 109 # Sphinx it might work, but let's not turn it on until someone confirms that it
110 110 # actually works.
111 111 if os_name == 'windows' and 'sdist' in sys.argv:
112 112 print('The sdist command is not available under Windows. Exiting.')
113 113 sys.exit(1)
114 114
115 115 #-------------------------------------------------------------------------------
116 116 # Make sure we aren't trying to run without submodules
117 117 #-------------------------------------------------------------------------------
118 118 here = os.path.abspath(os.path.dirname(__file__))
119 119
120 120 def require_clean_submodules():
121 121 """Check on git submodules before distutils can do anything
122 122
123 123 Since distutils cannot be trusted to update the tree
124 124 after everything has been set in motion,
125 125 this is not a distutils command.
126 126 """
127 127 # PACKAGERS: Add a return here to skip checks for git submodules
128 128
129 129 # don't do anything if nothing is actually supposed to happen
130 130 for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
131 131 if do_nothing in sys.argv:
132 132 return
133 133
134 134 status = check_submodule_status(here)
135 135
136 136 if status == "missing":
137 137 print("checking out submodules for the first time")
138 138 update_submodules(here)
139 139 elif status == "unclean":
140 140 print('\n'.join([
141 141 "Cannot build / install IPython with unclean submodules",
142 142 "Please update submodules with",
143 143 " python setup.py submodule",
144 144 "or",
145 145 " git submodule update",
146 146 "or commit any submodule changes you have made."
147 147 ]))
148 148 sys.exit(1)
149 149
150 150 require_clean_submodules()
151 151
152 152 #-------------------------------------------------------------------------------
153 153 # Things related to the IPython documentation
154 154 #-------------------------------------------------------------------------------
155 155
156 156 # update the manuals when building a source dist
157 157 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
158 158
159 159 # List of things to be updated. Each entry is a triplet of args for
160 160 # target_update()
161 161 to_update = [
162 162 # FIXME - Disabled for now: we need to redo an automatic way
163 163 # of generating the magic info inside the rst.
164 164 #('docs/magic.tex',
165 165 #['IPython/Magic.py'],
166 166 #"cd doc && ./update_magic.sh" ),
167 167
168 168 ('docs/man/ipcluster.1.gz',
169 169 ['docs/man/ipcluster.1'],
170 170 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
171 171
172 172 ('docs/man/ipcontroller.1.gz',
173 173 ['docs/man/ipcontroller.1'],
174 174 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
175 175
176 176 ('docs/man/ipengine.1.gz',
177 177 ['docs/man/ipengine.1'],
178 178 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
179 179
180 180 ('docs/man/ipython.1.gz',
181 181 ['docs/man/ipython.1'],
182 182 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
183 183
184 184 ]
185 185
186 186
187 187 [ target_update(*t) for t in to_update ]
188 188
189 189 #---------------------------------------------------------------------------
190 190 # Find all the packages, package data, and data_files
191 191 #---------------------------------------------------------------------------
192 192
193 193 packages = find_packages()
194 194 package_data = find_package_data()
195 195
196 196 data_files = find_data_files()
197 197
198 198 setup_args['packages'] = packages
199 199 setup_args['package_data'] = package_data
200 200 setup_args['data_files'] = data_files
201 201
202 202 #---------------------------------------------------------------------------
203 203 # custom distutils commands
204 204 #---------------------------------------------------------------------------
205 205 # imports here, so they are after setuptools import if there was one
206 206 from distutils.command.sdist import sdist
207 207 from distutils.command.upload import upload
208 208
209 209 class UploadWindowsInstallers(upload):
210 210
211 211 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
212 212 user_options = upload.user_options + [
213 213 ('files=', 'f', 'exe file (or glob) to upload')
214 214 ]
215 215 def initialize_options(self):
216 216 upload.initialize_options(self)
217 217 meta = self.distribution.metadata
218 218 base = '{name}-{version}'.format(
219 219 name=meta.get_name(),
220 220 version=meta.get_version()
221 221 )
222 222 self.files = os.path.join('dist', '%s.*.exe' % base)
223 223
224 224 def run(self):
225 225 for dist_file in glob(self.files):
226 226 self.upload_file('bdist_wininst', 'any', dist_file)
227 227
228 228 setup_args['cmdclass'] = {
229 229 'build_py': check_package_data_first(git_prebuild('IPython')),
230 230 'sdist' : git_prebuild('IPython', sdist),
231 231 'upload_wininst' : UploadWindowsInstallers,
232 232 'submodule' : UpdateSubmodules,
233 233 'css' : CompileCSS,
234 234 'symlink': install_symlinked,
235 235 'install_lib_symlink': install_lib_symlink,
236 236 'install_scripts_sym': install_scripts_for_symlink,
237 237 'unsymlink': unsymlink,
238 238 'jsversion' : JavascriptVersion,
239 239 }
240 240
241 241 #---------------------------------------------------------------------------
242 242 # Handle scripts, dependencies, and setuptools specific things
243 243 #---------------------------------------------------------------------------
244 244
245 245 # For some commands, use setuptools. Note that we do NOT list install here!
246 246 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
247 247 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
248 248 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
249 249 'egg_info', 'easy_install', 'upload', 'install_egg_info',
250 250 ))
251 251 if sys.platform == 'win32':
252 252 # Depend on setuptools for install on *Windows only*
253 253 # If we get script-installation working without setuptools,
254 254 # then we can back off, but until then use it.
255 255 # See Issue #369 on GitHub for more
256 256 needs_setuptools.add('install')
257 257
258 258 if len(needs_setuptools.intersection(sys.argv)) > 0:
259 259 import setuptools
260 260
261 261 # This dict is used for passing extra arguments that are setuptools
262 262 # specific to setup
263 263 setuptools_extra_args = {}
264 264
265 265 # setuptools requirements
266 266
267 267 extras_require = dict(
268 268 parallel = ['pyzmq>=2.1.11'],
269 269 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
270 270 zmq = ['pyzmq>=2.1.11'],
271 271 doc = ['Sphinx>=1.1', 'numpydoc'],
272 272 test = ['nose>=0.10.1'],
273 terminal = [],
273 274 notebook = ['tornado>=3.1', 'pyzmq>=2.1.11', 'jinja2'],
274 275 nbconvert = ['pygments', 'jinja2', 'Sphinx>=0.3']
275 276 )
276 277 if sys.version_info < (3, 3):
277 278 extras_require['test'].append('mock')
278 279
279 280 everything = set()
280 281 for deps in extras_require.values():
281 282 everything.update(deps)
282 283 extras_require['all'] = everything
283 284
284 285 install_requires = []
286
287 # add readline
285 288 if sys.platform == 'darwin':
286 289 if any(arg.startswith('bdist') for arg in sys.argv) or not setupext.check_for_readline():
287 290 install_requires.append('gnureadline')
291 elif sys.platform.startswith('win'):
292 extras_require['terminal'].append('pyreadline>=2.0')
288 293
289 294
290 295 if 'setuptools' in sys.modules:
291 296 # setup.py develop should check for submodules
292 297 from setuptools.command.develop import develop
293 298 setup_args['cmdclass']['develop'] = require_submodules(develop)
294 299 setup_args['cmdclass']['bdist_wheel'] = get_bdist_wheel()
295 300
296 301 setuptools_extra_args['zip_safe'] = False
297 302 setuptools_extra_args['entry_points'] = {'console_scripts':find_entry_points()}
298 303 setup_args['extras_require'] = extras_require
299 304 requires = setup_args['install_requires'] = install_requires
300 305
301 306 # Script to be run by the windows binary installer after the default setup
302 307 # routine, to add shortcuts and similar windows-only things. Windows
303 308 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
304 309 # doesn't find them.
305 310 if 'bdist_wininst' in sys.argv:
306 311 if len(sys.argv) > 2 and \
307 312 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
308 313 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
309 314 sys.exit(1)
310 315 setup_args['data_files'].append(
311 316 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
312 317 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
313 318 setup_args['options'] = {"bdist_wininst":
314 319 {"install_script":
315 320 "ipython_win_post_install.py"}}
316 321
317 322 else:
318 323 # If we are installing without setuptools, call this function which will
319 324 # check for dependencies an inform the user what is needed. This is
320 325 # just to make life easy for users.
321 326 for install_cmd in ('install', 'symlink'):
322 327 if install_cmd in sys.argv:
323 328 check_for_dependencies()
324 329 break
325 330 # scripts has to be a non-empty list, or install_scripts isn't called
326 331 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
327 332
328 333 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
329 334
330 335 #---------------------------------------------------------------------------
331 336 # Do the actual setup now
332 337 #---------------------------------------------------------------------------
333 338
334 339 setup_args.update(setuptools_extra_args)
335 340
336 341 def main():
337 342 setup(**setup_args)
338 343 cleanup()
339 344
340 345 if __name__ == '__main__':
341 346 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