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