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