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