##// END OF EJS Templates
Merge pull request #9118 from takluyver/ptshell...
Matthias Bussonnier -
r22108:7d6dfc3c merge
parent child Browse files
Show More
@@ -0,0 +1,16 b''
1 import importlib
2 import os
3
4 aliases = {
5 'qt4': 'qt',
6 }
7
8 def get_inputhook_func(gui):
9 if gui in aliases:
10 return get_inputhook_func(aliases[gui])
11
12 if gui == 'qt5':
13 os.environ['QT_API'] = 'pyqt5'
14
15 mod = importlib.import_module('IPython.terminal.pt_inputhooks.'+gui)
16 return mod.inputhook
@@ -0,0 +1,141 b''
1 """GLUT Input hook for interactive use with prompt_toolkit
2 """
3 from __future__ import print_function
4
5
6 # GLUT is quite an old library and it is difficult to ensure proper
7 # integration within IPython since original GLUT does not allow to handle
8 # events one by one. Instead, it requires for the mainloop to be entered
9 # and never returned (there is not even a function to exit he
10 # mainloop). Fortunately, there are alternatives such as freeglut
11 # (available for linux and windows) and the OSX implementation gives
12 # access to a glutCheckLoop() function that blocks itself until a new
13 # event is received. This means we have to setup the idle callback to
14 # ensure we got at least one event that will unblock the function.
15 #
16 # Furthermore, it is not possible to install these handlers without a window
17 # being first created. We choose to make this window invisible. This means that
18 # display mode options are set at this level and user won't be able to change
19 # them later without modifying the code. This should probably be made available
20 # via IPython options system.
21
22 import sys
23 import time
24 import signal
25 import OpenGL.GLUT as glut
26 import OpenGL.platform as platform
27 from timeit import default_timer as clock
28
29 # Frame per second : 60
30 # Should probably be an IPython option
31 glut_fps = 60
32
33 # Display mode : double buffeed + rgba + depth
34 # Should probably be an IPython option
35 glut_display_mode = (glut.GLUT_DOUBLE |
36 glut.GLUT_RGBA |
37 glut.GLUT_DEPTH)
38
39 glutMainLoopEvent = None
40 if sys.platform == 'darwin':
41 try:
42 glutCheckLoop = platform.createBaseFunction(
43 'glutCheckLoop', dll=platform.GLUT, resultType=None,
44 argTypes=[],
45 doc='glutCheckLoop( ) -> None',
46 argNames=(),
47 )
48 except AttributeError:
49 raise RuntimeError(
50 '''Your glut implementation does not allow interactive sessions'''
51 '''Consider installing freeglut.''')
52 glutMainLoopEvent = glutCheckLoop
53 elif glut.HAVE_FREEGLUT:
54 glutMainLoopEvent = glut.glutMainLoopEvent
55 else:
56 raise RuntimeError(
57 '''Your glut implementation does not allow interactive sessions. '''
58 '''Consider installing freeglut.''')
59
60
61 def glut_display():
62 # Dummy display function
63 pass
64
65 def glut_idle():
66 # Dummy idle function
67 pass
68
69 def glut_close():
70 # Close function only hides the current window
71 glut.glutHideWindow()
72 glutMainLoopEvent()
73
74 def glut_int_handler(signum, frame):
75 # Catch sigint and print the defaultipyt message
76 signal.signal(signal.SIGINT, signal.default_int_handler)
77 print('\nKeyboardInterrupt')
78 # Need to reprint the prompt at this stage
79
80 # Initialisation code
81 glut.glutInit( sys.argv )
82 glut.glutInitDisplayMode( glut_display_mode )
83 # This is specific to freeglut
84 if bool(glut.glutSetOption):
85 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
86 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
87 glut.glutCreateWindow( b'ipython' )
88 glut.glutReshapeWindow( 1, 1 )
89 glut.glutHideWindow( )
90 glut.glutWMCloseFunc( glut_close )
91 glut.glutDisplayFunc( glut_display )
92 glut.glutIdleFunc( glut_idle )
93
94
95 def inputhook(context):
96 """Run the pyglet event loop by processing pending events only.
97
98 This keeps processing pending events until stdin is ready. After
99 processing all pending events, a call to time.sleep is inserted. This is
100 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
101 though for best performance.
102 """
103 # We need to protect against a user pressing Control-C when IPython is
104 # idle and this is running. We trap KeyboardInterrupt and pass.
105
106 signal.signal(signal.SIGINT, glut_int_handler)
107
108 try:
109 t = clock()
110
111 # Make sure the default window is set after a window has been closed
112 if glut.glutGetWindow() == 0:
113 glut.glutSetWindow( 1 )
114 glutMainLoopEvent()
115 return 0
116
117 while not context.input_is_ready():
118 glutMainLoopEvent()
119 # We need to sleep at this point to keep the idle CPU load
120 # low. However, if sleep to long, GUI response is poor. As
121 # a compromise, we watch how often GUI events are being processed
122 # and switch between a short and long sleep time. Here are some
123 # stats useful in helping to tune this.
124 # time CPU load
125 # 0.001 13%
126 # 0.005 3%
127 # 0.01 1.5%
128 # 0.05 0.5%
129 used_time = clock() - t
130 if used_time > 10.0:
131 # print 'Sleep for 1 s' # dbg
132 time.sleep(1.0)
133 elif used_time > 0.1:
134 # Few GUI events coming in, so we can sleep longer
135 # print 'Sleep for 0.05 s' # dbg
136 time.sleep(0.05)
137 else:
138 # Many GUI events coming in, so sleep only very little
139 time.sleep(0.001)
140 except KeyboardInterrupt:
141 pass
@@ -0,0 +1,59 b''
1 # Code borrowed from python-prompt-toolkit examples
2 # https://github.com/jonathanslenders/python-prompt-toolkit/blob/77cdcfbc7f4b4c34a9d2f9a34d422d7152f16209/examples/inputhook.py
3
4 # Copyright (c) 2014, Jonathan Slenders
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without modification,
8 # are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice, this
14 # list of conditions and the following disclaimer in the documentation and/or
15 # other materials provided with the distribution.
16 #
17 # * Neither the name of the {organization} nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 """
33 PyGTK input hook for prompt_toolkit.
34
35 Listens on the pipe prompt_toolkit sets up for a notification that it should
36 return control to the terminal event loop.
37 """
38 from __future__ import absolute_import
39
40 import gtk, gobject
41
42 # Enable threading in GTK. (Otherwise, GTK will keep the GIL.)
43 gtk.gdk.threads_init()
44
45 def inputhook(context):
46 """
47 When the eventloop of prompt-toolkit is idle, call this inputhook.
48
49 This will run the GTK main loop until the file descriptor
50 `context.fileno()` becomes ready.
51
52 :param context: An `InputHookContext` instance.
53 """
54 def _main_quit(*a, **kw):
55 gtk.main_quit()
56 return False
57
58 gobject.io_add_watch(context.fileno(), gobject.IO_IN, _main_quit)
59 gtk.main()
@@ -0,0 +1,12 b''
1 """prompt_toolkit input hook for GTK 3
2 """
3
4 from gi.repository import Gtk, GLib
5
6 def _main_quit(*args, **kwargs):
7 Gtk.main_quit()
8 return False
9
10 def inputhook(context):
11 GLib.io_add_watch(context.fileno(), GLib.IO_IN, _main_quit)
12 Gtk.main()
@@ -0,0 +1,68 b''
1 """Enable pyglet to be used interacively with prompt_toolkit
2 """
3 from __future__ import absolute_import
4
5 import os
6 import sys
7 import time
8 from timeit import default_timer as clock
9 import pyglet
10
11 # On linux only, window.flip() has a bug that causes an AttributeError on
12 # window close. For details, see:
13 # http://groups.google.com/group/pyglet-users/browse_thread/thread/47c1aab9aa4a3d23/c22f9e819826799e?#c22f9e819826799e
14
15 if sys.platform.startswith('linux'):
16 def flip(window):
17 try:
18 window.flip()
19 except AttributeError:
20 pass
21 else:
22 def flip(window):
23 window.flip()
24
25
26 def inputhook(context):
27 """Run the pyglet event loop by processing pending events only.
28
29 This keeps processing pending events until stdin is ready. After
30 processing all pending events, a call to time.sleep is inserted. This is
31 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
32 though for best performance.
33 """
34 # We need to protect against a user pressing Control-C when IPython is
35 # idle and this is running. We trap KeyboardInterrupt and pass.
36 try:
37 t = clock()
38 while not context.input_is_ready():
39 pyglet.clock.tick()
40 for window in pyglet.app.windows:
41 window.switch_to()
42 window.dispatch_events()
43 window.dispatch_event('on_draw')
44 flip(window)
45
46 # We need to sleep at this point to keep the idle CPU load
47 # low. However, if sleep to long, GUI response is poor. As
48 # a compromise, we watch how often GUI events are being processed
49 # and switch between a short and long sleep time. Here are some
50 # stats useful in helping to tune this.
51 # time CPU load
52 # 0.001 13%
53 # 0.005 3%
54 # 0.01 1.5%
55 # 0.05 0.5%
56 used_time = clock() - t
57 if used_time > 10.0:
58 # print 'Sleep for 1 s' # dbg
59 time.sleep(1.0)
60 elif used_time > 0.1:
61 # Few GUI events coming in, so we can sleep longer
62 # print 'Sleep for 0.05 s' # dbg
63 time.sleep(0.05)
64 else:
65 # Many GUI events coming in, so sleep only very little
66 time.sleep(0.001)
67 except KeyboardInterrupt:
68 pass
@@ -0,0 +1,11 b''
1 from IPython.external.qt_for_kernel import QtCore, QtGui
2
3 def inputhook(context):
4 app = QtCore.QCoreApplication.instance()
5 if not app:
6 return
7 event_loop = QtCore.QEventLoop(app)
8 notifier = QtCore.QSocketNotifier(context.fileno(), QtCore.QSocketNotifier.Read)
9 notifier.setEnabled(True)
10 notifier.activated.connect(event_loop.exit)
11 event_loop.exec_()
@@ -0,0 +1,93 b''
1 # Code borrowed from ptpython
2 # https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py
3
4 # Copyright (c) 2015, Jonathan Slenders
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without modification,
8 # are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice, this
14 # list of conditions and the following disclaimer in the documentation and/or
15 # other materials provided with the distribution.
16 #
17 # * Neither the name of the {organization} nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 """
33 Wrapper around the eventloop that gives some time to the Tkinter GUI to process
34 events when it's loaded and while we are waiting for input at the REPL. This
35 way we don't block the UI of for instance ``turtle`` and other Tk libraries.
36
37 (Normally Tkinter registeres it's callbacks in ``PyOS_InputHook`` to integrate
38 in readline. ``prompt-toolkit`` doesn't understand that input hook, but this
39 will fix it for Tk.)
40 """
41 import time
42
43 import _tkinter
44 try:
45 import tkinter
46 except ImportError:
47 import Tkinter as tkinter # Python 2
48
49 def inputhook(inputhook_context):
50 """
51 Inputhook for Tk.
52 Run the Tk eventloop until prompt-toolkit needs to process the next input.
53 """
54 # Get the current TK application.
55 root = tkinter._default_root
56
57 def wait_using_filehandler():
58 """
59 Run the TK eventloop until the file handler that we got from the
60 inputhook becomes readable.
61 """
62 # Add a handler that sets the stop flag when `prompt-toolkit` has input
63 # to process.
64 stop = [False]
65 def done(*a):
66 stop[0] = True
67
68 root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done)
69
70 # Run the TK event loop as long as we don't receive input.
71 while root.dooneevent(_tkinter.ALL_EVENTS):
72 if stop[0]:
73 break
74
75 root.deletefilehandler(inputhook_context.fileno())
76
77 def wait_using_polling():
78 """
79 Windows TK doesn't support 'createfilehandler'.
80 So, run the TK eventloop and poll until input is ready.
81 """
82 while not inputhook_context.input_is_ready():
83 while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT):
84 pass
85 # Sleep to make the CPU idle, but not too long, so that the UI
86 # stays responsive.
87 time.sleep(.01)
88
89 if root is not None:
90 if hasattr(root, 'createfilehandler'):
91 wait_using_filehandler()
92 else:
93 wait_using_polling()
@@ -0,0 +1,148 b''
1 """Enable wxPython to be used interacively in prompt_toolkit
2 """
3 from __future__ import absolute_import
4
5 import sys
6 import signal
7 import time
8 from timeit import default_timer as clock
9 import wx
10
11
12 def inputhook_wx1(context):
13 """Run the wx event loop by processing pending events only.
14
15 This approach seems to work, but its performance is not great as it
16 relies on having PyOS_InputHook called regularly.
17 """
18 try:
19 app = wx.GetApp()
20 if app is not None:
21 assert wx.Thread_IsMain()
22
23 # Make a temporary event loop and process system events until
24 # there are no more waiting, then allow idle events (which
25 # will also deal with pending or posted wx events.)
26 evtloop = wx.EventLoop()
27 ea = wx.EventLoopActivator(evtloop)
28 while evtloop.Pending():
29 evtloop.Dispatch()
30 app.ProcessIdle()
31 del ea
32 except KeyboardInterrupt:
33 pass
34 return 0
35
36 class EventLoopTimer(wx.Timer):
37
38 def __init__(self, func):
39 self.func = func
40 wx.Timer.__init__(self)
41
42 def Notify(self):
43 self.func()
44
45 class EventLoopRunner(object):
46
47 def Run(self, time, input_is_ready):
48 self.input_is_ready = input_is_ready
49 self.evtloop = wx.EventLoop()
50 self.timer = EventLoopTimer(self.check_stdin)
51 self.timer.Start(time)
52 self.evtloop.Run()
53
54 def check_stdin(self):
55 if self.input_is_ready():
56 self.timer.Stop()
57 self.evtloop.Exit()
58
59 def inputhook_wx2(context):
60 """Run the wx event loop, polling for stdin.
61
62 This version runs the wx eventloop for an undetermined amount of time,
63 during which it periodically checks to see if anything is ready on
64 stdin. If anything is ready on stdin, the event loop exits.
65
66 The argument to elr.Run controls how often the event loop looks at stdin.
67 This determines the responsiveness at the keyboard. A setting of 1000
68 enables a user to type at most 1 char per second. I have found that a
69 setting of 10 gives good keyboard response. We can shorten it further,
70 but eventually performance would suffer from calling select/kbhit too
71 often.
72 """
73 try:
74 app = wx.GetApp()
75 if app is not None:
76 assert wx.Thread_IsMain()
77 elr = EventLoopRunner()
78 # As this time is made shorter, keyboard response improves, but idle
79 # CPU load goes up. 10 ms seems like a good compromise.
80 elr.Run(time=10, # CHANGE time here to control polling interval
81 input_is_ready=context.input_is_ready)
82 except KeyboardInterrupt:
83 pass
84 return 0
85
86 def inputhook_wx3(context):
87 """Run the wx event loop by processing pending events only.
88
89 This is like inputhook_wx1, but it keeps processing pending events
90 until stdin is ready. After processing all pending events, a call to
91 time.sleep is inserted. This is needed, otherwise, CPU usage is at 100%.
92 This sleep time should be tuned though for best performance.
93 """
94 # We need to protect against a user pressing Control-C when IPython is
95 # idle and this is running. We trap KeyboardInterrupt and pass.
96 try:
97 app = wx.GetApp()
98 if app is not None:
99 assert wx.Thread_IsMain()
100
101 # The import of wx on Linux sets the handler for signal.SIGINT
102 # to 0. This is a bug in wx or gtk. We fix by just setting it
103 # back to the Python default.
104 if not callable(signal.getsignal(signal.SIGINT)):
105 signal.signal(signal.SIGINT, signal.default_int_handler)
106
107 evtloop = wx.EventLoop()
108 ea = wx.EventLoopActivator(evtloop)
109 t = clock()
110 while not context.input_is_ready():
111 while evtloop.Pending():
112 t = clock()
113 evtloop.Dispatch()
114 app.ProcessIdle()
115 # We need to sleep at this point to keep the idle CPU load
116 # low. However, if sleep to long, GUI response is poor. As
117 # a compromise, we watch how often GUI events are being processed
118 # and switch between a short and long sleep time. Here are some
119 # stats useful in helping to tune this.
120 # time CPU load
121 # 0.001 13%
122 # 0.005 3%
123 # 0.01 1.5%
124 # 0.05 0.5%
125 used_time = clock() - t
126 if used_time > 10.0:
127 # print 'Sleep for 1 s' # dbg
128 time.sleep(1.0)
129 elif used_time > 0.1:
130 # Few GUI events coming in, so we can sleep longer
131 # print 'Sleep for 0.05 s' # dbg
132 time.sleep(0.05)
133 else:
134 # Many GUI events coming in, so sleep only very little
135 time.sleep(0.001)
136 del ea
137 except KeyboardInterrupt:
138 pass
139 return 0
140
141 if sys.platform == 'darwin':
142 # On OSX, evtloop.Pending() always returns True, regardless of there being
143 # any events pending. As such we can't use implementations 1 or 3 of the
144 # inputhook as those depend on a pending/dispatch loop.
145 inputhook = inputhook_wx2
146 else:
147 # This is our default implementation
148 inputhook = inputhook_wx3
@@ -0,0 +1,240 b''
1 """IPython terminal interface using prompt_toolkit in place of readline"""
2 from __future__ import print_function
3
4 import sys
5
6 from IPython.core.interactiveshell import InteractiveShell
7 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
8 from traitlets import Bool, Unicode, Dict
9
10 from prompt_toolkit.completion import Completer, Completion
11 from prompt_toolkit.enums import DEFAULT_BUFFER
12 from prompt_toolkit.filters import HasFocus, HasSelection
13 from prompt_toolkit.history import InMemoryHistory
14 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop
15 from prompt_toolkit.interface import CommandLineInterface
16 from prompt_toolkit.key_binding.manager import KeyBindingManager
17 from prompt_toolkit.key_binding.vi_state import InputMode
18 from prompt_toolkit.key_binding.bindings.vi import ViStateFilter
19 from prompt_toolkit.keys import Keys
20 from prompt_toolkit.layout.lexers import PygmentsLexer
21 from prompt_toolkit.styles import PygmentsStyle
22
23 from pygments.styles import get_style_by_name
24 from pygments.lexers import Python3Lexer, PythonLexer
25 from pygments.token import Token
26
27 from .pt_inputhooks import get_inputhook_func
28 from .interactiveshell import get_default_editor
29
30
31 class IPythonPTCompleter(Completer):
32 """Adaptor to provide IPython completions to prompt_toolkit"""
33 def __init__(self, ipy_completer):
34 self.ipy_completer = ipy_completer
35
36 def get_completions(self, document, complete_event):
37 if not document.current_line.strip():
38 return
39
40 used, matches = self.ipy_completer.complete(
41 line_buffer=document.current_line,
42 cursor_pos=document.cursor_position_col
43 )
44 start_pos = -len(used)
45 for m in matches:
46 yield Completion(m, start_position=start_pos)
47
48 class PTInteractiveShell(InteractiveShell):
49 colors_force = True
50
51 pt_cli = None
52
53 vi_mode = Bool(False, config=True,
54 help="Use vi style keybindings at the prompt",
55 )
56
57 mouse_support = Bool(False, config=True,
58 help="Enable mouse support in the prompt"
59 )
60
61 highlighting_style = Unicode('', config=True,
62 help="The name of a Pygments style to use for syntax highlighting"
63 )
64
65 highlighting_style_overrides = Dict(config=True,
66 help="Override highlighting format for specific tokens"
67 )
68
69 editor = Unicode(get_default_editor(), config=True,
70 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
71 )
72
73 def get_prompt_tokens(self, cli):
74 return [
75 (Token.Prompt, 'In ['),
76 (Token.PromptNum, str(self.execution_count)),
77 (Token.Prompt, ']: '),
78 ]
79
80 def get_continuation_tokens(self, cli, width):
81 return [
82 (Token.Prompt, (' ' * (width - 2)) + ': '),
83 ]
84
85 def init_prompt_toolkit_cli(self):
86 if not sys.stdin.isatty():
87 # Piped input - e.g. for tests. Fall back to plain non-interactive
88 # output. This is very limited, and only accepts a single line.
89 def prompt():
90 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
91 self.prompt_for_code = prompt
92 return
93
94 kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode)
95 insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT)
96 # Ctrl+J == Enter, seemingly
97 @kbmanager.registry.add_binding(Keys.ControlJ,
98 filter=(HasFocus(DEFAULT_BUFFER)
99 & ~HasSelection()
100 & insert_mode
101 ))
102 def _(event):
103 b = event.current_buffer
104 d = b.document
105 if not (d.on_last_line or d.cursor_position_row >= d.line_count
106 - d.empty_line_count_at_the_end()):
107 b.newline()
108 return
109
110 status, indent = self.input_splitter.check_complete(d.text)
111
112 if (status != 'incomplete') and b.accept_action.is_returnable:
113 b.accept_action.validate_and_handle(event.cli, b)
114 else:
115 b.insert_text('\n' + (' ' * (indent or 0)))
116
117 @kbmanager.registry.add_binding(Keys.ControlC)
118 def _(event):
119 event.current_buffer.reset()
120
121 # Pre-populate history from IPython's history database
122 history = InMemoryHistory()
123 last_cell = u""
124 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
125 include_latest=True):
126 # Ignore blank lines and consecutive duplicates
127 cell = cell.rstrip()
128 if cell and (cell != last_cell):
129 history.append(cell)
130
131 style_overrides = {
132 Token.Prompt: '#009900',
133 Token.PromptNum: '#00ff00 bold',
134 }
135 if self.highlighting_style:
136 style_cls = get_style_by_name(self.highlighting_style)
137 else:
138 style_cls = get_style_by_name('default')
139 # The default theme needs to be visible on both a dark background
140 # and a light background, because we can't tell what the terminal
141 # looks like. These tweaks to the default theme help with that.
142 style_overrides.update({
143 Token.Number: '#007700',
144 Token.Operator: 'noinherit',
145 Token.String: '#BB6622',
146 Token.Name.Function: '#2080D0',
147 Token.Name.Class: 'bold #2080D0',
148 Token.Name.Namespace: 'bold #2080D0',
149 })
150 style_overrides.update(self.highlighting_style_overrides)
151 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
152 style_dict=style_overrides)
153
154 app = create_prompt_application(multiline=True,
155 lexer=PygmentsLexer(Python3Lexer if PY3 else PythonLexer),
156 get_prompt_tokens=self.get_prompt_tokens,
157 # The line below is waiting for a new release of
158 # prompt_toolkit (> 0.57)
159 #get_continuation_tokens=self.get_continuation_tokens,
160 key_bindings_registry=kbmanager.registry,
161 history=history,
162 completer=IPythonPTCompleter(self.Completer),
163 enable_history_search=True,
164 style=style,
165 mouse_support=self.mouse_support,
166 )
167
168 self.pt_cli = CommandLineInterface(app,
169 eventloop=create_eventloop(self.inputhook))
170
171 def prompt_for_code(self):
172 document = self.pt_cli.run(pre_run=self.pre_prompt)
173 return document.text
174
175 def init_io(self):
176 if sys.platform not in {'win32', 'cli'}:
177 return
178
179 import colorama
180 colorama.init()
181
182 # For some reason we make these wrappers around stdout/stderr.
183 # For now, we need to reset them so all output gets coloured.
184 # https://github.com/ipython/ipython/issues/8669
185 from IPython.utils import io
186 io.stdout = io.IOStream(sys.stdout)
187 io.stderr = io.IOStream(sys.stderr)
188
189 def __init__(self, *args, **kwargs):
190 super(PTInteractiveShell, self).__init__(*args, **kwargs)
191 self.init_prompt_toolkit_cli()
192 self.keep_running = True
193
194 def ask_exit(self):
195 self.keep_running = False
196
197 rl_next_input = None
198
199 def pre_prompt(self):
200 if self.rl_next_input:
201 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
202 self.rl_next_input = None
203
204 def interact(self):
205 while self.keep_running:
206 print(self.separate_in, end='')
207
208 try:
209 code = self.prompt_for_code()
210 except EOFError:
211 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
212 self.ask_exit()
213
214 else:
215 if code:
216 self.run_cell(code, store_history=True)
217
218 def mainloop(self):
219 # An extra layer of protection in case someone mashing Ctrl-C breaks
220 # out of our internal code.
221 while True:
222 try:
223 self.interact()
224 break
225 except KeyboardInterrupt:
226 print("\nKeyboardInterrupt escaped interact()\n")
227
228 _inputhook = None
229 def inputhook(self, context):
230 if self._inputhook is not None:
231 self._inputhook(context)
232
233 def enable_gui(self, gui=None):
234 if gui:
235 self._inputhook = get_inputhook_func(gui)
236 else:
237 self._inputhook = None
238
239 if __name__ == '__main__':
240 PTInteractiveShell.instance().interact()
@@ -1,1276 +1,1272 b''
1 1 # encoding: utf-8
2 2 """Word completion for IPython.
3 3
4 4 This module is a fork of the rlcompleter module in the Python standard
5 5 library. The original enhancements made to rlcompleter have been sent
6 6 upstream and were accepted as of Python 2.3, but we need a lot more
7 7 functionality specific to IPython, so this module will continue to live as an
8 8 IPython-specific utility.
9 9
10 10 Original rlcompleter documentation:
11 11
12 12 This requires the latest extension to the readline module (the
13 13 completes keywords, built-ins and globals in __main__; when completing
14 14 NAME.NAME..., it evaluates (!) the expression up to the last dot and
15 15 completes its attributes.
16 16
17 17 It's very cool to do "import string" type "string.", hit the
18 18 completion key (twice), and see the list of names defined by the
19 19 string module!
20 20
21 21 Tip: to use the tab key as the completion key, call
22 22
23 23 readline.parse_and_bind("tab: complete")
24 24
25 25 Notes:
26 26
27 27 - Exceptions raised by the completer function are *ignored* (and
28 28 generally cause the completion to fail). This is a feature -- since
29 29 readline sets the tty device in raw (or cbreak) mode, printing a
30 30 traceback wouldn't work well without some complicated hoopla to save,
31 31 reset and restore the tty state.
32 32
33 33 - The evaluation of the NAME.NAME... form may cause arbitrary
34 34 application defined code to be executed if an object with a
35 35 ``__getattr__`` hook is found. Since it is the responsibility of the
36 36 application (or the user) to enable this feature, I consider this an
37 37 acceptable risk. More complicated expressions (e.g. function calls or
38 38 indexing operations) are *not* evaluated.
39 39
40 40 - GNU readline is also used by the built-in functions input() and
41 41 raw_input(), and thus these also benefit/suffer from the completer
42 42 features. Clearly an interactive application can benefit by
43 43 specifying its own completer function and using raw_input() for all
44 44 its input.
45 45
46 46 - When the original stdin is not a tty device, GNU readline is never
47 47 used, and this module (and the readline module) are silently inactive.
48 48 """
49 49
50 50 # Copyright (c) IPython Development Team.
51 51 # Distributed under the terms of the Modified BSD License.
52 52 #
53 53 # Some of this code originated from rlcompleter in the Python standard library
54 54 # Copyright (C) 2001 Python Software Foundation, www.python.org
55 55
56 56 import __main__
57 57 import glob
58 58 import inspect
59 59 import itertools
60 60 import keyword
61 61 import os
62 62 import re
63 63 import sys
64 64 import unicodedata
65 65 import string
66 66
67 67 from traitlets.config.configurable import Configurable
68 68 from IPython.core.error import TryNext
69 69 from IPython.core.inputsplitter import ESC_MAGIC
70 70 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
71 71 from IPython.utils import generics
72 72 from IPython.utils import io
73 73 from IPython.utils.decorators import undoc
74 74 from IPython.utils.dir2 import dir2
75 75 from IPython.utils.process import arg_split
76 76 from IPython.utils.py3compat import builtin_mod, string_types, PY3
77 77 from traitlets import CBool, Enum
78 78
79 79 #-----------------------------------------------------------------------------
80 80 # Globals
81 81 #-----------------------------------------------------------------------------
82 82
83 83 # Public API
84 84 __all__ = ['Completer','IPCompleter']
85 85
86 86 if sys.platform == 'win32':
87 87 PROTECTABLES = ' '
88 88 else:
89 89 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
90 90
91 91
92 92 #-----------------------------------------------------------------------------
93 93 # Main functions and classes
94 94 #-----------------------------------------------------------------------------
95 95
96 96 def has_open_quotes(s):
97 97 """Return whether a string has open quotes.
98 98
99 99 This simply counts whether the number of quote characters of either type in
100 100 the string is odd.
101 101
102 102 Returns
103 103 -------
104 104 If there is an open quote, the quote character is returned. Else, return
105 105 False.
106 106 """
107 107 # We check " first, then ', so complex cases with nested quotes will get
108 108 # the " to take precedence.
109 109 if s.count('"') % 2:
110 110 return '"'
111 111 elif s.count("'") % 2:
112 112 return "'"
113 113 else:
114 114 return False
115 115
116 116
117 117 def protect_filename(s):
118 118 """Escape a string to protect certain characters."""
119 119
120 120 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
121 121 for ch in s])
122 122
123 123 def expand_user(path):
124 124 """Expand '~'-style usernames in strings.
125 125
126 126 This is similar to :func:`os.path.expanduser`, but it computes and returns
127 127 extra information that will be useful if the input was being used in
128 128 computing completions, and you wish to return the completions with the
129 129 original '~' instead of its expanded value.
130 130
131 131 Parameters
132 132 ----------
133 133 path : str
134 134 String to be expanded. If no ~ is present, the output is the same as the
135 135 input.
136 136
137 137 Returns
138 138 -------
139 139 newpath : str
140 140 Result of ~ expansion in the input path.
141 141 tilde_expand : bool
142 142 Whether any expansion was performed or not.
143 143 tilde_val : str
144 144 The value that ~ was replaced with.
145 145 """
146 146 # Default values
147 147 tilde_expand = False
148 148 tilde_val = ''
149 149 newpath = path
150 150
151 151 if path.startswith('~'):
152 152 tilde_expand = True
153 153 rest = len(path)-1
154 154 newpath = os.path.expanduser(path)
155 155 if rest:
156 156 tilde_val = newpath[:-rest]
157 157 else:
158 158 tilde_val = newpath
159 159
160 160 return newpath, tilde_expand, tilde_val
161 161
162 162
163 163 def compress_user(path, tilde_expand, tilde_val):
164 164 """Does the opposite of expand_user, with its outputs.
165 165 """
166 166 if tilde_expand:
167 167 return path.replace(tilde_val, '~')
168 168 else:
169 169 return path
170 170
171 171
172 172
173 def penalize_magics_key(word):
174 """key for sorting that penalizes magic commands in the ordering
173 def completions_sorting_key(word):
174 """key for sorting completions
175 175
176 Normal words are left alone.
177
178 Magic commands have the initial % moved to the end, e.g.
179 %matplotlib is transformed as follows:
180
181 %matplotlib -> matplotlib%
182
183 [The choice of the final % is arbitrary.]
184
185 Since "matplotlib" < "matplotlib%" as strings,
186 "timeit" will appear before the magic "%timeit" in the ordering
187
188 For consistency, move "%%" to the end, so cell magics appear *after*
189 line magics with the same name.
190
191 A check is performed that there are no other "%" in the string;
192 if there are, then the string is not a magic command and is left unchanged.
176 This does several things:
193 177
178 - Lowercase all completions, so they are sorted alphabetically with
179 upper and lower case words mingled
180 - Demote any completions starting with underscores to the end
181 - Insert any %magic and %%cellmagic completions in the alphabetical order
182 by their name
194 183 """
184 # Case insensitive sort
185 word = word.lower()
195 186
196 # Move any % signs from start to end of the key
197 # provided there are no others elsewhere in the string
187 prio1, prio2 = 0, 0
198 188
199 if word[:2] == "%%":
200 if not "%" in word[2:]:
201 return word[2:] + "%%"
189 if word.startswith('__'):
190 prio1 = 2
191 elif word.startswith('_'):
192 prio1 = 1
202 193
203 if word[:1] == "%":
194 if word.startswith('%%'):
195 # If there's another % in there, this is something else, so leave it alone
196 if not "%" in word[2:]:
197 word = word[2:]
198 prio2 = 2
199 elif word.startswith('%'):
204 200 if not "%" in word[1:]:
205 return word[1:] + "%"
206
207 return word
201 word = word[1:]
202 prio2 = 1
203
204 return prio1, word, prio2
208 205
209 206
210 207 @undoc
211 208 class Bunch(object): pass
212 209
213 210
214 211 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
215 212 GREEDY_DELIMS = ' =\r\n'
216 213
217 214
218 215 class CompletionSplitter(object):
219 216 """An object to split an input line in a manner similar to readline.
220 217
221 218 By having our own implementation, we can expose readline-like completion in
222 219 a uniform manner to all frontends. This object only needs to be given the
223 220 line of text to be split and the cursor position on said line, and it
224 221 returns the 'word' to be completed on at the cursor after splitting the
225 222 entire line.
226 223
227 224 What characters are used as splitting delimiters can be controlled by
228 225 setting the `delims` attribute (this is a property that internally
229 226 automatically builds the necessary regular expression)"""
230 227
231 228 # Private interface
232 229
233 230 # A string of delimiter characters. The default value makes sense for
234 231 # IPython's most typical usage patterns.
235 232 _delims = DELIMS
236 233
237 234 # The expression (a normal string) to be compiled into a regular expression
238 235 # for actual splitting. We store it as an attribute mostly for ease of
239 236 # debugging, since this type of code can be so tricky to debug.
240 237 _delim_expr = None
241 238
242 239 # The regular expression that does the actual splitting
243 240 _delim_re = None
244 241
245 242 def __init__(self, delims=None):
246 243 delims = CompletionSplitter._delims if delims is None else delims
247 244 self.delims = delims
248 245
249 246 @property
250 247 def delims(self):
251 248 """Return the string of delimiter characters."""
252 249 return self._delims
253 250
254 251 @delims.setter
255 252 def delims(self, delims):
256 253 """Set the delimiters for line splitting."""
257 254 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
258 255 self._delim_re = re.compile(expr)
259 256 self._delims = delims
260 257 self._delim_expr = expr
261 258
262 259 def split_line(self, line, cursor_pos=None):
263 260 """Split a line of text with a cursor at the given position.
264 261 """
265 262 l = line if cursor_pos is None else line[:cursor_pos]
266 263 return self._delim_re.split(l)[-1]
267 264
268 265
269 266 class Completer(Configurable):
270 267
271 268 greedy = CBool(False, config=True,
272 269 help="""Activate greedy completion
273 270
274 271 This will enable completion on elements of lists, results of function calls, etc.,
275 272 but can be unsafe because the code is actually evaluated on TAB.
276 273 """
277 274 )
278 275
279 276
280 277 def __init__(self, namespace=None, global_namespace=None, **kwargs):
281 278 """Create a new completer for the command line.
282 279
283 280 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
284 281
285 282 If unspecified, the default namespace where completions are performed
286 283 is __main__ (technically, __main__.__dict__). Namespaces should be
287 284 given as dictionaries.
288 285
289 286 An optional second namespace can be given. This allows the completer
290 287 to handle cases where both the local and global scopes need to be
291 288 distinguished.
292 289
293 290 Completer instances should be used as the completion mechanism of
294 291 readline via the set_completer() call:
295 292
296 293 readline.set_completer(Completer(my_namespace).complete)
297 294 """
298 295
299 296 # Don't bind to namespace quite yet, but flag whether the user wants a
300 297 # specific namespace or to use __main__.__dict__. This will allow us
301 298 # to bind to __main__.__dict__ at completion time, not now.
302 299 if namespace is None:
303 300 self.use_main_ns = 1
304 301 else:
305 302 self.use_main_ns = 0
306 303 self.namespace = namespace
307 304
308 305 # The global namespace, if given, can be bound directly
309 306 if global_namespace is None:
310 307 self.global_namespace = {}
311 308 else:
312 309 self.global_namespace = global_namespace
313 310
314 311 super(Completer, self).__init__(**kwargs)
315 312
316 313 def complete(self, text, state):
317 314 """Return the next possible completion for 'text'.
318 315
319 316 This is called successively with state == 0, 1, 2, ... until it
320 317 returns None. The completion should begin with 'text'.
321 318
322 319 """
323 320 if self.use_main_ns:
324 321 self.namespace = __main__.__dict__
325 322
326 323 if state == 0:
327 324 if "." in text:
328 325 self.matches = self.attr_matches(text)
329 326 else:
330 327 self.matches = self.global_matches(text)
331 328 try:
332 329 return self.matches[state]
333 330 except IndexError:
334 331 return None
335 332
336 333 def global_matches(self, text):
337 334 """Compute matches when text is a simple name.
338 335
339 336 Return a list of all keywords, built-in functions and names currently
340 337 defined in self.namespace or self.global_namespace that match.
341 338
342 339 """
343 340 #print 'Completer->global_matches, txt=%r' % text # dbg
344 341 matches = []
345 342 match_append = matches.append
346 343 n = len(text)
347 344 for lst in [keyword.kwlist,
348 345 builtin_mod.__dict__.keys(),
349 346 self.namespace.keys(),
350 347 self.global_namespace.keys()]:
351 348 for word in lst:
352 349 if word[:n] == text and word != "__builtins__":
353 350 match_append(word)
354 351 return matches
355 352
356 353 def attr_matches(self, text):
357 354 """Compute matches when text contains a dot.
358 355
359 356 Assuming the text is of the form NAME.NAME....[NAME], and is
360 357 evaluatable in self.namespace or self.global_namespace, it will be
361 358 evaluated and its attributes (as revealed by dir()) are used as
362 359 possible completions. (For class instances, class members are are
363 360 also considered.)
364 361
365 362 WARNING: this can still invoke arbitrary C code, if an object
366 363 with a __getattr__ hook is evaluated.
367 364
368 365 """
369 366
370 367 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
371 368 # Another option, seems to work great. Catches things like ''.<tab>
372 369 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
373 370
374 371 if m:
375 372 expr, attr = m.group(1, 3)
376 373 elif self.greedy:
377 374 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
378 375 if not m2:
379 376 return []
380 377 expr, attr = m2.group(1,2)
381 378 else:
382 379 return []
383 380
384 381 try:
385 382 obj = eval(expr, self.namespace)
386 383 except:
387 384 try:
388 385 obj = eval(expr, self.global_namespace)
389 386 except:
390 387 return []
391 388
392 389 if self.limit_to__all__ and hasattr(obj, '__all__'):
393 390 words = get__all__entries(obj)
394 391 else:
395 392 words = dir2(obj)
396 393
397 394 try:
398 395 words = generics.complete_object(obj, words)
399 396 except TryNext:
400 397 pass
401 398 except Exception:
402 399 # Silence errors from completion function
403 400 #raise # dbg
404 401 pass
405 402 # Build match list to return
406 403 n = len(attr)
407 404 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
408 405 return res
409 406
410 407
411 408 def get__all__entries(obj):
412 409 """returns the strings in the __all__ attribute"""
413 410 try:
414 411 words = getattr(obj, '__all__')
415 412 except:
416 413 return []
417 414
418 415 return [w for w in words if isinstance(w, string_types)]
419 416
420 417
421 418 def match_dict_keys(keys, prefix, delims):
422 419 """Used by dict_key_matches, matching the prefix to a list of keys"""
423 420 if not prefix:
424 421 return None, 0, [repr(k) for k in keys
425 422 if isinstance(k, (string_types, bytes))]
426 423 quote_match = re.search('["\']', prefix)
427 424 quote = quote_match.group()
428 425 try:
429 426 prefix_str = eval(prefix + quote, {})
430 427 except Exception:
431 428 return None, 0, []
432 429
433 430 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
434 431 token_match = re.search(pattern, prefix, re.UNICODE)
435 432 token_start = token_match.start()
436 433 token_prefix = token_match.group()
437 434
438 435 # TODO: support bytes in Py3k
439 436 matched = []
440 437 for key in keys:
441 438 try:
442 439 if not key.startswith(prefix_str):
443 440 continue
444 441 except (AttributeError, TypeError, UnicodeError):
445 442 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
446 443 continue
447 444
448 445 # reformat remainder of key to begin with prefix
449 446 rem = key[len(prefix_str):]
450 447 # force repr wrapped in '
451 448 rem_repr = repr(rem + '"')
452 449 if rem_repr.startswith('u') and prefix[0] not in 'uU':
453 450 # Found key is unicode, but prefix is Py2 string.
454 451 # Therefore attempt to interpret key as string.
455 452 try:
456 453 rem_repr = repr(rem.encode('ascii') + '"')
457 454 except UnicodeEncodeError:
458 455 continue
459 456
460 457 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
461 458 if quote == '"':
462 459 # The entered prefix is quoted with ",
463 460 # but the match is quoted with '.
464 461 # A contained " hence needs escaping for comparison:
465 462 rem_repr = rem_repr.replace('"', '\\"')
466 463
467 464 # then reinsert prefix from start of token
468 465 matched.append('%s%s' % (token_prefix, rem_repr))
469 466 return quote, token_start, matched
470 467
471 468
472 469 def _safe_isinstance(obj, module, class_name):
473 470 """Checks if obj is an instance of module.class_name if loaded
474 471 """
475 472 return (module in sys.modules and
476 473 isinstance(obj, getattr(__import__(module), class_name)))
477 474
478 475
479 476
480 477 def back_unicode_name_matches(text):
481 478 u"""Match unicode characters back to unicode name
482 479
483 480 This does β˜ƒ -> \\snowman
484 481
485 482 Note that snowman is not a valid python3 combining character but will be expanded.
486 483 Though it will not recombine back to the snowman character by the completion machinery.
487 484
488 485 This will not either back-complete standard sequences like \\n, \\b ...
489 486
490 487 Used on Python 3 only.
491 488 """
492 489 if len(text)<2:
493 490 return u'', ()
494 491 maybe_slash = text[-2]
495 492 if maybe_slash != '\\':
496 493 return u'', ()
497 494
498 495 char = text[-1]
499 496 # no expand on quote for completion in strings.
500 497 # nor backcomplete standard ascii keys
501 498 if char in string.ascii_letters or char in ['"',"'"]:
502 499 return u'', ()
503 500 try :
504 501 unic = unicodedata.name(char)
505 502 return '\\'+char,['\\'+unic]
506 503 except KeyError as e:
507 504 pass
508 505 return u'', ()
509 506
510 507 def back_latex_name_matches(text):
511 508 u"""Match latex characters back to unicode name
512 509
513 510 This does ->\\sqrt
514 511
515 512 Used on Python 3 only.
516 513 """
517 514 if len(text)<2:
518 515 return u'', ()
519 516 maybe_slash = text[-2]
520 517 if maybe_slash != '\\':
521 518 return u'', ()
522 519
523 520
524 521 char = text[-1]
525 522 # no expand on quote for completion in strings.
526 523 # nor backcomplete standard ascii keys
527 524 if char in string.ascii_letters or char in ['"',"'"]:
528 525 return u'', ()
529 526 try :
530 527 latex = reverse_latex_symbol[char]
531 528 # '\\' replace the \ as well
532 529 return '\\'+char,[latex]
533 530 except KeyError as e:
534 531 pass
535 532 return u'', ()
536 533
537 534
538 535 class IPCompleter(Completer):
539 536 """Extension of the completer class with IPython-specific features"""
540 537
541 538 def _greedy_changed(self, name, old, new):
542 539 """update the splitter and readline delims when greedy is changed"""
543 540 if new:
544 541 self.splitter.delims = GREEDY_DELIMS
545 542 else:
546 543 self.splitter.delims = DELIMS
547 544
548 545 if self.readline:
549 546 self.readline.set_completer_delims(self.splitter.delims)
550 547
551 548 merge_completions = CBool(True, config=True,
552 549 help="""Whether to merge completion results into a single list
553 550
554 551 If False, only the completion results from the first non-empty
555 552 completer will be returned.
556 553 """
557 554 )
558 555 omit__names = Enum((0,1,2), default_value=2, config=True,
559 556 help="""Instruct the completer to omit private method names
560 557
561 558 Specifically, when completing on ``object.<tab>``.
562 559
563 560 When 2 [default]: all names that start with '_' will be excluded.
564 561
565 562 When 1: all 'magic' names (``__foo__``) will be excluded.
566 563
567 564 When 0: nothing will be excluded.
568 565 """
569 566 )
570 567 limit_to__all__ = CBool(default_value=False, config=True,
571 568 help="""Instruct the completer to use __all__ for the completion
572 569
573 570 Specifically, when completing on ``object.<tab>``.
574 571
575 572 When True: only those names in obj.__all__ will be included.
576 573
577 574 When False [default]: the __all__ attribute is ignored
578 575 """
579 576 )
580 577
581 578 def __init__(self, shell=None, namespace=None, global_namespace=None,
582 579 use_readline=True, config=None, **kwargs):
583 580 """IPCompleter() -> completer
584 581
585 582 Return a completer object suitable for use by the readline library
586 583 via readline.set_completer().
587 584
588 585 Inputs:
589 586
590 587 - shell: a pointer to the ipython shell itself. This is needed
591 588 because this completer knows about magic functions, and those can
592 589 only be accessed via the ipython instance.
593 590
594 591 - namespace: an optional dict where completions are performed.
595 592
596 593 - global_namespace: secondary optional dict for completions, to
597 594 handle cases (such as IPython embedded inside functions) where
598 595 both Python scopes are visible.
599 596
600 597 use_readline : bool, optional
601 598 If true, use the readline library. This completer can still function
602 599 without readline, though in that case callers must provide some extra
603 600 information on each call about the current line."""
604 601
605 602 self.magic_escape = ESC_MAGIC
606 603 self.splitter = CompletionSplitter()
607 604
608 605 # Readline configuration, only used by the rlcompleter method.
609 606 if use_readline:
610 607 # We store the right version of readline so that later code
611 608 import IPython.utils.rlineimpl as readline
612 609 self.readline = readline
613 610 else:
614 611 self.readline = None
615 612
616 613 # _greedy_changed() depends on splitter and readline being defined:
617 614 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
618 615 config=config, **kwargs)
619 616
620 617 # List where completion matches will be stored
621 618 self.matches = []
622 619 self.shell = shell
623 620 # Regexp to split filenames with spaces in them
624 621 self.space_name_re = re.compile(r'([^\\] )')
625 622 # Hold a local ref. to glob.glob for speed
626 623 self.glob = glob.glob
627 624
628 625 # Determine if we are running on 'dumb' terminals, like (X)Emacs
629 626 # buffers, to avoid completion problems.
630 627 term = os.environ.get('TERM','xterm')
631 628 self.dumb_terminal = term in ['dumb','emacs']
632 629
633 630 # Special handling of backslashes needed in win32 platforms
634 631 if sys.platform == "win32":
635 632 self.clean_glob = self._clean_glob_win32
636 633 else:
637 634 self.clean_glob = self._clean_glob
638 635
639 636 #regexp to parse docstring for function signature
640 637 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
641 638 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
642 639 #use this if positional argument name is also needed
643 640 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
644 641
645 642 # All active matcher routines for completion
646 643 self.matchers = [self.python_matches,
647 644 self.file_matches,
648 645 self.magic_matches,
649 646 self.python_func_kw_matches,
650 647 self.dict_key_matches,
651 648 ]
652 649
653 650 def all_completions(self, text):
654 651 """
655 652 Wrapper around the complete method for the benefit of emacs
656 653 and pydb.
657 654 """
658 655 return self.complete(text)[1]
659 656
660 657 def _clean_glob(self,text):
661 658 return self.glob("%s*" % text)
662 659
663 660 def _clean_glob_win32(self,text):
664 661 return [f.replace("\\","/")
665 662 for f in self.glob("%s*" % text)]
666 663
667 664 def file_matches(self, text):
668 665 """Match filenames, expanding ~USER type strings.
669 666
670 667 Most of the seemingly convoluted logic in this completer is an
671 668 attempt to handle filenames with spaces in them. And yet it's not
672 669 quite perfect, because Python's readline doesn't expose all of the
673 670 GNU readline details needed for this to be done correctly.
674 671
675 672 For a filename with a space in it, the printed completions will be
676 673 only the parts after what's already been typed (instead of the
677 674 full completions, as is normally done). I don't think with the
678 675 current (as of Python 2.3) Python readline it's possible to do
679 676 better."""
680 677
681 678 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
682 679
683 680 # chars that require escaping with backslash - i.e. chars
684 681 # that readline treats incorrectly as delimiters, but we
685 682 # don't want to treat as delimiters in filename matching
686 683 # when escaped with backslash
687 684 if text.startswith('!'):
688 685 text = text[1:]
689 686 text_prefix = '!'
690 687 else:
691 688 text_prefix = ''
692 689
693 690 text_until_cursor = self.text_until_cursor
694 691 # track strings with open quotes
695 692 open_quotes = has_open_quotes(text_until_cursor)
696 693
697 694 if '(' in text_until_cursor or '[' in text_until_cursor:
698 695 lsplit = text
699 696 else:
700 697 try:
701 698 # arg_split ~ shlex.split, but with unicode bugs fixed by us
702 699 lsplit = arg_split(text_until_cursor)[-1]
703 700 except ValueError:
704 701 # typically an unmatched ", or backslash without escaped char.
705 702 if open_quotes:
706 703 lsplit = text_until_cursor.split(open_quotes)[-1]
707 704 else:
708 705 return []
709 706 except IndexError:
710 707 # tab pressed on empty line
711 708 lsplit = ""
712 709
713 710 if not open_quotes and lsplit != protect_filename(lsplit):
714 711 # if protectables are found, do matching on the whole escaped name
715 712 has_protectables = True
716 713 text0,text = text,lsplit
717 714 else:
718 715 has_protectables = False
719 716 text = os.path.expanduser(text)
720 717
721 718 if text == "":
722 719 return [text_prefix + protect_filename(f) for f in self.glob("*")]
723 720
724 721 # Compute the matches from the filesystem
725 722 m0 = self.clean_glob(text.replace('\\',''))
726 723
727 724 if has_protectables:
728 725 # If we had protectables, we need to revert our changes to the
729 726 # beginning of filename so that we don't double-write the part
730 727 # of the filename we have so far
731 728 len_lsplit = len(lsplit)
732 729 matches = [text_prefix + text0 +
733 730 protect_filename(f[len_lsplit:]) for f in m0]
734 731 else:
735 732 if open_quotes:
736 733 # if we have a string with an open quote, we don't need to
737 734 # protect the names at all (and we _shouldn't_, as it
738 735 # would cause bugs when the filesystem call is made).
739 736 matches = m0
740 737 else:
741 738 matches = [text_prefix +
742 739 protect_filename(f) for f in m0]
743 740
744 741 #io.rprint('mm', matches) # dbg
745 742
746 743 # Mark directories in input list by appending '/' to their names.
747 744 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
748 745 return matches
749 746
750 747 def magic_matches(self, text):
751 748 """Match magics"""
752 749 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
753 750 # Get all shell magics now rather than statically, so magics loaded at
754 751 # runtime show up too.
755 752 lsm = self.shell.magics_manager.lsmagic()
756 753 line_magics = lsm['line']
757 754 cell_magics = lsm['cell']
758 755 pre = self.magic_escape
759 756 pre2 = pre+pre
760 757
761 758 # Completion logic:
762 759 # - user gives %%: only do cell magics
763 760 # - user gives %: do both line and cell magics
764 761 # - no prefix: do both
765 762 # In other words, line magics are skipped if the user gives %% explicitly
766 763 bare_text = text.lstrip(pre)
767 764 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
768 765 if not text.startswith(pre2):
769 766 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
770 767 return comp
771 768
772 769 def python_matches(self,text):
773 770 """Match attributes or global python names"""
774 771
775 772 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
776 773 if "." in text:
777 774 try:
778 775 matches = self.attr_matches(text)
779 776 if text.endswith('.') and self.omit__names:
780 777 if self.omit__names == 1:
781 778 # true if txt is _not_ a __ name, false otherwise:
782 779 no__name = (lambda txt:
783 780 re.match(r'.*\.__.*?__',txt) is None)
784 781 else:
785 782 # true if txt is _not_ a _ name, false otherwise:
786 783 no__name = (lambda txt:
787 784 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
788 785 matches = filter(no__name, matches)
789 786 except NameError:
790 787 # catches <undefined attributes>.<tab>
791 788 matches = []
792 789 else:
793 790 matches = self.global_matches(text)
794 791
795 792 return matches
796 793
797 794 def _default_arguments_from_docstring(self, doc):
798 795 """Parse the first line of docstring for call signature.
799 796
800 797 Docstring should be of the form 'min(iterable[, key=func])\n'.
801 798 It can also parse cython docstring of the form
802 799 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
803 800 """
804 801 if doc is None:
805 802 return []
806 803
807 804 #care only the firstline
808 805 line = doc.lstrip().splitlines()[0]
809 806
810 807 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
811 808 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
812 809 sig = self.docstring_sig_re.search(line)
813 810 if sig is None:
814 811 return []
815 812 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
816 813 sig = sig.groups()[0].split(',')
817 814 ret = []
818 815 for s in sig:
819 816 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
820 817 ret += self.docstring_kwd_re.findall(s)
821 818 return ret
822 819
823 820 def _default_arguments(self, obj):
824 821 """Return the list of default arguments of obj if it is callable,
825 822 or empty list otherwise."""
826 823 call_obj = obj
827 824 ret = []
828 825 if inspect.isbuiltin(obj):
829 826 pass
830 827 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
831 828 if inspect.isclass(obj):
832 829 #for cython embededsignature=True the constructor docstring
833 830 #belongs to the object itself not __init__
834 831 ret += self._default_arguments_from_docstring(
835 832 getattr(obj, '__doc__', ''))
836 833 # for classes, check for __init__,__new__
837 834 call_obj = (getattr(obj, '__init__', None) or
838 835 getattr(obj, '__new__', None))
839 836 # for all others, check if they are __call__able
840 837 elif hasattr(obj, '__call__'):
841 838 call_obj = obj.__call__
842 839 ret += self._default_arguments_from_docstring(
843 840 getattr(call_obj, '__doc__', ''))
844 841
845 842 if PY3:
846 843 _keeps = (inspect.Parameter.KEYWORD_ONLY,
847 844 inspect.Parameter.POSITIONAL_OR_KEYWORD)
848 845 signature = inspect.signature
849 846 else:
850 847 import IPython.utils.signatures
851 848 _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY,
852 849 IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD)
853 850 signature = IPython.utils.signatures.signature
854 851
855 852 try:
856 853 sig = signature(call_obj)
857 854 ret.extend(k for k, v in sig.parameters.items() if
858 855 v.kind in _keeps)
859 856 except ValueError:
860 857 pass
861 858
862 859 return list(set(ret))
863 860
864 861 def python_func_kw_matches(self,text):
865 862 """Match named parameters (kwargs) of the last open function"""
866 863
867 864 if "." in text: # a parameter cannot be dotted
868 865 return []
869 866 try: regexp = self.__funcParamsRegex
870 867 except AttributeError:
871 868 regexp = self.__funcParamsRegex = re.compile(r'''
872 869 '.*?(?<!\\)' | # single quoted strings or
873 870 ".*?(?<!\\)" | # double quoted strings or
874 871 \w+ | # identifier
875 872 \S # other characters
876 873 ''', re.VERBOSE | re.DOTALL)
877 874 # 1. find the nearest identifier that comes before an unclosed
878 875 # parenthesis before the cursor
879 876 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
880 877 tokens = regexp.findall(self.text_until_cursor)
881 878 tokens.reverse()
882 879 iterTokens = iter(tokens); openPar = 0
883 880
884 881 for token in iterTokens:
885 882 if token == ')':
886 883 openPar -= 1
887 884 elif token == '(':
888 885 openPar += 1
889 886 if openPar > 0:
890 887 # found the last unclosed parenthesis
891 888 break
892 889 else:
893 890 return []
894 891 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
895 892 ids = []
896 893 isId = re.compile(r'\w+$').match
897 894
898 895 while True:
899 896 try:
900 897 ids.append(next(iterTokens))
901 898 if not isId(ids[-1]):
902 899 ids.pop(); break
903 900 if not next(iterTokens) == '.':
904 901 break
905 902 except StopIteration:
906 903 break
907 904 # lookup the candidate callable matches either using global_matches
908 905 # or attr_matches for dotted names
909 906 if len(ids) == 1:
910 907 callableMatches = self.global_matches(ids[0])
911 908 else:
912 909 callableMatches = self.attr_matches('.'.join(ids[::-1]))
913 910 argMatches = []
914 911 for callableMatch in callableMatches:
915 912 try:
916 913 namedArgs = self._default_arguments(eval(callableMatch,
917 914 self.namespace))
918 915 except:
919 916 continue
920 917
921 918 for namedArg in namedArgs:
922 919 if namedArg.startswith(text):
923 920 argMatches.append("%s=" %namedArg)
924 921 return argMatches
925 922
926 923 def dict_key_matches(self, text):
927 924 "Match string keys in a dictionary, after e.g. 'foo[' "
928 925 def get_keys(obj):
929 926 # Only allow completion for known in-memory dict-like types
930 927 if isinstance(obj, dict) or\
931 928 _safe_isinstance(obj, 'pandas', 'DataFrame'):
932 929 try:
933 930 return list(obj.keys())
934 931 except Exception:
935 932 return []
936 933 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
937 934 _safe_isinstance(obj, 'numpy', 'void'):
938 935 return obj.dtype.names or []
939 936 return []
940 937
941 938 try:
942 939 regexps = self.__dict_key_regexps
943 940 except AttributeError:
944 941 dict_key_re_fmt = r'''(?x)
945 942 ( # match dict-referring expression wrt greedy setting
946 943 %s
947 944 )
948 945 \[ # open bracket
949 946 \s* # and optional whitespace
950 947 ([uUbB]? # string prefix (r not handled)
951 948 (?: # unclosed string
952 949 '(?:[^']|(?<!\\)\\')*
953 950 |
954 951 "(?:[^"]|(?<!\\)\\")*
955 952 )
956 953 )?
957 954 $
958 955 '''
959 956 regexps = self.__dict_key_regexps = {
960 957 False: re.compile(dict_key_re_fmt % '''
961 958 # identifiers separated by .
962 959 (?!\d)\w+
963 960 (?:\.(?!\d)\w+)*
964 961 '''),
965 962 True: re.compile(dict_key_re_fmt % '''
966 963 .+
967 964 ''')
968 965 }
969 966
970 967 match = regexps[self.greedy].search(self.text_until_cursor)
971 968 if match is None:
972 969 return []
973 970
974 971 expr, prefix = match.groups()
975 972 try:
976 973 obj = eval(expr, self.namespace)
977 974 except Exception:
978 975 try:
979 976 obj = eval(expr, self.global_namespace)
980 977 except Exception:
981 978 return []
982 979
983 980 keys = get_keys(obj)
984 981 if not keys:
985 982 return keys
986 983 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
987 984 if not matches:
988 985 return matches
989 986
990 987 # get the cursor position of
991 988 # - the text being completed
992 989 # - the start of the key text
993 990 # - the start of the completion
994 991 text_start = len(self.text_until_cursor) - len(text)
995 992 if prefix:
996 993 key_start = match.start(2)
997 994 completion_start = key_start + token_offset
998 995 else:
999 996 key_start = completion_start = match.end()
1000 997
1001 998 # grab the leading prefix, to make sure all completions start with `text`
1002 999 if text_start > key_start:
1003 1000 leading = ''
1004 1001 else:
1005 1002 leading = text[text_start:completion_start]
1006 1003
1007 1004 # the index of the `[` character
1008 1005 bracket_idx = match.end(1)
1009 1006
1010 1007 # append closing quote and bracket as appropriate
1011 1008 # this is *not* appropriate if the opening quote or bracket is outside
1012 1009 # the text given to this method
1013 1010 suf = ''
1014 1011 continuation = self.line_buffer[len(self.text_until_cursor):]
1015 1012 if key_start > text_start and closing_quote:
1016 1013 # quotes were opened inside text, maybe close them
1017 1014 if continuation.startswith(closing_quote):
1018 1015 continuation = continuation[len(closing_quote):]
1019 1016 else:
1020 1017 suf += closing_quote
1021 1018 if bracket_idx > text_start:
1022 1019 # brackets were opened inside text, maybe close them
1023 1020 if not continuation.startswith(']'):
1024 1021 suf += ']'
1025 1022
1026 1023 return [leading + k + suf for k in matches]
1027 1024
1028 1025 def unicode_name_matches(self, text):
1029 1026 u"""Match Latex-like syntax for unicode characters base
1030 1027 on the name of the character.
1031 1028
1032 1029 This does \\GREEK SMALL LETTER ETA -> Ξ·
1033 1030
1034 1031 Works only on valid python 3 identifier, or on combining characters that
1035 1032 will combine to form a valid identifier.
1036 1033
1037 1034 Used on Python 3 only.
1038 1035 """
1039 1036 slashpos = text.rfind('\\')
1040 1037 if slashpos > -1:
1041 1038 s = text[slashpos+1:]
1042 1039 try :
1043 1040 unic = unicodedata.lookup(s)
1044 1041 # allow combining chars
1045 1042 if ('a'+unic).isidentifier():
1046 1043 return '\\'+s,[unic]
1047 1044 except KeyError as e:
1048 1045 pass
1049 1046 return u'', []
1050 1047
1051 1048
1052 1049
1053 1050
1054 1051 def latex_matches(self, text):
1055 1052 u"""Match Latex syntax for unicode characters.
1056 1053
1057 1054 This does both \\alp -> \\alpha and \\alpha -> Ξ±
1058 1055
1059 1056 Used on Python 3 only.
1060 1057 """
1061 1058 slashpos = text.rfind('\\')
1062 1059 if slashpos > -1:
1063 1060 s = text[slashpos:]
1064 1061 if s in latex_symbols:
1065 1062 # Try to complete a full latex symbol to unicode
1066 1063 # \\alpha -> Ξ±
1067 1064 return s, [latex_symbols[s]]
1068 1065 else:
1069 1066 # If a user has partially typed a latex symbol, give them
1070 1067 # a full list of options \al -> [\aleph, \alpha]
1071 1068 matches = [k for k in latex_symbols if k.startswith(s)]
1072 1069 return s, matches
1073 1070 return u'', []
1074 1071
1075 1072 def dispatch_custom_completer(self, text):
1076 1073 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
1077 1074 line = self.line_buffer
1078 1075 if not line.strip():
1079 1076 return None
1080 1077
1081 1078 # Create a little structure to pass all the relevant information about
1082 1079 # the current completion to any custom completer.
1083 1080 event = Bunch()
1084 1081 event.line = line
1085 1082 event.symbol = text
1086 1083 cmd = line.split(None,1)[0]
1087 1084 event.command = cmd
1088 1085 event.text_until_cursor = self.text_until_cursor
1089 1086
1090 1087 #print "\ncustom:{%s]\n" % event # dbg
1091 1088
1092 1089 # for foo etc, try also to find completer for %foo
1093 1090 if not cmd.startswith(self.magic_escape):
1094 1091 try_magic = self.custom_completers.s_matches(
1095 1092 self.magic_escape + cmd)
1096 1093 else:
1097 1094 try_magic = []
1098 1095
1099 1096 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1100 1097 try_magic,
1101 1098 self.custom_completers.flat_matches(self.text_until_cursor)):
1102 1099 #print "try",c # dbg
1103 1100 try:
1104 1101 res = c(event)
1105 1102 if res:
1106 1103 # first, try case sensitive match
1107 1104 withcase = [r for r in res if r.startswith(text)]
1108 1105 if withcase:
1109 1106 return withcase
1110 1107 # if none, then case insensitive ones are ok too
1111 1108 text_low = text.lower()
1112 1109 return [r for r in res if r.lower().startswith(text_low)]
1113 1110 except TryNext:
1114 1111 pass
1115 1112
1116 1113 return None
1117 1114
1118 1115 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1119 1116 """Find completions for the given text and line context.
1120 1117
1121 1118 Note that both the text and the line_buffer are optional, but at least
1122 1119 one of them must be given.
1123 1120
1124 1121 Parameters
1125 1122 ----------
1126 1123 text : string, optional
1127 1124 Text to perform the completion on. If not given, the line buffer
1128 1125 is split using the instance's CompletionSplitter object.
1129 1126
1130 1127 line_buffer : string, optional
1131 1128 If not given, the completer attempts to obtain the current line
1132 1129 buffer via readline. This keyword allows clients which are
1133 1130 requesting for text completions in non-readline contexts to inform
1134 1131 the completer of the entire text.
1135 1132
1136 1133 cursor_pos : int, optional
1137 1134 Index of the cursor in the full line buffer. Should be provided by
1138 1135 remote frontends where kernel has no access to frontend state.
1139 1136
1140 1137 Returns
1141 1138 -------
1142 1139 text : str
1143 1140 Text that was actually used in the completion.
1144 1141
1145 1142 matches : list
1146 1143 A list of completion matches.
1147 1144 """
1148 1145 # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1149 1146
1150 1147 # if the cursor position isn't given, the only sane assumption we can
1151 1148 # make is that it's at the end of the line (the common case)
1152 1149 if cursor_pos is None:
1153 1150 cursor_pos = len(line_buffer) if text is None else len(text)
1154 1151
1155 1152 if PY3:
1156 1153
1157 1154 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1158 1155 latex_text, latex_matches = self.latex_matches(base_text)
1159 1156 if latex_matches:
1160 1157 return latex_text, latex_matches
1161 1158 name_text = ''
1162 1159 name_matches = []
1163 1160 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1164 1161 name_text, name_matches = meth(base_text)
1165 1162 if name_text:
1166 1163 return name_text, name_matches
1167 1164
1168 1165 # if text is either None or an empty string, rely on the line buffer
1169 1166 if not text:
1170 1167 text = self.splitter.split_line(line_buffer, cursor_pos)
1171 1168
1172 1169 # If no line buffer is given, assume the input text is all there was
1173 1170 if line_buffer is None:
1174 1171 line_buffer = text
1175 1172
1176 1173 self.line_buffer = line_buffer
1177 1174 self.text_until_cursor = self.line_buffer[:cursor_pos]
1178 1175 # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
1179 1176
1180 1177 # Start with a clean slate of completions
1181 1178 self.matches[:] = []
1182 1179 custom_res = self.dispatch_custom_completer(text)
1183 1180 if custom_res is not None:
1184 1181 # did custom completers produce something?
1185 1182 self.matches = custom_res
1186 1183 else:
1187 1184 # Extend the list of completions with the results of each
1188 1185 # matcher, so we return results to the user from all
1189 1186 # namespaces.
1190 1187 if self.merge_completions:
1191 1188 self.matches = []
1192 1189 for matcher in self.matchers:
1193 1190 try:
1194 1191 self.matches.extend(matcher(text))
1195 1192 except:
1196 1193 # Show the ugly traceback if the matcher causes an
1197 1194 # exception, but do NOT crash the kernel!
1198 1195 sys.excepthook(*sys.exc_info())
1199 1196 else:
1200 1197 for matcher in self.matchers:
1201 1198 self.matches = matcher(text)
1202 1199 if self.matches:
1203 1200 break
1204 1201 # FIXME: we should extend our api to return a dict with completions for
1205 1202 # different types of objects. The rlcomplete() method could then
1206 1203 # simply collapse the dict into a list for readline, but we'd have
1207 1204 # richer completion semantics in other evironments.
1208 1205
1209 # use penalize_magics_key to put magics after variables with same name
1210 self.matches = sorted(set(self.matches), key=penalize_magics_key)
1206 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1211 1207
1212 1208 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
1213 1209 return text, self.matches
1214 1210
1215 1211 def rlcomplete(self, text, state):
1216 1212 """Return the state-th possible completion for 'text'.
1217 1213
1218 1214 This is called successively with state == 0, 1, 2, ... until it
1219 1215 returns None. The completion should begin with 'text'.
1220 1216
1221 1217 Parameters
1222 1218 ----------
1223 1219 text : string
1224 1220 Text to perform the completion on.
1225 1221
1226 1222 state : int
1227 1223 Counter used by readline.
1228 1224 """
1229 1225 if state==0:
1230 1226
1231 1227 self.line_buffer = line_buffer = self.readline.get_line_buffer()
1232 1228 cursor_pos = self.readline.get_endidx()
1233 1229
1234 1230 #io.rprint("\nRLCOMPLETE: %r %r %r" %
1235 1231 # (text, line_buffer, cursor_pos) ) # dbg
1236 1232
1237 1233 # if there is only a tab on a line with only whitespace, instead of
1238 1234 # the mostly useless 'do you want to see all million completions'
1239 1235 # message, just do the right thing and give the user his tab!
1240 1236 # Incidentally, this enables pasting of tabbed text from an editor
1241 1237 # (as long as autoindent is off).
1242 1238
1243 1239 # It should be noted that at least pyreadline still shows file
1244 1240 # completions - is there a way around it?
1245 1241
1246 1242 # don't apply this on 'dumb' terminals, such as emacs buffers, so
1247 1243 # we don't interfere with their own tab-completion mechanism.
1248 1244 if not (self.dumb_terminal or line_buffer.strip()):
1249 1245 self.readline.insert_text('\t')
1250 1246 sys.stdout.flush()
1251 1247 return None
1252 1248
1253 1249 # Note: debugging exceptions that may occur in completion is very
1254 1250 # tricky, because readline unconditionally silences them. So if
1255 1251 # during development you suspect a bug in the completion code, turn
1256 1252 # this flag on temporarily by uncommenting the second form (don't
1257 1253 # flip the value in the first line, as the '# dbg' marker can be
1258 1254 # automatically detected and is used elsewhere).
1259 1255 DEBUG = False
1260 1256 #DEBUG = True # dbg
1261 1257 if DEBUG:
1262 1258 try:
1263 1259 self.complete(text, line_buffer, cursor_pos)
1264 1260 except:
1265 1261 import traceback; traceback.print_exc()
1266 1262 else:
1267 1263 # The normal production version is here
1268 1264
1269 1265 # This method computes the self.matches array
1270 1266 self.complete(text, line_buffer, cursor_pos)
1271 1267
1272 1268 try:
1273 1269 return self.matches[state]
1274 1270 except IndexError:
1275 1271 return None
1276 1272
@@ -1,68 +1,70 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for shellapp module.
3 3
4 4 Authors
5 5 -------
6 6 * Bradley Froehle
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2012 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 import unittest
19 19
20 20 from IPython.testing import decorators as dec
21 21 from IPython.testing import tools as tt
22 22 from IPython.utils.py3compat import PY3
23 23
24 24 sqlite_err_maybe = dec.module_not_available('sqlite3')
25 25 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
26 26 ' your history will not be saved\n')
27 27
28 28 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
29 29 """Test the behavior of the file_to_run parameter."""
30 30
31 31 def test_py_script_file_attribute(self):
32 32 """Test that `__file__` is set when running `ipython file.py`"""
33 33 src = "print(__file__)\n"
34 34 self.mktmp(src)
35 35
36 36 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
37 37 tt.ipexec_validate(self.fname, self.fname, err)
38 38
39 39 def test_ipy_script_file_attribute(self):
40 40 """Test that `__file__` is set when running `ipython file.ipy`"""
41 41 src = "print(__file__)\n"
42 42 self.mktmp(src, ext='.ipy')
43 43
44 44 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
45 45 tt.ipexec_validate(self.fname, self.fname, err)
46 46
47 47 # The commands option to ipexec_validate doesn't work on Windows, and it
48 48 # doesn't seem worth fixing
49 49 @dec.skip_win32
50 50 def test_py_script_file_attribute_interactively(self):
51 51 """Test that `__file__` is not set after `ipython -i file.py`"""
52 52 src = "True\n"
53 53 self.mktmp(src)
54 54
55 out = 'In [1]: False\n\nIn [2]:'
55 56 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
56 tt.ipexec_validate(self.fname, 'False', err, options=['-i'],
57 tt.ipexec_validate(self.fname, out, err, options=['-i'],
57 58 commands=['"__file__" in globals()', 'exit()'])
58 59
59 60 @dec.skip_win32
60 61 @dec.skipif(PY3)
61 62 def test_py_script_file_compiler_directive(self):
62 63 """Test `__future__` compiler directives with `ipython -i file.py`"""
63 64 src = "from __future__ import division\n"
64 65 self.mktmp(src)
65 66
67 out = 'In [1]: float\n\nIn [2]:'
66 68 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
67 tt.ipexec_validate(self.fname, 'float', err, options=['-i'],
69 tt.ipexec_validate(self.fname, out, err, options=['-i'],
68 70 commands=['type(1/2)', 'exit()'])
@@ -1,368 +1,368 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6 6 """
7 7
8 8 # Copyright (c) IPython Development Team.
9 9 # Distributed under the terms of the Modified BSD License.
10 10
11 11 from __future__ import absolute_import
12 12 from __future__ import print_function
13 13
14 14 import logging
15 15 import os
16 16 import sys
17 17
18 18 from traitlets.config.loader import Config
19 19 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 20 from IPython.core import release
21 21 from IPython.core import usage
22 22 from IPython.core.completer import IPCompleter
23 23 from IPython.core.crashhandler import CrashHandler
24 24 from IPython.core.formatters import PlainTextFormatter
25 25 from IPython.core.history import HistoryManager
26 26 from IPython.core.prompts import PromptManager
27 27 from IPython.core.application import (
28 28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 29 )
30 30 from IPython.core.magics import ScriptMagics
31 31 from IPython.core.shellapp import (
32 32 InteractiveShellApp, shell_flags, shell_aliases
33 33 )
34 34 from IPython.extensions.storemagic import StoreMagics
35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
35 from .ptshell import PTInteractiveShell as TerminalInteractiveShell
36 36 from IPython.utils import warn
37 37 from IPython.paths import get_ipython_dir
38 38 from traitlets import (
39 39 Bool, List, Dict,
40 40 )
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Globals, utilities and helpers
44 44 #-----------------------------------------------------------------------------
45 45
46 46 _examples = """
47 47 ipython --matplotlib # enable matplotlib integration
48 48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
49 49
50 50 ipython --log-level=DEBUG # set logging to DEBUG
51 51 ipython --profile=foo # start with profile foo
52 52
53 53 ipython profile create foo # create profile foo w/ default config files
54 54 ipython help profile # show the help for the profile subcmd
55 55
56 56 ipython locate # print the path to the IPython directory
57 57 ipython locate profile foo # print the path to the directory for profile `foo`
58 58 """
59 59
60 60 #-----------------------------------------------------------------------------
61 61 # Crash handler for this application
62 62 #-----------------------------------------------------------------------------
63 63
64 64 class IPAppCrashHandler(CrashHandler):
65 65 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
66 66
67 67 def __init__(self, app):
68 68 contact_name = release.author
69 69 contact_email = release.author_email
70 70 bug_tracker = 'https://github.com/ipython/ipython/issues'
71 71 super(IPAppCrashHandler,self).__init__(
72 72 app, contact_name, contact_email, bug_tracker
73 73 )
74 74
75 75 def make_report(self,traceback):
76 76 """Return a string containing a crash report."""
77 77
78 78 sec_sep = self.section_sep
79 79 # Start with parent report
80 80 report = [super(IPAppCrashHandler, self).make_report(traceback)]
81 81 # Add interactive-specific info we may have
82 82 rpt_add = report.append
83 83 try:
84 84 rpt_add(sec_sep+"History of session input:")
85 85 for line in self.app.shell.user_ns['_ih']:
86 86 rpt_add(line)
87 87 rpt_add('\n*** Last line of input (may not be in above history):\n')
88 88 rpt_add(self.app.shell._last_input_line+'\n')
89 89 except:
90 90 pass
91 91
92 92 return ''.join(report)
93 93
94 94 #-----------------------------------------------------------------------------
95 95 # Aliases and Flags
96 96 #-----------------------------------------------------------------------------
97 97 flags = dict(base_flags)
98 98 flags.update(shell_flags)
99 99 frontend_flags = {}
100 100 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
101 101 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
102 102 'Turn on auto editing of files with syntax errors.',
103 103 'Turn off auto editing of files with syntax errors.'
104 104 )
105 105 addflag('banner', 'TerminalIPythonApp.display_banner',
106 106 "Display a banner upon starting IPython.",
107 107 "Don't display a banner upon starting IPython."
108 108 )
109 109 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
110 110 """Set to confirm when you try to exit IPython with an EOF (Control-D
111 111 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
112 112 you can force a direct exit without any confirmation.""",
113 113 "Don't prompt the user when exiting."
114 114 )
115 115 addflag('term-title', 'TerminalInteractiveShell.term_title',
116 116 "Enable auto setting the terminal title.",
117 117 "Disable auto setting the terminal title."
118 118 )
119 119 classic_config = Config()
120 120 classic_config.InteractiveShell.cache_size = 0
121 121 classic_config.PlainTextFormatter.pprint = False
122 122 classic_config.PromptManager.in_template = '>>> '
123 123 classic_config.PromptManager.in2_template = '... '
124 124 classic_config.PromptManager.out_template = ''
125 125 classic_config.InteractiveShell.separate_in = ''
126 126 classic_config.InteractiveShell.separate_out = ''
127 127 classic_config.InteractiveShell.separate_out2 = ''
128 128 classic_config.InteractiveShell.colors = 'NoColor'
129 129 classic_config.InteractiveShell.xmode = 'Plain'
130 130
131 131 frontend_flags['classic']=(
132 132 classic_config,
133 133 "Gives IPython a similar feel to the classic Python prompt."
134 134 )
135 135 # # log doesn't make so much sense this way anymore
136 136 # paa('--log','-l',
137 137 # action='store_true', dest='InteractiveShell.logstart',
138 138 # help="Start logging to the default log file (./ipython_log.py).")
139 139 #
140 140 # # quick is harder to implement
141 141 frontend_flags['quick']=(
142 142 {'TerminalIPythonApp' : {'quick' : True}},
143 143 "Enable quick startup with no config files."
144 144 )
145 145
146 146 frontend_flags['i'] = (
147 147 {'TerminalIPythonApp' : {'force_interact' : True}},
148 148 """If running code from the command line, become interactive afterwards.
149 149 It is often useful to follow this with `--` to treat remaining flags as
150 150 script arguments.
151 151 """
152 152 )
153 153 flags.update(frontend_flags)
154 154
155 155 aliases = dict(base_aliases)
156 156 aliases.update(shell_aliases)
157 157
158 158 #-----------------------------------------------------------------------------
159 159 # Main classes and functions
160 160 #-----------------------------------------------------------------------------
161 161
162 162
163 163 class LocateIPythonApp(BaseIPythonApplication):
164 164 description = """print the path to the IPython dir"""
165 165 subcommands = Dict(dict(
166 166 profile=('IPython.core.profileapp.ProfileLocate',
167 167 "print the path to an IPython profile directory",
168 168 ),
169 169 ))
170 170 def start(self):
171 171 if self.subapp is not None:
172 172 return self.subapp.start()
173 173 else:
174 174 print(self.ipython_dir)
175 175
176 176
177 177 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
178 178 name = u'ipython'
179 179 description = usage.cl_usage
180 180 crash_handler_class = IPAppCrashHandler
181 181 examples = _examples
182 182
183 183 flags = Dict(flags)
184 184 aliases = Dict(aliases)
185 185 classes = List()
186 186 def _classes_default(self):
187 187 """This has to be in a method, for TerminalIPythonApp to be available."""
188 188 return [
189 189 InteractiveShellApp, # ShellApp comes before TerminalApp, because
190 190 self.__class__, # it will also affect subclasses (e.g. QtConsole)
191 191 TerminalInteractiveShell,
192 192 PromptManager,
193 193 HistoryManager,
194 194 ProfileDir,
195 195 PlainTextFormatter,
196 196 IPCompleter,
197 197 ScriptMagics,
198 198 StoreMagics,
199 199 ]
200 200
201 201 deprecated_subcommands = dict(
202 202 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
203 203 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
204 204 ),
205 205 notebook=('notebook.notebookapp.NotebookApp',
206 206 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
207 207 ),
208 208 console=('jupyter_console.app.ZMQTerminalIPythonApp',
209 209 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
210 210 ),
211 211 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
212 212 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
213 213 ),
214 214 trust=('nbformat.sign.TrustNotebookApp',
215 215 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
216 216 ),
217 217 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
218 218 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
219 219 ),
220 220 )
221 221 subcommands = dict(
222 222 profile = ("IPython.core.profileapp.ProfileApp",
223 223 "Create and manage IPython profiles."
224 224 ),
225 225 kernel = ("ipykernel.kernelapp.IPKernelApp",
226 226 "Start a kernel without an attached frontend."
227 227 ),
228 228 locate=('IPython.terminal.ipapp.LocateIPythonApp',
229 229 LocateIPythonApp.description
230 230 ),
231 231 history=('IPython.core.historyapp.HistoryApp',
232 232 "Manage the IPython history database."
233 233 ),
234 234 )
235 235 deprecated_subcommands['install-nbextension'] = (
236 236 "notebook.nbextensions.InstallNBExtensionApp",
237 237 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
238 238 )
239 239 subcommands.update(deprecated_subcommands)
240 240
241 241 # *do* autocreate requested profile, but don't create the config file.
242 242 auto_create=Bool(True)
243 243 # configurables
244 244 quick = Bool(False, config=True,
245 245 help="""Start IPython quickly by skipping the loading of config files."""
246 246 )
247 247 def _quick_changed(self, name, old, new):
248 248 if new:
249 249 self.load_config_file = lambda *a, **kw: None
250 250
251 251 display_banner = Bool(True, config=True,
252 252 help="Whether to display a banner upon starting IPython."
253 253 )
254 254
255 255 # if there is code of files to run from the cmd line, don't interact
256 256 # unless the --i flag (App.force_interact) is true.
257 257 force_interact = Bool(False, config=True,
258 258 help="""If a command or file is given via the command-line,
259 259 e.g. 'ipython foo.py', start an interactive shell after executing the
260 260 file or command."""
261 261 )
262 262 def _force_interact_changed(self, name, old, new):
263 263 if new:
264 264 self.interact = True
265 265
266 266 def _file_to_run_changed(self, name, old, new):
267 267 if new:
268 268 self.something_to_run = True
269 269 if new and not self.force_interact:
270 270 self.interact = False
271 271 _code_to_run_changed = _file_to_run_changed
272 272 _module_to_run_changed = _file_to_run_changed
273 273
274 274 # internal, not-configurable
275 275 something_to_run=Bool(False)
276 276
277 277 def parse_command_line(self, argv=None):
278 278 """override to allow old '-pylab' flag with deprecation warning"""
279 279
280 280 argv = sys.argv[1:] if argv is None else argv
281 281
282 282 if '-pylab' in argv:
283 283 # deprecated `-pylab` given,
284 284 # warn and transform into current syntax
285 285 argv = argv[:] # copy, don't clobber
286 286 idx = argv.index('-pylab')
287 287 warn.warn("`-pylab` flag has been deprecated.\n"
288 288 " Use `--matplotlib <backend>` and import pylab manually.")
289 289 argv[idx] = '--pylab'
290 290
291 291 return super(TerminalIPythonApp, self).parse_command_line(argv)
292 292
293 293 @catch_config_error
294 294 def initialize(self, argv=None):
295 295 """Do actions after construct, but before starting the app."""
296 296 super(TerminalIPythonApp, self).initialize(argv)
297 297 if self.subapp is not None:
298 298 # don't bother initializing further, starting subapp
299 299 return
300 300 # print self.extra_args
301 301 if self.extra_args and not self.something_to_run:
302 302 self.file_to_run = self.extra_args[0]
303 303 self.init_path()
304 304 # create the shell
305 305 self.init_shell()
306 306 # and draw the banner
307 307 self.init_banner()
308 308 # Now a variety of things that happen after the banner is printed.
309 309 self.init_gui_pylab()
310 310 self.init_extensions()
311 311 self.init_code()
312 312
313 313 def init_shell(self):
314 314 """initialize the InteractiveShell instance"""
315 315 # Create an InteractiveShell instance.
316 316 # shell.display_banner should always be False for the terminal
317 317 # based app, because we call shell.show_banner() by hand below
318 318 # so the banner shows *before* all extension loading stuff.
319 319 self.shell = TerminalInteractiveShell.instance(parent=self,
320 320 display_banner=False, profile_dir=self.profile_dir,
321 321 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
322 322 self.shell.configurables.append(self)
323 323
324 324 def init_banner(self):
325 325 """optionally display the banner"""
326 326 if self.display_banner and self.interact:
327 327 self.shell.show_banner()
328 328 # Make sure there is a space below the banner.
329 329 if self.log_level <= logging.INFO: print()
330 330
331 331 def _pylab_changed(self, name, old, new):
332 332 """Replace --pylab='inline' with --pylab='auto'"""
333 333 if new == 'inline':
334 334 warn.warn("'inline' not available as pylab backend, "
335 335 "using 'auto' instead.")
336 336 self.pylab = 'auto'
337 337
338 338 def start(self):
339 339 if self.subapp is not None:
340 340 return self.subapp.start()
341 341 # perform any prexec steps:
342 342 if self.interact:
343 343 self.log.debug("Starting IPython's mainloop...")
344 344 self.shell.mainloop()
345 345 else:
346 346 self.log.debug("IPython not interactive...")
347 347
348 348 def load_default_config(ipython_dir=None):
349 349 """Load the default config file from the default ipython_dir.
350 350
351 351 This is useful for embedded shells.
352 352 """
353 353 if ipython_dir is None:
354 354 ipython_dir = get_ipython_dir()
355 355
356 356 profile_dir = os.path.join(ipython_dir, 'profile_default')
357 357
358 358 config = Config()
359 359 for cf in Application._load_config_files("ipython_config", path=profile_dir):
360 360 config.update(cf)
361 361
362 362 return config
363 363
364 364 launch_new_instance = TerminalIPythonApp.launch_instance
365 365
366 366
367 367 if __name__ == '__main__':
368 368 launch_new_instance()
@@ -1,51 +1,51 b''
1 1 #!/usr/bin/env python
2 2 """Simple GLUT example to manually test event loop integration.
3 3
4 4 This is meant to run tests manually in ipython as:
5 5
6 6 In [5]: %gui glut
7 7
8 8 In [6]: %run gui-glut.py
9 9
10 10 In [7]: gl.glClearColor(1,1,1,1)
11 11 """
12 12
13 13 #!/usr/bin/env python
14 14 import sys
15 15 import OpenGL.GL as gl
16 16 import OpenGL.GLUT as glut
17 17
18 18 def close():
19 19 glut.glutDestroyWindow(glut.glutGetWindow())
20 20
21 21 def display():
22 22 gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
23 23 glut.glutSwapBuffers()
24 24
25 25 def resize(width,height):
26 26 gl.glViewport(0, 0, width, height+4)
27 27 gl.glMatrixMode(gl.GL_PROJECTION)
28 28 gl.glLoadIdentity()
29 29 gl.glOrtho(0, width, 0, height+4, -1, 1)
30 30 gl.glMatrixMode(gl.GL_MODELVIEW)
31 31
32 32 if glut.glutGetWindow() > 0:
33 33 interactive = True
34 34 glut.glutInit(sys.argv)
35 35 glut.glutInitDisplayMode(glut.GLUT_DOUBLE |
36 36 glut.GLUT_RGBA |
37 37 glut.GLUT_DEPTH)
38 38 else:
39 39 interactive = False
40 40
41 glut.glutCreateWindow('gui-glut')
41 glut.glutCreateWindow(b'gui-glut')
42 42 glut.glutDisplayFunc(display)
43 43 glut.glutReshapeFunc(resize)
44 44 # This is necessary on osx to be able to close the window
45 45 # (else the close button is disabled)
46 46 if sys.platform == 'darwin' and not bool(glut.HAVE_FREEGLUT):
47 47 glut.glutWMCloseFunc(close)
48 48 gl.glClearColor(0,0,0,1)
49 49
50 50 if not interactive:
51 51 glut.glutMainLoop()
@@ -1,37 +1,37 b''
1 1 #!/usr/bin/env python
2 2 """Simple Gtk example to manually test event loop integration.
3 3
4 4 This is meant to run tests manually in ipython as:
5 5
6 6 In [1]: %gui gtk3
7 7
8 8 In [2]: %run gui-gtk3.py
9 9 """
10 10
11 11 from gi.repository import Gtk
12 12
13 13
14 14 def hello_world(wigdet, data=None):
15 15 print("Hello World")
16 16
17 17 def delete_event(widget, event, data=None):
18 18 return False
19 19
20 20 def destroy(widget, data=None):
21 21 Gtk.main_quit()
22 22
23 window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
23 window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
24 24 window.connect("delete_event", delete_event)
25 25 window.connect("destroy", destroy)
26 button = Gtk.Button("Hello World")
26 button = Gtk.Button(label="Hello World")
27 27 button.connect("clicked", hello_world, None)
28 28
29 29 window.add(button)
30 30 button.show()
31 31 window.show()
32 32
33 33 try:
34 34 from IPython.lib.inputhook import enable_gui
35 35 enable_gui('gtk3')
36 36 except ImportError:
37 37 Gtk.main()
@@ -1,296 +1,295 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
46 46 from glob import glob
47 47
48 48 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
49 49 # update it when the contents of directories change.
50 50 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
51 51
52 52 from distutils.core import setup
53 53
54 54 # Our own imports
55 55 from setupbase import target_update
56 56
57 57 from setupbase import (
58 58 setup_args,
59 59 find_packages,
60 60 find_package_data,
61 61 check_package_data_first,
62 62 find_entry_points,
63 63 build_scripts_entrypt,
64 64 find_data_files,
65 65 git_prebuild,
66 66 install_symlinked,
67 67 install_lib_symlink,
68 68 install_scripts_for_symlink,
69 69 unsymlink,
70 70 )
71 71
72 72 isfile = os.path.isfile
73 73 pjoin = os.path.join
74 74
75 75 #-------------------------------------------------------------------------------
76 76 # Handle OS specific things
77 77 #-------------------------------------------------------------------------------
78 78
79 79 if os.name in ('nt','dos'):
80 80 os_name = 'windows'
81 81 else:
82 82 os_name = os.name
83 83
84 84 # Under Windows, 'sdist' has not been supported. Now that the docs build with
85 85 # Sphinx it might work, but let's not turn it on until someone confirms that it
86 86 # actually works.
87 87 if os_name == 'windows' and 'sdist' in sys.argv:
88 88 print('The sdist command is not available under Windows. Exiting.')
89 89 sys.exit(1)
90 90
91 91
92 92 #-------------------------------------------------------------------------------
93 93 # Things related to the IPython documentation
94 94 #-------------------------------------------------------------------------------
95 95
96 96 # update the manuals when building a source dist
97 97 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
98 98
99 99 # List of things to be updated. Each entry is a triplet of args for
100 100 # target_update()
101 101 to_update = [
102 102 ('docs/man/ipython.1.gz',
103 103 ['docs/man/ipython.1'],
104 104 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
105 105 ]
106 106
107 107
108 108 [ target_update(*t) for t in to_update ]
109 109
110 110 #---------------------------------------------------------------------------
111 111 # Find all the packages, package data, and data_files
112 112 #---------------------------------------------------------------------------
113 113
114 114 packages = find_packages()
115 115 package_data = find_package_data()
116 116
117 117 data_files = find_data_files()
118 118
119 119 setup_args['packages'] = packages
120 120 setup_args['package_data'] = package_data
121 121 setup_args['data_files'] = data_files
122 122
123 123 #---------------------------------------------------------------------------
124 124 # custom distutils commands
125 125 #---------------------------------------------------------------------------
126 126 # imports here, so they are after setuptools import if there was one
127 127 from distutils.command.sdist import sdist
128 128 from distutils.command.upload import upload
129 129
130 130 class UploadWindowsInstallers(upload):
131 131
132 132 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
133 133 user_options = upload.user_options + [
134 134 ('files=', 'f', 'exe file (or glob) to upload')
135 135 ]
136 136 def initialize_options(self):
137 137 upload.initialize_options(self)
138 138 meta = self.distribution.metadata
139 139 base = '{name}-{version}'.format(
140 140 name=meta.get_name(),
141 141 version=meta.get_version()
142 142 )
143 143 self.files = os.path.join('dist', '%s.*.exe' % base)
144 144
145 145 def run(self):
146 146 for dist_file in glob(self.files):
147 147 self.upload_file('bdist_wininst', 'any', dist_file)
148 148
149 149 setup_args['cmdclass'] = {
150 150 'build_py': \
151 151 check_package_data_first(git_prebuild('IPython')),
152 152 'sdist' : git_prebuild('IPython', sdist),
153 153 'upload_wininst' : UploadWindowsInstallers,
154 154 'symlink': install_symlinked,
155 155 'install_lib_symlink': install_lib_symlink,
156 156 'install_scripts_sym': install_scripts_for_symlink,
157 157 'unsymlink': unsymlink,
158 158 }
159 159
160 160
161 161 #---------------------------------------------------------------------------
162 162 # Handle scripts, dependencies, and setuptools specific things
163 163 #---------------------------------------------------------------------------
164 164
165 165 # For some commands, use setuptools. Note that we do NOT list install here!
166 166 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
167 167 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
168 168 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
169 169 'egg_info', 'easy_install', 'upload', 'install_egg_info',
170 170 ))
171 171
172 172 if len(needs_setuptools.intersection(sys.argv)) > 0:
173 173 import setuptools
174 174
175 175 # This dict is used for passing extra arguments that are setuptools
176 176 # specific to setup
177 177 setuptools_extra_args = {}
178 178
179 179 # setuptools requirements
180 180
181 181 extras_require = dict(
182 182 parallel = ['ipyparallel'],
183 183 qtconsole = ['qtconsole'],
184 184 doc = ['Sphinx>=1.3'],
185 185 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments'],
186 186 terminal = [],
187 187 kernel = ['ipykernel'],
188 188 nbformat = ['nbformat'],
189 189 notebook = ['notebook', 'ipywidgets'],
190 190 nbconvert = ['nbconvert'],
191 191 )
192 192 install_requires = [
193 193 'setuptools>=18.5',
194 194 'decorator',
195 195 'pickleshare',
196 196 'simplegeneric>0.8',
197 197 'traitlets',
198 'prompt_toolkit', # We will require > 0.57 once a new release is made
198 199 ]
199 200
200 201 # Platform-specific dependencies:
201 202 # This is the correct way to specify these,
202 203 # but requires pip >= 6. pip < 6 ignores these.
203 204
204 205 extras_require.update({
205 206 ':sys_platform != "win32"': ['pexpect'],
206 207 ':sys_platform == "darwin"': ['appnope'],
207 ':sys_platform == "darwin" and platform_python_implementation == "CPython"': ['gnureadline'],
208 'terminal:sys_platform == "win32"': ['pyreadline>=2'],
209 208 'test:python_version == "2.7"': ['mock'],
210 209 })
211 210 # FIXME: re-specify above platform dependencies for pip < 6
212 211 # These would result in non-portable bdists.
213 212 if not any(arg.startswith('bdist') for arg in sys.argv):
214 213 if sys.version_info < (3, 3):
215 214 extras_require['test'].append('mock')
216 215
217 216 if sys.platform == 'darwin':
218 217 install_requires.extend(['appnope'])
219 218 have_readline = False
220 219 try:
221 220 import readline
222 221 except ImportError:
223 222 pass
224 223 else:
225 224 if 'libedit' not in readline.__doc__:
226 225 have_readline = True
227 226 if not have_readline:
228 227 install_requires.extend(['gnureadline'])
229 228
230 229 if sys.platform.startswith('win'):
231 230 extras_require['terminal'].append('pyreadline>=2.0')
232 231 else:
233 232 install_requires.append('pexpect')
234 233
235 234 # workaround pypa/setuptools#147, where setuptools misspells
236 235 # platform_python_implementation as python_implementation
237 236 if 'setuptools' in sys.modules:
238 237 for key in list(extras_require):
239 238 if 'platform_python_implementation' in key:
240 239 new_key = key.replace('platform_python_implementation', 'python_implementation')
241 240 extras_require[new_key] = extras_require.pop(key)
242 241
243 242 everything = set()
244 243 for key, deps in extras_require.items():
245 244 if ':' not in key:
246 245 everything.update(deps)
247 246 extras_require['all'] = everything
248 247
249 248 if 'setuptools' in sys.modules:
250 249 setuptools_extra_args['zip_safe'] = False
251 250 setuptools_extra_args['entry_points'] = {
252 251 'console_scripts': find_entry_points(),
253 252 'pygments.lexers': [
254 253 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
255 254 'ipython = IPython.lib.lexers:IPythonLexer',
256 255 'ipython3 = IPython.lib.lexers:IPython3Lexer',
257 256 ],
258 257 }
259 258 setup_args['extras_require'] = extras_require
260 259 requires = setup_args['install_requires'] = install_requires
261 260
262 261 # Script to be run by the windows binary installer after the default setup
263 262 # routine, to add shortcuts and similar windows-only things. Windows
264 263 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
265 264 # doesn't find them.
266 265 if 'bdist_wininst' in sys.argv:
267 266 if len(sys.argv) > 2 and \
268 267 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
269 268 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
270 269 sys.exit(1)
271 270 setup_args['data_files'].append(
272 271 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
273 272 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
274 273 setup_args['options'] = {"bdist_wininst":
275 274 {"install_script":
276 275 "ipython_win_post_install.py"}}
277 276
278 277 else:
279 278 # scripts has to be a non-empty list, or install_scripts isn't called
280 279 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
281 280
282 281 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
283 282
284 283 #---------------------------------------------------------------------------
285 284 # Do the actual setup now
286 285 #---------------------------------------------------------------------------
287 286
288 287 setup_args.update(setuptools_extra_args)
289 288
290 289
291 290
292 291 def main():
293 292 setup(**setup_args)
294 293
295 294 if __name__ == '__main__':
296 295 main()
General Comments 0
You need to be logged in to leave comments. Login now