##// END OF EJS Templates
Fixed typo in reveal/*.tpl path in setupbase.
damianavila -
Show More
@@ -1,474 +1,474 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 distutils.cmd import Command
32 32 from glob import glob
33 33
34 34 from setupext import install_data_ext
35 35
36 36 #-------------------------------------------------------------------------------
37 37 # Useful globals and utility functions
38 38 #-------------------------------------------------------------------------------
39 39
40 40 # A few handy globals
41 41 isfile = os.path.isfile
42 42 pjoin = os.path.join
43 43 repo_root = os.path.dirname(os.path.abspath(__file__))
44 44
45 45 def oscmd(s):
46 46 print(">", s)
47 47 os.system(s)
48 48
49 49 # Py3 compatibility hacks, without assuming IPython itself is installed with
50 50 # the full py3compat machinery.
51 51
52 52 try:
53 53 execfile
54 54 except NameError:
55 55 def execfile(fname, globs, locs=None):
56 56 locs = locs or globs
57 57 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
58 58
59 59 # A little utility we'll need below, since glob() does NOT allow you to do
60 60 # exclusion on multiple endings!
61 61 def file_doesnt_endwith(test,endings):
62 62 """Return true if test is a file and its name does NOT end with any
63 63 of the strings listed in endings."""
64 64 if not isfile(test):
65 65 return False
66 66 for e in endings:
67 67 if test.endswith(e):
68 68 return False
69 69 return True
70 70
71 71 #---------------------------------------------------------------------------
72 72 # Basic project information
73 73 #---------------------------------------------------------------------------
74 74
75 75 # release.py contains version, authors, license, url, keywords, etc.
76 76 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
77 77
78 78 # Create a dict with the basic information
79 79 # This dict is eventually passed to setup after additional keys are added.
80 80 setup_args = dict(
81 81 name = name,
82 82 version = version,
83 83 description = description,
84 84 long_description = long_description,
85 85 author = author,
86 86 author_email = author_email,
87 87 url = url,
88 88 download_url = download_url,
89 89 license = license,
90 90 platforms = platforms,
91 91 keywords = keywords,
92 92 classifiers = classifiers,
93 93 cmdclass = {'install_data': install_data_ext},
94 94 )
95 95
96 96
97 97 #---------------------------------------------------------------------------
98 98 # Find packages
99 99 #---------------------------------------------------------------------------
100 100
101 101 def find_packages():
102 102 """
103 103 Find all of IPython's packages.
104 104 """
105 105 excludes = ['deathrow', 'quarantine']
106 106 packages = []
107 107 for dir,subdirs,files in os.walk('IPython'):
108 108 package = dir.replace(os.path.sep, '.')
109 109 if any(package.startswith('IPython.'+exc) for exc in excludes):
110 110 # package is to be excluded (e.g. deathrow)
111 111 continue
112 112 if '__init__.py' not in files:
113 113 # not a package
114 114 continue
115 115 packages.append(package)
116 116 return packages
117 117
118 118 #---------------------------------------------------------------------------
119 119 # Find package data
120 120 #---------------------------------------------------------------------------
121 121
122 122 def find_package_data():
123 123 """
124 124 Find IPython's package_data.
125 125 """
126 126 # This is not enough for these things to appear in an sdist.
127 127 # We need to muck with the MANIFEST to get this to work
128 128
129 129 # exclude static things that we don't ship (e.g. mathjax)
130 130 excludes = ['mathjax']
131 131
132 132 # add 'static/' prefix to exclusions, and tuplify for use in startswith
133 133 excludes = tuple([os.path.join('static', ex) for ex in excludes])
134 134
135 135 # walk notebook resources:
136 136 cwd = os.getcwd()
137 137 os.chdir(os.path.join('IPython', 'html'))
138 138 static_walk = list(os.walk('static'))
139 139 os.chdir(cwd)
140 140 static_data = []
141 141 for parent, dirs, files in static_walk:
142 142 if parent.startswith(excludes):
143 143 continue
144 144 for f in files:
145 145 static_data.append(os.path.join(parent, f))
146 146
147 147 package_data = {
148 148 'IPython.config.profile' : ['README*', '*/*.py'],
149 149 'IPython.core.tests' : ['*.png', '*.jpg'],
150 150 'IPython.testing' : ['*.txt'],
151 151 'IPython.testing.plugin' : ['*.txt'],
152 152 'IPython.html' : ['templates/*'] + static_data,
153 153 'IPython.qt.console' : ['resources/icon/*.svg'],
154 154 'IPython.nbconvert' : ['templates/*.tpl', 'templates/latex/*.tplx',
155 155 'templates/latex/skeleton/*.tplx', 'templates/skeleton/*',
156 'templates/reveal/*.tplx', 'tests/files/*.*', 'exporters/tests/files/*.*']
156 'templates/reveal/*.tpl', 'tests/files/*.*', 'exporters/tests/files/*.*']
157 157 }
158 158 return package_data
159 159
160 160
161 161 #---------------------------------------------------------------------------
162 162 # Find data files
163 163 #---------------------------------------------------------------------------
164 164
165 165 def make_dir_struct(tag,base,out_base):
166 166 """Make the directory structure of all files below a starting dir.
167 167
168 168 This is just a convenience routine to help build a nested directory
169 169 hierarchy because distutils is too stupid to do this by itself.
170 170
171 171 XXX - this needs a proper docstring!
172 172 """
173 173
174 174 # we'll use these a lot below
175 175 lbase = len(base)
176 176 pathsep = os.path.sep
177 177 lpathsep = len(pathsep)
178 178
179 179 out = []
180 180 for (dirpath,dirnames,filenames) in os.walk(base):
181 181 # we need to strip out the dirpath from the base to map it to the
182 182 # output (installation) path. This requires possibly stripping the
183 183 # path separator, because otherwise pjoin will not work correctly
184 184 # (pjoin('foo/','/bar') returns '/bar').
185 185
186 186 dp_eff = dirpath[lbase:]
187 187 if dp_eff.startswith(pathsep):
188 188 dp_eff = dp_eff[lpathsep:]
189 189 # The output path must be anchored at the out_base marker
190 190 out_path = pjoin(out_base,dp_eff)
191 191 # Now we can generate the final filenames. Since os.walk only produces
192 192 # filenames, we must join back with the dirpath to get full valid file
193 193 # paths:
194 194 pfiles = [pjoin(dirpath,f) for f in filenames]
195 195 # Finally, generate the entry we need, which is a pari of (output
196 196 # path, files) for use as a data_files parameter in install_data.
197 197 out.append((out_path, pfiles))
198 198
199 199 return out
200 200
201 201
202 202 def find_data_files():
203 203 """
204 204 Find IPython's data_files.
205 205
206 206 Most of these are docs.
207 207 """
208 208
209 209 docdirbase = pjoin('share', 'doc', 'ipython')
210 210 manpagebase = pjoin('share', 'man', 'man1')
211 211
212 212 # Simple file lists can be made by hand
213 213 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
214 214 if not manpages:
215 215 # When running from a source tree, the manpages aren't gzipped
216 216 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
217 217
218 218 igridhelpfiles = [f for f in glob(pjoin('IPython','extensions','igrid_help.*')) if isfile(f)]
219 219
220 220 # For nested structures, use the utility above
221 221 example_files = make_dir_struct(
222 222 'data',
223 223 pjoin('docs','examples'),
224 224 pjoin(docdirbase,'examples')
225 225 )
226 226 manual_files = make_dir_struct(
227 227 'data',
228 228 pjoin('docs','html'),
229 229 pjoin(docdirbase,'manual')
230 230 )
231 231
232 232 # And assemble the entire output list
233 233 data_files = [ (manpagebase, manpages),
234 234 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
235 235 ] + manual_files + example_files
236 236
237 237 return data_files
238 238
239 239
240 240 def make_man_update_target(manpage):
241 241 """Return a target_update-compliant tuple for the given manpage.
242 242
243 243 Parameters
244 244 ----------
245 245 manpage : string
246 246 Name of the manpage, must include the section number (trailing number).
247 247
248 248 Example
249 249 -------
250 250
251 251 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
252 252 ('docs/man/ipython.1.gz',
253 253 ['docs/man/ipython.1'],
254 254 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
255 255 """
256 256 man_dir = pjoin('docs', 'man')
257 257 manpage_gz = manpage + '.gz'
258 258 manpath = pjoin(man_dir, manpage)
259 259 manpath_gz = pjoin(man_dir, manpage_gz)
260 260 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
261 261 locals() )
262 262 return (manpath_gz, [manpath], gz_cmd)
263 263
264 264 # The two functions below are copied from IPython.utils.path, so we don't need
265 265 # to import IPython during setup, which fails on Python 3.
266 266
267 267 def target_outdated(target,deps):
268 268 """Determine whether a target is out of date.
269 269
270 270 target_outdated(target,deps) -> 1/0
271 271
272 272 deps: list of filenames which MUST exist.
273 273 target: single filename which may or may not exist.
274 274
275 275 If target doesn't exist or is older than any file listed in deps, return
276 276 true, otherwise return false.
277 277 """
278 278 try:
279 279 target_time = os.path.getmtime(target)
280 280 except os.error:
281 281 return 1
282 282 for dep in deps:
283 283 dep_time = os.path.getmtime(dep)
284 284 if dep_time > target_time:
285 285 #print "For target",target,"Dep failed:",dep # dbg
286 286 #print "times (dep,tar):",dep_time,target_time # dbg
287 287 return 1
288 288 return 0
289 289
290 290
291 291 def target_update(target,deps,cmd):
292 292 """Update a target with a given command given a list of dependencies.
293 293
294 294 target_update(target,deps,cmd) -> runs cmd if target is outdated.
295 295
296 296 This is just a wrapper around target_outdated() which calls the given
297 297 command if target is outdated."""
298 298
299 299 if target_outdated(target,deps):
300 300 os.system(cmd)
301 301
302 302 #---------------------------------------------------------------------------
303 303 # Find scripts
304 304 #---------------------------------------------------------------------------
305 305
306 306 def find_scripts(entry_points=False, suffix=''):
307 307 """Find IPython's scripts.
308 308
309 309 if entry_points is True:
310 310 return setuptools entry_point-style definitions
311 311 else:
312 312 return file paths of plain scripts [default]
313 313
314 314 suffix is appended to script names if entry_points is True, so that the
315 315 Python 3 scripts get named "ipython3" etc.
316 316 """
317 317 if entry_points:
318 318 console_scripts = [s % suffix for s in [
319 319 'ipython%s = IPython:start_ipython',
320 320 'pycolor%s = IPython.utils.PyColorize:main',
321 321 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
322 322 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
323 323 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
324 324 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
325 325 'iptest%s = IPython.testing.iptest:main',
326 326 'irunner%s = IPython.lib.irunner:main',
327 327 ]]
328 328 gui_scripts = []
329 329 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
330 330 else:
331 331 parallel_scripts = pjoin('IPython','parallel','scripts')
332 332 main_scripts = pjoin('IPython','scripts')
333 333 scripts = [
334 334 pjoin(parallel_scripts, 'ipengine'),
335 335 pjoin(parallel_scripts, 'ipcontroller'),
336 336 pjoin(parallel_scripts, 'ipcluster'),
337 337 pjoin(parallel_scripts, 'iplogger'),
338 338 pjoin(main_scripts, 'ipython'),
339 339 pjoin(main_scripts, 'pycolor'),
340 340 pjoin(main_scripts, 'irunner'),
341 341 pjoin(main_scripts, 'iptest')
342 342 ]
343 343 return scripts
344 344
345 345 #---------------------------------------------------------------------------
346 346 # Verify all dependencies
347 347 #---------------------------------------------------------------------------
348 348
349 349 def check_for_dependencies():
350 350 """Check for IPython's dependencies.
351 351
352 352 This function should NOT be called if running under setuptools!
353 353 """
354 354 from setupext.setupext import (
355 355 print_line, print_raw, print_status,
356 356 check_for_sphinx, check_for_pygments,
357 357 check_for_nose, check_for_pexpect,
358 358 check_for_pyzmq, check_for_readline,
359 359 check_for_jinja2
360 360 )
361 361 print_line()
362 362 print_raw("BUILDING IPYTHON")
363 363 print_status('python', sys.version)
364 364 print_status('platform', sys.platform)
365 365 if sys.platform == 'win32':
366 366 print_status('Windows version', sys.getwindowsversion())
367 367
368 368 print_raw("")
369 369 print_raw("OPTIONAL DEPENDENCIES")
370 370
371 371 check_for_sphinx()
372 372 check_for_pygments()
373 373 check_for_nose()
374 374 check_for_pexpect()
375 375 check_for_pyzmq()
376 376 check_for_readline()
377 377 check_for_jinja2()
378 378
379 379 #---------------------------------------------------------------------------
380 380 # VCS related
381 381 #---------------------------------------------------------------------------
382 382
383 383 # utils.submodule has checks for submodule status
384 384 execfile(pjoin('IPython','utils','submodule.py'), globals())
385 385
386 386 class UpdateSubmodules(Command):
387 387 """Update git submodules
388 388
389 389 IPython's external javascript dependencies live in a separate repo.
390 390 """
391 391 description = "Update git submodules"
392 392 user_options = []
393 393
394 394 def initialize_options(self):
395 395 pass
396 396
397 397 def finalize_options(self):
398 398 pass
399 399
400 400 def run(self):
401 401 failure = False
402 402 try:
403 403 self.spawn('git submodule init'.split())
404 404 self.spawn('git submodule update --recursive'.split())
405 405 except Exception as e:
406 406 failure = e
407 407 print(e)
408 408
409 409 if not check_submodule_status(repo_root) == 'clean':
410 410 print("submodules could not be checked out")
411 411 sys.exit(1)
412 412
413 413
414 414 def git_prebuild(pkg_dir, build_cmd=build_py):
415 415 """Return extended build or sdist command class for recording commit
416 416
417 417 records git commit in IPython.utils._sysinfo.commit
418 418
419 419 for use in IPython.utils.sysinfo.sys_info() calls after installation.
420 420
421 421 Also ensures that submodules exist prior to running
422 422 """
423 423
424 424 class MyBuildPy(build_cmd):
425 425 ''' Subclass to write commit data into installation tree '''
426 426 def run(self):
427 427 build_cmd.run(self)
428 428 # this one will only fire for build commands
429 429 if hasattr(self, 'build_lib'):
430 430 self._record_commit(self.build_lib)
431 431
432 432 def make_release_tree(self, base_dir, files):
433 433 # this one will fire for sdist
434 434 build_cmd.make_release_tree(self, base_dir, files)
435 435 self._record_commit(base_dir)
436 436
437 437 def _record_commit(self, base_dir):
438 438 import subprocess
439 439 proc = subprocess.Popen('git rev-parse --short HEAD',
440 440 stdout=subprocess.PIPE,
441 441 stderr=subprocess.PIPE,
442 442 shell=True)
443 443 repo_commit, _ = proc.communicate()
444 444 repo_commit = repo_commit.strip().decode("ascii")
445 445
446 446 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
447 447 if os.path.isfile(out_pth) and not repo_commit:
448 448 # nothing to write, don't clobber
449 449 return
450 450
451 451 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
452 452
453 453 # remove to avoid overwriting original via hard link
454 454 try:
455 455 os.remove(out_pth)
456 456 except (IOError, OSError):
457 457 pass
458 458 with open(out_pth, 'w') as out_file:
459 459 out_file.writelines([
460 460 '# GENERATED BY setup.py\n',
461 461 'commit = "%s"\n' % repo_commit,
462 462 ])
463 463 return require_submodules(MyBuildPy)
464 464
465 465
466 466 def require_submodules(command):
467 467 """decorator for instructing a command to check for submodules before running"""
468 468 class DecoratedCommand(command):
469 469 def run(self):
470 470 if not check_submodule_status(repo_root) == 'clean':
471 471 print("submodules missing! Run `setup.py submodule` and try again")
472 472 sys.exit(1)
473 473 command.run(self)
474 474 return DecoratedCommand
General Comments 0
You need to be logged in to leave comments. Login now