##// END OF EJS Templates
adopt traitlets 4.2 API...
Min RK -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,257 +1,257 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 System command aliases.
3 System command aliases.
4
4
5 Authors:
5 Authors:
6
6
7 * Fernando Perez
7 * Fernando Perez
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2011 The IPython Development Team
12 # Copyright (C) 2008-2011 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License.
14 # Distributed under the terms of the BSD License.
15 #
15 #
16 # The full license is in the file COPYING.txt, distributed with this software.
16 # The full license is in the file COPYING.txt, distributed with this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import re
24 import re
25 import sys
25 import sys
26
26
27 from traitlets.config.configurable import Configurable
27 from traitlets.config.configurable import Configurable
28 from IPython.core.error import UsageError
28 from IPython.core.error import UsageError
29
29
30 from IPython.utils.py3compat import string_types
30 from IPython.utils.py3compat import string_types
31 from traitlets import List, Instance
31 from traitlets import List, Instance
32 from logging import error
32 from logging import error
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Utilities
35 # Utilities
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 # This is used as the pattern for calls to split_user_input.
38 # This is used as the pattern for calls to split_user_input.
39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
40
40
41 def default_aliases():
41 def default_aliases():
42 """Return list of shell aliases to auto-define.
42 """Return list of shell aliases to auto-define.
43 """
43 """
44 # Note: the aliases defined here should be safe to use on a kernel
44 # Note: the aliases defined here should be safe to use on a kernel
45 # regardless of what frontend it is attached to. Frontends that use a
45 # regardless of what frontend it is attached to. Frontends that use a
46 # kernel in-process can define additional aliases that will only work in
46 # kernel in-process can define additional aliases that will only work in
47 # their case. For example, things like 'less' or 'clear' that manipulate
47 # their case. For example, things like 'less' or 'clear' that manipulate
48 # the terminal should NOT be declared here, as they will only work if the
48 # the terminal should NOT be declared here, as they will only work if the
49 # kernel is running inside a true terminal, and not over the network.
49 # kernel is running inside a true terminal, and not over the network.
50
50
51 if os.name == 'posix':
51 if os.name == 'posix':
52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
54 ('cat', 'cat'),
54 ('cat', 'cat'),
55 ]
55 ]
56 # Useful set of ls aliases. The GNU and BSD options are a little
56 # Useful set of ls aliases. The GNU and BSD options are a little
57 # different, so we make aliases that provide as similar as possible
57 # different, so we make aliases that provide as similar as possible
58 # behavior in ipython, by passing the right flags for each platform
58 # behavior in ipython, by passing the right flags for each platform
59 if sys.platform.startswith('linux'):
59 if sys.platform.startswith('linux'):
60 ls_aliases = [('ls', 'ls -F --color'),
60 ls_aliases = [('ls', 'ls -F --color'),
61 # long ls
61 # long ls
62 ('ll', 'ls -F -o --color'),
62 ('ll', 'ls -F -o --color'),
63 # ls normal files only
63 # ls normal files only
64 ('lf', 'ls -F -o --color %l | grep ^-'),
64 ('lf', 'ls -F -o --color %l | grep ^-'),
65 # ls symbolic links
65 # ls symbolic links
66 ('lk', 'ls -F -o --color %l | grep ^l'),
66 ('lk', 'ls -F -o --color %l | grep ^l'),
67 # directories or links to directories,
67 # directories or links to directories,
68 ('ldir', 'ls -F -o --color %l | grep /$'),
68 ('ldir', 'ls -F -o --color %l | grep /$'),
69 # things which are executable
69 # things which are executable
70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
71 ]
71 ]
72 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
72 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
74 # the -G switch and lack the ability to use colorized output.
74 # the -G switch and lack the ability to use colorized output.
75 ls_aliases = [('ls', 'ls -F'),
75 ls_aliases = [('ls', 'ls -F'),
76 # long ls
76 # long ls
77 ('ll', 'ls -F -l'),
77 ('ll', 'ls -F -l'),
78 # ls normal files only
78 # ls normal files only
79 ('lf', 'ls -F -l %l | grep ^-'),
79 ('lf', 'ls -F -l %l | grep ^-'),
80 # ls symbolic links
80 # ls symbolic links
81 ('lk', 'ls -F -l %l | grep ^l'),
81 ('lk', 'ls -F -l %l | grep ^l'),
82 # directories or links to directories,
82 # directories or links to directories,
83 ('ldir', 'ls -F -l %l | grep /$'),
83 ('ldir', 'ls -F -l %l | grep /$'),
84 # things which are executable
84 # things which are executable
85 ('lx', 'ls -F -l %l | grep ^-..x'),
85 ('lx', 'ls -F -l %l | grep ^-..x'),
86 ]
86 ]
87 else:
87 else:
88 # BSD, OSX, etc.
88 # BSD, OSX, etc.
89 ls_aliases = [('ls', 'ls -F -G'),
89 ls_aliases = [('ls', 'ls -F -G'),
90 # long ls
90 # long ls
91 ('ll', 'ls -F -l -G'),
91 ('ll', 'ls -F -l -G'),
92 # ls normal files only
92 # ls normal files only
93 ('lf', 'ls -F -l -G %l | grep ^-'),
93 ('lf', 'ls -F -l -G %l | grep ^-'),
94 # ls symbolic links
94 # ls symbolic links
95 ('lk', 'ls -F -l -G %l | grep ^l'),
95 ('lk', 'ls -F -l -G %l | grep ^l'),
96 # directories or links to directories,
96 # directories or links to directories,
97 ('ldir', 'ls -F -G -l %l | grep /$'),
97 ('ldir', 'ls -F -G -l %l | grep /$'),
98 # things which are executable
98 # things which are executable
99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
100 ]
100 ]
101 default_aliases = default_aliases + ls_aliases
101 default_aliases = default_aliases + ls_aliases
102 elif os.name in ['nt', 'dos']:
102 elif os.name in ['nt', 'dos']:
103 default_aliases = [('ls', 'dir /on'),
103 default_aliases = [('ls', 'dir /on'),
104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
107 ]
107 ]
108 else:
108 else:
109 default_aliases = []
109 default_aliases = []
110
110
111 return default_aliases
111 return default_aliases
112
112
113
113
114 class AliasError(Exception):
114 class AliasError(Exception):
115 pass
115 pass
116
116
117
117
118 class InvalidAliasError(AliasError):
118 class InvalidAliasError(AliasError):
119 pass
119 pass
120
120
121 class Alias(object):
121 class Alias(object):
122 """Callable object storing the details of one alias.
122 """Callable object storing the details of one alias.
123
123
124 Instances are registered as magic functions to allow use of aliases.
124 Instances are registered as magic functions to allow use of aliases.
125 """
125 """
126
126
127 # Prepare blacklist
127 # Prepare blacklist
128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
129
129
130 def __init__(self, shell, name, cmd):
130 def __init__(self, shell, name, cmd):
131 self.shell = shell
131 self.shell = shell
132 self.name = name
132 self.name = name
133 self.cmd = cmd
133 self.cmd = cmd
134 self.__doc__ = "Alias for `!{}`".format(cmd)
134 self.__doc__ = "Alias for `!{}`".format(cmd)
135 self.nargs = self.validate()
135 self.nargs = self.validate()
136
136
137 def validate(self):
137 def validate(self):
138 """Validate the alias, and return the number of arguments."""
138 """Validate the alias, and return the number of arguments."""
139 if self.name in self.blacklist:
139 if self.name in self.blacklist:
140 raise InvalidAliasError("The name %s can't be aliased "
140 raise InvalidAliasError("The name %s can't be aliased "
141 "because it is a keyword or builtin." % self.name)
141 "because it is a keyword or builtin." % self.name)
142 try:
142 try:
143 caller = self.shell.magics_manager.magics['line'][self.name]
143 caller = self.shell.magics_manager.magics['line'][self.name]
144 except KeyError:
144 except KeyError:
145 pass
145 pass
146 else:
146 else:
147 if not isinstance(caller, Alias):
147 if not isinstance(caller, Alias):
148 raise InvalidAliasError("The name %s can't be aliased "
148 raise InvalidAliasError("The name %s can't be aliased "
149 "because it is another magic command." % self.name)
149 "because it is another magic command." % self.name)
150
150
151 if not (isinstance(self.cmd, string_types)):
151 if not (isinstance(self.cmd, string_types)):
152 raise InvalidAliasError("An alias command must be a string, "
152 raise InvalidAliasError("An alias command must be a string, "
153 "got: %r" % self.cmd)
153 "got: %r" % self.cmd)
154
154
155 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
155 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
156
156
157 if (nargs > 0) and (self.cmd.find('%l') >= 0):
157 if (nargs > 0) and (self.cmd.find('%l') >= 0):
158 raise InvalidAliasError('The %s and %l specifiers are mutually '
158 raise InvalidAliasError('The %s and %l specifiers are mutually '
159 'exclusive in alias definitions.')
159 'exclusive in alias definitions.')
160
160
161 return nargs
161 return nargs
162
162
163 def __repr__(self):
163 def __repr__(self):
164 return "<alias {} for {!r}>".format(self.name, self.cmd)
164 return "<alias {} for {!r}>".format(self.name, self.cmd)
165
165
166 def __call__(self, rest=''):
166 def __call__(self, rest=''):
167 cmd = self.cmd
167 cmd = self.cmd
168 nargs = self.nargs
168 nargs = self.nargs
169 # Expand the %l special to be the user's input line
169 # Expand the %l special to be the user's input line
170 if cmd.find('%l') >= 0:
170 if cmd.find('%l') >= 0:
171 cmd = cmd.replace('%l', rest)
171 cmd = cmd.replace('%l', rest)
172 rest = ''
172 rest = ''
173
173
174 if nargs==0:
174 if nargs==0:
175 if cmd.find('%%s') >= 1:
175 if cmd.find('%%s') >= 1:
176 cmd = cmd.replace('%%s', '%s')
176 cmd = cmd.replace('%%s', '%s')
177 # Simple, argument-less aliases
177 # Simple, argument-less aliases
178 cmd = '%s %s' % (cmd, rest)
178 cmd = '%s %s' % (cmd, rest)
179 else:
179 else:
180 # Handle aliases with positional arguments
180 # Handle aliases with positional arguments
181 args = rest.split(None, nargs)
181 args = rest.split(None, nargs)
182 if len(args) < nargs:
182 if len(args) < nargs:
183 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
183 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
184 (self.name, nargs, len(args)))
184 (self.name, nargs, len(args)))
185 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
185 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
186
186
187 self.shell.system(cmd)
187 self.shell.system(cmd)
188
188
189 #-----------------------------------------------------------------------------
189 #-----------------------------------------------------------------------------
190 # Main AliasManager class
190 # Main AliasManager class
191 #-----------------------------------------------------------------------------
191 #-----------------------------------------------------------------------------
192
192
193 class AliasManager(Configurable):
193 class AliasManager(Configurable):
194
194
195 default_aliases = List(default_aliases(), config=True)
195 default_aliases = List(default_aliases()).tag(config=True)
196 user_aliases = List(default_value=[], config=True)
196 user_aliases = List(default_value=[]).tag(config=True)
197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
198
198
199 def __init__(self, shell=None, **kwargs):
199 def __init__(self, shell=None, **kwargs):
200 super(AliasManager, self).__init__(shell=shell, **kwargs)
200 super(AliasManager, self).__init__(shell=shell, **kwargs)
201 # For convenient access
201 # For convenient access
202 self.linemagics = self.shell.magics_manager.magics['line']
202 self.linemagics = self.shell.magics_manager.magics['line']
203 self.init_aliases()
203 self.init_aliases()
204
204
205 def init_aliases(self):
205 def init_aliases(self):
206 # Load default & user aliases
206 # Load default & user aliases
207 for name, cmd in self.default_aliases + self.user_aliases:
207 for name, cmd in self.default_aliases + self.user_aliases:
208 self.soft_define_alias(name, cmd)
208 self.soft_define_alias(name, cmd)
209
209
210 @property
210 @property
211 def aliases(self):
211 def aliases(self):
212 return [(n, func.cmd) for (n, func) in self.linemagics.items()
212 return [(n, func.cmd) for (n, func) in self.linemagics.items()
213 if isinstance(func, Alias)]
213 if isinstance(func, Alias)]
214
214
215 def soft_define_alias(self, name, cmd):
215 def soft_define_alias(self, name, cmd):
216 """Define an alias, but don't raise on an AliasError."""
216 """Define an alias, but don't raise on an AliasError."""
217 try:
217 try:
218 self.define_alias(name, cmd)
218 self.define_alias(name, cmd)
219 except AliasError as e:
219 except AliasError as e:
220 error("Invalid alias: %s" % e)
220 error("Invalid alias: %s" % e)
221
221
222 def define_alias(self, name, cmd):
222 def define_alias(self, name, cmd):
223 """Define a new alias after validating it.
223 """Define a new alias after validating it.
224
224
225 This will raise an :exc:`AliasError` if there are validation
225 This will raise an :exc:`AliasError` if there are validation
226 problems.
226 problems.
227 """
227 """
228 caller = Alias(shell=self.shell, name=name, cmd=cmd)
228 caller = Alias(shell=self.shell, name=name, cmd=cmd)
229 self.shell.magics_manager.register_function(caller, magic_kind='line',
229 self.shell.magics_manager.register_function(caller, magic_kind='line',
230 magic_name=name)
230 magic_name=name)
231
231
232 def get_alias(self, name):
232 def get_alias(self, name):
233 """Return an alias, or None if no alias by that name exists."""
233 """Return an alias, or None if no alias by that name exists."""
234 aname = self.linemagics.get(name, None)
234 aname = self.linemagics.get(name, None)
235 return aname if isinstance(aname, Alias) else None
235 return aname if isinstance(aname, Alias) else None
236
236
237 def is_alias(self, name):
237 def is_alias(self, name):
238 """Return whether or not a given name has been defined as an alias"""
238 """Return whether or not a given name has been defined as an alias"""
239 return self.get_alias(name) is not None
239 return self.get_alias(name) is not None
240
240
241 def undefine_alias(self, name):
241 def undefine_alias(self, name):
242 if self.is_alias(name):
242 if self.is_alias(name):
243 del self.linemagics[name]
243 del self.linemagics[name]
244 else:
244 else:
245 raise ValueError('%s is not an alias' % name)
245 raise ValueError('%s is not an alias' % name)
246
246
247 def clear_aliases(self):
247 def clear_aliases(self):
248 for name, cmd in self.aliases:
248 for name, cmd in self.aliases:
249 self.undefine_alias(name)
249 self.undefine_alias(name)
250
250
251 def retrieve_alias(self, name):
251 def retrieve_alias(self, name):
252 """Retrieve the command to which an alias expands."""
252 """Retrieve the command to which an alias expands."""
253 caller = self.get_alias(name)
253 caller = self.get_alias(name)
254 if caller:
254 if caller:
255 return caller.cmd
255 return caller.cmd
256 else:
256 else:
257 raise ValueError('%s is not an alias' % name)
257 raise ValueError('%s is not an alias' % name)
@@ -1,407 +1,428 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for IPython.
3 An application for IPython.
4
4
5 All top-level applications should use the classes in this module for
5 All top-level applications should use the classes in this module for
6 handling configuration and creating configurables.
6 handling configuration and creating configurables.
7
7
8 The job of an :class:`Application` is to create the master configuration
8 The job of an :class:`Application` is to create the master configuration
9 object and then create the configurable objects, passing the config to them.
9 object and then create the configurable objects, passing the config to them.
10 """
10 """
11
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15 import atexit
15 import atexit
16 import glob
16 import glob
17 import logging
17 import logging
18 import os
18 import os
19 import shutil
19 import shutil
20 import sys
20 import sys
21
21
22 from traitlets.config.application import Application, catch_config_error
22 from traitlets.config.application import Application, catch_config_error
23 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
23 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
24 from IPython.core import release, crashhandler
24 from IPython.core import release, crashhandler
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
26 from IPython.paths import get_ipython_dir, get_ipython_package_dir
26 from IPython.paths import get_ipython_dir, get_ipython_package_dir
27 from IPython.utils.path import ensure_dir_exists
27 from IPython.utils.path import ensure_dir_exists
28 from IPython.utils import py3compat
28 from IPython.utils import py3compat
29 from traitlets import List, Unicode, Type, Bool, Dict, Set, Instance, Undefined
29 from traitlets import (
30 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
31 default, observe,
32 )
30
33
31 if os.name == 'nt':
34 if os.name == 'nt':
32 programdata = os.environ.get('PROGRAMDATA', None)
35 programdata = os.environ.get('PROGRAMDATA', None)
33 if programdata:
36 if programdata:
34 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
35 else: # PROGRAMDATA is not defined by default on XP.
38 else: # PROGRAMDATA is not defined by default on XP.
36 SYSTEM_CONFIG_DIRS = []
39 SYSTEM_CONFIG_DIRS = []
37 else:
40 else:
38 SYSTEM_CONFIG_DIRS = [
41 SYSTEM_CONFIG_DIRS = [
39 "/usr/local/etc/ipython",
42 "/usr/local/etc/ipython",
40 "/etc/ipython",
43 "/etc/ipython",
41 ]
44 ]
42
45
43
46
44 # aliases and flags
47 # aliases and flags
45
48
46 base_aliases = {
49 base_aliases = {
47 'profile-dir' : 'ProfileDir.location',
50 'profile-dir' : 'ProfileDir.location',
48 'profile' : 'BaseIPythonApplication.profile',
51 'profile' : 'BaseIPythonApplication.profile',
49 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
52 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
50 'log-level' : 'Application.log_level',
53 'log-level' : 'Application.log_level',
51 'config' : 'BaseIPythonApplication.extra_config_file',
54 'config' : 'BaseIPythonApplication.extra_config_file',
52 }
55 }
53
56
54 base_flags = dict(
57 base_flags = dict(
55 debug = ({'Application' : {'log_level' : logging.DEBUG}},
58 debug = ({'Application' : {'log_level' : logging.DEBUG}},
56 "set log level to logging.DEBUG (maximize logging output)"),
59 "set log level to logging.DEBUG (maximize logging output)"),
57 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
60 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
58 "set log level to logging.CRITICAL (minimize logging output)"),
61 "set log level to logging.CRITICAL (minimize logging output)"),
59 init = ({'BaseIPythonApplication' : {
62 init = ({'BaseIPythonApplication' : {
60 'copy_config_files' : True,
63 'copy_config_files' : True,
61 'auto_create' : True}
64 'auto_create' : True}
62 }, """Initialize profile with default config files. This is equivalent
65 }, """Initialize profile with default config files. This is equivalent
63 to running `ipython profile create <profile>` prior to startup.
66 to running `ipython profile create <profile>` prior to startup.
64 """)
67 """)
65 )
68 )
66
69
67 class ProfileAwareConfigLoader(PyFileConfigLoader):
70 class ProfileAwareConfigLoader(PyFileConfigLoader):
68 """A Python file config loader that is aware of IPython profiles."""
71 """A Python file config loader that is aware of IPython profiles."""
69 def load_subconfig(self, fname, path=None, profile=None):
72 def load_subconfig(self, fname, path=None, profile=None):
70 if profile is not None:
73 if profile is not None:
71 try:
74 try:
72 profile_dir = ProfileDir.find_profile_dir_by_name(
75 profile_dir = ProfileDir.find_profile_dir_by_name(
73 get_ipython_dir(),
76 get_ipython_dir(),
74 profile,
77 profile,
75 )
78 )
76 except ProfileDirError:
79 except ProfileDirError:
77 return
80 return
78 path = profile_dir.location
81 path = profile_dir.location
79 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
82 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
80
83
81 class BaseIPythonApplication(Application):
84 class BaseIPythonApplication(Application):
82
85
83 name = Unicode(u'ipython')
86 name = Unicode(u'ipython')
84 description = Unicode(u'IPython: an enhanced interactive Python shell.')
87 description = Unicode(u'IPython: an enhanced interactive Python shell.')
85 version = Unicode(release.version)
88 version = Unicode(release.version)
86
89
87 aliases = Dict(base_aliases)
90 aliases = Dict(base_aliases)
88 flags = Dict(base_flags)
91 flags = Dict(base_flags)
89 classes = List([ProfileDir])
92 classes = List([ProfileDir])
90
93
91 # enable `load_subconfig('cfg.py', profile='name')`
94 # enable `load_subconfig('cfg.py', profile='name')`
92 python_config_loader_class = ProfileAwareConfigLoader
95 python_config_loader_class = ProfileAwareConfigLoader
93
96
94 # Track whether the config_file has changed,
97 # Track whether the config_file has changed,
95 # because some logic happens only if we aren't using the default.
98 # because some logic happens only if we aren't using the default.
96 config_file_specified = Set()
99 config_file_specified = Set()
97
100
98 config_file_name = Unicode()
101 config_file_name = Unicode()
102 @default('config_file_name')
99 def _config_file_name_default(self):
103 def _config_file_name_default(self):
100 return self.name.replace('-','_') + u'_config.py'
104 return self.name.replace('-','_') + u'_config.py'
101 def _config_file_name_changed(self, name, old, new):
105 @observe('config_file_name')
102 if new != old:
106 def _config_file_name_changed(self, change):
103 self.config_file_specified.add(new)
107 if change['new'] != change['old']:
108 self.config_file_specified.add(change['new'])
104
109
105 # The directory that contains IPython's builtin profiles.
110 # The directory that contains IPython's builtin profiles.
106 builtin_profile_dir = Unicode(
111 builtin_profile_dir = Unicode(
107 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
112 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
108 )
113 )
109
114
110 config_file_paths = List(Unicode())
115 config_file_paths = List(Unicode())
116 @default('config_file_paths')
111 def _config_file_paths_default(self):
117 def _config_file_paths_default(self):
112 return [py3compat.getcwd()]
118 return [py3compat.getcwd()]
113
119
114 extra_config_file = Unicode(config=True,
120 extra_config_file = Unicode(
115 help="""Path to an extra config file to load.
121 help="""Path to an extra config file to load.
116
122
117 If specified, load this config file in addition to any other IPython config.
123 If specified, load this config file in addition to any other IPython config.
118 """)
124 """).tag(config=True)
119 def _extra_config_file_changed(self, name, old, new):
125 @observe('extra_config_file')
126 def _extra_config_file_changed(self, change):
127 old = change['old']
128 new = change['new']
120 try:
129 try:
121 self.config_files.remove(old)
130 self.config_files.remove(old)
122 except ValueError:
131 except ValueError:
123 pass
132 pass
124 self.config_file_specified.add(new)
133 self.config_file_specified.add(new)
125 self.config_files.append(new)
134 self.config_files.append(new)
126
135
127 profile = Unicode(u'default', config=True,
136 profile = Unicode(u'default',
128 help="""The IPython profile to use."""
137 help="""The IPython profile to use."""
129 )
138 ).tag(config=True)
130
139
131 def _profile_changed(self, name, old, new):
140 @observe('profile')
141 def _profile_changed(self, change):
132 self.builtin_profile_dir = os.path.join(
142 self.builtin_profile_dir = os.path.join(
133 get_ipython_package_dir(), u'config', u'profile', new
143 get_ipython_package_dir(), u'config', u'profile', change['new']
134 )
144 )
135
145
136 ipython_dir = Unicode(config=True,
146 ipython_dir = Unicode(
137 help="""
147 help="""
138 The name of the IPython directory. This directory is used for logging
148 The name of the IPython directory. This directory is used for logging
139 configuration (through profiles), history storage, etc. The default
149 configuration (through profiles), history storage, etc. The default
140 is usually $HOME/.ipython. This option can also be specified through
150 is usually $HOME/.ipython. This option can also be specified through
141 the environment variable IPYTHONDIR.
151 the environment variable IPYTHONDIR.
142 """
152 """
143 )
153 ).tag(config=True)
154 @default('ipython_dir')
144 def _ipython_dir_default(self):
155 def _ipython_dir_default(self):
145 d = get_ipython_dir()
156 d = get_ipython_dir()
146 self._ipython_dir_changed('ipython_dir', d, d)
157 self._ipython_dir_changed({
158 'name': 'ipython_dir',
159 'old': d,
160 'new': d,
161 })
147 return d
162 return d
148
163
149 _in_init_profile_dir = False
164 _in_init_profile_dir = False
150 profile_dir = Instance(ProfileDir, allow_none=True)
165 profile_dir = Instance(ProfileDir, allow_none=True)
166 @default('profile_dir')
151 def _profile_dir_default(self):
167 def _profile_dir_default(self):
152 # avoid recursion
168 # avoid recursion
153 if self._in_init_profile_dir:
169 if self._in_init_profile_dir:
154 return
170 return
155 # profile_dir requested early, force initialization
171 # profile_dir requested early, force initialization
156 self.init_profile_dir()
172 self.init_profile_dir()
157 return self.profile_dir
173 return self.profile_dir
158
174
159 overwrite = Bool(False, config=True,
175 overwrite = Bool(False,
160 help="""Whether to overwrite existing config files when copying""")
176 help="""Whether to overwrite existing config files when copying"""
161 auto_create = Bool(False, config=True,
177 ).tag(config=True)
162 help="""Whether to create profile dir if it doesn't exist""")
178 auto_create = Bool(False,
179 help="""Whether to create profile dir if it doesn't exist"""
180 ).tag(config=True)
163
181
164 config_files = List(Unicode())
182 config_files = List(Unicode())
183 @default('config_files')
165 def _config_files_default(self):
184 def _config_files_default(self):
166 return [self.config_file_name]
185 return [self.config_file_name]
167
186
168 copy_config_files = Bool(False, config=True,
187 copy_config_files = Bool(False,
169 help="""Whether to install the default config files into the profile dir.
188 help="""Whether to install the default config files into the profile dir.
170 If a new profile is being created, and IPython contains config files for that
189 If a new profile is being created, and IPython contains config files for that
171 profile, then they will be staged into the new directory. Otherwise,
190 profile, then they will be staged into the new directory. Otherwise,
172 default config files will be automatically generated.
191 default config files will be automatically generated.
173 """)
192 """).tag(config=True)
174
193
175 verbose_crash = Bool(False, config=True,
194 verbose_crash = Bool(False,
176 help="""Create a massive crash report when IPython encounters what may be an
195 help="""Create a massive crash report when IPython encounters what may be an
177 internal error. The default is to append a short message to the
196 internal error. The default is to append a short message to the
178 usual traceback""")
197 usual traceback""").tag(config=True)
179
198
180 # The class to use as the crash handler.
199 # The class to use as the crash handler.
181 crash_handler_class = Type(crashhandler.CrashHandler)
200 crash_handler_class = Type(crashhandler.CrashHandler)
182
201
183 @catch_config_error
202 @catch_config_error
184 def __init__(self, **kwargs):
203 def __init__(self, **kwargs):
185 super(BaseIPythonApplication, self).__init__(**kwargs)
204 super(BaseIPythonApplication, self).__init__(**kwargs)
186 # ensure current working directory exists
205 # ensure current working directory exists
187 try:
206 try:
188 py3compat.getcwd()
207 py3compat.getcwd()
189 except:
208 except:
190 # exit if cwd doesn't exist
209 # exit if cwd doesn't exist
191 self.log.error("Current working directory doesn't exist.")
210 self.log.error("Current working directory doesn't exist.")
192 self.exit(1)
211 self.exit(1)
193
212
194 #-------------------------------------------------------------------------
213 #-------------------------------------------------------------------------
195 # Various stages of Application creation
214 # Various stages of Application creation
196 #-------------------------------------------------------------------------
215 #-------------------------------------------------------------------------
197
216
198 deprecated_subcommands = {}
217 deprecated_subcommands = {}
199
218
200 def initialize_subcommand(self, subc, argv=None):
219 def initialize_subcommand(self, subc, argv=None):
201 if subc in self.deprecated_subcommands:
220 if subc in self.deprecated_subcommands:
202 import time
203 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
221 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
204 "in future versions.".format(sub=subc))
222 "in future versions.".format(sub=subc))
205 self.log.warning("You likely want to use `jupyter {sub}` in the "
223 self.log.warning("You likely want to use `jupyter {sub}` in the "
206 "future".format(sub=subc))
224 "future".format(sub=subc))
207 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
225 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
208
226
209 def init_crash_handler(self):
227 def init_crash_handler(self):
210 """Create a crash handler, typically setting sys.excepthook to it."""
228 """Create a crash handler, typically setting sys.excepthook to it."""
211 self.crash_handler = self.crash_handler_class(self)
229 self.crash_handler = self.crash_handler_class(self)
212 sys.excepthook = self.excepthook
230 sys.excepthook = self.excepthook
213 def unset_crashhandler():
231 def unset_crashhandler():
214 sys.excepthook = sys.__excepthook__
232 sys.excepthook = sys.__excepthook__
215 atexit.register(unset_crashhandler)
233 atexit.register(unset_crashhandler)
216
234
217 def excepthook(self, etype, evalue, tb):
235 def excepthook(self, etype, evalue, tb):
218 """this is sys.excepthook after init_crashhandler
236 """this is sys.excepthook after init_crashhandler
219
237
220 set self.verbose_crash=True to use our full crashhandler, instead of
238 set self.verbose_crash=True to use our full crashhandler, instead of
221 a regular traceback with a short message (crash_handler_lite)
239 a regular traceback with a short message (crash_handler_lite)
222 """
240 """
223
241
224 if self.verbose_crash:
242 if self.verbose_crash:
225 return self.crash_handler(etype, evalue, tb)
243 return self.crash_handler(etype, evalue, tb)
226 else:
244 else:
227 return crashhandler.crash_handler_lite(etype, evalue, tb)
245 return crashhandler.crash_handler_lite(etype, evalue, tb)
228
246
229 def _ipython_dir_changed(self, name, old, new):
247 @observe('ipython_dir')
248 def _ipython_dir_changed(self, change):
249 old = change['old']
250 new = change['new']
230 if old is not Undefined:
251 if old is not Undefined:
231 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
252 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
232 sys.getfilesystemencoding()
253 sys.getfilesystemencoding()
233 )
254 )
234 if str_old in sys.path:
255 if str_old in sys.path:
235 sys.path.remove(str_old)
256 sys.path.remove(str_old)
236 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
257 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
237 sys.getfilesystemencoding()
258 sys.getfilesystemencoding()
238 )
259 )
239 sys.path.append(str_path)
260 sys.path.append(str_path)
240 ensure_dir_exists(new)
261 ensure_dir_exists(new)
241 readme = os.path.join(new, 'README')
262 readme = os.path.join(new, 'README')
242 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
263 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
243 if not os.path.exists(readme) and os.path.exists(readme_src):
264 if not os.path.exists(readme) and os.path.exists(readme_src):
244 shutil.copy(readme_src, readme)
265 shutil.copy(readme_src, readme)
245 for d in ('extensions', 'nbextensions'):
266 for d in ('extensions', 'nbextensions'):
246 path = os.path.join(new, d)
267 path = os.path.join(new, d)
247 try:
268 try:
248 ensure_dir_exists(path)
269 ensure_dir_exists(path)
249 except OSError as e:
270 except OSError as e:
250 # this will not be EEXIST
271 # this will not be EEXIST
251 self.log.error("couldn't create path %s: %s", path, e)
272 self.log.error("couldn't create path %s: %s", path, e)
252 self.log.debug("IPYTHONDIR set to: %s" % new)
273 self.log.debug("IPYTHONDIR set to: %s" % new)
253
274
254 def load_config_file(self, suppress_errors=True):
275 def load_config_file(self, suppress_errors=True):
255 """Load the config file.
276 """Load the config file.
256
277
257 By default, errors in loading config are handled, and a warning
278 By default, errors in loading config are handled, and a warning
258 printed on screen. For testing, the suppress_errors option is set
279 printed on screen. For testing, the suppress_errors option is set
259 to False, so errors will make tests fail.
280 to False, so errors will make tests fail.
260 """
281 """
261 self.log.debug("Searching path %s for config files", self.config_file_paths)
282 self.log.debug("Searching path %s for config files", self.config_file_paths)
262 base_config = 'ipython_config.py'
283 base_config = 'ipython_config.py'
263 self.log.debug("Attempting to load config file: %s" %
284 self.log.debug("Attempting to load config file: %s" %
264 base_config)
285 base_config)
265 try:
286 try:
266 Application.load_config_file(
287 Application.load_config_file(
267 self,
288 self,
268 base_config,
289 base_config,
269 path=self.config_file_paths
290 path=self.config_file_paths
270 )
291 )
271 except ConfigFileNotFound:
292 except ConfigFileNotFound:
272 # ignore errors loading parent
293 # ignore errors loading parent
273 self.log.debug("Config file %s not found", base_config)
294 self.log.debug("Config file %s not found", base_config)
274 pass
295 pass
275
296
276 for config_file_name in self.config_files:
297 for config_file_name in self.config_files:
277 if not config_file_name or config_file_name == base_config:
298 if not config_file_name or config_file_name == base_config:
278 continue
299 continue
279 self.log.debug("Attempting to load config file: %s" %
300 self.log.debug("Attempting to load config file: %s" %
280 self.config_file_name)
301 self.config_file_name)
281 try:
302 try:
282 Application.load_config_file(
303 Application.load_config_file(
283 self,
304 self,
284 config_file_name,
305 config_file_name,
285 path=self.config_file_paths
306 path=self.config_file_paths
286 )
307 )
287 except ConfigFileNotFound:
308 except ConfigFileNotFound:
288 # Only warn if the default config file was NOT being used.
309 # Only warn if the default config file was NOT being used.
289 if config_file_name in self.config_file_specified:
310 if config_file_name in self.config_file_specified:
290 msg = self.log.warning
311 msg = self.log.warning
291 else:
312 else:
292 msg = self.log.debug
313 msg = self.log.debug
293 msg("Config file not found, skipping: %s", config_file_name)
314 msg("Config file not found, skipping: %s", config_file_name)
294 except Exception:
315 except Exception:
295 # For testing purposes.
316 # For testing purposes.
296 if not suppress_errors:
317 if not suppress_errors:
297 raise
318 raise
298 self.log.warning("Error loading config file: %s" %
319 self.log.warning("Error loading config file: %s" %
299 self.config_file_name, exc_info=True)
320 self.config_file_name, exc_info=True)
300
321
301 def init_profile_dir(self):
322 def init_profile_dir(self):
302 """initialize the profile dir"""
323 """initialize the profile dir"""
303 self._in_init_profile_dir = True
324 self._in_init_profile_dir = True
304 if self.profile_dir is not None:
325 if self.profile_dir is not None:
305 # already ran
326 # already ran
306 return
327 return
307 if 'ProfileDir.location' not in self.config:
328 if 'ProfileDir.location' not in self.config:
308 # location not specified, find by profile name
329 # location not specified, find by profile name
309 try:
330 try:
310 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
331 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
311 except ProfileDirError:
332 except ProfileDirError:
312 # not found, maybe create it (always create default profile)
333 # not found, maybe create it (always create default profile)
313 if self.auto_create or self.profile == 'default':
334 if self.auto_create or self.profile == 'default':
314 try:
335 try:
315 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
336 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
316 except ProfileDirError:
337 except ProfileDirError:
317 self.log.fatal("Could not create profile: %r"%self.profile)
338 self.log.fatal("Could not create profile: %r"%self.profile)
318 self.exit(1)
339 self.exit(1)
319 else:
340 else:
320 self.log.info("Created profile dir: %r"%p.location)
341 self.log.info("Created profile dir: %r"%p.location)
321 else:
342 else:
322 self.log.fatal("Profile %r not found."%self.profile)
343 self.log.fatal("Profile %r not found."%self.profile)
323 self.exit(1)
344 self.exit(1)
324 else:
345 else:
325 self.log.debug("Using existing profile dir: %r"%p.location)
346 self.log.debug("Using existing profile dir: %r"%p.location)
326 else:
347 else:
327 location = self.config.ProfileDir.location
348 location = self.config.ProfileDir.location
328 # location is fully specified
349 # location is fully specified
329 try:
350 try:
330 p = ProfileDir.find_profile_dir(location, self.config)
351 p = ProfileDir.find_profile_dir(location, self.config)
331 except ProfileDirError:
352 except ProfileDirError:
332 # not found, maybe create it
353 # not found, maybe create it
333 if self.auto_create:
354 if self.auto_create:
334 try:
355 try:
335 p = ProfileDir.create_profile_dir(location, self.config)
356 p = ProfileDir.create_profile_dir(location, self.config)
336 except ProfileDirError:
357 except ProfileDirError:
337 self.log.fatal("Could not create profile directory: %r"%location)
358 self.log.fatal("Could not create profile directory: %r"%location)
338 self.exit(1)
359 self.exit(1)
339 else:
360 else:
340 self.log.debug("Creating new profile dir: %r"%location)
361 self.log.debug("Creating new profile dir: %r"%location)
341 else:
362 else:
342 self.log.fatal("Profile directory %r not found."%location)
363 self.log.fatal("Profile directory %r not found."%location)
343 self.exit(1)
364 self.exit(1)
344 else:
365 else:
345 self.log.info("Using existing profile dir: %r"%location)
366 self.log.info("Using existing profile dir: %r"%location)
346 # if profile_dir is specified explicitly, set profile name
367 # if profile_dir is specified explicitly, set profile name
347 dir_name = os.path.basename(p.location)
368 dir_name = os.path.basename(p.location)
348 if dir_name.startswith('profile_'):
369 if dir_name.startswith('profile_'):
349 self.profile = dir_name[8:]
370 self.profile = dir_name[8:]
350
371
351 self.profile_dir = p
372 self.profile_dir = p
352 self.config_file_paths.append(p.location)
373 self.config_file_paths.append(p.location)
353 self._in_init_profile_dir = False
374 self._in_init_profile_dir = False
354
375
355 def init_config_files(self):
376 def init_config_files(self):
356 """[optionally] copy default config files into profile dir."""
377 """[optionally] copy default config files into profile dir."""
357 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
378 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
358 # copy config files
379 # copy config files
359 path = self.builtin_profile_dir
380 path = self.builtin_profile_dir
360 if self.copy_config_files:
381 if self.copy_config_files:
361 src = self.profile
382 src = self.profile
362
383
363 cfg = self.config_file_name
384 cfg = self.config_file_name
364 if path and os.path.exists(os.path.join(path, cfg)):
385 if path and os.path.exists(os.path.join(path, cfg)):
365 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
386 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
366 cfg, src, self.profile_dir.location, self.overwrite)
387 cfg, src, self.profile_dir.location, self.overwrite)
367 )
388 )
368 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
389 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
369 else:
390 else:
370 self.stage_default_config_file()
391 self.stage_default_config_file()
371 else:
392 else:
372 # Still stage *bundled* config files, but not generated ones
393 # Still stage *bundled* config files, but not generated ones
373 # This is necessary for `ipython profile=sympy` to load the profile
394 # This is necessary for `ipython profile=sympy` to load the profile
374 # on the first go
395 # on the first go
375 files = glob.glob(os.path.join(path, '*.py'))
396 files = glob.glob(os.path.join(path, '*.py'))
376 for fullpath in files:
397 for fullpath in files:
377 cfg = os.path.basename(fullpath)
398 cfg = os.path.basename(fullpath)
378 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
399 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
379 # file was copied
400 # file was copied
380 self.log.warning("Staging bundled %s from %s into %r"%(
401 self.log.warning("Staging bundled %s from %s into %r"%(
381 cfg, self.profile, self.profile_dir.location)
402 cfg, self.profile, self.profile_dir.location)
382 )
403 )
383
404
384
405
385 def stage_default_config_file(self):
406 def stage_default_config_file(self):
386 """auto generate default config file, and stage it into the profile."""
407 """auto generate default config file, and stage it into the profile."""
387 s = self.generate_config_file()
408 s = self.generate_config_file()
388 fname = os.path.join(self.profile_dir.location, self.config_file_name)
409 fname = os.path.join(self.profile_dir.location, self.config_file_name)
389 if self.overwrite or not os.path.exists(fname):
410 if self.overwrite or not os.path.exists(fname):
390 self.log.warning("Generating default config file: %r"%(fname))
411 self.log.warning("Generating default config file: %r"%(fname))
391 with open(fname, 'w') as f:
412 with open(fname, 'w') as f:
392 f.write(s)
413 f.write(s)
393
414
394 @catch_config_error
415 @catch_config_error
395 def initialize(self, argv=None):
416 def initialize(self, argv=None):
396 # don't hook up crash handler before parsing command-line
417 # don't hook up crash handler before parsing command-line
397 self.parse_command_line(argv)
418 self.parse_command_line(argv)
398 self.init_crash_handler()
419 self.init_crash_handler()
399 if self.subapp is not None:
420 if self.subapp is not None:
400 # stop here if subapp is taking over
421 # stop here if subapp is taking over
401 return
422 return
402 cl_config = self.config
423 cl_config = self.config
403 self.init_profile_dir()
424 self.init_profile_dir()
404 self.init_config_files()
425 self.init_config_files()
405 self.load_config_file()
426 self.load_config_file()
406 # enforce cl-opts override configfile opts:
427 # enforce cl-opts override configfile opts:
407 self.update_config(cl_config)
428 self.update_config(cl_config)
@@ -1,1325 +1,1325 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 from __future__ import print_function
56 from __future__ import print_function
57
57
58 import __main__
58 import __main__
59 import glob
59 import glob
60 import inspect
60 import inspect
61 import itertools
61 import itertools
62 import keyword
62 import keyword
63 import os
63 import os
64 import re
64 import re
65 import sys
65 import sys
66 import unicodedata
66 import unicodedata
67 import string
67 import string
68
68
69 from traitlets.config.configurable import Configurable
69 from traitlets.config.configurable import Configurable
70 from IPython.core.error import TryNext
70 from IPython.core.error import TryNext
71 from IPython.core.inputsplitter import ESC_MAGIC
71 from IPython.core.inputsplitter import ESC_MAGIC
72 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
72 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
73 from IPython.utils import generics
73 from IPython.utils import generics
74 from IPython.utils.decorators import undoc
74 from IPython.utils.decorators import undoc
75 from IPython.utils.dir2 import dir2, get_real_method
75 from IPython.utils.dir2 import dir2, get_real_method
76 from IPython.utils.process import arg_split
76 from IPython.utils.process import arg_split
77 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
77 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
78 from traitlets import CBool, Enum
78 from traitlets import Bool, Enum, observe
79
79
80 import jedi
80 import jedi
81 import jedi.api.helpers
81 import jedi.api.helpers
82 import jedi.parser.user_context
82 import jedi.parser.user_context
83
83
84 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
85 # Globals
85 # Globals
86 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
87
87
88 # Public API
88 # Public API
89 __all__ = ['Completer','IPCompleter']
89 __all__ = ['Completer','IPCompleter']
90
90
91 if sys.platform == 'win32':
91 if sys.platform == 'win32':
92 PROTECTABLES = ' '
92 PROTECTABLES = ' '
93 else:
93 else:
94 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
94 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
95
95
96
96
97 #-----------------------------------------------------------------------------
97 #-----------------------------------------------------------------------------
98 # Main functions and classes
98 # Main functions and classes
99 #-----------------------------------------------------------------------------
99 #-----------------------------------------------------------------------------
100
100
101 def has_open_quotes(s):
101 def has_open_quotes(s):
102 """Return whether a string has open quotes.
102 """Return whether a string has open quotes.
103
103
104 This simply counts whether the number of quote characters of either type in
104 This simply counts whether the number of quote characters of either type in
105 the string is odd.
105 the string is odd.
106
106
107 Returns
107 Returns
108 -------
108 -------
109 If there is an open quote, the quote character is returned. Else, return
109 If there is an open quote, the quote character is returned. Else, return
110 False.
110 False.
111 """
111 """
112 # We check " first, then ', so complex cases with nested quotes will get
112 # We check " first, then ', so complex cases with nested quotes will get
113 # the " to take precedence.
113 # the " to take precedence.
114 if s.count('"') % 2:
114 if s.count('"') % 2:
115 return '"'
115 return '"'
116 elif s.count("'") % 2:
116 elif s.count("'") % 2:
117 return "'"
117 return "'"
118 else:
118 else:
119 return False
119 return False
120
120
121
121
122 def protect_filename(s):
122 def protect_filename(s):
123 """Escape a string to protect certain characters."""
123 """Escape a string to protect certain characters."""
124
124
125 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
125 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
126 for ch in s])
126 for ch in s])
127
127
128 def expand_user(path):
128 def expand_user(path):
129 """Expand '~'-style usernames in strings.
129 """Expand '~'-style usernames in strings.
130
130
131 This is similar to :func:`os.path.expanduser`, but it computes and returns
131 This is similar to :func:`os.path.expanduser`, but it computes and returns
132 extra information that will be useful if the input was being used in
132 extra information that will be useful if the input was being used in
133 computing completions, and you wish to return the completions with the
133 computing completions, and you wish to return the completions with the
134 original '~' instead of its expanded value.
134 original '~' instead of its expanded value.
135
135
136 Parameters
136 Parameters
137 ----------
137 ----------
138 path : str
138 path : str
139 String to be expanded. If no ~ is present, the output is the same as the
139 String to be expanded. If no ~ is present, the output is the same as the
140 input.
140 input.
141
141
142 Returns
142 Returns
143 -------
143 -------
144 newpath : str
144 newpath : str
145 Result of ~ expansion in the input path.
145 Result of ~ expansion in the input path.
146 tilde_expand : bool
146 tilde_expand : bool
147 Whether any expansion was performed or not.
147 Whether any expansion was performed or not.
148 tilde_val : str
148 tilde_val : str
149 The value that ~ was replaced with.
149 The value that ~ was replaced with.
150 """
150 """
151 # Default values
151 # Default values
152 tilde_expand = False
152 tilde_expand = False
153 tilde_val = ''
153 tilde_val = ''
154 newpath = path
154 newpath = path
155
155
156 if path.startswith('~'):
156 if path.startswith('~'):
157 tilde_expand = True
157 tilde_expand = True
158 rest = len(path)-1
158 rest = len(path)-1
159 newpath = os.path.expanduser(path)
159 newpath = os.path.expanduser(path)
160 if rest:
160 if rest:
161 tilde_val = newpath[:-rest]
161 tilde_val = newpath[:-rest]
162 else:
162 else:
163 tilde_val = newpath
163 tilde_val = newpath
164
164
165 return newpath, tilde_expand, tilde_val
165 return newpath, tilde_expand, tilde_val
166
166
167
167
168 def compress_user(path, tilde_expand, tilde_val):
168 def compress_user(path, tilde_expand, tilde_val):
169 """Does the opposite of expand_user, with its outputs.
169 """Does the opposite of expand_user, with its outputs.
170 """
170 """
171 if tilde_expand:
171 if tilde_expand:
172 return path.replace(tilde_val, '~')
172 return path.replace(tilde_val, '~')
173 else:
173 else:
174 return path
174 return path
175
175
176
176
177
178 def completions_sorting_key(word):
177 def completions_sorting_key(word):
179 """key for sorting completions
178 """key for sorting completions
180
179
181 This does several things:
180 This does several things:
182
181
183 - Lowercase all completions, so they are sorted alphabetically with
182 - Lowercase all completions, so they are sorted alphabetically with
184 upper and lower case words mingled
183 upper and lower case words mingled
185 - Demote any completions starting with underscores to the end
184 - Demote any completions starting with underscores to the end
186 - Insert any %magic and %%cellmagic completions in the alphabetical order
185 - Insert any %magic and %%cellmagic completions in the alphabetical order
187 by their name
186 by their name
188 """
187 """
189 # Case insensitive sort
188 # Case insensitive sort
190 word = word.lower()
189 word = word.lower()
191
190
192 prio1, prio2 = 0, 0
191 prio1, prio2 = 0, 0
193
192
194 if word.startswith('__'):
193 if word.startswith('__'):
195 prio1 = 2
194 prio1 = 2
196 elif word.startswith('_'):
195 elif word.startswith('_'):
197 prio1 = 1
196 prio1 = 1
198
197
199 if word.endswith('='):
198 if word.endswith('='):
200 prio1 = -1
199 prio1 = -1
201
200
202 if word.startswith('%%'):
201 if word.startswith('%%'):
203 # If there's another % in there, this is something else, so leave it alone
202 # If there's another % in there, this is something else, so leave it alone
204 if not "%" in word[2:]:
203 if not "%" in word[2:]:
205 word = word[2:]
204 word = word[2:]
206 prio2 = 2
205 prio2 = 2
207 elif word.startswith('%'):
206 elif word.startswith('%'):
208 if not "%" in word[1:]:
207 if not "%" in word[1:]:
209 word = word[1:]
208 word = word[1:]
210 prio2 = 1
209 prio2 = 1
211
210
212 return prio1, word, prio2
211 return prio1, word, prio2
213
212
214
213
215 @undoc
214 @undoc
216 class Bunch(object): pass
215 class Bunch(object): pass
217
216
218
217
219 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
218 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
220 GREEDY_DELIMS = ' =\r\n'
219 GREEDY_DELIMS = ' =\r\n'
221
220
222
221
223 class CompletionSplitter(object):
222 class CompletionSplitter(object):
224 """An object to split an input line in a manner similar to readline.
223 """An object to split an input line in a manner similar to readline.
225
224
226 By having our own implementation, we can expose readline-like completion in
225 By having our own implementation, we can expose readline-like completion in
227 a uniform manner to all frontends. This object only needs to be given the
226 a uniform manner to all frontends. This object only needs to be given the
228 line of text to be split and the cursor position on said line, and it
227 line of text to be split and the cursor position on said line, and it
229 returns the 'word' to be completed on at the cursor after splitting the
228 returns the 'word' to be completed on at the cursor after splitting the
230 entire line.
229 entire line.
231
230
232 What characters are used as splitting delimiters can be controlled by
231 What characters are used as splitting delimiters can be controlled by
233 setting the `delims` attribute (this is a property that internally
232 setting the `delims` attribute (this is a property that internally
234 automatically builds the necessary regular expression)"""
233 automatically builds the necessary regular expression)"""
235
234
236 # Private interface
235 # Private interface
237
236
238 # A string of delimiter characters. The default value makes sense for
237 # A string of delimiter characters. The default value makes sense for
239 # IPython's most typical usage patterns.
238 # IPython's most typical usage patterns.
240 _delims = DELIMS
239 _delims = DELIMS
241
240
242 # The expression (a normal string) to be compiled into a regular expression
241 # The expression (a normal string) to be compiled into a regular expression
243 # for actual splitting. We store it as an attribute mostly for ease of
242 # for actual splitting. We store it as an attribute mostly for ease of
244 # debugging, since this type of code can be so tricky to debug.
243 # debugging, since this type of code can be so tricky to debug.
245 _delim_expr = None
244 _delim_expr = None
246
245
247 # The regular expression that does the actual splitting
246 # The regular expression that does the actual splitting
248 _delim_re = None
247 _delim_re = None
249
248
250 def __init__(self, delims=None):
249 def __init__(self, delims=None):
251 delims = CompletionSplitter._delims if delims is None else delims
250 delims = CompletionSplitter._delims if delims is None else delims
252 self.delims = delims
251 self.delims = delims
253
252
254 @property
253 @property
255 def delims(self):
254 def delims(self):
256 """Return the string of delimiter characters."""
255 """Return the string of delimiter characters."""
257 return self._delims
256 return self._delims
258
257
259 @delims.setter
258 @delims.setter
260 def delims(self, delims):
259 def delims(self, delims):
261 """Set the delimiters for line splitting."""
260 """Set the delimiters for line splitting."""
262 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
261 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
263 self._delim_re = re.compile(expr)
262 self._delim_re = re.compile(expr)
264 self._delims = delims
263 self._delims = delims
265 self._delim_expr = expr
264 self._delim_expr = expr
266
265
267 def split_line(self, line, cursor_pos=None):
266 def split_line(self, line, cursor_pos=None):
268 """Split a line of text with a cursor at the given position.
267 """Split a line of text with a cursor at the given position.
269 """
268 """
270 l = line if cursor_pos is None else line[:cursor_pos]
269 l = line if cursor_pos is None else line[:cursor_pos]
271 return self._delim_re.split(l)[-1]
270 return self._delim_re.split(l)[-1]
272
271
273
272
274 class Completer(Configurable):
273 class Completer(Configurable):
275
274
276 greedy = CBool(False, config=True,
275 greedy = Bool(False,
277 help="""Activate greedy completion
276 help="""Activate greedy completion
278 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
277 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
279
278
280 This will enable completion on elements of lists, results of function calls, etc.,
279 This will enable completion on elements of lists, results of function calls, etc.,
281 but can be unsafe because the code is actually evaluated on TAB.
280 but can be unsafe because the code is actually evaluated on TAB.
282 """
281 """
283 )
282 ).tag(config=True)
284
283
285
284
286 def __init__(self, namespace=None, global_namespace=None, **kwargs):
285 def __init__(self, namespace=None, global_namespace=None, **kwargs):
287 """Create a new completer for the command line.
286 """Create a new completer for the command line.
288
287
289 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
288 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
290
289
291 If unspecified, the default namespace where completions are performed
290 If unspecified, the default namespace where completions are performed
292 is __main__ (technically, __main__.__dict__). Namespaces should be
291 is __main__ (technically, __main__.__dict__). Namespaces should be
293 given as dictionaries.
292 given as dictionaries.
294
293
295 An optional second namespace can be given. This allows the completer
294 An optional second namespace can be given. This allows the completer
296 to handle cases where both the local and global scopes need to be
295 to handle cases where both the local and global scopes need to be
297 distinguished.
296 distinguished.
298
297
299 Completer instances should be used as the completion mechanism of
298 Completer instances should be used as the completion mechanism of
300 readline via the set_completer() call:
299 readline via the set_completer() call:
301
300
302 readline.set_completer(Completer(my_namespace).complete)
301 readline.set_completer(Completer(my_namespace).complete)
303 """
302 """
304
303
305 # Don't bind to namespace quite yet, but flag whether the user wants a
304 # Don't bind to namespace quite yet, but flag whether the user wants a
306 # specific namespace or to use __main__.__dict__. This will allow us
305 # specific namespace or to use __main__.__dict__. This will allow us
307 # to bind to __main__.__dict__ at completion time, not now.
306 # to bind to __main__.__dict__ at completion time, not now.
308 if namespace is None:
307 if namespace is None:
309 self.use_main_ns = 1
308 self.use_main_ns = 1
310 else:
309 else:
311 self.use_main_ns = 0
310 self.use_main_ns = 0
312 self.namespace = namespace
311 self.namespace = namespace
313
312
314 # The global namespace, if given, can be bound directly
313 # The global namespace, if given, can be bound directly
315 if global_namespace is None:
314 if global_namespace is None:
316 self.global_namespace = {}
315 self.global_namespace = {}
317 else:
316 else:
318 self.global_namespace = global_namespace
317 self.global_namespace = global_namespace
319
318
320 super(Completer, self).__init__(**kwargs)
319 super(Completer, self).__init__(**kwargs)
321
320
322 def complete(self, text, state):
321 def complete(self, text, state):
323 """Return the next possible completion for 'text'.
322 """Return the next possible completion for 'text'.
324
323
325 This is called successively with state == 0, 1, 2, ... until it
324 This is called successively with state == 0, 1, 2, ... until it
326 returns None. The completion should begin with 'text'.
325 returns None. The completion should begin with 'text'.
327
326
328 """
327 """
329 if self.use_main_ns:
328 if self.use_main_ns:
330 self.namespace = __main__.__dict__
329 self.namespace = __main__.__dict__
331
330
332 if state == 0:
331 if state == 0:
333 if "." in text:
332 if "." in text:
334 self.matches = self.attr_matches(text)
333 self.matches = self.attr_matches(text)
335 else:
334 else:
336 self.matches = self.global_matches(text)
335 self.matches = self.global_matches(text)
337 try:
336 try:
338 return self.matches[state]
337 return self.matches[state]
339 except IndexError:
338 except IndexError:
340 return None
339 return None
341
340
342 def global_matches(self, text):
341 def global_matches(self, text):
343 """Compute matches when text is a simple name.
342 """Compute matches when text is a simple name.
344
343
345 Return a list of all keywords, built-in functions and names currently
344 Return a list of all keywords, built-in functions and names currently
346 defined in self.namespace or self.global_namespace that match.
345 defined in self.namespace or self.global_namespace that match.
347
346
348 """
347 """
349 matches = []
348 matches = []
350 match_append = matches.append
349 match_append = matches.append
351 n = len(text)
350 n = len(text)
352 for lst in [keyword.kwlist,
351 for lst in [keyword.kwlist,
353 builtin_mod.__dict__.keys(),
352 builtin_mod.__dict__.keys(),
354 self.namespace.keys(),
353 self.namespace.keys(),
355 self.global_namespace.keys()]:
354 self.global_namespace.keys()]:
356 for word in lst:
355 for word in lst:
357 if word[:n] == text and word != "__builtins__":
356 if word[:n] == text and word != "__builtins__":
358 match_append(word)
357 match_append(word)
359 return [cast_unicode_py2(m) for m in matches]
358 return [cast_unicode_py2(m) for m in matches]
360
359
361 def attr_matches(self, text):
360 def attr_matches(self, text):
362 """Compute matches when text contains a dot.
361 """Compute matches when text contains a dot.
363
362
364 Assuming the text is of the form NAME.NAME....[NAME], and is
363 Assuming the text is of the form NAME.NAME....[NAME], and is
365 evaluatable in self.namespace or self.global_namespace, it will be
364 evaluatable in self.namespace or self.global_namespace, it will be
366 evaluated and its attributes (as revealed by dir()) are used as
365 evaluated and its attributes (as revealed by dir()) are used as
367 possible completions. (For class instances, class members are are
366 possible completions. (For class instances, class members are are
368 also considered.)
367 also considered.)
369
368
370 WARNING: this can still invoke arbitrary C code, if an object
369 WARNING: this can still invoke arbitrary C code, if an object
371 with a __getattr__ hook is evaluated.
370 with a __getattr__ hook is evaluated.
372
371
373 """
372 """
374
373
375 # Another option, seems to work great. Catches things like ''.<tab>
374 # Another option, seems to work great. Catches things like ''.<tab>
376 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
375 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
377
376
378 if m:
377 if m:
379 expr, attr = m.group(1, 3)
378 expr, attr = m.group(1, 3)
380 elif self.greedy:
379 elif self.greedy:
381 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
380 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
382 if not m2:
381 if not m2:
383 return []
382 return []
384 expr, attr = m2.group(1,2)
383 expr, attr = m2.group(1,2)
385 else:
384 else:
386 return []
385 return []
387
386
388 try:
387 try:
389 obj = eval(expr, self.namespace)
388 obj = eval(expr, self.namespace)
390 except:
389 except:
391 try:
390 try:
392 obj = eval(expr, self.global_namespace)
391 obj = eval(expr, self.global_namespace)
393 except:
392 except:
394 return []
393 return []
395
394
396 if self.limit_to__all__ and hasattr(obj, '__all__'):
395 if self.limit_to__all__ and hasattr(obj, '__all__'):
397 words = get__all__entries(obj)
396 words = get__all__entries(obj)
398 else:
397 else:
399 words = dir2(obj)
398 words = dir2(obj)
400
399
401 try:
400 try:
402 words = generics.complete_object(obj, words)
401 words = generics.complete_object(obj, words)
403 except TryNext:
402 except TryNext:
404 pass
403 pass
405 except Exception:
404 except Exception:
406 # Silence errors from completion function
405 # Silence errors from completion function
407 #raise # dbg
406 #raise # dbg
408 pass
407 pass
409 # Build match list to return
408 # Build match list to return
410 n = len(attr)
409 n = len(attr)
411 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
410 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
412
411
413
412
414 def get__all__entries(obj):
413 def get__all__entries(obj):
415 """returns the strings in the __all__ attribute"""
414 """returns the strings in the __all__ attribute"""
416 try:
415 try:
417 words = getattr(obj, '__all__')
416 words = getattr(obj, '__all__')
418 except:
417 except:
419 return []
418 return []
420
419
421 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
420 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
422
421
423
422
424 def match_dict_keys(keys, prefix, delims):
423 def match_dict_keys(keys, prefix, delims):
425 """Used by dict_key_matches, matching the prefix to a list of keys"""
424 """Used by dict_key_matches, matching the prefix to a list of keys"""
426 if not prefix:
425 if not prefix:
427 return None, 0, [repr(k) for k in keys
426 return None, 0, [repr(k) for k in keys
428 if isinstance(k, (string_types, bytes))]
427 if isinstance(k, (string_types, bytes))]
429 quote_match = re.search('["\']', prefix)
428 quote_match = re.search('["\']', prefix)
430 quote = quote_match.group()
429 quote = quote_match.group()
431 try:
430 try:
432 prefix_str = eval(prefix + quote, {})
431 prefix_str = eval(prefix + quote, {})
433 except Exception:
432 except Exception:
434 return None, 0, []
433 return None, 0, []
435
434
436 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
435 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
437 token_match = re.search(pattern, prefix, re.UNICODE)
436 token_match = re.search(pattern, prefix, re.UNICODE)
438 token_start = token_match.start()
437 token_start = token_match.start()
439 token_prefix = token_match.group()
438 token_prefix = token_match.group()
440
439
441 # TODO: support bytes in Py3k
440 # TODO: support bytes in Py3k
442 matched = []
441 matched = []
443 for key in keys:
442 for key in keys:
444 try:
443 try:
445 if not key.startswith(prefix_str):
444 if not key.startswith(prefix_str):
446 continue
445 continue
447 except (AttributeError, TypeError, UnicodeError):
446 except (AttributeError, TypeError, UnicodeError):
448 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
447 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
449 continue
448 continue
450
449
451 # reformat remainder of key to begin with prefix
450 # reformat remainder of key to begin with prefix
452 rem = key[len(prefix_str):]
451 rem = key[len(prefix_str):]
453 # force repr wrapped in '
452 # force repr wrapped in '
454 rem_repr = repr(rem + '"')
453 rem_repr = repr(rem + '"')
455 if rem_repr.startswith('u') and prefix[0] not in 'uU':
454 if rem_repr.startswith('u') and prefix[0] not in 'uU':
456 # Found key is unicode, but prefix is Py2 string.
455 # Found key is unicode, but prefix is Py2 string.
457 # Therefore attempt to interpret key as string.
456 # Therefore attempt to interpret key as string.
458 try:
457 try:
459 rem_repr = repr(rem.encode('ascii') + '"')
458 rem_repr = repr(rem.encode('ascii') + '"')
460 except UnicodeEncodeError:
459 except UnicodeEncodeError:
461 continue
460 continue
462
461
463 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
462 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
464 if quote == '"':
463 if quote == '"':
465 # The entered prefix is quoted with ",
464 # The entered prefix is quoted with ",
466 # but the match is quoted with '.
465 # but the match is quoted with '.
467 # A contained " hence needs escaping for comparison:
466 # A contained " hence needs escaping for comparison:
468 rem_repr = rem_repr.replace('"', '\\"')
467 rem_repr = rem_repr.replace('"', '\\"')
469
468
470 # then reinsert prefix from start of token
469 # then reinsert prefix from start of token
471 matched.append('%s%s' % (token_prefix, rem_repr))
470 matched.append('%s%s' % (token_prefix, rem_repr))
472 return quote, token_start, matched
471 return quote, token_start, matched
473
472
474
473
475 def _safe_isinstance(obj, module, class_name):
474 def _safe_isinstance(obj, module, class_name):
476 """Checks if obj is an instance of module.class_name if loaded
475 """Checks if obj is an instance of module.class_name if loaded
477 """
476 """
478 return (module in sys.modules and
477 return (module in sys.modules and
479 isinstance(obj, getattr(__import__(module), class_name)))
478 isinstance(obj, getattr(__import__(module), class_name)))
480
479
481
480
482 def back_unicode_name_matches(text):
481 def back_unicode_name_matches(text):
483 u"""Match unicode characters back to unicode name
482 u"""Match unicode characters back to unicode name
484
483
485 This does ☃ -> \\snowman
484 This does ☃ -> \\snowman
486
485
487 Note that snowman is not a valid python3 combining character but will be expanded.
486 Note that snowman is not a valid python3 combining character but will be expanded.
488 Though it will not recombine back to the snowman character by the completion machinery.
487 Though it will not recombine back to the snowman character by the completion machinery.
489
488
490 This will not either back-complete standard sequences like \\n, \\b ...
489 This will not either back-complete standard sequences like \\n, \\b ...
491
490
492 Used on Python 3 only.
491 Used on Python 3 only.
493 """
492 """
494 if len(text)<2:
493 if len(text)<2:
495 return u'', ()
494 return u'', ()
496 maybe_slash = text[-2]
495 maybe_slash = text[-2]
497 if maybe_slash != '\\':
496 if maybe_slash != '\\':
498 return u'', ()
497 return u'', ()
499
498
500 char = text[-1]
499 char = text[-1]
501 # no expand on quote for completion in strings.
500 # no expand on quote for completion in strings.
502 # nor backcomplete standard ascii keys
501 # nor backcomplete standard ascii keys
503 if char in string.ascii_letters or char in ['"',"'"]:
502 if char in string.ascii_letters or char in ['"',"'"]:
504 return u'', ()
503 return u'', ()
505 try :
504 try :
506 unic = unicodedata.name(char)
505 unic = unicodedata.name(char)
507 return '\\'+char,['\\'+unic]
506 return '\\'+char,['\\'+unic]
508 except KeyError as e:
507 except KeyError:
509 pass
508 pass
510 return u'', ()
509 return u'', ()
511
510
512 def back_latex_name_matches(text):
511 def back_latex_name_matches(text):
513 u"""Match latex characters back to unicode name
512 u"""Match latex characters back to unicode name
514
513
515 This does ->\\sqrt
514 This does ->\\sqrt
516
515
517 Used on Python 3 only.
516 Used on Python 3 only.
518 """
517 """
519 if len(text)<2:
518 if len(text)<2:
520 return u'', ()
519 return u'', ()
521 maybe_slash = text[-2]
520 maybe_slash = text[-2]
522 if maybe_slash != '\\':
521 if maybe_slash != '\\':
523 return u'', ()
522 return u'', ()
524
523
525
524
526 char = text[-1]
525 char = text[-1]
527 # no expand on quote for completion in strings.
526 # no expand on quote for completion in strings.
528 # nor backcomplete standard ascii keys
527 # nor backcomplete standard ascii keys
529 if char in string.ascii_letters or char in ['"',"'"]:
528 if char in string.ascii_letters or char in ['"',"'"]:
530 return u'', ()
529 return u'', ()
531 try :
530 try :
532 latex = reverse_latex_symbol[char]
531 latex = reverse_latex_symbol[char]
533 # '\\' replace the \ as well
532 # '\\' replace the \ as well
534 return '\\'+char,[latex]
533 return '\\'+char,[latex]
535 except KeyError as e:
534 except KeyError:
536 pass
535 pass
537 return u'', ()
536 return u'', ()
538
537
539
538
540 class IPCompleter(Completer):
539 class IPCompleter(Completer):
541 """Extension of the completer class with IPython-specific features"""
540 """Extension of the completer class with IPython-specific features"""
542
541
543 def _greedy_changed(self, name, old, new):
542 @observe('greedy')
543 def _greedy_changed(self, change):
544 """update the splitter and readline delims when greedy is changed"""
544 """update the splitter and readline delims when greedy is changed"""
545 if new:
545 if change['new']:
546 self.splitter.delims = GREEDY_DELIMS
546 self.splitter.delims = GREEDY_DELIMS
547 else:
547 else:
548 self.splitter.delims = DELIMS
548 self.splitter.delims = DELIMS
549
549
550 if self.readline:
550 if self.readline:
551 self.readline.set_completer_delims(self.splitter.delims)
551 self.readline.set_completer_delims(self.splitter.delims)
552
552
553 merge_completions = CBool(True, config=True,
553 merge_completions = Bool(True,
554 help="""Whether to merge completion results into a single list
554 help="""Whether to merge completion results into a single list
555
555
556 If False, only the completion results from the first non-empty
556 If False, only the completion results from the first non-empty
557 completer will be returned.
557 completer will be returned.
558 """
558 """
559 )
559 ).tag(config=True)
560 omit__names = Enum((0,1,2), default_value=2, config=True,
560 omit__names = Enum((0,1,2), default_value=2,
561 help="""Instruct the completer to omit private method names
561 help="""Instruct the completer to omit private method names
562
562
563 Specifically, when completing on ``object.<tab>``.
563 Specifically, when completing on ``object.<tab>``.
564
564
565 When 2 [default]: all names that start with '_' will be excluded.
565 When 2 [default]: all names that start with '_' will be excluded.
566
566
567 When 1: all 'magic' names (``__foo__``) will be excluded.
567 When 1: all 'magic' names (``__foo__``) will be excluded.
568
568
569 When 0: nothing will be excluded.
569 When 0: nothing will be excluded.
570 """
570 """
571 )
571 ).tag(config=True)
572 limit_to__all__ = CBool(default_value=False, config=True,
572 limit_to__all__ = Bool(False,
573 help="""
573 help="""
574 DEPRECATED as of version 5.0.
574 DEPRECATED as of version 5.0.
575
575
576 Instruct the completer to use __all__ for the completion
576 Instruct the completer to use __all__ for the completion
577
577
578 Specifically, when completing on ``object.<tab>``.
578 Specifically, when completing on ``object.<tab>``.
579
579
580 When True: only those names in obj.__all__ will be included.
580 When True: only those names in obj.__all__ will be included.
581
581
582 When False [default]: the __all__ attribute is ignored
582 When False [default]: the __all__ attribute is ignored
583 """
583 """,
584 )
584 ).tag(config=True)
585
585
586 def __init__(self, shell=None, namespace=None, global_namespace=None,
586 def __init__(self, shell=None, namespace=None, global_namespace=None,
587 use_readline=True, config=None, **kwargs):
587 use_readline=True, config=None, **kwargs):
588 """IPCompleter() -> completer
588 """IPCompleter() -> completer
589
589
590 Return a completer object suitable for use by the readline library
590 Return a completer object suitable for use by the readline library
591 via readline.set_completer().
591 via readline.set_completer().
592
592
593 Inputs:
593 Inputs:
594
594
595 - shell: a pointer to the ipython shell itself. This is needed
595 - shell: a pointer to the ipython shell itself. This is needed
596 because this completer knows about magic functions, and those can
596 because this completer knows about magic functions, and those can
597 only be accessed via the ipython instance.
597 only be accessed via the ipython instance.
598
598
599 - namespace: an optional dict where completions are performed.
599 - namespace: an optional dict where completions are performed.
600
600
601 - global_namespace: secondary optional dict for completions, to
601 - global_namespace: secondary optional dict for completions, to
602 handle cases (such as IPython embedded inside functions) where
602 handle cases (such as IPython embedded inside functions) where
603 both Python scopes are visible.
603 both Python scopes are visible.
604
604
605 use_readline : bool, optional
605 use_readline : bool, optional
606 If true, use the readline library. This completer can still function
606 If true, use the readline library. This completer can still function
607 without readline, though in that case callers must provide some extra
607 without readline, though in that case callers must provide some extra
608 information on each call about the current line."""
608 information on each call about the current line."""
609
609
610 self.magic_escape = ESC_MAGIC
610 self.magic_escape = ESC_MAGIC
611 self.splitter = CompletionSplitter()
611 self.splitter = CompletionSplitter()
612
612
613 # Readline configuration, only used by the rlcompleter method.
613 # Readline configuration, only used by the rlcompleter method.
614 if use_readline:
614 if use_readline:
615 # We store the right version of readline so that later code
615 # We store the right version of readline so that later code
616 import IPython.utils.rlineimpl as readline
616 import IPython.utils.rlineimpl as readline
617 self.readline = readline
617 self.readline = readline
618 else:
618 else:
619 self.readline = None
619 self.readline = None
620
620
621 # _greedy_changed() depends on splitter and readline being defined:
621 # _greedy_changed() depends on splitter and readline being defined:
622 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
622 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
623 config=config, **kwargs)
623 config=config, **kwargs)
624
624
625 # List where completion matches will be stored
625 # List where completion matches will be stored
626 self.matches = []
626 self.matches = []
627 self.shell = shell
627 self.shell = shell
628 # Regexp to split filenames with spaces in them
628 # Regexp to split filenames with spaces in them
629 self.space_name_re = re.compile(r'([^\\] )')
629 self.space_name_re = re.compile(r'([^\\] )')
630 # Hold a local ref. to glob.glob for speed
630 # Hold a local ref. to glob.glob for speed
631 self.glob = glob.glob
631 self.glob = glob.glob
632
632
633 # Determine if we are running on 'dumb' terminals, like (X)Emacs
633 # Determine if we are running on 'dumb' terminals, like (X)Emacs
634 # buffers, to avoid completion problems.
634 # buffers, to avoid completion problems.
635 term = os.environ.get('TERM','xterm')
635 term = os.environ.get('TERM','xterm')
636 self.dumb_terminal = term in ['dumb','emacs']
636 self.dumb_terminal = term in ['dumb','emacs']
637
637
638 # Special handling of backslashes needed in win32 platforms
638 # Special handling of backslashes needed in win32 platforms
639 if sys.platform == "win32":
639 if sys.platform == "win32":
640 self.clean_glob = self._clean_glob_win32
640 self.clean_glob = self._clean_glob_win32
641 else:
641 else:
642 self.clean_glob = self._clean_glob
642 self.clean_glob = self._clean_glob
643
643
644 #regexp to parse docstring for function signature
644 #regexp to parse docstring for function signature
645 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
645 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
646 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
646 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
647 #use this if positional argument name is also needed
647 #use this if positional argument name is also needed
648 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
648 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
649
649
650 # All active matcher routines for completion
650 # All active matcher routines for completion
651 self.matchers = [
651 self.matchers = [
652 self.file_matches,
652 self.file_matches,
653 self.magic_matches,
653 self.magic_matches,
654 self.python_func_kw_matches,
654 self.python_func_kw_matches,
655 self.dict_key_matches,
655 self.dict_key_matches,
656 ]
656 ]
657
657
658 def all_completions(self, text):
658 def all_completions(self, text):
659 """
659 """
660 Wrapper around the complete method for the benefit of emacs
660 Wrapper around the complete method for the benefit of emacs
661 and pydb.
661 and pydb.
662 """
662 """
663 return self.complete(text)[1]
663 return self.complete(text)[1]
664
664
665 def _clean_glob(self, text):
665 def _clean_glob(self, text):
666 return self.glob("%s*" % text)
666 return self.glob("%s*" % text)
667
667
668 def _clean_glob_win32(self,text):
668 def _clean_glob_win32(self,text):
669 return [f.replace("\\","/")
669 return [f.replace("\\","/")
670 for f in self.glob("%s*" % text)]
670 for f in self.glob("%s*" % text)]
671
671
672 def file_matches(self, text):
672 def file_matches(self, text):
673 """Match filenames, expanding ~USER type strings.
673 """Match filenames, expanding ~USER type strings.
674
674
675 Most of the seemingly convoluted logic in this completer is an
675 Most of the seemingly convoluted logic in this completer is an
676 attempt to handle filenames with spaces in them. And yet it's not
676 attempt to handle filenames with spaces in them. And yet it's not
677 quite perfect, because Python's readline doesn't expose all of the
677 quite perfect, because Python's readline doesn't expose all of the
678 GNU readline details needed for this to be done correctly.
678 GNU readline details needed for this to be done correctly.
679
679
680 For a filename with a space in it, the printed completions will be
680 For a filename with a space in it, the printed completions will be
681 only the parts after what's already been typed (instead of the
681 only the parts after what's already been typed (instead of the
682 full completions, as is normally done). I don't think with the
682 full completions, as is normally done). I don't think with the
683 current (as of Python 2.3) Python readline it's possible to do
683 current (as of Python 2.3) Python readline it's possible to do
684 better."""
684 better."""
685
685
686 # chars that require escaping with backslash - i.e. chars
686 # chars that require escaping with backslash - i.e. chars
687 # that readline treats incorrectly as delimiters, but we
687 # that readline treats incorrectly as delimiters, but we
688 # don't want to treat as delimiters in filename matching
688 # don't want to treat as delimiters in filename matching
689 # when escaped with backslash
689 # when escaped with backslash
690 if text.startswith('!'):
690 if text.startswith('!'):
691 text = text[1:]
691 text = text[1:]
692 text_prefix = u'!'
692 text_prefix = u'!'
693 else:
693 else:
694 text_prefix = u''
694 text_prefix = u''
695
695
696 text_until_cursor = self.text_until_cursor
696 text_until_cursor = self.text_until_cursor
697 # track strings with open quotes
697 # track strings with open quotes
698 open_quotes = has_open_quotes(text_until_cursor)
698 open_quotes = has_open_quotes(text_until_cursor)
699
699
700 if '(' in text_until_cursor or '[' in text_until_cursor:
700 if '(' in text_until_cursor or '[' in text_until_cursor:
701 lsplit = text
701 lsplit = text
702 else:
702 else:
703 try:
703 try:
704 # arg_split ~ shlex.split, but with unicode bugs fixed by us
704 # arg_split ~ shlex.split, but with unicode bugs fixed by us
705 lsplit = arg_split(text_until_cursor)[-1]
705 lsplit = arg_split(text_until_cursor)[-1]
706 except ValueError:
706 except ValueError:
707 # typically an unmatched ", or backslash without escaped char.
707 # typically an unmatched ", or backslash without escaped char.
708 if open_quotes:
708 if open_quotes:
709 lsplit = text_until_cursor.split(open_quotes)[-1]
709 lsplit = text_until_cursor.split(open_quotes)[-1]
710 else:
710 else:
711 return []
711 return []
712 except IndexError:
712 except IndexError:
713 # tab pressed on empty line
713 # tab pressed on empty line
714 lsplit = ""
714 lsplit = ""
715
715
716 if not open_quotes and lsplit != protect_filename(lsplit):
716 if not open_quotes and lsplit != protect_filename(lsplit):
717 # if protectables are found, do matching on the whole escaped name
717 # if protectables are found, do matching on the whole escaped name
718 has_protectables = True
718 has_protectables = True
719 text0,text = text,lsplit
719 text0,text = text,lsplit
720 else:
720 else:
721 has_protectables = False
721 has_protectables = False
722 text = os.path.expanduser(text)
722 text = os.path.expanduser(text)
723
723
724 if text == "":
724 if text == "":
725 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
725 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
726
726
727 # Compute the matches from the filesystem
727 # Compute the matches from the filesystem
728 m0 = self.clean_glob(text.replace('\\',''))
728 m0 = self.clean_glob(text.replace('\\',''))
729
729
730 if has_protectables:
730 if has_protectables:
731 # If we had protectables, we need to revert our changes to the
731 # If we had protectables, we need to revert our changes to the
732 # beginning of filename so that we don't double-write the part
732 # beginning of filename so that we don't double-write the part
733 # of the filename we have so far
733 # of the filename we have so far
734 len_lsplit = len(lsplit)
734 len_lsplit = len(lsplit)
735 matches = [text_prefix + text0 +
735 matches = [text_prefix + text0 +
736 protect_filename(f[len_lsplit:]) for f in m0]
736 protect_filename(f[len_lsplit:]) for f in m0]
737 else:
737 else:
738 if open_quotes:
738 if open_quotes:
739 # if we have a string with an open quote, we don't need to
739 # if we have a string with an open quote, we don't need to
740 # protect the names at all (and we _shouldn't_, as it
740 # protect the names at all (and we _shouldn't_, as it
741 # would cause bugs when the filesystem call is made).
741 # would cause bugs when the filesystem call is made).
742 matches = m0
742 matches = m0
743 else:
743 else:
744 matches = [text_prefix +
744 matches = [text_prefix +
745 protect_filename(f) for f in m0]
745 protect_filename(f) for f in m0]
746
746
747 # Mark directories in input list by appending '/' to their names.
747 # Mark directories in input list by appending '/' to their names.
748 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
748 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
749
749
750 def magic_matches(self, text):
750 def magic_matches(self, text):
751 """Match magics"""
751 """Match magics"""
752 # Get all shell magics now rather than statically, so magics loaded at
752 # Get all shell magics now rather than statically, so magics loaded at
753 # runtime show up too.
753 # runtime show up too.
754 lsm = self.shell.magics_manager.lsmagic()
754 lsm = self.shell.magics_manager.lsmagic()
755 line_magics = lsm['line']
755 line_magics = lsm['line']
756 cell_magics = lsm['cell']
756 cell_magics = lsm['cell']
757 pre = self.magic_escape
757 pre = self.magic_escape
758 pre2 = pre+pre
758 pre2 = pre+pre
759
759
760 # Completion logic:
760 # Completion logic:
761 # - user gives %%: only do cell magics
761 # - user gives %%: only do cell magics
762 # - user gives %: do both line and cell magics
762 # - user gives %: do both line and cell magics
763 # - no prefix: do both
763 # - no prefix: do both
764 # In other words, line magics are skipped if the user gives %% explicitly
764 # In other words, line magics are skipped if the user gives %% explicitly
765 bare_text = text.lstrip(pre)
765 bare_text = text.lstrip(pre)
766 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
766 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
767 if not text.startswith(pre2):
767 if not text.startswith(pre2):
768 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
768 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
769 return [cast_unicode_py2(c) for c in comp]
769 return [cast_unicode_py2(c) for c in comp]
770
770
771 def python_jedi_matches(self, text, line_buffer, cursor_pos):
771 def python_jedi_matches(self, text, line_buffer, cursor_pos):
772 """Match attributes or global Python names using Jedi."""
772 """Match attributes or global Python names using Jedi."""
773 if line_buffer.startswith('aimport ') or line_buffer.startswith('%aimport '):
773 if line_buffer.startswith('aimport ') or line_buffer.startswith('%aimport '):
774 return ()
774 return ()
775 namespaces = []
775 namespaces = []
776 if self.namespace is None:
776 if self.namespace is None:
777 import __main__
777 import __main__
778 namespaces.append(__main__.__dict__)
778 namespaces.append(__main__.__dict__)
779 else:
779 else:
780 namespaces.append(self.namespace)
780 namespaces.append(self.namespace)
781 if self.global_namespace is not None:
781 if self.global_namespace is not None:
782 namespaces.append(self.global_namespace)
782 namespaces.append(self.global_namespace)
783
783
784 # cursor_pos is an it, jedi wants line and column
784 # cursor_pos is an it, jedi wants line and column
785
785
786 interpreter = jedi.Interpreter(line_buffer, namespaces, column=cursor_pos)
786 interpreter = jedi.Interpreter(line_buffer, namespaces, column=cursor_pos)
787 path = jedi.parser.user_context.UserContext(line_buffer, \
787 path = jedi.parser.user_context.UserContext(line_buffer, \
788 (1, len(line_buffer))).get_path_until_cursor()
788 (1, len(line_buffer))).get_path_until_cursor()
789 path, dot, like = jedi.api.helpers.completion_parts(path)
789 path, dot, like = jedi.api.helpers.completion_parts(path)
790 if text.startswith('.'):
790 if text.startswith('.'):
791 # text will be `.` on completions like `a[0].<tab>`
791 # text will be `.` on completions like `a[0].<tab>`
792 before = dot
792 before = dot
793 else:
793 else:
794 before = line_buffer[:len(line_buffer) - len(like)]
794 before = line_buffer[:len(line_buffer) - len(like)]
795
795
796
796
797 def trim_start(completion):
797 def trim_start(completion):
798 """completions need to start with `text`, trim the beginning until it does"""
798 """completions need to start with `text`, trim the beginning until it does"""
799 ltext = text.lower()
799 ltext = text.lower()
800 lcomp = completion.lower()
800 lcomp = completion.lower()
801 if ltext in lcomp and not (lcomp.startswith(ltext)):
801 if ltext in lcomp and not (lcomp.startswith(ltext)):
802 start_index = lcomp.index(ltext)
802 start_index = lcomp.index(ltext)
803 if cursor_pos:
803 if cursor_pos:
804 if start_index >= cursor_pos:
804 if start_index >= cursor_pos:
805 start_index = min(start_index, cursor_pos)
805 start_index = min(start_index, cursor_pos)
806 return completion[start_index:]
806 return completion[start_index:]
807 return completion
807 return completion
808
808
809 completions = interpreter.completions()
809 completions = interpreter.completions()
810
810
811 completion_text = [c.name_with_symbols for c in completions]
811 completion_text = [c.name_with_symbols for c in completions]
812
812
813 if self.omit__names:
813 if self.omit__names:
814 if self.omit__names == 1:
814 if self.omit__names == 1:
815 # true if txt is _not_ a __ name, false otherwise:
815 # true if txt is _not_ a __ name, false otherwise:
816 no__name = lambda txt: not txt.startswith('__')
816 no__name = lambda txt: not txt.startswith('__')
817 else:
817 else:
818 # true if txt is _not_ a _ name, false otherwise:
818 # true if txt is _not_ a _ name, false otherwise:
819 no__name = lambda txt: not txt.startswith('_')
819 no__name = lambda txt: not txt.startswith('_')
820 completion_text = filter(no__name, completion_text)
820 completion_text = filter(no__name, completion_text)
821
821
822
822
823 return [trim_start(before + c_text) for c_text in completion_text]
823 return [trim_start(before + c_text) for c_text in completion_text]
824
824
825
825
826 def python_matches(self, text):
826 def python_matches(self, text):
827 """Match attributes or global python names"""
827 """Match attributes or global python names"""
828 if "." in text:
828 if "." in text:
829 try:
829 try:
830 matches = self.attr_matches(text)
830 matches = self.attr_matches(text)
831 if text.endswith('.') and self.omit__names:
831 if text.endswith('.') and self.omit__names:
832 if self.omit__names == 1:
832 if self.omit__names == 1:
833 # true if txt is _not_ a __ name, false otherwise:
833 # true if txt is _not_ a __ name, false otherwise:
834 no__name = (lambda txt:
834 no__name = (lambda txt:
835 re.match(r'.*\.__.*?__',txt) is None)
835 re.match(r'.*\.__.*?__',txt) is None)
836 else:
836 else:
837 # true if txt is _not_ a _ name, false otherwise:
837 # true if txt is _not_ a _ name, false otherwise:
838 no__name = (lambda txt:
838 no__name = (lambda txt:
839 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
839 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
840 matches = filter(no__name, matches)
840 matches = filter(no__name, matches)
841 except NameError:
841 except NameError:
842 # catches <undefined attributes>.<tab>
842 # catches <undefined attributes>.<tab>
843 matches = []
843 matches = []
844 else:
844 else:
845 matches = self.global_matches(text)
845 matches = self.global_matches(text)
846 return matches
846 return matches
847
847
848 def _default_arguments_from_docstring(self, doc):
848 def _default_arguments_from_docstring(self, doc):
849 """Parse the first line of docstring for call signature.
849 """Parse the first line of docstring for call signature.
850
850
851 Docstring should be of the form 'min(iterable[, key=func])\n'.
851 Docstring should be of the form 'min(iterable[, key=func])\n'.
852 It can also parse cython docstring of the form
852 It can also parse cython docstring of the form
853 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
853 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
854 """
854 """
855 if doc is None:
855 if doc is None:
856 return []
856 return []
857
857
858 #care only the firstline
858 #care only the firstline
859 line = doc.lstrip().splitlines()[0]
859 line = doc.lstrip().splitlines()[0]
860
860
861 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
861 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
862 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
862 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
863 sig = self.docstring_sig_re.search(line)
863 sig = self.docstring_sig_re.search(line)
864 if sig is None:
864 if sig is None:
865 return []
865 return []
866 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
866 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
867 sig = sig.groups()[0].split(',')
867 sig = sig.groups()[0].split(',')
868 ret = []
868 ret = []
869 for s in sig:
869 for s in sig:
870 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
870 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
871 ret += self.docstring_kwd_re.findall(s)
871 ret += self.docstring_kwd_re.findall(s)
872 return ret
872 return ret
873
873
874 def _default_arguments(self, obj):
874 def _default_arguments(self, obj):
875 """Return the list of default arguments of obj if it is callable,
875 """Return the list of default arguments of obj if it is callable,
876 or empty list otherwise."""
876 or empty list otherwise."""
877 call_obj = obj
877 call_obj = obj
878 ret = []
878 ret = []
879 if inspect.isbuiltin(obj):
879 if inspect.isbuiltin(obj):
880 pass
880 pass
881 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
881 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
882 if inspect.isclass(obj):
882 if inspect.isclass(obj):
883 #for cython embededsignature=True the constructor docstring
883 #for cython embededsignature=True the constructor docstring
884 #belongs to the object itself not __init__
884 #belongs to the object itself not __init__
885 ret += self._default_arguments_from_docstring(
885 ret += self._default_arguments_from_docstring(
886 getattr(obj, '__doc__', ''))
886 getattr(obj, '__doc__', ''))
887 # for classes, check for __init__,__new__
887 # for classes, check for __init__,__new__
888 call_obj = (getattr(obj, '__init__', None) or
888 call_obj = (getattr(obj, '__init__', None) or
889 getattr(obj, '__new__', None))
889 getattr(obj, '__new__', None))
890 # for all others, check if they are __call__able
890 # for all others, check if they are __call__able
891 elif hasattr(obj, '__call__'):
891 elif hasattr(obj, '__call__'):
892 call_obj = obj.__call__
892 call_obj = obj.__call__
893 ret += self._default_arguments_from_docstring(
893 ret += self._default_arguments_from_docstring(
894 getattr(call_obj, '__doc__', ''))
894 getattr(call_obj, '__doc__', ''))
895
895
896 if PY3:
896 if PY3:
897 _keeps = (inspect.Parameter.KEYWORD_ONLY,
897 _keeps = (inspect.Parameter.KEYWORD_ONLY,
898 inspect.Parameter.POSITIONAL_OR_KEYWORD)
898 inspect.Parameter.POSITIONAL_OR_KEYWORD)
899 signature = inspect.signature
899 signature = inspect.signature
900 else:
900 else:
901 import IPython.utils.signatures
901 import IPython.utils.signatures
902 _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY,
902 _keeps = (IPython.utils.signatures.Parameter.KEYWORD_ONLY,
903 IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD)
903 IPython.utils.signatures.Parameter.POSITIONAL_OR_KEYWORD)
904 signature = IPython.utils.signatures.signature
904 signature = IPython.utils.signatures.signature
905
905
906 try:
906 try:
907 sig = signature(call_obj)
907 sig = signature(call_obj)
908 ret.extend(k for k, v in sig.parameters.items() if
908 ret.extend(k for k, v in sig.parameters.items() if
909 v.kind in _keeps)
909 v.kind in _keeps)
910 except ValueError:
910 except ValueError:
911 pass
911 pass
912
912
913 return list(set(ret))
913 return list(set(ret))
914
914
915 def python_func_kw_matches(self,text):
915 def python_func_kw_matches(self,text):
916 """Match named parameters (kwargs) of the last open function"""
916 """Match named parameters (kwargs) of the last open function"""
917
917
918 if "." in text: # a parameter cannot be dotted
918 if "." in text: # a parameter cannot be dotted
919 return []
919 return []
920 try: regexp = self.__funcParamsRegex
920 try: regexp = self.__funcParamsRegex
921 except AttributeError:
921 except AttributeError:
922 regexp = self.__funcParamsRegex = re.compile(r'''
922 regexp = self.__funcParamsRegex = re.compile(r'''
923 '.*?(?<!\\)' | # single quoted strings or
923 '.*?(?<!\\)' | # single quoted strings or
924 ".*?(?<!\\)" | # double quoted strings or
924 ".*?(?<!\\)" | # double quoted strings or
925 \w+ | # identifier
925 \w+ | # identifier
926 \S # other characters
926 \S # other characters
927 ''', re.VERBOSE | re.DOTALL)
927 ''', re.VERBOSE | re.DOTALL)
928 # 1. find the nearest identifier that comes before an unclosed
928 # 1. find the nearest identifier that comes before an unclosed
929 # parenthesis before the cursor
929 # parenthesis before the cursor
930 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
930 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
931 tokens = regexp.findall(self.text_until_cursor)
931 tokens = regexp.findall(self.text_until_cursor)
932 tokens.reverse()
932 tokens.reverse()
933 iterTokens = iter(tokens); openPar = 0
933 iterTokens = iter(tokens); openPar = 0
934
934
935 for token in iterTokens:
935 for token in iterTokens:
936 if token == ')':
936 if token == ')':
937 openPar -= 1
937 openPar -= 1
938 elif token == '(':
938 elif token == '(':
939 openPar += 1
939 openPar += 1
940 if openPar > 0:
940 if openPar > 0:
941 # found the last unclosed parenthesis
941 # found the last unclosed parenthesis
942 break
942 break
943 else:
943 else:
944 return []
944 return []
945 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
945 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
946 ids = []
946 ids = []
947 isId = re.compile(r'\w+$').match
947 isId = re.compile(r'\w+$').match
948
948
949 while True:
949 while True:
950 try:
950 try:
951 ids.append(next(iterTokens))
951 ids.append(next(iterTokens))
952 if not isId(ids[-1]):
952 if not isId(ids[-1]):
953 ids.pop(); break
953 ids.pop(); break
954 if not next(iterTokens) == '.':
954 if not next(iterTokens) == '.':
955 break
955 break
956 except StopIteration:
956 except StopIteration:
957 break
957 break
958 # lookup the candidate callable matches either using global_matches
958 # lookup the candidate callable matches either using global_matches
959 # or attr_matches for dotted names
959 # or attr_matches for dotted names
960 if len(ids) == 1:
960 if len(ids) == 1:
961 callableMatches = self.global_matches(ids[0])
961 callableMatches = self.global_matches(ids[0])
962 else:
962 else:
963 callableMatches = self.attr_matches('.'.join(ids[::-1]))
963 callableMatches = self.attr_matches('.'.join(ids[::-1]))
964 argMatches = []
964 argMatches = []
965 for callableMatch in callableMatches:
965 for callableMatch in callableMatches:
966 try:
966 try:
967 namedArgs = self._default_arguments(eval(callableMatch,
967 namedArgs = self._default_arguments(eval(callableMatch,
968 self.namespace))
968 self.namespace))
969 except:
969 except:
970 continue
970 continue
971
971
972 for namedArg in namedArgs:
972 for namedArg in namedArgs:
973 if namedArg.startswith(text):
973 if namedArg.startswith(text):
974 argMatches.append(u"%s=" %namedArg)
974 argMatches.append(u"%s=" %namedArg)
975 return argMatches
975 return argMatches
976
976
977 def dict_key_matches(self, text):
977 def dict_key_matches(self, text):
978 "Match string keys in a dictionary, after e.g. 'foo[' "
978 "Match string keys in a dictionary, after e.g. 'foo[' "
979 def get_keys(obj):
979 def get_keys(obj):
980 # Objects can define their own completions by defining an
980 # Objects can define their own completions by defining an
981 # _ipy_key_completions_() method.
981 # _ipy_key_completions_() method.
982 method = get_real_method(obj, '_ipython_key_completions_')
982 method = get_real_method(obj, '_ipython_key_completions_')
983 if method is not None:
983 if method is not None:
984 return method()
984 return method()
985
985
986 # Special case some common in-memory dict-like types
986 # Special case some common in-memory dict-like types
987 if isinstance(obj, dict) or\
987 if isinstance(obj, dict) or\
988 _safe_isinstance(obj, 'pandas', 'DataFrame'):
988 _safe_isinstance(obj, 'pandas', 'DataFrame'):
989 try:
989 try:
990 return list(obj.keys())
990 return list(obj.keys())
991 except Exception:
991 except Exception:
992 return []
992 return []
993 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
993 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
994 _safe_isinstance(obj, 'numpy', 'void'):
994 _safe_isinstance(obj, 'numpy', 'void'):
995 return obj.dtype.names or []
995 return obj.dtype.names or []
996 return []
996 return []
997
997
998 try:
998 try:
999 regexps = self.__dict_key_regexps
999 regexps = self.__dict_key_regexps
1000 except AttributeError:
1000 except AttributeError:
1001 dict_key_re_fmt = r'''(?x)
1001 dict_key_re_fmt = r'''(?x)
1002 ( # match dict-referring expression wrt greedy setting
1002 ( # match dict-referring expression wrt greedy setting
1003 %s
1003 %s
1004 )
1004 )
1005 \[ # open bracket
1005 \[ # open bracket
1006 \s* # and optional whitespace
1006 \s* # and optional whitespace
1007 ([uUbB]? # string prefix (r not handled)
1007 ([uUbB]? # string prefix (r not handled)
1008 (?: # unclosed string
1008 (?: # unclosed string
1009 '(?:[^']|(?<!\\)\\')*
1009 '(?:[^']|(?<!\\)\\')*
1010 |
1010 |
1011 "(?:[^"]|(?<!\\)\\")*
1011 "(?:[^"]|(?<!\\)\\")*
1012 )
1012 )
1013 )?
1013 )?
1014 $
1014 $
1015 '''
1015 '''
1016 regexps = self.__dict_key_regexps = {
1016 regexps = self.__dict_key_regexps = {
1017 False: re.compile(dict_key_re_fmt % '''
1017 False: re.compile(dict_key_re_fmt % '''
1018 # identifiers separated by .
1018 # identifiers separated by .
1019 (?!\d)\w+
1019 (?!\d)\w+
1020 (?:\.(?!\d)\w+)*
1020 (?:\.(?!\d)\w+)*
1021 '''),
1021 '''),
1022 True: re.compile(dict_key_re_fmt % '''
1022 True: re.compile(dict_key_re_fmt % '''
1023 .+
1023 .+
1024 ''')
1024 ''')
1025 }
1025 }
1026
1026
1027 match = regexps[self.greedy].search(self.text_until_cursor)
1027 match = regexps[self.greedy].search(self.text_until_cursor)
1028 if match is None:
1028 if match is None:
1029 return []
1029 return []
1030
1030
1031 expr, prefix = match.groups()
1031 expr, prefix = match.groups()
1032 try:
1032 try:
1033 obj = eval(expr, self.namespace)
1033 obj = eval(expr, self.namespace)
1034 except Exception:
1034 except Exception:
1035 try:
1035 try:
1036 obj = eval(expr, self.global_namespace)
1036 obj = eval(expr, self.global_namespace)
1037 except Exception:
1037 except Exception:
1038 return []
1038 return []
1039
1039
1040 keys = get_keys(obj)
1040 keys = get_keys(obj)
1041 if not keys:
1041 if not keys:
1042 return keys
1042 return keys
1043 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1043 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1044 if not matches:
1044 if not matches:
1045 return matches
1045 return matches
1046
1046
1047 # get the cursor position of
1047 # get the cursor position of
1048 # - the text being completed
1048 # - the text being completed
1049 # - the start of the key text
1049 # - the start of the key text
1050 # - the start of the completion
1050 # - the start of the completion
1051 text_start = len(self.text_until_cursor) - len(text)
1051 text_start = len(self.text_until_cursor) - len(text)
1052 if prefix:
1052 if prefix:
1053 key_start = match.start(2)
1053 key_start = match.start(2)
1054 completion_start = key_start + token_offset
1054 completion_start = key_start + token_offset
1055 else:
1055 else:
1056 key_start = completion_start = match.end()
1056 key_start = completion_start = match.end()
1057
1057
1058 # grab the leading prefix, to make sure all completions start with `text`
1058 # grab the leading prefix, to make sure all completions start with `text`
1059 if text_start > key_start:
1059 if text_start > key_start:
1060 leading = ''
1060 leading = ''
1061 else:
1061 else:
1062 leading = text[text_start:completion_start]
1062 leading = text[text_start:completion_start]
1063
1063
1064 # the index of the `[` character
1064 # the index of the `[` character
1065 bracket_idx = match.end(1)
1065 bracket_idx = match.end(1)
1066
1066
1067 # append closing quote and bracket as appropriate
1067 # append closing quote and bracket as appropriate
1068 # this is *not* appropriate if the opening quote or bracket is outside
1068 # this is *not* appropriate if the opening quote or bracket is outside
1069 # the text given to this method
1069 # the text given to this method
1070 suf = ''
1070 suf = ''
1071 continuation = self.line_buffer[len(self.text_until_cursor):]
1071 continuation = self.line_buffer[len(self.text_until_cursor):]
1072 if key_start > text_start and closing_quote:
1072 if key_start > text_start and closing_quote:
1073 # quotes were opened inside text, maybe close them
1073 # quotes were opened inside text, maybe close them
1074 if continuation.startswith(closing_quote):
1074 if continuation.startswith(closing_quote):
1075 continuation = continuation[len(closing_quote):]
1075 continuation = continuation[len(closing_quote):]
1076 else:
1076 else:
1077 suf += closing_quote
1077 suf += closing_quote
1078 if bracket_idx > text_start:
1078 if bracket_idx > text_start:
1079 # brackets were opened inside text, maybe close them
1079 # brackets were opened inside text, maybe close them
1080 if not continuation.startswith(']'):
1080 if not continuation.startswith(']'):
1081 suf += ']'
1081 suf += ']'
1082
1082
1083 return [leading + k + suf for k in matches]
1083 return [leading + k + suf for k in matches]
1084
1084
1085 def unicode_name_matches(self, text):
1085 def unicode_name_matches(self, text):
1086 u"""Match Latex-like syntax for unicode characters base
1086 u"""Match Latex-like syntax for unicode characters base
1087 on the name of the character.
1087 on the name of the character.
1088
1088
1089 This does \\GREEK SMALL LETTER ETA -> η
1089 This does \\GREEK SMALL LETTER ETA -> η
1090
1090
1091 Works only on valid python 3 identifier, or on combining characters that
1091 Works only on valid python 3 identifier, or on combining characters that
1092 will combine to form a valid identifier.
1092 will combine to form a valid identifier.
1093
1093
1094 Used on Python 3 only.
1094 Used on Python 3 only.
1095 """
1095 """
1096 slashpos = text.rfind('\\')
1096 slashpos = text.rfind('\\')
1097 if slashpos > -1:
1097 if slashpos > -1:
1098 s = text[slashpos+1:]
1098 s = text[slashpos+1:]
1099 try :
1099 try :
1100 unic = unicodedata.lookup(s)
1100 unic = unicodedata.lookup(s)
1101 # allow combining chars
1101 # allow combining chars
1102 if ('a'+unic).isidentifier():
1102 if ('a'+unic).isidentifier():
1103 return '\\'+s,[unic]
1103 return '\\'+s,[unic]
1104 except KeyError as e:
1104 except KeyError:
1105 pass
1105 pass
1106 return u'', []
1106 return u'', []
1107
1107
1108
1108
1109
1109
1110
1110
1111 def latex_matches(self, text):
1111 def latex_matches(self, text):
1112 u"""Match Latex syntax for unicode characters.
1112 u"""Match Latex syntax for unicode characters.
1113
1113
1114 This does both \\alp -> \\alpha and \\alpha -> α
1114 This does both \\alp -> \\alpha and \\alpha -> α
1115
1115
1116 Used on Python 3 only.
1116 Used on Python 3 only.
1117 """
1117 """
1118 slashpos = text.rfind('\\')
1118 slashpos = text.rfind('\\')
1119 if slashpos > -1:
1119 if slashpos > -1:
1120 s = text[slashpos:]
1120 s = text[slashpos:]
1121 if s in latex_symbols:
1121 if s in latex_symbols:
1122 # Try to complete a full latex symbol to unicode
1122 # Try to complete a full latex symbol to unicode
1123 # \\alpha -> α
1123 # \\alpha -> α
1124 return s, [latex_symbols[s]]
1124 return s, [latex_symbols[s]]
1125 else:
1125 else:
1126 # If a user has partially typed a latex symbol, give them
1126 # If a user has partially typed a latex symbol, give them
1127 # a full list of options \al -> [\aleph, \alpha]
1127 # a full list of options \al -> [\aleph, \alpha]
1128 matches = [k for k in latex_symbols if k.startswith(s)]
1128 matches = [k for k in latex_symbols if k.startswith(s)]
1129 return s, matches
1129 return s, matches
1130 return u'', []
1130 return u'', []
1131
1131
1132 def dispatch_custom_completer(self, text):
1132 def dispatch_custom_completer(self, text):
1133 line = self.line_buffer
1133 line = self.line_buffer
1134 if not line.strip():
1134 if not line.strip():
1135 return None
1135 return None
1136
1136
1137 # Create a little structure to pass all the relevant information about
1137 # Create a little structure to pass all the relevant information about
1138 # the current completion to any custom completer.
1138 # the current completion to any custom completer.
1139 event = Bunch()
1139 event = Bunch()
1140 event.line = line
1140 event.line = line
1141 event.symbol = text
1141 event.symbol = text
1142 cmd = line.split(None,1)[0]
1142 cmd = line.split(None,1)[0]
1143 event.command = cmd
1143 event.command = cmd
1144 event.text_until_cursor = self.text_until_cursor
1144 event.text_until_cursor = self.text_until_cursor
1145
1145
1146 # for foo etc, try also to find completer for %foo
1146 # for foo etc, try also to find completer for %foo
1147 if not cmd.startswith(self.magic_escape):
1147 if not cmd.startswith(self.magic_escape):
1148 try_magic = self.custom_completers.s_matches(
1148 try_magic = self.custom_completers.s_matches(
1149 self.magic_escape + cmd)
1149 self.magic_escape + cmd)
1150 else:
1150 else:
1151 try_magic = []
1151 try_magic = []
1152
1152
1153 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1153 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1154 try_magic,
1154 try_magic,
1155 self.custom_completers.flat_matches(self.text_until_cursor)):
1155 self.custom_completers.flat_matches(self.text_until_cursor)):
1156 try:
1156 try:
1157 res = c(event)
1157 res = c(event)
1158 if res:
1158 if res:
1159 # first, try case sensitive match
1159 # first, try case sensitive match
1160 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1160 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1161 if withcase:
1161 if withcase:
1162 return withcase
1162 return withcase
1163 # if none, then case insensitive ones are ok too
1163 # if none, then case insensitive ones are ok too
1164 text_low = text.lower()
1164 text_low = text.lower()
1165 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1165 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1166 except TryNext:
1166 except TryNext:
1167 pass
1167 pass
1168
1168
1169 return None
1169 return None
1170
1170
1171 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1171 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1172 """Find completions for the given text and line context.
1172 """Find completions for the given text and line context.
1173
1173
1174 Note that both the text and the line_buffer are optional, but at least
1174 Note that both the text and the line_buffer are optional, but at least
1175 one of them must be given.
1175 one of them must be given.
1176
1176
1177 Parameters
1177 Parameters
1178 ----------
1178 ----------
1179 text : string, optional
1179 text : string, optional
1180 Text to perform the completion on. If not given, the line buffer
1180 Text to perform the completion on. If not given, the line buffer
1181 is split using the instance's CompletionSplitter object.
1181 is split using the instance's CompletionSplitter object.
1182
1182
1183 line_buffer : string, optional
1183 line_buffer : string, optional
1184 If not given, the completer attempts to obtain the current line
1184 If not given, the completer attempts to obtain the current line
1185 buffer via readline. This keyword allows clients which are
1185 buffer via readline. This keyword allows clients which are
1186 requesting for text completions in non-readline contexts to inform
1186 requesting for text completions in non-readline contexts to inform
1187 the completer of the entire text.
1187 the completer of the entire text.
1188
1188
1189 cursor_pos : int, optional
1189 cursor_pos : int, optional
1190 Index of the cursor in the full line buffer. Should be provided by
1190 Index of the cursor in the full line buffer. Should be provided by
1191 remote frontends where kernel has no access to frontend state.
1191 remote frontends where kernel has no access to frontend state.
1192
1192
1193 Returns
1193 Returns
1194 -------
1194 -------
1195 text : str
1195 text : str
1196 Text that was actually used in the completion.
1196 Text that was actually used in the completion.
1197
1197
1198 matches : list
1198 matches : list
1199 A list of completion matches.
1199 A list of completion matches.
1200 """
1200 """
1201 # if the cursor position isn't given, the only sane assumption we can
1201 # if the cursor position isn't given, the only sane assumption we can
1202 # make is that it's at the end of the line (the common case)
1202 # make is that it's at the end of the line (the common case)
1203 if cursor_pos is None:
1203 if cursor_pos is None:
1204 cursor_pos = len(line_buffer) if text is None else len(text)
1204 cursor_pos = len(line_buffer) if text is None else len(text)
1205
1205
1206 if PY3:
1206 if PY3:
1207
1207
1208 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1208 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1209 latex_text, latex_matches = self.latex_matches(base_text)
1209 latex_text, latex_matches = self.latex_matches(base_text)
1210 if latex_matches:
1210 if latex_matches:
1211 return latex_text, latex_matches
1211 return latex_text, latex_matches
1212 name_text = ''
1212 name_text = ''
1213 name_matches = []
1213 name_matches = []
1214 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1214 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1215 name_text, name_matches = meth(base_text)
1215 name_text, name_matches = meth(base_text)
1216 if name_text:
1216 if name_text:
1217 return name_text, name_matches
1217 return name_text, name_matches
1218
1218
1219 # if text is either None or an empty string, rely on the line buffer
1219 # if text is either None or an empty string, rely on the line buffer
1220 if not text:
1220 if not text:
1221 text = self.splitter.split_line(line_buffer, cursor_pos)
1221 text = self.splitter.split_line(line_buffer, cursor_pos)
1222
1222
1223 # If no line buffer is given, assume the input text is all there was
1223 # If no line buffer is given, assume the input text is all there was
1224 if line_buffer is None:
1224 if line_buffer is None:
1225 line_buffer = text
1225 line_buffer = text
1226
1226
1227 self.line_buffer = line_buffer
1227 self.line_buffer = line_buffer
1228 self.text_until_cursor = self.line_buffer[:cursor_pos]
1228 self.text_until_cursor = self.line_buffer[:cursor_pos]
1229
1229
1230 # Start with a clean slate of completions
1230 # Start with a clean slate of completions
1231 self.matches[:] = []
1231 self.matches[:] = []
1232 custom_res = self.dispatch_custom_completer(text)
1232 custom_res = self.dispatch_custom_completer(text)
1233 if custom_res is not None:
1233 if custom_res is not None:
1234 # did custom completers produce something?
1234 # did custom completers produce something?
1235 self.matches = custom_res
1235 self.matches = custom_res
1236 else:
1236 else:
1237 # Extend the list of completions with the results of each
1237 # Extend the list of completions with the results of each
1238 # matcher, so we return results to the user from all
1238 # matcher, so we return results to the user from all
1239 # namespaces.
1239 # namespaces.
1240 if self.merge_completions:
1240 if self.merge_completions:
1241 self.matches = []
1241 self.matches = []
1242 for matcher in self.matchers:
1242 for matcher in self.matchers:
1243 try:
1243 try:
1244 self.matches.extend(matcher(text))
1244 self.matches.extend(matcher(text))
1245 except:
1245 except:
1246 # Show the ugly traceback if the matcher causes an
1246 # Show the ugly traceback if the matcher causes an
1247 # exception, but do NOT crash the kernel!
1247 # exception, but do NOT crash the kernel!
1248 sys.excepthook(*sys.exc_info())
1248 sys.excepthook(*sys.exc_info())
1249 else:
1249 else:
1250 for matcher in self.matchers:
1250 for matcher in self.matchers:
1251 self.matches = matcher(text)
1251 self.matches = matcher(text)
1252 if self.matches:
1252 if self.matches:
1253 break
1253 break
1254 # FIXME: we should extend our api to return a dict with completions for
1254 # FIXME: we should extend our api to return a dict with completions for
1255 # different types of objects. The rlcomplete() method could then
1255 # different types of objects. The rlcomplete() method could then
1256 # simply collapse the dict into a list for readline, but we'd have
1256 # simply collapse the dict into a list for readline, but we'd have
1257 # richer completion semantics in other evironments.
1257 # richer completion semantics in other evironments.
1258 self.matches.extend(self.python_jedi_matches(text, line_buffer, cursor_pos))
1258 self.matches.extend(self.python_jedi_matches(text, line_buffer, cursor_pos))
1259
1259
1260 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1260 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1261
1261
1262 return text, self.matches
1262 return text, self.matches
1263
1263
1264 def rlcomplete(self, text, state):
1264 def rlcomplete(self, text, state):
1265 """Return the state-th possible completion for 'text'.
1265 """Return the state-th possible completion for 'text'.
1266
1266
1267 This is called successively with state == 0, 1, 2, ... until it
1267 This is called successively with state == 0, 1, 2, ... until it
1268 returns None. The completion should begin with 'text'.
1268 returns None. The completion should begin with 'text'.
1269
1269
1270 Parameters
1270 Parameters
1271 ----------
1271 ----------
1272 text : string
1272 text : string
1273 Text to perform the completion on.
1273 Text to perform the completion on.
1274
1274
1275 state : int
1275 state : int
1276 Counter used by readline.
1276 Counter used by readline.
1277 """
1277 """
1278 if state==0:
1278 if state==0:
1279
1279
1280 self.line_buffer = line_buffer = self.readline.get_line_buffer()
1280 self.line_buffer = line_buffer = self.readline.get_line_buffer()
1281 cursor_pos = self.readline.get_endidx()
1281 cursor_pos = self.readline.get_endidx()
1282
1282
1283 #io.rprint("\nRLCOMPLETE: %r %r %r" %
1283 #io.rprint("\nRLCOMPLETE: %r %r %r" %
1284 # (text, line_buffer, cursor_pos) ) # dbg
1284 # (text, line_buffer, cursor_pos) ) # dbg
1285
1285
1286 # if there is only a tab on a line with only whitespace, instead of
1286 # if there is only a tab on a line with only whitespace, instead of
1287 # the mostly useless 'do you want to see all million completions'
1287 # the mostly useless 'do you want to see all million completions'
1288 # message, just do the right thing and give the user his tab!
1288 # message, just do the right thing and give the user his tab!
1289 # Incidentally, this enables pasting of tabbed text from an editor
1289 # Incidentally, this enables pasting of tabbed text from an editor
1290 # (as long as autoindent is off).
1290 # (as long as autoindent is off).
1291
1291
1292 # It should be noted that at least pyreadline still shows file
1292 # It should be noted that at least pyreadline still shows file
1293 # completions - is there a way around it?
1293 # completions - is there a way around it?
1294
1294
1295 # don't apply this on 'dumb' terminals, such as emacs buffers, so
1295 # don't apply this on 'dumb' terminals, such as emacs buffers, so
1296 # we don't interfere with their own tab-completion mechanism.
1296 # we don't interfere with their own tab-completion mechanism.
1297 if not (self.dumb_terminal or line_buffer.strip()):
1297 if not (self.dumb_terminal or line_buffer.strip()):
1298 self.readline.insert_text('\t')
1298 self.readline.insert_text('\t')
1299 sys.stdout.flush()
1299 sys.stdout.flush()
1300 return None
1300 return None
1301
1301
1302 # Note: debugging exceptions that may occur in completion is very
1302 # Note: debugging exceptions that may occur in completion is very
1303 # tricky, because readline unconditionally silences them. So if
1303 # tricky, because readline unconditionally silences them. So if
1304 # during development you suspect a bug in the completion code, turn
1304 # during development you suspect a bug in the completion code, turn
1305 # this flag on temporarily by uncommenting the second form (don't
1305 # this flag on temporarily by uncommenting the second form (don't
1306 # flip the value in the first line, as the '# dbg' marker can be
1306 # flip the value in the first line, as the '# dbg' marker can be
1307 # automatically detected and is used elsewhere).
1307 # automatically detected and is used elsewhere).
1308 DEBUG = False
1308 DEBUG = False
1309 #DEBUG = True # dbg
1309 #DEBUG = True # dbg
1310 if DEBUG:
1310 if DEBUG:
1311 try:
1311 try:
1312 self.complete(text, line_buffer, cursor_pos)
1312 self.complete(text, line_buffer, cursor_pos)
1313 except:
1313 except:
1314 import traceback; traceback.print_exc()
1314 import traceback; traceback.print_exc()
1315 else:
1315 else:
1316 # The normal production version is here
1316 # The normal production version is here
1317
1317
1318 # This method computes the self.matches array
1318 # This method computes the self.matches array
1319 self.complete(text, line_buffer, cursor_pos)
1319 self.complete(text, line_buffer, cursor_pos)
1320
1320
1321 try:
1321 try:
1322 return self.matches[state]
1322 return self.matches[state]
1323 except IndexError:
1323 except IndexError:
1324 return None
1324 return None
1325
1325
@@ -1,951 +1,960 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Display formatters.
2 """Display formatters.
3
3
4 Inheritance diagram:
4 Inheritance diagram:
5
5
6 .. inheritance-diagram:: IPython.core.formatters
6 .. inheritance-diagram:: IPython.core.formatters
7 :parts: 3
7 :parts: 3
8 """
8 """
9
9
10 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12
12
13 import abc
13 import abc
14 import json
14 import json
15 import sys
15 import sys
16 import traceback
16 import traceback
17 import warnings
17 import warnings
18
18
19 from decorator import decorator
19 from decorator import decorator
20
20
21 from traitlets.config.configurable import Configurable
21 from traitlets.config.configurable import Configurable
22 from IPython.core.getipython import get_ipython
22 from IPython.core.getipython import get_ipython
23 from IPython.utils.sentinel import Sentinel
23 from IPython.utils.sentinel import Sentinel
24 from IPython.utils.dir2 import get_real_method
24 from IPython.utils.dir2 import get_real_method
25 from IPython.lib import pretty
25 from IPython.lib import pretty
26 from traitlets import (
26 from traitlets import (
27 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
27 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
28 ForwardDeclaredInstance,
28 ForwardDeclaredInstance,
29 default, observe,
29 )
30 )
30 from IPython.utils.py3compat import (
31 from IPython.utils.py3compat import (
31 with_metaclass, string_types, unicode_type,
32 with_metaclass, string_types, unicode_type,
32 )
33 )
33
34
34
35
35 class DisplayFormatter(Configurable):
36 class DisplayFormatter(Configurable):
36
37
37 # When set to true only the default plain text formatter will be used.
38 # When set to true only the default plain text formatter will be used.
38 plain_text_only = Bool(False).tag(config=True)
39 plain_text_only = Bool(False).tag(config=True)
39 def _plain_text_only_changed(self, name, old, new):
40 def _plain_text_only_changed(self, name, old, new):
40 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
41 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
41
42
42 It will be removed in IPython 5.0
43 It will be removed in IPython 5.0
43
44
44 Use DisplayFormatter.active_types = ['text/plain']
45 Use DisplayFormatter.active_types = ['text/plain']
45 for the same effect.
46 for the same effect.
46 """, DeprecationWarning)
47 """, DeprecationWarning)
47 if new:
48 if new:
48 self.active_types = ['text/plain']
49 self.active_types = ['text/plain']
49 else:
50 else:
50 self.active_types = self.format_types
51 self.active_types = self.format_types
51
52
52 active_types = List(Unicode()).tag(config=True,
53 active_types = List(Unicode(),
53 help="""List of currently active mime-types to display.
54 help="""List of currently active mime-types to display.
54 You can use this to set a white-list for formats to display.
55 You can use this to set a white-list for formats to display.
55
56
56 Most users will not need to change this value.
57 Most users will not need to change this value.
57 """)
58 """).tag(config=True)
59
60 @default('active_types')
58 def _active_types_default(self):
61 def _active_types_default(self):
59 return self.format_types
62 return self.format_types
60
63
61 def _active_types_changed(self, name, old, new):
64 @observe('active_types')
65 def _active_types_changed(self, change):
62 for key, formatter in self.formatters.items():
66 for key, formatter in self.formatters.items():
63 if key in new:
67 if key in change['new']:
64 formatter.enabled = True
68 formatter.enabled = True
65 else:
69 else:
66 formatter.enabled = False
70 formatter.enabled = False
67
71
68 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
72 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
69 def _ipython_display_formatter_default(self):
73 @default('ipython_display_formatter')
74 def _default_formatter(self):
70 return IPythonDisplayFormatter(parent=self)
75 return IPythonDisplayFormatter(parent=self)
71
76
72 # A dict of formatter whose keys are format types (MIME types) and whose
77 # A dict of formatter whose keys are format types (MIME types) and whose
73 # values are subclasses of BaseFormatter.
78 # values are subclasses of BaseFormatter.
74 formatters = Dict()
79 formatters = Dict()
80 @default('formatters')
75 def _formatters_default(self):
81 def _formatters_default(self):
76 """Activate the default formatters."""
82 """Activate the default formatters."""
77 formatter_classes = [
83 formatter_classes = [
78 PlainTextFormatter,
84 PlainTextFormatter,
79 HTMLFormatter,
85 HTMLFormatter,
80 MarkdownFormatter,
86 MarkdownFormatter,
81 SVGFormatter,
87 SVGFormatter,
82 PNGFormatter,
88 PNGFormatter,
83 PDFFormatter,
89 PDFFormatter,
84 JPEGFormatter,
90 JPEGFormatter,
85 LatexFormatter,
91 LatexFormatter,
86 JSONFormatter,
92 JSONFormatter,
87 JavascriptFormatter
93 JavascriptFormatter
88 ]
94 ]
89 d = {}
95 d = {}
90 for cls in formatter_classes:
96 for cls in formatter_classes:
91 f = cls(parent=self)
97 f = cls(parent=self)
92 d[f.format_type] = f
98 d[f.format_type] = f
93 return d
99 return d
94
100
95 def format(self, obj, include=None, exclude=None):
101 def format(self, obj, include=None, exclude=None):
96 """Return a format data dict for an object.
102 """Return a format data dict for an object.
97
103
98 By default all format types will be computed.
104 By default all format types will be computed.
99
105
100 The following MIME types are currently implemented:
106 The following MIME types are currently implemented:
101
107
102 * text/plain
108 * text/plain
103 * text/html
109 * text/html
104 * text/markdown
110 * text/markdown
105 * text/latex
111 * text/latex
106 * application/json
112 * application/json
107 * application/javascript
113 * application/javascript
108 * application/pdf
114 * application/pdf
109 * image/png
115 * image/png
110 * image/jpeg
116 * image/jpeg
111 * image/svg+xml
117 * image/svg+xml
112
118
113 Parameters
119 Parameters
114 ----------
120 ----------
115 obj : object
121 obj : object
116 The Python object whose format data will be computed.
122 The Python object whose format data will be computed.
117 include : list or tuple, optional
123 include : list or tuple, optional
118 A list of format type strings (MIME types) to include in the
124 A list of format type strings (MIME types) to include in the
119 format data dict. If this is set *only* the format types included
125 format data dict. If this is set *only* the format types included
120 in this list will be computed.
126 in this list will be computed.
121 exclude : list or tuple, optional
127 exclude : list or tuple, optional
122 A list of format type string (MIME types) to exclude in the format
128 A list of format type string (MIME types) to exclude in the format
123 data dict. If this is set all format types will be computed,
129 data dict. If this is set all format types will be computed,
124 except for those included in this argument.
130 except for those included in this argument.
125
131
126 Returns
132 Returns
127 -------
133 -------
128 (format_dict, metadata_dict) : tuple of two dicts
134 (format_dict, metadata_dict) : tuple of two dicts
129
135
130 format_dict is a dictionary of key/value pairs, one of each format that was
136 format_dict is a dictionary of key/value pairs, one of each format that was
131 generated for the object. The keys are the format types, which
137 generated for the object. The keys are the format types, which
132 will usually be MIME type strings and the values and JSON'able
138 will usually be MIME type strings and the values and JSON'able
133 data structure containing the raw data for the representation in
139 data structure containing the raw data for the representation in
134 that format.
140 that format.
135
141
136 metadata_dict is a dictionary of metadata about each mime-type output.
142 metadata_dict is a dictionary of metadata about each mime-type output.
137 Its keys will be a strict subset of the keys in format_dict.
143 Its keys will be a strict subset of the keys in format_dict.
138 """
144 """
139 format_dict = {}
145 format_dict = {}
140 md_dict = {}
146 md_dict = {}
141
147
142 if self.ipython_display_formatter(obj):
148 if self.ipython_display_formatter(obj):
143 # object handled itself, don't proceed
149 # object handled itself, don't proceed
144 return {}, {}
150 return {}, {}
145
151
146 for format_type, formatter in self.formatters.items():
152 for format_type, formatter in self.formatters.items():
147 if include and format_type not in include:
153 if include and format_type not in include:
148 continue
154 continue
149 if exclude and format_type in exclude:
155 if exclude and format_type in exclude:
150 continue
156 continue
151
157
152 md = None
158 md = None
153 try:
159 try:
154 data = formatter(obj)
160 data = formatter(obj)
155 except:
161 except:
156 # FIXME: log the exception
162 # FIXME: log the exception
157 raise
163 raise
158
164
159 # formatters can return raw data or (data, metadata)
165 # formatters can return raw data or (data, metadata)
160 if isinstance(data, tuple) and len(data) == 2:
166 if isinstance(data, tuple) and len(data) == 2:
161 data, md = data
167 data, md = data
162
168
163 if data is not None:
169 if data is not None:
164 format_dict[format_type] = data
170 format_dict[format_type] = data
165 if md is not None:
171 if md is not None:
166 md_dict[format_type] = md
172 md_dict[format_type] = md
167
173
168 return format_dict, md_dict
174 return format_dict, md_dict
169
175
170 @property
176 @property
171 def format_types(self):
177 def format_types(self):
172 """Return the format types (MIME types) of the active formatters."""
178 """Return the format types (MIME types) of the active formatters."""
173 return list(self.formatters.keys())
179 return list(self.formatters.keys())
174
180
175
181
176 #-----------------------------------------------------------------------------
182 #-----------------------------------------------------------------------------
177 # Formatters for specific format types (text, html, svg, etc.)
183 # Formatters for specific format types (text, html, svg, etc.)
178 #-----------------------------------------------------------------------------
184 #-----------------------------------------------------------------------------
179
185
180
186
181 def _safe_repr(obj):
187 def _safe_repr(obj):
182 """Try to return a repr of an object
188 """Try to return a repr of an object
183
189
184 always returns a string, at least.
190 always returns a string, at least.
185 """
191 """
186 try:
192 try:
187 return repr(obj)
193 return repr(obj)
188 except Exception as e:
194 except Exception as e:
189 return "un-repr-able object (%r)" % e
195 return "un-repr-able object (%r)" % e
190
196
191
197
192 class FormatterWarning(UserWarning):
198 class FormatterWarning(UserWarning):
193 """Warning class for errors in formatters"""
199 """Warning class for errors in formatters"""
194
200
195 @decorator
201 @decorator
196 def catch_format_error(method, self, *args, **kwargs):
202 def catch_format_error(method, self, *args, **kwargs):
197 """show traceback on failed format call"""
203 """show traceback on failed format call"""
198 try:
204 try:
199 r = method(self, *args, **kwargs)
205 r = method(self, *args, **kwargs)
200 except NotImplementedError:
206 except NotImplementedError:
201 # don't warn on NotImplementedErrors
207 # don't warn on NotImplementedErrors
202 return None
208 return None
203 except Exception:
209 except Exception:
204 exc_info = sys.exc_info()
210 exc_info = sys.exc_info()
205 ip = get_ipython()
211 ip = get_ipython()
206 if ip is not None:
212 if ip is not None:
207 ip.showtraceback(exc_info)
213 ip.showtraceback(exc_info)
208 else:
214 else:
209 traceback.print_exception(*exc_info)
215 traceback.print_exception(*exc_info)
210 return None
216 return None
211 return self._check_return(r, args[0])
217 return self._check_return(r, args[0])
212
218
213
219
214 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
220 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
215 """ Abstract base class for Formatters.
221 """ Abstract base class for Formatters.
216
222
217 A formatter is a callable class that is responsible for computing the
223 A formatter is a callable class that is responsible for computing the
218 raw format data for a particular format type (MIME type). For example,
224 raw format data for a particular format type (MIME type). For example,
219 an HTML formatter would have a format type of `text/html` and would return
225 an HTML formatter would have a format type of `text/html` and would return
220 the HTML representation of the object when called.
226 the HTML representation of the object when called.
221 """
227 """
222
228
223 # The format type of the data returned, usually a MIME type.
229 # The format type of the data returned, usually a MIME type.
224 format_type = 'text/plain'
230 format_type = 'text/plain'
225
231
226 # Is the formatter enabled...
232 # Is the formatter enabled...
227 enabled = True
233 enabled = True
228
234
229 @abc.abstractmethod
235 @abc.abstractmethod
230 def __call__(self, obj):
236 def __call__(self, obj):
231 """Return a JSON'able representation of the object.
237 """Return a JSON'able representation of the object.
232
238
233 If the object cannot be formatted by this formatter,
239 If the object cannot be formatted by this formatter,
234 warn and return None.
240 warn and return None.
235 """
241 """
236 return repr(obj)
242 return repr(obj)
237
243
238
244
239 def _mod_name_key(typ):
245 def _mod_name_key(typ):
240 """Return a (__module__, __name__) tuple for a type.
246 """Return a (__module__, __name__) tuple for a type.
241
247
242 Used as key in Formatter.deferred_printers.
248 Used as key in Formatter.deferred_printers.
243 """
249 """
244 module = getattr(typ, '__module__', None)
250 module = getattr(typ, '__module__', None)
245 name = getattr(typ, '__name__', None)
251 name = getattr(typ, '__name__', None)
246 return (module, name)
252 return (module, name)
247
253
248
254
249 def _get_type(obj):
255 def _get_type(obj):
250 """Return the type of an instance (old and new-style)"""
256 """Return the type of an instance (old and new-style)"""
251 return getattr(obj, '__class__', None) or type(obj)
257 return getattr(obj, '__class__', None) or type(obj)
252
258
253
259
254 _raise_key_error = Sentinel('_raise_key_error', __name__,
260 _raise_key_error = Sentinel('_raise_key_error', __name__,
255 """
261 """
256 Special value to raise a KeyError
262 Special value to raise a KeyError
257
263
258 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
264 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
259 """)
265 """)
260
266
261
267
262 class BaseFormatter(Configurable):
268 class BaseFormatter(Configurable):
263 """A base formatter class that is configurable.
269 """A base formatter class that is configurable.
264
270
265 This formatter should usually be used as the base class of all formatters.
271 This formatter should usually be used as the base class of all formatters.
266 It is a traited :class:`Configurable` class and includes an extensible
272 It is a traited :class:`Configurable` class and includes an extensible
267 API for users to determine how their objects are formatted. The following
273 API for users to determine how their objects are formatted. The following
268 logic is used to find a function to format an given object.
274 logic is used to find a function to format an given object.
269
275
270 1. The object is introspected to see if it has a method with the name
276 1. The object is introspected to see if it has a method with the name
271 :attr:`print_method`. If is does, that object is passed to that method
277 :attr:`print_method`. If is does, that object is passed to that method
272 for formatting.
278 for formatting.
273 2. If no print method is found, three internal dictionaries are consulted
279 2. If no print method is found, three internal dictionaries are consulted
274 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
280 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
275 and :attr:`deferred_printers`.
281 and :attr:`deferred_printers`.
276
282
277 Users should use these dictionaries to register functions that will be
283 Users should use these dictionaries to register functions that will be
278 used to compute the format data for their objects (if those objects don't
284 used to compute the format data for their objects (if those objects don't
279 have the special print methods). The easiest way of using these
285 have the special print methods). The easiest way of using these
280 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
286 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
281 methods.
287 methods.
282
288
283 If no function/callable is found to compute the format data, ``None`` is
289 If no function/callable is found to compute the format data, ``None`` is
284 returned and this format type is not used.
290 returned and this format type is not used.
285 """
291 """
286
292
287 format_type = Unicode('text/plain')
293 format_type = Unicode('text/plain')
288 _return_type = string_types
294 _return_type = string_types
289
295
290 enabled = Bool(True).tag(config=True)
296 enabled = Bool(True).tag(config=True)
291
297
292 print_method = ObjectName('__repr__')
298 print_method = ObjectName('__repr__')
293
299
294 # The singleton printers.
300 # The singleton printers.
295 # Maps the IDs of the builtin singleton objects to the format functions.
301 # Maps the IDs of the builtin singleton objects to the format functions.
296 singleton_printers = Dict().tag(config=True)
302 singleton_printers = Dict().tag(config=True)
297
303
298 # The type-specific printers.
304 # The type-specific printers.
299 # Map type objects to the format functions.
305 # Map type objects to the format functions.
300 type_printers = Dict().tag(config=True)
306 type_printers = Dict().tag(config=True)
301
307
302 # The deferred-import type-specific printers.
308 # The deferred-import type-specific printers.
303 # Map (modulename, classname) pairs to the format functions.
309 # Map (modulename, classname) pairs to the format functions.
304 deferred_printers = Dict().tag(config=True)
310 deferred_printers = Dict().tag(config=True)
305
311
306 @catch_format_error
312 @catch_format_error
307 def __call__(self, obj):
313 def __call__(self, obj):
308 """Compute the format for an object."""
314 """Compute the format for an object."""
309 if self.enabled:
315 if self.enabled:
310 # lookup registered printer
316 # lookup registered printer
311 try:
317 try:
312 printer = self.lookup(obj)
318 printer = self.lookup(obj)
313 except KeyError:
319 except KeyError:
314 pass
320 pass
315 else:
321 else:
316 return printer(obj)
322 return printer(obj)
317 # Finally look for special method names
323 # Finally look for special method names
318 method = get_real_method(obj, self.print_method)
324 method = get_real_method(obj, self.print_method)
319 if method is not None:
325 if method is not None:
320 return method()
326 return method()
321 return None
327 return None
322 else:
328 else:
323 return None
329 return None
324
330
325 def __contains__(self, typ):
331 def __contains__(self, typ):
326 """map in to lookup_by_type"""
332 """map in to lookup_by_type"""
327 try:
333 try:
328 self.lookup_by_type(typ)
334 self.lookup_by_type(typ)
329 except KeyError:
335 except KeyError:
330 return False
336 return False
331 else:
337 else:
332 return True
338 return True
333
339
334 def _check_return(self, r, obj):
340 def _check_return(self, r, obj):
335 """Check that a return value is appropriate
341 """Check that a return value is appropriate
336
342
337 Return the value if so, None otherwise, warning if invalid.
343 Return the value if so, None otherwise, warning if invalid.
338 """
344 """
339 if r is None or isinstance(r, self._return_type) or \
345 if r is None or isinstance(r, self._return_type) or \
340 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
346 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
341 return r
347 return r
342 else:
348 else:
343 warnings.warn(
349 warnings.warn(
344 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
350 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
345 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
351 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
346 FormatterWarning
352 FormatterWarning
347 )
353 )
348
354
349 def lookup(self, obj):
355 def lookup(self, obj):
350 """Look up the formatter for a given instance.
356 """Look up the formatter for a given instance.
351
357
352 Parameters
358 Parameters
353 ----------
359 ----------
354 obj : object instance
360 obj : object instance
355
361
356 Returns
362 Returns
357 -------
363 -------
358 f : callable
364 f : callable
359 The registered formatting callable for the type.
365 The registered formatting callable for the type.
360
366
361 Raises
367 Raises
362 ------
368 ------
363 KeyError if the type has not been registered.
369 KeyError if the type has not been registered.
364 """
370 """
365 # look for singleton first
371 # look for singleton first
366 obj_id = id(obj)
372 obj_id = id(obj)
367 if obj_id in self.singleton_printers:
373 if obj_id in self.singleton_printers:
368 return self.singleton_printers[obj_id]
374 return self.singleton_printers[obj_id]
369 # then lookup by type
375 # then lookup by type
370 return self.lookup_by_type(_get_type(obj))
376 return self.lookup_by_type(_get_type(obj))
371
377
372 def lookup_by_type(self, typ):
378 def lookup_by_type(self, typ):
373 """Look up the registered formatter for a type.
379 """Look up the registered formatter for a type.
374
380
375 Parameters
381 Parameters
376 ----------
382 ----------
377 typ : type or '__module__.__name__' string for a type
383 typ : type or '__module__.__name__' string for a type
378
384
379 Returns
385 Returns
380 -------
386 -------
381 f : callable
387 f : callable
382 The registered formatting callable for the type.
388 The registered formatting callable for the type.
383
389
384 Raises
390 Raises
385 ------
391 ------
386 KeyError if the type has not been registered.
392 KeyError if the type has not been registered.
387 """
393 """
388 if isinstance(typ, string_types):
394 if isinstance(typ, string_types):
389 typ_key = tuple(typ.rsplit('.',1))
395 typ_key = tuple(typ.rsplit('.',1))
390 if typ_key not in self.deferred_printers:
396 if typ_key not in self.deferred_printers:
391 # We may have it cached in the type map. We will have to
397 # We may have it cached in the type map. We will have to
392 # iterate over all of the types to check.
398 # iterate over all of the types to check.
393 for cls in self.type_printers:
399 for cls in self.type_printers:
394 if _mod_name_key(cls) == typ_key:
400 if _mod_name_key(cls) == typ_key:
395 return self.type_printers[cls]
401 return self.type_printers[cls]
396 else:
402 else:
397 return self.deferred_printers[typ_key]
403 return self.deferred_printers[typ_key]
398 else:
404 else:
399 for cls in pretty._get_mro(typ):
405 for cls in pretty._get_mro(typ):
400 if cls in self.type_printers or self._in_deferred_types(cls):
406 if cls in self.type_printers or self._in_deferred_types(cls):
401 return self.type_printers[cls]
407 return self.type_printers[cls]
402
408
403 # If we have reached here, the lookup failed.
409 # If we have reached here, the lookup failed.
404 raise KeyError("No registered printer for {0!r}".format(typ))
410 raise KeyError("No registered printer for {0!r}".format(typ))
405
411
406 def for_type(self, typ, func=None):
412 def for_type(self, typ, func=None):
407 """Add a format function for a given type.
413 """Add a format function for a given type.
408
414
409 Parameters
415 Parameters
410 -----------
416 -----------
411 typ : type or '__module__.__name__' string for a type
417 typ : type or '__module__.__name__' string for a type
412 The class of the object that will be formatted using `func`.
418 The class of the object that will be formatted using `func`.
413 func : callable
419 func : callable
414 A callable for computing the format data.
420 A callable for computing the format data.
415 `func` will be called with the object to be formatted,
421 `func` will be called with the object to be formatted,
416 and will return the raw data in this formatter's format.
422 and will return the raw data in this formatter's format.
417 Subclasses may use a different call signature for the
423 Subclasses may use a different call signature for the
418 `func` argument.
424 `func` argument.
419
425
420 If `func` is None or not specified, there will be no change,
426 If `func` is None or not specified, there will be no change,
421 only returning the current value.
427 only returning the current value.
422
428
423 Returns
429 Returns
424 -------
430 -------
425 oldfunc : callable
431 oldfunc : callable
426 The currently registered callable.
432 The currently registered callable.
427 If you are registering a new formatter,
433 If you are registering a new formatter,
428 this will be the previous value (to enable restoring later).
434 this will be the previous value (to enable restoring later).
429 """
435 """
430 # if string given, interpret as 'pkg.module.class_name'
436 # if string given, interpret as 'pkg.module.class_name'
431 if isinstance(typ, string_types):
437 if isinstance(typ, string_types):
432 type_module, type_name = typ.rsplit('.', 1)
438 type_module, type_name = typ.rsplit('.', 1)
433 return self.for_type_by_name(type_module, type_name, func)
439 return self.for_type_by_name(type_module, type_name, func)
434
440
435 try:
441 try:
436 oldfunc = self.lookup_by_type(typ)
442 oldfunc = self.lookup_by_type(typ)
437 except KeyError:
443 except KeyError:
438 oldfunc = None
444 oldfunc = None
439
445
440 if func is not None:
446 if func is not None:
441 self.type_printers[typ] = func
447 self.type_printers[typ] = func
442
448
443 return oldfunc
449 return oldfunc
444
450
445 def for_type_by_name(self, type_module, type_name, func=None):
451 def for_type_by_name(self, type_module, type_name, func=None):
446 """Add a format function for a type specified by the full dotted
452 """Add a format function for a type specified by the full dotted
447 module and name of the type, rather than the type of the object.
453 module and name of the type, rather than the type of the object.
448
454
449 Parameters
455 Parameters
450 ----------
456 ----------
451 type_module : str
457 type_module : str
452 The full dotted name of the module the type is defined in, like
458 The full dotted name of the module the type is defined in, like
453 ``numpy``.
459 ``numpy``.
454 type_name : str
460 type_name : str
455 The name of the type (the class name), like ``dtype``
461 The name of the type (the class name), like ``dtype``
456 func : callable
462 func : callable
457 A callable for computing the format data.
463 A callable for computing the format data.
458 `func` will be called with the object to be formatted,
464 `func` will be called with the object to be formatted,
459 and will return the raw data in this formatter's format.
465 and will return the raw data in this formatter's format.
460 Subclasses may use a different call signature for the
466 Subclasses may use a different call signature for the
461 `func` argument.
467 `func` argument.
462
468
463 If `func` is None or unspecified, there will be no change,
469 If `func` is None or unspecified, there will be no change,
464 only returning the current value.
470 only returning the current value.
465
471
466 Returns
472 Returns
467 -------
473 -------
468 oldfunc : callable
474 oldfunc : callable
469 The currently registered callable.
475 The currently registered callable.
470 If you are registering a new formatter,
476 If you are registering a new formatter,
471 this will be the previous value (to enable restoring later).
477 this will be the previous value (to enable restoring later).
472 """
478 """
473 key = (type_module, type_name)
479 key = (type_module, type_name)
474
480
475 try:
481 try:
476 oldfunc = self.lookup_by_type("%s.%s" % key)
482 oldfunc = self.lookup_by_type("%s.%s" % key)
477 except KeyError:
483 except KeyError:
478 oldfunc = None
484 oldfunc = None
479
485
480 if func is not None:
486 if func is not None:
481 self.deferred_printers[key] = func
487 self.deferred_printers[key] = func
482 return oldfunc
488 return oldfunc
483
489
484 def pop(self, typ, default=_raise_key_error):
490 def pop(self, typ, default=_raise_key_error):
485 """Pop a formatter for the given type.
491 """Pop a formatter for the given type.
486
492
487 Parameters
493 Parameters
488 ----------
494 ----------
489 typ : type or '__module__.__name__' string for a type
495 typ : type or '__module__.__name__' string for a type
490 default : object
496 default : object
491 value to be returned if no formatter is registered for typ.
497 value to be returned if no formatter is registered for typ.
492
498
493 Returns
499 Returns
494 -------
500 -------
495 obj : object
501 obj : object
496 The last registered object for the type.
502 The last registered object for the type.
497
503
498 Raises
504 Raises
499 ------
505 ------
500 KeyError if the type is not registered and default is not specified.
506 KeyError if the type is not registered and default is not specified.
501 """
507 """
502
508
503 if isinstance(typ, string_types):
509 if isinstance(typ, string_types):
504 typ_key = tuple(typ.rsplit('.',1))
510 typ_key = tuple(typ.rsplit('.',1))
505 if typ_key not in self.deferred_printers:
511 if typ_key not in self.deferred_printers:
506 # We may have it cached in the type map. We will have to
512 # We may have it cached in the type map. We will have to
507 # iterate over all of the types to check.
513 # iterate over all of the types to check.
508 for cls in self.type_printers:
514 for cls in self.type_printers:
509 if _mod_name_key(cls) == typ_key:
515 if _mod_name_key(cls) == typ_key:
510 old = self.type_printers.pop(cls)
516 old = self.type_printers.pop(cls)
511 break
517 break
512 else:
518 else:
513 old = default
519 old = default
514 else:
520 else:
515 old = self.deferred_printers.pop(typ_key)
521 old = self.deferred_printers.pop(typ_key)
516 else:
522 else:
517 if typ in self.type_printers:
523 if typ in self.type_printers:
518 old = self.type_printers.pop(typ)
524 old = self.type_printers.pop(typ)
519 else:
525 else:
520 old = self.deferred_printers.pop(_mod_name_key(typ), default)
526 old = self.deferred_printers.pop(_mod_name_key(typ), default)
521 if old is _raise_key_error:
527 if old is _raise_key_error:
522 raise KeyError("No registered value for {0!r}".format(typ))
528 raise KeyError("No registered value for {0!r}".format(typ))
523 return old
529 return old
524
530
525 def _in_deferred_types(self, cls):
531 def _in_deferred_types(self, cls):
526 """
532 """
527 Check if the given class is specified in the deferred type registry.
533 Check if the given class is specified in the deferred type registry.
528
534
529 Successful matches will be moved to the regular type registry for future use.
535 Successful matches will be moved to the regular type registry for future use.
530 """
536 """
531 mod = getattr(cls, '__module__', None)
537 mod = getattr(cls, '__module__', None)
532 name = getattr(cls, '__name__', None)
538 name = getattr(cls, '__name__', None)
533 key = (mod, name)
539 key = (mod, name)
534 if key in self.deferred_printers:
540 if key in self.deferred_printers:
535 # Move the printer over to the regular registry.
541 # Move the printer over to the regular registry.
536 printer = self.deferred_printers.pop(key)
542 printer = self.deferred_printers.pop(key)
537 self.type_printers[cls] = printer
543 self.type_printers[cls] = printer
538 return True
544 return True
539 return False
545 return False
540
546
541
547
542 class PlainTextFormatter(BaseFormatter):
548 class PlainTextFormatter(BaseFormatter):
543 """The default pretty-printer.
549 """The default pretty-printer.
544
550
545 This uses :mod:`IPython.lib.pretty` to compute the format data of
551 This uses :mod:`IPython.lib.pretty` to compute the format data of
546 the object. If the object cannot be pretty printed, :func:`repr` is used.
552 the object. If the object cannot be pretty printed, :func:`repr` is used.
547 See the documentation of :mod:`IPython.lib.pretty` for details on
553 See the documentation of :mod:`IPython.lib.pretty` for details on
548 how to write pretty printers. Here is a simple example::
554 how to write pretty printers. Here is a simple example::
549
555
550 def dtype_pprinter(obj, p, cycle):
556 def dtype_pprinter(obj, p, cycle):
551 if cycle:
557 if cycle:
552 return p.text('dtype(...)')
558 return p.text('dtype(...)')
553 if hasattr(obj, 'fields'):
559 if hasattr(obj, 'fields'):
554 if obj.fields is None:
560 if obj.fields is None:
555 p.text(repr(obj))
561 p.text(repr(obj))
556 else:
562 else:
557 p.begin_group(7, 'dtype([')
563 p.begin_group(7, 'dtype([')
558 for i, field in enumerate(obj.descr):
564 for i, field in enumerate(obj.descr):
559 if i > 0:
565 if i > 0:
560 p.text(',')
566 p.text(',')
561 p.breakable()
567 p.breakable()
562 p.pretty(field)
568 p.pretty(field)
563 p.end_group(7, '])')
569 p.end_group(7, '])')
564 """
570 """
565
571
566 # The format type of data returned.
572 # The format type of data returned.
567 format_type = Unicode('text/plain')
573 format_type = Unicode('text/plain')
568
574
569 # This subclass ignores this attribute as it always need to return
575 # This subclass ignores this attribute as it always need to return
570 # something.
576 # something.
571 enabled = Bool(True).tag(config=False)
577 enabled = Bool(True).tag(config=False)
572
578
573 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH).tag(config=True,
579 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
574 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
580 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
575
581
576 Set to 0 to disable truncation.
582 Set to 0 to disable truncation.
577 """
583 """
578 )
584 ).tag(config=True)
579
585
580 # Look for a _repr_pretty_ methods to use for pretty printing.
586 # Look for a _repr_pretty_ methods to use for pretty printing.
581 print_method = ObjectName('_repr_pretty_')
587 print_method = ObjectName('_repr_pretty_')
582
588
583 # Whether to pretty-print or not.
589 # Whether to pretty-print or not.
584 pprint = Bool(True).tag(config=True)
590 pprint = Bool(True).tag(config=True)
585
591
586 # Whether to be verbose or not.
592 # Whether to be verbose or not.
587 verbose = Bool(False).tag(config=True)
593 verbose = Bool(False).tag(config=True)
588
594
589 # The maximum width.
595 # The maximum width.
590 max_width = Integer(79).tag(config=True)
596 max_width = Integer(79).tag(config=True)
591
597
592 # The newline character.
598 # The newline character.
593 newline = Unicode('\n').tag(config=True)
599 newline = Unicode('\n').tag(config=True)
594
600
595 # format-string for pprinting floats
601 # format-string for pprinting floats
596 float_format = Unicode('%r')
602 float_format = Unicode('%r')
597 # setter for float precision, either int or direct format-string
603 # setter for float precision, either int or direct format-string
598 float_precision = CUnicode('').tag(config=True)
604 float_precision = CUnicode('').tag(config=True)
599
605
600 def _float_precision_changed(self, name, old, new):
606 def _float_precision_changed(self, name, old, new):
601 """float_precision changed, set float_format accordingly.
607 """float_precision changed, set float_format accordingly.
602
608
603 float_precision can be set by int or str.
609 float_precision can be set by int or str.
604 This will set float_format, after interpreting input.
610 This will set float_format, after interpreting input.
605 If numpy has been imported, numpy print precision will also be set.
611 If numpy has been imported, numpy print precision will also be set.
606
612
607 integer `n` sets format to '%.nf', otherwise, format set directly.
613 integer `n` sets format to '%.nf', otherwise, format set directly.
608
614
609 An empty string returns to defaults (repr for float, 8 for numpy).
615 An empty string returns to defaults (repr for float, 8 for numpy).
610
616
611 This parameter can be set via the '%precision' magic.
617 This parameter can be set via the '%precision' magic.
612 """
618 """
613
619
614 if '%' in new:
620 if '%' in new:
615 # got explicit format string
621 # got explicit format string
616 fmt = new
622 fmt = new
617 try:
623 try:
618 fmt%3.14159
624 fmt%3.14159
619 except Exception:
625 except Exception:
620 raise ValueError("Precision must be int or format string, not %r"%new)
626 raise ValueError("Precision must be int or format string, not %r"%new)
621 elif new:
627 elif new:
622 # otherwise, should be an int
628 # otherwise, should be an int
623 try:
629 try:
624 i = int(new)
630 i = int(new)
625 assert i >= 0
631 assert i >= 0
626 except ValueError:
632 except ValueError:
627 raise ValueError("Precision must be int or format string, not %r"%new)
633 raise ValueError("Precision must be int or format string, not %r"%new)
628 except AssertionError:
634 except AssertionError:
629 raise ValueError("int precision must be non-negative, not %r"%i)
635 raise ValueError("int precision must be non-negative, not %r"%i)
630
636
631 fmt = '%%.%if'%i
637 fmt = '%%.%if'%i
632 if 'numpy' in sys.modules:
638 if 'numpy' in sys.modules:
633 # set numpy precision if it has been imported
639 # set numpy precision if it has been imported
634 import numpy
640 import numpy
635 numpy.set_printoptions(precision=i)
641 numpy.set_printoptions(precision=i)
636 else:
642 else:
637 # default back to repr
643 # default back to repr
638 fmt = '%r'
644 fmt = '%r'
639 if 'numpy' in sys.modules:
645 if 'numpy' in sys.modules:
640 import numpy
646 import numpy
641 # numpy default is 8
647 # numpy default is 8
642 numpy.set_printoptions(precision=8)
648 numpy.set_printoptions(precision=8)
643 self.float_format = fmt
649 self.float_format = fmt
644
650
645 # Use the default pretty printers from IPython.lib.pretty.
651 # Use the default pretty printers from IPython.lib.pretty.
652 @default('singleton_printers')
646 def _singleton_printers_default(self):
653 def _singleton_printers_default(self):
647 return pretty._singleton_pprinters.copy()
654 return pretty._singleton_pprinters.copy()
648
655
656 @default('type_printers')
649 def _type_printers_default(self):
657 def _type_printers_default(self):
650 d = pretty._type_pprinters.copy()
658 d = pretty._type_pprinters.copy()
651 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
659 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
652 return d
660 return d
653
661
662 @default('deferred_printers')
654 def _deferred_printers_default(self):
663 def _deferred_printers_default(self):
655 return pretty._deferred_type_pprinters.copy()
664 return pretty._deferred_type_pprinters.copy()
656
665
657 #### FormatterABC interface ####
666 #### FormatterABC interface ####
658
667
659 @catch_format_error
668 @catch_format_error
660 def __call__(self, obj):
669 def __call__(self, obj):
661 """Compute the pretty representation of the object."""
670 """Compute the pretty representation of the object."""
662 if not self.pprint:
671 if not self.pprint:
663 return repr(obj)
672 return repr(obj)
664 else:
673 else:
665 # handle str and unicode on Python 2
674 # handle str and unicode on Python 2
666 # io.StringIO only accepts unicode,
675 # io.StringIO only accepts unicode,
667 # cStringIO doesn't handle unicode on py2,
676 # cStringIO doesn't handle unicode on py2,
668 # StringIO allows str, unicode but only ascii str
677 # StringIO allows str, unicode but only ascii str
669 stream = pretty.CUnicodeIO()
678 stream = pretty.CUnicodeIO()
670 printer = pretty.RepresentationPrinter(stream, self.verbose,
679 printer = pretty.RepresentationPrinter(stream, self.verbose,
671 self.max_width, self.newline,
680 self.max_width, self.newline,
672 max_seq_length=self.max_seq_length,
681 max_seq_length=self.max_seq_length,
673 singleton_pprinters=self.singleton_printers,
682 singleton_pprinters=self.singleton_printers,
674 type_pprinters=self.type_printers,
683 type_pprinters=self.type_printers,
675 deferred_pprinters=self.deferred_printers)
684 deferred_pprinters=self.deferred_printers)
676 printer.pretty(obj)
685 printer.pretty(obj)
677 printer.flush()
686 printer.flush()
678 return stream.getvalue()
687 return stream.getvalue()
679
688
680
689
681 class HTMLFormatter(BaseFormatter):
690 class HTMLFormatter(BaseFormatter):
682 """An HTML formatter.
691 """An HTML formatter.
683
692
684 To define the callables that compute the HTML representation of your
693 To define the callables that compute the HTML representation of your
685 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
694 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
686 or :meth:`for_type_by_name` methods to register functions that handle
695 or :meth:`for_type_by_name` methods to register functions that handle
687 this.
696 this.
688
697
689 The return value of this formatter should be a valid HTML snippet that
698 The return value of this formatter should be a valid HTML snippet that
690 could be injected into an existing DOM. It should *not* include the
699 could be injected into an existing DOM. It should *not* include the
691 ```<html>`` or ```<body>`` tags.
700 ```<html>`` or ```<body>`` tags.
692 """
701 """
693 format_type = Unicode('text/html')
702 format_type = Unicode('text/html')
694
703
695 print_method = ObjectName('_repr_html_')
704 print_method = ObjectName('_repr_html_')
696
705
697
706
698 class MarkdownFormatter(BaseFormatter):
707 class MarkdownFormatter(BaseFormatter):
699 """A Markdown formatter.
708 """A Markdown formatter.
700
709
701 To define the callables that compute the Markdown representation of your
710 To define the callables that compute the Markdown representation of your
702 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
711 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
703 or :meth:`for_type_by_name` methods to register functions that handle
712 or :meth:`for_type_by_name` methods to register functions that handle
704 this.
713 this.
705
714
706 The return value of this formatter should be a valid Markdown.
715 The return value of this formatter should be a valid Markdown.
707 """
716 """
708 format_type = Unicode('text/markdown')
717 format_type = Unicode('text/markdown')
709
718
710 print_method = ObjectName('_repr_markdown_')
719 print_method = ObjectName('_repr_markdown_')
711
720
712 class SVGFormatter(BaseFormatter):
721 class SVGFormatter(BaseFormatter):
713 """An SVG formatter.
722 """An SVG formatter.
714
723
715 To define the callables that compute the SVG representation of your
724 To define the callables that compute the SVG representation of your
716 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
725 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
717 or :meth:`for_type_by_name` methods to register functions that handle
726 or :meth:`for_type_by_name` methods to register functions that handle
718 this.
727 this.
719
728
720 The return value of this formatter should be valid SVG enclosed in
729 The return value of this formatter should be valid SVG enclosed in
721 ```<svg>``` tags, that could be injected into an existing DOM. It should
730 ```<svg>``` tags, that could be injected into an existing DOM. It should
722 *not* include the ```<html>`` or ```<body>`` tags.
731 *not* include the ```<html>`` or ```<body>`` tags.
723 """
732 """
724 format_type = Unicode('image/svg+xml')
733 format_type = Unicode('image/svg+xml')
725
734
726 print_method = ObjectName('_repr_svg_')
735 print_method = ObjectName('_repr_svg_')
727
736
728
737
729 class PNGFormatter(BaseFormatter):
738 class PNGFormatter(BaseFormatter):
730 """A PNG formatter.
739 """A PNG formatter.
731
740
732 To define the callables that compute the PNG representation of your
741 To define the callables that compute the PNG representation of your
733 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
742 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
734 or :meth:`for_type_by_name` methods to register functions that handle
743 or :meth:`for_type_by_name` methods to register functions that handle
735 this.
744 this.
736
745
737 The return value of this formatter should be raw PNG data, *not*
746 The return value of this formatter should be raw PNG data, *not*
738 base64 encoded.
747 base64 encoded.
739 """
748 """
740 format_type = Unicode('image/png')
749 format_type = Unicode('image/png')
741
750
742 print_method = ObjectName('_repr_png_')
751 print_method = ObjectName('_repr_png_')
743
752
744 _return_type = (bytes, unicode_type)
753 _return_type = (bytes, unicode_type)
745
754
746
755
747 class JPEGFormatter(BaseFormatter):
756 class JPEGFormatter(BaseFormatter):
748 """A JPEG formatter.
757 """A JPEG formatter.
749
758
750 To define the callables that compute the JPEG representation of your
759 To define the callables that compute the JPEG representation of your
751 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
760 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
752 or :meth:`for_type_by_name` methods to register functions that handle
761 or :meth:`for_type_by_name` methods to register functions that handle
753 this.
762 this.
754
763
755 The return value of this formatter should be raw JPEG data, *not*
764 The return value of this formatter should be raw JPEG data, *not*
756 base64 encoded.
765 base64 encoded.
757 """
766 """
758 format_type = Unicode('image/jpeg')
767 format_type = Unicode('image/jpeg')
759
768
760 print_method = ObjectName('_repr_jpeg_')
769 print_method = ObjectName('_repr_jpeg_')
761
770
762 _return_type = (bytes, unicode_type)
771 _return_type = (bytes, unicode_type)
763
772
764
773
765 class LatexFormatter(BaseFormatter):
774 class LatexFormatter(BaseFormatter):
766 """A LaTeX formatter.
775 """A LaTeX formatter.
767
776
768 To define the callables that compute the LaTeX representation of your
777 To define the callables that compute the LaTeX representation of your
769 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
778 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
770 or :meth:`for_type_by_name` methods to register functions that handle
779 or :meth:`for_type_by_name` methods to register functions that handle
771 this.
780 this.
772
781
773 The return value of this formatter should be a valid LaTeX equation,
782 The return value of this formatter should be a valid LaTeX equation,
774 enclosed in either ```$```, ```$$``` or another LaTeX equation
783 enclosed in either ```$```, ```$$``` or another LaTeX equation
775 environment.
784 environment.
776 """
785 """
777 format_type = Unicode('text/latex')
786 format_type = Unicode('text/latex')
778
787
779 print_method = ObjectName('_repr_latex_')
788 print_method = ObjectName('_repr_latex_')
780
789
781
790
782 class JSONFormatter(BaseFormatter):
791 class JSONFormatter(BaseFormatter):
783 """A JSON string formatter.
792 """A JSON string formatter.
784
793
785 To define the callables that compute the JSONable representation of
794 To define the callables that compute the JSONable representation of
786 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
795 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
787 or :meth:`for_type_by_name` methods to register functions that handle
796 or :meth:`for_type_by_name` methods to register functions that handle
788 this.
797 this.
789
798
790 The return value of this formatter should be a JSONable list or dict.
799 The return value of this formatter should be a JSONable list or dict.
791 JSON scalars (None, number, string) are not allowed, only dict or list containers.
800 JSON scalars (None, number, string) are not allowed, only dict or list containers.
792 """
801 """
793 format_type = Unicode('application/json')
802 format_type = Unicode('application/json')
794 _return_type = (list, dict)
803 _return_type = (list, dict)
795
804
796 print_method = ObjectName('_repr_json_')
805 print_method = ObjectName('_repr_json_')
797
806
798 def _check_return(self, r, obj):
807 def _check_return(self, r, obj):
799 """Check that a return value is appropriate
808 """Check that a return value is appropriate
800
809
801 Return the value if so, None otherwise, warning if invalid.
810 Return the value if so, None otherwise, warning if invalid.
802 """
811 """
803 if r is None:
812 if r is None:
804 return
813 return
805 md = None
814 md = None
806 if isinstance(r, tuple):
815 if isinstance(r, tuple):
807 # unpack data, metadata tuple for type checking on first element
816 # unpack data, metadata tuple for type checking on first element
808 r, md = r
817 r, md = r
809
818
810 # handle deprecated JSON-as-string form from IPython < 3
819 # handle deprecated JSON-as-string form from IPython < 3
811 if isinstance(r, string_types):
820 if isinstance(r, string_types):
812 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
821 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
813 FormatterWarning)
822 FormatterWarning)
814 r = json.loads(r)
823 r = json.loads(r)
815
824
816 if md is not None:
825 if md is not None:
817 # put the tuple back together
826 # put the tuple back together
818 r = (r, md)
827 r = (r, md)
819 return super(JSONFormatter, self)._check_return(r, obj)
828 return super(JSONFormatter, self)._check_return(r, obj)
820
829
821
830
822 class JavascriptFormatter(BaseFormatter):
831 class JavascriptFormatter(BaseFormatter):
823 """A Javascript formatter.
832 """A Javascript formatter.
824
833
825 To define the callables that compute the Javascript representation of
834 To define the callables that compute the Javascript representation of
826 your objects, define a :meth:`_repr_javascript_` method or use the
835 your objects, define a :meth:`_repr_javascript_` method or use the
827 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
836 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
828 that handle this.
837 that handle this.
829
838
830 The return value of this formatter should be valid Javascript code and
839 The return value of this formatter should be valid Javascript code and
831 should *not* be enclosed in ```<script>``` tags.
840 should *not* be enclosed in ```<script>``` tags.
832 """
841 """
833 format_type = Unicode('application/javascript')
842 format_type = Unicode('application/javascript')
834
843
835 print_method = ObjectName('_repr_javascript_')
844 print_method = ObjectName('_repr_javascript_')
836
845
837
846
838 class PDFFormatter(BaseFormatter):
847 class PDFFormatter(BaseFormatter):
839 """A PDF formatter.
848 """A PDF formatter.
840
849
841 To define the callables that compute the PDF representation of your
850 To define the callables that compute the PDF representation of your
842 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
851 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
843 or :meth:`for_type_by_name` methods to register functions that handle
852 or :meth:`for_type_by_name` methods to register functions that handle
844 this.
853 this.
845
854
846 The return value of this formatter should be raw PDF data, *not*
855 The return value of this formatter should be raw PDF data, *not*
847 base64 encoded.
856 base64 encoded.
848 """
857 """
849 format_type = Unicode('application/pdf')
858 format_type = Unicode('application/pdf')
850
859
851 print_method = ObjectName('_repr_pdf_')
860 print_method = ObjectName('_repr_pdf_')
852
861
853 _return_type = (bytes, unicode_type)
862 _return_type = (bytes, unicode_type)
854
863
855 class IPythonDisplayFormatter(BaseFormatter):
864 class IPythonDisplayFormatter(BaseFormatter):
856 """A Formatter for objects that know how to display themselves.
865 """A Formatter for objects that know how to display themselves.
857
866
858 To define the callables that compute the representation of your
867 To define the callables that compute the representation of your
859 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
868 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
860 or :meth:`for_type_by_name` methods to register functions that handle
869 or :meth:`for_type_by_name` methods to register functions that handle
861 this. Unlike mime-type displays, this method should not return anything,
870 this. Unlike mime-type displays, this method should not return anything,
862 instead calling any appropriate display methods itself.
871 instead calling any appropriate display methods itself.
863
872
864 This display formatter has highest priority.
873 This display formatter has highest priority.
865 If it fires, no other display formatter will be called.
874 If it fires, no other display formatter will be called.
866 """
875 """
867 print_method = ObjectName('_ipython_display_')
876 print_method = ObjectName('_ipython_display_')
868 _return_type = (type(None), bool)
877 _return_type = (type(None), bool)
869
878
870
879
871 @catch_format_error
880 @catch_format_error
872 def __call__(self, obj):
881 def __call__(self, obj):
873 """Compute the format for an object."""
882 """Compute the format for an object."""
874 if self.enabled:
883 if self.enabled:
875 # lookup registered printer
884 # lookup registered printer
876 try:
885 try:
877 printer = self.lookup(obj)
886 printer = self.lookup(obj)
878 except KeyError:
887 except KeyError:
879 pass
888 pass
880 else:
889 else:
881 printer(obj)
890 printer(obj)
882 return True
891 return True
883 # Finally look for special method names
892 # Finally look for special method names
884 method = get_real_method(obj, self.print_method)
893 method = get_real_method(obj, self.print_method)
885 if method is not None:
894 if method is not None:
886 method()
895 method()
887 return True
896 return True
888
897
889
898
890 FormatterABC.register(BaseFormatter)
899 FormatterABC.register(BaseFormatter)
891 FormatterABC.register(PlainTextFormatter)
900 FormatterABC.register(PlainTextFormatter)
892 FormatterABC.register(HTMLFormatter)
901 FormatterABC.register(HTMLFormatter)
893 FormatterABC.register(MarkdownFormatter)
902 FormatterABC.register(MarkdownFormatter)
894 FormatterABC.register(SVGFormatter)
903 FormatterABC.register(SVGFormatter)
895 FormatterABC.register(PNGFormatter)
904 FormatterABC.register(PNGFormatter)
896 FormatterABC.register(PDFFormatter)
905 FormatterABC.register(PDFFormatter)
897 FormatterABC.register(JPEGFormatter)
906 FormatterABC.register(JPEGFormatter)
898 FormatterABC.register(LatexFormatter)
907 FormatterABC.register(LatexFormatter)
899 FormatterABC.register(JSONFormatter)
908 FormatterABC.register(JSONFormatter)
900 FormatterABC.register(JavascriptFormatter)
909 FormatterABC.register(JavascriptFormatter)
901 FormatterABC.register(IPythonDisplayFormatter)
910 FormatterABC.register(IPythonDisplayFormatter)
902
911
903
912
904 def format_display_data(obj, include=None, exclude=None):
913 def format_display_data(obj, include=None, exclude=None):
905 """Return a format data dict for an object.
914 """Return a format data dict for an object.
906
915
907 By default all format types will be computed.
916 By default all format types will be computed.
908
917
909 The following MIME types are currently implemented:
918 The following MIME types are currently implemented:
910
919
911 * text/plain
920 * text/plain
912 * text/html
921 * text/html
913 * text/markdown
922 * text/markdown
914 * text/latex
923 * text/latex
915 * application/json
924 * application/json
916 * application/javascript
925 * application/javascript
917 * application/pdf
926 * application/pdf
918 * image/png
927 * image/png
919 * image/jpeg
928 * image/jpeg
920 * image/svg+xml
929 * image/svg+xml
921
930
922 Parameters
931 Parameters
923 ----------
932 ----------
924 obj : object
933 obj : object
925 The Python object whose format data will be computed.
934 The Python object whose format data will be computed.
926
935
927 Returns
936 Returns
928 -------
937 -------
929 format_dict : dict
938 format_dict : dict
930 A dictionary of key/value pairs, one or each format that was
939 A dictionary of key/value pairs, one or each format that was
931 generated for the object. The keys are the format types, which
940 generated for the object. The keys are the format types, which
932 will usually be MIME type strings and the values and JSON'able
941 will usually be MIME type strings and the values and JSON'able
933 data structure containing the raw data for the representation in
942 data structure containing the raw data for the representation in
934 that format.
943 that format.
935 include : list or tuple, optional
944 include : list or tuple, optional
936 A list of format type strings (MIME types) to include in the
945 A list of format type strings (MIME types) to include in the
937 format data dict. If this is set *only* the format types included
946 format data dict. If this is set *only* the format types included
938 in this list will be computed.
947 in this list will be computed.
939 exclude : list or tuple, optional
948 exclude : list or tuple, optional
940 A list of format type string (MIME types) to exclue in the format
949 A list of format type string (MIME types) to exclue in the format
941 data dict. If this is set all format types will be computed,
950 data dict. If this is set all format types will be computed,
942 except for those included in this argument.
951 except for those included in this argument.
943 """
952 """
944 from IPython.core.interactiveshell import InteractiveShell
953 from IPython.core.interactiveshell import InteractiveShell
945
954
946 return InteractiveShell.instance().display_formatter.format(
955 return InteractiveShell.instance().display_formatter.format(
947 obj,
956 obj,
948 include,
957 include,
949 exclude
958 exclude
950 )
959 )
951
960
@@ -1,904 +1,908 b''
1 """ History related magics and functionality """
1 """ History related magics and functionality """
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 from __future__ import print_function
6 from __future__ import print_function
7
7
8 import atexit
8 import atexit
9 import datetime
9 import datetime
10 import os
10 import os
11 import re
11 import re
12 try:
12 try:
13 import sqlite3
13 import sqlite3
14 except ImportError:
14 except ImportError:
15 try:
15 try:
16 from pysqlite2 import dbapi2 as sqlite3
16 from pysqlite2 import dbapi2 as sqlite3
17 except ImportError:
17 except ImportError:
18 sqlite3 = None
18 sqlite3 = None
19 import threading
19 import threading
20
20
21 from traitlets.config.configurable import LoggingConfigurable
21 from traitlets.config.configurable import LoggingConfigurable
22 from decorator import decorator
22 from decorator import decorator
23 from IPython.utils.decorators import undoc
23 from IPython.utils.decorators import undoc
24 from IPython.utils.path import locate_profile
24 from IPython.utils.path import locate_profile
25 from IPython.utils import py3compat
25 from IPython.utils import py3compat
26 from traitlets import (
26 from traitlets import (
27 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
27 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
28 default, observe,
28 )
29 )
29 from warnings import warn
30 from warnings import warn
30
31
31 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
32 # Classes and functions
33 # Classes and functions
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34
35
35 @undoc
36 @undoc
36 class DummyDB(object):
37 class DummyDB(object):
37 """Dummy DB that will act as a black hole for history.
38 """Dummy DB that will act as a black hole for history.
38
39
39 Only used in the absence of sqlite"""
40 Only used in the absence of sqlite"""
40 def execute(*args, **kwargs):
41 def execute(*args, **kwargs):
41 return []
42 return []
42
43
43 def commit(self, *args, **kwargs):
44 def commit(self, *args, **kwargs):
44 pass
45 pass
45
46
46 def __enter__(self, *args, **kwargs):
47 def __enter__(self, *args, **kwargs):
47 pass
48 pass
48
49
49 def __exit__(self, *args, **kwargs):
50 def __exit__(self, *args, **kwargs):
50 pass
51 pass
51
52
52
53
53 @decorator
54 @decorator
54 def needs_sqlite(f, self, *a, **kw):
55 def needs_sqlite(f, self, *a, **kw):
55 """Decorator: return an empty list in the absence of sqlite."""
56 """Decorator: return an empty list in the absence of sqlite."""
56 if sqlite3 is None or not self.enabled:
57 if sqlite3 is None or not self.enabled:
57 return []
58 return []
58 else:
59 else:
59 return f(self, *a, **kw)
60 return f(self, *a, **kw)
60
61
61
62
62 if sqlite3 is not None:
63 if sqlite3 is not None:
63 DatabaseError = sqlite3.DatabaseError
64 DatabaseError = sqlite3.DatabaseError
64 OperationalError = sqlite3.OperationalError
65 OperationalError = sqlite3.OperationalError
65 else:
66 else:
66 @undoc
67 @undoc
67 class DatabaseError(Exception):
68 class DatabaseError(Exception):
68 "Dummy exception when sqlite could not be imported. Should never occur."
69 "Dummy exception when sqlite could not be imported. Should never occur."
69
70
70 @undoc
71 @undoc
71 class OperationalError(Exception):
72 class OperationalError(Exception):
72 "Dummy exception when sqlite could not be imported. Should never occur."
73 "Dummy exception when sqlite could not be imported. Should never occur."
73
74
74 # use 16kB as threshold for whether a corrupt history db should be saved
75 # use 16kB as threshold for whether a corrupt history db should be saved
75 # that should be at least 100 entries or so
76 # that should be at least 100 entries or so
76 _SAVE_DB_SIZE = 16384
77 _SAVE_DB_SIZE = 16384
77
78
78 @decorator
79 @decorator
79 def catch_corrupt_db(f, self, *a, **kw):
80 def catch_corrupt_db(f, self, *a, **kw):
80 """A decorator which wraps HistoryAccessor method calls to catch errors from
81 """A decorator which wraps HistoryAccessor method calls to catch errors from
81 a corrupt SQLite database, move the old database out of the way, and create
82 a corrupt SQLite database, move the old database out of the way, and create
82 a new one.
83 a new one.
83
84
84 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
85 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
85 not just a corrupt file.
86 not just a corrupt file.
86 """
87 """
87 try:
88 try:
88 return f(self, *a, **kw)
89 return f(self, *a, **kw)
89 except (DatabaseError, OperationalError) as e:
90 except (DatabaseError, OperationalError) as e:
90 self._corrupt_db_counter += 1
91 self._corrupt_db_counter += 1
91 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
92 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
92 if self.hist_file != ':memory:':
93 if self.hist_file != ':memory:':
93 if self._corrupt_db_counter > self._corrupt_db_limit:
94 if self._corrupt_db_counter > self._corrupt_db_limit:
94 self.hist_file = ':memory:'
95 self.hist_file = ':memory:'
95 self.log.error("Failed to load history too many times, history will not be saved.")
96 self.log.error("Failed to load history too many times, history will not be saved.")
96 elif os.path.isfile(self.hist_file):
97 elif os.path.isfile(self.hist_file):
97 # move the file out of the way
98 # move the file out of the way
98 base, ext = os.path.splitext(self.hist_file)
99 base, ext = os.path.splitext(self.hist_file)
99 size = os.stat(self.hist_file).st_size
100 size = os.stat(self.hist_file).st_size
100 if size >= _SAVE_DB_SIZE:
101 if size >= _SAVE_DB_SIZE:
101 # if there's significant content, avoid clobbering
102 # if there's significant content, avoid clobbering
102 now = datetime.datetime.now().isoformat().replace(':', '.')
103 now = datetime.datetime.now().isoformat().replace(':', '.')
103 newpath = base + '-corrupt-' + now + ext
104 newpath = base + '-corrupt-' + now + ext
104 # don't clobber previous corrupt backups
105 # don't clobber previous corrupt backups
105 for i in range(100):
106 for i in range(100):
106 if not os.path.isfile(newpath):
107 if not os.path.isfile(newpath):
107 break
108 break
108 else:
109 else:
109 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
110 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
110 else:
111 else:
111 # not much content, possibly empty; don't worry about clobbering
112 # not much content, possibly empty; don't worry about clobbering
112 # maybe we should just delete it?
113 # maybe we should just delete it?
113 newpath = base + '-corrupt' + ext
114 newpath = base + '-corrupt' + ext
114 os.rename(self.hist_file, newpath)
115 os.rename(self.hist_file, newpath)
115 self.log.error("History file was moved to %s and a new file created.", newpath)
116 self.log.error("History file was moved to %s and a new file created.", newpath)
116 self.init_db()
117 self.init_db()
117 return []
118 return []
118 else:
119 else:
119 # Failed with :memory:, something serious is wrong
120 # Failed with :memory:, something serious is wrong
120 raise
121 raise
121
122
122 class HistoryAccessorBase(LoggingConfigurable):
123 class HistoryAccessorBase(LoggingConfigurable):
123 """An abstract class for History Accessors """
124 """An abstract class for History Accessors """
124
125
125 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
126 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
126 raise NotImplementedError
127 raise NotImplementedError
127
128
128 def search(self, pattern="*", raw=True, search_raw=True,
129 def search(self, pattern="*", raw=True, search_raw=True,
129 output=False, n=None, unique=False):
130 output=False, n=None, unique=False):
130 raise NotImplementedError
131 raise NotImplementedError
131
132
132 def get_range(self, session, start=1, stop=None, raw=True,output=False):
133 def get_range(self, session, start=1, stop=None, raw=True,output=False):
133 raise NotImplementedError
134 raise NotImplementedError
134
135
135 def get_range_by_str(self, rangestr, raw=True, output=False):
136 def get_range_by_str(self, rangestr, raw=True, output=False):
136 raise NotImplementedError
137 raise NotImplementedError
137
138
138
139
139 class HistoryAccessor(HistoryAccessorBase):
140 class HistoryAccessor(HistoryAccessorBase):
140 """Access the history database without adding to it.
141 """Access the history database without adding to it.
141
142
142 This is intended for use by standalone history tools. IPython shells use
143 This is intended for use by standalone history tools. IPython shells use
143 HistoryManager, below, which is a subclass of this."""
144 HistoryManager, below, which is a subclass of this."""
144
145
145 # counter for init_db retries, so we don't keep trying over and over
146 # counter for init_db retries, so we don't keep trying over and over
146 _corrupt_db_counter = 0
147 _corrupt_db_counter = 0
147 # after two failures, fallback on :memory:
148 # after two failures, fallback on :memory:
148 _corrupt_db_limit = 2
149 _corrupt_db_limit = 2
149
150
150 # String holding the path to the history file
151 # String holding the path to the history file
151 hist_file = Unicode(config=True,
152 hist_file = Unicode(
152 help="""Path to file to use for SQLite history database.
153 help="""Path to file to use for SQLite history database.
153
154
154 By default, IPython will put the history database in the IPython
155 By default, IPython will put the history database in the IPython
155 profile directory. If you would rather share one history among
156 profile directory. If you would rather share one history among
156 profiles, you can set this value in each, so that they are consistent.
157 profiles, you can set this value in each, so that they are consistent.
157
158
158 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
159 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
159 mounts. If you see IPython hanging, try setting this to something on a
160 mounts. If you see IPython hanging, try setting this to something on a
160 local disk, e.g::
161 local disk, e.g::
161
162
162 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
163 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
163
164
164 """)
165 """).tag(config=True)
165
166
166 enabled = Bool(True, config=True,
167 enabled = Bool(True,
167 help="""enable the SQLite history
168 help="""enable the SQLite history
168
169
169 set enabled=False to disable the SQLite history,
170 set enabled=False to disable the SQLite history,
170 in which case there will be no stored history, no SQLite connection,
171 in which case there will be no stored history, no SQLite connection,
171 and no background saving thread. This may be necessary in some
172 and no background saving thread. This may be necessary in some
172 threaded environments where IPython is embedded.
173 threaded environments where IPython is embedded.
173 """
174 """
174 )
175 ).tag(config=True)
175
176
176 connection_options = Dict(config=True,
177 connection_options = Dict(
177 help="""Options for configuring the SQLite connection
178 help="""Options for configuring the SQLite connection
178
179
179 These options are passed as keyword args to sqlite3.connect
180 These options are passed as keyword args to sqlite3.connect
180 when establishing database conenctions.
181 when establishing database conenctions.
181 """
182 """
182 )
183 ).tag(config=True)
183
184
184 # The SQLite database
185 # The SQLite database
185 db = Any()
186 db = Any()
186 def _db_changed(self, name, old, new):
187 @observe('db')
188 def _db_changed(self, change):
187 """validate the db, since it can be an Instance of two different types"""
189 """validate the db, since it can be an Instance of two different types"""
190 new = change['new']
188 connection_types = (DummyDB,)
191 connection_types = (DummyDB,)
189 if sqlite3 is not None:
192 if sqlite3 is not None:
190 connection_types = (DummyDB, sqlite3.Connection)
193 connection_types = (DummyDB, sqlite3.Connection)
191 if not isinstance(new, connection_types):
194 if not isinstance(new, connection_types):
192 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
195 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
193 (self.__class__.__name__, new)
196 (self.__class__.__name__, new)
194 raise TraitError(msg)
197 raise TraitError(msg)
195
198
196 def __init__(self, profile='default', hist_file=u'', **traits):
199 def __init__(self, profile='default', hist_file=u'', **traits):
197 """Create a new history accessor.
200 """Create a new history accessor.
198
201
199 Parameters
202 Parameters
200 ----------
203 ----------
201 profile : str
204 profile : str
202 The name of the profile from which to open history.
205 The name of the profile from which to open history.
203 hist_file : str
206 hist_file : str
204 Path to an SQLite history database stored by IPython. If specified,
207 Path to an SQLite history database stored by IPython. If specified,
205 hist_file overrides profile.
208 hist_file overrides profile.
206 config : :class:`~traitlets.config.loader.Config`
209 config : :class:`~traitlets.config.loader.Config`
207 Config object. hist_file can also be set through this.
210 Config object. hist_file can also be set through this.
208 """
211 """
209 # We need a pointer back to the shell for various tasks.
212 # We need a pointer back to the shell for various tasks.
210 super(HistoryAccessor, self).__init__(**traits)
213 super(HistoryAccessor, self).__init__(**traits)
211 # defer setting hist_file from kwarg until after init,
214 # defer setting hist_file from kwarg until after init,
212 # otherwise the default kwarg value would clobber any value
215 # otherwise the default kwarg value would clobber any value
213 # set by config
216 # set by config
214 if hist_file:
217 if hist_file:
215 self.hist_file = hist_file
218 self.hist_file = hist_file
216
219
217 if self.hist_file == u'':
220 if self.hist_file == u'':
218 # No one has set the hist_file, yet.
221 # No one has set the hist_file, yet.
219 self.hist_file = self._get_hist_file_name(profile)
222 self.hist_file = self._get_hist_file_name(profile)
220
223
221 if sqlite3 is None and self.enabled:
224 if sqlite3 is None and self.enabled:
222 warn("IPython History requires SQLite, your history will not be saved")
225 warn("IPython History requires SQLite, your history will not be saved")
223 self.enabled = False
226 self.enabled = False
224
227
225 self.init_db()
228 self.init_db()
226
229
227 def _get_hist_file_name(self, profile='default'):
230 def _get_hist_file_name(self, profile='default'):
228 """Find the history file for the given profile name.
231 """Find the history file for the given profile name.
229
232
230 This is overridden by the HistoryManager subclass, to use the shell's
233 This is overridden by the HistoryManager subclass, to use the shell's
231 active profile.
234 active profile.
232
235
233 Parameters
236 Parameters
234 ----------
237 ----------
235 profile : str
238 profile : str
236 The name of a profile which has a history file.
239 The name of a profile which has a history file.
237 """
240 """
238 return os.path.join(locate_profile(profile), 'history.sqlite')
241 return os.path.join(locate_profile(profile), 'history.sqlite')
239
242
240 @catch_corrupt_db
243 @catch_corrupt_db
241 def init_db(self):
244 def init_db(self):
242 """Connect to the database, and create tables if necessary."""
245 """Connect to the database, and create tables if necessary."""
243 if not self.enabled:
246 if not self.enabled:
244 self.db = DummyDB()
247 self.db = DummyDB()
245 return
248 return
246
249
247 # use detect_types so that timestamps return datetime objects
250 # use detect_types so that timestamps return datetime objects
248 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
251 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
249 kwargs.update(self.connection_options)
252 kwargs.update(self.connection_options)
250 self.db = sqlite3.connect(self.hist_file, **kwargs)
253 self.db = sqlite3.connect(self.hist_file, **kwargs)
251 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
254 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
252 primary key autoincrement, start timestamp,
255 primary key autoincrement, start timestamp,
253 end timestamp, num_cmds integer, remark text)""")
256 end timestamp, num_cmds integer, remark text)""")
254 self.db.execute("""CREATE TABLE IF NOT EXISTS history
257 self.db.execute("""CREATE TABLE IF NOT EXISTS history
255 (session integer, line integer, source text, source_raw text,
258 (session integer, line integer, source text, source_raw text,
256 PRIMARY KEY (session, line))""")
259 PRIMARY KEY (session, line))""")
257 # Output history is optional, but ensure the table's there so it can be
260 # Output history is optional, but ensure the table's there so it can be
258 # enabled later.
261 # enabled later.
259 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
262 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
260 (session integer, line integer, output text,
263 (session integer, line integer, output text,
261 PRIMARY KEY (session, line))""")
264 PRIMARY KEY (session, line))""")
262 self.db.commit()
265 self.db.commit()
263 # success! reset corrupt db count
266 # success! reset corrupt db count
264 self._corrupt_db_counter = 0
267 self._corrupt_db_counter = 0
265
268
266 def writeout_cache(self):
269 def writeout_cache(self):
267 """Overridden by HistoryManager to dump the cache before certain
270 """Overridden by HistoryManager to dump the cache before certain
268 database lookups."""
271 database lookups."""
269 pass
272 pass
270
273
271 ## -------------------------------
274 ## -------------------------------
272 ## Methods for retrieving history:
275 ## Methods for retrieving history:
273 ## -------------------------------
276 ## -------------------------------
274 def _run_sql(self, sql, params, raw=True, output=False):
277 def _run_sql(self, sql, params, raw=True, output=False):
275 """Prepares and runs an SQL query for the history database.
278 """Prepares and runs an SQL query for the history database.
276
279
277 Parameters
280 Parameters
278 ----------
281 ----------
279 sql : str
282 sql : str
280 Any filtering expressions to go after SELECT ... FROM ...
283 Any filtering expressions to go after SELECT ... FROM ...
281 params : tuple
284 params : tuple
282 Parameters passed to the SQL query (to replace "?")
285 Parameters passed to the SQL query (to replace "?")
283 raw, output : bool
286 raw, output : bool
284 See :meth:`get_range`
287 See :meth:`get_range`
285
288
286 Returns
289 Returns
287 -------
290 -------
288 Tuples as :meth:`get_range`
291 Tuples as :meth:`get_range`
289 """
292 """
290 toget = 'source_raw' if raw else 'source'
293 toget = 'source_raw' if raw else 'source'
291 sqlfrom = "history"
294 sqlfrom = "history"
292 if output:
295 if output:
293 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
296 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
294 toget = "history.%s, output_history.output" % toget
297 toget = "history.%s, output_history.output" % toget
295 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
298 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
296 (toget, sqlfrom) + sql, params)
299 (toget, sqlfrom) + sql, params)
297 if output: # Regroup into 3-tuples, and parse JSON
300 if output: # Regroup into 3-tuples, and parse JSON
298 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
301 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
299 return cur
302 return cur
300
303
301 @needs_sqlite
304 @needs_sqlite
302 @catch_corrupt_db
305 @catch_corrupt_db
303 def get_session_info(self, session):
306 def get_session_info(self, session):
304 """Get info about a session.
307 """Get info about a session.
305
308
306 Parameters
309 Parameters
307 ----------
310 ----------
308
311
309 session : int
312 session : int
310 Session number to retrieve.
313 Session number to retrieve.
311
314
312 Returns
315 Returns
313 -------
316 -------
314
317
315 session_id : int
318 session_id : int
316 Session ID number
319 Session ID number
317 start : datetime
320 start : datetime
318 Timestamp for the start of the session.
321 Timestamp for the start of the session.
319 end : datetime
322 end : datetime
320 Timestamp for the end of the session, or None if IPython crashed.
323 Timestamp for the end of the session, or None if IPython crashed.
321 num_cmds : int
324 num_cmds : int
322 Number of commands run, or None if IPython crashed.
325 Number of commands run, or None if IPython crashed.
323 remark : unicode
326 remark : unicode
324 A manually set description.
327 A manually set description.
325 """
328 """
326 query = "SELECT * from sessions where session == ?"
329 query = "SELECT * from sessions where session == ?"
327 return self.db.execute(query, (session,)).fetchone()
330 return self.db.execute(query, (session,)).fetchone()
328
331
329 @catch_corrupt_db
332 @catch_corrupt_db
330 def get_last_session_id(self):
333 def get_last_session_id(self):
331 """Get the last session ID currently in the database.
334 """Get the last session ID currently in the database.
332
335
333 Within IPython, this should be the same as the value stored in
336 Within IPython, this should be the same as the value stored in
334 :attr:`HistoryManager.session_number`.
337 :attr:`HistoryManager.session_number`.
335 """
338 """
336 for record in self.get_tail(n=1, include_latest=True):
339 for record in self.get_tail(n=1, include_latest=True):
337 return record[0]
340 return record[0]
338
341
339 @catch_corrupt_db
342 @catch_corrupt_db
340 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
343 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
341 """Get the last n lines from the history database.
344 """Get the last n lines from the history database.
342
345
343 Parameters
346 Parameters
344 ----------
347 ----------
345 n : int
348 n : int
346 The number of lines to get
349 The number of lines to get
347 raw, output : bool
350 raw, output : bool
348 See :meth:`get_range`
351 See :meth:`get_range`
349 include_latest : bool
352 include_latest : bool
350 If False (default), n+1 lines are fetched, and the latest one
353 If False (default), n+1 lines are fetched, and the latest one
351 is discarded. This is intended to be used where the function
354 is discarded. This is intended to be used where the function
352 is called by a user command, which it should not return.
355 is called by a user command, which it should not return.
353
356
354 Returns
357 Returns
355 -------
358 -------
356 Tuples as :meth:`get_range`
359 Tuples as :meth:`get_range`
357 """
360 """
358 self.writeout_cache()
361 self.writeout_cache()
359 if not include_latest:
362 if not include_latest:
360 n += 1
363 n += 1
361 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
364 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
362 (n,), raw=raw, output=output)
365 (n,), raw=raw, output=output)
363 if not include_latest:
366 if not include_latest:
364 return reversed(list(cur)[1:])
367 return reversed(list(cur)[1:])
365 return reversed(list(cur))
368 return reversed(list(cur))
366
369
367 @catch_corrupt_db
370 @catch_corrupt_db
368 def search(self, pattern="*", raw=True, search_raw=True,
371 def search(self, pattern="*", raw=True, search_raw=True,
369 output=False, n=None, unique=False):
372 output=False, n=None, unique=False):
370 """Search the database using unix glob-style matching (wildcards
373 """Search the database using unix glob-style matching (wildcards
371 * and ?).
374 * and ?).
372
375
373 Parameters
376 Parameters
374 ----------
377 ----------
375 pattern : str
378 pattern : str
376 The wildcarded pattern to match when searching
379 The wildcarded pattern to match when searching
377 search_raw : bool
380 search_raw : bool
378 If True, search the raw input, otherwise, the parsed input
381 If True, search the raw input, otherwise, the parsed input
379 raw, output : bool
382 raw, output : bool
380 See :meth:`get_range`
383 See :meth:`get_range`
381 n : None or int
384 n : None or int
382 If an integer is given, it defines the limit of
385 If an integer is given, it defines the limit of
383 returned entries.
386 returned entries.
384 unique : bool
387 unique : bool
385 When it is true, return only unique entries.
388 When it is true, return only unique entries.
386
389
387 Returns
390 Returns
388 -------
391 -------
389 Tuples as :meth:`get_range`
392 Tuples as :meth:`get_range`
390 """
393 """
391 tosearch = "source_raw" if search_raw else "source"
394 tosearch = "source_raw" if search_raw else "source"
392 if output:
395 if output:
393 tosearch = "history." + tosearch
396 tosearch = "history." + tosearch
394 self.writeout_cache()
397 self.writeout_cache()
395 sqlform = "WHERE %s GLOB ?" % tosearch
398 sqlform = "WHERE %s GLOB ?" % tosearch
396 params = (pattern,)
399 params = (pattern,)
397 if unique:
400 if unique:
398 sqlform += ' GROUP BY {0}'.format(tosearch)
401 sqlform += ' GROUP BY {0}'.format(tosearch)
399 if n is not None:
402 if n is not None:
400 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
403 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
401 params += (n,)
404 params += (n,)
402 elif unique:
405 elif unique:
403 sqlform += " ORDER BY session, line"
406 sqlform += " ORDER BY session, line"
404 cur = self._run_sql(sqlform, params, raw=raw, output=output)
407 cur = self._run_sql(sqlform, params, raw=raw, output=output)
405 if n is not None:
408 if n is not None:
406 return reversed(list(cur))
409 return reversed(list(cur))
407 return cur
410 return cur
408
411
409 @catch_corrupt_db
412 @catch_corrupt_db
410 def get_range(self, session, start=1, stop=None, raw=True,output=False):
413 def get_range(self, session, start=1, stop=None, raw=True,output=False):
411 """Retrieve input by session.
414 """Retrieve input by session.
412
415
413 Parameters
416 Parameters
414 ----------
417 ----------
415 session : int
418 session : int
416 Session number to retrieve.
419 Session number to retrieve.
417 start : int
420 start : int
418 First line to retrieve.
421 First line to retrieve.
419 stop : int
422 stop : int
420 End of line range (excluded from output itself). If None, retrieve
423 End of line range (excluded from output itself). If None, retrieve
421 to the end of the session.
424 to the end of the session.
422 raw : bool
425 raw : bool
423 If True, return untranslated input
426 If True, return untranslated input
424 output : bool
427 output : bool
425 If True, attempt to include output. This will be 'real' Python
428 If True, attempt to include output. This will be 'real' Python
426 objects for the current session, or text reprs from previous
429 objects for the current session, or text reprs from previous
427 sessions if db_log_output was enabled at the time. Where no output
430 sessions if db_log_output was enabled at the time. Where no output
428 is found, None is used.
431 is found, None is used.
429
432
430 Returns
433 Returns
431 -------
434 -------
432 entries
435 entries
433 An iterator over the desired lines. Each line is a 3-tuple, either
436 An iterator over the desired lines. Each line is a 3-tuple, either
434 (session, line, input) if output is False, or
437 (session, line, input) if output is False, or
435 (session, line, (input, output)) if output is True.
438 (session, line, (input, output)) if output is True.
436 """
439 """
437 if stop:
440 if stop:
438 lineclause = "line >= ? AND line < ?"
441 lineclause = "line >= ? AND line < ?"
439 params = (session, start, stop)
442 params = (session, start, stop)
440 else:
443 else:
441 lineclause = "line>=?"
444 lineclause = "line>=?"
442 params = (session, start)
445 params = (session, start)
443
446
444 return self._run_sql("WHERE session==? AND %s" % lineclause,
447 return self._run_sql("WHERE session==? AND %s" % lineclause,
445 params, raw=raw, output=output)
448 params, raw=raw, output=output)
446
449
447 def get_range_by_str(self, rangestr, raw=True, output=False):
450 def get_range_by_str(self, rangestr, raw=True, output=False):
448 """Get lines of history from a string of ranges, as used by magic
451 """Get lines of history from a string of ranges, as used by magic
449 commands %hist, %save, %macro, etc.
452 commands %hist, %save, %macro, etc.
450
453
451 Parameters
454 Parameters
452 ----------
455 ----------
453 rangestr : str
456 rangestr : str
454 A string specifying ranges, e.g. "5 ~2/1-4". See
457 A string specifying ranges, e.g. "5 ~2/1-4". See
455 :func:`magic_history` for full details.
458 :func:`magic_history` for full details.
456 raw, output : bool
459 raw, output : bool
457 As :meth:`get_range`
460 As :meth:`get_range`
458
461
459 Returns
462 Returns
460 -------
463 -------
461 Tuples as :meth:`get_range`
464 Tuples as :meth:`get_range`
462 """
465 """
463 for sess, s, e in extract_hist_ranges(rangestr):
466 for sess, s, e in extract_hist_ranges(rangestr):
464 for line in self.get_range(sess, s, e, raw=raw, output=output):
467 for line in self.get_range(sess, s, e, raw=raw, output=output):
465 yield line
468 yield line
466
469
467
470
468 class HistoryManager(HistoryAccessor):
471 class HistoryManager(HistoryAccessor):
469 """A class to organize all history-related functionality in one place.
472 """A class to organize all history-related functionality in one place.
470 """
473 """
471 # Public interface
474 # Public interface
472
475
473 # An instance of the IPython shell we are attached to
476 # An instance of the IPython shell we are attached to
474 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
477 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
475 allow_none=True)
478 allow_none=True)
476 # Lists to hold processed and raw history. These start with a blank entry
479 # Lists to hold processed and raw history. These start with a blank entry
477 # so that we can index them starting from 1
480 # so that we can index them starting from 1
478 input_hist_parsed = List([""])
481 input_hist_parsed = List([""])
479 input_hist_raw = List([""])
482 input_hist_raw = List([""])
480 # A list of directories visited during session
483 # A list of directories visited during session
481 dir_hist = List()
484 dir_hist = List()
485 @default('dir_hist')
482 def _dir_hist_default(self):
486 def _dir_hist_default(self):
483 try:
487 try:
484 return [py3compat.getcwd()]
488 return [py3compat.getcwd()]
485 except OSError:
489 except OSError:
486 return []
490 return []
487
491
488 # A dict of output history, keyed with ints from the shell's
492 # A dict of output history, keyed with ints from the shell's
489 # execution count.
493 # execution count.
490 output_hist = Dict()
494 output_hist = Dict()
491 # The text/plain repr of outputs.
495 # The text/plain repr of outputs.
492 output_hist_reprs = Dict()
496 output_hist_reprs = Dict()
493
497
494 # The number of the current session in the history database
498 # The number of the current session in the history database
495 session_number = Integer()
499 session_number = Integer()
496
500
497 db_log_output = Bool(False, config=True,
501 db_log_output = Bool(False,
498 help="Should the history database include output? (default: no)"
502 help="Should the history database include output? (default: no)"
499 )
503 ).tag(config=True)
500 db_cache_size = Integer(0, config=True,
504 db_cache_size = Integer(0,
501 help="Write to database every x commands (higher values save disk access & power).\n"
505 help="Write to database every x commands (higher values save disk access & power).\n"
502 "Values of 1 or less effectively disable caching."
506 "Values of 1 or less effectively disable caching."
503 )
507 ).tag(config=True)
504 # The input and output caches
508 # The input and output caches
505 db_input_cache = List()
509 db_input_cache = List()
506 db_output_cache = List()
510 db_output_cache = List()
507
511
508 # History saving in separate thread
512 # History saving in separate thread
509 save_thread = Instance('IPython.core.history.HistorySavingThread',
513 save_thread = Instance('IPython.core.history.HistorySavingThread',
510 allow_none=True)
514 allow_none=True)
511 try: # Event is a function returning an instance of _Event...
515 try: # Event is a function returning an instance of _Event...
512 save_flag = Instance(threading._Event, allow_none=True)
516 save_flag = Instance(threading._Event, allow_none=True)
513 except AttributeError: # ...until Python 3.3, when it's a class.
517 except AttributeError: # ...until Python 3.3, when it's a class.
514 save_flag = Instance(threading.Event, allow_none=True)
518 save_flag = Instance(threading.Event, allow_none=True)
515
519
516 # Private interface
520 # Private interface
517 # Variables used to store the three last inputs from the user. On each new
521 # Variables used to store the three last inputs from the user. On each new
518 # history update, we populate the user's namespace with these, shifted as
522 # history update, we populate the user's namespace with these, shifted as
519 # necessary.
523 # necessary.
520 _i00 = Unicode(u'')
524 _i00 = Unicode(u'')
521 _i = Unicode(u'')
525 _i = Unicode(u'')
522 _ii = Unicode(u'')
526 _ii = Unicode(u'')
523 _iii = Unicode(u'')
527 _iii = Unicode(u'')
524
528
525 # A regex matching all forms of the exit command, so that we don't store
529 # A regex matching all forms of the exit command, so that we don't store
526 # them in the history (it's annoying to rewind the first entry and land on
530 # them in the history (it's annoying to rewind the first entry and land on
527 # an exit call).
531 # an exit call).
528 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
532 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
529
533
530 def __init__(self, shell=None, config=None, **traits):
534 def __init__(self, shell=None, config=None, **traits):
531 """Create a new history manager associated with a shell instance.
535 """Create a new history manager associated with a shell instance.
532 """
536 """
533 # We need a pointer back to the shell for various tasks.
537 # We need a pointer back to the shell for various tasks.
534 super(HistoryManager, self).__init__(shell=shell, config=config,
538 super(HistoryManager, self).__init__(shell=shell, config=config,
535 **traits)
539 **traits)
536 self.save_flag = threading.Event()
540 self.save_flag = threading.Event()
537 self.db_input_cache_lock = threading.Lock()
541 self.db_input_cache_lock = threading.Lock()
538 self.db_output_cache_lock = threading.Lock()
542 self.db_output_cache_lock = threading.Lock()
539
543
540 try:
544 try:
541 self.new_session()
545 self.new_session()
542 except OperationalError:
546 except OperationalError:
543 self.log.error("Failed to create history session in %s. History will not be saved.",
547 self.log.error("Failed to create history session in %s. History will not be saved.",
544 self.hist_file, exc_info=True)
548 self.hist_file, exc_info=True)
545 self.hist_file = ':memory:'
549 self.hist_file = ':memory:'
546
550
547 if self.enabled and self.hist_file != ':memory:':
551 if self.enabled and self.hist_file != ':memory:':
548 self.save_thread = HistorySavingThread(self)
552 self.save_thread = HistorySavingThread(self)
549 self.save_thread.start()
553 self.save_thread.start()
550
554
551 def _get_hist_file_name(self, profile=None):
555 def _get_hist_file_name(self, profile=None):
552 """Get default history file name based on the Shell's profile.
556 """Get default history file name based on the Shell's profile.
553
557
554 The profile parameter is ignored, but must exist for compatibility with
558 The profile parameter is ignored, but must exist for compatibility with
555 the parent class."""
559 the parent class."""
556 profile_dir = self.shell.profile_dir.location
560 profile_dir = self.shell.profile_dir.location
557 return os.path.join(profile_dir, 'history.sqlite')
561 return os.path.join(profile_dir, 'history.sqlite')
558
562
559 @needs_sqlite
563 @needs_sqlite
560 def new_session(self, conn=None):
564 def new_session(self, conn=None):
561 """Get a new session number."""
565 """Get a new session number."""
562 if conn is None:
566 if conn is None:
563 conn = self.db
567 conn = self.db
564
568
565 with conn:
569 with conn:
566 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
570 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
567 NULL, "") """, (datetime.datetime.now(),))
571 NULL, "") """, (datetime.datetime.now(),))
568 self.session_number = cur.lastrowid
572 self.session_number = cur.lastrowid
569
573
570 def end_session(self):
574 def end_session(self):
571 """Close the database session, filling in the end time and line count."""
575 """Close the database session, filling in the end time and line count."""
572 self.writeout_cache()
576 self.writeout_cache()
573 with self.db:
577 with self.db:
574 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
578 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
575 session==?""", (datetime.datetime.now(),
579 session==?""", (datetime.datetime.now(),
576 len(self.input_hist_parsed)-1, self.session_number))
580 len(self.input_hist_parsed)-1, self.session_number))
577 self.session_number = 0
581 self.session_number = 0
578
582
579 def name_session(self, name):
583 def name_session(self, name):
580 """Give the current session a name in the history database."""
584 """Give the current session a name in the history database."""
581 with self.db:
585 with self.db:
582 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
586 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
583 (name, self.session_number))
587 (name, self.session_number))
584
588
585 def reset(self, new_session=True):
589 def reset(self, new_session=True):
586 """Clear the session history, releasing all object references, and
590 """Clear the session history, releasing all object references, and
587 optionally open a new session."""
591 optionally open a new session."""
588 self.output_hist.clear()
592 self.output_hist.clear()
589 # The directory history can't be completely empty
593 # The directory history can't be completely empty
590 self.dir_hist[:] = [py3compat.getcwd()]
594 self.dir_hist[:] = [py3compat.getcwd()]
591
595
592 if new_session:
596 if new_session:
593 if self.session_number:
597 if self.session_number:
594 self.end_session()
598 self.end_session()
595 self.input_hist_parsed[:] = [""]
599 self.input_hist_parsed[:] = [""]
596 self.input_hist_raw[:] = [""]
600 self.input_hist_raw[:] = [""]
597 self.new_session()
601 self.new_session()
598
602
599 # ------------------------------
603 # ------------------------------
600 # Methods for retrieving history
604 # Methods for retrieving history
601 # ------------------------------
605 # ------------------------------
602 def get_session_info(self, session=0):
606 def get_session_info(self, session=0):
603 """Get info about a session.
607 """Get info about a session.
604
608
605 Parameters
609 Parameters
606 ----------
610 ----------
607
611
608 session : int
612 session : int
609 Session number to retrieve. The current session is 0, and negative
613 Session number to retrieve. The current session is 0, and negative
610 numbers count back from current session, so -1 is the previous session.
614 numbers count back from current session, so -1 is the previous session.
611
615
612 Returns
616 Returns
613 -------
617 -------
614
618
615 session_id : int
619 session_id : int
616 Session ID number
620 Session ID number
617 start : datetime
621 start : datetime
618 Timestamp for the start of the session.
622 Timestamp for the start of the session.
619 end : datetime
623 end : datetime
620 Timestamp for the end of the session, or None if IPython crashed.
624 Timestamp for the end of the session, or None if IPython crashed.
621 num_cmds : int
625 num_cmds : int
622 Number of commands run, or None if IPython crashed.
626 Number of commands run, or None if IPython crashed.
623 remark : unicode
627 remark : unicode
624 A manually set description.
628 A manually set description.
625 """
629 """
626 if session <= 0:
630 if session <= 0:
627 session += self.session_number
631 session += self.session_number
628
632
629 return super(HistoryManager, self).get_session_info(session=session)
633 return super(HistoryManager, self).get_session_info(session=session)
630
634
631 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
635 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
632 """Get input and output history from the current session. Called by
636 """Get input and output history from the current session. Called by
633 get_range, and takes similar parameters."""
637 get_range, and takes similar parameters."""
634 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
638 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
635
639
636 n = len(input_hist)
640 n = len(input_hist)
637 if start < 0:
641 if start < 0:
638 start += n
642 start += n
639 if not stop or (stop > n):
643 if not stop or (stop > n):
640 stop = n
644 stop = n
641 elif stop < 0:
645 elif stop < 0:
642 stop += n
646 stop += n
643
647
644 for i in range(start, stop):
648 for i in range(start, stop):
645 if output:
649 if output:
646 line = (input_hist[i], self.output_hist_reprs.get(i))
650 line = (input_hist[i], self.output_hist_reprs.get(i))
647 else:
651 else:
648 line = input_hist[i]
652 line = input_hist[i]
649 yield (0, i, line)
653 yield (0, i, line)
650
654
651 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
655 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
652 """Retrieve input by session.
656 """Retrieve input by session.
653
657
654 Parameters
658 Parameters
655 ----------
659 ----------
656 session : int
660 session : int
657 Session number to retrieve. The current session is 0, and negative
661 Session number to retrieve. The current session is 0, and negative
658 numbers count back from current session, so -1 is previous session.
662 numbers count back from current session, so -1 is previous session.
659 start : int
663 start : int
660 First line to retrieve.
664 First line to retrieve.
661 stop : int
665 stop : int
662 End of line range (excluded from output itself). If None, retrieve
666 End of line range (excluded from output itself). If None, retrieve
663 to the end of the session.
667 to the end of the session.
664 raw : bool
668 raw : bool
665 If True, return untranslated input
669 If True, return untranslated input
666 output : bool
670 output : bool
667 If True, attempt to include output. This will be 'real' Python
671 If True, attempt to include output. This will be 'real' Python
668 objects for the current session, or text reprs from previous
672 objects for the current session, or text reprs from previous
669 sessions if db_log_output was enabled at the time. Where no output
673 sessions if db_log_output was enabled at the time. Where no output
670 is found, None is used.
674 is found, None is used.
671
675
672 Returns
676 Returns
673 -------
677 -------
674 entries
678 entries
675 An iterator over the desired lines. Each line is a 3-tuple, either
679 An iterator over the desired lines. Each line is a 3-tuple, either
676 (session, line, input) if output is False, or
680 (session, line, input) if output is False, or
677 (session, line, (input, output)) if output is True.
681 (session, line, (input, output)) if output is True.
678 """
682 """
679 if session <= 0:
683 if session <= 0:
680 session += self.session_number
684 session += self.session_number
681 if session==self.session_number: # Current session
685 if session==self.session_number: # Current session
682 return self._get_range_session(start, stop, raw, output)
686 return self._get_range_session(start, stop, raw, output)
683 return super(HistoryManager, self).get_range(session, start, stop, raw,
687 return super(HistoryManager, self).get_range(session, start, stop, raw,
684 output)
688 output)
685
689
686 ## ----------------------------
690 ## ----------------------------
687 ## Methods for storing history:
691 ## Methods for storing history:
688 ## ----------------------------
692 ## ----------------------------
689 def store_inputs(self, line_num, source, source_raw=None):
693 def store_inputs(self, line_num, source, source_raw=None):
690 """Store source and raw input in history and create input cache
694 """Store source and raw input in history and create input cache
691 variables ``_i*``.
695 variables ``_i*``.
692
696
693 Parameters
697 Parameters
694 ----------
698 ----------
695 line_num : int
699 line_num : int
696 The prompt number of this input.
700 The prompt number of this input.
697
701
698 source : str
702 source : str
699 Python input.
703 Python input.
700
704
701 source_raw : str, optional
705 source_raw : str, optional
702 If given, this is the raw input without any IPython transformations
706 If given, this is the raw input without any IPython transformations
703 applied to it. If not given, ``source`` is used.
707 applied to it. If not given, ``source`` is used.
704 """
708 """
705 if source_raw is None:
709 if source_raw is None:
706 source_raw = source
710 source_raw = source
707 source = source.rstrip('\n')
711 source = source.rstrip('\n')
708 source_raw = source_raw.rstrip('\n')
712 source_raw = source_raw.rstrip('\n')
709
713
710 # do not store exit/quit commands
714 # do not store exit/quit commands
711 if self._exit_re.match(source_raw.strip()):
715 if self._exit_re.match(source_raw.strip()):
712 return
716 return
713
717
714 self.input_hist_parsed.append(source)
718 self.input_hist_parsed.append(source)
715 self.input_hist_raw.append(source_raw)
719 self.input_hist_raw.append(source_raw)
716
720
717 with self.db_input_cache_lock:
721 with self.db_input_cache_lock:
718 self.db_input_cache.append((line_num, source, source_raw))
722 self.db_input_cache.append((line_num, source, source_raw))
719 # Trigger to flush cache and write to DB.
723 # Trigger to flush cache and write to DB.
720 if len(self.db_input_cache) >= self.db_cache_size:
724 if len(self.db_input_cache) >= self.db_cache_size:
721 self.save_flag.set()
725 self.save_flag.set()
722
726
723 # update the auto _i variables
727 # update the auto _i variables
724 self._iii = self._ii
728 self._iii = self._ii
725 self._ii = self._i
729 self._ii = self._i
726 self._i = self._i00
730 self._i = self._i00
727 self._i00 = source_raw
731 self._i00 = source_raw
728
732
729 # hackish access to user namespace to create _i1,_i2... dynamically
733 # hackish access to user namespace to create _i1,_i2... dynamically
730 new_i = '_i%s' % line_num
734 new_i = '_i%s' % line_num
731 to_main = {'_i': self._i,
735 to_main = {'_i': self._i,
732 '_ii': self._ii,
736 '_ii': self._ii,
733 '_iii': self._iii,
737 '_iii': self._iii,
734 new_i : self._i00 }
738 new_i : self._i00 }
735
739
736 if self.shell is not None:
740 if self.shell is not None:
737 self.shell.push(to_main, interactive=False)
741 self.shell.push(to_main, interactive=False)
738
742
739 def store_output(self, line_num):
743 def store_output(self, line_num):
740 """If database output logging is enabled, this saves all the
744 """If database output logging is enabled, this saves all the
741 outputs from the indicated prompt number to the database. It's
745 outputs from the indicated prompt number to the database. It's
742 called by run_cell after code has been executed.
746 called by run_cell after code has been executed.
743
747
744 Parameters
748 Parameters
745 ----------
749 ----------
746 line_num : int
750 line_num : int
747 The line number from which to save outputs
751 The line number from which to save outputs
748 """
752 """
749 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
753 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
750 return
754 return
751 output = self.output_hist_reprs[line_num]
755 output = self.output_hist_reprs[line_num]
752
756
753 with self.db_output_cache_lock:
757 with self.db_output_cache_lock:
754 self.db_output_cache.append((line_num, output))
758 self.db_output_cache.append((line_num, output))
755 if self.db_cache_size <= 1:
759 if self.db_cache_size <= 1:
756 self.save_flag.set()
760 self.save_flag.set()
757
761
758 def _writeout_input_cache(self, conn):
762 def _writeout_input_cache(self, conn):
759 with conn:
763 with conn:
760 for line in self.db_input_cache:
764 for line in self.db_input_cache:
761 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
765 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
762 (self.session_number,)+line)
766 (self.session_number,)+line)
763
767
764 def _writeout_output_cache(self, conn):
768 def _writeout_output_cache(self, conn):
765 with conn:
769 with conn:
766 for line in self.db_output_cache:
770 for line in self.db_output_cache:
767 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
771 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
768 (self.session_number,)+line)
772 (self.session_number,)+line)
769
773
770 @needs_sqlite
774 @needs_sqlite
771 def writeout_cache(self, conn=None):
775 def writeout_cache(self, conn=None):
772 """Write any entries in the cache to the database."""
776 """Write any entries in the cache to the database."""
773 if conn is None:
777 if conn is None:
774 conn = self.db
778 conn = self.db
775
779
776 with self.db_input_cache_lock:
780 with self.db_input_cache_lock:
777 try:
781 try:
778 self._writeout_input_cache(conn)
782 self._writeout_input_cache(conn)
779 except sqlite3.IntegrityError:
783 except sqlite3.IntegrityError:
780 self.new_session(conn)
784 self.new_session(conn)
781 print("ERROR! Session/line number was not unique in",
785 print("ERROR! Session/line number was not unique in",
782 "database. History logging moved to new session",
786 "database. History logging moved to new session",
783 self.session_number)
787 self.session_number)
784 try:
788 try:
785 # Try writing to the new session. If this fails, don't
789 # Try writing to the new session. If this fails, don't
786 # recurse
790 # recurse
787 self._writeout_input_cache(conn)
791 self._writeout_input_cache(conn)
788 except sqlite3.IntegrityError:
792 except sqlite3.IntegrityError:
789 pass
793 pass
790 finally:
794 finally:
791 self.db_input_cache = []
795 self.db_input_cache = []
792
796
793 with self.db_output_cache_lock:
797 with self.db_output_cache_lock:
794 try:
798 try:
795 self._writeout_output_cache(conn)
799 self._writeout_output_cache(conn)
796 except sqlite3.IntegrityError:
800 except sqlite3.IntegrityError:
797 print("!! Session/line number for output was not unique",
801 print("!! Session/line number for output was not unique",
798 "in database. Output will not be stored.")
802 "in database. Output will not be stored.")
799 finally:
803 finally:
800 self.db_output_cache = []
804 self.db_output_cache = []
801
805
802
806
803 class HistorySavingThread(threading.Thread):
807 class HistorySavingThread(threading.Thread):
804 """This thread takes care of writing history to the database, so that
808 """This thread takes care of writing history to the database, so that
805 the UI isn't held up while that happens.
809 the UI isn't held up while that happens.
806
810
807 It waits for the HistoryManager's save_flag to be set, then writes out
811 It waits for the HistoryManager's save_flag to be set, then writes out
808 the history cache. The main thread is responsible for setting the flag when
812 the history cache. The main thread is responsible for setting the flag when
809 the cache size reaches a defined threshold."""
813 the cache size reaches a defined threshold."""
810 daemon = True
814 daemon = True
811 stop_now = False
815 stop_now = False
812 enabled = True
816 enabled = True
813 def __init__(self, history_manager):
817 def __init__(self, history_manager):
814 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
818 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
815 self.history_manager = history_manager
819 self.history_manager = history_manager
816 self.enabled = history_manager.enabled
820 self.enabled = history_manager.enabled
817 atexit.register(self.stop)
821 atexit.register(self.stop)
818
822
819 @needs_sqlite
823 @needs_sqlite
820 def run(self):
824 def run(self):
821 # We need a separate db connection per thread:
825 # We need a separate db connection per thread:
822 try:
826 try:
823 self.db = sqlite3.connect(self.history_manager.hist_file,
827 self.db = sqlite3.connect(self.history_manager.hist_file,
824 **self.history_manager.connection_options
828 **self.history_manager.connection_options
825 )
829 )
826 while True:
830 while True:
827 self.history_manager.save_flag.wait()
831 self.history_manager.save_flag.wait()
828 if self.stop_now:
832 if self.stop_now:
829 self.db.close()
833 self.db.close()
830 return
834 return
831 self.history_manager.save_flag.clear()
835 self.history_manager.save_flag.clear()
832 self.history_manager.writeout_cache(self.db)
836 self.history_manager.writeout_cache(self.db)
833 except Exception as e:
837 except Exception as e:
834 print(("The history saving thread hit an unexpected error (%s)."
838 print(("The history saving thread hit an unexpected error (%s)."
835 "History will not be written to the database.") % repr(e))
839 "History will not be written to the database.") % repr(e))
836
840
837 def stop(self):
841 def stop(self):
838 """This can be called from the main thread to safely stop this thread.
842 """This can be called from the main thread to safely stop this thread.
839
843
840 Note that it does not attempt to write out remaining history before
844 Note that it does not attempt to write out remaining history before
841 exiting. That should be done by calling the HistoryManager's
845 exiting. That should be done by calling the HistoryManager's
842 end_session method."""
846 end_session method."""
843 self.stop_now = True
847 self.stop_now = True
844 self.history_manager.save_flag.set()
848 self.history_manager.save_flag.set()
845 self.join()
849 self.join()
846
850
847
851
848 # To match, e.g. ~5/8-~2/3
852 # To match, e.g. ~5/8-~2/3
849 range_re = re.compile(r"""
853 range_re = re.compile(r"""
850 ((?P<startsess>~?\d+)/)?
854 ((?P<startsess>~?\d+)/)?
851 (?P<start>\d+)?
855 (?P<start>\d+)?
852 ((?P<sep>[\-:])
856 ((?P<sep>[\-:])
853 ((?P<endsess>~?\d+)/)?
857 ((?P<endsess>~?\d+)/)?
854 (?P<end>\d+))?
858 (?P<end>\d+))?
855 $""", re.VERBOSE)
859 $""", re.VERBOSE)
856
860
857
861
858 def extract_hist_ranges(ranges_str):
862 def extract_hist_ranges(ranges_str):
859 """Turn a string of history ranges into 3-tuples of (session, start, stop).
863 """Turn a string of history ranges into 3-tuples of (session, start, stop).
860
864
861 Examples
865 Examples
862 --------
866 --------
863 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
867 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
864 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
868 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
865 """
869 """
866 for range_str in ranges_str.split():
870 for range_str in ranges_str.split():
867 rmatch = range_re.match(range_str)
871 rmatch = range_re.match(range_str)
868 if not rmatch:
872 if not rmatch:
869 continue
873 continue
870 start = rmatch.group("start")
874 start = rmatch.group("start")
871 if start:
875 if start:
872 start = int(start)
876 start = int(start)
873 end = rmatch.group("end")
877 end = rmatch.group("end")
874 # If no end specified, get (a, a + 1)
878 # If no end specified, get (a, a + 1)
875 end = int(end) if end else start + 1
879 end = int(end) if end else start + 1
876 else: # start not specified
880 else: # start not specified
877 if not rmatch.group('startsess'): # no startsess
881 if not rmatch.group('startsess'): # no startsess
878 continue
882 continue
879 start = 1
883 start = 1
880 end = None # provide the entire session hist
884 end = None # provide the entire session hist
881
885
882 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
886 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
883 end += 1
887 end += 1
884 startsess = rmatch.group("startsess") or "0"
888 startsess = rmatch.group("startsess") or "0"
885 endsess = rmatch.group("endsess") or startsess
889 endsess = rmatch.group("endsess") or startsess
886 startsess = int(startsess.replace("~","-"))
890 startsess = int(startsess.replace("~","-"))
887 endsess = int(endsess.replace("~","-"))
891 endsess = int(endsess.replace("~","-"))
888 assert endsess >= startsess, "start session must be earlier than end session"
892 assert endsess >= startsess, "start session must be earlier than end session"
889
893
890 if endsess == startsess:
894 if endsess == startsess:
891 yield (startsess, start, end)
895 yield (startsess, start, end)
892 continue
896 continue
893 # Multiple sessions in one range:
897 # Multiple sessions in one range:
894 yield (startsess, start, None)
898 yield (startsess, start, None)
895 for sess in range(startsess+1, endsess):
899 for sess in range(startsess+1, endsess):
896 yield (sess, 1, None)
900 yield (sess, 1, None)
897 yield (endsess, 1, end)
901 yield (endsess, 1, end)
898
902
899
903
900 def _format_lineno(session, line):
904 def _format_lineno(session, line):
901 """Helper function to format line numbers properly."""
905 """Helper function to format line numbers properly."""
902 if session == 0:
906 if session == 0:
903 return str(line)
907 return str(line)
904 return "%s#%s" % (session, line)
908 return "%s#%s" % (session, line)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,703 +1,699 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4 from __future__ import print_function
4 from __future__ import print_function
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
8 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 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 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18 # Stdlib
19 import os
15 import os
20 import re
16 import re
21 import sys
17 import sys
22 import types
18 import types
23 from getopt import getopt, GetoptError
19 from getopt import getopt, GetoptError
24
20
25 # Our own
26 from traitlets.config.configurable import Configurable
21 from traitlets.config.configurable import Configurable
27 from IPython.core import oinspect
22 from IPython.core import oinspect
28 from IPython.core.error import UsageError
23 from IPython.core.error import UsageError
29 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
24 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
30 from decorator import decorator
25 from decorator import decorator
31 from IPython.utils.ipstruct import Struct
26 from IPython.utils.ipstruct import Struct
32 from IPython.utils.process import arg_split
27 from IPython.utils.process import arg_split
33 from IPython.utils.py3compat import string_types, iteritems
28 from IPython.utils.py3compat import string_types, iteritems
34 from IPython.utils.text import dedent
29 from IPython.utils.text import dedent
35 from traitlets import Bool, Dict, Instance
30 from traitlets import Bool, Dict, Instance, observe
36 from logging import error
31 from logging import error
37
32
38 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
39 # Globals
34 # Globals
40 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
41
36
42 # A dict we'll use for each class that has magics, used as temporary storage to
37 # A dict we'll use for each class that has magics, used as temporary storage to
43 # pass information between the @line/cell_magic method decorators and the
38 # pass information between the @line/cell_magic method decorators and the
44 # @magics_class class decorator, because the method decorators have no
39 # @magics_class class decorator, because the method decorators have no
45 # access to the class when they run. See for more details:
40 # access to the class when they run. See for more details:
46 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
41 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
47
42
48 magics = dict(line={}, cell={})
43 magics = dict(line={}, cell={})
49
44
50 magic_kinds = ('line', 'cell')
45 magic_kinds = ('line', 'cell')
51 magic_spec = ('line', 'cell', 'line_cell')
46 magic_spec = ('line', 'cell', 'line_cell')
52 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
47 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
53
48
54 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
55 # Utility classes and functions
50 # Utility classes and functions
56 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
57
52
58 class Bunch: pass
53 class Bunch: pass
59
54
60
55
61 def on_off(tag):
56 def on_off(tag):
62 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
57 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
63 return ['OFF','ON'][tag]
58 return ['OFF','ON'][tag]
64
59
65
60
66 def compress_dhist(dh):
61 def compress_dhist(dh):
67 """Compress a directory history into a new one with at most 20 entries.
62 """Compress a directory history into a new one with at most 20 entries.
68
63
69 Return a new list made from the first and last 10 elements of dhist after
64 Return a new list made from the first and last 10 elements of dhist after
70 removal of duplicates.
65 removal of duplicates.
71 """
66 """
72 head, tail = dh[:-10], dh[-10:]
67 head, tail = dh[:-10], dh[-10:]
73
68
74 newhead = []
69 newhead = []
75 done = set()
70 done = set()
76 for h in head:
71 for h in head:
77 if h in done:
72 if h in done:
78 continue
73 continue
79 newhead.append(h)
74 newhead.append(h)
80 done.add(h)
75 done.add(h)
81
76
82 return newhead + tail
77 return newhead + tail
83
78
84
79
85 def needs_local_scope(func):
80 def needs_local_scope(func):
86 """Decorator to mark magic functions which need to local scope to run."""
81 """Decorator to mark magic functions which need to local scope to run."""
87 func.needs_local_scope = True
82 func.needs_local_scope = True
88 return func
83 return func
89
84
90 #-----------------------------------------------------------------------------
85 #-----------------------------------------------------------------------------
91 # Class and method decorators for registering magics
86 # Class and method decorators for registering magics
92 #-----------------------------------------------------------------------------
87 #-----------------------------------------------------------------------------
93
88
94 def magics_class(cls):
89 def magics_class(cls):
95 """Class decorator for all subclasses of the main Magics class.
90 """Class decorator for all subclasses of the main Magics class.
96
91
97 Any class that subclasses Magics *must* also apply this decorator, to
92 Any class that subclasses Magics *must* also apply this decorator, to
98 ensure that all the methods that have been decorated as line/cell magics
93 ensure that all the methods that have been decorated as line/cell magics
99 get correctly registered in the class instance. This is necessary because
94 get correctly registered in the class instance. This is necessary because
100 when method decorators run, the class does not exist yet, so they
95 when method decorators run, the class does not exist yet, so they
101 temporarily store their information into a module global. Application of
96 temporarily store their information into a module global. Application of
102 this class decorator copies that global data to the class instance and
97 this class decorator copies that global data to the class instance and
103 clears the global.
98 clears the global.
104
99
105 Obviously, this mechanism is not thread-safe, which means that the
100 Obviously, this mechanism is not thread-safe, which means that the
106 *creation* of subclasses of Magic should only be done in a single-thread
101 *creation* of subclasses of Magic should only be done in a single-thread
107 context. Instantiation of the classes has no restrictions. Given that
102 context. Instantiation of the classes has no restrictions. Given that
108 these classes are typically created at IPython startup time and before user
103 these classes are typically created at IPython startup time and before user
109 application code becomes active, in practice this should not pose any
104 application code becomes active, in practice this should not pose any
110 problems.
105 problems.
111 """
106 """
112 cls.registered = True
107 cls.registered = True
113 cls.magics = dict(line = magics['line'],
108 cls.magics = dict(line = magics['line'],
114 cell = magics['cell'])
109 cell = magics['cell'])
115 magics['line'] = {}
110 magics['line'] = {}
116 magics['cell'] = {}
111 magics['cell'] = {}
117 return cls
112 return cls
118
113
119
114
120 def record_magic(dct, magic_kind, magic_name, func):
115 def record_magic(dct, magic_kind, magic_name, func):
121 """Utility function to store a function as a magic of a specific kind.
116 """Utility function to store a function as a magic of a specific kind.
122
117
123 Parameters
118 Parameters
124 ----------
119 ----------
125 dct : dict
120 dct : dict
126 A dictionary with 'line' and 'cell' subdicts.
121 A dictionary with 'line' and 'cell' subdicts.
127
122
128 magic_kind : str
123 magic_kind : str
129 Kind of magic to be stored.
124 Kind of magic to be stored.
130
125
131 magic_name : str
126 magic_name : str
132 Key to store the magic as.
127 Key to store the magic as.
133
128
134 func : function
129 func : function
135 Callable object to store.
130 Callable object to store.
136 """
131 """
137 if magic_kind == 'line_cell':
132 if magic_kind == 'line_cell':
138 dct['line'][magic_name] = dct['cell'][magic_name] = func
133 dct['line'][magic_name] = dct['cell'][magic_name] = func
139 else:
134 else:
140 dct[magic_kind][magic_name] = func
135 dct[magic_kind][magic_name] = func
141
136
142
137
143 def validate_type(magic_kind):
138 def validate_type(magic_kind):
144 """Ensure that the given magic_kind is valid.
139 """Ensure that the given magic_kind is valid.
145
140
146 Check that the given magic_kind is one of the accepted spec types (stored
141 Check that the given magic_kind is one of the accepted spec types (stored
147 in the global `magic_spec`), raise ValueError otherwise.
142 in the global `magic_spec`), raise ValueError otherwise.
148 """
143 """
149 if magic_kind not in magic_spec:
144 if magic_kind not in magic_spec:
150 raise ValueError('magic_kind must be one of %s, %s given' %
145 raise ValueError('magic_kind must be one of %s, %s given' %
151 magic_kinds, magic_kind)
146 magic_kinds, magic_kind)
152
147
153
148
154 # The docstrings for the decorator below will be fairly similar for the two
149 # The docstrings for the decorator below will be fairly similar for the two
155 # types (method and function), so we generate them here once and reuse the
150 # types (method and function), so we generate them here once and reuse the
156 # templates below.
151 # templates below.
157 _docstring_template = \
152 _docstring_template = \
158 """Decorate the given {0} as {1} magic.
153 """Decorate the given {0} as {1} magic.
159
154
160 The decorator can be used with or without arguments, as follows.
155 The decorator can be used with or without arguments, as follows.
161
156
162 i) without arguments: it will create a {1} magic named as the {0} being
157 i) without arguments: it will create a {1} magic named as the {0} being
163 decorated::
158 decorated::
164
159
165 @deco
160 @deco
166 def foo(...)
161 def foo(...)
167
162
168 will create a {1} magic named `foo`.
163 will create a {1} magic named `foo`.
169
164
170 ii) with one string argument: which will be used as the actual name of the
165 ii) with one string argument: which will be used as the actual name of the
171 resulting magic::
166 resulting magic::
172
167
173 @deco('bar')
168 @deco('bar')
174 def foo(...)
169 def foo(...)
175
170
176 will create a {1} magic named `bar`.
171 will create a {1} magic named `bar`.
177 """
172 """
178
173
179 # These two are decorator factories. While they are conceptually very similar,
174 # These two are decorator factories. While they are conceptually very similar,
180 # there are enough differences in the details that it's simpler to have them
175 # there are enough differences in the details that it's simpler to have them
181 # written as completely standalone functions rather than trying to share code
176 # written as completely standalone functions rather than trying to share code
182 # and make a single one with convoluted logic.
177 # and make a single one with convoluted logic.
183
178
184 def _method_magic_marker(magic_kind):
179 def _method_magic_marker(magic_kind):
185 """Decorator factory for methods in Magics subclasses.
180 """Decorator factory for methods in Magics subclasses.
186 """
181 """
187
182
188 validate_type(magic_kind)
183 validate_type(magic_kind)
189
184
190 # This is a closure to capture the magic_kind. We could also use a class,
185 # This is a closure to capture the magic_kind. We could also use a class,
191 # but it's overkill for just that one bit of state.
186 # but it's overkill for just that one bit of state.
192 def magic_deco(arg):
187 def magic_deco(arg):
193 call = lambda f, *a, **k: f(*a, **k)
188 call = lambda f, *a, **k: f(*a, **k)
194
189
195 if callable(arg):
190 if callable(arg):
196 # "Naked" decorator call (just @foo, no args)
191 # "Naked" decorator call (just @foo, no args)
197 func = arg
192 func = arg
198 name = func.__name__
193 name = func.__name__
199 retval = decorator(call, func)
194 retval = decorator(call, func)
200 record_magic(magics, magic_kind, name, name)
195 record_magic(magics, magic_kind, name, name)
201 elif isinstance(arg, string_types):
196 elif isinstance(arg, string_types):
202 # Decorator called with arguments (@foo('bar'))
197 # Decorator called with arguments (@foo('bar'))
203 name = arg
198 name = arg
204 def mark(func, *a, **kw):
199 def mark(func, *a, **kw):
205 record_magic(magics, magic_kind, name, func.__name__)
200 record_magic(magics, magic_kind, name, func.__name__)
206 return decorator(call, func)
201 return decorator(call, func)
207 retval = mark
202 retval = mark
208 else:
203 else:
209 raise TypeError("Decorator can only be called with "
204 raise TypeError("Decorator can only be called with "
210 "string or function")
205 "string or function")
211 return retval
206 return retval
212
207
213 # Ensure the resulting decorator has a usable docstring
208 # Ensure the resulting decorator has a usable docstring
214 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
209 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
215 return magic_deco
210 return magic_deco
216
211
217
212
218 def _function_magic_marker(magic_kind):
213 def _function_magic_marker(magic_kind):
219 """Decorator factory for standalone functions.
214 """Decorator factory for standalone functions.
220 """
215 """
221 validate_type(magic_kind)
216 validate_type(magic_kind)
222
217
223 # This is a closure to capture the magic_kind. We could also use a class,
218 # This is a closure to capture the magic_kind. We could also use a class,
224 # but it's overkill for just that one bit of state.
219 # but it's overkill for just that one bit of state.
225 def magic_deco(arg):
220 def magic_deco(arg):
226 call = lambda f, *a, **k: f(*a, **k)
221 call = lambda f, *a, **k: f(*a, **k)
227
222
228 # Find get_ipython() in the caller's namespace
223 # Find get_ipython() in the caller's namespace
229 caller = sys._getframe(1)
224 caller = sys._getframe(1)
230 for ns in ['f_locals', 'f_globals', 'f_builtins']:
225 for ns in ['f_locals', 'f_globals', 'f_builtins']:
231 get_ipython = getattr(caller, ns).get('get_ipython')
226 get_ipython = getattr(caller, ns).get('get_ipython')
232 if get_ipython is not None:
227 if get_ipython is not None:
233 break
228 break
234 else:
229 else:
235 raise NameError('Decorator can only run in context where '
230 raise NameError('Decorator can only run in context where '
236 '`get_ipython` exists')
231 '`get_ipython` exists')
237
232
238 ip = get_ipython()
233 ip = get_ipython()
239
234
240 if callable(arg):
235 if callable(arg):
241 # "Naked" decorator call (just @foo, no args)
236 # "Naked" decorator call (just @foo, no args)
242 func = arg
237 func = arg
243 name = func.__name__
238 name = func.__name__
244 ip.register_magic_function(func, magic_kind, name)
239 ip.register_magic_function(func, magic_kind, name)
245 retval = decorator(call, func)
240 retval = decorator(call, func)
246 elif isinstance(arg, string_types):
241 elif isinstance(arg, string_types):
247 # Decorator called with arguments (@foo('bar'))
242 # Decorator called with arguments (@foo('bar'))
248 name = arg
243 name = arg
249 def mark(func, *a, **kw):
244 def mark(func, *a, **kw):
250 ip.register_magic_function(func, magic_kind, name)
245 ip.register_magic_function(func, magic_kind, name)
251 return decorator(call, func)
246 return decorator(call, func)
252 retval = mark
247 retval = mark
253 else:
248 else:
254 raise TypeError("Decorator can only be called with "
249 raise TypeError("Decorator can only be called with "
255 "string or function")
250 "string or function")
256 return retval
251 return retval
257
252
258 # Ensure the resulting decorator has a usable docstring
253 # Ensure the resulting decorator has a usable docstring
259 ds = _docstring_template.format('function', magic_kind)
254 ds = _docstring_template.format('function', magic_kind)
260
255
261 ds += dedent("""
256 ds += dedent("""
262 Note: this decorator can only be used in a context where IPython is already
257 Note: this decorator can only be used in a context where IPython is already
263 active, so that the `get_ipython()` call succeeds. You can therefore use
258 active, so that the `get_ipython()` call succeeds. You can therefore use
264 it in your startup files loaded after IPython initializes, but *not* in the
259 it in your startup files loaded after IPython initializes, but *not* in the
265 IPython configuration file itself, which is executed before IPython is
260 IPython configuration file itself, which is executed before IPython is
266 fully up and running. Any file located in the `startup` subdirectory of
261 fully up and running. Any file located in the `startup` subdirectory of
267 your configuration profile will be OK in this sense.
262 your configuration profile will be OK in this sense.
268 """)
263 """)
269
264
270 magic_deco.__doc__ = ds
265 magic_deco.__doc__ = ds
271 return magic_deco
266 return magic_deco
272
267
273
268
274 # Create the actual decorators for public use
269 # Create the actual decorators for public use
275
270
276 # These three are used to decorate methods in class definitions
271 # These three are used to decorate methods in class definitions
277 line_magic = _method_magic_marker('line')
272 line_magic = _method_magic_marker('line')
278 cell_magic = _method_magic_marker('cell')
273 cell_magic = _method_magic_marker('cell')
279 line_cell_magic = _method_magic_marker('line_cell')
274 line_cell_magic = _method_magic_marker('line_cell')
280
275
281 # These three decorate standalone functions and perform the decoration
276 # These three decorate standalone functions and perform the decoration
282 # immediately. They can only run where get_ipython() works
277 # immediately. They can only run where get_ipython() works
283 register_line_magic = _function_magic_marker('line')
278 register_line_magic = _function_magic_marker('line')
284 register_cell_magic = _function_magic_marker('cell')
279 register_cell_magic = _function_magic_marker('cell')
285 register_line_cell_magic = _function_magic_marker('line_cell')
280 register_line_cell_magic = _function_magic_marker('line_cell')
286
281
287 #-----------------------------------------------------------------------------
282 #-----------------------------------------------------------------------------
288 # Core Magic classes
283 # Core Magic classes
289 #-----------------------------------------------------------------------------
284 #-----------------------------------------------------------------------------
290
285
291 class MagicsManager(Configurable):
286 class MagicsManager(Configurable):
292 """Object that handles all magic-related functionality for IPython.
287 """Object that handles all magic-related functionality for IPython.
293 """
288 """
294 # Non-configurable class attributes
289 # Non-configurable class attributes
295
290
296 # A two-level dict, first keyed by magic type, then by magic function, and
291 # A two-level dict, first keyed by magic type, then by magic function, and
297 # holding the actual callable object as value. This is the dict used for
292 # holding the actual callable object as value. This is the dict used for
298 # magic function dispatch
293 # magic function dispatch
299 magics = Dict()
294 magics = Dict()
300
295
301 # A registry of the original objects that we've been given holding magics.
296 # A registry of the original objects that we've been given holding magics.
302 registry = Dict()
297 registry = Dict()
303
298
304 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
299 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
305
300
306 auto_magic = Bool(True, config=True, help=
301 auto_magic = Bool(True, help=
307 "Automatically call line magics without requiring explicit % prefix")
302 "Automatically call line magics without requiring explicit % prefix"
308
303 ).tag(config=True)
309 def _auto_magic_changed(self, name, value):
304 @observe('auto_magic')
310 self.shell.automagic = value
305 def _auto_magic_changed(self, change):
306 self.shell.automagic = change['new']
311
307
312 _auto_status = [
308 _auto_status = [
313 'Automagic is OFF, % prefix IS needed for line magics.',
309 'Automagic is OFF, % prefix IS needed for line magics.',
314 'Automagic is ON, % prefix IS NOT needed for line magics.']
310 'Automagic is ON, % prefix IS NOT needed for line magics.']
315
311
316 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
312 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
317
313
318 def __init__(self, shell=None, config=None, user_magics=None, **traits):
314 def __init__(self, shell=None, config=None, user_magics=None, **traits):
319
315
320 super(MagicsManager, self).__init__(shell=shell, config=config,
316 super(MagicsManager, self).__init__(shell=shell, config=config,
321 user_magics=user_magics, **traits)
317 user_magics=user_magics, **traits)
322 self.magics = dict(line={}, cell={})
318 self.magics = dict(line={}, cell={})
323 # Let's add the user_magics to the registry for uniformity, so *all*
319 # Let's add the user_magics to the registry for uniformity, so *all*
324 # registered magic containers can be found there.
320 # registered magic containers can be found there.
325 self.registry[user_magics.__class__.__name__] = user_magics
321 self.registry[user_magics.__class__.__name__] = user_magics
326
322
327 def auto_status(self):
323 def auto_status(self):
328 """Return descriptive string with automagic status."""
324 """Return descriptive string with automagic status."""
329 return self._auto_status[self.auto_magic]
325 return self._auto_status[self.auto_magic]
330
326
331 def lsmagic(self):
327 def lsmagic(self):
332 """Return a dict of currently available magic functions.
328 """Return a dict of currently available magic functions.
333
329
334 The return dict has the keys 'line' and 'cell', corresponding to the
330 The return dict has the keys 'line' and 'cell', corresponding to the
335 two types of magics we support. Each value is a list of names.
331 two types of magics we support. Each value is a list of names.
336 """
332 """
337 return self.magics
333 return self.magics
338
334
339 def lsmagic_docs(self, brief=False, missing=''):
335 def lsmagic_docs(self, brief=False, missing=''):
340 """Return dict of documentation of magic functions.
336 """Return dict of documentation of magic functions.
341
337
342 The return dict has the keys 'line' and 'cell', corresponding to the
338 The return dict has the keys 'line' and 'cell', corresponding to the
343 two types of magics we support. Each value is a dict keyed by magic
339 two types of magics we support. Each value is a dict keyed by magic
344 name whose value is the function docstring. If a docstring is
340 name whose value is the function docstring. If a docstring is
345 unavailable, the value of `missing` is used instead.
341 unavailable, the value of `missing` is used instead.
346
342
347 If brief is True, only the first line of each docstring will be returned.
343 If brief is True, only the first line of each docstring will be returned.
348 """
344 """
349 docs = {}
345 docs = {}
350 for m_type in self.magics:
346 for m_type in self.magics:
351 m_docs = {}
347 m_docs = {}
352 for m_name, m_func in iteritems(self.magics[m_type]):
348 for m_name, m_func in iteritems(self.magics[m_type]):
353 if m_func.__doc__:
349 if m_func.__doc__:
354 if brief:
350 if brief:
355 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
351 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
356 else:
352 else:
357 m_docs[m_name] = m_func.__doc__.rstrip()
353 m_docs[m_name] = m_func.__doc__.rstrip()
358 else:
354 else:
359 m_docs[m_name] = missing
355 m_docs[m_name] = missing
360 docs[m_type] = m_docs
356 docs[m_type] = m_docs
361 return docs
357 return docs
362
358
363 def register(self, *magic_objects):
359 def register(self, *magic_objects):
364 """Register one or more instances of Magics.
360 """Register one or more instances of Magics.
365
361
366 Take one or more classes or instances of classes that subclass the main
362 Take one or more classes or instances of classes that subclass the main
367 `core.Magic` class, and register them with IPython to use the magic
363 `core.Magic` class, and register them with IPython to use the magic
368 functions they provide. The registration process will then ensure that
364 functions they provide. The registration process will then ensure that
369 any methods that have decorated to provide line and/or cell magics will
365 any methods that have decorated to provide line and/or cell magics will
370 be recognized with the `%x`/`%%x` syntax as a line/cell magic
366 be recognized with the `%x`/`%%x` syntax as a line/cell magic
371 respectively.
367 respectively.
372
368
373 If classes are given, they will be instantiated with the default
369 If classes are given, they will be instantiated with the default
374 constructor. If your classes need a custom constructor, you should
370 constructor. If your classes need a custom constructor, you should
375 instanitate them first and pass the instance.
371 instanitate them first and pass the instance.
376
372
377 The provided arguments can be an arbitrary mix of classes and instances.
373 The provided arguments can be an arbitrary mix of classes and instances.
378
374
379 Parameters
375 Parameters
380 ----------
376 ----------
381 magic_objects : one or more classes or instances
377 magic_objects : one or more classes or instances
382 """
378 """
383 # Start by validating them to ensure they have all had their magic
379 # Start by validating them to ensure they have all had their magic
384 # methods registered at the instance level
380 # methods registered at the instance level
385 for m in magic_objects:
381 for m in magic_objects:
386 if not m.registered:
382 if not m.registered:
387 raise ValueError("Class of magics %r was constructed without "
383 raise ValueError("Class of magics %r was constructed without "
388 "the @register_magics class decorator")
384 "the @register_magics class decorator")
389 if isinstance(m, type):
385 if isinstance(m, type):
390 # If we're given an uninstantiated class
386 # If we're given an uninstantiated class
391 m = m(shell=self.shell)
387 m = m(shell=self.shell)
392
388
393 # Now that we have an instance, we can register it and update the
389 # Now that we have an instance, we can register it and update the
394 # table of callables
390 # table of callables
395 self.registry[m.__class__.__name__] = m
391 self.registry[m.__class__.__name__] = m
396 for mtype in magic_kinds:
392 for mtype in magic_kinds:
397 self.magics[mtype].update(m.magics[mtype])
393 self.magics[mtype].update(m.magics[mtype])
398
394
399 def register_function(self, func, magic_kind='line', magic_name=None):
395 def register_function(self, func, magic_kind='line', magic_name=None):
400 """Expose a standalone function as magic function for IPython.
396 """Expose a standalone function as magic function for IPython.
401
397
402 This will create an IPython magic (line, cell or both) from a
398 This will create an IPython magic (line, cell or both) from a
403 standalone function. The functions should have the following
399 standalone function. The functions should have the following
404 signatures:
400 signatures:
405
401
406 * For line magics: `def f(line)`
402 * For line magics: `def f(line)`
407 * For cell magics: `def f(line, cell)`
403 * For cell magics: `def f(line, cell)`
408 * For a function that does both: `def f(line, cell=None)`
404 * For a function that does both: `def f(line, cell=None)`
409
405
410 In the latter case, the function will be called with `cell==None` when
406 In the latter case, the function will be called with `cell==None` when
411 invoked as `%f`, and with cell as a string when invoked as `%%f`.
407 invoked as `%f`, and with cell as a string when invoked as `%%f`.
412
408
413 Parameters
409 Parameters
414 ----------
410 ----------
415 func : callable
411 func : callable
416 Function to be registered as a magic.
412 Function to be registered as a magic.
417
413
418 magic_kind : str
414 magic_kind : str
419 Kind of magic, one of 'line', 'cell' or 'line_cell'
415 Kind of magic, one of 'line', 'cell' or 'line_cell'
420
416
421 magic_name : optional str
417 magic_name : optional str
422 If given, the name the magic will have in the IPython namespace. By
418 If given, the name the magic will have in the IPython namespace. By
423 default, the name of the function itself is used.
419 default, the name of the function itself is used.
424 """
420 """
425
421
426 # Create the new method in the user_magics and register it in the
422 # Create the new method in the user_magics and register it in the
427 # global table
423 # global table
428 validate_type(magic_kind)
424 validate_type(magic_kind)
429 magic_name = func.__name__ if magic_name is None else magic_name
425 magic_name = func.__name__ if magic_name is None else magic_name
430 setattr(self.user_magics, magic_name, func)
426 setattr(self.user_magics, magic_name, func)
431 record_magic(self.magics, magic_kind, magic_name, func)
427 record_magic(self.magics, magic_kind, magic_name, func)
432
428
433 def define_magic(self, name, func):
429 def define_magic(self, name, func):
434 """[Deprecated] Expose own function as magic function for IPython.
430 """[Deprecated] Expose own function as magic function for IPython.
435
431
436 Will be removed in IPython 5.0
432 Will be removed in IPython 5.0
437
433
438 Example::
434 Example::
439
435
440 def foo_impl(self, parameter_s=''):
436 def foo_impl(self, parameter_s=''):
441 'My very own magic!. (Use docstrings, IPython reads them).'
437 'My very own magic!. (Use docstrings, IPython reads them).'
442 print 'Magic function. Passed parameter is between < >:'
438 print 'Magic function. Passed parameter is between < >:'
443 print '<%s>' % parameter_s
439 print '<%s>' % parameter_s
444 print 'The self object is:', self
440 print 'The self object is:', self
445
441
446 ip.define_magic('foo',foo_impl)
442 ip.define_magic('foo',foo_impl)
447 """
443 """
448 meth = types.MethodType(func, self.user_magics)
444 meth = types.MethodType(func, self.user_magics)
449 setattr(self.user_magics, name, meth)
445 setattr(self.user_magics, name, meth)
450 record_magic(self.magics, 'line', name, meth)
446 record_magic(self.magics, 'line', name, meth)
451
447
452 def register_alias(self, alias_name, magic_name, magic_kind='line'):
448 def register_alias(self, alias_name, magic_name, magic_kind='line'):
453 """Register an alias to a magic function.
449 """Register an alias to a magic function.
454
450
455 The alias is an instance of :class:`MagicAlias`, which holds the
451 The alias is an instance of :class:`MagicAlias`, which holds the
456 name and kind of the magic it should call. Binding is done at
452 name and kind of the magic it should call. Binding is done at
457 call time, so if the underlying magic function is changed the alias
453 call time, so if the underlying magic function is changed the alias
458 will call the new function.
454 will call the new function.
459
455
460 Parameters
456 Parameters
461 ----------
457 ----------
462 alias_name : str
458 alias_name : str
463 The name of the magic to be registered.
459 The name of the magic to be registered.
464
460
465 magic_name : str
461 magic_name : str
466 The name of an existing magic.
462 The name of an existing magic.
467
463
468 magic_kind : str
464 magic_kind : str
469 Kind of magic, one of 'line' or 'cell'
465 Kind of magic, one of 'line' or 'cell'
470 """
466 """
471
467
472 # `validate_type` is too permissive, as it allows 'line_cell'
468 # `validate_type` is too permissive, as it allows 'line_cell'
473 # which we do not handle.
469 # which we do not handle.
474 if magic_kind not in magic_kinds:
470 if magic_kind not in magic_kinds:
475 raise ValueError('magic_kind must be one of %s, %s given' %
471 raise ValueError('magic_kind must be one of %s, %s given' %
476 magic_kinds, magic_kind)
472 magic_kinds, magic_kind)
477
473
478 alias = MagicAlias(self.shell, magic_name, magic_kind)
474 alias = MagicAlias(self.shell, magic_name, magic_kind)
479 setattr(self.user_magics, alias_name, alias)
475 setattr(self.user_magics, alias_name, alias)
480 record_magic(self.magics, magic_kind, alias_name, alias)
476 record_magic(self.magics, magic_kind, alias_name, alias)
481
477
482 # Key base class that provides the central functionality for magics.
478 # Key base class that provides the central functionality for magics.
483
479
484
480
485 class Magics(Configurable):
481 class Magics(Configurable):
486 """Base class for implementing magic functions.
482 """Base class for implementing magic functions.
487
483
488 Shell functions which can be reached as %function_name. All magic
484 Shell functions which can be reached as %function_name. All magic
489 functions should accept a string, which they can parse for their own
485 functions should accept a string, which they can parse for their own
490 needs. This can make some functions easier to type, eg `%cd ../`
486 needs. This can make some functions easier to type, eg `%cd ../`
491 vs. `%cd("../")`
487 vs. `%cd("../")`
492
488
493 Classes providing magic functions need to subclass this class, and they
489 Classes providing magic functions need to subclass this class, and they
494 MUST:
490 MUST:
495
491
496 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
492 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
497 individual methods as magic functions, AND
493 individual methods as magic functions, AND
498
494
499 - Use the class decorator `@magics_class` to ensure that the magic
495 - Use the class decorator `@magics_class` to ensure that the magic
500 methods are properly registered at the instance level upon instance
496 methods are properly registered at the instance level upon instance
501 initialization.
497 initialization.
502
498
503 See :mod:`magic_functions` for examples of actual implementation classes.
499 See :mod:`magic_functions` for examples of actual implementation classes.
504 """
500 """
505 # Dict holding all command-line options for each magic.
501 # Dict holding all command-line options for each magic.
506 options_table = None
502 options_table = None
507 # Dict for the mapping of magic names to methods, set by class decorator
503 # Dict for the mapping of magic names to methods, set by class decorator
508 magics = None
504 magics = None
509 # Flag to check that the class decorator was properly applied
505 # Flag to check that the class decorator was properly applied
510 registered = False
506 registered = False
511 # Instance of IPython shell
507 # Instance of IPython shell
512 shell = None
508 shell = None
513
509
514 def __init__(self, shell=None, **kwargs):
510 def __init__(self, shell=None, **kwargs):
515 if not(self.__class__.registered):
511 if not(self.__class__.registered):
516 raise ValueError('Magics subclass without registration - '
512 raise ValueError('Magics subclass without registration - '
517 'did you forget to apply @magics_class?')
513 'did you forget to apply @magics_class?')
518 if shell is not None:
514 if shell is not None:
519 if hasattr(shell, 'configurables'):
515 if hasattr(shell, 'configurables'):
520 shell.configurables.append(self)
516 shell.configurables.append(self)
521 if hasattr(shell, 'config'):
517 if hasattr(shell, 'config'):
522 kwargs.setdefault('parent', shell)
518 kwargs.setdefault('parent', shell)
523
519
524 self.shell = shell
520 self.shell = shell
525 self.options_table = {}
521 self.options_table = {}
526 # The method decorators are run when the instance doesn't exist yet, so
522 # The method decorators are run when the instance doesn't exist yet, so
527 # they can only record the names of the methods they are supposed to
523 # they can only record the names of the methods they are supposed to
528 # grab. Only now, that the instance exists, can we create the proper
524 # grab. Only now, that the instance exists, can we create the proper
529 # mapping to bound methods. So we read the info off the original names
525 # mapping to bound methods. So we read the info off the original names
530 # table and replace each method name by the actual bound method.
526 # table and replace each method name by the actual bound method.
531 # But we mustn't clobber the *class* mapping, in case of multiple instances.
527 # But we mustn't clobber the *class* mapping, in case of multiple instances.
532 class_magics = self.magics
528 class_magics = self.magics
533 self.magics = {}
529 self.magics = {}
534 for mtype in magic_kinds:
530 for mtype in magic_kinds:
535 tab = self.magics[mtype] = {}
531 tab = self.magics[mtype] = {}
536 cls_tab = class_magics[mtype]
532 cls_tab = class_magics[mtype]
537 for magic_name, meth_name in iteritems(cls_tab):
533 for magic_name, meth_name in iteritems(cls_tab):
538 if isinstance(meth_name, string_types):
534 if isinstance(meth_name, string_types):
539 # it's a method name, grab it
535 # it's a method name, grab it
540 tab[magic_name] = getattr(self, meth_name)
536 tab[magic_name] = getattr(self, meth_name)
541 else:
537 else:
542 # it's the real thing
538 # it's the real thing
543 tab[magic_name] = meth_name
539 tab[magic_name] = meth_name
544 # Configurable **needs** to be initiated at the end or the config
540 # Configurable **needs** to be initiated at the end or the config
545 # magics get screwed up.
541 # magics get screwed up.
546 super(Magics, self).__init__(**kwargs)
542 super(Magics, self).__init__(**kwargs)
547
543
548 def arg_err(self,func):
544 def arg_err(self,func):
549 """Print docstring if incorrect arguments were passed"""
545 """Print docstring if incorrect arguments were passed"""
550 print('Error in arguments:')
546 print('Error in arguments:')
551 print(oinspect.getdoc(func))
547 print(oinspect.getdoc(func))
552
548
553 def format_latex(self, strng):
549 def format_latex(self, strng):
554 """Format a string for latex inclusion."""
550 """Format a string for latex inclusion."""
555
551
556 # Characters that need to be escaped for latex:
552 # Characters that need to be escaped for latex:
557 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
553 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
558 # Magic command names as headers:
554 # Magic command names as headers:
559 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
555 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
560 re.MULTILINE)
556 re.MULTILINE)
561 # Magic commands
557 # Magic commands
562 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
558 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
563 re.MULTILINE)
559 re.MULTILINE)
564 # Paragraph continue
560 # Paragraph continue
565 par_re = re.compile(r'\\$',re.MULTILINE)
561 par_re = re.compile(r'\\$',re.MULTILINE)
566
562
567 # The "\n" symbol
563 # The "\n" symbol
568 newline_re = re.compile(r'\\n')
564 newline_re = re.compile(r'\\n')
569
565
570 # Now build the string for output:
566 # Now build the string for output:
571 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
567 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
572 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
568 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
573 strng)
569 strng)
574 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
570 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
575 strng = par_re.sub(r'\\\\',strng)
571 strng = par_re.sub(r'\\\\',strng)
576 strng = escape_re.sub(r'\\\1',strng)
572 strng = escape_re.sub(r'\\\1',strng)
577 strng = newline_re.sub(r'\\textbackslash{}n',strng)
573 strng = newline_re.sub(r'\\textbackslash{}n',strng)
578 return strng
574 return strng
579
575
580 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
576 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
581 """Parse options passed to an argument string.
577 """Parse options passed to an argument string.
582
578
583 The interface is similar to that of :func:`getopt.getopt`, but it
579 The interface is similar to that of :func:`getopt.getopt`, but it
584 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
580 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
585 and the stripped argument string still as a string.
581 and the stripped argument string still as a string.
586
582
587 arg_str is quoted as a true sys.argv vector by using shlex.split.
583 arg_str is quoted as a true sys.argv vector by using shlex.split.
588 This allows us to easily expand variables, glob files, quote
584 This allows us to easily expand variables, glob files, quote
589 arguments, etc.
585 arguments, etc.
590
586
591 Parameters
587 Parameters
592 ----------
588 ----------
593
589
594 arg_str : str
590 arg_str : str
595 The arguments to parse.
591 The arguments to parse.
596
592
597 opt_str : str
593 opt_str : str
598 The options specification.
594 The options specification.
599
595
600 mode : str, default 'string'
596 mode : str, default 'string'
601 If given as 'list', the argument string is returned as a list (split
597 If given as 'list', the argument string is returned as a list (split
602 on whitespace) instead of a string.
598 on whitespace) instead of a string.
603
599
604 list_all : bool, default False
600 list_all : bool, default False
605 Put all option values in lists. Normally only options
601 Put all option values in lists. Normally only options
606 appearing more than once are put in a list.
602 appearing more than once are put in a list.
607
603
608 posix : bool, default True
604 posix : bool, default True
609 Whether to split the input line in POSIX mode or not, as per the
605 Whether to split the input line in POSIX mode or not, as per the
610 conventions outlined in the :mod:`shlex` module from the standard
606 conventions outlined in the :mod:`shlex` module from the standard
611 library.
607 library.
612 """
608 """
613
609
614 # inject default options at the beginning of the input line
610 # inject default options at the beginning of the input line
615 caller = sys._getframe(1).f_code.co_name
611 caller = sys._getframe(1).f_code.co_name
616 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
612 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
617
613
618 mode = kw.get('mode','string')
614 mode = kw.get('mode','string')
619 if mode not in ['string','list']:
615 if mode not in ['string','list']:
620 raise ValueError('incorrect mode given: %s' % mode)
616 raise ValueError('incorrect mode given: %s' % mode)
621 # Get options
617 # Get options
622 list_all = kw.get('list_all',0)
618 list_all = kw.get('list_all',0)
623 posix = kw.get('posix', os.name == 'posix')
619 posix = kw.get('posix', os.name == 'posix')
624 strict = kw.get('strict', True)
620 strict = kw.get('strict', True)
625
621
626 # Check if we have more than one argument to warrant extra processing:
622 # Check if we have more than one argument to warrant extra processing:
627 odict = {} # Dictionary with options
623 odict = {} # Dictionary with options
628 args = arg_str.split()
624 args = arg_str.split()
629 if len(args) >= 1:
625 if len(args) >= 1:
630 # If the list of inputs only has 0 or 1 thing in it, there's no
626 # If the list of inputs only has 0 or 1 thing in it, there's no
631 # need to look for options
627 # need to look for options
632 argv = arg_split(arg_str, posix, strict)
628 argv = arg_split(arg_str, posix, strict)
633 # Do regular option processing
629 # Do regular option processing
634 try:
630 try:
635 opts,args = getopt(argv, opt_str, long_opts)
631 opts,args = getopt(argv, opt_str, long_opts)
636 except GetoptError as e:
632 except GetoptError as e:
637 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
633 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
638 " ".join(long_opts)))
634 " ".join(long_opts)))
639 for o,a in opts:
635 for o,a in opts:
640 if o.startswith('--'):
636 if o.startswith('--'):
641 o = o[2:]
637 o = o[2:]
642 else:
638 else:
643 o = o[1:]
639 o = o[1:]
644 try:
640 try:
645 odict[o].append(a)
641 odict[o].append(a)
646 except AttributeError:
642 except AttributeError:
647 odict[o] = [odict[o],a]
643 odict[o] = [odict[o],a]
648 except KeyError:
644 except KeyError:
649 if list_all:
645 if list_all:
650 odict[o] = [a]
646 odict[o] = [a]
651 else:
647 else:
652 odict[o] = a
648 odict[o] = a
653
649
654 # Prepare opts,args for return
650 # Prepare opts,args for return
655 opts = Struct(odict)
651 opts = Struct(odict)
656 if mode == 'string':
652 if mode == 'string':
657 args = ' '.join(args)
653 args = ' '.join(args)
658
654
659 return opts,args
655 return opts,args
660
656
661 def default_option(self, fn, optstr):
657 def default_option(self, fn, optstr):
662 """Make an entry in the options_table for fn, with value optstr"""
658 """Make an entry in the options_table for fn, with value optstr"""
663
659
664 if fn not in self.lsmagic():
660 if fn not in self.lsmagic():
665 error("%s is not a magic function" % fn)
661 error("%s is not a magic function" % fn)
666 self.options_table[fn] = optstr
662 self.options_table[fn] = optstr
667
663
668
664
669 class MagicAlias(object):
665 class MagicAlias(object):
670 """An alias to another magic function.
666 """An alias to another magic function.
671
667
672 An alias is determined by its magic name and magic kind. Lookup
668 An alias is determined by its magic name and magic kind. Lookup
673 is done at call time, so if the underlying magic changes the alias
669 is done at call time, so if the underlying magic changes the alias
674 will call the new function.
670 will call the new function.
675
671
676 Use the :meth:`MagicsManager.register_alias` method or the
672 Use the :meth:`MagicsManager.register_alias` method or the
677 `%alias_magic` magic function to create and register a new alias.
673 `%alias_magic` magic function to create and register a new alias.
678 """
674 """
679 def __init__(self, shell, magic_name, magic_kind):
675 def __init__(self, shell, magic_name, magic_kind):
680 self.shell = shell
676 self.shell = shell
681 self.magic_name = magic_name
677 self.magic_name = magic_name
682 self.magic_kind = magic_kind
678 self.magic_kind = magic_kind
683
679
684 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
680 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
685 self.__doc__ = "Alias for `%s`." % self.pretty_target
681 self.__doc__ = "Alias for `%s`." % self.pretty_target
686
682
687 self._in_call = False
683 self._in_call = False
688
684
689 def __call__(self, *args, **kwargs):
685 def __call__(self, *args, **kwargs):
690 """Call the magic alias."""
686 """Call the magic alias."""
691 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
687 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
692 if fn is None:
688 if fn is None:
693 raise UsageError("Magic `%s` not found." % self.pretty_target)
689 raise UsageError("Magic `%s` not found." % self.pretty_target)
694
690
695 # Protect against infinite recursion.
691 # Protect against infinite recursion.
696 if self._in_call:
692 if self._in_call:
697 raise UsageError("Infinite recursion detected; "
693 raise UsageError("Infinite recursion detected; "
698 "magic aliases cannot call themselves.")
694 "magic aliases cannot call themselves.")
699 self._in_call = True
695 self._in_call = True
700 try:
696 try:
701 return fn(*args, **kwargs)
697 return fn(*args, **kwargs)
702 finally:
698 finally:
703 self._in_call = False
699 self._in_call = False
@@ -1,282 +1,272 b''
1 """Magic functions for running cells in various scripts."""
1 """Magic functions for running cells in various scripts."""
2 from __future__ import print_function
2 from __future__ import print_function
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
3
11 #-----------------------------------------------------------------------------
4 # Copyright (c) IPython Development Team.
12 # Imports
5 # Distributed under the terms of the Modified BSD License.
13 #-----------------------------------------------------------------------------
14
6
15 # Stdlib
16 import errno
7 import errno
17 import os
8 import os
18 import sys
9 import sys
19 import signal
10 import signal
20 import time
11 import time
21 from subprocess import Popen, PIPE
12 from subprocess import Popen, PIPE
22 import atexit
13 import atexit
23
14
24 # Our own packages
25 from traitlets.config.configurable import Configurable
26 from IPython.core import magic_arguments
15 from IPython.core import magic_arguments
27 from IPython.core.magic import (
16 from IPython.core.magic import (
28 Magics, magics_class, line_magic, cell_magic
17 Magics, magics_class, line_magic, cell_magic
29 )
18 )
30 from IPython.lib.backgroundjobs import BackgroundJobManager
19 from IPython.lib.backgroundjobs import BackgroundJobManager
31 from IPython.utils import py3compat
20 from IPython.utils import py3compat
32 from IPython.utils.process import arg_split
21 from IPython.utils.process import arg_split
33 from traitlets import List, Dict
22 from traitlets import List, Dict, default
34
23
35 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
36 # Magic implementation classes
25 # Magic implementation classes
37 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
38
27
39 def script_args(f):
28 def script_args(f):
40 """single decorator for adding script args"""
29 """single decorator for adding script args"""
41 args = [
30 args = [
42 magic_arguments.argument(
31 magic_arguments.argument(
43 '--out', type=str,
32 '--out', type=str,
44 help="""The variable in which to store stdout from the script.
33 help="""The variable in which to store stdout from the script.
45 If the script is backgrounded, this will be the stdout *pipe*,
34 If the script is backgrounded, this will be the stdout *pipe*,
46 instead of the stderr text itself.
35 instead of the stderr text itself.
47 """
36 """
48 ),
37 ),
49 magic_arguments.argument(
38 magic_arguments.argument(
50 '--err', type=str,
39 '--err', type=str,
51 help="""The variable in which to store stderr from the script.
40 help="""The variable in which to store stderr from the script.
52 If the script is backgrounded, this will be the stderr *pipe*,
41 If the script is backgrounded, this will be the stderr *pipe*,
53 instead of the stderr text itself.
42 instead of the stderr text itself.
54 """
43 """
55 ),
44 ),
56 magic_arguments.argument(
45 magic_arguments.argument(
57 '--bg', action="store_true",
46 '--bg', action="store_true",
58 help="""Whether to run the script in the background.
47 help="""Whether to run the script in the background.
59 If given, the only way to see the output of the command is
48 If given, the only way to see the output of the command is
60 with --out/err.
49 with --out/err.
61 """
50 """
62 ),
51 ),
63 magic_arguments.argument(
52 magic_arguments.argument(
64 '--proc', type=str,
53 '--proc', type=str,
65 help="""The variable in which to store Popen instance.
54 help="""The variable in which to store Popen instance.
66 This is used only when --bg option is given.
55 This is used only when --bg option is given.
67 """
56 """
68 ),
57 ),
69 ]
58 ]
70 for arg in args:
59 for arg in args:
71 f = arg(f)
60 f = arg(f)
72 return f
61 return f
73
62
74 @magics_class
63 @magics_class
75 class ScriptMagics(Magics):
64 class ScriptMagics(Magics):
76 """Magics for talking to scripts
65 """Magics for talking to scripts
77
66
78 This defines a base `%%script` cell magic for running a cell
67 This defines a base `%%script` cell magic for running a cell
79 with a program in a subprocess, and registers a few top-level
68 with a program in a subprocess, and registers a few top-level
80 magics that call %%script with common interpreters.
69 magics that call %%script with common interpreters.
81 """
70 """
82 script_magics = List(config=True,
71 script_magics = List(
83 help="""Extra script cell magics to define
72 help="""Extra script cell magics to define
84
73
85 This generates simple wrappers of `%%script foo` as `%%foo`.
74 This generates simple wrappers of `%%script foo` as `%%foo`.
86
75
87 If you want to add script magics that aren't on your path,
76 If you want to add script magics that aren't on your path,
88 specify them in script_paths
77 specify them in script_paths
89 """,
78 """,
90 )
79 ).tag(config=True)
80 @default('script_magics')
91 def _script_magics_default(self):
81 def _script_magics_default(self):
92 """default to a common list of programs"""
82 """default to a common list of programs"""
93
83
94 defaults = [
84 defaults = [
95 'sh',
85 'sh',
96 'bash',
86 'bash',
97 'perl',
87 'perl',
98 'ruby',
88 'ruby',
99 'python',
89 'python',
100 'python2',
90 'python2',
101 'python3',
91 'python3',
102 'pypy',
92 'pypy',
103 ]
93 ]
104 if os.name == 'nt':
94 if os.name == 'nt':
105 defaults.extend([
95 defaults.extend([
106 'cmd',
96 'cmd',
107 ])
97 ])
108
98
109 return defaults
99 return defaults
110
100
111 script_paths = Dict(config=True,
101 script_paths = Dict(
112 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
102 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
113
103
114 Only necessary for items in script_magics where the default path will not
104 Only necessary for items in script_magics where the default path will not
115 find the right interpreter.
105 find the right interpreter.
116 """
106 """
117 )
107 ).tag(config=True)
118
108
119 def __init__(self, shell=None):
109 def __init__(self, shell=None):
120 super(ScriptMagics, self).__init__(shell=shell)
110 super(ScriptMagics, self).__init__(shell=shell)
121 self._generate_script_magics()
111 self._generate_script_magics()
122 self.job_manager = BackgroundJobManager()
112 self.job_manager = BackgroundJobManager()
123 self.bg_processes = []
113 self.bg_processes = []
124 atexit.register(self.kill_bg_processes)
114 atexit.register(self.kill_bg_processes)
125
115
126 def __del__(self):
116 def __del__(self):
127 self.kill_bg_processes()
117 self.kill_bg_processes()
128
118
129 def _generate_script_magics(self):
119 def _generate_script_magics(self):
130 cell_magics = self.magics['cell']
120 cell_magics = self.magics['cell']
131 for name in self.script_magics:
121 for name in self.script_magics:
132 cell_magics[name] = self._make_script_magic(name)
122 cell_magics[name] = self._make_script_magic(name)
133
123
134 def _make_script_magic(self, name):
124 def _make_script_magic(self, name):
135 """make a named magic, that calls %%script with a particular program"""
125 """make a named magic, that calls %%script with a particular program"""
136 # expand to explicit path if necessary:
126 # expand to explicit path if necessary:
137 script = self.script_paths.get(name, name)
127 script = self.script_paths.get(name, name)
138
128
139 @magic_arguments.magic_arguments()
129 @magic_arguments.magic_arguments()
140 @script_args
130 @script_args
141 def named_script_magic(line, cell):
131 def named_script_magic(line, cell):
142 # if line, add it as cl-flags
132 # if line, add it as cl-flags
143 if line:
133 if line:
144 line = "%s %s" % (script, line)
134 line = "%s %s" % (script, line)
145 else:
135 else:
146 line = script
136 line = script
147 return self.shebang(line, cell)
137 return self.shebang(line, cell)
148
138
149 # write a basic docstring:
139 # write a basic docstring:
150 named_script_magic.__doc__ = \
140 named_script_magic.__doc__ = \
151 """%%{name} script magic
141 """%%{name} script magic
152
142
153 Run cells with {script} in a subprocess.
143 Run cells with {script} in a subprocess.
154
144
155 This is a shortcut for `%%script {script}`
145 This is a shortcut for `%%script {script}`
156 """.format(**locals())
146 """.format(**locals())
157
147
158 return named_script_magic
148 return named_script_magic
159
149
160 @magic_arguments.magic_arguments()
150 @magic_arguments.magic_arguments()
161 @script_args
151 @script_args
162 @cell_magic("script")
152 @cell_magic("script")
163 def shebang(self, line, cell):
153 def shebang(self, line, cell):
164 """Run a cell via a shell command
154 """Run a cell via a shell command
165
155
166 The `%%script` line is like the #! line of script,
156 The `%%script` line is like the #! line of script,
167 specifying a program (bash, perl, ruby, etc.) with which to run.
157 specifying a program (bash, perl, ruby, etc.) with which to run.
168
158
169 The rest of the cell is run by that program.
159 The rest of the cell is run by that program.
170
160
171 Examples
161 Examples
172 --------
162 --------
173 ::
163 ::
174
164
175 In [1]: %%script bash
165 In [1]: %%script bash
176 ...: for i in 1 2 3; do
166 ...: for i in 1 2 3; do
177 ...: echo $i
167 ...: echo $i
178 ...: done
168 ...: done
179 1
169 1
180 2
170 2
181 3
171 3
182 """
172 """
183 argv = arg_split(line, posix = not sys.platform.startswith('win'))
173 argv = arg_split(line, posix = not sys.platform.startswith('win'))
184 args, cmd = self.shebang.parser.parse_known_args(argv)
174 args, cmd = self.shebang.parser.parse_known_args(argv)
185
175
186 try:
176 try:
187 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
177 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
188 except OSError as e:
178 except OSError as e:
189 if e.errno == errno.ENOENT:
179 if e.errno == errno.ENOENT:
190 print("Couldn't find program: %r" % cmd[0])
180 print("Couldn't find program: %r" % cmd[0])
191 return
181 return
192 else:
182 else:
193 raise
183 raise
194
184
195 if not cell.endswith('\n'):
185 if not cell.endswith('\n'):
196 cell += '\n'
186 cell += '\n'
197 cell = cell.encode('utf8', 'replace')
187 cell = cell.encode('utf8', 'replace')
198 if args.bg:
188 if args.bg:
199 self.bg_processes.append(p)
189 self.bg_processes.append(p)
200 self._gc_bg_processes()
190 self._gc_bg_processes()
201 if args.out:
191 if args.out:
202 self.shell.user_ns[args.out] = p.stdout
192 self.shell.user_ns[args.out] = p.stdout
203 if args.err:
193 if args.err:
204 self.shell.user_ns[args.err] = p.stderr
194 self.shell.user_ns[args.err] = p.stderr
205 self.job_manager.new(self._run_script, p, cell, daemon=True)
195 self.job_manager.new(self._run_script, p, cell, daemon=True)
206 if args.proc:
196 if args.proc:
207 self.shell.user_ns[args.proc] = p
197 self.shell.user_ns[args.proc] = p
208 return
198 return
209
199
210 try:
200 try:
211 out, err = p.communicate(cell)
201 out, err = p.communicate(cell)
212 except KeyboardInterrupt:
202 except KeyboardInterrupt:
213 try:
203 try:
214 p.send_signal(signal.SIGINT)
204 p.send_signal(signal.SIGINT)
215 time.sleep(0.1)
205 time.sleep(0.1)
216 if p.poll() is not None:
206 if p.poll() is not None:
217 print("Process is interrupted.")
207 print("Process is interrupted.")
218 return
208 return
219 p.terminate()
209 p.terminate()
220 time.sleep(0.1)
210 time.sleep(0.1)
221 if p.poll() is not None:
211 if p.poll() is not None:
222 print("Process is terminated.")
212 print("Process is terminated.")
223 return
213 return
224 p.kill()
214 p.kill()
225 print("Process is killed.")
215 print("Process is killed.")
226 except OSError:
216 except OSError:
227 pass
217 pass
228 except Exception as e:
218 except Exception as e:
229 print("Error while terminating subprocess (pid=%i): %s" \
219 print("Error while terminating subprocess (pid=%i): %s" \
230 % (p.pid, e))
220 % (p.pid, e))
231 return
221 return
232 out = py3compat.bytes_to_str(out)
222 out = py3compat.bytes_to_str(out)
233 err = py3compat.bytes_to_str(err)
223 err = py3compat.bytes_to_str(err)
234 if args.out:
224 if args.out:
235 self.shell.user_ns[args.out] = out
225 self.shell.user_ns[args.out] = out
236 else:
226 else:
237 sys.stdout.write(out)
227 sys.stdout.write(out)
238 sys.stdout.flush()
228 sys.stdout.flush()
239 if args.err:
229 if args.err:
240 self.shell.user_ns[args.err] = err
230 self.shell.user_ns[args.err] = err
241 else:
231 else:
242 sys.stderr.write(err)
232 sys.stderr.write(err)
243 sys.stderr.flush()
233 sys.stderr.flush()
244
234
245 def _run_script(self, p, cell):
235 def _run_script(self, p, cell):
246 """callback for running the script in the background"""
236 """callback for running the script in the background"""
247 p.stdin.write(cell)
237 p.stdin.write(cell)
248 p.stdin.close()
238 p.stdin.close()
249 p.wait()
239 p.wait()
250
240
251 @line_magic("killbgscripts")
241 @line_magic("killbgscripts")
252 def killbgscripts(self, _nouse_=''):
242 def killbgscripts(self, _nouse_=''):
253 """Kill all BG processes started by %%script and its family."""
243 """Kill all BG processes started by %%script and its family."""
254 self.kill_bg_processes()
244 self.kill_bg_processes()
255 print("All background processes were killed.")
245 print("All background processes were killed.")
256
246
257 def kill_bg_processes(self):
247 def kill_bg_processes(self):
258 """Kill all BG processes which are still running."""
248 """Kill all BG processes which are still running."""
259 for p in self.bg_processes:
249 for p in self.bg_processes:
260 if p.poll() is None:
250 if p.poll() is None:
261 try:
251 try:
262 p.send_signal(signal.SIGINT)
252 p.send_signal(signal.SIGINT)
263 except:
253 except:
264 pass
254 pass
265 time.sleep(0.1)
255 time.sleep(0.1)
266 for p in self.bg_processes:
256 for p in self.bg_processes:
267 if p.poll() is None:
257 if p.poll() is None:
268 try:
258 try:
269 p.terminate()
259 p.terminate()
270 except:
260 except:
271 pass
261 pass
272 time.sleep(0.1)
262 time.sleep(0.1)
273 for p in self.bg_processes:
263 for p in self.bg_processes:
274 if p.poll() is None:
264 if p.poll() is None:
275 try:
265 try:
276 p.kill()
266 p.kill()
277 except:
267 except:
278 pass
268 pass
279 self._gc_bg_processes()
269 self._gc_bg_processes()
280
270
281 def _gc_bg_processes(self):
271 def _gc_bg_processes(self):
282 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
272 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
@@ -1,715 +1,700 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Prefiltering components.
3 Prefiltering components.
4
4
5 Prefilters transform user input before it is exec'd by Python. These
5 Prefilters transform user input before it is exec'd by Python. These
6 transforms are used to implement additional syntax such as !ls and %magic.
6 transforms are used to implement additional syntax such as !ls and %magic.
7
8 Authors:
9
10 * Brian Granger
11 * Fernando Perez
12 * Dan Milstein
13 * Ville Vainio
14 """
7 """
15
8
16 #-----------------------------------------------------------------------------
9 # Copyright (c) IPython Development Team.
17 # Copyright (C) 2008-2011 The IPython Development Team
10 # Distributed under the terms of the Modified BSD License.
18 #
19 # Distributed under the terms of the BSD License. The full license is in
20 # the file COPYING, distributed as part of this software.
21 #-----------------------------------------------------------------------------
22
23 #-----------------------------------------------------------------------------
24 # Imports
25 #-----------------------------------------------------------------------------
26
11
27 from keyword import iskeyword
12 from keyword import iskeyword
28 import re
13 import re
29
14
30 from IPython.core.autocall import IPyAutocall
15 from IPython.core.autocall import IPyAutocall
31 from traitlets.config.configurable import Configurable
16 from traitlets.config.configurable import Configurable
32 from IPython.core.inputsplitter import (
17 from IPython.core.inputsplitter import (
33 ESC_MAGIC,
18 ESC_MAGIC,
34 ESC_QUOTE,
19 ESC_QUOTE,
35 ESC_QUOTE2,
20 ESC_QUOTE2,
36 ESC_PAREN,
21 ESC_PAREN,
37 )
22 )
38 from IPython.core.macro import Macro
23 from IPython.core.macro import Macro
39 from IPython.core.splitinput import LineInfo
24 from IPython.core.splitinput import LineInfo
40
25
41 from traitlets import (
26 from traitlets import (
42 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
27 List, Integer, Unicode, Bool, Instance, CRegExp
43 )
28 )
44
29
45 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
46 # Global utilities, errors and constants
31 # Global utilities, errors and constants
47 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
48
33
49
34
50 class PrefilterError(Exception):
35 class PrefilterError(Exception):
51 pass
36 pass
52
37
53
38
54 # RegExp to identify potential function names
39 # RegExp to identify potential function names
55 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
40 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
56
41
57 # RegExp to exclude strings with this start from autocalling. In
42 # RegExp to exclude strings with this start from autocalling. In
58 # particular, all binary operators should be excluded, so that if foo is
43 # particular, all binary operators should be excluded, so that if foo is
59 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
44 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
60 # characters '!=()' don't need to be checked for, as the checkPythonChars
45 # characters '!=()' don't need to be checked for, as the checkPythonChars
61 # routine explicitely does so, to catch direct calls and rebindings of
46 # routine explicitely does so, to catch direct calls and rebindings of
62 # existing names.
47 # existing names.
63
48
64 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
49 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
65 # it affects the rest of the group in square brackets.
50 # it affects the rest of the group in square brackets.
66 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
51 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
67 r'|^is |^not |^in |^and |^or ')
52 r'|^is |^not |^in |^and |^or ')
68
53
69 # try to catch also methods for stuff in lists/tuples/dicts: off
54 # try to catch also methods for stuff in lists/tuples/dicts: off
70 # (experimental). For this to work, the line_split regexp would need
55 # (experimental). For this to work, the line_split regexp would need
71 # to be modified so it wouldn't break things at '['. That line is
56 # to be modified so it wouldn't break things at '['. That line is
72 # nasty enough that I shouldn't change it until I can test it _well_.
57 # nasty enough that I shouldn't change it until I can test it _well_.
73 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
58 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
74
59
75
60
76 # Handler Check Utilities
61 # Handler Check Utilities
77 def is_shadowed(identifier, ip):
62 def is_shadowed(identifier, ip):
78 """Is the given identifier defined in one of the namespaces which shadow
63 """Is the given identifier defined in one of the namespaces which shadow
79 the alias and magic namespaces? Note that an identifier is different
64 the alias and magic namespaces? Note that an identifier is different
80 than ifun, because it can not contain a '.' character."""
65 than ifun, because it can not contain a '.' character."""
81 # This is much safer than calling ofind, which can change state
66 # This is much safer than calling ofind, which can change state
82 return (identifier in ip.user_ns \
67 return (identifier in ip.user_ns \
83 or identifier in ip.user_global_ns \
68 or identifier in ip.user_global_ns \
84 or identifier in ip.ns_table['builtin']\
69 or identifier in ip.ns_table['builtin']\
85 or iskeyword(identifier))
70 or iskeyword(identifier))
86
71
87
72
88 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
89 # Main Prefilter manager
74 # Main Prefilter manager
90 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
91
76
92
77
93 class PrefilterManager(Configurable):
78 class PrefilterManager(Configurable):
94 """Main prefilter component.
79 """Main prefilter component.
95
80
96 The IPython prefilter is run on all user input before it is run. The
81 The IPython prefilter is run on all user input before it is run. The
97 prefilter consumes lines of input and produces transformed lines of
82 prefilter consumes lines of input and produces transformed lines of
98 input.
83 input.
99
84
100 The iplementation consists of two phases:
85 The iplementation consists of two phases:
101
86
102 1. Transformers
87 1. Transformers
103 2. Checkers and handlers
88 2. Checkers and handlers
104
89
105 Over time, we plan on deprecating the checkers and handlers and doing
90 Over time, we plan on deprecating the checkers and handlers and doing
106 everything in the transformers.
91 everything in the transformers.
107
92
108 The transformers are instances of :class:`PrefilterTransformer` and have
93 The transformers are instances of :class:`PrefilterTransformer` and have
109 a single method :meth:`transform` that takes a line and returns a
94 a single method :meth:`transform` that takes a line and returns a
110 transformed line. The transformation can be accomplished using any
95 transformed line. The transformation can be accomplished using any
111 tool, but our current ones use regular expressions for speed.
96 tool, but our current ones use regular expressions for speed.
112
97
113 After all the transformers have been run, the line is fed to the checkers,
98 After all the transformers have been run, the line is fed to the checkers,
114 which are instances of :class:`PrefilterChecker`. The line is passed to
99 which are instances of :class:`PrefilterChecker`. The line is passed to
115 the :meth:`check` method, which either returns `None` or a
100 the :meth:`check` method, which either returns `None` or a
116 :class:`PrefilterHandler` instance. If `None` is returned, the other
101 :class:`PrefilterHandler` instance. If `None` is returned, the other
117 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
102 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
118 the line is passed to the :meth:`handle` method of the returned
103 the line is passed to the :meth:`handle` method of the returned
119 handler and no further checkers are tried.
104 handler and no further checkers are tried.
120
105
121 Both transformers and checkers have a `priority` attribute, that determines
106 Both transformers and checkers have a `priority` attribute, that determines
122 the order in which they are called. Smaller priorities are tried first.
107 the order in which they are called. Smaller priorities are tried first.
123
108
124 Both transformers and checkers also have `enabled` attribute, which is
109 Both transformers and checkers also have `enabled` attribute, which is
125 a boolean that determines if the instance is used.
110 a boolean that determines if the instance is used.
126
111
127 Users or developers can change the priority or enabled attribute of
112 Users or developers can change the priority or enabled attribute of
128 transformers or checkers, but they must call the :meth:`sort_checkers`
113 transformers or checkers, but they must call the :meth:`sort_checkers`
129 or :meth:`sort_transformers` method after changing the priority.
114 or :meth:`sort_transformers` method after changing the priority.
130 """
115 """
131
116
132 multi_line_specials = CBool(True).tag(config=True)
117 multi_line_specials = Bool(True).tag(config=True)
133 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
134
119
135 def __init__(self, shell=None, **kwargs):
120 def __init__(self, shell=None, **kwargs):
136 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
121 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
137 self.shell = shell
122 self.shell = shell
138 self.init_transformers()
123 self.init_transformers()
139 self.init_handlers()
124 self.init_handlers()
140 self.init_checkers()
125 self.init_checkers()
141
126
142 #-------------------------------------------------------------------------
127 #-------------------------------------------------------------------------
143 # API for managing transformers
128 # API for managing transformers
144 #-------------------------------------------------------------------------
129 #-------------------------------------------------------------------------
145
130
146 def init_transformers(self):
131 def init_transformers(self):
147 """Create the default transformers."""
132 """Create the default transformers."""
148 self._transformers = []
133 self._transformers = []
149 for transformer_cls in _default_transformers:
134 for transformer_cls in _default_transformers:
150 transformer_cls(
135 transformer_cls(
151 shell=self.shell, prefilter_manager=self, parent=self
136 shell=self.shell, prefilter_manager=self, parent=self
152 )
137 )
153
138
154 def sort_transformers(self):
139 def sort_transformers(self):
155 """Sort the transformers by priority.
140 """Sort the transformers by priority.
156
141
157 This must be called after the priority of a transformer is changed.
142 This must be called after the priority of a transformer is changed.
158 The :meth:`register_transformer` method calls this automatically.
143 The :meth:`register_transformer` method calls this automatically.
159 """
144 """
160 self._transformers.sort(key=lambda x: x.priority)
145 self._transformers.sort(key=lambda x: x.priority)
161
146
162 @property
147 @property
163 def transformers(self):
148 def transformers(self):
164 """Return a list of checkers, sorted by priority."""
149 """Return a list of checkers, sorted by priority."""
165 return self._transformers
150 return self._transformers
166
151
167 def register_transformer(self, transformer):
152 def register_transformer(self, transformer):
168 """Register a transformer instance."""
153 """Register a transformer instance."""
169 if transformer not in self._transformers:
154 if transformer not in self._transformers:
170 self._transformers.append(transformer)
155 self._transformers.append(transformer)
171 self.sort_transformers()
156 self.sort_transformers()
172
157
173 def unregister_transformer(self, transformer):
158 def unregister_transformer(self, transformer):
174 """Unregister a transformer instance."""
159 """Unregister a transformer instance."""
175 if transformer in self._transformers:
160 if transformer in self._transformers:
176 self._transformers.remove(transformer)
161 self._transformers.remove(transformer)
177
162
178 #-------------------------------------------------------------------------
163 #-------------------------------------------------------------------------
179 # API for managing checkers
164 # API for managing checkers
180 #-------------------------------------------------------------------------
165 #-------------------------------------------------------------------------
181
166
182 def init_checkers(self):
167 def init_checkers(self):
183 """Create the default checkers."""
168 """Create the default checkers."""
184 self._checkers = []
169 self._checkers = []
185 for checker in _default_checkers:
170 for checker in _default_checkers:
186 checker(
171 checker(
187 shell=self.shell, prefilter_manager=self, parent=self
172 shell=self.shell, prefilter_manager=self, parent=self
188 )
173 )
189
174
190 def sort_checkers(self):
175 def sort_checkers(self):
191 """Sort the checkers by priority.
176 """Sort the checkers by priority.
192
177
193 This must be called after the priority of a checker is changed.
178 This must be called after the priority of a checker is changed.
194 The :meth:`register_checker` method calls this automatically.
179 The :meth:`register_checker` method calls this automatically.
195 """
180 """
196 self._checkers.sort(key=lambda x: x.priority)
181 self._checkers.sort(key=lambda x: x.priority)
197
182
198 @property
183 @property
199 def checkers(self):
184 def checkers(self):
200 """Return a list of checkers, sorted by priority."""
185 """Return a list of checkers, sorted by priority."""
201 return self._checkers
186 return self._checkers
202
187
203 def register_checker(self, checker):
188 def register_checker(self, checker):
204 """Register a checker instance."""
189 """Register a checker instance."""
205 if checker not in self._checkers:
190 if checker not in self._checkers:
206 self._checkers.append(checker)
191 self._checkers.append(checker)
207 self.sort_checkers()
192 self.sort_checkers()
208
193
209 def unregister_checker(self, checker):
194 def unregister_checker(self, checker):
210 """Unregister a checker instance."""
195 """Unregister a checker instance."""
211 if checker in self._checkers:
196 if checker in self._checkers:
212 self._checkers.remove(checker)
197 self._checkers.remove(checker)
213
198
214 #-------------------------------------------------------------------------
199 #-------------------------------------------------------------------------
215 # API for managing handlers
200 # API for managing handlers
216 #-------------------------------------------------------------------------
201 #-------------------------------------------------------------------------
217
202
218 def init_handlers(self):
203 def init_handlers(self):
219 """Create the default handlers."""
204 """Create the default handlers."""
220 self._handlers = {}
205 self._handlers = {}
221 self._esc_handlers = {}
206 self._esc_handlers = {}
222 for handler in _default_handlers:
207 for handler in _default_handlers:
223 handler(
208 handler(
224 shell=self.shell, prefilter_manager=self, parent=self
209 shell=self.shell, prefilter_manager=self, parent=self
225 )
210 )
226
211
227 @property
212 @property
228 def handlers(self):
213 def handlers(self):
229 """Return a dict of all the handlers."""
214 """Return a dict of all the handlers."""
230 return self._handlers
215 return self._handlers
231
216
232 def register_handler(self, name, handler, esc_strings):
217 def register_handler(self, name, handler, esc_strings):
233 """Register a handler instance by name with esc_strings."""
218 """Register a handler instance by name with esc_strings."""
234 self._handlers[name] = handler
219 self._handlers[name] = handler
235 for esc_str in esc_strings:
220 for esc_str in esc_strings:
236 self._esc_handlers[esc_str] = handler
221 self._esc_handlers[esc_str] = handler
237
222
238 def unregister_handler(self, name, handler, esc_strings):
223 def unregister_handler(self, name, handler, esc_strings):
239 """Unregister a handler instance by name with esc_strings."""
224 """Unregister a handler instance by name with esc_strings."""
240 try:
225 try:
241 del self._handlers[name]
226 del self._handlers[name]
242 except KeyError:
227 except KeyError:
243 pass
228 pass
244 for esc_str in esc_strings:
229 for esc_str in esc_strings:
245 h = self._esc_handlers.get(esc_str)
230 h = self._esc_handlers.get(esc_str)
246 if h is handler:
231 if h is handler:
247 del self._esc_handlers[esc_str]
232 del self._esc_handlers[esc_str]
248
233
249 def get_handler_by_name(self, name):
234 def get_handler_by_name(self, name):
250 """Get a handler by its name."""
235 """Get a handler by its name."""
251 return self._handlers.get(name)
236 return self._handlers.get(name)
252
237
253 def get_handler_by_esc(self, esc_str):
238 def get_handler_by_esc(self, esc_str):
254 """Get a handler by its escape string."""
239 """Get a handler by its escape string."""
255 return self._esc_handlers.get(esc_str)
240 return self._esc_handlers.get(esc_str)
256
241
257 #-------------------------------------------------------------------------
242 #-------------------------------------------------------------------------
258 # Main prefiltering API
243 # Main prefiltering API
259 #-------------------------------------------------------------------------
244 #-------------------------------------------------------------------------
260
245
261 def prefilter_line_info(self, line_info):
246 def prefilter_line_info(self, line_info):
262 """Prefilter a line that has been converted to a LineInfo object.
247 """Prefilter a line that has been converted to a LineInfo object.
263
248
264 This implements the checker/handler part of the prefilter pipe.
249 This implements the checker/handler part of the prefilter pipe.
265 """
250 """
266 # print "prefilter_line_info: ", line_info
251 # print "prefilter_line_info: ", line_info
267 handler = self.find_handler(line_info)
252 handler = self.find_handler(line_info)
268 return handler.handle(line_info)
253 return handler.handle(line_info)
269
254
270 def find_handler(self, line_info):
255 def find_handler(self, line_info):
271 """Find a handler for the line_info by trying checkers."""
256 """Find a handler for the line_info by trying checkers."""
272 for checker in self.checkers:
257 for checker in self.checkers:
273 if checker.enabled:
258 if checker.enabled:
274 handler = checker.check(line_info)
259 handler = checker.check(line_info)
275 if handler:
260 if handler:
276 return handler
261 return handler
277 return self.get_handler_by_name('normal')
262 return self.get_handler_by_name('normal')
278
263
279 def transform_line(self, line, continue_prompt):
264 def transform_line(self, line, continue_prompt):
280 """Calls the enabled transformers in order of increasing priority."""
265 """Calls the enabled transformers in order of increasing priority."""
281 for transformer in self.transformers:
266 for transformer in self.transformers:
282 if transformer.enabled:
267 if transformer.enabled:
283 line = transformer.transform(line, continue_prompt)
268 line = transformer.transform(line, continue_prompt)
284 return line
269 return line
285
270
286 def prefilter_line(self, line, continue_prompt=False):
271 def prefilter_line(self, line, continue_prompt=False):
287 """Prefilter a single input line as text.
272 """Prefilter a single input line as text.
288
273
289 This method prefilters a single line of text by calling the
274 This method prefilters a single line of text by calling the
290 transformers and then the checkers/handlers.
275 transformers and then the checkers/handlers.
291 """
276 """
292
277
293 # print "prefilter_line: ", line, continue_prompt
278 # print "prefilter_line: ", line, continue_prompt
294 # All handlers *must* return a value, even if it's blank ('').
279 # All handlers *must* return a value, even if it's blank ('').
295
280
296 # save the line away in case we crash, so the post-mortem handler can
281 # save the line away in case we crash, so the post-mortem handler can
297 # record it
282 # record it
298 self.shell._last_input_line = line
283 self.shell._last_input_line = line
299
284
300 if not line:
285 if not line:
301 # Return immediately on purely empty lines, so that if the user
286 # Return immediately on purely empty lines, so that if the user
302 # previously typed some whitespace that started a continuation
287 # previously typed some whitespace that started a continuation
303 # prompt, he can break out of that loop with just an empty line.
288 # prompt, he can break out of that loop with just an empty line.
304 # This is how the default python prompt works.
289 # This is how the default python prompt works.
305 return ''
290 return ''
306
291
307 # At this point, we invoke our transformers.
292 # At this point, we invoke our transformers.
308 if not continue_prompt or (continue_prompt and self.multi_line_specials):
293 if not continue_prompt or (continue_prompt and self.multi_line_specials):
309 line = self.transform_line(line, continue_prompt)
294 line = self.transform_line(line, continue_prompt)
310
295
311 # Now we compute line_info for the checkers and handlers
296 # Now we compute line_info for the checkers and handlers
312 line_info = LineInfo(line, continue_prompt)
297 line_info = LineInfo(line, continue_prompt)
313
298
314 # the input history needs to track even empty lines
299 # the input history needs to track even empty lines
315 stripped = line.strip()
300 stripped = line.strip()
316
301
317 normal_handler = self.get_handler_by_name('normal')
302 normal_handler = self.get_handler_by_name('normal')
318 if not stripped:
303 if not stripped:
319 return normal_handler.handle(line_info)
304 return normal_handler.handle(line_info)
320
305
321 # special handlers are only allowed for single line statements
306 # special handlers are only allowed for single line statements
322 if continue_prompt and not self.multi_line_specials:
307 if continue_prompt and not self.multi_line_specials:
323 return normal_handler.handle(line_info)
308 return normal_handler.handle(line_info)
324
309
325 prefiltered = self.prefilter_line_info(line_info)
310 prefiltered = self.prefilter_line_info(line_info)
326 # print "prefiltered line: %r" % prefiltered
311 # print "prefiltered line: %r" % prefiltered
327 return prefiltered
312 return prefiltered
328
313
329 def prefilter_lines(self, lines, continue_prompt=False):
314 def prefilter_lines(self, lines, continue_prompt=False):
330 """Prefilter multiple input lines of text.
315 """Prefilter multiple input lines of text.
331
316
332 This is the main entry point for prefiltering multiple lines of
317 This is the main entry point for prefiltering multiple lines of
333 input. This simply calls :meth:`prefilter_line` for each line of
318 input. This simply calls :meth:`prefilter_line` for each line of
334 input.
319 input.
335
320
336 This covers cases where there are multiple lines in the user entry,
321 This covers cases where there are multiple lines in the user entry,
337 which is the case when the user goes back to a multiline history
322 which is the case when the user goes back to a multiline history
338 entry and presses enter.
323 entry and presses enter.
339 """
324 """
340 llines = lines.rstrip('\n').split('\n')
325 llines = lines.rstrip('\n').split('\n')
341 # We can get multiple lines in one shot, where multiline input 'blends'
326 # We can get multiple lines in one shot, where multiline input 'blends'
342 # into one line, in cases like recalling from the readline history
327 # into one line, in cases like recalling from the readline history
343 # buffer. We need to make sure that in such cases, we correctly
328 # buffer. We need to make sure that in such cases, we correctly
344 # communicate downstream which line is first and which are continuation
329 # communicate downstream which line is first and which are continuation
345 # ones.
330 # ones.
346 if len(llines) > 1:
331 if len(llines) > 1:
347 out = '\n'.join([self.prefilter_line(line, lnum>0)
332 out = '\n'.join([self.prefilter_line(line, lnum>0)
348 for lnum, line in enumerate(llines) ])
333 for lnum, line in enumerate(llines) ])
349 else:
334 else:
350 out = self.prefilter_line(llines[0], continue_prompt)
335 out = self.prefilter_line(llines[0], continue_prompt)
351
336
352 return out
337 return out
353
338
354 #-----------------------------------------------------------------------------
339 #-----------------------------------------------------------------------------
355 # Prefilter transformers
340 # Prefilter transformers
356 #-----------------------------------------------------------------------------
341 #-----------------------------------------------------------------------------
357
342
358
343
359 class PrefilterTransformer(Configurable):
344 class PrefilterTransformer(Configurable):
360 """Transform a line of user input."""
345 """Transform a line of user input."""
361
346
362 priority = Integer(100).tag(config=True)
347 priority = Integer(100).tag(config=True)
363 # Transformers don't currently use shell or prefilter_manager, but as we
348 # Transformers don't currently use shell or prefilter_manager, but as we
364 # move away from checkers and handlers, they will need them.
349 # move away from checkers and handlers, they will need them.
365 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
366 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
351 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
367 enabled = Bool(True).tag(config=True)
352 enabled = Bool(True).tag(config=True)
368
353
369 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
354 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
370 super(PrefilterTransformer, self).__init__(
355 super(PrefilterTransformer, self).__init__(
371 shell=shell, prefilter_manager=prefilter_manager, **kwargs
356 shell=shell, prefilter_manager=prefilter_manager, **kwargs
372 )
357 )
373 self.prefilter_manager.register_transformer(self)
358 self.prefilter_manager.register_transformer(self)
374
359
375 def transform(self, line, continue_prompt):
360 def transform(self, line, continue_prompt):
376 """Transform a line, returning the new one."""
361 """Transform a line, returning the new one."""
377 return None
362 return None
378
363
379 def __repr__(self):
364 def __repr__(self):
380 return "<%s(priority=%r, enabled=%r)>" % (
365 return "<%s(priority=%r, enabled=%r)>" % (
381 self.__class__.__name__, self.priority, self.enabled)
366 self.__class__.__name__, self.priority, self.enabled)
382
367
383
368
384 #-----------------------------------------------------------------------------
369 #-----------------------------------------------------------------------------
385 # Prefilter checkers
370 # Prefilter checkers
386 #-----------------------------------------------------------------------------
371 #-----------------------------------------------------------------------------
387
372
388
373
389 class PrefilterChecker(Configurable):
374 class PrefilterChecker(Configurable):
390 """Inspect an input line and return a handler for that line."""
375 """Inspect an input line and return a handler for that line."""
391
376
392 priority = Integer(100).tag(config=True)
377 priority = Integer(100).tag(config=True)
393 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
378 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
394 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
379 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
395 enabled = Bool(True).tag(config=True)
380 enabled = Bool(True).tag(config=True)
396
381
397 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
382 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
398 super(PrefilterChecker, self).__init__(
383 super(PrefilterChecker, self).__init__(
399 shell=shell, prefilter_manager=prefilter_manager, **kwargs
384 shell=shell, prefilter_manager=prefilter_manager, **kwargs
400 )
385 )
401 self.prefilter_manager.register_checker(self)
386 self.prefilter_manager.register_checker(self)
402
387
403 def check(self, line_info):
388 def check(self, line_info):
404 """Inspect line_info and return a handler instance or None."""
389 """Inspect line_info and return a handler instance or None."""
405 return None
390 return None
406
391
407 def __repr__(self):
392 def __repr__(self):
408 return "<%s(priority=%r, enabled=%r)>" % (
393 return "<%s(priority=%r, enabled=%r)>" % (
409 self.__class__.__name__, self.priority, self.enabled)
394 self.__class__.__name__, self.priority, self.enabled)
410
395
411
396
412 class EmacsChecker(PrefilterChecker):
397 class EmacsChecker(PrefilterChecker):
413
398
414 priority = Integer(100).tag(config=True)
399 priority = Integer(100).tag(config=True)
415 enabled = Bool(False).tag(config=True)
400 enabled = Bool(False).tag(config=True)
416
401
417 def check(self, line_info):
402 def check(self, line_info):
418 "Emacs ipython-mode tags certain input lines."
403 "Emacs ipython-mode tags certain input lines."
419 if line_info.line.endswith('# PYTHON-MODE'):
404 if line_info.line.endswith('# PYTHON-MODE'):
420 return self.prefilter_manager.get_handler_by_name('emacs')
405 return self.prefilter_manager.get_handler_by_name('emacs')
421 else:
406 else:
422 return None
407 return None
423
408
424
409
425 class MacroChecker(PrefilterChecker):
410 class MacroChecker(PrefilterChecker):
426
411
427 priority = Integer(250).tag(config=True)
412 priority = Integer(250).tag(config=True)
428
413
429 def check(self, line_info):
414 def check(self, line_info):
430 obj = self.shell.user_ns.get(line_info.ifun)
415 obj = self.shell.user_ns.get(line_info.ifun)
431 if isinstance(obj, Macro):
416 if isinstance(obj, Macro):
432 return self.prefilter_manager.get_handler_by_name('macro')
417 return self.prefilter_manager.get_handler_by_name('macro')
433 else:
418 else:
434 return None
419 return None
435
420
436
421
437 class IPyAutocallChecker(PrefilterChecker):
422 class IPyAutocallChecker(PrefilterChecker):
438
423
439 priority = Integer(300).tag(config=True)
424 priority = Integer(300).tag(config=True)
440
425
441 def check(self, line_info):
426 def check(self, line_info):
442 "Instances of IPyAutocall in user_ns get autocalled immediately"
427 "Instances of IPyAutocall in user_ns get autocalled immediately"
443 obj = self.shell.user_ns.get(line_info.ifun, None)
428 obj = self.shell.user_ns.get(line_info.ifun, None)
444 if isinstance(obj, IPyAutocall):
429 if isinstance(obj, IPyAutocall):
445 obj.set_ip(self.shell)
430 obj.set_ip(self.shell)
446 return self.prefilter_manager.get_handler_by_name('auto')
431 return self.prefilter_manager.get_handler_by_name('auto')
447 else:
432 else:
448 return None
433 return None
449
434
450
435
451 class AssignmentChecker(PrefilterChecker):
436 class AssignmentChecker(PrefilterChecker):
452
437
453 priority = Integer(600).tag(config=True)
438 priority = Integer(600).tag(config=True)
454
439
455 def check(self, line_info):
440 def check(self, line_info):
456 """Check to see if user is assigning to a var for the first time, in
441 """Check to see if user is assigning to a var for the first time, in
457 which case we want to avoid any sort of automagic / autocall games.
442 which case we want to avoid any sort of automagic / autocall games.
458
443
459 This allows users to assign to either alias or magic names true python
444 This allows users to assign to either alias or magic names true python
460 variables (the magic/alias systems always take second seat to true
445 variables (the magic/alias systems always take second seat to true
461 python code). E.g. ls='hi', or ls,that=1,2"""
446 python code). E.g. ls='hi', or ls,that=1,2"""
462 if line_info.the_rest:
447 if line_info.the_rest:
463 if line_info.the_rest[0] in '=,':
448 if line_info.the_rest[0] in '=,':
464 return self.prefilter_manager.get_handler_by_name('normal')
449 return self.prefilter_manager.get_handler_by_name('normal')
465 else:
450 else:
466 return None
451 return None
467
452
468
453
469 class AutoMagicChecker(PrefilterChecker):
454 class AutoMagicChecker(PrefilterChecker):
470
455
471 priority = Integer(700).tag(config=True)
456 priority = Integer(700).tag(config=True)
472
457
473 def check(self, line_info):
458 def check(self, line_info):
474 """If the ifun is magic, and automagic is on, run it. Note: normal,
459 """If the ifun is magic, and automagic is on, run it. Note: normal,
475 non-auto magic would already have been triggered via '%' in
460 non-auto magic would already have been triggered via '%' in
476 check_esc_chars. This just checks for automagic. Also, before
461 check_esc_chars. This just checks for automagic. Also, before
477 triggering the magic handler, make sure that there is nothing in the
462 triggering the magic handler, make sure that there is nothing in the
478 user namespace which could shadow it."""
463 user namespace which could shadow it."""
479 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
464 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
480 return None
465 return None
481
466
482 # We have a likely magic method. Make sure we should actually call it.
467 # We have a likely magic method. Make sure we should actually call it.
483 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
468 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
484 return None
469 return None
485
470
486 head = line_info.ifun.split('.',1)[0]
471 head = line_info.ifun.split('.',1)[0]
487 if is_shadowed(head, self.shell):
472 if is_shadowed(head, self.shell):
488 return None
473 return None
489
474
490 return self.prefilter_manager.get_handler_by_name('magic')
475 return self.prefilter_manager.get_handler_by_name('magic')
491
476
492
477
493 class PythonOpsChecker(PrefilterChecker):
478 class PythonOpsChecker(PrefilterChecker):
494
479
495 priority = Integer(900).tag(config=True)
480 priority = Integer(900).tag(config=True)
496
481
497 def check(self, line_info):
482 def check(self, line_info):
498 """If the 'rest' of the line begins with a function call or pretty much
483 """If the 'rest' of the line begins with a function call or pretty much
499 any python operator, we should simply execute the line (regardless of
484 any python operator, we should simply execute the line (regardless of
500 whether or not there's a possible autocall expansion). This avoids
485 whether or not there's a possible autocall expansion). This avoids
501 spurious (and very confusing) geattr() accesses."""
486 spurious (and very confusing) geattr() accesses."""
502 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
487 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
503 return self.prefilter_manager.get_handler_by_name('normal')
488 return self.prefilter_manager.get_handler_by_name('normal')
504 else:
489 else:
505 return None
490 return None
506
491
507
492
508 class AutocallChecker(PrefilterChecker):
493 class AutocallChecker(PrefilterChecker):
509
494
510 priority = Integer(1000).tag(config=True)
495 priority = Integer(1000).tag(config=True)
511
496
512 function_name_regexp = CRegExp(re_fun_name,
497 function_name_regexp = CRegExp(re_fun_name,
513 help="RegExp to identify potential function names."
498 help="RegExp to identify potential function names."
514 ).tag(config=True)
499 ).tag(config=True)
515 exclude_regexp = CRegExp(re_exclude_auto,
500 exclude_regexp = CRegExp(re_exclude_auto,
516 help="RegExp to exclude strings with this start from autocalling."
501 help="RegExp to exclude strings with this start from autocalling."
517 ).tag(config=True)
502 ).tag(config=True)
518
503
519 def check(self, line_info):
504 def check(self, line_info):
520 "Check if the initial word/function is callable and autocall is on."
505 "Check if the initial word/function is callable and autocall is on."
521 if not self.shell.autocall:
506 if not self.shell.autocall:
522 return None
507 return None
523
508
524 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
509 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
525 if not oinfo['found']:
510 if not oinfo['found']:
526 return None
511 return None
527
512
528 if callable(oinfo['obj']) \
513 if callable(oinfo['obj']) \
529 and (not self.exclude_regexp.match(line_info.the_rest)) \
514 and (not self.exclude_regexp.match(line_info.the_rest)) \
530 and self.function_name_regexp.match(line_info.ifun):
515 and self.function_name_regexp.match(line_info.ifun):
531 return self.prefilter_manager.get_handler_by_name('auto')
516 return self.prefilter_manager.get_handler_by_name('auto')
532 else:
517 else:
533 return None
518 return None
534
519
535
520
536 #-----------------------------------------------------------------------------
521 #-----------------------------------------------------------------------------
537 # Prefilter handlers
522 # Prefilter handlers
538 #-----------------------------------------------------------------------------
523 #-----------------------------------------------------------------------------
539
524
540
525
541 class PrefilterHandler(Configurable):
526 class PrefilterHandler(Configurable):
542
527
543 handler_name = Unicode('normal')
528 handler_name = Unicode('normal')
544 esc_strings = List([])
529 esc_strings = List([])
545 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
530 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
546 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
531 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
547
532
548 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
533 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
549 super(PrefilterHandler, self).__init__(
534 super(PrefilterHandler, self).__init__(
550 shell=shell, prefilter_manager=prefilter_manager, **kwargs
535 shell=shell, prefilter_manager=prefilter_manager, **kwargs
551 )
536 )
552 self.prefilter_manager.register_handler(
537 self.prefilter_manager.register_handler(
553 self.handler_name,
538 self.handler_name,
554 self,
539 self,
555 self.esc_strings
540 self.esc_strings
556 )
541 )
557
542
558 def handle(self, line_info):
543 def handle(self, line_info):
559 # print "normal: ", line_info
544 # print "normal: ", line_info
560 """Handle normal input lines. Use as a template for handlers."""
545 """Handle normal input lines. Use as a template for handlers."""
561
546
562 # With autoindent on, we need some way to exit the input loop, and I
547 # With autoindent on, we need some way to exit the input loop, and I
563 # don't want to force the user to have to backspace all the way to
548 # don't want to force the user to have to backspace all the way to
564 # clear the line. The rule will be in this case, that either two
549 # clear the line. The rule will be in this case, that either two
565 # lines of pure whitespace in a row, or a line of pure whitespace but
550 # lines of pure whitespace in a row, or a line of pure whitespace but
566 # of a size different to the indent level, will exit the input loop.
551 # of a size different to the indent level, will exit the input loop.
567 line = line_info.line
552 line = line_info.line
568 continue_prompt = line_info.continue_prompt
553 continue_prompt = line_info.continue_prompt
569
554
570 if (continue_prompt and
555 if (continue_prompt and
571 self.shell.autoindent and
556 self.shell.autoindent and
572 line.isspace() and
557 line.isspace() and
573 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
558 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
574 line = ''
559 line = ''
575
560
576 return line
561 return line
577
562
578 def __str__(self):
563 def __str__(self):
579 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
564 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
580
565
581
566
582 class MacroHandler(PrefilterHandler):
567 class MacroHandler(PrefilterHandler):
583 handler_name = Unicode("macro")
568 handler_name = Unicode("macro")
584
569
585 def handle(self, line_info):
570 def handle(self, line_info):
586 obj = self.shell.user_ns.get(line_info.ifun)
571 obj = self.shell.user_ns.get(line_info.ifun)
587 pre_space = line_info.pre_whitespace
572 pre_space = line_info.pre_whitespace
588 line_sep = "\n" + pre_space
573 line_sep = "\n" + pre_space
589 return pre_space + line_sep.join(obj.value.splitlines())
574 return pre_space + line_sep.join(obj.value.splitlines())
590
575
591
576
592 class MagicHandler(PrefilterHandler):
577 class MagicHandler(PrefilterHandler):
593
578
594 handler_name = Unicode('magic')
579 handler_name = Unicode('magic')
595 esc_strings = List([ESC_MAGIC])
580 esc_strings = List([ESC_MAGIC])
596
581
597 def handle(self, line_info):
582 def handle(self, line_info):
598 """Execute magic functions."""
583 """Execute magic functions."""
599 ifun = line_info.ifun
584 ifun = line_info.ifun
600 the_rest = line_info.the_rest
585 the_rest = line_info.the_rest
601 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
586 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
602 (ifun + " " + the_rest))
587 (ifun + " " + the_rest))
603 return cmd
588 return cmd
604
589
605
590
606 class AutoHandler(PrefilterHandler):
591 class AutoHandler(PrefilterHandler):
607
592
608 handler_name = Unicode('auto')
593 handler_name = Unicode('auto')
609 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
594 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
610
595
611 def handle(self, line_info):
596 def handle(self, line_info):
612 """Handle lines which can be auto-executed, quoting if requested."""
597 """Handle lines which can be auto-executed, quoting if requested."""
613 line = line_info.line
598 line = line_info.line
614 ifun = line_info.ifun
599 ifun = line_info.ifun
615 the_rest = line_info.the_rest
600 the_rest = line_info.the_rest
616 esc = line_info.esc
601 esc = line_info.esc
617 continue_prompt = line_info.continue_prompt
602 continue_prompt = line_info.continue_prompt
618 obj = line_info.ofind(self.shell)['obj']
603 obj = line_info.ofind(self.shell)['obj']
619
604
620 # This should only be active for single-line input!
605 # This should only be active for single-line input!
621 if continue_prompt:
606 if continue_prompt:
622 return line
607 return line
623
608
624 force_auto = isinstance(obj, IPyAutocall)
609 force_auto = isinstance(obj, IPyAutocall)
625
610
626 # User objects sometimes raise exceptions on attribute access other
611 # User objects sometimes raise exceptions on attribute access other
627 # than AttributeError (we've seen it in the past), so it's safest to be
612 # than AttributeError (we've seen it in the past), so it's safest to be
628 # ultra-conservative here and catch all.
613 # ultra-conservative here and catch all.
629 try:
614 try:
630 auto_rewrite = obj.rewrite
615 auto_rewrite = obj.rewrite
631 except Exception:
616 except Exception:
632 auto_rewrite = True
617 auto_rewrite = True
633
618
634 if esc == ESC_QUOTE:
619 if esc == ESC_QUOTE:
635 # Auto-quote splitting on whitespace
620 # Auto-quote splitting on whitespace
636 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
621 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
637 elif esc == ESC_QUOTE2:
622 elif esc == ESC_QUOTE2:
638 # Auto-quote whole string
623 # Auto-quote whole string
639 newcmd = '%s("%s")' % (ifun,the_rest)
624 newcmd = '%s("%s")' % (ifun,the_rest)
640 elif esc == ESC_PAREN:
625 elif esc == ESC_PAREN:
641 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
626 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
642 else:
627 else:
643 # Auto-paren.
628 # Auto-paren.
644 if force_auto:
629 if force_auto:
645 # Don't rewrite if it is already a call.
630 # Don't rewrite if it is already a call.
646 do_rewrite = not the_rest.startswith('(')
631 do_rewrite = not the_rest.startswith('(')
647 else:
632 else:
648 if not the_rest:
633 if not the_rest:
649 # We only apply it to argument-less calls if the autocall
634 # We only apply it to argument-less calls if the autocall
650 # parameter is set to 2.
635 # parameter is set to 2.
651 do_rewrite = (self.shell.autocall >= 2)
636 do_rewrite = (self.shell.autocall >= 2)
652 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
637 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
653 # Don't autocall in this case: item access for an object
638 # Don't autocall in this case: item access for an object
654 # which is BOTH callable and implements __getitem__.
639 # which is BOTH callable and implements __getitem__.
655 do_rewrite = False
640 do_rewrite = False
656 else:
641 else:
657 do_rewrite = True
642 do_rewrite = True
658
643
659 # Figure out the rewritten command
644 # Figure out the rewritten command
660 if do_rewrite:
645 if do_rewrite:
661 if the_rest.endswith(';'):
646 if the_rest.endswith(';'):
662 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
647 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
663 else:
648 else:
664 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
649 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
665 else:
650 else:
666 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
651 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
667 return normal_handler.handle(line_info)
652 return normal_handler.handle(line_info)
668
653
669 # Display the rewritten call
654 # Display the rewritten call
670 if auto_rewrite:
655 if auto_rewrite:
671 self.shell.auto_rewrite_input(newcmd)
656 self.shell.auto_rewrite_input(newcmd)
672
657
673 return newcmd
658 return newcmd
674
659
675
660
676 class EmacsHandler(PrefilterHandler):
661 class EmacsHandler(PrefilterHandler):
677
662
678 handler_name = Unicode('emacs')
663 handler_name = Unicode('emacs')
679 esc_strings = List([])
664 esc_strings = List([])
680
665
681 def handle(self, line_info):
666 def handle(self, line_info):
682 """Handle input lines marked by python-mode."""
667 """Handle input lines marked by python-mode."""
683
668
684 # Currently, nothing is done. Later more functionality can be added
669 # Currently, nothing is done. Later more functionality can be added
685 # here if needed.
670 # here if needed.
686
671
687 # The input cache shouldn't be updated
672 # The input cache shouldn't be updated
688 return line_info.line
673 return line_info.line
689
674
690
675
691 #-----------------------------------------------------------------------------
676 #-----------------------------------------------------------------------------
692 # Defaults
677 # Defaults
693 #-----------------------------------------------------------------------------
678 #-----------------------------------------------------------------------------
694
679
695
680
696 _default_transformers = [
681 _default_transformers = [
697 ]
682 ]
698
683
699 _default_checkers = [
684 _default_checkers = [
700 EmacsChecker,
685 EmacsChecker,
701 MacroChecker,
686 MacroChecker,
702 IPyAutocallChecker,
687 IPyAutocallChecker,
703 AssignmentChecker,
688 AssignmentChecker,
704 AutoMagicChecker,
689 AutoMagicChecker,
705 PythonOpsChecker,
690 PythonOpsChecker,
706 AutocallChecker
691 AutocallChecker
707 ]
692 ]
708
693
709 _default_handlers = [
694 _default_handlers = [
710 PrefilterHandler,
695 PrefilterHandler,
711 MacroHandler,
696 MacroHandler,
712 MagicHandler,
697 MagicHandler,
713 AutoHandler,
698 AutoHandler,
714 EmacsHandler
699 EmacsHandler
715 ]
700 ]
@@ -1,234 +1,224 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """An object for managing IPython profile directories."""
2 """An object for managing IPython profile directories."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import shutil
8 import shutil
9 import errno
9 import errno
10
10
11 from traitlets.config.configurable import LoggingConfigurable
11 from traitlets.config.configurable import LoggingConfigurable
12 from IPython.paths import get_ipython_package_dir
12 from IPython.paths import get_ipython_package_dir
13 from IPython.utils.path import expand_path, ensure_dir_exists
13 from IPython.utils.path import expand_path, ensure_dir_exists
14 from IPython.utils import py3compat
14 from IPython.utils import py3compat
15 from traitlets import Unicode, Bool
15 from traitlets import Unicode, Bool, observe
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Module errors
18 # Module errors
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 class ProfileDirError(Exception):
21 class ProfileDirError(Exception):
22 pass
22 pass
23
23
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Class for managing profile directories
26 # Class for managing profile directories
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 class ProfileDir(LoggingConfigurable):
29 class ProfileDir(LoggingConfigurable):
30 """An object to manage the profile directory and its resources.
30 """An object to manage the profile directory and its resources.
31
31
32 The profile directory is used by all IPython applications, to manage
32 The profile directory is used by all IPython applications, to manage
33 configuration, logging and security.
33 configuration, logging and security.
34
34
35 This object knows how to find, create and manage these directories. This
35 This object knows how to find, create and manage these directories. This
36 should be used by any code that wants to handle profiles.
36 should be used by any code that wants to handle profiles.
37 """
37 """
38
38
39 security_dir_name = Unicode('security')
39 security_dir_name = Unicode('security')
40 log_dir_name = Unicode('log')
40 log_dir_name = Unicode('log')
41 startup_dir_name = Unicode('startup')
41 startup_dir_name = Unicode('startup')
42 pid_dir_name = Unicode('pid')
42 pid_dir_name = Unicode('pid')
43 static_dir_name = Unicode('static')
43 static_dir_name = Unicode('static')
44 security_dir = Unicode(u'')
44 security_dir = Unicode(u'')
45 log_dir = Unicode(u'')
45 log_dir = Unicode(u'')
46 startup_dir = Unicode(u'')
46 startup_dir = Unicode(u'')
47 pid_dir = Unicode(u'')
47 pid_dir = Unicode(u'')
48 static_dir = Unicode(u'')
48 static_dir = Unicode(u'')
49
49
50 location = Unicode(u'', config=True,
50 location = Unicode(u'',
51 help="""Set the profile location directly. This overrides the logic used by the
51 help="""Set the profile location directly. This overrides the logic used by the
52 `profile` option.""",
52 `profile` option.""",
53 )
53 ).tag(config=True)
54
54
55 _location_isset = Bool(False) # flag for detecting multiply set location
55 _location_isset = Bool(False) # flag for detecting multiply set location
56
56 @observe('location')
57 def _location_changed(self, name, old, new):
57 def _location_changed(self, change):
58 if self._location_isset:
58 if self._location_isset:
59 raise RuntimeError("Cannot set profile location more than once.")
59 raise RuntimeError("Cannot set profile location more than once.")
60 self._location_isset = True
60 self._location_isset = True
61 new = change['new']
61 ensure_dir_exists(new)
62 ensure_dir_exists(new)
62
63
63 # ensure config files exist:
64 # ensure config files exist:
64 self.security_dir = os.path.join(new, self.security_dir_name)
65 self.security_dir = os.path.join(new, self.security_dir_name)
65 self.log_dir = os.path.join(new, self.log_dir_name)
66 self.log_dir = os.path.join(new, self.log_dir_name)
66 self.startup_dir = os.path.join(new, self.startup_dir_name)
67 self.startup_dir = os.path.join(new, self.startup_dir_name)
67 self.pid_dir = os.path.join(new, self.pid_dir_name)
68 self.pid_dir = os.path.join(new, self.pid_dir_name)
68 self.static_dir = os.path.join(new, self.static_dir_name)
69 self.static_dir = os.path.join(new, self.static_dir_name)
69 self.check_dirs()
70 self.check_dirs()
70
71
71 def _log_dir_changed(self, name, old, new):
72 self.check_log_dir()
73
74 def _mkdir(self, path, mode=None):
72 def _mkdir(self, path, mode=None):
75 """ensure a directory exists at a given path
73 """ensure a directory exists at a given path
76
74
77 This is a version of os.mkdir, with the following differences:
75 This is a version of os.mkdir, with the following differences:
78
76
79 - returns True if it created the directory, False otherwise
77 - returns True if it created the directory, False otherwise
80 - ignores EEXIST, protecting against race conditions where
78 - ignores EEXIST, protecting against race conditions where
81 the dir may have been created in between the check and
79 the dir may have been created in between the check and
82 the creation
80 the creation
83 - sets permissions if requested and the dir already exists
81 - sets permissions if requested and the dir already exists
84 """
82 """
85 if os.path.exists(path):
83 if os.path.exists(path):
86 if mode and os.stat(path).st_mode != mode:
84 if mode and os.stat(path).st_mode != mode:
87 try:
85 try:
88 os.chmod(path, mode)
86 os.chmod(path, mode)
89 except OSError:
87 except OSError:
90 self.log.warning(
88 self.log.warning(
91 "Could not set permissions on %s",
89 "Could not set permissions on %s",
92 path
90 path
93 )
91 )
94 return False
92 return False
95 try:
93 try:
96 if mode:
94 if mode:
97 os.mkdir(path, mode)
95 os.mkdir(path, mode)
98 else:
96 else:
99 os.mkdir(path)
97 os.mkdir(path)
100 except OSError as e:
98 except OSError as e:
101 if e.errno == errno.EEXIST:
99 if e.errno == errno.EEXIST:
102 return False
100 return False
103 else:
101 else:
104 raise
102 raise
105
103
106 return True
104 return True
107
105
108 def check_log_dir(self):
106 @observe('log_dir')
107 def check_log_dir(self, change=None):
109 self._mkdir(self.log_dir)
108 self._mkdir(self.log_dir)
110
109
111 def _startup_dir_changed(self, name, old, new):
110 @observe('startup_dir')
112 self.check_startup_dir()
111 def check_startup_dir(self, change=None):
113
114 def check_startup_dir(self):
115 self._mkdir(self.startup_dir)
112 self._mkdir(self.startup_dir)
116
113
117 readme = os.path.join(self.startup_dir, 'README')
114 readme = os.path.join(self.startup_dir, 'README')
118 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
115 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
119
116
120 if not os.path.exists(src):
117 if not os.path.exists(src):
121 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
118 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
122
119
123 if os.path.exists(src) and not os.path.exists(readme):
120 if os.path.exists(src) and not os.path.exists(readme):
124 shutil.copy(src, readme)
121 shutil.copy(src, readme)
125
122
126 def _security_dir_changed(self, name, old, new):
123 @observe('security_dir')
127 self.check_security_dir()
124 def check_security_dir(self, change=None):
128
129 def check_security_dir(self):
130 self._mkdir(self.security_dir, 0o40700)
125 self._mkdir(self.security_dir, 0o40700)
131
126
132 def _pid_dir_changed(self, name, old, new):
127 @observe('pid_dir')
133 self.check_pid_dir()
128 def check_pid_dir(self, change=None):
134
135 def check_pid_dir(self):
136 self._mkdir(self.pid_dir, 0o40700)
129 self._mkdir(self.pid_dir, 0o40700)
137
130
138 def _static_dir_changed(self, name, old, new):
139 self.check_startup_dir()
140
141 def check_dirs(self):
131 def check_dirs(self):
142 self.check_security_dir()
132 self.check_security_dir()
143 self.check_log_dir()
133 self.check_log_dir()
144 self.check_pid_dir()
134 self.check_pid_dir()
145 self.check_startup_dir()
135 self.check_startup_dir()
146
136
147 def copy_config_file(self, config_file, path=None, overwrite=False):
137 def copy_config_file(self, config_file, path=None, overwrite=False):
148 """Copy a default config file into the active profile directory.
138 """Copy a default config file into the active profile directory.
149
139
150 Default configuration files are kept in :mod:`IPython.core.profile`.
140 Default configuration files are kept in :mod:`IPython.core.profile`.
151 This function moves these from that location to the working profile
141 This function moves these from that location to the working profile
152 directory.
142 directory.
153 """
143 """
154 dst = os.path.join(self.location, config_file)
144 dst = os.path.join(self.location, config_file)
155 if os.path.isfile(dst) and not overwrite:
145 if os.path.isfile(dst) and not overwrite:
156 return False
146 return False
157 if path is None:
147 if path is None:
158 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
148 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
159 src = os.path.join(path, config_file)
149 src = os.path.join(path, config_file)
160 shutil.copy(src, dst)
150 shutil.copy(src, dst)
161 return True
151 return True
162
152
163 @classmethod
153 @classmethod
164 def create_profile_dir(cls, profile_dir, config=None):
154 def create_profile_dir(cls, profile_dir, config=None):
165 """Create a new profile directory given a full path.
155 """Create a new profile directory given a full path.
166
156
167 Parameters
157 Parameters
168 ----------
158 ----------
169 profile_dir : str
159 profile_dir : str
170 The full path to the profile directory. If it does exist, it will
160 The full path to the profile directory. If it does exist, it will
171 be used. If not, it will be created.
161 be used. If not, it will be created.
172 """
162 """
173 return cls(location=profile_dir, config=config)
163 return cls(location=profile_dir, config=config)
174
164
175 @classmethod
165 @classmethod
176 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
166 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
177 """Create a profile dir by profile name and path.
167 """Create a profile dir by profile name and path.
178
168
179 Parameters
169 Parameters
180 ----------
170 ----------
181 path : unicode
171 path : unicode
182 The path (directory) to put the profile directory in.
172 The path (directory) to put the profile directory in.
183 name : unicode
173 name : unicode
184 The name of the profile. The name of the profile directory will
174 The name of the profile. The name of the profile directory will
185 be "profile_<profile>".
175 be "profile_<profile>".
186 """
176 """
187 if not os.path.isdir(path):
177 if not os.path.isdir(path):
188 raise ProfileDirError('Directory not found: %s' % path)
178 raise ProfileDirError('Directory not found: %s' % path)
189 profile_dir = os.path.join(path, u'profile_' + name)
179 profile_dir = os.path.join(path, u'profile_' + name)
190 return cls(location=profile_dir, config=config)
180 return cls(location=profile_dir, config=config)
191
181
192 @classmethod
182 @classmethod
193 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
183 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
194 """Find an existing profile dir by profile name, return its ProfileDir.
184 """Find an existing profile dir by profile name, return its ProfileDir.
195
185
196 This searches through a sequence of paths for a profile dir. If it
186 This searches through a sequence of paths for a profile dir. If it
197 is not found, a :class:`ProfileDirError` exception will be raised.
187 is not found, a :class:`ProfileDirError` exception will be raised.
198
188
199 The search path algorithm is:
189 The search path algorithm is:
200 1. ``py3compat.getcwd()``
190 1. ``py3compat.getcwd()``
201 2. ``ipython_dir``
191 2. ``ipython_dir``
202
192
203 Parameters
193 Parameters
204 ----------
194 ----------
205 ipython_dir : unicode or str
195 ipython_dir : unicode or str
206 The IPython directory to use.
196 The IPython directory to use.
207 name : unicode or str
197 name : unicode or str
208 The name of the profile. The name of the profile directory
198 The name of the profile. The name of the profile directory
209 will be "profile_<profile>".
199 will be "profile_<profile>".
210 """
200 """
211 dirname = u'profile_' + name
201 dirname = u'profile_' + name
212 paths = [py3compat.getcwd(), ipython_dir]
202 paths = [py3compat.getcwd(), ipython_dir]
213 for p in paths:
203 for p in paths:
214 profile_dir = os.path.join(p, dirname)
204 profile_dir = os.path.join(p, dirname)
215 if os.path.isdir(profile_dir):
205 if os.path.isdir(profile_dir):
216 return cls(location=profile_dir, config=config)
206 return cls(location=profile_dir, config=config)
217 else:
207 else:
218 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
208 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
219
209
220 @classmethod
210 @classmethod
221 def find_profile_dir(cls, profile_dir, config=None):
211 def find_profile_dir(cls, profile_dir, config=None):
222 """Find/create a profile dir and return its ProfileDir.
212 """Find/create a profile dir and return its ProfileDir.
223
213
224 This will create the profile directory if it doesn't exist.
214 This will create the profile directory if it doesn't exist.
225
215
226 Parameters
216 Parameters
227 ----------
217 ----------
228 profile_dir : unicode or str
218 profile_dir : unicode or str
229 The path of the profile directory.
219 The path of the profile directory.
230 """
220 """
231 profile_dir = expand_path(profile_dir)
221 profile_dir = expand_path(profile_dir)
232 if not os.path.isdir(profile_dir):
222 if not os.path.isdir(profile_dir):
233 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
223 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
234 return cls(location=profile_dir, config=config)
224 return cls(location=profile_dir, config=config)
@@ -1,420 +1,409 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Classes for handling input/output prompts.
2 """Classes for handling input/output prompts."""
3
3
4 Authors:
4 # Copyright (c) 2001-2007 Fernando Perez <fperez@colorado.edu>
5
5 # Copyright (c) IPython Development Team.
6 * Fernando Perez
6 # Distributed under the terms of the Modified BSD License.
7 * Brian Granger
8 * Thomas Kluyver
9 """
10
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
7
23 import os
8 import os
24 import re
9 import re
25 import socket
10 import socket
26 import sys
11 import sys
27 import time
12 import time
28
13
29 from string import Formatter
14 from string import Formatter
30
15
31 from traitlets.config.configurable import Configurable
16 from traitlets.config.configurable import Configurable
32 from IPython.core import release
17 from IPython.core import release
33 from IPython.utils import coloransi, py3compat
18 from IPython.utils import coloransi, py3compat
34 from traitlets import Unicode, Instance, Dict, Bool, Int, observe
19 from traitlets import Unicode, Instance, Dict, Bool, Int, observe, default
35
20
36 from IPython.utils.PyColorize import LightBGColors, LinuxColors, NoColor
21 from IPython.utils.PyColorize import LightBGColors, LinuxColors, NoColor
37
22
38 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
39 # Color schemes for prompts
24 # Color schemes for prompts
40 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
41
26
42 InputColors = coloransi.InputTermColors # just a shorthand
27 InputColors = coloransi.InputTermColors # just a shorthand
43 Colors = coloransi.TermColors # just a shorthand
28 Colors = coloransi.TermColors # just a shorthand
44
29
45 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
30 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
46
31
47 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
48 # Utilities
33 # Utilities
49 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
50
35
51 class LazyEvaluate(object):
36 class LazyEvaluate(object):
52 """This is used for formatting strings with values that need to be updated
37 """This is used for formatting strings with values that need to be updated
53 at that time, such as the current time or working directory."""
38 at that time, such as the current time or working directory."""
54 def __init__(self, func, *args, **kwargs):
39 def __init__(self, func, *args, **kwargs):
55 self.func = func
40 self.func = func
56 self.args = args
41 self.args = args
57 self.kwargs = kwargs
42 self.kwargs = kwargs
58
43
59 def __call__(self, **kwargs):
44 def __call__(self, **kwargs):
60 self.kwargs.update(kwargs)
45 self.kwargs.update(kwargs)
61 return self.func(*self.args, **self.kwargs)
46 return self.func(*self.args, **self.kwargs)
62
47
63 def __str__(self):
48 def __str__(self):
64 return str(self())
49 return str(self())
65
50
66 def __unicode__(self):
51 def __unicode__(self):
67 return py3compat.unicode_type(self())
52 return py3compat.unicode_type(self())
68
53
69 def __format__(self, format_spec):
54 def __format__(self, format_spec):
70 return format(self(), format_spec)
55 return format(self(), format_spec)
71
56
72 def multiple_replace(dict, text):
57 def multiple_replace(dict, text):
73 """ Replace in 'text' all occurrences of any key in the given
58 """ Replace in 'text' all occurrences of any key in the given
74 dictionary by its corresponding value. Returns the new string."""
59 dictionary by its corresponding value. Returns the new string."""
75
60
76 # Function by Xavier Defrang, originally found at:
61 # Function by Xavier Defrang, originally found at:
77 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
62 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
78
63
79 # Create a regular expression from the dictionary keys
64 # Create a regular expression from the dictionary keys
80 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
65 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
81 # For each match, look-up corresponding value in dictionary
66 # For each match, look-up corresponding value in dictionary
82 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
67 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
83
68
84 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
85 # Special characters that can be used in prompt templates, mainly bash-like
70 # Special characters that can be used in prompt templates, mainly bash-like
86 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
87
72
88 # If $HOME isn't defined (Windows), make it an absurd string so that it can
73 # If $HOME isn't defined (Windows), make it an absurd string so that it can
89 # never be expanded out into '~'. Basically anything which can never be a
74 # never be expanded out into '~'. Basically anything which can never be a
90 # reasonable directory name will do, we just want the $HOME -> '~' operation
75 # reasonable directory name will do, we just want the $HOME -> '~' operation
91 # to become a no-op. We pre-compute $HOME here so it's not done on every
76 # to become a no-op. We pre-compute $HOME here so it's not done on every
92 # prompt call.
77 # prompt call.
93
78
94 # FIXME:
79 # FIXME:
95
80
96 # - This should be turned into a class which does proper namespace management,
81 # - This should be turned into a class which does proper namespace management,
97 # since the prompt specials need to be evaluated in a certain namespace.
82 # since the prompt specials need to be evaluated in a certain namespace.
98 # Currently it's just globals, which need to be managed manually by code
83 # Currently it's just globals, which need to be managed manually by code
99 # below.
84 # below.
100
85
101 # - I also need to split up the color schemes from the prompt specials
86 # - I also need to split up the color schemes from the prompt specials
102 # somehow. I don't have a clean design for that quite yet.
87 # somehow. I don't have a clean design for that quite yet.
103
88
104 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
89 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
105
90
106 # This is needed on FreeBSD, and maybe other systems which symlink /home to
91 # This is needed on FreeBSD, and maybe other systems which symlink /home to
107 # /usr/home, but retain the $HOME variable as pointing to /home
92 # /usr/home, but retain the $HOME variable as pointing to /home
108 HOME = os.path.realpath(HOME)
93 HOME = os.path.realpath(HOME)
109
94
110 # We precompute a few more strings here for the prompt_specials, which are
95 # We precompute a few more strings here for the prompt_specials, which are
111 # fixed once ipython starts. This reduces the runtime overhead of computing
96 # fixed once ipython starts. This reduces the runtime overhead of computing
112 # prompt strings.
97 # prompt strings.
113 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
98 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
114 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
99 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
115 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
100 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
116
101
117 # IronPython doesn't currently have os.getuid() even if
102 # IronPython doesn't currently have os.getuid() even if
118 # os.name == 'posix'; 2/8/2014
103 # os.name == 'posix'; 2/8/2014
119 ROOT_SYMBOL = "#" if (os.name=='nt' or sys.platform=='cli' or os.getuid()==0) else "$"
104 ROOT_SYMBOL = "#" if (os.name=='nt' or sys.platform=='cli' or os.getuid()==0) else "$"
120
105
121 prompt_abbreviations = {
106 prompt_abbreviations = {
122 # Prompt/history count
107 # Prompt/history count
123 '%n' : '{color.number}' '{count}' '{color.prompt}',
108 '%n' : '{color.number}' '{count}' '{color.prompt}',
124 r'\#': '{color.number}' '{count}' '{color.prompt}',
109 r'\#': '{color.number}' '{count}' '{color.prompt}',
125 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
110 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
126 # can get numbers displayed in whatever color they want.
111 # can get numbers displayed in whatever color they want.
127 r'\N': '{count}',
112 r'\N': '{count}',
128
113
129 # Prompt/history count, with the actual digits replaced by dots or
114 # Prompt/history count, with the actual digits replaced by dots or
130 # spaces. Used mainly in continuation prompts (prompt_in2).
115 # spaces. Used mainly in continuation prompts (prompt_in2).
131 r'\D': '{dots}',
116 r'\D': '{dots}',
132 r'\S': '{spaces}',
117 r'\S': '{spaces}',
133
118
134 # Current time
119 # Current time
135 r'\T' : '{time}',
120 r'\T' : '{time}',
136 # Current working directory
121 # Current working directory
137 r'\w': '{cwd}',
122 r'\w': '{cwd}',
138 # Basename of current working directory.
123 # Basename of current working directory.
139 # (use os.sep to make this portable across OSes)
124 # (use os.sep to make this portable across OSes)
140 r'\W' : '{cwd_last}',
125 r'\W' : '{cwd_last}',
141 # These X<N> are an extension to the normal bash prompts. They return
126 # These X<N> are an extension to the normal bash prompts. They return
142 # N terms of the path, after replacing $HOME with '~'
127 # N terms of the path, after replacing $HOME with '~'
143 r'\X0': '{cwd_x[0]}',
128 r'\X0': '{cwd_x[0]}',
144 r'\X1': '{cwd_x[1]}',
129 r'\X1': '{cwd_x[1]}',
145 r'\X2': '{cwd_x[2]}',
130 r'\X2': '{cwd_x[2]}',
146 r'\X3': '{cwd_x[3]}',
131 r'\X3': '{cwd_x[3]}',
147 r'\X4': '{cwd_x[4]}',
132 r'\X4': '{cwd_x[4]}',
148 r'\X5': '{cwd_x[5]}',
133 r'\X5': '{cwd_x[5]}',
149 # Y<N> are similar to X<N>, but they show '~' if it's the directory
134 # Y<N> are similar to X<N>, but they show '~' if it's the directory
150 # N+1 in the list. Somewhat like %cN in tcsh.
135 # N+1 in the list. Somewhat like %cN in tcsh.
151 r'\Y0': '{cwd_y[0]}',
136 r'\Y0': '{cwd_y[0]}',
152 r'\Y1': '{cwd_y[1]}',
137 r'\Y1': '{cwd_y[1]}',
153 r'\Y2': '{cwd_y[2]}',
138 r'\Y2': '{cwd_y[2]}',
154 r'\Y3': '{cwd_y[3]}',
139 r'\Y3': '{cwd_y[3]}',
155 r'\Y4': '{cwd_y[4]}',
140 r'\Y4': '{cwd_y[4]}',
156 r'\Y5': '{cwd_y[5]}',
141 r'\Y5': '{cwd_y[5]}',
157 # Hostname up to first .
142 # Hostname up to first .
158 r'\h': HOSTNAME_SHORT,
143 r'\h': HOSTNAME_SHORT,
159 # Full hostname
144 # Full hostname
160 r'\H': HOSTNAME,
145 r'\H': HOSTNAME,
161 # Username of current user
146 # Username of current user
162 r'\u': USER,
147 r'\u': USER,
163 # Escaped '\'
148 # Escaped '\'
164 '\\\\': '\\',
149 '\\\\': '\\',
165 # Newline
150 # Newline
166 r'\n': '\n',
151 r'\n': '\n',
167 # Carriage return
152 # Carriage return
168 r'\r': '\r',
153 r'\r': '\r',
169 # Release version
154 # Release version
170 r'\v': release.version,
155 r'\v': release.version,
171 # Root symbol ($ or #)
156 # Root symbol ($ or #)
172 r'\$': ROOT_SYMBOL,
157 r'\$': ROOT_SYMBOL,
173 }
158 }
174
159
175 #-----------------------------------------------------------------------------
160 #-----------------------------------------------------------------------------
176 # More utilities
161 # More utilities
177 #-----------------------------------------------------------------------------
162 #-----------------------------------------------------------------------------
178
163
179 def cwd_filt(depth):
164 def cwd_filt(depth):
180 """Return the last depth elements of the current working directory.
165 """Return the last depth elements of the current working directory.
181
166
182 $HOME is always replaced with '~'.
167 $HOME is always replaced with '~'.
183 If depth==0, the full path is returned."""
168 If depth==0, the full path is returned."""
184
169
185 cwd = py3compat.getcwd().replace(HOME,"~")
170 cwd = py3compat.getcwd().replace(HOME,"~")
186 out = os.sep.join(cwd.split(os.sep)[-depth:])
171 out = os.sep.join(cwd.split(os.sep)[-depth:])
187 return out or os.sep
172 return out or os.sep
188
173
189 def cwd_filt2(depth):
174 def cwd_filt2(depth):
190 """Return the last depth elements of the current working directory.
175 """Return the last depth elements of the current working directory.
191
176
192 $HOME is always replaced with '~'.
177 $HOME is always replaced with '~'.
193 If depth==0, the full path is returned."""
178 If depth==0, the full path is returned."""
194
179
195 full_cwd = py3compat.getcwd()
180 full_cwd = py3compat.getcwd()
196 cwd = full_cwd.replace(HOME,"~").split(os.sep)
181 cwd = full_cwd.replace(HOME,"~").split(os.sep)
197 if '~' in cwd and len(cwd) == depth+1:
182 if '~' in cwd and len(cwd) == depth+1:
198 depth += 1
183 depth += 1
199 drivepart = ''
184 drivepart = ''
200 if sys.platform == 'win32' and len(cwd) > depth:
185 if sys.platform == 'win32' and len(cwd) > depth:
201 drivepart = os.path.splitdrive(full_cwd)[0]
186 drivepart = os.path.splitdrive(full_cwd)[0]
202 out = drivepart + '/'.join(cwd[-depth:])
187 out = drivepart + '/'.join(cwd[-depth:])
203
188
204 return out or os.sep
189 return out or os.sep
205
190
206 #-----------------------------------------------------------------------------
191 #-----------------------------------------------------------------------------
207 # Prompt classes
192 # Prompt classes
208 #-----------------------------------------------------------------------------
193 #-----------------------------------------------------------------------------
209
194
210 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
195 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
211 'cwd': LazyEvaluate(py3compat.getcwd),
196 'cwd': LazyEvaluate(py3compat.getcwd),
212 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
197 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
213 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
198 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
214 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
199 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
215 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
200 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
216 }
201 }
217
202
218 def _lenlastline(s):
203 def _lenlastline(s):
219 """Get the length of the last line. More intelligent than
204 """Get the length of the last line. More intelligent than
220 len(s.splitlines()[-1]).
205 len(s.splitlines()[-1]).
221 """
206 """
222 if not s or s.endswith(('\n', '\r')):
207 if not s or s.endswith(('\n', '\r')):
223 return 0
208 return 0
224 return len(s.splitlines()[-1])
209 return len(s.splitlines()[-1])
225
210
226
211
227 invisible_chars_re = re.compile('\001[^\001\002]*\002')
212 invisible_chars_re = re.compile('\001[^\001\002]*\002')
228 def _invisible_characters(s):
213 def _invisible_characters(s):
229 """
214 """
230 Get the number of invisible ANSI characters in s. Invisible characters
215 Get the number of invisible ANSI characters in s. Invisible characters
231 must be delimited by \001 and \002.
216 must be delimited by \001 and \002.
232 """
217 """
233 return _lenlastline(s) - _lenlastline(invisible_chars_re.sub('', s))
218 return _lenlastline(s) - _lenlastline(invisible_chars_re.sub('', s))
234
219
235 class UserNSFormatter(Formatter):
220 class UserNSFormatter(Formatter):
236 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
221 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
237 def __init__(self, shell):
222 def __init__(self, shell):
238 self.shell = shell
223 self.shell = shell
239
224
240 def get_value(self, key, args, kwargs):
225 def get_value(self, key, args, kwargs):
241 # try regular formatting first:
226 # try regular formatting first:
242 try:
227 try:
243 return Formatter.get_value(self, key, args, kwargs)
228 return Formatter.get_value(self, key, args, kwargs)
244 except Exception:
229 except Exception:
245 pass
230 pass
246 # next, look in user_ns and builtins:
231 # next, look in user_ns and builtins:
247 for container in (self.shell.user_ns, __builtins__):
232 for container in (self.shell.user_ns, __builtins__):
248 if key in container:
233 if key in container:
249 return container[key]
234 return container[key]
250 # nothing found, put error message in its place
235 # nothing found, put error message in its place
251 return "<ERROR: '%s' not found>" % key
236 return "<ERROR: '%s' not found>" % key
252
237
253
238
254 class PromptManager(Configurable):
239 class PromptManager(Configurable):
255 """This is the primary interface for producing IPython's prompts."""
240 """This is the primary interface for producing IPython's prompts."""
256 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
241 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
257
242
258 color_scheme_table = Instance(coloransi.ColorSchemeTable, allow_none=True)
243 color_scheme_table = Instance(coloransi.ColorSchemeTable, allow_none=True)
259 color_scheme = Unicode('Linux').tag(config=True)
244 color_scheme = Unicode('Linux').tag(config=True)
260
245
261 @observe('color_scheme')
246 @observe('color_scheme')
262 def _color_scheme_changed(self, change):
247 def _color_scheme_changed(self, change):
263 self.color_scheme_table.set_active_scheme(change['new'])
248 self.color_scheme_table.set_active_scheme(change['new'])
264 for pname in ['in', 'in2', 'out', 'rewrite']:
249 for pname in ['in', 'in2', 'out', 'rewrite']:
265 # We need to recalculate the number of invisible characters
250 # We need to recalculate the number of invisible characters
266 self.update_prompt(pname)
251 self.update_prompt(pname)
267
252
268 lazy_evaluate_fields = Dict(help="""
253 lazy_evaluate_fields = Dict(help="""
269 This maps field names used in the prompt templates to functions which
254 This maps field names used in the prompt templates to functions which
270 will be called when the prompt is rendered. This allows us to include
255 will be called when the prompt is rendered. This allows us to include
271 things like the current time in the prompts. Functions are only called
256 things like the current time in the prompts. Functions are only called
272 if they are used in the prompt.
257 if they are used in the prompt.
273 """)
258 """)
274 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
275
259
276 in_template = Unicode('In [\\#]: ',
260 in_template = Unicode('In [\\#]: ',
277 help="Input prompt. '\\#' will be transformed to the prompt number"
261 help="Input prompt. '\\#' will be transformed to the prompt number"
278 ).tag(config=True)
262 ).tag(config=True)
279 in2_template = Unicode(' .\\D.: ',
263 in2_template = Unicode(' .\\D.: ',
280 help="Continuation prompt.").tag(config=True)
264 help="Continuation prompt.").tag(config=True)
281 out_template = Unicode('Out[\\#]: ',
265 out_template = Unicode('Out[\\#]: ',
282 help="Output prompt. '\\#' will be transformed to the prompt number"
266 help="Output prompt. '\\#' will be transformed to the prompt number"
283 ).tag(config=True)
267 ).tag(config=True)
284
268
269 @default('lazy_evaluate_fields')
270 def _lazy_evaluate_fields_default(self):
271 return lazily_evaluate.copy()
272
285 justify = Bool(True, help="""
273 justify = Bool(True, help="""
286 If True (default), each prompt will be right-aligned with the
274 If True (default), each prompt will be right-aligned with the
287 preceding one.
275 preceding one.
288 """).tag(config=True)
276 """).tag(config=True)
289
277
290 # We actually store the expanded templates here:
278 # We actually store the expanded templates here:
291 templates = Dict()
279 templates = Dict()
292
280
293 # The number of characters in the last prompt rendered, not including
281 # The number of characters in the last prompt rendered, not including
294 # colour characters.
282 # colour characters.
295 width = Int()
283 width = Int()
296 txtwidth = Int() # Not including right-justification
284 txtwidth = Int() # Not including right-justification
297
285
298 # The number of characters in each prompt which don't contribute to width
286 # The number of characters in each prompt which don't contribute to width
299 invisible_chars = Dict()
287 invisible_chars = Dict()
288 @default('invisible_chars')
300 def _invisible_chars_default(self):
289 def _invisible_chars_default(self):
301 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
290 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
302
291
303 def __init__(self, shell, **kwargs):
292 def __init__(self, shell, **kwargs):
304 super(PromptManager, self).__init__(shell=shell, **kwargs)
293 super(PromptManager, self).__init__(shell=shell, **kwargs)
305
294
306 # Prepare colour scheme table
295 # Prepare colour scheme table
307 self.color_scheme_table = coloransi.ColorSchemeTable([NoColor,
296 self.color_scheme_table = coloransi.ColorSchemeTable([NoColor,
308 LinuxColors, LightBGColors], self.color_scheme)
297 LinuxColors, LightBGColors], self.color_scheme)
309
298
310 self._formatter = UserNSFormatter(shell)
299 self._formatter = UserNSFormatter(shell)
311 # Prepare templates & numbers of invisible characters
300 # Prepare templates & numbers of invisible characters
312 self.update_prompt('in', self.in_template)
301 self.update_prompt('in', self.in_template)
313 self.update_prompt('in2', self.in2_template)
302 self.update_prompt('in2', self.in2_template)
314 self.update_prompt('out', self.out_template)
303 self.update_prompt('out', self.out_template)
315 self.update_prompt('rewrite')
304 self.update_prompt('rewrite')
316 self.on_trait_change(self._update_prompt_trait, ['in_template',
305 self.observe(self._update_prompt_trait,
317 'in2_template', 'out_template'])
306 names=['in_template', 'in2_template', 'out_template'])
318
307
319 def update_prompt(self, name, new_template=None):
308 def update_prompt(self, name, new_template=None):
320 """This is called when a prompt template is updated. It processes
309 """This is called when a prompt template is updated. It processes
321 abbreviations used in the prompt template (like \#) and calculates how
310 abbreviations used in the prompt template (like \#) and calculates how
322 many invisible characters (ANSI colour escapes) the resulting prompt
311 many invisible characters (ANSI colour escapes) the resulting prompt
323 contains.
312 contains.
324
313
325 It is also called for each prompt on changing the colour scheme. In both
314 It is also called for each prompt on changing the colour scheme. In both
326 cases, traitlets should take care of calling this automatically.
315 cases, traitlets should take care of calling this automatically.
327 """
316 """
328 if new_template is not None:
317 if new_template is not None:
329 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
318 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
330 # We count invisible characters (colour escapes) on the last line of the
319 # We count invisible characters (colour escapes) on the last line of the
331 # prompt, to calculate the width for lining up subsequent prompts.
320 # prompt, to calculate the width for lining up subsequent prompts.
332 invis_chars = _invisible_characters(self._render(name, color=True))
321 invis_chars = _invisible_characters(self._render(name, color=True))
333 self.invisible_chars[name] = invis_chars
322 self.invisible_chars[name] = invis_chars
334
323
335 def _update_prompt_trait(self, traitname, new_template):
324 def _update_prompt_trait(self, traitname, new_template):
336 name = traitname[:-9] # Cut off '_template'
325 name = traitname[:-9] # Cut off '_template'
337 self.update_prompt(name, new_template)
326 self.update_prompt(name, new_template)
338
327
339 def _render(self, name, color=True, **kwargs):
328 def _render(self, name, color=True, **kwargs):
340 """Render but don't justify, or update the width or txtwidth attributes.
329 """Render but don't justify, or update the width or txtwidth attributes.
341 """
330 """
342 if name == 'rewrite':
331 if name == 'rewrite':
343 return self._render_rewrite(color=color)
332 return self._render_rewrite(color=color)
344
333
345 if color:
334 if color:
346 scheme = self.color_scheme_table.active_colors
335 scheme = self.color_scheme_table.active_colors
347 if name=='out':
336 if name=='out':
348 colors = color_lists['normal']
337 colors = color_lists['normal']
349 colors.number, colors.prompt, colors.normal = \
338 colors.number, colors.prompt, colors.normal = \
350 scheme.out_number, scheme.out_prompt, scheme.normal
339 scheme.out_number, scheme.out_prompt, scheme.normal
351 else:
340 else:
352 colors = color_lists['inp']
341 colors = color_lists['inp']
353 colors.number, colors.prompt, colors.normal = \
342 colors.number, colors.prompt, colors.normal = \
354 scheme.in_number, scheme.in_prompt, scheme.in_normal
343 scheme.in_number, scheme.in_prompt, scheme.in_normal
355 if name=='in2':
344 if name=='in2':
356 colors.prompt = scheme.in_prompt2
345 colors.prompt = scheme.in_prompt2
357 else:
346 else:
358 # No color
347 # No color
359 colors = color_lists['nocolor']
348 colors = color_lists['nocolor']
360 colors.number, colors.prompt, colors.normal = '', '', ''
349 colors.number, colors.prompt, colors.normal = '', '', ''
361
350
362 count = self.shell.execution_count # Shorthand
351 count = self.shell.execution_count # Shorthand
363 # Build the dictionary to be passed to string formatting
352 # Build the dictionary to be passed to string formatting
364 fmtargs = dict(color=colors, count=count,
353 fmtargs = dict(color=colors, count=count,
365 dots="."*len(str(count)), spaces=" "*len(str(count)),
354 dots="."*len(str(count)), spaces=" "*len(str(count)),
366 width=self.width, txtwidth=self.txtwidth)
355 width=self.width, txtwidth=self.txtwidth)
367 fmtargs.update(self.lazy_evaluate_fields)
356 fmtargs.update(self.lazy_evaluate_fields)
368 fmtargs.update(kwargs)
357 fmtargs.update(kwargs)
369
358
370 # Prepare the prompt
359 # Prepare the prompt
371 prompt = colors.prompt + self.templates[name] + colors.normal
360 prompt = colors.prompt + self.templates[name] + colors.normal
372
361
373 # Fill in required fields
362 # Fill in required fields
374 return self._formatter.format(prompt, **fmtargs)
363 return self._formatter.format(prompt, **fmtargs)
375
364
376 def _render_rewrite(self, color=True):
365 def _render_rewrite(self, color=True):
377 """Render the ---> rewrite prompt."""
366 """Render the ---> rewrite prompt."""
378 if color:
367 if color:
379 scheme = self.color_scheme_table.active_colors
368 scheme = self.color_scheme_table.active_colors
380 # We need a non-input version of these escapes
369 # We need a non-input version of these escapes
381 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
370 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
382 color_normal = scheme.normal
371 color_normal = scheme.normal
383 else:
372 else:
384 color_prompt, color_normal = '', ''
373 color_prompt, color_normal = '', ''
385
374
386 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
375 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
387
376
388 def render(self, name, color=True, just=None, **kwargs):
377 def render(self, name, color=True, just=None, **kwargs):
389 """
378 """
390 Render the selected prompt.
379 Render the selected prompt.
391
380
392 Parameters
381 Parameters
393 ----------
382 ----------
394 name : str
383 name : str
395 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
384 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
396 color : bool
385 color : bool
397 If True (default), include ANSI escape sequences for a coloured prompt.
386 If True (default), include ANSI escape sequences for a coloured prompt.
398 just : bool
387 just : bool
399 If True, justify the prompt to the width of the last prompt. The
388 If True, justify the prompt to the width of the last prompt. The
400 default is stored in self.justify.
389 default is stored in self.justify.
401 **kwargs :
390 **kwargs :
402 Additional arguments will be passed to the string formatting operation,
391 Additional arguments will be passed to the string formatting operation,
403 so they can override the values that would otherwise fill in the
392 so they can override the values that would otherwise fill in the
404 template.
393 template.
405
394
406 Returns
395 Returns
407 -------
396 -------
408 A string containing the rendered prompt.
397 A string containing the rendered prompt.
409 """
398 """
410 res = self._render(name, color=color, **kwargs)
399 res = self._render(name, color=color, **kwargs)
411
400
412 # Handle justification of prompt
401 # Handle justification of prompt
413 invis_chars = self.invisible_chars[name] if color else 0
402 invis_chars = self.invisible_chars[name] if color else 0
414 self.txtwidth = _lenlastline(res) - invis_chars
403 self.txtwidth = _lenlastline(res) - invis_chars
415 just = self.justify if (just is None) else just
404 just = self.justify if (just is None) else just
416 # If the prompt spans more than one line, don't try to justify it:
405 # If the prompt spans more than one line, don't try to justify it:
417 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
406 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
418 res = res.rjust(self.width + invis_chars)
407 res = res.rjust(self.width + invis_chars)
419 self.width = _lenlastline(res) - invis_chars
408 self.width = _lenlastline(res) - invis_chars
420 return res
409 return res
@@ -1,440 +1,437 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A mixin for :class:`~IPython.core.application.Application` classes that
3 A mixin for :class:`~IPython.core.application.Application` classes that
4 launch InteractiveShell instances, load extensions, etc.
4 launch InteractiveShell instances, load extensions, etc.
5 """
5 """
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 from __future__ import absolute_import
10 from __future__ import absolute_import
11 from __future__ import print_function
11 from __future__ import print_function
12
12
13 import glob
13 import glob
14 import os
14 import os
15 import sys
15 import sys
16
16
17 from traitlets.config.application import boolean_flag
17 from traitlets.config.application import boolean_flag
18 from traitlets.config.configurable import Configurable
18 from traitlets.config.configurable import Configurable
19 from traitlets.config.loader import Config
19 from traitlets.config.loader import Config
20 from IPython.core import pylabtools
20 from IPython.core import pylabtools
21 from IPython.utils import py3compat
21 from IPython.utils import py3compat
22 from IPython.utils.contexts import preserve_keys
22 from IPython.utils.contexts import preserve_keys
23 from IPython.utils.path import filefind
23 from IPython.utils.path import filefind
24 from traitlets import (
24 from traitlets import (
25 Unicode, Instance, List, Bool, CaselessStrEnum
25 Unicode, Instance, List, Bool, CaselessStrEnum, default, observe,
26 )
26 )
27 from IPython.lib.inputhook import guis
27 from IPython.lib.inputhook import guis
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Aliases and Flags
30 # Aliases and Flags
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
33 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
34
34
35 backend_keys = sorted(pylabtools.backends.keys())
35 backend_keys = sorted(pylabtools.backends.keys())
36 backend_keys.insert(0, 'auto')
36 backend_keys.insert(0, 'auto')
37
37
38 shell_flags = {}
38 shell_flags = {}
39
39
40 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
40 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
41 addflag('autoindent', 'InteractiveShell.autoindent',
41 addflag('autoindent', 'InteractiveShell.autoindent',
42 'Turn on autoindenting.', 'Turn off autoindenting.'
42 'Turn on autoindenting.', 'Turn off autoindenting.'
43 )
43 )
44 addflag('automagic', 'InteractiveShell.automagic',
44 addflag('automagic', 'InteractiveShell.automagic',
45 """Turn on the auto calling of magic commands. Type %%magic at the
45 """Turn on the auto calling of magic commands. Type %%magic at the
46 IPython prompt for more information.""",
46 IPython prompt for more information.""",
47 'Turn off the auto calling of magic commands.'
47 'Turn off the auto calling of magic commands.'
48 )
48 )
49 addflag('pdb', 'InteractiveShell.pdb',
49 addflag('pdb', 'InteractiveShell.pdb',
50 "Enable auto calling the pdb debugger after every exception.",
50 "Enable auto calling the pdb debugger after every exception.",
51 "Disable auto calling the pdb debugger after every exception."
51 "Disable auto calling the pdb debugger after every exception."
52 )
52 )
53 # pydb flag doesn't do any config, as core.debugger switches on import,
53 # pydb flag doesn't do any config, as core.debugger switches on import,
54 # which is before parsing. This just allows the flag to be passed.
54 # which is before parsing. This just allows the flag to be passed.
55 shell_flags.update(dict(
55 shell_flags.update(dict(
56 pydb = ({},
56 pydb = ({},
57 """Use the third party 'pydb' package as debugger, instead of pdb.
57 """Use the third party 'pydb' package as debugger, instead of pdb.
58 Requires that pydb is installed."""
58 Requires that pydb is installed."""
59 )
59 )
60 ))
60 ))
61 addflag('pprint', 'PlainTextFormatter.pprint',
61 addflag('pprint', 'PlainTextFormatter.pprint',
62 "Enable auto pretty printing of results.",
62 "Enable auto pretty printing of results.",
63 "Disable auto pretty printing of results."
63 "Disable auto pretty printing of results."
64 )
64 )
65 addflag('color-info', 'InteractiveShell.color_info',
65 addflag('color-info', 'InteractiveShell.color_info',
66 """IPython can display information about objects via a set of functions,
66 """IPython can display information about objects via a set of functions,
67 and optionally can use colors for this, syntax highlighting
67 and optionally can use colors for this, syntax highlighting
68 source code and various other elements. This is on by default, but can cause
68 source code and various other elements. This is on by default, but can cause
69 problems with some pagers. If you see such problems, you can disable the
69 problems with some pagers. If you see such problems, you can disable the
70 colours.""",
70 colours.""",
71 "Disable using colors for info related things."
71 "Disable using colors for info related things."
72 )
72 )
73 addflag('deep-reload', 'InteractiveShell.deep_reload',
73 addflag('deep-reload', 'InteractiveShell.deep_reload',
74 """ **Deprecated** and will be removed in IPython 5.0.
74 """ **Deprecated** and will be removed in IPython 5.0.
75
75
76 Enable deep (recursive) reloading by default. IPython can use the
76 Enable deep (recursive) reloading by default. IPython can use the
77 deep_reload module which reloads changes in modules recursively (it
77 deep_reload module which reloads changes in modules recursively (it
78 replaces the reload() function, so you don't need to change anything to
78 replaces the reload() function, so you don't need to change anything to
79 use it). deep_reload() forces a full reload of modules whose code may
79 use it). deep_reload() forces a full reload of modules whose code may
80 have changed, which the default reload() function does not. When
80 have changed, which the default reload() function does not. When
81 deep_reload is off, IPython will use the normal reload(), but
81 deep_reload is off, IPython will use the normal reload(), but
82 deep_reload will still be available as dreload(). This feature is off
82 deep_reload will still be available as dreload(). This feature is off
83 by default [which means that you have both normal reload() and
83 by default [which means that you have both normal reload() and
84 dreload()].""",
84 dreload()].""",
85 "Disable deep (recursive) reloading by default."
85 "Disable deep (recursive) reloading by default."
86 )
86 )
87 nosep_config = Config()
87 nosep_config = Config()
88 nosep_config.InteractiveShell.separate_in = ''
88 nosep_config.InteractiveShell.separate_in = ''
89 nosep_config.InteractiveShell.separate_out = ''
89 nosep_config.InteractiveShell.separate_out = ''
90 nosep_config.InteractiveShell.separate_out2 = ''
90 nosep_config.InteractiveShell.separate_out2 = ''
91
91
92 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
92 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
93 shell_flags['pylab'] = (
93 shell_flags['pylab'] = (
94 {'InteractiveShellApp' : {'pylab' : 'auto'}},
94 {'InteractiveShellApp' : {'pylab' : 'auto'}},
95 """Pre-load matplotlib and numpy for interactive use with
95 """Pre-load matplotlib and numpy for interactive use with
96 the default matplotlib backend."""
96 the default matplotlib backend."""
97 )
97 )
98 shell_flags['matplotlib'] = (
98 shell_flags['matplotlib'] = (
99 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
99 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
100 """Configure matplotlib for interactive use with
100 """Configure matplotlib for interactive use with
101 the default matplotlib backend."""
101 the default matplotlib backend."""
102 )
102 )
103
103
104 # it's possible we don't want short aliases for *all* of these:
104 # it's possible we don't want short aliases for *all* of these:
105 shell_aliases = dict(
105 shell_aliases = dict(
106 autocall='InteractiveShell.autocall',
106 autocall='InteractiveShell.autocall',
107 colors='InteractiveShell.colors',
107 colors='InteractiveShell.colors',
108 logfile='InteractiveShell.logfile',
108 logfile='InteractiveShell.logfile',
109 logappend='InteractiveShell.logappend',
109 logappend='InteractiveShell.logappend',
110 c='InteractiveShellApp.code_to_run',
110 c='InteractiveShellApp.code_to_run',
111 m='InteractiveShellApp.module_to_run',
111 m='InteractiveShellApp.module_to_run',
112 ext='InteractiveShellApp.extra_extension',
112 ext='InteractiveShellApp.extra_extension',
113 gui='InteractiveShellApp.gui',
113 gui='InteractiveShellApp.gui',
114 pylab='InteractiveShellApp.pylab',
114 pylab='InteractiveShellApp.pylab',
115 matplotlib='InteractiveShellApp.matplotlib',
115 matplotlib='InteractiveShellApp.matplotlib',
116 )
116 )
117 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
117 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
118
118
119 #-----------------------------------------------------------------------------
119 #-----------------------------------------------------------------------------
120 # Main classes and functions
120 # Main classes and functions
121 #-----------------------------------------------------------------------------
121 #-----------------------------------------------------------------------------
122
122
123 class InteractiveShellApp(Configurable):
123 class InteractiveShellApp(Configurable):
124 """A Mixin for applications that start InteractiveShell instances.
124 """A Mixin for applications that start InteractiveShell instances.
125
125
126 Provides configurables for loading extensions and executing files
126 Provides configurables for loading extensions and executing files
127 as part of configuring a Shell environment.
127 as part of configuring a Shell environment.
128
128
129 The following methods should be called by the :meth:`initialize` method
129 The following methods should be called by the :meth:`initialize` method
130 of the subclass:
130 of the subclass:
131
131
132 - :meth:`init_path`
132 - :meth:`init_path`
133 - :meth:`init_shell` (to be implemented by the subclass)
133 - :meth:`init_shell` (to be implemented by the subclass)
134 - :meth:`init_gui_pylab`
134 - :meth:`init_gui_pylab`
135 - :meth:`init_extensions`
135 - :meth:`init_extensions`
136 - :meth:`init_code`
136 - :meth:`init_code`
137 """
137 """
138 extensions = List(Unicode(), config=True,
138 extensions = List(Unicode(),
139 help="A list of dotted module names of IPython extensions to load."
139 help="A list of dotted module names of IPython extensions to load."
140 )
140 ).tag(config=True)
141 extra_extension = Unicode('', config=True,
141 extra_extension = Unicode('',
142 help="dotted module name of an IPython extension to load."
142 help="dotted module name of an IPython extension to load."
143 )
143 ).tag(config=True)
144
144
145 reraise_ipython_extension_failures = Bool(
145 reraise_ipython_extension_failures = Bool(False,
146 False,
147 config=True,
148 help="Reraise exceptions encountered loading IPython extensions?",
146 help="Reraise exceptions encountered loading IPython extensions?",
149 )
147 ).tag(config=True)
150
148
151 # Extensions that are always loaded (not configurable)
149 # Extensions that are always loaded (not configurable)
152 default_extensions = List(Unicode(), [u'storemagic'], config=False)
150 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
153
151
154 hide_initial_ns = Bool(True, config=True,
152 hide_initial_ns = Bool(True,
155 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
153 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
156 be hidden from tools like %who?"""
154 be hidden from tools like %who?"""
157 )
155 ).tag(config=True)
158
156
159 exec_files = List(Unicode(), config=True,
157 exec_files = List(Unicode(),
160 help="""List of files to run at IPython startup."""
158 help="""List of files to run at IPython startup."""
161 )
159 ).tag(config=True)
162 exec_PYTHONSTARTUP = Bool(True, config=True,
160 exec_PYTHONSTARTUP = Bool(True,
163 help="""Run the file referenced by the PYTHONSTARTUP environment
161 help="""Run the file referenced by the PYTHONSTARTUP environment
164 variable at IPython startup."""
162 variable at IPython startup."""
165 )
163 ).tag(config=True)
166 file_to_run = Unicode('', config=True,
164 file_to_run = Unicode('',
167 help="""A file to be run""")
165 help="""A file to be run""").tag(config=True)
168
166
169 exec_lines = List(Unicode(), config=True,
167 exec_lines = List(Unicode(),
170 help="""lines of code to run at IPython startup."""
168 help="""lines of code to run at IPython startup."""
171 )
169 ).tag(config=True)
172 code_to_run = Unicode('', config=True,
170 code_to_run = Unicode('',
173 help="Execute the given command string."
171 help="Execute the given command string."
174 )
172 ).tag(config=True)
175 module_to_run = Unicode('', config=True,
173 module_to_run = Unicode('',
176 help="Run the module as a script."
174 help="Run the module as a script."
177 )
175 ).tag(config=True)
178 gui = CaselessStrEnum(gui_keys, config=True, allow_none=True,
176 gui = CaselessStrEnum(gui_keys, allow_none=True,
179 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
177 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
180 )
178 ).tag(config=True)
181 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
179 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
182 config=True,
183 help="""Configure matplotlib for interactive use with
180 help="""Configure matplotlib for interactive use with
184 the default matplotlib backend."""
181 the default matplotlib backend."""
185 )
182 ).tag(config=True)
186 pylab = CaselessStrEnum(backend_keys, allow_none=True,
183 pylab = CaselessStrEnum(backend_keys, allow_none=True,
187 config=True,
188 help="""Pre-load matplotlib and numpy for interactive use,
184 help="""Pre-load matplotlib and numpy for interactive use,
189 selecting a particular matplotlib backend and loop integration.
185 selecting a particular matplotlib backend and loop integration.
190 """
186 """
191 )
187 ).tag(config=True)
192 pylab_import_all = Bool(True, config=True,
188 pylab_import_all = Bool(True,
193 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
189 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
194 and an ``import *`` is done from numpy and pylab, when using pylab mode.
190 and an ``import *`` is done from numpy and pylab, when using pylab mode.
195
191
196 When False, pylab mode should not import any names into the user namespace.
192 When False, pylab mode should not import any names into the user namespace.
197 """
193 """
198 )
194 ).tag(config=True)
199 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
195 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
200 allow_none=True)
196 allow_none=True)
201 # whether interact-loop should start
197 # whether interact-loop should start
202 interact = Bool(True)
198 interact = Bool(True)
203
199
204 user_ns = Instance(dict, args=None, allow_none=True)
200 user_ns = Instance(dict, args=None, allow_none=True)
205 def _user_ns_changed(self, name, old, new):
201 @observe('user_ns')
202 def _user_ns_changed(self, change):
206 if self.shell is not None:
203 if self.shell is not None:
207 self.shell.user_ns = new
204 self.shell.user_ns = change['new']
208 self.shell.init_user_ns()
205 self.shell.init_user_ns()
209
206
210 def init_path(self):
207 def init_path(self):
211 """Add current working directory, '', to sys.path"""
208 """Add current working directory, '', to sys.path"""
212 if sys.path[0] != '':
209 if sys.path[0] != '':
213 sys.path.insert(0, '')
210 sys.path.insert(0, '')
214
211
215 def init_shell(self):
212 def init_shell(self):
216 raise NotImplementedError("Override in subclasses")
213 raise NotImplementedError("Override in subclasses")
217
214
218 def init_gui_pylab(self):
215 def init_gui_pylab(self):
219 """Enable GUI event loop integration, taking pylab into account."""
216 """Enable GUI event loop integration, taking pylab into account."""
220 enable = False
217 enable = False
221 shell = self.shell
218 shell = self.shell
222 if self.pylab:
219 if self.pylab:
223 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
220 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
224 key = self.pylab
221 key = self.pylab
225 elif self.matplotlib:
222 elif self.matplotlib:
226 enable = shell.enable_matplotlib
223 enable = shell.enable_matplotlib
227 key = self.matplotlib
224 key = self.matplotlib
228 elif self.gui:
225 elif self.gui:
229 enable = shell.enable_gui
226 enable = shell.enable_gui
230 key = self.gui
227 key = self.gui
231
228
232 if not enable:
229 if not enable:
233 return
230 return
234
231
235 try:
232 try:
236 r = enable(key)
233 r = enable(key)
237 except ImportError:
234 except ImportError:
238 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
235 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
239 self.shell.showtraceback()
236 self.shell.showtraceback()
240 return
237 return
241 except Exception:
238 except Exception:
242 self.log.warning("GUI event loop or pylab initialization failed")
239 self.log.warning("GUI event loop or pylab initialization failed")
243 self.shell.showtraceback()
240 self.shell.showtraceback()
244 return
241 return
245
242
246 if isinstance(r, tuple):
243 if isinstance(r, tuple):
247 gui, backend = r[:2]
244 gui, backend = r[:2]
248 self.log.info("Enabling GUI event loop integration, "
245 self.log.info("Enabling GUI event loop integration, "
249 "eventloop=%s, matplotlib=%s", gui, backend)
246 "eventloop=%s, matplotlib=%s", gui, backend)
250 if key == "auto":
247 if key == "auto":
251 print("Using matplotlib backend: %s" % backend)
248 print("Using matplotlib backend: %s" % backend)
252 else:
249 else:
253 gui = r
250 gui = r
254 self.log.info("Enabling GUI event loop integration, "
251 self.log.info("Enabling GUI event loop integration, "
255 "eventloop=%s", gui)
252 "eventloop=%s", gui)
256
253
257 def init_extensions(self):
254 def init_extensions(self):
258 """Load all IPython extensions in IPythonApp.extensions.
255 """Load all IPython extensions in IPythonApp.extensions.
259
256
260 This uses the :meth:`ExtensionManager.load_extensions` to load all
257 This uses the :meth:`ExtensionManager.load_extensions` to load all
261 the extensions listed in ``self.extensions``.
258 the extensions listed in ``self.extensions``.
262 """
259 """
263 try:
260 try:
264 self.log.debug("Loading IPython extensions...")
261 self.log.debug("Loading IPython extensions...")
265 extensions = self.default_extensions + self.extensions
262 extensions = self.default_extensions + self.extensions
266 if self.extra_extension:
263 if self.extra_extension:
267 extensions.append(self.extra_extension)
264 extensions.append(self.extra_extension)
268 for ext in extensions:
265 for ext in extensions:
269 try:
266 try:
270 self.log.info("Loading IPython extension: %s" % ext)
267 self.log.info("Loading IPython extension: %s" % ext)
271 self.shell.extension_manager.load_extension(ext)
268 self.shell.extension_manager.load_extension(ext)
272 except:
269 except:
273 if self.reraise_ipython_extension_failures:
270 if self.reraise_ipython_extension_failures:
274 raise
271 raise
275 msg = ("Error in loading extension: {ext}\n"
272 msg = ("Error in loading extension: {ext}\n"
276 "Check your config files in {location}".format(
273 "Check your config files in {location}".format(
277 ext=ext,
274 ext=ext,
278 location=self.profile_dir.location
275 location=self.profile_dir.location
279 ))
276 ))
280 self.log.warning(msg, exc_info=True)
277 self.log.warning(msg, exc_info=True)
281 except:
278 except:
282 if self.reraise_ipython_extension_failures:
279 if self.reraise_ipython_extension_failures:
283 raise
280 raise
284 self.log.warning("Unknown error in loading extensions:", exc_info=True)
281 self.log.warning("Unknown error in loading extensions:", exc_info=True)
285
282
286 def init_code(self):
283 def init_code(self):
287 """run the pre-flight code, specified via exec_lines"""
284 """run the pre-flight code, specified via exec_lines"""
288 self._run_startup_files()
285 self._run_startup_files()
289 self._run_exec_lines()
286 self._run_exec_lines()
290 self._run_exec_files()
287 self._run_exec_files()
291
288
292 # Hide variables defined here from %who etc.
289 # Hide variables defined here from %who etc.
293 if self.hide_initial_ns:
290 if self.hide_initial_ns:
294 self.shell.user_ns_hidden.update(self.shell.user_ns)
291 self.shell.user_ns_hidden.update(self.shell.user_ns)
295
292
296 # command-line execution (ipython -i script.py, ipython -m module)
293 # command-line execution (ipython -i script.py, ipython -m module)
297 # should *not* be excluded from %whos
294 # should *not* be excluded from %whos
298 self._run_cmd_line_code()
295 self._run_cmd_line_code()
299 self._run_module()
296 self._run_module()
300
297
301 # flush output, so itwon't be attached to the first cell
298 # flush output, so itwon't be attached to the first cell
302 sys.stdout.flush()
299 sys.stdout.flush()
303 sys.stderr.flush()
300 sys.stderr.flush()
304
301
305 def _run_exec_lines(self):
302 def _run_exec_lines(self):
306 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
303 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
307 if not self.exec_lines:
304 if not self.exec_lines:
308 return
305 return
309 try:
306 try:
310 self.log.debug("Running code from IPythonApp.exec_lines...")
307 self.log.debug("Running code from IPythonApp.exec_lines...")
311 for line in self.exec_lines:
308 for line in self.exec_lines:
312 try:
309 try:
313 self.log.info("Running code in user namespace: %s" %
310 self.log.info("Running code in user namespace: %s" %
314 line)
311 line)
315 self.shell.run_cell(line, store_history=False)
312 self.shell.run_cell(line, store_history=False)
316 except:
313 except:
317 self.log.warning("Error in executing line in user "
314 self.log.warning("Error in executing line in user "
318 "namespace: %s" % line)
315 "namespace: %s" % line)
319 self.shell.showtraceback()
316 self.shell.showtraceback()
320 except:
317 except:
321 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
318 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
322 self.shell.showtraceback()
319 self.shell.showtraceback()
323
320
324 def _exec_file(self, fname, shell_futures=False):
321 def _exec_file(self, fname, shell_futures=False):
325 try:
322 try:
326 full_filename = filefind(fname, [u'.', self.ipython_dir])
323 full_filename = filefind(fname, [u'.', self.ipython_dir])
327 except IOError as e:
324 except IOError as e:
328 self.log.warning("File not found: %r"%fname)
325 self.log.warning("File not found: %r"%fname)
329 return
326 return
330 # Make sure that the running script gets a proper sys.argv as if it
327 # Make sure that the running script gets a proper sys.argv as if it
331 # were run from a system shell.
328 # were run from a system shell.
332 save_argv = sys.argv
329 save_argv = sys.argv
333 sys.argv = [full_filename] + self.extra_args[1:]
330 sys.argv = [full_filename] + self.extra_args[1:]
334 # protect sys.argv from potential unicode strings on Python 2:
331 # protect sys.argv from potential unicode strings on Python 2:
335 if not py3compat.PY3:
332 if not py3compat.PY3:
336 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
333 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
337 try:
334 try:
338 if os.path.isfile(full_filename):
335 if os.path.isfile(full_filename):
339 self.log.info("Running file in user namespace: %s" %
336 self.log.info("Running file in user namespace: %s" %
340 full_filename)
337 full_filename)
341 # Ensure that __file__ is always defined to match Python
338 # Ensure that __file__ is always defined to match Python
342 # behavior.
339 # behavior.
343 with preserve_keys(self.shell.user_ns, '__file__'):
340 with preserve_keys(self.shell.user_ns, '__file__'):
344 self.shell.user_ns['__file__'] = fname
341 self.shell.user_ns['__file__'] = fname
345 if full_filename.endswith('.ipy'):
342 if full_filename.endswith('.ipy'):
346 self.shell.safe_execfile_ipy(full_filename,
343 self.shell.safe_execfile_ipy(full_filename,
347 shell_futures=shell_futures)
344 shell_futures=shell_futures)
348 else:
345 else:
349 # default to python, even without extension
346 # default to python, even without extension
350 self.shell.safe_execfile(full_filename,
347 self.shell.safe_execfile(full_filename,
351 self.shell.user_ns,
348 self.shell.user_ns,
352 shell_futures=shell_futures,
349 shell_futures=shell_futures,
353 raise_exceptions=True)
350 raise_exceptions=True)
354 finally:
351 finally:
355 sys.argv = save_argv
352 sys.argv = save_argv
356
353
357 def _run_startup_files(self):
354 def _run_startup_files(self):
358 """Run files from profile startup directory"""
355 """Run files from profile startup directory"""
359 startup_dir = self.profile_dir.startup_dir
356 startup_dir = self.profile_dir.startup_dir
360 startup_files = []
357 startup_files = []
361
358
362 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
359 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
363 not (self.file_to_run or self.code_to_run or self.module_to_run):
360 not (self.file_to_run or self.code_to_run or self.module_to_run):
364 python_startup = os.environ['PYTHONSTARTUP']
361 python_startup = os.environ['PYTHONSTARTUP']
365 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
362 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
366 try:
363 try:
367 self._exec_file(python_startup)
364 self._exec_file(python_startup)
368 except:
365 except:
369 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
366 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
370 self.shell.showtraceback()
367 self.shell.showtraceback()
371 finally:
368 finally:
372 # Many PYTHONSTARTUP files set up the readline completions,
369 # Many PYTHONSTARTUP files set up the readline completions,
373 # but this is often at odds with IPython's own completions.
370 # but this is often at odds with IPython's own completions.
374 # Do not allow PYTHONSTARTUP to set up readline.
371 # Do not allow PYTHONSTARTUP to set up readline.
375 if self.shell.has_readline:
372 if self.shell.has_readline:
376 self.shell.set_readline_completer()
373 self.shell.set_readline_completer()
377
374
378 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
375 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
379 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
376 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
380 if not startup_files:
377 if not startup_files:
381 return
378 return
382
379
383 self.log.debug("Running startup files from %s...", startup_dir)
380 self.log.debug("Running startup files from %s...", startup_dir)
384 try:
381 try:
385 for fname in sorted(startup_files):
382 for fname in sorted(startup_files):
386 self._exec_file(fname)
383 self._exec_file(fname)
387 except:
384 except:
388 self.log.warning("Unknown error in handling startup files:")
385 self.log.warning("Unknown error in handling startup files:")
389 self.shell.showtraceback()
386 self.shell.showtraceback()
390
387
391 def _run_exec_files(self):
388 def _run_exec_files(self):
392 """Run files from IPythonApp.exec_files"""
389 """Run files from IPythonApp.exec_files"""
393 if not self.exec_files:
390 if not self.exec_files:
394 return
391 return
395
392
396 self.log.debug("Running files in IPythonApp.exec_files...")
393 self.log.debug("Running files in IPythonApp.exec_files...")
397 try:
394 try:
398 for fname in self.exec_files:
395 for fname in self.exec_files:
399 self._exec_file(fname)
396 self._exec_file(fname)
400 except:
397 except:
401 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
398 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
402 self.shell.showtraceback()
399 self.shell.showtraceback()
403
400
404 def _run_cmd_line_code(self):
401 def _run_cmd_line_code(self):
405 """Run code or file specified at the command-line"""
402 """Run code or file specified at the command-line"""
406 if self.code_to_run:
403 if self.code_to_run:
407 line = self.code_to_run
404 line = self.code_to_run
408 try:
405 try:
409 self.log.info("Running code given at command line (c=): %s" %
406 self.log.info("Running code given at command line (c=): %s" %
410 line)
407 line)
411 self.shell.run_cell(line, store_history=False)
408 self.shell.run_cell(line, store_history=False)
412 except:
409 except:
413 self.log.warning("Error in executing line in user namespace: %s" %
410 self.log.warning("Error in executing line in user namespace: %s" %
414 line)
411 line)
415 self.shell.showtraceback()
412 self.shell.showtraceback()
416 if not self.interact:
413 if not self.interact:
417 self.exit(1)
414 self.exit(1)
418
415
419 # Like Python itself, ignore the second if the first of these is present
416 # Like Python itself, ignore the second if the first of these is present
420 elif self.file_to_run:
417 elif self.file_to_run:
421 fname = self.file_to_run
418 fname = self.file_to_run
422 try:
419 try:
423 self._exec_file(fname, shell_futures=True)
420 self._exec_file(fname, shell_futures=True)
424 except:
421 except:
425 self.shell.showtraceback(tb_offset=4)
422 self.shell.showtraceback(tb_offset=4)
426 if not self.interact:
423 if not self.interact:
427 self.exit(1)
424 self.exit(1)
428
425
429 def _run_module(self):
426 def _run_module(self):
430 """Run module specified at the command-line."""
427 """Run module specified at the command-line."""
431 if self.module_to_run:
428 if self.module_to_run:
432 # Make sure that the module gets a proper sys.argv as if it were
429 # Make sure that the module gets a proper sys.argv as if it were
433 # run using `python -m`.
430 # run using `python -m`.
434 save_argv = sys.argv
431 save_argv = sys.argv
435 sys.argv = [sys.executable] + self.extra_args
432 sys.argv = [sys.executable] + self.extra_args
436 try:
433 try:
437 self.shell.safe_run_module(self.module_to_run,
434 self.shell.safe_run_module(self.module_to_run,
438 self.shell.user_ns)
435 self.shell.user_ns)
439 finally:
436 finally:
440 sys.argv = save_argv
437 sys.argv = save_argv
@@ -1,241 +1,228 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 %store magic for lightweight persistence.
3 %store magic for lightweight persistence.
4
4
5 Stores variables, aliases and macros in IPython's database.
5 Stores variables, aliases and macros in IPython's database.
6
6
7 To automatically restore stored variables at startup, add this to your
7 To automatically restore stored variables at startup, add this to your
8 :file:`ipython_config.py` file::
8 :file:`ipython_config.py` file::
9
9
10 c.StoreMagics.autorestore = True
10 c.StoreMagics.autorestore = True
11 """
11 """
12 from __future__ import print_function
12 from __future__ import print_function
13 #-----------------------------------------------------------------------------
13
14 # Copyright (c) 2012, The IPython Development Team.
14 # Copyright (c) IPython Development Team.
15 #
15 # Distributed under the terms of the Modified BSD License.
16 # Distributed under the terms of the Modified BSD License.
16
17 #
18 # The full license is in the file COPYING.txt, distributed with this software.
19 #-----------------------------------------------------------------------------
20
21 #-----------------------------------------------------------------------------
22 # Imports
23 #-----------------------------------------------------------------------------
24
25 # Stdlib
26 import inspect, os, sys, textwrap
17 import inspect, os, sys, textwrap
27
18
28 # Our own
29 from IPython.core.error import UsageError
19 from IPython.core.error import UsageError
30 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.core.magic import Magics, magics_class, line_magic
31 from traitlets import Bool
21 from traitlets import Bool
32 from IPython.utils.py3compat import string_types
22 from IPython.utils.py3compat import string_types
33
23
34 #-----------------------------------------------------------------------------
35 # Functions and classes
36 #-----------------------------------------------------------------------------
37
24
38 def restore_aliases(ip):
25 def restore_aliases(ip):
39 staliases = ip.db.get('stored_aliases', {})
26 staliases = ip.db.get('stored_aliases', {})
40 for k,v in staliases.items():
27 for k,v in staliases.items():
41 #print "restore alias",k,v # dbg
28 #print "restore alias",k,v # dbg
42 #self.alias_table[k] = v
29 #self.alias_table[k] = v
43 ip.alias_manager.define_alias(k,v)
30 ip.alias_manager.define_alias(k,v)
44
31
45
32
46 def refresh_variables(ip):
33 def refresh_variables(ip):
47 db = ip.db
34 db = ip.db
48 for key in db.keys('autorestore/*'):
35 for key in db.keys('autorestore/*'):
49 # strip autorestore
36 # strip autorestore
50 justkey = os.path.basename(key)
37 justkey = os.path.basename(key)
51 try:
38 try:
52 obj = db[key]
39 obj = db[key]
53 except KeyError:
40 except KeyError:
54 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
41 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
55 print("The error was:", sys.exc_info()[0])
42 print("The error was:", sys.exc_info()[0])
56 else:
43 else:
57 #print "restored",justkey,"=",obj #dbg
44 #print "restored",justkey,"=",obj #dbg
58 ip.user_ns[justkey] = obj
45 ip.user_ns[justkey] = obj
59
46
60
47
61 def restore_dhist(ip):
48 def restore_dhist(ip):
62 ip.user_ns['_dh'] = ip.db.get('dhist',[])
49 ip.user_ns['_dh'] = ip.db.get('dhist',[])
63
50
64
51
65 def restore_data(ip):
52 def restore_data(ip):
66 refresh_variables(ip)
53 refresh_variables(ip)
67 restore_aliases(ip)
54 restore_aliases(ip)
68 restore_dhist(ip)
55 restore_dhist(ip)
69
56
70
57
71 @magics_class
58 @magics_class
72 class StoreMagics(Magics):
59 class StoreMagics(Magics):
73 """Lightweight persistence for python variables.
60 """Lightweight persistence for python variables.
74
61
75 Provides the %store magic."""
62 Provides the %store magic."""
76
63
77 autorestore = Bool(False, config=True, help=
64 autorestore = Bool(False, help=
78 """If True, any %store-d variables will be automatically restored
65 """If True, any %store-d variables will be automatically restored
79 when IPython starts.
66 when IPython starts.
80 """
67 """
81 )
68 ).tag(config=True)
82
69
83 def __init__(self, shell):
70 def __init__(self, shell):
84 super(StoreMagics, self).__init__(shell=shell)
71 super(StoreMagics, self).__init__(shell=shell)
85 self.shell.configurables.append(self)
72 self.shell.configurables.append(self)
86 if self.autorestore:
73 if self.autorestore:
87 restore_data(self.shell)
74 restore_data(self.shell)
88
75
89 @line_magic
76 @line_magic
90 def store(self, parameter_s=''):
77 def store(self, parameter_s=''):
91 """Lightweight persistence for python variables.
78 """Lightweight persistence for python variables.
92
79
93 Example::
80 Example::
94
81
95 In [1]: l = ['hello',10,'world']
82 In [1]: l = ['hello',10,'world']
96 In [2]: %store l
83 In [2]: %store l
97 In [3]: exit
84 In [3]: exit
98
85
99 (IPython session is closed and started again...)
86 (IPython session is closed and started again...)
100
87
101 ville@badger:~$ ipython
88 ville@badger:~$ ipython
102 In [1]: l
89 In [1]: l
103 NameError: name 'l' is not defined
90 NameError: name 'l' is not defined
104 In [2]: %store -r
91 In [2]: %store -r
105 In [3]: l
92 In [3]: l
106 Out[3]: ['hello', 10, 'world']
93 Out[3]: ['hello', 10, 'world']
107
94
108 Usage:
95 Usage:
109
96
110 * ``%store`` - Show list of all variables and their current
97 * ``%store`` - Show list of all variables and their current
111 values
98 values
112 * ``%store spam`` - Store the *current* value of the variable spam
99 * ``%store spam`` - Store the *current* value of the variable spam
113 to disk
100 to disk
114 * ``%store -d spam`` - Remove the variable and its value from storage
101 * ``%store -d spam`` - Remove the variable and its value from storage
115 * ``%store -z`` - Remove all variables from storage
102 * ``%store -z`` - Remove all variables from storage
116 * ``%store -r`` - Refresh all variables from store (overwrite
103 * ``%store -r`` - Refresh all variables from store (overwrite
117 current vals)
104 current vals)
118 * ``%store -r spam bar`` - Refresh specified variables from store
105 * ``%store -r spam bar`` - Refresh specified variables from store
119 (delete current val)
106 (delete current val)
120 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
107 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
121 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
108 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
122
109
123 It should be noted that if you change the value of a variable, you
110 It should be noted that if you change the value of a variable, you
124 need to %store it again if you want to persist the new value.
111 need to %store it again if you want to persist the new value.
125
112
126 Note also that the variables will need to be pickleable; most basic
113 Note also that the variables will need to be pickleable; most basic
127 python types can be safely %store'd.
114 python types can be safely %store'd.
128
115
129 Also aliases can be %store'd across sessions.
116 Also aliases can be %store'd across sessions.
130 """
117 """
131
118
132 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
119 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
133 args = argsl.split(None,1)
120 args = argsl.split(None,1)
134 ip = self.shell
121 ip = self.shell
135 db = ip.db
122 db = ip.db
136 # delete
123 # delete
137 if 'd' in opts:
124 if 'd' in opts:
138 try:
125 try:
139 todel = args[0]
126 todel = args[0]
140 except IndexError:
127 except IndexError:
141 raise UsageError('You must provide the variable to forget')
128 raise UsageError('You must provide the variable to forget')
142 else:
129 else:
143 try:
130 try:
144 del db['autorestore/' + todel]
131 del db['autorestore/' + todel]
145 except:
132 except:
146 raise UsageError("Can't delete variable '%s'" % todel)
133 raise UsageError("Can't delete variable '%s'" % todel)
147 # reset
134 # reset
148 elif 'z' in opts:
135 elif 'z' in opts:
149 for k in db.keys('autorestore/*'):
136 for k in db.keys('autorestore/*'):
150 del db[k]
137 del db[k]
151
138
152 elif 'r' in opts:
139 elif 'r' in opts:
153 if args:
140 if args:
154 for arg in args:
141 for arg in args:
155 try:
142 try:
156 obj = db['autorestore/' + arg]
143 obj = db['autorestore/' + arg]
157 except KeyError:
144 except KeyError:
158 print("no stored variable %s" % arg)
145 print("no stored variable %s" % arg)
159 else:
146 else:
160 ip.user_ns[arg] = obj
147 ip.user_ns[arg] = obj
161 else:
148 else:
162 restore_data(ip)
149 restore_data(ip)
163
150
164 # run without arguments -> list variables & values
151 # run without arguments -> list variables & values
165 elif not args:
152 elif not args:
166 vars = db.keys('autorestore/*')
153 vars = db.keys('autorestore/*')
167 vars.sort()
154 vars.sort()
168 if vars:
155 if vars:
169 size = max(map(len, vars))
156 size = max(map(len, vars))
170 else:
157 else:
171 size = 0
158 size = 0
172
159
173 print('Stored variables and their in-db values:')
160 print('Stored variables and their in-db values:')
174 fmt = '%-'+str(size)+'s -> %s'
161 fmt = '%-'+str(size)+'s -> %s'
175 get = db.get
162 get = db.get
176 for var in vars:
163 for var in vars:
177 justkey = os.path.basename(var)
164 justkey = os.path.basename(var)
178 # print 30 first characters from every var
165 # print 30 first characters from every var
179 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
166 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
180
167
181 # default action - store the variable
168 # default action - store the variable
182 else:
169 else:
183 # %store foo >file.txt or >>file.txt
170 # %store foo >file.txt or >>file.txt
184 if len(args) > 1 and args[1].startswith('>'):
171 if len(args) > 1 and args[1].startswith('>'):
185 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
172 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
186 if args[1].startswith('>>'):
173 if args[1].startswith('>>'):
187 fil = open(fnam, 'a')
174 fil = open(fnam, 'a')
188 else:
175 else:
189 fil = open(fnam, 'w')
176 fil = open(fnam, 'w')
190 obj = ip.ev(args[0])
177 obj = ip.ev(args[0])
191 print("Writing '%s' (%s) to file '%s'." % (args[0],
178 print("Writing '%s' (%s) to file '%s'." % (args[0],
192 obj.__class__.__name__, fnam))
179 obj.__class__.__name__, fnam))
193
180
194
181
195 if not isinstance (obj, string_types):
182 if not isinstance (obj, string_types):
196 from pprint import pprint
183 from pprint import pprint
197 pprint(obj, fil)
184 pprint(obj, fil)
198 else:
185 else:
199 fil.write(obj)
186 fil.write(obj)
200 if not obj.endswith('\n'):
187 if not obj.endswith('\n'):
201 fil.write('\n')
188 fil.write('\n')
202
189
203 fil.close()
190 fil.close()
204 return
191 return
205
192
206 # %store foo
193 # %store foo
207 try:
194 try:
208 obj = ip.user_ns[args[0]]
195 obj = ip.user_ns[args[0]]
209 except KeyError:
196 except KeyError:
210 # it might be an alias
197 # it might be an alias
211 name = args[0]
198 name = args[0]
212 try:
199 try:
213 cmd = ip.alias_manager.retrieve_alias(name)
200 cmd = ip.alias_manager.retrieve_alias(name)
214 except ValueError:
201 except ValueError:
215 raise UsageError("Unknown variable '%s'" % name)
202 raise UsageError("Unknown variable '%s'" % name)
216
203
217 staliases = db.get('stored_aliases',{})
204 staliases = db.get('stored_aliases',{})
218 staliases[name] = cmd
205 staliases[name] = cmd
219 db['stored_aliases'] = staliases
206 db['stored_aliases'] = staliases
220 print("Alias stored: %s (%s)" % (name, cmd))
207 print("Alias stored: %s (%s)" % (name, cmd))
221 return
208 return
222
209
223 else:
210 else:
224 modname = getattr(inspect.getmodule(obj), '__name__', '')
211 modname = getattr(inspect.getmodule(obj), '__name__', '')
225 if modname == '__main__':
212 if modname == '__main__':
226 print(textwrap.dedent("""\
213 print(textwrap.dedent("""\
227 Warning:%s is %s
214 Warning:%s is %s
228 Proper storage of interactively declared classes (or instances
215 Proper storage of interactively declared classes (or instances
229 of those classes) is not possible! Only instances
216 of those classes) is not possible! Only instances
230 of classes in real modules on file system can be %%store'd.
217 of classes in real modules on file system can be %%store'd.
231 """ % (args[0], obj) ))
218 """ % (args[0], obj) ))
232 return
219 return
233 #pickled = pickle.dumps(obj)
220 #pickled = pickle.dumps(obj)
234 db[ 'autorestore/' + args[0] ] = obj
221 db[ 'autorestore/' + args[0] ] = obj
235 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
222 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
236
223
237
224
238 def load_ipython_extension(ip):
225 def load_ipython_extension(ip):
239 """Load the extension in IPython."""
226 """Load the extension in IPython."""
240 ip.register_magics(StoreMagics)
227 ip.register_magics(StoreMagics)
241
228
@@ -1,368 +1,371 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 import warnings
17
18
18 from traitlets.config.loader import Config
19 from traitlets.config.loader import Config
19 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 from IPython.core import release
21 from IPython.core import release
21 from IPython.core import usage
22 from IPython.core import usage
22 from IPython.core.completer import IPCompleter
23 from IPython.core.completer import IPCompleter
23 from IPython.core.crashhandler import CrashHandler
24 from IPython.core.crashhandler import CrashHandler
24 from IPython.core.formatters import PlainTextFormatter
25 from IPython.core.formatters import PlainTextFormatter
25 from IPython.core.history import HistoryManager
26 from IPython.core.history import HistoryManager
26 from IPython.core.prompts import PromptManager
27 from IPython.core.prompts import PromptManager
27 from IPython.core.application import (
28 from IPython.core.application import (
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 )
30 )
30 from IPython.core.magics import ScriptMagics
31 from IPython.core.magics import ScriptMagics
31 from IPython.core.shellapp import (
32 from IPython.core.shellapp import (
32 InteractiveShellApp, shell_flags, shell_aliases
33 InteractiveShellApp, shell_flags, shell_aliases
33 )
34 )
34 from IPython.extensions.storemagic import StoreMagics
35 from IPython.extensions.storemagic import StoreMagics
35 from .ptshell import TerminalInteractiveShell
36 from .ptshell import TerminalInteractiveShell
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, default, observe,
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 @default('classes')
186 def _classes_default(self):
187 def _classes_default(self):
187 """This has to be in a method, for TerminalIPythonApp to be available."""
188 """This has to be in a method, for TerminalIPythonApp to be available."""
188 return [
189 return [
189 InteractiveShellApp, # ShellApp comes before TerminalApp, because
190 InteractiveShellApp, # ShellApp comes before TerminalApp, because
190 self.__class__, # it will also affect subclasses (e.g. QtConsole)
191 self.__class__, # it will also affect subclasses (e.g. QtConsole)
191 TerminalInteractiveShell,
192 TerminalInteractiveShell,
192 PromptManager,
193 PromptManager,
193 HistoryManager,
194 HistoryManager,
194 ProfileDir,
195 ProfileDir,
195 PlainTextFormatter,
196 PlainTextFormatter,
196 IPCompleter,
197 IPCompleter,
197 ScriptMagics,
198 ScriptMagics,
198 StoreMagics,
199 StoreMagics,
199 ]
200 ]
200
201
201 deprecated_subcommands = dict(
202 deprecated_subcommands = dict(
202 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
203 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
203 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
204 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
204 ),
205 ),
205 notebook=('notebook.notebookapp.NotebookApp',
206 notebook=('notebook.notebookapp.NotebookApp',
206 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
207 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
207 ),
208 ),
208 console=('jupyter_console.app.ZMQTerminalIPythonApp',
209 console=('jupyter_console.app.ZMQTerminalIPythonApp',
209 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
210 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
210 ),
211 ),
211 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
212 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
212 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
213 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
213 ),
214 ),
214 trust=('nbformat.sign.TrustNotebookApp',
215 trust=('nbformat.sign.TrustNotebookApp',
215 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
216 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
216 ),
217 ),
217 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
218 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
218 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
219 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
219 ),
220 ),
220 )
221 )
221 subcommands = dict(
222 subcommands = dict(
222 profile = ("IPython.core.profileapp.ProfileApp",
223 profile = ("IPython.core.profileapp.ProfileApp",
223 "Create and manage IPython profiles."
224 "Create and manage IPython profiles."
224 ),
225 ),
225 kernel = ("ipykernel.kernelapp.IPKernelApp",
226 kernel = ("ipykernel.kernelapp.IPKernelApp",
226 "Start a kernel without an attached frontend."
227 "Start a kernel without an attached frontend."
227 ),
228 ),
228 locate=('IPython.terminal.ipapp.LocateIPythonApp',
229 locate=('IPython.terminal.ipapp.LocateIPythonApp',
229 LocateIPythonApp.description
230 LocateIPythonApp.description
230 ),
231 ),
231 history=('IPython.core.historyapp.HistoryApp',
232 history=('IPython.core.historyapp.HistoryApp',
232 "Manage the IPython history database."
233 "Manage the IPython history database."
233 ),
234 ),
234 )
235 )
235 deprecated_subcommands['install-nbextension'] = (
236 deprecated_subcommands['install-nbextension'] = (
236 "notebook.nbextensions.InstallNBExtensionApp",
237 "notebook.nbextensions.InstallNBExtensionApp",
237 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
238 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
238 )
239 )
239 subcommands.update(deprecated_subcommands)
240 subcommands.update(deprecated_subcommands)
240
241
241 # *do* autocreate requested profile, but don't create the config file.
242 # *do* autocreate requested profile, but don't create the config file.
242 auto_create=Bool(True)
243 auto_create=Bool(True)
243 # configurables
244 # configurables
244 quick = Bool(False, config=True,
245 quick = Bool(False,
245 help="""Start IPython quickly by skipping the loading of config files."""
246 help="""Start IPython quickly by skipping the loading of config files."""
246 )
247 ).tag(config=True)
247 def _quick_changed(self, name, old, new):
248 @observe('quick')
248 if new:
249 def _quick_changed(self, change):
250 if change['new']:
249 self.load_config_file = lambda *a, **kw: None
251 self.load_config_file = lambda *a, **kw: None
250
252
251 display_banner = Bool(True, config=True,
253 display_banner = Bool(True,
252 help="Whether to display a banner upon starting IPython."
254 help="Whether to display a banner upon starting IPython."
253 )
255 ).tag(config=True)
254
256
255 # if there is code of files to run from the cmd line, don't interact
257 # 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.
258 # unless the --i flag (App.force_interact) is true.
257 force_interact = Bool(False, config=True,
259 force_interact = Bool(False,
258 help="""If a command or file is given via the command-line,
260 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
261 e.g. 'ipython foo.py', start an interactive shell after executing the
260 file or command."""
262 file or command."""
261 )
263 ).tag(config=True)
262 def _force_interact_changed(self, name, old, new):
264 @observe('force_interact')
263 if new:
265 def _force_interact_changed(self, change):
266 if change['new']:
264 self.interact = True
267 self.interact = True
265
268
266 def _file_to_run_changed(self, name, old, new):
269 @observe('file_to_run', 'code_to_run', 'module_to_run')
270 def _file_to_run_changed(self, change):
271 new = change['new']
267 if new:
272 if new:
268 self.something_to_run = True
273 self.something_to_run = True
269 if new and not self.force_interact:
274 if new and not self.force_interact:
270 self.interact = False
275 self.interact = False
271 _code_to_run_changed = _file_to_run_changed
272 _module_to_run_changed = _file_to_run_changed
273
276
274 # internal, not-configurable
277 # internal, not-configurable
275 something_to_run=Bool(False)
278 something_to_run=Bool(False)
276
279
277 def parse_command_line(self, argv=None):
280 def parse_command_line(self, argv=None):
278 """override to allow old '-pylab' flag with deprecation warning"""
281 """override to allow old '-pylab' flag with deprecation warning"""
279
282
280 argv = sys.argv[1:] if argv is None else argv
283 argv = sys.argv[1:] if argv is None else argv
281
284
282 if '-pylab' in argv:
285 if '-pylab' in argv:
283 # deprecated `-pylab` given,
286 # deprecated `-pylab` given,
284 # warn and transform into current syntax
287 # warn and transform into current syntax
285 argv = argv[:] # copy, don't clobber
288 argv = argv[:] # copy, don't clobber
286 idx = argv.index('-pylab')
289 idx = argv.index('-pylab')
287 warn.warn("`-pylab` flag has been deprecated.\n"
290 warnings.warn("`-pylab` flag has been deprecated.\n"
288 " Use `--matplotlib <backend>` and import pylab manually.")
291 " Use `--matplotlib <backend>` and import pylab manually.")
289 argv[idx] = '--pylab'
292 argv[idx] = '--pylab'
290
293
291 return super(TerminalIPythonApp, self).parse_command_line(argv)
294 return super(TerminalIPythonApp, self).parse_command_line(argv)
292
295
293 @catch_config_error
296 @catch_config_error
294 def initialize(self, argv=None):
297 def initialize(self, argv=None):
295 """Do actions after construct, but before starting the app."""
298 """Do actions after construct, but before starting the app."""
296 super(TerminalIPythonApp, self).initialize(argv)
299 super(TerminalIPythonApp, self).initialize(argv)
297 if self.subapp is not None:
300 if self.subapp is not None:
298 # don't bother initializing further, starting subapp
301 # don't bother initializing further, starting subapp
299 return
302 return
300 # print self.extra_args
303 # print self.extra_args
301 if self.extra_args and not self.something_to_run:
304 if self.extra_args and not self.something_to_run:
302 self.file_to_run = self.extra_args[0]
305 self.file_to_run = self.extra_args[0]
303 self.init_path()
306 self.init_path()
304 # create the shell
307 # create the shell
305 self.init_shell()
308 self.init_shell()
306 # and draw the banner
309 # and draw the banner
307 self.init_banner()
310 self.init_banner()
308 # Now a variety of things that happen after the banner is printed.
311 # Now a variety of things that happen after the banner is printed.
309 self.init_gui_pylab()
312 self.init_gui_pylab()
310 self.init_extensions()
313 self.init_extensions()
311 self.init_code()
314 self.init_code()
312
315
313 def init_shell(self):
316 def init_shell(self):
314 """initialize the InteractiveShell instance"""
317 """initialize the InteractiveShell instance"""
315 # Create an InteractiveShell instance.
318 # Create an InteractiveShell instance.
316 # shell.display_banner should always be False for the terminal
319 # shell.display_banner should always be False for the terminal
317 # based app, because we call shell.show_banner() by hand below
320 # based app, because we call shell.show_banner() by hand below
318 # so the banner shows *before* all extension loading stuff.
321 # so the banner shows *before* all extension loading stuff.
319 self.shell = TerminalInteractiveShell.instance(parent=self,
322 self.shell = TerminalInteractiveShell.instance(parent=self,
320 profile_dir=self.profile_dir,
323 profile_dir=self.profile_dir,
321 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
324 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
322 self.shell.configurables.append(self)
325 self.shell.configurables.append(self)
323
326
324 def init_banner(self):
327 def init_banner(self):
325 """optionally display the banner"""
328 """optionally display the banner"""
326 if self.display_banner and self.interact:
329 if self.display_banner and self.interact:
327 self.shell.show_banner()
330 self.shell.show_banner()
328 # Make sure there is a space below the banner.
331 # Make sure there is a space below the banner.
329 if self.log_level <= logging.INFO: print()
332 if self.log_level <= logging.INFO: print()
330
333
331 def _pylab_changed(self, name, old, new):
334 def _pylab_changed(self, name, old, new):
332 """Replace --pylab='inline' with --pylab='auto'"""
335 """Replace --pylab='inline' with --pylab='auto'"""
333 if new == 'inline':
336 if new == 'inline':
334 warn.warn("'inline' not available as pylab backend, "
337 warnings.warn("'inline' not available as pylab backend, "
335 "using 'auto' instead.")
338 "using 'auto' instead.")
336 self.pylab = 'auto'
339 self.pylab = 'auto'
337
340
338 def start(self):
341 def start(self):
339 if self.subapp is not None:
342 if self.subapp is not None:
340 return self.subapp.start()
343 return self.subapp.start()
341 # perform any prexec steps:
344 # perform any prexec steps:
342 if self.interact:
345 if self.interact:
343 self.log.debug("Starting IPython's mainloop...")
346 self.log.debug("Starting IPython's mainloop...")
344 self.shell.mainloop()
347 self.shell.mainloop()
345 else:
348 else:
346 self.log.debug("IPython not interactive...")
349 self.log.debug("IPython not interactive...")
347
350
348 def load_default_config(ipython_dir=None):
351 def load_default_config(ipython_dir=None):
349 """Load the default config file from the default ipython_dir.
352 """Load the default config file from the default ipython_dir.
350
353
351 This is useful for embedded shells.
354 This is useful for embedded shells.
352 """
355 """
353 if ipython_dir is None:
356 if ipython_dir is None:
354 ipython_dir = get_ipython_dir()
357 ipython_dir = get_ipython_dir()
355
358
356 profile_dir = os.path.join(ipython_dir, 'profile_default')
359 profile_dir = os.path.join(ipython_dir, 'profile_default')
357
360
358 config = Config()
361 config = Config()
359 for cf in Application._load_config_files("ipython_config", path=profile_dir):
362 for cf in Application._load_config_files("ipython_config", path=profile_dir):
360 config.update(cf)
363 config.update(cf)
361
364
362 return config
365 return config
363
366
364 launch_new_instance = TerminalIPythonApp.launch_instance
367 launch_new_instance = TerminalIPythonApp.launch_instance
365
368
366
369
367 if __name__ == '__main__':
370 if __name__ == '__main__':
368 launch_new_instance()
371 launch_new_instance()
@@ -1,464 +1,467 b''
1 """IPython terminal interface using prompt_toolkit in place of readline"""
1 """IPython terminal interface using prompt_toolkit in place of readline"""
2 from __future__ import print_function
2 from __future__ import print_function
3
3
4 import os
4 import os
5 import sys
5 import sys
6 import signal
6 import signal
7 import unicodedata
7 import unicodedata
8 from warnings import warn
8 from warnings import warn
9 from wcwidth import wcwidth
9 from wcwidth import wcwidth
10
10
11 from IPython.core.error import TryNext
11 from IPython.core.error import TryNext
12 from IPython.core.interactiveshell import InteractiveShell
12 from IPython.core.interactiveshell import InteractiveShell
13 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
13 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
14 from IPython.utils.terminal import toggle_set_term_title, set_term_title
14 from IPython.utils.terminal import toggle_set_term_title, set_term_title
15 from IPython.utils.process import abbrev_cwd
15 from IPython.utils.process import abbrev_cwd
16 from traitlets import Bool, CBool, Unicode, Dict, Integer, observe
16 from traitlets import Bool, Unicode, Dict, Integer, observe
17
17
18 from prompt_toolkit.completion import Completer, Completion
18 from prompt_toolkit.completion import Completer, Completion
19 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
19 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
20 from prompt_toolkit.filters import HasFocus, HasSelection, Condition, ViInsertMode, EmacsInsertMode
20 from prompt_toolkit.filters import HasFocus, HasSelection, Condition, ViInsertMode, EmacsInsertMode
21 from prompt_toolkit.history import InMemoryHistory
21 from prompt_toolkit.history import InMemoryHistory
22 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
22 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
23 from prompt_toolkit.interface import CommandLineInterface
23 from prompt_toolkit.interface import CommandLineInterface
24 from prompt_toolkit.key_binding.manager import KeyBindingManager
24 from prompt_toolkit.key_binding.manager import KeyBindingManager
25 from prompt_toolkit.keys import Keys
25 from prompt_toolkit.keys import Keys
26 from prompt_toolkit.layout.lexers import Lexer
26 from prompt_toolkit.layout.lexers import Lexer
27 from prompt_toolkit.layout.lexers import PygmentsLexer
27 from prompt_toolkit.layout.lexers import PygmentsLexer
28 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
28 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
29
29
30 from pygments.styles import get_style_by_name, get_all_styles
30 from pygments.styles import get_style_by_name, get_all_styles
31 from pygments.lexers import Python3Lexer, BashLexer, PythonLexer
31 from pygments.lexers import Python3Lexer, BashLexer, PythonLexer
32 from pygments.token import Token
32 from pygments.token import Token
33
33
34 from .pt_inputhooks import get_inputhook_func
34 from .pt_inputhooks import get_inputhook_func
35 from .interactiveshell import get_default_editor, TerminalMagics
35 from .interactiveshell import get_default_editor, TerminalMagics
36
36
37
37
38 class IPythonPTCompleter(Completer):
38 class IPythonPTCompleter(Completer):
39 """Adaptor to provide IPython completions to prompt_toolkit"""
39 """Adaptor to provide IPython completions to prompt_toolkit"""
40 def __init__(self, ipy_completer):
40 def __init__(self, ipy_completer):
41 self.ipy_completer = ipy_completer
41 self.ipy_completer = ipy_completer
42
42
43 def get_completions(self, document, complete_event):
43 def get_completions(self, document, complete_event):
44 if not document.current_line.strip():
44 if not document.current_line.strip():
45 return
45 return
46
46
47 used, matches = self.ipy_completer.complete(
47 used, matches = self.ipy_completer.complete(
48 line_buffer=document.current_line,
48 line_buffer=document.current_line,
49 cursor_pos=document.cursor_position_col
49 cursor_pos=document.cursor_position_col
50 )
50 )
51 start_pos = -len(used)
51 start_pos = -len(used)
52 for m in matches:
52 for m in matches:
53 m = unicodedata.normalize('NFC', m)
53 m = unicodedata.normalize('NFC', m)
54
54
55 # When the first character of the completion has a zero length,
55 # When the first character of the completion has a zero length,
56 # then it's probably a decomposed unicode character. E.g. caused by
56 # then it's probably a decomposed unicode character. E.g. caused by
57 # the "\dot" completion. Try to compose again with the previous
57 # the "\dot" completion. Try to compose again with the previous
58 # character.
58 # character.
59 if wcwidth(m[0]) == 0:
59 if wcwidth(m[0]) == 0:
60 if document.cursor_position + start_pos > 0:
60 if document.cursor_position + start_pos > 0:
61 char_before = document.text[document.cursor_position + start_pos - 1]
61 char_before = document.text[document.cursor_position + start_pos - 1]
62 m = unicodedata.normalize('NFC', char_before + m)
62 m = unicodedata.normalize('NFC', char_before + m)
63
63
64 # Yield the modified completion instead, if this worked.
64 # Yield the modified completion instead, if this worked.
65 if wcwidth(m[0:1]) == 1:
65 if wcwidth(m[0:1]) == 1:
66 yield Completion(m, start_position=start_pos - 1)
66 yield Completion(m, start_position=start_pos - 1)
67 continue
67 continue
68
68
69 # TODO: Use Jedi to determine meta_text
69 # TODO: Use Jedi to determine meta_text
70 # (Jedi currently has a bug that results in incorrect information.)
70 # (Jedi currently has a bug that results in incorrect information.)
71 # meta_text = ''
71 # meta_text = ''
72 # yield Completion(m, start_position=start_pos,
72 # yield Completion(m, start_position=start_pos,
73 # display_meta=meta_text)
73 # display_meta=meta_text)
74 yield Completion(m, start_position=start_pos)
74 yield Completion(m, start_position=start_pos)
75
75
76 class IPythonPTLexer(Lexer):
76 class IPythonPTLexer(Lexer):
77 """
77 """
78 Wrapper around PythonLexer and BashLexer.
78 Wrapper around PythonLexer and BashLexer.
79 """
79 """
80 def __init__(self):
80 def __init__(self):
81 self.python_lexer = PygmentsLexer(Python3Lexer if PY3 else PythonLexer)
81 self.python_lexer = PygmentsLexer(Python3Lexer if PY3 else PythonLexer)
82 self.shell_lexer = PygmentsLexer(BashLexer)
82 self.shell_lexer = PygmentsLexer(BashLexer)
83
83
84 def lex_document(self, cli, document):
84 def lex_document(self, cli, document):
85 if document.text.startswith('!'):
85 if document.text.startswith('!'):
86 return self.shell_lexer.lex_document(cli, document)
86 return self.shell_lexer.lex_document(cli, document)
87 else:
87 else:
88 return self.python_lexer.lex_document(cli, document)
88 return self.python_lexer.lex_document(cli, document)
89
89
90
90
91 class TerminalInteractiveShell(InteractiveShell):
91 class TerminalInteractiveShell(InteractiveShell):
92 colors_force = True
92 colors_force = True
93
93
94 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
94 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
95 'to reserve for the completion menu'
95 'to reserve for the completion menu'
96 ).tag(config=True)
96 ).tag(config=True)
97
97
98 def _space_for_menu_changed(self, old, new):
98 def _space_for_menu_changed(self, old, new):
99 self._update_layout()
99 self._update_layout()
100
100
101 pt_cli = None
101 pt_cli = None
102
102
103 autoedit_syntax = CBool(False).tag(config=True,
103 autoedit_syntax = Bool(False,
104 help="auto editing of files with syntax errors.")
104 help="auto editing of files with syntax errors.",
105 ).tag(config=True)
106
105
107
106 confirm_exit = CBool(True).tag(config=True,
108 confirm_exit = Bool(True,
107 help="""
109 help="""
108 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
109 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',
110 you can force a direct exit without any confirmation.""",
112 you can force a direct exit without any confirmation.""",
111 )
113 ).tag(config=True)
114
112 editing_mode = Unicode('emacs',
115 editing_mode = Unicode('emacs',
113 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
116 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
114 ).tag(config=True)
117 ).tag(config=True)
115
118
116 mouse_support = Bool(False,
119 mouse_support = Bool(False,
117 help="Enable mouse support in the prompt"
120 help="Enable mouse support in the prompt"
118 ).tag(config=True)
121 ).tag(config=True)
119
122
120 highlighting_style = Unicode('default',
123 highlighting_style = Unicode('default',
121 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
124 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
122 ).tag(config=True)
125 ).tag(config=True)
123
126
124 def _highlighting_style_changed(self, old, new):
127
128 @observe('highlighting_style')
129 def _highlighting_style_changed(self, change):
125 self._style = self._make_style_from_name(self.highlighting_style)
130 self._style = self._make_style_from_name(self.highlighting_style)
126
131
127 highlighting_style_overrides = Dict(
132 highlighting_style_overrides = Dict(
128 help="Override highlighting format for specific tokens"
133 help="Override highlighting format for specific tokens"
129 ).tag(config=True)
134 ).tag(config=True)
130
135
131 editor = Unicode(get_default_editor(),
136 editor = Unicode(get_default_editor(),
132 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
137 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
133 ).tag(config=True)
138 ).tag(config=True)
134
139
135 term_title = Bool(True,
140 term_title = Bool(True,
136 help="Automatically set the terminal title"
141 help="Automatically set the terminal title"
137 ).tag(config=True)
142 ).tag(config=True)
138
143
139 display_completions_in_columns = Bool(False,
144 display_completions_in_columns = Bool(False,
140 help="Display a multi column completion menu.",
145 help="Display a multi column completion menu.",
141 ).tag(config=True)
146 ).tag(config=True)
142
147
143 @observe('term_title')
144 def _term_title_changed(self, change):
145 self.init_term_title()
146
148
147 def init_term_title(self):
149 @observe('term_title')
150 def init_term_title(self, change=None):
148 # Enable or disable the terminal title.
151 # Enable or disable the terminal title.
149 if self.term_title:
152 if self.term_title:
150 toggle_set_term_title(True)
153 toggle_set_term_title(True)
151 set_term_title('IPython: ' + abbrev_cwd())
154 set_term_title('IPython: ' + abbrev_cwd())
152 else:
155 else:
153 toggle_set_term_title(False)
156 toggle_set_term_title(False)
154
157
155 def get_prompt_tokens(self, cli):
158 def get_prompt_tokens(self, cli):
156 return [
159 return [
157 (Token.Prompt, 'In ['),
160 (Token.Prompt, 'In ['),
158 (Token.PromptNum, str(self.execution_count)),
161 (Token.PromptNum, str(self.execution_count)),
159 (Token.Prompt, ']: '),
162 (Token.Prompt, ']: '),
160 ]
163 ]
161
164
162 def get_continuation_tokens(self, cli, width):
165 def get_continuation_tokens(self, cli, width):
163 return [
166 return [
164 (Token.Prompt, (' ' * (width - 5)) + '...: '),
167 (Token.Prompt, (' ' * (width - 5)) + '...: '),
165 ]
168 ]
166
169
167 def init_prompt_toolkit_cli(self):
170 def init_prompt_toolkit_cli(self):
168 if ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or not sys.stdin.isatty():
171 if ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or not sys.stdin.isatty():
169 # Fall back to plain non-interactive output for tests.
172 # Fall back to plain non-interactive output for tests.
170 # This is very limited, and only accepts a single line.
173 # This is very limited, and only accepts a single line.
171 def prompt():
174 def prompt():
172 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
175 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
173 self.prompt_for_code = prompt
176 self.prompt_for_code = prompt
174 return
177 return
175
178
176 kbmanager = KeyBindingManager.for_prompt()
179 kbmanager = KeyBindingManager.for_prompt()
177 insert_mode = ViInsertMode() | EmacsInsertMode()
180 insert_mode = ViInsertMode() | EmacsInsertMode()
178 # Ctrl+J == Enter, seemingly
181 # Ctrl+J == Enter, seemingly
179 @kbmanager.registry.add_binding(Keys.ControlJ,
182 @kbmanager.registry.add_binding(Keys.ControlJ,
180 filter=(HasFocus(DEFAULT_BUFFER)
183 filter=(HasFocus(DEFAULT_BUFFER)
181 & ~HasSelection()
184 & ~HasSelection()
182 & insert_mode
185 & insert_mode
183 ))
186 ))
184 def _(event):
187 def _(event):
185 b = event.current_buffer
188 b = event.current_buffer
186 d = b.document
189 d = b.document
187 if not (d.on_last_line or d.cursor_position_row >= d.line_count
190 if not (d.on_last_line or d.cursor_position_row >= d.line_count
188 - d.empty_line_count_at_the_end()):
191 - d.empty_line_count_at_the_end()):
189 b.newline()
192 b.newline()
190 return
193 return
191
194
192 status, indent = self.input_splitter.check_complete(d.text)
195 status, indent = self.input_splitter.check_complete(d.text)
193
196
194 if (status != 'incomplete') and b.accept_action.is_returnable:
197 if (status != 'incomplete') and b.accept_action.is_returnable:
195 b.accept_action.validate_and_handle(event.cli, b)
198 b.accept_action.validate_and_handle(event.cli, b)
196 else:
199 else:
197 b.insert_text('\n' + (' ' * (indent or 0)))
200 b.insert_text('\n' + (' ' * (indent or 0)))
198
201
199 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
202 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
200 def _reset_buffer(event):
203 def _reset_buffer(event):
201 event.current_buffer.reset()
204 event.current_buffer.reset()
202
205
203 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
206 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
204 def _reset_search_buffer(event):
207 def _reset_search_buffer(event):
205 if event.current_buffer.document.text:
208 if event.current_buffer.document.text:
206 event.current_buffer.reset()
209 event.current_buffer.reset()
207 else:
210 else:
208 event.cli.push_focus(DEFAULT_BUFFER)
211 event.cli.push_focus(DEFAULT_BUFFER)
209
212
210 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
213 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
211
214
212 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
215 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
213 def _suspend_to_bg(event):
216 def _suspend_to_bg(event):
214 event.cli.suspend_to_background()
217 event.cli.suspend_to_background()
215
218
216 @Condition
219 @Condition
217 def cursor_in_leading_ws(cli):
220 def cursor_in_leading_ws(cli):
218 before = cli.application.buffer.document.current_line_before_cursor
221 before = cli.application.buffer.document.current_line_before_cursor
219 return (not before) or before.isspace()
222 return (not before) or before.isspace()
220
223
221 # Ctrl+I == Tab
224 # Ctrl+I == Tab
222 @kbmanager.registry.add_binding(Keys.ControlI,
225 @kbmanager.registry.add_binding(Keys.ControlI,
223 filter=(HasFocus(DEFAULT_BUFFER)
226 filter=(HasFocus(DEFAULT_BUFFER)
224 & ~HasSelection()
227 & ~HasSelection()
225 & insert_mode
228 & insert_mode
226 & cursor_in_leading_ws
229 & cursor_in_leading_ws
227 ))
230 ))
228 def _indent_buffer(event):
231 def _indent_buffer(event):
229 event.current_buffer.insert_text(' ' * 4)
232 event.current_buffer.insert_text(' ' * 4)
230
233
231 # Pre-populate history from IPython's history database
234 # Pre-populate history from IPython's history database
232 history = InMemoryHistory()
235 history = InMemoryHistory()
233 last_cell = u""
236 last_cell = u""
234 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
237 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
235 include_latest=True):
238 include_latest=True):
236 # Ignore blank lines and consecutive duplicates
239 # Ignore blank lines and consecutive duplicates
237 cell = cell.rstrip()
240 cell = cell.rstrip()
238 if cell and (cell != last_cell):
241 if cell and (cell != last_cell):
239 history.append(cell)
242 history.append(cell)
240
243
241 self._style = self._make_style_from_name(self.highlighting_style)
244 self._style = self._make_style_from_name(self.highlighting_style)
242 style = DynamicStyle(lambda: self._style)
245 style = DynamicStyle(lambda: self._style)
243
246
244 editing_mode = getattr(EditingMode, self.editing_mode.upper())
247 editing_mode = getattr(EditingMode, self.editing_mode.upper())
245
248
246 self._app = create_prompt_application(
249 self._app = create_prompt_application(
247 editing_mode=editing_mode,
250 editing_mode=editing_mode,
248 key_bindings_registry=kbmanager.registry,
251 key_bindings_registry=kbmanager.registry,
249 history=history,
252 history=history,
250 completer=IPythonPTCompleter(self.Completer),
253 completer=IPythonPTCompleter(self.Completer),
251 enable_history_search=True,
254 enable_history_search=True,
252 style=style,
255 style=style,
253 mouse_support=self.mouse_support,
256 mouse_support=self.mouse_support,
254 **self._layout_options()
257 **self._layout_options()
255 )
258 )
256 self.pt_cli = CommandLineInterface(self._app,
259 self.pt_cli = CommandLineInterface(self._app,
257 eventloop=create_eventloop(self.inputhook))
260 eventloop=create_eventloop(self.inputhook))
258
261
259 def _make_style_from_name(self, name):
262 def _make_style_from_name(self, name):
260 """
263 """
261 Small wrapper that make an IPython compatible style from a style name
264 Small wrapper that make an IPython compatible style from a style name
262
265
263 We need that to add style for prompt ... etc.
266 We need that to add style for prompt ... etc.
264 """
267 """
265 style_cls = get_style_by_name(name)
268 style_cls = get_style_by_name(name)
266 style_overrides = {
269 style_overrides = {
267 Token.Prompt: '#009900',
270 Token.Prompt: '#009900',
268 Token.PromptNum: '#00ff00 bold',
271 Token.PromptNum: '#00ff00 bold',
269 }
272 }
270 if name == 'default':
273 if name == 'default':
271 style_cls = get_style_by_name('default')
274 style_cls = get_style_by_name('default')
272 # The default theme needs to be visible on both a dark background
275 # The default theme needs to be visible on both a dark background
273 # and a light background, because we can't tell what the terminal
276 # and a light background, because we can't tell what the terminal
274 # looks like. These tweaks to the default theme help with that.
277 # looks like. These tweaks to the default theme help with that.
275 style_overrides.update({
278 style_overrides.update({
276 Token.Number: '#007700',
279 Token.Number: '#007700',
277 Token.Operator: 'noinherit',
280 Token.Operator: 'noinherit',
278 Token.String: '#BB6622',
281 Token.String: '#BB6622',
279 Token.Name.Function: '#2080D0',
282 Token.Name.Function: '#2080D0',
280 Token.Name.Class: 'bold #2080D0',
283 Token.Name.Class: 'bold #2080D0',
281 Token.Name.Namespace: 'bold #2080D0',
284 Token.Name.Namespace: 'bold #2080D0',
282 })
285 })
283 style_overrides.update(self.highlighting_style_overrides)
286 style_overrides.update(self.highlighting_style_overrides)
284 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
287 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
285 style_dict=style_overrides)
288 style_dict=style_overrides)
286
289
287 return style
290 return style
288
291
289 def _layout_options(self):
292 def _layout_options(self):
290 """
293 """
291 Return the current layout option for the current Terminal InteractiveShell
294 Return the current layout option for the current Terminal InteractiveShell
292 """
295 """
293 return {
296 return {
294 'lexer':IPythonPTLexer(),
297 'lexer':IPythonPTLexer(),
295 'reserve_space_for_menu':self.space_for_menu,
298 'reserve_space_for_menu':self.space_for_menu,
296 'get_prompt_tokens':self.get_prompt_tokens,
299 'get_prompt_tokens':self.get_prompt_tokens,
297 'get_continuation_tokens':self.get_continuation_tokens,
300 'get_continuation_tokens':self.get_continuation_tokens,
298 'multiline':True,
301 'multiline':True,
299 'display_completions_in_columns': self.display_completions_in_columns,
302 'display_completions_in_columns': self.display_completions_in_columns,
300 }
303 }
301
304
302 def _update_layout(self):
305 def _update_layout(self):
303 """
306 """
304 Ask for a re computation of the application layout, if for example ,
307 Ask for a re computation of the application layout, if for example ,
305 some configuration options have changed.
308 some configuration options have changed.
306 """
309 """
307 self._app.layout = create_prompt_layout(**self._layout_options())
310 self._app.layout = create_prompt_layout(**self._layout_options())
308
311
309 def prompt_for_code(self):
312 def prompt_for_code(self):
310 document = self.pt_cli.run(
313 document = self.pt_cli.run(
311 pre_run=self.pre_prompt, reset_current_buffer=True)
314 pre_run=self.pre_prompt, reset_current_buffer=True)
312 return document.text
315 return document.text
313
316
314 def init_io(self):
317 def init_io(self):
315 if sys.platform not in {'win32', 'cli'}:
318 if sys.platform not in {'win32', 'cli'}:
316 return
319 return
317
320
318 import colorama
321 import colorama
319 colorama.init()
322 colorama.init()
320
323
321 # For some reason we make these wrappers around stdout/stderr.
324 # For some reason we make these wrappers around stdout/stderr.
322 # For now, we need to reset them so all output gets coloured.
325 # For now, we need to reset them so all output gets coloured.
323 # https://github.com/ipython/ipython/issues/8669
326 # https://github.com/ipython/ipython/issues/8669
324 from IPython.utils import io
327 from IPython.utils import io
325 io.stdout = io.IOStream(sys.stdout)
328 io.stdout = io.IOStream(sys.stdout)
326 io.stderr = io.IOStream(sys.stderr)
329 io.stderr = io.IOStream(sys.stderr)
327
330
328 def init_magics(self):
331 def init_magics(self):
329 super(TerminalInteractiveShell, self).init_magics()
332 super(TerminalInteractiveShell, self).init_magics()
330 self.register_magics(TerminalMagics)
333 self.register_magics(TerminalMagics)
331
334
332 def init_alias(self):
335 def init_alias(self):
333 # The parent class defines aliases that can be safely used with any
336 # The parent class defines aliases that can be safely used with any
334 # frontend.
337 # frontend.
335 super(TerminalInteractiveShell, self).init_alias()
338 super(TerminalInteractiveShell, self).init_alias()
336
339
337 # Now define aliases that only make sense on the terminal, because they
340 # Now define aliases that only make sense on the terminal, because they
338 # need direct access to the console in a way that we can't emulate in
341 # need direct access to the console in a way that we can't emulate in
339 # GUI or web frontend
342 # GUI or web frontend
340 if os.name == 'posix':
343 if os.name == 'posix':
341 for cmd in ['clear', 'more', 'less', 'man']:
344 for cmd in ['clear', 'more', 'less', 'man']:
342 self.alias_manager.soft_define_alias(cmd, cmd)
345 self.alias_manager.soft_define_alias(cmd, cmd)
343
346
344
347
345 def __init__(self, *args, **kwargs):
348 def __init__(self, *args, **kwargs):
346 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
349 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
347 self.init_prompt_toolkit_cli()
350 self.init_prompt_toolkit_cli()
348 self.init_term_title()
351 self.init_term_title()
349 self.keep_running = True
352 self.keep_running = True
350
353
351 def ask_exit(self):
354 def ask_exit(self):
352 self.keep_running = False
355 self.keep_running = False
353
356
354 rl_next_input = None
357 rl_next_input = None
355
358
356 def pre_prompt(self):
359 def pre_prompt(self):
357 if self.rl_next_input:
360 if self.rl_next_input:
358 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
361 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
359 self.rl_next_input = None
362 self.rl_next_input = None
360
363
361 def interact(self):
364 def interact(self):
362 while self.keep_running:
365 while self.keep_running:
363 print(self.separate_in, end='')
366 print(self.separate_in, end='')
364
367
365 try:
368 try:
366 code = self.prompt_for_code()
369 code = self.prompt_for_code()
367 except EOFError:
370 except EOFError:
368 if (not self.confirm_exit) \
371 if (not self.confirm_exit) \
369 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
372 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
370 self.ask_exit()
373 self.ask_exit()
371
374
372 else:
375 else:
373 if code:
376 if code:
374 self.run_cell(code, store_history=True)
377 self.run_cell(code, store_history=True)
375 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
378 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
376 self.edit_syntax_error()
379 self.edit_syntax_error()
377
380
378 def mainloop(self):
381 def mainloop(self):
379 # An extra layer of protection in case someone mashing Ctrl-C breaks
382 # An extra layer of protection in case someone mashing Ctrl-C breaks
380 # out of our internal code.
383 # out of our internal code.
381 while True:
384 while True:
382 try:
385 try:
383 self.interact()
386 self.interact()
384 break
387 break
385 except KeyboardInterrupt:
388 except KeyboardInterrupt:
386 print("\nKeyboardInterrupt escaped interact()\n")
389 print("\nKeyboardInterrupt escaped interact()\n")
387
390
388 _inputhook = None
391 _inputhook = None
389 def inputhook(self, context):
392 def inputhook(self, context):
390 if self._inputhook is not None:
393 if self._inputhook is not None:
391 self._inputhook(context)
394 self._inputhook(context)
392
395
393 def enable_gui(self, gui=None):
396 def enable_gui(self, gui=None):
394 if gui:
397 if gui:
395 self._inputhook = get_inputhook_func(gui)
398 self._inputhook = get_inputhook_func(gui)
396 else:
399 else:
397 self._inputhook = None
400 self._inputhook = None
398
401
399 # Methods to support auto-editing of SyntaxErrors:
402 # Methods to support auto-editing of SyntaxErrors:
400
403
401 def edit_syntax_error(self):
404 def edit_syntax_error(self):
402 """The bottom half of the syntax error handler called in the main loop.
405 """The bottom half of the syntax error handler called in the main loop.
403
406
404 Loop until syntax error is fixed or user cancels.
407 Loop until syntax error is fixed or user cancels.
405 """
408 """
406
409
407 while self.SyntaxTB.last_syntax_error:
410 while self.SyntaxTB.last_syntax_error:
408 # copy and clear last_syntax_error
411 # copy and clear last_syntax_error
409 err = self.SyntaxTB.clear_err_state()
412 err = self.SyntaxTB.clear_err_state()
410 if not self._should_recompile(err):
413 if not self._should_recompile(err):
411 return
414 return
412 try:
415 try:
413 # may set last_syntax_error again if a SyntaxError is raised
416 # may set last_syntax_error again if a SyntaxError is raised
414 self.safe_execfile(err.filename, self.user_ns)
417 self.safe_execfile(err.filename, self.user_ns)
415 except:
418 except:
416 self.showtraceback()
419 self.showtraceback()
417 else:
420 else:
418 try:
421 try:
419 with open(err.filename) as f:
422 with open(err.filename) as f:
420 # This should be inside a display_trap block and I
423 # This should be inside a display_trap block and I
421 # think it is.
424 # think it is.
422 sys.displayhook(f.read())
425 sys.displayhook(f.read())
423 except:
426 except:
424 self.showtraceback()
427 self.showtraceback()
425
428
426 def _should_recompile(self, e):
429 def _should_recompile(self, e):
427 """Utility routine for edit_syntax_error"""
430 """Utility routine for edit_syntax_error"""
428
431
429 if e.filename in ('<ipython console>', '<input>', '<string>',
432 if e.filename in ('<ipython console>', '<input>', '<string>',
430 '<console>', '<BackgroundJob compilation>',
433 '<console>', '<BackgroundJob compilation>',
431 None):
434 None):
432 return False
435 return False
433 try:
436 try:
434 if (self.autoedit_syntax and
437 if (self.autoedit_syntax and
435 not self.ask_yes_no(
438 not self.ask_yes_no(
436 'Return to editor to correct syntax error? '
439 'Return to editor to correct syntax error? '
437 '[Y/n] ', 'y')):
440 '[Y/n] ', 'y')):
438 return False
441 return False
439 except EOFError:
442 except EOFError:
440 return False
443 return False
441
444
442 def int0(x):
445 def int0(x):
443 try:
446 try:
444 return int(x)
447 return int(x)
445 except TypeError:
448 except TypeError:
446 return 0
449 return 0
447
450
448 # always pass integer line and offset values to editor hook
451 # always pass integer line and offset values to editor hook
449 try:
452 try:
450 self.hooks.fix_error_editor(e.filename,
453 self.hooks.fix_error_editor(e.filename,
451 int0(e.lineno), int0(e.offset),
454 int0(e.lineno), int0(e.offset),
452 e.msg)
455 e.msg)
453 except TryNext:
456 except TryNext:
454 warn('Could not open editor')
457 warn('Could not open editor')
455 return False
458 return False
456 return True
459 return True
457
460
458 # Run !system commands directly, not through pipes, so terminal programs
461 # Run !system commands directly, not through pipes, so terminal programs
459 # work correctly.
462 # work correctly.
460 system = InteractiveShell.system_raw
463 system = InteractiveShell.system_raw
461
464
462
465
463 if __name__ == '__main__':
466 if __name__ == '__main__':
464 TerminalInteractiveShell.instance().interact()
467 TerminalInteractiveShell.instance().interact()
@@ -1,26 +1,26 b''
1 #*****************************************************************************
1 #*****************************************************************************
2 # Copyright (C) 2016 The IPython Team <ipython-dev@scipy.org>
2 # Copyright (C) 2016 The IPython Team <ipython-dev@scipy.org>
3 #
3 #
4 # Distributed under the terms of the BSD License. The full license is in
4 # Distributed under the terms of the BSD License. The full license is in
5 # the file COPYING, distributed as part of this software.
5 # the file COPYING, distributed as part of this software.
6 #*****************************************************************************
6 #*****************************************************************************
7 from __future__ import absolute_import
7 from __future__ import absolute_import
8
8
9 """
9 """
10 Color managing related utilities
10 Color managing related utilities
11 """
11 """
12
12
13 import pygments
13 import pygments
14
14
15 from traitlets.config import Configurable
15 from traitlets.config import Configurable
16 from traitlets import Unicode
16 from traitlets import Unicode
17
17
18
18
19 available_themes = lambda : [s for s in pygments.styles.get_all_styles()]+['NoColor','LightBG','Linux']
19 available_themes = lambda : [s for s in pygments.styles.get_all_styles()]+['NoColor','LightBG','Linux']
20
20
21 class Colorable(Configurable):
21 class Colorable(Configurable):
22 """
22 """
23 A subclass of configurable for all the classes that have a `default_scheme`
23 A subclass of configurable for all the classes that have a `default_scheme`
24 """
24 """
25 default_style=Unicode('lightbg', config=True)
25 default_style=Unicode('lightbg').tag(config=True)
26
26
General Comments 0
You need to be logged in to leave comments. Login now