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