##// END OF EJS Templates
Exclude IPython.quarantine from installation.
Thomas Kluyver -
Show More
@@ -1,398 +1,398 b''
1 1 # encoding: utf-8
2 2 """
3 3 This module defines the things that are used in setup.py for building IPython
4 4
5 5 This includes:
6 6
7 7 * The basic arguments to setup
8 8 * Functions for finding things like packages, package data, etc.
9 9 * A function for checking dependencies.
10 10 """
11 11 from __future__ import print_function
12 12
13 13 #-------------------------------------------------------------------------------
14 14 # Copyright (C) 2008 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-------------------------------------------------------------------------------
19 19
20 20 #-------------------------------------------------------------------------------
21 21 # Imports
22 22 #-------------------------------------------------------------------------------
23 23 import os
24 24 import sys
25 25
26 26 try:
27 27 from configparser import ConfigParser
28 28 except:
29 29 from ConfigParser import ConfigParser
30 30 from distutils.command.build_py import build_py
31 31 from glob import glob
32 32
33 33 from setupext import install_data_ext
34 34
35 35 #-------------------------------------------------------------------------------
36 36 # Useful globals and utility functions
37 37 #-------------------------------------------------------------------------------
38 38
39 39 # A few handy globals
40 40 isfile = os.path.isfile
41 41 pjoin = os.path.join
42 42
43 43 def oscmd(s):
44 44 print(">", s)
45 45 os.system(s)
46 46
47 47 # Py3 compatibility hacks, without assuming IPython itself is installed with
48 48 # the full py3compat machinery.
49 49
50 50 try:
51 51 execfile
52 52 except NameError:
53 53 def execfile(fname, globs, locs=None):
54 54 locs = locs or globs
55 55 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
56 56
57 57 # A little utility we'll need below, since glob() does NOT allow you to do
58 58 # exclusion on multiple endings!
59 59 def file_doesnt_endwith(test,endings):
60 60 """Return true if test is a file and its name does NOT end with any
61 61 of the strings listed in endings."""
62 62 if not isfile(test):
63 63 return False
64 64 for e in endings:
65 65 if test.endswith(e):
66 66 return False
67 67 return True
68 68
69 69 #---------------------------------------------------------------------------
70 70 # Basic project information
71 71 #---------------------------------------------------------------------------
72 72
73 73 # release.py contains version, authors, license, url, keywords, etc.
74 74 execfile(pjoin('IPython','core','release.py'), globals())
75 75
76 76 # Create a dict with the basic information
77 77 # This dict is eventually passed to setup after additional keys are added.
78 78 setup_args = dict(
79 79 name = name,
80 80 version = version,
81 81 description = description,
82 82 long_description = long_description,
83 83 author = author,
84 84 author_email = author_email,
85 85 url = url,
86 86 download_url = download_url,
87 87 license = license,
88 88 platforms = platforms,
89 89 keywords = keywords,
90 90 classifiers = classifiers,
91 91 cmdclass = {'install_data': install_data_ext},
92 92 )
93 93
94 94
95 95 #---------------------------------------------------------------------------
96 96 # Find packages
97 97 #---------------------------------------------------------------------------
98 98
99 99 def find_packages():
100 100 """
101 101 Find all of IPython's packages.
102 102 """
103 excludes = ['deathrow']
103 excludes = ['deathrow', 'quarantine']
104 104 packages = []
105 105 for dir,subdirs,files in os.walk('IPython'):
106 106 package = dir.replace(os.path.sep, '.')
107 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
107 if any(package.startswith('IPython.'+exc) for exc in excludes):
108 108 # package is to be excluded (e.g. deathrow)
109 109 continue
110 110 if '__init__.py' not in files:
111 111 # not a package
112 112 continue
113 113 packages.append(package)
114 114 return packages
115 115
116 116 #---------------------------------------------------------------------------
117 117 # Find package data
118 118 #---------------------------------------------------------------------------
119 119
120 120 def find_package_data():
121 121 """
122 122 Find IPython's package_data.
123 123 """
124 124 # This is not enough for these things to appear in an sdist.
125 125 # We need to muck with the MANIFEST to get this to work
126 126
127 127 # exclude static things that we don't ship (e.g. mathjax)
128 128 excludes = ['mathjax']
129 129
130 130 # add 'static/' prefix to exclusions, and tuplify for use in startswith
131 131 excludes = tuple([os.path.join('static', ex) for ex in excludes])
132 132
133 133 # walk notebook resources:
134 134 cwd = os.getcwd()
135 135 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
136 136 static_walk = list(os.walk('static'))
137 137 os.chdir(cwd)
138 138 static_data = []
139 139 for parent, dirs, files in static_walk:
140 140 if parent.startswith(excludes):
141 141 continue
142 142 for f in files:
143 143 static_data.append(os.path.join(parent, f))
144 144
145 145 package_data = {
146 146 'IPython.config.profile' : ['README*', '*/*.py'],
147 147 'IPython.testing' : ['*.txt'],
148 148 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
149 149 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
150 150 }
151 151 return package_data
152 152
153 153
154 154 #---------------------------------------------------------------------------
155 155 # Find data files
156 156 #---------------------------------------------------------------------------
157 157
158 158 def make_dir_struct(tag,base,out_base):
159 159 """Make the directory structure of all files below a starting dir.
160 160
161 161 This is just a convenience routine to help build a nested directory
162 162 hierarchy because distutils is too stupid to do this by itself.
163 163
164 164 XXX - this needs a proper docstring!
165 165 """
166 166
167 167 # we'll use these a lot below
168 168 lbase = len(base)
169 169 pathsep = os.path.sep
170 170 lpathsep = len(pathsep)
171 171
172 172 out = []
173 173 for (dirpath,dirnames,filenames) in os.walk(base):
174 174 # we need to strip out the dirpath from the base to map it to the
175 175 # output (installation) path. This requires possibly stripping the
176 176 # path separator, because otherwise pjoin will not work correctly
177 177 # (pjoin('foo/','/bar') returns '/bar').
178 178
179 179 dp_eff = dirpath[lbase:]
180 180 if dp_eff.startswith(pathsep):
181 181 dp_eff = dp_eff[lpathsep:]
182 182 # The output path must be anchored at the out_base marker
183 183 out_path = pjoin(out_base,dp_eff)
184 184 # Now we can generate the final filenames. Since os.walk only produces
185 185 # filenames, we must join back with the dirpath to get full valid file
186 186 # paths:
187 187 pfiles = [pjoin(dirpath,f) for f in filenames]
188 188 # Finally, generate the entry we need, which is a pari of (output
189 189 # path, files) for use as a data_files parameter in install_data.
190 190 out.append((out_path, pfiles))
191 191
192 192 return out
193 193
194 194
195 195 def find_data_files():
196 196 """
197 197 Find IPython's data_files.
198 198
199 199 Most of these are docs.
200 200 """
201 201
202 202 docdirbase = pjoin('share', 'doc', 'ipython')
203 203 manpagebase = pjoin('share', 'man', 'man1')
204 204
205 205 # Simple file lists can be made by hand
206 206 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
207 207 if not manpages:
208 208 # When running from a source tree, the manpages aren't gzipped
209 209 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
210 210 igridhelpfiles = filter(isfile,
211 211 glob(pjoin('IPython','extensions','igrid_help.*')))
212 212
213 213 # For nested structures, use the utility above
214 214 example_files = make_dir_struct(
215 215 'data',
216 216 pjoin('docs','examples'),
217 217 pjoin(docdirbase,'examples')
218 218 )
219 219 manual_files = make_dir_struct(
220 220 'data',
221 221 pjoin('docs','html'),
222 222 pjoin(docdirbase,'manual')
223 223 )
224 224
225 225 # And assemble the entire output list
226 226 data_files = [ (manpagebase, manpages),
227 227 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
228 228 ] + manual_files + example_files
229 229
230 230 return data_files
231 231
232 232
233 233 def make_man_update_target(manpage):
234 234 """Return a target_update-compliant tuple for the given manpage.
235 235
236 236 Parameters
237 237 ----------
238 238 manpage : string
239 239 Name of the manpage, must include the section number (trailing number).
240 240
241 241 Example
242 242 -------
243 243
244 244 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
245 245 ('docs/man/ipython.1.gz',
246 246 ['docs/man/ipython.1'],
247 247 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
248 248 """
249 249 man_dir = pjoin('docs', 'man')
250 250 manpage_gz = manpage + '.gz'
251 251 manpath = pjoin(man_dir, manpage)
252 252 manpath_gz = pjoin(man_dir, manpage_gz)
253 253 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
254 254 locals() )
255 255 return (manpath_gz, [manpath], gz_cmd)
256 256
257 257 # The two functions below are copied from IPython.utils.path, so we don't need
258 258 # to import IPython during setup, which fails on Python 3.
259 259
260 260 def target_outdated(target,deps):
261 261 """Determine whether a target is out of date.
262 262
263 263 target_outdated(target,deps) -> 1/0
264 264
265 265 deps: list of filenames which MUST exist.
266 266 target: single filename which may or may not exist.
267 267
268 268 If target doesn't exist or is older than any file listed in deps, return
269 269 true, otherwise return false.
270 270 """
271 271 try:
272 272 target_time = os.path.getmtime(target)
273 273 except os.error:
274 274 return 1
275 275 for dep in deps:
276 276 dep_time = os.path.getmtime(dep)
277 277 if dep_time > target_time:
278 278 #print "For target",target,"Dep failed:",dep # dbg
279 279 #print "times (dep,tar):",dep_time,target_time # dbg
280 280 return 1
281 281 return 0
282 282
283 283
284 284 def target_update(target,deps,cmd):
285 285 """Update a target with a given command given a list of dependencies.
286 286
287 287 target_update(target,deps,cmd) -> runs cmd if target is outdated.
288 288
289 289 This is just a wrapper around target_outdated() which calls the given
290 290 command if target is outdated."""
291 291
292 292 if target_outdated(target,deps):
293 293 os.system(cmd)
294 294
295 295 #---------------------------------------------------------------------------
296 296 # Find scripts
297 297 #---------------------------------------------------------------------------
298 298
299 299 def find_scripts(entry_points=False, suffix=''):
300 300 """Find IPython's scripts.
301 301
302 302 if entry_points is True:
303 303 return setuptools entry_point-style definitions
304 304 else:
305 305 return file paths of plain scripts [default]
306 306
307 307 suffix is appended to script names if entry_points is True, so that the
308 308 Python 3 scripts get named "ipython3" etc.
309 309 """
310 310 if entry_points:
311 311 console_scripts = [s % suffix for s in [
312 312 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
313 313 'pycolor%s = IPython.utils.PyColorize:main',
314 314 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
315 315 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
316 316 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
317 317 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
318 318 'iptest%s = IPython.testing.iptest:main',
319 319 'irunner%s = IPython.lib.irunner:main'
320 320 ]]
321 321 gui_scripts = [s % suffix for s in [
322 322 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
323 323 ]]
324 324 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
325 325 else:
326 326 parallel_scripts = pjoin('IPython','parallel','scripts')
327 327 main_scripts = pjoin('IPython','scripts')
328 328 scripts = [
329 329 pjoin(parallel_scripts, 'ipengine'),
330 330 pjoin(parallel_scripts, 'ipcontroller'),
331 331 pjoin(parallel_scripts, 'ipcluster'),
332 332 pjoin(parallel_scripts, 'iplogger'),
333 333 pjoin(main_scripts, 'ipython'),
334 334 pjoin(main_scripts, 'pycolor'),
335 335 pjoin(main_scripts, 'irunner'),
336 336 pjoin(main_scripts, 'iptest')
337 337 ]
338 338 return scripts
339 339
340 340 #---------------------------------------------------------------------------
341 341 # Verify all dependencies
342 342 #---------------------------------------------------------------------------
343 343
344 344 def check_for_dependencies():
345 345 """Check for IPython's dependencies.
346 346
347 347 This function should NOT be called if running under setuptools!
348 348 """
349 349 from setupext.setupext import (
350 350 print_line, print_raw, print_status,
351 351 check_for_sphinx, check_for_pygments,
352 352 check_for_nose, check_for_pexpect,
353 353 check_for_pyzmq, check_for_readline
354 354 )
355 355 print_line()
356 356 print_raw("BUILDING IPYTHON")
357 357 print_status('python', sys.version)
358 358 print_status('platform', sys.platform)
359 359 if sys.platform == 'win32':
360 360 print_status('Windows version', sys.getwindowsversion())
361 361
362 362 print_raw("")
363 363 print_raw("OPTIONAL DEPENDENCIES")
364 364
365 365 check_for_sphinx()
366 366 check_for_pygments()
367 367 check_for_nose()
368 368 check_for_pexpect()
369 369 check_for_pyzmq()
370 370 check_for_readline()
371 371
372 372 def record_commit_info(pkg_dir, build_cmd=build_py):
373 373 """ Return extended build command class for recording commit
374 374
375 375 records git commit in IPython.utils._sysinfo.commit
376 376
377 377 for use in IPython.utils.sysinfo.sys_info() calls after installation.
378 378 """
379 379
380 380 class MyBuildPy(build_cmd):
381 381 ''' Subclass to write commit data into installation tree '''
382 382 def run(self):
383 383 build_cmd.run(self)
384 384 import subprocess
385 385 proc = subprocess.Popen('git rev-parse --short HEAD',
386 386 stdout=subprocess.PIPE,
387 387 stderr=subprocess.PIPE,
388 388 shell=True)
389 389 repo_commit, _ = proc.communicate()
390 390 repo_commit = repo_commit.strip()
391 391 # We write the installation commit even if it's empty
392 392 out_pth = pjoin(self.build_lib, pkg_dir, 'utils', '_sysinfo.py')
393 393 with open(out_pth, 'w') as out_file:
394 394 out_file.writelines([
395 395 '# GENERATED BY setup.py\n',
396 396 'commit = "%s"\n' % repo_commit.decode('ascii'),
397 397 ])
398 398 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now