##// END OF EJS Templates
Don't require win_unicode_console on Python 3.6...
Thomas Kluyver -
Show More
@@ -1,494 +1,499 b''
1 1 """IPython terminal interface using prompt_toolkit"""
2 2 from __future__ import print_function
3 3
4 4 import os
5 5 import sys
6 6 import warnings
7 7 from warnings import warn
8 8
9 9 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 10 from IPython.utils import io
11 11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input, string_types
12 12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
13 13 from IPython.utils.process import abbrev_cwd
14 14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
15 15
16 16 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
17 17 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
18 18 from prompt_toolkit.history import InMemoryHistory
19 19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
20 20 from prompt_toolkit.interface import CommandLineInterface
21 21 from prompt_toolkit.key_binding.manager import KeyBindingManager
22 22 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
23 23 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
24 24
25 25 from pygments.styles import get_style_by_name, get_all_styles
26 26 from pygments.style import Style
27 27 from pygments.token import Token
28 28
29 29 from .debugger import TerminalPdb, Pdb
30 30 from .magics import TerminalMagics
31 31 from .pt_inputhooks import get_inputhook_func
32 32 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
33 33 from .ptutils import IPythonPTCompleter, IPythonPTLexer
34 34 from .shortcuts import register_ipython_shortcuts
35 35
36 36 DISPLAY_BANNER_DEPRECATED = object()
37 37
38 38
39 39 from pygments.style import Style
40 40
41 41 class _NoStyle(Style): pass
42 42
43 43
44 44
45 45 _style_overrides_light_bg = {
46 46 Token.Prompt: '#0000ff',
47 47 Token.PromptNum: '#0000ee bold',
48 48 Token.OutPrompt: '#cc0000',
49 49 Token.OutPromptNum: '#bb0000 bold',
50 50 }
51 51
52 52 _style_overrides_linux = {
53 53 Token.Prompt: '#00cc00',
54 54 Token.PromptNum: '#00bb00 bold',
55 55 Token.OutPrompt: '#cc0000',
56 56 Token.OutPromptNum: '#bb0000 bold',
57 57 }
58 58
59 59
60 60
61 61 def get_default_editor():
62 62 try:
63 63 ed = os.environ['EDITOR']
64 64 if not PY3:
65 65 ed = ed.decode()
66 66 return ed
67 67 except KeyError:
68 68 pass
69 69 except UnicodeError:
70 70 warn("$EDITOR environment variable is not pure ASCII. Using platform "
71 71 "default editor.")
72 72
73 73 if os.name == 'posix':
74 74 return 'vi' # the only one guaranteed to be there!
75 75 else:
76 76 return 'notepad' # same in Windows!
77 77
78 78 # conservatively check for tty
79 79 # overridden streams can result in things like:
80 80 # - sys.stdin = None
81 81 # - no isatty method
82 82 for _name in ('stdin', 'stdout', 'stderr'):
83 83 _stream = getattr(sys, _name)
84 84 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
85 85 _is_tty = False
86 86 break
87 87 else:
88 88 _is_tty = True
89 89
90 90
91 91 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
92 92
93 93 class TerminalInteractiveShell(InteractiveShell):
94 94 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
95 95 'to reserve for the completion menu'
96 96 ).tag(config=True)
97 97
98 98 def _space_for_menu_changed(self, old, new):
99 99 self._update_layout()
100 100
101 101 pt_cli = None
102 102 debugger_history = None
103 103 _pt_app = None
104 104
105 105 simple_prompt = Bool(_use_simple_prompt,
106 106 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
107 107
108 108 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
109 109 IPython own testing machinery, and emacs inferior-shell integration through elpy.
110 110
111 111 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
112 112 environment variable is set, or the current terminal is not a tty.
113 113
114 114 """
115 115 ).tag(config=True)
116 116
117 117 @property
118 118 def debugger_cls(self):
119 119 return Pdb if self.simple_prompt else TerminalPdb
120 120
121 121 confirm_exit = Bool(True,
122 122 help="""
123 123 Set to confirm when you try to exit IPython with an EOF (Control-D
124 124 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
125 125 you can force a direct exit without any confirmation.""",
126 126 ).tag(config=True)
127 127
128 128 editing_mode = Unicode('emacs',
129 129 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
130 130 ).tag(config=True)
131 131
132 132 mouse_support = Bool(False,
133 133 help="Enable mouse support in the prompt"
134 134 ).tag(config=True)
135 135
136 136 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
137 137 help="""The name or class of a Pygments style to use for syntax
138 138 highlighting: \n %s""" % ', '.join(get_all_styles())
139 139 ).tag(config=True)
140 140
141 141
142 142 @observe('highlighting_style')
143 143 @observe('colors')
144 144 def _highlighting_style_changed(self, change):
145 145 self.refresh_style()
146 146
147 147 def refresh_style(self):
148 148 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
149 149
150 150
151 151 highlighting_style_overrides = Dict(
152 152 help="Override highlighting format for specific tokens"
153 153 ).tag(config=True)
154 154
155 155 true_color = Bool(False,
156 156 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
157 157 "If your terminal supports true color, the following command "
158 158 "should print 'TRUECOLOR' in orange: "
159 159 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
160 160 ).tag(config=True)
161 161
162 162 editor = Unicode(get_default_editor(),
163 163 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
164 164 ).tag(config=True)
165 165
166 166 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
167 167
168 168 prompts = Instance(Prompts)
169 169
170 170 @default('prompts')
171 171 def _prompts_default(self):
172 172 return self.prompts_class(self)
173 173
174 174 @observe('prompts')
175 175 def _(self, change):
176 176 self._update_layout()
177 177
178 178 @default('displayhook_class')
179 179 def _displayhook_class_default(self):
180 180 return RichPromptDisplayHook
181 181
182 182 term_title = Bool(True,
183 183 help="Automatically set the terminal title"
184 184 ).tag(config=True)
185 185
186 186 display_completions = Enum(('column', 'multicolumn','readlinelike'),
187 187 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
188 188 "'readlinelike'. These options are for `prompt_toolkit`, see "
189 189 "`prompt_toolkit` documentation for more information."
190 190 ),
191 191 default_value='multicolumn').tag(config=True)
192 192
193 193 highlight_matching_brackets = Bool(True,
194 194 help="Highlight matching brackets .",
195 195 ).tag(config=True)
196 196
197 197 @observe('term_title')
198 198 def init_term_title(self, change=None):
199 199 # Enable or disable the terminal title.
200 200 if self.term_title:
201 201 toggle_set_term_title(True)
202 202 set_term_title('IPython: ' + abbrev_cwd())
203 203 else:
204 204 toggle_set_term_title(False)
205 205
206 206 def init_display_formatter(self):
207 207 super(TerminalInteractiveShell, self).init_display_formatter()
208 208 # terminal only supports plain text
209 209 self.display_formatter.active_types = ['text/plain']
210 210
211 211 def init_prompt_toolkit_cli(self):
212 212 if self.simple_prompt:
213 213 # Fall back to plain non-interactive output for tests.
214 214 # This is very limited, and only accepts a single line.
215 215 def prompt():
216 216 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
217 217 self.prompt_for_code = prompt
218 218 return
219 219
220 220 # Set up keyboard shortcuts
221 221 kbmanager = KeyBindingManager.for_prompt()
222 222 register_ipython_shortcuts(kbmanager.registry, self)
223 223
224 224 # Pre-populate history from IPython's history database
225 225 history = InMemoryHistory()
226 226 last_cell = u""
227 227 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
228 228 include_latest=True):
229 229 # Ignore blank lines and consecutive duplicates
230 230 cell = cell.rstrip()
231 231 if cell and (cell != last_cell):
232 232 history.append(cell)
233 233 last_cell = cell
234 234
235 235 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
236 236 style = DynamicStyle(lambda: self._style)
237 237
238 238 editing_mode = getattr(EditingMode, self.editing_mode.upper())
239 239
240 240 self._pt_app = create_prompt_application(
241 241 editing_mode=editing_mode,
242 242 key_bindings_registry=kbmanager.registry,
243 243 history=history,
244 244 completer=IPythonPTCompleter(shell=self),
245 245 enable_history_search=True,
246 246 style=style,
247 247 mouse_support=self.mouse_support,
248 248 **self._layout_options()
249 249 )
250 250 self._eventloop = create_eventloop(self.inputhook)
251 251 self.pt_cli = CommandLineInterface(
252 252 self._pt_app, eventloop=self._eventloop,
253 253 output=create_output(true_color=self.true_color))
254 254
255 255 def _make_style_from_name_or_cls(self, name_or_cls):
256 256 """
257 257 Small wrapper that make an IPython compatible style from a style name
258 258
259 259 We need that to add style for prompt ... etc.
260 260 """
261 261 style_overrides = {}
262 262 if name_or_cls == 'legacy':
263 263 legacy = self.colors.lower()
264 264 if legacy == 'linux':
265 265 style_cls = get_style_by_name('monokai')
266 266 style_overrides = _style_overrides_linux
267 267 elif legacy == 'lightbg':
268 268 style_overrides = _style_overrides_light_bg
269 269 style_cls = get_style_by_name('pastie')
270 270 elif legacy == 'neutral':
271 271 # The default theme needs to be visible on both a dark background
272 272 # and a light background, because we can't tell what the terminal
273 273 # looks like. These tweaks to the default theme help with that.
274 274 style_cls = get_style_by_name('default')
275 275 style_overrides.update({
276 276 Token.Number: '#007700',
277 277 Token.Operator: 'noinherit',
278 278 Token.String: '#BB6622',
279 279 Token.Name.Function: '#2080D0',
280 280 Token.Name.Class: 'bold #2080D0',
281 281 Token.Name.Namespace: 'bold #2080D0',
282 282 Token.Prompt: '#009900',
283 283 Token.PromptNum: '#00ff00 bold',
284 284 Token.OutPrompt: '#990000',
285 285 Token.OutPromptNum: '#ff0000 bold',
286 286 })
287 287 elif legacy =='nocolor':
288 288 style_cls=_NoStyle
289 289 style_overrides = {}
290 290 else :
291 291 raise ValueError('Got unknown colors: ', legacy)
292 292 else :
293 293 if isinstance(name_or_cls, string_types):
294 294 style_cls = get_style_by_name(name_or_cls)
295 295 else:
296 296 style_cls = name_or_cls
297 297 style_overrides = {
298 298 Token.Prompt: '#009900',
299 299 Token.PromptNum: '#00ff00 bold',
300 300 Token.OutPrompt: '#990000',
301 301 Token.OutPromptNum: '#ff0000 bold',
302 302 }
303 303 style_overrides.update(self.highlighting_style_overrides)
304 304 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
305 305 style_dict=style_overrides)
306 306
307 307 return style
308 308
309 309 def _layout_options(self):
310 310 """
311 311 Return the current layout option for the current Terminal InteractiveShell
312 312 """
313 313 return {
314 314 'lexer':IPythonPTLexer(),
315 315 'reserve_space_for_menu':self.space_for_menu,
316 316 'get_prompt_tokens':self.prompts.in_prompt_tokens,
317 317 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
318 318 'multiline':True,
319 319 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
320 320
321 321 # Highlight matching brackets, but only when this setting is
322 322 # enabled, and only when the DEFAULT_BUFFER has the focus.
323 323 'extra_input_processors': [ConditionalProcessor(
324 324 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
325 325 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
326 326 Condition(lambda cli: self.highlight_matching_brackets))],
327 327 }
328 328
329 329 def _update_layout(self):
330 330 """
331 331 Ask for a re computation of the application layout, if for example ,
332 332 some configuration options have changed.
333 333 """
334 334 if self._pt_app:
335 335 self._pt_app.layout = create_prompt_layout(**self._layout_options())
336 336
337 337 def prompt_for_code(self):
338 338 document = self.pt_cli.run(
339 339 pre_run=self.pre_prompt, reset_current_buffer=True)
340 340 return document.text
341 341
342 342 def enable_win_unicode_console(self):
343 if sys.version_info >= (3, 6):
344 # Since PEP 528, Python uses the unicode APIs for the Windows
345 # console by default, so WUC shouldn't be needed.
346 return
347
343 348 import win_unicode_console
344 349
345 350 if PY3:
346 351 win_unicode_console.enable()
347 352 else:
348 353 # https://github.com/ipython/ipython/issues/9768
349 354 from win_unicode_console.streams import (TextStreamWrapper,
350 355 stdout_text_transcoded, stderr_text_transcoded)
351 356
352 357 class LenientStrStreamWrapper(TextStreamWrapper):
353 358 def write(self, s):
354 359 if isinstance(s, bytes):
355 360 s = s.decode(self.encoding, 'replace')
356 361
357 362 self.base.write(s)
358 363
359 364 stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded)
360 365 stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded)
361 366
362 367 win_unicode_console.enable(stdout=stdout_text_str,
363 368 stderr=stderr_text_str)
364 369
365 370 def init_io(self):
366 371 if sys.platform not in {'win32', 'cli'}:
367 372 return
368 373
369 374 self.enable_win_unicode_console()
370 375
371 376 import colorama
372 377 colorama.init()
373 378
374 379 # For some reason we make these wrappers around stdout/stderr.
375 380 # For now, we need to reset them so all output gets coloured.
376 381 # https://github.com/ipython/ipython/issues/8669
377 382 # io.std* are deprecated, but don't show our own deprecation warnings
378 383 # during initialization of the deprecated API.
379 384 with warnings.catch_warnings():
380 385 warnings.simplefilter('ignore', DeprecationWarning)
381 386 io.stdout = io.IOStream(sys.stdout)
382 387 io.stderr = io.IOStream(sys.stderr)
383 388
384 389 def init_magics(self):
385 390 super(TerminalInteractiveShell, self).init_magics()
386 391 self.register_magics(TerminalMagics)
387 392
388 393 def init_alias(self):
389 394 # The parent class defines aliases that can be safely used with any
390 395 # frontend.
391 396 super(TerminalInteractiveShell, self).init_alias()
392 397
393 398 # Now define aliases that only make sense on the terminal, because they
394 399 # need direct access to the console in a way that we can't emulate in
395 400 # GUI or web frontend
396 401 if os.name == 'posix':
397 402 for cmd in ['clear', 'more', 'less', 'man']:
398 403 self.alias_manager.soft_define_alias(cmd, cmd)
399 404
400 405
401 406 def __init__(self, *args, **kwargs):
402 407 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
403 408 self.init_prompt_toolkit_cli()
404 409 self.init_term_title()
405 410 self.keep_running = True
406 411
407 412 self.debugger_history = InMemoryHistory()
408 413
409 414 def ask_exit(self):
410 415 self.keep_running = False
411 416
412 417 rl_next_input = None
413 418
414 419 def pre_prompt(self):
415 420 if self.rl_next_input:
416 421 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
417 422 self.rl_next_input = None
418 423
419 424 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
420 425
421 426 if display_banner is not DISPLAY_BANNER_DEPRECATED:
422 427 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
423 428
424 429 self.keep_running = True
425 430 while self.keep_running:
426 431 print(self.separate_in, end='')
427 432
428 433 try:
429 434 code = self.prompt_for_code()
430 435 except EOFError:
431 436 if (not self.confirm_exit) \
432 437 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
433 438 self.ask_exit()
434 439
435 440 else:
436 441 if code:
437 442 self.run_cell(code, store_history=True)
438 443
439 444 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
440 445 # An extra layer of protection in case someone mashing Ctrl-C breaks
441 446 # out of our internal code.
442 447 if display_banner is not DISPLAY_BANNER_DEPRECATED:
443 448 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
444 449 while True:
445 450 try:
446 451 self.interact()
447 452 break
448 453 except KeyboardInterrupt:
449 454 print("\nKeyboardInterrupt escaped interact()\n")
450 455
451 456 _inputhook = None
452 457 def inputhook(self, context):
453 458 if self._inputhook is not None:
454 459 self._inputhook(context)
455 460
456 461 def enable_gui(self, gui=None):
457 462 if gui:
458 463 self._inputhook = get_inputhook_func(gui)
459 464 else:
460 465 self._inputhook = None
461 466
462 467 # Run !system commands directly, not through pipes, so terminal programs
463 468 # work correctly.
464 469 system = InteractiveShell.system_raw
465 470
466 471 def auto_rewrite_input(self, cmd):
467 472 """Overridden from the parent class to use fancy rewriting prompt"""
468 473 if not self.show_rewritten_input:
469 474 return
470 475
471 476 tokens = self.prompts.rewrite_prompt_tokens()
472 477 if self.pt_cli:
473 478 self.pt_cli.print_tokens(tokens)
474 479 print(cmd)
475 480 else:
476 481 prompt = ''.join(s for t, s in tokens)
477 482 print(prompt, cmd, sep='')
478 483
479 484 _prompts_before = None
480 485 def switch_doctest_mode(self, mode):
481 486 """Switch prompts to classic for %doctest_mode"""
482 487 if mode:
483 488 self._prompts_before = self.prompts
484 489 self.prompts = ClassicPrompts(self)
485 490 elif self._prompts_before:
486 491 self.prompts = self._prompts_before
487 492 self._prompts_before = None
488 493 self._update_layout()
489 494
490 495
491 496 InteractiveShellABC.register(TerminalInteractiveShell)
492 497
493 498 if __name__ == '__main__':
494 499 TerminalInteractiveShell.instance().interact()
@@ -1,298 +1,299 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 if sys.version_info < (3,3):
30 30 error = """
31 31 IPython 6.0+ does not support Python 2.6, 2.7, 3.0, 3.1, or 3.2.
32 32 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
33 33 Beginning with IPython 6.0, Python 3.3 and above is required.
34 34
35 35 See IPython `README.rst` file for more information:
36 36
37 37 https://github.com/ipython/ipython/blob/master/README.rst
38 38
39 39 """
40 40
41 41 print(error, file=sys.stderr)
42 42 sys.exit(1)
43 43
44 44 PY3 = (sys.version_info[0] >= 3)
45 45
46 46 # At least we're on the python version we need, move on.
47 47
48 48 #-------------------------------------------------------------------------------
49 49 # Imports
50 50 #-------------------------------------------------------------------------------
51 51
52 52 # Stdlib imports
53 53 import os
54 54
55 55 from glob import glob
56 56
57 57 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
58 58 # update it when the contents of directories change.
59 59 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
60 60
61 61 from distutils.core import setup
62 62
63 63 # Our own imports
64 64 from setupbase import target_update
65 65
66 66 from setupbase import (
67 67 setup_args,
68 68 find_packages,
69 69 find_package_data,
70 70 check_package_data_first,
71 71 find_entry_points,
72 72 build_scripts_entrypt,
73 73 find_data_files,
74 74 git_prebuild,
75 75 install_symlinked,
76 76 install_lib_symlink,
77 77 install_scripts_for_symlink,
78 78 unsymlink,
79 79 )
80 80
81 81 isfile = os.path.isfile
82 82 pjoin = os.path.join
83 83
84 84 #-------------------------------------------------------------------------------
85 85 # Handle OS specific things
86 86 #-------------------------------------------------------------------------------
87 87
88 88 if os.name in ('nt','dos'):
89 89 os_name = 'windows'
90 90 else:
91 91 os_name = os.name
92 92
93 93 # Under Windows, 'sdist' has not been supported. Now that the docs build with
94 94 # Sphinx it might work, but let's not turn it on until someone confirms that it
95 95 # actually works.
96 96 if os_name == 'windows' and 'sdist' in sys.argv:
97 97 print('The sdist command is not available under Windows. Exiting.')
98 98 sys.exit(1)
99 99
100 100
101 101 #-------------------------------------------------------------------------------
102 102 # Things related to the IPython documentation
103 103 #-------------------------------------------------------------------------------
104 104
105 105 # update the manuals when building a source dist
106 106 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
107 107
108 108 # List of things to be updated. Each entry is a triplet of args for
109 109 # target_update()
110 110 to_update = [
111 111 ('docs/man/ipython.1.gz',
112 112 ['docs/man/ipython.1'],
113 113 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
114 114 ]
115 115
116 116
117 117 [ target_update(*t) for t in to_update ]
118 118
119 119 #---------------------------------------------------------------------------
120 120 # Find all the packages, package data, and data_files
121 121 #---------------------------------------------------------------------------
122 122
123 123 packages = find_packages()
124 124 package_data = find_package_data()
125 125
126 126 data_files = find_data_files()
127 127
128 128 setup_args['packages'] = packages
129 129 setup_args['package_data'] = package_data
130 130 setup_args['data_files'] = data_files
131 131
132 132 #---------------------------------------------------------------------------
133 133 # custom distutils commands
134 134 #---------------------------------------------------------------------------
135 135 # imports here, so they are after setuptools import if there was one
136 136 from distutils.command.sdist import sdist
137 137 from distutils.command.upload import upload
138 138
139 139 class UploadWindowsInstallers(upload):
140 140
141 141 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
142 142 user_options = upload.user_options + [
143 143 ('files=', 'f', 'exe file (or glob) to upload')
144 144 ]
145 145 def initialize_options(self):
146 146 upload.initialize_options(self)
147 147 meta = self.distribution.metadata
148 148 base = '{name}-{version}'.format(
149 149 name=meta.get_name(),
150 150 version=meta.get_version()
151 151 )
152 152 self.files = os.path.join('dist', '%s.*.exe' % base)
153 153
154 154 def run(self):
155 155 for dist_file in glob(self.files):
156 156 self.upload_file('bdist_wininst', 'any', dist_file)
157 157
158 158 setup_args['cmdclass'] = {
159 159 'build_py': \
160 160 check_package_data_first(git_prebuild('IPython')),
161 161 'sdist' : git_prebuild('IPython', sdist),
162 162 'upload_wininst' : UploadWindowsInstallers,
163 163 'symlink': install_symlinked,
164 164 'install_lib_symlink': install_lib_symlink,
165 165 'install_scripts_sym': install_scripts_for_symlink,
166 166 'unsymlink': unsymlink,
167 167 }
168 168
169 169
170 170 #---------------------------------------------------------------------------
171 171 # Handle scripts, dependencies, and setuptools specific things
172 172 #---------------------------------------------------------------------------
173 173
174 174 # For some commands, use setuptools. Note that we do NOT list install here!
175 175 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
176 176 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
177 177 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
178 178 'egg_info', 'easy_install', 'upload', 'install_egg_info',
179 179 ))
180 180
181 181 if len(needs_setuptools.intersection(sys.argv)) > 0:
182 182 import setuptools
183 183
184 184 # This dict is used for passing extra arguments that are setuptools
185 185 # specific to setup
186 186 setuptools_extra_args = {}
187 187
188 188 # setuptools requirements
189 189
190 190 extras_require = dict(
191 191 parallel = ['ipyparallel'],
192 192 qtconsole = ['qtconsole'],
193 193 doc = ['Sphinx>=1.3'],
194 194 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy'],
195 195 terminal = [],
196 196 kernel = ['ipykernel'],
197 197 nbformat = ['nbformat'],
198 198 notebook = ['notebook', 'ipywidgets'],
199 199 nbconvert = ['nbconvert'],
200 200 )
201 201
202 202 install_requires = [
203 203 'setuptools>=18.5',
204 204 'decorator',
205 205 'pickleshare',
206 206 'simplegeneric>0.8',
207 207 'traitlets>=4.2',
208 208 'prompt_toolkit>=1.0.3,<2.0.0',
209 209 'pygments',
210 210 ]
211 211
212 212 # Platform-specific dependencies:
213 213 # This is the correct way to specify these,
214 214 # but requires pip >= 6. pip < 6 ignores these.
215 215
216 216 extras_require.update({
217 217 ':python_version == "2.7"': ['backports.shutil_get_terminal_size'],
218 218 ':python_version == "2.7" or python_version == "3.3"': ['pathlib2'],
219 219 ':sys_platform != "win32"': ['pexpect'],
220 220 ':sys_platform == "darwin"': ['appnope'],
221 ':sys_platform == "win32"': ['colorama', 'win_unicode_console>=0.5'],
221 ':sys_platform == "win32"': ['colorama'],
222 ':sys_platform == "win32" and python_version < "3.6"': ['win_unicode_console>=0.5'],
222 223 'test:python_version == "2.7"': ['mock'],
223 224 })
224 225 # FIXME: re-specify above platform dependencies for pip < 6
225 226 # These would result in non-portable bdists.
226 227 if not any(arg.startswith('bdist') for arg in sys.argv):
227 228 if sys.version_info < (3, 3):
228 229 extras_require['test'].append('mock')
229 230
230 231 if sys.platform == 'darwin':
231 232 install_requires.extend(['appnope'])
232 233
233 234 if not sys.platform.startswith('win'):
234 235 install_requires.append('pexpect')
235 236
236 237 # workaround pypa/setuptools#147, where setuptools misspells
237 238 # platform_python_implementation as python_implementation
238 239 if 'setuptools' in sys.modules:
239 240 for key in list(extras_require):
240 241 if 'platform_python_implementation' in key:
241 242 new_key = key.replace('platform_python_implementation', 'python_implementation')
242 243 extras_require[new_key] = extras_require.pop(key)
243 244
244 245 everything = set()
245 246 for key, deps in extras_require.items():
246 247 if ':' not in key:
247 248 everything.update(deps)
248 249 extras_require['all'] = everything
249 250
250 251 if 'setuptools' in sys.modules:
251 252 setuptools_extra_args['python_requires'] = '>=3.3'
252 253 setuptools_extra_args['zip_safe'] = False
253 254 setuptools_extra_args['entry_points'] = {
254 255 'console_scripts': find_entry_points(),
255 256 'pygments.lexers': [
256 257 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
257 258 'ipython = IPython.lib.lexers:IPythonLexer',
258 259 'ipython3 = IPython.lib.lexers:IPython3Lexer',
259 260 ],
260 261 }
261 262 setup_args['extras_require'] = extras_require
262 263 requires = setup_args['install_requires'] = install_requires
263 264
264 265 # Script to be run by the windows binary installer after the default setup
265 266 # routine, to add shortcuts and similar windows-only things. Windows
266 267 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
267 268 # doesn't find them.
268 269 if 'bdist_wininst' in sys.argv:
269 270 if len(sys.argv) > 2 and \
270 271 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
271 272 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
272 273 sys.exit(1)
273 274 setup_args['data_files'].append(
274 275 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
275 276 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
276 277 setup_args['options'] = {"bdist_wininst":
277 278 {"install_script":
278 279 "ipython_win_post_install.py"}}
279 280
280 281 else:
281 282 # scripts has to be a non-empty list, or install_scripts isn't called
282 283 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
283 284
284 285 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
285 286
286 287 #---------------------------------------------------------------------------
287 288 # Do the actual setup now
288 289 #---------------------------------------------------------------------------
289 290
290 291 setup_args.update(setuptools_extra_args)
291 292
292 293
293 294
294 295 def main():
295 296 setup(**setup_args)
296 297
297 298 if __name__ == '__main__':
298 299 main()
General Comments 0
You need to be logged in to leave comments. Login now