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