##// END OF EJS Templates
remove nbformat...
Min RK -
Show More
@@ -1,521 +1,519 b''
1 1 # -*- coding: utf-8 -*-
2 2 """IPython Test Suite Runner.
3 3
4 4 This module provides a main entry point to a user script to test IPython
5 5 itself from the command line. There are two ways of running this script:
6 6
7 7 1. With the syntax `iptest all`. This runs our entire test suite by
8 8 calling this script (with different arguments) recursively. This
9 9 causes modules and package to be tested in different processes, using nose
10 10 or trial where appropriate.
11 11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 12 the script simply calls nose, but with special command line flags and
13 13 plugins loaded.
14 14
15 15 """
16 16
17 17 # Copyright (c) IPython Development Team.
18 18 # Distributed under the terms of the Modified BSD License.
19 19
20 20 from __future__ import print_function
21 21
22 22 import glob
23 23 from io import BytesIO
24 24 import os
25 25 import os.path as path
26 26 import sys
27 27 from threading import Thread, Lock, Event
28 28 import warnings
29 29
30 30 import nose.plugins.builtin
31 31 from nose.plugins.xunit import Xunit
32 32 from nose import SkipTest
33 33 from nose.core import TestProgram
34 34 from nose.plugins import Plugin
35 35 from nose.util import safe_str
36 36
37 37 from IPython.utils.process import is_cmd_found
38 38 from IPython.utils.py3compat import bytes_to_str
39 39 from IPython.utils.importstring import import_item
40 40 from IPython.testing.plugin.ipdoctest import IPythonDoctest
41 41 from IPython.external.decorators import KnownFailure, knownfailureif
42 42
43 43 pjoin = path.join
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Warnings control
47 47 #-----------------------------------------------------------------------------
48 48
49 49 # Twisted generates annoying warnings with Python 2.6, as will do other code
50 50 # that imports 'sets' as of today
51 51 warnings.filterwarnings('ignore', 'the sets module is deprecated',
52 52 DeprecationWarning )
53 53
54 54 # This one also comes from Twisted
55 55 warnings.filterwarnings('ignore', 'the sha module is deprecated',
56 56 DeprecationWarning)
57 57
58 58 # Wx on Fedora11 spits these out
59 59 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
60 60 UserWarning)
61 61
62 62 # ------------------------------------------------------------------------------
63 63 # Monkeypatch Xunit to count known failures as skipped.
64 64 # ------------------------------------------------------------------------------
65 65 def monkeypatch_xunit():
66 66 try:
67 67 knownfailureif(True)(lambda: None)()
68 68 except Exception as e:
69 69 KnownFailureTest = type(e)
70 70
71 71 def addError(self, test, err, capt=None):
72 72 if issubclass(err[0], KnownFailureTest):
73 73 err = (SkipTest,) + err[1:]
74 74 return self.orig_addError(test, err, capt)
75 75
76 76 Xunit.orig_addError = Xunit.addError
77 77 Xunit.addError = addError
78 78
79 79 #-----------------------------------------------------------------------------
80 80 # Check which dependencies are installed and greater than minimum version.
81 81 #-----------------------------------------------------------------------------
82 82 def extract_version(mod):
83 83 return mod.__version__
84 84
85 85 def test_for(item, min_version=None, callback=extract_version):
86 86 """Test to see if item is importable, and optionally check against a minimum
87 87 version.
88 88
89 89 If min_version is given, the default behavior is to check against the
90 90 `__version__` attribute of the item, but specifying `callback` allows you to
91 91 extract the value you are interested in. e.g::
92 92
93 93 In [1]: import sys
94 94
95 95 In [2]: from IPython.testing.iptest import test_for
96 96
97 97 In [3]: test_for('sys', (2,6), callback=lambda sys: sys.version_info)
98 98 Out[3]: True
99 99
100 100 """
101 101 try:
102 102 check = import_item(item)
103 103 except (ImportError, RuntimeError):
104 104 # GTK reports Runtime error if it can't be initialized even if it's
105 105 # importable.
106 106 return False
107 107 else:
108 108 if min_version:
109 109 if callback:
110 110 # extra processing step to get version to compare
111 111 check = callback(check)
112 112
113 113 return check >= min_version
114 114 else:
115 115 return True
116 116
117 117 # Global dict where we can store information on what we have and what we don't
118 118 # have available at test run time
119 119 have = {}
120 120
121 121 have['curses'] = test_for('_curses')
122 122 have['matplotlib'] = test_for('matplotlib')
123 123 have['numpy'] = test_for('numpy')
124 124 have['pexpect'] = test_for('pexpect')
125 125 have['pymongo'] = test_for('pymongo')
126 126 have['pygments'] = test_for('pygments')
127 127 have['qt'] = test_for('IPython.external.qt')
128 128 have['sqlite3'] = test_for('sqlite3')
129 129 have['tornado'] = test_for('tornado.version_info', (4,0), callback=None)
130 130 have['jinja2'] = test_for('jinja2')
131 131 have['mistune'] = test_for('mistune')
132 132 have['requests'] = test_for('requests')
133 133 have['sphinx'] = test_for('sphinx')
134 134 have['jsonschema'] = test_for('jsonschema')
135 135 have['terminado'] = test_for('terminado')
136 136 have['casperjs'] = is_cmd_found('casperjs')
137 137 have['phantomjs'] = is_cmd_found('phantomjs')
138 138 have['slimerjs'] = is_cmd_found('slimerjs')
139 139
140 140 min_zmq = (13,)
141 141
142 142 have['zmq'] = test_for('zmq.pyzmq_version_info', min_zmq, callback=lambda x: x())
143 143
144 144 #-----------------------------------------------------------------------------
145 145 # Test suite definitions
146 146 #-----------------------------------------------------------------------------
147 147
148 148 test_group_names = ['parallel', 'kernel', 'kernel.inprocess', 'config', 'core',
149 149 'extensions', 'lib', 'terminal', 'testing', 'utils',
150 'nbformat', 'qt', 'html', 'nbconvert'
150 'qt', 'html', 'nbconvert'
151 151 ]
152 152
153 153 class TestSection(object):
154 154 def __init__(self, name, includes):
155 155 self.name = name
156 156 self.includes = includes
157 157 self.excludes = []
158 158 self.dependencies = []
159 159 self.enabled = True
160 160
161 161 def exclude(self, module):
162 162 if not module.startswith('IPython'):
163 163 module = self.includes[0] + "." + module
164 164 self.excludes.append(module.replace('.', os.sep))
165 165
166 166 def requires(self, *packages):
167 167 self.dependencies.extend(packages)
168 168
169 169 @property
170 170 def will_run(self):
171 171 return self.enabled and all(have[p] for p in self.dependencies)
172 172
173 173 shims = {
174 174 'parallel': 'ipython_parallel',
175 175 'kernel': 'ipython_kernel',
176 176 'kernel.inprocess': 'ipython_kernel.inprocess',
177 177 'config': 'traitlets',
178 178 }
179 179
180 180 # Name -> (include, exclude, dependencies_met)
181 181 test_sections = {n:TestSection(n, [shims.get(n, 'IPython.%s' % n)]) for n in test_group_names}
182 182
183 183
184 184 # Exclusions and dependencies
185 185 # ---------------------------
186 186
187 187 # core:
188 188 sec = test_sections['core']
189 189 if not have['sqlite3']:
190 190 sec.exclude('tests.test_history')
191 191 sec.exclude('history')
192 192 if not have['matplotlib']:
193 193 sec.exclude('pylabtools'),
194 194 sec.exclude('tests.test_pylabtools')
195 195
196 196 # lib:
197 197 sec = test_sections['lib']
198 198 if not have['zmq']:
199 199 sec.exclude('kernel')
200 200 # We do this unconditionally, so that the test suite doesn't import
201 201 # gtk, changing the default encoding and masking some unicode bugs.
202 202 sec.exclude('inputhookgtk')
203 203 # We also do this unconditionally, because wx can interfere with Unix signals.
204 204 # There are currently no tests for it anyway.
205 205 sec.exclude('inputhookwx')
206 206 # Testing inputhook will need a lot of thought, to figure out
207 207 # how to have tests that don't lock up with the gui event
208 208 # loops in the picture
209 209 sec.exclude('inputhook')
210 210
211 211 # testing:
212 212 sec = test_sections['testing']
213 213 # These have to be skipped on win32 because they use echo, rm, cd, etc.
214 214 # See ticket https://github.com/ipython/ipython/issues/87
215 215 if sys.platform == 'win32':
216 216 sec.exclude('plugin.test_exampleip')
217 217 sec.exclude('plugin.dtexample')
218 218
219 219 # terminal:
220 220 if (not have['pexpect']) or (not have['zmq']):
221 221 test_sections['terminal'].exclude('console')
222 222
223 223 # parallel
224 224 sec = test_sections['parallel']
225 225 sec.requires('zmq')
226 226 if not have['pymongo']:
227 227 sec.exclude('controller.mongodb')
228 228 sec.exclude('tests.test_mongodb')
229 229
230 230 # kernel:
231 231 sec = test_sections['kernel']
232 232 sec.requires('zmq')
233 233 # The in-process kernel tests are done in a separate section
234 234 sec.exclude('inprocess')
235 235 # importing gtk sets the default encoding, which we want to avoid
236 236 sec.exclude('gui.gtkembed')
237 237 sec.exclude('gui.gtk3embed')
238 238 if not have['matplotlib']:
239 239 sec.exclude('pylab')
240 240
241 241 # kernel.inprocess:
242 242 test_sections['kernel.inprocess'].requires('zmq')
243 243
244 244 # extensions:
245 245 sec = test_sections['extensions']
246 246 # This is deprecated in favour of rpy2
247 247 sec.exclude('rmagic')
248 248 # autoreload does some strange stuff, so move it to its own test section
249 249 sec.exclude('autoreload')
250 250 sec.exclude('tests.test_autoreload')
251 251 test_sections['autoreload'] = TestSection('autoreload',
252 252 ['IPython.extensions.autoreload', 'IPython.extensions.tests.test_autoreload'])
253 253 test_group_names.append('autoreload')
254 254
255 255 # qt:
256 256 test_sections['qt'].requires('zmq', 'qt', 'pygments')
257 257
258 258 # html:
259 259 sec = test_sections['html']
260 260 sec.requires('zmq', 'tornado', 'requests', 'sqlite3', 'jsonschema')
261 261 # The notebook 'static' directory contains JS, css and other
262 262 # files for web serving. Occasionally projects may put a .py
263 263 # file in there (MathJax ships a conf.py), so we might as
264 264 # well play it safe and skip the whole thing.
265 265 sec.exclude('static')
266 266 sec.exclude('tasks')
267 267 if not have['jinja2']:
268 268 sec.exclude('notebookapp')
269 269 if not have['pygments'] or not have['jinja2']:
270 270 sec.exclude('nbconvert')
271 271 if not have['terminado']:
272 272 sec.exclude('terminal')
273 273
274 274 # nbconvert:
275 275 sec = test_sections['nbconvert']
276 276 sec.requires('pygments', 'jinja2', 'jsonschema', 'mistune')
277 277 # Exclude nbconvert directories containing config files used to test.
278 278 # Executing the config files with iptest would cause an exception.
279 279 sec.exclude('tests.files')
280 280 sec.exclude('exporters.tests.files')
281 281 if not have['tornado']:
282 282 sec.exclude('nbconvert.post_processors.serve')
283 283 sec.exclude('nbconvert.post_processors.tests.test_serve')
284 284
285 # nbformat:
286 test_sections['nbformat'].requires('jsonschema')
287 285
288 286 #-----------------------------------------------------------------------------
289 287 # Functions and classes
290 288 #-----------------------------------------------------------------------------
291 289
292 290 def check_exclusions_exist():
293 291 from IPython.utils.path import get_ipython_package_dir
294 292 from IPython.utils.warn import warn
295 293 parent = os.path.dirname(get_ipython_package_dir())
296 294 for sec in test_sections:
297 295 for pattern in sec.exclusions:
298 296 fullpath = pjoin(parent, pattern)
299 297 if not os.path.exists(fullpath) and not glob.glob(fullpath + '.*'):
300 298 warn("Excluding nonexistent file: %r" % pattern)
301 299
302 300
303 301 class ExclusionPlugin(Plugin):
304 302 """A nose plugin to effect our exclusions of files and directories.
305 303 """
306 304 name = 'exclusions'
307 305 score = 3000 # Should come before any other plugins
308 306
309 307 def __init__(self, exclude_patterns=None):
310 308 """
311 309 Parameters
312 310 ----------
313 311
314 312 exclude_patterns : sequence of strings, optional
315 313 Filenames containing these patterns (as raw strings, not as regular
316 314 expressions) are excluded from the tests.
317 315 """
318 316 self.exclude_patterns = exclude_patterns or []
319 317 super(ExclusionPlugin, self).__init__()
320 318
321 319 def options(self, parser, env=os.environ):
322 320 Plugin.options(self, parser, env)
323 321
324 322 def configure(self, options, config):
325 323 Plugin.configure(self, options, config)
326 324 # Override nose trying to disable plugin.
327 325 self.enabled = True
328 326
329 327 def wantFile(self, filename):
330 328 """Return whether the given filename should be scanned for tests.
331 329 """
332 330 if any(pat in filename for pat in self.exclude_patterns):
333 331 return False
334 332 return None
335 333
336 334 def wantDirectory(self, directory):
337 335 """Return whether the given directory should be scanned for tests.
338 336 """
339 337 if any(pat in directory for pat in self.exclude_patterns):
340 338 return False
341 339 return None
342 340
343 341
344 342 class StreamCapturer(Thread):
345 343 daemon = True # Don't hang if main thread crashes
346 344 started = False
347 345 def __init__(self, echo=False):
348 346 super(StreamCapturer, self).__init__()
349 347 self.echo = echo
350 348 self.streams = []
351 349 self.buffer = BytesIO()
352 350 self.readfd, self.writefd = os.pipe()
353 351 self.buffer_lock = Lock()
354 352 self.stop = Event()
355 353
356 354 def run(self):
357 355 self.started = True
358 356
359 357 while not self.stop.is_set():
360 358 chunk = os.read(self.readfd, 1024)
361 359
362 360 with self.buffer_lock:
363 361 self.buffer.write(chunk)
364 362 if self.echo:
365 363 sys.stdout.write(bytes_to_str(chunk))
366 364
367 365 os.close(self.readfd)
368 366 os.close(self.writefd)
369 367
370 368 def reset_buffer(self):
371 369 with self.buffer_lock:
372 370 self.buffer.truncate(0)
373 371 self.buffer.seek(0)
374 372
375 373 def get_buffer(self):
376 374 with self.buffer_lock:
377 375 return self.buffer.getvalue()
378 376
379 377 def ensure_started(self):
380 378 if not self.started:
381 379 self.start()
382 380
383 381 def halt(self):
384 382 """Safely stop the thread."""
385 383 if not self.started:
386 384 return
387 385
388 386 self.stop.set()
389 387 os.write(self.writefd, b'\0') # Ensure we're not locked in a read()
390 388 self.join()
391 389
392 390 class SubprocessStreamCapturePlugin(Plugin):
393 391 name='subprocstreams'
394 392 def __init__(self):
395 393 Plugin.__init__(self)
396 394 self.stream_capturer = StreamCapturer()
397 395 self.destination = os.environ.get('IPTEST_SUBPROC_STREAMS', 'capture')
398 396 # This is ugly, but distant parts of the test machinery need to be able
399 397 # to redirect streams, so we make the object globally accessible.
400 398 nose.iptest_stdstreams_fileno = self.get_write_fileno
401 399
402 400 def get_write_fileno(self):
403 401 if self.destination == 'capture':
404 402 self.stream_capturer.ensure_started()
405 403 return self.stream_capturer.writefd
406 404 elif self.destination == 'discard':
407 405 return os.open(os.devnull, os.O_WRONLY)
408 406 else:
409 407 return sys.__stdout__.fileno()
410 408
411 409 def configure(self, options, config):
412 410 Plugin.configure(self, options, config)
413 411 # Override nose trying to disable plugin.
414 412 if self.destination == 'capture':
415 413 self.enabled = True
416 414
417 415 def startTest(self, test):
418 416 # Reset log capture
419 417 self.stream_capturer.reset_buffer()
420 418
421 419 def formatFailure(self, test, err):
422 420 # Show output
423 421 ec, ev, tb = err
424 422 captured = self.stream_capturer.get_buffer().decode('utf-8', 'replace')
425 423 if captured.strip():
426 424 ev = safe_str(ev)
427 425 out = [ev, '>> begin captured subprocess output <<',
428 426 captured,
429 427 '>> end captured subprocess output <<']
430 428 return ec, '\n'.join(out), tb
431 429
432 430 return err
433 431
434 432 formatError = formatFailure
435 433
436 434 def finalize(self, result):
437 435 self.stream_capturer.halt()
438 436
439 437
440 438 def run_iptest():
441 439 """Run the IPython test suite using nose.
442 440
443 441 This function is called when this script is **not** called with the form
444 442 `iptest all`. It simply calls nose with appropriate command line flags
445 443 and accepts all of the standard nose arguments.
446 444 """
447 445 # Apply our monkeypatch to Xunit
448 446 if '--with-xunit' in sys.argv and not hasattr(Xunit, 'orig_addError'):
449 447 monkeypatch_xunit()
450 448
451 449 warnings.filterwarnings('ignore',
452 450 'This will be removed soon. Use IPython.testing.util instead')
453 451
454 452 arg1 = sys.argv[1]
455 453 if arg1 in test_sections:
456 454 section = test_sections[arg1]
457 455 sys.argv[1:2] = section.includes
458 456 elif arg1.startswith('IPython.') and arg1[8:] in test_sections:
459 457 section = test_sections[arg1[8:]]
460 458 sys.argv[1:2] = section.includes
461 459 else:
462 460 section = TestSection(arg1, includes=[arg1])
463 461
464 462
465 463 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
466 464 # We add --exe because of setuptools' imbecility (it
467 465 # blindly does chmod +x on ALL files). Nose does the
468 466 # right thing and it tries to avoid executables,
469 467 # setuptools unfortunately forces our hand here. This
470 468 # has been discussed on the distutils list and the
471 469 # setuptools devs refuse to fix this problem!
472 470 '--exe',
473 471 ]
474 472 if '-a' not in argv and '-A' not in argv:
475 473 argv = argv + ['-a', '!crash']
476 474
477 475 if nose.__version__ >= '0.11':
478 476 # I don't fully understand why we need this one, but depending on what
479 477 # directory the test suite is run from, if we don't give it, 0 tests
480 478 # get run. Specifically, if the test suite is run from the source dir
481 479 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
482 480 # even if the same call done in this directory works fine). It appears
483 481 # that if the requested package is in the current dir, nose bails early
484 482 # by default. Since it's otherwise harmless, leave it in by default
485 483 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
486 484 argv.append('--traverse-namespace')
487 485
488 486 plugins = [ ExclusionPlugin(section.excludes), KnownFailure(),
489 487 SubprocessStreamCapturePlugin() ]
490 488
491 489 # we still have some vestigial doctests in core
492 490 if (section.name.startswith(('core', 'IPython.core'))):
493 491 plugins.append(IPythonDoctest())
494 492 argv.extend([
495 493 '--with-ipdoctest',
496 494 '--ipdoctest-tests',
497 495 '--ipdoctest-extension=txt',
498 496 ])
499 497
500 498
501 499 # Use working directory set by parent process (see iptestcontroller)
502 500 if 'IPTEST_WORKING_DIR' in os.environ:
503 501 os.chdir(os.environ['IPTEST_WORKING_DIR'])
504 502
505 503 # We need a global ipython running in this process, but the special
506 504 # in-process group spawns its own IPython kernels, so for *that* group we
507 505 # must avoid also opening the global one (otherwise there's a conflict of
508 506 # singletons). Ultimately the solution to this problem is to refactor our
509 507 # assumptions about what needs to be a singleton and what doesn't (app
510 508 # objects should, individual shells shouldn't). But for now, this
511 509 # workaround allows the test suite for the inprocess module to complete.
512 510 if 'kernel.inprocess' not in section.name:
513 511 from IPython.testing import globalipapp
514 512 globalipapp.start_ipython()
515 513
516 514 # Now nose can run
517 515 TestProgram(argv=argv, addplugins=plugins)
518 516
519 517 if __name__ == '__main__':
520 518 run_iptest()
521 519
@@ -1,361 +1,361 b''
1 1 #!/usr/bin/env python
2 2 # -*- coding: utf-8 -*-
3 3 """Setup script for IPython.
4 4
5 5 Under Posix environments it works like a typical setup.py script.
6 6 Under Windows, the command sdist is not supported, since IPython
7 7 requires utilities which are not available under Windows."""
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (c) 2008-2011, IPython Development Team.
11 11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.rst, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Minimal Python version sanity check
22 22 #-----------------------------------------------------------------------------
23 23 from __future__ import print_function
24 24
25 25 import sys
26 26
27 27 # This check is also made in IPython/__init__, don't forget to update both when
28 28 # changing Python version requirements.
29 29 v = sys.version_info
30 30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
31 31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
32 32 print(error, file=sys.stderr)
33 33 sys.exit(1)
34 34
35 35 PY3 = (sys.version_info[0] >= 3)
36 36
37 37 # At least we're on the python version we need, move on.
38 38
39 39 #-------------------------------------------------------------------------------
40 40 # Imports
41 41 #-------------------------------------------------------------------------------
42 42
43 43 # Stdlib imports
44 44 import os
45 45 import shutil
46 46
47 47 from glob import glob
48 48
49 49 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
50 50 # update it when the contents of directories change.
51 51 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
52 52
53 53 from distutils.core import setup
54 54
55 55 # Our own imports
56 56 from setupbase import target_update
57 57
58 58 from setupbase import (
59 59 setup_args,
60 60 find_packages,
61 61 find_package_data,
62 62 check_package_data_first,
63 63 find_entry_points,
64 64 build_scripts_entrypt,
65 65 find_data_files,
66 66 check_for_readline,
67 67 git_prebuild,
68 68 check_submodule_status,
69 69 update_submodules,
70 70 require_submodules,
71 71 UpdateSubmodules,
72 72 get_bdist_wheel,
73 73 CompileCSS,
74 74 JavascriptVersion,
75 75 css_js_prerelease,
76 76 install_symlinked,
77 77 install_lib_symlink,
78 78 install_scripts_for_symlink,
79 79 unsymlink,
80 80 )
81 81
82 82 isfile = os.path.isfile
83 83 pjoin = os.path.join
84 84
85 85 #-------------------------------------------------------------------------------
86 86 # Handle OS specific things
87 87 #-------------------------------------------------------------------------------
88 88
89 89 if os.name in ('nt','dos'):
90 90 os_name = 'windows'
91 91 else:
92 92 os_name = os.name
93 93
94 94 # Under Windows, 'sdist' has not been supported. Now that the docs build with
95 95 # Sphinx it might work, but let's not turn it on until someone confirms that it
96 96 # actually works.
97 97 if os_name == 'windows' and 'sdist' in sys.argv:
98 98 print('The sdist command is not available under Windows. Exiting.')
99 99 sys.exit(1)
100 100
101 101 #-------------------------------------------------------------------------------
102 102 # Make sure we aren't trying to run without submodules
103 103 #-------------------------------------------------------------------------------
104 104 here = os.path.abspath(os.path.dirname(__file__))
105 105
106 106 def require_clean_submodules():
107 107 """Check on git submodules before distutils can do anything
108 108
109 109 Since distutils cannot be trusted to update the tree
110 110 after everything has been set in motion,
111 111 this is not a distutils command.
112 112 """
113 113 # PACKAGERS: Add a return here to skip checks for git submodules
114 114
115 115 # don't do anything if nothing is actually supposed to happen
116 116 for do_nothing in ('-h', '--help', '--help-commands', 'clean', 'submodule'):
117 117 if do_nothing in sys.argv:
118 118 return
119 119
120 120 status = check_submodule_status(here)
121 121
122 122 if status == "missing":
123 123 print("checking out submodules for the first time")
124 124 update_submodules(here)
125 125 elif status == "unclean":
126 126 print('\n'.join([
127 127 "Cannot build / install IPython with unclean submodules",
128 128 "Please update submodules with",
129 129 " python setup.py submodule",
130 130 "or",
131 131 " git submodule update",
132 132 "or commit any submodule changes you have made."
133 133 ]))
134 134 sys.exit(1)
135 135
136 136 require_clean_submodules()
137 137
138 138 #-------------------------------------------------------------------------------
139 139 # Things related to the IPython documentation
140 140 #-------------------------------------------------------------------------------
141 141
142 142 # update the manuals when building a source dist
143 143 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
144 144
145 145 # List of things to be updated. Each entry is a triplet of args for
146 146 # target_update()
147 147 to_update = [
148 148 # FIXME - Disabled for now: we need to redo an automatic way
149 149 # of generating the magic info inside the rst.
150 150 #('docs/magic.tex',
151 151 #['IPython/Magic.py'],
152 152 #"cd doc && ./update_magic.sh" ),
153 153
154 154 ('docs/man/ipcluster.1.gz',
155 155 ['docs/man/ipcluster.1'],
156 156 'cd docs/man && gzip -9c ipcluster.1 > ipcluster.1.gz'),
157 157
158 158 ('docs/man/ipcontroller.1.gz',
159 159 ['docs/man/ipcontroller.1'],
160 160 'cd docs/man && gzip -9c ipcontroller.1 > ipcontroller.1.gz'),
161 161
162 162 ('docs/man/ipengine.1.gz',
163 163 ['docs/man/ipengine.1'],
164 164 'cd docs/man && gzip -9c ipengine.1 > ipengine.1.gz'),
165 165
166 166 ('docs/man/ipython.1.gz',
167 167 ['docs/man/ipython.1'],
168 168 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
169 169
170 170 ]
171 171
172 172
173 173 [ target_update(*t) for t in to_update ]
174 174
175 175 #---------------------------------------------------------------------------
176 176 # Find all the packages, package data, and data_files
177 177 #---------------------------------------------------------------------------
178 178
179 179 packages = find_packages()
180 180 package_data = find_package_data()
181 181
182 182 data_files = find_data_files()
183 183
184 184 setup_args['packages'] = packages
185 185 setup_args['package_data'] = package_data
186 186 setup_args['data_files'] = data_files
187 187
188 188 #---------------------------------------------------------------------------
189 189 # custom distutils commands
190 190 #---------------------------------------------------------------------------
191 191 # imports here, so they are after setuptools import if there was one
192 192 from distutils.command.sdist import sdist
193 193 from distutils.command.upload import upload
194 194
195 195 class UploadWindowsInstallers(upload):
196 196
197 197 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
198 198 user_options = upload.user_options + [
199 199 ('files=', 'f', 'exe file (or glob) to upload')
200 200 ]
201 201 def initialize_options(self):
202 202 upload.initialize_options(self)
203 203 meta = self.distribution.metadata
204 204 base = '{name}-{version}'.format(
205 205 name=meta.get_name(),
206 206 version=meta.get_version()
207 207 )
208 208 self.files = os.path.join('dist', '%s.*.exe' % base)
209 209
210 210 def run(self):
211 211 for dist_file in glob(self.files):
212 212 self.upload_file('bdist_wininst', 'any', dist_file)
213 213
214 214 setup_args['cmdclass'] = {
215 215 'build_py': css_js_prerelease(
216 216 check_package_data_first(git_prebuild('IPython'))),
217 217 'sdist' : css_js_prerelease(git_prebuild('IPython', sdist)),
218 218 'upload_wininst' : UploadWindowsInstallers,
219 219 'submodule' : UpdateSubmodules,
220 220 'css' : CompileCSS,
221 221 'symlink': install_symlinked,
222 222 'install_lib_symlink': install_lib_symlink,
223 223 'install_scripts_sym': install_scripts_for_symlink,
224 224 'unsymlink': unsymlink,
225 225 'jsversion' : JavascriptVersion,
226 226 }
227 227
228 228 ### Temporarily disable install while it's broken during the big split
229 229 from textwrap import dedent
230 230 from distutils.command.install import install
231 231
232 232 class DisabledInstall(install):
233 233 def run(self):
234 234 msg = dedent("""
235 235 While we are in the midst of The Big Split,
236 236 IPython cannot be installed from master.
237 237 You can use `pip install -e .` for an editable install,
238 238 which still works.
239 239 """)
240 240 print(msg, file=sys.stderr)
241 241 raise SystemExit(1)
242 242
243 243 setup_args['cmdclass']['install'] = DisabledInstall
244 244
245 245
246 246 #---------------------------------------------------------------------------
247 247 # Handle scripts, dependencies, and setuptools specific things
248 248 #---------------------------------------------------------------------------
249 249
250 250 # For some commands, use setuptools. Note that we do NOT list install here!
251 251 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
252 252 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
253 253 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
254 254 'egg_info', 'easy_install', 'upload', 'install_egg_info',
255 255 ))
256 256
257 257 if len(needs_setuptools.intersection(sys.argv)) > 0:
258 258 import setuptools
259 259
260 260 # This dict is used for passing extra arguments that are setuptools
261 261 # specific to setup
262 262 setuptools_extra_args = {}
263 263
264 264 # setuptools requirements
265 265
266 266 pyzmq = 'pyzmq>=13'
267 267
268 268 extras_require = dict(
269 269 parallel = [pyzmq],
270 270 qtconsole = [pyzmq, 'pygments'],
271 271 doc = ['Sphinx>=1.1', 'numpydoc'],
272 272 test = ['nose>=0.10.1', 'requests'],
273 273 terminal = [],
274 nbformat = ['jsonschema>=2.0'],
274 nbformat = ['jupyter_nbformat'],
275 275 notebook = ['tornado>=4.0', pyzmq, 'jinja2', 'pygments', 'mistune>=0.5'],
276 276 nbconvert = ['pygments', 'jinja2', 'mistune>=0.3.1']
277 277 )
278 278
279 279 if not sys.platform.startswith('win'):
280 280 extras_require['notebook'].append('terminado>=0.3.3')
281 281
282 282 if sys.version_info < (3, 3):
283 283 extras_require['test'].append('mock')
284 284
285 285 extras_require['notebook'].extend(extras_require['nbformat'])
286 286 extras_require['nbconvert'].extend(extras_require['nbformat'])
287 287
288 288 install_requires = [
289 289 'decorator',
290 290 'pickleshare',
291 291 'simplegeneric>0.8',
292 292 'traitlets',
293 293 ]
294 294
295 295 # add platform-specific dependencies
296 296 if sys.platform == 'darwin':
297 297 install_requires.append('appnope')
298 298 if 'bdist_wheel' in sys.argv[1:] or not check_for_readline():
299 299 install_requires.append('gnureadline')
300 300
301 301 if sys.platform.startswith('win'):
302 302 extras_require['terminal'].append('pyreadline>=2.0')
303 303 else:
304 304 install_requires.append('pexpect')
305 305
306 306 everything = set()
307 307 for deps in extras_require.values():
308 308 everything.update(deps)
309 309 extras_require['all'] = everything
310 310
311 311 if 'setuptools' in sys.modules:
312 312 # setup.py develop should check for submodules
313 313 from setuptools.command.develop import develop
314 314 setup_args['cmdclass']['develop'] = require_submodules(develop)
315 315 setup_args['cmdclass']['bdist_wheel'] = css_js_prerelease(get_bdist_wheel())
316 316
317 317 setuptools_extra_args['zip_safe'] = False
318 318 setuptools_extra_args['entry_points'] = {
319 319 'console_scripts': find_entry_points(),
320 320 'pygments.lexers': [
321 321 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
322 322 'ipython = IPython.lib.lexers:IPythonLexer',
323 323 'ipython3 = IPython.lib.lexers:IPython3Lexer',
324 324 ],
325 325 }
326 326 setup_args['extras_require'] = extras_require
327 327 requires = setup_args['install_requires'] = install_requires
328 328
329 329 # Script to be run by the windows binary installer after the default setup
330 330 # routine, to add shortcuts and similar windows-only things. Windows
331 331 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
332 332 # doesn't find them.
333 333 if 'bdist_wininst' in sys.argv:
334 334 if len(sys.argv) > 2 and \
335 335 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
336 336 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
337 337 sys.exit(1)
338 338 setup_args['data_files'].append(
339 339 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
340 340 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
341 341 setup_args['options'] = {"bdist_wininst":
342 342 {"install_script":
343 343 "ipython_win_post_install.py"}}
344 344
345 345 else:
346 346 # scripts has to be a non-empty list, or install_scripts isn't called
347 347 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
348 348
349 349 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
350 350
351 351 #---------------------------------------------------------------------------
352 352 # Do the actual setup now
353 353 #---------------------------------------------------------------------------
354 354
355 355 setup_args.update(setuptools_extra_args)
356 356
357 357 def main():
358 358 setup(**setup_args)
359 359
360 360 if __name__ == '__main__':
361 361 main()
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now