##// END OF EJS Templates
remove nbconvert from package data
Min RK -
Show More
@@ -1,755 +1,758
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
12 12 # Copyright (c) IPython Development Team.
13 13 # Distributed under the terms of the Modified BSD License.
14 14
15 15 from __future__ import print_function
16 16
17 17 import errno
18 18 import os
19 19 import sys
20 20
21 21 from distutils import log
22 22 from distutils.command.build_py import build_py
23 23 from distutils.command.build_scripts import build_scripts
24 24 from distutils.command.install import install
25 25 from distutils.command.install_scripts import install_scripts
26 26 from distutils.cmd import Command
27 27 from distutils.errors import DistutilsExecError
28 28 from fnmatch import fnmatch
29 29 from glob import glob
30 30 from subprocess import Popen, PIPE
31 31
32 32 from setupext import install_data_ext
33 33
34 34 #-------------------------------------------------------------------------------
35 35 # Useful globals and utility functions
36 36 #-------------------------------------------------------------------------------
37 37
38 38 # A few handy globals
39 39 isfile = os.path.isfile
40 40 pjoin = os.path.join
41 41 repo_root = os.path.dirname(os.path.abspath(__file__))
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(repo_root, '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 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 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 components and less from the walk;
128 128 # we will build the components separately
129 129 excludes = [
130 130 pjoin('static', 'components'),
131 131 pjoin('static', '*', 'less'),
132 132 ]
133 133
134 134 # walk notebook resources:
135 135 cwd = os.getcwd()
136 136 os.chdir(os.path.join('IPython', 'html'))
137 137 static_data = []
138 138 for parent, dirs, files in os.walk('static'):
139 139 if any(fnmatch(parent, pat) for pat in excludes):
140 140 # prevent descending into subdirs
141 141 dirs[:] = []
142 142 continue
143 143 for f in files:
144 144 static_data.append(pjoin(parent, f))
145 145
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", "js", "bootstrap.min.js"),
152 152 pjoin(components, "bootstrap-tour", "build", "css", "bootstrap-tour.min.css"),
153 153 pjoin(components, "bootstrap-tour", "build", "js", "bootstrap-tour.min.js"),
154 154 pjoin(components, "es6-promise", "*.js"),
155 155 pjoin(components, "font-awesome", "fonts", "*.*"),
156 156 pjoin(components, "google-caja", "html-css-sanitizer-minified.js"),
157 157 pjoin(components, "jquery", "jquery.min.js"),
158 158 pjoin(components, "jquery-ui", "ui", "minified", "jquery-ui.min.js"),
159 159 pjoin(components, "jquery-ui", "themes", "smoothness", "jquery-ui.min.css"),
160 160 pjoin(components, "jquery-ui", "themes", "smoothness", "images", "*"),
161 161 pjoin(components, "marked", "lib", "marked.js"),
162 162 pjoin(components, "requirejs", "require.js"),
163 163 pjoin(components, "underscore", "underscore-min.js"),
164 164 pjoin(components, "moment", "moment.js"),
165 165 pjoin(components, "moment", "min", "moment.min.js"),
166 166 pjoin(components, "term.js", "src", "term.js"),
167 167 pjoin(components, "text-encoding", "lib", "encoding.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
179 os.chdir(os.path.join(cwd, 'IPython', 'nbconvert'))
180 nbconvert_templates = [os.path.join(dirpath, '*.*')
181 for dirpath, _, _ in os.walk('templates')]
178
179 # nbconvert package_data:
180 # os.chdir(os.path.join(cwd, 'IPython', 'nbconvert'))
181 # nbconvert_templates = [os.path.join(dirpath, '*.*')
182 # for dirpath, _, _ in os.walk('templates')]
183 # package_data = {
184 # 'IPython.nbconvert.filters' : ['marked.js'],
185 # 'IPython.nbconvert' : nbconvert_templates +
186 # [
187 # 'tests/files/*.*',
188 # 'exporters/tests/files/*.*',
189 # 'preprocessors/tests/files/*.*',
190 # ],
191 # }
182 192
183 193 os.chdir(cwd)
184 194
185 195 package_data = {
186 196 'IPython.core' : ['profile/README*'],
187 197 'IPython.core.tests' : ['*.png', '*.jpg'],
188 198 'IPython.lib.tests' : ['*.wav'],
189 199 'IPython.testing.plugin' : ['*.txt'],
190 200 'IPython.html' : ['templates/*'] + static_data,
191 201 'IPython.html.tests' : js_tests,
192 'IPython.nbconvert' : nbconvert_templates +
193 [
194 'tests/files/*.*',
195 'exporters/tests/files/*.*',
196 'preprocessors/tests/files/*.*',
197 ],
198 'IPython.nbconvert.filters' : ['marked.js'],
199 202 # 'IPython.nbformat' : [
200 203 # 'tests/*.ipynb',
201 204 # 'v3/nbformat.v3.schema.json',
202 205 # 'v4/nbformat.v4.schema.json',
203 206 # ],
204 207 'IPython.kernel': ['resources/*.*'],
205 208 }
206 209
207 210 return package_data
208 211
209 212
210 213 def check_package_data(package_data):
211 214 """verify that package_data globs make sense"""
212 215 print("checking package data")
213 216 for pkg, data in package_data.items():
214 217 pkg_root = pjoin(*pkg.split('.'))
215 218 for d in data:
216 219 path = pjoin(pkg_root, d)
217 220 if '*' in path:
218 221 assert len(glob(path)) > 0, "No files match pattern %s" % path
219 222 else:
220 223 assert os.path.exists(path), "Missing package data: %s" % path
221 224
222 225
223 226 def check_package_data_first(command):
224 227 """decorator for checking package_data before running a given command
225 228
226 229 Probably only needs to wrap build_py
227 230 """
228 231 class DecoratedCommand(command):
229 232 def run(self):
230 233 check_package_data(self.package_data)
231 234 command.run(self)
232 235 return DecoratedCommand
233 236
234 237
235 238 #---------------------------------------------------------------------------
236 239 # Find data files
237 240 #---------------------------------------------------------------------------
238 241
239 242 def make_dir_struct(tag,base,out_base):
240 243 """Make the directory structure of all files below a starting dir.
241 244
242 245 This is just a convenience routine to help build a nested directory
243 246 hierarchy because distutils is too stupid to do this by itself.
244 247
245 248 XXX - this needs a proper docstring!
246 249 """
247 250
248 251 # we'll use these a lot below
249 252 lbase = len(base)
250 253 pathsep = os.path.sep
251 254 lpathsep = len(pathsep)
252 255
253 256 out = []
254 257 for (dirpath,dirnames,filenames) in os.walk(base):
255 258 # we need to strip out the dirpath from the base to map it to the
256 259 # output (installation) path. This requires possibly stripping the
257 260 # path separator, because otherwise pjoin will not work correctly
258 261 # (pjoin('foo/','/bar') returns '/bar').
259 262
260 263 dp_eff = dirpath[lbase:]
261 264 if dp_eff.startswith(pathsep):
262 265 dp_eff = dp_eff[lpathsep:]
263 266 # The output path must be anchored at the out_base marker
264 267 out_path = pjoin(out_base,dp_eff)
265 268 # Now we can generate the final filenames. Since os.walk only produces
266 269 # filenames, we must join back with the dirpath to get full valid file
267 270 # paths:
268 271 pfiles = [pjoin(dirpath,f) for f in filenames]
269 272 # Finally, generate the entry we need, which is a pari of (output
270 273 # path, files) for use as a data_files parameter in install_data.
271 274 out.append((out_path, pfiles))
272 275
273 276 return out
274 277
275 278
276 279 def find_data_files():
277 280 """
278 281 Find IPython's data_files.
279 282
280 283 Just man pages at this point.
281 284 """
282 285
283 286 manpagebase = pjoin('share', 'man', 'man1')
284 287
285 288 # Simple file lists can be made by hand
286 289 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
287 290 if not manpages:
288 291 # When running from a source tree, the manpages aren't gzipped
289 292 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
290 293
291 294 # And assemble the entire output list
292 295 data_files = [ (manpagebase, manpages) ]
293 296
294 297 return data_files
295 298
296 299
297 300 def make_man_update_target(manpage):
298 301 """Return a target_update-compliant tuple for the given manpage.
299 302
300 303 Parameters
301 304 ----------
302 305 manpage : string
303 306 Name of the manpage, must include the section number (trailing number).
304 307
305 308 Example
306 309 -------
307 310
308 311 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
309 312 ('docs/man/ipython.1.gz',
310 313 ['docs/man/ipython.1'],
311 314 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
312 315 """
313 316 man_dir = pjoin('docs', 'man')
314 317 manpage_gz = manpage + '.gz'
315 318 manpath = pjoin(man_dir, manpage)
316 319 manpath_gz = pjoin(man_dir, manpage_gz)
317 320 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
318 321 locals() )
319 322 return (manpath_gz, [manpath], gz_cmd)
320 323
321 324 # The two functions below are copied from IPython.utils.path, so we don't need
322 325 # to import IPython during setup, which fails on Python 3.
323 326
324 327 def target_outdated(target,deps):
325 328 """Determine whether a target is out of date.
326 329
327 330 target_outdated(target,deps) -> 1/0
328 331
329 332 deps: list of filenames which MUST exist.
330 333 target: single filename which may or may not exist.
331 334
332 335 If target doesn't exist or is older than any file listed in deps, return
333 336 true, otherwise return false.
334 337 """
335 338 try:
336 339 target_time = os.path.getmtime(target)
337 340 except os.error:
338 341 return 1
339 342 for dep in deps:
340 343 dep_time = os.path.getmtime(dep)
341 344 if dep_time > target_time:
342 345 #print "For target",target,"Dep failed:",dep # dbg
343 346 #print "times (dep,tar):",dep_time,target_time # dbg
344 347 return 1
345 348 return 0
346 349
347 350
348 351 def target_update(target,deps,cmd):
349 352 """Update a target with a given command given a list of dependencies.
350 353
351 354 target_update(target,deps,cmd) -> runs cmd if target is outdated.
352 355
353 356 This is just a wrapper around target_outdated() which calls the given
354 357 command if target is outdated."""
355 358
356 359 if target_outdated(target,deps):
357 360 os.system(cmd)
358 361
359 362 #---------------------------------------------------------------------------
360 363 # Find scripts
361 364 #---------------------------------------------------------------------------
362 365
363 366 def find_entry_points():
364 367 """Defines the command line entry points for IPython
365 368
366 369 This always uses setuptools-style entry points. When setuptools is not in
367 370 use, our own build_scripts_entrypt class below parses these and builds
368 371 command line scripts.
369 372
370 373 Each of our entry points gets both a plain name, e.g. ipython, and one
371 374 suffixed with the Python major version number, e.g. ipython3.
372 375 """
373 376 ep = [
374 377 'ipython%s = IPython:start_ipython',
375 378 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
376 379 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
377 380 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
378 381 'iptest%s = IPython.testing.iptestcontroller:main',
379 382 ]
380 383 suffix = str(sys.version_info[0])
381 384 return [e % '' for e in ep] + [e % suffix for e in ep]
382 385
383 386 script_src = """#!{executable}
384 387 # This script was automatically generated by setup.py
385 388 if __name__ == '__main__':
386 389 from {mod} import {func}
387 390 {func}()
388 391 """
389 392
390 393 class build_scripts_entrypt(build_scripts):
391 394 """Build the command line scripts
392 395
393 396 Parse setuptools style entry points and write simple scripts to run the
394 397 target functions.
395 398
396 399 On Windows, this also creates .cmd wrappers for the scripts so that you can
397 400 easily launch them from a command line.
398 401 """
399 402 def run(self):
400 403 self.mkpath(self.build_dir)
401 404 outfiles = []
402 405 for script in find_entry_points():
403 406 name, entrypt = script.split('=')
404 407 name = name.strip()
405 408 entrypt = entrypt.strip()
406 409 outfile = os.path.join(self.build_dir, name)
407 410 outfiles.append(outfile)
408 411 print('Writing script to', outfile)
409 412
410 413 mod, func = entrypt.split(':')
411 414 with open(outfile, 'w') as f:
412 415 f.write(script_src.format(executable=sys.executable,
413 416 mod=mod, func=func))
414 417
415 418 if sys.platform == 'win32':
416 419 # Write .cmd wrappers for Windows so 'ipython' etc. work at the
417 420 # command line
418 421 cmd_file = os.path.join(self.build_dir, name + '.cmd')
419 422 cmd = '@"{python}" "%~dp0\{script}" %*\r\n'.format(
420 423 python=sys.executable, script=name)
421 424 log.info("Writing %s wrapper script" % cmd_file)
422 425 with open(cmd_file, 'w') as f:
423 426 f.write(cmd)
424 427
425 428 return outfiles, outfiles
426 429
427 430 class install_lib_symlink(Command):
428 431 user_options = [
429 432 ('install-dir=', 'd', "directory to install to"),
430 433 ]
431 434
432 435 def initialize_options(self):
433 436 self.install_dir = None
434 437
435 438 def finalize_options(self):
436 439 self.set_undefined_options('symlink',
437 440 ('install_lib', 'install_dir'),
438 441 )
439 442
440 443 def run(self):
441 444 if sys.platform == 'win32':
442 445 raise Exception("This doesn't work on Windows.")
443 446 pkg = os.path.join(os.getcwd(), 'IPython')
444 447 dest = os.path.join(self.install_dir, 'IPython')
445 448 if os.path.islink(dest):
446 449 print('removing existing symlink at %s' % dest)
447 450 os.unlink(dest)
448 451 print('symlinking %s -> %s' % (pkg, dest))
449 452 os.symlink(pkg, dest)
450 453
451 454 class unsymlink(install):
452 455 def run(self):
453 456 dest = os.path.join(self.install_lib, 'IPython')
454 457 if os.path.islink(dest):
455 458 print('removing symlink at %s' % dest)
456 459 os.unlink(dest)
457 460 else:
458 461 print('No symlink exists at %s' % dest)
459 462
460 463 class install_symlinked(install):
461 464 def run(self):
462 465 if sys.platform == 'win32':
463 466 raise Exception("This doesn't work on Windows.")
464 467
465 468 # Run all sub-commands (at least those that need to be run)
466 469 for cmd_name in self.get_sub_commands():
467 470 self.run_command(cmd_name)
468 471
469 472 # 'sub_commands': a list of commands this command might have to run to
470 473 # get its work done. See cmd.py for more info.
471 474 sub_commands = [('install_lib_symlink', lambda self:True),
472 475 ('install_scripts_sym', lambda self:True),
473 476 ]
474 477
475 478 class install_scripts_for_symlink(install_scripts):
476 479 """Redefined to get options from 'symlink' instead of 'install'.
477 480
478 481 I love distutils almost as much as I love setuptools.
479 482 """
480 483 def finalize_options(self):
481 484 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
482 485 self.set_undefined_options('symlink',
483 486 ('install_scripts', 'install_dir'),
484 487 ('force', 'force'),
485 488 ('skip_build', 'skip_build'),
486 489 )
487 490
488 491 #---------------------------------------------------------------------------
489 492 # Verify all dependencies
490 493 #---------------------------------------------------------------------------
491 494
492 495 def check_for_readline():
493 496 """Check for GNU readline"""
494 497 try:
495 498 import gnureadline as readline
496 499 except ImportError:
497 500 pass
498 501 else:
499 502 return True
500 503 try:
501 504 import readline
502 505 except ImportError:
503 506 return False
504 507 else:
505 508 if sys.platform == 'darwin' and 'libedit' in readline.__doc__:
506 509 print("Ignoring readline linked to libedit", file=sys.stderr)
507 510 return False
508 511 return True
509 512
510 513 #---------------------------------------------------------------------------
511 514 # VCS related
512 515 #---------------------------------------------------------------------------
513 516
514 517 # utils.submodule has checks for submodule status
515 518 execfile(pjoin('IPython','utils','submodule.py'), globals())
516 519
517 520 class UpdateSubmodules(Command):
518 521 """Update git submodules
519 522
520 523 IPython's external javascript dependencies live in a separate repo.
521 524 """
522 525 description = "Update git submodules"
523 526 user_options = []
524 527
525 528 def initialize_options(self):
526 529 pass
527 530
528 531 def finalize_options(self):
529 532 pass
530 533
531 534 def run(self):
532 535 failure = False
533 536 try:
534 537 self.spawn('git submodule init'.split())
535 538 self.spawn('git submodule update --recursive'.split())
536 539 except Exception as e:
537 540 failure = e
538 541 print(e)
539 542
540 543 if not check_submodule_status(repo_root) == 'clean':
541 544 print("submodules could not be checked out")
542 545 sys.exit(1)
543 546
544 547
545 548 def git_prebuild(pkg_dir, build_cmd=build_py):
546 549 """Return extended build or sdist command class for recording commit
547 550
548 551 records git commit in IPython.utils._sysinfo.commit
549 552
550 553 for use in IPython.utils.sysinfo.sys_info() calls after installation.
551 554
552 555 Also ensures that submodules exist prior to running
553 556 """
554 557
555 558 class MyBuildPy(build_cmd):
556 559 ''' Subclass to write commit data into installation tree '''
557 560 def run(self):
558 561 build_cmd.run(self)
559 562 # this one will only fire for build commands
560 563 if hasattr(self, 'build_lib'):
561 564 self._record_commit(self.build_lib)
562 565
563 566 def make_release_tree(self, base_dir, files):
564 567 # this one will fire for sdist
565 568 build_cmd.make_release_tree(self, base_dir, files)
566 569 self._record_commit(base_dir)
567 570
568 571 def _record_commit(self, base_dir):
569 572 import subprocess
570 573 proc = subprocess.Popen('git rev-parse --short HEAD',
571 574 stdout=subprocess.PIPE,
572 575 stderr=subprocess.PIPE,
573 576 shell=True)
574 577 repo_commit, _ = proc.communicate()
575 578 repo_commit = repo_commit.strip().decode("ascii")
576 579
577 580 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
578 581 if os.path.isfile(out_pth) and not repo_commit:
579 582 # nothing to write, don't clobber
580 583 return
581 584
582 585 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
583 586
584 587 # remove to avoid overwriting original via hard link
585 588 try:
586 589 os.remove(out_pth)
587 590 except (IOError, OSError):
588 591 pass
589 592 with open(out_pth, 'w') as out_file:
590 593 out_file.writelines([
591 594 '# GENERATED BY setup.py\n',
592 595 'commit = u"%s"\n' % repo_commit,
593 596 ])
594 597 return require_submodules(MyBuildPy)
595 598
596 599
597 600 def require_submodules(command):
598 601 """decorator for instructing a command to check for submodules before running"""
599 602 class DecoratedCommand(command):
600 603 def run(self):
601 604 if not check_submodule_status(repo_root) == 'clean':
602 605 print("submodules missing! Run `setup.py submodule` and try again")
603 606 sys.exit(1)
604 607 command.run(self)
605 608 return DecoratedCommand
606 609
607 610 #---------------------------------------------------------------------------
608 611 # bdist related
609 612 #---------------------------------------------------------------------------
610 613
611 614 def get_bdist_wheel():
612 615 """Construct bdist_wheel command for building wheels
613 616
614 617 Constructs py2-none-any tag, instead of py2.7-none-any
615 618 """
616 619 class RequiresWheel(Command):
617 620 description = "Dummy command for missing bdist_wheel"
618 621 user_options = []
619 622
620 623 def initialize_options(self):
621 624 pass
622 625
623 626 def finalize_options(self):
624 627 pass
625 628
626 629 def run(self):
627 630 print("bdist_wheel requires the wheel package")
628 631 sys.exit(1)
629 632
630 633 if 'setuptools' not in sys.modules:
631 634 return RequiresWheel
632 635 else:
633 636 try:
634 637 from wheel.bdist_wheel import bdist_wheel, read_pkg_info, write_pkg_info
635 638 except ImportError:
636 639 return RequiresWheel
637 640
638 641 class bdist_wheel_tag(bdist_wheel):
639 642
640 643 def add_requirements(self, metadata_path):
641 644 """transform platform-dependent requirements"""
642 645 pkg_info = read_pkg_info(metadata_path)
643 646 # pkg_info is an email.Message object (?!)
644 647 # we have to remove the unconditional 'readline' and/or 'pyreadline' entries
645 648 # and transform them to conditionals
646 649 requires = pkg_info.get_all('Requires-Dist')
647 650 del pkg_info['Requires-Dist']
648 651 def _remove_startswith(lis, prefix):
649 652 """like list.remove, but with startswith instead of =="""
650 653 found = False
651 654 for idx, item in enumerate(lis):
652 655 if item.startswith(prefix):
653 656 found = True
654 657 break
655 658 if found:
656 659 lis.pop(idx)
657 660
658 661 for pkg in ("gnureadline", "pyreadline", "mock", "terminado", "appnope", "pexpect"):
659 662 _remove_startswith(requires, pkg)
660 663 requires.append("gnureadline; sys.platform == 'darwin' and platform.python_implementation == 'CPython'")
661 664 requires.append("terminado (>=0.3.3); extra == 'notebook' and sys.platform != 'win32'")
662 665 requires.append("terminado (>=0.3.3); extra == 'all' and sys.platform != 'win32'")
663 666 requires.append("pyreadline (>=2.0); extra == 'terminal' and sys.platform == 'win32' and platform.python_implementation == 'CPython'")
664 667 requires.append("pyreadline (>=2.0); extra == 'all' and sys.platform == 'win32' and platform.python_implementation == 'CPython'")
665 668 requires.append("mock; extra == 'test' and python_version < '3.3'")
666 669 requires.append("appnope; sys.platform == 'darwin'")
667 670 requires.append("pexpect; sys.platform != 'win32'")
668 671 for r in requires:
669 672 pkg_info['Requires-Dist'] = r
670 673 write_pkg_info(metadata_path, pkg_info)
671 674
672 675 return bdist_wheel_tag
673 676
674 677 #---------------------------------------------------------------------------
675 678 # Notebook related
676 679 #---------------------------------------------------------------------------
677 680
678 681 class CompileCSS(Command):
679 682 """Recompile Notebook CSS
680 683
681 684 Regenerate the compiled CSS from LESS sources.
682 685
683 686 Requires various dev dependencies, such as invoke and lessc.
684 687 """
685 688 description = "Recompile Notebook CSS"
686 689 user_options = [
687 690 ('minify', 'x', "minify CSS"),
688 691 ('force', 'f', "force recompilation of CSS"),
689 692 ]
690 693
691 694 def initialize_options(self):
692 695 self.minify = False
693 696 self.force = False
694 697
695 698 def finalize_options(self):
696 699 self.minify = bool(self.minify)
697 700 self.force = bool(self.force)
698 701
699 702 def run(self):
700 703 cmd = ['invoke', 'css']
701 704 if self.minify:
702 705 cmd.append('--minify')
703 706 if self.force:
704 707 cmd.append('--force')
705 708 try:
706 709 p = Popen(cmd, cwd=pjoin(repo_root, "IPython", "html"), stderr=PIPE)
707 710 except OSError:
708 711 raise DistutilsExecError("invoke is required to rebuild css (pip install invoke)")
709 712 out, err = p.communicate()
710 713 if p.returncode:
711 714 if sys.version_info[0] >= 3:
712 715 err = err.decode('utf8', 'replace')
713 716 raise DistutilsExecError(err.strip())
714 717
715 718
716 719 class JavascriptVersion(Command):
717 720 """write the javascript version to notebook javascript"""
718 721 description = "Write IPython version to javascript"
719 722 user_options = []
720 723
721 724 def initialize_options(self):
722 725 pass
723 726
724 727 def finalize_options(self):
725 728 pass
726 729
727 730 def run(self):
728 731 nsfile = pjoin(repo_root, "IPython", "html", "static", "base", "js", "namespace.js")
729 732 with open(nsfile) as f:
730 733 lines = f.readlines()
731 734 with open(nsfile, 'w') as f:
732 735 found = False
733 736 for line in lines:
734 737 if line.strip().startswith("IPython.version"):
735 738 line = ' IPython.version = "{0}";\n'.format(version)
736 739 found = True
737 740 f.write(line)
738 741 if not found:
739 742 raise RuntimeError("Didn't find IPython.version line in %s" % nsfile)
740 743
741 744
742 745 def css_js_prerelease(command):
743 746 """decorator for building js/minified css prior to a release"""
744 747 class DecoratedCommand(command):
745 748 def run(self):
746 749 self.distribution.run_command('jsversion')
747 750 css = self.distribution.get_command_obj('css')
748 751 css.minify = True
749 752 try:
750 753 self.distribution.run_command('css')
751 754 except Exception as e:
752 755 log.warn("rebuilding css and sourcemaps failed (not a problem)")
753 756 log.warn(str(e))
754 757 command.run(self)
755 758 return DecoratedCommand
General Comments 0
You need to be logged in to leave comments. Login now