##// END OF EJS Templates
merge separate input/expected notebooks for execute preprocessor
MinRK -
Show More
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Clear Output.ipynb to IPython/nbconvert/preprocessors/tests/files/Clear Output.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Clear Output.ipynb to IPython/nbconvert/preprocessors/tests/files/Clear Output.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Factorials.ipynb to IPython/nbconvert/preprocessors/tests/files/Factorials.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Factorials.ipynb to IPython/nbconvert/preprocessors/tests/files/Factorials.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/HelloWorld.ipynb to IPython/nbconvert/preprocessors/tests/files/HelloWorld.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/HelloWorld.ipynb to IPython/nbconvert/preprocessors/tests/files/HelloWorld.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Inline Image.ipynb to IPython/nbconvert/preprocessors/tests/files/Inline Image.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Inline Image.ipynb to IPython/nbconvert/preprocessors/tests/files/Inline Image.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/SVG.ipynb to IPython/nbconvert/preprocessors/tests/files/SVG.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/SVG.ipynb to IPython/nbconvert/preprocessors/tests/files/SVG.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Skip Exceptions.ipynb to IPython/nbconvert/preprocessors/tests/files/Skip Exceptions.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Skip Exceptions.ipynb to IPython/nbconvert/preprocessors/tests/files/Skip Exceptions.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Unicode.ipynb to IPython/nbconvert/preprocessors/tests/files/Unicode.ipynb
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/expected/Unicode.ipynb to IPython/nbconvert/preprocessors/tests/files/Unicode.ipynb
1 NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/input/python.png to IPython/nbconvert/preprocessors/tests/files/python.png
NO CONTENT: file renamed from IPython/nbconvert/preprocessors/tests/input/python.png to IPython/nbconvert/preprocessors/tests/files/python.png
@@ -1,86 +1,82 b''
1 """
1 """
2 Module with tests for the execute preprocessor.
2 Module with tests for the execute preprocessor.
3 """
3 """
4
4
5 # Copyright (c) IPython Development Team.
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7
7
8 import copy
8 import copy
9 import glob
9 import os
10 import os
10 import re
11 import re
11
12
12 from IPython.nbformat import current as nbformat
13 from IPython.nbformat import current as nbformat
13
14
14 from .base import PreprocessorTestsBase
15 from .base import PreprocessorTestsBase
15 from ..execute import ExecutePreprocessor
16 from ..execute import ExecutePreprocessor
16
17
17 from IPython.nbconvert.filters import strip_ansi
18 from IPython.nbconvert.filters import strip_ansi
18
19
19
20 addr_pat = re.compile(r'0x[0-9a-f]{7,9}')
20 addr_pat = re.compile(r'0x[0-9a-f]{7,9}')
21
21
22 class TestExecute(PreprocessorTestsBase):
22 class TestExecute(PreprocessorTestsBase):
23 """Contains test functions for execute.py"""
23 """Contains test functions for execute.py"""
24
24
25 @staticmethod
25 @staticmethod
26 def normalize_output(output):
26 def normalize_output(output):
27 """
27 """
28 Normalizes outputs for comparison.
28 Normalizes outputs for comparison.
29 """
29 """
30 output = dict(output)
30 output = dict(output)
31 if 'metadata' in output:
31 if 'metadata' in output:
32 del output['metadata']
32 del output['metadata']
33 if 'text' in output:
33 if 'text' in output:
34 output['text'] = re.sub(addr_pat, '<HEXADDR>', output['text'])
34 output['text'] = re.sub(addr_pat, '<HEXADDR>', output['text'])
35 if 'svg' in output:
35 if 'svg' in output:
36 del output['text']
36 del output['text']
37 if 'traceback' in output:
37 if 'traceback' in output:
38 tb = []
38 tb = []
39 for line in output['traceback']:
39 for line in output['traceback']:
40 tb.append(strip_ansi(line))
40 tb.append(strip_ansi(line))
41 output['traceback'] = tb
41 output['traceback'] = tb
42
42
43 return output
43 return output
44
44
45
45
46 def assert_notebooks_equal(self, expected, actual):
46 def assert_notebooks_equal(self, expected, actual):
47 expected_cells = expected['worksheets'][0]['cells']
47 expected_cells = expected['worksheets'][0]['cells']
48 actual_cells = actual['worksheets'][0]['cells']
48 actual_cells = actual['worksheets'][0]['cells']
49 assert len(expected_cells) == len(actual_cells)
49 assert len(expected_cells) == len(actual_cells)
50
50
51 for expected_cell, actual_cell in zip(expected_cells, actual_cells):
51 for expected_cell, actual_cell in zip(expected_cells, actual_cells):
52 expected_outputs = expected_cell.get('outputs', [])
52 expected_outputs = expected_cell.get('outputs', [])
53 actual_outputs = actual_cell.get('outputs', [])
53 actual_outputs = actual_cell.get('outputs', [])
54 normalized_expected_outputs = list(map(self.normalize_output, expected_outputs))
54 normalized_expected_outputs = list(map(self.normalize_output, expected_outputs))
55 normalized_actual_outputs = list(map(self.normalize_output, actual_outputs))
55 normalized_actual_outputs = list(map(self.normalize_output, actual_outputs))
56 assert normalized_expected_outputs == normalized_actual_outputs
56 assert normalized_expected_outputs == normalized_actual_outputs
57
57
58
58
59 def build_preprocessor(self):
59 def build_preprocessor(self):
60 """Make an instance of a preprocessor"""
60 """Make an instance of a preprocessor"""
61 preprocessor = ExecutePreprocessor()
61 preprocessor = ExecutePreprocessor()
62 preprocessor.enabled = True
62 preprocessor.enabled = True
63 return preprocessor
63 return preprocessor
64
64
65
65
66 def test_constructor(self):
66 def test_constructor(self):
67 """Can a ExecutePreprocessor be constructed?"""
67 """Can a ExecutePreprocessor be constructed?"""
68 self.build_preprocessor()
68 self.build_preprocessor()
69
69
70
70
71 def test_run_notebooks(self):
71 def test_run_notebooks(self):
72 """Runs a series of test notebooks and compares them to their actual output"""
72 """Runs a series of test notebooks and compares them to their actual output"""
73 current_dir = os.path.dirname(__file__)
73 current_dir = os.path.dirname(__file__)
74 input_files = os.listdir(os.path.join(current_dir, 'input'))
74 input_files = glob.glob(os.path.join(current_dir, 'files', '*.ipynb'))
75 for filename in input_files:
75 for filename in input_files:
76 if not filename.endswith(".ipynb"):
76 with open(os.path.join(current_dir, 'files', filename)) as f:
77 continue
78 with open(os.path.join(current_dir, 'input', filename)) as f:
79 input_nb = nbformat.read(f, 'ipynb')
77 input_nb = nbformat.read(f, 'ipynb')
80 with open(os.path.join(current_dir, 'expected', filename)) as f:
81 expected_nb = nbformat.read(f, 'ipynb')
82 res = self.build_resources()
78 res = self.build_resources()
83 preprocessor = self.build_preprocessor()
79 preprocessor = self.build_preprocessor()
84 output_nb, _ = preprocessor(input_nb, res)
80 output_nb, _ = preprocessor(copy.deepcopy(input_nb), res)
85 self.assert_notebooks_equal(output_nb, expected_nb)
81 self.assert_notebooks_equal(output_nb, input_nb)
86
82
@@ -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
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now