##// END OF EJS Templates
Fix renaming scripts with 3 suffix on Python 3
Thomas Kluyver -
Show More
@@ -1,331 +1,335 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.txt, 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 find_scripts,
62 build_scripts_rename,
62 63 find_data_files,
63 64 check_for_dependencies,
64 65 git_prebuild,
65 66 check_submodule_status,
66 67 update_submodules,
67 68 require_submodules,
68 69 UpdateSubmodules,
69 70 CompileCSS,
70 71 )
71 72 from setupext import setupext
72 73
73 74 isfile = os.path.isfile
74 75 pjoin = os.path.join
75 76
76 77 #-----------------------------------------------------------------------------
77 78 # Function definitions
78 79 #-----------------------------------------------------------------------------
79 80
80 81 def cleanup():
81 82 """Clean up the junk left around by the build process"""
82 83 if "develop" not in sys.argv and "egg_info" not in sys.argv:
83 84 try:
84 85 shutil.rmtree('ipython.egg-info')
85 86 except:
86 87 try:
87 88 os.unlink('ipython.egg-info')
88 89 except:
89 90 pass
90 91
91 92 #-------------------------------------------------------------------------------
92 93 # Handle OS specific things
93 94 #-------------------------------------------------------------------------------
94 95
95 96 if os.name in ('nt','dos'):
96 97 os_name = 'windows'
97 98 else:
98 99 os_name = os.name
99 100
100 101 # Under Windows, 'sdist' has not been supported. Now that the docs build with
101 102 # Sphinx it might work, but let's not turn it on until someone confirms that it
102 103 # actually works.
103 104 if os_name == 'windows' and 'sdist' in sys.argv:
104 105 print('The sdist command is not available under Windows. Exiting.')
105 106 sys.exit(1)
106 107
107 108 #-------------------------------------------------------------------------------
108 109 # Make sure we aren't trying to run without submodules
109 110 #-------------------------------------------------------------------------------
110 111 here = os.path.abspath(os.path.dirname(__file__))
111 112
112 113 def require_clean_submodules():
113 114 """Check on git submodules before distutils can do anything
114 115
115 116 Since distutils cannot be trusted to update the tree
116 117 after everything has been set in motion,
117 118 this is not a distutils command.
118 119 """
119 120 # PACKAGERS: Add a return here to skip checks for git submodules
120 121
121 122 # don't do anything if nothing is actually supposed to happen
122 123 for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
123 124 if do_nothing in sys.argv:
124 125 return
125 126
126 127 status = check_submodule_status(here)
127 128
128 129 if status == "missing":
129 130 print("checking out submodules for the first time")
130 131 update_submodules(here)
131 132 elif status == "unclean":
132 133 print('\n'.join([
133 134 "Cannot build / install IPython with unclean submodules",
134 135 "Please update submodules with",
135 136 " python setup.py submodule",
136 137 "or",
137 138 " git submodule update",
138 139 "or commit any submodule changes you have made."
139 140 ]))
140 141 sys.exit(1)
141 142
142 143 require_clean_submodules()
143 144
144 145 #-------------------------------------------------------------------------------
145 146 # Things related to the IPython documentation
146 147 #-------------------------------------------------------------------------------
147 148
148 149 # update the manuals when building a source dist
149 150 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
150 151 import textwrap
151 152
152 153 # List of things to be updated. Each entry is a triplet of args for
153 154 # target_update()
154 155 to_update = [
155 156 # FIXME - Disabled for now: we need to redo an automatic way
156 157 # of generating the magic info inside the rst.
157 158 #('docs/magic.tex',
158 159 #['IPython/Magic.py'],
159 160 #"cd doc && ./update_magic.sh" ),
160 161
161 162 ('docs/man/ipcluster.1.gz',
162 163 ['docs/man/ipcluster.1'],
163 164 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
164 165
165 166 ('docs/man/ipcontroller.1.gz',
166 167 ['docs/man/ipcontroller.1'],
167 168 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
168 169
169 170 ('docs/man/ipengine.1.gz',
170 171 ['docs/man/ipengine.1'],
171 172 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
172 173
173 174 ('docs/man/iplogger.1.gz',
174 175 ['docs/man/iplogger.1'],
175 176 'cd docs/man && gzip -9c iplogger.1 > iplogger.1.gz'),
176 177
177 178 ('docs/man/ipython.1.gz',
178 179 ['docs/man/ipython.1'],
179 180 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
180 181
181 182 ('docs/man/irunner.1.gz',
182 183 ['docs/man/irunner.1'],
183 184 'cd docs/man && gzip -9c irunner.1 > irunner.1.gz'),
184 185 ]
185 186
186 187
187 188 [ target_update(*t) for t in to_update ]
188 189
189 190 #---------------------------------------------------------------------------
190 191 # Find all the packages, package data, and data_files
191 192 #---------------------------------------------------------------------------
192 193
193 194 packages = find_packages()
194 195 package_data = find_package_data()
195 196 data_files = find_data_files()
196 197
197 198 setup_args['packages'] = packages
198 199 setup_args['package_data'] = package_data
199 200 setup_args['data_files'] = data_files
200 201
201 202 #---------------------------------------------------------------------------
202 203 # custom distutils commands
203 204 #---------------------------------------------------------------------------
204 205 # imports here, so they are after setuptools import if there was one
205 206 from distutils.command.sdist import sdist
206 207 from distutils.command.upload import upload
207 208
208 209 class UploadWindowsInstallers(upload):
209 210
210 211 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
211 212 user_options = upload.user_options + [
212 213 ('files=', 'f', 'exe file (or glob) to upload')
213 214 ]
214 215 def initialize_options(self):
215 216 upload.initialize_options(self)
216 217 meta = self.distribution.metadata
217 218 base = '{name}-{version}'.format(
218 219 name=meta.get_name(),
219 220 version=meta.get_version()
220 221 )
221 222 self.files = os.path.join('dist', '%s.*.exe' % base)
222 223
223 224 def run(self):
224 225 for dist_file in glob(self.files):
225 226 self.upload_file('bdist_wininst', 'any', dist_file)
226 227
227 228 setup_args['cmdclass'] = {
228 229 'build_py': git_prebuild('IPython'),
229 230 'sdist' : git_prebuild('IPython', sdist),
230 231 'upload_wininst' : UploadWindowsInstallers,
231 232 'submodule' : UpdateSubmodules,
232 233 'css' : CompileCSS,
233 234 }
234 235
235 236 #---------------------------------------------------------------------------
236 237 # Handle scripts, dependencies, and setuptools specific things
237 238 #---------------------------------------------------------------------------
238 239
239 240 # For some commands, use setuptools. Note that we do NOT list install here!
240 241 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
241 242 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
242 243 'bdist', 'bdist_dumb', 'bdist_wininst', 'install_egg_info',
243 244 'egg_info', 'easy_install', 'upload',
244 245 ))
245 246 if sys.platform == 'win32':
246 247 # Depend on setuptools for install on *Windows only*
247 248 # If we get script-installation working without setuptools,
248 249 # then we can back off, but until then use it.
249 250 # See Issue #369 on GitHub for more
250 251 needs_setuptools.add('install')
251 252
252 253 if len(needs_setuptools.intersection(sys.argv)) > 0:
253 254 import setuptools
254 255
255 256 # This dict is used for passing extra arguments that are setuptools
256 257 # specific to setup
257 258 setuptools_extra_args = {}
258 259
259 260 if 'setuptools' in sys.modules:
260 261 # setup.py develop should check for submodules
261 262 from setuptools.command.develop import develop
262 263 setup_args['cmdclass']['develop'] = require_submodules(develop)
263 264
264 265 setuptools_extra_args['zip_safe'] = False
265 266 setuptools_extra_args['entry_points'] = find_scripts(True, suffix = '3' if PY3 else '')
266 267 setup_args['extras_require'] = dict(
267 268 parallel = 'pyzmq>=2.1.11',
268 269 qtconsole = ['pyzmq>=2.1.11', 'pygments'],
269 270 zmq = 'pyzmq>=2.1.11',
270 271 doc = 'Sphinx>=0.3',
271 272 test = 'nose>=0.10.1',
272 273 notebook = ['tornado>=3.1', 'pyzmq>=2.1.11', 'jinja2'],
273 274 nbconvert = ['pygments', 'jinja2', 'Sphinx>=0.3']
274 275 )
275 276 everything = set()
276 277 for deps in setup_args['extras_require'].values():
277 278 if not isinstance(deps, list):
278 279 deps = [deps]
279 280 for dep in deps:
280 281 everything.add(dep)
281 282 setup_args['extras_require']['all'] = everything
282 283
283 284 requires = setup_args.setdefault('install_requires', [])
284 285 setupext.display_status = False
285 286 if not setupext.check_for_readline():
286 287 if sys.platform == 'darwin':
287 288 requires.append('readline')
288 289 elif sys.platform.startswith('win'):
289 290 # Pyreadline 64 bit windows issue solved in versions >=1.7.1
290 291 # Also solves issues with some older versions of pyreadline that
291 292 # satisfy the unconstrained depdendency.
292 293 requires.append('pyreadline>=1.7.1')
293 294 else:
294 295 pass
295 296 # do we want to install readline here?
296 297
297 298 # Script to be run by the windows binary installer after the default setup
298 299 # routine, to add shortcuts and similar windows-only things. Windows
299 300 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
300 301 # doesn't find them.
301 302 if 'bdist_wininst' in sys.argv:
302 303 if len(sys.argv) > 2 and \
303 304 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
304 305 print >> sys.stderr, "ERROR: bdist_wininst must be run alone. Exiting."
305 306 sys.exit(1)
306 307 setup_args['data_files'].append(
307 308 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
308 309 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
309 310 setup_args['options'] = {"bdist_wininst":
310 311 {"install_script":
311 312 "ipython_win_post_install.py"}}
312 313
313 314 else:
314 315 # If we are running without setuptools, call this function which will
315 316 # check for dependencies an inform the user what is needed. This is
316 317 # just to make life easy for users.
317 318 check_for_dependencies()
318 setup_args['scripts'] = find_scripts(False, suffix = '3' if PY3 else '')
319 setup_args['scripts'] = find_scripts(False)
320 if PY3:
321 # Rename scripts with '3' suffix
322 setup_args['cmdclass']['build_scripts'] = build_scripts_rename
319 323
320 324 #---------------------------------------------------------------------------
321 325 # Do the actual setup now
322 326 #---------------------------------------------------------------------------
323 327
324 328 setup_args.update(setuptools_extra_args)
325 329
326 330 def main():
327 331 setup(**setup_args)
328 332 cleanup()
329 333
330 334 if __name__ == '__main__':
331 335 main()
@@ -1,503 +1,517 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 11 from __future__ import print_function
12 12
13 13 #-------------------------------------------------------------------------------
14 14 # Copyright (C) 2008 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-------------------------------------------------------------------------------
19 19
20 20 #-------------------------------------------------------------------------------
21 21 # Imports
22 22 #-------------------------------------------------------------------------------
23 23 import os
24 24 import sys
25 25
26 26 try:
27 27 from configparser import ConfigParser
28 28 except:
29 29 from ConfigParser import ConfigParser
30 30 from distutils.command.build_py import build_py
31 from distutils.command.build_scripts import build_scripts
31 32 from distutils.cmd import Command
32 33 from glob import glob
33 34 from subprocess import call
34 35
35 36 from setupext import install_data_ext
36 37
37 38 #-------------------------------------------------------------------------------
38 39 # Useful globals and utility functions
39 40 #-------------------------------------------------------------------------------
40 41
41 42 # A few handy globals
42 43 isfile = os.path.isfile
43 44 pjoin = os.path.join
44 45 repo_root = os.path.dirname(os.path.abspath(__file__))
45 46
46 47 def oscmd(s):
47 48 print(">", s)
48 49 os.system(s)
49 50
50 51 # Py3 compatibility hacks, without assuming IPython itself is installed with
51 52 # the full py3compat machinery.
52 53
53 54 try:
54 55 execfile
55 56 except NameError:
56 57 def execfile(fname, globs, locs=None):
57 58 locs = locs or globs
58 59 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
59 60
60 61 # A little utility we'll need below, since glob() does NOT allow you to do
61 62 # exclusion on multiple endings!
62 63 def file_doesnt_endwith(test,endings):
63 64 """Return true if test is a file and its name does NOT end with any
64 65 of the strings listed in endings."""
65 66 if not isfile(test):
66 67 return False
67 68 for e in endings:
68 69 if test.endswith(e):
69 70 return False
70 71 return True
71 72
72 73 #---------------------------------------------------------------------------
73 74 # Basic project information
74 75 #---------------------------------------------------------------------------
75 76
76 77 # release.py contains version, authors, license, url, keywords, etc.
77 78 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
78 79
79 80 # Create a dict with the basic information
80 81 # This dict is eventually passed to setup after additional keys are added.
81 82 setup_args = dict(
82 83 name = name,
83 84 version = version,
84 85 description = description,
85 86 long_description = long_description,
86 87 author = author,
87 88 author_email = author_email,
88 89 url = url,
89 90 download_url = download_url,
90 91 license = license,
91 92 platforms = platforms,
92 93 keywords = keywords,
93 94 classifiers = classifiers,
94 95 cmdclass = {'install_data': install_data_ext},
95 96 )
96 97
97 98
98 99 #---------------------------------------------------------------------------
99 100 # Find packages
100 101 #---------------------------------------------------------------------------
101 102
102 103 def find_packages():
103 104 """
104 105 Find all of IPython's packages.
105 106 """
106 107 excludes = ['deathrow', 'quarantine']
107 108 packages = []
108 109 for dir,subdirs,files in os.walk('IPython'):
109 110 package = dir.replace(os.path.sep, '.')
110 111 if any(package.startswith('IPython.'+exc) for exc in excludes):
111 112 # package is to be excluded (e.g. deathrow)
112 113 continue
113 114 if '__init__.py' not in files:
114 115 # not a package
115 116 continue
116 117 packages.append(package)
117 118 return packages
118 119
119 120 #---------------------------------------------------------------------------
120 121 # Find package data
121 122 #---------------------------------------------------------------------------
122 123
123 124 def find_package_data():
124 125 """
125 126 Find IPython's package_data.
126 127 """
127 128 # This is not enough for these things to appear in an sdist.
128 129 # We need to muck with the MANIFEST to get this to work
129 130
130 131 # exclude static things that we don't ship (e.g. mathjax)
131 132 excludes = ['mathjax']
132 133
133 134 # add 'static/' prefix to exclusions, and tuplify for use in startswith
134 135 excludes = tuple([os.path.join('static', ex) for ex in excludes])
135 136
136 137 # walk notebook resources:
137 138 cwd = os.getcwd()
138 139 os.chdir(os.path.join('IPython', 'html'))
139 140 static_walk = list(os.walk('static'))
140 141 static_data = []
141 142 for parent, dirs, files in static_walk:
142 143 if parent.startswith(excludes):
143 144 continue
144 145 for f in files:
145 146 static_data.append(os.path.join(parent, f))
146 147
147 148 os.chdir(os.path.join('tests',))
148 149 js_tests = glob('casperjs/*.*') + glob('casperjs/*/*')
149 150 os.chdir(cwd)
150 151
151 152 package_data = {
152 153 'IPython.config.profile' : ['README*', '*/*.py'],
153 154 'IPython.core.tests' : ['*.png', '*.jpg'],
154 155 'IPython.testing' : ['*.txt'],
155 156 'IPython.testing.plugin' : ['*.txt'],
156 157 'IPython.html' : ['templates/*'] + static_data,
157 158 'IPython.html.tests' : js_tests,
158 159 'IPython.qt.console' : ['resources/icon/*.svg'],
159 160 'IPython.nbconvert' : ['templates/*.tpl', 'templates/latex/*.tplx',
160 161 'templates/latex/skeleton/*.tplx', 'templates/skeleton/*',
161 162 'templates/reveal_internals/*.tpl', 'tests/files/*.*',
162 163 'exporters/tests/files/*.*'],
163 164 'IPython.nbformat' : ['tests/*.ipynb']
164 165 }
165 166 return package_data
166 167
167 168
168 169 #---------------------------------------------------------------------------
169 170 # Find data files
170 171 #---------------------------------------------------------------------------
171 172
172 173 def make_dir_struct(tag,base,out_base):
173 174 """Make the directory structure of all files below a starting dir.
174 175
175 176 This is just a convenience routine to help build a nested directory
176 177 hierarchy because distutils is too stupid to do this by itself.
177 178
178 179 XXX - this needs a proper docstring!
179 180 """
180 181
181 182 # we'll use these a lot below
182 183 lbase = len(base)
183 184 pathsep = os.path.sep
184 185 lpathsep = len(pathsep)
185 186
186 187 out = []
187 188 for (dirpath,dirnames,filenames) in os.walk(base):
188 189 # we need to strip out the dirpath from the base to map it to the
189 190 # output (installation) path. This requires possibly stripping the
190 191 # path separator, because otherwise pjoin will not work correctly
191 192 # (pjoin('foo/','/bar') returns '/bar').
192 193
193 194 dp_eff = dirpath[lbase:]
194 195 if dp_eff.startswith(pathsep):
195 196 dp_eff = dp_eff[lpathsep:]
196 197 # The output path must be anchored at the out_base marker
197 198 out_path = pjoin(out_base,dp_eff)
198 199 # Now we can generate the final filenames. Since os.walk only produces
199 200 # filenames, we must join back with the dirpath to get full valid file
200 201 # paths:
201 202 pfiles = [pjoin(dirpath,f) for f in filenames]
202 203 # Finally, generate the entry we need, which is a pari of (output
203 204 # path, files) for use as a data_files parameter in install_data.
204 205 out.append((out_path, pfiles))
205 206
206 207 return out
207 208
208 209
209 210 def find_data_files():
210 211 """
211 212 Find IPython's data_files.
212 213
213 214 Most of these are docs.
214 215 """
215 216
216 217 docdirbase = pjoin('share', 'doc', 'ipython')
217 218 manpagebase = pjoin('share', 'man', 'man1')
218 219
219 220 # Simple file lists can be made by hand
220 221 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
221 222 if not manpages:
222 223 # When running from a source tree, the manpages aren't gzipped
223 224 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
224 225
225 226 igridhelpfiles = [f for f in glob(pjoin('IPython','extensions','igrid_help.*')) if isfile(f)]
226 227
227 228 # For nested structures, use the utility above
228 229 example_files = make_dir_struct(
229 230 'data',
230 231 pjoin('docs','examples'),
231 232 pjoin(docdirbase,'examples')
232 233 )
233 234 manual_files = make_dir_struct(
234 235 'data',
235 236 pjoin('docs','html'),
236 237 pjoin(docdirbase,'manual')
237 238 )
238 239
239 240 # And assemble the entire output list
240 241 data_files = [ (manpagebase, manpages),
241 242 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
242 243 ] + manual_files + example_files
243 244
244 245 return data_files
245 246
246 247
247 248 def make_man_update_target(manpage):
248 249 """Return a target_update-compliant tuple for the given manpage.
249 250
250 251 Parameters
251 252 ----------
252 253 manpage : string
253 254 Name of the manpage, must include the section number (trailing number).
254 255
255 256 Example
256 257 -------
257 258
258 259 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
259 260 ('docs/man/ipython.1.gz',
260 261 ['docs/man/ipython.1'],
261 262 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
262 263 """
263 264 man_dir = pjoin('docs', 'man')
264 265 manpage_gz = manpage + '.gz'
265 266 manpath = pjoin(man_dir, manpage)
266 267 manpath_gz = pjoin(man_dir, manpage_gz)
267 268 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
268 269 locals() )
269 270 return (manpath_gz, [manpath], gz_cmd)
270 271
271 272 # The two functions below are copied from IPython.utils.path, so we don't need
272 273 # to import IPython during setup, which fails on Python 3.
273 274
274 275 def target_outdated(target,deps):
275 276 """Determine whether a target is out of date.
276 277
277 278 target_outdated(target,deps) -> 1/0
278 279
279 280 deps: list of filenames which MUST exist.
280 281 target: single filename which may or may not exist.
281 282
282 283 If target doesn't exist or is older than any file listed in deps, return
283 284 true, otherwise return false.
284 285 """
285 286 try:
286 287 target_time = os.path.getmtime(target)
287 288 except os.error:
288 289 return 1
289 290 for dep in deps:
290 291 dep_time = os.path.getmtime(dep)
291 292 if dep_time > target_time:
292 293 #print "For target",target,"Dep failed:",dep # dbg
293 294 #print "times (dep,tar):",dep_time,target_time # dbg
294 295 return 1
295 296 return 0
296 297
297 298
298 299 def target_update(target,deps,cmd):
299 300 """Update a target with a given command given a list of dependencies.
300 301
301 302 target_update(target,deps,cmd) -> runs cmd if target is outdated.
302 303
303 304 This is just a wrapper around target_outdated() which calls the given
304 305 command if target is outdated."""
305 306
306 307 if target_outdated(target,deps):
307 308 os.system(cmd)
308 309
309 310 #---------------------------------------------------------------------------
310 311 # Find scripts
311 312 #---------------------------------------------------------------------------
312 313
313 314 def find_scripts(entry_points=False, suffix=''):
314 315 """Find IPython's scripts.
315 316
316 317 if entry_points is True:
317 318 return setuptools entry_point-style definitions
318 319 else:
319 320 return file paths of plain scripts [default]
320 321
321 322 suffix is appended to script names if entry_points is True, so that the
322 323 Python 3 scripts get named "ipython3" etc.
323 324 """
324 325 if entry_points:
325 326 console_scripts = [s % suffix for s in [
326 327 'ipython%s = IPython:start_ipython',
327 328 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
328 329 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
329 330 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
330 331 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
331 332 'iptest%s = IPython.testing.iptestcontroller:main',
332 333 'irunner%s = IPython.lib.irunner:main',
333 334 ]]
334 335 gui_scripts = []
335 336 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
336 337 else:
337 338 parallel_scripts = pjoin('IPython','parallel','scripts')
338 339 main_scripts = pjoin('IPython','scripts')
339 340 scripts = [
340 341 pjoin(parallel_scripts, 'ipengine'),
341 342 pjoin(parallel_scripts, 'ipcontroller'),
342 343 pjoin(parallel_scripts, 'ipcluster'),
343 344 pjoin(parallel_scripts, 'iplogger'),
344 345 pjoin(main_scripts, 'ipython'),
345 346 pjoin(main_scripts, 'irunner'),
346 347 pjoin(main_scripts, 'iptest')
347 348 ]
348 349 return scripts
349 350
351 class build_scripts_rename(build_scripts):
352 """Use this on Python 3 to rename scripts to ipython3 etc."""
353 _suffix = '3'
354
355 def copy_scripts(self):
356 outfiles, updated_files = super(build_scripts_rename, self).copy_scripts()
357 new_outfiles = [p + self._suffix for p in outfiles]
358 updated_files = [p + self._suffix for p in updated_files]
359 for old, new in zip(outfiles, new_outfiles):
360 self.move_file(old, new)
361 return new_outfiles, updated_files
362
363
350 364 #---------------------------------------------------------------------------
351 365 # Verify all dependencies
352 366 #---------------------------------------------------------------------------
353 367
354 368 def check_for_dependencies():
355 369 """Check for IPython's dependencies.
356 370
357 371 This function should NOT be called if running under setuptools!
358 372 """
359 373 from setupext.setupext import (
360 374 print_line, print_raw, print_status,
361 375 check_for_sphinx, check_for_pygments,
362 376 check_for_nose, check_for_pexpect,
363 377 check_for_pyzmq, check_for_readline,
364 378 check_for_jinja2, check_for_tornado
365 379 )
366 380 print_line()
367 381 print_raw("BUILDING IPYTHON")
368 382 print_status('python', sys.version)
369 383 print_status('platform', sys.platform)
370 384 if sys.platform == 'win32':
371 385 print_status('Windows version', sys.getwindowsversion())
372 386
373 387 print_raw("")
374 388 print_raw("OPTIONAL DEPENDENCIES")
375 389
376 390 check_for_sphinx()
377 391 check_for_pygments()
378 392 check_for_nose()
379 393 check_for_pexpect()
380 394 check_for_pyzmq()
381 395 check_for_tornado()
382 396 check_for_readline()
383 397 check_for_jinja2()
384 398
385 399 #---------------------------------------------------------------------------
386 400 # VCS related
387 401 #---------------------------------------------------------------------------
388 402
389 403 # utils.submodule has checks for submodule status
390 404 execfile(pjoin('IPython','utils','submodule.py'), globals())
391 405
392 406 class UpdateSubmodules(Command):
393 407 """Update git submodules
394 408
395 409 IPython's external javascript dependencies live in a separate repo.
396 410 """
397 411 description = "Update git submodules"
398 412 user_options = []
399 413
400 414 def initialize_options(self):
401 415 pass
402 416
403 417 def finalize_options(self):
404 418 pass
405 419
406 420 def run(self):
407 421 failure = False
408 422 try:
409 423 self.spawn('git submodule init'.split())
410 424 self.spawn('git submodule update --recursive'.split())
411 425 except Exception as e:
412 426 failure = e
413 427 print(e)
414 428
415 429 if not check_submodule_status(repo_root) == 'clean':
416 430 print("submodules could not be checked out")
417 431 sys.exit(1)
418 432
419 433
420 434 def git_prebuild(pkg_dir, build_cmd=build_py):
421 435 """Return extended build or sdist command class for recording commit
422 436
423 437 records git commit in IPython.utils._sysinfo.commit
424 438
425 439 for use in IPython.utils.sysinfo.sys_info() calls after installation.
426 440
427 441 Also ensures that submodules exist prior to running
428 442 """
429 443
430 444 class MyBuildPy(build_cmd):
431 445 ''' Subclass to write commit data into installation tree '''
432 446 def run(self):
433 447 build_cmd.run(self)
434 448 # this one will only fire for build commands
435 449 if hasattr(self, 'build_lib'):
436 450 self._record_commit(self.build_lib)
437 451
438 452 def make_release_tree(self, base_dir, files):
439 453 # this one will fire for sdist
440 454 build_cmd.make_release_tree(self, base_dir, files)
441 455 self._record_commit(base_dir)
442 456
443 457 def _record_commit(self, base_dir):
444 458 import subprocess
445 459 proc = subprocess.Popen('git rev-parse --short HEAD',
446 460 stdout=subprocess.PIPE,
447 461 stderr=subprocess.PIPE,
448 462 shell=True)
449 463 repo_commit, _ = proc.communicate()
450 464 repo_commit = repo_commit.strip().decode("ascii")
451 465
452 466 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
453 467 if os.path.isfile(out_pth) and not repo_commit:
454 468 # nothing to write, don't clobber
455 469 return
456 470
457 471 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
458 472
459 473 # remove to avoid overwriting original via hard link
460 474 try:
461 475 os.remove(out_pth)
462 476 except (IOError, OSError):
463 477 pass
464 478 with open(out_pth, 'w') as out_file:
465 479 out_file.writelines([
466 480 '# GENERATED BY setup.py\n',
467 481 'commit = "%s"\n' % repo_commit,
468 482 ])
469 483 return require_submodules(MyBuildPy)
470 484
471 485
472 486 def require_submodules(command):
473 487 """decorator for instructing a command to check for submodules before running"""
474 488 class DecoratedCommand(command):
475 489 def run(self):
476 490 if not check_submodule_status(repo_root) == 'clean':
477 491 print("submodules missing! Run `setup.py submodule` and try again")
478 492 sys.exit(1)
479 493 command.run(self)
480 494 return DecoratedCommand
481 495
482 496 #---------------------------------------------------------------------------
483 497 # Notebook related
484 498 #---------------------------------------------------------------------------
485 499
486 500 class CompileCSS(Command):
487 501 """Recompile Notebook CSS
488 502
489 503 Regenerate the compiled CSS from LESS sources.
490 504
491 505 Requires various dev dependencies, such as fabric and lessc.
492 506 """
493 507 description = "Recompile Notebook CSS"
494 508 user_options = []
495 509
496 510 def initialize_options(self):
497 511 pass
498 512
499 513 def finalize_options(self):
500 514 pass
501 515
502 516 def run(self):
503 517 call("fab css", shell=True, cwd=pjoin(repo_root, "IPython", "html"))
General Comments 0
You need to be logged in to leave comments. Login now