##// END OF EJS Templates
Merge pull request #10105 from srinivasreddy/dead_code...
Thomas Kluyver -
r23070:748d7071 merge
parent child Browse files
Show More
@@ -1,257 +1,256 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
31 from traitlets import List, Instance
30 from traitlets import List, Instance
32 from logging import error
31 from logging import error
33
32
34 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
35 # Utilities
34 # Utilities
36 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
37
36
38 # This is used as the pattern for calls to split_user_input.
37 # This is used as the pattern for calls to split_user_input.
39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
38 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
40
39
41 def default_aliases():
40 def default_aliases():
42 """Return list of shell aliases to auto-define.
41 """Return list of shell aliases to auto-define.
43 """
42 """
44 # Note: the aliases defined here should be safe to use on a kernel
43 # 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
44 # 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
45 # kernel in-process can define additional aliases that will only work in
47 # their case. For example, things like 'less' or 'clear' that manipulate
46 # 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
47 # 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.
48 # kernel is running inside a true terminal, and not over the network.
50
49
51 if os.name == 'posix':
50 if os.name == 'posix':
52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
51 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
52 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
54 ('cat', 'cat'),
53 ('cat', 'cat'),
55 ]
54 ]
56 # Useful set of ls aliases. The GNU and BSD options are a little
55 # 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
56 # different, so we make aliases that provide as similar as possible
58 # behavior in ipython, by passing the right flags for each platform
57 # behavior in ipython, by passing the right flags for each platform
59 if sys.platform.startswith('linux'):
58 if sys.platform.startswith('linux'):
60 ls_aliases = [('ls', 'ls -F --color'),
59 ls_aliases = [('ls', 'ls -F --color'),
61 # long ls
60 # long ls
62 ('ll', 'ls -F -o --color'),
61 ('ll', 'ls -F -o --color'),
63 # ls normal files only
62 # ls normal files only
64 ('lf', 'ls -F -o --color %l | grep ^-'),
63 ('lf', 'ls -F -o --color %l | grep ^-'),
65 # ls symbolic links
64 # ls symbolic links
66 ('lk', 'ls -F -o --color %l | grep ^l'),
65 ('lk', 'ls -F -o --color %l | grep ^l'),
67 # directories or links to directories,
66 # directories or links to directories,
68 ('ldir', 'ls -F -o --color %l | grep /$'),
67 ('ldir', 'ls -F -o --color %l | grep /$'),
69 # things which are executable
68 # things which are executable
70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
69 ('lx', 'ls -F -o --color %l | grep ^-..x'),
71 ]
70 ]
72 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
71 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
72 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
74 # the -G switch and lack the ability to use colorized output.
73 # the -G switch and lack the ability to use colorized output.
75 ls_aliases = [('ls', 'ls -F'),
74 ls_aliases = [('ls', 'ls -F'),
76 # long ls
75 # long ls
77 ('ll', 'ls -F -l'),
76 ('ll', 'ls -F -l'),
78 # ls normal files only
77 # ls normal files only
79 ('lf', 'ls -F -l %l | grep ^-'),
78 ('lf', 'ls -F -l %l | grep ^-'),
80 # ls symbolic links
79 # ls symbolic links
81 ('lk', 'ls -F -l %l | grep ^l'),
80 ('lk', 'ls -F -l %l | grep ^l'),
82 # directories or links to directories,
81 # directories or links to directories,
83 ('ldir', 'ls -F -l %l | grep /$'),
82 ('ldir', 'ls -F -l %l | grep /$'),
84 # things which are executable
83 # things which are executable
85 ('lx', 'ls -F -l %l | grep ^-..x'),
84 ('lx', 'ls -F -l %l | grep ^-..x'),
86 ]
85 ]
87 else:
86 else:
88 # BSD, OSX, etc.
87 # BSD, OSX, etc.
89 ls_aliases = [('ls', 'ls -F -G'),
88 ls_aliases = [('ls', 'ls -F -G'),
90 # long ls
89 # long ls
91 ('ll', 'ls -F -l -G'),
90 ('ll', 'ls -F -l -G'),
92 # ls normal files only
91 # ls normal files only
93 ('lf', 'ls -F -l -G %l | grep ^-'),
92 ('lf', 'ls -F -l -G %l | grep ^-'),
94 # ls symbolic links
93 # ls symbolic links
95 ('lk', 'ls -F -l -G %l | grep ^l'),
94 ('lk', 'ls -F -l -G %l | grep ^l'),
96 # directories or links to directories,
95 # directories or links to directories,
97 ('ldir', 'ls -F -G -l %l | grep /$'),
96 ('ldir', 'ls -F -G -l %l | grep /$'),
98 # things which are executable
97 # things which are executable
99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
98 ('lx', 'ls -F -l -G %l | grep ^-..x'),
100 ]
99 ]
101 default_aliases = default_aliases + ls_aliases
100 default_aliases = default_aliases + ls_aliases
102 elif os.name in ['nt', 'dos']:
101 elif os.name in ['nt', 'dos']:
103 default_aliases = [('ls', 'dir /on'),
102 default_aliases = [('ls', 'dir /on'),
104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
103 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
104 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
105 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
107 ]
106 ]
108 else:
107 else:
109 default_aliases = []
108 default_aliases = []
110
109
111 return default_aliases
110 return default_aliases
112
111
113
112
114 class AliasError(Exception):
113 class AliasError(Exception):
115 pass
114 pass
116
115
117
116
118 class InvalidAliasError(AliasError):
117 class InvalidAliasError(AliasError):
119 pass
118 pass
120
119
121 class Alias(object):
120 class Alias(object):
122 """Callable object storing the details of one alias.
121 """Callable object storing the details of one alias.
123
122
124 Instances are registered as magic functions to allow use of aliases.
123 Instances are registered as magic functions to allow use of aliases.
125 """
124 """
126
125
127 # Prepare blacklist
126 # Prepare blacklist
128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
127 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
129
128
130 def __init__(self, shell, name, cmd):
129 def __init__(self, shell, name, cmd):
131 self.shell = shell
130 self.shell = shell
132 self.name = name
131 self.name = name
133 self.cmd = cmd
132 self.cmd = cmd
134 self.__doc__ = "Alias for `!{}`".format(cmd)
133 self.__doc__ = "Alias for `!{}`".format(cmd)
135 self.nargs = self.validate()
134 self.nargs = self.validate()
136
135
137 def validate(self):
136 def validate(self):
138 """Validate the alias, and return the number of arguments."""
137 """Validate the alias, and return the number of arguments."""
139 if self.name in self.blacklist:
138 if self.name in self.blacklist:
140 raise InvalidAliasError("The name %s can't be aliased "
139 raise InvalidAliasError("The name %s can't be aliased "
141 "because it is a keyword or builtin." % self.name)
140 "because it is a keyword or builtin." % self.name)
142 try:
141 try:
143 caller = self.shell.magics_manager.magics['line'][self.name]
142 caller = self.shell.magics_manager.magics['line'][self.name]
144 except KeyError:
143 except KeyError:
145 pass
144 pass
146 else:
145 else:
147 if not isinstance(caller, Alias):
146 if not isinstance(caller, Alias):
148 raise InvalidAliasError("The name %s can't be aliased "
147 raise InvalidAliasError("The name %s can't be aliased "
149 "because it is another magic command." % self.name)
148 "because it is another magic command." % self.name)
150
149
151 if not (isinstance(self.cmd, string_types)):
150 if not (isinstance(self.cmd, str)):
152 raise InvalidAliasError("An alias command must be a string, "
151 raise InvalidAliasError("An alias command must be a string, "
153 "got: %r" % self.cmd)
152 "got: %r" % self.cmd)
154
153
155 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
154 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
156
155
157 if (nargs > 0) and (self.cmd.find('%l') >= 0):
156 if (nargs > 0) and (self.cmd.find('%l') >= 0):
158 raise InvalidAliasError('The %s and %l specifiers are mutually '
157 raise InvalidAliasError('The %s and %l specifiers are mutually '
159 'exclusive in alias definitions.')
158 'exclusive in alias definitions.')
160
159
161 return nargs
160 return nargs
162
161
163 def __repr__(self):
162 def __repr__(self):
164 return "<alias {} for {!r}>".format(self.name, self.cmd)
163 return "<alias {} for {!r}>".format(self.name, self.cmd)
165
164
166 def __call__(self, rest=''):
165 def __call__(self, rest=''):
167 cmd = self.cmd
166 cmd = self.cmd
168 nargs = self.nargs
167 nargs = self.nargs
169 # Expand the %l special to be the user's input line
168 # Expand the %l special to be the user's input line
170 if cmd.find('%l') >= 0:
169 if cmd.find('%l') >= 0:
171 cmd = cmd.replace('%l', rest)
170 cmd = cmd.replace('%l', rest)
172 rest = ''
171 rest = ''
173
172
174 if nargs==0:
173 if nargs==0:
175 if cmd.find('%%s') >= 1:
174 if cmd.find('%%s') >= 1:
176 cmd = cmd.replace('%%s', '%s')
175 cmd = cmd.replace('%%s', '%s')
177 # Simple, argument-less aliases
176 # Simple, argument-less aliases
178 cmd = '%s %s' % (cmd, rest)
177 cmd = '%s %s' % (cmd, rest)
179 else:
178 else:
180 # Handle aliases with positional arguments
179 # Handle aliases with positional arguments
181 args = rest.split(None, nargs)
180 args = rest.split(None, nargs)
182 if len(args) < nargs:
181 if len(args) < nargs:
183 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
182 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
184 (self.name, nargs, len(args)))
183 (self.name, nargs, len(args)))
185 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
184 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
186
185
187 self.shell.system(cmd)
186 self.shell.system(cmd)
188
187
189 #-----------------------------------------------------------------------------
188 #-----------------------------------------------------------------------------
190 # Main AliasManager class
189 # Main AliasManager class
191 #-----------------------------------------------------------------------------
190 #-----------------------------------------------------------------------------
192
191
193 class AliasManager(Configurable):
192 class AliasManager(Configurable):
194
193
195 default_aliases = List(default_aliases()).tag(config=True)
194 default_aliases = List(default_aliases()).tag(config=True)
196 user_aliases = List(default_value=[]).tag(config=True)
195 user_aliases = List(default_value=[]).tag(config=True)
197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
196 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
198
197
199 def __init__(self, shell=None, **kwargs):
198 def __init__(self, shell=None, **kwargs):
200 super(AliasManager, self).__init__(shell=shell, **kwargs)
199 super(AliasManager, self).__init__(shell=shell, **kwargs)
201 # For convenient access
200 # For convenient access
202 self.linemagics = self.shell.magics_manager.magics['line']
201 self.linemagics = self.shell.magics_manager.magics['line']
203 self.init_aliases()
202 self.init_aliases()
204
203
205 def init_aliases(self):
204 def init_aliases(self):
206 # Load default & user aliases
205 # Load default & user aliases
207 for name, cmd in self.default_aliases + self.user_aliases:
206 for name, cmd in self.default_aliases + self.user_aliases:
208 self.soft_define_alias(name, cmd)
207 self.soft_define_alias(name, cmd)
209
208
210 @property
209 @property
211 def aliases(self):
210 def aliases(self):
212 return [(n, func.cmd) for (n, func) in self.linemagics.items()
211 return [(n, func.cmd) for (n, func) in self.linemagics.items()
213 if isinstance(func, Alias)]
212 if isinstance(func, Alias)]
214
213
215 def soft_define_alias(self, name, cmd):
214 def soft_define_alias(self, name, cmd):
216 """Define an alias, but don't raise on an AliasError."""
215 """Define an alias, but don't raise on an AliasError."""
217 try:
216 try:
218 self.define_alias(name, cmd)
217 self.define_alias(name, cmd)
219 except AliasError as e:
218 except AliasError as e:
220 error("Invalid alias: %s" % e)
219 error("Invalid alias: %s" % e)
221
220
222 def define_alias(self, name, cmd):
221 def define_alias(self, name, cmd):
223 """Define a new alias after validating it.
222 """Define a new alias after validating it.
224
223
225 This will raise an :exc:`AliasError` if there are validation
224 This will raise an :exc:`AliasError` if there are validation
226 problems.
225 problems.
227 """
226 """
228 caller = Alias(shell=self.shell, name=name, cmd=cmd)
227 caller = Alias(shell=self.shell, name=name, cmd=cmd)
229 self.shell.magics_manager.register_function(caller, magic_kind='line',
228 self.shell.magics_manager.register_function(caller, magic_kind='line',
230 magic_name=name)
229 magic_name=name)
231
230
232 def get_alias(self, name):
231 def get_alias(self, name):
233 """Return an alias, or None if no alias by that name exists."""
232 """Return an alias, or None if no alias by that name exists."""
234 aname = self.linemagics.get(name, None)
233 aname = self.linemagics.get(name, None)
235 return aname if isinstance(aname, Alias) else None
234 return aname if isinstance(aname, Alias) else None
236
235
237 def is_alias(self, name):
236 def is_alias(self, name):
238 """Return whether or not a given name has been defined as an alias"""
237 """Return whether or not a given name has been defined as an alias"""
239 return self.get_alias(name) is not None
238 return self.get_alias(name) is not None
240
239
241 def undefine_alias(self, name):
240 def undefine_alias(self, name):
242 if self.is_alias(name):
241 if self.is_alias(name):
243 del self.linemagics[name]
242 del self.linemagics[name]
244 else:
243 else:
245 raise ValueError('%s is not an alias' % name)
244 raise ValueError('%s is not an alias' % name)
246
245
247 def clear_aliases(self):
246 def clear_aliases(self):
248 for name, cmd in self.aliases:
247 for name, cmd in self.aliases:
249 self.undefine_alias(name)
248 self.undefine_alias(name)
250
249
251 def retrieve_alias(self, name):
250 def retrieve_alias(self, name):
252 """Retrieve the command to which an alias expands."""
251 """Retrieve the command to which an alias expands."""
253 caller = self.get_alias(name)
252 caller = self.get_alias(name)
254 if caller:
253 if caller:
255 return caller.cmd
254 return caller.cmd
256 else:
255 else:
257 raise ValueError('%s is not an alias' % name)
256 raise ValueError('%s is not an alias' % name)
@@ -1,458 +1,458 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 from copy import deepcopy
16 from copy import deepcopy
17 import glob
17 import glob
18 import logging
18 import logging
19 import os
19 import os
20 import shutil
20 import shutil
21 import sys
21 import sys
22
22
23 from traitlets.config.application import Application, catch_config_error
23 from traitlets.config.application import Application, catch_config_error
24 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
24 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
25 from IPython.core import release, crashhandler
25 from IPython.core import release, crashhandler
26 from IPython.core.profiledir import ProfileDir, ProfileDirError
26 from IPython.core.profiledir import ProfileDir, ProfileDirError
27 from IPython.paths import get_ipython_dir, get_ipython_package_dir
27 from IPython.paths import get_ipython_dir, get_ipython_package_dir
28 from IPython.utils.path import ensure_dir_exists
28 from IPython.utils.path import ensure_dir_exists
29 from IPython.utils import py3compat
29 from IPython.utils import py3compat
30 from traitlets import (
30 from traitlets import (
31 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
31 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
32 default, observe,
32 default, observe,
33 )
33 )
34
34
35 if os.name == 'nt':
35 if os.name == 'nt':
36 programdata = os.environ.get('PROGRAMDATA', None)
36 programdata = os.environ.get('PROGRAMDATA', None)
37 if programdata:
37 if programdata:
38 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
38 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
39 else: # PROGRAMDATA is not defined by default on XP.
39 else: # PROGRAMDATA is not defined by default on XP.
40 SYSTEM_CONFIG_DIRS = []
40 SYSTEM_CONFIG_DIRS = []
41 else:
41 else:
42 SYSTEM_CONFIG_DIRS = [
42 SYSTEM_CONFIG_DIRS = [
43 "/usr/local/etc/ipython",
43 "/usr/local/etc/ipython",
44 "/etc/ipython",
44 "/etc/ipython",
45 ]
45 ]
46
46
47 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
47 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
48 if _envvar in {None, ''}:
48 if _envvar in {None, ''}:
49 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
49 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
50 else:
50 else:
51 if _envvar.lower() in {'1','true'}:
51 if _envvar.lower() in {'1','true'}:
52 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
52 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
53 elif _envvar.lower() in {'0','false'} :
53 elif _envvar.lower() in {'0','false'} :
54 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
54 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
55 else:
55 else:
56 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
56 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
57
57
58 # aliases and flags
58 # aliases and flags
59
59
60 base_aliases = {
60 base_aliases = {
61 'profile-dir' : 'ProfileDir.location',
61 'profile-dir' : 'ProfileDir.location',
62 'profile' : 'BaseIPythonApplication.profile',
62 'profile' : 'BaseIPythonApplication.profile',
63 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
63 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
64 'log-level' : 'Application.log_level',
64 'log-level' : 'Application.log_level',
65 'config' : 'BaseIPythonApplication.extra_config_file',
65 'config' : 'BaseIPythonApplication.extra_config_file',
66 }
66 }
67
67
68 base_flags = dict(
68 base_flags = dict(
69 debug = ({'Application' : {'log_level' : logging.DEBUG}},
69 debug = ({'Application' : {'log_level' : logging.DEBUG}},
70 "set log level to logging.DEBUG (maximize logging output)"),
70 "set log level to logging.DEBUG (maximize logging output)"),
71 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
71 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
72 "set log level to logging.CRITICAL (minimize logging output)"),
72 "set log level to logging.CRITICAL (minimize logging output)"),
73 init = ({'BaseIPythonApplication' : {
73 init = ({'BaseIPythonApplication' : {
74 'copy_config_files' : True,
74 'copy_config_files' : True,
75 'auto_create' : True}
75 'auto_create' : True}
76 }, """Initialize profile with default config files. This is equivalent
76 }, """Initialize profile with default config files. This is equivalent
77 to running `ipython profile create <profile>` prior to startup.
77 to running `ipython profile create <profile>` prior to startup.
78 """)
78 """)
79 )
79 )
80
80
81 class ProfileAwareConfigLoader(PyFileConfigLoader):
81 class ProfileAwareConfigLoader(PyFileConfigLoader):
82 """A Python file config loader that is aware of IPython profiles."""
82 """A Python file config loader that is aware of IPython profiles."""
83 def load_subconfig(self, fname, path=None, profile=None):
83 def load_subconfig(self, fname, path=None, profile=None):
84 if profile is not None:
84 if profile is not None:
85 try:
85 try:
86 profile_dir = ProfileDir.find_profile_dir_by_name(
86 profile_dir = ProfileDir.find_profile_dir_by_name(
87 get_ipython_dir(),
87 get_ipython_dir(),
88 profile,
88 profile,
89 )
89 )
90 except ProfileDirError:
90 except ProfileDirError:
91 return
91 return
92 path = profile_dir.location
92 path = profile_dir.location
93 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
93 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
94
94
95 class BaseIPythonApplication(Application):
95 class BaseIPythonApplication(Application):
96
96
97 name = Unicode(u'ipython')
97 name = Unicode(u'ipython')
98 description = Unicode(u'IPython: an enhanced interactive Python shell.')
98 description = Unicode(u'IPython: an enhanced interactive Python shell.')
99 version = Unicode(release.version)
99 version = Unicode(release.version)
100
100
101 aliases = Dict(base_aliases)
101 aliases = Dict(base_aliases)
102 flags = Dict(base_flags)
102 flags = Dict(base_flags)
103 classes = List([ProfileDir])
103 classes = List([ProfileDir])
104
104
105 # enable `load_subconfig('cfg.py', profile='name')`
105 # enable `load_subconfig('cfg.py', profile='name')`
106 python_config_loader_class = ProfileAwareConfigLoader
106 python_config_loader_class = ProfileAwareConfigLoader
107
107
108 # Track whether the config_file has changed,
108 # Track whether the config_file has changed,
109 # because some logic happens only if we aren't using the default.
109 # because some logic happens only if we aren't using the default.
110 config_file_specified = Set()
110 config_file_specified = Set()
111
111
112 config_file_name = Unicode()
112 config_file_name = Unicode()
113 @default('config_file_name')
113 @default('config_file_name')
114 def _config_file_name_default(self):
114 def _config_file_name_default(self):
115 return self.name.replace('-','_') + u'_config.py'
115 return self.name.replace('-','_') + u'_config.py'
116 @observe('config_file_name')
116 @observe('config_file_name')
117 def _config_file_name_changed(self, change):
117 def _config_file_name_changed(self, change):
118 if change['new'] != change['old']:
118 if change['new'] != change['old']:
119 self.config_file_specified.add(change['new'])
119 self.config_file_specified.add(change['new'])
120
120
121 # The directory that contains IPython's builtin profiles.
121 # The directory that contains IPython's builtin profiles.
122 builtin_profile_dir = Unicode(
122 builtin_profile_dir = Unicode(
123 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
123 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
124 )
124 )
125
125
126 config_file_paths = List(Unicode())
126 config_file_paths = List(Unicode())
127 @default('config_file_paths')
127 @default('config_file_paths')
128 def _config_file_paths_default(self):
128 def _config_file_paths_default(self):
129 return [py3compat.getcwd()]
129 return [os.getcwd()]
130
130
131 extra_config_file = Unicode(
131 extra_config_file = Unicode(
132 help="""Path to an extra config file to load.
132 help="""Path to an extra config file to load.
133
133
134 If specified, load this config file in addition to any other IPython config.
134 If specified, load this config file in addition to any other IPython config.
135 """).tag(config=True)
135 """).tag(config=True)
136 @observe('extra_config_file')
136 @observe('extra_config_file')
137 def _extra_config_file_changed(self, change):
137 def _extra_config_file_changed(self, change):
138 old = change['old']
138 old = change['old']
139 new = change['new']
139 new = change['new']
140 try:
140 try:
141 self.config_files.remove(old)
141 self.config_files.remove(old)
142 except ValueError:
142 except ValueError:
143 pass
143 pass
144 self.config_file_specified.add(new)
144 self.config_file_specified.add(new)
145 self.config_files.append(new)
145 self.config_files.append(new)
146
146
147 profile = Unicode(u'default',
147 profile = Unicode(u'default',
148 help="""The IPython profile to use."""
148 help="""The IPython profile to use."""
149 ).tag(config=True)
149 ).tag(config=True)
150
150
151 @observe('profile')
151 @observe('profile')
152 def _profile_changed(self, change):
152 def _profile_changed(self, change):
153 self.builtin_profile_dir = os.path.join(
153 self.builtin_profile_dir = os.path.join(
154 get_ipython_package_dir(), u'config', u'profile', change['new']
154 get_ipython_package_dir(), u'config', u'profile', change['new']
155 )
155 )
156
156
157 ipython_dir = Unicode(
157 ipython_dir = Unicode(
158 help="""
158 help="""
159 The name of the IPython directory. This directory is used for logging
159 The name of the IPython directory. This directory is used for logging
160 configuration (through profiles), history storage, etc. The default
160 configuration (through profiles), history storage, etc. The default
161 is usually $HOME/.ipython. This option can also be specified through
161 is usually $HOME/.ipython. This option can also be specified through
162 the environment variable IPYTHONDIR.
162 the environment variable IPYTHONDIR.
163 """
163 """
164 ).tag(config=True)
164 ).tag(config=True)
165 @default('ipython_dir')
165 @default('ipython_dir')
166 def _ipython_dir_default(self):
166 def _ipython_dir_default(self):
167 d = get_ipython_dir()
167 d = get_ipython_dir()
168 self._ipython_dir_changed({
168 self._ipython_dir_changed({
169 'name': 'ipython_dir',
169 'name': 'ipython_dir',
170 'old': d,
170 'old': d,
171 'new': d,
171 'new': d,
172 })
172 })
173 return d
173 return d
174
174
175 _in_init_profile_dir = False
175 _in_init_profile_dir = False
176 profile_dir = Instance(ProfileDir, allow_none=True)
176 profile_dir = Instance(ProfileDir, allow_none=True)
177 @default('profile_dir')
177 @default('profile_dir')
178 def _profile_dir_default(self):
178 def _profile_dir_default(self):
179 # avoid recursion
179 # avoid recursion
180 if self._in_init_profile_dir:
180 if self._in_init_profile_dir:
181 return
181 return
182 # profile_dir requested early, force initialization
182 # profile_dir requested early, force initialization
183 self.init_profile_dir()
183 self.init_profile_dir()
184 return self.profile_dir
184 return self.profile_dir
185
185
186 overwrite = Bool(False,
186 overwrite = Bool(False,
187 help="""Whether to overwrite existing config files when copying"""
187 help="""Whether to overwrite existing config files when copying"""
188 ).tag(config=True)
188 ).tag(config=True)
189 auto_create = Bool(False,
189 auto_create = Bool(False,
190 help="""Whether to create profile dir if it doesn't exist"""
190 help="""Whether to create profile dir if it doesn't exist"""
191 ).tag(config=True)
191 ).tag(config=True)
192
192
193 config_files = List(Unicode())
193 config_files = List(Unicode())
194 @default('config_files')
194 @default('config_files')
195 def _config_files_default(self):
195 def _config_files_default(self):
196 return [self.config_file_name]
196 return [self.config_file_name]
197
197
198 copy_config_files = Bool(False,
198 copy_config_files = Bool(False,
199 help="""Whether to install the default config files into the profile dir.
199 help="""Whether to install the default config files into the profile dir.
200 If a new profile is being created, and IPython contains config files for that
200 If a new profile is being created, and IPython contains config files for that
201 profile, then they will be staged into the new directory. Otherwise,
201 profile, then they will be staged into the new directory. Otherwise,
202 default config files will be automatically generated.
202 default config files will be automatically generated.
203 """).tag(config=True)
203 """).tag(config=True)
204
204
205 verbose_crash = Bool(False,
205 verbose_crash = Bool(False,
206 help="""Create a massive crash report when IPython encounters what may be an
206 help="""Create a massive crash report when IPython encounters what may be an
207 internal error. The default is to append a short message to the
207 internal error. The default is to append a short message to the
208 usual traceback""").tag(config=True)
208 usual traceback""").tag(config=True)
209
209
210 # The class to use as the crash handler.
210 # The class to use as the crash handler.
211 crash_handler_class = Type(crashhandler.CrashHandler)
211 crash_handler_class = Type(crashhandler.CrashHandler)
212
212
213 @catch_config_error
213 @catch_config_error
214 def __init__(self, **kwargs):
214 def __init__(self, **kwargs):
215 super(BaseIPythonApplication, self).__init__(**kwargs)
215 super(BaseIPythonApplication, self).__init__(**kwargs)
216 # ensure current working directory exists
216 # ensure current working directory exists
217 try:
217 try:
218 py3compat.getcwd()
218 os.getcwd()
219 except:
219 except:
220 # exit if cwd doesn't exist
220 # exit if cwd doesn't exist
221 self.log.error("Current working directory doesn't exist.")
221 self.log.error("Current working directory doesn't exist.")
222 self.exit(1)
222 self.exit(1)
223
223
224 #-------------------------------------------------------------------------
224 #-------------------------------------------------------------------------
225 # Various stages of Application creation
225 # Various stages of Application creation
226 #-------------------------------------------------------------------------
226 #-------------------------------------------------------------------------
227
227
228 deprecated_subcommands = {}
228 deprecated_subcommands = {}
229
229
230 def initialize_subcommand(self, subc, argv=None):
230 def initialize_subcommand(self, subc, argv=None):
231 if subc in self.deprecated_subcommands:
231 if subc in self.deprecated_subcommands:
232 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
232 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
233 "in future versions.".format(sub=subc))
233 "in future versions.".format(sub=subc))
234 self.log.warning("You likely want to use `jupyter {sub}` in the "
234 self.log.warning("You likely want to use `jupyter {sub}` in the "
235 "future".format(sub=subc))
235 "future".format(sub=subc))
236 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
236 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
237
237
238 def init_crash_handler(self):
238 def init_crash_handler(self):
239 """Create a crash handler, typically setting sys.excepthook to it."""
239 """Create a crash handler, typically setting sys.excepthook to it."""
240 self.crash_handler = self.crash_handler_class(self)
240 self.crash_handler = self.crash_handler_class(self)
241 sys.excepthook = self.excepthook
241 sys.excepthook = self.excepthook
242 def unset_crashhandler():
242 def unset_crashhandler():
243 sys.excepthook = sys.__excepthook__
243 sys.excepthook = sys.__excepthook__
244 atexit.register(unset_crashhandler)
244 atexit.register(unset_crashhandler)
245
245
246 def excepthook(self, etype, evalue, tb):
246 def excepthook(self, etype, evalue, tb):
247 """this is sys.excepthook after init_crashhandler
247 """this is sys.excepthook after init_crashhandler
248
248
249 set self.verbose_crash=True to use our full crashhandler, instead of
249 set self.verbose_crash=True to use our full crashhandler, instead of
250 a regular traceback with a short message (crash_handler_lite)
250 a regular traceback with a short message (crash_handler_lite)
251 """
251 """
252
252
253 if self.verbose_crash:
253 if self.verbose_crash:
254 return self.crash_handler(etype, evalue, tb)
254 return self.crash_handler(etype, evalue, tb)
255 else:
255 else:
256 return crashhandler.crash_handler_lite(etype, evalue, tb)
256 return crashhandler.crash_handler_lite(etype, evalue, tb)
257
257
258 @observe('ipython_dir')
258 @observe('ipython_dir')
259 def _ipython_dir_changed(self, change):
259 def _ipython_dir_changed(self, change):
260 old = change['old']
260 old = change['old']
261 new = change['new']
261 new = change['new']
262 if old is not Undefined:
262 if old is not Undefined:
263 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
263 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
264 sys.getfilesystemencoding()
264 sys.getfilesystemencoding()
265 )
265 )
266 if str_old in sys.path:
266 if str_old in sys.path:
267 sys.path.remove(str_old)
267 sys.path.remove(str_old)
268 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
268 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
269 sys.getfilesystemencoding()
269 sys.getfilesystemencoding()
270 )
270 )
271 sys.path.append(str_path)
271 sys.path.append(str_path)
272 ensure_dir_exists(new)
272 ensure_dir_exists(new)
273 readme = os.path.join(new, 'README')
273 readme = os.path.join(new, 'README')
274 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
274 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
275 if not os.path.exists(readme) and os.path.exists(readme_src):
275 if not os.path.exists(readme) and os.path.exists(readme_src):
276 shutil.copy(readme_src, readme)
276 shutil.copy(readme_src, readme)
277 for d in ('extensions', 'nbextensions'):
277 for d in ('extensions', 'nbextensions'):
278 path = os.path.join(new, d)
278 path = os.path.join(new, d)
279 try:
279 try:
280 ensure_dir_exists(path)
280 ensure_dir_exists(path)
281 except OSError as e:
281 except OSError as e:
282 # this will not be EEXIST
282 # this will not be EEXIST
283 self.log.error("couldn't create path %s: %s", path, e)
283 self.log.error("couldn't create path %s: %s", path, e)
284 self.log.debug("IPYTHONDIR set to: %s" % new)
284 self.log.debug("IPYTHONDIR set to: %s" % new)
285
285
286 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
286 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
287 """Load the config file.
287 """Load the config file.
288
288
289 By default, errors in loading config are handled, and a warning
289 By default, errors in loading config are handled, and a warning
290 printed on screen. For testing, the suppress_errors option is set
290 printed on screen. For testing, the suppress_errors option is set
291 to False, so errors will make tests fail.
291 to False, so errors will make tests fail.
292
292
293 `supress_errors` default value is to be `None` in which case the
293 `supress_errors` default value is to be `None` in which case the
294 behavior default to the one of `traitlets.Application`.
294 behavior default to the one of `traitlets.Application`.
295
295
296 The default value can be set :
296 The default value can be set :
297 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
297 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
298 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
298 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
299 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
299 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
300
300
301 Any other value are invalid, and will make IPython exit with a non-zero return code.
301 Any other value are invalid, and will make IPython exit with a non-zero return code.
302 """
302 """
303
303
304
304
305 self.log.debug("Searching path %s for config files", self.config_file_paths)
305 self.log.debug("Searching path %s for config files", self.config_file_paths)
306 base_config = 'ipython_config.py'
306 base_config = 'ipython_config.py'
307 self.log.debug("Attempting to load config file: %s" %
307 self.log.debug("Attempting to load config file: %s" %
308 base_config)
308 base_config)
309 try:
309 try:
310 if suppress_errors is not None:
310 if suppress_errors is not None:
311 old_value = Application.raise_config_file_errors
311 old_value = Application.raise_config_file_errors
312 Application.raise_config_file_errors = not suppress_errors;
312 Application.raise_config_file_errors = not suppress_errors;
313 Application.load_config_file(
313 Application.load_config_file(
314 self,
314 self,
315 base_config,
315 base_config,
316 path=self.config_file_paths
316 path=self.config_file_paths
317 )
317 )
318 except ConfigFileNotFound:
318 except ConfigFileNotFound:
319 # ignore errors loading parent
319 # ignore errors loading parent
320 self.log.debug("Config file %s not found", base_config)
320 self.log.debug("Config file %s not found", base_config)
321 pass
321 pass
322 if suppress_errors is not None:
322 if suppress_errors is not None:
323 Application.raise_config_file_errors = old_value
323 Application.raise_config_file_errors = old_value
324
324
325 for config_file_name in self.config_files:
325 for config_file_name in self.config_files:
326 if not config_file_name or config_file_name == base_config:
326 if not config_file_name or config_file_name == base_config:
327 continue
327 continue
328 self.log.debug("Attempting to load config file: %s" %
328 self.log.debug("Attempting to load config file: %s" %
329 self.config_file_name)
329 self.config_file_name)
330 try:
330 try:
331 Application.load_config_file(
331 Application.load_config_file(
332 self,
332 self,
333 config_file_name,
333 config_file_name,
334 path=self.config_file_paths
334 path=self.config_file_paths
335 )
335 )
336 except ConfigFileNotFound:
336 except ConfigFileNotFound:
337 # Only warn if the default config file was NOT being used.
337 # Only warn if the default config file was NOT being used.
338 if config_file_name in self.config_file_specified:
338 if config_file_name in self.config_file_specified:
339 msg = self.log.warning
339 msg = self.log.warning
340 else:
340 else:
341 msg = self.log.debug
341 msg = self.log.debug
342 msg("Config file not found, skipping: %s", config_file_name)
342 msg("Config file not found, skipping: %s", config_file_name)
343 except Exception:
343 except Exception:
344 # For testing purposes.
344 # For testing purposes.
345 if not suppress_errors:
345 if not suppress_errors:
346 raise
346 raise
347 self.log.warning("Error loading config file: %s" %
347 self.log.warning("Error loading config file: %s" %
348 self.config_file_name, exc_info=True)
348 self.config_file_name, exc_info=True)
349
349
350 def init_profile_dir(self):
350 def init_profile_dir(self):
351 """initialize the profile dir"""
351 """initialize the profile dir"""
352 self._in_init_profile_dir = True
352 self._in_init_profile_dir = True
353 if self.profile_dir is not None:
353 if self.profile_dir is not None:
354 # already ran
354 # already ran
355 return
355 return
356 if 'ProfileDir.location' not in self.config:
356 if 'ProfileDir.location' not in self.config:
357 # location not specified, find by profile name
357 # location not specified, find by profile name
358 try:
358 try:
359 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
359 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
360 except ProfileDirError:
360 except ProfileDirError:
361 # not found, maybe create it (always create default profile)
361 # not found, maybe create it (always create default profile)
362 if self.auto_create or self.profile == 'default':
362 if self.auto_create or self.profile == 'default':
363 try:
363 try:
364 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
364 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
365 except ProfileDirError:
365 except ProfileDirError:
366 self.log.fatal("Could not create profile: %r"%self.profile)
366 self.log.fatal("Could not create profile: %r"%self.profile)
367 self.exit(1)
367 self.exit(1)
368 else:
368 else:
369 self.log.info("Created profile dir: %r"%p.location)
369 self.log.info("Created profile dir: %r"%p.location)
370 else:
370 else:
371 self.log.fatal("Profile %r not found."%self.profile)
371 self.log.fatal("Profile %r not found."%self.profile)
372 self.exit(1)
372 self.exit(1)
373 else:
373 else:
374 self.log.debug("Using existing profile dir: %r"%p.location)
374 self.log.debug("Using existing profile dir: %r"%p.location)
375 else:
375 else:
376 location = self.config.ProfileDir.location
376 location = self.config.ProfileDir.location
377 # location is fully specified
377 # location is fully specified
378 try:
378 try:
379 p = ProfileDir.find_profile_dir(location, self.config)
379 p = ProfileDir.find_profile_dir(location, self.config)
380 except ProfileDirError:
380 except ProfileDirError:
381 # not found, maybe create it
381 # not found, maybe create it
382 if self.auto_create:
382 if self.auto_create:
383 try:
383 try:
384 p = ProfileDir.create_profile_dir(location, self.config)
384 p = ProfileDir.create_profile_dir(location, self.config)
385 except ProfileDirError:
385 except ProfileDirError:
386 self.log.fatal("Could not create profile directory: %r"%location)
386 self.log.fatal("Could not create profile directory: %r"%location)
387 self.exit(1)
387 self.exit(1)
388 else:
388 else:
389 self.log.debug("Creating new profile dir: %r"%location)
389 self.log.debug("Creating new profile dir: %r"%location)
390 else:
390 else:
391 self.log.fatal("Profile directory %r not found."%location)
391 self.log.fatal("Profile directory %r not found."%location)
392 self.exit(1)
392 self.exit(1)
393 else:
393 else:
394 self.log.info("Using existing profile dir: %r"%location)
394 self.log.info("Using existing profile dir: %r"%location)
395 # if profile_dir is specified explicitly, set profile name
395 # if profile_dir is specified explicitly, set profile name
396 dir_name = os.path.basename(p.location)
396 dir_name = os.path.basename(p.location)
397 if dir_name.startswith('profile_'):
397 if dir_name.startswith('profile_'):
398 self.profile = dir_name[8:]
398 self.profile = dir_name[8:]
399
399
400 self.profile_dir = p
400 self.profile_dir = p
401 self.config_file_paths.append(p.location)
401 self.config_file_paths.append(p.location)
402 self._in_init_profile_dir = False
402 self._in_init_profile_dir = False
403
403
404 def init_config_files(self):
404 def init_config_files(self):
405 """[optionally] copy default config files into profile dir."""
405 """[optionally] copy default config files into profile dir."""
406 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
406 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
407 # copy config files
407 # copy config files
408 path = self.builtin_profile_dir
408 path = self.builtin_profile_dir
409 if self.copy_config_files:
409 if self.copy_config_files:
410 src = self.profile
410 src = self.profile
411
411
412 cfg = self.config_file_name
412 cfg = self.config_file_name
413 if path and os.path.exists(os.path.join(path, cfg)):
413 if path and os.path.exists(os.path.join(path, cfg)):
414 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
414 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
415 cfg, src, self.profile_dir.location, self.overwrite)
415 cfg, src, self.profile_dir.location, self.overwrite)
416 )
416 )
417 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
417 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
418 else:
418 else:
419 self.stage_default_config_file()
419 self.stage_default_config_file()
420 else:
420 else:
421 # Still stage *bundled* config files, but not generated ones
421 # Still stage *bundled* config files, but not generated ones
422 # This is necessary for `ipython profile=sympy` to load the profile
422 # This is necessary for `ipython profile=sympy` to load the profile
423 # on the first go
423 # on the first go
424 files = glob.glob(os.path.join(path, '*.py'))
424 files = glob.glob(os.path.join(path, '*.py'))
425 for fullpath in files:
425 for fullpath in files:
426 cfg = os.path.basename(fullpath)
426 cfg = os.path.basename(fullpath)
427 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
427 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
428 # file was copied
428 # file was copied
429 self.log.warning("Staging bundled %s from %s into %r"%(
429 self.log.warning("Staging bundled %s from %s into %r"%(
430 cfg, self.profile, self.profile_dir.location)
430 cfg, self.profile, self.profile_dir.location)
431 )
431 )
432
432
433
433
434 def stage_default_config_file(self):
434 def stage_default_config_file(self):
435 """auto generate default config file, and stage it into the profile."""
435 """auto generate default config file, and stage it into the profile."""
436 s = self.generate_config_file()
436 s = self.generate_config_file()
437 fname = os.path.join(self.profile_dir.location, self.config_file_name)
437 fname = os.path.join(self.profile_dir.location, self.config_file_name)
438 if self.overwrite or not os.path.exists(fname):
438 if self.overwrite or not os.path.exists(fname):
439 self.log.warning("Generating default config file: %r"%(fname))
439 self.log.warning("Generating default config file: %r"%(fname))
440 with open(fname, 'w') as f:
440 with open(fname, 'w') as f:
441 f.write(s)
441 f.write(s)
442
442
443 @catch_config_error
443 @catch_config_error
444 def initialize(self, argv=None):
444 def initialize(self, argv=None):
445 # don't hook up crash handler before parsing command-line
445 # don't hook up crash handler before parsing command-line
446 self.parse_command_line(argv)
446 self.parse_command_line(argv)
447 self.init_crash_handler()
447 self.init_crash_handler()
448 if self.subapp is not None:
448 if self.subapp is not None:
449 # stop here if subapp is taking over
449 # stop here if subapp is taking over
450 return
450 return
451 # save a copy of CLI config to re-load after config files
451 # save a copy of CLI config to re-load after config files
452 # so that it has highest priority
452 # so that it has highest priority
453 cl_config = deepcopy(self.config)
453 cl_config = deepcopy(self.config)
454 self.init_profile_dir()
454 self.init_profile_dir()
455 self.init_config_files()
455 self.init_config_files()
456 self.load_config_file()
456 self.load_config_file()
457 # enforce cl-opts override configfile opts:
457 # enforce cl-opts override configfile opts:
458 self.update_config(cl_config)
458 self.update_config(cl_config)
@@ -1,103 +1,103 b''
1 """
1 """
2 A context manager for managing things injected into :mod:`__builtin__`.
2 A context manager for managing things injected into :mod:`__builtin__`.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 * Fernando Perez
7 * Fernando Perez
8 """
8 """
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010-2011 The IPython Development Team.
10 # Copyright (C) 2010-2011 The IPython Development Team.
11 #
11 #
12 # Distributed under the terms of the BSD License.
12 # Distributed under the terms of the BSD License.
13 #
13 #
14 # Complete license in the file COPYING.txt, distributed with this software.
14 # Complete license in the file COPYING.txt, distributed with this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 from traitlets.config.configurable import Configurable
21 from traitlets.config.configurable import Configurable
22
22
23 from IPython.utils.py3compat import builtin_mod, iteritems
23 from IPython.utils.py3compat import builtin_mod
24 from traitlets import Instance
24 from traitlets import Instance
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Classes and functions
27 # Classes and functions
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 class __BuiltinUndefined(object): pass
30 class __BuiltinUndefined(object): pass
31 BuiltinUndefined = __BuiltinUndefined()
31 BuiltinUndefined = __BuiltinUndefined()
32
32
33 class __HideBuiltin(object): pass
33 class __HideBuiltin(object): pass
34 HideBuiltin = __HideBuiltin()
34 HideBuiltin = __HideBuiltin()
35
35
36
36
37 class BuiltinTrap(Configurable):
37 class BuiltinTrap(Configurable):
38
38
39 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
39 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
40 allow_none=True)
40 allow_none=True)
41
41
42 def __init__(self, shell=None):
42 def __init__(self, shell=None):
43 super(BuiltinTrap, self).__init__(shell=shell, config=None)
43 super(BuiltinTrap, self).__init__(shell=shell, config=None)
44 self._orig_builtins = {}
44 self._orig_builtins = {}
45 # We define this to track if a single BuiltinTrap is nested.
45 # We define this to track if a single BuiltinTrap is nested.
46 # Only turn off the trap when the outermost call to __exit__ is made.
46 # Only turn off the trap when the outermost call to __exit__ is made.
47 self._nested_level = 0
47 self._nested_level = 0
48 self.shell = shell
48 self.shell = shell
49 # builtins we always add - if set to HideBuiltin, they will just
49 # builtins we always add - if set to HideBuiltin, they will just
50 # be removed instead of being replaced by something else
50 # be removed instead of being replaced by something else
51 self.auto_builtins = {'exit': HideBuiltin,
51 self.auto_builtins = {'exit': HideBuiltin,
52 'quit': HideBuiltin,
52 'quit': HideBuiltin,
53 'get_ipython': self.shell.get_ipython,
53 'get_ipython': self.shell.get_ipython,
54 }
54 }
55
55
56 def __enter__(self):
56 def __enter__(self):
57 if self._nested_level == 0:
57 if self._nested_level == 0:
58 self.activate()
58 self.activate()
59 self._nested_level += 1
59 self._nested_level += 1
60 # I return self, so callers can use add_builtin in a with clause.
60 # I return self, so callers can use add_builtin in a with clause.
61 return self
61 return self
62
62
63 def __exit__(self, type, value, traceback):
63 def __exit__(self, type, value, traceback):
64 if self._nested_level == 1:
64 if self._nested_level == 1:
65 self.deactivate()
65 self.deactivate()
66 self._nested_level -= 1
66 self._nested_level -= 1
67 # Returning False will cause exceptions to propagate
67 # Returning False will cause exceptions to propagate
68 return False
68 return False
69
69
70 def add_builtin(self, key, value):
70 def add_builtin(self, key, value):
71 """Add a builtin and save the original."""
71 """Add a builtin and save the original."""
72 bdict = builtin_mod.__dict__
72 bdict = builtin_mod.__dict__
73 orig = bdict.get(key, BuiltinUndefined)
73 orig = bdict.get(key, BuiltinUndefined)
74 if value is HideBuiltin:
74 if value is HideBuiltin:
75 if orig is not BuiltinUndefined: #same as 'key in bdict'
75 if orig is not BuiltinUndefined: #same as 'key in bdict'
76 self._orig_builtins[key] = orig
76 self._orig_builtins[key] = orig
77 del bdict[key]
77 del bdict[key]
78 else:
78 else:
79 self._orig_builtins[key] = orig
79 self._orig_builtins[key] = orig
80 bdict[key] = value
80 bdict[key] = value
81
81
82 def remove_builtin(self, key, orig):
82 def remove_builtin(self, key, orig):
83 """Remove an added builtin and re-set the original."""
83 """Remove an added builtin and re-set the original."""
84 if orig is BuiltinUndefined:
84 if orig is BuiltinUndefined:
85 del builtin_mod.__dict__[key]
85 del builtin_mod.__dict__[key]
86 else:
86 else:
87 builtin_mod.__dict__[key] = orig
87 builtin_mod.__dict__[key] = orig
88
88
89 def activate(self):
89 def activate(self):
90 """Store ipython references in the __builtin__ namespace."""
90 """Store ipython references in the __builtin__ namespace."""
91
91
92 add_builtin = self.add_builtin
92 add_builtin = self.add_builtin
93 for name, func in iteritems(self.auto_builtins):
93 for name, func in self.auto_builtins.items():
94 add_builtin(name, func)
94 add_builtin(name, func)
95
95
96 def deactivate(self):
96 def deactivate(self):
97 """Remove any builtins which might have been added by add_builtins, or
97 """Remove any builtins which might have been added by add_builtins, or
98 restore overwritten ones to their previous values."""
98 restore overwritten ones to their previous values."""
99 remove_builtin = self.remove_builtin
99 remove_builtin = self.remove_builtin
100 for key, val in iteritems(self._orig_builtins):
100 for key, val in self._orig_builtins.items():
101 remove_builtin(key, val)
101 remove_builtin(key, val)
102 self._orig_builtins.clear()
102 self._orig_builtins.clear()
103 self._builtins_added = False
103 self._builtins_added = False
@@ -1,1229 +1,1229 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Word completion for IPython.
2 """Word completion for IPython.
3
3
4 This module started as fork of the rlcompleter module in the Python standard
4 This module started as 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,
6 upstream and were accepted as of Python 2.3,
7
7
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 # Some of this code originated from rlcompleter in the Python standard library
13 # Some of this code originated from rlcompleter in the Python standard library
14 # Copyright (C) 2001 Python Software Foundation, www.python.org
14 # Copyright (C) 2001 Python Software Foundation, www.python.org
15
15
16
16
17 import __main__
17 import __main__
18 import glob
18 import glob
19 import inspect
19 import inspect
20 import itertools
20 import itertools
21 import keyword
21 import keyword
22 import os
22 import os
23 import re
23 import re
24 import sys
24 import sys
25 import unicodedata
25 import unicodedata
26 import string
26 import string
27 import warnings
27 import warnings
28 from importlib import import_module
28 from importlib import import_module
29
29
30 from traitlets.config.configurable import Configurable
30 from traitlets.config.configurable import Configurable
31 from IPython.core.error import TryNext
31 from IPython.core.error import TryNext
32 from IPython.core.inputsplitter import ESC_MAGIC
32 from IPython.core.inputsplitter import ESC_MAGIC
33 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
33 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
34 from IPython.utils import generics
34 from IPython.utils import generics
35 from IPython.utils.decorators import undoc
35 from IPython.utils.decorators import undoc
36 from IPython.utils.dir2 import dir2, get_real_method
36 from IPython.utils.dir2 import dir2, get_real_method
37 from IPython.utils.process import arg_split
37 from IPython.utils.process import arg_split
38 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
38 from IPython.utils.py3compat import builtin_mod, PY3, cast_unicode_py2
39 from traitlets import Bool, Enum, observe
39 from traitlets import Bool, Enum, observe
40
40
41 from functools import wraps
41 from functools import wraps
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Globals
44 # Globals
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46
46
47 # Public API
47 # Public API
48 __all__ = ['Completer','IPCompleter']
48 __all__ = ['Completer','IPCompleter']
49
49
50 if sys.platform == 'win32':
50 if sys.platform == 'win32':
51 PROTECTABLES = ' '
51 PROTECTABLES = ' '
52 else:
52 else:
53 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
53 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
54
54
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Work around BUG decorators.
57 # Work around BUG decorators.
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 def _strip_single_trailing_space(complete):
60 def _strip_single_trailing_space(complete):
61 """
61 """
62 This is a workaround for a weird IPython/Prompt_toolkit behavior,
62 This is a workaround for a weird IPython/Prompt_toolkit behavior,
63 that can be removed once we rely on a slightly more recent prompt_toolkit
63 that can be removed once we rely on a slightly more recent prompt_toolkit
64 version (likely > 1.0.3). So this can likely be removed in IPython 6.0
64 version (likely > 1.0.3). So this can likely be removed in IPython 6.0
65
65
66 cf https://github.com/ipython/ipython/issues/9658
66 cf https://github.com/ipython/ipython/issues/9658
67 and https://github.com/jonathanslenders/python-prompt-toolkit/pull/328
67 and https://github.com/jonathanslenders/python-prompt-toolkit/pull/328
68
68
69 The bug is due to the fact that in PTK the completer will reinvoke itself
69 The bug is due to the fact that in PTK the completer will reinvoke itself
70 after trying to completer to the longuest common prefix of all the
70 after trying to completer to the longuest common prefix of all the
71 completions, unless only one completion is available.
71 completions, unless only one completion is available.
72
72
73 This logic is faulty if the completion ends with space, which can happen in
73 This logic is faulty if the completion ends with space, which can happen in
74 case like::
74 case like::
75
75
76 from foo import im<ta>
76 from foo import im<ta>
77
77
78 which only matching completion is `import `. Note the leading space at the
78 which only matching completion is `import `. Note the leading space at the
79 end. So leaving a space at the end is a reasonable request, but for now
79 end. So leaving a space at the end is a reasonable request, but for now
80 we'll strip it.
80 we'll strip it.
81 """
81 """
82
82
83 @wraps(complete)
83 @wraps(complete)
84 def comp(*args, **kwargs):
84 def comp(*args, **kwargs):
85 text, matches = complete(*args, **kwargs)
85 text, matches = complete(*args, **kwargs)
86 if len(matches) == 1:
86 if len(matches) == 1:
87 return text, [matches[0].rstrip()]
87 return text, [matches[0].rstrip()]
88 return text, matches
88 return text, matches
89
89
90 return comp
90 return comp
91
91
92
92
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Main functions and classes
95 # Main functions and classes
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98 def has_open_quotes(s):
98 def has_open_quotes(s):
99 """Return whether a string has open quotes.
99 """Return whether a string has open quotes.
100
100
101 This simply counts whether the number of quote characters of either type in
101 This simply counts whether the number of quote characters of either type in
102 the string is odd.
102 the string is odd.
103
103
104 Returns
104 Returns
105 -------
105 -------
106 If there is an open quote, the quote character is returned. Else, return
106 If there is an open quote, the quote character is returned. Else, return
107 False.
107 False.
108 """
108 """
109 # We check " first, then ', so complex cases with nested quotes will get
109 # We check " first, then ', so complex cases with nested quotes will get
110 # the " to take precedence.
110 # the " to take precedence.
111 if s.count('"') % 2:
111 if s.count('"') % 2:
112 return '"'
112 return '"'
113 elif s.count("'") % 2:
113 elif s.count("'") % 2:
114 return "'"
114 return "'"
115 else:
115 else:
116 return False
116 return False
117
117
118
118
119 def protect_filename(s):
119 def protect_filename(s):
120 """Escape a string to protect certain characters."""
120 """Escape a string to protect certain characters."""
121 if set(s) & set(PROTECTABLES):
121 if set(s) & set(PROTECTABLES):
122 if sys.platform == "win32":
122 if sys.platform == "win32":
123 return '"' + s + '"'
123 return '"' + s + '"'
124 else:
124 else:
125 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
125 return "".join(("\\" + c if c in PROTECTABLES else c) for c in s)
126 else:
126 else:
127 return s
127 return s
128
128
129
129
130 def expand_user(path):
130 def expand_user(path):
131 """Expand '~'-style usernames in strings.
131 """Expand '~'-style usernames in strings.
132
132
133 This is similar to :func:`os.path.expanduser`, but it computes and returns
133 This is similar to :func:`os.path.expanduser`, but it computes and returns
134 extra information that will be useful if the input was being used in
134 extra information that will be useful if the input was being used in
135 computing completions, and you wish to return the completions with the
135 computing completions, and you wish to return the completions with the
136 original '~' instead of its expanded value.
136 original '~' instead of its expanded value.
137
137
138 Parameters
138 Parameters
139 ----------
139 ----------
140 path : str
140 path : str
141 String to be expanded. If no ~ is present, the output is the same as the
141 String to be expanded. If no ~ is present, the output is the same as the
142 input.
142 input.
143
143
144 Returns
144 Returns
145 -------
145 -------
146 newpath : str
146 newpath : str
147 Result of ~ expansion in the input path.
147 Result of ~ expansion in the input path.
148 tilde_expand : bool
148 tilde_expand : bool
149 Whether any expansion was performed or not.
149 Whether any expansion was performed or not.
150 tilde_val : str
150 tilde_val : str
151 The value that ~ was replaced with.
151 The value that ~ was replaced with.
152 """
152 """
153 # Default values
153 # Default values
154 tilde_expand = False
154 tilde_expand = False
155 tilde_val = ''
155 tilde_val = ''
156 newpath = path
156 newpath = path
157
157
158 if path.startswith('~'):
158 if path.startswith('~'):
159 tilde_expand = True
159 tilde_expand = True
160 rest = len(path)-1
160 rest = len(path)-1
161 newpath = os.path.expanduser(path)
161 newpath = os.path.expanduser(path)
162 if rest:
162 if rest:
163 tilde_val = newpath[:-rest]
163 tilde_val = newpath[:-rest]
164 else:
164 else:
165 tilde_val = newpath
165 tilde_val = newpath
166
166
167 return newpath, tilde_expand, tilde_val
167 return newpath, tilde_expand, tilde_val
168
168
169
169
170 def compress_user(path, tilde_expand, tilde_val):
170 def compress_user(path, tilde_expand, tilde_val):
171 """Does the opposite of expand_user, with its outputs.
171 """Does the opposite of expand_user, with its outputs.
172 """
172 """
173 if tilde_expand:
173 if tilde_expand:
174 return path.replace(tilde_val, '~')
174 return path.replace(tilde_val, '~')
175 else:
175 else:
176 return path
176 return path
177
177
178
178
179 def completions_sorting_key(word):
179 def completions_sorting_key(word):
180 """key for sorting completions
180 """key for sorting completions
181
181
182 This does several things:
182 This does several things:
183
183
184 - Lowercase all completions, so they are sorted alphabetically with
184 - Lowercase all completions, so they are sorted alphabetically with
185 upper and lower case words mingled
185 upper and lower case words mingled
186 - Demote any completions starting with underscores to the end
186 - Demote any completions starting with underscores to the end
187 - Insert any %magic and %%cellmagic completions in the alphabetical order
187 - Insert any %magic and %%cellmagic completions in the alphabetical order
188 by their name
188 by their name
189 """
189 """
190 # Case insensitive sort
190 # Case insensitive sort
191 word = word.lower()
191 word = word.lower()
192
192
193 prio1, prio2 = 0, 0
193 prio1, prio2 = 0, 0
194
194
195 if word.startswith('__'):
195 if word.startswith('__'):
196 prio1 = 2
196 prio1 = 2
197 elif word.startswith('_'):
197 elif word.startswith('_'):
198 prio1 = 1
198 prio1 = 1
199
199
200 if word.endswith('='):
200 if word.endswith('='):
201 prio1 = -1
201 prio1 = -1
202
202
203 if word.startswith('%%'):
203 if word.startswith('%%'):
204 # If there's another % in there, this is something else, so leave it alone
204 # If there's another % in there, this is something else, so leave it alone
205 if not "%" in word[2:]:
205 if not "%" in word[2:]:
206 word = word[2:]
206 word = word[2:]
207 prio2 = 2
207 prio2 = 2
208 elif word.startswith('%'):
208 elif word.startswith('%'):
209 if not "%" in word[1:]:
209 if not "%" in word[1:]:
210 word = word[1:]
210 word = word[1:]
211 prio2 = 1
211 prio2 = 1
212
212
213 return prio1, word, prio2
213 return prio1, word, prio2
214
214
215
215
216 @undoc
216 @undoc
217 class Bunch(object): pass
217 class Bunch(object): pass
218
218
219
219
220 if sys.platform == 'win32':
220 if sys.platform == 'win32':
221 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
221 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
222 else:
222 else:
223 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
223 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
224
224
225 GREEDY_DELIMS = ' =\r\n'
225 GREEDY_DELIMS = ' =\r\n'
226
226
227
227
228 class CompletionSplitter(object):
228 class CompletionSplitter(object):
229 """An object to split an input line in a manner similar to readline.
229 """An object to split an input line in a manner similar to readline.
230
230
231 By having our own implementation, we can expose readline-like completion in
231 By having our own implementation, we can expose readline-like completion in
232 a uniform manner to all frontends. This object only needs to be given the
232 a uniform manner to all frontends. This object only needs to be given the
233 line of text to be split and the cursor position on said line, and it
233 line of text to be split and the cursor position on said line, and it
234 returns the 'word' to be completed on at the cursor after splitting the
234 returns the 'word' to be completed on at the cursor after splitting the
235 entire line.
235 entire line.
236
236
237 What characters are used as splitting delimiters can be controlled by
237 What characters are used as splitting delimiters can be controlled by
238 setting the `delims` attribute (this is a property that internally
238 setting the `delims` attribute (this is a property that internally
239 automatically builds the necessary regular expression)"""
239 automatically builds the necessary regular expression)"""
240
240
241 # Private interface
241 # Private interface
242
242
243 # A string of delimiter characters. The default value makes sense for
243 # A string of delimiter characters. The default value makes sense for
244 # IPython's most typical usage patterns.
244 # IPython's most typical usage patterns.
245 _delims = DELIMS
245 _delims = DELIMS
246
246
247 # The expression (a normal string) to be compiled into a regular expression
247 # The expression (a normal string) to be compiled into a regular expression
248 # for actual splitting. We store it as an attribute mostly for ease of
248 # for actual splitting. We store it as an attribute mostly for ease of
249 # debugging, since this type of code can be so tricky to debug.
249 # debugging, since this type of code can be so tricky to debug.
250 _delim_expr = None
250 _delim_expr = None
251
251
252 # The regular expression that does the actual splitting
252 # The regular expression that does the actual splitting
253 _delim_re = None
253 _delim_re = None
254
254
255 def __init__(self, delims=None):
255 def __init__(self, delims=None):
256 delims = CompletionSplitter._delims if delims is None else delims
256 delims = CompletionSplitter._delims if delims is None else delims
257 self.delims = delims
257 self.delims = delims
258
258
259 @property
259 @property
260 def delims(self):
260 def delims(self):
261 """Return the string of delimiter characters."""
261 """Return the string of delimiter characters."""
262 return self._delims
262 return self._delims
263
263
264 @delims.setter
264 @delims.setter
265 def delims(self, delims):
265 def delims(self, delims):
266 """Set the delimiters for line splitting."""
266 """Set the delimiters for line splitting."""
267 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
267 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
268 self._delim_re = re.compile(expr)
268 self._delim_re = re.compile(expr)
269 self._delims = delims
269 self._delims = delims
270 self._delim_expr = expr
270 self._delim_expr = expr
271
271
272 def split_line(self, line, cursor_pos=None):
272 def split_line(self, line, cursor_pos=None):
273 """Split a line of text with a cursor at the given position.
273 """Split a line of text with a cursor at the given position.
274 """
274 """
275 l = line if cursor_pos is None else line[:cursor_pos]
275 l = line if cursor_pos is None else line[:cursor_pos]
276 return self._delim_re.split(l)[-1]
276 return self._delim_re.split(l)[-1]
277
277
278
278
279 class Completer(Configurable):
279 class Completer(Configurable):
280
280
281 greedy = Bool(False,
281 greedy = Bool(False,
282 help="""Activate greedy completion
282 help="""Activate greedy completion
283 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
283 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
284
284
285 This will enable completion on elements of lists, results of function calls, etc.,
285 This will enable completion on elements of lists, results of function calls, etc.,
286 but can be unsafe because the code is actually evaluated on TAB.
286 but can be unsafe because the code is actually evaluated on TAB.
287 """
287 """
288 ).tag(config=True)
288 ).tag(config=True)
289
289
290
290
291 def __init__(self, namespace=None, global_namespace=None, **kwargs):
291 def __init__(self, namespace=None, global_namespace=None, **kwargs):
292 """Create a new completer for the command line.
292 """Create a new completer for the command line.
293
293
294 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
294 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
295
295
296 If unspecified, the default namespace where completions are performed
296 If unspecified, the default namespace where completions are performed
297 is __main__ (technically, __main__.__dict__). Namespaces should be
297 is __main__ (technically, __main__.__dict__). Namespaces should be
298 given as dictionaries.
298 given as dictionaries.
299
299
300 An optional second namespace can be given. This allows the completer
300 An optional second namespace can be given. This allows the completer
301 to handle cases where both the local and global scopes need to be
301 to handle cases where both the local and global scopes need to be
302 distinguished.
302 distinguished.
303
303
304 Completer instances should be used as the completion mechanism of
304 Completer instances should be used as the completion mechanism of
305 readline via the set_completer() call:
305 readline via the set_completer() call:
306
306
307 readline.set_completer(Completer(my_namespace).complete)
307 readline.set_completer(Completer(my_namespace).complete)
308 """
308 """
309
309
310 # Don't bind to namespace quite yet, but flag whether the user wants a
310 # Don't bind to namespace quite yet, but flag whether the user wants a
311 # specific namespace or to use __main__.__dict__. This will allow us
311 # specific namespace or to use __main__.__dict__. This will allow us
312 # to bind to __main__.__dict__ at completion time, not now.
312 # to bind to __main__.__dict__ at completion time, not now.
313 if namespace is None:
313 if namespace is None:
314 self.use_main_ns = 1
314 self.use_main_ns = 1
315 else:
315 else:
316 self.use_main_ns = 0
316 self.use_main_ns = 0
317 self.namespace = namespace
317 self.namespace = namespace
318
318
319 # The global namespace, if given, can be bound directly
319 # The global namespace, if given, can be bound directly
320 if global_namespace is None:
320 if global_namespace is None:
321 self.global_namespace = {}
321 self.global_namespace = {}
322 else:
322 else:
323 self.global_namespace = global_namespace
323 self.global_namespace = global_namespace
324
324
325 super(Completer, self).__init__(**kwargs)
325 super(Completer, self).__init__(**kwargs)
326
326
327 def complete(self, text, state):
327 def complete(self, text, state):
328 """Return the next possible completion for 'text'.
328 """Return the next possible completion for 'text'.
329
329
330 This is called successively with state == 0, 1, 2, ... until it
330 This is called successively with state == 0, 1, 2, ... until it
331 returns None. The completion should begin with 'text'.
331 returns None. The completion should begin with 'text'.
332
332
333 """
333 """
334 if self.use_main_ns:
334 if self.use_main_ns:
335 self.namespace = __main__.__dict__
335 self.namespace = __main__.__dict__
336
336
337 if state == 0:
337 if state == 0:
338 if "." in text:
338 if "." in text:
339 self.matches = self.attr_matches(text)
339 self.matches = self.attr_matches(text)
340 else:
340 else:
341 self.matches = self.global_matches(text)
341 self.matches = self.global_matches(text)
342 try:
342 try:
343 return self.matches[state]
343 return self.matches[state]
344 except IndexError:
344 except IndexError:
345 return None
345 return None
346
346
347 def global_matches(self, text):
347 def global_matches(self, text):
348 """Compute matches when text is a simple name.
348 """Compute matches when text is a simple name.
349
349
350 Return a list of all keywords, built-in functions and names currently
350 Return a list of all keywords, built-in functions and names currently
351 defined in self.namespace or self.global_namespace that match.
351 defined in self.namespace or self.global_namespace that match.
352
352
353 """
353 """
354 matches = []
354 matches = []
355 match_append = matches.append
355 match_append = matches.append
356 n = len(text)
356 n = len(text)
357 for lst in [keyword.kwlist,
357 for lst in [keyword.kwlist,
358 builtin_mod.__dict__.keys(),
358 builtin_mod.__dict__.keys(),
359 self.namespace.keys(),
359 self.namespace.keys(),
360 self.global_namespace.keys()]:
360 self.global_namespace.keys()]:
361 for word in lst:
361 for word in lst:
362 if word[:n] == text and word != "__builtins__":
362 if word[:n] == text and word != "__builtins__":
363 match_append(word)
363 match_append(word)
364 return [cast_unicode_py2(m) for m in matches]
364 return [cast_unicode_py2(m) for m in matches]
365
365
366 def attr_matches(self, text):
366 def attr_matches(self, text):
367 """Compute matches when text contains a dot.
367 """Compute matches when text contains a dot.
368
368
369 Assuming the text is of the form NAME.NAME....[NAME], and is
369 Assuming the text is of the form NAME.NAME....[NAME], and is
370 evaluatable in self.namespace or self.global_namespace, it will be
370 evaluatable in self.namespace or self.global_namespace, it will be
371 evaluated and its attributes (as revealed by dir()) are used as
371 evaluated and its attributes (as revealed by dir()) are used as
372 possible completions. (For class instances, class members are are
372 possible completions. (For class instances, class members are are
373 also considered.)
373 also considered.)
374
374
375 WARNING: this can still invoke arbitrary C code, if an object
375 WARNING: this can still invoke arbitrary C code, if an object
376 with a __getattr__ hook is evaluated.
376 with a __getattr__ hook is evaluated.
377
377
378 """
378 """
379
379
380 # Another option, seems to work great. Catches things like ''.<tab>
380 # Another option, seems to work great. Catches things like ''.<tab>
381 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
381 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
382
382
383 if m:
383 if m:
384 expr, attr = m.group(1, 3)
384 expr, attr = m.group(1, 3)
385 elif self.greedy:
385 elif self.greedy:
386 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
386 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
387 if not m2:
387 if not m2:
388 return []
388 return []
389 expr, attr = m2.group(1,2)
389 expr, attr = m2.group(1,2)
390 else:
390 else:
391 return []
391 return []
392
392
393 try:
393 try:
394 obj = eval(expr, self.namespace)
394 obj = eval(expr, self.namespace)
395 except:
395 except:
396 try:
396 try:
397 obj = eval(expr, self.global_namespace)
397 obj = eval(expr, self.global_namespace)
398 except:
398 except:
399 return []
399 return []
400
400
401 if self.limit_to__all__ and hasattr(obj, '__all__'):
401 if self.limit_to__all__ and hasattr(obj, '__all__'):
402 words = get__all__entries(obj)
402 words = get__all__entries(obj)
403 else:
403 else:
404 words = dir2(obj)
404 words = dir2(obj)
405
405
406 try:
406 try:
407 words = generics.complete_object(obj, words)
407 words = generics.complete_object(obj, words)
408 except TryNext:
408 except TryNext:
409 pass
409 pass
410 except Exception:
410 except Exception:
411 # Silence errors from completion function
411 # Silence errors from completion function
412 #raise # dbg
412 #raise # dbg
413 pass
413 pass
414 # Build match list to return
414 # Build match list to return
415 n = len(attr)
415 n = len(attr)
416 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
416 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
417
417
418
418
419 def get__all__entries(obj):
419 def get__all__entries(obj):
420 """returns the strings in the __all__ attribute"""
420 """returns the strings in the __all__ attribute"""
421 try:
421 try:
422 words = getattr(obj, '__all__')
422 words = getattr(obj, '__all__')
423 except:
423 except:
424 return []
424 return []
425
425
426 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
426 return [cast_unicode_py2(w) for w in words if isinstance(w, str)]
427
427
428
428
429 def match_dict_keys(keys, prefix, delims):
429 def match_dict_keys(keys, prefix, delims):
430 """Used by dict_key_matches, matching the prefix to a list of keys"""
430 """Used by dict_key_matches, matching the prefix to a list of keys"""
431 if not prefix:
431 if not prefix:
432 return None, 0, [repr(k) for k in keys
432 return None, 0, [repr(k) for k in keys
433 if isinstance(k, (string_types, bytes))]
433 if isinstance(k, (str, bytes))]
434 quote_match = re.search('["\']', prefix)
434 quote_match = re.search('["\']', prefix)
435 quote = quote_match.group()
435 quote = quote_match.group()
436 try:
436 try:
437 prefix_str = eval(prefix + quote, {})
437 prefix_str = eval(prefix + quote, {})
438 except Exception:
438 except Exception:
439 return None, 0, []
439 return None, 0, []
440
440
441 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
441 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
442 token_match = re.search(pattern, prefix, re.UNICODE)
442 token_match = re.search(pattern, prefix, re.UNICODE)
443 token_start = token_match.start()
443 token_start = token_match.start()
444 token_prefix = token_match.group()
444 token_prefix = token_match.group()
445
445
446 # TODO: support bytes in Py3k
446 # TODO: support bytes in Py3k
447 matched = []
447 matched = []
448 for key in keys:
448 for key in keys:
449 try:
449 try:
450 if not key.startswith(prefix_str):
450 if not key.startswith(prefix_str):
451 continue
451 continue
452 except (AttributeError, TypeError, UnicodeError):
452 except (AttributeError, TypeError, UnicodeError):
453 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
453 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
454 continue
454 continue
455
455
456 # reformat remainder of key to begin with prefix
456 # reformat remainder of key to begin with prefix
457 rem = key[len(prefix_str):]
457 rem = key[len(prefix_str):]
458 # force repr wrapped in '
458 # force repr wrapped in '
459 rem_repr = repr(rem + '"')
459 rem_repr = repr(rem + '"')
460 if rem_repr.startswith('u') and prefix[0] not in 'uU':
460 if rem_repr.startswith('u') and prefix[0] not in 'uU':
461 # Found key is unicode, but prefix is Py2 string.
461 # Found key is unicode, but prefix is Py2 string.
462 # Therefore attempt to interpret key as string.
462 # Therefore attempt to interpret key as string.
463 try:
463 try:
464 rem_repr = repr(rem.encode('ascii') + '"')
464 rem_repr = repr(rem.encode('ascii') + '"')
465 except UnicodeEncodeError:
465 except UnicodeEncodeError:
466 continue
466 continue
467
467
468 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
468 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
469 if quote == '"':
469 if quote == '"':
470 # The entered prefix is quoted with ",
470 # The entered prefix is quoted with ",
471 # but the match is quoted with '.
471 # but the match is quoted with '.
472 # A contained " hence needs escaping for comparison:
472 # A contained " hence needs escaping for comparison:
473 rem_repr = rem_repr.replace('"', '\\"')
473 rem_repr = rem_repr.replace('"', '\\"')
474
474
475 # then reinsert prefix from start of token
475 # then reinsert prefix from start of token
476 matched.append('%s%s' % (token_prefix, rem_repr))
476 matched.append('%s%s' % (token_prefix, rem_repr))
477 return quote, token_start, matched
477 return quote, token_start, matched
478
478
479
479
480 def _safe_isinstance(obj, module, class_name):
480 def _safe_isinstance(obj, module, class_name):
481 """Checks if obj is an instance of module.class_name if loaded
481 """Checks if obj is an instance of module.class_name if loaded
482 """
482 """
483 return (module in sys.modules and
483 return (module in sys.modules and
484 isinstance(obj, getattr(import_module(module), class_name)))
484 isinstance(obj, getattr(import_module(module), class_name)))
485
485
486
486
487 def back_unicode_name_matches(text):
487 def back_unicode_name_matches(text):
488 u"""Match unicode characters back to unicode name
488 u"""Match unicode characters back to unicode name
489
489
490 This does ☃ -> \\snowman
490 This does ☃ -> \\snowman
491
491
492 Note that snowman is not a valid python3 combining character but will be expanded.
492 Note that snowman is not a valid python3 combining character but will be expanded.
493 Though it will not recombine back to the snowman character by the completion machinery.
493 Though it will not recombine back to the snowman character by the completion machinery.
494
494
495 This will not either back-complete standard sequences like \\n, \\b ...
495 This will not either back-complete standard sequences like \\n, \\b ...
496
496
497 Used on Python 3 only.
497 Used on Python 3 only.
498 """
498 """
499 if len(text)<2:
499 if len(text)<2:
500 return u'', ()
500 return u'', ()
501 maybe_slash = text[-2]
501 maybe_slash = text[-2]
502 if maybe_slash != '\\':
502 if maybe_slash != '\\':
503 return u'', ()
503 return u'', ()
504
504
505 char = text[-1]
505 char = text[-1]
506 # no expand on quote for completion in strings.
506 # no expand on quote for completion in strings.
507 # nor backcomplete standard ascii keys
507 # nor backcomplete standard ascii keys
508 if char in string.ascii_letters or char in ['"',"'"]:
508 if char in string.ascii_letters or char in ['"',"'"]:
509 return u'', ()
509 return u'', ()
510 try :
510 try :
511 unic = unicodedata.name(char)
511 unic = unicodedata.name(char)
512 return '\\'+char,['\\'+unic]
512 return '\\'+char,['\\'+unic]
513 except KeyError:
513 except KeyError:
514 pass
514 pass
515 return u'', ()
515 return u'', ()
516
516
517 def back_latex_name_matches(text):
517 def back_latex_name_matches(text):
518 u"""Match latex characters back to unicode name
518 u"""Match latex characters back to unicode name
519
519
520 This does ->\\sqrt
520 This does ->\\sqrt
521
521
522 Used on Python 3 only.
522 Used on Python 3 only.
523 """
523 """
524 if len(text)<2:
524 if len(text)<2:
525 return u'', ()
525 return u'', ()
526 maybe_slash = text[-2]
526 maybe_slash = text[-2]
527 if maybe_slash != '\\':
527 if maybe_slash != '\\':
528 return u'', ()
528 return u'', ()
529
529
530
530
531 char = text[-1]
531 char = text[-1]
532 # no expand on quote for completion in strings.
532 # no expand on quote for completion in strings.
533 # nor backcomplete standard ascii keys
533 # nor backcomplete standard ascii keys
534 if char in string.ascii_letters or char in ['"',"'"]:
534 if char in string.ascii_letters or char in ['"',"'"]:
535 return u'', ()
535 return u'', ()
536 try :
536 try :
537 latex = reverse_latex_symbol[char]
537 latex = reverse_latex_symbol[char]
538 # '\\' replace the \ as well
538 # '\\' replace the \ as well
539 return '\\'+char,[latex]
539 return '\\'+char,[latex]
540 except KeyError:
540 except KeyError:
541 pass
541 pass
542 return u'', ()
542 return u'', ()
543
543
544
544
545 class IPCompleter(Completer):
545 class IPCompleter(Completer):
546 """Extension of the completer class with IPython-specific features"""
546 """Extension of the completer class with IPython-specific features"""
547
547
548 @observe('greedy')
548 @observe('greedy')
549 def _greedy_changed(self, change):
549 def _greedy_changed(self, change):
550 """update the splitter and readline delims when greedy is changed"""
550 """update the splitter and readline delims when greedy is changed"""
551 if change['new']:
551 if change['new']:
552 self.splitter.delims = GREEDY_DELIMS
552 self.splitter.delims = GREEDY_DELIMS
553 else:
553 else:
554 self.splitter.delims = DELIMS
554 self.splitter.delims = DELIMS
555
555
556 merge_completions = Bool(True,
556 merge_completions = Bool(True,
557 help="""Whether to merge completion results into a single list
557 help="""Whether to merge completion results into a single list
558
558
559 If False, only the completion results from the first non-empty
559 If False, only the completion results from the first non-empty
560 completer will be returned.
560 completer will be returned.
561 """
561 """
562 ).tag(config=True)
562 ).tag(config=True)
563 omit__names = Enum((0,1,2), default_value=2,
563 omit__names = Enum((0,1,2), default_value=2,
564 help="""Instruct the completer to omit private method names
564 help="""Instruct the completer to omit private method names
565
565
566 Specifically, when completing on ``object.<tab>``.
566 Specifically, when completing on ``object.<tab>``.
567
567
568 When 2 [default]: all names that start with '_' will be excluded.
568 When 2 [default]: all names that start with '_' will be excluded.
569
569
570 When 1: all 'magic' names (``__foo__``) will be excluded.
570 When 1: all 'magic' names (``__foo__``) will be excluded.
571
571
572 When 0: nothing will be excluded.
572 When 0: nothing will be excluded.
573 """
573 """
574 ).tag(config=True)
574 ).tag(config=True)
575 limit_to__all__ = Bool(False,
575 limit_to__all__ = Bool(False,
576 help="""
576 help="""
577 DEPRECATED as of version 5.0.
577 DEPRECATED as of version 5.0.
578
578
579 Instruct the completer to use __all__ for the completion
579 Instruct the completer to use __all__ for the completion
580
580
581 Specifically, when completing on ``object.<tab>``.
581 Specifically, when completing on ``object.<tab>``.
582
582
583 When True: only those names in obj.__all__ will be included.
583 When True: only those names in obj.__all__ will be included.
584
584
585 When False [default]: the __all__ attribute is ignored
585 When False [default]: the __all__ attribute is ignored
586 """,
586 """,
587 ).tag(config=True)
587 ).tag(config=True)
588
588
589 def __init__(self, shell=None, namespace=None, global_namespace=None,
589 def __init__(self, shell=None, namespace=None, global_namespace=None,
590 use_readline=False, config=None, **kwargs):
590 use_readline=False, config=None, **kwargs):
591 """IPCompleter() -> completer
591 """IPCompleter() -> completer
592
592
593 Return a completer object suitable for use by the readline library
593 Return a completer object suitable for use by the readline library
594 via readline.set_completer().
594 via readline.set_completer().
595
595
596 Inputs:
596 Inputs:
597
597
598 - shell: a pointer to the ipython shell itself. This is needed
598 - shell: a pointer to the ipython shell itself. This is needed
599 because this completer knows about magic functions, and those can
599 because this completer knows about magic functions, and those can
600 only be accessed via the ipython instance.
600 only be accessed via the ipython instance.
601
601
602 - namespace: an optional dict where completions are performed.
602 - namespace: an optional dict where completions are performed.
603
603
604 - global_namespace: secondary optional dict for completions, to
604 - global_namespace: secondary optional dict for completions, to
605 handle cases (such as IPython embedded inside functions) where
605 handle cases (such as IPython embedded inside functions) where
606 both Python scopes are visible.
606 both Python scopes are visible.
607
607
608 use_readline : bool, optional
608 use_readline : bool, optional
609 DEPRECATED, ignored.
609 DEPRECATED, ignored.
610 """
610 """
611
611
612 self.magic_escape = ESC_MAGIC
612 self.magic_escape = ESC_MAGIC
613 self.splitter = CompletionSplitter()
613 self.splitter = CompletionSplitter()
614
614
615 if use_readline:
615 if use_readline:
616 warnings.warn('The use_readline parameter is deprecated and ignored since IPython 6.0.',
616 warnings.warn('The use_readline parameter is deprecated and ignored since IPython 6.0.',
617 DeprecationWarning, stacklevel=2)
617 DeprecationWarning, stacklevel=2)
618
618
619 # _greedy_changed() depends on splitter and readline being defined:
619 # _greedy_changed() depends on splitter and readline being defined:
620 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
620 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
621 config=config, **kwargs)
621 config=config, **kwargs)
622
622
623 # List where completion matches will be stored
623 # List where completion matches will be stored
624 self.matches = []
624 self.matches = []
625 self.shell = shell
625 self.shell = shell
626 # Regexp to split filenames with spaces in them
626 # Regexp to split filenames with spaces in them
627 self.space_name_re = re.compile(r'([^\\] )')
627 self.space_name_re = re.compile(r'([^\\] )')
628 # Hold a local ref. to glob.glob for speed
628 # Hold a local ref. to glob.glob for speed
629 self.glob = glob.glob
629 self.glob = glob.glob
630
630
631 # Determine if we are running on 'dumb' terminals, like (X)Emacs
631 # Determine if we are running on 'dumb' terminals, like (X)Emacs
632 # buffers, to avoid completion problems.
632 # buffers, to avoid completion problems.
633 term = os.environ.get('TERM','xterm')
633 term = os.environ.get('TERM','xterm')
634 self.dumb_terminal = term in ['dumb','emacs']
634 self.dumb_terminal = term in ['dumb','emacs']
635
635
636 # Special handling of backslashes needed in win32 platforms
636 # Special handling of backslashes needed in win32 platforms
637 if sys.platform == "win32":
637 if sys.platform == "win32":
638 self.clean_glob = self._clean_glob_win32
638 self.clean_glob = self._clean_glob_win32
639 else:
639 else:
640 self.clean_glob = self._clean_glob
640 self.clean_glob = self._clean_glob
641
641
642 #regexp to parse docstring for function signature
642 #regexp to parse docstring for function signature
643 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
643 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
644 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
644 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
645 #use this if positional argument name is also needed
645 #use this if positional argument name is also needed
646 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
646 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
647
647
648 # All active matcher routines for completion
648 # All active matcher routines for completion
649 self.matchers = [
649 self.matchers = [
650 self.python_matches,
650 self.python_matches,
651 self.file_matches,
651 self.file_matches,
652 self.magic_matches,
652 self.magic_matches,
653 self.python_func_kw_matches,
653 self.python_func_kw_matches,
654 self.dict_key_matches,
654 self.dict_key_matches,
655 ]
655 ]
656
656
657 # This is set externally by InteractiveShell
657 # This is set externally by InteractiveShell
658 self.custom_completers = None
658 self.custom_completers = None
659
659
660 def all_completions(self, text):
660 def all_completions(self, text):
661 """
661 """
662 Wrapper around the complete method for the benefit of emacs.
662 Wrapper around the complete method for the benefit of emacs.
663 """
663 """
664 return self.complete(text)[1]
664 return self.complete(text)[1]
665
665
666 def _clean_glob(self, text):
666 def _clean_glob(self, text):
667 return self.glob("%s*" % text)
667 return self.glob("%s*" % text)
668
668
669 def _clean_glob_win32(self,text):
669 def _clean_glob_win32(self,text):
670 return [f.replace("\\","/")
670 return [f.replace("\\","/")
671 for f in self.glob("%s*" % text)]
671 for f in self.glob("%s*" % text)]
672
672
673 def file_matches(self, text):
673 def file_matches(self, text):
674 """Match filenames, expanding ~USER type strings.
674 """Match filenames, expanding ~USER type strings.
675
675
676 Most of the seemingly convoluted logic in this completer is an
676 Most of the seemingly convoluted logic in this completer is an
677 attempt to handle filenames with spaces in them. And yet it's not
677 attempt to handle filenames with spaces in them. And yet it's not
678 quite perfect, because Python's readline doesn't expose all of the
678 quite perfect, because Python's readline doesn't expose all of the
679 GNU readline details needed for this to be done correctly.
679 GNU readline details needed for this to be done correctly.
680
680
681 For a filename with a space in it, the printed completions will be
681 For a filename with a space in it, the printed completions will be
682 only the parts after what's already been typed (instead of the
682 only the parts after what's already been typed (instead of the
683 full completions, as is normally done). I don't think with the
683 full completions, as is normally done). I don't think with the
684 current (as of Python 2.3) Python readline it's possible to do
684 current (as of Python 2.3) Python readline it's possible to do
685 better."""
685 better."""
686
686
687 # chars that require escaping with backslash - i.e. chars
687 # chars that require escaping with backslash - i.e. chars
688 # that readline treats incorrectly as delimiters, but we
688 # that readline treats incorrectly as delimiters, but we
689 # don't want to treat as delimiters in filename matching
689 # don't want to treat as delimiters in filename matching
690 # when escaped with backslash
690 # when escaped with backslash
691 if text.startswith('!'):
691 if text.startswith('!'):
692 text = text[1:]
692 text = text[1:]
693 text_prefix = u'!'
693 text_prefix = u'!'
694 else:
694 else:
695 text_prefix = u''
695 text_prefix = u''
696
696
697 text_until_cursor = self.text_until_cursor
697 text_until_cursor = self.text_until_cursor
698 # track strings with open quotes
698 # track strings with open quotes
699 open_quotes = has_open_quotes(text_until_cursor)
699 open_quotes = has_open_quotes(text_until_cursor)
700
700
701 if '(' in text_until_cursor or '[' in text_until_cursor:
701 if '(' in text_until_cursor or '[' in text_until_cursor:
702 lsplit = text
702 lsplit = text
703 else:
703 else:
704 try:
704 try:
705 # arg_split ~ shlex.split, but with unicode bugs fixed by us
705 # arg_split ~ shlex.split, but with unicode bugs fixed by us
706 lsplit = arg_split(text_until_cursor)[-1]
706 lsplit = arg_split(text_until_cursor)[-1]
707 except ValueError:
707 except ValueError:
708 # typically an unmatched ", or backslash without escaped char.
708 # typically an unmatched ", or backslash without escaped char.
709 if open_quotes:
709 if open_quotes:
710 lsplit = text_until_cursor.split(open_quotes)[-1]
710 lsplit = text_until_cursor.split(open_quotes)[-1]
711 else:
711 else:
712 return []
712 return []
713 except IndexError:
713 except IndexError:
714 # tab pressed on empty line
714 # tab pressed on empty line
715 lsplit = ""
715 lsplit = ""
716
716
717 if not open_quotes and lsplit != protect_filename(lsplit):
717 if not open_quotes and lsplit != protect_filename(lsplit):
718 # if protectables are found, do matching on the whole escaped name
718 # if protectables are found, do matching on the whole escaped name
719 has_protectables = True
719 has_protectables = True
720 text0,text = text,lsplit
720 text0,text = text,lsplit
721 else:
721 else:
722 has_protectables = False
722 has_protectables = False
723 text = os.path.expanduser(text)
723 text = os.path.expanduser(text)
724
724
725 if text == "":
725 if text == "":
726 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
726 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
727
727
728 # Compute the matches from the filesystem
728 # Compute the matches from the filesystem
729 if sys.platform == 'win32':
729 if sys.platform == 'win32':
730 m0 = self.clean_glob(text)
730 m0 = self.clean_glob(text)
731 else:
731 else:
732 m0 = self.clean_glob(text.replace('\\', ''))
732 m0 = self.clean_glob(text.replace('\\', ''))
733
733
734 if has_protectables:
734 if has_protectables:
735 # If we had protectables, we need to revert our changes to the
735 # If we had protectables, we need to revert our changes to the
736 # beginning of filename so that we don't double-write the part
736 # beginning of filename so that we don't double-write the part
737 # of the filename we have so far
737 # of the filename we have so far
738 len_lsplit = len(lsplit)
738 len_lsplit = len(lsplit)
739 matches = [text_prefix + text0 +
739 matches = [text_prefix + text0 +
740 protect_filename(f[len_lsplit:]) for f in m0]
740 protect_filename(f[len_lsplit:]) for f in m0]
741 else:
741 else:
742 if open_quotes:
742 if open_quotes:
743 # if we have a string with an open quote, we don't need to
743 # if we have a string with an open quote, we don't need to
744 # protect the names at all (and we _shouldn't_, as it
744 # protect the names at all (and we _shouldn't_, as it
745 # would cause bugs when the filesystem call is made).
745 # would cause bugs when the filesystem call is made).
746 matches = m0
746 matches = m0
747 else:
747 else:
748 matches = [text_prefix +
748 matches = [text_prefix +
749 protect_filename(f) for f in m0]
749 protect_filename(f) for f in m0]
750
750
751 # Mark directories in input list by appending '/' to their names.
751 # Mark directories in input list by appending '/' to their names.
752 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
752 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
753
753
754 def magic_matches(self, text):
754 def magic_matches(self, text):
755 """Match magics"""
755 """Match magics"""
756 # Get all shell magics now rather than statically, so magics loaded at
756 # Get all shell magics now rather than statically, so magics loaded at
757 # runtime show up too.
757 # runtime show up too.
758 lsm = self.shell.magics_manager.lsmagic()
758 lsm = self.shell.magics_manager.lsmagic()
759 line_magics = lsm['line']
759 line_magics = lsm['line']
760 cell_magics = lsm['cell']
760 cell_magics = lsm['cell']
761 pre = self.magic_escape
761 pre = self.magic_escape
762 pre2 = pre+pre
762 pre2 = pre+pre
763
763
764 # Completion logic:
764 # Completion logic:
765 # - user gives %%: only do cell magics
765 # - user gives %%: only do cell magics
766 # - user gives %: do both line and cell magics
766 # - user gives %: do both line and cell magics
767 # - no prefix: do both
767 # - no prefix: do both
768 # In other words, line magics are skipped if the user gives %% explicitly
768 # In other words, line magics are skipped if the user gives %% explicitly
769 bare_text = text.lstrip(pre)
769 bare_text = text.lstrip(pre)
770 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
770 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
771 if not text.startswith(pre2):
771 if not text.startswith(pre2):
772 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
772 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
773 return [cast_unicode_py2(c) for c in comp]
773 return [cast_unicode_py2(c) for c in comp]
774
774
775
775
776 def python_matches(self, text):
776 def python_matches(self, text):
777 """Match attributes or global python names"""
777 """Match attributes or global python names"""
778 if "." in text:
778 if "." in text:
779 try:
779 try:
780 matches = self.attr_matches(text)
780 matches = self.attr_matches(text)
781 if text.endswith('.') and self.omit__names:
781 if text.endswith('.') and self.omit__names:
782 if self.omit__names == 1:
782 if self.omit__names == 1:
783 # true if txt is _not_ a __ name, false otherwise:
783 # true if txt is _not_ a __ name, false otherwise:
784 no__name = (lambda txt:
784 no__name = (lambda txt:
785 re.match(r'.*\.__.*?__',txt) is None)
785 re.match(r'.*\.__.*?__',txt) is None)
786 else:
786 else:
787 # true if txt is _not_ a _ name, false otherwise:
787 # true if txt is _not_ a _ name, false otherwise:
788 no__name = (lambda txt:
788 no__name = (lambda txt:
789 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
789 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
790 matches = filter(no__name, matches)
790 matches = filter(no__name, matches)
791 except NameError:
791 except NameError:
792 # catches <undefined attributes>.<tab>
792 # catches <undefined attributes>.<tab>
793 matches = []
793 matches = []
794 else:
794 else:
795 matches = self.global_matches(text)
795 matches = self.global_matches(text)
796 return matches
796 return matches
797
797
798 def _default_arguments_from_docstring(self, doc):
798 def _default_arguments_from_docstring(self, doc):
799 """Parse the first line of docstring for call signature.
799 """Parse the first line of docstring for call signature.
800
800
801 Docstring should be of the form 'min(iterable[, key=func])\n'.
801 Docstring should be of the form 'min(iterable[, key=func])\n'.
802 It can also parse cython docstring of the form
802 It can also parse cython docstring of the form
803 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
803 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
804 """
804 """
805 if doc is None:
805 if doc is None:
806 return []
806 return []
807
807
808 #care only the firstline
808 #care only the firstline
809 line = doc.lstrip().splitlines()[0]
809 line = doc.lstrip().splitlines()[0]
810
810
811 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
811 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
812 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
812 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
813 sig = self.docstring_sig_re.search(line)
813 sig = self.docstring_sig_re.search(line)
814 if sig is None:
814 if sig is None:
815 return []
815 return []
816 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
816 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
817 sig = sig.groups()[0].split(',')
817 sig = sig.groups()[0].split(',')
818 ret = []
818 ret = []
819 for s in sig:
819 for s in sig:
820 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
820 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
821 ret += self.docstring_kwd_re.findall(s)
821 ret += self.docstring_kwd_re.findall(s)
822 return ret
822 return ret
823
823
824 def _default_arguments(self, obj):
824 def _default_arguments(self, obj):
825 """Return the list of default arguments of obj if it is callable,
825 """Return the list of default arguments of obj if it is callable,
826 or empty list otherwise."""
826 or empty list otherwise."""
827 call_obj = obj
827 call_obj = obj
828 ret = []
828 ret = []
829 if inspect.isbuiltin(obj):
829 if inspect.isbuiltin(obj):
830 pass
830 pass
831 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
831 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
832 if inspect.isclass(obj):
832 if inspect.isclass(obj):
833 #for cython embededsignature=True the constructor docstring
833 #for cython embededsignature=True the constructor docstring
834 #belongs to the object itself not __init__
834 #belongs to the object itself not __init__
835 ret += self._default_arguments_from_docstring(
835 ret += self._default_arguments_from_docstring(
836 getattr(obj, '__doc__', ''))
836 getattr(obj, '__doc__', ''))
837 # for classes, check for __init__,__new__
837 # for classes, check for __init__,__new__
838 call_obj = (getattr(obj, '__init__', None) or
838 call_obj = (getattr(obj, '__init__', None) or
839 getattr(obj, '__new__', None))
839 getattr(obj, '__new__', None))
840 # for all others, check if they are __call__able
840 # for all others, check if they are __call__able
841 elif hasattr(obj, '__call__'):
841 elif hasattr(obj, '__call__'):
842 call_obj = obj.__call__
842 call_obj = obj.__call__
843 ret += self._default_arguments_from_docstring(
843 ret += self._default_arguments_from_docstring(
844 getattr(call_obj, '__doc__', ''))
844 getattr(call_obj, '__doc__', ''))
845
845
846 _keeps = (inspect.Parameter.KEYWORD_ONLY,
846 _keeps = (inspect.Parameter.KEYWORD_ONLY,
847 inspect.Parameter.POSITIONAL_OR_KEYWORD)
847 inspect.Parameter.POSITIONAL_OR_KEYWORD)
848
848
849 try:
849 try:
850 sig = inspect.signature(call_obj)
850 sig = inspect.signature(call_obj)
851 ret.extend(k for k, v in sig.parameters.items() if
851 ret.extend(k for k, v in sig.parameters.items() if
852 v.kind in _keeps)
852 v.kind in _keeps)
853 except ValueError:
853 except ValueError:
854 pass
854 pass
855
855
856 return list(set(ret))
856 return list(set(ret))
857
857
858 def python_func_kw_matches(self,text):
858 def python_func_kw_matches(self,text):
859 """Match named parameters (kwargs) of the last open function"""
859 """Match named parameters (kwargs) of the last open function"""
860
860
861 if "." in text: # a parameter cannot be dotted
861 if "." in text: # a parameter cannot be dotted
862 return []
862 return []
863 try: regexp = self.__funcParamsRegex
863 try: regexp = self.__funcParamsRegex
864 except AttributeError:
864 except AttributeError:
865 regexp = self.__funcParamsRegex = re.compile(r'''
865 regexp = self.__funcParamsRegex = re.compile(r'''
866 '.*?(?<!\\)' | # single quoted strings or
866 '.*?(?<!\\)' | # single quoted strings or
867 ".*?(?<!\\)" | # double quoted strings or
867 ".*?(?<!\\)" | # double quoted strings or
868 \w+ | # identifier
868 \w+ | # identifier
869 \S # other characters
869 \S # other characters
870 ''', re.VERBOSE | re.DOTALL)
870 ''', re.VERBOSE | re.DOTALL)
871 # 1. find the nearest identifier that comes before an unclosed
871 # 1. find the nearest identifier that comes before an unclosed
872 # parenthesis before the cursor
872 # parenthesis before the cursor
873 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
873 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
874 tokens = regexp.findall(self.text_until_cursor)
874 tokens = regexp.findall(self.text_until_cursor)
875 iterTokens = reversed(tokens); openPar = 0
875 iterTokens = reversed(tokens); openPar = 0
876
876
877 for token in iterTokens:
877 for token in iterTokens:
878 if token == ')':
878 if token == ')':
879 openPar -= 1
879 openPar -= 1
880 elif token == '(':
880 elif token == '(':
881 openPar += 1
881 openPar += 1
882 if openPar > 0:
882 if openPar > 0:
883 # found the last unclosed parenthesis
883 # found the last unclosed parenthesis
884 break
884 break
885 else:
885 else:
886 return []
886 return []
887 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
887 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
888 ids = []
888 ids = []
889 isId = re.compile(r'\w+$').match
889 isId = re.compile(r'\w+$').match
890
890
891 while True:
891 while True:
892 try:
892 try:
893 ids.append(next(iterTokens))
893 ids.append(next(iterTokens))
894 if not isId(ids[-1]):
894 if not isId(ids[-1]):
895 ids.pop(); break
895 ids.pop(); break
896 if not next(iterTokens) == '.':
896 if not next(iterTokens) == '.':
897 break
897 break
898 except StopIteration:
898 except StopIteration:
899 break
899 break
900
900
901 # Find all named arguments already assigned to, as to avoid suggesting
901 # Find all named arguments already assigned to, as to avoid suggesting
902 # them again
902 # them again
903 usedNamedArgs = set()
903 usedNamedArgs = set()
904 par_level = -1
904 par_level = -1
905 for token, next_token in zip(tokens, tokens[1:]):
905 for token, next_token in zip(tokens, tokens[1:]):
906 if token == '(':
906 if token == '(':
907 par_level += 1
907 par_level += 1
908 elif token == ')':
908 elif token == ')':
909 par_level -= 1
909 par_level -= 1
910
910
911 if par_level != 0:
911 if par_level != 0:
912 continue
912 continue
913
913
914 if next_token != '=':
914 if next_token != '=':
915 continue
915 continue
916
916
917 usedNamedArgs.add(token)
917 usedNamedArgs.add(token)
918
918
919 # lookup the candidate callable matches either using global_matches
919 # lookup the candidate callable matches either using global_matches
920 # or attr_matches for dotted names
920 # or attr_matches for dotted names
921 if len(ids) == 1:
921 if len(ids) == 1:
922 callableMatches = self.global_matches(ids[0])
922 callableMatches = self.global_matches(ids[0])
923 else:
923 else:
924 callableMatches = self.attr_matches('.'.join(ids[::-1]))
924 callableMatches = self.attr_matches('.'.join(ids[::-1]))
925 argMatches = []
925 argMatches = []
926 for callableMatch in callableMatches:
926 for callableMatch in callableMatches:
927 try:
927 try:
928 namedArgs = self._default_arguments(eval(callableMatch,
928 namedArgs = self._default_arguments(eval(callableMatch,
929 self.namespace))
929 self.namespace))
930 except:
930 except:
931 continue
931 continue
932
932
933 # Remove used named arguments from the list, no need to show twice
933 # Remove used named arguments from the list, no need to show twice
934 for namedArg in set(namedArgs) - usedNamedArgs:
934 for namedArg in set(namedArgs) - usedNamedArgs:
935 if namedArg.startswith(text):
935 if namedArg.startswith(text):
936 argMatches.append(u"%s=" %namedArg)
936 argMatches.append(u"%s=" %namedArg)
937 return argMatches
937 return argMatches
938
938
939 def dict_key_matches(self, text):
939 def dict_key_matches(self, text):
940 "Match string keys in a dictionary, after e.g. 'foo[' "
940 "Match string keys in a dictionary, after e.g. 'foo[' "
941 def get_keys(obj):
941 def get_keys(obj):
942 # Objects can define their own completions by defining an
942 # Objects can define their own completions by defining an
943 # _ipy_key_completions_() method.
943 # _ipy_key_completions_() method.
944 method = get_real_method(obj, '_ipython_key_completions_')
944 method = get_real_method(obj, '_ipython_key_completions_')
945 if method is not None:
945 if method is not None:
946 return method()
946 return method()
947
947
948 # Special case some common in-memory dict-like types
948 # Special case some common in-memory dict-like types
949 if isinstance(obj, dict) or\
949 if isinstance(obj, dict) or\
950 _safe_isinstance(obj, 'pandas', 'DataFrame'):
950 _safe_isinstance(obj, 'pandas', 'DataFrame'):
951 try:
951 try:
952 return list(obj.keys())
952 return list(obj.keys())
953 except Exception:
953 except Exception:
954 return []
954 return []
955 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
955 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
956 _safe_isinstance(obj, 'numpy', 'void'):
956 _safe_isinstance(obj, 'numpy', 'void'):
957 return obj.dtype.names or []
957 return obj.dtype.names or []
958 return []
958 return []
959
959
960 try:
960 try:
961 regexps = self.__dict_key_regexps
961 regexps = self.__dict_key_regexps
962 except AttributeError:
962 except AttributeError:
963 dict_key_re_fmt = r'''(?x)
963 dict_key_re_fmt = r'''(?x)
964 ( # match dict-referring expression wrt greedy setting
964 ( # match dict-referring expression wrt greedy setting
965 %s
965 %s
966 )
966 )
967 \[ # open bracket
967 \[ # open bracket
968 \s* # and optional whitespace
968 \s* # and optional whitespace
969 ([uUbB]? # string prefix (r not handled)
969 ([uUbB]? # string prefix (r not handled)
970 (?: # unclosed string
970 (?: # unclosed string
971 '(?:[^']|(?<!\\)\\')*
971 '(?:[^']|(?<!\\)\\')*
972 |
972 |
973 "(?:[^"]|(?<!\\)\\")*
973 "(?:[^"]|(?<!\\)\\")*
974 )
974 )
975 )?
975 )?
976 $
976 $
977 '''
977 '''
978 regexps = self.__dict_key_regexps = {
978 regexps = self.__dict_key_regexps = {
979 False: re.compile(dict_key_re_fmt % '''
979 False: re.compile(dict_key_re_fmt % '''
980 # identifiers separated by .
980 # identifiers separated by .
981 (?!\d)\w+
981 (?!\d)\w+
982 (?:\.(?!\d)\w+)*
982 (?:\.(?!\d)\w+)*
983 '''),
983 '''),
984 True: re.compile(dict_key_re_fmt % '''
984 True: re.compile(dict_key_re_fmt % '''
985 .+
985 .+
986 ''')
986 ''')
987 }
987 }
988
988
989 match = regexps[self.greedy].search(self.text_until_cursor)
989 match = regexps[self.greedy].search(self.text_until_cursor)
990 if match is None:
990 if match is None:
991 return []
991 return []
992
992
993 expr, prefix = match.groups()
993 expr, prefix = match.groups()
994 try:
994 try:
995 obj = eval(expr, self.namespace)
995 obj = eval(expr, self.namespace)
996 except Exception:
996 except Exception:
997 try:
997 try:
998 obj = eval(expr, self.global_namespace)
998 obj = eval(expr, self.global_namespace)
999 except Exception:
999 except Exception:
1000 return []
1000 return []
1001
1001
1002 keys = get_keys(obj)
1002 keys = get_keys(obj)
1003 if not keys:
1003 if not keys:
1004 return keys
1004 return keys
1005 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1005 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1006 if not matches:
1006 if not matches:
1007 return matches
1007 return matches
1008
1008
1009 # get the cursor position of
1009 # get the cursor position of
1010 # - the text being completed
1010 # - the text being completed
1011 # - the start of the key text
1011 # - the start of the key text
1012 # - the start of the completion
1012 # - the start of the completion
1013 text_start = len(self.text_until_cursor) - len(text)
1013 text_start = len(self.text_until_cursor) - len(text)
1014 if prefix:
1014 if prefix:
1015 key_start = match.start(2)
1015 key_start = match.start(2)
1016 completion_start = key_start + token_offset
1016 completion_start = key_start + token_offset
1017 else:
1017 else:
1018 key_start = completion_start = match.end()
1018 key_start = completion_start = match.end()
1019
1019
1020 # grab the leading prefix, to make sure all completions start with `text`
1020 # grab the leading prefix, to make sure all completions start with `text`
1021 if text_start > key_start:
1021 if text_start > key_start:
1022 leading = ''
1022 leading = ''
1023 else:
1023 else:
1024 leading = text[text_start:completion_start]
1024 leading = text[text_start:completion_start]
1025
1025
1026 # the index of the `[` character
1026 # the index of the `[` character
1027 bracket_idx = match.end(1)
1027 bracket_idx = match.end(1)
1028
1028
1029 # append closing quote and bracket as appropriate
1029 # append closing quote and bracket as appropriate
1030 # this is *not* appropriate if the opening quote or bracket is outside
1030 # this is *not* appropriate if the opening quote or bracket is outside
1031 # the text given to this method
1031 # the text given to this method
1032 suf = ''
1032 suf = ''
1033 continuation = self.line_buffer[len(self.text_until_cursor):]
1033 continuation = self.line_buffer[len(self.text_until_cursor):]
1034 if key_start > text_start and closing_quote:
1034 if key_start > text_start and closing_quote:
1035 # quotes were opened inside text, maybe close them
1035 # quotes were opened inside text, maybe close them
1036 if continuation.startswith(closing_quote):
1036 if continuation.startswith(closing_quote):
1037 continuation = continuation[len(closing_quote):]
1037 continuation = continuation[len(closing_quote):]
1038 else:
1038 else:
1039 suf += closing_quote
1039 suf += closing_quote
1040 if bracket_idx > text_start:
1040 if bracket_idx > text_start:
1041 # brackets were opened inside text, maybe close them
1041 # brackets were opened inside text, maybe close them
1042 if not continuation.startswith(']'):
1042 if not continuation.startswith(']'):
1043 suf += ']'
1043 suf += ']'
1044
1044
1045 return [leading + k + suf for k in matches]
1045 return [leading + k + suf for k in matches]
1046
1046
1047 def unicode_name_matches(self, text):
1047 def unicode_name_matches(self, text):
1048 u"""Match Latex-like syntax for unicode characters base
1048 u"""Match Latex-like syntax for unicode characters base
1049 on the name of the character.
1049 on the name of the character.
1050
1050
1051 This does \\GREEK SMALL LETTER ETA -> η
1051 This does \\GREEK SMALL LETTER ETA -> η
1052
1052
1053 Works only on valid python 3 identifier, or on combining characters that
1053 Works only on valid python 3 identifier, or on combining characters that
1054 will combine to form a valid identifier.
1054 will combine to form a valid identifier.
1055
1055
1056 Used on Python 3 only.
1056 Used on Python 3 only.
1057 """
1057 """
1058 slashpos = text.rfind('\\')
1058 slashpos = text.rfind('\\')
1059 if slashpos > -1:
1059 if slashpos > -1:
1060 s = text[slashpos+1:]
1060 s = text[slashpos+1:]
1061 try :
1061 try :
1062 unic = unicodedata.lookup(s)
1062 unic = unicodedata.lookup(s)
1063 # allow combining chars
1063 # allow combining chars
1064 if ('a'+unic).isidentifier():
1064 if ('a'+unic).isidentifier():
1065 return '\\'+s,[unic]
1065 return '\\'+s,[unic]
1066 except KeyError:
1066 except KeyError:
1067 pass
1067 pass
1068 return u'', []
1068 return u'', []
1069
1069
1070
1070
1071
1071
1072
1072
1073 def latex_matches(self, text):
1073 def latex_matches(self, text):
1074 u"""Match Latex syntax for unicode characters.
1074 u"""Match Latex syntax for unicode characters.
1075
1075
1076 This does both \\alp -> \\alpha and \\alpha -> α
1076 This does both \\alp -> \\alpha and \\alpha -> α
1077
1077
1078 Used on Python 3 only.
1078 Used on Python 3 only.
1079 """
1079 """
1080 slashpos = text.rfind('\\')
1080 slashpos = text.rfind('\\')
1081 if slashpos > -1:
1081 if slashpos > -1:
1082 s = text[slashpos:]
1082 s = text[slashpos:]
1083 if s in latex_symbols:
1083 if s in latex_symbols:
1084 # Try to complete a full latex symbol to unicode
1084 # Try to complete a full latex symbol to unicode
1085 # \\alpha -> α
1085 # \\alpha -> α
1086 return s, [latex_symbols[s]]
1086 return s, [latex_symbols[s]]
1087 else:
1087 else:
1088 # If a user has partially typed a latex symbol, give them
1088 # If a user has partially typed a latex symbol, give them
1089 # a full list of options \al -> [\aleph, \alpha]
1089 # a full list of options \al -> [\aleph, \alpha]
1090 matches = [k for k in latex_symbols if k.startswith(s)]
1090 matches = [k for k in latex_symbols if k.startswith(s)]
1091 return s, matches
1091 return s, matches
1092 return u'', []
1092 return u'', []
1093
1093
1094 def dispatch_custom_completer(self, text):
1094 def dispatch_custom_completer(self, text):
1095 if not self.custom_completers:
1095 if not self.custom_completers:
1096 return
1096 return
1097
1097
1098 line = self.line_buffer
1098 line = self.line_buffer
1099 if not line.strip():
1099 if not line.strip():
1100 return None
1100 return None
1101
1101
1102 # Create a little structure to pass all the relevant information about
1102 # Create a little structure to pass all the relevant information about
1103 # the current completion to any custom completer.
1103 # the current completion to any custom completer.
1104 event = Bunch()
1104 event = Bunch()
1105 event.line = line
1105 event.line = line
1106 event.symbol = text
1106 event.symbol = text
1107 cmd = line.split(None,1)[0]
1107 cmd = line.split(None,1)[0]
1108 event.command = cmd
1108 event.command = cmd
1109 event.text_until_cursor = self.text_until_cursor
1109 event.text_until_cursor = self.text_until_cursor
1110
1110
1111 # for foo etc, try also to find completer for %foo
1111 # for foo etc, try also to find completer for %foo
1112 if not cmd.startswith(self.magic_escape):
1112 if not cmd.startswith(self.magic_escape):
1113 try_magic = self.custom_completers.s_matches(
1113 try_magic = self.custom_completers.s_matches(
1114 self.magic_escape + cmd)
1114 self.magic_escape + cmd)
1115 else:
1115 else:
1116 try_magic = []
1116 try_magic = []
1117
1117
1118 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1118 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1119 try_magic,
1119 try_magic,
1120 self.custom_completers.flat_matches(self.text_until_cursor)):
1120 self.custom_completers.flat_matches(self.text_until_cursor)):
1121 try:
1121 try:
1122 res = c(event)
1122 res = c(event)
1123 if res:
1123 if res:
1124 # first, try case sensitive match
1124 # first, try case sensitive match
1125 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1125 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1126 if withcase:
1126 if withcase:
1127 return withcase
1127 return withcase
1128 # if none, then case insensitive ones are ok too
1128 # if none, then case insensitive ones are ok too
1129 text_low = text.lower()
1129 text_low = text.lower()
1130 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1130 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1131 except TryNext:
1131 except TryNext:
1132 pass
1132 pass
1133
1133
1134 return None
1134 return None
1135
1135
1136 @_strip_single_trailing_space
1136 @_strip_single_trailing_space
1137 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1137 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1138 """Find completions for the given text and line context.
1138 """Find completions for the given text and line context.
1139
1139
1140 Note that both the text and the line_buffer are optional, but at least
1140 Note that both the text and the line_buffer are optional, but at least
1141 one of them must be given.
1141 one of them must be given.
1142
1142
1143 Parameters
1143 Parameters
1144 ----------
1144 ----------
1145 text : string, optional
1145 text : string, optional
1146 Text to perform the completion on. If not given, the line buffer
1146 Text to perform the completion on. If not given, the line buffer
1147 is split using the instance's CompletionSplitter object.
1147 is split using the instance's CompletionSplitter object.
1148
1148
1149 line_buffer : string, optional
1149 line_buffer : string, optional
1150 If not given, the completer attempts to obtain the current line
1150 If not given, the completer attempts to obtain the current line
1151 buffer via readline. This keyword allows clients which are
1151 buffer via readline. This keyword allows clients which are
1152 requesting for text completions in non-readline contexts to inform
1152 requesting for text completions in non-readline contexts to inform
1153 the completer of the entire text.
1153 the completer of the entire text.
1154
1154
1155 cursor_pos : int, optional
1155 cursor_pos : int, optional
1156 Index of the cursor in the full line buffer. Should be provided by
1156 Index of the cursor in the full line buffer. Should be provided by
1157 remote frontends where kernel has no access to frontend state.
1157 remote frontends where kernel has no access to frontend state.
1158
1158
1159 Returns
1159 Returns
1160 -------
1160 -------
1161 text : str
1161 text : str
1162 Text that was actually used in the completion.
1162 Text that was actually used in the completion.
1163
1163
1164 matches : list
1164 matches : list
1165 A list of completion matches.
1165 A list of completion matches.
1166 """
1166 """
1167 # if the cursor position isn't given, the only sane assumption we can
1167 # if the cursor position isn't given, the only sane assumption we can
1168 # make is that it's at the end of the line (the common case)
1168 # make is that it's at the end of the line (the common case)
1169 if cursor_pos is None:
1169 if cursor_pos is None:
1170 cursor_pos = len(line_buffer) if text is None else len(text)
1170 cursor_pos = len(line_buffer) if text is None else len(text)
1171
1171
1172 if self.use_main_ns:
1172 if self.use_main_ns:
1173 self.namespace = __main__.__dict__
1173 self.namespace = __main__.__dict__
1174
1174
1175 if PY3:
1175 if PY3:
1176
1176
1177 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1177 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1178 latex_text, latex_matches = self.latex_matches(base_text)
1178 latex_text, latex_matches = self.latex_matches(base_text)
1179 if latex_matches:
1179 if latex_matches:
1180 return latex_text, latex_matches
1180 return latex_text, latex_matches
1181 name_text = ''
1181 name_text = ''
1182 name_matches = []
1182 name_matches = []
1183 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1183 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1184 name_text, name_matches = meth(base_text)
1184 name_text, name_matches = meth(base_text)
1185 if name_text:
1185 if name_text:
1186 return name_text, name_matches
1186 return name_text, name_matches
1187
1187
1188 # if text is either None or an empty string, rely on the line buffer
1188 # if text is either None or an empty string, rely on the line buffer
1189 if not text:
1189 if not text:
1190 text = self.splitter.split_line(line_buffer, cursor_pos)
1190 text = self.splitter.split_line(line_buffer, cursor_pos)
1191
1191
1192 # If no line buffer is given, assume the input text is all there was
1192 # If no line buffer is given, assume the input text is all there was
1193 if line_buffer is None:
1193 if line_buffer is None:
1194 line_buffer = text
1194 line_buffer = text
1195
1195
1196 self.line_buffer = line_buffer
1196 self.line_buffer = line_buffer
1197 self.text_until_cursor = self.line_buffer[:cursor_pos]
1197 self.text_until_cursor = self.line_buffer[:cursor_pos]
1198
1198
1199 # Start with a clean slate of completions
1199 # Start with a clean slate of completions
1200 self.matches[:] = []
1200 self.matches[:] = []
1201 custom_res = self.dispatch_custom_completer(text)
1201 custom_res = self.dispatch_custom_completer(text)
1202 if custom_res is not None:
1202 if custom_res is not None:
1203 # did custom completers produce something?
1203 # did custom completers produce something?
1204 self.matches = custom_res
1204 self.matches = custom_res
1205 else:
1205 else:
1206 # Extend the list of completions with the results of each
1206 # Extend the list of completions with the results of each
1207 # matcher, so we return results to the user from all
1207 # matcher, so we return results to the user from all
1208 # namespaces.
1208 # namespaces.
1209 if self.merge_completions:
1209 if self.merge_completions:
1210 self.matches = []
1210 self.matches = []
1211 for matcher in self.matchers:
1211 for matcher in self.matchers:
1212 try:
1212 try:
1213 self.matches.extend(matcher(text))
1213 self.matches.extend(matcher(text))
1214 except:
1214 except:
1215 # Show the ugly traceback if the matcher causes an
1215 # Show the ugly traceback if the matcher causes an
1216 # exception, but do NOT crash the kernel!
1216 # exception, but do NOT crash the kernel!
1217 sys.excepthook(*sys.exc_info())
1217 sys.excepthook(*sys.exc_info())
1218 else:
1218 else:
1219 for matcher in self.matchers:
1219 for matcher in self.matchers:
1220 self.matches = matcher(text)
1220 self.matches = matcher(text)
1221 if self.matches:
1221 if self.matches:
1222 break
1222 break
1223 # FIXME: we should extend our api to return a dict with completions for
1223 # FIXME: we should extend our api to return a dict with completions for
1224 # different types of objects. The rlcomplete() method could then
1224 # different types of objects. The rlcomplete() method could then
1225 # simply collapse the dict into a list for readline, but we'd have
1225 # simply collapse the dict into a list for readline, but we'd have
1226 # richer completion semantics in other evironments.
1226 # richer completion semantics in other evironments.
1227 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1227 self.matches = sorted(set(self.matches), key=completions_sorting_key)
1228
1228
1229 return text, self.matches
1229 return text, self.matches
@@ -1,343 +1,342 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Implementations for various useful completers.
2 """Implementations for various useful completers.
3
3
4 These are all loaded by default by IPython.
4 These are all loaded by default by IPython.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2010-2011 The IPython Development Team.
7 # Copyright (C) 2010-2011 The IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the BSD License.
9 # Distributed under the terms of the BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Stdlib imports
18 # Stdlib imports
19 import glob
19 import glob
20 import inspect
20 import inspect
21 import os
21 import os
22 import re
22 import re
23 import sys
23 import sys
24 from importlib import import_module
24 from importlib import import_module
25 from importlib.machinery import all_suffixes
25 from importlib.machinery import all_suffixes
26
26
27
27
28 # Third-party imports
28 # Third-party imports
29 from time import time
29 from time import time
30 from zipimport import zipimporter
30 from zipimport import zipimporter
31
31
32 # Our own imports
32 # Our own imports
33 from IPython.core.completer import expand_user, compress_user
33 from IPython.core.completer import expand_user, compress_user
34 from IPython.core.error import TryNext
34 from IPython.core.error import TryNext
35 from IPython.utils._process_common import arg_split
35 from IPython.utils._process_common import arg_split
36 from IPython.utils.py3compat import string_types
37
36
38 # FIXME: this should be pulled in with the right call via the component system
37 # FIXME: this should be pulled in with the right call via the component system
39 from IPython import get_ipython
38 from IPython import get_ipython
40
39
41 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
42 # Globals and constants
41 # Globals and constants
43 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
44 _suffixes = all_suffixes()
43 _suffixes = all_suffixes()
45
44
46 # Time in seconds after which the rootmodules will be stored permanently in the
45 # Time in seconds after which the rootmodules will be stored permanently in the
47 # ipython ip.db database (kept in the user's .ipython dir).
46 # ipython ip.db database (kept in the user's .ipython dir).
48 TIMEOUT_STORAGE = 2
47 TIMEOUT_STORAGE = 2
49
48
50 # Time in seconds after which we give up
49 # Time in seconds after which we give up
51 TIMEOUT_GIVEUP = 20
50 TIMEOUT_GIVEUP = 20
52
51
53 # Regular expression for the python import statement
52 # Regular expression for the python import statement
54 import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)'
53 import_re = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*?)'
55 r'(?P<package>[/\\]__init__)?'
54 r'(?P<package>[/\\]__init__)?'
56 r'(?P<suffix>%s)$' %
55 r'(?P<suffix>%s)$' %
57 r'|'.join(re.escape(s) for s in _suffixes))
56 r'|'.join(re.escape(s) for s in _suffixes))
58
57
59 # RE for the ipython %run command (python + ipython scripts)
58 # RE for the ipython %run command (python + ipython scripts)
60 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
59 magic_run_re = re.compile(r'.*(\.ipy|\.ipynb|\.py[w]?)$')
61
60
62 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
63 # Local utilities
62 # Local utilities
64 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
65
64
66 def module_list(path):
65 def module_list(path):
67 """
66 """
68 Return the list containing the names of the modules available in the given
67 Return the list containing the names of the modules available in the given
69 folder.
68 folder.
70 """
69 """
71 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
70 # sys.path has the cwd as an empty string, but isdir/listdir need it as '.'
72 if path == '':
71 if path == '':
73 path = '.'
72 path = '.'
74
73
75 # A few local constants to be used in loops below
74 # A few local constants to be used in loops below
76 pjoin = os.path.join
75 pjoin = os.path.join
77
76
78 if os.path.isdir(path):
77 if os.path.isdir(path):
79 # Build a list of all files in the directory and all files
78 # Build a list of all files in the directory and all files
80 # in its subdirectories. For performance reasons, do not
79 # in its subdirectories. For performance reasons, do not
81 # recurse more than one level into subdirectories.
80 # recurse more than one level into subdirectories.
82 files = []
81 files = []
83 for root, dirs, nondirs in os.walk(path, followlinks=True):
82 for root, dirs, nondirs in os.walk(path, followlinks=True):
84 subdir = root[len(path)+1:]
83 subdir = root[len(path)+1:]
85 if subdir:
84 if subdir:
86 files.extend(pjoin(subdir, f) for f in nondirs)
85 files.extend(pjoin(subdir, f) for f in nondirs)
87 dirs[:] = [] # Do not recurse into additional subdirectories.
86 dirs[:] = [] # Do not recurse into additional subdirectories.
88 else:
87 else:
89 files.extend(nondirs)
88 files.extend(nondirs)
90
89
91 else:
90 else:
92 try:
91 try:
93 files = list(zipimporter(path)._files.keys())
92 files = list(zipimporter(path)._files.keys())
94 except:
93 except:
95 files = []
94 files = []
96
95
97 # Build a list of modules which match the import_re regex.
96 # Build a list of modules which match the import_re regex.
98 modules = []
97 modules = []
99 for f in files:
98 for f in files:
100 m = import_re.match(f)
99 m = import_re.match(f)
101 if m:
100 if m:
102 modules.append(m.group('name'))
101 modules.append(m.group('name'))
103 return list(set(modules))
102 return list(set(modules))
104
103
105
104
106 def get_root_modules():
105 def get_root_modules():
107 """
106 """
108 Returns a list containing the names of all the modules available in the
107 Returns a list containing the names of all the modules available in the
109 folders of the pythonpath.
108 folders of the pythonpath.
110
109
111 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
110 ip.db['rootmodules_cache'] maps sys.path entries to list of modules.
112 """
111 """
113 ip = get_ipython()
112 ip = get_ipython()
114 rootmodules_cache = ip.db.get('rootmodules_cache', {})
113 rootmodules_cache = ip.db.get('rootmodules_cache', {})
115 rootmodules = list(sys.builtin_module_names)
114 rootmodules = list(sys.builtin_module_names)
116 start_time = time()
115 start_time = time()
117 store = False
116 store = False
118 for path in sys.path:
117 for path in sys.path:
119 try:
118 try:
120 modules = rootmodules_cache[path]
119 modules = rootmodules_cache[path]
121 except KeyError:
120 except KeyError:
122 modules = module_list(path)
121 modules = module_list(path)
123 try:
122 try:
124 modules.remove('__init__')
123 modules.remove('__init__')
125 except ValueError:
124 except ValueError:
126 pass
125 pass
127 if path not in ('', '.'): # cwd modules should not be cached
126 if path not in ('', '.'): # cwd modules should not be cached
128 rootmodules_cache[path] = modules
127 rootmodules_cache[path] = modules
129 if time() - start_time > TIMEOUT_STORAGE and not store:
128 if time() - start_time > TIMEOUT_STORAGE and not store:
130 store = True
129 store = True
131 print("\nCaching the list of root modules, please wait!")
130 print("\nCaching the list of root modules, please wait!")
132 print("(This will only be done once - type '%rehashx' to "
131 print("(This will only be done once - type '%rehashx' to "
133 "reset cache!)\n")
132 "reset cache!)\n")
134 sys.stdout.flush()
133 sys.stdout.flush()
135 if time() - start_time > TIMEOUT_GIVEUP:
134 if time() - start_time > TIMEOUT_GIVEUP:
136 print("This is taking too long, we give up.\n")
135 print("This is taking too long, we give up.\n")
137 return []
136 return []
138 rootmodules.extend(modules)
137 rootmodules.extend(modules)
139 if store:
138 if store:
140 ip.db['rootmodules_cache'] = rootmodules_cache
139 ip.db['rootmodules_cache'] = rootmodules_cache
141 rootmodules = list(set(rootmodules))
140 rootmodules = list(set(rootmodules))
142 return rootmodules
141 return rootmodules
143
142
144
143
145 def is_importable(module, attr, only_modules):
144 def is_importable(module, attr, only_modules):
146 if only_modules:
145 if only_modules:
147 return inspect.ismodule(getattr(module, attr))
146 return inspect.ismodule(getattr(module, attr))
148 else:
147 else:
149 return not(attr[:2] == '__' and attr[-2:] == '__')
148 return not(attr[:2] == '__' and attr[-2:] == '__')
150
149
151 def try_import(mod, only_modules=False):
150 def try_import(mod, only_modules=False):
152 try:
151 try:
153 m = import_module(mod)
152 m = import_module(mod)
154 except:
153 except:
155 return []
154 return []
156
155
157 m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__
156 m_is_init = hasattr(m, '__file__') and '__init__' in m.__file__
158
157
159 completions = []
158 completions = []
160 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
159 if (not hasattr(m, '__file__')) or (not only_modules) or m_is_init:
161 completions.extend( [attr for attr in dir(m) if
160 completions.extend( [attr for attr in dir(m) if
162 is_importable(m, attr, only_modules)])
161 is_importable(m, attr, only_modules)])
163
162
164 completions.extend(getattr(m, '__all__', []))
163 completions.extend(getattr(m, '__all__', []))
165 if m_is_init:
164 if m_is_init:
166 completions.extend(module_list(os.path.dirname(m.__file__)))
165 completions.extend(module_list(os.path.dirname(m.__file__)))
167 completions = {c for c in completions if isinstance(c, string_types)}
166 completions = {c for c in completions if isinstance(c, str)}
168 completions.discard('__init__')
167 completions.discard('__init__')
169 return list(completions)
168 return list(completions)
170
169
171
170
172 #-----------------------------------------------------------------------------
171 #-----------------------------------------------------------------------------
173 # Completion-related functions.
172 # Completion-related functions.
174 #-----------------------------------------------------------------------------
173 #-----------------------------------------------------------------------------
175
174
176 def quick_completer(cmd, completions):
175 def quick_completer(cmd, completions):
177 """ Easily create a trivial completer for a command.
176 """ Easily create a trivial completer for a command.
178
177
179 Takes either a list of completions, or all completions in string (that will
178 Takes either a list of completions, or all completions in string (that will
180 be split on whitespace).
179 be split on whitespace).
181
180
182 Example::
181 Example::
183
182
184 [d:\ipython]|1> import ipy_completers
183 [d:\ipython]|1> import ipy_completers
185 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
184 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
186 [d:\ipython]|3> foo b<TAB>
185 [d:\ipython]|3> foo b<TAB>
187 bar baz
186 bar baz
188 [d:\ipython]|3> foo ba
187 [d:\ipython]|3> foo ba
189 """
188 """
190
189
191 if isinstance(completions, string_types):
190 if isinstance(completions, str):
192 completions = completions.split()
191 completions = completions.split()
193
192
194 def do_complete(self, event):
193 def do_complete(self, event):
195 return completions
194 return completions
196
195
197 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
196 get_ipython().set_hook('complete_command',do_complete, str_key = cmd)
198
197
199 def module_completion(line):
198 def module_completion(line):
200 """
199 """
201 Returns a list containing the completion possibilities for an import line.
200 Returns a list containing the completion possibilities for an import line.
202
201
203 The line looks like this :
202 The line looks like this :
204 'import xml.d'
203 'import xml.d'
205 'from xml.dom import'
204 'from xml.dom import'
206 """
205 """
207
206
208 words = line.split(' ')
207 words = line.split(' ')
209 nwords = len(words)
208 nwords = len(words)
210
209
211 # from whatever <tab> -> 'import '
210 # from whatever <tab> -> 'import '
212 if nwords == 3 and words[0] == 'from':
211 if nwords == 3 and words[0] == 'from':
213 return ['import ']
212 return ['import ']
214
213
215 # 'from xy<tab>' or 'import xy<tab>'
214 # 'from xy<tab>' or 'import xy<tab>'
216 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
215 if nwords < 3 and (words[0] in {'%aimport', 'import', 'from'}) :
217 if nwords == 1:
216 if nwords == 1:
218 return get_root_modules()
217 return get_root_modules()
219 mod = words[1].split('.')
218 mod = words[1].split('.')
220 if len(mod) < 2:
219 if len(mod) < 2:
221 return get_root_modules()
220 return get_root_modules()
222 completion_list = try_import('.'.join(mod[:-1]), True)
221 completion_list = try_import('.'.join(mod[:-1]), True)
223 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
222 return ['.'.join(mod[:-1] + [el]) for el in completion_list]
224
223
225 # 'from xyz import abc<tab>'
224 # 'from xyz import abc<tab>'
226 if nwords >= 3 and words[0] == 'from':
225 if nwords >= 3 and words[0] == 'from':
227 mod = words[1]
226 mod = words[1]
228 return try_import(mod)
227 return try_import(mod)
229
228
230 #-----------------------------------------------------------------------------
229 #-----------------------------------------------------------------------------
231 # Completers
230 # Completers
232 #-----------------------------------------------------------------------------
231 #-----------------------------------------------------------------------------
233 # These all have the func(self, event) signature to be used as custom
232 # These all have the func(self, event) signature to be used as custom
234 # completers
233 # completers
235
234
236 def module_completer(self,event):
235 def module_completer(self,event):
237 """Give completions after user has typed 'import ...' or 'from ...'"""
236 """Give completions after user has typed 'import ...' or 'from ...'"""
238
237
239 # This works in all versions of python. While 2.5 has
238 # This works in all versions of python. While 2.5 has
240 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
239 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
241 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
240 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
242 # of possibly problematic side effects.
241 # of possibly problematic side effects.
243 # This search the folders in the sys.path for available modules.
242 # This search the folders in the sys.path for available modules.
244
243
245 return module_completion(event.line)
244 return module_completion(event.line)
246
245
247 # FIXME: there's a lot of logic common to the run, cd and builtin file
246 # FIXME: there's a lot of logic common to the run, cd and builtin file
248 # completers, that is currently reimplemented in each.
247 # completers, that is currently reimplemented in each.
249
248
250 def magic_run_completer(self, event):
249 def magic_run_completer(self, event):
251 """Complete files that end in .py or .ipy or .ipynb for the %run command.
250 """Complete files that end in .py or .ipy or .ipynb for the %run command.
252 """
251 """
253 comps = arg_split(event.line, strict=False)
252 comps = arg_split(event.line, strict=False)
254 # relpath should be the current token that we need to complete.
253 # relpath should be the current token that we need to complete.
255 if (len(comps) > 1) and (not event.line.endswith(' ')):
254 if (len(comps) > 1) and (not event.line.endswith(' ')):
256 relpath = comps[-1].strip("'\"")
255 relpath = comps[-1].strip("'\"")
257 else:
256 else:
258 relpath = ''
257 relpath = ''
259
258
260 #print("\nev=", event) # dbg
259 #print("\nev=", event) # dbg
261 #print("rp=", relpath) # dbg
260 #print("rp=", relpath) # dbg
262 #print('comps=', comps) # dbg
261 #print('comps=', comps) # dbg
263
262
264 lglob = glob.glob
263 lglob = glob.glob
265 isdir = os.path.isdir
264 isdir = os.path.isdir
266 relpath, tilde_expand, tilde_val = expand_user(relpath)
265 relpath, tilde_expand, tilde_val = expand_user(relpath)
267
266
268 # Find if the user has already typed the first filename, after which we
267 # Find if the user has already typed the first filename, after which we
269 # should complete on all files, since after the first one other files may
268 # should complete on all files, since after the first one other files may
270 # be arguments to the input script.
269 # be arguments to the input script.
271
270
272 if any(magic_run_re.match(c) for c in comps):
271 if any(magic_run_re.match(c) for c in comps):
273 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
272 matches = [f.replace('\\','/') + ('/' if isdir(f) else '')
274 for f in lglob(relpath+'*')]
273 for f in lglob(relpath+'*')]
275 else:
274 else:
276 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
275 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*') if isdir(f)]
277 pys = [f.replace('\\','/')
276 pys = [f.replace('\\','/')
278 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
277 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
279 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
278 lglob(relpath+'*.ipynb') + lglob(relpath + '*.pyw')]
280
279
281 matches = dirs + pys
280 matches = dirs + pys
282
281
283 #print('run comp:', dirs+pys) # dbg
282 #print('run comp:', dirs+pys) # dbg
284 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
283 return [compress_user(p, tilde_expand, tilde_val) for p in matches]
285
284
286
285
287 def cd_completer(self, event):
286 def cd_completer(self, event):
288 """Completer function for cd, which only returns directories."""
287 """Completer function for cd, which only returns directories."""
289 ip = get_ipython()
288 ip = get_ipython()
290 relpath = event.symbol
289 relpath = event.symbol
291
290
292 #print(event) # dbg
291 #print(event) # dbg
293 if event.line.endswith('-b') or ' -b ' in event.line:
292 if event.line.endswith('-b') or ' -b ' in event.line:
294 # return only bookmark completions
293 # return only bookmark completions
295 bkms = self.db.get('bookmarks', None)
294 bkms = self.db.get('bookmarks', None)
296 if bkms:
295 if bkms:
297 return bkms.keys()
296 return bkms.keys()
298 else:
297 else:
299 return []
298 return []
300
299
301 if event.symbol == '-':
300 if event.symbol == '-':
302 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
301 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
303 # jump in directory history by number
302 # jump in directory history by number
304 fmt = '-%0' + width_dh +'d [%s]'
303 fmt = '-%0' + width_dh +'d [%s]'
305 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
304 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
306 if len(ents) > 1:
305 if len(ents) > 1:
307 return ents
306 return ents
308 return []
307 return []
309
308
310 if event.symbol.startswith('--'):
309 if event.symbol.startswith('--'):
311 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
310 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
312
311
313 # Expand ~ in path and normalize directory separators.
312 # Expand ~ in path and normalize directory separators.
314 relpath, tilde_expand, tilde_val = expand_user(relpath)
313 relpath, tilde_expand, tilde_val = expand_user(relpath)
315 relpath = relpath.replace('\\','/')
314 relpath = relpath.replace('\\','/')
316
315
317 found = []
316 found = []
318 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
317 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
319 if os.path.isdir(f)]:
318 if os.path.isdir(f)]:
320 if ' ' in d:
319 if ' ' in d:
321 # we don't want to deal with any of that, complex code
320 # we don't want to deal with any of that, complex code
322 # for this is elsewhere
321 # for this is elsewhere
323 raise TryNext
322 raise TryNext
324
323
325 found.append(d)
324 found.append(d)
326
325
327 if not found:
326 if not found:
328 if os.path.isdir(relpath):
327 if os.path.isdir(relpath):
329 return [compress_user(relpath, tilde_expand, tilde_val)]
328 return [compress_user(relpath, tilde_expand, tilde_val)]
330
329
331 # if no completions so far, try bookmarks
330 # if no completions so far, try bookmarks
332 bks = self.db.get('bookmarks',{})
331 bks = self.db.get('bookmarks',{})
333 bkmatches = [s for s in bks if s.startswith(event.symbol)]
332 bkmatches = [s for s in bks if s.startswith(event.symbol)]
334 if bkmatches:
333 if bkmatches:
335 return bkmatches
334 return bkmatches
336
335
337 raise TryNext
336 raise TryNext
338
337
339 return [compress_user(p, tilde_expand, tilde_val) for p in found]
338 return [compress_user(p, tilde_expand, tilde_val) for p in found]
340
339
341 def reset_completer(self, event):
340 def reset_completer(self, event):
342 "A completer for %reset magic"
341 "A completer for %reset magic"
343 return '-f -s in out array dhist'.split()
342 return '-f -s in out array dhist'.split()
@@ -1,215 +1,215 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3
3
4 Authors:
4 Authors:
5
5
6 * Fernando Perez
6 * Fernando Perez
7 * Brian E. Granger
7 * Brian E. Granger
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
11 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
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. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import os
22 import os
23 import sys
23 import sys
24 import traceback
24 import traceback
25 from pprint import pformat
25 from pprint import pformat
26
26
27 from IPython.core import ultratb
27 from IPython.core import ultratb
28 from IPython.core.release import author_email
28 from IPython.core.release import author_email
29 from IPython.utils.sysinfo import sys_info
29 from IPython.utils.sysinfo import sys_info
30 from IPython.utils.py3compat import input, getcwd
30 from IPython.utils.py3compat import input
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Code
33 # Code
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36 # Template for the user message.
36 # Template for the user message.
37 _default_message_template = """\
37 _default_message_template = """\
38 Oops, {app_name} crashed. We do our best to make it stable, but...
38 Oops, {app_name} crashed. We do our best to make it stable, but...
39
39
40 A crash report was automatically generated with the following information:
40 A crash report was automatically generated with the following information:
41 - A verbatim copy of the crash traceback.
41 - A verbatim copy of the crash traceback.
42 - A copy of your input history during this session.
42 - A copy of your input history during this session.
43 - Data on your current {app_name} configuration.
43 - Data on your current {app_name} configuration.
44
44
45 It was left in the file named:
45 It was left in the file named:
46 \t'{crash_report_fname}'
46 \t'{crash_report_fname}'
47 If you can email this file to the developers, the information in it will help
47 If you can email this file to the developers, the information in it will help
48 them in understanding and correcting the problem.
48 them in understanding and correcting the problem.
49
49
50 You can mail it to: {contact_name} at {contact_email}
50 You can mail it to: {contact_name} at {contact_email}
51 with the subject '{app_name} Crash Report'.
51 with the subject '{app_name} Crash Report'.
52
52
53 If you want to do it now, the following command will work (under Unix):
53 If you want to do it now, the following command will work (under Unix):
54 mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
54 mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
55
55
56 To ensure accurate tracking of this issue, please file a report about it at:
56 To ensure accurate tracking of this issue, please file a report about it at:
57 {bug_tracker}
57 {bug_tracker}
58 """
58 """
59
59
60 _lite_message_template = """
60 _lite_message_template = """
61 If you suspect this is an IPython bug, please report it at:
61 If you suspect this is an IPython bug, please report it at:
62 https://github.com/ipython/ipython/issues
62 https://github.com/ipython/ipython/issues
63 or send an email to the mailing list at {email}
63 or send an email to the mailing list at {email}
64
64
65 You can print a more detailed traceback right now with "%tb", or use "%debug"
65 You can print a more detailed traceback right now with "%tb", or use "%debug"
66 to interactively debug it.
66 to interactively debug it.
67
67
68 Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
68 Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
69 {config}Application.verbose_crash=True
69 {config}Application.verbose_crash=True
70 """
70 """
71
71
72
72
73 class CrashHandler(object):
73 class CrashHandler(object):
74 """Customizable crash handlers for IPython applications.
74 """Customizable crash handlers for IPython applications.
75
75
76 Instances of this class provide a :meth:`__call__` method which can be
76 Instances of this class provide a :meth:`__call__` method which can be
77 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
77 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
78
78
79 def __call__(self, etype, evalue, etb)
79 def __call__(self, etype, evalue, etb)
80 """
80 """
81
81
82 message_template = _default_message_template
82 message_template = _default_message_template
83 section_sep = '\n\n'+'*'*75+'\n\n'
83 section_sep = '\n\n'+'*'*75+'\n\n'
84
84
85 def __init__(self, app, contact_name=None, contact_email=None,
85 def __init__(self, app, contact_name=None, contact_email=None,
86 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
86 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
87 """Create a new crash handler
87 """Create a new crash handler
88
88
89 Parameters
89 Parameters
90 ----------
90 ----------
91 app : Application
91 app : Application
92 A running :class:`Application` instance, which will be queried at
92 A running :class:`Application` instance, which will be queried at
93 crash time for internal information.
93 crash time for internal information.
94
94
95 contact_name : str
95 contact_name : str
96 A string with the name of the person to contact.
96 A string with the name of the person to contact.
97
97
98 contact_email : str
98 contact_email : str
99 A string with the email address of the contact.
99 A string with the email address of the contact.
100
100
101 bug_tracker : str
101 bug_tracker : str
102 A string with the URL for your project's bug tracker.
102 A string with the URL for your project's bug tracker.
103
103
104 show_crash_traceback : bool
104 show_crash_traceback : bool
105 If false, don't print the crash traceback on stderr, only generate
105 If false, don't print the crash traceback on stderr, only generate
106 the on-disk report
106 the on-disk report
107
107
108 Non-argument instance attributes:
108 Non-argument instance attributes:
109
109
110 These instances contain some non-argument attributes which allow for
110 These instances contain some non-argument attributes which allow for
111 further customization of the crash handler's behavior. Please see the
111 further customization of the crash handler's behavior. Please see the
112 source for further details.
112 source for further details.
113 """
113 """
114 self.crash_report_fname = "Crash_report_%s.txt" % app.name
114 self.crash_report_fname = "Crash_report_%s.txt" % app.name
115 self.app = app
115 self.app = app
116 self.call_pdb = call_pdb
116 self.call_pdb = call_pdb
117 #self.call_pdb = True # dbg
117 #self.call_pdb = True # dbg
118 self.show_crash_traceback = show_crash_traceback
118 self.show_crash_traceback = show_crash_traceback
119 self.info = dict(app_name = app.name,
119 self.info = dict(app_name = app.name,
120 contact_name = contact_name,
120 contact_name = contact_name,
121 contact_email = contact_email,
121 contact_email = contact_email,
122 bug_tracker = bug_tracker,
122 bug_tracker = bug_tracker,
123 crash_report_fname = self.crash_report_fname)
123 crash_report_fname = self.crash_report_fname)
124
124
125
125
126 def __call__(self, etype, evalue, etb):
126 def __call__(self, etype, evalue, etb):
127 """Handle an exception, call for compatible with sys.excepthook"""
127 """Handle an exception, call for compatible with sys.excepthook"""
128
128
129 # do not allow the crash handler to be called twice without reinstalling it
129 # do not allow the crash handler to be called twice without reinstalling it
130 # this prevents unlikely errors in the crash handling from entering an
130 # this prevents unlikely errors in the crash handling from entering an
131 # infinite loop.
131 # infinite loop.
132 sys.excepthook = sys.__excepthook__
132 sys.excepthook = sys.__excepthook__
133
133
134 # Report tracebacks shouldn't use color in general (safer for users)
134 # Report tracebacks shouldn't use color in general (safer for users)
135 color_scheme = 'NoColor'
135 color_scheme = 'NoColor'
136
136
137 # Use this ONLY for developer debugging (keep commented out for release)
137 # Use this ONLY for developer debugging (keep commented out for release)
138 #color_scheme = 'Linux' # dbg
138 #color_scheme = 'Linux' # dbg
139 try:
139 try:
140 rptdir = self.app.ipython_dir
140 rptdir = self.app.ipython_dir
141 except:
141 except:
142 rptdir = getcwd()
142 rptdir = os.getcwd()
143 if rptdir is None or not os.path.isdir(rptdir):
143 if rptdir is None or not os.path.isdir(rptdir):
144 rptdir = getcwd()
144 rptdir = os.getcwd()
145 report_name = os.path.join(rptdir,self.crash_report_fname)
145 report_name = os.path.join(rptdir,self.crash_report_fname)
146 # write the report filename into the instance dict so it can get
146 # write the report filename into the instance dict so it can get
147 # properly expanded out in the user message template
147 # properly expanded out in the user message template
148 self.crash_report_fname = report_name
148 self.crash_report_fname = report_name
149 self.info['crash_report_fname'] = report_name
149 self.info['crash_report_fname'] = report_name
150 TBhandler = ultratb.VerboseTB(
150 TBhandler = ultratb.VerboseTB(
151 color_scheme=color_scheme,
151 color_scheme=color_scheme,
152 long_header=1,
152 long_header=1,
153 call_pdb=self.call_pdb,
153 call_pdb=self.call_pdb,
154 )
154 )
155 if self.call_pdb:
155 if self.call_pdb:
156 TBhandler(etype,evalue,etb)
156 TBhandler(etype,evalue,etb)
157 return
157 return
158 else:
158 else:
159 traceback = TBhandler.text(etype,evalue,etb,context=31)
159 traceback = TBhandler.text(etype,evalue,etb,context=31)
160
160
161 # print traceback to screen
161 # print traceback to screen
162 if self.show_crash_traceback:
162 if self.show_crash_traceback:
163 print(traceback, file=sys.stderr)
163 print(traceback, file=sys.stderr)
164
164
165 # and generate a complete report on disk
165 # and generate a complete report on disk
166 try:
166 try:
167 report = open(report_name,'w')
167 report = open(report_name,'w')
168 except:
168 except:
169 print('Could not create crash report on disk.', file=sys.stderr)
169 print('Could not create crash report on disk.', file=sys.stderr)
170 return
170 return
171
171
172 # Inform user on stderr of what happened
172 # Inform user on stderr of what happened
173 print('\n'+'*'*70+'\n', file=sys.stderr)
173 print('\n'+'*'*70+'\n', file=sys.stderr)
174 print(self.message_template.format(**self.info), file=sys.stderr)
174 print(self.message_template.format(**self.info), file=sys.stderr)
175
175
176 # Construct report on disk
176 # Construct report on disk
177 report.write(self.make_report(traceback))
177 report.write(self.make_report(traceback))
178 report.close()
178 report.close()
179 input("Hit <Enter> to quit (your terminal may close):")
179 input("Hit <Enter> to quit (your terminal may close):")
180
180
181 def make_report(self,traceback):
181 def make_report(self,traceback):
182 """Return a string containing a crash report."""
182 """Return a string containing a crash report."""
183
183
184 sec_sep = self.section_sep
184 sec_sep = self.section_sep
185
185
186 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
186 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
187 rpt_add = report.append
187 rpt_add = report.append
188 rpt_add(sys_info())
188 rpt_add(sys_info())
189
189
190 try:
190 try:
191 config = pformat(self.app.config)
191 config = pformat(self.app.config)
192 rpt_add(sec_sep)
192 rpt_add(sec_sep)
193 rpt_add('Application name: %s\n\n' % self.app_name)
193 rpt_add('Application name: %s\n\n' % self.app_name)
194 rpt_add('Current user configuration structure:\n\n')
194 rpt_add('Current user configuration structure:\n\n')
195 rpt_add(config)
195 rpt_add(config)
196 except:
196 except:
197 pass
197 pass
198 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
198 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
199
199
200 return ''.join(report)
200 return ''.join(report)
201
201
202
202
203 def crash_handler_lite(etype, evalue, tb):
203 def crash_handler_lite(etype, evalue, tb):
204 """a light excepthook, adding a small message to the usual traceback"""
204 """a light excepthook, adding a small message to the usual traceback"""
205 traceback.print_exception(etype, evalue, tb)
205 traceback.print_exception(etype, evalue, tb)
206
206
207 from IPython.core.interactiveshell import InteractiveShell
207 from IPython.core.interactiveshell import InteractiveShell
208 if InteractiveShell.initialized():
208 if InteractiveShell.initialized():
209 # we are in a Shell environment, give %magic example
209 # we are in a Shell environment, give %magic example
210 config = "%config "
210 config = "%config "
211 else:
211 else:
212 # we are not in a shell, show generic config
212 # we are not in a shell, show generic config
213 config = "c."
213 config = "c."
214 print(_lite_message_template.format(email=author_email, config=config), file=sys.stderr)
214 print(_lite_message_template.format(email=author_email, config=config), file=sys.stderr)
215
215
@@ -1,1136 +1,1135 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats."""
2 """Top-level display functions for displaying object in different formats."""
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
7
8 try:
8 try:
9 from base64 import encodebytes as base64_encode
9 from base64 import encodebytes as base64_encode
10 except ImportError:
10 except ImportError:
11 from base64 import encodestring as base64_encode
11 from base64 import encodestring as base64_encode
12
12
13 from binascii import b2a_hex
13 from binascii import b2a_hex
14 import json
14 import json
15 import mimetypes
15 import mimetypes
16 import os
16 import os
17 import struct
17 import struct
18 import sys
18 import sys
19 import warnings
19 import warnings
20
20
21 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
21 from IPython.utils.py3compat import cast_bytes_py2, cast_unicode
22 unicode_type)
23 from IPython.testing.skipdoctest import skip_doctest
22 from IPython.testing.skipdoctest import skip_doctest
24
23
25 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
24 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
26 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
25 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
27 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
26 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
28 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
27 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
29 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
28 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
30 'publish_display_data', 'update_display', 'DisplayHandle']
29 'publish_display_data', 'update_display', 'DisplayHandle']
31
30
32 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
33 # utility functions
32 # utility functions
34 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
35
34
36 def _safe_exists(path):
35 def _safe_exists(path):
37 """Check path, but don't let exceptions raise"""
36 """Check path, but don't let exceptions raise"""
38 try:
37 try:
39 return os.path.exists(path)
38 return os.path.exists(path)
40 except Exception:
39 except Exception:
41 return False
40 return False
42
41
43 def _merge(d1, d2):
42 def _merge(d1, d2):
44 """Like update, but merges sub-dicts instead of clobbering at the top level.
43 """Like update, but merges sub-dicts instead of clobbering at the top level.
45
44
46 Updates d1 in-place
45 Updates d1 in-place
47 """
46 """
48
47
49 if not isinstance(d2, dict) or not isinstance(d1, dict):
48 if not isinstance(d2, dict) or not isinstance(d1, dict):
50 return d2
49 return d2
51 for key, value in d2.items():
50 for key, value in d2.items():
52 d1[key] = _merge(d1.get(key), value)
51 d1[key] = _merge(d1.get(key), value)
53 return d1
52 return d1
54
53
55 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
54 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
56 """internal implementation of all display_foo methods
55 """internal implementation of all display_foo methods
57
56
58 Parameters
57 Parameters
59 ----------
58 ----------
60 mimetype : str
59 mimetype : str
61 The mimetype to be published (e.g. 'image/png')
60 The mimetype to be published (e.g. 'image/png')
62 objs : tuple of objects
61 objs : tuple of objects
63 The Python objects to display, or if raw=True raw text data to
62 The Python objects to display, or if raw=True raw text data to
64 display.
63 display.
65 raw : bool
64 raw : bool
66 Are the data objects raw data or Python objects that need to be
65 Are the data objects raw data or Python objects that need to be
67 formatted before display? [default: False]
66 formatted before display? [default: False]
68 metadata : dict (optional)
67 metadata : dict (optional)
69 Metadata to be associated with the specific mimetype output.
68 Metadata to be associated with the specific mimetype output.
70 """
69 """
71 if metadata:
70 if metadata:
72 metadata = {mimetype: metadata}
71 metadata = {mimetype: metadata}
73 if raw:
72 if raw:
74 # turn list of pngdata into list of { 'image/png': pngdata }
73 # turn list of pngdata into list of { 'image/png': pngdata }
75 objs = [ {mimetype: obj} for obj in objs ]
74 objs = [ {mimetype: obj} for obj in objs ]
76 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
75 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
77
76
78 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
79 # Main functions
78 # Main functions
80 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
81
80
82 # use * to indicate transient is keyword-only
81 # use * to indicate transient is keyword-only
83 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
82 def publish_display_data(data, metadata=None, source=None, *, transient=None, **kwargs):
84 """Publish data and metadata to all frontends.
83 """Publish data and metadata to all frontends.
85
84
86 See the ``display_data`` message in the messaging documentation for
85 See the ``display_data`` message in the messaging documentation for
87 more details about this message type.
86 more details about this message type.
88
87
89 The following MIME types are currently implemented:
88 The following MIME types are currently implemented:
90
89
91 * text/plain
90 * text/plain
92 * text/html
91 * text/html
93 * text/markdown
92 * text/markdown
94 * text/latex
93 * text/latex
95 * application/json
94 * application/json
96 * application/javascript
95 * application/javascript
97 * image/png
96 * image/png
98 * image/jpeg
97 * image/jpeg
99 * image/svg+xml
98 * image/svg+xml
100
99
101 Parameters
100 Parameters
102 ----------
101 ----------
103 data : dict
102 data : dict
104 A dictionary having keys that are valid MIME types (like
103 A dictionary having keys that are valid MIME types (like
105 'text/plain' or 'image/svg+xml') and values that are the data for
104 'text/plain' or 'image/svg+xml') and values that are the data for
106 that MIME type. The data itself must be a JSON'able data
105 that MIME type. The data itself must be a JSON'able data
107 structure. Minimally all data should have the 'text/plain' data,
106 structure. Minimally all data should have the 'text/plain' data,
108 which can be displayed by all frontends. If more than the plain
107 which can be displayed by all frontends. If more than the plain
109 text is given, it is up to the frontend to decide which
108 text is given, it is up to the frontend to decide which
110 representation to use.
109 representation to use.
111 metadata : dict
110 metadata : dict
112 A dictionary for metadata related to the data. This can contain
111 A dictionary for metadata related to the data. This can contain
113 arbitrary key, value pairs that frontends can use to interpret
112 arbitrary key, value pairs that frontends can use to interpret
114 the data. mime-type keys matching those in data can be used
113 the data. mime-type keys matching those in data can be used
115 to specify metadata about particular representations.
114 to specify metadata about particular representations.
116 source : str, deprecated
115 source : str, deprecated
117 Unused.
116 Unused.
118 transient : dict, keyword-only
117 transient : dict, keyword-only
119 A dictionary of transient data, such as display_id.
118 A dictionary of transient data, such as display_id.
120 """
119 """
121 from IPython.core.interactiveshell import InteractiveShell
120 from IPython.core.interactiveshell import InteractiveShell
122
121
123 display_pub = InteractiveShell.instance().display_pub
122 display_pub = InteractiveShell.instance().display_pub
124
123
125 # only pass transient if supplied,
124 # only pass transient if supplied,
126 # to avoid errors with older ipykernel.
125 # to avoid errors with older ipykernel.
127 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
126 # TODO: We could check for ipykernel version and provide a detailed upgrade message.
128 if transient:
127 if transient:
129 kwargs['transient'] = transient
128 kwargs['transient'] = transient
130
129
131 display_pub.publish(
130 display_pub.publish(
132 data=data,
131 data=data,
133 metadata=metadata,
132 metadata=metadata,
134 **kwargs
133 **kwargs
135 )
134 )
136
135
137
136
138 def _new_id():
137 def _new_id():
139 """Generate a new random text id with urandom"""
138 """Generate a new random text id with urandom"""
140 return b2a_hex(os.urandom(16)).decode('ascii')
139 return b2a_hex(os.urandom(16)).decode('ascii')
141
140
142
141
143 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
142 def display(*objs, include=None, exclude=None, metadata=None, transient=None, display_id=None, **kwargs):
144 """Display a Python object in all frontends.
143 """Display a Python object in all frontends.
145
144
146 By default all representations will be computed and sent to the frontends.
145 By default all representations will be computed and sent to the frontends.
147 Frontends can decide which representation is used and how.
146 Frontends can decide which representation is used and how.
148
147
149 Parameters
148 Parameters
150 ----------
149 ----------
151 objs : tuple of objects
150 objs : tuple of objects
152 The Python objects to display.
151 The Python objects to display.
153 raw : bool, optional
152 raw : bool, optional
154 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
153 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
155 or Python objects that need to be formatted before display? [default: False]
154 or Python objects that need to be formatted before display? [default: False]
156 include : list or tuple, optional
155 include : list or tuple, optional
157 A list of format type strings (MIME types) to include in the
156 A list of format type strings (MIME types) to include in the
158 format data dict. If this is set *only* the format types included
157 format data dict. If this is set *only* the format types included
159 in this list will be computed.
158 in this list will be computed.
160 exclude : list or tuple, optional
159 exclude : list or tuple, optional
161 A list of format type strings (MIME types) to exclude in the format
160 A list of format type strings (MIME types) to exclude in the format
162 data dict. If this is set all format types will be computed,
161 data dict. If this is set all format types will be computed,
163 except for those included in this argument.
162 except for those included in this argument.
164 metadata : dict, optional
163 metadata : dict, optional
165 A dictionary of metadata to associate with the output.
164 A dictionary of metadata to associate with the output.
166 mime-type keys in this dictionary will be associated with the individual
165 mime-type keys in this dictionary will be associated with the individual
167 representation formats, if they exist.
166 representation formats, if they exist.
168 transient : dict, optional
167 transient : dict, optional
169 A dictionary of transient data to associate with the output.
168 A dictionary of transient data to associate with the output.
170 Data in this dict should not be persisted to files (e.g. notebooks).
169 Data in this dict should not be persisted to files (e.g. notebooks).
171 display_id : str, optional
170 display_id : str, optional
172 Set an id for the display.
171 Set an id for the display.
173 This id can be used for updating this display area later via update_display.
172 This id can be used for updating this display area later via update_display.
174 If given as True, generate a new display_id
173 If given as True, generate a new display_id
175 kwargs: additional keyword-args, optional
174 kwargs: additional keyword-args, optional
176 Additional keyword-arguments are passed through to the display publisher.
175 Additional keyword-arguments are passed through to the display publisher.
177
176
178 Returns
177 Returns
179 -------
178 -------
180
179
181 handle: DisplayHandle
180 handle: DisplayHandle
182 Returns a handle on updatable displays, if display_id is given.
181 Returns a handle on updatable displays, if display_id is given.
183 Returns None if no display_id is given (default).
182 Returns None if no display_id is given (default).
184 """
183 """
185 raw = kwargs.pop('raw', False)
184 raw = kwargs.pop('raw', False)
186 if transient is None:
185 if transient is None:
187 transient = {}
186 transient = {}
188 if display_id:
187 if display_id:
189 if display_id == True:
188 if display_id == True:
190 display_id = _new_id()
189 display_id = _new_id()
191 transient['display_id'] = display_id
190 transient['display_id'] = display_id
192 if kwargs.get('update') and 'display_id' not in transient:
191 if kwargs.get('update') and 'display_id' not in transient:
193 raise TypeError('display_id required for update_display')
192 raise TypeError('display_id required for update_display')
194 if transient:
193 if transient:
195 kwargs['transient'] = transient
194 kwargs['transient'] = transient
196
195
197 from IPython.core.interactiveshell import InteractiveShell
196 from IPython.core.interactiveshell import InteractiveShell
198
197
199 if not raw:
198 if not raw:
200 format = InteractiveShell.instance().display_formatter.format
199 format = InteractiveShell.instance().display_formatter.format
201
200
202 for obj in objs:
201 for obj in objs:
203 if raw:
202 if raw:
204 publish_display_data(data=obj, metadata=metadata, **kwargs)
203 publish_display_data(data=obj, metadata=metadata, **kwargs)
205 else:
204 else:
206 format_dict, md_dict = format(obj, include=include, exclude=exclude)
205 format_dict, md_dict = format(obj, include=include, exclude=exclude)
207 if not format_dict:
206 if not format_dict:
208 # nothing to display (e.g. _ipython_display_ took over)
207 # nothing to display (e.g. _ipython_display_ took over)
209 continue
208 continue
210 if metadata:
209 if metadata:
211 # kwarg-specified metadata gets precedence
210 # kwarg-specified metadata gets precedence
212 _merge(md_dict, metadata)
211 _merge(md_dict, metadata)
213 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
212 publish_display_data(data=format_dict, metadata=md_dict, **kwargs)
214 if display_id:
213 if display_id:
215 return DisplayHandle(display_id)
214 return DisplayHandle(display_id)
216
215
217
216
218 # use * for keyword-only display_id arg
217 # use * for keyword-only display_id arg
219 def update_display(obj, *, display_id, **kwargs):
218 def update_display(obj, *, display_id, **kwargs):
220 """Update an existing display by id
219 """Update an existing display by id
221
220
222 Parameters
221 Parameters
223 ----------
222 ----------
224
223
225 obj:
224 obj:
226 The object with which to update the display
225 The object with which to update the display
227 display_id: keyword-only
226 display_id: keyword-only
228 The id of the display to update
227 The id of the display to update
229 """
228 """
230 kwargs['update'] = True
229 kwargs['update'] = True
231 display(obj, display_id=display_id, **kwargs)
230 display(obj, display_id=display_id, **kwargs)
232
231
233
232
234 class DisplayHandle(object):
233 class DisplayHandle(object):
235 """A handle on an updatable display
234 """A handle on an updatable display
236
235
237 Call .update(obj) to display a new object.
236 Call .update(obj) to display a new object.
238
237
239 Call .display(obj) to add a new instance of this display,
238 Call .display(obj) to add a new instance of this display,
240 and update existing instances.
239 and update existing instances.
241 """
240 """
242
241
243 def __init__(self, display_id=None):
242 def __init__(self, display_id=None):
244 if display_id is None:
243 if display_id is None:
245 display_id = _new_id()
244 display_id = _new_id()
246 self.display_id = display_id
245 self.display_id = display_id
247
246
248 def __repr__(self):
247 def __repr__(self):
249 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
248 return "<%s display_id=%s>" % (self.__class__.__name__, self.display_id)
250
249
251 def display(self, obj, **kwargs):
250 def display(self, obj, **kwargs):
252 """Make a new display with my id, updating existing instances.
251 """Make a new display with my id, updating existing instances.
253
252
254 Parameters
253 Parameters
255 ----------
254 ----------
256
255
257 obj:
256 obj:
258 object to display
257 object to display
259 **kwargs:
258 **kwargs:
260 additional keyword arguments passed to display
259 additional keyword arguments passed to display
261 """
260 """
262 display(obj, display_id=self.display_id, **kwargs)
261 display(obj, display_id=self.display_id, **kwargs)
263
262
264 def update(self, obj, **kwargs):
263 def update(self, obj, **kwargs):
265 """Update existing displays with my id
264 """Update existing displays with my id
266
265
267 Parameters
266 Parameters
268 ----------
267 ----------
269
268
270 obj:
269 obj:
271 object to display
270 object to display
272 **kwargs:
271 **kwargs:
273 additional keyword arguments passed to update_display
272 additional keyword arguments passed to update_display
274 """
273 """
275 update_display(obj, display_id=self.display_id, **kwargs)
274 update_display(obj, display_id=self.display_id, **kwargs)
276
275
277
276
278 def display_pretty(*objs, **kwargs):
277 def display_pretty(*objs, **kwargs):
279 """Display the pretty (default) representation of an object.
278 """Display the pretty (default) representation of an object.
280
279
281 Parameters
280 Parameters
282 ----------
281 ----------
283 objs : tuple of objects
282 objs : tuple of objects
284 The Python objects to display, or if raw=True raw text data to
283 The Python objects to display, or if raw=True raw text data to
285 display.
284 display.
286 raw : bool
285 raw : bool
287 Are the data objects raw data or Python objects that need to be
286 Are the data objects raw data or Python objects that need to be
288 formatted before display? [default: False]
287 formatted before display? [default: False]
289 metadata : dict (optional)
288 metadata : dict (optional)
290 Metadata to be associated with the specific mimetype output.
289 Metadata to be associated with the specific mimetype output.
291 """
290 """
292 _display_mimetype('text/plain', objs, **kwargs)
291 _display_mimetype('text/plain', objs, **kwargs)
293
292
294
293
295 def display_html(*objs, **kwargs):
294 def display_html(*objs, **kwargs):
296 """Display the HTML representation of an object.
295 """Display the HTML representation of an object.
297
296
298 Note: If raw=False and the object does not have a HTML
297 Note: If raw=False and the object does not have a HTML
299 representation, no HTML will be shown.
298 representation, no HTML will be shown.
300
299
301 Parameters
300 Parameters
302 ----------
301 ----------
303 objs : tuple of objects
302 objs : tuple of objects
304 The Python objects to display, or if raw=True raw HTML data to
303 The Python objects to display, or if raw=True raw HTML data to
305 display.
304 display.
306 raw : bool
305 raw : bool
307 Are the data objects raw data or Python objects that need to be
306 Are the data objects raw data or Python objects that need to be
308 formatted before display? [default: False]
307 formatted before display? [default: False]
309 metadata : dict (optional)
308 metadata : dict (optional)
310 Metadata to be associated with the specific mimetype output.
309 Metadata to be associated with the specific mimetype output.
311 """
310 """
312 _display_mimetype('text/html', objs, **kwargs)
311 _display_mimetype('text/html', objs, **kwargs)
313
312
314
313
315 def display_markdown(*objs, **kwargs):
314 def display_markdown(*objs, **kwargs):
316 """Displays the Markdown representation of an object.
315 """Displays the Markdown representation of an object.
317
316
318 Parameters
317 Parameters
319 ----------
318 ----------
320 objs : tuple of objects
319 objs : tuple of objects
321 The Python objects to display, or if raw=True raw markdown data to
320 The Python objects to display, or if raw=True raw markdown data to
322 display.
321 display.
323 raw : bool
322 raw : bool
324 Are the data objects raw data or Python objects that need to be
323 Are the data objects raw data or Python objects that need to be
325 formatted before display? [default: False]
324 formatted before display? [default: False]
326 metadata : dict (optional)
325 metadata : dict (optional)
327 Metadata to be associated with the specific mimetype output.
326 Metadata to be associated with the specific mimetype output.
328 """
327 """
329
328
330 _display_mimetype('text/markdown', objs, **kwargs)
329 _display_mimetype('text/markdown', objs, **kwargs)
331
330
332
331
333 def display_svg(*objs, **kwargs):
332 def display_svg(*objs, **kwargs):
334 """Display the SVG representation of an object.
333 """Display the SVG representation of an object.
335
334
336 Parameters
335 Parameters
337 ----------
336 ----------
338 objs : tuple of objects
337 objs : tuple of objects
339 The Python objects to display, or if raw=True raw svg data to
338 The Python objects to display, or if raw=True raw svg data to
340 display.
339 display.
341 raw : bool
340 raw : bool
342 Are the data objects raw data or Python objects that need to be
341 Are the data objects raw data or Python objects that need to be
343 formatted before display? [default: False]
342 formatted before display? [default: False]
344 metadata : dict (optional)
343 metadata : dict (optional)
345 Metadata to be associated with the specific mimetype output.
344 Metadata to be associated with the specific mimetype output.
346 """
345 """
347 _display_mimetype('image/svg+xml', objs, **kwargs)
346 _display_mimetype('image/svg+xml', objs, **kwargs)
348
347
349
348
350 def display_png(*objs, **kwargs):
349 def display_png(*objs, **kwargs):
351 """Display the PNG representation of an object.
350 """Display the PNG representation of an object.
352
351
353 Parameters
352 Parameters
354 ----------
353 ----------
355 objs : tuple of objects
354 objs : tuple of objects
356 The Python objects to display, or if raw=True raw png data to
355 The Python objects to display, or if raw=True raw png data to
357 display.
356 display.
358 raw : bool
357 raw : bool
359 Are the data objects raw data or Python objects that need to be
358 Are the data objects raw data or Python objects that need to be
360 formatted before display? [default: False]
359 formatted before display? [default: False]
361 metadata : dict (optional)
360 metadata : dict (optional)
362 Metadata to be associated with the specific mimetype output.
361 Metadata to be associated with the specific mimetype output.
363 """
362 """
364 _display_mimetype('image/png', objs, **kwargs)
363 _display_mimetype('image/png', objs, **kwargs)
365
364
366
365
367 def display_jpeg(*objs, **kwargs):
366 def display_jpeg(*objs, **kwargs):
368 """Display the JPEG representation of an object.
367 """Display the JPEG representation of an object.
369
368
370 Parameters
369 Parameters
371 ----------
370 ----------
372 objs : tuple of objects
371 objs : tuple of objects
373 The Python objects to display, or if raw=True raw JPEG data to
372 The Python objects to display, or if raw=True raw JPEG data to
374 display.
373 display.
375 raw : bool
374 raw : bool
376 Are the data objects raw data or Python objects that need to be
375 Are the data objects raw data or Python objects that need to be
377 formatted before display? [default: False]
376 formatted before display? [default: False]
378 metadata : dict (optional)
377 metadata : dict (optional)
379 Metadata to be associated with the specific mimetype output.
378 Metadata to be associated with the specific mimetype output.
380 """
379 """
381 _display_mimetype('image/jpeg', objs, **kwargs)
380 _display_mimetype('image/jpeg', objs, **kwargs)
382
381
383
382
384 def display_latex(*objs, **kwargs):
383 def display_latex(*objs, **kwargs):
385 """Display the LaTeX representation of an object.
384 """Display the LaTeX representation of an object.
386
385
387 Parameters
386 Parameters
388 ----------
387 ----------
389 objs : tuple of objects
388 objs : tuple of objects
390 The Python objects to display, or if raw=True raw latex data to
389 The Python objects to display, or if raw=True raw latex data to
391 display.
390 display.
392 raw : bool
391 raw : bool
393 Are the data objects raw data or Python objects that need to be
392 Are the data objects raw data or Python objects that need to be
394 formatted before display? [default: False]
393 formatted before display? [default: False]
395 metadata : dict (optional)
394 metadata : dict (optional)
396 Metadata to be associated with the specific mimetype output.
395 Metadata to be associated with the specific mimetype output.
397 """
396 """
398 _display_mimetype('text/latex', objs, **kwargs)
397 _display_mimetype('text/latex', objs, **kwargs)
399
398
400
399
401 def display_json(*objs, **kwargs):
400 def display_json(*objs, **kwargs):
402 """Display the JSON representation of an object.
401 """Display the JSON representation of an object.
403
402
404 Note that not many frontends support displaying JSON.
403 Note that not many frontends support displaying JSON.
405
404
406 Parameters
405 Parameters
407 ----------
406 ----------
408 objs : tuple of objects
407 objs : tuple of objects
409 The Python objects to display, or if raw=True raw json data to
408 The Python objects to display, or if raw=True raw json data to
410 display.
409 display.
411 raw : bool
410 raw : bool
412 Are the data objects raw data or Python objects that need to be
411 Are the data objects raw data or Python objects that need to be
413 formatted before display? [default: False]
412 formatted before display? [default: False]
414 metadata : dict (optional)
413 metadata : dict (optional)
415 Metadata to be associated with the specific mimetype output.
414 Metadata to be associated with the specific mimetype output.
416 """
415 """
417 _display_mimetype('application/json', objs, **kwargs)
416 _display_mimetype('application/json', objs, **kwargs)
418
417
419
418
420 def display_javascript(*objs, **kwargs):
419 def display_javascript(*objs, **kwargs):
421 """Display the Javascript representation of an object.
420 """Display the Javascript representation of an object.
422
421
423 Parameters
422 Parameters
424 ----------
423 ----------
425 objs : tuple of objects
424 objs : tuple of objects
426 The Python objects to display, or if raw=True raw javascript data to
425 The Python objects to display, or if raw=True raw javascript data to
427 display.
426 display.
428 raw : bool
427 raw : bool
429 Are the data objects raw data or Python objects that need to be
428 Are the data objects raw data or Python objects that need to be
430 formatted before display? [default: False]
429 formatted before display? [default: False]
431 metadata : dict (optional)
430 metadata : dict (optional)
432 Metadata to be associated with the specific mimetype output.
431 Metadata to be associated with the specific mimetype output.
433 """
432 """
434 _display_mimetype('application/javascript', objs, **kwargs)
433 _display_mimetype('application/javascript', objs, **kwargs)
435
434
436
435
437 def display_pdf(*objs, **kwargs):
436 def display_pdf(*objs, **kwargs):
438 """Display the PDF representation of an object.
437 """Display the PDF representation of an object.
439
438
440 Parameters
439 Parameters
441 ----------
440 ----------
442 objs : tuple of objects
441 objs : tuple of objects
443 The Python objects to display, or if raw=True raw javascript data to
442 The Python objects to display, or if raw=True raw javascript data to
444 display.
443 display.
445 raw : bool
444 raw : bool
446 Are the data objects raw data or Python objects that need to be
445 Are the data objects raw data or Python objects that need to be
447 formatted before display? [default: False]
446 formatted before display? [default: False]
448 metadata : dict (optional)
447 metadata : dict (optional)
449 Metadata to be associated with the specific mimetype output.
448 Metadata to be associated with the specific mimetype output.
450 """
449 """
451 _display_mimetype('application/pdf', objs, **kwargs)
450 _display_mimetype('application/pdf', objs, **kwargs)
452
451
453
452
454 #-----------------------------------------------------------------------------
453 #-----------------------------------------------------------------------------
455 # Smart classes
454 # Smart classes
456 #-----------------------------------------------------------------------------
455 #-----------------------------------------------------------------------------
457
456
458
457
459 class DisplayObject(object):
458 class DisplayObject(object):
460 """An object that wraps data to be displayed."""
459 """An object that wraps data to be displayed."""
461
460
462 _read_flags = 'r'
461 _read_flags = 'r'
463 _show_mem_addr = False
462 _show_mem_addr = False
464
463
465 def __init__(self, data=None, url=None, filename=None):
464 def __init__(self, data=None, url=None, filename=None):
466 """Create a display object given raw data.
465 """Create a display object given raw data.
467
466
468 When this object is returned by an expression or passed to the
467 When this object is returned by an expression or passed to the
469 display function, it will result in the data being displayed
468 display function, it will result in the data being displayed
470 in the frontend. The MIME type of the data should match the
469 in the frontend. The MIME type of the data should match the
471 subclasses used, so the Png subclass should be used for 'image/png'
470 subclasses used, so the Png subclass should be used for 'image/png'
472 data. If the data is a URL, the data will first be downloaded
471 data. If the data is a URL, the data will first be downloaded
473 and then displayed. If
472 and then displayed. If
474
473
475 Parameters
474 Parameters
476 ----------
475 ----------
477 data : unicode, str or bytes
476 data : unicode, str or bytes
478 The raw data or a URL or file to load the data from
477 The raw data or a URL or file to load the data from
479 url : unicode
478 url : unicode
480 A URL to download the data from.
479 A URL to download the data from.
481 filename : unicode
480 filename : unicode
482 Path to a local file to load the data from.
481 Path to a local file to load the data from.
483 """
482 """
484 if data is not None and isinstance(data, string_types):
483 if data is not None and isinstance(data, str):
485 if data.startswith('http') and url is None:
484 if data.startswith('http') and url is None:
486 url = data
485 url = data
487 filename = None
486 filename = None
488 data = None
487 data = None
489 elif _safe_exists(data) and filename is None:
488 elif _safe_exists(data) and filename is None:
490 url = None
489 url = None
491 filename = data
490 filename = data
492 data = None
491 data = None
493
492
494 self.data = data
493 self.data = data
495 self.url = url
494 self.url = url
496 self.filename = None if filename is None else unicode_type(filename)
495 self.filename = filename
497
496
498 self.reload()
497 self.reload()
499 self._check_data()
498 self._check_data()
500
499
501 def __repr__(self):
500 def __repr__(self):
502 if not self._show_mem_addr:
501 if not self._show_mem_addr:
503 cls = self.__class__
502 cls = self.__class__
504 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
503 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
505 else:
504 else:
506 r = super(DisplayObject, self).__repr__()
505 r = super(DisplayObject, self).__repr__()
507 return r
506 return r
508
507
509 def _check_data(self):
508 def _check_data(self):
510 """Override in subclasses if there's something to check."""
509 """Override in subclasses if there's something to check."""
511 pass
510 pass
512
511
513 def reload(self):
512 def reload(self):
514 """Reload the raw data from file or URL."""
513 """Reload the raw data from file or URL."""
515 if self.filename is not None:
514 if self.filename is not None:
516 with open(self.filename, self._read_flags) as f:
515 with open(self.filename, self._read_flags) as f:
517 self.data = f.read()
516 self.data = f.read()
518 elif self.url is not None:
517 elif self.url is not None:
519 try:
518 try:
520 try:
519 try:
521 from urllib.request import urlopen # Py3
520 from urllib.request import urlopen # Py3
522 except ImportError:
521 except ImportError:
523 from urllib2 import urlopen
522 from urllib2 import urlopen
524 response = urlopen(self.url)
523 response = urlopen(self.url)
525 self.data = response.read()
524 self.data = response.read()
526 # extract encoding from header, if there is one:
525 # extract encoding from header, if there is one:
527 encoding = None
526 encoding = None
528 for sub in response.headers['content-type'].split(';'):
527 for sub in response.headers['content-type'].split(';'):
529 sub = sub.strip()
528 sub = sub.strip()
530 if sub.startswith('charset'):
529 if sub.startswith('charset'):
531 encoding = sub.split('=')[-1].strip()
530 encoding = sub.split('=')[-1].strip()
532 break
531 break
533 # decode data, if an encoding was specified
532 # decode data, if an encoding was specified
534 if encoding:
533 if encoding:
535 self.data = self.data.decode(encoding, 'replace')
534 self.data = self.data.decode(encoding, 'replace')
536 except:
535 except:
537 self.data = None
536 self.data = None
538
537
539 class TextDisplayObject(DisplayObject):
538 class TextDisplayObject(DisplayObject):
540 """Validate that display data is text"""
539 """Validate that display data is text"""
541 def _check_data(self):
540 def _check_data(self):
542 if self.data is not None and not isinstance(self.data, string_types):
541 if self.data is not None and not isinstance(self.data, str):
543 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
542 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
544
543
545 class Pretty(TextDisplayObject):
544 class Pretty(TextDisplayObject):
546
545
547 def _repr_pretty_(self):
546 def _repr_pretty_(self):
548 return self.data
547 return self.data
549
548
550
549
551 class HTML(TextDisplayObject):
550 class HTML(TextDisplayObject):
552
551
553 def _repr_html_(self):
552 def _repr_html_(self):
554 return self.data
553 return self.data
555
554
556 def __html__(self):
555 def __html__(self):
557 """
556 """
558 This method exists to inform other HTML-using modules (e.g. Markupsafe,
557 This method exists to inform other HTML-using modules (e.g. Markupsafe,
559 htmltag, etc) that this object is HTML and does not need things like
558 htmltag, etc) that this object is HTML and does not need things like
560 special characters (<>&) escaped.
559 special characters (<>&) escaped.
561 """
560 """
562 return self._repr_html_()
561 return self._repr_html_()
563
562
564
563
565 class Markdown(TextDisplayObject):
564 class Markdown(TextDisplayObject):
566
565
567 def _repr_markdown_(self):
566 def _repr_markdown_(self):
568 return self.data
567 return self.data
569
568
570
569
571 class Math(TextDisplayObject):
570 class Math(TextDisplayObject):
572
571
573 def _repr_latex_(self):
572 def _repr_latex_(self):
574 s = self.data.strip('$')
573 s = self.data.strip('$')
575 return "$$%s$$" % s
574 return "$$%s$$" % s
576
575
577
576
578 class Latex(TextDisplayObject):
577 class Latex(TextDisplayObject):
579
578
580 def _repr_latex_(self):
579 def _repr_latex_(self):
581 return self.data
580 return self.data
582
581
583
582
584 class SVG(DisplayObject):
583 class SVG(DisplayObject):
585
584
586 _read_flags = 'rb'
585 _read_flags = 'rb'
587 # wrap data in a property, which extracts the <svg> tag, discarding
586 # wrap data in a property, which extracts the <svg> tag, discarding
588 # document headers
587 # document headers
589 _data = None
588 _data = None
590
589
591 @property
590 @property
592 def data(self):
591 def data(self):
593 return self._data
592 return self._data
594
593
595 @data.setter
594 @data.setter
596 def data(self, svg):
595 def data(self, svg):
597 if svg is None:
596 if svg is None:
598 self._data = None
597 self._data = None
599 return
598 return
600 # parse into dom object
599 # parse into dom object
601 from xml.dom import minidom
600 from xml.dom import minidom
602 svg = cast_bytes_py2(svg)
601 svg = cast_bytes_py2(svg)
603 x = minidom.parseString(svg)
602 x = minidom.parseString(svg)
604 # get svg tag (should be 1)
603 # get svg tag (should be 1)
605 found_svg = x.getElementsByTagName('svg')
604 found_svg = x.getElementsByTagName('svg')
606 if found_svg:
605 if found_svg:
607 svg = found_svg[0].toxml()
606 svg = found_svg[0].toxml()
608 else:
607 else:
609 # fallback on the input, trust the user
608 # fallback on the input, trust the user
610 # but this is probably an error.
609 # but this is probably an error.
611 pass
610 pass
612 svg = cast_unicode(svg)
611 svg = cast_unicode(svg)
613 self._data = svg
612 self._data = svg
614
613
615 def _repr_svg_(self):
614 def _repr_svg_(self):
616 return self.data
615 return self.data
617
616
618
617
619 class JSON(DisplayObject):
618 class JSON(DisplayObject):
620 """JSON expects a JSON-able dict or list
619 """JSON expects a JSON-able dict or list
621
620
622 not an already-serialized JSON string.
621 not an already-serialized JSON string.
623
622
624 Scalar types (None, number, string) are not allowed, only dict or list containers.
623 Scalar types (None, number, string) are not allowed, only dict or list containers.
625 """
624 """
626 # wrap data in a property, which warns about passing already-serialized JSON
625 # wrap data in a property, which warns about passing already-serialized JSON
627 _data = None
626 _data = None
628 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None):
627 def __init__(self, data=None, url=None, filename=None, expanded=False, metadata=None):
629 """Create a JSON display object given raw data.
628 """Create a JSON display object given raw data.
630
629
631 Parameters
630 Parameters
632 ----------
631 ----------
633 data : dict or list
632 data : dict or list
634 JSON data to display. Not an already-serialized JSON string.
633 JSON data to display. Not an already-serialized JSON string.
635 Scalar types (None, number, string) are not allowed, only dict
634 Scalar types (None, number, string) are not allowed, only dict
636 or list containers.
635 or list containers.
637 url : unicode
636 url : unicode
638 A URL to download the data from.
637 A URL to download the data from.
639 filename : unicode
638 filename : unicode
640 Path to a local file to load the data from.
639 Path to a local file to load the data from.
641 expanded : boolean
640 expanded : boolean
642 Metadata to control whether a JSON display component is expanded.
641 Metadata to control whether a JSON display component is expanded.
643 metadata: dict
642 metadata: dict
644 Specify extra metadata to attach to the json display object.
643 Specify extra metadata to attach to the json display object.
645 """
644 """
646 self.expanded = expanded
645 self.expanded = expanded
647 self.metadata = metadata
646 self.metadata = metadata
648 super(JSON, self).__init__(data=data, url=url, filename=filename)
647 super(JSON, self).__init__(data=data, url=url, filename=filename)
649
648
650 def _check_data(self):
649 def _check_data(self):
651 if self.data is not None and not isinstance(self.data, (dict, list)):
650 if self.data is not None and not isinstance(self.data, (dict, list)):
652 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
651 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
653
652
654 @property
653 @property
655 def data(self):
654 def data(self):
656 return self._data
655 return self._data
657
656
658 @data.setter
657 @data.setter
659 def data(self, data):
658 def data(self, data):
660 if isinstance(data, string_types):
659 if isinstance(data, str):
661 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
660 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
662 data = json.loads(data)
661 data = json.loads(data)
663 self._data = data
662 self._data = data
664
663
665 def _data_and_metadata(self):
664 def _data_and_metadata(self):
666 md = {'expanded': self.expanded}
665 md = {'expanded': self.expanded}
667 if self.metadata:
666 if self.metadata:
668 md.update(self.metadata)
667 md.update(self.metadata)
669 return self.data, md
668 return self.data, md
670
669
671 def _repr_json_(self):
670 def _repr_json_(self):
672 return self._data_and_metadata()
671 return self._data_and_metadata()
673
672
674 css_t = """$("head").append($("<link/>").attr({
673 css_t = """$("head").append($("<link/>").attr({
675 rel: "stylesheet",
674 rel: "stylesheet",
676 type: "text/css",
675 type: "text/css",
677 href: "%s"
676 href: "%s"
678 }));
677 }));
679 """
678 """
680
679
681 lib_t1 = """$.getScript("%s", function () {
680 lib_t1 = """$.getScript("%s", function () {
682 """
681 """
683 lib_t2 = """});
682 lib_t2 = """});
684 """
683 """
685
684
686 class Javascript(TextDisplayObject):
685 class Javascript(TextDisplayObject):
687
686
688 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
687 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
689 """Create a Javascript display object given raw data.
688 """Create a Javascript display object given raw data.
690
689
691 When this object is returned by an expression or passed to the
690 When this object is returned by an expression or passed to the
692 display function, it will result in the data being displayed
691 display function, it will result in the data being displayed
693 in the frontend. If the data is a URL, the data will first be
692 in the frontend. If the data is a URL, the data will first be
694 downloaded and then displayed.
693 downloaded and then displayed.
695
694
696 In the Notebook, the containing element will be available as `element`,
695 In the Notebook, the containing element will be available as `element`,
697 and jQuery will be available. Content appended to `element` will be
696 and jQuery will be available. Content appended to `element` will be
698 visible in the output area.
697 visible in the output area.
699
698
700 Parameters
699 Parameters
701 ----------
700 ----------
702 data : unicode, str or bytes
701 data : unicode, str or bytes
703 The Javascript source code or a URL to download it from.
702 The Javascript source code or a URL to download it from.
704 url : unicode
703 url : unicode
705 A URL to download the data from.
704 A URL to download the data from.
706 filename : unicode
705 filename : unicode
707 Path to a local file to load the data from.
706 Path to a local file to load the data from.
708 lib : list or str
707 lib : list or str
709 A sequence of Javascript library URLs to load asynchronously before
708 A sequence of Javascript library URLs to load asynchronously before
710 running the source code. The full URLs of the libraries should
709 running the source code. The full URLs of the libraries should
711 be given. A single Javascript library URL can also be given as a
710 be given. A single Javascript library URL can also be given as a
712 string.
711 string.
713 css: : list or str
712 css: : list or str
714 A sequence of css files to load before running the source code.
713 A sequence of css files to load before running the source code.
715 The full URLs of the css files should be given. A single css URL
714 The full URLs of the css files should be given. A single css URL
716 can also be given as a string.
715 can also be given as a string.
717 """
716 """
718 if isinstance(lib, string_types):
717 if isinstance(lib, str):
719 lib = [lib]
718 lib = [lib]
720 elif lib is None:
719 elif lib is None:
721 lib = []
720 lib = []
722 if isinstance(css, string_types):
721 if isinstance(css, str):
723 css = [css]
722 css = [css]
724 elif css is None:
723 elif css is None:
725 css = []
724 css = []
726 if not isinstance(lib, (list,tuple)):
725 if not isinstance(lib, (list,tuple)):
727 raise TypeError('expected sequence, got: %r' % lib)
726 raise TypeError('expected sequence, got: %r' % lib)
728 if not isinstance(css, (list,tuple)):
727 if not isinstance(css, (list,tuple)):
729 raise TypeError('expected sequence, got: %r' % css)
728 raise TypeError('expected sequence, got: %r' % css)
730 self.lib = lib
729 self.lib = lib
731 self.css = css
730 self.css = css
732 super(Javascript, self).__init__(data=data, url=url, filename=filename)
731 super(Javascript, self).__init__(data=data, url=url, filename=filename)
733
732
734 def _repr_javascript_(self):
733 def _repr_javascript_(self):
735 r = ''
734 r = ''
736 for c in self.css:
735 for c in self.css:
737 r += css_t % c
736 r += css_t % c
738 for l in self.lib:
737 for l in self.lib:
739 r += lib_t1 % l
738 r += lib_t1 % l
740 r += self.data
739 r += self.data
741 r += lib_t2*len(self.lib)
740 r += lib_t2*len(self.lib)
742 return r
741 return r
743
742
744 # constants for identifying png/jpeg data
743 # constants for identifying png/jpeg data
745 _PNG = b'\x89PNG\r\n\x1a\n'
744 _PNG = b'\x89PNG\r\n\x1a\n'
746 _JPEG = b'\xff\xd8'
745 _JPEG = b'\xff\xd8'
747
746
748 def _pngxy(data):
747 def _pngxy(data):
749 """read the (width, height) from a PNG header"""
748 """read the (width, height) from a PNG header"""
750 ihdr = data.index(b'IHDR')
749 ihdr = data.index(b'IHDR')
751 # next 8 bytes are width/height
750 # next 8 bytes are width/height
752 w4h4 = data[ihdr+4:ihdr+12]
751 w4h4 = data[ihdr+4:ihdr+12]
753 return struct.unpack('>ii', w4h4)
752 return struct.unpack('>ii', w4h4)
754
753
755 def _jpegxy(data):
754 def _jpegxy(data):
756 """read the (width, height) from a JPEG header"""
755 """read the (width, height) from a JPEG header"""
757 # adapted from http://www.64lines.com/jpeg-width-height
756 # adapted from http://www.64lines.com/jpeg-width-height
758
757
759 idx = 4
758 idx = 4
760 while True:
759 while True:
761 block_size = struct.unpack('>H', data[idx:idx+2])[0]
760 block_size = struct.unpack('>H', data[idx:idx+2])[0]
762 idx = idx + block_size
761 idx = idx + block_size
763 if data[idx:idx+2] == b'\xFF\xC0':
762 if data[idx:idx+2] == b'\xFF\xC0':
764 # found Start of Frame
763 # found Start of Frame
765 iSOF = idx
764 iSOF = idx
766 break
765 break
767 else:
766 else:
768 # read another block
767 # read another block
769 idx += 2
768 idx += 2
770
769
771 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
770 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
772 return w, h
771 return w, h
773
772
774 class Image(DisplayObject):
773 class Image(DisplayObject):
775
774
776 _read_flags = 'rb'
775 _read_flags = 'rb'
777 _FMT_JPEG = u'jpeg'
776 _FMT_JPEG = u'jpeg'
778 _FMT_PNG = u'png'
777 _FMT_PNG = u'png'
779 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
778 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
780
779
781 def __init__(self, data=None, url=None, filename=None, format=None,
780 def __init__(self, data=None, url=None, filename=None, format=None,
782 embed=None, width=None, height=None, retina=False,
781 embed=None, width=None, height=None, retina=False,
783 unconfined=False, metadata=None):
782 unconfined=False, metadata=None):
784 """Create a PNG/JPEG image object given raw data.
783 """Create a PNG/JPEG image object given raw data.
785
784
786 When this object is returned by an input cell or passed to the
785 When this object is returned by an input cell or passed to the
787 display function, it will result in the image being displayed
786 display function, it will result in the image being displayed
788 in the frontend.
787 in the frontend.
789
788
790 Parameters
789 Parameters
791 ----------
790 ----------
792 data : unicode, str or bytes
791 data : unicode, str or bytes
793 The raw image data or a URL or filename to load the data from.
792 The raw image data or a URL or filename to load the data from.
794 This always results in embedded image data.
793 This always results in embedded image data.
795 url : unicode
794 url : unicode
796 A URL to download the data from. If you specify `url=`,
795 A URL to download the data from. If you specify `url=`,
797 the image data will not be embedded unless you also specify `embed=True`.
796 the image data will not be embedded unless you also specify `embed=True`.
798 filename : unicode
797 filename : unicode
799 Path to a local file to load the data from.
798 Path to a local file to load the data from.
800 Images from a file are always embedded.
799 Images from a file are always embedded.
801 format : unicode
800 format : unicode
802 The format of the image data (png/jpeg/jpg). If a filename or URL is given
801 The format of the image data (png/jpeg/jpg). If a filename or URL is given
803 for format will be inferred from the filename extension.
802 for format will be inferred from the filename extension.
804 embed : bool
803 embed : bool
805 Should the image data be embedded using a data URI (True) or be
804 Should the image data be embedded using a data URI (True) or be
806 loaded using an <img> tag. Set this to True if you want the image
805 loaded using an <img> tag. Set this to True if you want the image
807 to be viewable later with no internet connection in the notebook.
806 to be viewable later with no internet connection in the notebook.
808
807
809 Default is `True`, unless the keyword argument `url` is set, then
808 Default is `True`, unless the keyword argument `url` is set, then
810 default value is `False`.
809 default value is `False`.
811
810
812 Note that QtConsole is not able to display images if `embed` is set to `False`
811 Note that QtConsole is not able to display images if `embed` is set to `False`
813 width : int
812 width : int
814 Width in pixels to which to constrain the image in html
813 Width in pixels to which to constrain the image in html
815 height : int
814 height : int
816 Height in pixels to which to constrain the image in html
815 Height in pixels to which to constrain the image in html
817 retina : bool
816 retina : bool
818 Automatically set the width and height to half of the measured
817 Automatically set the width and height to half of the measured
819 width and height.
818 width and height.
820 This only works for embedded images because it reads the width/height
819 This only works for embedded images because it reads the width/height
821 from image data.
820 from image data.
822 For non-embedded images, you can just set the desired display width
821 For non-embedded images, you can just set the desired display width
823 and height directly.
822 and height directly.
824 unconfined: bool
823 unconfined: bool
825 Set unconfined=True to disable max-width confinement of the image.
824 Set unconfined=True to disable max-width confinement of the image.
826 metadata: dict
825 metadata: dict
827 Specify extra metadata to attach to the image.
826 Specify extra metadata to attach to the image.
828
827
829 Examples
828 Examples
830 --------
829 --------
831 # embedded image data, works in qtconsole and notebook
830 # embedded image data, works in qtconsole and notebook
832 # when passed positionally, the first arg can be any of raw image data,
831 # when passed positionally, the first arg can be any of raw image data,
833 # a URL, or a filename from which to load image data.
832 # a URL, or a filename from which to load image data.
834 # The result is always embedding image data for inline images.
833 # The result is always embedding image data for inline images.
835 Image('http://www.google.fr/images/srpr/logo3w.png')
834 Image('http://www.google.fr/images/srpr/logo3w.png')
836 Image('/path/to/image.jpg')
835 Image('/path/to/image.jpg')
837 Image(b'RAW_PNG_DATA...')
836 Image(b'RAW_PNG_DATA...')
838
837
839 # Specifying Image(url=...) does not embed the image data,
838 # Specifying Image(url=...) does not embed the image data,
840 # it only generates `<img>` tag with a link to the source.
839 # it only generates `<img>` tag with a link to the source.
841 # This will not work in the qtconsole or offline.
840 # This will not work in the qtconsole or offline.
842 Image(url='http://www.google.fr/images/srpr/logo3w.png')
841 Image(url='http://www.google.fr/images/srpr/logo3w.png')
843
842
844 """
843 """
845 if filename is not None:
844 if filename is not None:
846 ext = self._find_ext(filename)
845 ext = self._find_ext(filename)
847 elif url is not None:
846 elif url is not None:
848 ext = self._find_ext(url)
847 ext = self._find_ext(url)
849 elif data is None:
848 elif data is None:
850 raise ValueError("No image data found. Expecting filename, url, or data.")
849 raise ValueError("No image data found. Expecting filename, url, or data.")
851 elif isinstance(data, string_types) and (
850 elif isinstance(data, str) and (
852 data.startswith('http') or _safe_exists(data)
851 data.startswith('http') or _safe_exists(data)
853 ):
852 ):
854 ext = self._find_ext(data)
853 ext = self._find_ext(data)
855 else:
854 else:
856 ext = None
855 ext = None
857
856
858 if format is None:
857 if format is None:
859 if ext is not None:
858 if ext is not None:
860 if ext == u'jpg' or ext == u'jpeg':
859 if ext == u'jpg' or ext == u'jpeg':
861 format = self._FMT_JPEG
860 format = self._FMT_JPEG
862 if ext == u'png':
861 if ext == u'png':
863 format = self._FMT_PNG
862 format = self._FMT_PNG
864 else:
863 else:
865 format = ext.lower()
864 format = ext.lower()
866 elif isinstance(data, bytes):
865 elif isinstance(data, bytes):
867 # infer image type from image data header,
866 # infer image type from image data header,
868 # only if format has not been specified.
867 # only if format has not been specified.
869 if data[:2] == _JPEG:
868 if data[:2] == _JPEG:
870 format = self._FMT_JPEG
869 format = self._FMT_JPEG
871
870
872 # failed to detect format, default png
871 # failed to detect format, default png
873 if format is None:
872 if format is None:
874 format = 'png'
873 format = 'png'
875
874
876 if format.lower() == 'jpg':
875 if format.lower() == 'jpg':
877 # jpg->jpeg
876 # jpg->jpeg
878 format = self._FMT_JPEG
877 format = self._FMT_JPEG
879
878
880 self.format = unicode_type(format).lower()
879 self.format = format.lower()
881 self.embed = embed if embed is not None else (url is None)
880 self.embed = embed if embed is not None else (url is None)
882
881
883 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
882 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
884 raise ValueError("Cannot embed the '%s' image format" % (self.format))
883 raise ValueError("Cannot embed the '%s' image format" % (self.format))
885 self.width = width
884 self.width = width
886 self.height = height
885 self.height = height
887 self.retina = retina
886 self.retina = retina
888 self.unconfined = unconfined
887 self.unconfined = unconfined
889 self.metadata = metadata
888 self.metadata = metadata
890 super(Image, self).__init__(data=data, url=url, filename=filename)
889 super(Image, self).__init__(data=data, url=url, filename=filename)
891
890
892 if retina:
891 if retina:
893 self._retina_shape()
892 self._retina_shape()
894
893
895 def _retina_shape(self):
894 def _retina_shape(self):
896 """load pixel-doubled width and height from image data"""
895 """load pixel-doubled width and height from image data"""
897 if not self.embed:
896 if not self.embed:
898 return
897 return
899 if self.format == 'png':
898 if self.format == 'png':
900 w, h = _pngxy(self.data)
899 w, h = _pngxy(self.data)
901 elif self.format == 'jpeg':
900 elif self.format == 'jpeg':
902 w, h = _jpegxy(self.data)
901 w, h = _jpegxy(self.data)
903 else:
902 else:
904 # retina only supports png
903 # retina only supports png
905 return
904 return
906 self.width = w // 2
905 self.width = w // 2
907 self.height = h // 2
906 self.height = h // 2
908
907
909 def reload(self):
908 def reload(self):
910 """Reload the raw data from file or URL."""
909 """Reload the raw data from file or URL."""
911 if self.embed:
910 if self.embed:
912 super(Image,self).reload()
911 super(Image,self).reload()
913 if self.retina:
912 if self.retina:
914 self._retina_shape()
913 self._retina_shape()
915
914
916 def _repr_html_(self):
915 def _repr_html_(self):
917 if not self.embed:
916 if not self.embed:
918 width = height = klass = ''
917 width = height = klass = ''
919 if self.width:
918 if self.width:
920 width = ' width="%d"' % self.width
919 width = ' width="%d"' % self.width
921 if self.height:
920 if self.height:
922 height = ' height="%d"' % self.height
921 height = ' height="%d"' % self.height
923 if self.unconfined:
922 if self.unconfined:
924 klass = ' class="unconfined"'
923 klass = ' class="unconfined"'
925 return u'<img src="{url}"{width}{height}{klass}/>'.format(
924 return u'<img src="{url}"{width}{height}{klass}/>'.format(
926 url=self.url,
925 url=self.url,
927 width=width,
926 width=width,
928 height=height,
927 height=height,
929 klass=klass,
928 klass=klass,
930 )
929 )
931
930
932 def _data_and_metadata(self):
931 def _data_and_metadata(self):
933 """shortcut for returning metadata with shape information, if defined"""
932 """shortcut for returning metadata with shape information, if defined"""
934 md = {}
933 md = {}
935 if self.width:
934 if self.width:
936 md['width'] = self.width
935 md['width'] = self.width
937 if self.height:
936 if self.height:
938 md['height'] = self.height
937 md['height'] = self.height
939 if self.unconfined:
938 if self.unconfined:
940 md['unconfined'] = self.unconfined
939 md['unconfined'] = self.unconfined
941 if self.metadata:
940 if self.metadata:
942 md.update(self.metadata)
941 md.update(self.metadata)
943 if md:
942 if md:
944 return self.data, md
943 return self.data, md
945 else:
944 else:
946 return self.data
945 return self.data
947
946
948 def _repr_png_(self):
947 def _repr_png_(self):
949 if self.embed and self.format == u'png':
948 if self.embed and self.format == u'png':
950 return self._data_and_metadata()
949 return self._data_and_metadata()
951
950
952 def _repr_jpeg_(self):
951 def _repr_jpeg_(self):
953 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
952 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
954 return self._data_and_metadata()
953 return self._data_and_metadata()
955
954
956 def _find_ext(self, s):
955 def _find_ext(self, s):
957 return unicode_type(s.split('.')[-1].lower())
956 return s.split('.')[-1].lower()
958
957
959 class Video(DisplayObject):
958 class Video(DisplayObject):
960
959
961 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
960 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
962 """Create a video object given raw data or an URL.
961 """Create a video object given raw data or an URL.
963
962
964 When this object is returned by an input cell or passed to the
963 When this object is returned by an input cell or passed to the
965 display function, it will result in the video being displayed
964 display function, it will result in the video being displayed
966 in the frontend.
965 in the frontend.
967
966
968 Parameters
967 Parameters
969 ----------
968 ----------
970 data : unicode, str or bytes
969 data : unicode, str or bytes
971 The raw video data or a URL or filename to load the data from.
970 The raw video data or a URL or filename to load the data from.
972 Raw data will require passing `embed=True`.
971 Raw data will require passing `embed=True`.
973 url : unicode
972 url : unicode
974 A URL for the video. If you specify `url=`,
973 A URL for the video. If you specify `url=`,
975 the image data will not be embedded.
974 the image data will not be embedded.
976 filename : unicode
975 filename : unicode
977 Path to a local file containing the video.
976 Path to a local file containing the video.
978 Will be interpreted as a local URL unless `embed=True`.
977 Will be interpreted as a local URL unless `embed=True`.
979 embed : bool
978 embed : bool
980 Should the video be embedded using a data URI (True) or be
979 Should the video be embedded using a data URI (True) or be
981 loaded using a <video> tag (False).
980 loaded using a <video> tag (False).
982
981
983 Since videos are large, embedding them should be avoided, if possible.
982 Since videos are large, embedding them should be avoided, if possible.
984 You must confirm embedding as your intention by passing `embed=True`.
983 You must confirm embedding as your intention by passing `embed=True`.
985
984
986 Local files can be displayed with URLs without embedding the content, via::
985 Local files can be displayed with URLs without embedding the content, via::
987
986
988 Video('./video.mp4')
987 Video('./video.mp4')
989
988
990 mimetype: unicode
989 mimetype: unicode
991 Specify the mimetype for embedded videos.
990 Specify the mimetype for embedded videos.
992 Default will be guessed from file extension, if available.
991 Default will be guessed from file extension, if available.
993
992
994 Examples
993 Examples
995 --------
994 --------
996
995
997 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
996 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
998 Video('path/to/video.mp4')
997 Video('path/to/video.mp4')
999 Video('path/to/video.mp4', embed=True)
998 Video('path/to/video.mp4', embed=True)
1000 Video(b'raw-videodata', embed=True)
999 Video(b'raw-videodata', embed=True)
1001 """
1000 """
1002 if url is None and isinstance(data, string_types) and data.startswith(('http:', 'https:')):
1001 if url is None and isinstance(data, str) and data.startswith(('http:', 'https:')):
1003 url = data
1002 url = data
1004 data = None
1003 data = None
1005 elif os.path.exists(data):
1004 elif os.path.exists(data):
1006 filename = data
1005 filename = data
1007 data = None
1006 data = None
1008
1007
1009 if data and not embed:
1008 if data and not embed:
1010 msg = ''.join([
1009 msg = ''.join([
1011 "To embed videos, you must pass embed=True ",
1010 "To embed videos, you must pass embed=True ",
1012 "(this may make your notebook files huge)\n",
1011 "(this may make your notebook files huge)\n",
1013 "Consider passing Video(url='...')",
1012 "Consider passing Video(url='...')",
1014 ])
1013 ])
1015 raise ValueError(msg)
1014 raise ValueError(msg)
1016
1015
1017 self.mimetype = mimetype
1016 self.mimetype = mimetype
1018 self.embed = embed
1017 self.embed = embed
1019 super(Video, self).__init__(data=data, url=url, filename=filename)
1018 super(Video, self).__init__(data=data, url=url, filename=filename)
1020
1019
1021 def _repr_html_(self):
1020 def _repr_html_(self):
1022 # External URLs and potentially local files are not embedded into the
1021 # External URLs and potentially local files are not embedded into the
1023 # notebook output.
1022 # notebook output.
1024 if not self.embed:
1023 if not self.embed:
1025 url = self.url if self.url is not None else self.filename
1024 url = self.url if self.url is not None else self.filename
1026 output = """<video src="{0}" controls>
1025 output = """<video src="{0}" controls>
1027 Your browser does not support the <code>video</code> element.
1026 Your browser does not support the <code>video</code> element.
1028 </video>""".format(url)
1027 </video>""".format(url)
1029 return output
1028 return output
1030
1029
1031 # Embedded videos are base64-encoded.
1030 # Embedded videos are base64-encoded.
1032 mimetype = self.mimetype
1031 mimetype = self.mimetype
1033 if self.filename is not None:
1032 if self.filename is not None:
1034 if not mimetype:
1033 if not mimetype:
1035 mimetype, _ = mimetypes.guess_type(self.filename)
1034 mimetype, _ = mimetypes.guess_type(self.filename)
1036
1035
1037 with open(self.filename, 'rb') as f:
1036 with open(self.filename, 'rb') as f:
1038 video = f.read()
1037 video = f.read()
1039 else:
1038 else:
1040 video = self.data
1039 video = self.data
1041 if isinstance(video, unicode_type):
1040 if isinstance(video, str):
1042 # unicode input is already b64-encoded
1041 # unicode input is already b64-encoded
1043 b64_video = video
1042 b64_video = video
1044 else:
1043 else:
1045 b64_video = base64_encode(video).decode('ascii').rstrip()
1044 b64_video = base64_encode(video).decode('ascii').rstrip()
1046
1045
1047 output = """<video controls>
1046 output = """<video controls>
1048 <source src="data:{0};base64,{1}" type="{0}">
1047 <source src="data:{0};base64,{1}" type="{0}">
1049 Your browser does not support the video tag.
1048 Your browser does not support the video tag.
1050 </video>""".format(mimetype, b64_video)
1049 </video>""".format(mimetype, b64_video)
1051 return output
1050 return output
1052
1051
1053 def reload(self):
1052 def reload(self):
1054 # TODO
1053 # TODO
1055 pass
1054 pass
1056
1055
1057 def _repr_png_(self):
1056 def _repr_png_(self):
1058 # TODO
1057 # TODO
1059 pass
1058 pass
1060 def _repr_jpeg_(self):
1059 def _repr_jpeg_(self):
1061 # TODO
1060 # TODO
1062 pass
1061 pass
1063
1062
1064 def clear_output(wait=False):
1063 def clear_output(wait=False):
1065 """Clear the output of the current cell receiving output.
1064 """Clear the output of the current cell receiving output.
1066
1065
1067 Parameters
1066 Parameters
1068 ----------
1067 ----------
1069 wait : bool [default: false]
1068 wait : bool [default: false]
1070 Wait to clear the output until new output is available to replace it."""
1069 Wait to clear the output until new output is available to replace it."""
1071 from IPython.core.interactiveshell import InteractiveShell
1070 from IPython.core.interactiveshell import InteractiveShell
1072 if InteractiveShell.initialized():
1071 if InteractiveShell.initialized():
1073 InteractiveShell.instance().display_pub.clear_output(wait)
1072 InteractiveShell.instance().display_pub.clear_output(wait)
1074 else:
1073 else:
1075 print('\033[2K\r', end='')
1074 print('\033[2K\r', end='')
1076 sys.stdout.flush()
1075 sys.stdout.flush()
1077 print('\033[2K\r', end='')
1076 print('\033[2K\r', end='')
1078 sys.stderr.flush()
1077 sys.stderr.flush()
1079
1078
1080
1079
1081 @skip_doctest
1080 @skip_doctest
1082 def set_matplotlib_formats(*formats, **kwargs):
1081 def set_matplotlib_formats(*formats, **kwargs):
1083 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1082 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
1084
1083
1085 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1084 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
1086
1085
1087 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1086 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
1088
1087
1089 To set this in your config files use the following::
1088 To set this in your config files use the following::
1090
1089
1091 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1090 c.InlineBackend.figure_formats = {'png', 'jpeg'}
1092 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1091 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
1093
1092
1094 Parameters
1093 Parameters
1095 ----------
1094 ----------
1096 *formats : strs
1095 *formats : strs
1097 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1096 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
1098 **kwargs :
1097 **kwargs :
1099 Keyword args will be relayed to ``figure.canvas.print_figure``.
1098 Keyword args will be relayed to ``figure.canvas.print_figure``.
1100 """
1099 """
1101 from IPython.core.interactiveshell import InteractiveShell
1100 from IPython.core.interactiveshell import InteractiveShell
1102 from IPython.core.pylabtools import select_figure_formats
1101 from IPython.core.pylabtools import select_figure_formats
1103 # build kwargs, starting with InlineBackend config
1102 # build kwargs, starting with InlineBackend config
1104 kw = {}
1103 kw = {}
1105 from ipykernel.pylab.config import InlineBackend
1104 from ipykernel.pylab.config import InlineBackend
1106 cfg = InlineBackend.instance()
1105 cfg = InlineBackend.instance()
1107 kw.update(cfg.print_figure_kwargs)
1106 kw.update(cfg.print_figure_kwargs)
1108 kw.update(**kwargs)
1107 kw.update(**kwargs)
1109 shell = InteractiveShell.instance()
1108 shell = InteractiveShell.instance()
1110 select_figure_formats(shell, formats, **kw)
1109 select_figure_formats(shell, formats, **kw)
1111
1110
1112 @skip_doctest
1111 @skip_doctest
1113 def set_matplotlib_close(close=True):
1112 def set_matplotlib_close(close=True):
1114 """Set whether the inline backend closes all figures automatically or not.
1113 """Set whether the inline backend closes all figures automatically or not.
1115
1114
1116 By default, the inline backend used in the IPython Notebook will close all
1115 By default, the inline backend used in the IPython Notebook will close all
1117 matplotlib figures automatically after each cell is run. This means that
1116 matplotlib figures automatically after each cell is run. This means that
1118 plots in different cells won't interfere. Sometimes, you may want to make
1117 plots in different cells won't interfere. Sometimes, you may want to make
1119 a plot in one cell and then refine it in later cells. This can be accomplished
1118 a plot in one cell and then refine it in later cells. This can be accomplished
1120 by::
1119 by::
1121
1120
1122 In [1]: set_matplotlib_close(False)
1121 In [1]: set_matplotlib_close(False)
1123
1122
1124 To set this in your config files use the following::
1123 To set this in your config files use the following::
1125
1124
1126 c.InlineBackend.close_figures = False
1125 c.InlineBackend.close_figures = False
1127
1126
1128 Parameters
1127 Parameters
1129 ----------
1128 ----------
1130 close : bool
1129 close : bool
1131 Should all matplotlib figures be automatically closed after each cell is
1130 Should all matplotlib figures be automatically closed after each cell is
1132 run?
1131 run?
1133 """
1132 """
1134 from ipykernel.pylab.config import InlineBackend
1133 from ipykernel.pylab.config import InlineBackend
1135 cfg = InlineBackend.instance()
1134 cfg = InlineBackend.instance()
1136 cfg.close_figures = close
1135 cfg.close_figures = close
@@ -1,947 +1,947 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 default, observe,
30 )
30 )
31 from IPython.utils.py3compat import (
31 from IPython.utils.py3compat import (
32 with_metaclass, string_types, unicode_type,
32 with_metaclass
33 )
33 )
34
34
35
35
36 class DisplayFormatter(Configurable):
36 class DisplayFormatter(Configurable):
37
37
38 active_types = List(Unicode(),
38 active_types = List(Unicode(),
39 help="""List of currently active mime-types to display.
39 help="""List of currently active mime-types to display.
40 You can use this to set a white-list for formats to display.
40 You can use this to set a white-list for formats to display.
41
41
42 Most users will not need to change this value.
42 Most users will not need to change this value.
43 """).tag(config=True)
43 """).tag(config=True)
44
44
45 @default('active_types')
45 @default('active_types')
46 def _active_types_default(self):
46 def _active_types_default(self):
47 return self.format_types
47 return self.format_types
48
48
49 @observe('active_types')
49 @observe('active_types')
50 def _active_types_changed(self, change):
50 def _active_types_changed(self, change):
51 for key, formatter in self.formatters.items():
51 for key, formatter in self.formatters.items():
52 if key in change['new']:
52 if key in change['new']:
53 formatter.enabled = True
53 formatter.enabled = True
54 else:
54 else:
55 formatter.enabled = False
55 formatter.enabled = False
56
56
57 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
57 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
58 @default('ipython_display_formatter')
58 @default('ipython_display_formatter')
59 def _default_formatter(self):
59 def _default_formatter(self):
60 return IPythonDisplayFormatter(parent=self)
60 return IPythonDisplayFormatter(parent=self)
61
61
62 # A dict of formatter whose keys are format types (MIME types) and whose
62 # A dict of formatter whose keys are format types (MIME types) and whose
63 # values are subclasses of BaseFormatter.
63 # values are subclasses of BaseFormatter.
64 formatters = Dict()
64 formatters = Dict()
65 @default('formatters')
65 @default('formatters')
66 def _formatters_default(self):
66 def _formatters_default(self):
67 """Activate the default formatters."""
67 """Activate the default formatters."""
68 formatter_classes = [
68 formatter_classes = [
69 PlainTextFormatter,
69 PlainTextFormatter,
70 HTMLFormatter,
70 HTMLFormatter,
71 MarkdownFormatter,
71 MarkdownFormatter,
72 SVGFormatter,
72 SVGFormatter,
73 PNGFormatter,
73 PNGFormatter,
74 PDFFormatter,
74 PDFFormatter,
75 JPEGFormatter,
75 JPEGFormatter,
76 LatexFormatter,
76 LatexFormatter,
77 JSONFormatter,
77 JSONFormatter,
78 JavascriptFormatter
78 JavascriptFormatter
79 ]
79 ]
80 d = {}
80 d = {}
81 for cls in formatter_classes:
81 for cls in formatter_classes:
82 f = cls(parent=self)
82 f = cls(parent=self)
83 d[f.format_type] = f
83 d[f.format_type] = f
84 return d
84 return d
85
85
86 def format(self, obj, include=None, exclude=None):
86 def format(self, obj, include=None, exclude=None):
87 """Return a format data dict for an object.
87 """Return a format data dict for an object.
88
88
89 By default all format types will be computed.
89 By default all format types will be computed.
90
90
91 The following MIME types are currently implemented:
91 The following MIME types are currently implemented:
92
92
93 * text/plain
93 * text/plain
94 * text/html
94 * text/html
95 * text/markdown
95 * text/markdown
96 * text/latex
96 * text/latex
97 * application/json
97 * application/json
98 * application/javascript
98 * application/javascript
99 * application/pdf
99 * application/pdf
100 * image/png
100 * image/png
101 * image/jpeg
101 * image/jpeg
102 * image/svg+xml
102 * image/svg+xml
103
103
104 Parameters
104 Parameters
105 ----------
105 ----------
106 obj : object
106 obj : object
107 The Python object whose format data will be computed.
107 The Python object whose format data will be computed.
108 include : list or tuple, optional
108 include : list or tuple, optional
109 A list of format type strings (MIME types) to include in the
109 A list of format type strings (MIME types) to include in the
110 format data dict. If this is set *only* the format types included
110 format data dict. If this is set *only* the format types included
111 in this list will be computed.
111 in this list will be computed.
112 exclude : list or tuple, optional
112 exclude : list or tuple, optional
113 A list of format type string (MIME types) to exclude in the format
113 A list of format type string (MIME types) to exclude in the format
114 data dict. If this is set all format types will be computed,
114 data dict. If this is set all format types will be computed,
115 except for those included in this argument.
115 except for those included in this argument.
116
116
117 Returns
117 Returns
118 -------
118 -------
119 (format_dict, metadata_dict) : tuple of two dicts
119 (format_dict, metadata_dict) : tuple of two dicts
120
120
121 format_dict is a dictionary of key/value pairs, one of each format that was
121 format_dict is a dictionary of key/value pairs, one of each format that was
122 generated for the object. The keys are the format types, which
122 generated for the object. The keys are the format types, which
123 will usually be MIME type strings and the values and JSON'able
123 will usually be MIME type strings and the values and JSON'able
124 data structure containing the raw data for the representation in
124 data structure containing the raw data for the representation in
125 that format.
125 that format.
126
126
127 metadata_dict is a dictionary of metadata about each mime-type output.
127 metadata_dict is a dictionary of metadata about each mime-type output.
128 Its keys will be a strict subset of the keys in format_dict.
128 Its keys will be a strict subset of the keys in format_dict.
129 """
129 """
130 format_dict = {}
130 format_dict = {}
131 md_dict = {}
131 md_dict = {}
132
132
133 if self.ipython_display_formatter(obj):
133 if self.ipython_display_formatter(obj):
134 # object handled itself, don't proceed
134 # object handled itself, don't proceed
135 return {}, {}
135 return {}, {}
136
136
137 for format_type, formatter in self.formatters.items():
137 for format_type, formatter in self.formatters.items():
138 if include and format_type not in include:
138 if include and format_type not in include:
139 continue
139 continue
140 if exclude and format_type in exclude:
140 if exclude and format_type in exclude:
141 continue
141 continue
142
142
143 md = None
143 md = None
144 try:
144 try:
145 data = formatter(obj)
145 data = formatter(obj)
146 except:
146 except:
147 # FIXME: log the exception
147 # FIXME: log the exception
148 raise
148 raise
149
149
150 # formatters can return raw data or (data, metadata)
150 # formatters can return raw data or (data, metadata)
151 if isinstance(data, tuple) and len(data) == 2:
151 if isinstance(data, tuple) and len(data) == 2:
152 data, md = data
152 data, md = data
153
153
154 if data is not None:
154 if data is not None:
155 format_dict[format_type] = data
155 format_dict[format_type] = data
156 if md is not None:
156 if md is not None:
157 md_dict[format_type] = md
157 md_dict[format_type] = md
158
158
159 return format_dict, md_dict
159 return format_dict, md_dict
160
160
161 @property
161 @property
162 def format_types(self):
162 def format_types(self):
163 """Return the format types (MIME types) of the active formatters."""
163 """Return the format types (MIME types) of the active formatters."""
164 return list(self.formatters.keys())
164 return list(self.formatters.keys())
165
165
166
166
167 #-----------------------------------------------------------------------------
167 #-----------------------------------------------------------------------------
168 # Formatters for specific format types (text, html, svg, etc.)
168 # Formatters for specific format types (text, html, svg, etc.)
169 #-----------------------------------------------------------------------------
169 #-----------------------------------------------------------------------------
170
170
171
171
172 def _safe_repr(obj):
172 def _safe_repr(obj):
173 """Try to return a repr of an object
173 """Try to return a repr of an object
174
174
175 always returns a string, at least.
175 always returns a string, at least.
176 """
176 """
177 try:
177 try:
178 return repr(obj)
178 return repr(obj)
179 except Exception as e:
179 except Exception as e:
180 return "un-repr-able object (%r)" % e
180 return "un-repr-able object (%r)" % e
181
181
182
182
183 class FormatterWarning(UserWarning):
183 class FormatterWarning(UserWarning):
184 """Warning class for errors in formatters"""
184 """Warning class for errors in formatters"""
185
185
186 @decorator
186 @decorator
187 def catch_format_error(method, self, *args, **kwargs):
187 def catch_format_error(method, self, *args, **kwargs):
188 """show traceback on failed format call"""
188 """show traceback on failed format call"""
189 try:
189 try:
190 r = method(self, *args, **kwargs)
190 r = method(self, *args, **kwargs)
191 except NotImplementedError:
191 except NotImplementedError:
192 # don't warn on NotImplementedErrors
192 # don't warn on NotImplementedErrors
193 return None
193 return None
194 except Exception:
194 except Exception:
195 exc_info = sys.exc_info()
195 exc_info = sys.exc_info()
196 ip = get_ipython()
196 ip = get_ipython()
197 if ip is not None:
197 if ip is not None:
198 ip.showtraceback(exc_info)
198 ip.showtraceback(exc_info)
199 else:
199 else:
200 traceback.print_exception(*exc_info)
200 traceback.print_exception(*exc_info)
201 return None
201 return None
202 return self._check_return(r, args[0])
202 return self._check_return(r, args[0])
203
203
204
204
205 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
205 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
206 """ Abstract base class for Formatters.
206 """ Abstract base class for Formatters.
207
207
208 A formatter is a callable class that is responsible for computing the
208 A formatter is a callable class that is responsible for computing the
209 raw format data for a particular format type (MIME type). For example,
209 raw format data for a particular format type (MIME type). For example,
210 an HTML formatter would have a format type of `text/html` and would return
210 an HTML formatter would have a format type of `text/html` and would return
211 the HTML representation of the object when called.
211 the HTML representation of the object when called.
212 """
212 """
213
213
214 # The format type of the data returned, usually a MIME type.
214 # The format type of the data returned, usually a MIME type.
215 format_type = 'text/plain'
215 format_type = 'text/plain'
216
216
217 # Is the formatter enabled...
217 # Is the formatter enabled...
218 enabled = True
218 enabled = True
219
219
220 @abc.abstractmethod
220 @abc.abstractmethod
221 def __call__(self, obj):
221 def __call__(self, obj):
222 """Return a JSON'able representation of the object.
222 """Return a JSON'able representation of the object.
223
223
224 If the object cannot be formatted by this formatter,
224 If the object cannot be formatted by this formatter,
225 warn and return None.
225 warn and return None.
226 """
226 """
227 return repr(obj)
227 return repr(obj)
228
228
229
229
230 def _mod_name_key(typ):
230 def _mod_name_key(typ):
231 """Return a (__module__, __name__) tuple for a type.
231 """Return a (__module__, __name__) tuple for a type.
232
232
233 Used as key in Formatter.deferred_printers.
233 Used as key in Formatter.deferred_printers.
234 """
234 """
235 module = getattr(typ, '__module__', None)
235 module = getattr(typ, '__module__', None)
236 name = getattr(typ, '__name__', None)
236 name = getattr(typ, '__name__', None)
237 return (module, name)
237 return (module, name)
238
238
239
239
240 def _get_type(obj):
240 def _get_type(obj):
241 """Return the type of an instance (old and new-style)"""
241 """Return the type of an instance (old and new-style)"""
242 return getattr(obj, '__class__', None) or type(obj)
242 return getattr(obj, '__class__', None) or type(obj)
243
243
244
244
245 _raise_key_error = Sentinel('_raise_key_error', __name__,
245 _raise_key_error = Sentinel('_raise_key_error', __name__,
246 """
246 """
247 Special value to raise a KeyError
247 Special value to raise a KeyError
248
248
249 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
249 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
250 """)
250 """)
251
251
252
252
253 class BaseFormatter(Configurable):
253 class BaseFormatter(Configurable):
254 """A base formatter class that is configurable.
254 """A base formatter class that is configurable.
255
255
256 This formatter should usually be used as the base class of all formatters.
256 This formatter should usually be used as the base class of all formatters.
257 It is a traited :class:`Configurable` class and includes an extensible
257 It is a traited :class:`Configurable` class and includes an extensible
258 API for users to determine how their objects are formatted. The following
258 API for users to determine how their objects are formatted. The following
259 logic is used to find a function to format an given object.
259 logic is used to find a function to format an given object.
260
260
261 1. The object is introspected to see if it has a method with the name
261 1. The object is introspected to see if it has a method with the name
262 :attr:`print_method`. If is does, that object is passed to that method
262 :attr:`print_method`. If is does, that object is passed to that method
263 for formatting.
263 for formatting.
264 2. If no print method is found, three internal dictionaries are consulted
264 2. If no print method is found, three internal dictionaries are consulted
265 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
265 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
266 and :attr:`deferred_printers`.
266 and :attr:`deferred_printers`.
267
267
268 Users should use these dictionaries to register functions that will be
268 Users should use these dictionaries to register functions that will be
269 used to compute the format data for their objects (if those objects don't
269 used to compute the format data for their objects (if those objects don't
270 have the special print methods). The easiest way of using these
270 have the special print methods). The easiest way of using these
271 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
271 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
272 methods.
272 methods.
273
273
274 If no function/callable is found to compute the format data, ``None`` is
274 If no function/callable is found to compute the format data, ``None`` is
275 returned and this format type is not used.
275 returned and this format type is not used.
276 """
276 """
277
277
278 format_type = Unicode('text/plain')
278 format_type = Unicode('text/plain')
279 _return_type = string_types
279 _return_type = str
280
280
281 enabled = Bool(True).tag(config=True)
281 enabled = Bool(True).tag(config=True)
282
282
283 print_method = ObjectName('__repr__')
283 print_method = ObjectName('__repr__')
284
284
285 # The singleton printers.
285 # The singleton printers.
286 # Maps the IDs of the builtin singleton objects to the format functions.
286 # Maps the IDs of the builtin singleton objects to the format functions.
287 singleton_printers = Dict().tag(config=True)
287 singleton_printers = Dict().tag(config=True)
288
288
289 # The type-specific printers.
289 # The type-specific printers.
290 # Map type objects to the format functions.
290 # Map type objects to the format functions.
291 type_printers = Dict().tag(config=True)
291 type_printers = Dict().tag(config=True)
292
292
293 # The deferred-import type-specific printers.
293 # The deferred-import type-specific printers.
294 # Map (modulename, classname) pairs to the format functions.
294 # Map (modulename, classname) pairs to the format functions.
295 deferred_printers = Dict().tag(config=True)
295 deferred_printers = Dict().tag(config=True)
296
296
297 @catch_format_error
297 @catch_format_error
298 def __call__(self, obj):
298 def __call__(self, obj):
299 """Compute the format for an object."""
299 """Compute the format for an object."""
300 if self.enabled:
300 if self.enabled:
301 # lookup registered printer
301 # lookup registered printer
302 try:
302 try:
303 printer = self.lookup(obj)
303 printer = self.lookup(obj)
304 except KeyError:
304 except KeyError:
305 pass
305 pass
306 else:
306 else:
307 return printer(obj)
307 return printer(obj)
308 # Finally look for special method names
308 # Finally look for special method names
309 method = get_real_method(obj, self.print_method)
309 method = get_real_method(obj, self.print_method)
310 if method is not None:
310 if method is not None:
311 return method()
311 return method()
312 return None
312 return None
313 else:
313 else:
314 return None
314 return None
315
315
316 def __contains__(self, typ):
316 def __contains__(self, typ):
317 """map in to lookup_by_type"""
317 """map in to lookup_by_type"""
318 try:
318 try:
319 self.lookup_by_type(typ)
319 self.lookup_by_type(typ)
320 except KeyError:
320 except KeyError:
321 return False
321 return False
322 else:
322 else:
323 return True
323 return True
324
324
325 def _check_return(self, r, obj):
325 def _check_return(self, r, obj):
326 """Check that a return value is appropriate
326 """Check that a return value is appropriate
327
327
328 Return the value if so, None otherwise, warning if invalid.
328 Return the value if so, None otherwise, warning if invalid.
329 """
329 """
330 if r is None or isinstance(r, self._return_type) or \
330 if r is None or isinstance(r, self._return_type) or \
331 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
331 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
332 return r
332 return r
333 else:
333 else:
334 warnings.warn(
334 warnings.warn(
335 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
335 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
336 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
336 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
337 FormatterWarning
337 FormatterWarning
338 )
338 )
339
339
340 def lookup(self, obj):
340 def lookup(self, obj):
341 """Look up the formatter for a given instance.
341 """Look up the formatter for a given instance.
342
342
343 Parameters
343 Parameters
344 ----------
344 ----------
345 obj : object instance
345 obj : object instance
346
346
347 Returns
347 Returns
348 -------
348 -------
349 f : callable
349 f : callable
350 The registered formatting callable for the type.
350 The registered formatting callable for the type.
351
351
352 Raises
352 Raises
353 ------
353 ------
354 KeyError if the type has not been registered.
354 KeyError if the type has not been registered.
355 """
355 """
356 # look for singleton first
356 # look for singleton first
357 obj_id = id(obj)
357 obj_id = id(obj)
358 if obj_id in self.singleton_printers:
358 if obj_id in self.singleton_printers:
359 return self.singleton_printers[obj_id]
359 return self.singleton_printers[obj_id]
360 # then lookup by type
360 # then lookup by type
361 return self.lookup_by_type(_get_type(obj))
361 return self.lookup_by_type(_get_type(obj))
362
362
363 def lookup_by_type(self, typ):
363 def lookup_by_type(self, typ):
364 """Look up the registered formatter for a type.
364 """Look up the registered formatter for a type.
365
365
366 Parameters
366 Parameters
367 ----------
367 ----------
368 typ : type or '__module__.__name__' string for a type
368 typ : type or '__module__.__name__' string for a type
369
369
370 Returns
370 Returns
371 -------
371 -------
372 f : callable
372 f : callable
373 The registered formatting callable for the type.
373 The registered formatting callable for the type.
374
374
375 Raises
375 Raises
376 ------
376 ------
377 KeyError if the type has not been registered.
377 KeyError if the type has not been registered.
378 """
378 """
379 if isinstance(typ, string_types):
379 if isinstance(typ, str):
380 typ_key = tuple(typ.rsplit('.',1))
380 typ_key = tuple(typ.rsplit('.',1))
381 if typ_key not in self.deferred_printers:
381 if typ_key not in self.deferred_printers:
382 # We may have it cached in the type map. We will have to
382 # We may have it cached in the type map. We will have to
383 # iterate over all of the types to check.
383 # iterate over all of the types to check.
384 for cls in self.type_printers:
384 for cls in self.type_printers:
385 if _mod_name_key(cls) == typ_key:
385 if _mod_name_key(cls) == typ_key:
386 return self.type_printers[cls]
386 return self.type_printers[cls]
387 else:
387 else:
388 return self.deferred_printers[typ_key]
388 return self.deferred_printers[typ_key]
389 else:
389 else:
390 for cls in pretty._get_mro(typ):
390 for cls in pretty._get_mro(typ):
391 if cls in self.type_printers or self._in_deferred_types(cls):
391 if cls in self.type_printers or self._in_deferred_types(cls):
392 return self.type_printers[cls]
392 return self.type_printers[cls]
393
393
394 # If we have reached here, the lookup failed.
394 # If we have reached here, the lookup failed.
395 raise KeyError("No registered printer for {0!r}".format(typ))
395 raise KeyError("No registered printer for {0!r}".format(typ))
396
396
397 def for_type(self, typ, func=None):
397 def for_type(self, typ, func=None):
398 """Add a format function for a given type.
398 """Add a format function for a given type.
399
399
400 Parameters
400 Parameters
401 -----------
401 -----------
402 typ : type or '__module__.__name__' string for a type
402 typ : type or '__module__.__name__' string for a type
403 The class of the object that will be formatted using `func`.
403 The class of the object that will be formatted using `func`.
404 func : callable
404 func : callable
405 A callable for computing the format data.
405 A callable for computing the format data.
406 `func` will be called with the object to be formatted,
406 `func` will be called with the object to be formatted,
407 and will return the raw data in this formatter's format.
407 and will return the raw data in this formatter's format.
408 Subclasses may use a different call signature for the
408 Subclasses may use a different call signature for the
409 `func` argument.
409 `func` argument.
410
410
411 If `func` is None or not specified, there will be no change,
411 If `func` is None or not specified, there will be no change,
412 only returning the current value.
412 only returning the current value.
413
413
414 Returns
414 Returns
415 -------
415 -------
416 oldfunc : callable
416 oldfunc : callable
417 The currently registered callable.
417 The currently registered callable.
418 If you are registering a new formatter,
418 If you are registering a new formatter,
419 this will be the previous value (to enable restoring later).
419 this will be the previous value (to enable restoring later).
420 """
420 """
421 # if string given, interpret as 'pkg.module.class_name'
421 # if string given, interpret as 'pkg.module.class_name'
422 if isinstance(typ, string_types):
422 if isinstance(typ, str):
423 type_module, type_name = typ.rsplit('.', 1)
423 type_module, type_name = typ.rsplit('.', 1)
424 return self.for_type_by_name(type_module, type_name, func)
424 return self.for_type_by_name(type_module, type_name, func)
425
425
426 try:
426 try:
427 oldfunc = self.lookup_by_type(typ)
427 oldfunc = self.lookup_by_type(typ)
428 except KeyError:
428 except KeyError:
429 oldfunc = None
429 oldfunc = None
430
430
431 if func is not None:
431 if func is not None:
432 self.type_printers[typ] = func
432 self.type_printers[typ] = func
433
433
434 return oldfunc
434 return oldfunc
435
435
436 def for_type_by_name(self, type_module, type_name, func=None):
436 def for_type_by_name(self, type_module, type_name, func=None):
437 """Add a format function for a type specified by the full dotted
437 """Add a format function for a type specified by the full dotted
438 module and name of the type, rather than the type of the object.
438 module and name of the type, rather than the type of the object.
439
439
440 Parameters
440 Parameters
441 ----------
441 ----------
442 type_module : str
442 type_module : str
443 The full dotted name of the module the type is defined in, like
443 The full dotted name of the module the type is defined in, like
444 ``numpy``.
444 ``numpy``.
445 type_name : str
445 type_name : str
446 The name of the type (the class name), like ``dtype``
446 The name of the type (the class name), like ``dtype``
447 func : callable
447 func : callable
448 A callable for computing the format data.
448 A callable for computing the format data.
449 `func` will be called with the object to be formatted,
449 `func` will be called with the object to be formatted,
450 and will return the raw data in this formatter's format.
450 and will return the raw data in this formatter's format.
451 Subclasses may use a different call signature for the
451 Subclasses may use a different call signature for the
452 `func` argument.
452 `func` argument.
453
453
454 If `func` is None or unspecified, there will be no change,
454 If `func` is None or unspecified, there will be no change,
455 only returning the current value.
455 only returning the current value.
456
456
457 Returns
457 Returns
458 -------
458 -------
459 oldfunc : callable
459 oldfunc : callable
460 The currently registered callable.
460 The currently registered callable.
461 If you are registering a new formatter,
461 If you are registering a new formatter,
462 this will be the previous value (to enable restoring later).
462 this will be the previous value (to enable restoring later).
463 """
463 """
464 key = (type_module, type_name)
464 key = (type_module, type_name)
465
465
466 try:
466 try:
467 oldfunc = self.lookup_by_type("%s.%s" % key)
467 oldfunc = self.lookup_by_type("%s.%s" % key)
468 except KeyError:
468 except KeyError:
469 oldfunc = None
469 oldfunc = None
470
470
471 if func is not None:
471 if func is not None:
472 self.deferred_printers[key] = func
472 self.deferred_printers[key] = func
473 return oldfunc
473 return oldfunc
474
474
475 def pop(self, typ, default=_raise_key_error):
475 def pop(self, typ, default=_raise_key_error):
476 """Pop a formatter for the given type.
476 """Pop a formatter for the given type.
477
477
478 Parameters
478 Parameters
479 ----------
479 ----------
480 typ : type or '__module__.__name__' string for a type
480 typ : type or '__module__.__name__' string for a type
481 default : object
481 default : object
482 value to be returned if no formatter is registered for typ.
482 value to be returned if no formatter is registered for typ.
483
483
484 Returns
484 Returns
485 -------
485 -------
486 obj : object
486 obj : object
487 The last registered object for the type.
487 The last registered object for the type.
488
488
489 Raises
489 Raises
490 ------
490 ------
491 KeyError if the type is not registered and default is not specified.
491 KeyError if the type is not registered and default is not specified.
492 """
492 """
493
493
494 if isinstance(typ, string_types):
494 if isinstance(typ, str):
495 typ_key = tuple(typ.rsplit('.',1))
495 typ_key = tuple(typ.rsplit('.',1))
496 if typ_key not in self.deferred_printers:
496 if typ_key not in self.deferred_printers:
497 # We may have it cached in the type map. We will have to
497 # We may have it cached in the type map. We will have to
498 # iterate over all of the types to check.
498 # iterate over all of the types to check.
499 for cls in self.type_printers:
499 for cls in self.type_printers:
500 if _mod_name_key(cls) == typ_key:
500 if _mod_name_key(cls) == typ_key:
501 old = self.type_printers.pop(cls)
501 old = self.type_printers.pop(cls)
502 break
502 break
503 else:
503 else:
504 old = default
504 old = default
505 else:
505 else:
506 old = self.deferred_printers.pop(typ_key)
506 old = self.deferred_printers.pop(typ_key)
507 else:
507 else:
508 if typ in self.type_printers:
508 if typ in self.type_printers:
509 old = self.type_printers.pop(typ)
509 old = self.type_printers.pop(typ)
510 else:
510 else:
511 old = self.deferred_printers.pop(_mod_name_key(typ), default)
511 old = self.deferred_printers.pop(_mod_name_key(typ), default)
512 if old is _raise_key_error:
512 if old is _raise_key_error:
513 raise KeyError("No registered value for {0!r}".format(typ))
513 raise KeyError("No registered value for {0!r}".format(typ))
514 return old
514 return old
515
515
516 def _in_deferred_types(self, cls):
516 def _in_deferred_types(self, cls):
517 """
517 """
518 Check if the given class is specified in the deferred type registry.
518 Check if the given class is specified in the deferred type registry.
519
519
520 Successful matches will be moved to the regular type registry for future use.
520 Successful matches will be moved to the regular type registry for future use.
521 """
521 """
522 mod = getattr(cls, '__module__', None)
522 mod = getattr(cls, '__module__', None)
523 name = getattr(cls, '__name__', None)
523 name = getattr(cls, '__name__', None)
524 key = (mod, name)
524 key = (mod, name)
525 if key in self.deferred_printers:
525 if key in self.deferred_printers:
526 # Move the printer over to the regular registry.
526 # Move the printer over to the regular registry.
527 printer = self.deferred_printers.pop(key)
527 printer = self.deferred_printers.pop(key)
528 self.type_printers[cls] = printer
528 self.type_printers[cls] = printer
529 return True
529 return True
530 return False
530 return False
531
531
532
532
533 class PlainTextFormatter(BaseFormatter):
533 class PlainTextFormatter(BaseFormatter):
534 """The default pretty-printer.
534 """The default pretty-printer.
535
535
536 This uses :mod:`IPython.lib.pretty` to compute the format data of
536 This uses :mod:`IPython.lib.pretty` to compute the format data of
537 the object. If the object cannot be pretty printed, :func:`repr` is used.
537 the object. If the object cannot be pretty printed, :func:`repr` is used.
538 See the documentation of :mod:`IPython.lib.pretty` for details on
538 See the documentation of :mod:`IPython.lib.pretty` for details on
539 how to write pretty printers. Here is a simple example::
539 how to write pretty printers. Here is a simple example::
540
540
541 def dtype_pprinter(obj, p, cycle):
541 def dtype_pprinter(obj, p, cycle):
542 if cycle:
542 if cycle:
543 return p.text('dtype(...)')
543 return p.text('dtype(...)')
544 if hasattr(obj, 'fields'):
544 if hasattr(obj, 'fields'):
545 if obj.fields is None:
545 if obj.fields is None:
546 p.text(repr(obj))
546 p.text(repr(obj))
547 else:
547 else:
548 p.begin_group(7, 'dtype([')
548 p.begin_group(7, 'dtype([')
549 for i, field in enumerate(obj.descr):
549 for i, field in enumerate(obj.descr):
550 if i > 0:
550 if i > 0:
551 p.text(',')
551 p.text(',')
552 p.breakable()
552 p.breakable()
553 p.pretty(field)
553 p.pretty(field)
554 p.end_group(7, '])')
554 p.end_group(7, '])')
555 """
555 """
556
556
557 # The format type of data returned.
557 # The format type of data returned.
558 format_type = Unicode('text/plain')
558 format_type = Unicode('text/plain')
559
559
560 # This subclass ignores this attribute as it always need to return
560 # This subclass ignores this attribute as it always need to return
561 # something.
561 # something.
562 enabled = Bool(True).tag(config=False)
562 enabled = Bool(True).tag(config=False)
563
563
564 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
564 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
565 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
565 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
566
566
567 Set to 0 to disable truncation.
567 Set to 0 to disable truncation.
568 """
568 """
569 ).tag(config=True)
569 ).tag(config=True)
570
570
571 # Look for a _repr_pretty_ methods to use for pretty printing.
571 # Look for a _repr_pretty_ methods to use for pretty printing.
572 print_method = ObjectName('_repr_pretty_')
572 print_method = ObjectName('_repr_pretty_')
573
573
574 # Whether to pretty-print or not.
574 # Whether to pretty-print or not.
575 pprint = Bool(True).tag(config=True)
575 pprint = Bool(True).tag(config=True)
576
576
577 # Whether to be verbose or not.
577 # Whether to be verbose or not.
578 verbose = Bool(False).tag(config=True)
578 verbose = Bool(False).tag(config=True)
579
579
580 # The maximum width.
580 # The maximum width.
581 max_width = Integer(79).tag(config=True)
581 max_width = Integer(79).tag(config=True)
582
582
583 # The newline character.
583 # The newline character.
584 newline = Unicode('\n').tag(config=True)
584 newline = Unicode('\n').tag(config=True)
585
585
586 # format-string for pprinting floats
586 # format-string for pprinting floats
587 float_format = Unicode('%r')
587 float_format = Unicode('%r')
588 # setter for float precision, either int or direct format-string
588 # setter for float precision, either int or direct format-string
589 float_precision = CUnicode('').tag(config=True)
589 float_precision = CUnicode('').tag(config=True)
590
590
591 @observe('float_precision')
591 @observe('float_precision')
592 def _float_precision_changed(self, change):
592 def _float_precision_changed(self, change):
593 """float_precision changed, set float_format accordingly.
593 """float_precision changed, set float_format accordingly.
594
594
595 float_precision can be set by int or str.
595 float_precision can be set by int or str.
596 This will set float_format, after interpreting input.
596 This will set float_format, after interpreting input.
597 If numpy has been imported, numpy print precision will also be set.
597 If numpy has been imported, numpy print precision will also be set.
598
598
599 integer `n` sets format to '%.nf', otherwise, format set directly.
599 integer `n` sets format to '%.nf', otherwise, format set directly.
600
600
601 An empty string returns to defaults (repr for float, 8 for numpy).
601 An empty string returns to defaults (repr for float, 8 for numpy).
602
602
603 This parameter can be set via the '%precision' magic.
603 This parameter can be set via the '%precision' magic.
604 """
604 """
605
605
606 new = change['new']
606 new = change['new']
607 if '%' in new:
607 if '%' in new:
608 # got explicit format string
608 # got explicit format string
609 fmt = new
609 fmt = new
610 try:
610 try:
611 fmt%3.14159
611 fmt%3.14159
612 except Exception:
612 except Exception:
613 raise ValueError("Precision must be int or format string, not %r"%new)
613 raise ValueError("Precision must be int or format string, not %r"%new)
614 elif new:
614 elif new:
615 # otherwise, should be an int
615 # otherwise, should be an int
616 try:
616 try:
617 i = int(new)
617 i = int(new)
618 assert i >= 0
618 assert i >= 0
619 except ValueError:
619 except ValueError:
620 raise ValueError("Precision must be int or format string, not %r"%new)
620 raise ValueError("Precision must be int or format string, not %r"%new)
621 except AssertionError:
621 except AssertionError:
622 raise ValueError("int precision must be non-negative, not %r"%i)
622 raise ValueError("int precision must be non-negative, not %r"%i)
623
623
624 fmt = '%%.%if'%i
624 fmt = '%%.%if'%i
625 if 'numpy' in sys.modules:
625 if 'numpy' in sys.modules:
626 # set numpy precision if it has been imported
626 # set numpy precision if it has been imported
627 import numpy
627 import numpy
628 numpy.set_printoptions(precision=i)
628 numpy.set_printoptions(precision=i)
629 else:
629 else:
630 # default back to repr
630 # default back to repr
631 fmt = '%r'
631 fmt = '%r'
632 if 'numpy' in sys.modules:
632 if 'numpy' in sys.modules:
633 import numpy
633 import numpy
634 # numpy default is 8
634 # numpy default is 8
635 numpy.set_printoptions(precision=8)
635 numpy.set_printoptions(precision=8)
636 self.float_format = fmt
636 self.float_format = fmt
637
637
638 # Use the default pretty printers from IPython.lib.pretty.
638 # Use the default pretty printers from IPython.lib.pretty.
639 @default('singleton_printers')
639 @default('singleton_printers')
640 def _singleton_printers_default(self):
640 def _singleton_printers_default(self):
641 return pretty._singleton_pprinters.copy()
641 return pretty._singleton_pprinters.copy()
642
642
643 @default('type_printers')
643 @default('type_printers')
644 def _type_printers_default(self):
644 def _type_printers_default(self):
645 d = pretty._type_pprinters.copy()
645 d = pretty._type_pprinters.copy()
646 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
646 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
647 return d
647 return d
648
648
649 @default('deferred_printers')
649 @default('deferred_printers')
650 def _deferred_printers_default(self):
650 def _deferred_printers_default(self):
651 return pretty._deferred_type_pprinters.copy()
651 return pretty._deferred_type_pprinters.copy()
652
652
653 #### FormatterABC interface ####
653 #### FormatterABC interface ####
654
654
655 @catch_format_error
655 @catch_format_error
656 def __call__(self, obj):
656 def __call__(self, obj):
657 """Compute the pretty representation of the object."""
657 """Compute the pretty representation of the object."""
658 if not self.pprint:
658 if not self.pprint:
659 return repr(obj)
659 return repr(obj)
660 else:
660 else:
661 # handle str and unicode on Python 2
661 # handle str and unicode on Python 2
662 # io.StringIO only accepts unicode,
662 # io.StringIO only accepts unicode,
663 # cStringIO doesn't handle unicode on py2,
663 # cStringIO doesn't handle unicode on py2,
664 # StringIO allows str, unicode but only ascii str
664 # StringIO allows str, unicode but only ascii str
665 stream = pretty.CUnicodeIO()
665 stream = pretty.CUnicodeIO()
666 printer = pretty.RepresentationPrinter(stream, self.verbose,
666 printer = pretty.RepresentationPrinter(stream, self.verbose,
667 self.max_width, self.newline,
667 self.max_width, self.newline,
668 max_seq_length=self.max_seq_length,
668 max_seq_length=self.max_seq_length,
669 singleton_pprinters=self.singleton_printers,
669 singleton_pprinters=self.singleton_printers,
670 type_pprinters=self.type_printers,
670 type_pprinters=self.type_printers,
671 deferred_pprinters=self.deferred_printers)
671 deferred_pprinters=self.deferred_printers)
672 printer.pretty(obj)
672 printer.pretty(obj)
673 printer.flush()
673 printer.flush()
674 return stream.getvalue()
674 return stream.getvalue()
675
675
676
676
677 class HTMLFormatter(BaseFormatter):
677 class HTMLFormatter(BaseFormatter):
678 """An HTML formatter.
678 """An HTML formatter.
679
679
680 To define the callables that compute the HTML representation of your
680 To define the callables that compute the HTML representation of your
681 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
681 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
682 or :meth:`for_type_by_name` methods to register functions that handle
682 or :meth:`for_type_by_name` methods to register functions that handle
683 this.
683 this.
684
684
685 The return value of this formatter should be a valid HTML snippet that
685 The return value of this formatter should be a valid HTML snippet that
686 could be injected into an existing DOM. It should *not* include the
686 could be injected into an existing DOM. It should *not* include the
687 ```<html>`` or ```<body>`` tags.
687 ```<html>`` or ```<body>`` tags.
688 """
688 """
689 format_type = Unicode('text/html')
689 format_type = Unicode('text/html')
690
690
691 print_method = ObjectName('_repr_html_')
691 print_method = ObjectName('_repr_html_')
692
692
693
693
694 class MarkdownFormatter(BaseFormatter):
694 class MarkdownFormatter(BaseFormatter):
695 """A Markdown formatter.
695 """A Markdown formatter.
696
696
697 To define the callables that compute the Markdown representation of your
697 To define the callables that compute the Markdown representation of your
698 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
698 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
699 or :meth:`for_type_by_name` methods to register functions that handle
699 or :meth:`for_type_by_name` methods to register functions that handle
700 this.
700 this.
701
701
702 The return value of this formatter should be a valid Markdown.
702 The return value of this formatter should be a valid Markdown.
703 """
703 """
704 format_type = Unicode('text/markdown')
704 format_type = Unicode('text/markdown')
705
705
706 print_method = ObjectName('_repr_markdown_')
706 print_method = ObjectName('_repr_markdown_')
707
707
708 class SVGFormatter(BaseFormatter):
708 class SVGFormatter(BaseFormatter):
709 """An SVG formatter.
709 """An SVG formatter.
710
710
711 To define the callables that compute the SVG representation of your
711 To define the callables that compute the SVG representation of your
712 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
712 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
713 or :meth:`for_type_by_name` methods to register functions that handle
713 or :meth:`for_type_by_name` methods to register functions that handle
714 this.
714 this.
715
715
716 The return value of this formatter should be valid SVG enclosed in
716 The return value of this formatter should be valid SVG enclosed in
717 ```<svg>``` tags, that could be injected into an existing DOM. It should
717 ```<svg>``` tags, that could be injected into an existing DOM. It should
718 *not* include the ```<html>`` or ```<body>`` tags.
718 *not* include the ```<html>`` or ```<body>`` tags.
719 """
719 """
720 format_type = Unicode('image/svg+xml')
720 format_type = Unicode('image/svg+xml')
721
721
722 print_method = ObjectName('_repr_svg_')
722 print_method = ObjectName('_repr_svg_')
723
723
724
724
725 class PNGFormatter(BaseFormatter):
725 class PNGFormatter(BaseFormatter):
726 """A PNG formatter.
726 """A PNG formatter.
727
727
728 To define the callables that compute the PNG representation of your
728 To define the callables that compute the PNG representation of your
729 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
729 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
730 or :meth:`for_type_by_name` methods to register functions that handle
730 or :meth:`for_type_by_name` methods to register functions that handle
731 this.
731 this.
732
732
733 The return value of this formatter should be raw PNG data, *not*
733 The return value of this formatter should be raw PNG data, *not*
734 base64 encoded.
734 base64 encoded.
735 """
735 """
736 format_type = Unicode('image/png')
736 format_type = Unicode('image/png')
737
737
738 print_method = ObjectName('_repr_png_')
738 print_method = ObjectName('_repr_png_')
739
739
740 _return_type = (bytes, unicode_type)
740 _return_type = (bytes, str)
741
741
742
742
743 class JPEGFormatter(BaseFormatter):
743 class JPEGFormatter(BaseFormatter):
744 """A JPEG formatter.
744 """A JPEG formatter.
745
745
746 To define the callables that compute the JPEG representation of your
746 To define the callables that compute the JPEG representation of your
747 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
747 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
748 or :meth:`for_type_by_name` methods to register functions that handle
748 or :meth:`for_type_by_name` methods to register functions that handle
749 this.
749 this.
750
750
751 The return value of this formatter should be raw JPEG data, *not*
751 The return value of this formatter should be raw JPEG data, *not*
752 base64 encoded.
752 base64 encoded.
753 """
753 """
754 format_type = Unicode('image/jpeg')
754 format_type = Unicode('image/jpeg')
755
755
756 print_method = ObjectName('_repr_jpeg_')
756 print_method = ObjectName('_repr_jpeg_')
757
757
758 _return_type = (bytes, unicode_type)
758 _return_type = (bytes, str)
759
759
760
760
761 class LatexFormatter(BaseFormatter):
761 class LatexFormatter(BaseFormatter):
762 """A LaTeX formatter.
762 """A LaTeX formatter.
763
763
764 To define the callables that compute the LaTeX representation of your
764 To define the callables that compute the LaTeX representation of your
765 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
765 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
766 or :meth:`for_type_by_name` methods to register functions that handle
766 or :meth:`for_type_by_name` methods to register functions that handle
767 this.
767 this.
768
768
769 The return value of this formatter should be a valid LaTeX equation,
769 The return value of this formatter should be a valid LaTeX equation,
770 enclosed in either ```$```, ```$$``` or another LaTeX equation
770 enclosed in either ```$```, ```$$``` or another LaTeX equation
771 environment.
771 environment.
772 """
772 """
773 format_type = Unicode('text/latex')
773 format_type = Unicode('text/latex')
774
774
775 print_method = ObjectName('_repr_latex_')
775 print_method = ObjectName('_repr_latex_')
776
776
777
777
778 class JSONFormatter(BaseFormatter):
778 class JSONFormatter(BaseFormatter):
779 """A JSON string formatter.
779 """A JSON string formatter.
780
780
781 To define the callables that compute the JSONable representation of
781 To define the callables that compute the JSONable representation of
782 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
782 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
783 or :meth:`for_type_by_name` methods to register functions that handle
783 or :meth:`for_type_by_name` methods to register functions that handle
784 this.
784 this.
785
785
786 The return value of this formatter should be a JSONable list or dict.
786 The return value of this formatter should be a JSONable list or dict.
787 JSON scalars (None, number, string) are not allowed, only dict or list containers.
787 JSON scalars (None, number, string) are not allowed, only dict or list containers.
788 """
788 """
789 format_type = Unicode('application/json')
789 format_type = Unicode('application/json')
790 _return_type = (list, dict)
790 _return_type = (list, dict)
791
791
792 print_method = ObjectName('_repr_json_')
792 print_method = ObjectName('_repr_json_')
793
793
794 def _check_return(self, r, obj):
794 def _check_return(self, r, obj):
795 """Check that a return value is appropriate
795 """Check that a return value is appropriate
796
796
797 Return the value if so, None otherwise, warning if invalid.
797 Return the value if so, None otherwise, warning if invalid.
798 """
798 """
799 if r is None:
799 if r is None:
800 return
800 return
801 md = None
801 md = None
802 if isinstance(r, tuple):
802 if isinstance(r, tuple):
803 # unpack data, metadata tuple for type checking on first element
803 # unpack data, metadata tuple for type checking on first element
804 r, md = r
804 r, md = r
805
805
806 # handle deprecated JSON-as-string form from IPython < 3
806 # handle deprecated JSON-as-string form from IPython < 3
807 if isinstance(r, string_types):
807 if isinstance(r, str):
808 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
808 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
809 FormatterWarning)
809 FormatterWarning)
810 r = json.loads(r)
810 r = json.loads(r)
811
811
812 if md is not None:
812 if md is not None:
813 # put the tuple back together
813 # put the tuple back together
814 r = (r, md)
814 r = (r, md)
815 return super(JSONFormatter, self)._check_return(r, obj)
815 return super(JSONFormatter, self)._check_return(r, obj)
816
816
817
817
818 class JavascriptFormatter(BaseFormatter):
818 class JavascriptFormatter(BaseFormatter):
819 """A Javascript formatter.
819 """A Javascript formatter.
820
820
821 To define the callables that compute the Javascript representation of
821 To define the callables that compute the Javascript representation of
822 your objects, define a :meth:`_repr_javascript_` method or use the
822 your objects, define a :meth:`_repr_javascript_` method or use the
823 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
823 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
824 that handle this.
824 that handle this.
825
825
826 The return value of this formatter should be valid Javascript code and
826 The return value of this formatter should be valid Javascript code and
827 should *not* be enclosed in ```<script>``` tags.
827 should *not* be enclosed in ```<script>``` tags.
828 """
828 """
829 format_type = Unicode('application/javascript')
829 format_type = Unicode('application/javascript')
830
830
831 print_method = ObjectName('_repr_javascript_')
831 print_method = ObjectName('_repr_javascript_')
832
832
833
833
834 class PDFFormatter(BaseFormatter):
834 class PDFFormatter(BaseFormatter):
835 """A PDF formatter.
835 """A PDF formatter.
836
836
837 To define the callables that compute the PDF representation of your
837 To define the callables that compute the PDF representation of your
838 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
838 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
839 or :meth:`for_type_by_name` methods to register functions that handle
839 or :meth:`for_type_by_name` methods to register functions that handle
840 this.
840 this.
841
841
842 The return value of this formatter should be raw PDF data, *not*
842 The return value of this formatter should be raw PDF data, *not*
843 base64 encoded.
843 base64 encoded.
844 """
844 """
845 format_type = Unicode('application/pdf')
845 format_type = Unicode('application/pdf')
846
846
847 print_method = ObjectName('_repr_pdf_')
847 print_method = ObjectName('_repr_pdf_')
848
848
849 _return_type = (bytes, unicode_type)
849 _return_type = (bytes, str)
850
850
851 class IPythonDisplayFormatter(BaseFormatter):
851 class IPythonDisplayFormatter(BaseFormatter):
852 """A Formatter for objects that know how to display themselves.
852 """A Formatter for objects that know how to display themselves.
853
853
854 To define the callables that compute the representation of your
854 To define the callables that compute the representation of your
855 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
855 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
856 or :meth:`for_type_by_name` methods to register functions that handle
856 or :meth:`for_type_by_name` methods to register functions that handle
857 this. Unlike mime-type displays, this method should not return anything,
857 this. Unlike mime-type displays, this method should not return anything,
858 instead calling any appropriate display methods itself.
858 instead calling any appropriate display methods itself.
859
859
860 This display formatter has highest priority.
860 This display formatter has highest priority.
861 If it fires, no other display formatter will be called.
861 If it fires, no other display formatter will be called.
862 """
862 """
863 print_method = ObjectName('_ipython_display_')
863 print_method = ObjectName('_ipython_display_')
864 _return_type = (type(None), bool)
864 _return_type = (type(None), bool)
865
865
866
866
867 @catch_format_error
867 @catch_format_error
868 def __call__(self, obj):
868 def __call__(self, obj):
869 """Compute the format for an object."""
869 """Compute the format for an object."""
870 if self.enabled:
870 if self.enabled:
871 # lookup registered printer
871 # lookup registered printer
872 try:
872 try:
873 printer = self.lookup(obj)
873 printer = self.lookup(obj)
874 except KeyError:
874 except KeyError:
875 pass
875 pass
876 else:
876 else:
877 printer(obj)
877 printer(obj)
878 return True
878 return True
879 # Finally look for special method names
879 # Finally look for special method names
880 method = get_real_method(obj, self.print_method)
880 method = get_real_method(obj, self.print_method)
881 if method is not None:
881 if method is not None:
882 method()
882 method()
883 return True
883 return True
884
884
885
885
886 FormatterABC.register(BaseFormatter)
886 FormatterABC.register(BaseFormatter)
887 FormatterABC.register(PlainTextFormatter)
887 FormatterABC.register(PlainTextFormatter)
888 FormatterABC.register(HTMLFormatter)
888 FormatterABC.register(HTMLFormatter)
889 FormatterABC.register(MarkdownFormatter)
889 FormatterABC.register(MarkdownFormatter)
890 FormatterABC.register(SVGFormatter)
890 FormatterABC.register(SVGFormatter)
891 FormatterABC.register(PNGFormatter)
891 FormatterABC.register(PNGFormatter)
892 FormatterABC.register(PDFFormatter)
892 FormatterABC.register(PDFFormatter)
893 FormatterABC.register(JPEGFormatter)
893 FormatterABC.register(JPEGFormatter)
894 FormatterABC.register(LatexFormatter)
894 FormatterABC.register(LatexFormatter)
895 FormatterABC.register(JSONFormatter)
895 FormatterABC.register(JSONFormatter)
896 FormatterABC.register(JavascriptFormatter)
896 FormatterABC.register(JavascriptFormatter)
897 FormatterABC.register(IPythonDisplayFormatter)
897 FormatterABC.register(IPythonDisplayFormatter)
898
898
899
899
900 def format_display_data(obj, include=None, exclude=None):
900 def format_display_data(obj, include=None, exclude=None):
901 """Return a format data dict for an object.
901 """Return a format data dict for an object.
902
902
903 By default all format types will be computed.
903 By default all format types will be computed.
904
904
905 The following MIME types are currently implemented:
905 The following MIME types are currently implemented:
906
906
907 * text/plain
907 * text/plain
908 * text/html
908 * text/html
909 * text/markdown
909 * text/markdown
910 * text/latex
910 * text/latex
911 * application/json
911 * application/json
912 * application/javascript
912 * application/javascript
913 * application/pdf
913 * application/pdf
914 * image/png
914 * image/png
915 * image/jpeg
915 * image/jpeg
916 * image/svg+xml
916 * image/svg+xml
917
917
918 Parameters
918 Parameters
919 ----------
919 ----------
920 obj : object
920 obj : object
921 The Python object whose format data will be computed.
921 The Python object whose format data will be computed.
922
922
923 Returns
923 Returns
924 -------
924 -------
925 format_dict : dict
925 format_dict : dict
926 A dictionary of key/value pairs, one or each format that was
926 A dictionary of key/value pairs, one or each format that was
927 generated for the object. The keys are the format types, which
927 generated for the object. The keys are the format types, which
928 will usually be MIME type strings and the values and JSON'able
928 will usually be MIME type strings and the values and JSON'able
929 data structure containing the raw data for the representation in
929 data structure containing the raw data for the representation in
930 that format.
930 that format.
931 include : list or tuple, optional
931 include : list or tuple, optional
932 A list of format type strings (MIME types) to include in the
932 A list of format type strings (MIME types) to include in the
933 format data dict. If this is set *only* the format types included
933 format data dict. If this is set *only* the format types included
934 in this list will be computed.
934 in this list will be computed.
935 exclude : list or tuple, optional
935 exclude : list or tuple, optional
936 A list of format type string (MIME types) to exclue in the format
936 A list of format type string (MIME types) to exclue in the format
937 data dict. If this is set all format types will be computed,
937 data dict. If this is set all format types will be computed,
938 except for those included in this argument.
938 except for those included in this argument.
939 """
939 """
940 from IPython.core.interactiveshell import InteractiveShell
940 from IPython.core.interactiveshell import InteractiveShell
941
941
942 return InteractiveShell.instance().display_formatter.format(
942 return InteractiveShell.instance().display_formatter.format(
943 obj,
943 obj,
944 include,
944 include,
945 exclude
945 exclude
946 )
946 )
947
947
@@ -1,910 +1,910 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
6
7 import atexit
7 import atexit
8 import datetime
8 import datetime
9 import os
9 import os
10 import re
10 import re
11 try:
11 try:
12 import sqlite3
12 import sqlite3
13 except ImportError:
13 except ImportError:
14 try:
14 try:
15 from pysqlite2 import dbapi2 as sqlite3
15 from pysqlite2 import dbapi2 as sqlite3
16 except ImportError:
16 except ImportError:
17 sqlite3 = None
17 sqlite3 = None
18 import threading
18 import threading
19
19
20 from traitlets.config.configurable import LoggingConfigurable
20 from traitlets.config.configurable import LoggingConfigurable
21 from decorator import decorator
21 from decorator import decorator
22 from IPython.utils.decorators import undoc
22 from IPython.utils.decorators import undoc
23 from IPython.utils.path import locate_profile
23 from IPython.utils.path import locate_profile
24 from IPython.utils import py3compat
24 from IPython.utils import py3compat
25 from traitlets import (
25 from traitlets import (
26 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
26 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
27 default, observe,
27 default, observe,
28 )
28 )
29 from warnings import warn
29 from warnings import warn
30
30
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 # Classes and functions
32 # Classes and functions
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34
34
35 @undoc
35 @undoc
36 class DummyDB(object):
36 class DummyDB(object):
37 """Dummy DB that will act as a black hole for history.
37 """Dummy DB that will act as a black hole for history.
38
38
39 Only used in the absence of sqlite"""
39 Only used in the absence of sqlite"""
40 def execute(*args, **kwargs):
40 def execute(*args, **kwargs):
41 return []
41 return []
42
42
43 def commit(self, *args, **kwargs):
43 def commit(self, *args, **kwargs):
44 pass
44 pass
45
45
46 def __enter__(self, *args, **kwargs):
46 def __enter__(self, *args, **kwargs):
47 pass
47 pass
48
48
49 def __exit__(self, *args, **kwargs):
49 def __exit__(self, *args, **kwargs):
50 pass
50 pass
51
51
52
52
53 @decorator
53 @decorator
54 def needs_sqlite(f, self, *a, **kw):
54 def needs_sqlite(f, self, *a, **kw):
55 """Decorator: return an empty list in the absence of sqlite."""
55 """Decorator: return an empty list in the absence of sqlite."""
56 if sqlite3 is None or not self.enabled:
56 if sqlite3 is None or not self.enabled:
57 return []
57 return []
58 else:
58 else:
59 return f(self, *a, **kw)
59 return f(self, *a, **kw)
60
60
61
61
62 if sqlite3 is not None:
62 if sqlite3 is not None:
63 DatabaseError = sqlite3.DatabaseError
63 DatabaseError = sqlite3.DatabaseError
64 OperationalError = sqlite3.OperationalError
64 OperationalError = sqlite3.OperationalError
65 else:
65 else:
66 @undoc
66 @undoc
67 class DatabaseError(Exception):
67 class DatabaseError(Exception):
68 "Dummy exception when sqlite could not be imported. Should never occur."
68 "Dummy exception when sqlite could not be imported. Should never occur."
69
69
70 @undoc
70 @undoc
71 class OperationalError(Exception):
71 class OperationalError(Exception):
72 "Dummy exception when sqlite could not be imported. Should never occur."
72 "Dummy exception when sqlite could not be imported. Should never occur."
73
73
74 # use 16kB as threshold for whether a corrupt history db should be saved
74 # use 16kB as threshold for whether a corrupt history db should be saved
75 # that should be at least 100 entries or so
75 # that should be at least 100 entries or so
76 _SAVE_DB_SIZE = 16384
76 _SAVE_DB_SIZE = 16384
77
77
78 @decorator
78 @decorator
79 def catch_corrupt_db(f, self, *a, **kw):
79 def catch_corrupt_db(f, self, *a, **kw):
80 """A decorator which wraps HistoryAccessor method calls to catch errors from
80 """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
81 a corrupt SQLite database, move the old database out of the way, and create
82 a new one.
82 a new one.
83
83
84 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
84 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
85 not just a corrupt file.
85 not just a corrupt file.
86 """
86 """
87 try:
87 try:
88 return f(self, *a, **kw)
88 return f(self, *a, **kw)
89 except (DatabaseError, OperationalError) as e:
89 except (DatabaseError, OperationalError) as e:
90 self._corrupt_db_counter += 1
90 self._corrupt_db_counter += 1
91 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
91 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
92 if self.hist_file != ':memory:':
92 if self.hist_file != ':memory:':
93 if self._corrupt_db_counter > self._corrupt_db_limit:
93 if self._corrupt_db_counter > self._corrupt_db_limit:
94 self.hist_file = ':memory:'
94 self.hist_file = ':memory:'
95 self.log.error("Failed to load history too many times, history will not be saved.")
95 self.log.error("Failed to load history too many times, history will not be saved.")
96 elif os.path.isfile(self.hist_file):
96 elif os.path.isfile(self.hist_file):
97 # move the file out of the way
97 # move the file out of the way
98 base, ext = os.path.splitext(self.hist_file)
98 base, ext = os.path.splitext(self.hist_file)
99 size = os.stat(self.hist_file).st_size
99 size = os.stat(self.hist_file).st_size
100 if size >= _SAVE_DB_SIZE:
100 if size >= _SAVE_DB_SIZE:
101 # if there's significant content, avoid clobbering
101 # if there's significant content, avoid clobbering
102 now = datetime.datetime.now().isoformat().replace(':', '.')
102 now = datetime.datetime.now().isoformat().replace(':', '.')
103 newpath = base + '-corrupt-' + now + ext
103 newpath = base + '-corrupt-' + now + ext
104 # don't clobber previous corrupt backups
104 # don't clobber previous corrupt backups
105 for i in range(100):
105 for i in range(100):
106 if not os.path.isfile(newpath):
106 if not os.path.isfile(newpath):
107 break
107 break
108 else:
108 else:
109 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
109 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
110 else:
110 else:
111 # not much content, possibly empty; don't worry about clobbering
111 # not much content, possibly empty; don't worry about clobbering
112 # maybe we should just delete it?
112 # maybe we should just delete it?
113 newpath = base + '-corrupt' + ext
113 newpath = base + '-corrupt' + ext
114 os.rename(self.hist_file, newpath)
114 os.rename(self.hist_file, newpath)
115 self.log.error("History file was moved to %s and a new file created.", newpath)
115 self.log.error("History file was moved to %s and a new file created.", newpath)
116 self.init_db()
116 self.init_db()
117 return []
117 return []
118 else:
118 else:
119 # Failed with :memory:, something serious is wrong
119 # Failed with :memory:, something serious is wrong
120 raise
120 raise
121
121
122 class HistoryAccessorBase(LoggingConfigurable):
122 class HistoryAccessorBase(LoggingConfigurable):
123 """An abstract class for History Accessors """
123 """An abstract class for History Accessors """
124
124
125 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
125 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
126 raise NotImplementedError
126 raise NotImplementedError
127
127
128 def search(self, pattern="*", raw=True, search_raw=True,
128 def search(self, pattern="*", raw=True, search_raw=True,
129 output=False, n=None, unique=False):
129 output=False, n=None, unique=False):
130 raise NotImplementedError
130 raise NotImplementedError
131
131
132 def get_range(self, session, start=1, stop=None, raw=True,output=False):
132 def get_range(self, session, start=1, stop=None, raw=True,output=False):
133 raise NotImplementedError
133 raise NotImplementedError
134
134
135 def get_range_by_str(self, rangestr, raw=True, output=False):
135 def get_range_by_str(self, rangestr, raw=True, output=False):
136 raise NotImplementedError
136 raise NotImplementedError
137
137
138
138
139 class HistoryAccessor(HistoryAccessorBase):
139 class HistoryAccessor(HistoryAccessorBase):
140 """Access the history database without adding to it.
140 """Access the history database without adding to it.
141
141
142 This is intended for use by standalone history tools. IPython shells use
142 This is intended for use by standalone history tools. IPython shells use
143 HistoryManager, below, which is a subclass of this."""
143 HistoryManager, below, which is a subclass of this."""
144
144
145 # counter for init_db retries, so we don't keep trying over and over
145 # counter for init_db retries, so we don't keep trying over and over
146 _corrupt_db_counter = 0
146 _corrupt_db_counter = 0
147 # after two failures, fallback on :memory:
147 # after two failures, fallback on :memory:
148 _corrupt_db_limit = 2
148 _corrupt_db_limit = 2
149
149
150 # String holding the path to the history file
150 # String holding the path to the history file
151 hist_file = Unicode(
151 hist_file = Unicode(
152 help="""Path to file to use for SQLite history database.
152 help="""Path to file to use for SQLite history database.
153
153
154 By default, IPython will put the history database in the IPython
154 By default, IPython will put the history database in the IPython
155 profile directory. If you would rather share one history among
155 profile directory. If you would rather share one history among
156 profiles, you can set this value in each, so that they are consistent.
156 profiles, you can set this value in each, so that they are consistent.
157
157
158 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
158 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
159 mounts. If you see IPython hanging, try setting this to something on a
160 local disk, e.g::
160 local disk, e.g::
161
161
162 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
162 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
163
163
164 you can also use the specific value `:memory:` (including the colon
164 you can also use the specific value `:memory:` (including the colon
165 at both end but not the back ticks), to avoid creating an history file.
165 at both end but not the back ticks), to avoid creating an history file.
166
166
167 """).tag(config=True)
167 """).tag(config=True)
168
168
169 enabled = Bool(True,
169 enabled = Bool(True,
170 help="""enable the SQLite history
170 help="""enable the SQLite history
171
171
172 set enabled=False to disable the SQLite history,
172 set enabled=False to disable the SQLite history,
173 in which case there will be no stored history, no SQLite connection,
173 in which case there will be no stored history, no SQLite connection,
174 and no background saving thread. This may be necessary in some
174 and no background saving thread. This may be necessary in some
175 threaded environments where IPython is embedded.
175 threaded environments where IPython is embedded.
176 """
176 """
177 ).tag(config=True)
177 ).tag(config=True)
178
178
179 connection_options = Dict(
179 connection_options = Dict(
180 help="""Options for configuring the SQLite connection
180 help="""Options for configuring the SQLite connection
181
181
182 These options are passed as keyword args to sqlite3.connect
182 These options are passed as keyword args to sqlite3.connect
183 when establishing database conenctions.
183 when establishing database conenctions.
184 """
184 """
185 ).tag(config=True)
185 ).tag(config=True)
186
186
187 # The SQLite database
187 # The SQLite database
188 db = Any()
188 db = Any()
189 @observe('db')
189 @observe('db')
190 def _db_changed(self, change):
190 def _db_changed(self, change):
191 """validate the db, since it can be an Instance of two different types"""
191 """validate the db, since it can be an Instance of two different types"""
192 new = change['new']
192 new = change['new']
193 connection_types = (DummyDB,)
193 connection_types = (DummyDB,)
194 if sqlite3 is not None:
194 if sqlite3 is not None:
195 connection_types = (DummyDB, sqlite3.Connection)
195 connection_types = (DummyDB, sqlite3.Connection)
196 if not isinstance(new, connection_types):
196 if not isinstance(new, connection_types):
197 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
197 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
198 (self.__class__.__name__, new)
198 (self.__class__.__name__, new)
199 raise TraitError(msg)
199 raise TraitError(msg)
200
200
201 def __init__(self, profile='default', hist_file=u'', **traits):
201 def __init__(self, profile='default', hist_file=u'', **traits):
202 """Create a new history accessor.
202 """Create a new history accessor.
203
203
204 Parameters
204 Parameters
205 ----------
205 ----------
206 profile : str
206 profile : str
207 The name of the profile from which to open history.
207 The name of the profile from which to open history.
208 hist_file : str
208 hist_file : str
209 Path to an SQLite history database stored by IPython. If specified,
209 Path to an SQLite history database stored by IPython. If specified,
210 hist_file overrides profile.
210 hist_file overrides profile.
211 config : :class:`~traitlets.config.loader.Config`
211 config : :class:`~traitlets.config.loader.Config`
212 Config object. hist_file can also be set through this.
212 Config object. hist_file can also be set through this.
213 """
213 """
214 # We need a pointer back to the shell for various tasks.
214 # We need a pointer back to the shell for various tasks.
215 super(HistoryAccessor, self).__init__(**traits)
215 super(HistoryAccessor, self).__init__(**traits)
216 # defer setting hist_file from kwarg until after init,
216 # defer setting hist_file from kwarg until after init,
217 # otherwise the default kwarg value would clobber any value
217 # otherwise the default kwarg value would clobber any value
218 # set by config
218 # set by config
219 if hist_file:
219 if hist_file:
220 self.hist_file = hist_file
220 self.hist_file = hist_file
221
221
222 if self.hist_file == u'':
222 if self.hist_file == u'':
223 # No one has set the hist_file, yet.
223 # No one has set the hist_file, yet.
224 self.hist_file = self._get_hist_file_name(profile)
224 self.hist_file = self._get_hist_file_name(profile)
225
225
226 if sqlite3 is None and self.enabled:
226 if sqlite3 is None and self.enabled:
227 warn("IPython History requires SQLite, your history will not be saved")
227 warn("IPython History requires SQLite, your history will not be saved")
228 self.enabled = False
228 self.enabled = False
229
229
230 self.init_db()
230 self.init_db()
231
231
232 def _get_hist_file_name(self, profile='default'):
232 def _get_hist_file_name(self, profile='default'):
233 """Find the history file for the given profile name.
233 """Find the history file for the given profile name.
234
234
235 This is overridden by the HistoryManager subclass, to use the shell's
235 This is overridden by the HistoryManager subclass, to use the shell's
236 active profile.
236 active profile.
237
237
238 Parameters
238 Parameters
239 ----------
239 ----------
240 profile : str
240 profile : str
241 The name of a profile which has a history file.
241 The name of a profile which has a history file.
242 """
242 """
243 return os.path.join(locate_profile(profile), 'history.sqlite')
243 return os.path.join(locate_profile(profile), 'history.sqlite')
244
244
245 @catch_corrupt_db
245 @catch_corrupt_db
246 def init_db(self):
246 def init_db(self):
247 """Connect to the database, and create tables if necessary."""
247 """Connect to the database, and create tables if necessary."""
248 if not self.enabled:
248 if not self.enabled:
249 self.db = DummyDB()
249 self.db = DummyDB()
250 return
250 return
251
251
252 # use detect_types so that timestamps return datetime objects
252 # use detect_types so that timestamps return datetime objects
253 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
253 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
254 kwargs.update(self.connection_options)
254 kwargs.update(self.connection_options)
255 self.db = sqlite3.connect(self.hist_file, **kwargs)
255 self.db = sqlite3.connect(self.hist_file, **kwargs)
256 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
256 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
257 primary key autoincrement, start timestamp,
257 primary key autoincrement, start timestamp,
258 end timestamp, num_cmds integer, remark text)""")
258 end timestamp, num_cmds integer, remark text)""")
259 self.db.execute("""CREATE TABLE IF NOT EXISTS history
259 self.db.execute("""CREATE TABLE IF NOT EXISTS history
260 (session integer, line integer, source text, source_raw text,
260 (session integer, line integer, source text, source_raw text,
261 PRIMARY KEY (session, line))""")
261 PRIMARY KEY (session, line))""")
262 # Output history is optional, but ensure the table's there so it can be
262 # Output history is optional, but ensure the table's there so it can be
263 # enabled later.
263 # enabled later.
264 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
264 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
265 (session integer, line integer, output text,
265 (session integer, line integer, output text,
266 PRIMARY KEY (session, line))""")
266 PRIMARY KEY (session, line))""")
267 self.db.commit()
267 self.db.commit()
268 # success! reset corrupt db count
268 # success! reset corrupt db count
269 self._corrupt_db_counter = 0
269 self._corrupt_db_counter = 0
270
270
271 def writeout_cache(self):
271 def writeout_cache(self):
272 """Overridden by HistoryManager to dump the cache before certain
272 """Overridden by HistoryManager to dump the cache before certain
273 database lookups."""
273 database lookups."""
274 pass
274 pass
275
275
276 ## -------------------------------
276 ## -------------------------------
277 ## Methods for retrieving history:
277 ## Methods for retrieving history:
278 ## -------------------------------
278 ## -------------------------------
279 def _run_sql(self, sql, params, raw=True, output=False):
279 def _run_sql(self, sql, params, raw=True, output=False):
280 """Prepares and runs an SQL query for the history database.
280 """Prepares and runs an SQL query for the history database.
281
281
282 Parameters
282 Parameters
283 ----------
283 ----------
284 sql : str
284 sql : str
285 Any filtering expressions to go after SELECT ... FROM ...
285 Any filtering expressions to go after SELECT ... FROM ...
286 params : tuple
286 params : tuple
287 Parameters passed to the SQL query (to replace "?")
287 Parameters passed to the SQL query (to replace "?")
288 raw, output : bool
288 raw, output : bool
289 See :meth:`get_range`
289 See :meth:`get_range`
290
290
291 Returns
291 Returns
292 -------
292 -------
293 Tuples as :meth:`get_range`
293 Tuples as :meth:`get_range`
294 """
294 """
295 toget = 'source_raw' if raw else 'source'
295 toget = 'source_raw' if raw else 'source'
296 sqlfrom = "history"
296 sqlfrom = "history"
297 if output:
297 if output:
298 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
298 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
299 toget = "history.%s, output_history.output" % toget
299 toget = "history.%s, output_history.output" % toget
300 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
300 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
301 (toget, sqlfrom) + sql, params)
301 (toget, sqlfrom) + sql, params)
302 if output: # Regroup into 3-tuples, and parse JSON
302 if output: # Regroup into 3-tuples, and parse JSON
303 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
303 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
304 return cur
304 return cur
305
305
306 @needs_sqlite
306 @needs_sqlite
307 @catch_corrupt_db
307 @catch_corrupt_db
308 def get_session_info(self, session):
308 def get_session_info(self, session):
309 """Get info about a session.
309 """Get info about a session.
310
310
311 Parameters
311 Parameters
312 ----------
312 ----------
313
313
314 session : int
314 session : int
315 Session number to retrieve.
315 Session number to retrieve.
316
316
317 Returns
317 Returns
318 -------
318 -------
319
319
320 session_id : int
320 session_id : int
321 Session ID number
321 Session ID number
322 start : datetime
322 start : datetime
323 Timestamp for the start of the session.
323 Timestamp for the start of the session.
324 end : datetime
324 end : datetime
325 Timestamp for the end of the session, or None if IPython crashed.
325 Timestamp for the end of the session, or None if IPython crashed.
326 num_cmds : int
326 num_cmds : int
327 Number of commands run, or None if IPython crashed.
327 Number of commands run, or None if IPython crashed.
328 remark : unicode
328 remark : unicode
329 A manually set description.
329 A manually set description.
330 """
330 """
331 query = "SELECT * from sessions where session == ?"
331 query = "SELECT * from sessions where session == ?"
332 return self.db.execute(query, (session,)).fetchone()
332 return self.db.execute(query, (session,)).fetchone()
333
333
334 @catch_corrupt_db
334 @catch_corrupt_db
335 def get_last_session_id(self):
335 def get_last_session_id(self):
336 """Get the last session ID currently in the database.
336 """Get the last session ID currently in the database.
337
337
338 Within IPython, this should be the same as the value stored in
338 Within IPython, this should be the same as the value stored in
339 :attr:`HistoryManager.session_number`.
339 :attr:`HistoryManager.session_number`.
340 """
340 """
341 for record in self.get_tail(n=1, include_latest=True):
341 for record in self.get_tail(n=1, include_latest=True):
342 return record[0]
342 return record[0]
343
343
344 @catch_corrupt_db
344 @catch_corrupt_db
345 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
345 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
346 """Get the last n lines from the history database.
346 """Get the last n lines from the history database.
347
347
348 Parameters
348 Parameters
349 ----------
349 ----------
350 n : int
350 n : int
351 The number of lines to get
351 The number of lines to get
352 raw, output : bool
352 raw, output : bool
353 See :meth:`get_range`
353 See :meth:`get_range`
354 include_latest : bool
354 include_latest : bool
355 If False (default), n+1 lines are fetched, and the latest one
355 If False (default), n+1 lines are fetched, and the latest one
356 is discarded. This is intended to be used where the function
356 is discarded. This is intended to be used where the function
357 is called by a user command, which it should not return.
357 is called by a user command, which it should not return.
358
358
359 Returns
359 Returns
360 -------
360 -------
361 Tuples as :meth:`get_range`
361 Tuples as :meth:`get_range`
362 """
362 """
363 self.writeout_cache()
363 self.writeout_cache()
364 if not include_latest:
364 if not include_latest:
365 n += 1
365 n += 1
366 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
366 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
367 (n,), raw=raw, output=output)
367 (n,), raw=raw, output=output)
368 if not include_latest:
368 if not include_latest:
369 return reversed(list(cur)[1:])
369 return reversed(list(cur)[1:])
370 return reversed(list(cur))
370 return reversed(list(cur))
371
371
372 @catch_corrupt_db
372 @catch_corrupt_db
373 def search(self, pattern="*", raw=True, search_raw=True,
373 def search(self, pattern="*", raw=True, search_raw=True,
374 output=False, n=None, unique=False):
374 output=False, n=None, unique=False):
375 """Search the database using unix glob-style matching (wildcards
375 """Search the database using unix glob-style matching (wildcards
376 * and ?).
376 * and ?).
377
377
378 Parameters
378 Parameters
379 ----------
379 ----------
380 pattern : str
380 pattern : str
381 The wildcarded pattern to match when searching
381 The wildcarded pattern to match when searching
382 search_raw : bool
382 search_raw : bool
383 If True, search the raw input, otherwise, the parsed input
383 If True, search the raw input, otherwise, the parsed input
384 raw, output : bool
384 raw, output : bool
385 See :meth:`get_range`
385 See :meth:`get_range`
386 n : None or int
386 n : None or int
387 If an integer is given, it defines the limit of
387 If an integer is given, it defines the limit of
388 returned entries.
388 returned entries.
389 unique : bool
389 unique : bool
390 When it is true, return only unique entries.
390 When it is true, return only unique entries.
391
391
392 Returns
392 Returns
393 -------
393 -------
394 Tuples as :meth:`get_range`
394 Tuples as :meth:`get_range`
395 """
395 """
396 tosearch = "source_raw" if search_raw else "source"
396 tosearch = "source_raw" if search_raw else "source"
397 if output:
397 if output:
398 tosearch = "history." + tosearch
398 tosearch = "history." + tosearch
399 self.writeout_cache()
399 self.writeout_cache()
400 sqlform = "WHERE %s GLOB ?" % tosearch
400 sqlform = "WHERE %s GLOB ?" % tosearch
401 params = (pattern,)
401 params = (pattern,)
402 if unique:
402 if unique:
403 sqlform += ' GROUP BY {0}'.format(tosearch)
403 sqlform += ' GROUP BY {0}'.format(tosearch)
404 if n is not None:
404 if n is not None:
405 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
405 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
406 params += (n,)
406 params += (n,)
407 elif unique:
407 elif unique:
408 sqlform += " ORDER BY session, line"
408 sqlform += " ORDER BY session, line"
409 cur = self._run_sql(sqlform, params, raw=raw, output=output)
409 cur = self._run_sql(sqlform, params, raw=raw, output=output)
410 if n is not None:
410 if n is not None:
411 return reversed(list(cur))
411 return reversed(list(cur))
412 return cur
412 return cur
413
413
414 @catch_corrupt_db
414 @catch_corrupt_db
415 def get_range(self, session, start=1, stop=None, raw=True,output=False):
415 def get_range(self, session, start=1, stop=None, raw=True,output=False):
416 """Retrieve input by session.
416 """Retrieve input by session.
417
417
418 Parameters
418 Parameters
419 ----------
419 ----------
420 session : int
420 session : int
421 Session number to retrieve.
421 Session number to retrieve.
422 start : int
422 start : int
423 First line to retrieve.
423 First line to retrieve.
424 stop : int
424 stop : int
425 End of line range (excluded from output itself). If None, retrieve
425 End of line range (excluded from output itself). If None, retrieve
426 to the end of the session.
426 to the end of the session.
427 raw : bool
427 raw : bool
428 If True, return untranslated input
428 If True, return untranslated input
429 output : bool
429 output : bool
430 If True, attempt to include output. This will be 'real' Python
430 If True, attempt to include output. This will be 'real' Python
431 objects for the current session, or text reprs from previous
431 objects for the current session, or text reprs from previous
432 sessions if db_log_output was enabled at the time. Where no output
432 sessions if db_log_output was enabled at the time. Where no output
433 is found, None is used.
433 is found, None is used.
434
434
435 Returns
435 Returns
436 -------
436 -------
437 entries
437 entries
438 An iterator over the desired lines. Each line is a 3-tuple, either
438 An iterator over the desired lines. Each line is a 3-tuple, either
439 (session, line, input) if output is False, or
439 (session, line, input) if output is False, or
440 (session, line, (input, output)) if output is True.
440 (session, line, (input, output)) if output is True.
441 """
441 """
442 if stop:
442 if stop:
443 lineclause = "line >= ? AND line < ?"
443 lineclause = "line >= ? AND line < ?"
444 params = (session, start, stop)
444 params = (session, start, stop)
445 else:
445 else:
446 lineclause = "line>=?"
446 lineclause = "line>=?"
447 params = (session, start)
447 params = (session, start)
448
448
449 return self._run_sql("WHERE session==? AND %s" % lineclause,
449 return self._run_sql("WHERE session==? AND %s" % lineclause,
450 params, raw=raw, output=output)
450 params, raw=raw, output=output)
451
451
452 def get_range_by_str(self, rangestr, raw=True, output=False):
452 def get_range_by_str(self, rangestr, raw=True, output=False):
453 """Get lines of history from a string of ranges, as used by magic
453 """Get lines of history from a string of ranges, as used by magic
454 commands %hist, %save, %macro, etc.
454 commands %hist, %save, %macro, etc.
455
455
456 Parameters
456 Parameters
457 ----------
457 ----------
458 rangestr : str
458 rangestr : str
459 A string specifying ranges, e.g. "5 ~2/1-4". See
459 A string specifying ranges, e.g. "5 ~2/1-4". See
460 :func:`magic_history` for full details.
460 :func:`magic_history` for full details.
461 raw, output : bool
461 raw, output : bool
462 As :meth:`get_range`
462 As :meth:`get_range`
463
463
464 Returns
464 Returns
465 -------
465 -------
466 Tuples as :meth:`get_range`
466 Tuples as :meth:`get_range`
467 """
467 """
468 for sess, s, e in extract_hist_ranges(rangestr):
468 for sess, s, e in extract_hist_ranges(rangestr):
469 for line in self.get_range(sess, s, e, raw=raw, output=output):
469 for line in self.get_range(sess, s, e, raw=raw, output=output):
470 yield line
470 yield line
471
471
472
472
473 class HistoryManager(HistoryAccessor):
473 class HistoryManager(HistoryAccessor):
474 """A class to organize all history-related functionality in one place.
474 """A class to organize all history-related functionality in one place.
475 """
475 """
476 # Public interface
476 # Public interface
477
477
478 # An instance of the IPython shell we are attached to
478 # An instance of the IPython shell we are attached to
479 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
479 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
480 allow_none=True)
480 allow_none=True)
481 # Lists to hold processed and raw history. These start with a blank entry
481 # Lists to hold processed and raw history. These start with a blank entry
482 # so that we can index them starting from 1
482 # so that we can index them starting from 1
483 input_hist_parsed = List([""])
483 input_hist_parsed = List([""])
484 input_hist_raw = List([""])
484 input_hist_raw = List([""])
485 # A list of directories visited during session
485 # A list of directories visited during session
486 dir_hist = List()
486 dir_hist = List()
487 @default('dir_hist')
487 @default('dir_hist')
488 def _dir_hist_default(self):
488 def _dir_hist_default(self):
489 try:
489 try:
490 return [py3compat.getcwd()]
490 return [os.getcwd()]
491 except OSError:
491 except OSError:
492 return []
492 return []
493
493
494 # A dict of output history, keyed with ints from the shell's
494 # A dict of output history, keyed with ints from the shell's
495 # execution count.
495 # execution count.
496 output_hist = Dict()
496 output_hist = Dict()
497 # The text/plain repr of outputs.
497 # The text/plain repr of outputs.
498 output_hist_reprs = Dict()
498 output_hist_reprs = Dict()
499
499
500 # The number of the current session in the history database
500 # The number of the current session in the history database
501 session_number = Integer()
501 session_number = Integer()
502
502
503 db_log_output = Bool(False,
503 db_log_output = Bool(False,
504 help="Should the history database include output? (default: no)"
504 help="Should the history database include output? (default: no)"
505 ).tag(config=True)
505 ).tag(config=True)
506 db_cache_size = Integer(0,
506 db_cache_size = Integer(0,
507 help="Write to database every x commands (higher values save disk access & power).\n"
507 help="Write to database every x commands (higher values save disk access & power).\n"
508 "Values of 1 or less effectively disable caching."
508 "Values of 1 or less effectively disable caching."
509 ).tag(config=True)
509 ).tag(config=True)
510 # The input and output caches
510 # The input and output caches
511 db_input_cache = List()
511 db_input_cache = List()
512 db_output_cache = List()
512 db_output_cache = List()
513
513
514 # History saving in separate thread
514 # History saving in separate thread
515 save_thread = Instance('IPython.core.history.HistorySavingThread',
515 save_thread = Instance('IPython.core.history.HistorySavingThread',
516 allow_none=True)
516 allow_none=True)
517 try: # Event is a function returning an instance of _Event...
517 try: # Event is a function returning an instance of _Event...
518 save_flag = Instance(threading._Event, allow_none=True)
518 save_flag = Instance(threading._Event, allow_none=True)
519 except AttributeError: # ...until Python 3.3, when it's a class.
519 except AttributeError: # ...until Python 3.3, when it's a class.
520 save_flag = Instance(threading.Event, allow_none=True)
520 save_flag = Instance(threading.Event, allow_none=True)
521
521
522 # Private interface
522 # Private interface
523 # Variables used to store the three last inputs from the user. On each new
523 # Variables used to store the three last inputs from the user. On each new
524 # history update, we populate the user's namespace with these, shifted as
524 # history update, we populate the user's namespace with these, shifted as
525 # necessary.
525 # necessary.
526 _i00 = Unicode(u'')
526 _i00 = Unicode(u'')
527 _i = Unicode(u'')
527 _i = Unicode(u'')
528 _ii = Unicode(u'')
528 _ii = Unicode(u'')
529 _iii = Unicode(u'')
529 _iii = Unicode(u'')
530
530
531 # A regex matching all forms of the exit command, so that we don't store
531 # A regex matching all forms of the exit command, so that we don't store
532 # them in the history (it's annoying to rewind the first entry and land on
532 # them in the history (it's annoying to rewind the first entry and land on
533 # an exit call).
533 # an exit call).
534 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
534 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
535
535
536 def __init__(self, shell=None, config=None, **traits):
536 def __init__(self, shell=None, config=None, **traits):
537 """Create a new history manager associated with a shell instance.
537 """Create a new history manager associated with a shell instance.
538 """
538 """
539 # We need a pointer back to the shell for various tasks.
539 # We need a pointer back to the shell for various tasks.
540 super(HistoryManager, self).__init__(shell=shell, config=config,
540 super(HistoryManager, self).__init__(shell=shell, config=config,
541 **traits)
541 **traits)
542 self.save_flag = threading.Event()
542 self.save_flag = threading.Event()
543 self.db_input_cache_lock = threading.Lock()
543 self.db_input_cache_lock = threading.Lock()
544 self.db_output_cache_lock = threading.Lock()
544 self.db_output_cache_lock = threading.Lock()
545
545
546 try:
546 try:
547 self.new_session()
547 self.new_session()
548 except OperationalError:
548 except OperationalError:
549 self.log.error("Failed to create history session in %s. History will not be saved.",
549 self.log.error("Failed to create history session in %s. History will not be saved.",
550 self.hist_file, exc_info=True)
550 self.hist_file, exc_info=True)
551 self.hist_file = ':memory:'
551 self.hist_file = ':memory:'
552
552
553 if self.enabled and self.hist_file != ':memory:':
553 if self.enabled and self.hist_file != ':memory:':
554 self.save_thread = HistorySavingThread(self)
554 self.save_thread = HistorySavingThread(self)
555 self.save_thread.start()
555 self.save_thread.start()
556
556
557 def _get_hist_file_name(self, profile=None):
557 def _get_hist_file_name(self, profile=None):
558 """Get default history file name based on the Shell's profile.
558 """Get default history file name based on the Shell's profile.
559
559
560 The profile parameter is ignored, but must exist for compatibility with
560 The profile parameter is ignored, but must exist for compatibility with
561 the parent class."""
561 the parent class."""
562 profile_dir = self.shell.profile_dir.location
562 profile_dir = self.shell.profile_dir.location
563 return os.path.join(profile_dir, 'history.sqlite')
563 return os.path.join(profile_dir, 'history.sqlite')
564
564
565 @needs_sqlite
565 @needs_sqlite
566 def new_session(self, conn=None):
566 def new_session(self, conn=None):
567 """Get a new session number."""
567 """Get a new session number."""
568 if conn is None:
568 if conn is None:
569 conn = self.db
569 conn = self.db
570
570
571 with conn:
571 with conn:
572 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
572 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
573 NULL, "") """, (datetime.datetime.now(),))
573 NULL, "") """, (datetime.datetime.now(),))
574 self.session_number = cur.lastrowid
574 self.session_number = cur.lastrowid
575
575
576 def end_session(self):
576 def end_session(self):
577 """Close the database session, filling in the end time and line count."""
577 """Close the database session, filling in the end time and line count."""
578 self.writeout_cache()
578 self.writeout_cache()
579 with self.db:
579 with self.db:
580 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
580 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
581 session==?""", (datetime.datetime.now(),
581 session==?""", (datetime.datetime.now(),
582 len(self.input_hist_parsed)-1, self.session_number))
582 len(self.input_hist_parsed)-1, self.session_number))
583 self.session_number = 0
583 self.session_number = 0
584
584
585 def name_session(self, name):
585 def name_session(self, name):
586 """Give the current session a name in the history database."""
586 """Give the current session a name in the history database."""
587 with self.db:
587 with self.db:
588 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
588 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
589 (name, self.session_number))
589 (name, self.session_number))
590
590
591 def reset(self, new_session=True):
591 def reset(self, new_session=True):
592 """Clear the session history, releasing all object references, and
592 """Clear the session history, releasing all object references, and
593 optionally open a new session."""
593 optionally open a new session."""
594 self.output_hist.clear()
594 self.output_hist.clear()
595 # The directory history can't be completely empty
595 # The directory history can't be completely empty
596 self.dir_hist[:] = [py3compat.getcwd()]
596 self.dir_hist[:] = [os.getcwd()]
597
597
598 if new_session:
598 if new_session:
599 if self.session_number:
599 if self.session_number:
600 self.end_session()
600 self.end_session()
601 self.input_hist_parsed[:] = [""]
601 self.input_hist_parsed[:] = [""]
602 self.input_hist_raw[:] = [""]
602 self.input_hist_raw[:] = [""]
603 self.new_session()
603 self.new_session()
604
604
605 # ------------------------------
605 # ------------------------------
606 # Methods for retrieving history
606 # Methods for retrieving history
607 # ------------------------------
607 # ------------------------------
608 def get_session_info(self, session=0):
608 def get_session_info(self, session=0):
609 """Get info about a session.
609 """Get info about a session.
610
610
611 Parameters
611 Parameters
612 ----------
612 ----------
613
613
614 session : int
614 session : int
615 Session number to retrieve. The current session is 0, and negative
615 Session number to retrieve. The current session is 0, and negative
616 numbers count back from current session, so -1 is the previous session.
616 numbers count back from current session, so -1 is the previous session.
617
617
618 Returns
618 Returns
619 -------
619 -------
620
620
621 session_id : int
621 session_id : int
622 Session ID number
622 Session ID number
623 start : datetime
623 start : datetime
624 Timestamp for the start of the session.
624 Timestamp for the start of the session.
625 end : datetime
625 end : datetime
626 Timestamp for the end of the session, or None if IPython crashed.
626 Timestamp for the end of the session, or None if IPython crashed.
627 num_cmds : int
627 num_cmds : int
628 Number of commands run, or None if IPython crashed.
628 Number of commands run, or None if IPython crashed.
629 remark : unicode
629 remark : unicode
630 A manually set description.
630 A manually set description.
631 """
631 """
632 if session <= 0:
632 if session <= 0:
633 session += self.session_number
633 session += self.session_number
634
634
635 return super(HistoryManager, self).get_session_info(session=session)
635 return super(HistoryManager, self).get_session_info(session=session)
636
636
637 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
637 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
638 """Get input and output history from the current session. Called by
638 """Get input and output history from the current session. Called by
639 get_range, and takes similar parameters."""
639 get_range, and takes similar parameters."""
640 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
640 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
641
641
642 n = len(input_hist)
642 n = len(input_hist)
643 if start < 0:
643 if start < 0:
644 start += n
644 start += n
645 if not stop or (stop > n):
645 if not stop or (stop > n):
646 stop = n
646 stop = n
647 elif stop < 0:
647 elif stop < 0:
648 stop += n
648 stop += n
649
649
650 for i in range(start, stop):
650 for i in range(start, stop):
651 if output:
651 if output:
652 line = (input_hist[i], self.output_hist_reprs.get(i))
652 line = (input_hist[i], self.output_hist_reprs.get(i))
653 else:
653 else:
654 line = input_hist[i]
654 line = input_hist[i]
655 yield (0, i, line)
655 yield (0, i, line)
656
656
657 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
657 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
658 """Retrieve input by session.
658 """Retrieve input by session.
659
659
660 Parameters
660 Parameters
661 ----------
661 ----------
662 session : int
662 session : int
663 Session number to retrieve. The current session is 0, and negative
663 Session number to retrieve. The current session is 0, and negative
664 numbers count back from current session, so -1 is previous session.
664 numbers count back from current session, so -1 is previous session.
665 start : int
665 start : int
666 First line to retrieve.
666 First line to retrieve.
667 stop : int
667 stop : int
668 End of line range (excluded from output itself). If None, retrieve
668 End of line range (excluded from output itself). If None, retrieve
669 to the end of the session.
669 to the end of the session.
670 raw : bool
670 raw : bool
671 If True, return untranslated input
671 If True, return untranslated input
672 output : bool
672 output : bool
673 If True, attempt to include output. This will be 'real' Python
673 If True, attempt to include output. This will be 'real' Python
674 objects for the current session, or text reprs from previous
674 objects for the current session, or text reprs from previous
675 sessions if db_log_output was enabled at the time. Where no output
675 sessions if db_log_output was enabled at the time. Where no output
676 is found, None is used.
676 is found, None is used.
677
677
678 Returns
678 Returns
679 -------
679 -------
680 entries
680 entries
681 An iterator over the desired lines. Each line is a 3-tuple, either
681 An iterator over the desired lines. Each line is a 3-tuple, either
682 (session, line, input) if output is False, or
682 (session, line, input) if output is False, or
683 (session, line, (input, output)) if output is True.
683 (session, line, (input, output)) if output is True.
684 """
684 """
685 if session <= 0:
685 if session <= 0:
686 session += self.session_number
686 session += self.session_number
687 if session==self.session_number: # Current session
687 if session==self.session_number: # Current session
688 return self._get_range_session(start, stop, raw, output)
688 return self._get_range_session(start, stop, raw, output)
689 return super(HistoryManager, self).get_range(session, start, stop, raw,
689 return super(HistoryManager, self).get_range(session, start, stop, raw,
690 output)
690 output)
691
691
692 ## ----------------------------
692 ## ----------------------------
693 ## Methods for storing history:
693 ## Methods for storing history:
694 ## ----------------------------
694 ## ----------------------------
695 def store_inputs(self, line_num, source, source_raw=None):
695 def store_inputs(self, line_num, source, source_raw=None):
696 """Store source and raw input in history and create input cache
696 """Store source and raw input in history and create input cache
697 variables ``_i*``.
697 variables ``_i*``.
698
698
699 Parameters
699 Parameters
700 ----------
700 ----------
701 line_num : int
701 line_num : int
702 The prompt number of this input.
702 The prompt number of this input.
703
703
704 source : str
704 source : str
705 Python input.
705 Python input.
706
706
707 source_raw : str, optional
707 source_raw : str, optional
708 If given, this is the raw input without any IPython transformations
708 If given, this is the raw input without any IPython transformations
709 applied to it. If not given, ``source`` is used.
709 applied to it. If not given, ``source`` is used.
710 """
710 """
711 if source_raw is None:
711 if source_raw is None:
712 source_raw = source
712 source_raw = source
713 source = source.rstrip('\n')
713 source = source.rstrip('\n')
714 source_raw = source_raw.rstrip('\n')
714 source_raw = source_raw.rstrip('\n')
715
715
716 # do not store exit/quit commands
716 # do not store exit/quit commands
717 if self._exit_re.match(source_raw.strip()):
717 if self._exit_re.match(source_raw.strip()):
718 return
718 return
719
719
720 self.input_hist_parsed.append(source)
720 self.input_hist_parsed.append(source)
721 self.input_hist_raw.append(source_raw)
721 self.input_hist_raw.append(source_raw)
722
722
723 with self.db_input_cache_lock:
723 with self.db_input_cache_lock:
724 self.db_input_cache.append((line_num, source, source_raw))
724 self.db_input_cache.append((line_num, source, source_raw))
725 # Trigger to flush cache and write to DB.
725 # Trigger to flush cache and write to DB.
726 if len(self.db_input_cache) >= self.db_cache_size:
726 if len(self.db_input_cache) >= self.db_cache_size:
727 self.save_flag.set()
727 self.save_flag.set()
728
728
729 # update the auto _i variables
729 # update the auto _i variables
730 self._iii = self._ii
730 self._iii = self._ii
731 self._ii = self._i
731 self._ii = self._i
732 self._i = self._i00
732 self._i = self._i00
733 self._i00 = source_raw
733 self._i00 = source_raw
734
734
735 # hackish access to user namespace to create _i1,_i2... dynamically
735 # hackish access to user namespace to create _i1,_i2... dynamically
736 new_i = '_i%s' % line_num
736 new_i = '_i%s' % line_num
737 to_main = {'_i': self._i,
737 to_main = {'_i': self._i,
738 '_ii': self._ii,
738 '_ii': self._ii,
739 '_iii': self._iii,
739 '_iii': self._iii,
740 new_i : self._i00 }
740 new_i : self._i00 }
741
741
742 if self.shell is not None:
742 if self.shell is not None:
743 self.shell.push(to_main, interactive=False)
743 self.shell.push(to_main, interactive=False)
744
744
745 def store_output(self, line_num):
745 def store_output(self, line_num):
746 """If database output logging is enabled, this saves all the
746 """If database output logging is enabled, this saves all the
747 outputs from the indicated prompt number to the database. It's
747 outputs from the indicated prompt number to the database. It's
748 called by run_cell after code has been executed.
748 called by run_cell after code has been executed.
749
749
750 Parameters
750 Parameters
751 ----------
751 ----------
752 line_num : int
752 line_num : int
753 The line number from which to save outputs
753 The line number from which to save outputs
754 """
754 """
755 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
755 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
756 return
756 return
757 output = self.output_hist_reprs[line_num]
757 output = self.output_hist_reprs[line_num]
758
758
759 with self.db_output_cache_lock:
759 with self.db_output_cache_lock:
760 self.db_output_cache.append((line_num, output))
760 self.db_output_cache.append((line_num, output))
761 if self.db_cache_size <= 1:
761 if self.db_cache_size <= 1:
762 self.save_flag.set()
762 self.save_flag.set()
763
763
764 def _writeout_input_cache(self, conn):
764 def _writeout_input_cache(self, conn):
765 with conn:
765 with conn:
766 for line in self.db_input_cache:
766 for line in self.db_input_cache:
767 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
767 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
768 (self.session_number,)+line)
768 (self.session_number,)+line)
769
769
770 def _writeout_output_cache(self, conn):
770 def _writeout_output_cache(self, conn):
771 with conn:
771 with conn:
772 for line in self.db_output_cache:
772 for line in self.db_output_cache:
773 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
773 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
774 (self.session_number,)+line)
774 (self.session_number,)+line)
775
775
776 @needs_sqlite
776 @needs_sqlite
777 def writeout_cache(self, conn=None):
777 def writeout_cache(self, conn=None):
778 """Write any entries in the cache to the database."""
778 """Write any entries in the cache to the database."""
779 if conn is None:
779 if conn is None:
780 conn = self.db
780 conn = self.db
781
781
782 with self.db_input_cache_lock:
782 with self.db_input_cache_lock:
783 try:
783 try:
784 self._writeout_input_cache(conn)
784 self._writeout_input_cache(conn)
785 except sqlite3.IntegrityError:
785 except sqlite3.IntegrityError:
786 self.new_session(conn)
786 self.new_session(conn)
787 print("ERROR! Session/line number was not unique in",
787 print("ERROR! Session/line number was not unique in",
788 "database. History logging moved to new session",
788 "database. History logging moved to new session",
789 self.session_number)
789 self.session_number)
790 try:
790 try:
791 # Try writing to the new session. If this fails, don't
791 # Try writing to the new session. If this fails, don't
792 # recurse
792 # recurse
793 self._writeout_input_cache(conn)
793 self._writeout_input_cache(conn)
794 except sqlite3.IntegrityError:
794 except sqlite3.IntegrityError:
795 pass
795 pass
796 finally:
796 finally:
797 self.db_input_cache = []
797 self.db_input_cache = []
798
798
799 with self.db_output_cache_lock:
799 with self.db_output_cache_lock:
800 try:
800 try:
801 self._writeout_output_cache(conn)
801 self._writeout_output_cache(conn)
802 except sqlite3.IntegrityError:
802 except sqlite3.IntegrityError:
803 print("!! Session/line number for output was not unique",
803 print("!! Session/line number for output was not unique",
804 "in database. Output will not be stored.")
804 "in database. Output will not be stored.")
805 finally:
805 finally:
806 self.db_output_cache = []
806 self.db_output_cache = []
807
807
808
808
809 class HistorySavingThread(threading.Thread):
809 class HistorySavingThread(threading.Thread):
810 """This thread takes care of writing history to the database, so that
810 """This thread takes care of writing history to the database, so that
811 the UI isn't held up while that happens.
811 the UI isn't held up while that happens.
812
812
813 It waits for the HistoryManager's save_flag to be set, then writes out
813 It waits for the HistoryManager's save_flag to be set, then writes out
814 the history cache. The main thread is responsible for setting the flag when
814 the history cache. The main thread is responsible for setting the flag when
815 the cache size reaches a defined threshold."""
815 the cache size reaches a defined threshold."""
816 daemon = True
816 daemon = True
817 stop_now = False
817 stop_now = False
818 enabled = True
818 enabled = True
819 def __init__(self, history_manager):
819 def __init__(self, history_manager):
820 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
820 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
821 self.history_manager = history_manager
821 self.history_manager = history_manager
822 self.enabled = history_manager.enabled
822 self.enabled = history_manager.enabled
823 atexit.register(self.stop)
823 atexit.register(self.stop)
824
824
825 @needs_sqlite
825 @needs_sqlite
826 def run(self):
826 def run(self):
827 # We need a separate db connection per thread:
827 # We need a separate db connection per thread:
828 try:
828 try:
829 self.db = sqlite3.connect(self.history_manager.hist_file,
829 self.db = sqlite3.connect(self.history_manager.hist_file,
830 **self.history_manager.connection_options
830 **self.history_manager.connection_options
831 )
831 )
832 while True:
832 while True:
833 self.history_manager.save_flag.wait()
833 self.history_manager.save_flag.wait()
834 if self.stop_now:
834 if self.stop_now:
835 self.db.close()
835 self.db.close()
836 return
836 return
837 self.history_manager.save_flag.clear()
837 self.history_manager.save_flag.clear()
838 self.history_manager.writeout_cache(self.db)
838 self.history_manager.writeout_cache(self.db)
839 except Exception as e:
839 except Exception as e:
840 print(("The history saving thread hit an unexpected error (%s)."
840 print(("The history saving thread hit an unexpected error (%s)."
841 "History will not be written to the database.") % repr(e))
841 "History will not be written to the database.") % repr(e))
842
842
843 def stop(self):
843 def stop(self):
844 """This can be called from the main thread to safely stop this thread.
844 """This can be called from the main thread to safely stop this thread.
845
845
846 Note that it does not attempt to write out remaining history before
846 Note that it does not attempt to write out remaining history before
847 exiting. That should be done by calling the HistoryManager's
847 exiting. That should be done by calling the HistoryManager's
848 end_session method."""
848 end_session method."""
849 self.stop_now = True
849 self.stop_now = True
850 self.history_manager.save_flag.set()
850 self.history_manager.save_flag.set()
851 self.join()
851 self.join()
852
852
853
853
854 # To match, e.g. ~5/8-~2/3
854 # To match, e.g. ~5/8-~2/3
855 range_re = re.compile(r"""
855 range_re = re.compile(r"""
856 ((?P<startsess>~?\d+)/)?
856 ((?P<startsess>~?\d+)/)?
857 (?P<start>\d+)?
857 (?P<start>\d+)?
858 ((?P<sep>[\-:])
858 ((?P<sep>[\-:])
859 ((?P<endsess>~?\d+)/)?
859 ((?P<endsess>~?\d+)/)?
860 (?P<end>\d+))?
860 (?P<end>\d+))?
861 $""", re.VERBOSE)
861 $""", re.VERBOSE)
862
862
863
863
864 def extract_hist_ranges(ranges_str):
864 def extract_hist_ranges(ranges_str):
865 """Turn a string of history ranges into 3-tuples of (session, start, stop).
865 """Turn a string of history ranges into 3-tuples of (session, start, stop).
866
866
867 Examples
867 Examples
868 --------
868 --------
869 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
869 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
870 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
870 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
871 """
871 """
872 for range_str in ranges_str.split():
872 for range_str in ranges_str.split():
873 rmatch = range_re.match(range_str)
873 rmatch = range_re.match(range_str)
874 if not rmatch:
874 if not rmatch:
875 continue
875 continue
876 start = rmatch.group("start")
876 start = rmatch.group("start")
877 if start:
877 if start:
878 start = int(start)
878 start = int(start)
879 end = rmatch.group("end")
879 end = rmatch.group("end")
880 # If no end specified, get (a, a + 1)
880 # If no end specified, get (a, a + 1)
881 end = int(end) if end else start + 1
881 end = int(end) if end else start + 1
882 else: # start not specified
882 else: # start not specified
883 if not rmatch.group('startsess'): # no startsess
883 if not rmatch.group('startsess'): # no startsess
884 continue
884 continue
885 start = 1
885 start = 1
886 end = None # provide the entire session hist
886 end = None # provide the entire session hist
887
887
888 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
888 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
889 end += 1
889 end += 1
890 startsess = rmatch.group("startsess") or "0"
890 startsess = rmatch.group("startsess") or "0"
891 endsess = rmatch.group("endsess") or startsess
891 endsess = rmatch.group("endsess") or startsess
892 startsess = int(startsess.replace("~","-"))
892 startsess = int(startsess.replace("~","-"))
893 endsess = int(endsess.replace("~","-"))
893 endsess = int(endsess.replace("~","-"))
894 assert endsess >= startsess, "start session must be earlier than end session"
894 assert endsess >= startsess, "start session must be earlier than end session"
895
895
896 if endsess == startsess:
896 if endsess == startsess:
897 yield (startsess, start, end)
897 yield (startsess, start, end)
898 continue
898 continue
899 # Multiple sessions in one range:
899 # Multiple sessions in one range:
900 yield (startsess, start, None)
900 yield (startsess, start, None)
901 for sess in range(startsess+1, endsess):
901 for sess in range(startsess+1, endsess):
902 yield (sess, 1, None)
902 yield (sess, 1, None)
903 yield (endsess, 1, end)
903 yield (endsess, 1, end)
904
904
905
905
906 def _format_lineno(session, line):
906 def _format_lineno(session, line):
907 """Helper function to format line numbers properly."""
907 """Helper function to format line numbers properly."""
908 if session == 0:
908 if session == 0:
909 return str(line)
909 return str(line)
910 return "%s#%s" % (session, line)
910 return "%s#%s" % (session, line)
@@ -1,3226 +1,3223 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Main IPython class."""
2 """Main IPython class."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13
13
14 import __future__
14 import __future__
15 import abc
15 import abc
16 import ast
16 import ast
17 import atexit
17 import atexit
18 import functools
18 import functools
19 import os
19 import os
20 import re
20 import re
21 import runpy
21 import runpy
22 import sys
22 import sys
23 import tempfile
23 import tempfile
24 import traceback
24 import traceback
25 import types
25 import types
26 import subprocess
26 import subprocess
27 import warnings
27 import warnings
28 from io import open as io_open
28 from io import open as io_open
29
29
30 from pickleshare import PickleShareDB
30 from pickleshare import PickleShareDB
31
31
32 from traitlets.config.configurable import SingletonConfigurable
32 from traitlets.config.configurable import SingletonConfigurable
33 from IPython.core import oinspect
33 from IPython.core import oinspect
34 from IPython.core import magic
34 from IPython.core import magic
35 from IPython.core import page
35 from IPython.core import page
36 from IPython.core import prefilter
36 from IPython.core import prefilter
37 from IPython.core import shadowns
37 from IPython.core import shadowns
38 from IPython.core import ultratb
38 from IPython.core import ultratb
39 from IPython.core.alias import Alias, AliasManager
39 from IPython.core.alias import Alias, AliasManager
40 from IPython.core.autocall import ExitAutocall
40 from IPython.core.autocall import ExitAutocall
41 from IPython.core.builtin_trap import BuiltinTrap
41 from IPython.core.builtin_trap import BuiltinTrap
42 from IPython.core.events import EventManager, available_events
42 from IPython.core.events import EventManager, available_events
43 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
43 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
44 from IPython.core.debugger import Pdb
44 from IPython.core.debugger import Pdb
45 from IPython.core.display_trap import DisplayTrap
45 from IPython.core.display_trap import DisplayTrap
46 from IPython.core.displayhook import DisplayHook
46 from IPython.core.displayhook import DisplayHook
47 from IPython.core.displaypub import DisplayPublisher
47 from IPython.core.displaypub import DisplayPublisher
48 from IPython.core.error import InputRejected, UsageError
48 from IPython.core.error import InputRejected, UsageError
49 from IPython.core.extensions import ExtensionManager
49 from IPython.core.extensions import ExtensionManager
50 from IPython.core.formatters import DisplayFormatter
50 from IPython.core.formatters import DisplayFormatter
51 from IPython.core.history import HistoryManager
51 from IPython.core.history import HistoryManager
52 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
52 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
53 from IPython.core.logger import Logger
53 from IPython.core.logger import Logger
54 from IPython.core.macro import Macro
54 from IPython.core.macro import Macro
55 from IPython.core.payload import PayloadManager
55 from IPython.core.payload import PayloadManager
56 from IPython.core.prefilter import PrefilterManager
56 from IPython.core.prefilter import PrefilterManager
57 from IPython.core.profiledir import ProfileDir
57 from IPython.core.profiledir import ProfileDir
58 from IPython.core.usage import default_banner
58 from IPython.core.usage import default_banner
59 from IPython.testing.skipdoctest import skip_doctest
59 from IPython.testing.skipdoctest import skip_doctest
60 from IPython.utils import PyColorize
60 from IPython.utils import PyColorize
61 from IPython.utils import io
61 from IPython.utils import io
62 from IPython.utils import py3compat
62 from IPython.utils import py3compat
63 from IPython.utils import openpy
63 from IPython.utils import openpy
64 from IPython.utils.decorators import undoc
64 from IPython.utils.decorators import undoc
65 from IPython.utils.io import ask_yes_no
65 from IPython.utils.io import ask_yes_no
66 from IPython.utils.ipstruct import Struct
66 from IPython.utils.ipstruct import Struct
67 from IPython.paths import get_ipython_dir
67 from IPython.paths import get_ipython_dir
68 from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists
68 from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists
69 from IPython.utils.process import system, getoutput
69 from IPython.utils.process import system, getoutput
70 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
70 from IPython.utils.py3compat import builtin_mod, with_metaclass
71 with_metaclass, iteritems)
72 from IPython.utils.strdispatch import StrDispatch
71 from IPython.utils.strdispatch import StrDispatch
73 from IPython.utils.syspathcontext import prepended_to_syspath
72 from IPython.utils.syspathcontext import prepended_to_syspath
74 from IPython.utils.text import format_screen, LSString, SList, DollarFormatter
73 from IPython.utils.text import format_screen, LSString, SList, DollarFormatter
75 from IPython.utils.tempdir import TemporaryDirectory
74 from IPython.utils.tempdir import TemporaryDirectory
76 from traitlets import (
75 from traitlets import (
77 Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
76 Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
78 observe, default,
77 observe, default,
79 )
78 )
80 from warnings import warn
79 from warnings import warn
81 from logging import error
80 from logging import error
82 import IPython.core.hooks
81 import IPython.core.hooks
83
82
84 # NoOpContext is deprecated, but ipykernel imports it from here.
83 # NoOpContext is deprecated, but ipykernel imports it from here.
85 # See https://github.com/ipython/ipykernel/issues/157
84 # See https://github.com/ipython/ipykernel/issues/157
86 from IPython.utils.contexts import NoOpContext
85 from IPython.utils.contexts import NoOpContext
87
86
88 try:
87 try:
89 import docrepr.sphinxify as sphx
88 import docrepr.sphinxify as sphx
90
89
91 def sphinxify(doc):
90 def sphinxify(doc):
92 with TemporaryDirectory() as dirname:
91 with TemporaryDirectory() as dirname:
93 return {
92 return {
94 'text/html': sphx.sphinxify(doc, dirname),
93 'text/html': sphx.sphinxify(doc, dirname),
95 'text/plain': doc
94 'text/plain': doc
96 }
95 }
97 except ImportError:
96 except ImportError:
98 sphinxify = None
97 sphinxify = None
99
98
100
99
101 class ProvisionalWarning(DeprecationWarning):
100 class ProvisionalWarning(DeprecationWarning):
102 """
101 """
103 Warning class for unstable features
102 Warning class for unstable features
104 """
103 """
105 pass
104 pass
106
105
107 #-----------------------------------------------------------------------------
106 #-----------------------------------------------------------------------------
108 # Globals
107 # Globals
109 #-----------------------------------------------------------------------------
108 #-----------------------------------------------------------------------------
110
109
111 # compiled regexps for autoindent management
110 # compiled regexps for autoindent management
112 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
111 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
113
112
114 #-----------------------------------------------------------------------------
113 #-----------------------------------------------------------------------------
115 # Utilities
114 # Utilities
116 #-----------------------------------------------------------------------------
115 #-----------------------------------------------------------------------------
117
116
118 @undoc
117 @undoc
119 def softspace(file, newvalue):
118 def softspace(file, newvalue):
120 """Copied from code.py, to remove the dependency"""
119 """Copied from code.py, to remove the dependency"""
121
120
122 oldvalue = 0
121 oldvalue = 0
123 try:
122 try:
124 oldvalue = file.softspace
123 oldvalue = file.softspace
125 except AttributeError:
124 except AttributeError:
126 pass
125 pass
127 try:
126 try:
128 file.softspace = newvalue
127 file.softspace = newvalue
129 except (AttributeError, TypeError):
128 except (AttributeError, TypeError):
130 # "attribute-less object" or "read-only attributes"
129 # "attribute-less object" or "read-only attributes"
131 pass
130 pass
132 return oldvalue
131 return oldvalue
133
132
134 @undoc
133 @undoc
135 def no_op(*a, **kw): pass
134 def no_op(*a, **kw): pass
136
135
137
136
138 class SpaceInInput(Exception): pass
137 class SpaceInInput(Exception): pass
139
138
140
139
141 def get_default_colors():
140 def get_default_colors():
142 "DEPRECATED"
141 "DEPRECATED"
143 warn('get_default_color is Deprecated, and is `Neutral` on all platforms.',
142 warn('get_default_color is Deprecated, and is `Neutral` on all platforms.',
144 DeprecationWarning, stacklevel=2)
143 DeprecationWarning, stacklevel=2)
145 return 'Neutral'
144 return 'Neutral'
146
145
147
146
148 class SeparateUnicode(Unicode):
147 class SeparateUnicode(Unicode):
149 r"""A Unicode subclass to validate separate_in, separate_out, etc.
148 r"""A Unicode subclass to validate separate_in, separate_out, etc.
150
149
151 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
150 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
152 """
151 """
153
152
154 def validate(self, obj, value):
153 def validate(self, obj, value):
155 if value == '0': value = ''
154 if value == '0': value = ''
156 value = value.replace('\\n','\n')
155 value = value.replace('\\n','\n')
157 return super(SeparateUnicode, self).validate(obj, value)
156 return super(SeparateUnicode, self).validate(obj, value)
158
157
159
158
160 @undoc
159 @undoc
161 class DummyMod(object):
160 class DummyMod(object):
162 """A dummy module used for IPython's interactive module when
161 """A dummy module used for IPython's interactive module when
163 a namespace must be assigned to the module's __dict__."""
162 a namespace must be assigned to the module's __dict__."""
164 pass
163 pass
165
164
166
165
167 class ExecutionResult(object):
166 class ExecutionResult(object):
168 """The result of a call to :meth:`InteractiveShell.run_cell`
167 """The result of a call to :meth:`InteractiveShell.run_cell`
169
168
170 Stores information about what took place.
169 Stores information about what took place.
171 """
170 """
172 execution_count = None
171 execution_count = None
173 error_before_exec = None
172 error_before_exec = None
174 error_in_exec = None
173 error_in_exec = None
175 result = None
174 result = None
176
175
177 @property
176 @property
178 def success(self):
177 def success(self):
179 return (self.error_before_exec is None) and (self.error_in_exec is None)
178 return (self.error_before_exec is None) and (self.error_in_exec is None)
180
179
181 def raise_error(self):
180 def raise_error(self):
182 """Reraises error if `success` is `False`, otherwise does nothing"""
181 """Reraises error if `success` is `False`, otherwise does nothing"""
183 if self.error_before_exec is not None:
182 if self.error_before_exec is not None:
184 raise self.error_before_exec
183 raise self.error_before_exec
185 if self.error_in_exec is not None:
184 if self.error_in_exec is not None:
186 raise self.error_in_exec
185 raise self.error_in_exec
187
186
188 def __repr__(self):
187 def __repr__(self):
189 name = self.__class__.__qualname__
188 name = self.__class__.__qualname__
190 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s result=%s>' %\
189 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s result=%s>' %\
191 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.result))
190 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.result))
192
191
193
192
194 class InteractiveShell(SingletonConfigurable):
193 class InteractiveShell(SingletonConfigurable):
195 """An enhanced, interactive shell for Python."""
194 """An enhanced, interactive shell for Python."""
196
195
197 _instance = None
196 _instance = None
198
197
199 ast_transformers = List([], help=
198 ast_transformers = List([], help=
200 """
199 """
201 A list of ast.NodeTransformer subclass instances, which will be applied
200 A list of ast.NodeTransformer subclass instances, which will be applied
202 to user input before code is run.
201 to user input before code is run.
203 """
202 """
204 ).tag(config=True)
203 ).tag(config=True)
205
204
206 autocall = Enum((0,1,2), default_value=0, help=
205 autocall = Enum((0,1,2), default_value=0, help=
207 """
206 """
208 Make IPython automatically call any callable object even if you didn't
207 Make IPython automatically call any callable object even if you didn't
209 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
208 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
210 automatically. The value can be '0' to disable the feature, '1' for
209 automatically. The value can be '0' to disable the feature, '1' for
211 'smart' autocall, where it is not applied if there are no more
210 'smart' autocall, where it is not applied if there are no more
212 arguments on the line, and '2' for 'full' autocall, where all callable
211 arguments on the line, and '2' for 'full' autocall, where all callable
213 objects are automatically called (even if no arguments are present).
212 objects are automatically called (even if no arguments are present).
214 """
213 """
215 ).tag(config=True)
214 ).tag(config=True)
216 # TODO: remove all autoindent logic and put into frontends.
215 # TODO: remove all autoindent logic and put into frontends.
217 # We can't do this yet because even runlines uses the autoindent.
216 # We can't do this yet because even runlines uses the autoindent.
218 autoindent = Bool(True, help=
217 autoindent = Bool(True, help=
219 """
218 """
220 Autoindent IPython code entered interactively.
219 Autoindent IPython code entered interactively.
221 """
220 """
222 ).tag(config=True)
221 ).tag(config=True)
223
222
224 automagic = Bool(True, help=
223 automagic = Bool(True, help=
225 """
224 """
226 Enable magic commands to be called without the leading %.
225 Enable magic commands to be called without the leading %.
227 """
226 """
228 ).tag(config=True)
227 ).tag(config=True)
229
228
230 banner1 = Unicode(default_banner,
229 banner1 = Unicode(default_banner,
231 help="""The part of the banner to be printed before the profile"""
230 help="""The part of the banner to be printed before the profile"""
232 ).tag(config=True)
231 ).tag(config=True)
233 banner2 = Unicode('',
232 banner2 = Unicode('',
234 help="""The part of the banner to be printed after the profile"""
233 help="""The part of the banner to be printed after the profile"""
235 ).tag(config=True)
234 ).tag(config=True)
236
235
237 cache_size = Integer(1000, help=
236 cache_size = Integer(1000, help=
238 """
237 """
239 Set the size of the output cache. The default is 1000, you can
238 Set the size of the output cache. The default is 1000, you can
240 change it permanently in your config file. Setting it to 0 completely
239 change it permanently in your config file. Setting it to 0 completely
241 disables the caching system, and the minimum value accepted is 20 (if
240 disables the caching system, and the minimum value accepted is 20 (if
242 you provide a value less than 20, it is reset to 0 and a warning is
241 you provide a value less than 20, it is reset to 0 and a warning is
243 issued). This limit is defined because otherwise you'll spend more
242 issued). This limit is defined because otherwise you'll spend more
244 time re-flushing a too small cache than working
243 time re-flushing a too small cache than working
245 """
244 """
246 ).tag(config=True)
245 ).tag(config=True)
247 color_info = Bool(True, help=
246 color_info = Bool(True, help=
248 """
247 """
249 Use colors for displaying information about objects. Because this
248 Use colors for displaying information about objects. Because this
250 information is passed through a pager (like 'less'), and some pagers
249 information is passed through a pager (like 'less'), and some pagers
251 get confused with color codes, this capability can be turned off.
250 get confused with color codes, this capability can be turned off.
252 """
251 """
253 ).tag(config=True)
252 ).tag(config=True)
254 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
253 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
255 default_value='Neutral',
254 default_value='Neutral',
256 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
255 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
257 ).tag(config=True)
256 ).tag(config=True)
258 debug = Bool(False).tag(config=True)
257 debug = Bool(False).tag(config=True)
259 disable_failing_post_execute = Bool(False,
258 disable_failing_post_execute = Bool(False,
260 help="Don't call post-execute functions that have failed in the past."
259 help="Don't call post-execute functions that have failed in the past."
261 ).tag(config=True)
260 ).tag(config=True)
262 display_formatter = Instance(DisplayFormatter, allow_none=True)
261 display_formatter = Instance(DisplayFormatter, allow_none=True)
263 displayhook_class = Type(DisplayHook)
262 displayhook_class = Type(DisplayHook)
264 display_pub_class = Type(DisplayPublisher)
263 display_pub_class = Type(DisplayPublisher)
265
264
266 sphinxify_docstring = Bool(False, help=
265 sphinxify_docstring = Bool(False, help=
267 """
266 """
268 Enables rich html representation of docstrings. (This requires the
267 Enables rich html representation of docstrings. (This requires the
269 docrepr module).
268 docrepr module).
270 """).tag(config=True)
269 """).tag(config=True)
271
270
272 @observe("sphinxify_docstring")
271 @observe("sphinxify_docstring")
273 def _sphinxify_docstring_changed(self, change):
272 def _sphinxify_docstring_changed(self, change):
274 if change['new']:
273 if change['new']:
275 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
274 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
276
275
277 enable_html_pager = Bool(False, help=
276 enable_html_pager = Bool(False, help=
278 """
277 """
279 (Provisional API) enables html representation in mime bundles sent
278 (Provisional API) enables html representation in mime bundles sent
280 to pagers.
279 to pagers.
281 """).tag(config=True)
280 """).tag(config=True)
282
281
283 @observe("enable_html_pager")
282 @observe("enable_html_pager")
284 def _enable_html_pager_changed(self, change):
283 def _enable_html_pager_changed(self, change):
285 if change['new']:
284 if change['new']:
286 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
285 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
287
286
288 data_pub_class = None
287 data_pub_class = None
289
288
290 exit_now = Bool(False)
289 exit_now = Bool(False)
291 exiter = Instance(ExitAutocall)
290 exiter = Instance(ExitAutocall)
292 @default('exiter')
291 @default('exiter')
293 def _exiter_default(self):
292 def _exiter_default(self):
294 return ExitAutocall(self)
293 return ExitAutocall(self)
295 # Monotonically increasing execution counter
294 # Monotonically increasing execution counter
296 execution_count = Integer(1)
295 execution_count = Integer(1)
297 filename = Unicode("<ipython console>")
296 filename = Unicode("<ipython console>")
298 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
297 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
299
298
300 # Input splitter, to transform input line by line and detect when a block
299 # Input splitter, to transform input line by line and detect when a block
301 # is ready to be executed.
300 # is ready to be executed.
302 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
301 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
303 (), {'line_input_checker': True})
302 (), {'line_input_checker': True})
304
303
305 # This InputSplitter instance is used to transform completed cells before
304 # This InputSplitter instance is used to transform completed cells before
306 # running them. It allows cell magics to contain blank lines.
305 # running them. It allows cell magics to contain blank lines.
307 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
306 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
308 (), {'line_input_checker': False})
307 (), {'line_input_checker': False})
309
308
310 logstart = Bool(False, help=
309 logstart = Bool(False, help=
311 """
310 """
312 Start logging to the default log file in overwrite mode.
311 Start logging to the default log file in overwrite mode.
313 Use `logappend` to specify a log file to **append** logs to.
312 Use `logappend` to specify a log file to **append** logs to.
314 """
313 """
315 ).tag(config=True)
314 ).tag(config=True)
316 logfile = Unicode('', help=
315 logfile = Unicode('', help=
317 """
316 """
318 The name of the logfile to use.
317 The name of the logfile to use.
319 """
318 """
320 ).tag(config=True)
319 ).tag(config=True)
321 logappend = Unicode('', help=
320 logappend = Unicode('', help=
322 """
321 """
323 Start logging to the given file in append mode.
322 Start logging to the given file in append mode.
324 Use `logfile` to specify a log file to **overwrite** logs to.
323 Use `logfile` to specify a log file to **overwrite** logs to.
325 """
324 """
326 ).tag(config=True)
325 ).tag(config=True)
327 object_info_string_level = Enum((0,1,2), default_value=0,
326 object_info_string_level = Enum((0,1,2), default_value=0,
328 ).tag(config=True)
327 ).tag(config=True)
329 pdb = Bool(False, help=
328 pdb = Bool(False, help=
330 """
329 """
331 Automatically call the pdb debugger after every exception.
330 Automatically call the pdb debugger after every exception.
332 """
331 """
333 ).tag(config=True)
332 ).tag(config=True)
334 display_page = Bool(False,
333 display_page = Bool(False,
335 help="""If True, anything that would be passed to the pager
334 help="""If True, anything that would be passed to the pager
336 will be displayed as regular output instead."""
335 will be displayed as regular output instead."""
337 ).tag(config=True)
336 ).tag(config=True)
338
337
339 # deprecated prompt traits:
338 # deprecated prompt traits:
340
339
341 prompt_in1 = Unicode('In [\\#]: ',
340 prompt_in1 = Unicode('In [\\#]: ',
342 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
341 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
343 ).tag(config=True)
342 ).tag(config=True)
344 prompt_in2 = Unicode(' .\\D.: ',
343 prompt_in2 = Unicode(' .\\D.: ',
345 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
344 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
346 ).tag(config=True)
345 ).tag(config=True)
347 prompt_out = Unicode('Out[\\#]: ',
346 prompt_out = Unicode('Out[\\#]: ',
348 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
347 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
349 ).tag(config=True)
348 ).tag(config=True)
350 prompts_pad_left = Bool(True,
349 prompts_pad_left = Bool(True,
351 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
350 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
352 ).tag(config=True)
351 ).tag(config=True)
353
352
354 @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left')
353 @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left')
355 def _prompt_trait_changed(self, change):
354 def _prompt_trait_changed(self, change):
356 name = change['name']
355 name = change['name']
357 warn("InteractiveShell.{name} is deprecated since IPython 4.0"
356 warn("InteractiveShell.{name} is deprecated since IPython 4.0"
358 " and ignored since 5.0, set TerminalInteractiveShell.prompts"
357 " and ignored since 5.0, set TerminalInteractiveShell.prompts"
359 " object directly.".format(name=name))
358 " object directly.".format(name=name))
360
359
361 # protect against weird cases where self.config may not exist:
360 # protect against weird cases where self.config may not exist:
362
361
363 show_rewritten_input = Bool(True,
362 show_rewritten_input = Bool(True,
364 help="Show rewritten input, e.g. for autocall."
363 help="Show rewritten input, e.g. for autocall."
365 ).tag(config=True)
364 ).tag(config=True)
366
365
367 quiet = Bool(False).tag(config=True)
366 quiet = Bool(False).tag(config=True)
368
367
369 history_length = Integer(10000,
368 history_length = Integer(10000,
370 help='Total length of command history'
369 help='Total length of command history'
371 ).tag(config=True)
370 ).tag(config=True)
372
371
373 history_load_length = Integer(1000, help=
372 history_load_length = Integer(1000, help=
374 """
373 """
375 The number of saved history entries to be loaded
374 The number of saved history entries to be loaded
376 into the history buffer at startup.
375 into the history buffer at startup.
377 """
376 """
378 ).tag(config=True)
377 ).tag(config=True)
379
378
380 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
379 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
381 default_value='last_expr',
380 default_value='last_expr',
382 help="""
381 help="""
383 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
382 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
384 run interactively (displaying output from expressions)."""
383 run interactively (displaying output from expressions)."""
385 ).tag(config=True)
384 ).tag(config=True)
386
385
387 # TODO: this part of prompt management should be moved to the frontends.
386 # TODO: this part of prompt management should be moved to the frontends.
388 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
387 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
389 separate_in = SeparateUnicode('\n').tag(config=True)
388 separate_in = SeparateUnicode('\n').tag(config=True)
390 separate_out = SeparateUnicode('').tag(config=True)
389 separate_out = SeparateUnicode('').tag(config=True)
391 separate_out2 = SeparateUnicode('').tag(config=True)
390 separate_out2 = SeparateUnicode('').tag(config=True)
392 wildcards_case_sensitive = Bool(True).tag(config=True)
391 wildcards_case_sensitive = Bool(True).tag(config=True)
393 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
392 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
394 default_value='Context').tag(config=True)
393 default_value='Context').tag(config=True)
395
394
396 # Subcomponents of InteractiveShell
395 # Subcomponents of InteractiveShell
397 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
396 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
398 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
397 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
399 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
398 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
400 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
399 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
401 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
400 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
402 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
401 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
403 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
402 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
404 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
403 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
405
404
406 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
405 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
407 @property
406 @property
408 def profile(self):
407 def profile(self):
409 if self.profile_dir is not None:
408 if self.profile_dir is not None:
410 name = os.path.basename(self.profile_dir.location)
409 name = os.path.basename(self.profile_dir.location)
411 return name.replace('profile_','')
410 return name.replace('profile_','')
412
411
413
412
414 # Private interface
413 # Private interface
415 _post_execute = Dict()
414 _post_execute = Dict()
416
415
417 # Tracks any GUI loop loaded for pylab
416 # Tracks any GUI loop loaded for pylab
418 pylab_gui_select = None
417 pylab_gui_select = None
419
418
420 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
419 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
421
420
422 def __init__(self, ipython_dir=None, profile_dir=None,
421 def __init__(self, ipython_dir=None, profile_dir=None,
423 user_module=None, user_ns=None,
422 user_module=None, user_ns=None,
424 custom_exceptions=((), None), **kwargs):
423 custom_exceptions=((), None), **kwargs):
425
424
426 # This is where traits with a config_key argument are updated
425 # This is where traits with a config_key argument are updated
427 # from the values on config.
426 # from the values on config.
428 super(InteractiveShell, self).__init__(**kwargs)
427 super(InteractiveShell, self).__init__(**kwargs)
429 if 'PromptManager' in self.config:
428 if 'PromptManager' in self.config:
430 warn('As of IPython 5.0 `PromptManager` config will have no effect'
429 warn('As of IPython 5.0 `PromptManager` config will have no effect'
431 ' and has been replaced by TerminalInteractiveShell.prompts_class')
430 ' and has been replaced by TerminalInteractiveShell.prompts_class')
432 self.configurables = [self]
431 self.configurables = [self]
433
432
434 # These are relatively independent and stateless
433 # These are relatively independent and stateless
435 self.init_ipython_dir(ipython_dir)
434 self.init_ipython_dir(ipython_dir)
436 self.init_profile_dir(profile_dir)
435 self.init_profile_dir(profile_dir)
437 self.init_instance_attrs()
436 self.init_instance_attrs()
438 self.init_environment()
437 self.init_environment()
439
438
440 # Check if we're in a virtualenv, and set up sys.path.
439 # Check if we're in a virtualenv, and set up sys.path.
441 self.init_virtualenv()
440 self.init_virtualenv()
442
441
443 # Create namespaces (user_ns, user_global_ns, etc.)
442 # Create namespaces (user_ns, user_global_ns, etc.)
444 self.init_create_namespaces(user_module, user_ns)
443 self.init_create_namespaces(user_module, user_ns)
445 # This has to be done after init_create_namespaces because it uses
444 # This has to be done after init_create_namespaces because it uses
446 # something in self.user_ns, but before init_sys_modules, which
445 # something in self.user_ns, but before init_sys_modules, which
447 # is the first thing to modify sys.
446 # is the first thing to modify sys.
448 # TODO: When we override sys.stdout and sys.stderr before this class
447 # TODO: When we override sys.stdout and sys.stderr before this class
449 # is created, we are saving the overridden ones here. Not sure if this
448 # is created, we are saving the overridden ones here. Not sure if this
450 # is what we want to do.
449 # is what we want to do.
451 self.save_sys_module_state()
450 self.save_sys_module_state()
452 self.init_sys_modules()
451 self.init_sys_modules()
453
452
454 # While we're trying to have each part of the code directly access what
453 # While we're trying to have each part of the code directly access what
455 # it needs without keeping redundant references to objects, we have too
454 # it needs without keeping redundant references to objects, we have too
456 # much legacy code that expects ip.db to exist.
455 # much legacy code that expects ip.db to exist.
457 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
456 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
458
457
459 self.init_history()
458 self.init_history()
460 self.init_encoding()
459 self.init_encoding()
461 self.init_prefilter()
460 self.init_prefilter()
462
461
463 self.init_syntax_highlighting()
462 self.init_syntax_highlighting()
464 self.init_hooks()
463 self.init_hooks()
465 self.init_events()
464 self.init_events()
466 self.init_pushd_popd_magic()
465 self.init_pushd_popd_magic()
467 self.init_user_ns()
466 self.init_user_ns()
468 self.init_logger()
467 self.init_logger()
469 self.init_builtins()
468 self.init_builtins()
470
469
471 # The following was in post_config_initialization
470 # The following was in post_config_initialization
472 self.init_inspector()
471 self.init_inspector()
473 self.raw_input_original = input
472 self.raw_input_original = input
474 self.init_completer()
473 self.init_completer()
475 # TODO: init_io() needs to happen before init_traceback handlers
474 # TODO: init_io() needs to happen before init_traceback handlers
476 # because the traceback handlers hardcode the stdout/stderr streams.
475 # because the traceback handlers hardcode the stdout/stderr streams.
477 # This logic in in debugger.Pdb and should eventually be changed.
476 # This logic in in debugger.Pdb and should eventually be changed.
478 self.init_io()
477 self.init_io()
479 self.init_traceback_handlers(custom_exceptions)
478 self.init_traceback_handlers(custom_exceptions)
480 self.init_prompts()
479 self.init_prompts()
481 self.init_display_formatter()
480 self.init_display_formatter()
482 self.init_display_pub()
481 self.init_display_pub()
483 self.init_data_pub()
482 self.init_data_pub()
484 self.init_displayhook()
483 self.init_displayhook()
485 self.init_magics()
484 self.init_magics()
486 self.init_alias()
485 self.init_alias()
487 self.init_logstart()
486 self.init_logstart()
488 self.init_pdb()
487 self.init_pdb()
489 self.init_extension_manager()
488 self.init_extension_manager()
490 self.init_payload()
489 self.init_payload()
491 self.init_deprecation_warnings()
490 self.init_deprecation_warnings()
492 self.hooks.late_startup_hook()
491 self.hooks.late_startup_hook()
493 self.events.trigger('shell_initialized', self)
492 self.events.trigger('shell_initialized', self)
494 atexit.register(self.atexit_operations)
493 atexit.register(self.atexit_operations)
495
494
496 def get_ipython(self):
495 def get_ipython(self):
497 """Return the currently running IPython instance."""
496 """Return the currently running IPython instance."""
498 return self
497 return self
499
498
500 #-------------------------------------------------------------------------
499 #-------------------------------------------------------------------------
501 # Trait changed handlers
500 # Trait changed handlers
502 #-------------------------------------------------------------------------
501 #-------------------------------------------------------------------------
503 @observe('ipython_dir')
502 @observe('ipython_dir')
504 def _ipython_dir_changed(self, change):
503 def _ipython_dir_changed(self, change):
505 ensure_dir_exists(change['new'])
504 ensure_dir_exists(change['new'])
506
505
507 def set_autoindent(self,value=None):
506 def set_autoindent(self,value=None):
508 """Set the autoindent flag.
507 """Set the autoindent flag.
509
508
510 If called with no arguments, it acts as a toggle."""
509 If called with no arguments, it acts as a toggle."""
511 if value is None:
510 if value is None:
512 self.autoindent = not self.autoindent
511 self.autoindent = not self.autoindent
513 else:
512 else:
514 self.autoindent = value
513 self.autoindent = value
515
514
516 #-------------------------------------------------------------------------
515 #-------------------------------------------------------------------------
517 # init_* methods called by __init__
516 # init_* methods called by __init__
518 #-------------------------------------------------------------------------
517 #-------------------------------------------------------------------------
519
518
520 def init_ipython_dir(self, ipython_dir):
519 def init_ipython_dir(self, ipython_dir):
521 if ipython_dir is not None:
520 if ipython_dir is not None:
522 self.ipython_dir = ipython_dir
521 self.ipython_dir = ipython_dir
523 return
522 return
524
523
525 self.ipython_dir = get_ipython_dir()
524 self.ipython_dir = get_ipython_dir()
526
525
527 def init_profile_dir(self, profile_dir):
526 def init_profile_dir(self, profile_dir):
528 if profile_dir is not None:
527 if profile_dir is not None:
529 self.profile_dir = profile_dir
528 self.profile_dir = profile_dir
530 return
529 return
531 self.profile_dir =\
530 self.profile_dir =\
532 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
531 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
533
532
534 def init_instance_attrs(self):
533 def init_instance_attrs(self):
535 self.more = False
534 self.more = False
536
535
537 # command compiler
536 # command compiler
538 self.compile = CachingCompiler()
537 self.compile = CachingCompiler()
539
538
540 # Make an empty namespace, which extension writers can rely on both
539 # Make an empty namespace, which extension writers can rely on both
541 # existing and NEVER being used by ipython itself. This gives them a
540 # existing and NEVER being used by ipython itself. This gives them a
542 # convenient location for storing additional information and state
541 # convenient location for storing additional information and state
543 # their extensions may require, without fear of collisions with other
542 # their extensions may require, without fear of collisions with other
544 # ipython names that may develop later.
543 # ipython names that may develop later.
545 self.meta = Struct()
544 self.meta = Struct()
546
545
547 # Temporary files used for various purposes. Deleted at exit.
546 # Temporary files used for various purposes. Deleted at exit.
548 self.tempfiles = []
547 self.tempfiles = []
549 self.tempdirs = []
548 self.tempdirs = []
550
549
551 # keep track of where we started running (mainly for crash post-mortem)
550 # keep track of where we started running (mainly for crash post-mortem)
552 # This is not being used anywhere currently.
551 # This is not being used anywhere currently.
553 self.starting_dir = py3compat.getcwd()
552 self.starting_dir = os.getcwd()
554
553
555 # Indentation management
554 # Indentation management
556 self.indent_current_nsp = 0
555 self.indent_current_nsp = 0
557
556
558 # Dict to track post-execution functions that have been registered
557 # Dict to track post-execution functions that have been registered
559 self._post_execute = {}
558 self._post_execute = {}
560
559
561 def init_environment(self):
560 def init_environment(self):
562 """Any changes we need to make to the user's environment."""
561 """Any changes we need to make to the user's environment."""
563 pass
562 pass
564
563
565 def init_encoding(self):
564 def init_encoding(self):
566 # Get system encoding at startup time. Certain terminals (like Emacs
565 # Get system encoding at startup time. Certain terminals (like Emacs
567 # under Win32 have it set to None, and we need to have a known valid
566 # under Win32 have it set to None, and we need to have a known valid
568 # encoding to use in the raw_input() method
567 # encoding to use in the raw_input() method
569 try:
568 try:
570 self.stdin_encoding = sys.stdin.encoding or 'ascii'
569 self.stdin_encoding = sys.stdin.encoding or 'ascii'
571 except AttributeError:
570 except AttributeError:
572 self.stdin_encoding = 'ascii'
571 self.stdin_encoding = 'ascii'
573
572
574
573
575 @observe('colors')
574 @observe('colors')
576 def init_syntax_highlighting(self, changes=None):
575 def init_syntax_highlighting(self, changes=None):
577 # Python source parser/formatter for syntax highlighting
576 # Python source parser/formatter for syntax highlighting
578 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
577 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
579 self.pycolorize = lambda src: pyformat(src,'str')
578 self.pycolorize = lambda src: pyformat(src,'str')
580
579
581 def refresh_style(self):
580 def refresh_style(self):
582 # No-op here, used in subclass
581 # No-op here, used in subclass
583 pass
582 pass
584
583
585 def init_pushd_popd_magic(self):
584 def init_pushd_popd_magic(self):
586 # for pushd/popd management
585 # for pushd/popd management
587 self.home_dir = get_home_dir()
586 self.home_dir = get_home_dir()
588
587
589 self.dir_stack = []
588 self.dir_stack = []
590
589
591 def init_logger(self):
590 def init_logger(self):
592 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
591 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
593 logmode='rotate')
592 logmode='rotate')
594
593
595 def init_logstart(self):
594 def init_logstart(self):
596 """Initialize logging in case it was requested at the command line.
595 """Initialize logging in case it was requested at the command line.
597 """
596 """
598 if self.logappend:
597 if self.logappend:
599 self.magic('logstart %s append' % self.logappend)
598 self.magic('logstart %s append' % self.logappend)
600 elif self.logfile:
599 elif self.logfile:
601 self.magic('logstart %s' % self.logfile)
600 self.magic('logstart %s' % self.logfile)
602 elif self.logstart:
601 elif self.logstart:
603 self.magic('logstart')
602 self.magic('logstart')
604
603
605 def init_deprecation_warnings(self):
604 def init_deprecation_warnings(self):
606 """
605 """
607 register default filter for deprecation warning.
606 register default filter for deprecation warning.
608
607
609 This will allow deprecation warning of function used interactively to show
608 This will allow deprecation warning of function used interactively to show
610 warning to users, and still hide deprecation warning from libraries import.
609 warning to users, and still hide deprecation warning from libraries import.
611 """
610 """
612 warnings.filterwarnings("default", category=DeprecationWarning, module=self.user_ns.get("__name__"))
611 warnings.filterwarnings("default", category=DeprecationWarning, module=self.user_ns.get("__name__"))
613
612
614 def init_builtins(self):
613 def init_builtins(self):
615 # A single, static flag that we set to True. Its presence indicates
614 # A single, static flag that we set to True. Its presence indicates
616 # that an IPython shell has been created, and we make no attempts at
615 # that an IPython shell has been created, and we make no attempts at
617 # removing on exit or representing the existence of more than one
616 # removing on exit or representing the existence of more than one
618 # IPython at a time.
617 # IPython at a time.
619 builtin_mod.__dict__['__IPYTHON__'] = True
618 builtin_mod.__dict__['__IPYTHON__'] = True
620
619
621 self.builtin_trap = BuiltinTrap(shell=self)
620 self.builtin_trap = BuiltinTrap(shell=self)
622
621
623 def init_inspector(self):
622 def init_inspector(self):
624 # Object inspector
623 # Object inspector
625 self.inspector = oinspect.Inspector(oinspect.InspectColors,
624 self.inspector = oinspect.Inspector(oinspect.InspectColors,
626 PyColorize.ANSICodeColors,
625 PyColorize.ANSICodeColors,
627 'NoColor',
626 'NoColor',
628 self.object_info_string_level)
627 self.object_info_string_level)
629
628
630 def init_io(self):
629 def init_io(self):
631 # This will just use sys.stdout and sys.stderr. If you want to
630 # This will just use sys.stdout and sys.stderr. If you want to
632 # override sys.stdout and sys.stderr themselves, you need to do that
631 # override sys.stdout and sys.stderr themselves, you need to do that
633 # *before* instantiating this class, because io holds onto
632 # *before* instantiating this class, because io holds onto
634 # references to the underlying streams.
633 # references to the underlying streams.
635 # io.std* are deprecated, but don't show our own deprecation warnings
634 # io.std* are deprecated, but don't show our own deprecation warnings
636 # during initialization of the deprecated API.
635 # during initialization of the deprecated API.
637 with warnings.catch_warnings():
636 with warnings.catch_warnings():
638 warnings.simplefilter('ignore', DeprecationWarning)
637 warnings.simplefilter('ignore', DeprecationWarning)
639 io.stdout = io.IOStream(sys.stdout)
638 io.stdout = io.IOStream(sys.stdout)
640 io.stderr = io.IOStream(sys.stderr)
639 io.stderr = io.IOStream(sys.stderr)
641
640
642 def init_prompts(self):
641 def init_prompts(self):
643 # Set system prompts, so that scripts can decide if they are running
642 # Set system prompts, so that scripts can decide if they are running
644 # interactively.
643 # interactively.
645 sys.ps1 = 'In : '
644 sys.ps1 = 'In : '
646 sys.ps2 = '...: '
645 sys.ps2 = '...: '
647 sys.ps3 = 'Out: '
646 sys.ps3 = 'Out: '
648
647
649 def init_display_formatter(self):
648 def init_display_formatter(self):
650 self.display_formatter = DisplayFormatter(parent=self)
649 self.display_formatter = DisplayFormatter(parent=self)
651 self.configurables.append(self.display_formatter)
650 self.configurables.append(self.display_formatter)
652
651
653 def init_display_pub(self):
652 def init_display_pub(self):
654 self.display_pub = self.display_pub_class(parent=self)
653 self.display_pub = self.display_pub_class(parent=self)
655 self.configurables.append(self.display_pub)
654 self.configurables.append(self.display_pub)
656
655
657 def init_data_pub(self):
656 def init_data_pub(self):
658 if not self.data_pub_class:
657 if not self.data_pub_class:
659 self.data_pub = None
658 self.data_pub = None
660 return
659 return
661 self.data_pub = self.data_pub_class(parent=self)
660 self.data_pub = self.data_pub_class(parent=self)
662 self.configurables.append(self.data_pub)
661 self.configurables.append(self.data_pub)
663
662
664 def init_displayhook(self):
663 def init_displayhook(self):
665 # Initialize displayhook, set in/out prompts and printing system
664 # Initialize displayhook, set in/out prompts and printing system
666 self.displayhook = self.displayhook_class(
665 self.displayhook = self.displayhook_class(
667 parent=self,
666 parent=self,
668 shell=self,
667 shell=self,
669 cache_size=self.cache_size,
668 cache_size=self.cache_size,
670 )
669 )
671 self.configurables.append(self.displayhook)
670 self.configurables.append(self.displayhook)
672 # This is a context manager that installs/revmoes the displayhook at
671 # This is a context manager that installs/revmoes the displayhook at
673 # the appropriate time.
672 # the appropriate time.
674 self.display_trap = DisplayTrap(hook=self.displayhook)
673 self.display_trap = DisplayTrap(hook=self.displayhook)
675
674
676 def init_virtualenv(self):
675 def init_virtualenv(self):
677 """Add a virtualenv to sys.path so the user can import modules from it.
676 """Add a virtualenv to sys.path so the user can import modules from it.
678 This isn't perfect: it doesn't use the Python interpreter with which the
677 This isn't perfect: it doesn't use the Python interpreter with which the
679 virtualenv was built, and it ignores the --no-site-packages option. A
678 virtualenv was built, and it ignores the --no-site-packages option. A
680 warning will appear suggesting the user installs IPython in the
679 warning will appear suggesting the user installs IPython in the
681 virtualenv, but for many cases, it probably works well enough.
680 virtualenv, but for many cases, it probably works well enough.
682
681
683 Adapted from code snippets online.
682 Adapted from code snippets online.
684
683
685 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
684 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
686 """
685 """
687 if 'VIRTUAL_ENV' not in os.environ:
686 if 'VIRTUAL_ENV' not in os.environ:
688 # Not in a virtualenv
687 # Not in a virtualenv
689 return
688 return
690
689
691 # venv detection:
690 # venv detection:
692 # stdlib venv may symlink sys.executable, so we can't use realpath.
691 # stdlib venv may symlink sys.executable, so we can't use realpath.
693 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
692 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
694 # So we just check every item in the symlink tree (generally <= 3)
693 # So we just check every item in the symlink tree (generally <= 3)
695 p = os.path.normcase(sys.executable)
694 p = os.path.normcase(sys.executable)
696 paths = [p]
695 paths = [p]
697 while os.path.islink(p):
696 while os.path.islink(p):
698 p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
697 p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
699 paths.append(p)
698 paths.append(p)
700 p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
699 p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
701 if any(p.startswith(p_venv) for p in paths):
700 if any(p.startswith(p_venv) for p in paths):
702 # Running properly in the virtualenv, don't need to do anything
701 # Running properly in the virtualenv, don't need to do anything
703 return
702 return
704
703
705 warn("Attempting to work in a virtualenv. If you encounter problems, please "
704 warn("Attempting to work in a virtualenv. If you encounter problems, please "
706 "install IPython inside the virtualenv.")
705 "install IPython inside the virtualenv.")
707 if sys.platform == "win32":
706 if sys.platform == "win32":
708 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
707 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
709 else:
708 else:
710 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
709 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
711 'python%d.%d' % sys.version_info[:2], 'site-packages')
710 'python%d.%d' % sys.version_info[:2], 'site-packages')
712
711
713 import site
712 import site
714 sys.path.insert(0, virtual_env)
713 sys.path.insert(0, virtual_env)
715 site.addsitedir(virtual_env)
714 site.addsitedir(virtual_env)
716
715
717 #-------------------------------------------------------------------------
716 #-------------------------------------------------------------------------
718 # Things related to injections into the sys module
717 # Things related to injections into the sys module
719 #-------------------------------------------------------------------------
718 #-------------------------------------------------------------------------
720
719
721 def save_sys_module_state(self):
720 def save_sys_module_state(self):
722 """Save the state of hooks in the sys module.
721 """Save the state of hooks in the sys module.
723
722
724 This has to be called after self.user_module is created.
723 This has to be called after self.user_module is created.
725 """
724 """
726 self._orig_sys_module_state = {'stdin': sys.stdin,
725 self._orig_sys_module_state = {'stdin': sys.stdin,
727 'stdout': sys.stdout,
726 'stdout': sys.stdout,
728 'stderr': sys.stderr,
727 'stderr': sys.stderr,
729 'excepthook': sys.excepthook}
728 'excepthook': sys.excepthook}
730 self._orig_sys_modules_main_name = self.user_module.__name__
729 self._orig_sys_modules_main_name = self.user_module.__name__
731 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
730 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
732
731
733 def restore_sys_module_state(self):
732 def restore_sys_module_state(self):
734 """Restore the state of the sys module."""
733 """Restore the state of the sys module."""
735 try:
734 try:
736 for k, v in iteritems(self._orig_sys_module_state):
735 for k, v in self._orig_sys_module_state.items():
737 setattr(sys, k, v)
736 setattr(sys, k, v)
738 except AttributeError:
737 except AttributeError:
739 pass
738 pass
740 # Reset what what done in self.init_sys_modules
739 # Reset what what done in self.init_sys_modules
741 if self._orig_sys_modules_main_mod is not None:
740 if self._orig_sys_modules_main_mod is not None:
742 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
741 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
743
742
744 #-------------------------------------------------------------------------
743 #-------------------------------------------------------------------------
745 # Things related to the banner
744 # Things related to the banner
746 #-------------------------------------------------------------------------
745 #-------------------------------------------------------------------------
747
746
748 @property
747 @property
749 def banner(self):
748 def banner(self):
750 banner = self.banner1
749 banner = self.banner1
751 if self.profile and self.profile != 'default':
750 if self.profile and self.profile != 'default':
752 banner += '\nIPython profile: %s\n' % self.profile
751 banner += '\nIPython profile: %s\n' % self.profile
753 if self.banner2:
752 if self.banner2:
754 banner += '\n' + self.banner2
753 banner += '\n' + self.banner2
755 return banner
754 return banner
756
755
757 def show_banner(self, banner=None):
756 def show_banner(self, banner=None):
758 if banner is None:
757 if banner is None:
759 banner = self.banner
758 banner = self.banner
760 sys.stdout.write(banner)
759 sys.stdout.write(banner)
761
760
762 #-------------------------------------------------------------------------
761 #-------------------------------------------------------------------------
763 # Things related to hooks
762 # Things related to hooks
764 #-------------------------------------------------------------------------
763 #-------------------------------------------------------------------------
765
764
766 def init_hooks(self):
765 def init_hooks(self):
767 # hooks holds pointers used for user-side customizations
766 # hooks holds pointers used for user-side customizations
768 self.hooks = Struct()
767 self.hooks = Struct()
769
768
770 self.strdispatchers = {}
769 self.strdispatchers = {}
771
770
772 # Set all default hooks, defined in the IPython.hooks module.
771 # Set all default hooks, defined in the IPython.hooks module.
773 hooks = IPython.core.hooks
772 hooks = IPython.core.hooks
774 for hook_name in hooks.__all__:
773 for hook_name in hooks.__all__:
775 # default hooks have priority 100, i.e. low; user hooks should have
774 # default hooks have priority 100, i.e. low; user hooks should have
776 # 0-100 priority
775 # 0-100 priority
777 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
776 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
778
777
779 if self.display_page:
778 if self.display_page:
780 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
779 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
781
780
782 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
781 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
783 _warn_deprecated=True):
782 _warn_deprecated=True):
784 """set_hook(name,hook) -> sets an internal IPython hook.
783 """set_hook(name,hook) -> sets an internal IPython hook.
785
784
786 IPython exposes some of its internal API as user-modifiable hooks. By
785 IPython exposes some of its internal API as user-modifiable hooks. By
787 adding your function to one of these hooks, you can modify IPython's
786 adding your function to one of these hooks, you can modify IPython's
788 behavior to call at runtime your own routines."""
787 behavior to call at runtime your own routines."""
789
788
790 # At some point in the future, this should validate the hook before it
789 # At some point in the future, this should validate the hook before it
791 # accepts it. Probably at least check that the hook takes the number
790 # accepts it. Probably at least check that the hook takes the number
792 # of args it's supposed to.
791 # of args it's supposed to.
793
792
794 f = types.MethodType(hook,self)
793 f = types.MethodType(hook,self)
795
794
796 # check if the hook is for strdispatcher first
795 # check if the hook is for strdispatcher first
797 if str_key is not None:
796 if str_key is not None:
798 sdp = self.strdispatchers.get(name, StrDispatch())
797 sdp = self.strdispatchers.get(name, StrDispatch())
799 sdp.add_s(str_key, f, priority )
798 sdp.add_s(str_key, f, priority )
800 self.strdispatchers[name] = sdp
799 self.strdispatchers[name] = sdp
801 return
800 return
802 if re_key is not None:
801 if re_key is not None:
803 sdp = self.strdispatchers.get(name, StrDispatch())
802 sdp = self.strdispatchers.get(name, StrDispatch())
804 sdp.add_re(re.compile(re_key), f, priority )
803 sdp.add_re(re.compile(re_key), f, priority )
805 self.strdispatchers[name] = sdp
804 self.strdispatchers[name] = sdp
806 return
805 return
807
806
808 dp = getattr(self.hooks, name, None)
807 dp = getattr(self.hooks, name, None)
809 if name not in IPython.core.hooks.__all__:
808 if name not in IPython.core.hooks.__all__:
810 print("Warning! Hook '%s' is not one of %s" % \
809 print("Warning! Hook '%s' is not one of %s" % \
811 (name, IPython.core.hooks.__all__ ))
810 (name, IPython.core.hooks.__all__ ))
812
811
813 if _warn_deprecated and (name in IPython.core.hooks.deprecated):
812 if _warn_deprecated and (name in IPython.core.hooks.deprecated):
814 alternative = IPython.core.hooks.deprecated[name]
813 alternative = IPython.core.hooks.deprecated[name]
815 warn("Hook {} is deprecated. Use {} instead.".format(name, alternative), stacklevel=2)
814 warn("Hook {} is deprecated. Use {} instead.".format(name, alternative), stacklevel=2)
816
815
817 if not dp:
816 if not dp:
818 dp = IPython.core.hooks.CommandChainDispatcher()
817 dp = IPython.core.hooks.CommandChainDispatcher()
819
818
820 try:
819 try:
821 dp.add(f,priority)
820 dp.add(f,priority)
822 except AttributeError:
821 except AttributeError:
823 # it was not commandchain, plain old func - replace
822 # it was not commandchain, plain old func - replace
824 dp = f
823 dp = f
825
824
826 setattr(self.hooks,name, dp)
825 setattr(self.hooks,name, dp)
827
826
828 #-------------------------------------------------------------------------
827 #-------------------------------------------------------------------------
829 # Things related to events
828 # Things related to events
830 #-------------------------------------------------------------------------
829 #-------------------------------------------------------------------------
831
830
832 def init_events(self):
831 def init_events(self):
833 self.events = EventManager(self, available_events)
832 self.events = EventManager(self, available_events)
834
833
835 self.events.register("pre_execute", self._clear_warning_registry)
834 self.events.register("pre_execute", self._clear_warning_registry)
836
835
837 def register_post_execute(self, func):
836 def register_post_execute(self, func):
838 """DEPRECATED: Use ip.events.register('post_run_cell', func)
837 """DEPRECATED: Use ip.events.register('post_run_cell', func)
839
838
840 Register a function for calling after code execution.
839 Register a function for calling after code execution.
841 """
840 """
842 warn("ip.register_post_execute is deprecated, use "
841 warn("ip.register_post_execute is deprecated, use "
843 "ip.events.register('post_run_cell', func) instead.", stacklevel=2)
842 "ip.events.register('post_run_cell', func) instead.", stacklevel=2)
844 self.events.register('post_run_cell', func)
843 self.events.register('post_run_cell', func)
845
844
846 def _clear_warning_registry(self):
845 def _clear_warning_registry(self):
847 # clear the warning registry, so that different code blocks with
846 # clear the warning registry, so that different code blocks with
848 # overlapping line number ranges don't cause spurious suppression of
847 # overlapping line number ranges don't cause spurious suppression of
849 # warnings (see gh-6611 for details)
848 # warnings (see gh-6611 for details)
850 if "__warningregistry__" in self.user_global_ns:
849 if "__warningregistry__" in self.user_global_ns:
851 del self.user_global_ns["__warningregistry__"]
850 del self.user_global_ns["__warningregistry__"]
852
851
853 #-------------------------------------------------------------------------
852 #-------------------------------------------------------------------------
854 # Things related to the "main" module
853 # Things related to the "main" module
855 #-------------------------------------------------------------------------
854 #-------------------------------------------------------------------------
856
855
857 def new_main_mod(self, filename, modname):
856 def new_main_mod(self, filename, modname):
858 """Return a new 'main' module object for user code execution.
857 """Return a new 'main' module object for user code execution.
859
858
860 ``filename`` should be the path of the script which will be run in the
859 ``filename`` should be the path of the script which will be run in the
861 module. Requests with the same filename will get the same module, with
860 module. Requests with the same filename will get the same module, with
862 its namespace cleared.
861 its namespace cleared.
863
862
864 ``modname`` should be the module name - normally either '__main__' or
863 ``modname`` should be the module name - normally either '__main__' or
865 the basename of the file without the extension.
864 the basename of the file without the extension.
866
865
867 When scripts are executed via %run, we must keep a reference to their
866 When scripts are executed via %run, we must keep a reference to their
868 __main__ module around so that Python doesn't
867 __main__ module around so that Python doesn't
869 clear it, rendering references to module globals useless.
868 clear it, rendering references to module globals useless.
870
869
871 This method keeps said reference in a private dict, keyed by the
870 This method keeps said reference in a private dict, keyed by the
872 absolute path of the script. This way, for multiple executions of the
871 absolute path of the script. This way, for multiple executions of the
873 same script we only keep one copy of the namespace (the last one),
872 same script we only keep one copy of the namespace (the last one),
874 thus preventing memory leaks from old references while allowing the
873 thus preventing memory leaks from old references while allowing the
875 objects from the last execution to be accessible.
874 objects from the last execution to be accessible.
876 """
875 """
877 filename = os.path.abspath(filename)
876 filename = os.path.abspath(filename)
878 try:
877 try:
879 main_mod = self._main_mod_cache[filename]
878 main_mod = self._main_mod_cache[filename]
880 except KeyError:
879 except KeyError:
881 main_mod = self._main_mod_cache[filename] = types.ModuleType(
880 main_mod = self._main_mod_cache[filename] = types.ModuleType(
882 py3compat.cast_bytes_py2(modname),
881 py3compat.cast_bytes_py2(modname),
883 doc="Module created for script run in IPython")
882 doc="Module created for script run in IPython")
884 else:
883 else:
885 main_mod.__dict__.clear()
884 main_mod.__dict__.clear()
886 main_mod.__name__ = modname
885 main_mod.__name__ = modname
887
886
888 main_mod.__file__ = filename
887 main_mod.__file__ = filename
889 # It seems pydoc (and perhaps others) needs any module instance to
888 # It seems pydoc (and perhaps others) needs any module instance to
890 # implement a __nonzero__ method
889 # implement a __nonzero__ method
891 main_mod.__nonzero__ = lambda : True
890 main_mod.__nonzero__ = lambda : True
892
891
893 return main_mod
892 return main_mod
894
893
895 def clear_main_mod_cache(self):
894 def clear_main_mod_cache(self):
896 """Clear the cache of main modules.
895 """Clear the cache of main modules.
897
896
898 Mainly for use by utilities like %reset.
897 Mainly for use by utilities like %reset.
899
898
900 Examples
899 Examples
901 --------
900 --------
902
901
903 In [15]: import IPython
902 In [15]: import IPython
904
903
905 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
904 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
906
905
907 In [17]: len(_ip._main_mod_cache) > 0
906 In [17]: len(_ip._main_mod_cache) > 0
908 Out[17]: True
907 Out[17]: True
909
908
910 In [18]: _ip.clear_main_mod_cache()
909 In [18]: _ip.clear_main_mod_cache()
911
910
912 In [19]: len(_ip._main_mod_cache) == 0
911 In [19]: len(_ip._main_mod_cache) == 0
913 Out[19]: True
912 Out[19]: True
914 """
913 """
915 self._main_mod_cache.clear()
914 self._main_mod_cache.clear()
916
915
917 #-------------------------------------------------------------------------
916 #-------------------------------------------------------------------------
918 # Things related to debugging
917 # Things related to debugging
919 #-------------------------------------------------------------------------
918 #-------------------------------------------------------------------------
920
919
921 def init_pdb(self):
920 def init_pdb(self):
922 # Set calling of pdb on exceptions
921 # Set calling of pdb on exceptions
923 # self.call_pdb is a property
922 # self.call_pdb is a property
924 self.call_pdb = self.pdb
923 self.call_pdb = self.pdb
925
924
926 def _get_call_pdb(self):
925 def _get_call_pdb(self):
927 return self._call_pdb
926 return self._call_pdb
928
927
929 def _set_call_pdb(self,val):
928 def _set_call_pdb(self,val):
930
929
931 if val not in (0,1,False,True):
930 if val not in (0,1,False,True):
932 raise ValueError('new call_pdb value must be boolean')
931 raise ValueError('new call_pdb value must be boolean')
933
932
934 # store value in instance
933 # store value in instance
935 self._call_pdb = val
934 self._call_pdb = val
936
935
937 # notify the actual exception handlers
936 # notify the actual exception handlers
938 self.InteractiveTB.call_pdb = val
937 self.InteractiveTB.call_pdb = val
939
938
940 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
939 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
941 'Control auto-activation of pdb at exceptions')
940 'Control auto-activation of pdb at exceptions')
942
941
943 def debugger(self,force=False):
942 def debugger(self,force=False):
944 """Call the pdb debugger.
943 """Call the pdb debugger.
945
944
946 Keywords:
945 Keywords:
947
946
948 - force(False): by default, this routine checks the instance call_pdb
947 - force(False): by default, this routine checks the instance call_pdb
949 flag and does not actually invoke the debugger if the flag is false.
948 flag and does not actually invoke the debugger if the flag is false.
950 The 'force' option forces the debugger to activate even if the flag
949 The 'force' option forces the debugger to activate even if the flag
951 is false.
950 is false.
952 """
951 """
953
952
954 if not (force or self.call_pdb):
953 if not (force or self.call_pdb):
955 return
954 return
956
955
957 if not hasattr(sys,'last_traceback'):
956 if not hasattr(sys,'last_traceback'):
958 error('No traceback has been produced, nothing to debug.')
957 error('No traceback has been produced, nothing to debug.')
959 return
958 return
960
959
961 self.InteractiveTB.debugger(force=True)
960 self.InteractiveTB.debugger(force=True)
962
961
963 #-------------------------------------------------------------------------
962 #-------------------------------------------------------------------------
964 # Things related to IPython's various namespaces
963 # Things related to IPython's various namespaces
965 #-------------------------------------------------------------------------
964 #-------------------------------------------------------------------------
966 default_user_namespaces = True
965 default_user_namespaces = True
967
966
968 def init_create_namespaces(self, user_module=None, user_ns=None):
967 def init_create_namespaces(self, user_module=None, user_ns=None):
969 # Create the namespace where the user will operate. user_ns is
968 # Create the namespace where the user will operate. user_ns is
970 # normally the only one used, and it is passed to the exec calls as
969 # normally the only one used, and it is passed to the exec calls as
971 # the locals argument. But we do carry a user_global_ns namespace
970 # the locals argument. But we do carry a user_global_ns namespace
972 # given as the exec 'globals' argument, This is useful in embedding
971 # given as the exec 'globals' argument, This is useful in embedding
973 # situations where the ipython shell opens in a context where the
972 # situations where the ipython shell opens in a context where the
974 # distinction between locals and globals is meaningful. For
973 # distinction between locals and globals is meaningful. For
975 # non-embedded contexts, it is just the same object as the user_ns dict.
974 # non-embedded contexts, it is just the same object as the user_ns dict.
976
975
977 # FIXME. For some strange reason, __builtins__ is showing up at user
976 # FIXME. For some strange reason, __builtins__ is showing up at user
978 # level as a dict instead of a module. This is a manual fix, but I
977 # level as a dict instead of a module. This is a manual fix, but I
979 # should really track down where the problem is coming from. Alex
978 # should really track down where the problem is coming from. Alex
980 # Schmolck reported this problem first.
979 # Schmolck reported this problem first.
981
980
982 # A useful post by Alex Martelli on this topic:
981 # A useful post by Alex Martelli on this topic:
983 # Re: inconsistent value from __builtins__
982 # Re: inconsistent value from __builtins__
984 # Von: Alex Martelli <aleaxit@yahoo.com>
983 # Von: Alex Martelli <aleaxit@yahoo.com>
985 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
984 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
986 # Gruppen: comp.lang.python
985 # Gruppen: comp.lang.python
987
986
988 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
987 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
989 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
988 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
990 # > <type 'dict'>
989 # > <type 'dict'>
991 # > >>> print type(__builtins__)
990 # > >>> print type(__builtins__)
992 # > <type 'module'>
991 # > <type 'module'>
993 # > Is this difference in return value intentional?
992 # > Is this difference in return value intentional?
994
993
995 # Well, it's documented that '__builtins__' can be either a dictionary
994 # Well, it's documented that '__builtins__' can be either a dictionary
996 # or a module, and it's been that way for a long time. Whether it's
995 # or a module, and it's been that way for a long time. Whether it's
997 # intentional (or sensible), I don't know. In any case, the idea is
996 # intentional (or sensible), I don't know. In any case, the idea is
998 # that if you need to access the built-in namespace directly, you
997 # that if you need to access the built-in namespace directly, you
999 # should start with "import __builtin__" (note, no 's') which will
998 # should start with "import __builtin__" (note, no 's') which will
1000 # definitely give you a module. Yeah, it's somewhat confusing:-(.
999 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1001
1000
1002 # These routines return a properly built module and dict as needed by
1001 # These routines return a properly built module and dict as needed by
1003 # the rest of the code, and can also be used by extension writers to
1002 # the rest of the code, and can also be used by extension writers to
1004 # generate properly initialized namespaces.
1003 # generate properly initialized namespaces.
1005 if (user_ns is not None) or (user_module is not None):
1004 if (user_ns is not None) or (user_module is not None):
1006 self.default_user_namespaces = False
1005 self.default_user_namespaces = False
1007 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1006 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1008
1007
1009 # A record of hidden variables we have added to the user namespace, so
1008 # A record of hidden variables we have added to the user namespace, so
1010 # we can list later only variables defined in actual interactive use.
1009 # we can list later only variables defined in actual interactive use.
1011 self.user_ns_hidden = {}
1010 self.user_ns_hidden = {}
1012
1011
1013 # Now that FakeModule produces a real module, we've run into a nasty
1012 # Now that FakeModule produces a real module, we've run into a nasty
1014 # problem: after script execution (via %run), the module where the user
1013 # problem: after script execution (via %run), the module where the user
1015 # code ran is deleted. Now that this object is a true module (needed
1014 # code ran is deleted. Now that this object is a true module (needed
1016 # so doctest and other tools work correctly), the Python module
1015 # so doctest and other tools work correctly), the Python module
1017 # teardown mechanism runs over it, and sets to None every variable
1016 # teardown mechanism runs over it, and sets to None every variable
1018 # present in that module. Top-level references to objects from the
1017 # present in that module. Top-level references to objects from the
1019 # script survive, because the user_ns is updated with them. However,
1018 # script survive, because the user_ns is updated with them. However,
1020 # calling functions defined in the script that use other things from
1019 # calling functions defined in the script that use other things from
1021 # the script will fail, because the function's closure had references
1020 # the script will fail, because the function's closure had references
1022 # to the original objects, which are now all None. So we must protect
1021 # to the original objects, which are now all None. So we must protect
1023 # these modules from deletion by keeping a cache.
1022 # these modules from deletion by keeping a cache.
1024 #
1023 #
1025 # To avoid keeping stale modules around (we only need the one from the
1024 # To avoid keeping stale modules around (we only need the one from the
1026 # last run), we use a dict keyed with the full path to the script, so
1025 # last run), we use a dict keyed with the full path to the script, so
1027 # only the last version of the module is held in the cache. Note,
1026 # only the last version of the module is held in the cache. Note,
1028 # however, that we must cache the module *namespace contents* (their
1027 # however, that we must cache the module *namespace contents* (their
1029 # __dict__). Because if we try to cache the actual modules, old ones
1028 # __dict__). Because if we try to cache the actual modules, old ones
1030 # (uncached) could be destroyed while still holding references (such as
1029 # (uncached) could be destroyed while still holding references (such as
1031 # those held by GUI objects that tend to be long-lived)>
1030 # those held by GUI objects that tend to be long-lived)>
1032 #
1031 #
1033 # The %reset command will flush this cache. See the cache_main_mod()
1032 # The %reset command will flush this cache. See the cache_main_mod()
1034 # and clear_main_mod_cache() methods for details on use.
1033 # and clear_main_mod_cache() methods for details on use.
1035
1034
1036 # This is the cache used for 'main' namespaces
1035 # This is the cache used for 'main' namespaces
1037 self._main_mod_cache = {}
1036 self._main_mod_cache = {}
1038
1037
1039 # A table holding all the namespaces IPython deals with, so that
1038 # A table holding all the namespaces IPython deals with, so that
1040 # introspection facilities can search easily.
1039 # introspection facilities can search easily.
1041 self.ns_table = {'user_global':self.user_module.__dict__,
1040 self.ns_table = {'user_global':self.user_module.__dict__,
1042 'user_local':self.user_ns,
1041 'user_local':self.user_ns,
1043 'builtin':builtin_mod.__dict__
1042 'builtin':builtin_mod.__dict__
1044 }
1043 }
1045
1044
1046 @property
1045 @property
1047 def user_global_ns(self):
1046 def user_global_ns(self):
1048 return self.user_module.__dict__
1047 return self.user_module.__dict__
1049
1048
1050 def prepare_user_module(self, user_module=None, user_ns=None):
1049 def prepare_user_module(self, user_module=None, user_ns=None):
1051 """Prepare the module and namespace in which user code will be run.
1050 """Prepare the module and namespace in which user code will be run.
1052
1051
1053 When IPython is started normally, both parameters are None: a new module
1052 When IPython is started normally, both parameters are None: a new module
1054 is created automatically, and its __dict__ used as the namespace.
1053 is created automatically, and its __dict__ used as the namespace.
1055
1054
1056 If only user_module is provided, its __dict__ is used as the namespace.
1055 If only user_module is provided, its __dict__ is used as the namespace.
1057 If only user_ns is provided, a dummy module is created, and user_ns
1056 If only user_ns is provided, a dummy module is created, and user_ns
1058 becomes the global namespace. If both are provided (as they may be
1057 becomes the global namespace. If both are provided (as they may be
1059 when embedding), user_ns is the local namespace, and user_module
1058 when embedding), user_ns is the local namespace, and user_module
1060 provides the global namespace.
1059 provides the global namespace.
1061
1060
1062 Parameters
1061 Parameters
1063 ----------
1062 ----------
1064 user_module : module, optional
1063 user_module : module, optional
1065 The current user module in which IPython is being run. If None,
1064 The current user module in which IPython is being run. If None,
1066 a clean module will be created.
1065 a clean module will be created.
1067 user_ns : dict, optional
1066 user_ns : dict, optional
1068 A namespace in which to run interactive commands.
1067 A namespace in which to run interactive commands.
1069
1068
1070 Returns
1069 Returns
1071 -------
1070 -------
1072 A tuple of user_module and user_ns, each properly initialised.
1071 A tuple of user_module and user_ns, each properly initialised.
1073 """
1072 """
1074 if user_module is None and user_ns is not None:
1073 if user_module is None and user_ns is not None:
1075 user_ns.setdefault("__name__", "__main__")
1074 user_ns.setdefault("__name__", "__main__")
1076 user_module = DummyMod()
1075 user_module = DummyMod()
1077 user_module.__dict__ = user_ns
1076 user_module.__dict__ = user_ns
1078
1077
1079 if user_module is None:
1078 if user_module is None:
1080 user_module = types.ModuleType("__main__",
1079 user_module = types.ModuleType("__main__",
1081 doc="Automatically created module for IPython interactive environment")
1080 doc="Automatically created module for IPython interactive environment")
1082
1081
1083 # We must ensure that __builtin__ (without the final 's') is always
1082 # We must ensure that __builtin__ (without the final 's') is always
1084 # available and pointing to the __builtin__ *module*. For more details:
1083 # available and pointing to the __builtin__ *module*. For more details:
1085 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1084 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1086 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1085 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1087 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1086 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1088
1087
1089 if user_ns is None:
1088 if user_ns is None:
1090 user_ns = user_module.__dict__
1089 user_ns = user_module.__dict__
1091
1090
1092 return user_module, user_ns
1091 return user_module, user_ns
1093
1092
1094 def init_sys_modules(self):
1093 def init_sys_modules(self):
1095 # We need to insert into sys.modules something that looks like a
1094 # We need to insert into sys.modules something that looks like a
1096 # module but which accesses the IPython namespace, for shelve and
1095 # module but which accesses the IPython namespace, for shelve and
1097 # pickle to work interactively. Normally they rely on getting
1096 # pickle to work interactively. Normally they rely on getting
1098 # everything out of __main__, but for embedding purposes each IPython
1097 # everything out of __main__, but for embedding purposes each IPython
1099 # instance has its own private namespace, so we can't go shoving
1098 # instance has its own private namespace, so we can't go shoving
1100 # everything into __main__.
1099 # everything into __main__.
1101
1100
1102 # note, however, that we should only do this for non-embedded
1101 # note, however, that we should only do this for non-embedded
1103 # ipythons, which really mimic the __main__.__dict__ with their own
1102 # ipythons, which really mimic the __main__.__dict__ with their own
1104 # namespace. Embedded instances, on the other hand, should not do
1103 # namespace. Embedded instances, on the other hand, should not do
1105 # this because they need to manage the user local/global namespaces
1104 # this because they need to manage the user local/global namespaces
1106 # only, but they live within a 'normal' __main__ (meaning, they
1105 # only, but they live within a 'normal' __main__ (meaning, they
1107 # shouldn't overtake the execution environment of the script they're
1106 # shouldn't overtake the execution environment of the script they're
1108 # embedded in).
1107 # embedded in).
1109
1108
1110 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1109 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1111 main_name = self.user_module.__name__
1110 main_name = self.user_module.__name__
1112 sys.modules[main_name] = self.user_module
1111 sys.modules[main_name] = self.user_module
1113
1112
1114 def init_user_ns(self):
1113 def init_user_ns(self):
1115 """Initialize all user-visible namespaces to their minimum defaults.
1114 """Initialize all user-visible namespaces to their minimum defaults.
1116
1115
1117 Certain history lists are also initialized here, as they effectively
1116 Certain history lists are also initialized here, as they effectively
1118 act as user namespaces.
1117 act as user namespaces.
1119
1118
1120 Notes
1119 Notes
1121 -----
1120 -----
1122 All data structures here are only filled in, they are NOT reset by this
1121 All data structures here are only filled in, they are NOT reset by this
1123 method. If they were not empty before, data will simply be added to
1122 method. If they were not empty before, data will simply be added to
1124 therm.
1123 therm.
1125 """
1124 """
1126 # This function works in two parts: first we put a few things in
1125 # This function works in two parts: first we put a few things in
1127 # user_ns, and we sync that contents into user_ns_hidden so that these
1126 # user_ns, and we sync that contents into user_ns_hidden so that these
1128 # initial variables aren't shown by %who. After the sync, we add the
1127 # initial variables aren't shown by %who. After the sync, we add the
1129 # rest of what we *do* want the user to see with %who even on a new
1128 # rest of what we *do* want the user to see with %who even on a new
1130 # session (probably nothing, so they really only see their own stuff)
1129 # session (probably nothing, so they really only see their own stuff)
1131
1130
1132 # The user dict must *always* have a __builtin__ reference to the
1131 # The user dict must *always* have a __builtin__ reference to the
1133 # Python standard __builtin__ namespace, which must be imported.
1132 # Python standard __builtin__ namespace, which must be imported.
1134 # This is so that certain operations in prompt evaluation can be
1133 # This is so that certain operations in prompt evaluation can be
1135 # reliably executed with builtins. Note that we can NOT use
1134 # reliably executed with builtins. Note that we can NOT use
1136 # __builtins__ (note the 's'), because that can either be a dict or a
1135 # __builtins__ (note the 's'), because that can either be a dict or a
1137 # module, and can even mutate at runtime, depending on the context
1136 # module, and can even mutate at runtime, depending on the context
1138 # (Python makes no guarantees on it). In contrast, __builtin__ is
1137 # (Python makes no guarantees on it). In contrast, __builtin__ is
1139 # always a module object, though it must be explicitly imported.
1138 # always a module object, though it must be explicitly imported.
1140
1139
1141 # For more details:
1140 # For more details:
1142 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1141 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1143 ns = dict()
1142 ns = dict()
1144
1143
1145 # make global variables for user access to the histories
1144 # make global variables for user access to the histories
1146 ns['_ih'] = self.history_manager.input_hist_parsed
1145 ns['_ih'] = self.history_manager.input_hist_parsed
1147 ns['_oh'] = self.history_manager.output_hist
1146 ns['_oh'] = self.history_manager.output_hist
1148 ns['_dh'] = self.history_manager.dir_hist
1147 ns['_dh'] = self.history_manager.dir_hist
1149
1148
1150 ns['_sh'] = shadowns
1149 ns['_sh'] = shadowns
1151
1150
1152 # user aliases to input and output histories. These shouldn't show up
1151 # user aliases to input and output histories. These shouldn't show up
1153 # in %who, as they can have very large reprs.
1152 # in %who, as they can have very large reprs.
1154 ns['In'] = self.history_manager.input_hist_parsed
1153 ns['In'] = self.history_manager.input_hist_parsed
1155 ns['Out'] = self.history_manager.output_hist
1154 ns['Out'] = self.history_manager.output_hist
1156
1155
1157 # Store myself as the public api!!!
1156 # Store myself as the public api!!!
1158 ns['get_ipython'] = self.get_ipython
1157 ns['get_ipython'] = self.get_ipython
1159
1158
1160 ns['exit'] = self.exiter
1159 ns['exit'] = self.exiter
1161 ns['quit'] = self.exiter
1160 ns['quit'] = self.exiter
1162
1161
1163 # Sync what we've added so far to user_ns_hidden so these aren't seen
1162 # Sync what we've added so far to user_ns_hidden so these aren't seen
1164 # by %who
1163 # by %who
1165 self.user_ns_hidden.update(ns)
1164 self.user_ns_hidden.update(ns)
1166
1165
1167 # Anything put into ns now would show up in %who. Think twice before
1166 # Anything put into ns now would show up in %who. Think twice before
1168 # putting anything here, as we really want %who to show the user their
1167 # putting anything here, as we really want %who to show the user their
1169 # stuff, not our variables.
1168 # stuff, not our variables.
1170
1169
1171 # Finally, update the real user's namespace
1170 # Finally, update the real user's namespace
1172 self.user_ns.update(ns)
1171 self.user_ns.update(ns)
1173
1172
1174 @property
1173 @property
1175 def all_ns_refs(self):
1174 def all_ns_refs(self):
1176 """Get a list of references to all the namespace dictionaries in which
1175 """Get a list of references to all the namespace dictionaries in which
1177 IPython might store a user-created object.
1176 IPython might store a user-created object.
1178
1177
1179 Note that this does not include the displayhook, which also caches
1178 Note that this does not include the displayhook, which also caches
1180 objects from the output."""
1179 objects from the output."""
1181 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1180 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1182 [m.__dict__ for m in self._main_mod_cache.values()]
1181 [m.__dict__ for m in self._main_mod_cache.values()]
1183
1182
1184 def reset(self, new_session=True):
1183 def reset(self, new_session=True):
1185 """Clear all internal namespaces, and attempt to release references to
1184 """Clear all internal namespaces, and attempt to release references to
1186 user objects.
1185 user objects.
1187
1186
1188 If new_session is True, a new history session will be opened.
1187 If new_session is True, a new history session will be opened.
1189 """
1188 """
1190 # Clear histories
1189 # Clear histories
1191 self.history_manager.reset(new_session)
1190 self.history_manager.reset(new_session)
1192 # Reset counter used to index all histories
1191 # Reset counter used to index all histories
1193 if new_session:
1192 if new_session:
1194 self.execution_count = 1
1193 self.execution_count = 1
1195
1194
1196 # Flush cached output items
1195 # Flush cached output items
1197 if self.displayhook.do_full_cache:
1196 if self.displayhook.do_full_cache:
1198 self.displayhook.flush()
1197 self.displayhook.flush()
1199
1198
1200 # The main execution namespaces must be cleared very carefully,
1199 # The main execution namespaces must be cleared very carefully,
1201 # skipping the deletion of the builtin-related keys, because doing so
1200 # skipping the deletion of the builtin-related keys, because doing so
1202 # would cause errors in many object's __del__ methods.
1201 # would cause errors in many object's __del__ methods.
1203 if self.user_ns is not self.user_global_ns:
1202 if self.user_ns is not self.user_global_ns:
1204 self.user_ns.clear()
1203 self.user_ns.clear()
1205 ns = self.user_global_ns
1204 ns = self.user_global_ns
1206 drop_keys = set(ns.keys())
1205 drop_keys = set(ns.keys())
1207 drop_keys.discard('__builtin__')
1206 drop_keys.discard('__builtin__')
1208 drop_keys.discard('__builtins__')
1207 drop_keys.discard('__builtins__')
1209 drop_keys.discard('__name__')
1208 drop_keys.discard('__name__')
1210 for k in drop_keys:
1209 for k in drop_keys:
1211 del ns[k]
1210 del ns[k]
1212
1211
1213 self.user_ns_hidden.clear()
1212 self.user_ns_hidden.clear()
1214
1213
1215 # Restore the user namespaces to minimal usability
1214 # Restore the user namespaces to minimal usability
1216 self.init_user_ns()
1215 self.init_user_ns()
1217
1216
1218 # Restore the default and user aliases
1217 # Restore the default and user aliases
1219 self.alias_manager.clear_aliases()
1218 self.alias_manager.clear_aliases()
1220 self.alias_manager.init_aliases()
1219 self.alias_manager.init_aliases()
1221
1220
1222 # Flush the private list of module references kept for script
1221 # Flush the private list of module references kept for script
1223 # execution protection
1222 # execution protection
1224 self.clear_main_mod_cache()
1223 self.clear_main_mod_cache()
1225
1224
1226 def del_var(self, varname, by_name=False):
1225 def del_var(self, varname, by_name=False):
1227 """Delete a variable from the various namespaces, so that, as
1226 """Delete a variable from the various namespaces, so that, as
1228 far as possible, we're not keeping any hidden references to it.
1227 far as possible, we're not keeping any hidden references to it.
1229
1228
1230 Parameters
1229 Parameters
1231 ----------
1230 ----------
1232 varname : str
1231 varname : str
1233 The name of the variable to delete.
1232 The name of the variable to delete.
1234 by_name : bool
1233 by_name : bool
1235 If True, delete variables with the given name in each
1234 If True, delete variables with the given name in each
1236 namespace. If False (default), find the variable in the user
1235 namespace. If False (default), find the variable in the user
1237 namespace, and delete references to it.
1236 namespace, and delete references to it.
1238 """
1237 """
1239 if varname in ('__builtin__', '__builtins__'):
1238 if varname in ('__builtin__', '__builtins__'):
1240 raise ValueError("Refusing to delete %s" % varname)
1239 raise ValueError("Refusing to delete %s" % varname)
1241
1240
1242 ns_refs = self.all_ns_refs
1241 ns_refs = self.all_ns_refs
1243
1242
1244 if by_name: # Delete by name
1243 if by_name: # Delete by name
1245 for ns in ns_refs:
1244 for ns in ns_refs:
1246 try:
1245 try:
1247 del ns[varname]
1246 del ns[varname]
1248 except KeyError:
1247 except KeyError:
1249 pass
1248 pass
1250 else: # Delete by object
1249 else: # Delete by object
1251 try:
1250 try:
1252 obj = self.user_ns[varname]
1251 obj = self.user_ns[varname]
1253 except KeyError:
1252 except KeyError:
1254 raise NameError("name '%s' is not defined" % varname)
1253 raise NameError("name '%s' is not defined" % varname)
1255 # Also check in output history
1254 # Also check in output history
1256 ns_refs.append(self.history_manager.output_hist)
1255 ns_refs.append(self.history_manager.output_hist)
1257 for ns in ns_refs:
1256 for ns in ns_refs:
1258 to_delete = [n for n, o in iteritems(ns) if o is obj]
1257 to_delete = [n for n, o in ns.items() if o is obj]
1259 for name in to_delete:
1258 for name in to_delete:
1260 del ns[name]
1259 del ns[name]
1261
1260
1262 # displayhook keeps extra references, but not in a dictionary
1261 # displayhook keeps extra references, but not in a dictionary
1263 for name in ('_', '__', '___'):
1262 for name in ('_', '__', '___'):
1264 if getattr(self.displayhook, name) is obj:
1263 if getattr(self.displayhook, name) is obj:
1265 setattr(self.displayhook, name, None)
1264 setattr(self.displayhook, name, None)
1266
1265
1267 def reset_selective(self, regex=None):
1266 def reset_selective(self, regex=None):
1268 """Clear selective variables from internal namespaces based on a
1267 """Clear selective variables from internal namespaces based on a
1269 specified regular expression.
1268 specified regular expression.
1270
1269
1271 Parameters
1270 Parameters
1272 ----------
1271 ----------
1273 regex : string or compiled pattern, optional
1272 regex : string or compiled pattern, optional
1274 A regular expression pattern that will be used in searching
1273 A regular expression pattern that will be used in searching
1275 variable names in the users namespaces.
1274 variable names in the users namespaces.
1276 """
1275 """
1277 if regex is not None:
1276 if regex is not None:
1278 try:
1277 try:
1279 m = re.compile(regex)
1278 m = re.compile(regex)
1280 except TypeError:
1279 except TypeError:
1281 raise TypeError('regex must be a string or compiled pattern')
1280 raise TypeError('regex must be a string or compiled pattern')
1282 # Search for keys in each namespace that match the given regex
1281 # Search for keys in each namespace that match the given regex
1283 # If a match is found, delete the key/value pair.
1282 # If a match is found, delete the key/value pair.
1284 for ns in self.all_ns_refs:
1283 for ns in self.all_ns_refs:
1285 for var in ns:
1284 for var in ns:
1286 if m.search(var):
1285 if m.search(var):
1287 del ns[var]
1286 del ns[var]
1288
1287
1289 def push(self, variables, interactive=True):
1288 def push(self, variables, interactive=True):
1290 """Inject a group of variables into the IPython user namespace.
1289 """Inject a group of variables into the IPython user namespace.
1291
1290
1292 Parameters
1291 Parameters
1293 ----------
1292 ----------
1294 variables : dict, str or list/tuple of str
1293 variables : dict, str or list/tuple of str
1295 The variables to inject into the user's namespace. If a dict, a
1294 The variables to inject into the user's namespace. If a dict, a
1296 simple update is done. If a str, the string is assumed to have
1295 simple update is done. If a str, the string is assumed to have
1297 variable names separated by spaces. A list/tuple of str can also
1296 variable names separated by spaces. A list/tuple of str can also
1298 be used to give the variable names. If just the variable names are
1297 be used to give the variable names. If just the variable names are
1299 give (list/tuple/str) then the variable values looked up in the
1298 give (list/tuple/str) then the variable values looked up in the
1300 callers frame.
1299 callers frame.
1301 interactive : bool
1300 interactive : bool
1302 If True (default), the variables will be listed with the ``who``
1301 If True (default), the variables will be listed with the ``who``
1303 magic.
1302 magic.
1304 """
1303 """
1305 vdict = None
1304 vdict = None
1306
1305
1307 # We need a dict of name/value pairs to do namespace updates.
1306 # We need a dict of name/value pairs to do namespace updates.
1308 if isinstance(variables, dict):
1307 if isinstance(variables, dict):
1309 vdict = variables
1308 vdict = variables
1310 elif isinstance(variables, string_types+(list, tuple)):
1309 elif isinstance(variables, (str, list, tuple)):
1311 if isinstance(variables, string_types):
1310 if isinstance(variables, str):
1312 vlist = variables.split()
1311 vlist = variables.split()
1313 else:
1312 else:
1314 vlist = variables
1313 vlist = variables
1315 vdict = {}
1314 vdict = {}
1316 cf = sys._getframe(1)
1315 cf = sys._getframe(1)
1317 for name in vlist:
1316 for name in vlist:
1318 try:
1317 try:
1319 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1318 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1320 except:
1319 except:
1321 print('Could not get variable %s from %s' %
1320 print('Could not get variable %s from %s' %
1322 (name,cf.f_code.co_name))
1321 (name,cf.f_code.co_name))
1323 else:
1322 else:
1324 raise ValueError('variables must be a dict/str/list/tuple')
1323 raise ValueError('variables must be a dict/str/list/tuple')
1325
1324
1326 # Propagate variables to user namespace
1325 # Propagate variables to user namespace
1327 self.user_ns.update(vdict)
1326 self.user_ns.update(vdict)
1328
1327
1329 # And configure interactive visibility
1328 # And configure interactive visibility
1330 user_ns_hidden = self.user_ns_hidden
1329 user_ns_hidden = self.user_ns_hidden
1331 if interactive:
1330 if interactive:
1332 for name in vdict:
1331 for name in vdict:
1333 user_ns_hidden.pop(name, None)
1332 user_ns_hidden.pop(name, None)
1334 else:
1333 else:
1335 user_ns_hidden.update(vdict)
1334 user_ns_hidden.update(vdict)
1336
1335
1337 def drop_by_id(self, variables):
1336 def drop_by_id(self, variables):
1338 """Remove a dict of variables from the user namespace, if they are the
1337 """Remove a dict of variables from the user namespace, if they are the
1339 same as the values in the dictionary.
1338 same as the values in the dictionary.
1340
1339
1341 This is intended for use by extensions: variables that they've added can
1340 This is intended for use by extensions: variables that they've added can
1342 be taken back out if they are unloaded, without removing any that the
1341 be taken back out if they are unloaded, without removing any that the
1343 user has overwritten.
1342 user has overwritten.
1344
1343
1345 Parameters
1344 Parameters
1346 ----------
1345 ----------
1347 variables : dict
1346 variables : dict
1348 A dictionary mapping object names (as strings) to the objects.
1347 A dictionary mapping object names (as strings) to the objects.
1349 """
1348 """
1350 for name, obj in iteritems(variables):
1349 for name, obj in variables.items():
1351 if name in self.user_ns and self.user_ns[name] is obj:
1350 if name in self.user_ns and self.user_ns[name] is obj:
1352 del self.user_ns[name]
1351 del self.user_ns[name]
1353 self.user_ns_hidden.pop(name, None)
1352 self.user_ns_hidden.pop(name, None)
1354
1353
1355 #-------------------------------------------------------------------------
1354 #-------------------------------------------------------------------------
1356 # Things related to object introspection
1355 # Things related to object introspection
1357 #-------------------------------------------------------------------------
1356 #-------------------------------------------------------------------------
1358
1357
1359 def _ofind(self, oname, namespaces=None):
1358 def _ofind(self, oname, namespaces=None):
1360 """Find an object in the available namespaces.
1359 """Find an object in the available namespaces.
1361
1360
1362 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1361 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1363
1362
1364 Has special code to detect magic functions.
1363 Has special code to detect magic functions.
1365 """
1364 """
1366 oname = oname.strip()
1365 oname = oname.strip()
1367 #print '1- oname: <%r>' % oname # dbg
1366 #print '1- oname: <%r>' % oname # dbg
1368 if not oname.startswith(ESC_MAGIC) and \
1367 if not oname.startswith(ESC_MAGIC) and \
1369 not oname.startswith(ESC_MAGIC2) and \
1368 not oname.startswith(ESC_MAGIC2) and \
1370 not py3compat.isidentifier(oname, dotted=True):
1369 not py3compat.isidentifier(oname, dotted=True):
1371 return dict(found=False)
1370 return dict(found=False)
1372
1371
1373 if namespaces is None:
1372 if namespaces is None:
1374 # Namespaces to search in:
1373 # Namespaces to search in:
1375 # Put them in a list. The order is important so that we
1374 # Put them in a list. The order is important so that we
1376 # find things in the same order that Python finds them.
1375 # find things in the same order that Python finds them.
1377 namespaces = [ ('Interactive', self.user_ns),
1376 namespaces = [ ('Interactive', self.user_ns),
1378 ('Interactive (global)', self.user_global_ns),
1377 ('Interactive (global)', self.user_global_ns),
1379 ('Python builtin', builtin_mod.__dict__),
1378 ('Python builtin', builtin_mod.__dict__),
1380 ]
1379 ]
1381
1380
1382 # initialize results to 'null'
1381 # initialize results to 'null'
1383 found = False; obj = None; ospace = None;
1382 found = False; obj = None; ospace = None;
1384 ismagic = False; isalias = False; parent = None
1383 ismagic = False; isalias = False; parent = None
1385
1384
1386 # We need to special-case 'print', which as of python2.6 registers as a
1385 # We need to special-case 'print', which as of python2.6 registers as a
1387 # function but should only be treated as one if print_function was
1386 # function but should only be treated as one if print_function was
1388 # loaded with a future import. In this case, just bail.
1387 # loaded with a future import. In this case, just bail.
1389 if (oname == 'print' and not py3compat.PY3 and not \
1388 if (oname == 'print' and not py3compat.PY3 and not \
1390 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1389 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1391 return {'found':found, 'obj':obj, 'namespace':ospace,
1390 return {'found':found, 'obj':obj, 'namespace':ospace,
1392 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1391 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1393
1392
1394 # Look for the given name by splitting it in parts. If the head is
1393 # Look for the given name by splitting it in parts. If the head is
1395 # found, then we look for all the remaining parts as members, and only
1394 # found, then we look for all the remaining parts as members, and only
1396 # declare success if we can find them all.
1395 # declare success if we can find them all.
1397 oname_parts = oname.split('.')
1396 oname_parts = oname.split('.')
1398 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1397 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1399 for nsname,ns in namespaces:
1398 for nsname,ns in namespaces:
1400 try:
1399 try:
1401 obj = ns[oname_head]
1400 obj = ns[oname_head]
1402 except KeyError:
1401 except KeyError:
1403 continue
1402 continue
1404 else:
1403 else:
1405 #print 'oname_rest:', oname_rest # dbg
1404 #print 'oname_rest:', oname_rest # dbg
1406 for idx, part in enumerate(oname_rest):
1405 for idx, part in enumerate(oname_rest):
1407 try:
1406 try:
1408 parent = obj
1407 parent = obj
1409 # The last part is looked up in a special way to avoid
1408 # The last part is looked up in a special way to avoid
1410 # descriptor invocation as it may raise or have side
1409 # descriptor invocation as it may raise or have side
1411 # effects.
1410 # effects.
1412 if idx == len(oname_rest) - 1:
1411 if idx == len(oname_rest) - 1:
1413 obj = self._getattr_property(obj, part)
1412 obj = self._getattr_property(obj, part)
1414 else:
1413 else:
1415 obj = getattr(obj, part)
1414 obj = getattr(obj, part)
1416 except:
1415 except:
1417 # Blanket except b/c some badly implemented objects
1416 # Blanket except b/c some badly implemented objects
1418 # allow __getattr__ to raise exceptions other than
1417 # allow __getattr__ to raise exceptions other than
1419 # AttributeError, which then crashes IPython.
1418 # AttributeError, which then crashes IPython.
1420 break
1419 break
1421 else:
1420 else:
1422 # If we finish the for loop (no break), we got all members
1421 # If we finish the for loop (no break), we got all members
1423 found = True
1422 found = True
1424 ospace = nsname
1423 ospace = nsname
1425 break # namespace loop
1424 break # namespace loop
1426
1425
1427 # Try to see if it's magic
1426 # Try to see if it's magic
1428 if not found:
1427 if not found:
1429 obj = None
1428 obj = None
1430 if oname.startswith(ESC_MAGIC2):
1429 if oname.startswith(ESC_MAGIC2):
1431 oname = oname.lstrip(ESC_MAGIC2)
1430 oname = oname.lstrip(ESC_MAGIC2)
1432 obj = self.find_cell_magic(oname)
1431 obj = self.find_cell_magic(oname)
1433 elif oname.startswith(ESC_MAGIC):
1432 elif oname.startswith(ESC_MAGIC):
1434 oname = oname.lstrip(ESC_MAGIC)
1433 oname = oname.lstrip(ESC_MAGIC)
1435 obj = self.find_line_magic(oname)
1434 obj = self.find_line_magic(oname)
1436 else:
1435 else:
1437 # search without prefix, so run? will find %run?
1436 # search without prefix, so run? will find %run?
1438 obj = self.find_line_magic(oname)
1437 obj = self.find_line_magic(oname)
1439 if obj is None:
1438 if obj is None:
1440 obj = self.find_cell_magic(oname)
1439 obj = self.find_cell_magic(oname)
1441 if obj is not None:
1440 if obj is not None:
1442 found = True
1441 found = True
1443 ospace = 'IPython internal'
1442 ospace = 'IPython internal'
1444 ismagic = True
1443 ismagic = True
1445 isalias = isinstance(obj, Alias)
1444 isalias = isinstance(obj, Alias)
1446
1445
1447 # Last try: special-case some literals like '', [], {}, etc:
1446 # Last try: special-case some literals like '', [], {}, etc:
1448 if not found and oname_head in ["''",'""','[]','{}','()']:
1447 if not found and oname_head in ["''",'""','[]','{}','()']:
1449 obj = eval(oname_head)
1448 obj = eval(oname_head)
1450 found = True
1449 found = True
1451 ospace = 'Interactive'
1450 ospace = 'Interactive'
1452
1451
1453 return {'found':found, 'obj':obj, 'namespace':ospace,
1452 return {'found':found, 'obj':obj, 'namespace':ospace,
1454 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1453 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1455
1454
1456 @staticmethod
1455 @staticmethod
1457 def _getattr_property(obj, attrname):
1456 def _getattr_property(obj, attrname):
1458 """Property-aware getattr to use in object finding.
1457 """Property-aware getattr to use in object finding.
1459
1458
1460 If attrname represents a property, return it unevaluated (in case it has
1459 If attrname represents a property, return it unevaluated (in case it has
1461 side effects or raises an error.
1460 side effects or raises an error.
1462
1461
1463 """
1462 """
1464 if not isinstance(obj, type):
1463 if not isinstance(obj, type):
1465 try:
1464 try:
1466 # `getattr(type(obj), attrname)` is not guaranteed to return
1465 # `getattr(type(obj), attrname)` is not guaranteed to return
1467 # `obj`, but does so for property:
1466 # `obj`, but does so for property:
1468 #
1467 #
1469 # property.__get__(self, None, cls) -> self
1468 # property.__get__(self, None, cls) -> self
1470 #
1469 #
1471 # The universal alternative is to traverse the mro manually
1470 # The universal alternative is to traverse the mro manually
1472 # searching for attrname in class dicts.
1471 # searching for attrname in class dicts.
1473 attr = getattr(type(obj), attrname)
1472 attr = getattr(type(obj), attrname)
1474 except AttributeError:
1473 except AttributeError:
1475 pass
1474 pass
1476 else:
1475 else:
1477 # This relies on the fact that data descriptors (with both
1476 # This relies on the fact that data descriptors (with both
1478 # __get__ & __set__ magic methods) take precedence over
1477 # __get__ & __set__ magic methods) take precedence over
1479 # instance-level attributes:
1478 # instance-level attributes:
1480 #
1479 #
1481 # class A(object):
1480 # class A(object):
1482 # @property
1481 # @property
1483 # def foobar(self): return 123
1482 # def foobar(self): return 123
1484 # a = A()
1483 # a = A()
1485 # a.__dict__['foobar'] = 345
1484 # a.__dict__['foobar'] = 345
1486 # a.foobar # == 123
1485 # a.foobar # == 123
1487 #
1486 #
1488 # So, a property may be returned right away.
1487 # So, a property may be returned right away.
1489 if isinstance(attr, property):
1488 if isinstance(attr, property):
1490 return attr
1489 return attr
1491
1490
1492 # Nothing helped, fall back.
1491 # Nothing helped, fall back.
1493 return getattr(obj, attrname)
1492 return getattr(obj, attrname)
1494
1493
1495 def _object_find(self, oname, namespaces=None):
1494 def _object_find(self, oname, namespaces=None):
1496 """Find an object and return a struct with info about it."""
1495 """Find an object and return a struct with info about it."""
1497 return Struct(self._ofind(oname, namespaces))
1496 return Struct(self._ofind(oname, namespaces))
1498
1497
1499 def _inspect(self, meth, oname, namespaces=None, **kw):
1498 def _inspect(self, meth, oname, namespaces=None, **kw):
1500 """Generic interface to the inspector system.
1499 """Generic interface to the inspector system.
1501
1500
1502 This function is meant to be called by pdef, pdoc & friends.
1501 This function is meant to be called by pdef, pdoc & friends.
1503 """
1502 """
1504 info = self._object_find(oname, namespaces)
1503 info = self._object_find(oname, namespaces)
1505 docformat = sphinxify if self.sphinxify_docstring else None
1504 docformat = sphinxify if self.sphinxify_docstring else None
1506 if info.found:
1505 if info.found:
1507 pmethod = getattr(self.inspector, meth)
1506 pmethod = getattr(self.inspector, meth)
1508 # TODO: only apply format_screen to the plain/text repr of the mime
1507 # TODO: only apply format_screen to the plain/text repr of the mime
1509 # bundle.
1508 # bundle.
1510 formatter = format_screen if info.ismagic else docformat
1509 formatter = format_screen if info.ismagic else docformat
1511 if meth == 'pdoc':
1510 if meth == 'pdoc':
1512 pmethod(info.obj, oname, formatter)
1511 pmethod(info.obj, oname, formatter)
1513 elif meth == 'pinfo':
1512 elif meth == 'pinfo':
1514 pmethod(info.obj, oname, formatter, info,
1513 pmethod(info.obj, oname, formatter, info,
1515 enable_html_pager=self.enable_html_pager, **kw)
1514 enable_html_pager=self.enable_html_pager, **kw)
1516 else:
1515 else:
1517 pmethod(info.obj, oname)
1516 pmethod(info.obj, oname)
1518 else:
1517 else:
1519 print('Object `%s` not found.' % oname)
1518 print('Object `%s` not found.' % oname)
1520 return 'not found' # so callers can take other action
1519 return 'not found' # so callers can take other action
1521
1520
1522 def object_inspect(self, oname, detail_level=0):
1521 def object_inspect(self, oname, detail_level=0):
1523 """Get object info about oname"""
1522 """Get object info about oname"""
1524 with self.builtin_trap:
1523 with self.builtin_trap:
1525 info = self._object_find(oname)
1524 info = self._object_find(oname)
1526 if info.found:
1525 if info.found:
1527 return self.inspector.info(info.obj, oname, info=info,
1526 return self.inspector.info(info.obj, oname, info=info,
1528 detail_level=detail_level
1527 detail_level=detail_level
1529 )
1528 )
1530 else:
1529 else:
1531 return oinspect.object_info(name=oname, found=False)
1530 return oinspect.object_info(name=oname, found=False)
1532
1531
1533 def object_inspect_text(self, oname, detail_level=0):
1532 def object_inspect_text(self, oname, detail_level=0):
1534 """Get object info as formatted text"""
1533 """Get object info as formatted text"""
1535 return self.object_inspect_mime(oname, detail_level)['text/plain']
1534 return self.object_inspect_mime(oname, detail_level)['text/plain']
1536
1535
1537 def object_inspect_mime(self, oname, detail_level=0):
1536 def object_inspect_mime(self, oname, detail_level=0):
1538 """Get object info as a mimebundle of formatted representations.
1537 """Get object info as a mimebundle of formatted representations.
1539
1538
1540 A mimebundle is a dictionary, keyed by mime-type.
1539 A mimebundle is a dictionary, keyed by mime-type.
1541 It must always have the key `'text/plain'`.
1540 It must always have the key `'text/plain'`.
1542 """
1541 """
1543 with self.builtin_trap:
1542 with self.builtin_trap:
1544 info = self._object_find(oname)
1543 info = self._object_find(oname)
1545 if info.found:
1544 if info.found:
1546 return self.inspector._get_info(info.obj, oname, info=info,
1545 return self.inspector._get_info(info.obj, oname, info=info,
1547 detail_level=detail_level
1546 detail_level=detail_level
1548 )
1547 )
1549 else:
1548 else:
1550 raise KeyError(oname)
1549 raise KeyError(oname)
1551
1550
1552 #-------------------------------------------------------------------------
1551 #-------------------------------------------------------------------------
1553 # Things related to history management
1552 # Things related to history management
1554 #-------------------------------------------------------------------------
1553 #-------------------------------------------------------------------------
1555
1554
1556 def init_history(self):
1555 def init_history(self):
1557 """Sets up the command history, and starts regular autosaves."""
1556 """Sets up the command history, and starts regular autosaves."""
1558 self.history_manager = HistoryManager(shell=self, parent=self)
1557 self.history_manager = HistoryManager(shell=self, parent=self)
1559 self.configurables.append(self.history_manager)
1558 self.configurables.append(self.history_manager)
1560
1559
1561 #-------------------------------------------------------------------------
1560 #-------------------------------------------------------------------------
1562 # Things related to exception handling and tracebacks (not debugging)
1561 # Things related to exception handling and tracebacks (not debugging)
1563 #-------------------------------------------------------------------------
1562 #-------------------------------------------------------------------------
1564
1563
1565 debugger_cls = Pdb
1564 debugger_cls = Pdb
1566
1565
1567 def init_traceback_handlers(self, custom_exceptions):
1566 def init_traceback_handlers(self, custom_exceptions):
1568 # Syntax error handler.
1567 # Syntax error handler.
1569 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1568 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1570
1569
1571 # The interactive one is initialized with an offset, meaning we always
1570 # The interactive one is initialized with an offset, meaning we always
1572 # want to remove the topmost item in the traceback, which is our own
1571 # want to remove the topmost item in the traceback, which is our own
1573 # internal code. Valid modes: ['Plain','Context','Verbose']
1572 # internal code. Valid modes: ['Plain','Context','Verbose']
1574 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1573 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1575 color_scheme='NoColor',
1574 color_scheme='NoColor',
1576 tb_offset = 1,
1575 tb_offset = 1,
1577 check_cache=check_linecache_ipython,
1576 check_cache=check_linecache_ipython,
1578 debugger_cls=self.debugger_cls, parent=self)
1577 debugger_cls=self.debugger_cls, parent=self)
1579
1578
1580 # The instance will store a pointer to the system-wide exception hook,
1579 # The instance will store a pointer to the system-wide exception hook,
1581 # so that runtime code (such as magics) can access it. This is because
1580 # so that runtime code (such as magics) can access it. This is because
1582 # during the read-eval loop, it may get temporarily overwritten.
1581 # during the read-eval loop, it may get temporarily overwritten.
1583 self.sys_excepthook = sys.excepthook
1582 self.sys_excepthook = sys.excepthook
1584
1583
1585 # and add any custom exception handlers the user may have specified
1584 # and add any custom exception handlers the user may have specified
1586 self.set_custom_exc(*custom_exceptions)
1585 self.set_custom_exc(*custom_exceptions)
1587
1586
1588 # Set the exception mode
1587 # Set the exception mode
1589 self.InteractiveTB.set_mode(mode=self.xmode)
1588 self.InteractiveTB.set_mode(mode=self.xmode)
1590
1589
1591 def set_custom_exc(self, exc_tuple, handler):
1590 def set_custom_exc(self, exc_tuple, handler):
1592 """set_custom_exc(exc_tuple, handler)
1591 """set_custom_exc(exc_tuple, handler)
1593
1592
1594 Set a custom exception handler, which will be called if any of the
1593 Set a custom exception handler, which will be called if any of the
1595 exceptions in exc_tuple occur in the mainloop (specifically, in the
1594 exceptions in exc_tuple occur in the mainloop (specifically, in the
1596 run_code() method).
1595 run_code() method).
1597
1596
1598 Parameters
1597 Parameters
1599 ----------
1598 ----------
1600
1599
1601 exc_tuple : tuple of exception classes
1600 exc_tuple : tuple of exception classes
1602 A *tuple* of exception classes, for which to call the defined
1601 A *tuple* of exception classes, for which to call the defined
1603 handler. It is very important that you use a tuple, and NOT A
1602 handler. It is very important that you use a tuple, and NOT A
1604 LIST here, because of the way Python's except statement works. If
1603 LIST here, because of the way Python's except statement works. If
1605 you only want to trap a single exception, use a singleton tuple::
1604 you only want to trap a single exception, use a singleton tuple::
1606
1605
1607 exc_tuple == (MyCustomException,)
1606 exc_tuple == (MyCustomException,)
1608
1607
1609 handler : callable
1608 handler : callable
1610 handler must have the following signature::
1609 handler must have the following signature::
1611
1610
1612 def my_handler(self, etype, value, tb, tb_offset=None):
1611 def my_handler(self, etype, value, tb, tb_offset=None):
1613 ...
1612 ...
1614 return structured_traceback
1613 return structured_traceback
1615
1614
1616 Your handler must return a structured traceback (a list of strings),
1615 Your handler must return a structured traceback (a list of strings),
1617 or None.
1616 or None.
1618
1617
1619 This will be made into an instance method (via types.MethodType)
1618 This will be made into an instance method (via types.MethodType)
1620 of IPython itself, and it will be called if any of the exceptions
1619 of IPython itself, and it will be called if any of the exceptions
1621 listed in the exc_tuple are caught. If the handler is None, an
1620 listed in the exc_tuple are caught. If the handler is None, an
1622 internal basic one is used, which just prints basic info.
1621 internal basic one is used, which just prints basic info.
1623
1622
1624 To protect IPython from crashes, if your handler ever raises an
1623 To protect IPython from crashes, if your handler ever raises an
1625 exception or returns an invalid result, it will be immediately
1624 exception or returns an invalid result, it will be immediately
1626 disabled.
1625 disabled.
1627
1626
1628 WARNING: by putting in your own exception handler into IPython's main
1627 WARNING: by putting in your own exception handler into IPython's main
1629 execution loop, you run a very good chance of nasty crashes. This
1628 execution loop, you run a very good chance of nasty crashes. This
1630 facility should only be used if you really know what you are doing."""
1629 facility should only be used if you really know what you are doing."""
1631
1630
1632 assert type(exc_tuple)==type(()) , \
1631 assert type(exc_tuple)==type(()) , \
1633 "The custom exceptions must be given AS A TUPLE."
1632 "The custom exceptions must be given AS A TUPLE."
1634
1633
1635 def dummy_handler(self, etype, value, tb, tb_offset=None):
1634 def dummy_handler(self, etype, value, tb, tb_offset=None):
1636 print('*** Simple custom exception handler ***')
1635 print('*** Simple custom exception handler ***')
1637 print('Exception type :',etype)
1636 print('Exception type :',etype)
1638 print('Exception value:',value)
1637 print('Exception value:',value)
1639 print('Traceback :',tb)
1638 print('Traceback :',tb)
1640 #print 'Source code :','\n'.join(self.buffer)
1639 #print 'Source code :','\n'.join(self.buffer)
1641
1640
1642 def validate_stb(stb):
1641 def validate_stb(stb):
1643 """validate structured traceback return type
1642 """validate structured traceback return type
1644
1643
1645 return type of CustomTB *should* be a list of strings, but allow
1644 return type of CustomTB *should* be a list of strings, but allow
1646 single strings or None, which are harmless.
1645 single strings or None, which are harmless.
1647
1646
1648 This function will *always* return a list of strings,
1647 This function will *always* return a list of strings,
1649 and will raise a TypeError if stb is inappropriate.
1648 and will raise a TypeError if stb is inappropriate.
1650 """
1649 """
1651 msg = "CustomTB must return list of strings, not %r" % stb
1650 msg = "CustomTB must return list of strings, not %r" % stb
1652 if stb is None:
1651 if stb is None:
1653 return []
1652 return []
1654 elif isinstance(stb, string_types):
1653 elif isinstance(stb, str):
1655 return [stb]
1654 return [stb]
1656 elif not isinstance(stb, list):
1655 elif not isinstance(stb, list):
1657 raise TypeError(msg)
1656 raise TypeError(msg)
1658 # it's a list
1657 # it's a list
1659 for line in stb:
1658 for line in stb:
1660 # check every element
1659 # check every element
1661 if not isinstance(line, string_types):
1660 if not isinstance(line, str):
1662 raise TypeError(msg)
1661 raise TypeError(msg)
1663 return stb
1662 return stb
1664
1663
1665 if handler is None:
1664 if handler is None:
1666 wrapped = dummy_handler
1665 wrapped = dummy_handler
1667 else:
1666 else:
1668 def wrapped(self,etype,value,tb,tb_offset=None):
1667 def wrapped(self,etype,value,tb,tb_offset=None):
1669 """wrap CustomTB handler, to protect IPython from user code
1668 """wrap CustomTB handler, to protect IPython from user code
1670
1669
1671 This makes it harder (but not impossible) for custom exception
1670 This makes it harder (but not impossible) for custom exception
1672 handlers to crash IPython.
1671 handlers to crash IPython.
1673 """
1672 """
1674 try:
1673 try:
1675 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1674 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1676 return validate_stb(stb)
1675 return validate_stb(stb)
1677 except:
1676 except:
1678 # clear custom handler immediately
1677 # clear custom handler immediately
1679 self.set_custom_exc((), None)
1678 self.set_custom_exc((), None)
1680 print("Custom TB Handler failed, unregistering", file=sys.stderr)
1679 print("Custom TB Handler failed, unregistering", file=sys.stderr)
1681 # show the exception in handler first
1680 # show the exception in handler first
1682 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1681 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1683 print(self.InteractiveTB.stb2text(stb))
1682 print(self.InteractiveTB.stb2text(stb))
1684 print("The original exception:")
1683 print("The original exception:")
1685 stb = self.InteractiveTB.structured_traceback(
1684 stb = self.InteractiveTB.structured_traceback(
1686 (etype,value,tb), tb_offset=tb_offset
1685 (etype,value,tb), tb_offset=tb_offset
1687 )
1686 )
1688 return stb
1687 return stb
1689
1688
1690 self.CustomTB = types.MethodType(wrapped,self)
1689 self.CustomTB = types.MethodType(wrapped,self)
1691 self.custom_exceptions = exc_tuple
1690 self.custom_exceptions = exc_tuple
1692
1691
1693 def excepthook(self, etype, value, tb):
1692 def excepthook(self, etype, value, tb):
1694 """One more defense for GUI apps that call sys.excepthook.
1693 """One more defense for GUI apps that call sys.excepthook.
1695
1694
1696 GUI frameworks like wxPython trap exceptions and call
1695 GUI frameworks like wxPython trap exceptions and call
1697 sys.excepthook themselves. I guess this is a feature that
1696 sys.excepthook themselves. I guess this is a feature that
1698 enables them to keep running after exceptions that would
1697 enables them to keep running after exceptions that would
1699 otherwise kill their mainloop. This is a bother for IPython
1698 otherwise kill their mainloop. This is a bother for IPython
1700 which excepts to catch all of the program exceptions with a try:
1699 which excepts to catch all of the program exceptions with a try:
1701 except: statement.
1700 except: statement.
1702
1701
1703 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1702 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1704 any app directly invokes sys.excepthook, it will look to the user like
1703 any app directly invokes sys.excepthook, it will look to the user like
1705 IPython crashed. In order to work around this, we can disable the
1704 IPython crashed. In order to work around this, we can disable the
1706 CrashHandler and replace it with this excepthook instead, which prints a
1705 CrashHandler and replace it with this excepthook instead, which prints a
1707 regular traceback using our InteractiveTB. In this fashion, apps which
1706 regular traceback using our InteractiveTB. In this fashion, apps which
1708 call sys.excepthook will generate a regular-looking exception from
1707 call sys.excepthook will generate a regular-looking exception from
1709 IPython, and the CrashHandler will only be triggered by real IPython
1708 IPython, and the CrashHandler will only be triggered by real IPython
1710 crashes.
1709 crashes.
1711
1710
1712 This hook should be used sparingly, only in places which are not likely
1711 This hook should be used sparingly, only in places which are not likely
1713 to be true IPython errors.
1712 to be true IPython errors.
1714 """
1713 """
1715 self.showtraceback((etype, value, tb), tb_offset=0)
1714 self.showtraceback((etype, value, tb), tb_offset=0)
1716
1715
1717 def _get_exc_info(self, exc_tuple=None):
1716 def _get_exc_info(self, exc_tuple=None):
1718 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1717 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1719
1718
1720 Ensures sys.last_type,value,traceback hold the exc_info we found,
1719 Ensures sys.last_type,value,traceback hold the exc_info we found,
1721 from whichever source.
1720 from whichever source.
1722
1721
1723 raises ValueError if none of these contain any information
1722 raises ValueError if none of these contain any information
1724 """
1723 """
1725 if exc_tuple is None:
1724 if exc_tuple is None:
1726 etype, value, tb = sys.exc_info()
1725 etype, value, tb = sys.exc_info()
1727 else:
1726 else:
1728 etype, value, tb = exc_tuple
1727 etype, value, tb = exc_tuple
1729
1728
1730 if etype is None:
1729 if etype is None:
1731 if hasattr(sys, 'last_type'):
1730 if hasattr(sys, 'last_type'):
1732 etype, value, tb = sys.last_type, sys.last_value, \
1731 etype, value, tb = sys.last_type, sys.last_value, \
1733 sys.last_traceback
1732 sys.last_traceback
1734
1733
1735 if etype is None:
1734 if etype is None:
1736 raise ValueError("No exception to find")
1735 raise ValueError("No exception to find")
1737
1736
1738 # Now store the exception info in sys.last_type etc.
1737 # Now store the exception info in sys.last_type etc.
1739 # WARNING: these variables are somewhat deprecated and not
1738 # WARNING: these variables are somewhat deprecated and not
1740 # necessarily safe to use in a threaded environment, but tools
1739 # necessarily safe to use in a threaded environment, but tools
1741 # like pdb depend on their existence, so let's set them. If we
1740 # like pdb depend on their existence, so let's set them. If we
1742 # find problems in the field, we'll need to revisit their use.
1741 # find problems in the field, we'll need to revisit their use.
1743 sys.last_type = etype
1742 sys.last_type = etype
1744 sys.last_value = value
1743 sys.last_value = value
1745 sys.last_traceback = tb
1744 sys.last_traceback = tb
1746
1745
1747 return etype, value, tb
1746 return etype, value, tb
1748
1747
1749 def show_usage_error(self, exc):
1748 def show_usage_error(self, exc):
1750 """Show a short message for UsageErrors
1749 """Show a short message for UsageErrors
1751
1750
1752 These are special exceptions that shouldn't show a traceback.
1751 These are special exceptions that shouldn't show a traceback.
1753 """
1752 """
1754 print("UsageError: %s" % exc, file=sys.stderr)
1753 print("UsageError: %s" % exc, file=sys.stderr)
1755
1754
1756 def get_exception_only(self, exc_tuple=None):
1755 def get_exception_only(self, exc_tuple=None):
1757 """
1756 """
1758 Return as a string (ending with a newline) the exception that
1757 Return as a string (ending with a newline) the exception that
1759 just occurred, without any traceback.
1758 just occurred, without any traceback.
1760 """
1759 """
1761 etype, value, tb = self._get_exc_info(exc_tuple)
1760 etype, value, tb = self._get_exc_info(exc_tuple)
1762 msg = traceback.format_exception_only(etype, value)
1761 msg = traceback.format_exception_only(etype, value)
1763 return ''.join(msg)
1762 return ''.join(msg)
1764
1763
1765 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1764 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1766 exception_only=False):
1765 exception_only=False):
1767 """Display the exception that just occurred.
1766 """Display the exception that just occurred.
1768
1767
1769 If nothing is known about the exception, this is the method which
1768 If nothing is known about the exception, this is the method which
1770 should be used throughout the code for presenting user tracebacks,
1769 should be used throughout the code for presenting user tracebacks,
1771 rather than directly invoking the InteractiveTB object.
1770 rather than directly invoking the InteractiveTB object.
1772
1771
1773 A specific showsyntaxerror() also exists, but this method can take
1772 A specific showsyntaxerror() also exists, but this method can take
1774 care of calling it if needed, so unless you are explicitly catching a
1773 care of calling it if needed, so unless you are explicitly catching a
1775 SyntaxError exception, don't try to analyze the stack manually and
1774 SyntaxError exception, don't try to analyze the stack manually and
1776 simply call this method."""
1775 simply call this method."""
1777
1776
1778 try:
1777 try:
1779 try:
1778 try:
1780 etype, value, tb = self._get_exc_info(exc_tuple)
1779 etype, value, tb = self._get_exc_info(exc_tuple)
1781 except ValueError:
1780 except ValueError:
1782 print('No traceback available to show.', file=sys.stderr)
1781 print('No traceback available to show.', file=sys.stderr)
1783 return
1782 return
1784
1783
1785 if issubclass(etype, SyntaxError):
1784 if issubclass(etype, SyntaxError):
1786 # Though this won't be called by syntax errors in the input
1785 # Though this won't be called by syntax errors in the input
1787 # line, there may be SyntaxError cases with imported code.
1786 # line, there may be SyntaxError cases with imported code.
1788 self.showsyntaxerror(filename)
1787 self.showsyntaxerror(filename)
1789 elif etype is UsageError:
1788 elif etype is UsageError:
1790 self.show_usage_error(value)
1789 self.show_usage_error(value)
1791 else:
1790 else:
1792 if exception_only:
1791 if exception_only:
1793 stb = ['An exception has occurred, use %tb to see '
1792 stb = ['An exception has occurred, use %tb to see '
1794 'the full traceback.\n']
1793 'the full traceback.\n']
1795 stb.extend(self.InteractiveTB.get_exception_only(etype,
1794 stb.extend(self.InteractiveTB.get_exception_only(etype,
1796 value))
1795 value))
1797 else:
1796 else:
1798 try:
1797 try:
1799 # Exception classes can customise their traceback - we
1798 # Exception classes can customise their traceback - we
1800 # use this in IPython.parallel for exceptions occurring
1799 # use this in IPython.parallel for exceptions occurring
1801 # in the engines. This should return a list of strings.
1800 # in the engines. This should return a list of strings.
1802 stb = value._render_traceback_()
1801 stb = value._render_traceback_()
1803 except Exception:
1802 except Exception:
1804 stb = self.InteractiveTB.structured_traceback(etype,
1803 stb = self.InteractiveTB.structured_traceback(etype,
1805 value, tb, tb_offset=tb_offset)
1804 value, tb, tb_offset=tb_offset)
1806
1805
1807 self._showtraceback(etype, value, stb)
1806 self._showtraceback(etype, value, stb)
1808 if self.call_pdb:
1807 if self.call_pdb:
1809 # drop into debugger
1808 # drop into debugger
1810 self.debugger(force=True)
1809 self.debugger(force=True)
1811 return
1810 return
1812
1811
1813 # Actually show the traceback
1812 # Actually show the traceback
1814 self._showtraceback(etype, value, stb)
1813 self._showtraceback(etype, value, stb)
1815
1814
1816 except KeyboardInterrupt:
1815 except KeyboardInterrupt:
1817 print('\n' + self.get_exception_only(), file=sys.stderr)
1816 print('\n' + self.get_exception_only(), file=sys.stderr)
1818
1817
1819 def _showtraceback(self, etype, evalue, stb):
1818 def _showtraceback(self, etype, evalue, stb):
1820 """Actually show a traceback.
1819 """Actually show a traceback.
1821
1820
1822 Subclasses may override this method to put the traceback on a different
1821 Subclasses may override this method to put the traceback on a different
1823 place, like a side channel.
1822 place, like a side channel.
1824 """
1823 """
1825 print(self.InteractiveTB.stb2text(stb))
1824 print(self.InteractiveTB.stb2text(stb))
1826
1825
1827 def showsyntaxerror(self, filename=None):
1826 def showsyntaxerror(self, filename=None):
1828 """Display the syntax error that just occurred.
1827 """Display the syntax error that just occurred.
1829
1828
1830 This doesn't display a stack trace because there isn't one.
1829 This doesn't display a stack trace because there isn't one.
1831
1830
1832 If a filename is given, it is stuffed in the exception instead
1831 If a filename is given, it is stuffed in the exception instead
1833 of what was there before (because Python's parser always uses
1832 of what was there before (because Python's parser always uses
1834 "<string>" when reading from a string).
1833 "<string>" when reading from a string).
1835 """
1834 """
1836 etype, value, last_traceback = self._get_exc_info()
1835 etype, value, last_traceback = self._get_exc_info()
1837
1836
1838 if filename and issubclass(etype, SyntaxError):
1837 if filename and issubclass(etype, SyntaxError):
1839 try:
1838 try:
1840 value.filename = filename
1839 value.filename = filename
1841 except:
1840 except:
1842 # Not the format we expect; leave it alone
1841 # Not the format we expect; leave it alone
1843 pass
1842 pass
1844
1843
1845 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1844 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1846 self._showtraceback(etype, value, stb)
1845 self._showtraceback(etype, value, stb)
1847
1846
1848 # This is overridden in TerminalInteractiveShell to show a message about
1847 # This is overridden in TerminalInteractiveShell to show a message about
1849 # the %paste magic.
1848 # the %paste magic.
1850 def showindentationerror(self):
1849 def showindentationerror(self):
1851 """Called by run_cell when there's an IndentationError in code entered
1850 """Called by run_cell when there's an IndentationError in code entered
1852 at the prompt.
1851 at the prompt.
1853
1852
1854 This is overridden in TerminalInteractiveShell to show a message about
1853 This is overridden in TerminalInteractiveShell to show a message about
1855 the %paste magic."""
1854 the %paste magic."""
1856 self.showsyntaxerror()
1855 self.showsyntaxerror()
1857
1856
1858 #-------------------------------------------------------------------------
1857 #-------------------------------------------------------------------------
1859 # Things related to readline
1858 # Things related to readline
1860 #-------------------------------------------------------------------------
1859 #-------------------------------------------------------------------------
1861
1860
1862 def init_readline(self):
1861 def init_readline(self):
1863 """DEPRECATED
1862 """DEPRECATED
1864
1863
1865 Moved to terminal subclass, here only to simplify the init logic."""
1864 Moved to terminal subclass, here only to simplify the init logic."""
1866 # Set a number of methods that depend on readline to be no-op
1865 # Set a number of methods that depend on readline to be no-op
1867 warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated',
1866 warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated',
1868 DeprecationWarning, stacklevel=2)
1867 DeprecationWarning, stacklevel=2)
1869 self.set_custom_completer = no_op
1868 self.set_custom_completer = no_op
1870
1869
1871 @skip_doctest
1870 @skip_doctest
1872 def set_next_input(self, s, replace=False):
1871 def set_next_input(self, s, replace=False):
1873 """ Sets the 'default' input string for the next command line.
1872 """ Sets the 'default' input string for the next command line.
1874
1873
1875 Example::
1874 Example::
1876
1875
1877 In [1]: _ip.set_next_input("Hello Word")
1876 In [1]: _ip.set_next_input("Hello Word")
1878 In [2]: Hello Word_ # cursor is here
1877 In [2]: Hello Word_ # cursor is here
1879 """
1878 """
1880 self.rl_next_input = py3compat.cast_bytes_py2(s)
1879 self.rl_next_input = py3compat.cast_bytes_py2(s)
1881
1880
1882 def _indent_current_str(self):
1881 def _indent_current_str(self):
1883 """return the current level of indentation as a string"""
1882 """return the current level of indentation as a string"""
1884 return self.input_splitter.indent_spaces * ' '
1883 return self.input_splitter.indent_spaces * ' '
1885
1884
1886 #-------------------------------------------------------------------------
1885 #-------------------------------------------------------------------------
1887 # Things related to text completion
1886 # Things related to text completion
1888 #-------------------------------------------------------------------------
1887 #-------------------------------------------------------------------------
1889
1888
1890 def init_completer(self):
1889 def init_completer(self):
1891 """Initialize the completion machinery.
1890 """Initialize the completion machinery.
1892
1891
1893 This creates completion machinery that can be used by client code,
1892 This creates completion machinery that can be used by client code,
1894 either interactively in-process (typically triggered by the readline
1893 either interactively in-process (typically triggered by the readline
1895 library), programmatically (such as in test suites) or out-of-process
1894 library), programmatically (such as in test suites) or out-of-process
1896 (typically over the network by remote frontends).
1895 (typically over the network by remote frontends).
1897 """
1896 """
1898 from IPython.core.completer import IPCompleter
1897 from IPython.core.completer import IPCompleter
1899 from IPython.core.completerlib import (module_completer,
1898 from IPython.core.completerlib import (module_completer,
1900 magic_run_completer, cd_completer, reset_completer)
1899 magic_run_completer, cd_completer, reset_completer)
1901
1900
1902 self.Completer = IPCompleter(shell=self,
1901 self.Completer = IPCompleter(shell=self,
1903 namespace=self.user_ns,
1902 namespace=self.user_ns,
1904 global_namespace=self.user_global_ns,
1903 global_namespace=self.user_global_ns,
1905 parent=self,
1904 parent=self,
1906 )
1905 )
1907 self.configurables.append(self.Completer)
1906 self.configurables.append(self.Completer)
1908
1907
1909 # Add custom completers to the basic ones built into IPCompleter
1908 # Add custom completers to the basic ones built into IPCompleter
1910 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1909 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1911 self.strdispatchers['complete_command'] = sdisp
1910 self.strdispatchers['complete_command'] = sdisp
1912 self.Completer.custom_completers = sdisp
1911 self.Completer.custom_completers = sdisp
1913
1912
1914 self.set_hook('complete_command', module_completer, str_key = 'import')
1913 self.set_hook('complete_command', module_completer, str_key = 'import')
1915 self.set_hook('complete_command', module_completer, str_key = 'from')
1914 self.set_hook('complete_command', module_completer, str_key = 'from')
1916 self.set_hook('complete_command', module_completer, str_key = '%aimport')
1915 self.set_hook('complete_command', module_completer, str_key = '%aimport')
1917 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
1916 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
1918 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1917 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1919 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1918 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1920
1919
1921
1920
1922 def complete(self, text, line=None, cursor_pos=None):
1921 def complete(self, text, line=None, cursor_pos=None):
1923 """Return the completed text and a list of completions.
1922 """Return the completed text and a list of completions.
1924
1923
1925 Parameters
1924 Parameters
1926 ----------
1925 ----------
1927
1926
1928 text : string
1927 text : string
1929 A string of text to be completed on. It can be given as empty and
1928 A string of text to be completed on. It can be given as empty and
1930 instead a line/position pair are given. In this case, the
1929 instead a line/position pair are given. In this case, the
1931 completer itself will split the line like readline does.
1930 completer itself will split the line like readline does.
1932
1931
1933 line : string, optional
1932 line : string, optional
1934 The complete line that text is part of.
1933 The complete line that text is part of.
1935
1934
1936 cursor_pos : int, optional
1935 cursor_pos : int, optional
1937 The position of the cursor on the input line.
1936 The position of the cursor on the input line.
1938
1937
1939 Returns
1938 Returns
1940 -------
1939 -------
1941 text : string
1940 text : string
1942 The actual text that was completed.
1941 The actual text that was completed.
1943
1942
1944 matches : list
1943 matches : list
1945 A sorted list with all possible completions.
1944 A sorted list with all possible completions.
1946
1945
1947 The optional arguments allow the completion to take more context into
1946 The optional arguments allow the completion to take more context into
1948 account, and are part of the low-level completion API.
1947 account, and are part of the low-level completion API.
1949
1948
1950 This is a wrapper around the completion mechanism, similar to what
1949 This is a wrapper around the completion mechanism, similar to what
1951 readline does at the command line when the TAB key is hit. By
1950 readline does at the command line when the TAB key is hit. By
1952 exposing it as a method, it can be used by other non-readline
1951 exposing it as a method, it can be used by other non-readline
1953 environments (such as GUIs) for text completion.
1952 environments (such as GUIs) for text completion.
1954
1953
1955 Simple usage example:
1954 Simple usage example:
1956
1955
1957 In [1]: x = 'hello'
1956 In [1]: x = 'hello'
1958
1957
1959 In [2]: _ip.complete('x.l')
1958 In [2]: _ip.complete('x.l')
1960 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
1959 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
1961 """
1960 """
1962
1961
1963 # Inject names into __builtin__ so we can complete on the added names.
1962 # Inject names into __builtin__ so we can complete on the added names.
1964 with self.builtin_trap:
1963 with self.builtin_trap:
1965 return self.Completer.complete(text, line, cursor_pos)
1964 return self.Completer.complete(text, line, cursor_pos)
1966
1965
1967 def set_custom_completer(self, completer, pos=0):
1966 def set_custom_completer(self, completer, pos=0):
1968 """Adds a new custom completer function.
1967 """Adds a new custom completer function.
1969
1968
1970 The position argument (defaults to 0) is the index in the completers
1969 The position argument (defaults to 0) is the index in the completers
1971 list where you want the completer to be inserted."""
1970 list where you want the completer to be inserted."""
1972
1971
1973 newcomp = types.MethodType(completer,self.Completer)
1972 newcomp = types.MethodType(completer,self.Completer)
1974 self.Completer.matchers.insert(pos,newcomp)
1973 self.Completer.matchers.insert(pos,newcomp)
1975
1974
1976 def set_completer_frame(self, frame=None):
1975 def set_completer_frame(self, frame=None):
1977 """Set the frame of the completer."""
1976 """Set the frame of the completer."""
1978 if frame:
1977 if frame:
1979 self.Completer.namespace = frame.f_locals
1978 self.Completer.namespace = frame.f_locals
1980 self.Completer.global_namespace = frame.f_globals
1979 self.Completer.global_namespace = frame.f_globals
1981 else:
1980 else:
1982 self.Completer.namespace = self.user_ns
1981 self.Completer.namespace = self.user_ns
1983 self.Completer.global_namespace = self.user_global_ns
1982 self.Completer.global_namespace = self.user_global_ns
1984
1983
1985 #-------------------------------------------------------------------------
1984 #-------------------------------------------------------------------------
1986 # Things related to magics
1985 # Things related to magics
1987 #-------------------------------------------------------------------------
1986 #-------------------------------------------------------------------------
1988
1987
1989 def init_magics(self):
1988 def init_magics(self):
1990 from IPython.core import magics as m
1989 from IPython.core import magics as m
1991 self.magics_manager = magic.MagicsManager(shell=self,
1990 self.magics_manager = magic.MagicsManager(shell=self,
1992 parent=self,
1991 parent=self,
1993 user_magics=m.UserMagics(self))
1992 user_magics=m.UserMagics(self))
1994 self.configurables.append(self.magics_manager)
1993 self.configurables.append(self.magics_manager)
1995
1994
1996 # Expose as public API from the magics manager
1995 # Expose as public API from the magics manager
1997 self.register_magics = self.magics_manager.register
1996 self.register_magics = self.magics_manager.register
1998
1997
1999 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
1998 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2000 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
1999 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2001 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2000 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2002 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2001 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2003 )
2002 )
2004
2003
2005 # Register Magic Aliases
2004 # Register Magic Aliases
2006 mman = self.magics_manager
2005 mman = self.magics_manager
2007 # FIXME: magic aliases should be defined by the Magics classes
2006 # FIXME: magic aliases should be defined by the Magics classes
2008 # or in MagicsManager, not here
2007 # or in MagicsManager, not here
2009 mman.register_alias('ed', 'edit')
2008 mman.register_alias('ed', 'edit')
2010 mman.register_alias('hist', 'history')
2009 mman.register_alias('hist', 'history')
2011 mman.register_alias('rep', 'recall')
2010 mman.register_alias('rep', 'recall')
2012 mman.register_alias('SVG', 'svg', 'cell')
2011 mman.register_alias('SVG', 'svg', 'cell')
2013 mman.register_alias('HTML', 'html', 'cell')
2012 mman.register_alias('HTML', 'html', 'cell')
2014 mman.register_alias('file', 'writefile', 'cell')
2013 mman.register_alias('file', 'writefile', 'cell')
2015
2014
2016 # FIXME: Move the color initialization to the DisplayHook, which
2015 # FIXME: Move the color initialization to the DisplayHook, which
2017 # should be split into a prompt manager and displayhook. We probably
2016 # should be split into a prompt manager and displayhook. We probably
2018 # even need a centralize colors management object.
2017 # even need a centralize colors management object.
2019 self.magic('colors %s' % self.colors)
2018 self.magic('colors %s' % self.colors)
2020
2019
2021 # Defined here so that it's included in the documentation
2020 # Defined here so that it's included in the documentation
2022 @functools.wraps(magic.MagicsManager.register_function)
2021 @functools.wraps(magic.MagicsManager.register_function)
2023 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2022 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2024 self.magics_manager.register_function(func,
2023 self.magics_manager.register_function(func,
2025 magic_kind=magic_kind, magic_name=magic_name)
2024 magic_kind=magic_kind, magic_name=magic_name)
2026
2025
2027 def run_line_magic(self, magic_name, line):
2026 def run_line_magic(self, magic_name, line):
2028 """Execute the given line magic.
2027 """Execute the given line magic.
2029
2028
2030 Parameters
2029 Parameters
2031 ----------
2030 ----------
2032 magic_name : str
2031 magic_name : str
2033 Name of the desired magic function, without '%' prefix.
2032 Name of the desired magic function, without '%' prefix.
2034
2033
2035 line : str
2034 line : str
2036 The rest of the input line as a single string.
2035 The rest of the input line as a single string.
2037 """
2036 """
2038 fn = self.find_line_magic(magic_name)
2037 fn = self.find_line_magic(magic_name)
2039 if fn is None:
2038 if fn is None:
2040 cm = self.find_cell_magic(magic_name)
2039 cm = self.find_cell_magic(magic_name)
2041 etpl = "Line magic function `%%%s` not found%s."
2040 etpl = "Line magic function `%%%s` not found%s."
2042 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2041 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2043 'did you mean that instead?)' % magic_name )
2042 'did you mean that instead?)' % magic_name )
2044 error(etpl % (magic_name, extra))
2043 error(etpl % (magic_name, extra))
2045 else:
2044 else:
2046 # Note: this is the distance in the stack to the user's frame.
2045 # Note: this is the distance in the stack to the user's frame.
2047 # This will need to be updated if the internal calling logic gets
2046 # This will need to be updated if the internal calling logic gets
2048 # refactored, or else we'll be expanding the wrong variables.
2047 # refactored, or else we'll be expanding the wrong variables.
2049 stack_depth = 2
2048 stack_depth = 2
2050 magic_arg_s = self.var_expand(line, stack_depth)
2049 magic_arg_s = self.var_expand(line, stack_depth)
2051 # Put magic args in a list so we can call with f(*a) syntax
2050 # Put magic args in a list so we can call with f(*a) syntax
2052 args = [magic_arg_s]
2051 args = [magic_arg_s]
2053 kwargs = {}
2052 kwargs = {}
2054 # Grab local namespace if we need it:
2053 # Grab local namespace if we need it:
2055 if getattr(fn, "needs_local_scope", False):
2054 if getattr(fn, "needs_local_scope", False):
2056 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2055 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2057 with self.builtin_trap:
2056 with self.builtin_trap:
2058 result = fn(*args,**kwargs)
2057 result = fn(*args,**kwargs)
2059 return result
2058 return result
2060
2059
2061 def run_cell_magic(self, magic_name, line, cell):
2060 def run_cell_magic(self, magic_name, line, cell):
2062 """Execute the given cell magic.
2061 """Execute the given cell magic.
2063
2062
2064 Parameters
2063 Parameters
2065 ----------
2064 ----------
2066 magic_name : str
2065 magic_name : str
2067 Name of the desired magic function, without '%' prefix.
2066 Name of the desired magic function, without '%' prefix.
2068
2067
2069 line : str
2068 line : str
2070 The rest of the first input line as a single string.
2069 The rest of the first input line as a single string.
2071
2070
2072 cell : str
2071 cell : str
2073 The body of the cell as a (possibly multiline) string.
2072 The body of the cell as a (possibly multiline) string.
2074 """
2073 """
2075 fn = self.find_cell_magic(magic_name)
2074 fn = self.find_cell_magic(magic_name)
2076 if fn is None:
2075 if fn is None:
2077 lm = self.find_line_magic(magic_name)
2076 lm = self.find_line_magic(magic_name)
2078 etpl = "Cell magic `%%{0}` not found{1}."
2077 etpl = "Cell magic `%%{0}` not found{1}."
2079 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2078 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2080 'did you mean that instead?)'.format(magic_name))
2079 'did you mean that instead?)'.format(magic_name))
2081 error(etpl.format(magic_name, extra))
2080 error(etpl.format(magic_name, extra))
2082 elif cell == '':
2081 elif cell == '':
2083 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2082 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2084 if self.find_line_magic(magic_name) is not None:
2083 if self.find_line_magic(magic_name) is not None:
2085 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2084 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2086 raise UsageError(message)
2085 raise UsageError(message)
2087 else:
2086 else:
2088 # Note: this is the distance in the stack to the user's frame.
2087 # Note: this is the distance in the stack to the user's frame.
2089 # This will need to be updated if the internal calling logic gets
2088 # This will need to be updated if the internal calling logic gets
2090 # refactored, or else we'll be expanding the wrong variables.
2089 # refactored, or else we'll be expanding the wrong variables.
2091 stack_depth = 2
2090 stack_depth = 2
2092 magic_arg_s = self.var_expand(line, stack_depth)
2091 magic_arg_s = self.var_expand(line, stack_depth)
2093 with self.builtin_trap:
2092 with self.builtin_trap:
2094 result = fn(magic_arg_s, cell)
2093 result = fn(magic_arg_s, cell)
2095 return result
2094 return result
2096
2095
2097 def find_line_magic(self, magic_name):
2096 def find_line_magic(self, magic_name):
2098 """Find and return a line magic by name.
2097 """Find and return a line magic by name.
2099
2098
2100 Returns None if the magic isn't found."""
2099 Returns None if the magic isn't found."""
2101 return self.magics_manager.magics['line'].get(magic_name)
2100 return self.magics_manager.magics['line'].get(magic_name)
2102
2101
2103 def find_cell_magic(self, magic_name):
2102 def find_cell_magic(self, magic_name):
2104 """Find and return a cell magic by name.
2103 """Find and return a cell magic by name.
2105
2104
2106 Returns None if the magic isn't found."""
2105 Returns None if the magic isn't found."""
2107 return self.magics_manager.magics['cell'].get(magic_name)
2106 return self.magics_manager.magics['cell'].get(magic_name)
2108
2107
2109 def find_magic(self, magic_name, magic_kind='line'):
2108 def find_magic(self, magic_name, magic_kind='line'):
2110 """Find and return a magic of the given type by name.
2109 """Find and return a magic of the given type by name.
2111
2110
2112 Returns None if the magic isn't found."""
2111 Returns None if the magic isn't found."""
2113 return self.magics_manager.magics[magic_kind].get(magic_name)
2112 return self.magics_manager.magics[magic_kind].get(magic_name)
2114
2113
2115 def magic(self, arg_s):
2114 def magic(self, arg_s):
2116 """DEPRECATED. Use run_line_magic() instead.
2115 """DEPRECATED. Use run_line_magic() instead.
2117
2116
2118 Call a magic function by name.
2117 Call a magic function by name.
2119
2118
2120 Input: a string containing the name of the magic function to call and
2119 Input: a string containing the name of the magic function to call and
2121 any additional arguments to be passed to the magic.
2120 any additional arguments to be passed to the magic.
2122
2121
2123 magic('name -opt foo bar') is equivalent to typing at the ipython
2122 magic('name -opt foo bar') is equivalent to typing at the ipython
2124 prompt:
2123 prompt:
2125
2124
2126 In[1]: %name -opt foo bar
2125 In[1]: %name -opt foo bar
2127
2126
2128 To call a magic without arguments, simply use magic('name').
2127 To call a magic without arguments, simply use magic('name').
2129
2128
2130 This provides a proper Python function to call IPython's magics in any
2129 This provides a proper Python function to call IPython's magics in any
2131 valid Python code you can type at the interpreter, including loops and
2130 valid Python code you can type at the interpreter, including loops and
2132 compound statements.
2131 compound statements.
2133 """
2132 """
2134 # TODO: should we issue a loud deprecation warning here?
2133 # TODO: should we issue a loud deprecation warning here?
2135 magic_name, _, magic_arg_s = arg_s.partition(' ')
2134 magic_name, _, magic_arg_s = arg_s.partition(' ')
2136 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2135 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2137 return self.run_line_magic(magic_name, magic_arg_s)
2136 return self.run_line_magic(magic_name, magic_arg_s)
2138
2137
2139 #-------------------------------------------------------------------------
2138 #-------------------------------------------------------------------------
2140 # Things related to macros
2139 # Things related to macros
2141 #-------------------------------------------------------------------------
2140 #-------------------------------------------------------------------------
2142
2141
2143 def define_macro(self, name, themacro):
2142 def define_macro(self, name, themacro):
2144 """Define a new macro
2143 """Define a new macro
2145
2144
2146 Parameters
2145 Parameters
2147 ----------
2146 ----------
2148 name : str
2147 name : str
2149 The name of the macro.
2148 The name of the macro.
2150 themacro : str or Macro
2149 themacro : str or Macro
2151 The action to do upon invoking the macro. If a string, a new
2150 The action to do upon invoking the macro. If a string, a new
2152 Macro object is created by passing the string to it.
2151 Macro object is created by passing the string to it.
2153 """
2152 """
2154
2153
2155 from IPython.core import macro
2154 from IPython.core import macro
2156
2155
2157 if isinstance(themacro, string_types):
2156 if isinstance(themacro, str):
2158 themacro = macro.Macro(themacro)
2157 themacro = macro.Macro(themacro)
2159 if not isinstance(themacro, macro.Macro):
2158 if not isinstance(themacro, macro.Macro):
2160 raise ValueError('A macro must be a string or a Macro instance.')
2159 raise ValueError('A macro must be a string or a Macro instance.')
2161 self.user_ns[name] = themacro
2160 self.user_ns[name] = themacro
2162
2161
2163 #-------------------------------------------------------------------------
2162 #-------------------------------------------------------------------------
2164 # Things related to the running of system commands
2163 # Things related to the running of system commands
2165 #-------------------------------------------------------------------------
2164 #-------------------------------------------------------------------------
2166
2165
2167 def system_piped(self, cmd):
2166 def system_piped(self, cmd):
2168 """Call the given cmd in a subprocess, piping stdout/err
2167 """Call the given cmd in a subprocess, piping stdout/err
2169
2168
2170 Parameters
2169 Parameters
2171 ----------
2170 ----------
2172 cmd : str
2171 cmd : str
2173 Command to execute (can not end in '&', as background processes are
2172 Command to execute (can not end in '&', as background processes are
2174 not supported. Should not be a command that expects input
2173 not supported. Should not be a command that expects input
2175 other than simple text.
2174 other than simple text.
2176 """
2175 """
2177 if cmd.rstrip().endswith('&'):
2176 if cmd.rstrip().endswith('&'):
2178 # this is *far* from a rigorous test
2177 # this is *far* from a rigorous test
2179 # We do not support backgrounding processes because we either use
2178 # We do not support backgrounding processes because we either use
2180 # pexpect or pipes to read from. Users can always just call
2179 # pexpect or pipes to read from. Users can always just call
2181 # os.system() or use ip.system=ip.system_raw
2180 # os.system() or use ip.system=ip.system_raw
2182 # if they really want a background process.
2181 # if they really want a background process.
2183 raise OSError("Background processes not supported.")
2182 raise OSError("Background processes not supported.")
2184
2183
2185 # we explicitly do NOT return the subprocess status code, because
2184 # we explicitly do NOT return the subprocess status code, because
2186 # a non-None value would trigger :func:`sys.displayhook` calls.
2185 # a non-None value would trigger :func:`sys.displayhook` calls.
2187 # Instead, we store the exit_code in user_ns.
2186 # Instead, we store the exit_code in user_ns.
2188 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2187 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2189
2188
2190 def system_raw(self, cmd):
2189 def system_raw(self, cmd):
2191 """Call the given cmd in a subprocess using os.system on Windows or
2190 """Call the given cmd in a subprocess using os.system on Windows or
2192 subprocess.call using the system shell on other platforms.
2191 subprocess.call using the system shell on other platforms.
2193
2192
2194 Parameters
2193 Parameters
2195 ----------
2194 ----------
2196 cmd : str
2195 cmd : str
2197 Command to execute.
2196 Command to execute.
2198 """
2197 """
2199 cmd = self.var_expand(cmd, depth=1)
2198 cmd = self.var_expand(cmd, depth=1)
2200 # protect os.system from UNC paths on Windows, which it can't handle:
2199 # protect os.system from UNC paths on Windows, which it can't handle:
2201 if sys.platform == 'win32':
2200 if sys.platform == 'win32':
2202 from IPython.utils._process_win32 import AvoidUNCPath
2201 from IPython.utils._process_win32 import AvoidUNCPath
2203 with AvoidUNCPath() as path:
2202 with AvoidUNCPath() as path:
2204 if path is not None:
2203 if path is not None:
2205 cmd = '"pushd %s &&"%s' % (path, cmd)
2204 cmd = '"pushd %s &&"%s' % (path, cmd)
2206 cmd = py3compat.unicode_to_str(cmd)
2207 try:
2205 try:
2208 ec = os.system(cmd)
2206 ec = os.system(cmd)
2209 except KeyboardInterrupt:
2207 except KeyboardInterrupt:
2210 print('\n' + self.get_exception_only(), file=sys.stderr)
2208 print('\n' + self.get_exception_only(), file=sys.stderr)
2211 ec = -2
2209 ec = -2
2212 else:
2210 else:
2213 cmd = py3compat.unicode_to_str(cmd)
2214 # For posix the result of the subprocess.call() below is an exit
2211 # For posix the result of the subprocess.call() below is an exit
2215 # code, which by convention is zero for success, positive for
2212 # code, which by convention is zero for success, positive for
2216 # program failure. Exit codes above 128 are reserved for signals,
2213 # program failure. Exit codes above 128 are reserved for signals,
2217 # and the formula for converting a signal to an exit code is usually
2214 # and the formula for converting a signal to an exit code is usually
2218 # signal_number+128. To more easily differentiate between exit
2215 # signal_number+128. To more easily differentiate between exit
2219 # codes and signals, ipython uses negative numbers. For instance
2216 # codes and signals, ipython uses negative numbers. For instance
2220 # since control-c is signal 2 but exit code 130, ipython's
2217 # since control-c is signal 2 but exit code 130, ipython's
2221 # _exit_code variable will read -2. Note that some shells like
2218 # _exit_code variable will read -2. Note that some shells like
2222 # csh and fish don't follow sh/bash conventions for exit codes.
2219 # csh and fish don't follow sh/bash conventions for exit codes.
2223 executable = os.environ.get('SHELL', None)
2220 executable = os.environ.get('SHELL', None)
2224 try:
2221 try:
2225 # Use env shell instead of default /bin/sh
2222 # Use env shell instead of default /bin/sh
2226 ec = subprocess.call(cmd, shell=True, executable=executable)
2223 ec = subprocess.call(cmd, shell=True, executable=executable)
2227 except KeyboardInterrupt:
2224 except KeyboardInterrupt:
2228 # intercept control-C; a long traceback is not useful here
2225 # intercept control-C; a long traceback is not useful here
2229 print('\n' + self.get_exception_only(), file=sys.stderr)
2226 print('\n' + self.get_exception_only(), file=sys.stderr)
2230 ec = 130
2227 ec = 130
2231 if ec > 128:
2228 if ec > 128:
2232 ec = -(ec - 128)
2229 ec = -(ec - 128)
2233
2230
2234 # We explicitly do NOT return the subprocess status code, because
2231 # We explicitly do NOT return the subprocess status code, because
2235 # a non-None value would trigger :func:`sys.displayhook` calls.
2232 # a non-None value would trigger :func:`sys.displayhook` calls.
2236 # Instead, we store the exit_code in user_ns. Note the semantics
2233 # Instead, we store the exit_code in user_ns. Note the semantics
2237 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2234 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2238 # but raising SystemExit(_exit_code) will give status 254!
2235 # but raising SystemExit(_exit_code) will give status 254!
2239 self.user_ns['_exit_code'] = ec
2236 self.user_ns['_exit_code'] = ec
2240
2237
2241 # use piped system by default, because it is better behaved
2238 # use piped system by default, because it is better behaved
2242 system = system_piped
2239 system = system_piped
2243
2240
2244 def getoutput(self, cmd, split=True, depth=0):
2241 def getoutput(self, cmd, split=True, depth=0):
2245 """Get output (possibly including stderr) from a subprocess.
2242 """Get output (possibly including stderr) from a subprocess.
2246
2243
2247 Parameters
2244 Parameters
2248 ----------
2245 ----------
2249 cmd : str
2246 cmd : str
2250 Command to execute (can not end in '&', as background processes are
2247 Command to execute (can not end in '&', as background processes are
2251 not supported.
2248 not supported.
2252 split : bool, optional
2249 split : bool, optional
2253 If True, split the output into an IPython SList. Otherwise, an
2250 If True, split the output into an IPython SList. Otherwise, an
2254 IPython LSString is returned. These are objects similar to normal
2251 IPython LSString is returned. These are objects similar to normal
2255 lists and strings, with a few convenience attributes for easier
2252 lists and strings, with a few convenience attributes for easier
2256 manipulation of line-based output. You can use '?' on them for
2253 manipulation of line-based output. You can use '?' on them for
2257 details.
2254 details.
2258 depth : int, optional
2255 depth : int, optional
2259 How many frames above the caller are the local variables which should
2256 How many frames above the caller are the local variables which should
2260 be expanded in the command string? The default (0) assumes that the
2257 be expanded in the command string? The default (0) assumes that the
2261 expansion variables are in the stack frame calling this function.
2258 expansion variables are in the stack frame calling this function.
2262 """
2259 """
2263 if cmd.rstrip().endswith('&'):
2260 if cmd.rstrip().endswith('&'):
2264 # this is *far* from a rigorous test
2261 # this is *far* from a rigorous test
2265 raise OSError("Background processes not supported.")
2262 raise OSError("Background processes not supported.")
2266 out = getoutput(self.var_expand(cmd, depth=depth+1))
2263 out = getoutput(self.var_expand(cmd, depth=depth+1))
2267 if split:
2264 if split:
2268 out = SList(out.splitlines())
2265 out = SList(out.splitlines())
2269 else:
2266 else:
2270 out = LSString(out)
2267 out = LSString(out)
2271 return out
2268 return out
2272
2269
2273 #-------------------------------------------------------------------------
2270 #-------------------------------------------------------------------------
2274 # Things related to aliases
2271 # Things related to aliases
2275 #-------------------------------------------------------------------------
2272 #-------------------------------------------------------------------------
2276
2273
2277 def init_alias(self):
2274 def init_alias(self):
2278 self.alias_manager = AliasManager(shell=self, parent=self)
2275 self.alias_manager = AliasManager(shell=self, parent=self)
2279 self.configurables.append(self.alias_manager)
2276 self.configurables.append(self.alias_manager)
2280
2277
2281 #-------------------------------------------------------------------------
2278 #-------------------------------------------------------------------------
2282 # Things related to extensions
2279 # Things related to extensions
2283 #-------------------------------------------------------------------------
2280 #-------------------------------------------------------------------------
2284
2281
2285 def init_extension_manager(self):
2282 def init_extension_manager(self):
2286 self.extension_manager = ExtensionManager(shell=self, parent=self)
2283 self.extension_manager = ExtensionManager(shell=self, parent=self)
2287 self.configurables.append(self.extension_manager)
2284 self.configurables.append(self.extension_manager)
2288
2285
2289 #-------------------------------------------------------------------------
2286 #-------------------------------------------------------------------------
2290 # Things related to payloads
2287 # Things related to payloads
2291 #-------------------------------------------------------------------------
2288 #-------------------------------------------------------------------------
2292
2289
2293 def init_payload(self):
2290 def init_payload(self):
2294 self.payload_manager = PayloadManager(parent=self)
2291 self.payload_manager = PayloadManager(parent=self)
2295 self.configurables.append(self.payload_manager)
2292 self.configurables.append(self.payload_manager)
2296
2293
2297 #-------------------------------------------------------------------------
2294 #-------------------------------------------------------------------------
2298 # Things related to the prefilter
2295 # Things related to the prefilter
2299 #-------------------------------------------------------------------------
2296 #-------------------------------------------------------------------------
2300
2297
2301 def init_prefilter(self):
2298 def init_prefilter(self):
2302 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2299 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2303 self.configurables.append(self.prefilter_manager)
2300 self.configurables.append(self.prefilter_manager)
2304 # Ultimately this will be refactored in the new interpreter code, but
2301 # Ultimately this will be refactored in the new interpreter code, but
2305 # for now, we should expose the main prefilter method (there's legacy
2302 # for now, we should expose the main prefilter method (there's legacy
2306 # code out there that may rely on this).
2303 # code out there that may rely on this).
2307 self.prefilter = self.prefilter_manager.prefilter_lines
2304 self.prefilter = self.prefilter_manager.prefilter_lines
2308
2305
2309 def auto_rewrite_input(self, cmd):
2306 def auto_rewrite_input(self, cmd):
2310 """Print to the screen the rewritten form of the user's command.
2307 """Print to the screen the rewritten form of the user's command.
2311
2308
2312 This shows visual feedback by rewriting input lines that cause
2309 This shows visual feedback by rewriting input lines that cause
2313 automatic calling to kick in, like::
2310 automatic calling to kick in, like::
2314
2311
2315 /f x
2312 /f x
2316
2313
2317 into::
2314 into::
2318
2315
2319 ------> f(x)
2316 ------> f(x)
2320
2317
2321 after the user's input prompt. This helps the user understand that the
2318 after the user's input prompt. This helps the user understand that the
2322 input line was transformed automatically by IPython.
2319 input line was transformed automatically by IPython.
2323 """
2320 """
2324 if not self.show_rewritten_input:
2321 if not self.show_rewritten_input:
2325 return
2322 return
2326
2323
2327 # This is overridden in TerminalInteractiveShell to use fancy prompts
2324 # This is overridden in TerminalInteractiveShell to use fancy prompts
2328 print("------> " + cmd)
2325 print("------> " + cmd)
2329
2326
2330 #-------------------------------------------------------------------------
2327 #-------------------------------------------------------------------------
2331 # Things related to extracting values/expressions from kernel and user_ns
2328 # Things related to extracting values/expressions from kernel and user_ns
2332 #-------------------------------------------------------------------------
2329 #-------------------------------------------------------------------------
2333
2330
2334 def _user_obj_error(self):
2331 def _user_obj_error(self):
2335 """return simple exception dict
2332 """return simple exception dict
2336
2333
2337 for use in user_expressions
2334 for use in user_expressions
2338 """
2335 """
2339
2336
2340 etype, evalue, tb = self._get_exc_info()
2337 etype, evalue, tb = self._get_exc_info()
2341 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2338 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2342
2339
2343 exc_info = {
2340 exc_info = {
2344 u'status' : 'error',
2341 u'status' : 'error',
2345 u'traceback' : stb,
2342 u'traceback' : stb,
2346 u'ename' : unicode_type(etype.__name__),
2343 u'ename' : etype.__name__,
2347 u'evalue' : py3compat.safe_unicode(evalue),
2344 u'evalue' : py3compat.safe_unicode(evalue),
2348 }
2345 }
2349
2346
2350 return exc_info
2347 return exc_info
2351
2348
2352 def _format_user_obj(self, obj):
2349 def _format_user_obj(self, obj):
2353 """format a user object to display dict
2350 """format a user object to display dict
2354
2351
2355 for use in user_expressions
2352 for use in user_expressions
2356 """
2353 """
2357
2354
2358 data, md = self.display_formatter.format(obj)
2355 data, md = self.display_formatter.format(obj)
2359 value = {
2356 value = {
2360 'status' : 'ok',
2357 'status' : 'ok',
2361 'data' : data,
2358 'data' : data,
2362 'metadata' : md,
2359 'metadata' : md,
2363 }
2360 }
2364 return value
2361 return value
2365
2362
2366 def user_expressions(self, expressions):
2363 def user_expressions(self, expressions):
2367 """Evaluate a dict of expressions in the user's namespace.
2364 """Evaluate a dict of expressions in the user's namespace.
2368
2365
2369 Parameters
2366 Parameters
2370 ----------
2367 ----------
2371 expressions : dict
2368 expressions : dict
2372 A dict with string keys and string values. The expression values
2369 A dict with string keys and string values. The expression values
2373 should be valid Python expressions, each of which will be evaluated
2370 should be valid Python expressions, each of which will be evaluated
2374 in the user namespace.
2371 in the user namespace.
2375
2372
2376 Returns
2373 Returns
2377 -------
2374 -------
2378 A dict, keyed like the input expressions dict, with the rich mime-typed
2375 A dict, keyed like the input expressions dict, with the rich mime-typed
2379 display_data of each value.
2376 display_data of each value.
2380 """
2377 """
2381 out = {}
2378 out = {}
2382 user_ns = self.user_ns
2379 user_ns = self.user_ns
2383 global_ns = self.user_global_ns
2380 global_ns = self.user_global_ns
2384
2381
2385 for key, expr in iteritems(expressions):
2382 for key, expr in expressions.items():
2386 try:
2383 try:
2387 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2384 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2388 except:
2385 except:
2389 value = self._user_obj_error()
2386 value = self._user_obj_error()
2390 out[key] = value
2387 out[key] = value
2391 return out
2388 return out
2392
2389
2393 #-------------------------------------------------------------------------
2390 #-------------------------------------------------------------------------
2394 # Things related to the running of code
2391 # Things related to the running of code
2395 #-------------------------------------------------------------------------
2392 #-------------------------------------------------------------------------
2396
2393
2397 def ex(self, cmd):
2394 def ex(self, cmd):
2398 """Execute a normal python statement in user namespace."""
2395 """Execute a normal python statement in user namespace."""
2399 with self.builtin_trap:
2396 with self.builtin_trap:
2400 exec(cmd, self.user_global_ns, self.user_ns)
2397 exec(cmd, self.user_global_ns, self.user_ns)
2401
2398
2402 def ev(self, expr):
2399 def ev(self, expr):
2403 """Evaluate python expression expr in user namespace.
2400 """Evaluate python expression expr in user namespace.
2404
2401
2405 Returns the result of evaluation
2402 Returns the result of evaluation
2406 """
2403 """
2407 with self.builtin_trap:
2404 with self.builtin_trap:
2408 return eval(expr, self.user_global_ns, self.user_ns)
2405 return eval(expr, self.user_global_ns, self.user_ns)
2409
2406
2410 def safe_execfile(self, fname, *where, **kw):
2407 def safe_execfile(self, fname, *where, **kw):
2411 """A safe version of the builtin execfile().
2408 """A safe version of the builtin execfile().
2412
2409
2413 This version will never throw an exception, but instead print
2410 This version will never throw an exception, but instead print
2414 helpful error messages to the screen. This only works on pure
2411 helpful error messages to the screen. This only works on pure
2415 Python files with the .py extension.
2412 Python files with the .py extension.
2416
2413
2417 Parameters
2414 Parameters
2418 ----------
2415 ----------
2419 fname : string
2416 fname : string
2420 The name of the file to be executed.
2417 The name of the file to be executed.
2421 where : tuple
2418 where : tuple
2422 One or two namespaces, passed to execfile() as (globals,locals).
2419 One or two namespaces, passed to execfile() as (globals,locals).
2423 If only one is given, it is passed as both.
2420 If only one is given, it is passed as both.
2424 exit_ignore : bool (False)
2421 exit_ignore : bool (False)
2425 If True, then silence SystemExit for non-zero status (it is always
2422 If True, then silence SystemExit for non-zero status (it is always
2426 silenced for zero status, as it is so common).
2423 silenced for zero status, as it is so common).
2427 raise_exceptions : bool (False)
2424 raise_exceptions : bool (False)
2428 If True raise exceptions everywhere. Meant for testing.
2425 If True raise exceptions everywhere. Meant for testing.
2429 shell_futures : bool (False)
2426 shell_futures : bool (False)
2430 If True, the code will share future statements with the interactive
2427 If True, the code will share future statements with the interactive
2431 shell. It will both be affected by previous __future__ imports, and
2428 shell. It will both be affected by previous __future__ imports, and
2432 any __future__ imports in the code will affect the shell. If False,
2429 any __future__ imports in the code will affect the shell. If False,
2433 __future__ imports are not shared in either direction.
2430 __future__ imports are not shared in either direction.
2434
2431
2435 """
2432 """
2436 kw.setdefault('exit_ignore', False)
2433 kw.setdefault('exit_ignore', False)
2437 kw.setdefault('raise_exceptions', False)
2434 kw.setdefault('raise_exceptions', False)
2438 kw.setdefault('shell_futures', False)
2435 kw.setdefault('shell_futures', False)
2439
2436
2440 fname = os.path.abspath(os.path.expanduser(fname))
2437 fname = os.path.abspath(os.path.expanduser(fname))
2441
2438
2442 # Make sure we can open the file
2439 # Make sure we can open the file
2443 try:
2440 try:
2444 with open(fname):
2441 with open(fname):
2445 pass
2442 pass
2446 except:
2443 except:
2447 warn('Could not open file <%s> for safe execution.' % fname)
2444 warn('Could not open file <%s> for safe execution.' % fname)
2448 return
2445 return
2449
2446
2450 # Find things also in current directory. This is needed to mimic the
2447 # Find things also in current directory. This is needed to mimic the
2451 # behavior of running a script from the system command line, where
2448 # behavior of running a script from the system command line, where
2452 # Python inserts the script's directory into sys.path
2449 # Python inserts the script's directory into sys.path
2453 dname = os.path.dirname(fname)
2450 dname = os.path.dirname(fname)
2454
2451
2455 with prepended_to_syspath(dname), self.builtin_trap:
2452 with prepended_to_syspath(dname), self.builtin_trap:
2456 try:
2453 try:
2457 glob, loc = (where + (None, ))[:2]
2454 glob, loc = (where + (None, ))[:2]
2458 py3compat.execfile(
2455 py3compat.execfile(
2459 fname, glob, loc,
2456 fname, glob, loc,
2460 self.compile if kw['shell_futures'] else None)
2457 self.compile if kw['shell_futures'] else None)
2461 except SystemExit as status:
2458 except SystemExit as status:
2462 # If the call was made with 0 or None exit status (sys.exit(0)
2459 # If the call was made with 0 or None exit status (sys.exit(0)
2463 # or sys.exit() ), don't bother showing a traceback, as both of
2460 # or sys.exit() ), don't bother showing a traceback, as both of
2464 # these are considered normal by the OS:
2461 # these are considered normal by the OS:
2465 # > python -c'import sys;sys.exit(0)'; echo $?
2462 # > python -c'import sys;sys.exit(0)'; echo $?
2466 # 0
2463 # 0
2467 # > python -c'import sys;sys.exit()'; echo $?
2464 # > python -c'import sys;sys.exit()'; echo $?
2468 # 0
2465 # 0
2469 # For other exit status, we show the exception unless
2466 # For other exit status, we show the exception unless
2470 # explicitly silenced, but only in short form.
2467 # explicitly silenced, but only in short form.
2471 if status.code:
2468 if status.code:
2472 if kw['raise_exceptions']:
2469 if kw['raise_exceptions']:
2473 raise
2470 raise
2474 if not kw['exit_ignore']:
2471 if not kw['exit_ignore']:
2475 self.showtraceback(exception_only=True)
2472 self.showtraceback(exception_only=True)
2476 except:
2473 except:
2477 if kw['raise_exceptions']:
2474 if kw['raise_exceptions']:
2478 raise
2475 raise
2479 # tb offset is 2 because we wrap execfile
2476 # tb offset is 2 because we wrap execfile
2480 self.showtraceback(tb_offset=2)
2477 self.showtraceback(tb_offset=2)
2481
2478
2482 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2479 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2483 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2480 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2484
2481
2485 Parameters
2482 Parameters
2486 ----------
2483 ----------
2487 fname : str
2484 fname : str
2488 The name of the file to execute. The filename must have a
2485 The name of the file to execute. The filename must have a
2489 .ipy or .ipynb extension.
2486 .ipy or .ipynb extension.
2490 shell_futures : bool (False)
2487 shell_futures : bool (False)
2491 If True, the code will share future statements with the interactive
2488 If True, the code will share future statements with the interactive
2492 shell. It will both be affected by previous __future__ imports, and
2489 shell. It will both be affected by previous __future__ imports, and
2493 any __future__ imports in the code will affect the shell. If False,
2490 any __future__ imports in the code will affect the shell. If False,
2494 __future__ imports are not shared in either direction.
2491 __future__ imports are not shared in either direction.
2495 raise_exceptions : bool (False)
2492 raise_exceptions : bool (False)
2496 If True raise exceptions everywhere. Meant for testing.
2493 If True raise exceptions everywhere. Meant for testing.
2497 """
2494 """
2498 fname = os.path.abspath(os.path.expanduser(fname))
2495 fname = os.path.abspath(os.path.expanduser(fname))
2499
2496
2500 # Make sure we can open the file
2497 # Make sure we can open the file
2501 try:
2498 try:
2502 with open(fname):
2499 with open(fname):
2503 pass
2500 pass
2504 except:
2501 except:
2505 warn('Could not open file <%s> for safe execution.' % fname)
2502 warn('Could not open file <%s> for safe execution.' % fname)
2506 return
2503 return
2507
2504
2508 # Find things also in current directory. This is needed to mimic the
2505 # Find things also in current directory. This is needed to mimic the
2509 # behavior of running a script from the system command line, where
2506 # behavior of running a script from the system command line, where
2510 # Python inserts the script's directory into sys.path
2507 # Python inserts the script's directory into sys.path
2511 dname = os.path.dirname(fname)
2508 dname = os.path.dirname(fname)
2512
2509
2513 def get_cells():
2510 def get_cells():
2514 """generator for sequence of code blocks to run"""
2511 """generator for sequence of code blocks to run"""
2515 if fname.endswith('.ipynb'):
2512 if fname.endswith('.ipynb'):
2516 from nbformat import read
2513 from nbformat import read
2517 with io_open(fname) as f:
2514 with io_open(fname) as f:
2518 nb = read(f, as_version=4)
2515 nb = read(f, as_version=4)
2519 if not nb.cells:
2516 if not nb.cells:
2520 return
2517 return
2521 for cell in nb.cells:
2518 for cell in nb.cells:
2522 if cell.cell_type == 'code':
2519 if cell.cell_type == 'code':
2523 yield cell.source
2520 yield cell.source
2524 else:
2521 else:
2525 with open(fname) as f:
2522 with open(fname) as f:
2526 yield f.read()
2523 yield f.read()
2527
2524
2528 with prepended_to_syspath(dname):
2525 with prepended_to_syspath(dname):
2529 try:
2526 try:
2530 for cell in get_cells():
2527 for cell in get_cells():
2531 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2528 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2532 if raise_exceptions:
2529 if raise_exceptions:
2533 result.raise_error()
2530 result.raise_error()
2534 elif not result.success:
2531 elif not result.success:
2535 break
2532 break
2536 except:
2533 except:
2537 if raise_exceptions:
2534 if raise_exceptions:
2538 raise
2535 raise
2539 self.showtraceback()
2536 self.showtraceback()
2540 warn('Unknown failure executing file: <%s>' % fname)
2537 warn('Unknown failure executing file: <%s>' % fname)
2541
2538
2542 def safe_run_module(self, mod_name, where):
2539 def safe_run_module(self, mod_name, where):
2543 """A safe version of runpy.run_module().
2540 """A safe version of runpy.run_module().
2544
2541
2545 This version will never throw an exception, but instead print
2542 This version will never throw an exception, but instead print
2546 helpful error messages to the screen.
2543 helpful error messages to the screen.
2547
2544
2548 `SystemExit` exceptions with status code 0 or None are ignored.
2545 `SystemExit` exceptions with status code 0 or None are ignored.
2549
2546
2550 Parameters
2547 Parameters
2551 ----------
2548 ----------
2552 mod_name : string
2549 mod_name : string
2553 The name of the module to be executed.
2550 The name of the module to be executed.
2554 where : dict
2551 where : dict
2555 The globals namespace.
2552 The globals namespace.
2556 """
2553 """
2557 try:
2554 try:
2558 try:
2555 try:
2559 where.update(
2556 where.update(
2560 runpy.run_module(str(mod_name), run_name="__main__",
2557 runpy.run_module(str(mod_name), run_name="__main__",
2561 alter_sys=True)
2558 alter_sys=True)
2562 )
2559 )
2563 except SystemExit as status:
2560 except SystemExit as status:
2564 if status.code:
2561 if status.code:
2565 raise
2562 raise
2566 except:
2563 except:
2567 self.showtraceback()
2564 self.showtraceback()
2568 warn('Unknown failure executing module: <%s>' % mod_name)
2565 warn('Unknown failure executing module: <%s>' % mod_name)
2569
2566
2570 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2567 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2571 """Run a complete IPython cell.
2568 """Run a complete IPython cell.
2572
2569
2573 Parameters
2570 Parameters
2574 ----------
2571 ----------
2575 raw_cell : str
2572 raw_cell : str
2576 The code (including IPython code such as %magic functions) to run.
2573 The code (including IPython code such as %magic functions) to run.
2577 store_history : bool
2574 store_history : bool
2578 If True, the raw and translated cell will be stored in IPython's
2575 If True, the raw and translated cell will be stored in IPython's
2579 history. For user code calling back into IPython's machinery, this
2576 history. For user code calling back into IPython's machinery, this
2580 should be set to False.
2577 should be set to False.
2581 silent : bool
2578 silent : bool
2582 If True, avoid side-effects, such as implicit displayhooks and
2579 If True, avoid side-effects, such as implicit displayhooks and
2583 and logging. silent=True forces store_history=False.
2580 and logging. silent=True forces store_history=False.
2584 shell_futures : bool
2581 shell_futures : bool
2585 If True, the code will share future statements with the interactive
2582 If True, the code will share future statements with the interactive
2586 shell. It will both be affected by previous __future__ imports, and
2583 shell. It will both be affected by previous __future__ imports, and
2587 any __future__ imports in the code will affect the shell. If False,
2584 any __future__ imports in the code will affect the shell. If False,
2588 __future__ imports are not shared in either direction.
2585 __future__ imports are not shared in either direction.
2589
2586
2590 Returns
2587 Returns
2591 -------
2588 -------
2592 result : :class:`ExecutionResult`
2589 result : :class:`ExecutionResult`
2593 """
2590 """
2594 result = ExecutionResult()
2591 result = ExecutionResult()
2595
2592
2596 if (not raw_cell) or raw_cell.isspace():
2593 if (not raw_cell) or raw_cell.isspace():
2597 self.last_execution_succeeded = True
2594 self.last_execution_succeeded = True
2598 return result
2595 return result
2599
2596
2600 if silent:
2597 if silent:
2601 store_history = False
2598 store_history = False
2602
2599
2603 if store_history:
2600 if store_history:
2604 result.execution_count = self.execution_count
2601 result.execution_count = self.execution_count
2605
2602
2606 def error_before_exec(value):
2603 def error_before_exec(value):
2607 result.error_before_exec = value
2604 result.error_before_exec = value
2608 self.last_execution_succeeded = False
2605 self.last_execution_succeeded = False
2609 return result
2606 return result
2610
2607
2611 self.events.trigger('pre_execute')
2608 self.events.trigger('pre_execute')
2612 if not silent:
2609 if not silent:
2613 self.events.trigger('pre_run_cell')
2610 self.events.trigger('pre_run_cell')
2614
2611
2615 # If any of our input transformation (input_transformer_manager or
2612 # If any of our input transformation (input_transformer_manager or
2616 # prefilter_manager) raises an exception, we store it in this variable
2613 # prefilter_manager) raises an exception, we store it in this variable
2617 # so that we can display the error after logging the input and storing
2614 # so that we can display the error after logging the input and storing
2618 # it in the history.
2615 # it in the history.
2619 preprocessing_exc_tuple = None
2616 preprocessing_exc_tuple = None
2620 try:
2617 try:
2621 # Static input transformations
2618 # Static input transformations
2622 cell = self.input_transformer_manager.transform_cell(raw_cell)
2619 cell = self.input_transformer_manager.transform_cell(raw_cell)
2623 except SyntaxError:
2620 except SyntaxError:
2624 preprocessing_exc_tuple = sys.exc_info()
2621 preprocessing_exc_tuple = sys.exc_info()
2625 cell = raw_cell # cell has to exist so it can be stored/logged
2622 cell = raw_cell # cell has to exist so it can be stored/logged
2626 else:
2623 else:
2627 if len(cell.splitlines()) == 1:
2624 if len(cell.splitlines()) == 1:
2628 # Dynamic transformations - only applied for single line commands
2625 # Dynamic transformations - only applied for single line commands
2629 with self.builtin_trap:
2626 with self.builtin_trap:
2630 try:
2627 try:
2631 # use prefilter_lines to handle trailing newlines
2628 # use prefilter_lines to handle trailing newlines
2632 # restore trailing newline for ast.parse
2629 # restore trailing newline for ast.parse
2633 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2630 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2634 except Exception:
2631 except Exception:
2635 # don't allow prefilter errors to crash IPython
2632 # don't allow prefilter errors to crash IPython
2636 preprocessing_exc_tuple = sys.exc_info()
2633 preprocessing_exc_tuple = sys.exc_info()
2637
2634
2638 # Store raw and processed history
2635 # Store raw and processed history
2639 if store_history:
2636 if store_history:
2640 self.history_manager.store_inputs(self.execution_count,
2637 self.history_manager.store_inputs(self.execution_count,
2641 cell, raw_cell)
2638 cell, raw_cell)
2642 if not silent:
2639 if not silent:
2643 self.logger.log(cell, raw_cell)
2640 self.logger.log(cell, raw_cell)
2644
2641
2645 # Display the exception if input processing failed.
2642 # Display the exception if input processing failed.
2646 if preprocessing_exc_tuple is not None:
2643 if preprocessing_exc_tuple is not None:
2647 self.showtraceback(preprocessing_exc_tuple)
2644 self.showtraceback(preprocessing_exc_tuple)
2648 if store_history:
2645 if store_history:
2649 self.execution_count += 1
2646 self.execution_count += 1
2650 return error_before_exec(preprocessing_exc_tuple[2])
2647 return error_before_exec(preprocessing_exc_tuple[2])
2651
2648
2652 # Our own compiler remembers the __future__ environment. If we want to
2649 # Our own compiler remembers the __future__ environment. If we want to
2653 # run code with a separate __future__ environment, use the default
2650 # run code with a separate __future__ environment, use the default
2654 # compiler
2651 # compiler
2655 compiler = self.compile if shell_futures else CachingCompiler()
2652 compiler = self.compile if shell_futures else CachingCompiler()
2656
2653
2657 with self.builtin_trap:
2654 with self.builtin_trap:
2658 cell_name = self.compile.cache(cell, self.execution_count)
2655 cell_name = self.compile.cache(cell, self.execution_count)
2659
2656
2660 with self.display_trap:
2657 with self.display_trap:
2661 # Compile to bytecode
2658 # Compile to bytecode
2662 try:
2659 try:
2663 code_ast = compiler.ast_parse(cell, filename=cell_name)
2660 code_ast = compiler.ast_parse(cell, filename=cell_name)
2664 except self.custom_exceptions as e:
2661 except self.custom_exceptions as e:
2665 etype, value, tb = sys.exc_info()
2662 etype, value, tb = sys.exc_info()
2666 self.CustomTB(etype, value, tb)
2663 self.CustomTB(etype, value, tb)
2667 return error_before_exec(e)
2664 return error_before_exec(e)
2668 except IndentationError as e:
2665 except IndentationError as e:
2669 self.showindentationerror()
2666 self.showindentationerror()
2670 if store_history:
2667 if store_history:
2671 self.execution_count += 1
2668 self.execution_count += 1
2672 return error_before_exec(e)
2669 return error_before_exec(e)
2673 except (OverflowError, SyntaxError, ValueError, TypeError,
2670 except (OverflowError, SyntaxError, ValueError, TypeError,
2674 MemoryError) as e:
2671 MemoryError) as e:
2675 self.showsyntaxerror()
2672 self.showsyntaxerror()
2676 if store_history:
2673 if store_history:
2677 self.execution_count += 1
2674 self.execution_count += 1
2678 return error_before_exec(e)
2675 return error_before_exec(e)
2679
2676
2680 # Apply AST transformations
2677 # Apply AST transformations
2681 try:
2678 try:
2682 code_ast = self.transform_ast(code_ast)
2679 code_ast = self.transform_ast(code_ast)
2683 except InputRejected as e:
2680 except InputRejected as e:
2684 self.showtraceback()
2681 self.showtraceback()
2685 if store_history:
2682 if store_history:
2686 self.execution_count += 1
2683 self.execution_count += 1
2687 return error_before_exec(e)
2684 return error_before_exec(e)
2688
2685
2689 # Give the displayhook a reference to our ExecutionResult so it
2686 # Give the displayhook a reference to our ExecutionResult so it
2690 # can fill in the output value.
2687 # can fill in the output value.
2691 self.displayhook.exec_result = result
2688 self.displayhook.exec_result = result
2692
2689
2693 # Execute the user code
2690 # Execute the user code
2694 interactivity = "none" if silent else self.ast_node_interactivity
2691 interactivity = "none" if silent else self.ast_node_interactivity
2695 has_raised = self.run_ast_nodes(code_ast.body, cell_name,
2692 has_raised = self.run_ast_nodes(code_ast.body, cell_name,
2696 interactivity=interactivity, compiler=compiler, result=result)
2693 interactivity=interactivity, compiler=compiler, result=result)
2697
2694
2698 self.last_execution_succeeded = not has_raised
2695 self.last_execution_succeeded = not has_raised
2699
2696
2700 # Reset this so later displayed values do not modify the
2697 # Reset this so later displayed values do not modify the
2701 # ExecutionResult
2698 # ExecutionResult
2702 self.displayhook.exec_result = None
2699 self.displayhook.exec_result = None
2703
2700
2704 self.events.trigger('post_execute')
2701 self.events.trigger('post_execute')
2705 if not silent:
2702 if not silent:
2706 self.events.trigger('post_run_cell')
2703 self.events.trigger('post_run_cell')
2707
2704
2708 if store_history:
2705 if store_history:
2709 # Write output to the database. Does nothing unless
2706 # Write output to the database. Does nothing unless
2710 # history output logging is enabled.
2707 # history output logging is enabled.
2711 self.history_manager.store_output(self.execution_count)
2708 self.history_manager.store_output(self.execution_count)
2712 # Each cell is a *single* input, regardless of how many lines it has
2709 # Each cell is a *single* input, regardless of how many lines it has
2713 self.execution_count += 1
2710 self.execution_count += 1
2714
2711
2715 return result
2712 return result
2716
2713
2717 def transform_ast(self, node):
2714 def transform_ast(self, node):
2718 """Apply the AST transformations from self.ast_transformers
2715 """Apply the AST transformations from self.ast_transformers
2719
2716
2720 Parameters
2717 Parameters
2721 ----------
2718 ----------
2722 node : ast.Node
2719 node : ast.Node
2723 The root node to be transformed. Typically called with the ast.Module
2720 The root node to be transformed. Typically called with the ast.Module
2724 produced by parsing user input.
2721 produced by parsing user input.
2725
2722
2726 Returns
2723 Returns
2727 -------
2724 -------
2728 An ast.Node corresponding to the node it was called with. Note that it
2725 An ast.Node corresponding to the node it was called with. Note that it
2729 may also modify the passed object, so don't rely on references to the
2726 may also modify the passed object, so don't rely on references to the
2730 original AST.
2727 original AST.
2731 """
2728 """
2732 for transformer in self.ast_transformers:
2729 for transformer in self.ast_transformers:
2733 try:
2730 try:
2734 node = transformer.visit(node)
2731 node = transformer.visit(node)
2735 except InputRejected:
2732 except InputRejected:
2736 # User-supplied AST transformers can reject an input by raising
2733 # User-supplied AST transformers can reject an input by raising
2737 # an InputRejected. Short-circuit in this case so that we
2734 # an InputRejected. Short-circuit in this case so that we
2738 # don't unregister the transform.
2735 # don't unregister the transform.
2739 raise
2736 raise
2740 except Exception:
2737 except Exception:
2741 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2738 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2742 self.ast_transformers.remove(transformer)
2739 self.ast_transformers.remove(transformer)
2743
2740
2744 if self.ast_transformers:
2741 if self.ast_transformers:
2745 ast.fix_missing_locations(node)
2742 ast.fix_missing_locations(node)
2746 return node
2743 return node
2747
2744
2748
2745
2749 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2746 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2750 compiler=compile, result=None):
2747 compiler=compile, result=None):
2751 """Run a sequence of AST nodes. The execution mode depends on the
2748 """Run a sequence of AST nodes. The execution mode depends on the
2752 interactivity parameter.
2749 interactivity parameter.
2753
2750
2754 Parameters
2751 Parameters
2755 ----------
2752 ----------
2756 nodelist : list
2753 nodelist : list
2757 A sequence of AST nodes to run.
2754 A sequence of AST nodes to run.
2758 cell_name : str
2755 cell_name : str
2759 Will be passed to the compiler as the filename of the cell. Typically
2756 Will be passed to the compiler as the filename of the cell. Typically
2760 the value returned by ip.compile.cache(cell).
2757 the value returned by ip.compile.cache(cell).
2761 interactivity : str
2758 interactivity : str
2762 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2759 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2763 run interactively (displaying output from expressions). 'last_expr'
2760 run interactively (displaying output from expressions). 'last_expr'
2764 will run the last node interactively only if it is an expression (i.e.
2761 will run the last node interactively only if it is an expression (i.e.
2765 expressions in loops or other blocks are not displayed. Other values
2762 expressions in loops or other blocks are not displayed. Other values
2766 for this parameter will raise a ValueError.
2763 for this parameter will raise a ValueError.
2767 compiler : callable
2764 compiler : callable
2768 A function with the same interface as the built-in compile(), to turn
2765 A function with the same interface as the built-in compile(), to turn
2769 the AST nodes into code objects. Default is the built-in compile().
2766 the AST nodes into code objects. Default is the built-in compile().
2770 result : ExecutionResult, optional
2767 result : ExecutionResult, optional
2771 An object to store exceptions that occur during execution.
2768 An object to store exceptions that occur during execution.
2772
2769
2773 Returns
2770 Returns
2774 -------
2771 -------
2775 True if an exception occurred while running code, False if it finished
2772 True if an exception occurred while running code, False if it finished
2776 running.
2773 running.
2777 """
2774 """
2778 if not nodelist:
2775 if not nodelist:
2779 return
2776 return
2780
2777
2781 if interactivity == 'last_expr':
2778 if interactivity == 'last_expr':
2782 if isinstance(nodelist[-1], ast.Expr):
2779 if isinstance(nodelist[-1], ast.Expr):
2783 interactivity = "last"
2780 interactivity = "last"
2784 else:
2781 else:
2785 interactivity = "none"
2782 interactivity = "none"
2786
2783
2787 if interactivity == 'none':
2784 if interactivity == 'none':
2788 to_run_exec, to_run_interactive = nodelist, []
2785 to_run_exec, to_run_interactive = nodelist, []
2789 elif interactivity == 'last':
2786 elif interactivity == 'last':
2790 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2787 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2791 elif interactivity == 'all':
2788 elif interactivity == 'all':
2792 to_run_exec, to_run_interactive = [], nodelist
2789 to_run_exec, to_run_interactive = [], nodelist
2793 else:
2790 else:
2794 raise ValueError("Interactivity was %r" % interactivity)
2791 raise ValueError("Interactivity was %r" % interactivity)
2795
2792
2796 try:
2793 try:
2797 for i, node in enumerate(to_run_exec):
2794 for i, node in enumerate(to_run_exec):
2798 mod = ast.Module([node])
2795 mod = ast.Module([node])
2799 code = compiler(mod, cell_name, "exec")
2796 code = compiler(mod, cell_name, "exec")
2800 if self.run_code(code, result):
2797 if self.run_code(code, result):
2801 return True
2798 return True
2802
2799
2803 for i, node in enumerate(to_run_interactive):
2800 for i, node in enumerate(to_run_interactive):
2804 mod = ast.Interactive([node])
2801 mod = ast.Interactive([node])
2805 code = compiler(mod, cell_name, "single")
2802 code = compiler(mod, cell_name, "single")
2806 if self.run_code(code, result):
2803 if self.run_code(code, result):
2807 return True
2804 return True
2808
2805
2809 # Flush softspace
2806 # Flush softspace
2810 if softspace(sys.stdout, 0):
2807 if softspace(sys.stdout, 0):
2811 print()
2808 print()
2812
2809
2813 except:
2810 except:
2814 # It's possible to have exceptions raised here, typically by
2811 # It's possible to have exceptions raised here, typically by
2815 # compilation of odd code (such as a naked 'return' outside a
2812 # compilation of odd code (such as a naked 'return' outside a
2816 # function) that did parse but isn't valid. Typically the exception
2813 # function) that did parse but isn't valid. Typically the exception
2817 # is a SyntaxError, but it's safest just to catch anything and show
2814 # is a SyntaxError, but it's safest just to catch anything and show
2818 # the user a traceback.
2815 # the user a traceback.
2819
2816
2820 # We do only one try/except outside the loop to minimize the impact
2817 # We do only one try/except outside the loop to minimize the impact
2821 # on runtime, and also because if any node in the node list is
2818 # on runtime, and also because if any node in the node list is
2822 # broken, we should stop execution completely.
2819 # broken, we should stop execution completely.
2823 if result:
2820 if result:
2824 result.error_before_exec = sys.exc_info()[1]
2821 result.error_before_exec = sys.exc_info()[1]
2825 self.showtraceback()
2822 self.showtraceback()
2826 return True
2823 return True
2827
2824
2828 return False
2825 return False
2829
2826
2830 def run_code(self, code_obj, result=None):
2827 def run_code(self, code_obj, result=None):
2831 """Execute a code object.
2828 """Execute a code object.
2832
2829
2833 When an exception occurs, self.showtraceback() is called to display a
2830 When an exception occurs, self.showtraceback() is called to display a
2834 traceback.
2831 traceback.
2835
2832
2836 Parameters
2833 Parameters
2837 ----------
2834 ----------
2838 code_obj : code object
2835 code_obj : code object
2839 A compiled code object, to be executed
2836 A compiled code object, to be executed
2840 result : ExecutionResult, optional
2837 result : ExecutionResult, optional
2841 An object to store exceptions that occur during execution.
2838 An object to store exceptions that occur during execution.
2842
2839
2843 Returns
2840 Returns
2844 -------
2841 -------
2845 False : successful execution.
2842 False : successful execution.
2846 True : an error occurred.
2843 True : an error occurred.
2847 """
2844 """
2848 # Set our own excepthook in case the user code tries to call it
2845 # Set our own excepthook in case the user code tries to call it
2849 # directly, so that the IPython crash handler doesn't get triggered
2846 # directly, so that the IPython crash handler doesn't get triggered
2850 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2847 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2851
2848
2852 # we save the original sys.excepthook in the instance, in case config
2849 # we save the original sys.excepthook in the instance, in case config
2853 # code (such as magics) needs access to it.
2850 # code (such as magics) needs access to it.
2854 self.sys_excepthook = old_excepthook
2851 self.sys_excepthook = old_excepthook
2855 outflag = 1 # happens in more places, so it's easier as default
2852 outflag = 1 # happens in more places, so it's easier as default
2856 try:
2853 try:
2857 try:
2854 try:
2858 self.hooks.pre_run_code_hook()
2855 self.hooks.pre_run_code_hook()
2859 #rprint('Running code', repr(code_obj)) # dbg
2856 #rprint('Running code', repr(code_obj)) # dbg
2860 exec(code_obj, self.user_global_ns, self.user_ns)
2857 exec(code_obj, self.user_global_ns, self.user_ns)
2861 finally:
2858 finally:
2862 # Reset our crash handler in place
2859 # Reset our crash handler in place
2863 sys.excepthook = old_excepthook
2860 sys.excepthook = old_excepthook
2864 except SystemExit as e:
2861 except SystemExit as e:
2865 if result is not None:
2862 if result is not None:
2866 result.error_in_exec = e
2863 result.error_in_exec = e
2867 self.showtraceback(exception_only=True)
2864 self.showtraceback(exception_only=True)
2868 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
2865 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
2869 except self.custom_exceptions:
2866 except self.custom_exceptions:
2870 etype, value, tb = sys.exc_info()
2867 etype, value, tb = sys.exc_info()
2871 if result is not None:
2868 if result is not None:
2872 result.error_in_exec = value
2869 result.error_in_exec = value
2873 self.CustomTB(etype, value, tb)
2870 self.CustomTB(etype, value, tb)
2874 except:
2871 except:
2875 if result is not None:
2872 if result is not None:
2876 result.error_in_exec = sys.exc_info()[1]
2873 result.error_in_exec = sys.exc_info()[1]
2877 self.showtraceback()
2874 self.showtraceback()
2878 else:
2875 else:
2879 outflag = 0
2876 outflag = 0
2880 return outflag
2877 return outflag
2881
2878
2882 # For backwards compatibility
2879 # For backwards compatibility
2883 runcode = run_code
2880 runcode = run_code
2884
2881
2885 #-------------------------------------------------------------------------
2882 #-------------------------------------------------------------------------
2886 # Things related to GUI support and pylab
2883 # Things related to GUI support and pylab
2887 #-------------------------------------------------------------------------
2884 #-------------------------------------------------------------------------
2888
2885
2889 active_eventloop = None
2886 active_eventloop = None
2890
2887
2891 def enable_gui(self, gui=None):
2888 def enable_gui(self, gui=None):
2892 raise NotImplementedError('Implement enable_gui in a subclass')
2889 raise NotImplementedError('Implement enable_gui in a subclass')
2893
2890
2894 def enable_matplotlib(self, gui=None):
2891 def enable_matplotlib(self, gui=None):
2895 """Enable interactive matplotlib and inline figure support.
2892 """Enable interactive matplotlib and inline figure support.
2896
2893
2897 This takes the following steps:
2894 This takes the following steps:
2898
2895
2899 1. select the appropriate eventloop and matplotlib backend
2896 1. select the appropriate eventloop and matplotlib backend
2900 2. set up matplotlib for interactive use with that backend
2897 2. set up matplotlib for interactive use with that backend
2901 3. configure formatters for inline figure display
2898 3. configure formatters for inline figure display
2902 4. enable the selected gui eventloop
2899 4. enable the selected gui eventloop
2903
2900
2904 Parameters
2901 Parameters
2905 ----------
2902 ----------
2906 gui : optional, string
2903 gui : optional, string
2907 If given, dictates the choice of matplotlib GUI backend to use
2904 If given, dictates the choice of matplotlib GUI backend to use
2908 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2905 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2909 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2906 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2910 matplotlib (as dictated by the matplotlib build-time options plus the
2907 matplotlib (as dictated by the matplotlib build-time options plus the
2911 user's matplotlibrc configuration file). Note that not all backends
2908 user's matplotlibrc configuration file). Note that not all backends
2912 make sense in all contexts, for example a terminal ipython can't
2909 make sense in all contexts, for example a terminal ipython can't
2913 display figures inline.
2910 display figures inline.
2914 """
2911 """
2915 from IPython.core import pylabtools as pt
2912 from IPython.core import pylabtools as pt
2916 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
2913 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
2917
2914
2918 if gui != 'inline':
2915 if gui != 'inline':
2919 # If we have our first gui selection, store it
2916 # If we have our first gui selection, store it
2920 if self.pylab_gui_select is None:
2917 if self.pylab_gui_select is None:
2921 self.pylab_gui_select = gui
2918 self.pylab_gui_select = gui
2922 # Otherwise if they are different
2919 # Otherwise if they are different
2923 elif gui != self.pylab_gui_select:
2920 elif gui != self.pylab_gui_select:
2924 print ('Warning: Cannot change to a different GUI toolkit: %s.'
2921 print ('Warning: Cannot change to a different GUI toolkit: %s.'
2925 ' Using %s instead.' % (gui, self.pylab_gui_select))
2922 ' Using %s instead.' % (gui, self.pylab_gui_select))
2926 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
2923 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
2927
2924
2928 pt.activate_matplotlib(backend)
2925 pt.activate_matplotlib(backend)
2929 pt.configure_inline_support(self, backend)
2926 pt.configure_inline_support(self, backend)
2930
2927
2931 # Now we must activate the gui pylab wants to use, and fix %run to take
2928 # Now we must activate the gui pylab wants to use, and fix %run to take
2932 # plot updates into account
2929 # plot updates into account
2933 self.enable_gui(gui)
2930 self.enable_gui(gui)
2934 self.magics_manager.registry['ExecutionMagics'].default_runner = \
2931 self.magics_manager.registry['ExecutionMagics'].default_runner = \
2935 pt.mpl_runner(self.safe_execfile)
2932 pt.mpl_runner(self.safe_execfile)
2936
2933
2937 return gui, backend
2934 return gui, backend
2938
2935
2939 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
2936 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
2940 """Activate pylab support at runtime.
2937 """Activate pylab support at runtime.
2941
2938
2942 This turns on support for matplotlib, preloads into the interactive
2939 This turns on support for matplotlib, preloads into the interactive
2943 namespace all of numpy and pylab, and configures IPython to correctly
2940 namespace all of numpy and pylab, and configures IPython to correctly
2944 interact with the GUI event loop. The GUI backend to be used can be
2941 interact with the GUI event loop. The GUI backend to be used can be
2945 optionally selected with the optional ``gui`` argument.
2942 optionally selected with the optional ``gui`` argument.
2946
2943
2947 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
2944 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
2948
2945
2949 Parameters
2946 Parameters
2950 ----------
2947 ----------
2951 gui : optional, string
2948 gui : optional, string
2952 If given, dictates the choice of matplotlib GUI backend to use
2949 If given, dictates the choice of matplotlib GUI backend to use
2953 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2950 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2954 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2951 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2955 matplotlib (as dictated by the matplotlib build-time options plus the
2952 matplotlib (as dictated by the matplotlib build-time options plus the
2956 user's matplotlibrc configuration file). Note that not all backends
2953 user's matplotlibrc configuration file). Note that not all backends
2957 make sense in all contexts, for example a terminal ipython can't
2954 make sense in all contexts, for example a terminal ipython can't
2958 display figures inline.
2955 display figures inline.
2959 import_all : optional, bool, default: True
2956 import_all : optional, bool, default: True
2960 Whether to do `from numpy import *` and `from pylab import *`
2957 Whether to do `from numpy import *` and `from pylab import *`
2961 in addition to module imports.
2958 in addition to module imports.
2962 welcome_message : deprecated
2959 welcome_message : deprecated
2963 This argument is ignored, no welcome message will be displayed.
2960 This argument is ignored, no welcome message will be displayed.
2964 """
2961 """
2965 from IPython.core.pylabtools import import_pylab
2962 from IPython.core.pylabtools import import_pylab
2966
2963
2967 gui, backend = self.enable_matplotlib(gui)
2964 gui, backend = self.enable_matplotlib(gui)
2968
2965
2969 # We want to prevent the loading of pylab to pollute the user's
2966 # We want to prevent the loading of pylab to pollute the user's
2970 # namespace as shown by the %who* magics, so we execute the activation
2967 # namespace as shown by the %who* magics, so we execute the activation
2971 # code in an empty namespace, and we update *both* user_ns and
2968 # code in an empty namespace, and we update *both* user_ns and
2972 # user_ns_hidden with this information.
2969 # user_ns_hidden with this information.
2973 ns = {}
2970 ns = {}
2974 import_pylab(ns, import_all)
2971 import_pylab(ns, import_all)
2975 # warn about clobbered names
2972 # warn about clobbered names
2976 ignored = {"__builtins__"}
2973 ignored = {"__builtins__"}
2977 both = set(ns).intersection(self.user_ns).difference(ignored)
2974 both = set(ns).intersection(self.user_ns).difference(ignored)
2978 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
2975 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
2979 self.user_ns.update(ns)
2976 self.user_ns.update(ns)
2980 self.user_ns_hidden.update(ns)
2977 self.user_ns_hidden.update(ns)
2981 return gui, backend, clobbered
2978 return gui, backend, clobbered
2982
2979
2983 #-------------------------------------------------------------------------
2980 #-------------------------------------------------------------------------
2984 # Utilities
2981 # Utilities
2985 #-------------------------------------------------------------------------
2982 #-------------------------------------------------------------------------
2986
2983
2987 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
2984 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
2988 """Expand python variables in a string.
2985 """Expand python variables in a string.
2989
2986
2990 The depth argument indicates how many frames above the caller should
2987 The depth argument indicates how many frames above the caller should
2991 be walked to look for the local namespace where to expand variables.
2988 be walked to look for the local namespace where to expand variables.
2992
2989
2993 The global namespace for expansion is always the user's interactive
2990 The global namespace for expansion is always the user's interactive
2994 namespace.
2991 namespace.
2995 """
2992 """
2996 ns = self.user_ns.copy()
2993 ns = self.user_ns.copy()
2997 try:
2994 try:
2998 frame = sys._getframe(depth+1)
2995 frame = sys._getframe(depth+1)
2999 except ValueError:
2996 except ValueError:
3000 # This is thrown if there aren't that many frames on the stack,
2997 # This is thrown if there aren't that many frames on the stack,
3001 # e.g. if a script called run_line_magic() directly.
2998 # e.g. if a script called run_line_magic() directly.
3002 pass
2999 pass
3003 else:
3000 else:
3004 ns.update(frame.f_locals)
3001 ns.update(frame.f_locals)
3005
3002
3006 try:
3003 try:
3007 # We have to use .vformat() here, because 'self' is a valid and common
3004 # We have to use .vformat() here, because 'self' is a valid and common
3008 # name, and expanding **ns for .format() would make it collide with
3005 # name, and expanding **ns for .format() would make it collide with
3009 # the 'self' argument of the method.
3006 # the 'self' argument of the method.
3010 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3007 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3011 except Exception:
3008 except Exception:
3012 # if formatter couldn't format, just let it go untransformed
3009 # if formatter couldn't format, just let it go untransformed
3013 pass
3010 pass
3014 return cmd
3011 return cmd
3015
3012
3016 def mktempfile(self, data=None, prefix='ipython_edit_'):
3013 def mktempfile(self, data=None, prefix='ipython_edit_'):
3017 """Make a new tempfile and return its filename.
3014 """Make a new tempfile and return its filename.
3018
3015
3019 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3016 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3020 but it registers the created filename internally so ipython cleans it up
3017 but it registers the created filename internally so ipython cleans it up
3021 at exit time.
3018 at exit time.
3022
3019
3023 Optional inputs:
3020 Optional inputs:
3024
3021
3025 - data(None): if data is given, it gets written out to the temp file
3022 - data(None): if data is given, it gets written out to the temp file
3026 immediately, and the file is closed again."""
3023 immediately, and the file is closed again."""
3027
3024
3028 dirname = tempfile.mkdtemp(prefix=prefix)
3025 dirname = tempfile.mkdtemp(prefix=prefix)
3029 self.tempdirs.append(dirname)
3026 self.tempdirs.append(dirname)
3030
3027
3031 handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
3028 handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
3032 os.close(handle) # On Windows, there can only be one open handle on a file
3029 os.close(handle) # On Windows, there can only be one open handle on a file
3033 self.tempfiles.append(filename)
3030 self.tempfiles.append(filename)
3034
3031
3035 if data:
3032 if data:
3036 tmp_file = open(filename,'w')
3033 tmp_file = open(filename,'w')
3037 tmp_file.write(data)
3034 tmp_file.write(data)
3038 tmp_file.close()
3035 tmp_file.close()
3039 return filename
3036 return filename
3040
3037
3041 @undoc
3038 @undoc
3042 def write(self,data):
3039 def write(self,data):
3043 """DEPRECATED: Write a string to the default output"""
3040 """DEPRECATED: Write a string to the default output"""
3044 warn('InteractiveShell.write() is deprecated, use sys.stdout instead',
3041 warn('InteractiveShell.write() is deprecated, use sys.stdout instead',
3045 DeprecationWarning, stacklevel=2)
3042 DeprecationWarning, stacklevel=2)
3046 sys.stdout.write(data)
3043 sys.stdout.write(data)
3047
3044
3048 @undoc
3045 @undoc
3049 def write_err(self,data):
3046 def write_err(self,data):
3050 """DEPRECATED: Write a string to the default error output"""
3047 """DEPRECATED: Write a string to the default error output"""
3051 warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead',
3048 warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead',
3052 DeprecationWarning, stacklevel=2)
3049 DeprecationWarning, stacklevel=2)
3053 sys.stderr.write(data)
3050 sys.stderr.write(data)
3054
3051
3055 def ask_yes_no(self, prompt, default=None, interrupt=None):
3052 def ask_yes_no(self, prompt, default=None, interrupt=None):
3056 if self.quiet:
3053 if self.quiet:
3057 return True
3054 return True
3058 return ask_yes_no(prompt,default,interrupt)
3055 return ask_yes_no(prompt,default,interrupt)
3059
3056
3060 def show_usage(self):
3057 def show_usage(self):
3061 """Show a usage message"""
3058 """Show a usage message"""
3062 page.page(IPython.core.usage.interactive_usage)
3059 page.page(IPython.core.usage.interactive_usage)
3063
3060
3064 def extract_input_lines(self, range_str, raw=False):
3061 def extract_input_lines(self, range_str, raw=False):
3065 """Return as a string a set of input history slices.
3062 """Return as a string a set of input history slices.
3066
3063
3067 Parameters
3064 Parameters
3068 ----------
3065 ----------
3069 range_str : string
3066 range_str : string
3070 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3067 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3071 since this function is for use by magic functions which get their
3068 since this function is for use by magic functions which get their
3072 arguments as strings. The number before the / is the session
3069 arguments as strings. The number before the / is the session
3073 number: ~n goes n back from the current session.
3070 number: ~n goes n back from the current session.
3074
3071
3075 raw : bool, optional
3072 raw : bool, optional
3076 By default, the processed input is used. If this is true, the raw
3073 By default, the processed input is used. If this is true, the raw
3077 input history is used instead.
3074 input history is used instead.
3078
3075
3079 Notes
3076 Notes
3080 -----
3077 -----
3081
3078
3082 Slices can be described with two notations:
3079 Slices can be described with two notations:
3083
3080
3084 * ``N:M`` -> standard python form, means including items N...(M-1).
3081 * ``N:M`` -> standard python form, means including items N...(M-1).
3085 * ``N-M`` -> include items N..M (closed endpoint).
3082 * ``N-M`` -> include items N..M (closed endpoint).
3086 """
3083 """
3087 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3084 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3088 return "\n".join(x for _, _, x in lines)
3085 return "\n".join(x for _, _, x in lines)
3089
3086
3090 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3087 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3091 """Get a code string from history, file, url, or a string or macro.
3088 """Get a code string from history, file, url, or a string or macro.
3092
3089
3093 This is mainly used by magic functions.
3090 This is mainly used by magic functions.
3094
3091
3095 Parameters
3092 Parameters
3096 ----------
3093 ----------
3097
3094
3098 target : str
3095 target : str
3099
3096
3100 A string specifying code to retrieve. This will be tried respectively
3097 A string specifying code to retrieve. This will be tried respectively
3101 as: ranges of input history (see %history for syntax), url,
3098 as: ranges of input history (see %history for syntax), url,
3102 corresponding .py file, filename, or an expression evaluating to a
3099 corresponding .py file, filename, or an expression evaluating to a
3103 string or Macro in the user namespace.
3100 string or Macro in the user namespace.
3104
3101
3105 raw : bool
3102 raw : bool
3106 If true (default), retrieve raw history. Has no effect on the other
3103 If true (default), retrieve raw history. Has no effect on the other
3107 retrieval mechanisms.
3104 retrieval mechanisms.
3108
3105
3109 py_only : bool (default False)
3106 py_only : bool (default False)
3110 Only try to fetch python code, do not try alternative methods to decode file
3107 Only try to fetch python code, do not try alternative methods to decode file
3111 if unicode fails.
3108 if unicode fails.
3112
3109
3113 Returns
3110 Returns
3114 -------
3111 -------
3115 A string of code.
3112 A string of code.
3116
3113
3117 ValueError is raised if nothing is found, and TypeError if it evaluates
3114 ValueError is raised if nothing is found, and TypeError if it evaluates
3118 to an object of another type. In each case, .args[0] is a printable
3115 to an object of another type. In each case, .args[0] is a printable
3119 message.
3116 message.
3120 """
3117 """
3121 code = self.extract_input_lines(target, raw=raw) # Grab history
3118 code = self.extract_input_lines(target, raw=raw) # Grab history
3122 if code:
3119 if code:
3123 return code
3120 return code
3124 try:
3121 try:
3125 if target.startswith(('http://', 'https://')):
3122 if target.startswith(('http://', 'https://')):
3126 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3123 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3127 except UnicodeDecodeError:
3124 except UnicodeDecodeError:
3128 if not py_only :
3125 if not py_only :
3129 # Deferred import
3126 # Deferred import
3130 try:
3127 try:
3131 from urllib.request import urlopen # Py3
3128 from urllib.request import urlopen # Py3
3132 except ImportError:
3129 except ImportError:
3133 from urllib import urlopen
3130 from urllib import urlopen
3134 response = urlopen(target)
3131 response = urlopen(target)
3135 return response.read().decode('latin1')
3132 return response.read().decode('latin1')
3136 raise ValueError(("'%s' seem to be unreadable.") % target)
3133 raise ValueError(("'%s' seem to be unreadable.") % target)
3137
3134
3138 potential_target = [target]
3135 potential_target = [target]
3139 try :
3136 try :
3140 potential_target.insert(0,get_py_filename(target))
3137 potential_target.insert(0,get_py_filename(target))
3141 except IOError:
3138 except IOError:
3142 pass
3139 pass
3143
3140
3144 for tgt in potential_target :
3141 for tgt in potential_target :
3145 if os.path.isfile(tgt): # Read file
3142 if os.path.isfile(tgt): # Read file
3146 try :
3143 try :
3147 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3144 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3148 except UnicodeDecodeError :
3145 except UnicodeDecodeError :
3149 if not py_only :
3146 if not py_only :
3150 with io_open(tgt,'r', encoding='latin1') as f :
3147 with io_open(tgt,'r', encoding='latin1') as f :
3151 return f.read()
3148 return f.read()
3152 raise ValueError(("'%s' seem to be unreadable.") % target)
3149 raise ValueError(("'%s' seem to be unreadable.") % target)
3153 elif os.path.isdir(os.path.expanduser(tgt)):
3150 elif os.path.isdir(os.path.expanduser(tgt)):
3154 raise ValueError("'%s' is a directory, not a regular file." % target)
3151 raise ValueError("'%s' is a directory, not a regular file." % target)
3155
3152
3156 if search_ns:
3153 if search_ns:
3157 # Inspect namespace to load object source
3154 # Inspect namespace to load object source
3158 object_info = self.object_inspect(target, detail_level=1)
3155 object_info = self.object_inspect(target, detail_level=1)
3159 if object_info['found'] and object_info['source']:
3156 if object_info['found'] and object_info['source']:
3160 return object_info['source']
3157 return object_info['source']
3161
3158
3162 try: # User namespace
3159 try: # User namespace
3163 codeobj = eval(target, self.user_ns)
3160 codeobj = eval(target, self.user_ns)
3164 except Exception:
3161 except Exception:
3165 raise ValueError(("'%s' was not found in history, as a file, url, "
3162 raise ValueError(("'%s' was not found in history, as a file, url, "
3166 "nor in the user namespace.") % target)
3163 "nor in the user namespace.") % target)
3167
3164
3168 if isinstance(codeobj, string_types):
3165 if isinstance(codeobj, str):
3169 return codeobj
3166 return codeobj
3170 elif isinstance(codeobj, Macro):
3167 elif isinstance(codeobj, Macro):
3171 return codeobj.value
3168 return codeobj.value
3172
3169
3173 raise TypeError("%s is neither a string nor a macro." % target,
3170 raise TypeError("%s is neither a string nor a macro." % target,
3174 codeobj)
3171 codeobj)
3175
3172
3176 #-------------------------------------------------------------------------
3173 #-------------------------------------------------------------------------
3177 # Things related to IPython exiting
3174 # Things related to IPython exiting
3178 #-------------------------------------------------------------------------
3175 #-------------------------------------------------------------------------
3179 def atexit_operations(self):
3176 def atexit_operations(self):
3180 """This will be executed at the time of exit.
3177 """This will be executed at the time of exit.
3181
3178
3182 Cleanup operations and saving of persistent data that is done
3179 Cleanup operations and saving of persistent data that is done
3183 unconditionally by IPython should be performed here.
3180 unconditionally by IPython should be performed here.
3184
3181
3185 For things that may depend on startup flags or platform specifics (such
3182 For things that may depend on startup flags or platform specifics (such
3186 as having readline or not), register a separate atexit function in the
3183 as having readline or not), register a separate atexit function in the
3187 code that has the appropriate information, rather than trying to
3184 code that has the appropriate information, rather than trying to
3188 clutter
3185 clutter
3189 """
3186 """
3190 # Close the history session (this stores the end time and line count)
3187 # Close the history session (this stores the end time and line count)
3191 # this must be *before* the tempfile cleanup, in case of temporary
3188 # this must be *before* the tempfile cleanup, in case of temporary
3192 # history db
3189 # history db
3193 self.history_manager.end_session()
3190 self.history_manager.end_session()
3194
3191
3195 # Cleanup all tempfiles and folders left around
3192 # Cleanup all tempfiles and folders left around
3196 for tfile in self.tempfiles:
3193 for tfile in self.tempfiles:
3197 try:
3194 try:
3198 os.unlink(tfile)
3195 os.unlink(tfile)
3199 except OSError:
3196 except OSError:
3200 pass
3197 pass
3201
3198
3202 for tdir in self.tempdirs:
3199 for tdir in self.tempdirs:
3203 try:
3200 try:
3204 os.rmdir(tdir)
3201 os.rmdir(tdir)
3205 except OSError:
3202 except OSError:
3206 pass
3203 pass
3207
3204
3208 # Clear all user namespaces to release all references cleanly.
3205 # Clear all user namespaces to release all references cleanly.
3209 self.reset(new_session=False)
3206 self.reset(new_session=False)
3210
3207
3211 # Run user hooks
3208 # Run user hooks
3212 self.hooks.shutdown_hook()
3209 self.hooks.shutdown_hook()
3213
3210
3214 def cleanup(self):
3211 def cleanup(self):
3215 self.restore_sys_module_state()
3212 self.restore_sys_module_state()
3216
3213
3217
3214
3218 # Overridden in terminal subclass to change prompts
3215 # Overridden in terminal subclass to change prompts
3219 def switch_doctest_mode(self, mode):
3216 def switch_doctest_mode(self, mode):
3220 pass
3217 pass
3221
3218
3222
3219
3223 class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
3220 class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
3224 """An abstract base class for InteractiveShell."""
3221 """An abstract base class for InteractiveShell."""
3225
3222
3226 InteractiveShellABC.register(InteractiveShell)
3223 InteractiveShellABC.register(InteractiveShell)
@@ -1,220 +1,218 b''
1 """Logger class for IPython's logging facilities.
1 """Logger class for IPython's logging facilities.
2 """
2 """
3
3
4 #*****************************************************************************
4 #*****************************************************************************
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
6 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #*****************************************************************************
10 #*****************************************************************************
11
11
12 #****************************************************************************
12 #****************************************************************************
13 # Modules and globals
13 # Modules and globals
14
14
15 # Python standard modules
15 # Python standard modules
16 import glob
16 import glob
17 import io
17 import io
18 import os
18 import os
19 import time
19 import time
20
20
21 from IPython.utils.py3compat import str_to_unicode
22
21
23 #****************************************************************************
22 #****************************************************************************
24 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
23 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
25 # ipython and does input cache management. Finish cleanup later...
24 # ipython and does input cache management. Finish cleanup later...
26
25
27 class Logger(object):
26 class Logger(object):
28 """A Logfile class with different policies for file creation"""
27 """A Logfile class with different policies for file creation"""
29
28
30 def __init__(self, home_dir, logfname='Logger.log', loghead=u'',
29 def __init__(self, home_dir, logfname='Logger.log', loghead=u'',
31 logmode='over'):
30 logmode='over'):
32
31
33 # this is the full ipython instance, we need some attributes from it
32 # this is the full ipython instance, we need some attributes from it
34 # which won't exist until later. What a mess, clean up later...
33 # which won't exist until later. What a mess, clean up later...
35 self.home_dir = home_dir
34 self.home_dir = home_dir
36
35
37 self.logfname = logfname
36 self.logfname = logfname
38 self.loghead = loghead
37 self.loghead = loghead
39 self.logmode = logmode
38 self.logmode = logmode
40 self.logfile = None
39 self.logfile = None
41
40
42 # Whether to log raw or processed input
41 # Whether to log raw or processed input
43 self.log_raw_input = False
42 self.log_raw_input = False
44
43
45 # whether to also log output
44 # whether to also log output
46 self.log_output = False
45 self.log_output = False
47
46
48 # whether to put timestamps before each log entry
47 # whether to put timestamps before each log entry
49 self.timestamp = False
48 self.timestamp = False
50
49
51 # activity control flags
50 # activity control flags
52 self.log_active = False
51 self.log_active = False
53
52
54 # logmode is a validated property
53 # logmode is a validated property
55 def _set_mode(self,mode):
54 def _set_mode(self,mode):
56 if mode not in ['append','backup','global','over','rotate']:
55 if mode not in ['append','backup','global','over','rotate']:
57 raise ValueError('invalid log mode %s given' % mode)
56 raise ValueError('invalid log mode %s given' % mode)
58 self._logmode = mode
57 self._logmode = mode
59
58
60 def _get_mode(self):
59 def _get_mode(self):
61 return self._logmode
60 return self._logmode
62
61
63 logmode = property(_get_mode,_set_mode)
62 logmode = property(_get_mode,_set_mode)
64
63
65 def logstart(self, logfname=None, loghead=None, logmode=None,
64 def logstart(self, logfname=None, loghead=None, logmode=None,
66 log_output=False, timestamp=False, log_raw_input=False):
65 log_output=False, timestamp=False, log_raw_input=False):
67 """Generate a new log-file with a default header.
66 """Generate a new log-file with a default header.
68
67
69 Raises RuntimeError if the log has already been started"""
68 Raises RuntimeError if the log has already been started"""
70
69
71 if self.logfile is not None:
70 if self.logfile is not None:
72 raise RuntimeError('Log file is already active: %s' %
71 raise RuntimeError('Log file is already active: %s' %
73 self.logfname)
72 self.logfname)
74
73
75 # The parameters can override constructor defaults
74 # The parameters can override constructor defaults
76 if logfname is not None: self.logfname = logfname
75 if logfname is not None: self.logfname = logfname
77 if loghead is not None: self.loghead = loghead
76 if loghead is not None: self.loghead = loghead
78 if logmode is not None: self.logmode = logmode
77 if logmode is not None: self.logmode = logmode
79
78
80 # Parameters not part of the constructor
79 # Parameters not part of the constructor
81 self.timestamp = timestamp
80 self.timestamp = timestamp
82 self.log_output = log_output
81 self.log_output = log_output
83 self.log_raw_input = log_raw_input
82 self.log_raw_input = log_raw_input
84
83
85 # init depending on the log mode requested
84 # init depending on the log mode requested
86 isfile = os.path.isfile
85 isfile = os.path.isfile
87 logmode = self.logmode
86 logmode = self.logmode
88
87
89 if logmode == 'append':
88 if logmode == 'append':
90 self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
89 self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
91
90
92 elif logmode == 'backup':
91 elif logmode == 'backup':
93 if isfile(self.logfname):
92 if isfile(self.logfname):
94 backup_logname = self.logfname+'~'
93 backup_logname = self.logfname+'~'
95 # Manually remove any old backup, since os.rename may fail
94 # Manually remove any old backup, since os.rename may fail
96 # under Windows.
95 # under Windows.
97 if isfile(backup_logname):
96 if isfile(backup_logname):
98 os.remove(backup_logname)
97 os.remove(backup_logname)
99 os.rename(self.logfname,backup_logname)
98 os.rename(self.logfname,backup_logname)
100 self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
99 self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
101
100
102 elif logmode == 'global':
101 elif logmode == 'global':
103 self.logfname = os.path.join(self.home_dir,self.logfname)
102 self.logfname = os.path.join(self.home_dir,self.logfname)
104 self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
103 self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
105
104
106 elif logmode == 'over':
105 elif logmode == 'over':
107 if isfile(self.logfname):
106 if isfile(self.logfname):
108 os.remove(self.logfname)
107 os.remove(self.logfname)
109 self.logfile = io.open(self.logfname,'w', encoding='utf-8')
108 self.logfile = io.open(self.logfname,'w', encoding='utf-8')
110
109
111 elif logmode == 'rotate':
110 elif logmode == 'rotate':
112 if isfile(self.logfname):
111 if isfile(self.logfname):
113 if isfile(self.logfname+'.001~'):
112 if isfile(self.logfname+'.001~'):
114 old = glob.glob(self.logfname+'.*~')
113 old = glob.glob(self.logfname+'.*~')
115 old.sort()
114 old.sort()
116 old.reverse()
115 old.reverse()
117 for f in old:
116 for f in old:
118 root, ext = os.path.splitext(f)
117 root, ext = os.path.splitext(f)
119 num = int(ext[1:-1])+1
118 num = int(ext[1:-1])+1
120 os.rename(f, root+'.'+repr(num).zfill(3)+'~')
119 os.rename(f, root+'.'+repr(num).zfill(3)+'~')
121 os.rename(self.logfname, self.logfname+'.001~')
120 os.rename(self.logfname, self.logfname+'.001~')
122 self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
121 self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
123
122
124 if logmode != 'append':
123 if logmode != 'append':
125 self.logfile.write(self.loghead)
124 self.logfile.write(self.loghead)
126
125
127 self.logfile.flush()
126 self.logfile.flush()
128 self.log_active = True
127 self.log_active = True
129
128
130 def switch_log(self,val):
129 def switch_log(self,val):
131 """Switch logging on/off. val should be ONLY a boolean."""
130 """Switch logging on/off. val should be ONLY a boolean."""
132
131
133 if val not in [False,True,0,1]:
132 if val not in [False,True,0,1]:
134 raise ValueError('Call switch_log ONLY with a boolean argument, '
133 raise ValueError('Call switch_log ONLY with a boolean argument, '
135 'not with: %s' % val)
134 'not with: %s' % val)
136
135
137 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
136 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
138
137
139 if self.logfile is None:
138 if self.logfile is None:
140 print("""
139 print("""
141 Logging hasn't been started yet (use logstart for that).
140 Logging hasn't been started yet (use logstart for that).
142
141
143 %logon/%logoff are for temporarily starting and stopping logging for a logfile
142 %logon/%logoff are for temporarily starting and stopping logging for a logfile
144 which already exists. But you must first start the logging process with
143 which already exists. But you must first start the logging process with
145 %logstart (optionally giving a logfile name).""")
144 %logstart (optionally giving a logfile name).""")
146
145
147 else:
146 else:
148 if self.log_active == val:
147 if self.log_active == val:
149 print('Logging is already',label[val])
148 print('Logging is already',label[val])
150 else:
149 else:
151 print('Switching logging',label[val])
150 print('Switching logging',label[val])
152 self.log_active = not self.log_active
151 self.log_active = not self.log_active
153 self.log_active_out = self.log_active
152 self.log_active_out = self.log_active
154
153
155 def logstate(self):
154 def logstate(self):
156 """Print a status message about the logger."""
155 """Print a status message about the logger."""
157 if self.logfile is None:
156 if self.logfile is None:
158 print('Logging has not been activated.')
157 print('Logging has not been activated.')
159 else:
158 else:
160 state = self.log_active and 'active' or 'temporarily suspended'
159 state = self.log_active and 'active' or 'temporarily suspended'
161 print('Filename :', self.logfname)
160 print('Filename :', self.logfname)
162 print('Mode :', self.logmode)
161 print('Mode :', self.logmode)
163 print('Output logging :', self.log_output)
162 print('Output logging :', self.log_output)
164 print('Raw input log :', self.log_raw_input)
163 print('Raw input log :', self.log_raw_input)
165 print('Timestamping :', self.timestamp)
164 print('Timestamping :', self.timestamp)
166 print('State :', state)
165 print('State :', state)
167
166
168 def log(self, line_mod, line_ori):
167 def log(self, line_mod, line_ori):
169 """Write the sources to a log.
168 """Write the sources to a log.
170
169
171 Inputs:
170 Inputs:
172
171
173 - line_mod: possibly modified input, such as the transformations made
172 - line_mod: possibly modified input, such as the transformations made
174 by input prefilters or input handlers of various kinds. This should
173 by input prefilters or input handlers of various kinds. This should
175 always be valid Python.
174 always be valid Python.
176
175
177 - line_ori: unmodified input line from the user. This is not
176 - line_ori: unmodified input line from the user. This is not
178 necessarily valid Python.
177 necessarily valid Python.
179 """
178 """
180
179
181 # Write the log line, but decide which one according to the
180 # Write the log line, but decide which one according to the
182 # log_raw_input flag, set when the log is started.
181 # log_raw_input flag, set when the log is started.
183 if self.log_raw_input:
182 if self.log_raw_input:
184 self.log_write(line_ori)
183 self.log_write(line_ori)
185 else:
184 else:
186 self.log_write(line_mod)
185 self.log_write(line_mod)
187
186
188 def log_write(self, data, kind='input'):
187 def log_write(self, data, kind='input'):
189 """Write data to the log file, if active"""
188 """Write data to the log file, if active"""
190
189
191 #print 'data: %r' % data # dbg
190 #print 'data: %r' % data # dbg
192 if self.log_active and data:
191 if self.log_active and data:
193 write = self.logfile.write
192 write = self.logfile.write
194 if kind=='input':
193 if kind=='input':
195 if self.timestamp:
194 if self.timestamp:
196 write(str_to_unicode(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
195 write(time.strftime('# %a, %d %b %Y %H:%M:%S\n', time.localtime()))
197 time.localtime())))
198 write(data)
196 write(data)
199 elif kind=='output' and self.log_output:
197 elif kind=='output' and self.log_output:
200 odata = u'\n'.join([u'#[Out]# %s' % s
198 odata = u'\n'.join([u'#[Out]# %s' % s
201 for s in data.splitlines()])
199 for s in data.splitlines()])
202 write(u'%s\n' % odata)
200 write(u'%s\n' % odata)
203 self.logfile.flush()
201 self.logfile.flush()
204
202
205 def logstop(self):
203 def logstop(self):
206 """Fully stop logging and close log file.
204 """Fully stop logging and close log file.
207
205
208 In order to start logging again, a new logstart() call needs to be
206 In order to start logging again, a new logstart() call needs to be
209 made, possibly (though not necessarily) with a new filename, mode and
207 made, possibly (though not necessarily) with a new filename, mode and
210 other options."""
208 other options."""
211
209
212 if self.logfile is not None:
210 if self.logfile is not None:
213 self.logfile.close()
211 self.logfile.close()
214 self.logfile = None
212 self.logfile = None
215 else:
213 else:
216 print("Logging hadn't been started.")
214 print("Logging hadn't been started.")
217 self.log_active = False
215 self.log_active = False
218
216
219 # For backwards compatibility, in case anyone was using this.
217 # For backwards compatibility, in case anyone was using this.
220 close_log = logstop
218 close_log = logstop
@@ -1,57 +1,57 b''
1 """Support for interactive macros in IPython"""
1 """Support for interactive macros in IPython"""
2
2
3 #*****************************************************************************
3 #*****************************************************************************
4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #*****************************************************************************
8 #*****************************************************************************
9
9
10 import re
10 import re
11
11
12 from IPython.utils import py3compat
12 from IPython.utils import py3compat
13 from IPython.utils.encoding import DEFAULT_ENCODING
13 from IPython.utils.encoding import DEFAULT_ENCODING
14
14
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
16
16
17 class Macro(object):
17 class Macro(object):
18 """Simple class to store the value of macros as strings.
18 """Simple class to store the value of macros as strings.
19
19
20 Macro is just a callable that executes a string of IPython
20 Macro is just a callable that executes a string of IPython
21 input when called.
21 input when called.
22 """
22 """
23
23
24 def __init__(self,code):
24 def __init__(self,code):
25 """store the macro value, as a single string which can be executed"""
25 """store the macro value, as a single string which can be executed"""
26 lines = []
26 lines = []
27 enc = None
27 enc = None
28 for line in code.splitlines():
28 for line in code.splitlines():
29 coding_match = coding_declaration.match(line)
29 coding_match = coding_declaration.match(line)
30 if coding_match:
30 if coding_match:
31 enc = coding_match.group(1)
31 enc = coding_match.group(1)
32 else:
32 else:
33 lines.append(line)
33 lines.append(line)
34 code = "\n".join(lines)
34 code = "\n".join(lines)
35 if isinstance(code, bytes):
35 if isinstance(code, bytes):
36 code = code.decode(enc or DEFAULT_ENCODING)
36 code = code.decode(enc or DEFAULT_ENCODING)
37 self.value = code + '\n'
37 self.value = code + '\n'
38
38
39 def __str__(self):
39 def __str__(self):
40 return py3compat.unicode_to_str(self.value)
40 return self.value
41
41
42 def __unicode__(self):
42 def __unicode__(self):
43 return self.value
43 return self.value
44
44
45 def __repr__(self):
45 def __repr__(self):
46 return 'IPython.macro.Macro(%s)' % repr(self.value)
46 return 'IPython.macro.Macro(%s)' % repr(self.value)
47
47
48 def __getstate__(self):
48 def __getstate__(self):
49 """ needed for safe pickling via %store """
49 """ needed for safe pickling via %store """
50 return {'value': self.value}
50 return {'value': self.value}
51
51
52 def __add__(self, other):
52 def __add__(self, other):
53 if isinstance(other, Macro):
53 if isinstance(other, Macro):
54 return Macro(self.value + other.value)
54 return Macro(self.value + other.value)
55 elif isinstance(other, py3compat.string_types):
55 elif isinstance(other, str):
56 return Macro(self.value + other)
56 return Macro(self.value + other)
57 raise TypeError
57 raise TypeError
@@ -1,679 +1,678 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9
9
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import os
14 import os
15 import re
15 import re
16 import sys
16 import sys
17 import types
17 import types
18 from getopt import getopt, GetoptError
18 from getopt import getopt, GetoptError
19
19
20 from traitlets.config.configurable import Configurable
20 from traitlets.config.configurable import Configurable
21 from IPython.core import oinspect
21 from IPython.core import oinspect
22 from IPython.core.error import UsageError
22 from IPython.core.error import UsageError
23 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
23 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
24 from decorator import decorator
24 from decorator import decorator
25 from IPython.utils.ipstruct import Struct
25 from IPython.utils.ipstruct import Struct
26 from IPython.utils.process import arg_split
26 from IPython.utils.process import arg_split
27 from IPython.utils.py3compat import string_types, iteritems
28 from IPython.utils.text import dedent
27 from IPython.utils.text import dedent
29 from traitlets import Bool, Dict, Instance, observe
28 from traitlets import Bool, Dict, Instance, observe
30 from logging import error
29 from logging import error
31
30
32 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
33 # Globals
32 # Globals
34 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
35
34
36 # A dict we'll use for each class that has magics, used as temporary storage to
35 # A dict we'll use for each class that has magics, used as temporary storage to
37 # pass information between the @line/cell_magic method decorators and the
36 # pass information between the @line/cell_magic method decorators and the
38 # @magics_class class decorator, because the method decorators have no
37 # @magics_class class decorator, because the method decorators have no
39 # access to the class when they run. See for more details:
38 # access to the class when they run. See for more details:
40 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
39 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
41
40
42 magics = dict(line={}, cell={})
41 magics = dict(line={}, cell={})
43
42
44 magic_kinds = ('line', 'cell')
43 magic_kinds = ('line', 'cell')
45 magic_spec = ('line', 'cell', 'line_cell')
44 magic_spec = ('line', 'cell', 'line_cell')
46 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
45 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
47
46
48 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
49 # Utility classes and functions
48 # Utility classes and functions
50 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
51
50
52 class Bunch: pass
51 class Bunch: pass
53
52
54
53
55 def on_off(tag):
54 def on_off(tag):
56 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
55 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
57 return ['OFF','ON'][tag]
56 return ['OFF','ON'][tag]
58
57
59
58
60 def compress_dhist(dh):
59 def compress_dhist(dh):
61 """Compress a directory history into a new one with at most 20 entries.
60 """Compress a directory history into a new one with at most 20 entries.
62
61
63 Return a new list made from the first and last 10 elements of dhist after
62 Return a new list made from the first and last 10 elements of dhist after
64 removal of duplicates.
63 removal of duplicates.
65 """
64 """
66 head, tail = dh[:-10], dh[-10:]
65 head, tail = dh[:-10], dh[-10:]
67
66
68 newhead = []
67 newhead = []
69 done = set()
68 done = set()
70 for h in head:
69 for h in head:
71 if h in done:
70 if h in done:
72 continue
71 continue
73 newhead.append(h)
72 newhead.append(h)
74 done.add(h)
73 done.add(h)
75
74
76 return newhead + tail
75 return newhead + tail
77
76
78
77
79 def needs_local_scope(func):
78 def needs_local_scope(func):
80 """Decorator to mark magic functions which need to local scope to run."""
79 """Decorator to mark magic functions which need to local scope to run."""
81 func.needs_local_scope = True
80 func.needs_local_scope = True
82 return func
81 return func
83
82
84 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
85 # Class and method decorators for registering magics
84 # Class and method decorators for registering magics
86 #-----------------------------------------------------------------------------
85 #-----------------------------------------------------------------------------
87
86
88 def magics_class(cls):
87 def magics_class(cls):
89 """Class decorator for all subclasses of the main Magics class.
88 """Class decorator for all subclasses of the main Magics class.
90
89
91 Any class that subclasses Magics *must* also apply this decorator, to
90 Any class that subclasses Magics *must* also apply this decorator, to
92 ensure that all the methods that have been decorated as line/cell magics
91 ensure that all the methods that have been decorated as line/cell magics
93 get correctly registered in the class instance. This is necessary because
92 get correctly registered in the class instance. This is necessary because
94 when method decorators run, the class does not exist yet, so they
93 when method decorators run, the class does not exist yet, so they
95 temporarily store their information into a module global. Application of
94 temporarily store their information into a module global. Application of
96 this class decorator copies that global data to the class instance and
95 this class decorator copies that global data to the class instance and
97 clears the global.
96 clears the global.
98
97
99 Obviously, this mechanism is not thread-safe, which means that the
98 Obviously, this mechanism is not thread-safe, which means that the
100 *creation* of subclasses of Magic should only be done in a single-thread
99 *creation* of subclasses of Magic should only be done in a single-thread
101 context. Instantiation of the classes has no restrictions. Given that
100 context. Instantiation of the classes has no restrictions. Given that
102 these classes are typically created at IPython startup time and before user
101 these classes are typically created at IPython startup time and before user
103 application code becomes active, in practice this should not pose any
102 application code becomes active, in practice this should not pose any
104 problems.
103 problems.
105 """
104 """
106 cls.registered = True
105 cls.registered = True
107 cls.magics = dict(line = magics['line'],
106 cls.magics = dict(line = magics['line'],
108 cell = magics['cell'])
107 cell = magics['cell'])
109 magics['line'] = {}
108 magics['line'] = {}
110 magics['cell'] = {}
109 magics['cell'] = {}
111 return cls
110 return cls
112
111
113
112
114 def record_magic(dct, magic_kind, magic_name, func):
113 def record_magic(dct, magic_kind, magic_name, func):
115 """Utility function to store a function as a magic of a specific kind.
114 """Utility function to store a function as a magic of a specific kind.
116
115
117 Parameters
116 Parameters
118 ----------
117 ----------
119 dct : dict
118 dct : dict
120 A dictionary with 'line' and 'cell' subdicts.
119 A dictionary with 'line' and 'cell' subdicts.
121
120
122 magic_kind : str
121 magic_kind : str
123 Kind of magic to be stored.
122 Kind of magic to be stored.
124
123
125 magic_name : str
124 magic_name : str
126 Key to store the magic as.
125 Key to store the magic as.
127
126
128 func : function
127 func : function
129 Callable object to store.
128 Callable object to store.
130 """
129 """
131 if magic_kind == 'line_cell':
130 if magic_kind == 'line_cell':
132 dct['line'][magic_name] = dct['cell'][magic_name] = func
131 dct['line'][magic_name] = dct['cell'][magic_name] = func
133 else:
132 else:
134 dct[magic_kind][magic_name] = func
133 dct[magic_kind][magic_name] = func
135
134
136
135
137 def validate_type(magic_kind):
136 def validate_type(magic_kind):
138 """Ensure that the given magic_kind is valid.
137 """Ensure that the given magic_kind is valid.
139
138
140 Check that the given magic_kind is one of the accepted spec types (stored
139 Check that the given magic_kind is one of the accepted spec types (stored
141 in the global `magic_spec`), raise ValueError otherwise.
140 in the global `magic_spec`), raise ValueError otherwise.
142 """
141 """
143 if magic_kind not in magic_spec:
142 if magic_kind not in magic_spec:
144 raise ValueError('magic_kind must be one of %s, %s given' %
143 raise ValueError('magic_kind must be one of %s, %s given' %
145 magic_kinds, magic_kind)
144 magic_kinds, magic_kind)
146
145
147
146
148 # The docstrings for the decorator below will be fairly similar for the two
147 # The docstrings for the decorator below will be fairly similar for the two
149 # types (method and function), so we generate them here once and reuse the
148 # types (method and function), so we generate them here once and reuse the
150 # templates below.
149 # templates below.
151 _docstring_template = \
150 _docstring_template = \
152 """Decorate the given {0} as {1} magic.
151 """Decorate the given {0} as {1} magic.
153
152
154 The decorator can be used with or without arguments, as follows.
153 The decorator can be used with or without arguments, as follows.
155
154
156 i) without arguments: it will create a {1} magic named as the {0} being
155 i) without arguments: it will create a {1} magic named as the {0} being
157 decorated::
156 decorated::
158
157
159 @deco
158 @deco
160 def foo(...)
159 def foo(...)
161
160
162 will create a {1} magic named `foo`.
161 will create a {1} magic named `foo`.
163
162
164 ii) with one string argument: which will be used as the actual name of the
163 ii) with one string argument: which will be used as the actual name of the
165 resulting magic::
164 resulting magic::
166
165
167 @deco('bar')
166 @deco('bar')
168 def foo(...)
167 def foo(...)
169
168
170 will create a {1} magic named `bar`.
169 will create a {1} magic named `bar`.
171 """
170 """
172
171
173 # These two are decorator factories. While they are conceptually very similar,
172 # These two are decorator factories. While they are conceptually very similar,
174 # there are enough differences in the details that it's simpler to have them
173 # there are enough differences in the details that it's simpler to have them
175 # written as completely standalone functions rather than trying to share code
174 # written as completely standalone functions rather than trying to share code
176 # and make a single one with convoluted logic.
175 # and make a single one with convoluted logic.
177
176
178 def _method_magic_marker(magic_kind):
177 def _method_magic_marker(magic_kind):
179 """Decorator factory for methods in Magics subclasses.
178 """Decorator factory for methods in Magics subclasses.
180 """
179 """
181
180
182 validate_type(magic_kind)
181 validate_type(magic_kind)
183
182
184 # This is a closure to capture the magic_kind. We could also use a class,
183 # This is a closure to capture the magic_kind. We could also use a class,
185 # but it's overkill for just that one bit of state.
184 # but it's overkill for just that one bit of state.
186 def magic_deco(arg):
185 def magic_deco(arg):
187 call = lambda f, *a, **k: f(*a, **k)
186 call = lambda f, *a, **k: f(*a, **k)
188
187
189 if callable(arg):
188 if callable(arg):
190 # "Naked" decorator call (just @foo, no args)
189 # "Naked" decorator call (just @foo, no args)
191 func = arg
190 func = arg
192 name = func.__name__
191 name = func.__name__
193 retval = decorator(call, func)
192 retval = decorator(call, func)
194 record_magic(magics, magic_kind, name, name)
193 record_magic(magics, magic_kind, name, name)
195 elif isinstance(arg, string_types):
194 elif isinstance(arg, str):
196 # Decorator called with arguments (@foo('bar'))
195 # Decorator called with arguments (@foo('bar'))
197 name = arg
196 name = arg
198 def mark(func, *a, **kw):
197 def mark(func, *a, **kw):
199 record_magic(magics, magic_kind, name, func.__name__)
198 record_magic(magics, magic_kind, name, func.__name__)
200 return decorator(call, func)
199 return decorator(call, func)
201 retval = mark
200 retval = mark
202 else:
201 else:
203 raise TypeError("Decorator can only be called with "
202 raise TypeError("Decorator can only be called with "
204 "string or function")
203 "string or function")
205 return retval
204 return retval
206
205
207 # Ensure the resulting decorator has a usable docstring
206 # Ensure the resulting decorator has a usable docstring
208 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
207 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
209 return magic_deco
208 return magic_deco
210
209
211
210
212 def _function_magic_marker(magic_kind):
211 def _function_magic_marker(magic_kind):
213 """Decorator factory for standalone functions.
212 """Decorator factory for standalone functions.
214 """
213 """
215 validate_type(magic_kind)
214 validate_type(magic_kind)
216
215
217 # This is a closure to capture the magic_kind. We could also use a class,
216 # This is a closure to capture the magic_kind. We could also use a class,
218 # but it's overkill for just that one bit of state.
217 # but it's overkill for just that one bit of state.
219 def magic_deco(arg):
218 def magic_deco(arg):
220 call = lambda f, *a, **k: f(*a, **k)
219 call = lambda f, *a, **k: f(*a, **k)
221
220
222 # Find get_ipython() in the caller's namespace
221 # Find get_ipython() in the caller's namespace
223 caller = sys._getframe(1)
222 caller = sys._getframe(1)
224 for ns in ['f_locals', 'f_globals', 'f_builtins']:
223 for ns in ['f_locals', 'f_globals', 'f_builtins']:
225 get_ipython = getattr(caller, ns).get('get_ipython')
224 get_ipython = getattr(caller, ns).get('get_ipython')
226 if get_ipython is not None:
225 if get_ipython is not None:
227 break
226 break
228 else:
227 else:
229 raise NameError('Decorator can only run in context where '
228 raise NameError('Decorator can only run in context where '
230 '`get_ipython` exists')
229 '`get_ipython` exists')
231
230
232 ip = get_ipython()
231 ip = get_ipython()
233
232
234 if callable(arg):
233 if callable(arg):
235 # "Naked" decorator call (just @foo, no args)
234 # "Naked" decorator call (just @foo, no args)
236 func = arg
235 func = arg
237 name = func.__name__
236 name = func.__name__
238 ip.register_magic_function(func, magic_kind, name)
237 ip.register_magic_function(func, magic_kind, name)
239 retval = decorator(call, func)
238 retval = decorator(call, func)
240 elif isinstance(arg, string_types):
239 elif isinstance(arg, str):
241 # Decorator called with arguments (@foo('bar'))
240 # Decorator called with arguments (@foo('bar'))
242 name = arg
241 name = arg
243 def mark(func, *a, **kw):
242 def mark(func, *a, **kw):
244 ip.register_magic_function(func, magic_kind, name)
243 ip.register_magic_function(func, magic_kind, name)
245 return decorator(call, func)
244 return decorator(call, func)
246 retval = mark
245 retval = mark
247 else:
246 else:
248 raise TypeError("Decorator can only be called with "
247 raise TypeError("Decorator can only be called with "
249 "string or function")
248 "string or function")
250 return retval
249 return retval
251
250
252 # Ensure the resulting decorator has a usable docstring
251 # Ensure the resulting decorator has a usable docstring
253 ds = _docstring_template.format('function', magic_kind)
252 ds = _docstring_template.format('function', magic_kind)
254
253
255 ds += dedent("""
254 ds += dedent("""
256 Note: this decorator can only be used in a context where IPython is already
255 Note: this decorator can only be used in a context where IPython is already
257 active, so that the `get_ipython()` call succeeds. You can therefore use
256 active, so that the `get_ipython()` call succeeds. You can therefore use
258 it in your startup files loaded after IPython initializes, but *not* in the
257 it in your startup files loaded after IPython initializes, but *not* in the
259 IPython configuration file itself, which is executed before IPython is
258 IPython configuration file itself, which is executed before IPython is
260 fully up and running. Any file located in the `startup` subdirectory of
259 fully up and running. Any file located in the `startup` subdirectory of
261 your configuration profile will be OK in this sense.
260 your configuration profile will be OK in this sense.
262 """)
261 """)
263
262
264 magic_deco.__doc__ = ds
263 magic_deco.__doc__ = ds
265 return magic_deco
264 return magic_deco
266
265
267
266
268 # Create the actual decorators for public use
267 # Create the actual decorators for public use
269
268
270 # These three are used to decorate methods in class definitions
269 # These three are used to decorate methods in class definitions
271 line_magic = _method_magic_marker('line')
270 line_magic = _method_magic_marker('line')
272 cell_magic = _method_magic_marker('cell')
271 cell_magic = _method_magic_marker('cell')
273 line_cell_magic = _method_magic_marker('line_cell')
272 line_cell_magic = _method_magic_marker('line_cell')
274
273
275 # These three decorate standalone functions and perform the decoration
274 # These three decorate standalone functions and perform the decoration
276 # immediately. They can only run where get_ipython() works
275 # immediately. They can only run where get_ipython() works
277 register_line_magic = _function_magic_marker('line')
276 register_line_magic = _function_magic_marker('line')
278 register_cell_magic = _function_magic_marker('cell')
277 register_cell_magic = _function_magic_marker('cell')
279 register_line_cell_magic = _function_magic_marker('line_cell')
278 register_line_cell_magic = _function_magic_marker('line_cell')
280
279
281 #-----------------------------------------------------------------------------
280 #-----------------------------------------------------------------------------
282 # Core Magic classes
281 # Core Magic classes
283 #-----------------------------------------------------------------------------
282 #-----------------------------------------------------------------------------
284
283
285 class MagicsManager(Configurable):
284 class MagicsManager(Configurable):
286 """Object that handles all magic-related functionality for IPython.
285 """Object that handles all magic-related functionality for IPython.
287 """
286 """
288 # Non-configurable class attributes
287 # Non-configurable class attributes
289
288
290 # A two-level dict, first keyed by magic type, then by magic function, and
289 # A two-level dict, first keyed by magic type, then by magic function, and
291 # holding the actual callable object as value. This is the dict used for
290 # holding the actual callable object as value. This is the dict used for
292 # magic function dispatch
291 # magic function dispatch
293 magics = Dict()
292 magics = Dict()
294
293
295 # A registry of the original objects that we've been given holding magics.
294 # A registry of the original objects that we've been given holding magics.
296 registry = Dict()
295 registry = Dict()
297
296
298 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
297 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
299
298
300 auto_magic = Bool(True, help=
299 auto_magic = Bool(True, help=
301 "Automatically call line magics without requiring explicit % prefix"
300 "Automatically call line magics without requiring explicit % prefix"
302 ).tag(config=True)
301 ).tag(config=True)
303 @observe('auto_magic')
302 @observe('auto_magic')
304 def _auto_magic_changed(self, change):
303 def _auto_magic_changed(self, change):
305 self.shell.automagic = change['new']
304 self.shell.automagic = change['new']
306
305
307 _auto_status = [
306 _auto_status = [
308 'Automagic is OFF, % prefix IS needed for line magics.',
307 'Automagic is OFF, % prefix IS needed for line magics.',
309 'Automagic is ON, % prefix IS NOT needed for line magics.']
308 'Automagic is ON, % prefix IS NOT needed for line magics.']
310
309
311 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
310 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
312
311
313 def __init__(self, shell=None, config=None, user_magics=None, **traits):
312 def __init__(self, shell=None, config=None, user_magics=None, **traits):
314
313
315 super(MagicsManager, self).__init__(shell=shell, config=config,
314 super(MagicsManager, self).__init__(shell=shell, config=config,
316 user_magics=user_magics, **traits)
315 user_magics=user_magics, **traits)
317 self.magics = dict(line={}, cell={})
316 self.magics = dict(line={}, cell={})
318 # Let's add the user_magics to the registry for uniformity, so *all*
317 # Let's add the user_magics to the registry for uniformity, so *all*
319 # registered magic containers can be found there.
318 # registered magic containers can be found there.
320 self.registry[user_magics.__class__.__name__] = user_magics
319 self.registry[user_magics.__class__.__name__] = user_magics
321
320
322 def auto_status(self):
321 def auto_status(self):
323 """Return descriptive string with automagic status."""
322 """Return descriptive string with automagic status."""
324 return self._auto_status[self.auto_magic]
323 return self._auto_status[self.auto_magic]
325
324
326 def lsmagic(self):
325 def lsmagic(self):
327 """Return a dict of currently available magic functions.
326 """Return a dict of currently available magic functions.
328
327
329 The return dict has the keys 'line' and 'cell', corresponding to the
328 The return dict has the keys 'line' and 'cell', corresponding to the
330 two types of magics we support. Each value is a list of names.
329 two types of magics we support. Each value is a list of names.
331 """
330 """
332 return self.magics
331 return self.magics
333
332
334 def lsmagic_docs(self, brief=False, missing=''):
333 def lsmagic_docs(self, brief=False, missing=''):
335 """Return dict of documentation of magic functions.
334 """Return dict of documentation of magic functions.
336
335
337 The return dict has the keys 'line' and 'cell', corresponding to the
336 The return dict has the keys 'line' and 'cell', corresponding to the
338 two types of magics we support. Each value is a dict keyed by magic
337 two types of magics we support. Each value is a dict keyed by magic
339 name whose value is the function docstring. If a docstring is
338 name whose value is the function docstring. If a docstring is
340 unavailable, the value of `missing` is used instead.
339 unavailable, the value of `missing` is used instead.
341
340
342 If brief is True, only the first line of each docstring will be returned.
341 If brief is True, only the first line of each docstring will be returned.
343 """
342 """
344 docs = {}
343 docs = {}
345 for m_type in self.magics:
344 for m_type in self.magics:
346 m_docs = {}
345 m_docs = {}
347 for m_name, m_func in iteritems(self.magics[m_type]):
346 for m_name, m_func in self.magics[m_type].items():
348 if m_func.__doc__:
347 if m_func.__doc__:
349 if brief:
348 if brief:
350 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
349 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
351 else:
350 else:
352 m_docs[m_name] = m_func.__doc__.rstrip()
351 m_docs[m_name] = m_func.__doc__.rstrip()
353 else:
352 else:
354 m_docs[m_name] = missing
353 m_docs[m_name] = missing
355 docs[m_type] = m_docs
354 docs[m_type] = m_docs
356 return docs
355 return docs
357
356
358 def register(self, *magic_objects):
357 def register(self, *magic_objects):
359 """Register one or more instances of Magics.
358 """Register one or more instances of Magics.
360
359
361 Take one or more classes or instances of classes that subclass the main
360 Take one or more classes or instances of classes that subclass the main
362 `core.Magic` class, and register them with IPython to use the magic
361 `core.Magic` class, and register them with IPython to use the magic
363 functions they provide. The registration process will then ensure that
362 functions they provide. The registration process will then ensure that
364 any methods that have decorated to provide line and/or cell magics will
363 any methods that have decorated to provide line and/or cell magics will
365 be recognized with the `%x`/`%%x` syntax as a line/cell magic
364 be recognized with the `%x`/`%%x` syntax as a line/cell magic
366 respectively.
365 respectively.
367
366
368 If classes are given, they will be instantiated with the default
367 If classes are given, they will be instantiated with the default
369 constructor. If your classes need a custom constructor, you should
368 constructor. If your classes need a custom constructor, you should
370 instanitate them first and pass the instance.
369 instanitate them first and pass the instance.
371
370
372 The provided arguments can be an arbitrary mix of classes and instances.
371 The provided arguments can be an arbitrary mix of classes and instances.
373
372
374 Parameters
373 Parameters
375 ----------
374 ----------
376 magic_objects : one or more classes or instances
375 magic_objects : one or more classes or instances
377 """
376 """
378 # Start by validating them to ensure they have all had their magic
377 # Start by validating them to ensure they have all had their magic
379 # methods registered at the instance level
378 # methods registered at the instance level
380 for m in magic_objects:
379 for m in magic_objects:
381 if not m.registered:
380 if not m.registered:
382 raise ValueError("Class of magics %r was constructed without "
381 raise ValueError("Class of magics %r was constructed without "
383 "the @register_magics class decorator")
382 "the @register_magics class decorator")
384 if isinstance(m, type):
383 if isinstance(m, type):
385 # If we're given an uninstantiated class
384 # If we're given an uninstantiated class
386 m = m(shell=self.shell)
385 m = m(shell=self.shell)
387
386
388 # Now that we have an instance, we can register it and update the
387 # Now that we have an instance, we can register it and update the
389 # table of callables
388 # table of callables
390 self.registry[m.__class__.__name__] = m
389 self.registry[m.__class__.__name__] = m
391 for mtype in magic_kinds:
390 for mtype in magic_kinds:
392 self.magics[mtype].update(m.magics[mtype])
391 self.magics[mtype].update(m.magics[mtype])
393
392
394 def register_function(self, func, magic_kind='line', magic_name=None):
393 def register_function(self, func, magic_kind='line', magic_name=None):
395 """Expose a standalone function as magic function for IPython.
394 """Expose a standalone function as magic function for IPython.
396
395
397 This will create an IPython magic (line, cell or both) from a
396 This will create an IPython magic (line, cell or both) from a
398 standalone function. The functions should have the following
397 standalone function. The functions should have the following
399 signatures:
398 signatures:
400
399
401 * For line magics: `def f(line)`
400 * For line magics: `def f(line)`
402 * For cell magics: `def f(line, cell)`
401 * For cell magics: `def f(line, cell)`
403 * For a function that does both: `def f(line, cell=None)`
402 * For a function that does both: `def f(line, cell=None)`
404
403
405 In the latter case, the function will be called with `cell==None` when
404 In the latter case, the function will be called with `cell==None` when
406 invoked as `%f`, and with cell as a string when invoked as `%%f`.
405 invoked as `%f`, and with cell as a string when invoked as `%%f`.
407
406
408 Parameters
407 Parameters
409 ----------
408 ----------
410 func : callable
409 func : callable
411 Function to be registered as a magic.
410 Function to be registered as a magic.
412
411
413 magic_kind : str
412 magic_kind : str
414 Kind of magic, one of 'line', 'cell' or 'line_cell'
413 Kind of magic, one of 'line', 'cell' or 'line_cell'
415
414
416 magic_name : optional str
415 magic_name : optional str
417 If given, the name the magic will have in the IPython namespace. By
416 If given, the name the magic will have in the IPython namespace. By
418 default, the name of the function itself is used.
417 default, the name of the function itself is used.
419 """
418 """
420
419
421 # Create the new method in the user_magics and register it in the
420 # Create the new method in the user_magics and register it in the
422 # global table
421 # global table
423 validate_type(magic_kind)
422 validate_type(magic_kind)
424 magic_name = func.__name__ if magic_name is None else magic_name
423 magic_name = func.__name__ if magic_name is None else magic_name
425 setattr(self.user_magics, magic_name, func)
424 setattr(self.user_magics, magic_name, func)
426 record_magic(self.magics, magic_kind, magic_name, func)
425 record_magic(self.magics, magic_kind, magic_name, func)
427
426
428 def register_alias(self, alias_name, magic_name, magic_kind='line'):
427 def register_alias(self, alias_name, magic_name, magic_kind='line'):
429 """Register an alias to a magic function.
428 """Register an alias to a magic function.
430
429
431 The alias is an instance of :class:`MagicAlias`, which holds the
430 The alias is an instance of :class:`MagicAlias`, which holds the
432 name and kind of the magic it should call. Binding is done at
431 name and kind of the magic it should call. Binding is done at
433 call time, so if the underlying magic function is changed the alias
432 call time, so if the underlying magic function is changed the alias
434 will call the new function.
433 will call the new function.
435
434
436 Parameters
435 Parameters
437 ----------
436 ----------
438 alias_name : str
437 alias_name : str
439 The name of the magic to be registered.
438 The name of the magic to be registered.
440
439
441 magic_name : str
440 magic_name : str
442 The name of an existing magic.
441 The name of an existing magic.
443
442
444 magic_kind : str
443 magic_kind : str
445 Kind of magic, one of 'line' or 'cell'
444 Kind of magic, one of 'line' or 'cell'
446 """
445 """
447
446
448 # `validate_type` is too permissive, as it allows 'line_cell'
447 # `validate_type` is too permissive, as it allows 'line_cell'
449 # which we do not handle.
448 # which we do not handle.
450 if magic_kind not in magic_kinds:
449 if magic_kind not in magic_kinds:
451 raise ValueError('magic_kind must be one of %s, %s given' %
450 raise ValueError('magic_kind must be one of %s, %s given' %
452 magic_kinds, magic_kind)
451 magic_kinds, magic_kind)
453
452
454 alias = MagicAlias(self.shell, magic_name, magic_kind)
453 alias = MagicAlias(self.shell, magic_name, magic_kind)
455 setattr(self.user_magics, alias_name, alias)
454 setattr(self.user_magics, alias_name, alias)
456 record_magic(self.magics, magic_kind, alias_name, alias)
455 record_magic(self.magics, magic_kind, alias_name, alias)
457
456
458 # Key base class that provides the central functionality for magics.
457 # Key base class that provides the central functionality for magics.
459
458
460
459
461 class Magics(Configurable):
460 class Magics(Configurable):
462 """Base class for implementing magic functions.
461 """Base class for implementing magic functions.
463
462
464 Shell functions which can be reached as %function_name. All magic
463 Shell functions which can be reached as %function_name. All magic
465 functions should accept a string, which they can parse for their own
464 functions should accept a string, which they can parse for their own
466 needs. This can make some functions easier to type, eg `%cd ../`
465 needs. This can make some functions easier to type, eg `%cd ../`
467 vs. `%cd("../")`
466 vs. `%cd("../")`
468
467
469 Classes providing magic functions need to subclass this class, and they
468 Classes providing magic functions need to subclass this class, and they
470 MUST:
469 MUST:
471
470
472 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
471 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
473 individual methods as magic functions, AND
472 individual methods as magic functions, AND
474
473
475 - Use the class decorator `@magics_class` to ensure that the magic
474 - Use the class decorator `@magics_class` to ensure that the magic
476 methods are properly registered at the instance level upon instance
475 methods are properly registered at the instance level upon instance
477 initialization.
476 initialization.
478
477
479 See :mod:`magic_functions` for examples of actual implementation classes.
478 See :mod:`magic_functions` for examples of actual implementation classes.
480 """
479 """
481 # Dict holding all command-line options for each magic.
480 # Dict holding all command-line options for each magic.
482 options_table = None
481 options_table = None
483 # Dict for the mapping of magic names to methods, set by class decorator
482 # Dict for the mapping of magic names to methods, set by class decorator
484 magics = None
483 magics = None
485 # Flag to check that the class decorator was properly applied
484 # Flag to check that the class decorator was properly applied
486 registered = False
485 registered = False
487 # Instance of IPython shell
486 # Instance of IPython shell
488 shell = None
487 shell = None
489
488
490 def __init__(self, shell=None, **kwargs):
489 def __init__(self, shell=None, **kwargs):
491 if not(self.__class__.registered):
490 if not(self.__class__.registered):
492 raise ValueError('Magics subclass without registration - '
491 raise ValueError('Magics subclass without registration - '
493 'did you forget to apply @magics_class?')
492 'did you forget to apply @magics_class?')
494 if shell is not None:
493 if shell is not None:
495 if hasattr(shell, 'configurables'):
494 if hasattr(shell, 'configurables'):
496 shell.configurables.append(self)
495 shell.configurables.append(self)
497 if hasattr(shell, 'config'):
496 if hasattr(shell, 'config'):
498 kwargs.setdefault('parent', shell)
497 kwargs.setdefault('parent', shell)
499
498
500 self.shell = shell
499 self.shell = shell
501 self.options_table = {}
500 self.options_table = {}
502 # The method decorators are run when the instance doesn't exist yet, so
501 # The method decorators are run when the instance doesn't exist yet, so
503 # they can only record the names of the methods they are supposed to
502 # they can only record the names of the methods they are supposed to
504 # grab. Only now, that the instance exists, can we create the proper
503 # grab. Only now, that the instance exists, can we create the proper
505 # mapping to bound methods. So we read the info off the original names
504 # mapping to bound methods. So we read the info off the original names
506 # table and replace each method name by the actual bound method.
505 # table and replace each method name by the actual bound method.
507 # But we mustn't clobber the *class* mapping, in case of multiple instances.
506 # But we mustn't clobber the *class* mapping, in case of multiple instances.
508 class_magics = self.magics
507 class_magics = self.magics
509 self.magics = {}
508 self.magics = {}
510 for mtype in magic_kinds:
509 for mtype in magic_kinds:
511 tab = self.magics[mtype] = {}
510 tab = self.magics[mtype] = {}
512 cls_tab = class_magics[mtype]
511 cls_tab = class_magics[mtype]
513 for magic_name, meth_name in iteritems(cls_tab):
512 for magic_name, meth_name in cls_tab.items():
514 if isinstance(meth_name, string_types):
513 if isinstance(meth_name, str):
515 # it's a method name, grab it
514 # it's a method name, grab it
516 tab[magic_name] = getattr(self, meth_name)
515 tab[magic_name] = getattr(self, meth_name)
517 else:
516 else:
518 # it's the real thing
517 # it's the real thing
519 tab[magic_name] = meth_name
518 tab[magic_name] = meth_name
520 # Configurable **needs** to be initiated at the end or the config
519 # Configurable **needs** to be initiated at the end or the config
521 # magics get screwed up.
520 # magics get screwed up.
522 super(Magics, self).__init__(**kwargs)
521 super(Magics, self).__init__(**kwargs)
523
522
524 def arg_err(self,func):
523 def arg_err(self,func):
525 """Print docstring if incorrect arguments were passed"""
524 """Print docstring if incorrect arguments were passed"""
526 print('Error in arguments:')
525 print('Error in arguments:')
527 print(oinspect.getdoc(func))
526 print(oinspect.getdoc(func))
528
527
529 def format_latex(self, strng):
528 def format_latex(self, strng):
530 """Format a string for latex inclusion."""
529 """Format a string for latex inclusion."""
531
530
532 # Characters that need to be escaped for latex:
531 # Characters that need to be escaped for latex:
533 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
532 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
534 # Magic command names as headers:
533 # Magic command names as headers:
535 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
534 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
536 re.MULTILINE)
535 re.MULTILINE)
537 # Magic commands
536 # Magic commands
538 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
537 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
539 re.MULTILINE)
538 re.MULTILINE)
540 # Paragraph continue
539 # Paragraph continue
541 par_re = re.compile(r'\\$',re.MULTILINE)
540 par_re = re.compile(r'\\$',re.MULTILINE)
542
541
543 # The "\n" symbol
542 # The "\n" symbol
544 newline_re = re.compile(r'\\n')
543 newline_re = re.compile(r'\\n')
545
544
546 # Now build the string for output:
545 # Now build the string for output:
547 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
546 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
548 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
547 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
549 strng)
548 strng)
550 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
549 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
551 strng = par_re.sub(r'\\\\',strng)
550 strng = par_re.sub(r'\\\\',strng)
552 strng = escape_re.sub(r'\\\1',strng)
551 strng = escape_re.sub(r'\\\1',strng)
553 strng = newline_re.sub(r'\\textbackslash{}n',strng)
552 strng = newline_re.sub(r'\\textbackslash{}n',strng)
554 return strng
553 return strng
555
554
556 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
555 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
557 """Parse options passed to an argument string.
556 """Parse options passed to an argument string.
558
557
559 The interface is similar to that of :func:`getopt.getopt`, but it
558 The interface is similar to that of :func:`getopt.getopt`, but it
560 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
559 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
561 and the stripped argument string still as a string.
560 and the stripped argument string still as a string.
562
561
563 arg_str is quoted as a true sys.argv vector by using shlex.split.
562 arg_str is quoted as a true sys.argv vector by using shlex.split.
564 This allows us to easily expand variables, glob files, quote
563 This allows us to easily expand variables, glob files, quote
565 arguments, etc.
564 arguments, etc.
566
565
567 Parameters
566 Parameters
568 ----------
567 ----------
569
568
570 arg_str : str
569 arg_str : str
571 The arguments to parse.
570 The arguments to parse.
572
571
573 opt_str : str
572 opt_str : str
574 The options specification.
573 The options specification.
575
574
576 mode : str, default 'string'
575 mode : str, default 'string'
577 If given as 'list', the argument string is returned as a list (split
576 If given as 'list', the argument string is returned as a list (split
578 on whitespace) instead of a string.
577 on whitespace) instead of a string.
579
578
580 list_all : bool, default False
579 list_all : bool, default False
581 Put all option values in lists. Normally only options
580 Put all option values in lists. Normally only options
582 appearing more than once are put in a list.
581 appearing more than once are put in a list.
583
582
584 posix : bool, default True
583 posix : bool, default True
585 Whether to split the input line in POSIX mode or not, as per the
584 Whether to split the input line in POSIX mode or not, as per the
586 conventions outlined in the :mod:`shlex` module from the standard
585 conventions outlined in the :mod:`shlex` module from the standard
587 library.
586 library.
588 """
587 """
589
588
590 # inject default options at the beginning of the input line
589 # inject default options at the beginning of the input line
591 caller = sys._getframe(1).f_code.co_name
590 caller = sys._getframe(1).f_code.co_name
592 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
591 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
593
592
594 mode = kw.get('mode','string')
593 mode = kw.get('mode','string')
595 if mode not in ['string','list']:
594 if mode not in ['string','list']:
596 raise ValueError('incorrect mode given: %s' % mode)
595 raise ValueError('incorrect mode given: %s' % mode)
597 # Get options
596 # Get options
598 list_all = kw.get('list_all',0)
597 list_all = kw.get('list_all',0)
599 posix = kw.get('posix', os.name == 'posix')
598 posix = kw.get('posix', os.name == 'posix')
600 strict = kw.get('strict', True)
599 strict = kw.get('strict', True)
601
600
602 # Check if we have more than one argument to warrant extra processing:
601 # Check if we have more than one argument to warrant extra processing:
603 odict = {} # Dictionary with options
602 odict = {} # Dictionary with options
604 args = arg_str.split()
603 args = arg_str.split()
605 if len(args) >= 1:
604 if len(args) >= 1:
606 # If the list of inputs only has 0 or 1 thing in it, there's no
605 # If the list of inputs only has 0 or 1 thing in it, there's no
607 # need to look for options
606 # need to look for options
608 argv = arg_split(arg_str, posix, strict)
607 argv = arg_split(arg_str, posix, strict)
609 # Do regular option processing
608 # Do regular option processing
610 try:
609 try:
611 opts,args = getopt(argv, opt_str, long_opts)
610 opts,args = getopt(argv, opt_str, long_opts)
612 except GetoptError as e:
611 except GetoptError as e:
613 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
612 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
614 " ".join(long_opts)))
613 " ".join(long_opts)))
615 for o,a in opts:
614 for o,a in opts:
616 if o.startswith('--'):
615 if o.startswith('--'):
617 o = o[2:]
616 o = o[2:]
618 else:
617 else:
619 o = o[1:]
618 o = o[1:]
620 try:
619 try:
621 odict[o].append(a)
620 odict[o].append(a)
622 except AttributeError:
621 except AttributeError:
623 odict[o] = [odict[o],a]
622 odict[o] = [odict[o],a]
624 except KeyError:
623 except KeyError:
625 if list_all:
624 if list_all:
626 odict[o] = [a]
625 odict[o] = [a]
627 else:
626 else:
628 odict[o] = a
627 odict[o] = a
629
628
630 # Prepare opts,args for return
629 # Prepare opts,args for return
631 opts = Struct(odict)
630 opts = Struct(odict)
632 if mode == 'string':
631 if mode == 'string':
633 args = ' '.join(args)
632 args = ' '.join(args)
634
633
635 return opts,args
634 return opts,args
636
635
637 def default_option(self, fn, optstr):
636 def default_option(self, fn, optstr):
638 """Make an entry in the options_table for fn, with value optstr"""
637 """Make an entry in the options_table for fn, with value optstr"""
639
638
640 if fn not in self.lsmagic():
639 if fn not in self.lsmagic():
641 error("%s is not a magic function" % fn)
640 error("%s is not a magic function" % fn)
642 self.options_table[fn] = optstr
641 self.options_table[fn] = optstr
643
642
644
643
645 class MagicAlias(object):
644 class MagicAlias(object):
646 """An alias to another magic function.
645 """An alias to another magic function.
647
646
648 An alias is determined by its magic name and magic kind. Lookup
647 An alias is determined by its magic name and magic kind. Lookup
649 is done at call time, so if the underlying magic changes the alias
648 is done at call time, so if the underlying magic changes the alias
650 will call the new function.
649 will call the new function.
651
650
652 Use the :meth:`MagicsManager.register_alias` method or the
651 Use the :meth:`MagicsManager.register_alias` method or the
653 `%alias_magic` magic function to create and register a new alias.
652 `%alias_magic` magic function to create and register a new alias.
654 """
653 """
655 def __init__(self, shell, magic_name, magic_kind):
654 def __init__(self, shell, magic_name, magic_kind):
656 self.shell = shell
655 self.shell = shell
657 self.magic_name = magic_name
656 self.magic_name = magic_name
658 self.magic_kind = magic_kind
657 self.magic_kind = magic_kind
659
658
660 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
659 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
661 self.__doc__ = "Alias for `%s`." % self.pretty_target
660 self.__doc__ = "Alias for `%s`." % self.pretty_target
662
661
663 self._in_call = False
662 self._in_call = False
664
663
665 def __call__(self, *args, **kwargs):
664 def __call__(self, *args, **kwargs):
666 """Call the magic alias."""
665 """Call the magic alias."""
667 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
666 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
668 if fn is None:
667 if fn is None:
669 raise UsageError("Magic `%s` not found." % self.pretty_target)
668 raise UsageError("Magic `%s` not found." % self.pretty_target)
670
669
671 # Protect against infinite recursion.
670 # Protect against infinite recursion.
672 if self._in_call:
671 if self._in_call:
673 raise UsageError("Infinite recursion detected; "
672 raise UsageError("Infinite recursion detected; "
674 "magic aliases cannot call themselves.")
673 "magic aliases cannot call themselves.")
675 self._in_call = True
674 self._in_call = True
676 try:
675 try:
677 return fn(*args, **kwargs)
676 return fn(*args, **kwargs)
678 finally:
677 finally:
679 self._in_call = False
678 self._in_call = False
@@ -1,581 +1,580 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3
3
4 import argparse
4 import argparse
5 import io
5 import io
6 import sys
6 import sys
7 from pprint import pformat
7 from pprint import pformat
8
8
9 from IPython.core import magic_arguments, page
9 from IPython.core import magic_arguments, page
10 from IPython.core.error import UsageError
10 from IPython.core.error import UsageError
11 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
11 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
12 from IPython.utils.text import format_screen, dedent, indent
12 from IPython.utils.text import format_screen, dedent, indent
13 from IPython.testing.skipdoctest import skip_doctest
13 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.utils.ipstruct import Struct
14 from IPython.utils.ipstruct import Struct
15 from IPython.utils.py3compat import unicode_type
16 from warnings import warn
15 from warnings import warn
17 from logging import error
16 from logging import error
18
17
19
18
20 class MagicsDisplay(object):
19 class MagicsDisplay(object):
21 def __init__(self, magics_manager):
20 def __init__(self, magics_manager):
22 self.magics_manager = magics_manager
21 self.magics_manager = magics_manager
23
22
24 def _lsmagic(self):
23 def _lsmagic(self):
25 """The main implementation of the %lsmagic"""
24 """The main implementation of the %lsmagic"""
26 mesc = magic_escapes['line']
25 mesc = magic_escapes['line']
27 cesc = magic_escapes['cell']
26 cesc = magic_escapes['cell']
28 mman = self.magics_manager
27 mman = self.magics_manager
29 magics = mman.lsmagic()
28 magics = mman.lsmagic()
30 out = ['Available line magics:',
29 out = ['Available line magics:',
31 mesc + (' '+mesc).join(sorted(magics['line'])),
30 mesc + (' '+mesc).join(sorted(magics['line'])),
32 '',
31 '',
33 'Available cell magics:',
32 'Available cell magics:',
34 cesc + (' '+cesc).join(sorted(magics['cell'])),
33 cesc + (' '+cesc).join(sorted(magics['cell'])),
35 '',
34 '',
36 mman.auto_status()]
35 mman.auto_status()]
37 return '\n'.join(out)
36 return '\n'.join(out)
38
37
39 def _repr_pretty_(self, p, cycle):
38 def _repr_pretty_(self, p, cycle):
40 p.text(self._lsmagic())
39 p.text(self._lsmagic())
41
40
42 def __str__(self):
41 def __str__(self):
43 return self._lsmagic()
42 return self._lsmagic()
44
43
45 def _jsonable(self):
44 def _jsonable(self):
46 """turn magics dict into jsonable dict of the same structure
45 """turn magics dict into jsonable dict of the same structure
47
46
48 replaces object instances with their class names as strings
47 replaces object instances with their class names as strings
49 """
48 """
50 magic_dict = {}
49 magic_dict = {}
51 mman = self.magics_manager
50 mman = self.magics_manager
52 magics = mman.lsmagic()
51 magics = mman.lsmagic()
53 for key, subdict in magics.items():
52 for key, subdict in magics.items():
54 d = {}
53 d = {}
55 magic_dict[key] = d
54 magic_dict[key] = d
56 for name, obj in subdict.items():
55 for name, obj in subdict.items():
57 try:
56 try:
58 classname = obj.__self__.__class__.__name__
57 classname = obj.__self__.__class__.__name__
59 except AttributeError:
58 except AttributeError:
60 classname = 'Other'
59 classname = 'Other'
61
60
62 d[name] = classname
61 d[name] = classname
63 return magic_dict
62 return magic_dict
64
63
65 def _repr_json_(self):
64 def _repr_json_(self):
66 return self._jsonable()
65 return self._jsonable()
67
66
68
67
69 @magics_class
68 @magics_class
70 class BasicMagics(Magics):
69 class BasicMagics(Magics):
71 """Magics that provide central IPython functionality.
70 """Magics that provide central IPython functionality.
72
71
73 These are various magics that don't fit into specific categories but that
72 These are various magics that don't fit into specific categories but that
74 are all part of the base 'IPython experience'."""
73 are all part of the base 'IPython experience'."""
75
74
76 @magic_arguments.magic_arguments()
75 @magic_arguments.magic_arguments()
77 @magic_arguments.argument(
76 @magic_arguments.argument(
78 '-l', '--line', action='store_true',
77 '-l', '--line', action='store_true',
79 help="""Create a line magic alias."""
78 help="""Create a line magic alias."""
80 )
79 )
81 @magic_arguments.argument(
80 @magic_arguments.argument(
82 '-c', '--cell', action='store_true',
81 '-c', '--cell', action='store_true',
83 help="""Create a cell magic alias."""
82 help="""Create a cell magic alias."""
84 )
83 )
85 @magic_arguments.argument(
84 @magic_arguments.argument(
86 'name',
85 'name',
87 help="""Name of the magic to be created."""
86 help="""Name of the magic to be created."""
88 )
87 )
89 @magic_arguments.argument(
88 @magic_arguments.argument(
90 'target',
89 'target',
91 help="""Name of the existing line or cell magic."""
90 help="""Name of the existing line or cell magic."""
92 )
91 )
93 @line_magic
92 @line_magic
94 def alias_magic(self, line=''):
93 def alias_magic(self, line=''):
95 """Create an alias for an existing line or cell magic.
94 """Create an alias for an existing line or cell magic.
96
95
97 Examples
96 Examples
98 --------
97 --------
99 ::
98 ::
100
99
101 In [1]: %alias_magic t timeit
100 In [1]: %alias_magic t timeit
102 Created `%t` as an alias for `%timeit`.
101 Created `%t` as an alias for `%timeit`.
103 Created `%%t` as an alias for `%%timeit`.
102 Created `%%t` as an alias for `%%timeit`.
104
103
105 In [2]: %t -n1 pass
104 In [2]: %t -n1 pass
106 1 loops, best of 3: 954 ns per loop
105 1 loops, best of 3: 954 ns per loop
107
106
108 In [3]: %%t -n1
107 In [3]: %%t -n1
109 ...: pass
108 ...: pass
110 ...:
109 ...:
111 1 loops, best of 3: 954 ns per loop
110 1 loops, best of 3: 954 ns per loop
112
111
113 In [4]: %alias_magic --cell whereami pwd
112 In [4]: %alias_magic --cell whereami pwd
114 UsageError: Cell magic function `%%pwd` not found.
113 UsageError: Cell magic function `%%pwd` not found.
115 In [5]: %alias_magic --line whereami pwd
114 In [5]: %alias_magic --line whereami pwd
116 Created `%whereami` as an alias for `%pwd`.
115 Created `%whereami` as an alias for `%pwd`.
117
116
118 In [6]: %whereami
117 In [6]: %whereami
119 Out[6]: u'/home/testuser'
118 Out[6]: u'/home/testuser'
120 """
119 """
121 args = magic_arguments.parse_argstring(self.alias_magic, line)
120 args = magic_arguments.parse_argstring(self.alias_magic, line)
122 shell = self.shell
121 shell = self.shell
123 mman = self.shell.magics_manager
122 mman = self.shell.magics_manager
124 escs = ''.join(magic_escapes.values())
123 escs = ''.join(magic_escapes.values())
125
124
126 target = args.target.lstrip(escs)
125 target = args.target.lstrip(escs)
127 name = args.name.lstrip(escs)
126 name = args.name.lstrip(escs)
128
127
129 # Find the requested magics.
128 # Find the requested magics.
130 m_line = shell.find_magic(target, 'line')
129 m_line = shell.find_magic(target, 'line')
131 m_cell = shell.find_magic(target, 'cell')
130 m_cell = shell.find_magic(target, 'cell')
132 if args.line and m_line is None:
131 if args.line and m_line is None:
133 raise UsageError('Line magic function `%s%s` not found.' %
132 raise UsageError('Line magic function `%s%s` not found.' %
134 (magic_escapes['line'], target))
133 (magic_escapes['line'], target))
135 if args.cell and m_cell is None:
134 if args.cell and m_cell is None:
136 raise UsageError('Cell magic function `%s%s` not found.' %
135 raise UsageError('Cell magic function `%s%s` not found.' %
137 (magic_escapes['cell'], target))
136 (magic_escapes['cell'], target))
138
137
139 # If --line and --cell are not specified, default to the ones
138 # If --line and --cell are not specified, default to the ones
140 # that are available.
139 # that are available.
141 if not args.line and not args.cell:
140 if not args.line and not args.cell:
142 if not m_line and not m_cell:
141 if not m_line and not m_cell:
143 raise UsageError(
142 raise UsageError(
144 'No line or cell magic with name `%s` found.' % target
143 'No line or cell magic with name `%s` found.' % target
145 )
144 )
146 args.line = bool(m_line)
145 args.line = bool(m_line)
147 args.cell = bool(m_cell)
146 args.cell = bool(m_cell)
148
147
149 if args.line:
148 if args.line:
150 mman.register_alias(name, target, 'line')
149 mman.register_alias(name, target, 'line')
151 print('Created `%s%s` as an alias for `%s%s`.' % (
150 print('Created `%s%s` as an alias for `%s%s`.' % (
152 magic_escapes['line'], name,
151 magic_escapes['line'], name,
153 magic_escapes['line'], target))
152 magic_escapes['line'], target))
154
153
155 if args.cell:
154 if args.cell:
156 mman.register_alias(name, target, 'cell')
155 mman.register_alias(name, target, 'cell')
157 print('Created `%s%s` as an alias for `%s%s`.' % (
156 print('Created `%s%s` as an alias for `%s%s`.' % (
158 magic_escapes['cell'], name,
157 magic_escapes['cell'], name,
159 magic_escapes['cell'], target))
158 magic_escapes['cell'], target))
160
159
161 @line_magic
160 @line_magic
162 def lsmagic(self, parameter_s=''):
161 def lsmagic(self, parameter_s=''):
163 """List currently available magic functions."""
162 """List currently available magic functions."""
164 return MagicsDisplay(self.shell.magics_manager)
163 return MagicsDisplay(self.shell.magics_manager)
165
164
166 def _magic_docs(self, brief=False, rest=False):
165 def _magic_docs(self, brief=False, rest=False):
167 """Return docstrings from magic functions."""
166 """Return docstrings from magic functions."""
168 mman = self.shell.magics_manager
167 mman = self.shell.magics_manager
169 docs = mman.lsmagic_docs(brief, missing='No documentation')
168 docs = mman.lsmagic_docs(brief, missing='No documentation')
170
169
171 if rest:
170 if rest:
172 format_string = '**%s%s**::\n\n%s\n\n'
171 format_string = '**%s%s**::\n\n%s\n\n'
173 else:
172 else:
174 format_string = '%s%s:\n%s\n'
173 format_string = '%s%s:\n%s\n'
175
174
176 return ''.join(
175 return ''.join(
177 [format_string % (magic_escapes['line'], fname,
176 [format_string % (magic_escapes['line'], fname,
178 indent(dedent(fndoc)))
177 indent(dedent(fndoc)))
179 for fname, fndoc in sorted(docs['line'].items())]
178 for fname, fndoc in sorted(docs['line'].items())]
180 +
179 +
181 [format_string % (magic_escapes['cell'], fname,
180 [format_string % (magic_escapes['cell'], fname,
182 indent(dedent(fndoc)))
181 indent(dedent(fndoc)))
183 for fname, fndoc in sorted(docs['cell'].items())]
182 for fname, fndoc in sorted(docs['cell'].items())]
184 )
183 )
185
184
186 @line_magic
185 @line_magic
187 def magic(self, parameter_s=''):
186 def magic(self, parameter_s=''):
188 """Print information about the magic function system.
187 """Print information about the magic function system.
189
188
190 Supported formats: -latex, -brief, -rest
189 Supported formats: -latex, -brief, -rest
191 """
190 """
192
191
193 mode = ''
192 mode = ''
194 try:
193 try:
195 mode = parameter_s.split()[0][1:]
194 mode = parameter_s.split()[0][1:]
196 except IndexError:
195 except IndexError:
197 pass
196 pass
198
197
199 brief = (mode == 'brief')
198 brief = (mode == 'brief')
200 rest = (mode == 'rest')
199 rest = (mode == 'rest')
201 magic_docs = self._magic_docs(brief, rest)
200 magic_docs = self._magic_docs(brief, rest)
202
201
203 if mode == 'latex':
202 if mode == 'latex':
204 print(self.format_latex(magic_docs))
203 print(self.format_latex(magic_docs))
205 return
204 return
206 else:
205 else:
207 magic_docs = format_screen(magic_docs)
206 magic_docs = format_screen(magic_docs)
208
207
209 out = ["""
208 out = ["""
210 IPython's 'magic' functions
209 IPython's 'magic' functions
211 ===========================
210 ===========================
212
211
213 The magic function system provides a series of functions which allow you to
212 The magic function system provides a series of functions which allow you to
214 control the behavior of IPython itself, plus a lot of system-type
213 control the behavior of IPython itself, plus a lot of system-type
215 features. There are two kinds of magics, line-oriented and cell-oriented.
214 features. There are two kinds of magics, line-oriented and cell-oriented.
216
215
217 Line magics are prefixed with the % character and work much like OS
216 Line magics are prefixed with the % character and work much like OS
218 command-line calls: they get as an argument the rest of the line, where
217 command-line calls: they get as an argument the rest of the line, where
219 arguments are passed without parentheses or quotes. For example, this will
218 arguments are passed without parentheses or quotes. For example, this will
220 time the given statement::
219 time the given statement::
221
220
222 %timeit range(1000)
221 %timeit range(1000)
223
222
224 Cell magics are prefixed with a double %%, and they are functions that get as
223 Cell magics are prefixed with a double %%, and they are functions that get as
225 an argument not only the rest of the line, but also the lines below it in a
224 an argument not only the rest of the line, but also the lines below it in a
226 separate argument. These magics are called with two arguments: the rest of the
225 separate argument. These magics are called with two arguments: the rest of the
227 call line and the body of the cell, consisting of the lines below the first.
226 call line and the body of the cell, consisting of the lines below the first.
228 For example::
227 For example::
229
228
230 %%timeit x = numpy.random.randn((100, 100))
229 %%timeit x = numpy.random.randn((100, 100))
231 numpy.linalg.svd(x)
230 numpy.linalg.svd(x)
232
231
233 will time the execution of the numpy svd routine, running the assignment of x
232 will time the execution of the numpy svd routine, running the assignment of x
234 as part of the setup phase, which is not timed.
233 as part of the setup phase, which is not timed.
235
234
236 In a line-oriented client (the terminal or Qt console IPython), starting a new
235 In a line-oriented client (the terminal or Qt console IPython), starting a new
237 input with %% will automatically enter cell mode, and IPython will continue
236 input with %% will automatically enter cell mode, and IPython will continue
238 reading input until a blank line is given. In the notebook, simply type the
237 reading input until a blank line is given. In the notebook, simply type the
239 whole cell as one entity, but keep in mind that the %% escape can only be at
238 whole cell as one entity, but keep in mind that the %% escape can only be at
240 the very start of the cell.
239 the very start of the cell.
241
240
242 NOTE: If you have 'automagic' enabled (via the command line option or with the
241 NOTE: If you have 'automagic' enabled (via the command line option or with the
243 %automagic function), you don't need to type in the % explicitly for line
242 %automagic function), you don't need to type in the % explicitly for line
244 magics; cell magics always require an explicit '%%' escape. By default,
243 magics; cell magics always require an explicit '%%' escape. By default,
245 IPython ships with automagic on, so you should only rarely need the % escape.
244 IPython ships with automagic on, so you should only rarely need the % escape.
246
245
247 Example: typing '%cd mydir' (without the quotes) changes your working directory
246 Example: typing '%cd mydir' (without the quotes) changes your working directory
248 to 'mydir', if it exists.
247 to 'mydir', if it exists.
249
248
250 For a list of the available magic functions, use %lsmagic. For a description
249 For a list of the available magic functions, use %lsmagic. For a description
251 of any of them, type %magic_name?, e.g. '%cd?'.
250 of any of them, type %magic_name?, e.g. '%cd?'.
252
251
253 Currently the magic system has the following functions:""",
252 Currently the magic system has the following functions:""",
254 magic_docs,
253 magic_docs,
255 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
254 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
256 str(self.lsmagic()),
255 str(self.lsmagic()),
257 ]
256 ]
258 page.page('\n'.join(out))
257 page.page('\n'.join(out))
259
258
260
259
261 @line_magic
260 @line_magic
262 def page(self, parameter_s=''):
261 def page(self, parameter_s=''):
263 """Pretty print the object and display it through a pager.
262 """Pretty print the object and display it through a pager.
264
263
265 %page [options] OBJECT
264 %page [options] OBJECT
266
265
267 If no object is given, use _ (last output).
266 If no object is given, use _ (last output).
268
267
269 Options:
268 Options:
270
269
271 -r: page str(object), don't pretty-print it."""
270 -r: page str(object), don't pretty-print it."""
272
271
273 # After a function contributed by Olivier Aubert, slightly modified.
272 # After a function contributed by Olivier Aubert, slightly modified.
274
273
275 # Process options/args
274 # Process options/args
276 opts, args = self.parse_options(parameter_s, 'r')
275 opts, args = self.parse_options(parameter_s, 'r')
277 raw = 'r' in opts
276 raw = 'r' in opts
278
277
279 oname = args and args or '_'
278 oname = args and args or '_'
280 info = self.shell._ofind(oname)
279 info = self.shell._ofind(oname)
281 if info['found']:
280 if info['found']:
282 txt = (raw and str or pformat)( info['obj'] )
281 txt = (raw and str or pformat)( info['obj'] )
283 page.page(txt)
282 page.page(txt)
284 else:
283 else:
285 print('Object `%s` not found' % oname)
284 print('Object `%s` not found' % oname)
286
285
287 @line_magic
286 @line_magic
288 def profile(self, parameter_s=''):
287 def profile(self, parameter_s=''):
289 """Print your currently active IPython profile.
288 """Print your currently active IPython profile.
290
289
291 See Also
290 See Also
292 --------
291 --------
293 prun : run code using the Python profiler
292 prun : run code using the Python profiler
294 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
293 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
295 """
294 """
296 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
295 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
297 from IPython.core.application import BaseIPythonApplication
296 from IPython.core.application import BaseIPythonApplication
298 if BaseIPythonApplication.initialized():
297 if BaseIPythonApplication.initialized():
299 print(BaseIPythonApplication.instance().profile)
298 print(BaseIPythonApplication.instance().profile)
300 else:
299 else:
301 error("profile is an application-level value, but you don't appear to be in an IPython application")
300 error("profile is an application-level value, but you don't appear to be in an IPython application")
302
301
303 @line_magic
302 @line_magic
304 def pprint(self, parameter_s=''):
303 def pprint(self, parameter_s=''):
305 """Toggle pretty printing on/off."""
304 """Toggle pretty printing on/off."""
306 ptformatter = self.shell.display_formatter.formatters['text/plain']
305 ptformatter = self.shell.display_formatter.formatters['text/plain']
307 ptformatter.pprint = bool(1 - ptformatter.pprint)
306 ptformatter.pprint = bool(1 - ptformatter.pprint)
308 print('Pretty printing has been turned',
307 print('Pretty printing has been turned',
309 ['OFF','ON'][ptformatter.pprint])
308 ['OFF','ON'][ptformatter.pprint])
310
309
311 @line_magic
310 @line_magic
312 def colors(self, parameter_s=''):
311 def colors(self, parameter_s=''):
313 """Switch color scheme for prompts, info system and exception handlers.
312 """Switch color scheme for prompts, info system and exception handlers.
314
313
315 Currently implemented schemes: NoColor, Linux, LightBG.
314 Currently implemented schemes: NoColor, Linux, LightBG.
316
315
317 Color scheme names are not case-sensitive.
316 Color scheme names are not case-sensitive.
318
317
319 Examples
318 Examples
320 --------
319 --------
321 To get a plain black and white terminal::
320 To get a plain black and white terminal::
322
321
323 %colors nocolor
322 %colors nocolor
324 """
323 """
325 def color_switch_err(name):
324 def color_switch_err(name):
326 warn('Error changing %s color schemes.\n%s' %
325 warn('Error changing %s color schemes.\n%s' %
327 (name, sys.exc_info()[1]), stacklevel=2)
326 (name, sys.exc_info()[1]), stacklevel=2)
328
327
329
328
330 new_scheme = parameter_s.strip()
329 new_scheme = parameter_s.strip()
331 if not new_scheme:
330 if not new_scheme:
332 raise UsageError(
331 raise UsageError(
333 "%colors: you must specify a color scheme. See '%colors?'")
332 "%colors: you must specify a color scheme. See '%colors?'")
334 # local shortcut
333 # local shortcut
335 shell = self.shell
334 shell = self.shell
336
335
337 # Set shell colour scheme
336 # Set shell colour scheme
338 try:
337 try:
339 shell.colors = new_scheme
338 shell.colors = new_scheme
340 shell.refresh_style()
339 shell.refresh_style()
341 except:
340 except:
342 color_switch_err('shell')
341 color_switch_err('shell')
343
342
344 # Set exception colors
343 # Set exception colors
345 try:
344 try:
346 shell.InteractiveTB.set_colors(scheme = new_scheme)
345 shell.InteractiveTB.set_colors(scheme = new_scheme)
347 shell.SyntaxTB.set_colors(scheme = new_scheme)
346 shell.SyntaxTB.set_colors(scheme = new_scheme)
348 except:
347 except:
349 color_switch_err('exception')
348 color_switch_err('exception')
350
349
351 # Set info (for 'object?') colors
350 # Set info (for 'object?') colors
352 if shell.color_info:
351 if shell.color_info:
353 try:
352 try:
354 shell.inspector.set_active_scheme(new_scheme)
353 shell.inspector.set_active_scheme(new_scheme)
355 except:
354 except:
356 color_switch_err('object inspector')
355 color_switch_err('object inspector')
357 else:
356 else:
358 shell.inspector.set_active_scheme('NoColor')
357 shell.inspector.set_active_scheme('NoColor')
359
358
360 @line_magic
359 @line_magic
361 def xmode(self, parameter_s=''):
360 def xmode(self, parameter_s=''):
362 """Switch modes for the exception handlers.
361 """Switch modes for the exception handlers.
363
362
364 Valid modes: Plain, Context and Verbose.
363 Valid modes: Plain, Context and Verbose.
365
364
366 If called without arguments, acts as a toggle."""
365 If called without arguments, acts as a toggle."""
367
366
368 def xmode_switch_err(name):
367 def xmode_switch_err(name):
369 warn('Error changing %s exception modes.\n%s' %
368 warn('Error changing %s exception modes.\n%s' %
370 (name,sys.exc_info()[1]))
369 (name,sys.exc_info()[1]))
371
370
372 shell = self.shell
371 shell = self.shell
373 new_mode = parameter_s.strip().capitalize()
372 new_mode = parameter_s.strip().capitalize()
374 try:
373 try:
375 shell.InteractiveTB.set_mode(mode=new_mode)
374 shell.InteractiveTB.set_mode(mode=new_mode)
376 print('Exception reporting mode:',shell.InteractiveTB.mode)
375 print('Exception reporting mode:',shell.InteractiveTB.mode)
377 except:
376 except:
378 xmode_switch_err('user')
377 xmode_switch_err('user')
379
378
380 @line_magic
379 @line_magic
381 def quickref(self,arg):
380 def quickref(self,arg):
382 """ Show a quick reference sheet """
381 """ Show a quick reference sheet """
383 from IPython.core.usage import quick_reference
382 from IPython.core.usage import quick_reference
384 qr = quick_reference + self._magic_docs(brief=True)
383 qr = quick_reference + self._magic_docs(brief=True)
385 page.page(qr)
384 page.page(qr)
386
385
387 @line_magic
386 @line_magic
388 def doctest_mode(self, parameter_s=''):
387 def doctest_mode(self, parameter_s=''):
389 """Toggle doctest mode on and off.
388 """Toggle doctest mode on and off.
390
389
391 This mode is intended to make IPython behave as much as possible like a
390 This mode is intended to make IPython behave as much as possible like a
392 plain Python shell, from the perspective of how its prompts, exceptions
391 plain Python shell, from the perspective of how its prompts, exceptions
393 and output look. This makes it easy to copy and paste parts of a
392 and output look. This makes it easy to copy and paste parts of a
394 session into doctests. It does so by:
393 session into doctests. It does so by:
395
394
396 - Changing the prompts to the classic ``>>>`` ones.
395 - Changing the prompts to the classic ``>>>`` ones.
397 - Changing the exception reporting mode to 'Plain'.
396 - Changing the exception reporting mode to 'Plain'.
398 - Disabling pretty-printing of output.
397 - Disabling pretty-printing of output.
399
398
400 Note that IPython also supports the pasting of code snippets that have
399 Note that IPython also supports the pasting of code snippets that have
401 leading '>>>' and '...' prompts in them. This means that you can paste
400 leading '>>>' and '...' prompts in them. This means that you can paste
402 doctests from files or docstrings (even if they have leading
401 doctests from files or docstrings (even if they have leading
403 whitespace), and the code will execute correctly. You can then use
402 whitespace), and the code will execute correctly. You can then use
404 '%history -t' to see the translated history; this will give you the
403 '%history -t' to see the translated history; this will give you the
405 input after removal of all the leading prompts and whitespace, which
404 input after removal of all the leading prompts and whitespace, which
406 can be pasted back into an editor.
405 can be pasted back into an editor.
407
406
408 With these features, you can switch into this mode easily whenever you
407 With these features, you can switch into this mode easily whenever you
409 need to do testing and changes to doctests, without having to leave
408 need to do testing and changes to doctests, without having to leave
410 your existing IPython session.
409 your existing IPython session.
411 """
410 """
412
411
413 # Shorthands
412 # Shorthands
414 shell = self.shell
413 shell = self.shell
415 meta = shell.meta
414 meta = shell.meta
416 disp_formatter = self.shell.display_formatter
415 disp_formatter = self.shell.display_formatter
417 ptformatter = disp_formatter.formatters['text/plain']
416 ptformatter = disp_formatter.formatters['text/plain']
418 # dstore is a data store kept in the instance metadata bag to track any
417 # dstore is a data store kept in the instance metadata bag to track any
419 # changes we make, so we can undo them later.
418 # changes we make, so we can undo them later.
420 dstore = meta.setdefault('doctest_mode',Struct())
419 dstore = meta.setdefault('doctest_mode',Struct())
421 save_dstore = dstore.setdefault
420 save_dstore = dstore.setdefault
422
421
423 # save a few values we'll need to recover later
422 # save a few values we'll need to recover later
424 mode = save_dstore('mode',False)
423 mode = save_dstore('mode',False)
425 save_dstore('rc_pprint',ptformatter.pprint)
424 save_dstore('rc_pprint',ptformatter.pprint)
426 save_dstore('xmode',shell.InteractiveTB.mode)
425 save_dstore('xmode',shell.InteractiveTB.mode)
427 save_dstore('rc_separate_out',shell.separate_out)
426 save_dstore('rc_separate_out',shell.separate_out)
428 save_dstore('rc_separate_out2',shell.separate_out2)
427 save_dstore('rc_separate_out2',shell.separate_out2)
429 save_dstore('rc_separate_in',shell.separate_in)
428 save_dstore('rc_separate_in',shell.separate_in)
430 save_dstore('rc_active_types',disp_formatter.active_types)
429 save_dstore('rc_active_types',disp_formatter.active_types)
431
430
432 if not mode:
431 if not mode:
433 # turn on
432 # turn on
434
433
435 # Prompt separators like plain python
434 # Prompt separators like plain python
436 shell.separate_in = ''
435 shell.separate_in = ''
437 shell.separate_out = ''
436 shell.separate_out = ''
438 shell.separate_out2 = ''
437 shell.separate_out2 = ''
439
438
440
439
441 ptformatter.pprint = False
440 ptformatter.pprint = False
442 disp_formatter.active_types = ['text/plain']
441 disp_formatter.active_types = ['text/plain']
443
442
444 shell.magic('xmode Plain')
443 shell.magic('xmode Plain')
445 else:
444 else:
446 # turn off
445 # turn off
447 shell.separate_in = dstore.rc_separate_in
446 shell.separate_in = dstore.rc_separate_in
448
447
449 shell.separate_out = dstore.rc_separate_out
448 shell.separate_out = dstore.rc_separate_out
450 shell.separate_out2 = dstore.rc_separate_out2
449 shell.separate_out2 = dstore.rc_separate_out2
451
450
452 ptformatter.pprint = dstore.rc_pprint
451 ptformatter.pprint = dstore.rc_pprint
453 disp_formatter.active_types = dstore.rc_active_types
452 disp_formatter.active_types = dstore.rc_active_types
454
453
455 shell.magic('xmode ' + dstore.xmode)
454 shell.magic('xmode ' + dstore.xmode)
456
455
457 # mode here is the state before we switch; switch_doctest_mode takes
456 # mode here is the state before we switch; switch_doctest_mode takes
458 # the mode we're switching to.
457 # the mode we're switching to.
459 shell.switch_doctest_mode(not mode)
458 shell.switch_doctest_mode(not mode)
460
459
461 # Store new mode and inform
460 # Store new mode and inform
462 dstore.mode = bool(not mode)
461 dstore.mode = bool(not mode)
463 mode_label = ['OFF','ON'][dstore.mode]
462 mode_label = ['OFF','ON'][dstore.mode]
464 print('Doctest mode is:', mode_label)
463 print('Doctest mode is:', mode_label)
465
464
466 @line_magic
465 @line_magic
467 def gui(self, parameter_s=''):
466 def gui(self, parameter_s=''):
468 """Enable or disable IPython GUI event loop integration.
467 """Enable or disable IPython GUI event loop integration.
469
468
470 %gui [GUINAME]
469 %gui [GUINAME]
471
470
472 This magic replaces IPython's threaded shells that were activated
471 This magic replaces IPython's threaded shells that were activated
473 using the (pylab/wthread/etc.) command line flags. GUI toolkits
472 using the (pylab/wthread/etc.) command line flags. GUI toolkits
474 can now be enabled at runtime and keyboard
473 can now be enabled at runtime and keyboard
475 interrupts should work without any problems. The following toolkits
474 interrupts should work without any problems. The following toolkits
476 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
475 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
477
476
478 %gui wx # enable wxPython event loop integration
477 %gui wx # enable wxPython event loop integration
479 %gui qt4|qt # enable PyQt4 event loop integration
478 %gui qt4|qt # enable PyQt4 event loop integration
480 %gui qt5 # enable PyQt5 event loop integration
479 %gui qt5 # enable PyQt5 event loop integration
481 %gui gtk # enable PyGTK event loop integration
480 %gui gtk # enable PyGTK event loop integration
482 %gui gtk3 # enable Gtk3 event loop integration
481 %gui gtk3 # enable Gtk3 event loop integration
483 %gui tk # enable Tk event loop integration
482 %gui tk # enable Tk event loop integration
484 %gui osx # enable Cocoa event loop integration
483 %gui osx # enable Cocoa event loop integration
485 # (requires %matplotlib 1.1)
484 # (requires %matplotlib 1.1)
486 %gui # disable all event loop integration
485 %gui # disable all event loop integration
487
486
488 WARNING: after any of these has been called you can simply create
487 WARNING: after any of these has been called you can simply create
489 an application object, but DO NOT start the event loop yourself, as
488 an application object, but DO NOT start the event loop yourself, as
490 we have already handled that.
489 we have already handled that.
491 """
490 """
492 opts, arg = self.parse_options(parameter_s, '')
491 opts, arg = self.parse_options(parameter_s, '')
493 if arg=='': arg = None
492 if arg=='': arg = None
494 try:
493 try:
495 return self.shell.enable_gui(arg)
494 return self.shell.enable_gui(arg)
496 except Exception as e:
495 except Exception as e:
497 # print simple error message, rather than traceback if we can't
496 # print simple error message, rather than traceback if we can't
498 # hook up the GUI
497 # hook up the GUI
499 error(str(e))
498 error(str(e))
500
499
501 @skip_doctest
500 @skip_doctest
502 @line_magic
501 @line_magic
503 def precision(self, s=''):
502 def precision(self, s=''):
504 """Set floating point precision for pretty printing.
503 """Set floating point precision for pretty printing.
505
504
506 Can set either integer precision or a format string.
505 Can set either integer precision or a format string.
507
506
508 If numpy has been imported and precision is an int,
507 If numpy has been imported and precision is an int,
509 numpy display precision will also be set, via ``numpy.set_printoptions``.
508 numpy display precision will also be set, via ``numpy.set_printoptions``.
510
509
511 If no argument is given, defaults will be restored.
510 If no argument is given, defaults will be restored.
512
511
513 Examples
512 Examples
514 --------
513 --------
515 ::
514 ::
516
515
517 In [1]: from math import pi
516 In [1]: from math import pi
518
517
519 In [2]: %precision 3
518 In [2]: %precision 3
520 Out[2]: u'%.3f'
519 Out[2]: u'%.3f'
521
520
522 In [3]: pi
521 In [3]: pi
523 Out[3]: 3.142
522 Out[3]: 3.142
524
523
525 In [4]: %precision %i
524 In [4]: %precision %i
526 Out[4]: u'%i'
525 Out[4]: u'%i'
527
526
528 In [5]: pi
527 In [5]: pi
529 Out[5]: 3
528 Out[5]: 3
530
529
531 In [6]: %precision %e
530 In [6]: %precision %e
532 Out[6]: u'%e'
531 Out[6]: u'%e'
533
532
534 In [7]: pi**10
533 In [7]: pi**10
535 Out[7]: 9.364805e+04
534 Out[7]: 9.364805e+04
536
535
537 In [8]: %precision
536 In [8]: %precision
538 Out[8]: u'%r'
537 Out[8]: u'%r'
539
538
540 In [9]: pi**10
539 In [9]: pi**10
541 Out[9]: 93648.047476082982
540 Out[9]: 93648.047476082982
542 """
541 """
543 ptformatter = self.shell.display_formatter.formatters['text/plain']
542 ptformatter = self.shell.display_formatter.formatters['text/plain']
544 ptformatter.float_precision = s
543 ptformatter.float_precision = s
545 return ptformatter.float_format
544 return ptformatter.float_format
546
545
547 @magic_arguments.magic_arguments()
546 @magic_arguments.magic_arguments()
548 @magic_arguments.argument(
547 @magic_arguments.argument(
549 '-e', '--export', action='store_true', default=False,
548 '-e', '--export', action='store_true', default=False,
550 help=argparse.SUPPRESS
549 help=argparse.SUPPRESS
551 )
550 )
552 @magic_arguments.argument(
551 @magic_arguments.argument(
553 'filename', type=unicode_type,
552 'filename', type=str,
554 help='Notebook name or filename'
553 help='Notebook name or filename'
555 )
554 )
556 @line_magic
555 @line_magic
557 def notebook(self, s):
556 def notebook(self, s):
558 """Export and convert IPython notebooks.
557 """Export and convert IPython notebooks.
559
558
560 This function can export the current IPython history to a notebook file.
559 This function can export the current IPython history to a notebook file.
561 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
560 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
562
561
563 The -e or --export flag is deprecated in IPython 5.2, and will be
562 The -e or --export flag is deprecated in IPython 5.2, and will be
564 removed in the future.
563 removed in the future.
565 """
564 """
566 args = magic_arguments.parse_argstring(self.notebook, s)
565 args = magic_arguments.parse_argstring(self.notebook, s)
567
566
568 from nbformat import write, v4
567 from nbformat import write, v4
569
568
570 cells = []
569 cells = []
571 hist = list(self.shell.history_manager.get_range())
570 hist = list(self.shell.history_manager.get_range())
572 if(len(hist)<=1):
571 if(len(hist)<=1):
573 raise ValueError('History is empty, cannot export')
572 raise ValueError('History is empty, cannot export')
574 for session, execution_count, source in hist[:-1]:
573 for session, execution_count, source in hist[:-1]:
575 cells.append(v4.new_code_cell(
574 cells.append(v4.new_code_cell(
576 execution_count=execution_count,
575 execution_count=execution_count,
577 source=source
576 source=source
578 ))
577 ))
579 nb = v4.new_notebook(cells=cells)
578 nb = v4.new_notebook(cells=cells)
580 with io.open(args.filename, 'w', encoding='utf-8') as f:
579 with io.open(args.filename, 'w', encoding='utf-8') as f:
581 write(nb, f, version=4)
580 write(nb, f, version=4)
@@ -1,744 +1,743 b''
1 """Implementation of code management magic functions.
1 """Implementation of code management magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import inspect
16 import inspect
17 import io
17 import io
18 import os
18 import os
19 import re
19 import re
20 import sys
20 import sys
21 import ast
21 import ast
22 from itertools import chain
22 from itertools import chain
23
23
24 # Our own packages
24 # Our own packages
25 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
25 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
26 from IPython.core.macro import Macro
26 from IPython.core.macro import Macro
27 from IPython.core.magic import Magics, magics_class, line_magic
27 from IPython.core.magic import Magics, magics_class, line_magic
28 from IPython.core.oinspect import find_file, find_source_lines
28 from IPython.core.oinspect import find_file, find_source_lines
29 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.testing.skipdoctest import skip_doctest
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31 from IPython.utils.py3compat import string_types
32 from IPython.utils.contexts import preserve_keys
31 from IPython.utils.contexts import preserve_keys
33 from IPython.utils.path import get_py_filename
32 from IPython.utils.path import get_py_filename
34 from warnings import warn
33 from warnings import warn
35 from logging import error
34 from logging import error
36 from IPython.utils.text import get_text_list
35 from IPython.utils.text import get_text_list
37
36
38 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
39 # Magic implementation classes
38 # Magic implementation classes
40 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
41
40
42 # Used for exception handling in magic_edit
41 # Used for exception handling in magic_edit
43 class MacroToEdit(ValueError): pass
42 class MacroToEdit(ValueError): pass
44
43
45 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
44 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
46
45
47 # To match, e.g. 8-10 1:5 :10 3-
46 # To match, e.g. 8-10 1:5 :10 3-
48 range_re = re.compile(r"""
47 range_re = re.compile(r"""
49 (?P<start>\d+)?
48 (?P<start>\d+)?
50 ((?P<sep>[\-:])
49 ((?P<sep>[\-:])
51 (?P<end>\d+)?)?
50 (?P<end>\d+)?)?
52 $""", re.VERBOSE)
51 $""", re.VERBOSE)
53
52
54
53
55 def extract_code_ranges(ranges_str):
54 def extract_code_ranges(ranges_str):
56 """Turn a string of range for %%load into 2-tuples of (start, stop)
55 """Turn a string of range for %%load into 2-tuples of (start, stop)
57 ready to use as a slice of the content splitted by lines.
56 ready to use as a slice of the content splitted by lines.
58
57
59 Examples
58 Examples
60 --------
59 --------
61 list(extract_input_ranges("5-10 2"))
60 list(extract_input_ranges("5-10 2"))
62 [(4, 10), (1, 2)]
61 [(4, 10), (1, 2)]
63 """
62 """
64 for range_str in ranges_str.split():
63 for range_str in ranges_str.split():
65 rmatch = range_re.match(range_str)
64 rmatch = range_re.match(range_str)
66 if not rmatch:
65 if not rmatch:
67 continue
66 continue
68 sep = rmatch.group("sep")
67 sep = rmatch.group("sep")
69 start = rmatch.group("start")
68 start = rmatch.group("start")
70 end = rmatch.group("end")
69 end = rmatch.group("end")
71
70
72 if sep == '-':
71 if sep == '-':
73 start = int(start) - 1 if start else None
72 start = int(start) - 1 if start else None
74 end = int(end) if end else None
73 end = int(end) if end else None
75 elif sep == ':':
74 elif sep == ':':
76 start = int(start) - 1 if start else None
75 start = int(start) - 1 if start else None
77 end = int(end) - 1 if end else None
76 end = int(end) - 1 if end else None
78 else:
77 else:
79 end = int(start)
78 end = int(start)
80 start = int(start) - 1
79 start = int(start) - 1
81 yield (start, end)
80 yield (start, end)
82
81
83
82
84 @skip_doctest
83 @skip_doctest
85 def extract_symbols(code, symbols):
84 def extract_symbols(code, symbols):
86 """
85 """
87 Return a tuple (blocks, not_found)
86 Return a tuple (blocks, not_found)
88 where ``blocks`` is a list of code fragments
87 where ``blocks`` is a list of code fragments
89 for each symbol parsed from code, and ``not_found`` are
88 for each symbol parsed from code, and ``not_found`` are
90 symbols not found in the code.
89 symbols not found in the code.
91
90
92 For example::
91 For example::
93
92
94 >>> code = '''a = 10
93 >>> code = '''a = 10
95
94
96 def b(): return 42
95 def b(): return 42
97
96
98 class A: pass'''
97 class A: pass'''
99
98
100 >>> extract_symbols(code, 'A,b,z')
99 >>> extract_symbols(code, 'A,b,z')
101 (["class A: pass", "def b(): return 42"], ['z'])
100 (["class A: pass", "def b(): return 42"], ['z'])
102 """
101 """
103 symbols = symbols.split(',')
102 symbols = symbols.split(',')
104
103
105 # this will raise SyntaxError if code isn't valid Python
104 # this will raise SyntaxError if code isn't valid Python
106 py_code = ast.parse(code)
105 py_code = ast.parse(code)
107
106
108 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
107 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
109 code = code.split('\n')
108 code = code.split('\n')
110
109
111 symbols_lines = {}
110 symbols_lines = {}
112
111
113 # we already know the start_lineno of each symbol (marks).
112 # we already know the start_lineno of each symbol (marks).
114 # To find each end_lineno, we traverse in reverse order until each
113 # To find each end_lineno, we traverse in reverse order until each
115 # non-blank line
114 # non-blank line
116 end = len(code)
115 end = len(code)
117 for name, start in reversed(marks):
116 for name, start in reversed(marks):
118 while not code[end - 1].strip():
117 while not code[end - 1].strip():
119 end -= 1
118 end -= 1
120 if name:
119 if name:
121 symbols_lines[name] = (start - 1, end)
120 symbols_lines[name] = (start - 1, end)
122 end = start - 1
121 end = start - 1
123
122
124 # Now symbols_lines is a map
123 # Now symbols_lines is a map
125 # {'symbol_name': (start_lineno, end_lineno), ...}
124 # {'symbol_name': (start_lineno, end_lineno), ...}
126
125
127 # fill a list with chunks of codes for each requested symbol
126 # fill a list with chunks of codes for each requested symbol
128 blocks = []
127 blocks = []
129 not_found = []
128 not_found = []
130 for symbol in symbols:
129 for symbol in symbols:
131 if symbol in symbols_lines:
130 if symbol in symbols_lines:
132 start, end = symbols_lines[symbol]
131 start, end = symbols_lines[symbol]
133 blocks.append('\n'.join(code[start:end]) + '\n')
132 blocks.append('\n'.join(code[start:end]) + '\n')
134 else:
133 else:
135 not_found.append(symbol)
134 not_found.append(symbol)
136
135
137 return blocks, not_found
136 return blocks, not_found
138
137
139 def strip_initial_indent(lines):
138 def strip_initial_indent(lines):
140 """For %load, strip indent from lines until finding an unindented line.
139 """For %load, strip indent from lines until finding an unindented line.
141
140
142 https://github.com/ipython/ipython/issues/9775
141 https://github.com/ipython/ipython/issues/9775
143 """
142 """
144 indent_re = re.compile(r'\s+')
143 indent_re = re.compile(r'\s+')
145
144
146 it = iter(lines)
145 it = iter(lines)
147 first_line = next(it)
146 first_line = next(it)
148 indent_match = indent_re.match(first_line)
147 indent_match = indent_re.match(first_line)
149
148
150 if indent_match:
149 if indent_match:
151 # First line was indented
150 # First line was indented
152 indent = indent_match.group()
151 indent = indent_match.group()
153 yield first_line[len(indent):]
152 yield first_line[len(indent):]
154
153
155 for line in it:
154 for line in it:
156 if line.startswith(indent):
155 if line.startswith(indent):
157 yield line[len(indent):]
156 yield line[len(indent):]
158 else:
157 else:
159 # Less indented than the first line - stop dedenting
158 # Less indented than the first line - stop dedenting
160 yield line
159 yield line
161 break
160 break
162 else:
161 else:
163 yield first_line
162 yield first_line
164
163
165 # Pass the remaining lines through without dedenting
164 # Pass the remaining lines through without dedenting
166 for line in it:
165 for line in it:
167 yield line
166 yield line
168
167
169
168
170 class InteractivelyDefined(Exception):
169 class InteractivelyDefined(Exception):
171 """Exception for interactively defined variable in magic_edit"""
170 """Exception for interactively defined variable in magic_edit"""
172 def __init__(self, index):
171 def __init__(self, index):
173 self.index = index
172 self.index = index
174
173
175
174
176 @magics_class
175 @magics_class
177 class CodeMagics(Magics):
176 class CodeMagics(Magics):
178 """Magics related to code management (loading, saving, editing, ...)."""
177 """Magics related to code management (loading, saving, editing, ...)."""
179
178
180 def __init__(self, *args, **kwargs):
179 def __init__(self, *args, **kwargs):
181 self._knowntemps = set()
180 self._knowntemps = set()
182 super(CodeMagics, self).__init__(*args, **kwargs)
181 super(CodeMagics, self).__init__(*args, **kwargs)
183
182
184 @line_magic
183 @line_magic
185 def save(self, parameter_s=''):
184 def save(self, parameter_s=''):
186 """Save a set of lines or a macro to a given filename.
185 """Save a set of lines or a macro to a given filename.
187
186
188 Usage:\\
187 Usage:\\
189 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
188 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
190
189
191 Options:
190 Options:
192
191
193 -r: use 'raw' input. By default, the 'processed' history is used,
192 -r: use 'raw' input. By default, the 'processed' history is used,
194 so that magics are loaded in their transformed version to valid
193 so that magics are loaded in their transformed version to valid
195 Python. If this option is given, the raw input as typed as the
194 Python. If this option is given, the raw input as typed as the
196 command line is used instead.
195 command line is used instead.
197
196
198 -f: force overwrite. If file exists, %save will prompt for overwrite
197 -f: force overwrite. If file exists, %save will prompt for overwrite
199 unless -f is given.
198 unless -f is given.
200
199
201 -a: append to the file instead of overwriting it.
200 -a: append to the file instead of overwriting it.
202
201
203 This function uses the same syntax as %history for input ranges,
202 This function uses the same syntax as %history for input ranges,
204 then saves the lines to the filename you specify.
203 then saves the lines to the filename you specify.
205
204
206 It adds a '.py' extension to the file if you don't do so yourself, and
205 It adds a '.py' extension to the file if you don't do so yourself, and
207 it asks for confirmation before overwriting existing files.
206 it asks for confirmation before overwriting existing files.
208
207
209 If `-r` option is used, the default extension is `.ipy`.
208 If `-r` option is used, the default extension is `.ipy`.
210 """
209 """
211
210
212 opts,args = self.parse_options(parameter_s,'fra',mode='list')
211 opts,args = self.parse_options(parameter_s,'fra',mode='list')
213 if not args:
212 if not args:
214 raise UsageError('Missing filename.')
213 raise UsageError('Missing filename.')
215 raw = 'r' in opts
214 raw = 'r' in opts
216 force = 'f' in opts
215 force = 'f' in opts
217 append = 'a' in opts
216 append = 'a' in opts
218 mode = 'a' if append else 'w'
217 mode = 'a' if append else 'w'
219 ext = u'.ipy' if raw else u'.py'
218 ext = u'.ipy' if raw else u'.py'
220 fname, codefrom = args[0], " ".join(args[1:])
219 fname, codefrom = args[0], " ".join(args[1:])
221 if not fname.endswith((u'.py',u'.ipy')):
220 if not fname.endswith((u'.py',u'.ipy')):
222 fname += ext
221 fname += ext
223 file_exists = os.path.isfile(fname)
222 file_exists = os.path.isfile(fname)
224 if file_exists and not force and not append:
223 if file_exists and not force and not append:
225 try:
224 try:
226 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
225 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
227 except StdinNotImplementedError:
226 except StdinNotImplementedError:
228 print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
227 print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
229 return
228 return
230 if not overwrite :
229 if not overwrite :
231 print('Operation cancelled.')
230 print('Operation cancelled.')
232 return
231 return
233 try:
232 try:
234 cmds = self.shell.find_user_code(codefrom,raw)
233 cmds = self.shell.find_user_code(codefrom,raw)
235 except (TypeError, ValueError) as e:
234 except (TypeError, ValueError) as e:
236 print(e.args[0])
235 print(e.args[0])
237 return
236 return
238 out = py3compat.cast_unicode(cmds)
237 out = py3compat.cast_unicode(cmds)
239 with io.open(fname, mode, encoding="utf-8") as f:
238 with io.open(fname, mode, encoding="utf-8") as f:
240 if not file_exists or not append:
239 if not file_exists or not append:
241 f.write(u"# coding: utf-8\n")
240 f.write(u"# coding: utf-8\n")
242 f.write(out)
241 f.write(out)
243 # make sure we end on a newline
242 # make sure we end on a newline
244 if not out.endswith(u'\n'):
243 if not out.endswith(u'\n'):
245 f.write(u'\n')
244 f.write(u'\n')
246 print('The following commands were written to file `%s`:' % fname)
245 print('The following commands were written to file `%s`:' % fname)
247 print(cmds)
246 print(cmds)
248
247
249 @line_magic
248 @line_magic
250 def pastebin(self, parameter_s=''):
249 def pastebin(self, parameter_s=''):
251 """Upload code to Github's Gist paste bin, returning the URL.
250 """Upload code to Github's Gist paste bin, returning the URL.
252
251
253 Usage:\\
252 Usage:\\
254 %pastebin [-d "Custom description"] 1-7
253 %pastebin [-d "Custom description"] 1-7
255
254
256 The argument can be an input history range, a filename, or the name of a
255 The argument can be an input history range, a filename, or the name of a
257 string or macro.
256 string or macro.
258
257
259 Options:
258 Options:
260
259
261 -d: Pass a custom description for the gist. The default will say
260 -d: Pass a custom description for the gist. The default will say
262 "Pasted from IPython".
261 "Pasted from IPython".
263 """
262 """
264 opts, args = self.parse_options(parameter_s, 'd:')
263 opts, args = self.parse_options(parameter_s, 'd:')
265
264
266 try:
265 try:
267 code = self.shell.find_user_code(args)
266 code = self.shell.find_user_code(args)
268 except (ValueError, TypeError) as e:
267 except (ValueError, TypeError) as e:
269 print(e.args[0])
268 print(e.args[0])
270 return
269 return
271
270
272 # Deferred import
271 # Deferred import
273 try:
272 try:
274 from urllib.request import urlopen # Py 3
273 from urllib.request import urlopen # Py 3
275 except ImportError:
274 except ImportError:
276 from urllib2 import urlopen
275 from urllib2 import urlopen
277 import json
276 import json
278 post_data = json.dumps({
277 post_data = json.dumps({
279 "description": opts.get('d', "Pasted from IPython"),
278 "description": opts.get('d', "Pasted from IPython"),
280 "public": True,
279 "public": True,
281 "files": {
280 "files": {
282 "file1.py": {
281 "file1.py": {
283 "content": code
282 "content": code
284 }
283 }
285 }
284 }
286 }).encode('utf-8')
285 }).encode('utf-8')
287
286
288 response = urlopen("https://api.github.com/gists", post_data)
287 response = urlopen("https://api.github.com/gists", post_data)
289 response_data = json.loads(response.read().decode('utf-8'))
288 response_data = json.loads(response.read().decode('utf-8'))
290 return response_data['html_url']
289 return response_data['html_url']
291
290
292 @line_magic
291 @line_magic
293 def loadpy(self, arg_s):
292 def loadpy(self, arg_s):
294 """Alias of `%load`
293 """Alias of `%load`
295
294
296 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
295 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
297 extension. So it has been renamed simply into %load. You can look at
296 extension. So it has been renamed simply into %load. You can look at
298 `%load`'s docstring for more info.
297 `%load`'s docstring for more info.
299 """
298 """
300 self.load(arg_s)
299 self.load(arg_s)
301
300
302 @line_magic
301 @line_magic
303 def load(self, arg_s):
302 def load(self, arg_s):
304 """Load code into the current frontend.
303 """Load code into the current frontend.
305
304
306 Usage:\\
305 Usage:\\
307 %load [options] source
306 %load [options] source
308
307
309 where source can be a filename, URL, input history range, macro, or
308 where source can be a filename, URL, input history range, macro, or
310 element in the user namespace
309 element in the user namespace
311
310
312 Options:
311 Options:
313
312
314 -r <lines>: Specify lines or ranges of lines to load from the source.
313 -r <lines>: Specify lines or ranges of lines to load from the source.
315 Ranges could be specified as x-y (x..y) or in python-style x:y
314 Ranges could be specified as x-y (x..y) or in python-style x:y
316 (x..(y-1)). Both limits x and y can be left blank (meaning the
315 (x..(y-1)). Both limits x and y can be left blank (meaning the
317 beginning and end of the file, respectively).
316 beginning and end of the file, respectively).
318
317
319 -s <symbols>: Specify function or classes to load from python source.
318 -s <symbols>: Specify function or classes to load from python source.
320
319
321 -y : Don't ask confirmation for loading source above 200 000 characters.
320 -y : Don't ask confirmation for loading source above 200 000 characters.
322
321
323 -n : Include the user's namespace when searching for source code.
322 -n : Include the user's namespace when searching for source code.
324
323
325 This magic command can either take a local filename, a URL, an history
324 This magic command can either take a local filename, a URL, an history
326 range (see %history) or a macro as argument, it will prompt for
325 range (see %history) or a macro as argument, it will prompt for
327 confirmation before loading source with more than 200 000 characters, unless
326 confirmation before loading source with more than 200 000 characters, unless
328 -y flag is passed or if the frontend does not support raw_input::
327 -y flag is passed or if the frontend does not support raw_input::
329
328
330 %load myscript.py
329 %load myscript.py
331 %load 7-27
330 %load 7-27
332 %load myMacro
331 %load myMacro
333 %load http://www.example.com/myscript.py
332 %load http://www.example.com/myscript.py
334 %load -r 5-10 myscript.py
333 %load -r 5-10 myscript.py
335 %load -r 10-20,30,40: foo.py
334 %load -r 10-20,30,40: foo.py
336 %load -s MyClass,wonder_function myscript.py
335 %load -s MyClass,wonder_function myscript.py
337 %load -n MyClass
336 %load -n MyClass
338 %load -n my_module.wonder_function
337 %load -n my_module.wonder_function
339 """
338 """
340 opts,args = self.parse_options(arg_s,'yns:r:')
339 opts,args = self.parse_options(arg_s,'yns:r:')
341
340
342 if not args:
341 if not args:
343 raise UsageError('Missing filename, URL, input history range, '
342 raise UsageError('Missing filename, URL, input history range, '
344 'macro, or element in the user namespace.')
343 'macro, or element in the user namespace.')
345
344
346 search_ns = 'n' in opts
345 search_ns = 'n' in opts
347
346
348 contents = self.shell.find_user_code(args, search_ns=search_ns)
347 contents = self.shell.find_user_code(args, search_ns=search_ns)
349
348
350 if 's' in opts:
349 if 's' in opts:
351 try:
350 try:
352 blocks, not_found = extract_symbols(contents, opts['s'])
351 blocks, not_found = extract_symbols(contents, opts['s'])
353 except SyntaxError:
352 except SyntaxError:
354 # non python code
353 # non python code
355 error("Unable to parse the input as valid Python code")
354 error("Unable to parse the input as valid Python code")
356 return
355 return
357
356
358 if len(not_found) == 1:
357 if len(not_found) == 1:
359 warn('The symbol `%s` was not found' % not_found[0])
358 warn('The symbol `%s` was not found' % not_found[0])
360 elif len(not_found) > 1:
359 elif len(not_found) > 1:
361 warn('The symbols %s were not found' % get_text_list(not_found,
360 warn('The symbols %s were not found' % get_text_list(not_found,
362 wrap_item_with='`')
361 wrap_item_with='`')
363 )
362 )
364
363
365 contents = '\n'.join(blocks)
364 contents = '\n'.join(blocks)
366
365
367 if 'r' in opts:
366 if 'r' in opts:
368 ranges = opts['r'].replace(',', ' ')
367 ranges = opts['r'].replace(',', ' ')
369 lines = contents.split('\n')
368 lines = contents.split('\n')
370 slices = extract_code_ranges(ranges)
369 slices = extract_code_ranges(ranges)
371 contents = [lines[slice(*slc)] for slc in slices]
370 contents = [lines[slice(*slc)] for slc in slices]
372 contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
371 contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
373
372
374 l = len(contents)
373 l = len(contents)
375
374
376 # 200 000 is ~ 2500 full 80 caracter lines
375 # 200 000 is ~ 2500 full 80 caracter lines
377 # so in average, more than 5000 lines
376 # so in average, more than 5000 lines
378 if l > 200000 and 'y' not in opts:
377 if l > 200000 and 'y' not in opts:
379 try:
378 try:
380 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
379 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
381 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
380 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
382 except StdinNotImplementedError:
381 except StdinNotImplementedError:
383 #asume yes if raw input not implemented
382 #asume yes if raw input not implemented
384 ans = True
383 ans = True
385
384
386 if ans is False :
385 if ans is False :
387 print('Operation cancelled.')
386 print('Operation cancelled.')
388 return
387 return
389
388
390 contents = "# %load {}\n".format(arg_s) + contents
389 contents = "# %load {}\n".format(arg_s) + contents
391
390
392 self.shell.set_next_input(contents, replace=True)
391 self.shell.set_next_input(contents, replace=True)
393
392
394 @staticmethod
393 @staticmethod
395 def _find_edit_target(shell, args, opts, last_call):
394 def _find_edit_target(shell, args, opts, last_call):
396 """Utility method used by magic_edit to find what to edit."""
395 """Utility method used by magic_edit to find what to edit."""
397
396
398 def make_filename(arg):
397 def make_filename(arg):
399 "Make a filename from the given args"
398 "Make a filename from the given args"
400 try:
399 try:
401 filename = get_py_filename(arg)
400 filename = get_py_filename(arg)
402 except IOError:
401 except IOError:
403 # If it ends with .py but doesn't already exist, assume we want
402 # If it ends with .py but doesn't already exist, assume we want
404 # a new file.
403 # a new file.
405 if arg.endswith('.py'):
404 if arg.endswith('.py'):
406 filename = arg
405 filename = arg
407 else:
406 else:
408 filename = None
407 filename = None
409 return filename
408 return filename
410
409
411 # Set a few locals from the options for convenience:
410 # Set a few locals from the options for convenience:
412 opts_prev = 'p' in opts
411 opts_prev = 'p' in opts
413 opts_raw = 'r' in opts
412 opts_raw = 'r' in opts
414
413
415 # custom exceptions
414 # custom exceptions
416 class DataIsObject(Exception): pass
415 class DataIsObject(Exception): pass
417
416
418 # Default line number value
417 # Default line number value
419 lineno = opts.get('n',None)
418 lineno = opts.get('n',None)
420
419
421 if opts_prev:
420 if opts_prev:
422 args = '_%s' % last_call[0]
421 args = '_%s' % last_call[0]
423 if args not in shell.user_ns:
422 if args not in shell.user_ns:
424 args = last_call[1]
423 args = last_call[1]
425
424
426 # by default this is done with temp files, except when the given
425 # by default this is done with temp files, except when the given
427 # arg is a filename
426 # arg is a filename
428 use_temp = True
427 use_temp = True
429
428
430 data = ''
429 data = ''
431
430
432 # First, see if the arguments should be a filename.
431 # First, see if the arguments should be a filename.
433 filename = make_filename(args)
432 filename = make_filename(args)
434 if filename:
433 if filename:
435 use_temp = False
434 use_temp = False
436 elif args:
435 elif args:
437 # Mode where user specifies ranges of lines, like in %macro.
436 # Mode where user specifies ranges of lines, like in %macro.
438 data = shell.extract_input_lines(args, opts_raw)
437 data = shell.extract_input_lines(args, opts_raw)
439 if not data:
438 if not data:
440 try:
439 try:
441 # Load the parameter given as a variable. If not a string,
440 # Load the parameter given as a variable. If not a string,
442 # process it as an object instead (below)
441 # process it as an object instead (below)
443
442
444 #print '*** args',args,'type',type(args) # dbg
443 #print '*** args',args,'type',type(args) # dbg
445 data = eval(args, shell.user_ns)
444 data = eval(args, shell.user_ns)
446 if not isinstance(data, string_types):
445 if not isinstance(data, str):
447 raise DataIsObject
446 raise DataIsObject
448
447
449 except (NameError,SyntaxError):
448 except (NameError,SyntaxError):
450 # given argument is not a variable, try as a filename
449 # given argument is not a variable, try as a filename
451 filename = make_filename(args)
450 filename = make_filename(args)
452 if filename is None:
451 if filename is None:
453 warn("Argument given (%s) can't be found as a variable "
452 warn("Argument given (%s) can't be found as a variable "
454 "or as a filename." % args)
453 "or as a filename." % args)
455 return (None, None, None)
454 return (None, None, None)
456 use_temp = False
455 use_temp = False
457
456
458 except DataIsObject:
457 except DataIsObject:
459 # macros have a special edit function
458 # macros have a special edit function
460 if isinstance(data, Macro):
459 if isinstance(data, Macro):
461 raise MacroToEdit(data)
460 raise MacroToEdit(data)
462
461
463 # For objects, try to edit the file where they are defined
462 # For objects, try to edit the file where they are defined
464 filename = find_file(data)
463 filename = find_file(data)
465 if filename:
464 if filename:
466 if 'fakemodule' in filename.lower() and \
465 if 'fakemodule' in filename.lower() and \
467 inspect.isclass(data):
466 inspect.isclass(data):
468 # class created by %edit? Try to find source
467 # class created by %edit? Try to find source
469 # by looking for method definitions instead, the
468 # by looking for method definitions instead, the
470 # __module__ in those classes is FakeModule.
469 # __module__ in those classes is FakeModule.
471 attrs = [getattr(data, aname) for aname in dir(data)]
470 attrs = [getattr(data, aname) for aname in dir(data)]
472 for attr in attrs:
471 for attr in attrs:
473 if not inspect.ismethod(attr):
472 if not inspect.ismethod(attr):
474 continue
473 continue
475 filename = find_file(attr)
474 filename = find_file(attr)
476 if filename and \
475 if filename and \
477 'fakemodule' not in filename.lower():
476 'fakemodule' not in filename.lower():
478 # change the attribute to be the edit
477 # change the attribute to be the edit
479 # target instead
478 # target instead
480 data = attr
479 data = attr
481 break
480 break
482
481
483 m = ipython_input_pat.match(os.path.basename(filename))
482 m = ipython_input_pat.match(os.path.basename(filename))
484 if m:
483 if m:
485 raise InteractivelyDefined(int(m.groups()[0]))
484 raise InteractivelyDefined(int(m.groups()[0]))
486
485
487 datafile = 1
486 datafile = 1
488 if filename is None:
487 if filename is None:
489 filename = make_filename(args)
488 filename = make_filename(args)
490 datafile = 1
489 datafile = 1
491 if filename is not None:
490 if filename is not None:
492 # only warn about this if we get a real name
491 # only warn about this if we get a real name
493 warn('Could not find file where `%s` is defined.\n'
492 warn('Could not find file where `%s` is defined.\n'
494 'Opening a file named `%s`' % (args, filename))
493 'Opening a file named `%s`' % (args, filename))
495 # Now, make sure we can actually read the source (if it was
494 # Now, make sure we can actually read the source (if it was
496 # in a temp file it's gone by now).
495 # in a temp file it's gone by now).
497 if datafile:
496 if datafile:
498 if lineno is None:
497 if lineno is None:
499 lineno = find_source_lines(data)
498 lineno = find_source_lines(data)
500 if lineno is None:
499 if lineno is None:
501 filename = make_filename(args)
500 filename = make_filename(args)
502 if filename is None:
501 if filename is None:
503 warn('The file where `%s` was defined '
502 warn('The file where `%s` was defined '
504 'cannot be read or found.' % data)
503 'cannot be read or found.' % data)
505 return (None, None, None)
504 return (None, None, None)
506 use_temp = False
505 use_temp = False
507
506
508 if use_temp:
507 if use_temp:
509 filename = shell.mktempfile(data)
508 filename = shell.mktempfile(data)
510 print('IPython will make a temporary file named:',filename)
509 print('IPython will make a temporary file named:',filename)
511
510
512 # use last_call to remember the state of the previous call, but don't
511 # use last_call to remember the state of the previous call, but don't
513 # let it be clobbered by successive '-p' calls.
512 # let it be clobbered by successive '-p' calls.
514 try:
513 try:
515 last_call[0] = shell.displayhook.prompt_count
514 last_call[0] = shell.displayhook.prompt_count
516 if not opts_prev:
515 if not opts_prev:
517 last_call[1] = args
516 last_call[1] = args
518 except:
517 except:
519 pass
518 pass
520
519
521
520
522 return filename, lineno, use_temp
521 return filename, lineno, use_temp
523
522
524 def _edit_macro(self,mname,macro):
523 def _edit_macro(self,mname,macro):
525 """open an editor with the macro data in a file"""
524 """open an editor with the macro data in a file"""
526 filename = self.shell.mktempfile(macro.value)
525 filename = self.shell.mktempfile(macro.value)
527 self.shell.hooks.editor(filename)
526 self.shell.hooks.editor(filename)
528
527
529 # and make a new macro object, to replace the old one
528 # and make a new macro object, to replace the old one
530 with open(filename) as mfile:
529 with open(filename) as mfile:
531 mvalue = mfile.read()
530 mvalue = mfile.read()
532 self.shell.user_ns[mname] = Macro(mvalue)
531 self.shell.user_ns[mname] = Macro(mvalue)
533
532
534 @skip_doctest
533 @skip_doctest
535 @line_magic
534 @line_magic
536 def edit(self, parameter_s='',last_call=['','']):
535 def edit(self, parameter_s='',last_call=['','']):
537 """Bring up an editor and execute the resulting code.
536 """Bring up an editor and execute the resulting code.
538
537
539 Usage:
538 Usage:
540 %edit [options] [args]
539 %edit [options] [args]
541
540
542 %edit runs IPython's editor hook. The default version of this hook is
541 %edit runs IPython's editor hook. The default version of this hook is
543 set to call the editor specified by your $EDITOR environment variable.
542 set to call the editor specified by your $EDITOR environment variable.
544 If this isn't found, it will default to vi under Linux/Unix and to
543 If this isn't found, it will default to vi under Linux/Unix and to
545 notepad under Windows. See the end of this docstring for how to change
544 notepad under Windows. See the end of this docstring for how to change
546 the editor hook.
545 the editor hook.
547
546
548 You can also set the value of this editor via the
547 You can also set the value of this editor via the
549 ``TerminalInteractiveShell.editor`` option in your configuration file.
548 ``TerminalInteractiveShell.editor`` option in your configuration file.
550 This is useful if you wish to use a different editor from your typical
549 This is useful if you wish to use a different editor from your typical
551 default with IPython (and for Windows users who typically don't set
550 default with IPython (and for Windows users who typically don't set
552 environment variables).
551 environment variables).
553
552
554 This command allows you to conveniently edit multi-line code right in
553 This command allows you to conveniently edit multi-line code right in
555 your IPython session.
554 your IPython session.
556
555
557 If called without arguments, %edit opens up an empty editor with a
556 If called without arguments, %edit opens up an empty editor with a
558 temporary file and will execute the contents of this file when you
557 temporary file and will execute the contents of this file when you
559 close it (don't forget to save it!).
558 close it (don't forget to save it!).
560
559
561
560
562 Options:
561 Options:
563
562
564 -n <number>: open the editor at a specified line number. By default,
563 -n <number>: open the editor at a specified line number. By default,
565 the IPython editor hook uses the unix syntax 'editor +N filename', but
564 the IPython editor hook uses the unix syntax 'editor +N filename', but
566 you can configure this by providing your own modified hook if your
565 you can configure this by providing your own modified hook if your
567 favorite editor supports line-number specifications with a different
566 favorite editor supports line-number specifications with a different
568 syntax.
567 syntax.
569
568
570 -p: this will call the editor with the same data as the previous time
569 -p: this will call the editor with the same data as the previous time
571 it was used, regardless of how long ago (in your current session) it
570 it was used, regardless of how long ago (in your current session) it
572 was.
571 was.
573
572
574 -r: use 'raw' input. This option only applies to input taken from the
573 -r: use 'raw' input. This option only applies to input taken from the
575 user's history. By default, the 'processed' history is used, so that
574 user's history. By default, the 'processed' history is used, so that
576 magics are loaded in their transformed version to valid Python. If
575 magics are loaded in their transformed version to valid Python. If
577 this option is given, the raw input as typed as the command line is
576 this option is given, the raw input as typed as the command line is
578 used instead. When you exit the editor, it will be executed by
577 used instead. When you exit the editor, it will be executed by
579 IPython's own processor.
578 IPython's own processor.
580
579
581 -x: do not execute the edited code immediately upon exit. This is
580 -x: do not execute the edited code immediately upon exit. This is
582 mainly useful if you are editing programs which need to be called with
581 mainly useful if you are editing programs which need to be called with
583 command line arguments, which you can then do using %run.
582 command line arguments, which you can then do using %run.
584
583
585
584
586 Arguments:
585 Arguments:
587
586
588 If arguments are given, the following possibilities exist:
587 If arguments are given, the following possibilities exist:
589
588
590 - If the argument is a filename, IPython will load that into the
589 - If the argument is a filename, IPython will load that into the
591 editor. It will execute its contents with execfile() when you exit,
590 editor. It will execute its contents with execfile() when you exit,
592 loading any code in the file into your interactive namespace.
591 loading any code in the file into your interactive namespace.
593
592
594 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
593 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
595 The syntax is the same as in the %history magic.
594 The syntax is the same as in the %history magic.
596
595
597 - If the argument is a string variable, its contents are loaded
596 - If the argument is a string variable, its contents are loaded
598 into the editor. You can thus edit any string which contains
597 into the editor. You can thus edit any string which contains
599 python code (including the result of previous edits).
598 python code (including the result of previous edits).
600
599
601 - If the argument is the name of an object (other than a string),
600 - If the argument is the name of an object (other than a string),
602 IPython will try to locate the file where it was defined and open the
601 IPython will try to locate the file where it was defined and open the
603 editor at the point where it is defined. You can use `%edit function`
602 editor at the point where it is defined. You can use `%edit function`
604 to load an editor exactly at the point where 'function' is defined,
603 to load an editor exactly at the point where 'function' is defined,
605 edit it and have the file be executed automatically.
604 edit it and have the file be executed automatically.
606
605
607 - If the object is a macro (see %macro for details), this opens up your
606 - If the object is a macro (see %macro for details), this opens up your
608 specified editor with a temporary file containing the macro's data.
607 specified editor with a temporary file containing the macro's data.
609 Upon exit, the macro is reloaded with the contents of the file.
608 Upon exit, the macro is reloaded with the contents of the file.
610
609
611 Note: opening at an exact line is only supported under Unix, and some
610 Note: opening at an exact line is only supported under Unix, and some
612 editors (like kedit and gedit up to Gnome 2.8) do not understand the
611 editors (like kedit and gedit up to Gnome 2.8) do not understand the
613 '+NUMBER' parameter necessary for this feature. Good editors like
612 '+NUMBER' parameter necessary for this feature. Good editors like
614 (X)Emacs, vi, jed, pico and joe all do.
613 (X)Emacs, vi, jed, pico and joe all do.
615
614
616 After executing your code, %edit will return as output the code you
615 After executing your code, %edit will return as output the code you
617 typed in the editor (except when it was an existing file). This way
616 typed in the editor (except when it was an existing file). This way
618 you can reload the code in further invocations of %edit as a variable,
617 you can reload the code in further invocations of %edit as a variable,
619 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
618 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
620 the output.
619 the output.
621
620
622 Note that %edit is also available through the alias %ed.
621 Note that %edit is also available through the alias %ed.
623
622
624 This is an example of creating a simple function inside the editor and
623 This is an example of creating a simple function inside the editor and
625 then modifying it. First, start up the editor::
624 then modifying it. First, start up the editor::
626
625
627 In [1]: edit
626 In [1]: edit
628 Editing... done. Executing edited code...
627 Editing... done. Executing edited code...
629 Out[1]: 'def foo():\\n print "foo() was defined in an editing
628 Out[1]: 'def foo():\\n print "foo() was defined in an editing
630 session"\\n'
629 session"\\n'
631
630
632 We can then call the function foo()::
631 We can then call the function foo()::
633
632
634 In [2]: foo()
633 In [2]: foo()
635 foo() was defined in an editing session
634 foo() was defined in an editing session
636
635
637 Now we edit foo. IPython automatically loads the editor with the
636 Now we edit foo. IPython automatically loads the editor with the
638 (temporary) file where foo() was previously defined::
637 (temporary) file where foo() was previously defined::
639
638
640 In [3]: edit foo
639 In [3]: edit foo
641 Editing... done. Executing edited code...
640 Editing... done. Executing edited code...
642
641
643 And if we call foo() again we get the modified version::
642 And if we call foo() again we get the modified version::
644
643
645 In [4]: foo()
644 In [4]: foo()
646 foo() has now been changed!
645 foo() has now been changed!
647
646
648 Here is an example of how to edit a code snippet successive
647 Here is an example of how to edit a code snippet successive
649 times. First we call the editor::
648 times. First we call the editor::
650
649
651 In [5]: edit
650 In [5]: edit
652 Editing... done. Executing edited code...
651 Editing... done. Executing edited code...
653 hello
652 hello
654 Out[5]: "print 'hello'\\n"
653 Out[5]: "print 'hello'\\n"
655
654
656 Now we call it again with the previous output (stored in _)::
655 Now we call it again with the previous output (stored in _)::
657
656
658 In [6]: edit _
657 In [6]: edit _
659 Editing... done. Executing edited code...
658 Editing... done. Executing edited code...
660 hello world
659 hello world
661 Out[6]: "print 'hello world'\\n"
660 Out[6]: "print 'hello world'\\n"
662
661
663 Now we call it with the output #8 (stored in _8, also as Out[8])::
662 Now we call it with the output #8 (stored in _8, also as Out[8])::
664
663
665 In [7]: edit _8
664 In [7]: edit _8
666 Editing... done. Executing edited code...
665 Editing... done. Executing edited code...
667 hello again
666 hello again
668 Out[7]: "print 'hello again'\\n"
667 Out[7]: "print 'hello again'\\n"
669
668
670
669
671 Changing the default editor hook:
670 Changing the default editor hook:
672
671
673 If you wish to write your own editor hook, you can put it in a
672 If you wish to write your own editor hook, you can put it in a
674 configuration file which you load at startup time. The default hook
673 configuration file which you load at startup time. The default hook
675 is defined in the IPython.core.hooks module, and you can use that as a
674 is defined in the IPython.core.hooks module, and you can use that as a
676 starting example for further modifications. That file also has
675 starting example for further modifications. That file also has
677 general instructions on how to set a new hook for use once you've
676 general instructions on how to set a new hook for use once you've
678 defined it."""
677 defined it."""
679 opts,args = self.parse_options(parameter_s,'prxn:')
678 opts,args = self.parse_options(parameter_s,'prxn:')
680
679
681 try:
680 try:
682 filename, lineno, is_temp = self._find_edit_target(self.shell,
681 filename, lineno, is_temp = self._find_edit_target(self.shell,
683 args, opts, last_call)
682 args, opts, last_call)
684 except MacroToEdit as e:
683 except MacroToEdit as e:
685 self._edit_macro(args, e.args[0])
684 self._edit_macro(args, e.args[0])
686 return
685 return
687 except InteractivelyDefined as e:
686 except InteractivelyDefined as e:
688 print("Editing In[%i]" % e.index)
687 print("Editing In[%i]" % e.index)
689 args = str(e.index)
688 args = str(e.index)
690 filename, lineno, is_temp = self._find_edit_target(self.shell,
689 filename, lineno, is_temp = self._find_edit_target(self.shell,
691 args, opts, last_call)
690 args, opts, last_call)
692 if filename is None:
691 if filename is None:
693 # nothing was found, warnings have already been issued,
692 # nothing was found, warnings have already been issued,
694 # just give up.
693 # just give up.
695 return
694 return
696
695
697 if is_temp:
696 if is_temp:
698 self._knowntemps.add(filename)
697 self._knowntemps.add(filename)
699 elif (filename in self._knowntemps):
698 elif (filename in self._knowntemps):
700 is_temp = True
699 is_temp = True
701
700
702
701
703 # do actual editing here
702 # do actual editing here
704 print('Editing...', end=' ')
703 print('Editing...', end=' ')
705 sys.stdout.flush()
704 sys.stdout.flush()
706 try:
705 try:
707 # Quote filenames that may have spaces in them
706 # Quote filenames that may have spaces in them
708 if ' ' in filename:
707 if ' ' in filename:
709 filename = "'%s'" % filename
708 filename = "'%s'" % filename
710 self.shell.hooks.editor(filename,lineno)
709 self.shell.hooks.editor(filename,lineno)
711 except TryNext:
710 except TryNext:
712 warn('Could not open editor')
711 warn('Could not open editor')
713 return
712 return
714
713
715 # XXX TODO: should this be generalized for all string vars?
714 # XXX TODO: should this be generalized for all string vars?
716 # For now, this is special-cased to blocks created by cpaste
715 # For now, this is special-cased to blocks created by cpaste
717 if args.strip() == 'pasted_block':
716 if args.strip() == 'pasted_block':
718 with open(filename, 'r') as f:
717 with open(filename, 'r') as f:
719 self.shell.user_ns['pasted_block'] = f.read()
718 self.shell.user_ns['pasted_block'] = f.read()
720
719
721 if 'x' in opts: # -x prevents actual execution
720 if 'x' in opts: # -x prevents actual execution
722 print()
721 print()
723 else:
722 else:
724 print('done. Executing edited code...')
723 print('done. Executing edited code...')
725 with preserve_keys(self.shell.user_ns, '__file__'):
724 with preserve_keys(self.shell.user_ns, '__file__'):
726 if not is_temp:
725 if not is_temp:
727 self.shell.user_ns['__file__'] = filename
726 self.shell.user_ns['__file__'] = filename
728 if 'r' in opts: # Untranslated IPython code
727 if 'r' in opts: # Untranslated IPython code
729 with open(filename, 'r') as f:
728 with open(filename, 'r') as f:
730 source = f.read()
729 source = f.read()
731 self.shell.run_cell(source, store_history=False)
730 self.shell.run_cell(source, store_history=False)
732 else:
731 else:
733 self.shell.safe_execfile(filename, self.shell.user_ns,
732 self.shell.safe_execfile(filename, self.shell.user_ns,
734 self.shell.user_ns)
733 self.shell.user_ns)
735
734
736 if is_temp:
735 if is_temp:
737 try:
736 try:
738 return open(filename).read()
737 return open(filename).read()
739 except IOError as msg:
738 except IOError as msg:
740 if msg.filename == filename:
739 if msg.filename == filename:
741 warn('File not found. Did you forget to save?')
740 warn('File not found. Did you forget to save?')
742 return
741 return
743 else:
742 else:
744 self.shell.showtraceback()
743 self.shell.showtraceback()
@@ -1,1381 +1,1380 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Implementation of execution-related magic functions."""
2 """Implementation of execution-related magic functions."""
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
7
8 import ast
8 import ast
9 import bdb
9 import bdb
10 import gc
10 import gc
11 import itertools
11 import itertools
12 import os
12 import os
13 import sys
13 import sys
14 import time
14 import time
15 import timeit
15 import timeit
16 import math
16 import math
17 from pdb import Restart
17 from pdb import Restart
18
18
19 # cProfile was added in Python2.5
19 # cProfile was added in Python2.5
20 try:
20 try:
21 import cProfile as profile
21 import cProfile as profile
22 import pstats
22 import pstats
23 except ImportError:
23 except ImportError:
24 # profile isn't bundled by default in Debian for license reasons
24 # profile isn't bundled by default in Debian for license reasons
25 try:
25 try:
26 import profile, pstats
26 import profile, pstats
27 except ImportError:
27 except ImportError:
28 profile = pstats = None
28 profile = pstats = None
29
29
30 from IPython.core import oinspect
30 from IPython.core import oinspect
31 from IPython.core import magic_arguments
31 from IPython.core import magic_arguments
32 from IPython.core import page
32 from IPython.core import page
33 from IPython.core.error import UsageError
33 from IPython.core.error import UsageError
34 from IPython.core.macro import Macro
34 from IPython.core.macro import Macro
35 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
35 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
36 line_cell_magic, on_off, needs_local_scope)
36 line_cell_magic, on_off, needs_local_scope)
37 from IPython.testing.skipdoctest import skip_doctest
37 from IPython.testing.skipdoctest import skip_doctest
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39 from IPython.utils.py3compat import builtin_mod, iteritems, PY3
39 from IPython.utils.py3compat import builtin_mod, PY3
40 from IPython.utils.contexts import preserve_keys
40 from IPython.utils.contexts import preserve_keys
41 from IPython.utils.capture import capture_output
41 from IPython.utils.capture import capture_output
42 from IPython.utils.ipstruct import Struct
42 from IPython.utils.ipstruct import Struct
43 from IPython.utils.module_paths import find_mod
43 from IPython.utils.module_paths import find_mod
44 from IPython.utils.path import get_py_filename, shellglob
44 from IPython.utils.path import get_py_filename, shellglob
45 from IPython.utils.timing import clock, clock2
45 from IPython.utils.timing import clock, clock2
46 from warnings import warn
46 from warnings import warn
47 from logging import error
47 from logging import error
48
48
49 if PY3:
49 if PY3:
50 from io import StringIO
50 from io import StringIO
51 else:
51 else:
52 from StringIO import StringIO
52 from StringIO import StringIO
53
53
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55 # Magic implementation classes
55 # Magic implementation classes
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57
57
58
58
59 class TimeitResult(object):
59 class TimeitResult(object):
60 """
60 """
61 Object returned by the timeit magic with info about the run.
61 Object returned by the timeit magic with info about the run.
62
62
63 Contains the following attributes :
63 Contains the following attributes :
64
64
65 loops: (int) number of loops done per measurement
65 loops: (int) number of loops done per measurement
66 repeat: (int) number of times the measurement has been repeated
66 repeat: (int) number of times the measurement has been repeated
67 best: (float) best execution time / number
67 best: (float) best execution time / number
68 all_runs: (list of float) execution time of each run (in s)
68 all_runs: (list of float) execution time of each run (in s)
69 compile_time: (float) time of statement compilation (s)
69 compile_time: (float) time of statement compilation (s)
70
70
71 """
71 """
72 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
72 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
73 self.loops = loops
73 self.loops = loops
74 self.repeat = repeat
74 self.repeat = repeat
75 self.best = best
75 self.best = best
76 self.worst = worst
76 self.worst = worst
77 self.all_runs = all_runs
77 self.all_runs = all_runs
78 self.compile_time = compile_time
78 self.compile_time = compile_time
79 self._precision = precision
79 self._precision = precision
80 self.timings = [ dt / self.loops for dt in all_runs]
80 self.timings = [ dt / self.loops for dt in all_runs]
81
81
82 @property
82 @property
83 def average(self):
83 def average(self):
84 return math.fsum(self.timings) / len(self.timings)
84 return math.fsum(self.timings) / len(self.timings)
85
85
86 @property
86 @property
87 def stdev(self):
87 def stdev(self):
88 mean = self.average
88 mean = self.average
89 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
89 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
90
90
91 def __str__(self):
91 def __str__(self):
92 return (u"%s loop%s, average of %d: %s +- %s per loop (using standard deviation)"
92 return (u"%s loop%s, average of %d: %s +- %s per loop (using standard deviation)"
93 % (self.loops,"" if self.loops == 1 else "s", self.repeat,
93 % (self.loops,"" if self.loops == 1 else "s", self.repeat,
94 _format_time(self.average, self._precision),
94 _format_time(self.average, self._precision),
95 _format_time(self.stdev, self._precision)))
95 _format_time(self.stdev, self._precision)))
96
96
97 def _repr_pretty_(self, p , cycle):
97 def _repr_pretty_(self, p , cycle):
98 unic = self.__str__()
98 unic = self.__str__()
99 p.text(u'<TimeitResult : '+unic+u'>')
99 p.text(u'<TimeitResult : '+unic+u'>')
100
100
101
101
102
102
103 class TimeitTemplateFiller(ast.NodeTransformer):
103 class TimeitTemplateFiller(ast.NodeTransformer):
104 """Fill in the AST template for timing execution.
104 """Fill in the AST template for timing execution.
105
105
106 This is quite closely tied to the template definition, which is in
106 This is quite closely tied to the template definition, which is in
107 :meth:`ExecutionMagics.timeit`.
107 :meth:`ExecutionMagics.timeit`.
108 """
108 """
109 def __init__(self, ast_setup, ast_stmt):
109 def __init__(self, ast_setup, ast_stmt):
110 self.ast_setup = ast_setup
110 self.ast_setup = ast_setup
111 self.ast_stmt = ast_stmt
111 self.ast_stmt = ast_stmt
112
112
113 def visit_FunctionDef(self, node):
113 def visit_FunctionDef(self, node):
114 "Fill in the setup statement"
114 "Fill in the setup statement"
115 self.generic_visit(node)
115 self.generic_visit(node)
116 if node.name == "inner":
116 if node.name == "inner":
117 node.body[:1] = self.ast_setup.body
117 node.body[:1] = self.ast_setup.body
118
118
119 return node
119 return node
120
120
121 def visit_For(self, node):
121 def visit_For(self, node):
122 "Fill in the statement to be timed"
122 "Fill in the statement to be timed"
123 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
123 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
124 node.body = self.ast_stmt.body
124 node.body = self.ast_stmt.body
125 return node
125 return node
126
126
127
127
128 class Timer(timeit.Timer):
128 class Timer(timeit.Timer):
129 """Timer class that explicitly uses self.inner
129 """Timer class that explicitly uses self.inner
130
130
131 which is an undocumented implementation detail of CPython,
131 which is an undocumented implementation detail of CPython,
132 not shared by PyPy.
132 not shared by PyPy.
133 """
133 """
134 # Timer.timeit copied from CPython 3.4.2
134 # Timer.timeit copied from CPython 3.4.2
135 def timeit(self, number=timeit.default_number):
135 def timeit(self, number=timeit.default_number):
136 """Time 'number' executions of the main statement.
136 """Time 'number' executions of the main statement.
137
137
138 To be precise, this executes the setup statement once, and
138 To be precise, this executes the setup statement once, and
139 then returns the time it takes to execute the main statement
139 then returns the time it takes to execute the main statement
140 a number of times, as a float measured in seconds. The
140 a number of times, as a float measured in seconds. The
141 argument is the number of times through the loop, defaulting
141 argument is the number of times through the loop, defaulting
142 to one million. The main statement, the setup statement and
142 to one million. The main statement, the setup statement and
143 the timer function to be used are passed to the constructor.
143 the timer function to be used are passed to the constructor.
144 """
144 """
145 it = itertools.repeat(None, number)
145 it = itertools.repeat(None, number)
146 gcold = gc.isenabled()
146 gcold = gc.isenabled()
147 gc.disable()
147 gc.disable()
148 try:
148 try:
149 timing = self.inner(it, self.timer)
149 timing = self.inner(it, self.timer)
150 finally:
150 finally:
151 if gcold:
151 if gcold:
152 gc.enable()
152 gc.enable()
153 return timing
153 return timing
154
154
155
155
156 @magics_class
156 @magics_class
157 class ExecutionMagics(Magics):
157 class ExecutionMagics(Magics):
158 """Magics related to code execution, debugging, profiling, etc.
158 """Magics related to code execution, debugging, profiling, etc.
159
159
160 """
160 """
161
161
162 def __init__(self, shell):
162 def __init__(self, shell):
163 super(ExecutionMagics, self).__init__(shell)
163 super(ExecutionMagics, self).__init__(shell)
164 if profile is None:
164 if profile is None:
165 self.prun = self.profile_missing_notice
165 self.prun = self.profile_missing_notice
166 # Default execution function used to actually run user code.
166 # Default execution function used to actually run user code.
167 self.default_runner = None
167 self.default_runner = None
168
168
169 def profile_missing_notice(self, *args, **kwargs):
169 def profile_missing_notice(self, *args, **kwargs):
170 error("""\
170 error("""\
171 The profile module could not be found. It has been removed from the standard
171 The profile module could not be found. It has been removed from the standard
172 python packages because of its non-free license. To use profiling, install the
172 python packages because of its non-free license. To use profiling, install the
173 python-profiler package from non-free.""")
173 python-profiler package from non-free.""")
174
174
175 @skip_doctest
175 @skip_doctest
176 @line_cell_magic
176 @line_cell_magic
177 def prun(self, parameter_s='', cell=None):
177 def prun(self, parameter_s='', cell=None):
178
178
179 """Run a statement through the python code profiler.
179 """Run a statement through the python code profiler.
180
180
181 Usage, in line mode:
181 Usage, in line mode:
182 %prun [options] statement
182 %prun [options] statement
183
183
184 Usage, in cell mode:
184 Usage, in cell mode:
185 %%prun [options] [statement]
185 %%prun [options] [statement]
186 code...
186 code...
187 code...
187 code...
188
188
189 In cell mode, the additional code lines are appended to the (possibly
189 In cell mode, the additional code lines are appended to the (possibly
190 empty) statement in the first line. Cell mode allows you to easily
190 empty) statement in the first line. Cell mode allows you to easily
191 profile multiline blocks without having to put them in a separate
191 profile multiline blocks without having to put them in a separate
192 function.
192 function.
193
193
194 The given statement (which doesn't require quote marks) is run via the
194 The given statement (which doesn't require quote marks) is run via the
195 python profiler in a manner similar to the profile.run() function.
195 python profiler in a manner similar to the profile.run() function.
196 Namespaces are internally managed to work correctly; profile.run
196 Namespaces are internally managed to work correctly; profile.run
197 cannot be used in IPython because it makes certain assumptions about
197 cannot be used in IPython because it makes certain assumptions about
198 namespaces which do not hold under IPython.
198 namespaces which do not hold under IPython.
199
199
200 Options:
200 Options:
201
201
202 -l <limit>
202 -l <limit>
203 you can place restrictions on what or how much of the
203 you can place restrictions on what or how much of the
204 profile gets printed. The limit value can be:
204 profile gets printed. The limit value can be:
205
205
206 * A string: only information for function names containing this string
206 * A string: only information for function names containing this string
207 is printed.
207 is printed.
208
208
209 * An integer: only these many lines are printed.
209 * An integer: only these many lines are printed.
210
210
211 * A float (between 0 and 1): this fraction of the report is printed
211 * A float (between 0 and 1): this fraction of the report is printed
212 (for example, use a limit of 0.4 to see the topmost 40% only).
212 (for example, use a limit of 0.4 to see the topmost 40% only).
213
213
214 You can combine several limits with repeated use of the option. For
214 You can combine several limits with repeated use of the option. For
215 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
215 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
216 information about class constructors.
216 information about class constructors.
217
217
218 -r
218 -r
219 return the pstats.Stats object generated by the profiling. This
219 return the pstats.Stats object generated by the profiling. This
220 object has all the information about the profile in it, and you can
220 object has all the information about the profile in it, and you can
221 later use it for further analysis or in other functions.
221 later use it for further analysis or in other functions.
222
222
223 -s <key>
223 -s <key>
224 sort profile by given key. You can provide more than one key
224 sort profile by given key. You can provide more than one key
225 by using the option several times: '-s key1 -s key2 -s key3...'. The
225 by using the option several times: '-s key1 -s key2 -s key3...'. The
226 default sorting key is 'time'.
226 default sorting key is 'time'.
227
227
228 The following is copied verbatim from the profile documentation
228 The following is copied verbatim from the profile documentation
229 referenced below:
229 referenced below:
230
230
231 When more than one key is provided, additional keys are used as
231 When more than one key is provided, additional keys are used as
232 secondary criteria when the there is equality in all keys selected
232 secondary criteria when the there is equality in all keys selected
233 before them.
233 before them.
234
234
235 Abbreviations can be used for any key names, as long as the
235 Abbreviations can be used for any key names, as long as the
236 abbreviation is unambiguous. The following are the keys currently
236 abbreviation is unambiguous. The following are the keys currently
237 defined:
237 defined:
238
238
239 ============ =====================
239 ============ =====================
240 Valid Arg Meaning
240 Valid Arg Meaning
241 ============ =====================
241 ============ =====================
242 "calls" call count
242 "calls" call count
243 "cumulative" cumulative time
243 "cumulative" cumulative time
244 "file" file name
244 "file" file name
245 "module" file name
245 "module" file name
246 "pcalls" primitive call count
246 "pcalls" primitive call count
247 "line" line number
247 "line" line number
248 "name" function name
248 "name" function name
249 "nfl" name/file/line
249 "nfl" name/file/line
250 "stdname" standard name
250 "stdname" standard name
251 "time" internal time
251 "time" internal time
252 ============ =====================
252 ============ =====================
253
253
254 Note that all sorts on statistics are in descending order (placing
254 Note that all sorts on statistics are in descending order (placing
255 most time consuming items first), where as name, file, and line number
255 most time consuming items first), where as name, file, and line number
256 searches are in ascending order (i.e., alphabetical). The subtle
256 searches are in ascending order (i.e., alphabetical). The subtle
257 distinction between "nfl" and "stdname" is that the standard name is a
257 distinction between "nfl" and "stdname" is that the standard name is a
258 sort of the name as printed, which means that the embedded line
258 sort of the name as printed, which means that the embedded line
259 numbers get compared in an odd way. For example, lines 3, 20, and 40
259 numbers get compared in an odd way. For example, lines 3, 20, and 40
260 would (if the file names were the same) appear in the string order
260 would (if the file names were the same) appear in the string order
261 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
261 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
262 line numbers. In fact, sort_stats("nfl") is the same as
262 line numbers. In fact, sort_stats("nfl") is the same as
263 sort_stats("name", "file", "line").
263 sort_stats("name", "file", "line").
264
264
265 -T <filename>
265 -T <filename>
266 save profile results as shown on screen to a text
266 save profile results as shown on screen to a text
267 file. The profile is still shown on screen.
267 file. The profile is still shown on screen.
268
268
269 -D <filename>
269 -D <filename>
270 save (via dump_stats) profile statistics to given
270 save (via dump_stats) profile statistics to given
271 filename. This data is in a format understood by the pstats module, and
271 filename. This data is in a format understood by the pstats module, and
272 is generated by a call to the dump_stats() method of profile
272 is generated by a call to the dump_stats() method of profile
273 objects. The profile is still shown on screen.
273 objects. The profile is still shown on screen.
274
274
275 -q
275 -q
276 suppress output to the pager. Best used with -T and/or -D above.
276 suppress output to the pager. Best used with -T and/or -D above.
277
277
278 If you want to run complete programs under the profiler's control, use
278 If you want to run complete programs under the profiler's control, use
279 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
279 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
280 contains profiler specific options as described here.
280 contains profiler specific options as described here.
281
281
282 You can read the complete documentation for the profile module with::
282 You can read the complete documentation for the profile module with::
283
283
284 In [1]: import profile; profile.help()
284 In [1]: import profile; profile.help()
285 """
285 """
286 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
286 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
287 list_all=True, posix=False)
287 list_all=True, posix=False)
288 if cell is not None:
288 if cell is not None:
289 arg_str += '\n' + cell
289 arg_str += '\n' + cell
290 arg_str = self.shell.input_splitter.transform_cell(arg_str)
290 arg_str = self.shell.input_splitter.transform_cell(arg_str)
291 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
291 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
292
292
293 def _run_with_profiler(self, code, opts, namespace):
293 def _run_with_profiler(self, code, opts, namespace):
294 """
294 """
295 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
295 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
296
296
297 Parameters
297 Parameters
298 ----------
298 ----------
299 code : str
299 code : str
300 Code to be executed.
300 Code to be executed.
301 opts : Struct
301 opts : Struct
302 Options parsed by `self.parse_options`.
302 Options parsed by `self.parse_options`.
303 namespace : dict
303 namespace : dict
304 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
304 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
305
305
306 """
306 """
307
307
308 # Fill default values for unspecified options:
308 # Fill default values for unspecified options:
309 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
309 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
310
310
311 prof = profile.Profile()
311 prof = profile.Profile()
312 try:
312 try:
313 prof = prof.runctx(code, namespace, namespace)
313 prof = prof.runctx(code, namespace, namespace)
314 sys_exit = ''
314 sys_exit = ''
315 except SystemExit:
315 except SystemExit:
316 sys_exit = """*** SystemExit exception caught in code being profiled."""
316 sys_exit = """*** SystemExit exception caught in code being profiled."""
317
317
318 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
318 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
319
319
320 lims = opts.l
320 lims = opts.l
321 if lims:
321 if lims:
322 lims = [] # rebuild lims with ints/floats/strings
322 lims = [] # rebuild lims with ints/floats/strings
323 for lim in opts.l:
323 for lim in opts.l:
324 try:
324 try:
325 lims.append(int(lim))
325 lims.append(int(lim))
326 except ValueError:
326 except ValueError:
327 try:
327 try:
328 lims.append(float(lim))
328 lims.append(float(lim))
329 except ValueError:
329 except ValueError:
330 lims.append(lim)
330 lims.append(lim)
331
331
332 # Trap output.
332 # Trap output.
333 stdout_trap = StringIO()
333 stdout_trap = StringIO()
334 stats_stream = stats.stream
334 stats_stream = stats.stream
335 try:
335 try:
336 stats.stream = stdout_trap
336 stats.stream = stdout_trap
337 stats.print_stats(*lims)
337 stats.print_stats(*lims)
338 finally:
338 finally:
339 stats.stream = stats_stream
339 stats.stream = stats_stream
340
340
341 output = stdout_trap.getvalue()
341 output = stdout_trap.getvalue()
342 output = output.rstrip()
342 output = output.rstrip()
343
343
344 if 'q' not in opts:
344 if 'q' not in opts:
345 page.page(output)
345 page.page(output)
346 print(sys_exit, end=' ')
346 print(sys_exit, end=' ')
347
347
348 dump_file = opts.D[0]
348 dump_file = opts.D[0]
349 text_file = opts.T[0]
349 text_file = opts.T[0]
350 if dump_file:
350 if dump_file:
351 prof.dump_stats(dump_file)
351 prof.dump_stats(dump_file)
352 print('\n*** Profile stats marshalled to file',\
352 print('\n*** Profile stats marshalled to file',\
353 repr(dump_file)+'.',sys_exit)
353 repr(dump_file)+'.',sys_exit)
354 if text_file:
354 if text_file:
355 pfile = open(text_file,'w')
355 pfile = open(text_file,'w')
356 pfile.write(output)
356 pfile.write(output)
357 pfile.close()
357 pfile.close()
358 print('\n*** Profile printout saved to text file',\
358 print('\n*** Profile printout saved to text file',\
359 repr(text_file)+'.',sys_exit)
359 repr(text_file)+'.',sys_exit)
360
360
361 if 'r' in opts:
361 if 'r' in opts:
362 return stats
362 return stats
363 else:
363 else:
364 return None
364 return None
365
365
366 @line_magic
366 @line_magic
367 def pdb(self, parameter_s=''):
367 def pdb(self, parameter_s=''):
368 """Control the automatic calling of the pdb interactive debugger.
368 """Control the automatic calling of the pdb interactive debugger.
369
369
370 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
370 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
371 argument it works as a toggle.
371 argument it works as a toggle.
372
372
373 When an exception is triggered, IPython can optionally call the
373 When an exception is triggered, IPython can optionally call the
374 interactive pdb debugger after the traceback printout. %pdb toggles
374 interactive pdb debugger after the traceback printout. %pdb toggles
375 this feature on and off.
375 this feature on and off.
376
376
377 The initial state of this feature is set in your configuration
377 The initial state of this feature is set in your configuration
378 file (the option is ``InteractiveShell.pdb``).
378 file (the option is ``InteractiveShell.pdb``).
379
379
380 If you want to just activate the debugger AFTER an exception has fired,
380 If you want to just activate the debugger AFTER an exception has fired,
381 without having to type '%pdb on' and rerunning your code, you can use
381 without having to type '%pdb on' and rerunning your code, you can use
382 the %debug magic."""
382 the %debug magic."""
383
383
384 par = parameter_s.strip().lower()
384 par = parameter_s.strip().lower()
385
385
386 if par:
386 if par:
387 try:
387 try:
388 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
388 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
389 except KeyError:
389 except KeyError:
390 print ('Incorrect argument. Use on/1, off/0, '
390 print ('Incorrect argument. Use on/1, off/0, '
391 'or nothing for a toggle.')
391 'or nothing for a toggle.')
392 return
392 return
393 else:
393 else:
394 # toggle
394 # toggle
395 new_pdb = not self.shell.call_pdb
395 new_pdb = not self.shell.call_pdb
396
396
397 # set on the shell
397 # set on the shell
398 self.shell.call_pdb = new_pdb
398 self.shell.call_pdb = new_pdb
399 print('Automatic pdb calling has been turned',on_off(new_pdb))
399 print('Automatic pdb calling has been turned',on_off(new_pdb))
400
400
401 @skip_doctest
401 @skip_doctest
402 @magic_arguments.magic_arguments()
402 @magic_arguments.magic_arguments()
403 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
403 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
404 help="""
404 help="""
405 Set break point at LINE in FILE.
405 Set break point at LINE in FILE.
406 """
406 """
407 )
407 )
408 @magic_arguments.argument('statement', nargs='*',
408 @magic_arguments.argument('statement', nargs='*',
409 help="""
409 help="""
410 Code to run in debugger.
410 Code to run in debugger.
411 You can omit this in cell magic mode.
411 You can omit this in cell magic mode.
412 """
412 """
413 )
413 )
414 @line_cell_magic
414 @line_cell_magic
415 def debug(self, line='', cell=None):
415 def debug(self, line='', cell=None):
416 """Activate the interactive debugger.
416 """Activate the interactive debugger.
417
417
418 This magic command support two ways of activating debugger.
418 This magic command support two ways of activating debugger.
419 One is to activate debugger before executing code. This way, you
419 One is to activate debugger before executing code. This way, you
420 can set a break point, to step through the code from the point.
420 can set a break point, to step through the code from the point.
421 You can use this mode by giving statements to execute and optionally
421 You can use this mode by giving statements to execute and optionally
422 a breakpoint.
422 a breakpoint.
423
423
424 The other one is to activate debugger in post-mortem mode. You can
424 The other one is to activate debugger in post-mortem mode. You can
425 activate this mode simply running %debug without any argument.
425 activate this mode simply running %debug without any argument.
426 If an exception has just occurred, this lets you inspect its stack
426 If an exception has just occurred, this lets you inspect its stack
427 frames interactively. Note that this will always work only on the last
427 frames interactively. Note that this will always work only on the last
428 traceback that occurred, so you must call this quickly after an
428 traceback that occurred, so you must call this quickly after an
429 exception that you wish to inspect has fired, because if another one
429 exception that you wish to inspect has fired, because if another one
430 occurs, it clobbers the previous one.
430 occurs, it clobbers the previous one.
431
431
432 If you want IPython to automatically do this on every exception, see
432 If you want IPython to automatically do this on every exception, see
433 the %pdb magic for more details.
433 the %pdb magic for more details.
434 """
434 """
435 args = magic_arguments.parse_argstring(self.debug, line)
435 args = magic_arguments.parse_argstring(self.debug, line)
436
436
437 if not (args.breakpoint or args.statement or cell):
437 if not (args.breakpoint or args.statement or cell):
438 self._debug_post_mortem()
438 self._debug_post_mortem()
439 else:
439 else:
440 code = "\n".join(args.statement)
440 code = "\n".join(args.statement)
441 if cell:
441 if cell:
442 code += "\n" + cell
442 code += "\n" + cell
443 self._debug_exec(code, args.breakpoint)
443 self._debug_exec(code, args.breakpoint)
444
444
445 def _debug_post_mortem(self):
445 def _debug_post_mortem(self):
446 self.shell.debugger(force=True)
446 self.shell.debugger(force=True)
447
447
448 def _debug_exec(self, code, breakpoint):
448 def _debug_exec(self, code, breakpoint):
449 if breakpoint:
449 if breakpoint:
450 (filename, bp_line) = breakpoint.rsplit(':', 1)
450 (filename, bp_line) = breakpoint.rsplit(':', 1)
451 bp_line = int(bp_line)
451 bp_line = int(bp_line)
452 else:
452 else:
453 (filename, bp_line) = (None, None)
453 (filename, bp_line) = (None, None)
454 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
454 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
455
455
456 @line_magic
456 @line_magic
457 def tb(self, s):
457 def tb(self, s):
458 """Print the last traceback with the currently active exception mode.
458 """Print the last traceback with the currently active exception mode.
459
459
460 See %xmode for changing exception reporting modes."""
460 See %xmode for changing exception reporting modes."""
461 self.shell.showtraceback()
461 self.shell.showtraceback()
462
462
463 @skip_doctest
463 @skip_doctest
464 @line_magic
464 @line_magic
465 def run(self, parameter_s='', runner=None,
465 def run(self, parameter_s='', runner=None,
466 file_finder=get_py_filename):
466 file_finder=get_py_filename):
467 """Run the named file inside IPython as a program.
467 """Run the named file inside IPython as a program.
468
468
469 Usage::
469 Usage::
470
470
471 %run [-n -i -e -G]
471 %run [-n -i -e -G]
472 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
472 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
473 ( -m mod | file ) [args]
473 ( -m mod | file ) [args]
474
474
475 Parameters after the filename are passed as command-line arguments to
475 Parameters after the filename are passed as command-line arguments to
476 the program (put in sys.argv). Then, control returns to IPython's
476 the program (put in sys.argv). Then, control returns to IPython's
477 prompt.
477 prompt.
478
478
479 This is similar to running at a system prompt ``python file args``,
479 This is similar to running at a system prompt ``python file args``,
480 but with the advantage of giving you IPython's tracebacks, and of
480 but with the advantage of giving you IPython's tracebacks, and of
481 loading all variables into your interactive namespace for further use
481 loading all variables into your interactive namespace for further use
482 (unless -p is used, see below).
482 (unless -p is used, see below).
483
483
484 The file is executed in a namespace initially consisting only of
484 The file is executed in a namespace initially consisting only of
485 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
485 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
486 sees its environment as if it were being run as a stand-alone program
486 sees its environment as if it were being run as a stand-alone program
487 (except for sharing global objects such as previously imported
487 (except for sharing global objects such as previously imported
488 modules). But after execution, the IPython interactive namespace gets
488 modules). But after execution, the IPython interactive namespace gets
489 updated with all variables defined in the program (except for __name__
489 updated with all variables defined in the program (except for __name__
490 and sys.argv). This allows for very convenient loading of code for
490 and sys.argv). This allows for very convenient loading of code for
491 interactive work, while giving each program a 'clean sheet' to run in.
491 interactive work, while giving each program a 'clean sheet' to run in.
492
492
493 Arguments are expanded using shell-like glob match. Patterns
493 Arguments are expanded using shell-like glob match. Patterns
494 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
494 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
495 tilde '~' will be expanded into user's home directory. Unlike
495 tilde '~' will be expanded into user's home directory. Unlike
496 real shells, quotation does not suppress expansions. Use
496 real shells, quotation does not suppress expansions. Use
497 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
497 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
498 To completely disable these expansions, you can use -G flag.
498 To completely disable these expansions, you can use -G flag.
499
499
500 Options:
500 Options:
501
501
502 -n
502 -n
503 __name__ is NOT set to '__main__', but to the running file's name
503 __name__ is NOT set to '__main__', but to the running file's name
504 without extension (as python does under import). This allows running
504 without extension (as python does under import). This allows running
505 scripts and reloading the definitions in them without calling code
505 scripts and reloading the definitions in them without calling code
506 protected by an ``if __name__ == "__main__"`` clause.
506 protected by an ``if __name__ == "__main__"`` clause.
507
507
508 -i
508 -i
509 run the file in IPython's namespace instead of an empty one. This
509 run the file in IPython's namespace instead of an empty one. This
510 is useful if you are experimenting with code written in a text editor
510 is useful if you are experimenting with code written in a text editor
511 which depends on variables defined interactively.
511 which depends on variables defined interactively.
512
512
513 -e
513 -e
514 ignore sys.exit() calls or SystemExit exceptions in the script
514 ignore sys.exit() calls or SystemExit exceptions in the script
515 being run. This is particularly useful if IPython is being used to
515 being run. This is particularly useful if IPython is being used to
516 run unittests, which always exit with a sys.exit() call. In such
516 run unittests, which always exit with a sys.exit() call. In such
517 cases you are interested in the output of the test results, not in
517 cases you are interested in the output of the test results, not in
518 seeing a traceback of the unittest module.
518 seeing a traceback of the unittest module.
519
519
520 -t
520 -t
521 print timing information at the end of the run. IPython will give
521 print timing information at the end of the run. IPython will give
522 you an estimated CPU time consumption for your script, which under
522 you an estimated CPU time consumption for your script, which under
523 Unix uses the resource module to avoid the wraparound problems of
523 Unix uses the resource module to avoid the wraparound problems of
524 time.clock(). Under Unix, an estimate of time spent on system tasks
524 time.clock(). Under Unix, an estimate of time spent on system tasks
525 is also given (for Windows platforms this is reported as 0.0).
525 is also given (for Windows platforms this is reported as 0.0).
526
526
527 If -t is given, an additional ``-N<N>`` option can be given, where <N>
527 If -t is given, an additional ``-N<N>`` option can be given, where <N>
528 must be an integer indicating how many times you want the script to
528 must be an integer indicating how many times you want the script to
529 run. The final timing report will include total and per run results.
529 run. The final timing report will include total and per run results.
530
530
531 For example (testing the script uniq_stable.py)::
531 For example (testing the script uniq_stable.py)::
532
532
533 In [1]: run -t uniq_stable
533 In [1]: run -t uniq_stable
534
534
535 IPython CPU timings (estimated):
535 IPython CPU timings (estimated):
536 User : 0.19597 s.
536 User : 0.19597 s.
537 System: 0.0 s.
537 System: 0.0 s.
538
538
539 In [2]: run -t -N5 uniq_stable
539 In [2]: run -t -N5 uniq_stable
540
540
541 IPython CPU timings (estimated):
541 IPython CPU timings (estimated):
542 Total runs performed: 5
542 Total runs performed: 5
543 Times : Total Per run
543 Times : Total Per run
544 User : 0.910862 s, 0.1821724 s.
544 User : 0.910862 s, 0.1821724 s.
545 System: 0.0 s, 0.0 s.
545 System: 0.0 s, 0.0 s.
546
546
547 -d
547 -d
548 run your program under the control of pdb, the Python debugger.
548 run your program under the control of pdb, the Python debugger.
549 This allows you to execute your program step by step, watch variables,
549 This allows you to execute your program step by step, watch variables,
550 etc. Internally, what IPython does is similar to calling::
550 etc. Internally, what IPython does is similar to calling::
551
551
552 pdb.run('execfile("YOURFILENAME")')
552 pdb.run('execfile("YOURFILENAME")')
553
553
554 with a breakpoint set on line 1 of your file. You can change the line
554 with a breakpoint set on line 1 of your file. You can change the line
555 number for this automatic breakpoint to be <N> by using the -bN option
555 number for this automatic breakpoint to be <N> by using the -bN option
556 (where N must be an integer). For example::
556 (where N must be an integer). For example::
557
557
558 %run -d -b40 myscript
558 %run -d -b40 myscript
559
559
560 will set the first breakpoint at line 40 in myscript.py. Note that
560 will set the first breakpoint at line 40 in myscript.py. Note that
561 the first breakpoint must be set on a line which actually does
561 the first breakpoint must be set on a line which actually does
562 something (not a comment or docstring) for it to stop execution.
562 something (not a comment or docstring) for it to stop execution.
563
563
564 Or you can specify a breakpoint in a different file::
564 Or you can specify a breakpoint in a different file::
565
565
566 %run -d -b myotherfile.py:20 myscript
566 %run -d -b myotherfile.py:20 myscript
567
567
568 When the pdb debugger starts, you will see a (Pdb) prompt. You must
568 When the pdb debugger starts, you will see a (Pdb) prompt. You must
569 first enter 'c' (without quotes) to start execution up to the first
569 first enter 'c' (without quotes) to start execution up to the first
570 breakpoint.
570 breakpoint.
571
571
572 Entering 'help' gives information about the use of the debugger. You
572 Entering 'help' gives information about the use of the debugger. You
573 can easily see pdb's full documentation with "import pdb;pdb.help()"
573 can easily see pdb's full documentation with "import pdb;pdb.help()"
574 at a prompt.
574 at a prompt.
575
575
576 -p
576 -p
577 run program under the control of the Python profiler module (which
577 run program under the control of the Python profiler module (which
578 prints a detailed report of execution times, function calls, etc).
578 prints a detailed report of execution times, function calls, etc).
579
579
580 You can pass other options after -p which affect the behavior of the
580 You can pass other options after -p which affect the behavior of the
581 profiler itself. See the docs for %prun for details.
581 profiler itself. See the docs for %prun for details.
582
582
583 In this mode, the program's variables do NOT propagate back to the
583 In this mode, the program's variables do NOT propagate back to the
584 IPython interactive namespace (because they remain in the namespace
584 IPython interactive namespace (because they remain in the namespace
585 where the profiler executes them).
585 where the profiler executes them).
586
586
587 Internally this triggers a call to %prun, see its documentation for
587 Internally this triggers a call to %prun, see its documentation for
588 details on the options available specifically for profiling.
588 details on the options available specifically for profiling.
589
589
590 There is one special usage for which the text above doesn't apply:
590 There is one special usage for which the text above doesn't apply:
591 if the filename ends with .ipy[nb], the file is run as ipython script,
591 if the filename ends with .ipy[nb], the file is run as ipython script,
592 just as if the commands were written on IPython prompt.
592 just as if the commands were written on IPython prompt.
593
593
594 -m
594 -m
595 specify module name to load instead of script path. Similar to
595 specify module name to load instead of script path. Similar to
596 the -m option for the python interpreter. Use this option last if you
596 the -m option for the python interpreter. Use this option last if you
597 want to combine with other %run options. Unlike the python interpreter
597 want to combine with other %run options. Unlike the python interpreter
598 only source modules are allowed no .pyc or .pyo files.
598 only source modules are allowed no .pyc or .pyo files.
599 For example::
599 For example::
600
600
601 %run -m example
601 %run -m example
602
602
603 will run the example module.
603 will run the example module.
604
604
605 -G
605 -G
606 disable shell-like glob expansion of arguments.
606 disable shell-like glob expansion of arguments.
607
607
608 """
608 """
609
609
610 # get arguments and set sys.argv for program to be run.
610 # get arguments and set sys.argv for program to be run.
611 opts, arg_lst = self.parse_options(parameter_s,
611 opts, arg_lst = self.parse_options(parameter_s,
612 'nidtN:b:pD:l:rs:T:em:G',
612 'nidtN:b:pD:l:rs:T:em:G',
613 mode='list', list_all=1)
613 mode='list', list_all=1)
614 if "m" in opts:
614 if "m" in opts:
615 modulename = opts["m"][0]
615 modulename = opts["m"][0]
616 modpath = find_mod(modulename)
616 modpath = find_mod(modulename)
617 if modpath is None:
617 if modpath is None:
618 warn('%r is not a valid modulename on sys.path'%modulename)
618 warn('%r is not a valid modulename on sys.path'%modulename)
619 return
619 return
620 arg_lst = [modpath] + arg_lst
620 arg_lst = [modpath] + arg_lst
621 try:
621 try:
622 filename = file_finder(arg_lst[0])
622 filename = file_finder(arg_lst[0])
623 except IndexError:
623 except IndexError:
624 warn('you must provide at least a filename.')
624 warn('you must provide at least a filename.')
625 print('\n%run:\n', oinspect.getdoc(self.run))
625 print('\n%run:\n', oinspect.getdoc(self.run))
626 return
626 return
627 except IOError as e:
627 except IOError as e:
628 try:
628 try:
629 msg = str(e)
629 msg = str(e)
630 except UnicodeError:
630 except UnicodeError:
631 msg = e.message
631 msg = e.message
632 error(msg)
632 error(msg)
633 return
633 return
634
634
635 if filename.lower().endswith(('.ipy', '.ipynb')):
635 if filename.lower().endswith(('.ipy', '.ipynb')):
636 with preserve_keys(self.shell.user_ns, '__file__'):
636 with preserve_keys(self.shell.user_ns, '__file__'):
637 self.shell.user_ns['__file__'] = filename
637 self.shell.user_ns['__file__'] = filename
638 self.shell.safe_execfile_ipy(filename)
638 self.shell.safe_execfile_ipy(filename)
639 return
639 return
640
640
641 # Control the response to exit() calls made by the script being run
641 # Control the response to exit() calls made by the script being run
642 exit_ignore = 'e' in opts
642 exit_ignore = 'e' in opts
643
643
644 # Make sure that the running script gets a proper sys.argv as if it
644 # Make sure that the running script gets a proper sys.argv as if it
645 # were run from a system shell.
645 # were run from a system shell.
646 save_argv = sys.argv # save it for later restoring
646 save_argv = sys.argv # save it for later restoring
647
647
648 if 'G' in opts:
648 if 'G' in opts:
649 args = arg_lst[1:]
649 args = arg_lst[1:]
650 else:
650 else:
651 # tilde and glob expansion
651 # tilde and glob expansion
652 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
652 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
653
653
654 sys.argv = [filename] + args # put in the proper filename
654 sys.argv = [filename] + args # put in the proper filename
655 # protect sys.argv from potential unicode strings on Python 2:
655 # protect sys.argv from potential unicode strings on Python 2:
656 if not py3compat.PY3:
656 if not py3compat.PY3:
657 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
657 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
658
658
659 if 'i' in opts:
659 if 'i' in opts:
660 # Run in user's interactive namespace
660 # Run in user's interactive namespace
661 prog_ns = self.shell.user_ns
661 prog_ns = self.shell.user_ns
662 __name__save = self.shell.user_ns['__name__']
662 __name__save = self.shell.user_ns['__name__']
663 prog_ns['__name__'] = '__main__'
663 prog_ns['__name__'] = '__main__'
664 main_mod = self.shell.user_module
664 main_mod = self.shell.user_module
665
665
666 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
666 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
667 # set the __file__ global in the script's namespace
667 # set the __file__ global in the script's namespace
668 # TK: Is this necessary in interactive mode?
668 # TK: Is this necessary in interactive mode?
669 prog_ns['__file__'] = filename
669 prog_ns['__file__'] = filename
670 else:
670 else:
671 # Run in a fresh, empty namespace
671 # Run in a fresh, empty namespace
672 if 'n' in opts:
672 if 'n' in opts:
673 name = os.path.splitext(os.path.basename(filename))[0]
673 name = os.path.splitext(os.path.basename(filename))[0]
674 else:
674 else:
675 name = '__main__'
675 name = '__main__'
676
676
677 # The shell MUST hold a reference to prog_ns so after %run
677 # The shell MUST hold a reference to prog_ns so after %run
678 # exits, the python deletion mechanism doesn't zero it out
678 # exits, the python deletion mechanism doesn't zero it out
679 # (leaving dangling references). See interactiveshell for details
679 # (leaving dangling references). See interactiveshell for details
680 main_mod = self.shell.new_main_mod(filename, name)
680 main_mod = self.shell.new_main_mod(filename, name)
681 prog_ns = main_mod.__dict__
681 prog_ns = main_mod.__dict__
682
682
683 # pickle fix. See interactiveshell for an explanation. But we need to
683 # pickle fix. See interactiveshell for an explanation. But we need to
684 # make sure that, if we overwrite __main__, we replace it at the end
684 # make sure that, if we overwrite __main__, we replace it at the end
685 main_mod_name = prog_ns['__name__']
685 main_mod_name = prog_ns['__name__']
686
686
687 if main_mod_name == '__main__':
687 if main_mod_name == '__main__':
688 restore_main = sys.modules['__main__']
688 restore_main = sys.modules['__main__']
689 else:
689 else:
690 restore_main = False
690 restore_main = False
691
691
692 # This needs to be undone at the end to prevent holding references to
692 # This needs to be undone at the end to prevent holding references to
693 # every single object ever created.
693 # every single object ever created.
694 sys.modules[main_mod_name] = main_mod
694 sys.modules[main_mod_name] = main_mod
695
695
696 if 'p' in opts or 'd' in opts:
696 if 'p' in opts or 'd' in opts:
697 if 'm' in opts:
697 if 'm' in opts:
698 code = 'run_module(modulename, prog_ns)'
698 code = 'run_module(modulename, prog_ns)'
699 code_ns = {
699 code_ns = {
700 'run_module': self.shell.safe_run_module,
700 'run_module': self.shell.safe_run_module,
701 'prog_ns': prog_ns,
701 'prog_ns': prog_ns,
702 'modulename': modulename,
702 'modulename': modulename,
703 }
703 }
704 else:
704 else:
705 if 'd' in opts:
705 if 'd' in opts:
706 # allow exceptions to raise in debug mode
706 # allow exceptions to raise in debug mode
707 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
707 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
708 else:
708 else:
709 code = 'execfile(filename, prog_ns)'
709 code = 'execfile(filename, prog_ns)'
710 code_ns = {
710 code_ns = {
711 'execfile': self.shell.safe_execfile,
711 'execfile': self.shell.safe_execfile,
712 'prog_ns': prog_ns,
712 'prog_ns': prog_ns,
713 'filename': get_py_filename(filename),
713 'filename': get_py_filename(filename),
714 }
714 }
715
715
716 try:
716 try:
717 stats = None
717 stats = None
718 if 'p' in opts:
718 if 'p' in opts:
719 stats = self._run_with_profiler(code, opts, code_ns)
719 stats = self._run_with_profiler(code, opts, code_ns)
720 else:
720 else:
721 if 'd' in opts:
721 if 'd' in opts:
722 bp_file, bp_line = parse_breakpoint(
722 bp_file, bp_line = parse_breakpoint(
723 opts.get('b', ['1'])[0], filename)
723 opts.get('b', ['1'])[0], filename)
724 self._run_with_debugger(
724 self._run_with_debugger(
725 code, code_ns, filename, bp_line, bp_file)
725 code, code_ns, filename, bp_line, bp_file)
726 else:
726 else:
727 if 'm' in opts:
727 if 'm' in opts:
728 def run():
728 def run():
729 self.shell.safe_run_module(modulename, prog_ns)
729 self.shell.safe_run_module(modulename, prog_ns)
730 else:
730 else:
731 if runner is None:
731 if runner is None:
732 runner = self.default_runner
732 runner = self.default_runner
733 if runner is None:
733 if runner is None:
734 runner = self.shell.safe_execfile
734 runner = self.shell.safe_execfile
735
735
736 def run():
736 def run():
737 runner(filename, prog_ns, prog_ns,
737 runner(filename, prog_ns, prog_ns,
738 exit_ignore=exit_ignore)
738 exit_ignore=exit_ignore)
739
739
740 if 't' in opts:
740 if 't' in opts:
741 # timed execution
741 # timed execution
742 try:
742 try:
743 nruns = int(opts['N'][0])
743 nruns = int(opts['N'][0])
744 if nruns < 1:
744 if nruns < 1:
745 error('Number of runs must be >=1')
745 error('Number of runs must be >=1')
746 return
746 return
747 except (KeyError):
747 except (KeyError):
748 nruns = 1
748 nruns = 1
749 self._run_with_timing(run, nruns)
749 self._run_with_timing(run, nruns)
750 else:
750 else:
751 # regular execution
751 # regular execution
752 run()
752 run()
753
753
754 if 'i' in opts:
754 if 'i' in opts:
755 self.shell.user_ns['__name__'] = __name__save
755 self.shell.user_ns['__name__'] = __name__save
756 else:
756 else:
757 # update IPython interactive namespace
757 # update IPython interactive namespace
758
758
759 # Some forms of read errors on the file may mean the
759 # Some forms of read errors on the file may mean the
760 # __name__ key was never set; using pop we don't have to
760 # __name__ key was never set; using pop we don't have to
761 # worry about a possible KeyError.
761 # worry about a possible KeyError.
762 prog_ns.pop('__name__', None)
762 prog_ns.pop('__name__', None)
763
763
764 with preserve_keys(self.shell.user_ns, '__file__'):
764 with preserve_keys(self.shell.user_ns, '__file__'):
765 self.shell.user_ns.update(prog_ns)
765 self.shell.user_ns.update(prog_ns)
766 finally:
766 finally:
767 # It's a bit of a mystery why, but __builtins__ can change from
767 # It's a bit of a mystery why, but __builtins__ can change from
768 # being a module to becoming a dict missing some key data after
768 # being a module to becoming a dict missing some key data after
769 # %run. As best I can see, this is NOT something IPython is doing
769 # %run. As best I can see, this is NOT something IPython is doing
770 # at all, and similar problems have been reported before:
770 # at all, and similar problems have been reported before:
771 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
771 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
772 # Since this seems to be done by the interpreter itself, the best
772 # Since this seems to be done by the interpreter itself, the best
773 # we can do is to at least restore __builtins__ for the user on
773 # we can do is to at least restore __builtins__ for the user on
774 # exit.
774 # exit.
775 self.shell.user_ns['__builtins__'] = builtin_mod
775 self.shell.user_ns['__builtins__'] = builtin_mod
776
776
777 # Ensure key global structures are restored
777 # Ensure key global structures are restored
778 sys.argv = save_argv
778 sys.argv = save_argv
779 if restore_main:
779 if restore_main:
780 sys.modules['__main__'] = restore_main
780 sys.modules['__main__'] = restore_main
781 else:
781 else:
782 # Remove from sys.modules the reference to main_mod we'd
782 # Remove from sys.modules the reference to main_mod we'd
783 # added. Otherwise it will trap references to objects
783 # added. Otherwise it will trap references to objects
784 # contained therein.
784 # contained therein.
785 del sys.modules[main_mod_name]
785 del sys.modules[main_mod_name]
786
786
787 return stats
787 return stats
788
788
789 def _run_with_debugger(self, code, code_ns, filename=None,
789 def _run_with_debugger(self, code, code_ns, filename=None,
790 bp_line=None, bp_file=None):
790 bp_line=None, bp_file=None):
791 """
791 """
792 Run `code` in debugger with a break point.
792 Run `code` in debugger with a break point.
793
793
794 Parameters
794 Parameters
795 ----------
795 ----------
796 code : str
796 code : str
797 Code to execute.
797 Code to execute.
798 code_ns : dict
798 code_ns : dict
799 A namespace in which `code` is executed.
799 A namespace in which `code` is executed.
800 filename : str
800 filename : str
801 `code` is ran as if it is in `filename`.
801 `code` is ran as if it is in `filename`.
802 bp_line : int, optional
802 bp_line : int, optional
803 Line number of the break point.
803 Line number of the break point.
804 bp_file : str, optional
804 bp_file : str, optional
805 Path to the file in which break point is specified.
805 Path to the file in which break point is specified.
806 `filename` is used if not given.
806 `filename` is used if not given.
807
807
808 Raises
808 Raises
809 ------
809 ------
810 UsageError
810 UsageError
811 If the break point given by `bp_line` is not valid.
811 If the break point given by `bp_line` is not valid.
812
812
813 """
813 """
814 deb = self.shell.InteractiveTB.pdb
814 deb = self.shell.InteractiveTB.pdb
815 if not deb:
815 if not deb:
816 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
816 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
817 deb = self.shell.InteractiveTB.pdb
817 deb = self.shell.InteractiveTB.pdb
818
818
819 # deb.checkline() fails if deb.curframe exists but is None; it can
819 # deb.checkline() fails if deb.curframe exists but is None; it can
820 # handle it not existing. https://github.com/ipython/ipython/issues/10028
820 # handle it not existing. https://github.com/ipython/ipython/issues/10028
821 if hasattr(deb, 'curframe'):
821 if hasattr(deb, 'curframe'):
822 del deb.curframe
822 del deb.curframe
823
823
824 # reset Breakpoint state, which is moronically kept
824 # reset Breakpoint state, which is moronically kept
825 # in a class
825 # in a class
826 bdb.Breakpoint.next = 1
826 bdb.Breakpoint.next = 1
827 bdb.Breakpoint.bplist = {}
827 bdb.Breakpoint.bplist = {}
828 bdb.Breakpoint.bpbynumber = [None]
828 bdb.Breakpoint.bpbynumber = [None]
829 if bp_line is not None:
829 if bp_line is not None:
830 # Set an initial breakpoint to stop execution
830 # Set an initial breakpoint to stop execution
831 maxtries = 10
831 maxtries = 10
832 bp_file = bp_file or filename
832 bp_file = bp_file or filename
833 checkline = deb.checkline(bp_file, bp_line)
833 checkline = deb.checkline(bp_file, bp_line)
834 if not checkline:
834 if not checkline:
835 for bp in range(bp_line + 1, bp_line + maxtries + 1):
835 for bp in range(bp_line + 1, bp_line + maxtries + 1):
836 if deb.checkline(bp_file, bp):
836 if deb.checkline(bp_file, bp):
837 break
837 break
838 else:
838 else:
839 msg = ("\nI failed to find a valid line to set "
839 msg = ("\nI failed to find a valid line to set "
840 "a breakpoint\n"
840 "a breakpoint\n"
841 "after trying up to line: %s.\n"
841 "after trying up to line: %s.\n"
842 "Please set a valid breakpoint manually "
842 "Please set a valid breakpoint manually "
843 "with the -b option." % bp)
843 "with the -b option." % bp)
844 raise UsageError(msg)
844 raise UsageError(msg)
845 # if we find a good linenumber, set the breakpoint
845 # if we find a good linenumber, set the breakpoint
846 deb.do_break('%s:%s' % (bp_file, bp_line))
846 deb.do_break('%s:%s' % (bp_file, bp_line))
847
847
848 if filename:
848 if filename:
849 # Mimic Pdb._runscript(...)
849 # Mimic Pdb._runscript(...)
850 deb._wait_for_mainpyfile = True
850 deb._wait_for_mainpyfile = True
851 deb.mainpyfile = deb.canonic(filename)
851 deb.mainpyfile = deb.canonic(filename)
852
852
853 # Start file run
853 # Start file run
854 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
854 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
855 try:
855 try:
856 if filename:
856 if filename:
857 # save filename so it can be used by methods on the deb object
857 # save filename so it can be used by methods on the deb object
858 deb._exec_filename = filename
858 deb._exec_filename = filename
859 while True:
859 while True:
860 try:
860 try:
861 deb.run(code, code_ns)
861 deb.run(code, code_ns)
862 except Restart:
862 except Restart:
863 print("Restarting")
863 print("Restarting")
864 if filename:
864 if filename:
865 deb._wait_for_mainpyfile = True
865 deb._wait_for_mainpyfile = True
866 deb.mainpyfile = deb.canonic(filename)
866 deb.mainpyfile = deb.canonic(filename)
867 continue
867 continue
868 else:
868 else:
869 break
869 break
870
870
871
871
872 except:
872 except:
873 etype, value, tb = sys.exc_info()
873 etype, value, tb = sys.exc_info()
874 # Skip three frames in the traceback: the %run one,
874 # Skip three frames in the traceback: the %run one,
875 # one inside bdb.py, and the command-line typed by the
875 # one inside bdb.py, and the command-line typed by the
876 # user (run by exec in pdb itself).
876 # user (run by exec in pdb itself).
877 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
877 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
878
878
879 @staticmethod
879 @staticmethod
880 def _run_with_timing(run, nruns):
880 def _run_with_timing(run, nruns):
881 """
881 """
882 Run function `run` and print timing information.
882 Run function `run` and print timing information.
883
883
884 Parameters
884 Parameters
885 ----------
885 ----------
886 run : callable
886 run : callable
887 Any callable object which takes no argument.
887 Any callable object which takes no argument.
888 nruns : int
888 nruns : int
889 Number of times to execute `run`.
889 Number of times to execute `run`.
890
890
891 """
891 """
892 twall0 = time.time()
892 twall0 = time.time()
893 if nruns == 1:
893 if nruns == 1:
894 t0 = clock2()
894 t0 = clock2()
895 run()
895 run()
896 t1 = clock2()
896 t1 = clock2()
897 t_usr = t1[0] - t0[0]
897 t_usr = t1[0] - t0[0]
898 t_sys = t1[1] - t0[1]
898 t_sys = t1[1] - t0[1]
899 print("\nIPython CPU timings (estimated):")
899 print("\nIPython CPU timings (estimated):")
900 print(" User : %10.2f s." % t_usr)
900 print(" User : %10.2f s." % t_usr)
901 print(" System : %10.2f s." % t_sys)
901 print(" System : %10.2f s." % t_sys)
902 else:
902 else:
903 runs = range(nruns)
903 runs = range(nruns)
904 t0 = clock2()
904 t0 = clock2()
905 for nr in runs:
905 for nr in runs:
906 run()
906 run()
907 t1 = clock2()
907 t1 = clock2()
908 t_usr = t1[0] - t0[0]
908 t_usr = t1[0] - t0[0]
909 t_sys = t1[1] - t0[1]
909 t_sys = t1[1] - t0[1]
910 print("\nIPython CPU timings (estimated):")
910 print("\nIPython CPU timings (estimated):")
911 print("Total runs performed:", nruns)
911 print("Total runs performed:", nruns)
912 print(" Times : %10s %10s" % ('Total', 'Per run'))
912 print(" Times : %10s %10s" % ('Total', 'Per run'))
913 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
913 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
914 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
914 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
915 twall1 = time.time()
915 twall1 = time.time()
916 print("Wall time: %10.2f s." % (twall1 - twall0))
916 print("Wall time: %10.2f s." % (twall1 - twall0))
917
917
918 @skip_doctest
918 @skip_doctest
919 @line_cell_magic
919 @line_cell_magic
920 def timeit(self, line='', cell=None):
920 def timeit(self, line='', cell=None):
921 """Time execution of a Python statement or expression
921 """Time execution of a Python statement or expression
922
922
923 Usage, in line mode:
923 Usage, in line mode:
924 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
924 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
925 or in cell mode:
925 or in cell mode:
926 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
926 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
927 code
927 code
928 code...
928 code...
929
929
930 Time execution of a Python statement or expression using the timeit
930 Time execution of a Python statement or expression using the timeit
931 module. This function can be used both as a line and cell magic:
931 module. This function can be used both as a line and cell magic:
932
932
933 - In line mode you can time a single-line statement (though multiple
933 - In line mode you can time a single-line statement (though multiple
934 ones can be chained with using semicolons).
934 ones can be chained with using semicolons).
935
935
936 - In cell mode, the statement in the first line is used as setup code
936 - In cell mode, the statement in the first line is used as setup code
937 (executed but not timed) and the body of the cell is timed. The cell
937 (executed but not timed) and the body of the cell is timed. The cell
938 body has access to any variables created in the setup code.
938 body has access to any variables created in the setup code.
939
939
940 Options:
940 Options:
941 -n<N>: execute the given statement <N> times in a loop. If this value
941 -n<N>: execute the given statement <N> times in a loop. If this value
942 is not given, a fitting value is chosen.
942 is not given, a fitting value is chosen.
943
943
944 -r<R>: repeat the loop iteration <R> times and take the best result.
944 -r<R>: repeat the loop iteration <R> times and take the best result.
945 Default: 3
945 Default: 3
946
946
947 -t: use time.time to measure the time, which is the default on Unix.
947 -t: use time.time to measure the time, which is the default on Unix.
948 This function measures wall time.
948 This function measures wall time.
949
949
950 -c: use time.clock to measure the time, which is the default on
950 -c: use time.clock to measure the time, which is the default on
951 Windows and measures wall time. On Unix, resource.getrusage is used
951 Windows and measures wall time. On Unix, resource.getrusage is used
952 instead and returns the CPU user time.
952 instead and returns the CPU user time.
953
953
954 -p<P>: use a precision of <P> digits to display the timing result.
954 -p<P>: use a precision of <P> digits to display the timing result.
955 Default: 3
955 Default: 3
956
956
957 -q: Quiet, do not print result.
957 -q: Quiet, do not print result.
958
958
959 -o: return a TimeitResult that can be stored in a variable to inspect
959 -o: return a TimeitResult that can be stored in a variable to inspect
960 the result in more details.
960 the result in more details.
961
961
962
962
963 Examples
963 Examples
964 --------
964 --------
965 ::
965 ::
966
966
967 In [1]: %timeit pass
967 In [1]: %timeit pass
968 100000000 loops, average of 7: 5.48 ns +- 0.354 ns per loop (using standard deviation)
968 100000000 loops, average of 7: 5.48 ns +- 0.354 ns per loop (using standard deviation)
969
969
970 In [2]: u = None
970 In [2]: u = None
971
971
972 In [3]: %timeit u is None
972 In [3]: %timeit u is None
973 10000000 loops, average of 7: 22.7 ns +- 2.33 ns per loop (using standard deviation)
973 10000000 loops, average of 7: 22.7 ns +- 2.33 ns per loop (using standard deviation)
974
974
975 In [4]: %timeit -r 4 u == None
975 In [4]: %timeit -r 4 u == None
976 10000000 loops, average of 4: 27.5 ns +- 2.91 ns per loop (using standard deviation)
976 10000000 loops, average of 4: 27.5 ns +- 2.91 ns per loop (using standard deviation)
977
977
978 In [5]: import time
978 In [5]: import time
979
979
980 In [6]: %timeit -n1 time.sleep(2)
980 In [6]: %timeit -n1 time.sleep(2)
981 1 loop, average of 7: 2 s +- 4.71 µs per loop (using standard deviation)
981 1 loop, average of 7: 2 s +- 4.71 µs per loop (using standard deviation)
982
982
983
983
984 The times reported by %timeit will be slightly higher than those
984 The times reported by %timeit will be slightly higher than those
985 reported by the timeit.py script when variables are accessed. This is
985 reported by the timeit.py script when variables are accessed. This is
986 due to the fact that %timeit executes the statement in the namespace
986 due to the fact that %timeit executes the statement in the namespace
987 of the shell, compared with timeit.py, which uses a single setup
987 of the shell, compared with timeit.py, which uses a single setup
988 statement to import function or create variables. Generally, the bias
988 statement to import function or create variables. Generally, the bias
989 does not matter as long as results from timeit.py are not mixed with
989 does not matter as long as results from timeit.py are not mixed with
990 those from %timeit."""
990 those from %timeit."""
991
991
992 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
992 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
993 posix=False, strict=False)
993 posix=False, strict=False)
994 if stmt == "" and cell is None:
994 if stmt == "" and cell is None:
995 return
995 return
996
996
997 timefunc = timeit.default_timer
997 timefunc = timeit.default_timer
998 number = int(getattr(opts, "n", 0))
998 number = int(getattr(opts, "n", 0))
999 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
999 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1000 repeat = int(getattr(opts, "r", default_repeat))
1000 repeat = int(getattr(opts, "r", default_repeat))
1001 precision = int(getattr(opts, "p", 3))
1001 precision = int(getattr(opts, "p", 3))
1002 quiet = 'q' in opts
1002 quiet = 'q' in opts
1003 return_result = 'o' in opts
1003 return_result = 'o' in opts
1004 if hasattr(opts, "t"):
1004 if hasattr(opts, "t"):
1005 timefunc = time.time
1005 timefunc = time.time
1006 if hasattr(opts, "c"):
1006 if hasattr(opts, "c"):
1007 timefunc = clock
1007 timefunc = clock
1008
1008
1009 timer = Timer(timer=timefunc)
1009 timer = Timer(timer=timefunc)
1010 # this code has tight coupling to the inner workings of timeit.Timer,
1010 # this code has tight coupling to the inner workings of timeit.Timer,
1011 # but is there a better way to achieve that the code stmt has access
1011 # but is there a better way to achieve that the code stmt has access
1012 # to the shell namespace?
1012 # to the shell namespace?
1013 transform = self.shell.input_splitter.transform_cell
1013 transform = self.shell.input_splitter.transform_cell
1014
1014
1015 if cell is None:
1015 if cell is None:
1016 # called as line magic
1016 # called as line magic
1017 ast_setup = self.shell.compile.ast_parse("pass")
1017 ast_setup = self.shell.compile.ast_parse("pass")
1018 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1018 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1019 else:
1019 else:
1020 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1020 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1021 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1021 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1022
1022
1023 ast_setup = self.shell.transform_ast(ast_setup)
1023 ast_setup = self.shell.transform_ast(ast_setup)
1024 ast_stmt = self.shell.transform_ast(ast_stmt)
1024 ast_stmt = self.shell.transform_ast(ast_stmt)
1025
1025
1026 # This codestring is taken from timeit.template - we fill it in as an
1026 # This codestring is taken from timeit.template - we fill it in as an
1027 # AST, so that we can apply our AST transformations to the user code
1027 # AST, so that we can apply our AST transformations to the user code
1028 # without affecting the timing code.
1028 # without affecting the timing code.
1029 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1029 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1030 ' setup\n'
1030 ' setup\n'
1031 ' _t0 = _timer()\n'
1031 ' _t0 = _timer()\n'
1032 ' for _i in _it:\n'
1032 ' for _i in _it:\n'
1033 ' stmt\n'
1033 ' stmt\n'
1034 ' _t1 = _timer()\n'
1034 ' _t1 = _timer()\n'
1035 ' return _t1 - _t0\n')
1035 ' return _t1 - _t0\n')
1036
1036
1037 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1037 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1038 timeit_ast = ast.fix_missing_locations(timeit_ast)
1038 timeit_ast = ast.fix_missing_locations(timeit_ast)
1039
1039
1040 # Track compilation time so it can be reported if too long
1040 # Track compilation time so it can be reported if too long
1041 # Minimum time above which compilation time will be reported
1041 # Minimum time above which compilation time will be reported
1042 tc_min = 0.1
1042 tc_min = 0.1
1043
1043
1044 t0 = clock()
1044 t0 = clock()
1045 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1045 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1046 tc = clock()-t0
1046 tc = clock()-t0
1047
1047
1048 ns = {}
1048 ns = {}
1049 exec(code, self.shell.user_ns, ns)
1049 exec(code, self.shell.user_ns, ns)
1050 timer.inner = ns["inner"]
1050 timer.inner = ns["inner"]
1051
1051
1052 # This is used to check if there is a huge difference between the
1052 # This is used to check if there is a huge difference between the
1053 # best and worst timings.
1053 # best and worst timings.
1054 # Issue: https://github.com/ipython/ipython/issues/6471
1054 # Issue: https://github.com/ipython/ipython/issues/6471
1055 if number == 0:
1055 if number == 0:
1056 # determine number so that 0.2 <= total time < 2.0
1056 # determine number so that 0.2 <= total time < 2.0
1057 for index in range(0, 10):
1057 for index in range(0, 10):
1058 number = 10 ** index
1058 number = 10 ** index
1059 time_number = timer.timeit(number)
1059 time_number = timer.timeit(number)
1060 if time_number >= 0.2:
1060 if time_number >= 0.2:
1061 break
1061 break
1062
1062
1063 all_runs = timer.repeat(repeat, number)
1063 all_runs = timer.repeat(repeat, number)
1064 best = min(all_runs) / number
1064 best = min(all_runs) / number
1065 worst = max(all_runs) / number
1065 worst = max(all_runs) / number
1066 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1066 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1067
1067
1068 if not quiet :
1068 if not quiet :
1069 # Check best timing is greater than zero to avoid a
1069 # Check best timing is greater than zero to avoid a
1070 # ZeroDivisionError.
1070 # ZeroDivisionError.
1071 # In cases where the slowest timing is lesser than a micosecond
1071 # In cases where the slowest timing is lesser than a micosecond
1072 # we assume that it does not really matter if the fastest
1072 # we assume that it does not really matter if the fastest
1073 # timing is 4 times faster than the slowest timing or not.
1073 # timing is 4 times faster than the slowest timing or not.
1074 if worst > 4 * best and best > 0 and worst > 1e-6:
1074 if worst > 4 * best and best > 0 and worst > 1e-6:
1075 print("The slowest run took %0.2f times longer than the "
1075 print("The slowest run took %0.2f times longer than the "
1076 "fastest. This could mean that an intermediate result "
1076 "fastest. This could mean that an intermediate result "
1077 "is being cached." % (worst / best))
1077 "is being cached." % (worst / best))
1078
1078
1079 print( timeit_result )
1079 print( timeit_result )
1080
1080
1081 if tc > tc_min:
1081 if tc > tc_min:
1082 print("Compiler time: %.2f s" % tc)
1082 print("Compiler time: %.2f s" % tc)
1083 if return_result:
1083 if return_result:
1084 return timeit_result
1084 return timeit_result
1085
1085
1086 @skip_doctest
1086 @skip_doctest
1087 @needs_local_scope
1087 @needs_local_scope
1088 @line_cell_magic
1088 @line_cell_magic
1089 def time(self,line='', cell=None, local_ns=None):
1089 def time(self,line='', cell=None, local_ns=None):
1090 """Time execution of a Python statement or expression.
1090 """Time execution of a Python statement or expression.
1091
1091
1092 The CPU and wall clock times are printed, and the value of the
1092 The CPU and wall clock times are printed, and the value of the
1093 expression (if any) is returned. Note that under Win32, system time
1093 expression (if any) is returned. Note that under Win32, system time
1094 is always reported as 0, since it can not be measured.
1094 is always reported as 0, since it can not be measured.
1095
1095
1096 This function can be used both as a line and cell magic:
1096 This function can be used both as a line and cell magic:
1097
1097
1098 - In line mode you can time a single-line statement (though multiple
1098 - In line mode you can time a single-line statement (though multiple
1099 ones can be chained with using semicolons).
1099 ones can be chained with using semicolons).
1100
1100
1101 - In cell mode, you can time the cell body (a directly
1101 - In cell mode, you can time the cell body (a directly
1102 following statement raises an error).
1102 following statement raises an error).
1103
1103
1104 This function provides very basic timing functionality. Use the timeit
1104 This function provides very basic timing functionality. Use the timeit
1105 magic for more control over the measurement.
1105 magic for more control over the measurement.
1106
1106
1107 Examples
1107 Examples
1108 --------
1108 --------
1109 ::
1109 ::
1110
1110
1111 In [1]: %time 2**128
1111 In [1]: %time 2**128
1112 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1112 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1113 Wall time: 0.00
1113 Wall time: 0.00
1114 Out[1]: 340282366920938463463374607431768211456L
1114 Out[1]: 340282366920938463463374607431768211456L
1115
1115
1116 In [2]: n = 1000000
1116 In [2]: n = 1000000
1117
1117
1118 In [3]: %time sum(range(n))
1118 In [3]: %time sum(range(n))
1119 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1119 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1120 Wall time: 1.37
1120 Wall time: 1.37
1121 Out[3]: 499999500000L
1121 Out[3]: 499999500000L
1122
1122
1123 In [4]: %time print 'hello world'
1123 In [4]: %time print 'hello world'
1124 hello world
1124 hello world
1125 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1125 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1126 Wall time: 0.00
1126 Wall time: 0.00
1127
1127
1128 Note that the time needed by Python to compile the given expression
1128 Note that the time needed by Python to compile the given expression
1129 will be reported if it is more than 0.1s. In this example, the
1129 will be reported if it is more than 0.1s. In this example, the
1130 actual exponentiation is done by Python at compilation time, so while
1130 actual exponentiation is done by Python at compilation time, so while
1131 the expression can take a noticeable amount of time to compute, that
1131 the expression can take a noticeable amount of time to compute, that
1132 time is purely due to the compilation:
1132 time is purely due to the compilation:
1133
1133
1134 In [5]: %time 3**9999;
1134 In [5]: %time 3**9999;
1135 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1135 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1136 Wall time: 0.00 s
1136 Wall time: 0.00 s
1137
1137
1138 In [6]: %time 3**999999;
1138 In [6]: %time 3**999999;
1139 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1139 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1140 Wall time: 0.00 s
1140 Wall time: 0.00 s
1141 Compiler : 0.78 s
1141 Compiler : 0.78 s
1142 """
1142 """
1143
1143
1144 # fail immediately if the given expression can't be compiled
1144 # fail immediately if the given expression can't be compiled
1145
1145
1146 if line and cell:
1146 if line and cell:
1147 raise UsageError("Can't use statement directly after '%%time'!")
1147 raise UsageError("Can't use statement directly after '%%time'!")
1148
1148
1149 if cell:
1149 if cell:
1150 expr = self.shell.input_transformer_manager.transform_cell(cell)
1150 expr = self.shell.input_transformer_manager.transform_cell(cell)
1151 else:
1151 else:
1152 expr = self.shell.input_transformer_manager.transform_cell(line)
1152 expr = self.shell.input_transformer_manager.transform_cell(line)
1153
1153
1154 # Minimum time above which parse time will be reported
1154 # Minimum time above which parse time will be reported
1155 tp_min = 0.1
1155 tp_min = 0.1
1156
1156
1157 t0 = clock()
1157 t0 = clock()
1158 expr_ast = self.shell.compile.ast_parse(expr)
1158 expr_ast = self.shell.compile.ast_parse(expr)
1159 tp = clock()-t0
1159 tp = clock()-t0
1160
1160
1161 # Apply AST transformations
1161 # Apply AST transformations
1162 expr_ast = self.shell.transform_ast(expr_ast)
1162 expr_ast = self.shell.transform_ast(expr_ast)
1163
1163
1164 # Minimum time above which compilation time will be reported
1164 # Minimum time above which compilation time will be reported
1165 tc_min = 0.1
1165 tc_min = 0.1
1166
1166
1167 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1167 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1168 mode = 'eval'
1168 mode = 'eval'
1169 source = '<timed eval>'
1169 source = '<timed eval>'
1170 expr_ast = ast.Expression(expr_ast.body[0].value)
1170 expr_ast = ast.Expression(expr_ast.body[0].value)
1171 else:
1171 else:
1172 mode = 'exec'
1172 mode = 'exec'
1173 source = '<timed exec>'
1173 source = '<timed exec>'
1174 t0 = clock()
1174 t0 = clock()
1175 code = self.shell.compile(expr_ast, source, mode)
1175 code = self.shell.compile(expr_ast, source, mode)
1176 tc = clock()-t0
1176 tc = clock()-t0
1177
1177
1178 # skew measurement as little as possible
1178 # skew measurement as little as possible
1179 glob = self.shell.user_ns
1179 glob = self.shell.user_ns
1180 wtime = time.time
1180 wtime = time.time
1181 # time execution
1181 # time execution
1182 wall_st = wtime()
1182 wall_st = wtime()
1183 if mode=='eval':
1183 if mode=='eval':
1184 st = clock2()
1184 st = clock2()
1185 try:
1185 try:
1186 out = eval(code, glob, local_ns)
1186 out = eval(code, glob, local_ns)
1187 except:
1187 except:
1188 self.shell.showtraceback()
1188 self.shell.showtraceback()
1189 return
1189 return
1190 end = clock2()
1190 end = clock2()
1191 else:
1191 else:
1192 st = clock2()
1192 st = clock2()
1193 try:
1193 try:
1194 exec(code, glob, local_ns)
1194 exec(code, glob, local_ns)
1195 except:
1195 except:
1196 self.shell.showtraceback()
1196 self.shell.showtraceback()
1197 return
1197 return
1198 end = clock2()
1198 end = clock2()
1199 out = None
1199 out = None
1200 wall_end = wtime()
1200 wall_end = wtime()
1201 # Compute actual times and report
1201 # Compute actual times and report
1202 wall_time = wall_end-wall_st
1202 wall_time = wall_end-wall_st
1203 cpu_user = end[0]-st[0]
1203 cpu_user = end[0]-st[0]
1204 cpu_sys = end[1]-st[1]
1204 cpu_sys = end[1]-st[1]
1205 cpu_tot = cpu_user+cpu_sys
1205 cpu_tot = cpu_user+cpu_sys
1206 # On windows cpu_sys is always zero, so no new information to the next print
1206 # On windows cpu_sys is always zero, so no new information to the next print
1207 if sys.platform != 'win32':
1207 if sys.platform != 'win32':
1208 print("CPU times: user %s, sys: %s, total: %s" % \
1208 print("CPU times: user %s, sys: %s, total: %s" % \
1209 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1209 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1210 print("Wall time: %s" % _format_time(wall_time))
1210 print("Wall time: %s" % _format_time(wall_time))
1211 if tc > tc_min:
1211 if tc > tc_min:
1212 print("Compiler : %s" % _format_time(tc))
1212 print("Compiler : %s" % _format_time(tc))
1213 if tp > tp_min:
1213 if tp > tp_min:
1214 print("Parser : %s" % _format_time(tp))
1214 print("Parser : %s" % _format_time(tp))
1215 return out
1215 return out
1216
1216
1217 @skip_doctest
1217 @skip_doctest
1218 @line_magic
1218 @line_magic
1219 def macro(self, parameter_s=''):
1219 def macro(self, parameter_s=''):
1220 """Define a macro for future re-execution. It accepts ranges of history,
1220 """Define a macro for future re-execution. It accepts ranges of history,
1221 filenames or string objects.
1221 filenames or string objects.
1222
1222
1223 Usage:\\
1223 Usage:\\
1224 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1224 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1225
1225
1226 Options:
1226 Options:
1227
1227
1228 -r: use 'raw' input. By default, the 'processed' history is used,
1228 -r: use 'raw' input. By default, the 'processed' history is used,
1229 so that magics are loaded in their transformed version to valid
1229 so that magics are loaded in their transformed version to valid
1230 Python. If this option is given, the raw input as typed at the
1230 Python. If this option is given, the raw input as typed at the
1231 command line is used instead.
1231 command line is used instead.
1232
1232
1233 -q: quiet macro definition. By default, a tag line is printed
1233 -q: quiet macro definition. By default, a tag line is printed
1234 to indicate the macro has been created, and then the contents of
1234 to indicate the macro has been created, and then the contents of
1235 the macro are printed. If this option is given, then no printout
1235 the macro are printed. If this option is given, then no printout
1236 is produced once the macro is created.
1236 is produced once the macro is created.
1237
1237
1238 This will define a global variable called `name` which is a string
1238 This will define a global variable called `name` which is a string
1239 made of joining the slices and lines you specify (n1,n2,... numbers
1239 made of joining the slices and lines you specify (n1,n2,... numbers
1240 above) from your input history into a single string. This variable
1240 above) from your input history into a single string. This variable
1241 acts like an automatic function which re-executes those lines as if
1241 acts like an automatic function which re-executes those lines as if
1242 you had typed them. You just type 'name' at the prompt and the code
1242 you had typed them. You just type 'name' at the prompt and the code
1243 executes.
1243 executes.
1244
1244
1245 The syntax for indicating input ranges is described in %history.
1245 The syntax for indicating input ranges is described in %history.
1246
1246
1247 Note: as a 'hidden' feature, you can also use traditional python slice
1247 Note: as a 'hidden' feature, you can also use traditional python slice
1248 notation, where N:M means numbers N through M-1.
1248 notation, where N:M means numbers N through M-1.
1249
1249
1250 For example, if your history contains (print using %hist -n )::
1250 For example, if your history contains (print using %hist -n )::
1251
1251
1252 44: x=1
1252 44: x=1
1253 45: y=3
1253 45: y=3
1254 46: z=x+y
1254 46: z=x+y
1255 47: print x
1255 47: print x
1256 48: a=5
1256 48: a=5
1257 49: print 'x',x,'y',y
1257 49: print 'x',x,'y',y
1258
1258
1259 you can create a macro with lines 44 through 47 (included) and line 49
1259 you can create a macro with lines 44 through 47 (included) and line 49
1260 called my_macro with::
1260 called my_macro with::
1261
1261
1262 In [55]: %macro my_macro 44-47 49
1262 In [55]: %macro my_macro 44-47 49
1263
1263
1264 Now, typing `my_macro` (without quotes) will re-execute all this code
1264 Now, typing `my_macro` (without quotes) will re-execute all this code
1265 in one pass.
1265 in one pass.
1266
1266
1267 You don't need to give the line-numbers in order, and any given line
1267 You don't need to give the line-numbers in order, and any given line
1268 number can appear multiple times. You can assemble macros with any
1268 number can appear multiple times. You can assemble macros with any
1269 lines from your input history in any order.
1269 lines from your input history in any order.
1270
1270
1271 The macro is a simple object which holds its value in an attribute,
1271 The macro is a simple object which holds its value in an attribute,
1272 but IPython's display system checks for macros and executes them as
1272 but IPython's display system checks for macros and executes them as
1273 code instead of printing them when you type their name.
1273 code instead of printing them when you type their name.
1274
1274
1275 You can view a macro's contents by explicitly printing it with::
1275 You can view a macro's contents by explicitly printing it with::
1276
1276
1277 print macro_name
1277 print macro_name
1278
1278
1279 """
1279 """
1280 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1280 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1281 if not args: # List existing macros
1281 if not args: # List existing macros
1282 return sorted(k for k,v in iteritems(self.shell.user_ns) if\
1282 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1283 isinstance(v, Macro))
1284 if len(args) == 1:
1283 if len(args) == 1:
1285 raise UsageError(
1284 raise UsageError(
1286 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1285 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1287 name, codefrom = args[0], " ".join(args[1:])
1286 name, codefrom = args[0], " ".join(args[1:])
1288
1287
1289 #print 'rng',ranges # dbg
1288 #print 'rng',ranges # dbg
1290 try:
1289 try:
1291 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1290 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1292 except (ValueError, TypeError) as e:
1291 except (ValueError, TypeError) as e:
1293 print(e.args[0])
1292 print(e.args[0])
1294 return
1293 return
1295 macro = Macro(lines)
1294 macro = Macro(lines)
1296 self.shell.define_macro(name, macro)
1295 self.shell.define_macro(name, macro)
1297 if not ( 'q' in opts) :
1296 if not ( 'q' in opts) :
1298 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1297 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1299 print('=== Macro contents: ===')
1298 print('=== Macro contents: ===')
1300 print(macro, end=' ')
1299 print(macro, end=' ')
1301
1300
1302 @magic_arguments.magic_arguments()
1301 @magic_arguments.magic_arguments()
1303 @magic_arguments.argument('output', type=str, default='', nargs='?',
1302 @magic_arguments.argument('output', type=str, default='', nargs='?',
1304 help="""The name of the variable in which to store output.
1303 help="""The name of the variable in which to store output.
1305 This is a utils.io.CapturedIO object with stdout/err attributes
1304 This is a utils.io.CapturedIO object with stdout/err attributes
1306 for the text of the captured output.
1305 for the text of the captured output.
1307
1306
1308 CapturedOutput also has a show() method for displaying the output,
1307 CapturedOutput also has a show() method for displaying the output,
1309 and __call__ as well, so you can use that to quickly display the
1308 and __call__ as well, so you can use that to quickly display the
1310 output.
1309 output.
1311
1310
1312 If unspecified, captured output is discarded.
1311 If unspecified, captured output is discarded.
1313 """
1312 """
1314 )
1313 )
1315 @magic_arguments.argument('--no-stderr', action="store_true",
1314 @magic_arguments.argument('--no-stderr', action="store_true",
1316 help="""Don't capture stderr."""
1315 help="""Don't capture stderr."""
1317 )
1316 )
1318 @magic_arguments.argument('--no-stdout', action="store_true",
1317 @magic_arguments.argument('--no-stdout', action="store_true",
1319 help="""Don't capture stdout."""
1318 help="""Don't capture stdout."""
1320 )
1319 )
1321 @magic_arguments.argument('--no-display', action="store_true",
1320 @magic_arguments.argument('--no-display', action="store_true",
1322 help="""Don't capture IPython's rich display."""
1321 help="""Don't capture IPython's rich display."""
1323 )
1322 )
1324 @cell_magic
1323 @cell_magic
1325 def capture(self, line, cell):
1324 def capture(self, line, cell):
1326 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1325 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1327 args = magic_arguments.parse_argstring(self.capture, line)
1326 args = magic_arguments.parse_argstring(self.capture, line)
1328 out = not args.no_stdout
1327 out = not args.no_stdout
1329 err = not args.no_stderr
1328 err = not args.no_stderr
1330 disp = not args.no_display
1329 disp = not args.no_display
1331 with capture_output(out, err, disp) as io:
1330 with capture_output(out, err, disp) as io:
1332 self.shell.run_cell(cell)
1331 self.shell.run_cell(cell)
1333 if args.output:
1332 if args.output:
1334 self.shell.user_ns[args.output] = io
1333 self.shell.user_ns[args.output] = io
1335
1334
1336 def parse_breakpoint(text, current_file):
1335 def parse_breakpoint(text, current_file):
1337 '''Returns (file, line) for file:line and (current_file, line) for line'''
1336 '''Returns (file, line) for file:line and (current_file, line) for line'''
1338 colon = text.find(':')
1337 colon = text.find(':')
1339 if colon == -1:
1338 if colon == -1:
1340 return current_file, int(text)
1339 return current_file, int(text)
1341 else:
1340 else:
1342 return text[:colon], int(text[colon+1:])
1341 return text[:colon], int(text[colon+1:])
1343
1342
1344 def _format_time(timespan, precision=3):
1343 def _format_time(timespan, precision=3):
1345 """Formats the timespan in a human readable form"""
1344 """Formats the timespan in a human readable form"""
1346
1345
1347 if timespan >= 60.0:
1346 if timespan >= 60.0:
1348 # we have more than a minute, format that in a human readable form
1347 # we have more than a minute, format that in a human readable form
1349 # Idea from http://snipplr.com/view/5713/
1348 # Idea from http://snipplr.com/view/5713/
1350 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1349 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1351 time = []
1350 time = []
1352 leftover = timespan
1351 leftover = timespan
1353 for suffix, length in parts:
1352 for suffix, length in parts:
1354 value = int(leftover / length)
1353 value = int(leftover / length)
1355 if value > 0:
1354 if value > 0:
1356 leftover = leftover % length
1355 leftover = leftover % length
1357 time.append(u'%s%s' % (str(value), suffix))
1356 time.append(u'%s%s' % (str(value), suffix))
1358 if leftover < 1:
1357 if leftover < 1:
1359 break
1358 break
1360 return " ".join(time)
1359 return " ".join(time)
1361
1360
1362
1361
1363 # Unfortunately the unicode 'micro' symbol can cause problems in
1362 # Unfortunately the unicode 'micro' symbol can cause problems in
1364 # certain terminals.
1363 # certain terminals.
1365 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1364 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1366 # Try to prevent crashes by being more secure than it needs to
1365 # Try to prevent crashes by being more secure than it needs to
1367 # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1366 # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1368 units = [u"s", u"ms",u'us',"ns"] # the save value
1367 units = [u"s", u"ms",u'us',"ns"] # the save value
1369 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1368 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1370 try:
1369 try:
1371 u'\xb5'.encode(sys.stdout.encoding)
1370 u'\xb5'.encode(sys.stdout.encoding)
1372 units = [u"s", u"ms",u'\xb5s',"ns"]
1371 units = [u"s", u"ms",u'\xb5s',"ns"]
1373 except:
1372 except:
1374 pass
1373 pass
1375 scaling = [1, 1e3, 1e6, 1e9]
1374 scaling = [1, 1e3, 1e6, 1e9]
1376
1375
1377 if timespan > 0.0:
1376 if timespan > 0.0:
1378 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1377 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1379 else:
1378 else:
1380 order = 3
1379 order = 3
1381 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
1380 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,184 +1,183 b''
1 """Implementation of magic functions for IPython's own logging.
1 """Implementation of magic functions for IPython's own logging.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import os
16 import os
17 import sys
17 import sys
18
18
19 # Our own packages
19 # Our own packages
20 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.core.magic import Magics, magics_class, line_magic
21 from warnings import warn
21 from warnings import warn
22 from IPython.utils.py3compat import str_to_unicode
23
22
24 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
25 # Magic implementation classes
24 # Magic implementation classes
26 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
27
26
28 @magics_class
27 @magics_class
29 class LoggingMagics(Magics):
28 class LoggingMagics(Magics):
30 """Magics related to all logging machinery."""
29 """Magics related to all logging machinery."""
31
30
32 @line_magic
31 @line_magic
33 def logstart(self, parameter_s=''):
32 def logstart(self, parameter_s=''):
34 """Start logging anywhere in a session.
33 """Start logging anywhere in a session.
35
34
36 %logstart [-o|-r|-t] [log_name [log_mode]]
35 %logstart [-o|-r|-t] [log_name [log_mode]]
37
36
38 If no name is given, it defaults to a file named 'ipython_log.py' in your
37 If no name is given, it defaults to a file named 'ipython_log.py' in your
39 current directory, in 'rotate' mode (see below).
38 current directory, in 'rotate' mode (see below).
40
39
41 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
40 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
42 history up to that point and then continues logging.
41 history up to that point and then continues logging.
43
42
44 %logstart takes a second optional parameter: logging mode. This can be one
43 %logstart takes a second optional parameter: logging mode. This can be one
45 of (note that the modes are given unquoted):
44 of (note that the modes are given unquoted):
46
45
47 append
46 append
48 Keep logging at the end of any existing file.
47 Keep logging at the end of any existing file.
49
48
50 backup
49 backup
51 Rename any existing file to name~ and start name.
50 Rename any existing file to name~ and start name.
52
51
53 global
52 global
54 Append to a single logfile in your home directory.
53 Append to a single logfile in your home directory.
55
54
56 over
55 over
57 Overwrite any existing log.
56 Overwrite any existing log.
58
57
59 rotate
58 rotate
60 Create rotating logs: name.1~, name.2~, etc.
59 Create rotating logs: name.1~, name.2~, etc.
61
60
62 Options:
61 Options:
63
62
64 -o
63 -o
65 log also IPython's output. In this mode, all commands which
64 log also IPython's output. In this mode, all commands which
66 generate an Out[NN] prompt are recorded to the logfile, right after
65 generate an Out[NN] prompt are recorded to the logfile, right after
67 their corresponding input line. The output lines are always
66 their corresponding input line. The output lines are always
68 prepended with a '#[Out]# ' marker, so that the log remains valid
67 prepended with a '#[Out]# ' marker, so that the log remains valid
69 Python code.
68 Python code.
70
69
71 Since this marker is always the same, filtering only the output from
70 Since this marker is always the same, filtering only the output from
72 a log is very easy, using for example a simple awk call::
71 a log is very easy, using for example a simple awk call::
73
72
74 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
73 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
75
74
76 -r
75 -r
77 log 'raw' input. Normally, IPython's logs contain the processed
76 log 'raw' input. Normally, IPython's logs contain the processed
78 input, so that user lines are logged in their final form, converted
77 input, so that user lines are logged in their final form, converted
79 into valid Python. For example, %Exit is logged as
78 into valid Python. For example, %Exit is logged as
80 _ip.magic("Exit"). If the -r flag is given, all input is logged
79 _ip.magic("Exit"). If the -r flag is given, all input is logged
81 exactly as typed, with no transformations applied.
80 exactly as typed, with no transformations applied.
82
81
83 -t
82 -t
84 put timestamps before each input line logged (these are put in
83 put timestamps before each input line logged (these are put in
85 comments).
84 comments).
86 """
85 """
87
86
88 opts,par = self.parse_options(parameter_s,'ort')
87 opts,par = self.parse_options(parameter_s,'ort')
89 log_output = 'o' in opts
88 log_output = 'o' in opts
90 log_raw_input = 'r' in opts
89 log_raw_input = 'r' in opts
91 timestamp = 't' in opts
90 timestamp = 't' in opts
92
91
93 logger = self.shell.logger
92 logger = self.shell.logger
94
93
95 # if no args are given, the defaults set in the logger constructor by
94 # if no args are given, the defaults set in the logger constructor by
96 # ipython remain valid
95 # ipython remain valid
97 if par:
96 if par:
98 try:
97 try:
99 logfname,logmode = par.split()
98 logfname,logmode = par.split()
100 except:
99 except:
101 logfname = par
100 logfname = par
102 logmode = 'backup'
101 logmode = 'backup'
103 else:
102 else:
104 logfname = logger.logfname
103 logfname = logger.logfname
105 logmode = logger.logmode
104 logmode = logger.logmode
106 # put logfname into rc struct as if it had been called on the command
105 # put logfname into rc struct as if it had been called on the command
107 # line, so it ends up saved in the log header Save it in case we need
106 # line, so it ends up saved in the log header Save it in case we need
108 # to restore it...
107 # to restore it...
109 old_logfile = self.shell.logfile
108 old_logfile = self.shell.logfile
110 if logfname:
109 if logfname:
111 logfname = os.path.expanduser(logfname)
110 logfname = os.path.expanduser(logfname)
112 self.shell.logfile = logfname
111 self.shell.logfile = logfname
113
112
114 loghead = u'# IPython log file\n\n'
113 loghead = u'# IPython log file\n\n'
115 try:
114 try:
116 logger.logstart(logfname, loghead, logmode, log_output, timestamp,
115 logger.logstart(logfname, loghead, logmode, log_output, timestamp,
117 log_raw_input)
116 log_raw_input)
118 except:
117 except:
119 self.shell.logfile = old_logfile
118 self.shell.logfile = old_logfile
120 warn("Couldn't start log: %s" % sys.exc_info()[1])
119 warn("Couldn't start log: %s" % sys.exc_info()[1])
121 else:
120 else:
122 # log input history up to this point, optionally interleaving
121 # log input history up to this point, optionally interleaving
123 # output if requested
122 # output if requested
124
123
125 if timestamp:
124 if timestamp:
126 # disable timestamping for the previous history, since we've
125 # disable timestamping for the previous history, since we've
127 # lost those already (no time machine here).
126 # lost those already (no time machine here).
128 logger.timestamp = False
127 logger.timestamp = False
129
128
130 if log_raw_input:
129 if log_raw_input:
131 input_hist = self.shell.history_manager.input_hist_raw
130 input_hist = self.shell.history_manager.input_hist_raw
132 else:
131 else:
133 input_hist = self.shell.history_manager.input_hist_parsed
132 input_hist = self.shell.history_manager.input_hist_parsed
134
133
135 if log_output:
134 if log_output:
136 log_write = logger.log_write
135 log_write = logger.log_write
137 output_hist = self.shell.history_manager.output_hist
136 output_hist = self.shell.history_manager.output_hist
138 for n in range(1,len(input_hist)-1):
137 for n in range(1,len(input_hist)-1):
139 log_write(input_hist[n].rstrip() + u'\n')
138 log_write(input_hist[n].rstrip() + u'\n')
140 if n in output_hist:
139 if n in output_hist:
141 log_write(str_to_unicode(repr(output_hist[n])),'output')
140 log_write(repr(output_hist[n]),'output')
142 else:
141 else:
143 logger.log_write(u'\n'.join(input_hist[1:]))
142 logger.log_write(u'\n'.join(input_hist[1:]))
144 logger.log_write(u'\n')
143 logger.log_write(u'\n')
145 if timestamp:
144 if timestamp:
146 # re-enable timestamping
145 # re-enable timestamping
147 logger.timestamp = True
146 logger.timestamp = True
148
147
149 print ('Activating auto-logging. '
148 print ('Activating auto-logging. '
150 'Current session state plus future input saved.')
149 'Current session state plus future input saved.')
151 logger.logstate()
150 logger.logstate()
152
151
153 @line_magic
152 @line_magic
154 def logstop(self, parameter_s=''):
153 def logstop(self, parameter_s=''):
155 """Fully stop logging and close log file.
154 """Fully stop logging and close log file.
156
155
157 In order to start logging again, a new %logstart call needs to be made,
156 In order to start logging again, a new %logstart call needs to be made,
158 possibly (though not necessarily) with a new filename, mode and other
157 possibly (though not necessarily) with a new filename, mode and other
159 options."""
158 options."""
160 self.shell.logger.logstop()
159 self.shell.logger.logstop()
161
160
162 @line_magic
161 @line_magic
163 def logoff(self, parameter_s=''):
162 def logoff(self, parameter_s=''):
164 """Temporarily stop logging.
163 """Temporarily stop logging.
165
164
166 You must have previously started logging."""
165 You must have previously started logging."""
167 self.shell.logger.switch_log(0)
166 self.shell.logger.switch_log(0)
168
167
169 @line_magic
168 @line_magic
170 def logon(self, parameter_s=''):
169 def logon(self, parameter_s=''):
171 """Restart logging.
170 """Restart logging.
172
171
173 This function is for restarting logging which you've temporarily
172 This function is for restarting logging which you've temporarily
174 stopped with %logoff. For starting logging for the first time, you
173 stopped with %logoff. For starting logging for the first time, you
175 must use the %logstart function, which allows you to specify an
174 must use the %logstart function, which allows you to specify an
176 optional log filename."""
175 optional log filename."""
177
176
178 self.shell.logger.switch_log(1)
177 self.shell.logger.switch_log(1)
179
178
180 @line_magic
179 @line_magic
181 def logstate(self, parameter_s=''):
180 def logstate(self, parameter_s=''):
182 """Print the status of the logging system."""
181 """Print the status of the logging system."""
183
182
184 self.shell.logger.logstate()
183 self.shell.logger.logstate()
@@ -1,703 +1,702 b''
1 """Implementation of namespace-related magic functions.
1 """Implementation of namespace-related magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import gc
16 import gc
17 import re
17 import re
18 import sys
18 import sys
19
19
20 # Our own packages
20 # Our own packages
21 from IPython.core import page
21 from IPython.core import page
22 from IPython.core.error import StdinNotImplementedError, UsageError
22 from IPython.core.error import StdinNotImplementedError, UsageError
23 from IPython.core.magic import Magics, magics_class, line_magic
23 from IPython.core.magic import Magics, magics_class, line_magic
24 from IPython.testing.skipdoctest import skip_doctest
24 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.utils.encoding import DEFAULT_ENCODING
25 from IPython.utils.encoding import DEFAULT_ENCODING
26 from IPython.utils.openpy import read_py_file
26 from IPython.utils.openpy import read_py_file
27 from IPython.utils.path import get_py_filename
27 from IPython.utils.path import get_py_filename
28 from IPython.utils.py3compat import unicode_type
29
28
30 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
31 # Magic implementation classes
30 # Magic implementation classes
32 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
33
32
34 @magics_class
33 @magics_class
35 class NamespaceMagics(Magics):
34 class NamespaceMagics(Magics):
36 """Magics to manage various aspects of the user's namespace.
35 """Magics to manage various aspects of the user's namespace.
37
36
38 These include listing variables, introspecting into them, etc.
37 These include listing variables, introspecting into them, etc.
39 """
38 """
40
39
41 @line_magic
40 @line_magic
42 def pinfo(self, parameter_s='', namespaces=None):
41 def pinfo(self, parameter_s='', namespaces=None):
43 """Provide detailed information about an object.
42 """Provide detailed information about an object.
44
43
45 '%pinfo object' is just a synonym for object? or ?object."""
44 '%pinfo object' is just a synonym for object? or ?object."""
46
45
47 #print 'pinfo par: <%s>' % parameter_s # dbg
46 #print 'pinfo par: <%s>' % parameter_s # dbg
48 # detail_level: 0 -> obj? , 1 -> obj??
47 # detail_level: 0 -> obj? , 1 -> obj??
49 detail_level = 0
48 detail_level = 0
50 # We need to detect if we got called as 'pinfo pinfo foo', which can
49 # We need to detect if we got called as 'pinfo pinfo foo', which can
51 # happen if the user types 'pinfo foo?' at the cmd line.
50 # happen if the user types 'pinfo foo?' at the cmd line.
52 pinfo,qmark1,oname,qmark2 = \
51 pinfo,qmark1,oname,qmark2 = \
53 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
52 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
54 if pinfo or qmark1 or qmark2:
53 if pinfo or qmark1 or qmark2:
55 detail_level = 1
54 detail_level = 1
56 if "*" in oname:
55 if "*" in oname:
57 self.psearch(oname)
56 self.psearch(oname)
58 else:
57 else:
59 self.shell._inspect('pinfo', oname, detail_level=detail_level,
58 self.shell._inspect('pinfo', oname, detail_level=detail_level,
60 namespaces=namespaces)
59 namespaces=namespaces)
61
60
62 @line_magic
61 @line_magic
63 def pinfo2(self, parameter_s='', namespaces=None):
62 def pinfo2(self, parameter_s='', namespaces=None):
64 """Provide extra detailed information about an object.
63 """Provide extra detailed information about an object.
65
64
66 '%pinfo2 object' is just a synonym for object?? or ??object."""
65 '%pinfo2 object' is just a synonym for object?? or ??object."""
67 self.shell._inspect('pinfo', parameter_s, detail_level=1,
66 self.shell._inspect('pinfo', parameter_s, detail_level=1,
68 namespaces=namespaces)
67 namespaces=namespaces)
69
68
70 @skip_doctest
69 @skip_doctest
71 @line_magic
70 @line_magic
72 def pdef(self, parameter_s='', namespaces=None):
71 def pdef(self, parameter_s='', namespaces=None):
73 """Print the call signature for any callable object.
72 """Print the call signature for any callable object.
74
73
75 If the object is a class, print the constructor information.
74 If the object is a class, print the constructor information.
76
75
77 Examples
76 Examples
78 --------
77 --------
79 ::
78 ::
80
79
81 In [3]: %pdef urllib.urlopen
80 In [3]: %pdef urllib.urlopen
82 urllib.urlopen(url, data=None, proxies=None)
81 urllib.urlopen(url, data=None, proxies=None)
83 """
82 """
84 self.shell._inspect('pdef',parameter_s, namespaces)
83 self.shell._inspect('pdef',parameter_s, namespaces)
85
84
86 @line_magic
85 @line_magic
87 def pdoc(self, parameter_s='', namespaces=None):
86 def pdoc(self, parameter_s='', namespaces=None):
88 """Print the docstring for an object.
87 """Print the docstring for an object.
89
88
90 If the given object is a class, it will print both the class and the
89 If the given object is a class, it will print both the class and the
91 constructor docstrings."""
90 constructor docstrings."""
92 self.shell._inspect('pdoc',parameter_s, namespaces)
91 self.shell._inspect('pdoc',parameter_s, namespaces)
93
92
94 @line_magic
93 @line_magic
95 def psource(self, parameter_s='', namespaces=None):
94 def psource(self, parameter_s='', namespaces=None):
96 """Print (or run through pager) the source code for an object."""
95 """Print (or run through pager) the source code for an object."""
97 if not parameter_s:
96 if not parameter_s:
98 raise UsageError('Missing object name.')
97 raise UsageError('Missing object name.')
99 self.shell._inspect('psource',parameter_s, namespaces)
98 self.shell._inspect('psource',parameter_s, namespaces)
100
99
101 @line_magic
100 @line_magic
102 def pfile(self, parameter_s='', namespaces=None):
101 def pfile(self, parameter_s='', namespaces=None):
103 """Print (or run through pager) the file where an object is defined.
102 """Print (or run through pager) the file where an object is defined.
104
103
105 The file opens at the line where the object definition begins. IPython
104 The file opens at the line where the object definition begins. IPython
106 will honor the environment variable PAGER if set, and otherwise will
105 will honor the environment variable PAGER if set, and otherwise will
107 do its best to print the file in a convenient form.
106 do its best to print the file in a convenient form.
108
107
109 If the given argument is not an object currently defined, IPython will
108 If the given argument is not an object currently defined, IPython will
110 try to interpret it as a filename (automatically adding a .py extension
109 try to interpret it as a filename (automatically adding a .py extension
111 if needed). You can thus use %pfile as a syntax highlighting code
110 if needed). You can thus use %pfile as a syntax highlighting code
112 viewer."""
111 viewer."""
113
112
114 # first interpret argument as an object name
113 # first interpret argument as an object name
115 out = self.shell._inspect('pfile',parameter_s, namespaces)
114 out = self.shell._inspect('pfile',parameter_s, namespaces)
116 # if not, try the input as a filename
115 # if not, try the input as a filename
117 if out == 'not found':
116 if out == 'not found':
118 try:
117 try:
119 filename = get_py_filename(parameter_s)
118 filename = get_py_filename(parameter_s)
120 except IOError as msg:
119 except IOError as msg:
121 print(msg)
120 print(msg)
122 return
121 return
123 page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
122 page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
124
123
125 @line_magic
124 @line_magic
126 def psearch(self, parameter_s=''):
125 def psearch(self, parameter_s=''):
127 """Search for object in namespaces by wildcard.
126 """Search for object in namespaces by wildcard.
128
127
129 %psearch [options] PATTERN [OBJECT TYPE]
128 %psearch [options] PATTERN [OBJECT TYPE]
130
129
131 Note: ? can be used as a synonym for %psearch, at the beginning or at
130 Note: ? can be used as a synonym for %psearch, at the beginning or at
132 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
131 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
133 rest of the command line must be unchanged (options come first), so
132 rest of the command line must be unchanged (options come first), so
134 for example the following forms are equivalent
133 for example the following forms are equivalent
135
134
136 %psearch -i a* function
135 %psearch -i a* function
137 -i a* function?
136 -i a* function?
138 ?-i a* function
137 ?-i a* function
139
138
140 Arguments:
139 Arguments:
141
140
142 PATTERN
141 PATTERN
143
142
144 where PATTERN is a string containing * as a wildcard similar to its
143 where PATTERN is a string containing * as a wildcard similar to its
145 use in a shell. The pattern is matched in all namespaces on the
144 use in a shell. The pattern is matched in all namespaces on the
146 search path. By default objects starting with a single _ are not
145 search path. By default objects starting with a single _ are not
147 matched, many IPython generated objects have a single
146 matched, many IPython generated objects have a single
148 underscore. The default is case insensitive matching. Matching is
147 underscore. The default is case insensitive matching. Matching is
149 also done on the attributes of objects and not only on the objects
148 also done on the attributes of objects and not only on the objects
150 in a module.
149 in a module.
151
150
152 [OBJECT TYPE]
151 [OBJECT TYPE]
153
152
154 Is the name of a python type from the types module. The name is
153 Is the name of a python type from the types module. The name is
155 given in lowercase without the ending type, ex. StringType is
154 given in lowercase without the ending type, ex. StringType is
156 written string. By adding a type here only objects matching the
155 written string. By adding a type here only objects matching the
157 given type are matched. Using all here makes the pattern match all
156 given type are matched. Using all here makes the pattern match all
158 types (this is the default).
157 types (this is the default).
159
158
160 Options:
159 Options:
161
160
162 -a: makes the pattern match even objects whose names start with a
161 -a: makes the pattern match even objects whose names start with a
163 single underscore. These names are normally omitted from the
162 single underscore. These names are normally omitted from the
164 search.
163 search.
165
164
166 -i/-c: make the pattern case insensitive/sensitive. If neither of
165 -i/-c: make the pattern case insensitive/sensitive. If neither of
167 these options are given, the default is read from your configuration
166 these options are given, the default is read from your configuration
168 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
167 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
169 If this option is not specified in your configuration file, IPython's
168 If this option is not specified in your configuration file, IPython's
170 internal default is to do a case sensitive search.
169 internal default is to do a case sensitive search.
171
170
172 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
171 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
173 specify can be searched in any of the following namespaces:
172 specify can be searched in any of the following namespaces:
174 'builtin', 'user', 'user_global','internal', 'alias', where
173 'builtin', 'user', 'user_global','internal', 'alias', where
175 'builtin' and 'user' are the search defaults. Note that you should
174 'builtin' and 'user' are the search defaults. Note that you should
176 not use quotes when specifying namespaces.
175 not use quotes when specifying namespaces.
177
176
178 'Builtin' contains the python module builtin, 'user' contains all
177 'Builtin' contains the python module builtin, 'user' contains all
179 user data, 'alias' only contain the shell aliases and no python
178 user data, 'alias' only contain the shell aliases and no python
180 objects, 'internal' contains objects used by IPython. The
179 objects, 'internal' contains objects used by IPython. The
181 'user_global' namespace is only used by embedded IPython instances,
180 'user_global' namespace is only used by embedded IPython instances,
182 and it contains module-level globals. You can add namespaces to the
181 and it contains module-level globals. You can add namespaces to the
183 search with -s or exclude them with -e (these options can be given
182 search with -s or exclude them with -e (these options can be given
184 more than once).
183 more than once).
185
184
186 Examples
185 Examples
187 --------
186 --------
188 ::
187 ::
189
188
190 %psearch a* -> objects beginning with an a
189 %psearch a* -> objects beginning with an a
191 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
190 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
192 %psearch a* function -> all functions beginning with an a
191 %psearch a* function -> all functions beginning with an a
193 %psearch re.e* -> objects beginning with an e in module re
192 %psearch re.e* -> objects beginning with an e in module re
194 %psearch r*.e* -> objects that start with e in modules starting in r
193 %psearch r*.e* -> objects that start with e in modules starting in r
195 %psearch r*.* string -> all strings in modules beginning with r
194 %psearch r*.* string -> all strings in modules beginning with r
196
195
197 Case sensitive search::
196 Case sensitive search::
198
197
199 %psearch -c a* list all object beginning with lower case a
198 %psearch -c a* list all object beginning with lower case a
200
199
201 Show objects beginning with a single _::
200 Show objects beginning with a single _::
202
201
203 %psearch -a _* list objects beginning with a single underscore
202 %psearch -a _* list objects beginning with a single underscore
204 """
203 """
205 try:
204 try:
206 parameter_s.encode('ascii')
205 parameter_s.encode('ascii')
207 except UnicodeEncodeError:
206 except UnicodeEncodeError:
208 print('Python identifiers can only contain ascii characters.')
207 print('Python identifiers can only contain ascii characters.')
209 return
208 return
210
209
211 # default namespaces to be searched
210 # default namespaces to be searched
212 def_search = ['user_local', 'user_global', 'builtin']
211 def_search = ['user_local', 'user_global', 'builtin']
213
212
214 # Process options/args
213 # Process options/args
215 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
214 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
216 opt = opts.get
215 opt = opts.get
217 shell = self.shell
216 shell = self.shell
218 psearch = shell.inspector.psearch
217 psearch = shell.inspector.psearch
219
218
220 # select case options
219 # select case options
221 if 'i' in opts:
220 if 'i' in opts:
222 ignore_case = True
221 ignore_case = True
223 elif 'c' in opts:
222 elif 'c' in opts:
224 ignore_case = False
223 ignore_case = False
225 else:
224 else:
226 ignore_case = not shell.wildcards_case_sensitive
225 ignore_case = not shell.wildcards_case_sensitive
227
226
228 # Build list of namespaces to search from user options
227 # Build list of namespaces to search from user options
229 def_search.extend(opt('s',[]))
228 def_search.extend(opt('s',[]))
230 ns_exclude = ns_exclude=opt('e',[])
229 ns_exclude = ns_exclude=opt('e',[])
231 ns_search = [nm for nm in def_search if nm not in ns_exclude]
230 ns_search = [nm for nm in def_search if nm not in ns_exclude]
232
231
233 # Call the actual search
232 # Call the actual search
234 try:
233 try:
235 psearch(args,shell.ns_table,ns_search,
234 psearch(args,shell.ns_table,ns_search,
236 show_all=opt('a'),ignore_case=ignore_case)
235 show_all=opt('a'),ignore_case=ignore_case)
237 except:
236 except:
238 shell.showtraceback()
237 shell.showtraceback()
239
238
240 @skip_doctest
239 @skip_doctest
241 @line_magic
240 @line_magic
242 def who_ls(self, parameter_s=''):
241 def who_ls(self, parameter_s=''):
243 """Return a sorted list of all interactive variables.
242 """Return a sorted list of all interactive variables.
244
243
245 If arguments are given, only variables of types matching these
244 If arguments are given, only variables of types matching these
246 arguments are returned.
245 arguments are returned.
247
246
248 Examples
247 Examples
249 --------
248 --------
250
249
251 Define two variables and list them with who_ls::
250 Define two variables and list them with who_ls::
252
251
253 In [1]: alpha = 123
252 In [1]: alpha = 123
254
253
255 In [2]: beta = 'test'
254 In [2]: beta = 'test'
256
255
257 In [3]: %who_ls
256 In [3]: %who_ls
258 Out[3]: ['alpha', 'beta']
257 Out[3]: ['alpha', 'beta']
259
258
260 In [4]: %who_ls int
259 In [4]: %who_ls int
261 Out[4]: ['alpha']
260 Out[4]: ['alpha']
262
261
263 In [5]: %who_ls str
262 In [5]: %who_ls str
264 Out[5]: ['beta']
263 Out[5]: ['beta']
265 """
264 """
266
265
267 user_ns = self.shell.user_ns
266 user_ns = self.shell.user_ns
268 user_ns_hidden = self.shell.user_ns_hidden
267 user_ns_hidden = self.shell.user_ns_hidden
269 nonmatching = object() # This can never be in user_ns
268 nonmatching = object() # This can never be in user_ns
270 out = [ i for i in user_ns
269 out = [ i for i in user_ns
271 if not i.startswith('_') \
270 if not i.startswith('_') \
272 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
271 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
273
272
274 typelist = parameter_s.split()
273 typelist = parameter_s.split()
275 if typelist:
274 if typelist:
276 typeset = set(typelist)
275 typeset = set(typelist)
277 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
276 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
278
277
279 out.sort()
278 out.sort()
280 return out
279 return out
281
280
282 @skip_doctest
281 @skip_doctest
283 @line_magic
282 @line_magic
284 def who(self, parameter_s=''):
283 def who(self, parameter_s=''):
285 """Print all interactive variables, with some minimal formatting.
284 """Print all interactive variables, with some minimal formatting.
286
285
287 If any arguments are given, only variables whose type matches one of
286 If any arguments are given, only variables whose type matches one of
288 these are printed. For example::
287 these are printed. For example::
289
288
290 %who function str
289 %who function str
291
290
292 will only list functions and strings, excluding all other types of
291 will only list functions and strings, excluding all other types of
293 variables. To find the proper type names, simply use type(var) at a
292 variables. To find the proper type names, simply use type(var) at a
294 command line to see how python prints type names. For example:
293 command line to see how python prints type names. For example:
295
294
296 ::
295 ::
297
296
298 In [1]: type('hello')\\
297 In [1]: type('hello')\\
299 Out[1]: <type 'str'>
298 Out[1]: <type 'str'>
300
299
301 indicates that the type name for strings is 'str'.
300 indicates that the type name for strings is 'str'.
302
301
303 ``%who`` always excludes executed names loaded through your configuration
302 ``%who`` always excludes executed names loaded through your configuration
304 file and things which are internal to IPython.
303 file and things which are internal to IPython.
305
304
306 This is deliberate, as typically you may load many modules and the
305 This is deliberate, as typically you may load many modules and the
307 purpose of %who is to show you only what you've manually defined.
306 purpose of %who is to show you only what you've manually defined.
308
307
309 Examples
308 Examples
310 --------
309 --------
311
310
312 Define two variables and list them with who::
311 Define two variables and list them with who::
313
312
314 In [1]: alpha = 123
313 In [1]: alpha = 123
315
314
316 In [2]: beta = 'test'
315 In [2]: beta = 'test'
317
316
318 In [3]: %who
317 In [3]: %who
319 alpha beta
318 alpha beta
320
319
321 In [4]: %who int
320 In [4]: %who int
322 alpha
321 alpha
323
322
324 In [5]: %who str
323 In [5]: %who str
325 beta
324 beta
326 """
325 """
327
326
328 varlist = self.who_ls(parameter_s)
327 varlist = self.who_ls(parameter_s)
329 if not varlist:
328 if not varlist:
330 if parameter_s:
329 if parameter_s:
331 print('No variables match your requested type.')
330 print('No variables match your requested type.')
332 else:
331 else:
333 print('Interactive namespace is empty.')
332 print('Interactive namespace is empty.')
334 return
333 return
335
334
336 # if we have variables, move on...
335 # if we have variables, move on...
337 count = 0
336 count = 0
338 for i in varlist:
337 for i in varlist:
339 print(i+'\t', end=' ')
338 print(i+'\t', end=' ')
340 count += 1
339 count += 1
341 if count > 8:
340 if count > 8:
342 count = 0
341 count = 0
343 print()
342 print()
344 print()
343 print()
345
344
346 @skip_doctest
345 @skip_doctest
347 @line_magic
346 @line_magic
348 def whos(self, parameter_s=''):
347 def whos(self, parameter_s=''):
349 """Like %who, but gives some extra information about each variable.
348 """Like %who, but gives some extra information about each variable.
350
349
351 The same type filtering of %who can be applied here.
350 The same type filtering of %who can be applied here.
352
351
353 For all variables, the type is printed. Additionally it prints:
352 For all variables, the type is printed. Additionally it prints:
354
353
355 - For {},[],(): their length.
354 - For {},[],(): their length.
356
355
357 - For numpy arrays, a summary with shape, number of
356 - For numpy arrays, a summary with shape, number of
358 elements, typecode and size in memory.
357 elements, typecode and size in memory.
359
358
360 - Everything else: a string representation, snipping their middle if
359 - Everything else: a string representation, snipping their middle if
361 too long.
360 too long.
362
361
363 Examples
362 Examples
364 --------
363 --------
365
364
366 Define two variables and list them with whos::
365 Define two variables and list them with whos::
367
366
368 In [1]: alpha = 123
367 In [1]: alpha = 123
369
368
370 In [2]: beta = 'test'
369 In [2]: beta = 'test'
371
370
372 In [3]: %whos
371 In [3]: %whos
373 Variable Type Data/Info
372 Variable Type Data/Info
374 --------------------------------
373 --------------------------------
375 alpha int 123
374 alpha int 123
376 beta str test
375 beta str test
377 """
376 """
378
377
379 varnames = self.who_ls(parameter_s)
378 varnames = self.who_ls(parameter_s)
380 if not varnames:
379 if not varnames:
381 if parameter_s:
380 if parameter_s:
382 print('No variables match your requested type.')
381 print('No variables match your requested type.')
383 else:
382 else:
384 print('Interactive namespace is empty.')
383 print('Interactive namespace is empty.')
385 return
384 return
386
385
387 # if we have variables, move on...
386 # if we have variables, move on...
388
387
389 # for these types, show len() instead of data:
388 # for these types, show len() instead of data:
390 seq_types = ['dict', 'list', 'tuple']
389 seq_types = ['dict', 'list', 'tuple']
391
390
392 # for numpy arrays, display summary info
391 # for numpy arrays, display summary info
393 ndarray_type = None
392 ndarray_type = None
394 if 'numpy' in sys.modules:
393 if 'numpy' in sys.modules:
395 try:
394 try:
396 from numpy import ndarray
395 from numpy import ndarray
397 except ImportError:
396 except ImportError:
398 pass
397 pass
399 else:
398 else:
400 ndarray_type = ndarray.__name__
399 ndarray_type = ndarray.__name__
401
400
402 # Find all variable names and types so we can figure out column sizes
401 # Find all variable names and types so we can figure out column sizes
403
402
404 # some types are well known and can be shorter
403 # some types are well known and can be shorter
405 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
404 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
406 def type_name(v):
405 def type_name(v):
407 tn = type(v).__name__
406 tn = type(v).__name__
408 return abbrevs.get(tn,tn)
407 return abbrevs.get(tn,tn)
409
408
410 varlist = [self.shell.user_ns[n] for n in varnames]
409 varlist = [self.shell.user_ns[n] for n in varnames]
411
410
412 typelist = []
411 typelist = []
413 for vv in varlist:
412 for vv in varlist:
414 tt = type_name(vv)
413 tt = type_name(vv)
415
414
416 if tt=='instance':
415 if tt=='instance':
417 typelist.append( abbrevs.get(str(vv.__class__),
416 typelist.append( abbrevs.get(str(vv.__class__),
418 str(vv.__class__)))
417 str(vv.__class__)))
419 else:
418 else:
420 typelist.append(tt)
419 typelist.append(tt)
421
420
422 # column labels and # of spaces as separator
421 # column labels and # of spaces as separator
423 varlabel = 'Variable'
422 varlabel = 'Variable'
424 typelabel = 'Type'
423 typelabel = 'Type'
425 datalabel = 'Data/Info'
424 datalabel = 'Data/Info'
426 colsep = 3
425 colsep = 3
427 # variable format strings
426 # variable format strings
428 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
427 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
429 aformat = "%s: %s elems, type `%s`, %s bytes"
428 aformat = "%s: %s elems, type `%s`, %s bytes"
430 # find the size of the columns to format the output nicely
429 # find the size of the columns to format the output nicely
431 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
430 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
432 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
431 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
433 # table header
432 # table header
434 print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
433 print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
435 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
434 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
436 # and the table itself
435 # and the table itself
437 kb = 1024
436 kb = 1024
438 Mb = 1048576 # kb**2
437 Mb = 1048576 # kb**2
439 for vname,var,vtype in zip(varnames,varlist,typelist):
438 for vname,var,vtype in zip(varnames,varlist,typelist):
440 print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
439 print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
441 if vtype in seq_types:
440 if vtype in seq_types:
442 print("n="+str(len(var)))
441 print("n="+str(len(var)))
443 elif vtype == ndarray_type:
442 elif vtype == ndarray_type:
444 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
443 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
445 if vtype==ndarray_type:
444 if vtype==ndarray_type:
446 # numpy
445 # numpy
447 vsize = var.size
446 vsize = var.size
448 vbytes = vsize*var.itemsize
447 vbytes = vsize*var.itemsize
449 vdtype = var.dtype
448 vdtype = var.dtype
450
449
451 if vbytes < 100000:
450 if vbytes < 100000:
452 print(aformat % (vshape, vsize, vdtype, vbytes))
451 print(aformat % (vshape, vsize, vdtype, vbytes))
453 else:
452 else:
454 print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
453 print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
455 if vbytes < Mb:
454 if vbytes < Mb:
456 print('(%s kb)' % (vbytes/kb,))
455 print('(%s kb)' % (vbytes/kb,))
457 else:
456 else:
458 print('(%s Mb)' % (vbytes/Mb,))
457 print('(%s Mb)' % (vbytes/Mb,))
459 else:
458 else:
460 try:
459 try:
461 vstr = str(var)
460 vstr = str(var)
462 except UnicodeEncodeError:
461 except UnicodeEncodeError:
463 vstr = unicode_type(var).encode(DEFAULT_ENCODING,
462 vstr = var.encode(DEFAULT_ENCODING,
464 'backslashreplace')
463 'backslashreplace')
465 except:
464 except:
466 vstr = "<object with id %d (str() failed)>" % id(var)
465 vstr = "<object with id %d (str() failed)>" % id(var)
467 vstr = vstr.replace('\n', '\\n')
466 vstr = vstr.replace('\n', '\\n')
468 if len(vstr) < 50:
467 if len(vstr) < 50:
469 print(vstr)
468 print(vstr)
470 else:
469 else:
471 print(vstr[:25] + "<...>" + vstr[-25:])
470 print(vstr[:25] + "<...>" + vstr[-25:])
472
471
473 @line_magic
472 @line_magic
474 def reset(self, parameter_s=''):
473 def reset(self, parameter_s=''):
475 """Resets the namespace by removing all names defined by the user, if
474 """Resets the namespace by removing all names defined by the user, if
476 called without arguments, or by removing some types of objects, such
475 called without arguments, or by removing some types of objects, such
477 as everything currently in IPython's In[] and Out[] containers (see
476 as everything currently in IPython's In[] and Out[] containers (see
478 the parameters for details).
477 the parameters for details).
479
478
480 Parameters
479 Parameters
481 ----------
480 ----------
482 -f : force reset without asking for confirmation.
481 -f : force reset without asking for confirmation.
483
482
484 -s : 'Soft' reset: Only clears your namespace, leaving history intact.
483 -s : 'Soft' reset: Only clears your namespace, leaving history intact.
485 References to objects may be kept. By default (without this option),
484 References to objects may be kept. By default (without this option),
486 we do a 'hard' reset, giving you a new session and removing all
485 we do a 'hard' reset, giving you a new session and removing all
487 references to objects from the current session.
486 references to objects from the current session.
488
487
489 in : reset input history
488 in : reset input history
490
489
491 out : reset output history
490 out : reset output history
492
491
493 dhist : reset directory history
492 dhist : reset directory history
494
493
495 array : reset only variables that are NumPy arrays
494 array : reset only variables that are NumPy arrays
496
495
497 See Also
496 See Also
498 --------
497 --------
499 reset_selective : invoked as ``%reset_selective``
498 reset_selective : invoked as ``%reset_selective``
500
499
501 Examples
500 Examples
502 --------
501 --------
503 ::
502 ::
504
503
505 In [6]: a = 1
504 In [6]: a = 1
506
505
507 In [7]: a
506 In [7]: a
508 Out[7]: 1
507 Out[7]: 1
509
508
510 In [8]: 'a' in _ip.user_ns
509 In [8]: 'a' in _ip.user_ns
511 Out[8]: True
510 Out[8]: True
512
511
513 In [9]: %reset -f
512 In [9]: %reset -f
514
513
515 In [1]: 'a' in _ip.user_ns
514 In [1]: 'a' in _ip.user_ns
516 Out[1]: False
515 Out[1]: False
517
516
518 In [2]: %reset -f in
517 In [2]: %reset -f in
519 Flushing input history
518 Flushing input history
520
519
521 In [3]: %reset -f dhist in
520 In [3]: %reset -f dhist in
522 Flushing directory history
521 Flushing directory history
523 Flushing input history
522 Flushing input history
524
523
525 Notes
524 Notes
526 -----
525 -----
527 Calling this magic from clients that do not implement standard input,
526 Calling this magic from clients that do not implement standard input,
528 such as the ipython notebook interface, will reset the namespace
527 such as the ipython notebook interface, will reset the namespace
529 without confirmation.
528 without confirmation.
530 """
529 """
531 opts, args = self.parse_options(parameter_s,'sf', mode='list')
530 opts, args = self.parse_options(parameter_s,'sf', mode='list')
532 if 'f' in opts:
531 if 'f' in opts:
533 ans = True
532 ans = True
534 else:
533 else:
535 try:
534 try:
536 ans = self.shell.ask_yes_no(
535 ans = self.shell.ask_yes_no(
537 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
536 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
538 default='n')
537 default='n')
539 except StdinNotImplementedError:
538 except StdinNotImplementedError:
540 ans = True
539 ans = True
541 if not ans:
540 if not ans:
542 print('Nothing done.')
541 print('Nothing done.')
543 return
542 return
544
543
545 if 's' in opts: # Soft reset
544 if 's' in opts: # Soft reset
546 user_ns = self.shell.user_ns
545 user_ns = self.shell.user_ns
547 for i in self.who_ls():
546 for i in self.who_ls():
548 del(user_ns[i])
547 del(user_ns[i])
549 elif len(args) == 0: # Hard reset
548 elif len(args) == 0: # Hard reset
550 self.shell.reset(new_session = False)
549 self.shell.reset(new_session = False)
551
550
552 # reset in/out/dhist/array: previously extensinions/clearcmd.py
551 # reset in/out/dhist/array: previously extensinions/clearcmd.py
553 ip = self.shell
552 ip = self.shell
554 user_ns = self.shell.user_ns # local lookup, heavily used
553 user_ns = self.shell.user_ns # local lookup, heavily used
555
554
556 for target in args:
555 for target in args:
557 target = target.lower() # make matches case insensitive
556 target = target.lower() # make matches case insensitive
558 if target == 'out':
557 if target == 'out':
559 print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
558 print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
560 self.shell.displayhook.flush()
559 self.shell.displayhook.flush()
561
560
562 elif target == 'in':
561 elif target == 'in':
563 print("Flushing input history")
562 print("Flushing input history")
564 pc = self.shell.displayhook.prompt_count + 1
563 pc = self.shell.displayhook.prompt_count + 1
565 for n in range(1, pc):
564 for n in range(1, pc):
566 key = '_i'+repr(n)
565 key = '_i'+repr(n)
567 user_ns.pop(key,None)
566 user_ns.pop(key,None)
568 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
567 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
569 hm = ip.history_manager
568 hm = ip.history_manager
570 # don't delete these, as %save and %macro depending on the
569 # don't delete these, as %save and %macro depending on the
571 # length of these lists to be preserved
570 # length of these lists to be preserved
572 hm.input_hist_parsed[:] = [''] * pc
571 hm.input_hist_parsed[:] = [''] * pc
573 hm.input_hist_raw[:] = [''] * pc
572 hm.input_hist_raw[:] = [''] * pc
574 # hm has internal machinery for _i,_ii,_iii, clear it out
573 # hm has internal machinery for _i,_ii,_iii, clear it out
575 hm._i = hm._ii = hm._iii = hm._i00 = u''
574 hm._i = hm._ii = hm._iii = hm._i00 = u''
576
575
577 elif target == 'array':
576 elif target == 'array':
578 # Support cleaning up numpy arrays
577 # Support cleaning up numpy arrays
579 try:
578 try:
580 from numpy import ndarray
579 from numpy import ndarray
581 # This must be done with items and not iteritems because
580 # This must be done with items and not iteritems because
582 # we're going to modify the dict in-place.
581 # we're going to modify the dict in-place.
583 for x,val in list(user_ns.items()):
582 for x,val in list(user_ns.items()):
584 if isinstance(val,ndarray):
583 if isinstance(val,ndarray):
585 del user_ns[x]
584 del user_ns[x]
586 except ImportError:
585 except ImportError:
587 print("reset array only works if Numpy is available.")
586 print("reset array only works if Numpy is available.")
588
587
589 elif target == 'dhist':
588 elif target == 'dhist':
590 print("Flushing directory history")
589 print("Flushing directory history")
591 del user_ns['_dh'][:]
590 del user_ns['_dh'][:]
592
591
593 else:
592 else:
594 print("Don't know how to reset ", end=' ')
593 print("Don't know how to reset ", end=' ')
595 print(target + ", please run `%reset?` for details")
594 print(target + ", please run `%reset?` for details")
596
595
597 gc.collect()
596 gc.collect()
598
597
599 @line_magic
598 @line_magic
600 def reset_selective(self, parameter_s=''):
599 def reset_selective(self, parameter_s=''):
601 """Resets the namespace by removing names defined by the user.
600 """Resets the namespace by removing names defined by the user.
602
601
603 Input/Output history are left around in case you need them.
602 Input/Output history are left around in case you need them.
604
603
605 %reset_selective [-f] regex
604 %reset_selective [-f] regex
606
605
607 No action is taken if regex is not included
606 No action is taken if regex is not included
608
607
609 Options
608 Options
610 -f : force reset without asking for confirmation.
609 -f : force reset without asking for confirmation.
611
610
612 See Also
611 See Also
613 --------
612 --------
614 reset : invoked as ``%reset``
613 reset : invoked as ``%reset``
615
614
616 Examples
615 Examples
617 --------
616 --------
618
617
619 We first fully reset the namespace so your output looks identical to
618 We first fully reset the namespace so your output looks identical to
620 this example for pedagogical reasons; in practice you do not need a
619 this example for pedagogical reasons; in practice you do not need a
621 full reset::
620 full reset::
622
621
623 In [1]: %reset -f
622 In [1]: %reset -f
624
623
625 Now, with a clean namespace we can make a few variables and use
624 Now, with a clean namespace we can make a few variables and use
626 ``%reset_selective`` to only delete names that match our regexp::
625 ``%reset_selective`` to only delete names that match our regexp::
627
626
628 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
627 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
629
628
630 In [3]: who_ls
629 In [3]: who_ls
631 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
630 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
632
631
633 In [4]: %reset_selective -f b[2-3]m
632 In [4]: %reset_selective -f b[2-3]m
634
633
635 In [5]: who_ls
634 In [5]: who_ls
636 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
635 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
637
636
638 In [6]: %reset_selective -f d
637 In [6]: %reset_selective -f d
639
638
640 In [7]: who_ls
639 In [7]: who_ls
641 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
640 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
642
641
643 In [8]: %reset_selective -f c
642 In [8]: %reset_selective -f c
644
643
645 In [9]: who_ls
644 In [9]: who_ls
646 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
645 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
647
646
648 In [10]: %reset_selective -f b
647 In [10]: %reset_selective -f b
649
648
650 In [11]: who_ls
649 In [11]: who_ls
651 Out[11]: ['a']
650 Out[11]: ['a']
652
651
653 Notes
652 Notes
654 -----
653 -----
655 Calling this magic from clients that do not implement standard input,
654 Calling this magic from clients that do not implement standard input,
656 such as the ipython notebook interface, will reset the namespace
655 such as the ipython notebook interface, will reset the namespace
657 without confirmation.
656 without confirmation.
658 """
657 """
659
658
660 opts, regex = self.parse_options(parameter_s,'f')
659 opts, regex = self.parse_options(parameter_s,'f')
661
660
662 if 'f' in opts:
661 if 'f' in opts:
663 ans = True
662 ans = True
664 else:
663 else:
665 try:
664 try:
666 ans = self.shell.ask_yes_no(
665 ans = self.shell.ask_yes_no(
667 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
666 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
668 default='n')
667 default='n')
669 except StdinNotImplementedError:
668 except StdinNotImplementedError:
670 ans = True
669 ans = True
671 if not ans:
670 if not ans:
672 print('Nothing done.')
671 print('Nothing done.')
673 return
672 return
674 user_ns = self.shell.user_ns
673 user_ns = self.shell.user_ns
675 if not regex:
674 if not regex:
676 print('No regex pattern specified. Nothing done.')
675 print('No regex pattern specified. Nothing done.')
677 return
676 return
678 else:
677 else:
679 try:
678 try:
680 m = re.compile(regex)
679 m = re.compile(regex)
681 except TypeError:
680 except TypeError:
682 raise TypeError('regex must be a string or compiled pattern')
681 raise TypeError('regex must be a string or compiled pattern')
683 for i in self.who_ls():
682 for i in self.who_ls():
684 if m.search(i):
683 if m.search(i):
685 del(user_ns[i])
684 del(user_ns[i])
686
685
687 @line_magic
686 @line_magic
688 def xdel(self, parameter_s=''):
687 def xdel(self, parameter_s=''):
689 """Delete a variable, trying to clear it from anywhere that
688 """Delete a variable, trying to clear it from anywhere that
690 IPython's machinery has references to it. By default, this uses
689 IPython's machinery has references to it. By default, this uses
691 the identity of the named object in the user namespace to remove
690 the identity of the named object in the user namespace to remove
692 references held under other names. The object is also removed
691 references held under other names. The object is also removed
693 from the output history.
692 from the output history.
694
693
695 Options
694 Options
696 -n : Delete the specified name from all namespaces, without
695 -n : Delete the specified name from all namespaces, without
697 checking their identity.
696 checking their identity.
698 """
697 """
699 opts, varname = self.parse_options(parameter_s,'n')
698 opts, varname = self.parse_options(parameter_s,'n')
700 try:
699 try:
701 self.shell.del_var(varname, ('n' in opts))
700 self.shell.del_var(varname, ('n' in opts))
702 except (NameError, ValueError) as e:
701 except (NameError, ValueError) as e:
703 print(type(e).__name__ +": "+ str(e))
702 print(type(e).__name__ +": "+ str(e))
@@ -1,789 +1,788 b''
1 """Implementation of magic functions for interaction with the OS.
1 """Implementation of magic functions for interaction with the OS.
2
2
3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 builtin.
4 builtin.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2012 The IPython Development Team.
7 # Copyright (c) 2012 The IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Stdlib
18 # Stdlib
19 import io
19 import io
20 import os
20 import os
21 import re
21 import re
22 import sys
22 import sys
23 from pprint import pformat
23 from pprint import pformat
24
24
25 # Our own packages
25 # Our own packages
26 from IPython.core import magic_arguments
26 from IPython.core import magic_arguments
27 from IPython.core import oinspect
27 from IPython.core import oinspect
28 from IPython.core import page
28 from IPython.core import page
29 from IPython.core.alias import AliasError, Alias
29 from IPython.core.alias import AliasError, Alias
30 from IPython.core.error import UsageError
30 from IPython.core.error import UsageError
31 from IPython.core.magic import (
31 from IPython.core.magic import (
32 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
32 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
33 )
33 )
34 from IPython.testing.skipdoctest import skip_doctest
34 from IPython.testing.skipdoctest import skip_doctest
35 from IPython.utils.openpy import source_to_unicode
35 from IPython.utils.openpy import source_to_unicode
36 from IPython.utils.process import abbrev_cwd
36 from IPython.utils.process import abbrev_cwd
37 from IPython.utils import py3compat
37 from IPython.utils import py3compat
38 from IPython.utils.py3compat import unicode_type
39 from IPython.utils.terminal import set_term_title
38 from IPython.utils.terminal import set_term_title
40
39
41 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
42 # Magic implementation classes
41 # Magic implementation classes
43 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
44 @magics_class
43 @magics_class
45 class OSMagics(Magics):
44 class OSMagics(Magics):
46 """Magics to interact with the underlying OS (shell-type functionality).
45 """Magics to interact with the underlying OS (shell-type functionality).
47 """
46 """
48
47
49 @skip_doctest
48 @skip_doctest
50 @line_magic
49 @line_magic
51 def alias(self, parameter_s=''):
50 def alias(self, parameter_s=''):
52 """Define an alias for a system command.
51 """Define an alias for a system command.
53
52
54 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
53 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
55
54
56 Then, typing 'alias_name params' will execute the system command 'cmd
55 Then, typing 'alias_name params' will execute the system command 'cmd
57 params' (from your underlying operating system).
56 params' (from your underlying operating system).
58
57
59 Aliases have lower precedence than magic functions and Python normal
58 Aliases have lower precedence than magic functions and Python normal
60 variables, so if 'foo' is both a Python variable and an alias, the
59 variables, so if 'foo' is both a Python variable and an alias, the
61 alias can not be executed until 'del foo' removes the Python variable.
60 alias can not be executed until 'del foo' removes the Python variable.
62
61
63 You can use the %l specifier in an alias definition to represent the
62 You can use the %l specifier in an alias definition to represent the
64 whole line when the alias is called. For example::
63 whole line when the alias is called. For example::
65
64
66 In [2]: alias bracket echo "Input in brackets: <%l>"
65 In [2]: alias bracket echo "Input in brackets: <%l>"
67 In [3]: bracket hello world
66 In [3]: bracket hello world
68 Input in brackets: <hello world>
67 Input in brackets: <hello world>
69
68
70 You can also define aliases with parameters using %s specifiers (one
69 You can also define aliases with parameters using %s specifiers (one
71 per parameter)::
70 per parameter)::
72
71
73 In [1]: alias parts echo first %s second %s
72 In [1]: alias parts echo first %s second %s
74 In [2]: %parts A B
73 In [2]: %parts A B
75 first A second B
74 first A second B
76 In [3]: %parts A
75 In [3]: %parts A
77 Incorrect number of arguments: 2 expected.
76 Incorrect number of arguments: 2 expected.
78 parts is an alias to: 'echo first %s second %s'
77 parts is an alias to: 'echo first %s second %s'
79
78
80 Note that %l and %s are mutually exclusive. You can only use one or
79 Note that %l and %s are mutually exclusive. You can only use one or
81 the other in your aliases.
80 the other in your aliases.
82
81
83 Aliases expand Python variables just like system calls using ! or !!
82 Aliases expand Python variables just like system calls using ! or !!
84 do: all expressions prefixed with '$' get expanded. For details of
83 do: all expressions prefixed with '$' get expanded. For details of
85 the semantic rules, see PEP-215:
84 the semantic rules, see PEP-215:
86 http://www.python.org/peps/pep-0215.html. This is the library used by
85 http://www.python.org/peps/pep-0215.html. This is the library used by
87 IPython for variable expansion. If you want to access a true shell
86 IPython for variable expansion. If you want to access a true shell
88 variable, an extra $ is necessary to prevent its expansion by
87 variable, an extra $ is necessary to prevent its expansion by
89 IPython::
88 IPython::
90
89
91 In [6]: alias show echo
90 In [6]: alias show echo
92 In [7]: PATH='A Python string'
91 In [7]: PATH='A Python string'
93 In [8]: show $PATH
92 In [8]: show $PATH
94 A Python string
93 A Python string
95 In [9]: show $$PATH
94 In [9]: show $$PATH
96 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
95 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
97
96
98 You can use the alias facility to acess all of $PATH. See the %rehashx
97 You can use the alias facility to acess all of $PATH. See the %rehashx
99 function, which automatically creates aliases for the contents of your
98 function, which automatically creates aliases for the contents of your
100 $PATH.
99 $PATH.
101
100
102 If called with no parameters, %alias prints the current alias table."""
101 If called with no parameters, %alias prints the current alias table."""
103
102
104 par = parameter_s.strip()
103 par = parameter_s.strip()
105 if not par:
104 if not par:
106 aliases = sorted(self.shell.alias_manager.aliases)
105 aliases = sorted(self.shell.alias_manager.aliases)
107 # stored = self.shell.db.get('stored_aliases', {} )
106 # stored = self.shell.db.get('stored_aliases', {} )
108 # for k, v in stored:
107 # for k, v in stored:
109 # atab.append(k, v[0])
108 # atab.append(k, v[0])
110
109
111 print("Total number of aliases:", len(aliases))
110 print("Total number of aliases:", len(aliases))
112 sys.stdout.flush()
111 sys.stdout.flush()
113 return aliases
112 return aliases
114
113
115 # Now try to define a new one
114 # Now try to define a new one
116 try:
115 try:
117 alias,cmd = par.split(None, 1)
116 alias,cmd = par.split(None, 1)
118 except TypeError:
117 except TypeError:
119 print(oinspect.getdoc(self.alias))
118 print(oinspect.getdoc(self.alias))
120 return
119 return
121
120
122 try:
121 try:
123 self.shell.alias_manager.define_alias(alias, cmd)
122 self.shell.alias_manager.define_alias(alias, cmd)
124 except AliasError as e:
123 except AliasError as e:
125 print(e)
124 print(e)
126 # end magic_alias
125 # end magic_alias
127
126
128 @line_magic
127 @line_magic
129 def unalias(self, parameter_s=''):
128 def unalias(self, parameter_s=''):
130 """Remove an alias"""
129 """Remove an alias"""
131
130
132 aname = parameter_s.strip()
131 aname = parameter_s.strip()
133 try:
132 try:
134 self.shell.alias_manager.undefine_alias(aname)
133 self.shell.alias_manager.undefine_alias(aname)
135 except ValueError as e:
134 except ValueError as e:
136 print(e)
135 print(e)
137 return
136 return
138
137
139 stored = self.shell.db.get('stored_aliases', {} )
138 stored = self.shell.db.get('stored_aliases', {} )
140 if aname in stored:
139 if aname in stored:
141 print("Removing %stored alias",aname)
140 print("Removing %stored alias",aname)
142 del stored[aname]
141 del stored[aname]
143 self.shell.db['stored_aliases'] = stored
142 self.shell.db['stored_aliases'] = stored
144
143
145 @line_magic
144 @line_magic
146 def rehashx(self, parameter_s=''):
145 def rehashx(self, parameter_s=''):
147 """Update the alias table with all executable files in $PATH.
146 """Update the alias table with all executable files in $PATH.
148
147
149 rehashx explicitly checks that every entry in $PATH is a file
148 rehashx explicitly checks that every entry in $PATH is a file
150 with execute access (os.X_OK).
149 with execute access (os.X_OK).
151
150
152 Under Windows, it checks executability as a match against a
151 Under Windows, it checks executability as a match against a
153 '|'-separated string of extensions, stored in the IPython config
152 '|'-separated string of extensions, stored in the IPython config
154 variable win_exec_ext. This defaults to 'exe|com|bat'.
153 variable win_exec_ext. This defaults to 'exe|com|bat'.
155
154
156 This function also resets the root module cache of module completer,
155 This function also resets the root module cache of module completer,
157 used on slow filesystems.
156 used on slow filesystems.
158 """
157 """
159 from IPython.core.alias import InvalidAliasError
158 from IPython.core.alias import InvalidAliasError
160
159
161 # for the benefit of module completer in ipy_completers.py
160 # for the benefit of module completer in ipy_completers.py
162 del self.shell.db['rootmodules_cache']
161 del self.shell.db['rootmodules_cache']
163
162
164 path = [os.path.abspath(os.path.expanduser(p)) for p in
163 path = [os.path.abspath(os.path.expanduser(p)) for p in
165 os.environ.get('PATH','').split(os.pathsep)]
164 os.environ.get('PATH','').split(os.pathsep)]
166
165
167 syscmdlist = []
166 syscmdlist = []
168 # Now define isexec in a cross platform manner.
167 # Now define isexec in a cross platform manner.
169 if os.name == 'posix':
168 if os.name == 'posix':
170 isexec = lambda fname:os.path.isfile(fname) and \
169 isexec = lambda fname:os.path.isfile(fname) and \
171 os.access(fname,os.X_OK)
170 os.access(fname,os.X_OK)
172 else:
171 else:
173 try:
172 try:
174 winext = os.environ['pathext'].replace(';','|').replace('.','')
173 winext = os.environ['pathext'].replace(';','|').replace('.','')
175 except KeyError:
174 except KeyError:
176 winext = 'exe|com|bat|py'
175 winext = 'exe|com|bat|py'
177 if 'py' not in winext:
176 if 'py' not in winext:
178 winext += '|py'
177 winext += '|py'
179 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
178 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
180 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
179 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
181 savedir = py3compat.getcwd()
180 savedir = os.getcwd()
182
181
183 # Now walk the paths looking for executables to alias.
182 # Now walk the paths looking for executables to alias.
184 try:
183 try:
185 # write the whole loop for posix/Windows so we don't have an if in
184 # write the whole loop for posix/Windows so we don't have an if in
186 # the innermost part
185 # the innermost part
187 if os.name == 'posix':
186 if os.name == 'posix':
188 for pdir in path:
187 for pdir in path:
189 try:
188 try:
190 os.chdir(pdir)
189 os.chdir(pdir)
191 dirlist = os.listdir(pdir)
190 dirlist = os.listdir(pdir)
192 except OSError:
191 except OSError:
193 continue
192 continue
194 for ff in dirlist:
193 for ff in dirlist:
195 if isexec(ff):
194 if isexec(ff):
196 try:
195 try:
197 # Removes dots from the name since ipython
196 # Removes dots from the name since ipython
198 # will assume names with dots to be python.
197 # will assume names with dots to be python.
199 if not self.shell.alias_manager.is_alias(ff):
198 if not self.shell.alias_manager.is_alias(ff):
200 self.shell.alias_manager.define_alias(
199 self.shell.alias_manager.define_alias(
201 ff.replace('.',''), ff)
200 ff.replace('.',''), ff)
202 except InvalidAliasError:
201 except InvalidAliasError:
203 pass
202 pass
204 else:
203 else:
205 syscmdlist.append(ff)
204 syscmdlist.append(ff)
206 else:
205 else:
207 no_alias = Alias.blacklist
206 no_alias = Alias.blacklist
208 for pdir in path:
207 for pdir in path:
209 try:
208 try:
210 os.chdir(pdir)
209 os.chdir(pdir)
211 dirlist = os.listdir(pdir)
210 dirlist = os.listdir(pdir)
212 except OSError:
211 except OSError:
213 continue
212 continue
214 for ff in dirlist:
213 for ff in dirlist:
215 base, ext = os.path.splitext(ff)
214 base, ext = os.path.splitext(ff)
216 if isexec(ff) and base.lower() not in no_alias:
215 if isexec(ff) and base.lower() not in no_alias:
217 if ext.lower() == '.exe':
216 if ext.lower() == '.exe':
218 ff = base
217 ff = base
219 try:
218 try:
220 # Removes dots from the name since ipython
219 # Removes dots from the name since ipython
221 # will assume names with dots to be python.
220 # will assume names with dots to be python.
222 self.shell.alias_manager.define_alias(
221 self.shell.alias_manager.define_alias(
223 base.lower().replace('.',''), ff)
222 base.lower().replace('.',''), ff)
224 except InvalidAliasError:
223 except InvalidAliasError:
225 pass
224 pass
226 syscmdlist.append(ff)
225 syscmdlist.append(ff)
227 self.shell.db['syscmdlist'] = syscmdlist
226 self.shell.db['syscmdlist'] = syscmdlist
228 finally:
227 finally:
229 os.chdir(savedir)
228 os.chdir(savedir)
230
229
231 @skip_doctest
230 @skip_doctest
232 @line_magic
231 @line_magic
233 def pwd(self, parameter_s=''):
232 def pwd(self, parameter_s=''):
234 """Return the current working directory path.
233 """Return the current working directory path.
235
234
236 Examples
235 Examples
237 --------
236 --------
238 ::
237 ::
239
238
240 In [9]: pwd
239 In [9]: pwd
241 Out[9]: '/home/tsuser/sprint/ipython'
240 Out[9]: '/home/tsuser/sprint/ipython'
242 """
241 """
243 return py3compat.getcwd()
242 return os.getcwd()
244
243
245 @skip_doctest
244 @skip_doctest
246 @line_magic
245 @line_magic
247 def cd(self, parameter_s=''):
246 def cd(self, parameter_s=''):
248 """Change the current working directory.
247 """Change the current working directory.
249
248
250 This command automatically maintains an internal list of directories
249 This command automatically maintains an internal list of directories
251 you visit during your IPython session, in the variable _dh. The
250 you visit during your IPython session, in the variable _dh. The
252 command %dhist shows this history nicely formatted. You can also
251 command %dhist shows this history nicely formatted. You can also
253 do 'cd -<tab>' to see directory history conveniently.
252 do 'cd -<tab>' to see directory history conveniently.
254
253
255 Usage:
254 Usage:
256
255
257 cd 'dir': changes to directory 'dir'.
256 cd 'dir': changes to directory 'dir'.
258
257
259 cd -: changes to the last visited directory.
258 cd -: changes to the last visited directory.
260
259
261 cd -<n>: changes to the n-th directory in the directory history.
260 cd -<n>: changes to the n-th directory in the directory history.
262
261
263 cd --foo: change to directory that matches 'foo' in history
262 cd --foo: change to directory that matches 'foo' in history
264
263
265 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
264 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
266 (note: cd <bookmark_name> is enough if there is no
265 (note: cd <bookmark_name> is enough if there is no
267 directory <bookmark_name>, but a bookmark with the name exists.)
266 directory <bookmark_name>, but a bookmark with the name exists.)
268 'cd -b <tab>' allows you to tab-complete bookmark names.
267 'cd -b <tab>' allows you to tab-complete bookmark names.
269
268
270 Options:
269 Options:
271
270
272 -q: quiet. Do not print the working directory after the cd command is
271 -q: quiet. Do not print the working directory after the cd command is
273 executed. By default IPython's cd command does print this directory,
272 executed. By default IPython's cd command does print this directory,
274 since the default prompts do not display path information.
273 since the default prompts do not display path information.
275
274
276 Note that !cd doesn't work for this purpose because the shell where
275 Note that !cd doesn't work for this purpose because the shell where
277 !command runs is immediately discarded after executing 'command'.
276 !command runs is immediately discarded after executing 'command'.
278
277
279 Examples
278 Examples
280 --------
279 --------
281 ::
280 ::
282
281
283 In [10]: cd parent/child
282 In [10]: cd parent/child
284 /home/tsuser/parent/child
283 /home/tsuser/parent/child
285 """
284 """
286
285
287 oldcwd = py3compat.getcwd()
286 oldcwd = os.getcwd()
288 numcd = re.match(r'(-)(\d+)$',parameter_s)
287 numcd = re.match(r'(-)(\d+)$',parameter_s)
289 # jump in directory history by number
288 # jump in directory history by number
290 if numcd:
289 if numcd:
291 nn = int(numcd.group(2))
290 nn = int(numcd.group(2))
292 try:
291 try:
293 ps = self.shell.user_ns['_dh'][nn]
292 ps = self.shell.user_ns['_dh'][nn]
294 except IndexError:
293 except IndexError:
295 print('The requested directory does not exist in history.')
294 print('The requested directory does not exist in history.')
296 return
295 return
297 else:
296 else:
298 opts = {}
297 opts = {}
299 elif parameter_s.startswith('--'):
298 elif parameter_s.startswith('--'):
300 ps = None
299 ps = None
301 fallback = None
300 fallback = None
302 pat = parameter_s[2:]
301 pat = parameter_s[2:]
303 dh = self.shell.user_ns['_dh']
302 dh = self.shell.user_ns['_dh']
304 # first search only by basename (last component)
303 # first search only by basename (last component)
305 for ent in reversed(dh):
304 for ent in reversed(dh):
306 if pat in os.path.basename(ent) and os.path.isdir(ent):
305 if pat in os.path.basename(ent) and os.path.isdir(ent):
307 ps = ent
306 ps = ent
308 break
307 break
309
308
310 if fallback is None and pat in ent and os.path.isdir(ent):
309 if fallback is None and pat in ent and os.path.isdir(ent):
311 fallback = ent
310 fallback = ent
312
311
313 # if we have no last part match, pick the first full path match
312 # if we have no last part match, pick the first full path match
314 if ps is None:
313 if ps is None:
315 ps = fallback
314 ps = fallback
316
315
317 if ps is None:
316 if ps is None:
318 print("No matching entry in directory history")
317 print("No matching entry in directory history")
319 return
318 return
320 else:
319 else:
321 opts = {}
320 opts = {}
322
321
323
322
324 else:
323 else:
325 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
324 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
326 # jump to previous
325 # jump to previous
327 if ps == '-':
326 if ps == '-':
328 try:
327 try:
329 ps = self.shell.user_ns['_dh'][-2]
328 ps = self.shell.user_ns['_dh'][-2]
330 except IndexError:
329 except IndexError:
331 raise UsageError('%cd -: No previous directory to change to.')
330 raise UsageError('%cd -: No previous directory to change to.')
332 # jump to bookmark if needed
331 # jump to bookmark if needed
333 else:
332 else:
334 if not os.path.isdir(ps) or 'b' in opts:
333 if not os.path.isdir(ps) or 'b' in opts:
335 bkms = self.shell.db.get('bookmarks', {})
334 bkms = self.shell.db.get('bookmarks', {})
336
335
337 if ps in bkms:
336 if ps in bkms:
338 target = bkms[ps]
337 target = bkms[ps]
339 print('(bookmark:%s) -> %s' % (ps, target))
338 print('(bookmark:%s) -> %s' % (ps, target))
340 ps = target
339 ps = target
341 else:
340 else:
342 if 'b' in opts:
341 if 'b' in opts:
343 raise UsageError("Bookmark '%s' not found. "
342 raise UsageError("Bookmark '%s' not found. "
344 "Use '%%bookmark -l' to see your bookmarks." % ps)
343 "Use '%%bookmark -l' to see your bookmarks." % ps)
345
344
346 # at this point ps should point to the target dir
345 # at this point ps should point to the target dir
347 if ps:
346 if ps:
348 try:
347 try:
349 os.chdir(os.path.expanduser(ps))
348 os.chdir(os.path.expanduser(ps))
350 if hasattr(self.shell, 'term_title') and self.shell.term_title:
349 if hasattr(self.shell, 'term_title') and self.shell.term_title:
351 set_term_title('IPython: ' + abbrev_cwd())
350 set_term_title('IPython: ' + abbrev_cwd())
352 except OSError:
351 except OSError:
353 print(sys.exc_info()[1])
352 print(sys.exc_info()[1])
354 else:
353 else:
355 cwd = py3compat.getcwd()
354 cwd = os.getcwd()
356 dhist = self.shell.user_ns['_dh']
355 dhist = self.shell.user_ns['_dh']
357 if oldcwd != cwd:
356 if oldcwd != cwd:
358 dhist.append(cwd)
357 dhist.append(cwd)
359 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
358 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
360
359
361 else:
360 else:
362 os.chdir(self.shell.home_dir)
361 os.chdir(self.shell.home_dir)
363 if hasattr(self.shell, 'term_title') and self.shell.term_title:
362 if hasattr(self.shell, 'term_title') and self.shell.term_title:
364 set_term_title('IPython: ' + '~')
363 set_term_title('IPython: ' + '~')
365 cwd = py3compat.getcwd()
364 cwd = os.getcwd()
366 dhist = self.shell.user_ns['_dh']
365 dhist = self.shell.user_ns['_dh']
367
366
368 if oldcwd != cwd:
367 if oldcwd != cwd:
369 dhist.append(cwd)
368 dhist.append(cwd)
370 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
369 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
371 if not 'q' in opts and self.shell.user_ns['_dh']:
370 if not 'q' in opts and self.shell.user_ns['_dh']:
372 print(self.shell.user_ns['_dh'][-1])
371 print(self.shell.user_ns['_dh'][-1])
373
372
374 @line_magic
373 @line_magic
375 def env(self, parameter_s=''):
374 def env(self, parameter_s=''):
376 """Get, set, or list environment variables.
375 """Get, set, or list environment variables.
377
376
378 Usage:\\
377 Usage:\\
379
378
380 %env: lists all environment variables/values
379 %env: lists all environment variables/values
381 %env var: get value for var
380 %env var: get value for var
382 %env var val: set value for var
381 %env var val: set value for var
383 %env var=val: set value for var
382 %env var=val: set value for var
384 %env var=$val: set value for var, using python expansion if possible
383 %env var=$val: set value for var, using python expansion if possible
385 """
384 """
386 if parameter_s.strip():
385 if parameter_s.strip():
387 split = '=' if '=' in parameter_s else ' '
386 split = '=' if '=' in parameter_s else ' '
388 bits = parameter_s.split(split)
387 bits = parameter_s.split(split)
389 if len(bits) == 1:
388 if len(bits) == 1:
390 key = parameter_s.strip()
389 key = parameter_s.strip()
391 if key in os.environ:
390 if key in os.environ:
392 return os.environ[key]
391 return os.environ[key]
393 else:
392 else:
394 err = "Environment does not have key: {0}".format(key)
393 err = "Environment does not have key: {0}".format(key)
395 raise UsageError(err)
394 raise UsageError(err)
396 if len(bits) > 1:
395 if len(bits) > 1:
397 return self.set_env(parameter_s)
396 return self.set_env(parameter_s)
398 return dict(os.environ)
397 return dict(os.environ)
399
398
400 @line_magic
399 @line_magic
401 def set_env(self, parameter_s):
400 def set_env(self, parameter_s):
402 """Set environment variables. Assumptions are that either "val" is a
401 """Set environment variables. Assumptions are that either "val" is a
403 name in the user namespace, or val is something that evaluates to a
402 name in the user namespace, or val is something that evaluates to a
404 string.
403 string.
405
404
406 Usage:\\
405 Usage:\\
407 %set_env var val: set value for var
406 %set_env var val: set value for var
408 %set_env var=val: set value for var
407 %set_env var=val: set value for var
409 %set_env var=$val: set value for var, using python expansion if possible
408 %set_env var=$val: set value for var, using python expansion if possible
410 """
409 """
411 split = '=' if '=' in parameter_s else ' '
410 split = '=' if '=' in parameter_s else ' '
412 bits = parameter_s.split(split, 1)
411 bits = parameter_s.split(split, 1)
413 if not parameter_s.strip() or len(bits)<2:
412 if not parameter_s.strip() or len(bits)<2:
414 raise UsageError("usage is 'set_env var=val'")
413 raise UsageError("usage is 'set_env var=val'")
415 var = bits[0].strip()
414 var = bits[0].strip()
416 val = bits[1].strip()
415 val = bits[1].strip()
417 if re.match(r'.*\s.*', var):
416 if re.match(r'.*\s.*', var):
418 # an environment variable with whitespace is almost certainly
417 # an environment variable with whitespace is almost certainly
419 # not what the user intended. what's more likely is the wrong
418 # not what the user intended. what's more likely is the wrong
420 # split was chosen, ie for "set_env cmd_args A=B", we chose
419 # split was chosen, ie for "set_env cmd_args A=B", we chose
421 # '=' for the split and should have chosen ' '. to get around
420 # '=' for the split and should have chosen ' '. to get around
422 # this, users should just assign directly to os.environ or use
421 # this, users should just assign directly to os.environ or use
423 # standard magic {var} expansion.
422 # standard magic {var} expansion.
424 err = "refusing to set env var with whitespace: '{0}'"
423 err = "refusing to set env var with whitespace: '{0}'"
425 err = err.format(val)
424 err = err.format(val)
426 raise UsageError(err)
425 raise UsageError(err)
427 os.environ[py3compat.cast_bytes_py2(var)] = py3compat.cast_bytes_py2(val)
426 os.environ[py3compat.cast_bytes_py2(var)] = py3compat.cast_bytes_py2(val)
428 print('env: {0}={1}'.format(var,val))
427 print('env: {0}={1}'.format(var,val))
429
428
430 @line_magic
429 @line_magic
431 def pushd(self, parameter_s=''):
430 def pushd(self, parameter_s=''):
432 """Place the current dir on stack and change directory.
431 """Place the current dir on stack and change directory.
433
432
434 Usage:\\
433 Usage:\\
435 %pushd ['dirname']
434 %pushd ['dirname']
436 """
435 """
437
436
438 dir_s = self.shell.dir_stack
437 dir_s = self.shell.dir_stack
439 tgt = os.path.expanduser(parameter_s)
438 tgt = os.path.expanduser(parameter_s)
440 cwd = py3compat.getcwd().replace(self.shell.home_dir,'~')
439 cwd = os.getcwd().replace(self.shell.home_dir,'~')
441 if tgt:
440 if tgt:
442 self.cd(parameter_s)
441 self.cd(parameter_s)
443 dir_s.insert(0,cwd)
442 dir_s.insert(0,cwd)
444 return self.shell.magic('dirs')
443 return self.shell.magic('dirs')
445
444
446 @line_magic
445 @line_magic
447 def popd(self, parameter_s=''):
446 def popd(self, parameter_s=''):
448 """Change to directory popped off the top of the stack.
447 """Change to directory popped off the top of the stack.
449 """
448 """
450 if not self.shell.dir_stack:
449 if not self.shell.dir_stack:
451 raise UsageError("%popd on empty stack")
450 raise UsageError("%popd on empty stack")
452 top = self.shell.dir_stack.pop(0)
451 top = self.shell.dir_stack.pop(0)
453 self.cd(top)
452 self.cd(top)
454 print("popd ->",top)
453 print("popd ->",top)
455
454
456 @line_magic
455 @line_magic
457 def dirs(self, parameter_s=''):
456 def dirs(self, parameter_s=''):
458 """Return the current directory stack."""
457 """Return the current directory stack."""
459
458
460 return self.shell.dir_stack
459 return self.shell.dir_stack
461
460
462 @line_magic
461 @line_magic
463 def dhist(self, parameter_s=''):
462 def dhist(self, parameter_s=''):
464 """Print your history of visited directories.
463 """Print your history of visited directories.
465
464
466 %dhist -> print full history\\
465 %dhist -> print full history\\
467 %dhist n -> print last n entries only\\
466 %dhist n -> print last n entries only\\
468 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
467 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
469
468
470 This history is automatically maintained by the %cd command, and
469 This history is automatically maintained by the %cd command, and
471 always available as the global list variable _dh. You can use %cd -<n>
470 always available as the global list variable _dh. You can use %cd -<n>
472 to go to directory number <n>.
471 to go to directory number <n>.
473
472
474 Note that most of time, you should view directory history by entering
473 Note that most of time, you should view directory history by entering
475 cd -<TAB>.
474 cd -<TAB>.
476
475
477 """
476 """
478
477
479 dh = self.shell.user_ns['_dh']
478 dh = self.shell.user_ns['_dh']
480 if parameter_s:
479 if parameter_s:
481 try:
480 try:
482 args = map(int,parameter_s.split())
481 args = map(int,parameter_s.split())
483 except:
482 except:
484 self.arg_err(self.dhist)
483 self.arg_err(self.dhist)
485 return
484 return
486 if len(args) == 1:
485 if len(args) == 1:
487 ini,fin = max(len(dh)-(args[0]),0),len(dh)
486 ini,fin = max(len(dh)-(args[0]),0),len(dh)
488 elif len(args) == 2:
487 elif len(args) == 2:
489 ini,fin = args
488 ini,fin = args
490 fin = min(fin, len(dh))
489 fin = min(fin, len(dh))
491 else:
490 else:
492 self.arg_err(self.dhist)
491 self.arg_err(self.dhist)
493 return
492 return
494 else:
493 else:
495 ini,fin = 0,len(dh)
494 ini,fin = 0,len(dh)
496 print('Directory history (kept in _dh)')
495 print('Directory history (kept in _dh)')
497 for i in range(ini, fin):
496 for i in range(ini, fin):
498 print("%d: %s" % (i, dh[i]))
497 print("%d: %s" % (i, dh[i]))
499
498
500 @skip_doctest
499 @skip_doctest
501 @line_magic
500 @line_magic
502 def sc(self, parameter_s=''):
501 def sc(self, parameter_s=''):
503 """Shell capture - run shell command and capture output (DEPRECATED use !).
502 """Shell capture - run shell command and capture output (DEPRECATED use !).
504
503
505 DEPRECATED. Suboptimal, retained for backwards compatibility.
504 DEPRECATED. Suboptimal, retained for backwards compatibility.
506
505
507 You should use the form 'var = !command' instead. Example:
506 You should use the form 'var = !command' instead. Example:
508
507
509 "%sc -l myfiles = ls ~" should now be written as
508 "%sc -l myfiles = ls ~" should now be written as
510
509
511 "myfiles = !ls ~"
510 "myfiles = !ls ~"
512
511
513 myfiles.s, myfiles.l and myfiles.n still apply as documented
512 myfiles.s, myfiles.l and myfiles.n still apply as documented
514 below.
513 below.
515
514
516 --
515 --
517 %sc [options] varname=command
516 %sc [options] varname=command
518
517
519 IPython will run the given command using commands.getoutput(), and
518 IPython will run the given command using commands.getoutput(), and
520 will then update the user's interactive namespace with a variable
519 will then update the user's interactive namespace with a variable
521 called varname, containing the value of the call. Your command can
520 called varname, containing the value of the call. Your command can
522 contain shell wildcards, pipes, etc.
521 contain shell wildcards, pipes, etc.
523
522
524 The '=' sign in the syntax is mandatory, and the variable name you
523 The '=' sign in the syntax is mandatory, and the variable name you
525 supply must follow Python's standard conventions for valid names.
524 supply must follow Python's standard conventions for valid names.
526
525
527 (A special format without variable name exists for internal use)
526 (A special format without variable name exists for internal use)
528
527
529 Options:
528 Options:
530
529
531 -l: list output. Split the output on newlines into a list before
530 -l: list output. Split the output on newlines into a list before
532 assigning it to the given variable. By default the output is stored
531 assigning it to the given variable. By default the output is stored
533 as a single string.
532 as a single string.
534
533
535 -v: verbose. Print the contents of the variable.
534 -v: verbose. Print the contents of the variable.
536
535
537 In most cases you should not need to split as a list, because the
536 In most cases you should not need to split as a list, because the
538 returned value is a special type of string which can automatically
537 returned value is a special type of string which can automatically
539 provide its contents either as a list (split on newlines) or as a
538 provide its contents either as a list (split on newlines) or as a
540 space-separated string. These are convenient, respectively, either
539 space-separated string. These are convenient, respectively, either
541 for sequential processing or to be passed to a shell command.
540 for sequential processing or to be passed to a shell command.
542
541
543 For example::
542 For example::
544
543
545 # Capture into variable a
544 # Capture into variable a
546 In [1]: sc a=ls *py
545 In [1]: sc a=ls *py
547
546
548 # a is a string with embedded newlines
547 # a is a string with embedded newlines
549 In [2]: a
548 In [2]: a
550 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
549 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
551
550
552 # which can be seen as a list:
551 # which can be seen as a list:
553 In [3]: a.l
552 In [3]: a.l
554 Out[3]: ['setup.py', 'win32_manual_post_install.py']
553 Out[3]: ['setup.py', 'win32_manual_post_install.py']
555
554
556 # or as a whitespace-separated string:
555 # or as a whitespace-separated string:
557 In [4]: a.s
556 In [4]: a.s
558 Out[4]: 'setup.py win32_manual_post_install.py'
557 Out[4]: 'setup.py win32_manual_post_install.py'
559
558
560 # a.s is useful to pass as a single command line:
559 # a.s is useful to pass as a single command line:
561 In [5]: !wc -l $a.s
560 In [5]: !wc -l $a.s
562 146 setup.py
561 146 setup.py
563 130 win32_manual_post_install.py
562 130 win32_manual_post_install.py
564 276 total
563 276 total
565
564
566 # while the list form is useful to loop over:
565 # while the list form is useful to loop over:
567 In [6]: for f in a.l:
566 In [6]: for f in a.l:
568 ...: !wc -l $f
567 ...: !wc -l $f
569 ...:
568 ...:
570 146 setup.py
569 146 setup.py
571 130 win32_manual_post_install.py
570 130 win32_manual_post_install.py
572
571
573 Similarly, the lists returned by the -l option are also special, in
572 Similarly, the lists returned by the -l option are also special, in
574 the sense that you can equally invoke the .s attribute on them to
573 the sense that you can equally invoke the .s attribute on them to
575 automatically get a whitespace-separated string from their contents::
574 automatically get a whitespace-separated string from their contents::
576
575
577 In [7]: sc -l b=ls *py
576 In [7]: sc -l b=ls *py
578
577
579 In [8]: b
578 In [8]: b
580 Out[8]: ['setup.py', 'win32_manual_post_install.py']
579 Out[8]: ['setup.py', 'win32_manual_post_install.py']
581
580
582 In [9]: b.s
581 In [9]: b.s
583 Out[9]: 'setup.py win32_manual_post_install.py'
582 Out[9]: 'setup.py win32_manual_post_install.py'
584
583
585 In summary, both the lists and strings used for output capture have
584 In summary, both the lists and strings used for output capture have
586 the following special attributes::
585 the following special attributes::
587
586
588 .l (or .list) : value as list.
587 .l (or .list) : value as list.
589 .n (or .nlstr): value as newline-separated string.
588 .n (or .nlstr): value as newline-separated string.
590 .s (or .spstr): value as space-separated string.
589 .s (or .spstr): value as space-separated string.
591 """
590 """
592
591
593 opts,args = self.parse_options(parameter_s, 'lv')
592 opts,args = self.parse_options(parameter_s, 'lv')
594 # Try to get a variable name and command to run
593 # Try to get a variable name and command to run
595 try:
594 try:
596 # the variable name must be obtained from the parse_options
595 # the variable name must be obtained from the parse_options
597 # output, which uses shlex.split to strip options out.
596 # output, which uses shlex.split to strip options out.
598 var,_ = args.split('=', 1)
597 var,_ = args.split('=', 1)
599 var = var.strip()
598 var = var.strip()
600 # But the command has to be extracted from the original input
599 # But the command has to be extracted from the original input
601 # parameter_s, not on what parse_options returns, to avoid the
600 # parameter_s, not on what parse_options returns, to avoid the
602 # quote stripping which shlex.split performs on it.
601 # quote stripping which shlex.split performs on it.
603 _,cmd = parameter_s.split('=', 1)
602 _,cmd = parameter_s.split('=', 1)
604 except ValueError:
603 except ValueError:
605 var,cmd = '',''
604 var,cmd = '',''
606 # If all looks ok, proceed
605 # If all looks ok, proceed
607 split = 'l' in opts
606 split = 'l' in opts
608 out = self.shell.getoutput(cmd, split=split)
607 out = self.shell.getoutput(cmd, split=split)
609 if 'v' in opts:
608 if 'v' in opts:
610 print('%s ==\n%s' % (var, pformat(out)))
609 print('%s ==\n%s' % (var, pformat(out)))
611 if var:
610 if var:
612 self.shell.user_ns.update({var:out})
611 self.shell.user_ns.update({var:out})
613 else:
612 else:
614 return out
613 return out
615
614
616 @line_cell_magic
615 @line_cell_magic
617 def sx(self, line='', cell=None):
616 def sx(self, line='', cell=None):
618 """Shell execute - run shell command and capture output (!! is short-hand).
617 """Shell execute - run shell command and capture output (!! is short-hand).
619
618
620 %sx command
619 %sx command
621
620
622 IPython will run the given command using commands.getoutput(), and
621 IPython will run the given command using commands.getoutput(), and
623 return the result formatted as a list (split on '\\n'). Since the
622 return the result formatted as a list (split on '\\n'). Since the
624 output is _returned_, it will be stored in ipython's regular output
623 output is _returned_, it will be stored in ipython's regular output
625 cache Out[N] and in the '_N' automatic variables.
624 cache Out[N] and in the '_N' automatic variables.
626
625
627 Notes:
626 Notes:
628
627
629 1) If an input line begins with '!!', then %sx is automatically
628 1) If an input line begins with '!!', then %sx is automatically
630 invoked. That is, while::
629 invoked. That is, while::
631
630
632 !ls
631 !ls
633
632
634 causes ipython to simply issue system('ls'), typing::
633 causes ipython to simply issue system('ls'), typing::
635
634
636 !!ls
635 !!ls
637
636
638 is a shorthand equivalent to::
637 is a shorthand equivalent to::
639
638
640 %sx ls
639 %sx ls
641
640
642 2) %sx differs from %sc in that %sx automatically splits into a list,
641 2) %sx differs from %sc in that %sx automatically splits into a list,
643 like '%sc -l'. The reason for this is to make it as easy as possible
642 like '%sc -l'. The reason for this is to make it as easy as possible
644 to process line-oriented shell output via further python commands.
643 to process line-oriented shell output via further python commands.
645 %sc is meant to provide much finer control, but requires more
644 %sc is meant to provide much finer control, but requires more
646 typing.
645 typing.
647
646
648 3) Just like %sc -l, this is a list with special attributes:
647 3) Just like %sc -l, this is a list with special attributes:
649 ::
648 ::
650
649
651 .l (or .list) : value as list.
650 .l (or .list) : value as list.
652 .n (or .nlstr): value as newline-separated string.
651 .n (or .nlstr): value as newline-separated string.
653 .s (or .spstr): value as whitespace-separated string.
652 .s (or .spstr): value as whitespace-separated string.
654
653
655 This is very useful when trying to use such lists as arguments to
654 This is very useful when trying to use such lists as arguments to
656 system commands."""
655 system commands."""
657
656
658 if cell is None:
657 if cell is None:
659 # line magic
658 # line magic
660 return self.shell.getoutput(line)
659 return self.shell.getoutput(line)
661 else:
660 else:
662 opts,args = self.parse_options(line, '', 'out=')
661 opts,args = self.parse_options(line, '', 'out=')
663 output = self.shell.getoutput(cell)
662 output = self.shell.getoutput(cell)
664 out_name = opts.get('out', opts.get('o'))
663 out_name = opts.get('out', opts.get('o'))
665 if out_name:
664 if out_name:
666 self.shell.user_ns[out_name] = output
665 self.shell.user_ns[out_name] = output
667 else:
666 else:
668 return output
667 return output
669
668
670 system = line_cell_magic('system')(sx)
669 system = line_cell_magic('system')(sx)
671 bang = cell_magic('!')(sx)
670 bang = cell_magic('!')(sx)
672
671
673 @line_magic
672 @line_magic
674 def bookmark(self, parameter_s=''):
673 def bookmark(self, parameter_s=''):
675 """Manage IPython's bookmark system.
674 """Manage IPython's bookmark system.
676
675
677 %bookmark <name> - set bookmark to current dir
676 %bookmark <name> - set bookmark to current dir
678 %bookmark <name> <dir> - set bookmark to <dir>
677 %bookmark <name> <dir> - set bookmark to <dir>
679 %bookmark -l - list all bookmarks
678 %bookmark -l - list all bookmarks
680 %bookmark -d <name> - remove bookmark
679 %bookmark -d <name> - remove bookmark
681 %bookmark -r - remove all bookmarks
680 %bookmark -r - remove all bookmarks
682
681
683 You can later on access a bookmarked folder with::
682 You can later on access a bookmarked folder with::
684
683
685 %cd -b <name>
684 %cd -b <name>
686
685
687 or simply '%cd <name>' if there is no directory called <name> AND
686 or simply '%cd <name>' if there is no directory called <name> AND
688 there is such a bookmark defined.
687 there is such a bookmark defined.
689
688
690 Your bookmarks persist through IPython sessions, but they are
689 Your bookmarks persist through IPython sessions, but they are
691 associated with each profile."""
690 associated with each profile."""
692
691
693 opts,args = self.parse_options(parameter_s,'drl',mode='list')
692 opts,args = self.parse_options(parameter_s,'drl',mode='list')
694 if len(args) > 2:
693 if len(args) > 2:
695 raise UsageError("%bookmark: too many arguments")
694 raise UsageError("%bookmark: too many arguments")
696
695
697 bkms = self.shell.db.get('bookmarks',{})
696 bkms = self.shell.db.get('bookmarks',{})
698
697
699 if 'd' in opts:
698 if 'd' in opts:
700 try:
699 try:
701 todel = args[0]
700 todel = args[0]
702 except IndexError:
701 except IndexError:
703 raise UsageError(
702 raise UsageError(
704 "%bookmark -d: must provide a bookmark to delete")
703 "%bookmark -d: must provide a bookmark to delete")
705 else:
704 else:
706 try:
705 try:
707 del bkms[todel]
706 del bkms[todel]
708 except KeyError:
707 except KeyError:
709 raise UsageError(
708 raise UsageError(
710 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
709 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
711
710
712 elif 'r' in opts:
711 elif 'r' in opts:
713 bkms = {}
712 bkms = {}
714 elif 'l' in opts:
713 elif 'l' in opts:
715 bks = sorted(bkms)
714 bks = sorted(bkms)
716 if bks:
715 if bks:
717 size = max(map(len, bks))
716 size = max(map(len, bks))
718 else:
717 else:
719 size = 0
718 size = 0
720 fmt = '%-'+str(size)+'s -> %s'
719 fmt = '%-'+str(size)+'s -> %s'
721 print('Current bookmarks:')
720 print('Current bookmarks:')
722 for bk in bks:
721 for bk in bks:
723 print(fmt % (bk, bkms[bk]))
722 print(fmt % (bk, bkms[bk]))
724 else:
723 else:
725 if not args:
724 if not args:
726 raise UsageError("%bookmark: You must specify the bookmark name")
725 raise UsageError("%bookmark: You must specify the bookmark name")
727 elif len(args)==1:
726 elif len(args)==1:
728 bkms[args[0]] = py3compat.getcwd()
727 bkms[args[0]] = os.getcwd()
729 elif len(args)==2:
728 elif len(args)==2:
730 bkms[args[0]] = args[1]
729 bkms[args[0]] = args[1]
731 self.shell.db['bookmarks'] = bkms
730 self.shell.db['bookmarks'] = bkms
732
731
733 @line_magic
732 @line_magic
734 def pycat(self, parameter_s=''):
733 def pycat(self, parameter_s=''):
735 """Show a syntax-highlighted file through a pager.
734 """Show a syntax-highlighted file through a pager.
736
735
737 This magic is similar to the cat utility, but it will assume the file
736 This magic is similar to the cat utility, but it will assume the file
738 to be Python source and will show it with syntax highlighting.
737 to be Python source and will show it with syntax highlighting.
739
738
740 This magic command can either take a local filename, an url,
739 This magic command can either take a local filename, an url,
741 an history range (see %history) or a macro as argument ::
740 an history range (see %history) or a macro as argument ::
742
741
743 %pycat myscript.py
742 %pycat myscript.py
744 %pycat 7-27
743 %pycat 7-27
745 %pycat myMacro
744 %pycat myMacro
746 %pycat http://www.example.com/myscript.py
745 %pycat http://www.example.com/myscript.py
747 """
746 """
748 if not parameter_s:
747 if not parameter_s:
749 raise UsageError('Missing filename, URL, input history range, '
748 raise UsageError('Missing filename, URL, input history range, '
750 'or macro.')
749 'or macro.')
751
750
752 try :
751 try :
753 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
752 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
754 except (ValueError, IOError):
753 except (ValueError, IOError):
755 print("Error: no such file, variable, URL, history range or macro")
754 print("Error: no such file, variable, URL, history range or macro")
756 return
755 return
757
756
758 page.page(self.shell.pycolorize(source_to_unicode(cont)))
757 page.page(self.shell.pycolorize(source_to_unicode(cont)))
759
758
760 @magic_arguments.magic_arguments()
759 @magic_arguments.magic_arguments()
761 @magic_arguments.argument(
760 @magic_arguments.argument(
762 '-a', '--append', action='store_true', default=False,
761 '-a', '--append', action='store_true', default=False,
763 help='Append contents of the cell to an existing file. '
762 help='Append contents of the cell to an existing file. '
764 'The file will be created if it does not exist.'
763 'The file will be created if it does not exist.'
765 )
764 )
766 @magic_arguments.argument(
765 @magic_arguments.argument(
767 'filename', type=unicode_type,
766 'filename', type=str,
768 help='file to write'
767 help='file to write'
769 )
768 )
770 @cell_magic
769 @cell_magic
771 def writefile(self, line, cell):
770 def writefile(self, line, cell):
772 """Write the contents of the cell to a file.
771 """Write the contents of the cell to a file.
773
772
774 The file will be overwritten unless the -a (--append) flag is specified.
773 The file will be overwritten unless the -a (--append) flag is specified.
775 """
774 """
776 args = magic_arguments.parse_argstring(self.writefile, line)
775 args = magic_arguments.parse_argstring(self.writefile, line)
777 filename = os.path.expanduser(args.filename)
776 filename = os.path.expanduser(args.filename)
778
777
779 if os.path.exists(filename):
778 if os.path.exists(filename):
780 if args.append:
779 if args.append:
781 print("Appending to %s" % filename)
780 print("Appending to %s" % filename)
782 else:
781 else:
783 print("Overwriting %s" % filename)
782 print("Overwriting %s" % filename)
784 else:
783 else:
785 print("Writing %s" % filename)
784 print("Writing %s" % filename)
786
785
787 mode = 'a' if args.append else 'w'
786 mode = 'a' if args.append else 'w'
788 with io.open(filename, mode, encoding='utf-8') as f:
787 with io.open(filename, mode, encoding='utf-8') as f:
789 f.write(cell)
788 f.write(cell)
@@ -1,987 +1,987 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
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 __all__ = ['Inspector','InspectColors']
13 __all__ = ['Inspector','InspectColors']
14
14
15 # stdlib modules
15 # stdlib modules
16 import inspect
16 import inspect
17 from inspect import signature
17 from inspect import signature
18 import linecache
18 import linecache
19 import warnings
19 import warnings
20 import os
20 import os
21 from textwrap import dedent
21 from textwrap import dedent
22 import types
22 import types
23 import io as stdlib_io
23 import io as stdlib_io
24 from itertools import zip_longest
24 from itertools import zip_longest
25
25
26 # IPython's own
26 # IPython's own
27 from IPython.core import page
27 from IPython.core import page
28 from IPython.lib.pretty import pretty
28 from IPython.lib.pretty import pretty
29 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.testing.skipdoctest import skip_doctest
30 from IPython.utils import PyColorize
30 from IPython.utils import PyColorize
31 from IPython.utils import openpy
31 from IPython.utils import openpy
32 from IPython.utils import py3compat
32 from IPython.utils import py3compat
33 from IPython.utils.dir2 import safe_hasattr
33 from IPython.utils.dir2 import safe_hasattr
34 from IPython.utils.path import compress_user
34 from IPython.utils.path import compress_user
35 from IPython.utils.text import indent
35 from IPython.utils.text import indent
36 from IPython.utils.wildcard import list_namespace
36 from IPython.utils.wildcard import list_namespace
37 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
37 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
38 from IPython.utils.py3compat import cast_unicode, string_types, PY3
38 from IPython.utils.py3compat import cast_unicode, PY3
39 from IPython.utils.colorable import Colorable
39 from IPython.utils.colorable import Colorable
40 from IPython.utils.decorators import undoc
40 from IPython.utils.decorators import undoc
41
41
42 from pygments import highlight
42 from pygments import highlight
43 from pygments.lexers import PythonLexer
43 from pygments.lexers import PythonLexer
44 from pygments.formatters import HtmlFormatter
44 from pygments.formatters import HtmlFormatter
45
45
46 def pylight(code):
46 def pylight(code):
47 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
47 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
48
48
49 # builtin docstrings to ignore
49 # builtin docstrings to ignore
50 _func_call_docstring = types.FunctionType.__call__.__doc__
50 _func_call_docstring = types.FunctionType.__call__.__doc__
51 _object_init_docstring = object.__init__.__doc__
51 _object_init_docstring = object.__init__.__doc__
52 _builtin_type_docstrings = {
52 _builtin_type_docstrings = {
53 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
53 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
54 types.FunctionType, property)
54 types.FunctionType, property)
55 }
55 }
56
56
57 _builtin_func_type = type(all)
57 _builtin_func_type = type(all)
58 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
58 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
59 #****************************************************************************
59 #****************************************************************************
60 # Builtin color schemes
60 # Builtin color schemes
61
61
62 Colors = TermColors # just a shorthand
62 Colors = TermColors # just a shorthand
63
63
64 InspectColors = PyColorize.ANSICodeColors
64 InspectColors = PyColorize.ANSICodeColors
65
65
66 #****************************************************************************
66 #****************************************************************************
67 # Auxiliary functions and objects
67 # Auxiliary functions and objects
68
68
69 # See the messaging spec for the definition of all these fields. This list
69 # See the messaging spec for the definition of all these fields. This list
70 # effectively defines the order of display
70 # effectively defines the order of display
71 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
71 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
72 'length', 'file', 'definition', 'docstring', 'source',
72 'length', 'file', 'definition', 'docstring', 'source',
73 'init_definition', 'class_docstring', 'init_docstring',
73 'init_definition', 'class_docstring', 'init_docstring',
74 'call_def', 'call_docstring',
74 'call_def', 'call_docstring',
75 # These won't be printed but will be used to determine how to
75 # These won't be printed but will be used to determine how to
76 # format the object
76 # format the object
77 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
77 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
78 ]
78 ]
79
79
80
80
81 def object_info(**kw):
81 def object_info(**kw):
82 """Make an object info dict with all fields present."""
82 """Make an object info dict with all fields present."""
83 infodict = dict(zip_longest(info_fields, [None]))
83 infodict = dict(zip_longest(info_fields, [None]))
84 infodict.update(kw)
84 infodict.update(kw)
85 return infodict
85 return infodict
86
86
87
87
88 def get_encoding(obj):
88 def get_encoding(obj):
89 """Get encoding for python source file defining obj
89 """Get encoding for python source file defining obj
90
90
91 Returns None if obj is not defined in a sourcefile.
91 Returns None if obj is not defined in a sourcefile.
92 """
92 """
93 ofile = find_file(obj)
93 ofile = find_file(obj)
94 # run contents of file through pager starting at line where the object
94 # run contents of file through pager starting at line where the object
95 # is defined, as long as the file isn't binary and is actually on the
95 # is defined, as long as the file isn't binary and is actually on the
96 # filesystem.
96 # filesystem.
97 if ofile is None:
97 if ofile is None:
98 return None
98 return None
99 elif ofile.endswith(('.so', '.dll', '.pyd')):
99 elif ofile.endswith(('.so', '.dll', '.pyd')):
100 return None
100 return None
101 elif not os.path.isfile(ofile):
101 elif not os.path.isfile(ofile):
102 return None
102 return None
103 else:
103 else:
104 # Print only text files, not extension binaries. Note that
104 # Print only text files, not extension binaries. Note that
105 # getsourcelines returns lineno with 1-offset and page() uses
105 # getsourcelines returns lineno with 1-offset and page() uses
106 # 0-offset, so we must adjust.
106 # 0-offset, so we must adjust.
107 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
107 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
108 encoding, lines = openpy.detect_encoding(buffer.readline)
108 encoding, lines = openpy.detect_encoding(buffer.readline)
109 return encoding
109 return encoding
110
110
111 def getdoc(obj):
111 def getdoc(obj):
112 """Stable wrapper around inspect.getdoc.
112 """Stable wrapper around inspect.getdoc.
113
113
114 This can't crash because of attribute problems.
114 This can't crash because of attribute problems.
115
115
116 It also attempts to call a getdoc() method on the given object. This
116 It also attempts to call a getdoc() method on the given object. This
117 allows objects which provide their docstrings via non-standard mechanisms
117 allows objects which provide their docstrings via non-standard mechanisms
118 (like Pyro proxies) to still be inspected by ipython's ? system.
118 (like Pyro proxies) to still be inspected by ipython's ? system.
119 """
119 """
120 # Allow objects to offer customized documentation via a getdoc method:
120 # Allow objects to offer customized documentation via a getdoc method:
121 try:
121 try:
122 ds = obj.getdoc()
122 ds = obj.getdoc()
123 except Exception:
123 except Exception:
124 pass
124 pass
125 else:
125 else:
126 # if we get extra info, we add it to the normal docstring.
126 # if we get extra info, we add it to the normal docstring.
127 if isinstance(ds, string_types):
127 if isinstance(ds, str):
128 return inspect.cleandoc(ds)
128 return inspect.cleandoc(ds)
129 try:
129 try:
130 docstr = inspect.getdoc(obj)
130 docstr = inspect.getdoc(obj)
131 encoding = get_encoding(obj)
131 encoding = get_encoding(obj)
132 return py3compat.cast_unicode(docstr, encoding=encoding)
132 return py3compat.cast_unicode(docstr, encoding=encoding)
133 except Exception:
133 except Exception:
134 # Harden against an inspect failure, which can occur with
134 # Harden against an inspect failure, which can occur with
135 # extensions modules.
135 # extensions modules.
136 raise
136 raise
137 return None
137 return None
138
138
139
139
140 def getsource(obj, oname=''):
140 def getsource(obj, oname=''):
141 """Wrapper around inspect.getsource.
141 """Wrapper around inspect.getsource.
142
142
143 This can be modified by other projects to provide customized source
143 This can be modified by other projects to provide customized source
144 extraction.
144 extraction.
145
145
146 Parameters
146 Parameters
147 ----------
147 ----------
148 obj : object
148 obj : object
149 an object whose source code we will attempt to extract
149 an object whose source code we will attempt to extract
150 oname : str
150 oname : str
151 (optional) a name under which the object is known
151 (optional) a name under which the object is known
152
152
153 Returns
153 Returns
154 -------
154 -------
155 src : unicode or None
155 src : unicode or None
156
156
157 """
157 """
158
158
159 if isinstance(obj, property):
159 if isinstance(obj, property):
160 sources = []
160 sources = []
161 for attrname in ['fget', 'fset', 'fdel']:
161 for attrname in ['fget', 'fset', 'fdel']:
162 fn = getattr(obj, attrname)
162 fn = getattr(obj, attrname)
163 if fn is not None:
163 if fn is not None:
164 encoding = get_encoding(fn)
164 encoding = get_encoding(fn)
165 oname_prefix = ('%s.' % oname) if oname else ''
165 oname_prefix = ('%s.' % oname) if oname else ''
166 sources.append(cast_unicode(
166 sources.append(cast_unicode(
167 ''.join(('# ', oname_prefix, attrname)),
167 ''.join(('# ', oname_prefix, attrname)),
168 encoding=encoding))
168 encoding=encoding))
169 if inspect.isfunction(fn):
169 if inspect.isfunction(fn):
170 sources.append(dedent(getsource(fn)))
170 sources.append(dedent(getsource(fn)))
171 else:
171 else:
172 # Default str/repr only prints function name,
172 # Default str/repr only prints function name,
173 # pretty.pretty prints module name too.
173 # pretty.pretty prints module name too.
174 sources.append(cast_unicode(
174 sources.append(cast_unicode(
175 '%s%s = %s\n' % (
175 '%s%s = %s\n' % (
176 oname_prefix, attrname, pretty(fn)),
176 oname_prefix, attrname, pretty(fn)),
177 encoding=encoding))
177 encoding=encoding))
178 if sources:
178 if sources:
179 return '\n'.join(sources)
179 return '\n'.join(sources)
180 else:
180 else:
181 return None
181 return None
182
182
183 else:
183 else:
184 # Get source for non-property objects.
184 # Get source for non-property objects.
185
185
186 obj = _get_wrapped(obj)
186 obj = _get_wrapped(obj)
187
187
188 try:
188 try:
189 src = inspect.getsource(obj)
189 src = inspect.getsource(obj)
190 except TypeError:
190 except TypeError:
191 # The object itself provided no meaningful source, try looking for
191 # The object itself provided no meaningful source, try looking for
192 # its class definition instead.
192 # its class definition instead.
193 if hasattr(obj, '__class__'):
193 if hasattr(obj, '__class__'):
194 try:
194 try:
195 src = inspect.getsource(obj.__class__)
195 src = inspect.getsource(obj.__class__)
196 except TypeError:
196 except TypeError:
197 return None
197 return None
198
198
199 encoding = get_encoding(obj)
199 encoding = get_encoding(obj)
200 return cast_unicode(src, encoding=encoding)
200 return cast_unicode(src, encoding=encoding)
201
201
202
202
203 def is_simple_callable(obj):
203 def is_simple_callable(obj):
204 """True if obj is a function ()"""
204 """True if obj is a function ()"""
205 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
205 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
206 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
206 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
207
207
208
208
209 def getargspec(obj):
209 def getargspec(obj):
210 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
210 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
211 :func:inspect.getargspec` on Python 2.
211 :func:inspect.getargspec` on Python 2.
212
212
213 In addition to functions and methods, this can also handle objects with a
213 In addition to functions and methods, this can also handle objects with a
214 ``__call__`` attribute.
214 ``__call__`` attribute.
215 """
215 """
216 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
216 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
217 obj = obj.__call__
217 obj = obj.__call__
218
218
219 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
219 return inspect.getfullargspec(obj) if PY3 else inspect.getargspec(obj)
220
220
221
221
222 def format_argspec(argspec):
222 def format_argspec(argspec):
223 """Format argspect, convenience wrapper around inspect's.
223 """Format argspect, convenience wrapper around inspect's.
224
224
225 This takes a dict instead of ordered arguments and calls
225 This takes a dict instead of ordered arguments and calls
226 inspect.format_argspec with the arguments in the necessary order.
226 inspect.format_argspec with the arguments in the necessary order.
227 """
227 """
228 return inspect.formatargspec(argspec['args'], argspec['varargs'],
228 return inspect.formatargspec(argspec['args'], argspec['varargs'],
229 argspec['varkw'], argspec['defaults'])
229 argspec['varkw'], argspec['defaults'])
230
230
231 @undoc
231 @undoc
232 def call_tip(oinfo, format_call=True):
232 def call_tip(oinfo, format_call=True):
233 """DEPRECATED. Extract call tip data from an oinfo dict.
233 """DEPRECATED. Extract call tip data from an oinfo dict.
234 """
234 """
235 warnings.warn('`call_tip` function is deprecated as of IPython 6.0'
235 warnings.warn('`call_tip` function is deprecated as of IPython 6.0'
236 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
236 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
237 # Get call definition
237 # Get call definition
238 argspec = oinfo.get('argspec')
238 argspec = oinfo.get('argspec')
239 if argspec is None:
239 if argspec is None:
240 call_line = None
240 call_line = None
241 else:
241 else:
242 # Callable objects will have 'self' as their first argument, prune
242 # Callable objects will have 'self' as their first argument, prune
243 # it out if it's there for clarity (since users do *not* pass an
243 # it out if it's there for clarity (since users do *not* pass an
244 # extra first argument explicitly).
244 # extra first argument explicitly).
245 try:
245 try:
246 has_self = argspec['args'][0] == 'self'
246 has_self = argspec['args'][0] == 'self'
247 except (KeyError, IndexError):
247 except (KeyError, IndexError):
248 pass
248 pass
249 else:
249 else:
250 if has_self:
250 if has_self:
251 argspec['args'] = argspec['args'][1:]
251 argspec['args'] = argspec['args'][1:]
252
252
253 call_line = oinfo['name']+format_argspec(argspec)
253 call_line = oinfo['name']+format_argspec(argspec)
254
254
255 # Now get docstring.
255 # Now get docstring.
256 # The priority is: call docstring, constructor docstring, main one.
256 # The priority is: call docstring, constructor docstring, main one.
257 doc = oinfo.get('call_docstring')
257 doc = oinfo.get('call_docstring')
258 if doc is None:
258 if doc is None:
259 doc = oinfo.get('init_docstring')
259 doc = oinfo.get('init_docstring')
260 if doc is None:
260 if doc is None:
261 doc = oinfo.get('docstring','')
261 doc = oinfo.get('docstring','')
262
262
263 return call_line, doc
263 return call_line, doc
264
264
265
265
266 def _get_wrapped(obj):
266 def _get_wrapped(obj):
267 """Get the original object if wrapped in one or more @decorators
267 """Get the original object if wrapped in one or more @decorators
268
268
269 Some objects automatically construct similar objects on any unrecognised
269 Some objects automatically construct similar objects on any unrecognised
270 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
270 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
271 this will arbitrarily cut off after 100 levels of obj.__wrapped__
271 this will arbitrarily cut off after 100 levels of obj.__wrapped__
272 attribute access. --TK, Jan 2016
272 attribute access. --TK, Jan 2016
273 """
273 """
274 orig_obj = obj
274 orig_obj = obj
275 i = 0
275 i = 0
276 while safe_hasattr(obj, '__wrapped__'):
276 while safe_hasattr(obj, '__wrapped__'):
277 obj = obj.__wrapped__
277 obj = obj.__wrapped__
278 i += 1
278 i += 1
279 if i > 100:
279 if i > 100:
280 # __wrapped__ is probably a lie, so return the thing we started with
280 # __wrapped__ is probably a lie, so return the thing we started with
281 return orig_obj
281 return orig_obj
282 return obj
282 return obj
283
283
284 def find_file(obj):
284 def find_file(obj):
285 """Find the absolute path to the file where an object was defined.
285 """Find the absolute path to the file where an object was defined.
286
286
287 This is essentially a robust wrapper around `inspect.getabsfile`.
287 This is essentially a robust wrapper around `inspect.getabsfile`.
288
288
289 Returns None if no file can be found.
289 Returns None if no file can be found.
290
290
291 Parameters
291 Parameters
292 ----------
292 ----------
293 obj : any Python object
293 obj : any Python object
294
294
295 Returns
295 Returns
296 -------
296 -------
297 fname : str
297 fname : str
298 The absolute path to the file where the object was defined.
298 The absolute path to the file where the object was defined.
299 """
299 """
300 obj = _get_wrapped(obj)
300 obj = _get_wrapped(obj)
301
301
302 fname = None
302 fname = None
303 try:
303 try:
304 fname = inspect.getabsfile(obj)
304 fname = inspect.getabsfile(obj)
305 except TypeError:
305 except TypeError:
306 # For an instance, the file that matters is where its class was
306 # For an instance, the file that matters is where its class was
307 # declared.
307 # declared.
308 if hasattr(obj, '__class__'):
308 if hasattr(obj, '__class__'):
309 try:
309 try:
310 fname = inspect.getabsfile(obj.__class__)
310 fname = inspect.getabsfile(obj.__class__)
311 except TypeError:
311 except TypeError:
312 # Can happen for builtins
312 # Can happen for builtins
313 pass
313 pass
314 except:
314 except:
315 pass
315 pass
316 return cast_unicode(fname)
316 return cast_unicode(fname)
317
317
318
318
319 def find_source_lines(obj):
319 def find_source_lines(obj):
320 """Find the line number in a file where an object was defined.
320 """Find the line number in a file where an object was defined.
321
321
322 This is essentially a robust wrapper around `inspect.getsourcelines`.
322 This is essentially a robust wrapper around `inspect.getsourcelines`.
323
323
324 Returns None if no file can be found.
324 Returns None if no file can be found.
325
325
326 Parameters
326 Parameters
327 ----------
327 ----------
328 obj : any Python object
328 obj : any Python object
329
329
330 Returns
330 Returns
331 -------
331 -------
332 lineno : int
332 lineno : int
333 The line number where the object definition starts.
333 The line number where the object definition starts.
334 """
334 """
335 obj = _get_wrapped(obj)
335 obj = _get_wrapped(obj)
336
336
337 try:
337 try:
338 try:
338 try:
339 lineno = inspect.getsourcelines(obj)[1]
339 lineno = inspect.getsourcelines(obj)[1]
340 except TypeError:
340 except TypeError:
341 # For instances, try the class object like getsource() does
341 # For instances, try the class object like getsource() does
342 if hasattr(obj, '__class__'):
342 if hasattr(obj, '__class__'):
343 lineno = inspect.getsourcelines(obj.__class__)[1]
343 lineno = inspect.getsourcelines(obj.__class__)[1]
344 else:
344 else:
345 lineno = None
345 lineno = None
346 except:
346 except:
347 return None
347 return None
348
348
349 return lineno
349 return lineno
350
350
351 class Inspector(Colorable):
351 class Inspector(Colorable):
352
352
353 def __init__(self, color_table=InspectColors,
353 def __init__(self, color_table=InspectColors,
354 code_color_table=PyColorize.ANSICodeColors,
354 code_color_table=PyColorize.ANSICodeColors,
355 scheme='NoColor',
355 scheme='NoColor',
356 str_detail_level=0,
356 str_detail_level=0,
357 parent=None, config=None):
357 parent=None, config=None):
358 super(Inspector, self).__init__(parent=parent, config=config)
358 super(Inspector, self).__init__(parent=parent, config=config)
359 self.color_table = color_table
359 self.color_table = color_table
360 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
360 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
361 self.format = self.parser.format
361 self.format = self.parser.format
362 self.str_detail_level = str_detail_level
362 self.str_detail_level = str_detail_level
363 self.set_active_scheme(scheme)
363 self.set_active_scheme(scheme)
364
364
365 def _getdef(self,obj,oname=''):
365 def _getdef(self,obj,oname=''):
366 """Return the call signature for any callable object.
366 """Return the call signature for any callable object.
367
367
368 If any exception is generated, None is returned instead and the
368 If any exception is generated, None is returned instead and the
369 exception is suppressed."""
369 exception is suppressed."""
370 try:
370 try:
371 hdef = oname + str(signature(obj))
371 hdef = oname + str(signature(obj))
372 return cast_unicode(hdef)
372 return cast_unicode(hdef)
373 except:
373 except:
374 return None
374 return None
375
375
376 def __head(self,h):
376 def __head(self,h):
377 """Return a header string with proper colors."""
377 """Return a header string with proper colors."""
378 return '%s%s%s' % (self.color_table.active_colors.header,h,
378 return '%s%s%s' % (self.color_table.active_colors.header,h,
379 self.color_table.active_colors.normal)
379 self.color_table.active_colors.normal)
380
380
381 def set_active_scheme(self, scheme):
381 def set_active_scheme(self, scheme):
382 self.color_table.set_active_scheme(scheme)
382 self.color_table.set_active_scheme(scheme)
383 self.parser.color_table.set_active_scheme(scheme)
383 self.parser.color_table.set_active_scheme(scheme)
384
384
385 def noinfo(self, msg, oname):
385 def noinfo(self, msg, oname):
386 """Generic message when no information is found."""
386 """Generic message when no information is found."""
387 print('No %s found' % msg, end=' ')
387 print('No %s found' % msg, end=' ')
388 if oname:
388 if oname:
389 print('for %s' % oname)
389 print('for %s' % oname)
390 else:
390 else:
391 print()
391 print()
392
392
393 def pdef(self, obj, oname=''):
393 def pdef(self, obj, oname=''):
394 """Print the call signature for any callable object.
394 """Print the call signature for any callable object.
395
395
396 If the object is a class, print the constructor information."""
396 If the object is a class, print the constructor information."""
397
397
398 if not callable(obj):
398 if not callable(obj):
399 print('Object is not callable.')
399 print('Object is not callable.')
400 return
400 return
401
401
402 header = ''
402 header = ''
403
403
404 if inspect.isclass(obj):
404 if inspect.isclass(obj):
405 header = self.__head('Class constructor information:\n')
405 header = self.__head('Class constructor information:\n')
406 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
406 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
407 obj = obj.__call__
407 obj = obj.__call__
408
408
409 output = self._getdef(obj,oname)
409 output = self._getdef(obj,oname)
410 if output is None:
410 if output is None:
411 self.noinfo('definition header',oname)
411 self.noinfo('definition header',oname)
412 else:
412 else:
413 print(header,self.format(output), end=' ')
413 print(header,self.format(output), end=' ')
414
414
415 # In Python 3, all classes are new-style, so they all have __init__.
415 # In Python 3, all classes are new-style, so they all have __init__.
416 @skip_doctest
416 @skip_doctest
417 def pdoc(self, obj, oname='', formatter=None):
417 def pdoc(self, obj, oname='', formatter=None):
418 """Print the docstring for any object.
418 """Print the docstring for any object.
419
419
420 Optional:
420 Optional:
421 -formatter: a function to run the docstring through for specially
421 -formatter: a function to run the docstring through for specially
422 formatted docstrings.
422 formatted docstrings.
423
423
424 Examples
424 Examples
425 --------
425 --------
426
426
427 In [1]: class NoInit:
427 In [1]: class NoInit:
428 ...: pass
428 ...: pass
429
429
430 In [2]: class NoDoc:
430 In [2]: class NoDoc:
431 ...: def __init__(self):
431 ...: def __init__(self):
432 ...: pass
432 ...: pass
433
433
434 In [3]: %pdoc NoDoc
434 In [3]: %pdoc NoDoc
435 No documentation found for NoDoc
435 No documentation found for NoDoc
436
436
437 In [4]: %pdoc NoInit
437 In [4]: %pdoc NoInit
438 No documentation found for NoInit
438 No documentation found for NoInit
439
439
440 In [5]: obj = NoInit()
440 In [5]: obj = NoInit()
441
441
442 In [6]: %pdoc obj
442 In [6]: %pdoc obj
443 No documentation found for obj
443 No documentation found for obj
444
444
445 In [5]: obj2 = NoDoc()
445 In [5]: obj2 = NoDoc()
446
446
447 In [6]: %pdoc obj2
447 In [6]: %pdoc obj2
448 No documentation found for obj2
448 No documentation found for obj2
449 """
449 """
450
450
451 head = self.__head # For convenience
451 head = self.__head # For convenience
452 lines = []
452 lines = []
453 ds = getdoc(obj)
453 ds = getdoc(obj)
454 if formatter:
454 if formatter:
455 ds = formatter(ds).get('plain/text', ds)
455 ds = formatter(ds).get('plain/text', ds)
456 if ds:
456 if ds:
457 lines.append(head("Class docstring:"))
457 lines.append(head("Class docstring:"))
458 lines.append(indent(ds))
458 lines.append(indent(ds))
459 if inspect.isclass(obj) and hasattr(obj, '__init__'):
459 if inspect.isclass(obj) and hasattr(obj, '__init__'):
460 init_ds = getdoc(obj.__init__)
460 init_ds = getdoc(obj.__init__)
461 if init_ds is not None:
461 if init_ds is not None:
462 lines.append(head("Init docstring:"))
462 lines.append(head("Init docstring:"))
463 lines.append(indent(init_ds))
463 lines.append(indent(init_ds))
464 elif hasattr(obj,'__call__'):
464 elif hasattr(obj,'__call__'):
465 call_ds = getdoc(obj.__call__)
465 call_ds = getdoc(obj.__call__)
466 if call_ds:
466 if call_ds:
467 lines.append(head("Call docstring:"))
467 lines.append(head("Call docstring:"))
468 lines.append(indent(call_ds))
468 lines.append(indent(call_ds))
469
469
470 if not lines:
470 if not lines:
471 self.noinfo('documentation',oname)
471 self.noinfo('documentation',oname)
472 else:
472 else:
473 page.page('\n'.join(lines))
473 page.page('\n'.join(lines))
474
474
475 def psource(self, obj, oname=''):
475 def psource(self, obj, oname=''):
476 """Print the source code for an object."""
476 """Print the source code for an object."""
477
477
478 # Flush the source cache because inspect can return out-of-date source
478 # Flush the source cache because inspect can return out-of-date source
479 linecache.checkcache()
479 linecache.checkcache()
480 try:
480 try:
481 src = getsource(obj, oname=oname)
481 src = getsource(obj, oname=oname)
482 except Exception:
482 except Exception:
483 src = None
483 src = None
484
484
485 if src is None:
485 if src is None:
486 self.noinfo('source', oname)
486 self.noinfo('source', oname)
487 else:
487 else:
488 page.page(self.format(src))
488 page.page(self.format(src))
489
489
490 def pfile(self, obj, oname=''):
490 def pfile(self, obj, oname=''):
491 """Show the whole file where an object was defined."""
491 """Show the whole file where an object was defined."""
492
492
493 lineno = find_source_lines(obj)
493 lineno = find_source_lines(obj)
494 if lineno is None:
494 if lineno is None:
495 self.noinfo('file', oname)
495 self.noinfo('file', oname)
496 return
496 return
497
497
498 ofile = find_file(obj)
498 ofile = find_file(obj)
499 # run contents of file through pager starting at line where the object
499 # run contents of file through pager starting at line where the object
500 # is defined, as long as the file isn't binary and is actually on the
500 # is defined, as long as the file isn't binary and is actually on the
501 # filesystem.
501 # filesystem.
502 if ofile.endswith(('.so', '.dll', '.pyd')):
502 if ofile.endswith(('.so', '.dll', '.pyd')):
503 print('File %r is binary, not printing.' % ofile)
503 print('File %r is binary, not printing.' % ofile)
504 elif not os.path.isfile(ofile):
504 elif not os.path.isfile(ofile):
505 print('File %r does not exist, not printing.' % ofile)
505 print('File %r does not exist, not printing.' % ofile)
506 else:
506 else:
507 # Print only text files, not extension binaries. Note that
507 # Print only text files, not extension binaries. Note that
508 # getsourcelines returns lineno with 1-offset and page() uses
508 # getsourcelines returns lineno with 1-offset and page() uses
509 # 0-offset, so we must adjust.
509 # 0-offset, so we must adjust.
510 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
510 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
511
511
512 def _format_fields(self, fields, title_width=0):
512 def _format_fields(self, fields, title_width=0):
513 """Formats a list of fields for display.
513 """Formats a list of fields for display.
514
514
515 Parameters
515 Parameters
516 ----------
516 ----------
517 fields : list
517 fields : list
518 A list of 2-tuples: (field_title, field_content)
518 A list of 2-tuples: (field_title, field_content)
519 title_width : int
519 title_width : int
520 How many characters to pad titles to. Default to longest title.
520 How many characters to pad titles to. Default to longest title.
521 """
521 """
522 out = []
522 out = []
523 header = self.__head
523 header = self.__head
524 if title_width == 0:
524 if title_width == 0:
525 title_width = max(len(title) + 2 for title, _ in fields)
525 title_width = max(len(title) + 2 for title, _ in fields)
526 for title, content in fields:
526 for title, content in fields:
527 if len(content.splitlines()) > 1:
527 if len(content.splitlines()) > 1:
528 title = header(title + ':') + '\n'
528 title = header(title + ':') + '\n'
529 else:
529 else:
530 title = header((title + ':').ljust(title_width))
530 title = header((title + ':').ljust(title_width))
531 out.append(cast_unicode(title) + cast_unicode(content))
531 out.append(cast_unicode(title) + cast_unicode(content))
532 return "\n".join(out)
532 return "\n".join(out)
533
533
534 def _mime_format(self, text, formatter=None):
534 def _mime_format(self, text, formatter=None):
535 """Return a mime bundle representation of the input text.
535 """Return a mime bundle representation of the input text.
536
536
537 - if `formatter` is None, the returned mime bundle has
537 - if `formatter` is None, the returned mime bundle has
538 a `text/plain` field, with the input text.
538 a `text/plain` field, with the input text.
539 a `text/html` field with a `<pre>` tag containing the input text.
539 a `text/html` field with a `<pre>` tag containing the input text.
540
540
541 - if `formatter` is not None, it must be a callable transforming the
541 - if `formatter` is not None, it must be a callable transforming the
542 input text into a mime bundle. Default values for `text/plain` and
542 input text into a mime bundle. Default values for `text/plain` and
543 `text/html` representations are the ones described above.
543 `text/html` representations are the ones described above.
544
544
545 Note:
545 Note:
546
546
547 Formatters returning strings are supported but this behavior is deprecated.
547 Formatters returning strings are supported but this behavior is deprecated.
548
548
549 """
549 """
550 text = cast_unicode(text)
550 text = cast_unicode(text)
551 defaults = {
551 defaults = {
552 'text/plain': text,
552 'text/plain': text,
553 'text/html': '<pre>' + text + '</pre>'
553 'text/html': '<pre>' + text + '</pre>'
554 }
554 }
555
555
556 if formatter is None:
556 if formatter is None:
557 return defaults
557 return defaults
558 else:
558 else:
559 formatted = formatter(text)
559 formatted = formatter(text)
560
560
561 if not isinstance(formatted, dict):
561 if not isinstance(formatted, dict):
562 # Handle the deprecated behavior of a formatter returning
562 # Handle the deprecated behavior of a formatter returning
563 # a string instead of a mime bundle.
563 # a string instead of a mime bundle.
564 return {
564 return {
565 'text/plain': formatted,
565 'text/plain': formatted,
566 'text/html': '<pre>' + formatted + '</pre>'
566 'text/html': '<pre>' + formatted + '</pre>'
567 }
567 }
568
568
569 else:
569 else:
570 return dict(defaults, **formatted)
570 return dict(defaults, **formatted)
571
571
572
572
573 def format_mime(self, bundle):
573 def format_mime(self, bundle):
574
574
575 text_plain = bundle['text/plain']
575 text_plain = bundle['text/plain']
576
576
577 text = ''
577 text = ''
578 heads, bodies = list(zip(*text_plain))
578 heads, bodies = list(zip(*text_plain))
579 _len = max(len(h) for h in heads)
579 _len = max(len(h) for h in heads)
580
580
581 for head, body in zip(heads, bodies):
581 for head, body in zip(heads, bodies):
582 body = body.strip('\n')
582 body = body.strip('\n')
583 delim = '\n' if '\n' in body else ' '
583 delim = '\n' if '\n' in body else ' '
584 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
584 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
585
585
586 bundle['text/plain'] = text
586 bundle['text/plain'] = text
587 return bundle
587 return bundle
588
588
589 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
589 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
590 """Retrieve an info dict and format it."""
590 """Retrieve an info dict and format it."""
591
591
592 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
592 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
593
593
594 _mime = {
594 _mime = {
595 'text/plain': [],
595 'text/plain': [],
596 'text/html': '',
596 'text/html': '',
597 }
597 }
598
598
599 def append_field(bundle, title, key, formatter=None):
599 def append_field(bundle, title, key, formatter=None):
600 field = info[key]
600 field = info[key]
601 if field is not None:
601 if field is not None:
602 formatted_field = self._mime_format(field, formatter)
602 formatted_field = self._mime_format(field, formatter)
603 bundle['text/plain'].append((title, formatted_field['text/plain']))
603 bundle['text/plain'].append((title, formatted_field['text/plain']))
604 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
604 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
605
605
606 def code_formatter(text):
606 def code_formatter(text):
607 return {
607 return {
608 'text/plain': self.format(text),
608 'text/plain': self.format(text),
609 'text/html': pylight(text)
609 'text/html': pylight(text)
610 }
610 }
611
611
612 if info['isalias']:
612 if info['isalias']:
613 append_field(_mime, 'Repr', 'string_form')
613 append_field(_mime, 'Repr', 'string_form')
614
614
615 elif info['ismagic']:
615 elif info['ismagic']:
616 if detail_level > 0:
616 if detail_level > 0:
617 append_field(_mime, 'Source', 'source', code_formatter)
617 append_field(_mime, 'Source', 'source', code_formatter)
618 else:
618 else:
619 append_field(_mime, 'Docstring', 'docstring', formatter)
619 append_field(_mime, 'Docstring', 'docstring', formatter)
620 append_field(_mime, 'File', 'file')
620 append_field(_mime, 'File', 'file')
621
621
622 elif info['isclass'] or is_simple_callable(obj):
622 elif info['isclass'] or is_simple_callable(obj):
623 # Functions, methods, classes
623 # Functions, methods, classes
624 append_field(_mime, 'Signature', 'definition', code_formatter)
624 append_field(_mime, 'Signature', 'definition', code_formatter)
625 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
625 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
626 if detail_level > 0 and info['source']:
626 if detail_level > 0 and info['source']:
627 append_field(_mime, 'Source', 'source', code_formatter)
627 append_field(_mime, 'Source', 'source', code_formatter)
628 else:
628 else:
629 append_field(_mime, 'Docstring', 'docstring', formatter)
629 append_field(_mime, 'Docstring', 'docstring', formatter)
630 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
630 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
631
631
632 append_field(_mime, 'File', 'file')
632 append_field(_mime, 'File', 'file')
633 append_field(_mime, 'Type', 'type_name')
633 append_field(_mime, 'Type', 'type_name')
634
634
635 else:
635 else:
636 # General Python objects
636 # General Python objects
637 append_field(_mime, 'Signature', 'definition', code_formatter)
637 append_field(_mime, 'Signature', 'definition', code_formatter)
638 append_field(_mime, 'Call signature', 'call_def', code_formatter)
638 append_field(_mime, 'Call signature', 'call_def', code_formatter)
639
639
640 append_field(_mime, 'Type', 'type_name')
640 append_field(_mime, 'Type', 'type_name')
641
641
642 # Base class for old-style instances
642 # Base class for old-style instances
643 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
643 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
644 append_field(_mime, 'Base Class', 'base_class')
644 append_field(_mime, 'Base Class', 'base_class')
645
645
646 append_field(_mime, 'String form', 'string_form')
646 append_field(_mime, 'String form', 'string_form')
647
647
648 # Namespace
648 # Namespace
649 if info['namespace'] != 'Interactive':
649 if info['namespace'] != 'Interactive':
650 append_field(_mime, 'Namespace', 'namespace')
650 append_field(_mime, 'Namespace', 'namespace')
651
651
652 append_field(_mime, 'Length', 'length')
652 append_field(_mime, 'Length', 'length')
653 append_field(_mime, 'File', 'file')
653 append_field(_mime, 'File', 'file')
654
654
655 # Source or docstring, depending on detail level and whether
655 # Source or docstring, depending on detail level and whether
656 # source found.
656 # source found.
657 if detail_level > 0:
657 if detail_level > 0:
658 append_field(_mime, 'Source', 'source', code_formatter)
658 append_field(_mime, 'Source', 'source', code_formatter)
659 else:
659 else:
660 append_field(_mime, 'Docstring', 'docstring', formatter)
660 append_field(_mime, 'Docstring', 'docstring', formatter)
661
661
662 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
662 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
663 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
663 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
664 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
664 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
665
665
666
666
667 return self.format_mime(_mime)
667 return self.format_mime(_mime)
668
668
669 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
669 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
670 """Show detailed information about an object.
670 """Show detailed information about an object.
671
671
672 Optional arguments:
672 Optional arguments:
673
673
674 - oname: name of the variable pointing to the object.
674 - oname: name of the variable pointing to the object.
675
675
676 - formatter: callable (optional)
676 - formatter: callable (optional)
677 A special formatter for docstrings.
677 A special formatter for docstrings.
678
678
679 The formatter is a callable that takes a string as an input
679 The formatter is a callable that takes a string as an input
680 and returns either a formatted string or a mime type bundle
680 and returns either a formatted string or a mime type bundle
681 in the form of a dictionnary.
681 in the form of a dictionnary.
682
682
683 Although the support of custom formatter returning a string
683 Although the support of custom formatter returning a string
684 instead of a mime type bundle is deprecated.
684 instead of a mime type bundle is deprecated.
685
685
686 - info: a structure with some information fields which may have been
686 - info: a structure with some information fields which may have been
687 precomputed already.
687 precomputed already.
688
688
689 - detail_level: if set to 1, more information is given.
689 - detail_level: if set to 1, more information is given.
690 """
690 """
691 info = self._get_info(obj, oname, formatter, info, detail_level)
691 info = self._get_info(obj, oname, formatter, info, detail_level)
692 if not enable_html_pager:
692 if not enable_html_pager:
693 del info['text/html']
693 del info['text/html']
694 page.page(info)
694 page.page(info)
695
695
696 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
696 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
697 """DEPRECATED. Compute a dict with detailed information about an object.
697 """DEPRECATED. Compute a dict with detailed information about an object.
698 """
698 """
699 if formatter is not None:
699 if formatter is not None:
700 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
700 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
701 'is deprecated as of IPython 5.0 and will have no effects.',
701 'is deprecated as of IPython 5.0 and will have no effects.',
702 DeprecationWarning, stacklevel=2)
702 DeprecationWarning, stacklevel=2)
703 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
703 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
704
704
705 def _info(self, obj, oname='', info=None, detail_level=0):
705 def _info(self, obj, oname='', info=None, detail_level=0):
706 """Compute a dict with detailed information about an object.
706 """Compute a dict with detailed information about an object.
707
707
708 Optional arguments:
708 Optional arguments:
709
709
710 - oname: name of the variable pointing to the object.
710 - oname: name of the variable pointing to the object.
711
711
712 - info: a structure with some information fields which may have been
712 - info: a structure with some information fields which may have been
713 precomputed already.
713 precomputed already.
714
714
715 - detail_level: if set to 1, more information is given.
715 - detail_level: if set to 1, more information is given.
716 """
716 """
717
717
718 obj_type = type(obj)
718 obj_type = type(obj)
719
719
720 if info is None:
720 if info is None:
721 ismagic = 0
721 ismagic = 0
722 isalias = 0
722 isalias = 0
723 ospace = ''
723 ospace = ''
724 else:
724 else:
725 ismagic = info.ismagic
725 ismagic = info.ismagic
726 isalias = info.isalias
726 isalias = info.isalias
727 ospace = info.namespace
727 ospace = info.namespace
728
728
729 # Get docstring, special-casing aliases:
729 # Get docstring, special-casing aliases:
730 if isalias:
730 if isalias:
731 if not callable(obj):
731 if not callable(obj):
732 try:
732 try:
733 ds = "Alias to the system command:\n %s" % obj[1]
733 ds = "Alias to the system command:\n %s" % obj[1]
734 except:
734 except:
735 ds = "Alias: " + str(obj)
735 ds = "Alias: " + str(obj)
736 else:
736 else:
737 ds = "Alias to " + str(obj)
737 ds = "Alias to " + str(obj)
738 if obj.__doc__:
738 if obj.__doc__:
739 ds += "\nDocstring:\n" + obj.__doc__
739 ds += "\nDocstring:\n" + obj.__doc__
740 else:
740 else:
741 ds = getdoc(obj)
741 ds = getdoc(obj)
742 if ds is None:
742 if ds is None:
743 ds = '<no docstring>'
743 ds = '<no docstring>'
744
744
745 # store output in a dict, we initialize it here and fill it as we go
745 # store output in a dict, we initialize it here and fill it as we go
746 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
746 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
747
747
748 string_max = 200 # max size of strings to show (snipped if longer)
748 string_max = 200 # max size of strings to show (snipped if longer)
749 shalf = int((string_max - 5) / 2)
749 shalf = int((string_max - 5) / 2)
750
750
751 if ismagic:
751 if ismagic:
752 obj_type_name = 'Magic function'
752 obj_type_name = 'Magic function'
753 elif isalias:
753 elif isalias:
754 obj_type_name = 'System alias'
754 obj_type_name = 'System alias'
755 else:
755 else:
756 obj_type_name = obj_type.__name__
756 obj_type_name = obj_type.__name__
757 out['type_name'] = obj_type_name
757 out['type_name'] = obj_type_name
758
758
759 try:
759 try:
760 bclass = obj.__class__
760 bclass = obj.__class__
761 out['base_class'] = str(bclass)
761 out['base_class'] = str(bclass)
762 except: pass
762 except: pass
763
763
764 # String form, but snip if too long in ? form (full in ??)
764 # String form, but snip if too long in ? form (full in ??)
765 if detail_level >= self.str_detail_level:
765 if detail_level >= self.str_detail_level:
766 try:
766 try:
767 ostr = str(obj)
767 ostr = str(obj)
768 str_head = 'string_form'
768 str_head = 'string_form'
769 if not detail_level and len(ostr)>string_max:
769 if not detail_level and len(ostr)>string_max:
770 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
770 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
771 ostr = ("\n" + " " * len(str_head.expandtabs())).\
771 ostr = ("\n" + " " * len(str_head.expandtabs())).\
772 join(q.strip() for q in ostr.split("\n"))
772 join(q.strip() for q in ostr.split("\n"))
773 out[str_head] = ostr
773 out[str_head] = ostr
774 except:
774 except:
775 pass
775 pass
776
776
777 if ospace:
777 if ospace:
778 out['namespace'] = ospace
778 out['namespace'] = ospace
779
779
780 # Length (for strings and lists)
780 # Length (for strings and lists)
781 try:
781 try:
782 out['length'] = str(len(obj))
782 out['length'] = str(len(obj))
783 except: pass
783 except: pass
784
784
785 # Filename where object was defined
785 # Filename where object was defined
786 binary_file = False
786 binary_file = False
787 fname = find_file(obj)
787 fname = find_file(obj)
788 if fname is None:
788 if fname is None:
789 # if anything goes wrong, we don't want to show source, so it's as
789 # if anything goes wrong, we don't want to show source, so it's as
790 # if the file was binary
790 # if the file was binary
791 binary_file = True
791 binary_file = True
792 else:
792 else:
793 if fname.endswith(('.so', '.dll', '.pyd')):
793 if fname.endswith(('.so', '.dll', '.pyd')):
794 binary_file = True
794 binary_file = True
795 elif fname.endswith('<string>'):
795 elif fname.endswith('<string>'):
796 fname = 'Dynamically generated function. No source code available.'
796 fname = 'Dynamically generated function. No source code available.'
797 out['file'] = compress_user(fname)
797 out['file'] = compress_user(fname)
798
798
799 # Original source code for a callable, class or property.
799 # Original source code for a callable, class or property.
800 if detail_level:
800 if detail_level:
801 # Flush the source cache because inspect can return out-of-date
801 # Flush the source cache because inspect can return out-of-date
802 # source
802 # source
803 linecache.checkcache()
803 linecache.checkcache()
804 try:
804 try:
805 if isinstance(obj, property) or not binary_file:
805 if isinstance(obj, property) or not binary_file:
806 src = getsource(obj, oname)
806 src = getsource(obj, oname)
807 if src is not None:
807 if src is not None:
808 src = src.rstrip()
808 src = src.rstrip()
809 out['source'] = src
809 out['source'] = src
810
810
811 except Exception:
811 except Exception:
812 pass
812 pass
813
813
814 # Add docstring only if no source is to be shown (avoid repetitions).
814 # Add docstring only if no source is to be shown (avoid repetitions).
815 if ds and out.get('source', None) is None:
815 if ds and out.get('source', None) is None:
816 out['docstring'] = ds
816 out['docstring'] = ds
817
817
818 # Constructor docstring for classes
818 # Constructor docstring for classes
819 if inspect.isclass(obj):
819 if inspect.isclass(obj):
820 out['isclass'] = True
820 out['isclass'] = True
821
821
822 # get the init signature:
822 # get the init signature:
823 try:
823 try:
824 init_def = self._getdef(obj, oname)
824 init_def = self._getdef(obj, oname)
825 except AttributeError:
825 except AttributeError:
826 init_def = None
826 init_def = None
827
827
828 # get the __init__ docstring
828 # get the __init__ docstring
829 try:
829 try:
830 obj_init = obj.__init__
830 obj_init = obj.__init__
831 except AttributeError:
831 except AttributeError:
832 init_ds = None
832 init_ds = None
833 else:
833 else:
834 if init_def is None:
834 if init_def is None:
835 # Get signature from init if top-level sig failed.
835 # Get signature from init if top-level sig failed.
836 # Can happen for built-in types (list, etc.).
836 # Can happen for built-in types (list, etc.).
837 try:
837 try:
838 init_def = self._getdef(obj_init, oname)
838 init_def = self._getdef(obj_init, oname)
839 except AttributeError:
839 except AttributeError:
840 pass
840 pass
841 init_ds = getdoc(obj_init)
841 init_ds = getdoc(obj_init)
842 # Skip Python's auto-generated docstrings
842 # Skip Python's auto-generated docstrings
843 if init_ds == _object_init_docstring:
843 if init_ds == _object_init_docstring:
844 init_ds = None
844 init_ds = None
845
845
846 if init_def:
846 if init_def:
847 out['init_definition'] = init_def
847 out['init_definition'] = init_def
848
848
849 if init_ds:
849 if init_ds:
850 out['init_docstring'] = init_ds
850 out['init_docstring'] = init_ds
851
851
852 # and class docstring for instances:
852 # and class docstring for instances:
853 else:
853 else:
854 # reconstruct the function definition and print it:
854 # reconstruct the function definition and print it:
855 defln = self._getdef(obj, oname)
855 defln = self._getdef(obj, oname)
856 if defln:
856 if defln:
857 out['definition'] = defln
857 out['definition'] = defln
858
858
859 # First, check whether the instance docstring is identical to the
859 # First, check whether the instance docstring is identical to the
860 # class one, and print it separately if they don't coincide. In
860 # class one, and print it separately if they don't coincide. In
861 # most cases they will, but it's nice to print all the info for
861 # most cases they will, but it's nice to print all the info for
862 # objects which use instance-customized docstrings.
862 # objects which use instance-customized docstrings.
863 if ds:
863 if ds:
864 try:
864 try:
865 cls = getattr(obj,'__class__')
865 cls = getattr(obj,'__class__')
866 except:
866 except:
867 class_ds = None
867 class_ds = None
868 else:
868 else:
869 class_ds = getdoc(cls)
869 class_ds = getdoc(cls)
870 # Skip Python's auto-generated docstrings
870 # Skip Python's auto-generated docstrings
871 if class_ds in _builtin_type_docstrings:
871 if class_ds in _builtin_type_docstrings:
872 class_ds = None
872 class_ds = None
873 if class_ds and ds != class_ds:
873 if class_ds and ds != class_ds:
874 out['class_docstring'] = class_ds
874 out['class_docstring'] = class_ds
875
875
876 # Next, try to show constructor docstrings
876 # Next, try to show constructor docstrings
877 try:
877 try:
878 init_ds = getdoc(obj.__init__)
878 init_ds = getdoc(obj.__init__)
879 # Skip Python's auto-generated docstrings
879 # Skip Python's auto-generated docstrings
880 if init_ds == _object_init_docstring:
880 if init_ds == _object_init_docstring:
881 init_ds = None
881 init_ds = None
882 except AttributeError:
882 except AttributeError:
883 init_ds = None
883 init_ds = None
884 if init_ds:
884 if init_ds:
885 out['init_docstring'] = init_ds
885 out['init_docstring'] = init_ds
886
886
887 # Call form docstring for callable instances
887 # Call form docstring for callable instances
888 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
888 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
889 call_def = self._getdef(obj.__call__, oname)
889 call_def = self._getdef(obj.__call__, oname)
890 if call_def and (call_def != out.get('definition')):
890 if call_def and (call_def != out.get('definition')):
891 # it may never be the case that call def and definition differ,
891 # it may never be the case that call def and definition differ,
892 # but don't include the same signature twice
892 # but don't include the same signature twice
893 out['call_def'] = call_def
893 out['call_def'] = call_def
894 call_ds = getdoc(obj.__call__)
894 call_ds = getdoc(obj.__call__)
895 # Skip Python's auto-generated docstrings
895 # Skip Python's auto-generated docstrings
896 if call_ds == _func_call_docstring:
896 if call_ds == _func_call_docstring:
897 call_ds = None
897 call_ds = None
898 if call_ds:
898 if call_ds:
899 out['call_docstring'] = call_ds
899 out['call_docstring'] = call_ds
900
900
901 # Compute the object's argspec as a callable. The key is to decide
901 # Compute the object's argspec as a callable. The key is to decide
902 # whether to pull it from the object itself, from its __init__ or
902 # whether to pull it from the object itself, from its __init__ or
903 # from its __call__ method.
903 # from its __call__ method.
904
904
905 if inspect.isclass(obj):
905 if inspect.isclass(obj):
906 # Old-style classes need not have an __init__
906 # Old-style classes need not have an __init__
907 callable_obj = getattr(obj, "__init__", None)
907 callable_obj = getattr(obj, "__init__", None)
908 elif callable(obj):
908 elif callable(obj):
909 callable_obj = obj
909 callable_obj = obj
910 else:
910 else:
911 callable_obj = None
911 callable_obj = None
912
912
913 if callable_obj is not None:
913 if callable_obj is not None:
914 try:
914 try:
915 argspec = getargspec(callable_obj)
915 argspec = getargspec(callable_obj)
916 except (TypeError, AttributeError):
916 except (TypeError, AttributeError):
917 # For extensions/builtins we can't retrieve the argspec
917 # For extensions/builtins we can't retrieve the argspec
918 pass
918 pass
919 else:
919 else:
920 # named tuples' _asdict() method returns an OrderedDict, but we
920 # named tuples' _asdict() method returns an OrderedDict, but we
921 # we want a normal
921 # we want a normal
922 out['argspec'] = argspec_dict = dict(argspec._asdict())
922 out['argspec'] = argspec_dict = dict(argspec._asdict())
923 # We called this varkw before argspec became a named tuple.
923 # We called this varkw before argspec became a named tuple.
924 # With getfullargspec it's also called varkw.
924 # With getfullargspec it's also called varkw.
925 if 'varkw' not in argspec_dict:
925 if 'varkw' not in argspec_dict:
926 argspec_dict['varkw'] = argspec_dict.pop('keywords')
926 argspec_dict['varkw'] = argspec_dict.pop('keywords')
927
927
928 return object_info(**out)
928 return object_info(**out)
929
929
930 def psearch(self,pattern,ns_table,ns_search=[],
930 def psearch(self,pattern,ns_table,ns_search=[],
931 ignore_case=False,show_all=False):
931 ignore_case=False,show_all=False):
932 """Search namespaces with wildcards for objects.
932 """Search namespaces with wildcards for objects.
933
933
934 Arguments:
934 Arguments:
935
935
936 - pattern: string containing shell-like wildcards to use in namespace
936 - pattern: string containing shell-like wildcards to use in namespace
937 searches and optionally a type specification to narrow the search to
937 searches and optionally a type specification to narrow the search to
938 objects of that type.
938 objects of that type.
939
939
940 - ns_table: dict of name->namespaces for search.
940 - ns_table: dict of name->namespaces for search.
941
941
942 Optional arguments:
942 Optional arguments:
943
943
944 - ns_search: list of namespace names to include in search.
944 - ns_search: list of namespace names to include in search.
945
945
946 - ignore_case(False): make the search case-insensitive.
946 - ignore_case(False): make the search case-insensitive.
947
947
948 - show_all(False): show all names, including those starting with
948 - show_all(False): show all names, including those starting with
949 underscores.
949 underscores.
950 """
950 """
951 #print 'ps pattern:<%r>' % pattern # dbg
951 #print 'ps pattern:<%r>' % pattern # dbg
952
952
953 # defaults
953 # defaults
954 type_pattern = 'all'
954 type_pattern = 'all'
955 filter = ''
955 filter = ''
956
956
957 cmds = pattern.split()
957 cmds = pattern.split()
958 len_cmds = len(cmds)
958 len_cmds = len(cmds)
959 if len_cmds == 1:
959 if len_cmds == 1:
960 # Only filter pattern given
960 # Only filter pattern given
961 filter = cmds[0]
961 filter = cmds[0]
962 elif len_cmds == 2:
962 elif len_cmds == 2:
963 # Both filter and type specified
963 # Both filter and type specified
964 filter,type_pattern = cmds
964 filter,type_pattern = cmds
965 else:
965 else:
966 raise ValueError('invalid argument string for psearch: <%s>' %
966 raise ValueError('invalid argument string for psearch: <%s>' %
967 pattern)
967 pattern)
968
968
969 # filter search namespaces
969 # filter search namespaces
970 for name in ns_search:
970 for name in ns_search:
971 if name not in ns_table:
971 if name not in ns_table:
972 raise ValueError('invalid namespace <%s>. Valid names: %s' %
972 raise ValueError('invalid namespace <%s>. Valid names: %s' %
973 (name,ns_table.keys()))
973 (name,ns_table.keys()))
974
974
975 #print 'type_pattern:',type_pattern # dbg
975 #print 'type_pattern:',type_pattern # dbg
976 search_result, namespaces_seen = set(), set()
976 search_result, namespaces_seen = set(), set()
977 for ns_name in ns_search:
977 for ns_name in ns_search:
978 ns = ns_table[ns_name]
978 ns = ns_table[ns_name]
979 # Normally, locals and globals are the same, so we just check one.
979 # Normally, locals and globals are the same, so we just check one.
980 if id(ns) in namespaces_seen:
980 if id(ns) in namespaces_seen:
981 continue
981 continue
982 namespaces_seen.add(id(ns))
982 namespaces_seen.add(id(ns))
983 tmp_res = list_namespace(ns, type_pattern, filter,
983 tmp_res = list_namespace(ns, type_pattern, filter,
984 ignore_case=ignore_case, show_all=show_all)
984 ignore_case=ignore_case, show_all=show_all)
985 search_result.update(tmp_res)
985 search_result.update(tmp_res)
986
986
987 page.page('\n'.join(sorted(search_result)))
987 page.page('\n'.join(sorted(search_result)))
@@ -1,313 +1,313 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25
25
26 from traitlets.config.application import Application
26 from traitlets.config.application import Application
27 from IPython.core.application import (
27 from IPython.core.application import (
28 BaseIPythonApplication, base_flags
28 BaseIPythonApplication, base_flags
29 )
29 )
30 from IPython.core.profiledir import ProfileDir
30 from IPython.core.profiledir import ProfileDir
31 from IPython.utils.importstring import import_item
31 from IPython.utils.importstring import import_item
32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
33 from IPython.utils import py3compat
33 from IPython.utils import py3compat
34 from traitlets import Unicode, Bool, Dict, observe
34 from traitlets import Unicode, Bool, Dict, observe
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Constants
37 # Constants
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 create_help = """Create an IPython profile by name
40 create_help = """Create an IPython profile by name
41
41
42 Create an ipython profile directory by its name or
42 Create an ipython profile directory by its name or
43 profile directory path. Profile directories contain
43 profile directory path. Profile directories contain
44 configuration, log and security related files and are named
44 configuration, log and security related files and are named
45 using the convention 'profile_<name>'. By default they are
45 using the convention 'profile_<name>'. By default they are
46 located in your ipython directory. Once created, you will
46 located in your ipython directory. Once created, you will
47 can edit the configuration files in the profile
47 can edit the configuration files in the profile
48 directory to configure IPython. Most users will create a
48 directory to configure IPython. Most users will create a
49 profile directory by name,
49 profile directory by name,
50 `ipython profile create myprofile`, which will put the directory
50 `ipython profile create myprofile`, which will put the directory
51 in `<ipython_dir>/profile_myprofile`.
51 in `<ipython_dir>/profile_myprofile`.
52 """
52 """
53 list_help = """List available IPython profiles
53 list_help = """List available IPython profiles
54
54
55 List all available profiles, by profile location, that can
55 List all available profiles, by profile location, that can
56 be found in the current working directly or in the ipython
56 be found in the current working directly or in the ipython
57 directory. Profile directories are named using the convention
57 directory. Profile directories are named using the convention
58 'profile_<profile>'.
58 'profile_<profile>'.
59 """
59 """
60 profile_help = """Manage IPython profiles
60 profile_help = """Manage IPython profiles
61
61
62 Profile directories contain
62 Profile directories contain
63 configuration, log and security related files and are named
63 configuration, log and security related files and are named
64 using the convention 'profile_<name>'. By default they are
64 using the convention 'profile_<name>'. By default they are
65 located in your ipython directory. You can create profiles
65 located in your ipython directory. You can create profiles
66 with `ipython profile create <name>`, or see the profiles you
66 with `ipython profile create <name>`, or see the profiles you
67 already have with `ipython profile list`
67 already have with `ipython profile list`
68
68
69 To get started configuring IPython, simply do:
69 To get started configuring IPython, simply do:
70
70
71 $> ipython profile create
71 $> ipython profile create
72
72
73 and IPython will create the default profile in <ipython_dir>/profile_default,
73 and IPython will create the default profile in <ipython_dir>/profile_default,
74 where you can edit ipython_config.py to start configuring IPython.
74 where you can edit ipython_config.py to start configuring IPython.
75
75
76 """
76 """
77
77
78 _list_examples = "ipython profile list # list all profiles"
78 _list_examples = "ipython profile list # list all profiles"
79
79
80 _create_examples = """
80 _create_examples = """
81 ipython profile create foo # create profile foo w/ default config files
81 ipython profile create foo # create profile foo w/ default config files
82 ipython profile create foo --reset # restage default config files over current
82 ipython profile create foo --reset # restage default config files over current
83 ipython profile create foo --parallel # also stage parallel config files
83 ipython profile create foo --parallel # also stage parallel config files
84 """
84 """
85
85
86 _main_examples = """
86 _main_examples = """
87 ipython profile create -h # show the help string for the create subcommand
87 ipython profile create -h # show the help string for the create subcommand
88 ipython profile list -h # show the help string for the list subcommand
88 ipython profile list -h # show the help string for the list subcommand
89
89
90 ipython locate profile foo # print the path to the directory for profile 'foo'
90 ipython locate profile foo # print the path to the directory for profile 'foo'
91 """
91 """
92
92
93 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
94 # Profile Application Class (for `ipython profile` subcommand)
94 # Profile Application Class (for `ipython profile` subcommand)
95 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
96
96
97
97
98 def list_profiles_in(path):
98 def list_profiles_in(path):
99 """list profiles in a given root directory"""
99 """list profiles in a given root directory"""
100 files = os.listdir(path)
100 files = os.listdir(path)
101 profiles = []
101 profiles = []
102 for f in files:
102 for f in files:
103 try:
103 try:
104 full_path = os.path.join(path, f)
104 full_path = os.path.join(path, f)
105 except UnicodeError:
105 except UnicodeError:
106 continue
106 continue
107 if os.path.isdir(full_path) and f.startswith('profile_'):
107 if os.path.isdir(full_path) and f.startswith('profile_'):
108 profiles.append(f.split('_',1)[-1])
108 profiles.append(f.split('_',1)[-1])
109 return profiles
109 return profiles
110
110
111
111
112 def list_bundled_profiles():
112 def list_bundled_profiles():
113 """list profiles that are bundled with IPython."""
113 """list profiles that are bundled with IPython."""
114 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
114 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
115 files = os.listdir(path)
115 files = os.listdir(path)
116 profiles = []
116 profiles = []
117 for profile in files:
117 for profile in files:
118 full_path = os.path.join(path, profile)
118 full_path = os.path.join(path, profile)
119 if os.path.isdir(full_path) and profile != "__pycache__":
119 if os.path.isdir(full_path) and profile != "__pycache__":
120 profiles.append(profile)
120 profiles.append(profile)
121 return profiles
121 return profiles
122
122
123
123
124 class ProfileLocate(BaseIPythonApplication):
124 class ProfileLocate(BaseIPythonApplication):
125 description = """print the path to an IPython profile dir"""
125 description = """print the path to an IPython profile dir"""
126
126
127 def parse_command_line(self, argv=None):
127 def parse_command_line(self, argv=None):
128 super(ProfileLocate, self).parse_command_line(argv)
128 super(ProfileLocate, self).parse_command_line(argv)
129 if self.extra_args:
129 if self.extra_args:
130 self.profile = self.extra_args[0]
130 self.profile = self.extra_args[0]
131
131
132 def start(self):
132 def start(self):
133 print(self.profile_dir.location)
133 print(self.profile_dir.location)
134
134
135
135
136 class ProfileList(Application):
136 class ProfileList(Application):
137 name = u'ipython-profile'
137 name = u'ipython-profile'
138 description = list_help
138 description = list_help
139 examples = _list_examples
139 examples = _list_examples
140
140
141 aliases = Dict({
141 aliases = Dict({
142 'ipython-dir' : 'ProfileList.ipython_dir',
142 'ipython-dir' : 'ProfileList.ipython_dir',
143 'log-level' : 'Application.log_level',
143 'log-level' : 'Application.log_level',
144 })
144 })
145 flags = Dict(dict(
145 flags = Dict(dict(
146 debug = ({'Application' : {'log_level' : 0}},
146 debug = ({'Application' : {'log_level' : 0}},
147 "Set Application.log_level to 0, maximizing log output."
147 "Set Application.log_level to 0, maximizing log output."
148 )
148 )
149 ))
149 ))
150
150
151 ipython_dir = Unicode(get_ipython_dir(),
151 ipython_dir = Unicode(get_ipython_dir(),
152 help="""
152 help="""
153 The name of the IPython directory. This directory is used for logging
153 The name of the IPython directory. This directory is used for logging
154 configuration (through profiles), history storage, etc. The default
154 configuration (through profiles), history storage, etc. The default
155 is usually $HOME/.ipython. This options can also be specified through
155 is usually $HOME/.ipython. This options can also be specified through
156 the environment variable IPYTHONDIR.
156 the environment variable IPYTHONDIR.
157 """
157 """
158 ).tag(config=True)
158 ).tag(config=True)
159
159
160
160
161 def _print_profiles(self, profiles):
161 def _print_profiles(self, profiles):
162 """print list of profiles, indented."""
162 """print list of profiles, indented."""
163 for profile in profiles:
163 for profile in profiles:
164 print(' %s' % profile)
164 print(' %s' % profile)
165
165
166 def list_profile_dirs(self):
166 def list_profile_dirs(self):
167 profiles = list_bundled_profiles()
167 profiles = list_bundled_profiles()
168 if profiles:
168 if profiles:
169 print()
169 print()
170 print("Available profiles in IPython:")
170 print("Available profiles in IPython:")
171 self._print_profiles(profiles)
171 self._print_profiles(profiles)
172 print()
172 print()
173 print(" The first request for a bundled profile will copy it")
173 print(" The first request for a bundled profile will copy it")
174 print(" into your IPython directory (%s)," % self.ipython_dir)
174 print(" into your IPython directory (%s)," % self.ipython_dir)
175 print(" where you can customize it.")
175 print(" where you can customize it.")
176
176
177 profiles = list_profiles_in(self.ipython_dir)
177 profiles = list_profiles_in(self.ipython_dir)
178 if profiles:
178 if profiles:
179 print()
179 print()
180 print("Available profiles in %s:" % self.ipython_dir)
180 print("Available profiles in %s:" % self.ipython_dir)
181 self._print_profiles(profiles)
181 self._print_profiles(profiles)
182
182
183 profiles = list_profiles_in(py3compat.getcwd())
183 profiles = list_profiles_in(os.getcwd())
184 if profiles:
184 if profiles:
185 print()
185 print()
186 print("Available profiles in current directory (%s):" % py3compat.getcwd())
186 print("Available profiles in current directory (%s):" % os.getcwd())
187 self._print_profiles(profiles)
187 self._print_profiles(profiles)
188
188
189 print()
189 print()
190 print("To use any of the above profiles, start IPython with:")
190 print("To use any of the above profiles, start IPython with:")
191 print(" ipython --profile=<name>")
191 print(" ipython --profile=<name>")
192 print()
192 print()
193
193
194 def start(self):
194 def start(self):
195 self.list_profile_dirs()
195 self.list_profile_dirs()
196
196
197
197
198 create_flags = {}
198 create_flags = {}
199 create_flags.update(base_flags)
199 create_flags.update(base_flags)
200 # don't include '--init' flag, which implies running profile create in other apps
200 # don't include '--init' flag, which implies running profile create in other apps
201 create_flags.pop('init')
201 create_flags.pop('init')
202 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
202 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 "reset config files in this profile to the defaults.")
203 "reset config files in this profile to the defaults.")
204 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
204 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 "Include the config files for parallel "
205 "Include the config files for parallel "
206 "computing apps (ipengine, ipcontroller, etc.)")
206 "computing apps (ipengine, ipcontroller, etc.)")
207
207
208
208
209 class ProfileCreate(BaseIPythonApplication):
209 class ProfileCreate(BaseIPythonApplication):
210 name = u'ipython-profile'
210 name = u'ipython-profile'
211 description = create_help
211 description = create_help
212 examples = _create_examples
212 examples = _create_examples
213 auto_create = Bool(True)
213 auto_create = Bool(True)
214 def _log_format_default(self):
214 def _log_format_default(self):
215 return "[%(name)s] %(message)s"
215 return "[%(name)s] %(message)s"
216
216
217 def _copy_config_files_default(self):
217 def _copy_config_files_default(self):
218 return True
218 return True
219
219
220 parallel = Bool(False,
220 parallel = Bool(False,
221 help="whether to include parallel computing config files"
221 help="whether to include parallel computing config files"
222 ).tag(config=True)
222 ).tag(config=True)
223
223
224 @observe('parallel')
224 @observe('parallel')
225 def _parallel_changed(self, change):
225 def _parallel_changed(self, change):
226 parallel_files = [ 'ipcontroller_config.py',
226 parallel_files = [ 'ipcontroller_config.py',
227 'ipengine_config.py',
227 'ipengine_config.py',
228 'ipcluster_config.py'
228 'ipcluster_config.py'
229 ]
229 ]
230 if change['new']:
230 if change['new']:
231 for cf in parallel_files:
231 for cf in parallel_files:
232 self.config_files.append(cf)
232 self.config_files.append(cf)
233 else:
233 else:
234 for cf in parallel_files:
234 for cf in parallel_files:
235 if cf in self.config_files:
235 if cf in self.config_files:
236 self.config_files.remove(cf)
236 self.config_files.remove(cf)
237
237
238 def parse_command_line(self, argv):
238 def parse_command_line(self, argv):
239 super(ProfileCreate, self).parse_command_line(argv)
239 super(ProfileCreate, self).parse_command_line(argv)
240 # accept positional arg as profile name
240 # accept positional arg as profile name
241 if self.extra_args:
241 if self.extra_args:
242 self.profile = self.extra_args[0]
242 self.profile = self.extra_args[0]
243
243
244 flags = Dict(create_flags)
244 flags = Dict(create_flags)
245
245
246 classes = [ProfileDir]
246 classes = [ProfileDir]
247
247
248 def _import_app(self, app_path):
248 def _import_app(self, app_path):
249 """import an app class"""
249 """import an app class"""
250 app = None
250 app = None
251 name = app_path.rsplit('.', 1)[-1]
251 name = app_path.rsplit('.', 1)[-1]
252 try:
252 try:
253 app = import_item(app_path)
253 app = import_item(app_path)
254 except ImportError:
254 except ImportError:
255 self.log.info("Couldn't import %s, config file will be excluded", name)
255 self.log.info("Couldn't import %s, config file will be excluded", name)
256 except Exception:
256 except Exception:
257 self.log.warning('Unexpected error importing %s', name, exc_info=True)
257 self.log.warning('Unexpected error importing %s', name, exc_info=True)
258 return app
258 return app
259
259
260 def init_config_files(self):
260 def init_config_files(self):
261 super(ProfileCreate, self).init_config_files()
261 super(ProfileCreate, self).init_config_files()
262 # use local imports, since these classes may import from here
262 # use local imports, since these classes may import from here
263 from IPython.terminal.ipapp import TerminalIPythonApp
263 from IPython.terminal.ipapp import TerminalIPythonApp
264 apps = [TerminalIPythonApp]
264 apps = [TerminalIPythonApp]
265 for app_path in (
265 for app_path in (
266 'ipykernel.kernelapp.IPKernelApp',
266 'ipykernel.kernelapp.IPKernelApp',
267 ):
267 ):
268 app = self._import_app(app_path)
268 app = self._import_app(app_path)
269 if app is not None:
269 if app is not None:
270 apps.append(app)
270 apps.append(app)
271 if self.parallel:
271 if self.parallel:
272 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
272 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
273 from ipyparallel.apps.ipengineapp import IPEngineApp
273 from ipyparallel.apps.ipengineapp import IPEngineApp
274 from ipyparallel.apps.ipclusterapp import IPClusterStart
274 from ipyparallel.apps.ipclusterapp import IPClusterStart
275 apps.extend([
275 apps.extend([
276 IPControllerApp,
276 IPControllerApp,
277 IPEngineApp,
277 IPEngineApp,
278 IPClusterStart,
278 IPClusterStart,
279 ])
279 ])
280 for App in apps:
280 for App in apps:
281 app = App()
281 app = App()
282 app.config.update(self.config)
282 app.config.update(self.config)
283 app.log = self.log
283 app.log = self.log
284 app.overwrite = self.overwrite
284 app.overwrite = self.overwrite
285 app.copy_config_files=True
285 app.copy_config_files=True
286 app.ipython_dir=self.ipython_dir
286 app.ipython_dir=self.ipython_dir
287 app.profile_dir=self.profile_dir
287 app.profile_dir=self.profile_dir
288 app.init_config_files()
288 app.init_config_files()
289
289
290 def stage_default_config_file(self):
290 def stage_default_config_file(self):
291 pass
291 pass
292
292
293
293
294 class ProfileApp(Application):
294 class ProfileApp(Application):
295 name = u'ipython profile'
295 name = u'ipython profile'
296 description = profile_help
296 description = profile_help
297 examples = _main_examples
297 examples = _main_examples
298
298
299 subcommands = Dict(dict(
299 subcommands = Dict(dict(
300 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
300 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
301 list = (ProfileList, ProfileList.description.splitlines()[0]),
301 list = (ProfileList, ProfileList.description.splitlines()[0]),
302 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
302 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
303 ))
303 ))
304
304
305 def start(self):
305 def start(self):
306 if self.subapp is None:
306 if self.subapp is None:
307 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
307 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
308 print()
308 print()
309 self.print_description()
309 self.print_description()
310 self.print_subcommands()
310 self.print_subcommands()
311 self.exit(1)
311 self.exit(1)
312 else:
312 else:
313 return self.subapp.start()
313 return self.subapp.start()
@@ -1,224 +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, observe
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'',
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 ).tag(config=True)
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 @observe('location')
56 @observe('location')
57 def _location_changed(self, change):
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 new = change['new']
62 ensure_dir_exists(new)
62 ensure_dir_exists(new)
63
63
64 # ensure config files exist:
64 # ensure config files exist:
65 self.security_dir = os.path.join(new, self.security_dir_name)
65 self.security_dir = os.path.join(new, self.security_dir_name)
66 self.log_dir = os.path.join(new, self.log_dir_name)
66 self.log_dir = os.path.join(new, self.log_dir_name)
67 self.startup_dir = os.path.join(new, self.startup_dir_name)
67 self.startup_dir = os.path.join(new, self.startup_dir_name)
68 self.pid_dir = os.path.join(new, self.pid_dir_name)
68 self.pid_dir = os.path.join(new, self.pid_dir_name)
69 self.static_dir = os.path.join(new, self.static_dir_name)
69 self.static_dir = os.path.join(new, self.static_dir_name)
70 self.check_dirs()
70 self.check_dirs()
71
71
72 def _mkdir(self, path, mode=None):
72 def _mkdir(self, path, mode=None):
73 """ensure a directory exists at a given path
73 """ensure a directory exists at a given path
74
74
75 This is a version of os.mkdir, with the following differences:
75 This is a version of os.mkdir, with the following differences:
76
76
77 - returns True if it created the directory, False otherwise
77 - returns True if it created the directory, False otherwise
78 - ignores EEXIST, protecting against race conditions where
78 - ignores EEXIST, protecting against race conditions where
79 the dir may have been created in between the check and
79 the dir may have been created in between the check and
80 the creation
80 the creation
81 - sets permissions if requested and the dir already exists
81 - sets permissions if requested and the dir already exists
82 """
82 """
83 if os.path.exists(path):
83 if os.path.exists(path):
84 if mode and os.stat(path).st_mode != mode:
84 if mode and os.stat(path).st_mode != mode:
85 try:
85 try:
86 os.chmod(path, mode)
86 os.chmod(path, mode)
87 except OSError:
87 except OSError:
88 self.log.warning(
88 self.log.warning(
89 "Could not set permissions on %s",
89 "Could not set permissions on %s",
90 path
90 path
91 )
91 )
92 return False
92 return False
93 try:
93 try:
94 if mode:
94 if mode:
95 os.mkdir(path, mode)
95 os.mkdir(path, mode)
96 else:
96 else:
97 os.mkdir(path)
97 os.mkdir(path)
98 except OSError as e:
98 except OSError as e:
99 if e.errno == errno.EEXIST:
99 if e.errno == errno.EEXIST:
100 return False
100 return False
101 else:
101 else:
102 raise
102 raise
103
103
104 return True
104 return True
105
105
106 @observe('log_dir')
106 @observe('log_dir')
107 def check_log_dir(self, change=None):
107 def check_log_dir(self, change=None):
108 self._mkdir(self.log_dir)
108 self._mkdir(self.log_dir)
109
109
110 @observe('startup_dir')
110 @observe('startup_dir')
111 def check_startup_dir(self, change=None):
111 def check_startup_dir(self, change=None):
112 self._mkdir(self.startup_dir)
112 self._mkdir(self.startup_dir)
113
113
114 readme = os.path.join(self.startup_dir, 'README')
114 readme = os.path.join(self.startup_dir, 'README')
115 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')
116
116
117 if not os.path.exists(src):
117 if not os.path.exists(src):
118 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)
119
119
120 if os.path.exists(src) and not os.path.exists(readme):
120 if os.path.exists(src) and not os.path.exists(readme):
121 shutil.copy(src, readme)
121 shutil.copy(src, readme)
122
122
123 @observe('security_dir')
123 @observe('security_dir')
124 def check_security_dir(self, change=None):
124 def check_security_dir(self, change=None):
125 self._mkdir(self.security_dir, 0o40700)
125 self._mkdir(self.security_dir, 0o40700)
126
126
127 @observe('pid_dir')
127 @observe('pid_dir')
128 def check_pid_dir(self, change=None):
128 def check_pid_dir(self, change=None):
129 self._mkdir(self.pid_dir, 0o40700)
129 self._mkdir(self.pid_dir, 0o40700)
130
130
131 def check_dirs(self):
131 def check_dirs(self):
132 self.check_security_dir()
132 self.check_security_dir()
133 self.check_log_dir()
133 self.check_log_dir()
134 self.check_pid_dir()
134 self.check_pid_dir()
135 self.check_startup_dir()
135 self.check_startup_dir()
136
136
137 def copy_config_file(self, config_file, path=None, overwrite=False):
137 def copy_config_file(self, config_file, path=None, overwrite=False):
138 """Copy a default config file into the active profile directory.
138 """Copy a default config file into the active profile directory.
139
139
140 Default configuration files are kept in :mod:`IPython.core.profile`.
140 Default configuration files are kept in :mod:`IPython.core.profile`.
141 This function moves these from that location to the working profile
141 This function moves these from that location to the working profile
142 directory.
142 directory.
143 """
143 """
144 dst = os.path.join(self.location, config_file)
144 dst = os.path.join(self.location, config_file)
145 if os.path.isfile(dst) and not overwrite:
145 if os.path.isfile(dst) and not overwrite:
146 return False
146 return False
147 if path is None:
147 if path is None:
148 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')
149 src = os.path.join(path, config_file)
149 src = os.path.join(path, config_file)
150 shutil.copy(src, dst)
150 shutil.copy(src, dst)
151 return True
151 return True
152
152
153 @classmethod
153 @classmethod
154 def create_profile_dir(cls, profile_dir, config=None):
154 def create_profile_dir(cls, profile_dir, config=None):
155 """Create a new profile directory given a full path.
155 """Create a new profile directory given a full path.
156
156
157 Parameters
157 Parameters
158 ----------
158 ----------
159 profile_dir : str
159 profile_dir : str
160 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
161 be used. If not, it will be created.
161 be used. If not, it will be created.
162 """
162 """
163 return cls(location=profile_dir, config=config)
163 return cls(location=profile_dir, config=config)
164
164
165 @classmethod
165 @classmethod
166 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):
167 """Create a profile dir by profile name and path.
167 """Create a profile dir by profile name and path.
168
168
169 Parameters
169 Parameters
170 ----------
170 ----------
171 path : unicode
171 path : unicode
172 The path (directory) to put the profile directory in.
172 The path (directory) to put the profile directory in.
173 name : unicode
173 name : unicode
174 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
175 be "profile_<profile>".
175 be "profile_<profile>".
176 """
176 """
177 if not os.path.isdir(path):
177 if not os.path.isdir(path):
178 raise ProfileDirError('Directory not found: %s' % path)
178 raise ProfileDirError('Directory not found: %s' % path)
179 profile_dir = os.path.join(path, u'profile_' + name)
179 profile_dir = os.path.join(path, u'profile_' + name)
180 return cls(location=profile_dir, config=config)
180 return cls(location=profile_dir, config=config)
181
181
182 @classmethod
182 @classmethod
183 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):
184 """Find an existing profile dir by profile name, return its ProfileDir.
184 """Find an existing profile dir by profile name, return its ProfileDir.
185
185
186 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
187 is not found, a :class:`ProfileDirError` exception will be raised.
187 is not found, a :class:`ProfileDirError` exception will be raised.
188
188
189 The search path algorithm is:
189 The search path algorithm is:
190 1. ``py3compat.getcwd()``
190 1. ``os.getcwd()``
191 2. ``ipython_dir``
191 2. ``ipython_dir``
192
192
193 Parameters
193 Parameters
194 ----------
194 ----------
195 ipython_dir : unicode or str
195 ipython_dir : unicode or str
196 The IPython directory to use.
196 The IPython directory to use.
197 name : unicode or str
197 name : unicode or str
198 The name of the profile. The name of the profile directory
198 The name of the profile. The name of the profile directory
199 will be "profile_<profile>".
199 will be "profile_<profile>".
200 """
200 """
201 dirname = u'profile_' + name
201 dirname = u'profile_' + name
202 paths = [py3compat.getcwd(), ipython_dir]
202 paths = [os.getcwd(), ipython_dir]
203 for p in paths:
203 for p in paths:
204 profile_dir = os.path.join(p, dirname)
204 profile_dir = os.path.join(p, dirname)
205 if os.path.isdir(profile_dir):
205 if os.path.isdir(profile_dir):
206 return cls(location=profile_dir, config=config)
206 return cls(location=profile_dir, config=config)
207 else:
207 else:
208 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
208 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
209
209
210 @classmethod
210 @classmethod
211 def find_profile_dir(cls, profile_dir, config=None):
211 def find_profile_dir(cls, profile_dir, config=None):
212 """Find/create a profile dir and return its ProfileDir.
212 """Find/create a profile dir and return its ProfileDir.
213
213
214 This will create the profile directory if it doesn't exist.
214 This will create the profile directory if it doesn't exist.
215
215
216 Parameters
216 Parameters
217 ----------
217 ----------
218 profile_dir : unicode or str
218 profile_dir : unicode or str
219 The path of the profile directory.
219 The path of the profile directory.
220 """
220 """
221 profile_dir = expand_path(profile_dir)
221 profile_dir = expand_path(profile_dir)
222 if not os.path.isdir(profile_dir):
222 if not os.path.isdir(profile_dir):
223 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
223 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
224 return cls(location=profile_dir, config=config)
224 return cls(location=profile_dir, config=config)
@@ -1,26 +1,23 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Being removed
2 """Being removed
3 """
3 """
4
4
5 from IPython.utils import py3compat
5 from IPython.utils import py3compat
6
6
7 class LazyEvaluate(object):
7 class LazyEvaluate(object):
8 """This is used for formatting strings with values that need to be updated
8 """This is used for formatting strings with values that need to be updated
9 at that time, such as the current time or working directory."""
9 at that time, such as the current time or working directory."""
10 def __init__(self, func, *args, **kwargs):
10 def __init__(self, func, *args, **kwargs):
11 self.func = func
11 self.func = func
12 self.args = args
12 self.args = args
13 self.kwargs = kwargs
13 self.kwargs = kwargs
14
14
15 def __call__(self, **kwargs):
15 def __call__(self, **kwargs):
16 self.kwargs.update(kwargs)
16 self.kwargs.update(kwargs)
17 return self.func(*self.args, **self.kwargs)
17 return self.func(*self.args, **self.kwargs)
18
18
19 def __str__(self):
19 def __str__(self):
20 return str(self())
20 return str(self())
21
21
22 def __unicode__(self):
23 return py3compat.unicode_type(self())
24
25 def __format__(self, format_spec):
22 def __format__(self, format_spec):
26 return format(self(), format_spec)
23 return format(self(), format_spec)
@@ -1,410 +1,410 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities."""
2 """Pylab (matplotlib) support utilities."""
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 from io import BytesIO
7 from io import BytesIO
8
8
9 from IPython.core.display import _pngxy
9 from IPython.core.display import _pngxy
10 from IPython.utils.decorators import flag_calls
10 from IPython.utils.decorators import flag_calls
11 from IPython.utils import py3compat
11 from IPython.utils import py3compat
12
12
13 # If user specifies a GUI, that dictates the backend, otherwise we read the
13 # If user specifies a GUI, that dictates the backend, otherwise we read the
14 # user's mpl default from the mpl rc structure
14 # user's mpl default from the mpl rc structure
15 backends = {'tk': 'TkAgg',
15 backends = {'tk': 'TkAgg',
16 'gtk': 'GTKAgg',
16 'gtk': 'GTKAgg',
17 'gtk3': 'GTK3Agg',
17 'gtk3': 'GTK3Agg',
18 'wx': 'WXAgg',
18 'wx': 'WXAgg',
19 'qt': 'Qt4Agg', # qt3 not supported
19 'qt': 'Qt4Agg', # qt3 not supported
20 'qt4': 'Qt4Agg',
20 'qt4': 'Qt4Agg',
21 'qt5': 'Qt5Agg',
21 'qt5': 'Qt5Agg',
22 'osx': 'MacOSX',
22 'osx': 'MacOSX',
23 'nbagg': 'nbAgg',
23 'nbagg': 'nbAgg',
24 'notebook': 'nbAgg',
24 'notebook': 'nbAgg',
25 'agg': 'agg',
25 'agg': 'agg',
26 'inline': 'module://ipykernel.pylab.backend_inline',
26 'inline': 'module://ipykernel.pylab.backend_inline',
27 'ipympl': 'module://ipympl.backend_nbagg',
27 'ipympl': 'module://ipympl.backend_nbagg',
28 }
28 }
29
29
30 # We also need a reverse backends2guis mapping that will properly choose which
30 # We also need a reverse backends2guis mapping that will properly choose which
31 # GUI support to activate based on the desired matplotlib backend. For the
31 # GUI support to activate based on the desired matplotlib backend. For the
32 # most part it's just a reverse of the above dict, but we also need to add a
32 # most part it's just a reverse of the above dict, but we also need to add a
33 # few others that map to the same GUI manually:
33 # few others that map to the same GUI manually:
34 backend2gui = dict(zip(backends.values(), backends.keys()))
34 backend2gui = dict(zip(backends.values(), backends.keys()))
35 # Our tests expect backend2gui to just return 'qt'
35 # Our tests expect backend2gui to just return 'qt'
36 backend2gui['Qt4Agg'] = 'qt'
36 backend2gui['Qt4Agg'] = 'qt'
37 # In the reverse mapping, there are a few extra valid matplotlib backends that
37 # In the reverse mapping, there are a few extra valid matplotlib backends that
38 # map to the same GUI support
38 # map to the same GUI support
39 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
39 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
40 backend2gui['GTK3Cairo'] = 'gtk3'
40 backend2gui['GTK3Cairo'] = 'gtk3'
41 backend2gui['WX'] = 'wx'
41 backend2gui['WX'] = 'wx'
42 backend2gui['CocoaAgg'] = 'osx'
42 backend2gui['CocoaAgg'] = 'osx'
43 # And some backends that don't need GUI integration
43 # And some backends that don't need GUI integration
44 del backend2gui['nbAgg']
44 del backend2gui['nbAgg']
45 del backend2gui['agg']
45 del backend2gui['agg']
46 del backend2gui['module://ipykernel.pylab.backend_inline']
46 del backend2gui['module://ipykernel.pylab.backend_inline']
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Matplotlib utilities
49 # Matplotlib utilities
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52
52
53 def getfigs(*fig_nums):
53 def getfigs(*fig_nums):
54 """Get a list of matplotlib figures by figure numbers.
54 """Get a list of matplotlib figures by figure numbers.
55
55
56 If no arguments are given, all available figures are returned. If the
56 If no arguments are given, all available figures are returned. If the
57 argument list contains references to invalid figures, a warning is printed
57 argument list contains references to invalid figures, a warning is printed
58 but the function continues pasting further figures.
58 but the function continues pasting further figures.
59
59
60 Parameters
60 Parameters
61 ----------
61 ----------
62 figs : tuple
62 figs : tuple
63 A tuple of ints giving the figure numbers of the figures to return.
63 A tuple of ints giving the figure numbers of the figures to return.
64 """
64 """
65 from matplotlib._pylab_helpers import Gcf
65 from matplotlib._pylab_helpers import Gcf
66 if not fig_nums:
66 if not fig_nums:
67 fig_managers = Gcf.get_all_fig_managers()
67 fig_managers = Gcf.get_all_fig_managers()
68 return [fm.canvas.figure for fm in fig_managers]
68 return [fm.canvas.figure for fm in fig_managers]
69 else:
69 else:
70 figs = []
70 figs = []
71 for num in fig_nums:
71 for num in fig_nums:
72 f = Gcf.figs.get(num)
72 f = Gcf.figs.get(num)
73 if f is None:
73 if f is None:
74 print('Warning: figure %s not available.' % num)
74 print('Warning: figure %s not available.' % num)
75 else:
75 else:
76 figs.append(f.canvas.figure)
76 figs.append(f.canvas.figure)
77 return figs
77 return figs
78
78
79
79
80 def figsize(sizex, sizey):
80 def figsize(sizex, sizey):
81 """Set the default figure size to be [sizex, sizey].
81 """Set the default figure size to be [sizex, sizey].
82
82
83 This is just an easy to remember, convenience wrapper that sets::
83 This is just an easy to remember, convenience wrapper that sets::
84
84
85 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
85 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
86 """
86 """
87 import matplotlib
87 import matplotlib
88 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
88 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89
89
90
90
91 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
91 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
92 """Print a figure to an image, and return the resulting file data
92 """Print a figure to an image, and return the resulting file data
93
93
94 Returned data will be bytes unless ``fmt='svg'``,
94 Returned data will be bytes unless ``fmt='svg'``,
95 in which case it will be unicode.
95 in which case it will be unicode.
96
96
97 Any keyword args are passed to fig.canvas.print_figure,
97 Any keyword args are passed to fig.canvas.print_figure,
98 such as ``quality`` or ``bbox_inches``.
98 such as ``quality`` or ``bbox_inches``.
99 """
99 """
100 from matplotlib import rcParams
100 from matplotlib import rcParams
101 # When there's an empty figure, we shouldn't return anything, otherwise we
101 # When there's an empty figure, we shouldn't return anything, otherwise we
102 # get big blank areas in the qt console.
102 # get big blank areas in the qt console.
103 if not fig.axes and not fig.lines:
103 if not fig.axes and not fig.lines:
104 return
104 return
105
105
106 dpi = fig.dpi
106 dpi = fig.dpi
107 if fmt == 'retina':
107 if fmt == 'retina':
108 dpi = dpi * 2
108 dpi = dpi * 2
109 fmt = 'png'
109 fmt = 'png'
110
110
111 # build keyword args
111 # build keyword args
112 kw = dict(
112 kw = dict(
113 format=fmt,
113 format=fmt,
114 facecolor=fig.get_facecolor(),
114 facecolor=fig.get_facecolor(),
115 edgecolor=fig.get_edgecolor(),
115 edgecolor=fig.get_edgecolor(),
116 dpi=dpi,
116 dpi=dpi,
117 bbox_inches=bbox_inches,
117 bbox_inches=bbox_inches,
118 )
118 )
119 # **kwargs get higher priority
119 # **kwargs get higher priority
120 kw.update(kwargs)
120 kw.update(kwargs)
121
121
122 bytes_io = BytesIO()
122 bytes_io = BytesIO()
123 fig.canvas.print_figure(bytes_io, **kw)
123 fig.canvas.print_figure(bytes_io, **kw)
124 data = bytes_io.getvalue()
124 data = bytes_io.getvalue()
125 if fmt == 'svg':
125 if fmt == 'svg':
126 data = data.decode('utf-8')
126 data = data.decode('utf-8')
127 return data
127 return data
128
128
129 def retina_figure(fig, **kwargs):
129 def retina_figure(fig, **kwargs):
130 """format a figure as a pixel-doubled (retina) PNG"""
130 """format a figure as a pixel-doubled (retina) PNG"""
131 pngdata = print_figure(fig, fmt='retina', **kwargs)
131 pngdata = print_figure(fig, fmt='retina', **kwargs)
132 # Make sure that retina_figure acts just like print_figure and returns
132 # Make sure that retina_figure acts just like print_figure and returns
133 # None when the figure is empty.
133 # None when the figure is empty.
134 if pngdata is None:
134 if pngdata is None:
135 return
135 return
136 w, h = _pngxy(pngdata)
136 w, h = _pngxy(pngdata)
137 metadata = dict(width=w//2, height=h//2)
137 metadata = dict(width=w//2, height=h//2)
138 return pngdata, metadata
138 return pngdata, metadata
139
139
140 # We need a little factory function here to create the closure where
140 # We need a little factory function here to create the closure where
141 # safe_execfile can live.
141 # safe_execfile can live.
142 def mpl_runner(safe_execfile):
142 def mpl_runner(safe_execfile):
143 """Factory to return a matplotlib-enabled runner for %run.
143 """Factory to return a matplotlib-enabled runner for %run.
144
144
145 Parameters
145 Parameters
146 ----------
146 ----------
147 safe_execfile : function
147 safe_execfile : function
148 This must be a function with the same interface as the
148 This must be a function with the same interface as the
149 :meth:`safe_execfile` method of IPython.
149 :meth:`safe_execfile` method of IPython.
150
150
151 Returns
151 Returns
152 -------
152 -------
153 A function suitable for use as the ``runner`` argument of the %run magic
153 A function suitable for use as the ``runner`` argument of the %run magic
154 function.
154 function.
155 """
155 """
156
156
157 def mpl_execfile(fname,*where,**kw):
157 def mpl_execfile(fname,*where,**kw):
158 """matplotlib-aware wrapper around safe_execfile.
158 """matplotlib-aware wrapper around safe_execfile.
159
159
160 Its interface is identical to that of the :func:`execfile` builtin.
160 Its interface is identical to that of the :func:`execfile` builtin.
161
161
162 This is ultimately a call to execfile(), but wrapped in safeties to
162 This is ultimately a call to execfile(), but wrapped in safeties to
163 properly handle interactive rendering."""
163 properly handle interactive rendering."""
164
164
165 import matplotlib
165 import matplotlib
166 import matplotlib.pyplot as plt
166 import matplotlib.pyplot as plt
167
167
168 #print '*** Matplotlib runner ***' # dbg
168 #print '*** Matplotlib runner ***' # dbg
169 # turn off rendering until end of script
169 # turn off rendering until end of script
170 is_interactive = matplotlib.rcParams['interactive']
170 is_interactive = matplotlib.rcParams['interactive']
171 matplotlib.interactive(False)
171 matplotlib.interactive(False)
172 safe_execfile(fname,*where,**kw)
172 safe_execfile(fname,*where,**kw)
173 matplotlib.interactive(is_interactive)
173 matplotlib.interactive(is_interactive)
174 # make rendering call now, if the user tried to do it
174 # make rendering call now, if the user tried to do it
175 if plt.draw_if_interactive.called:
175 if plt.draw_if_interactive.called:
176 plt.draw()
176 plt.draw()
177 plt.draw_if_interactive.called = False
177 plt.draw_if_interactive.called = False
178
178
179 # re-draw everything that is stale
179 # re-draw everything that is stale
180 try:
180 try:
181 da = plt.draw_all
181 da = plt.draw_all
182 except AttributeError:
182 except AttributeError:
183 pass
183 pass
184 else:
184 else:
185 da()
185 da()
186
186
187 return mpl_execfile
187 return mpl_execfile
188
188
189
189
190 def _reshow_nbagg_figure(fig):
190 def _reshow_nbagg_figure(fig):
191 """reshow an nbagg figure"""
191 """reshow an nbagg figure"""
192 try:
192 try:
193 reshow = fig.canvas.manager.reshow
193 reshow = fig.canvas.manager.reshow
194 except AttributeError:
194 except AttributeError:
195 raise NotImplementedError()
195 raise NotImplementedError()
196 else:
196 else:
197 reshow()
197 reshow()
198
198
199
199
200 def select_figure_formats(shell, formats, **kwargs):
200 def select_figure_formats(shell, formats, **kwargs):
201 """Select figure formats for the inline backend.
201 """Select figure formats for the inline backend.
202
202
203 Parameters
203 Parameters
204 ==========
204 ==========
205 shell : InteractiveShell
205 shell : InteractiveShell
206 The main IPython instance.
206 The main IPython instance.
207 formats : str or set
207 formats : str or set
208 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
208 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
209 **kwargs : any
209 **kwargs : any
210 Extra keyword arguments to be passed to fig.canvas.print_figure.
210 Extra keyword arguments to be passed to fig.canvas.print_figure.
211 """
211 """
212 import matplotlib
212 import matplotlib
213 from matplotlib.figure import Figure
213 from matplotlib.figure import Figure
214
214
215 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
215 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
216 png_formatter = shell.display_formatter.formatters['image/png']
216 png_formatter = shell.display_formatter.formatters['image/png']
217 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
217 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
218 pdf_formatter = shell.display_formatter.formatters['application/pdf']
218 pdf_formatter = shell.display_formatter.formatters['application/pdf']
219
219
220 if isinstance(formats, py3compat.string_types):
220 if isinstance(formats, str):
221 formats = {formats}
221 formats = {formats}
222 # cast in case of list / tuple
222 # cast in case of list / tuple
223 formats = set(formats)
223 formats = set(formats)
224
224
225 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
225 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
226 mplbackend = matplotlib.get_backend().lower()
226 mplbackend = matplotlib.get_backend().lower()
227 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
227 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
228 formatter = shell.display_formatter.ipython_display_formatter
228 formatter = shell.display_formatter.ipython_display_formatter
229 formatter.for_type(Figure, _reshow_nbagg_figure)
229 formatter.for_type(Figure, _reshow_nbagg_figure)
230
230
231 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
231 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
232 bad = formats.difference(supported)
232 bad = formats.difference(supported)
233 if bad:
233 if bad:
234 bs = "%s" % ','.join([repr(f) for f in bad])
234 bs = "%s" % ','.join([repr(f) for f in bad])
235 gs = "%s" % ','.join([repr(f) for f in supported])
235 gs = "%s" % ','.join([repr(f) for f in supported])
236 raise ValueError("supported formats are: %s not %s" % (gs, bs))
236 raise ValueError("supported formats are: %s not %s" % (gs, bs))
237
237
238 if 'png' in formats:
238 if 'png' in formats:
239 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
239 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
240 if 'retina' in formats or 'png2x' in formats:
240 if 'retina' in formats or 'png2x' in formats:
241 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
241 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
242 if 'jpg' in formats or 'jpeg' in formats:
242 if 'jpg' in formats or 'jpeg' in formats:
243 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
243 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
244 if 'svg' in formats:
244 if 'svg' in formats:
245 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
245 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
246 if 'pdf' in formats:
246 if 'pdf' in formats:
247 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
247 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
248
248
249 #-----------------------------------------------------------------------------
249 #-----------------------------------------------------------------------------
250 # Code for initializing matplotlib and importing pylab
250 # Code for initializing matplotlib and importing pylab
251 #-----------------------------------------------------------------------------
251 #-----------------------------------------------------------------------------
252
252
253
253
254 def find_gui_and_backend(gui=None, gui_select=None):
254 def find_gui_and_backend(gui=None, gui_select=None):
255 """Given a gui string return the gui and mpl backend.
255 """Given a gui string return the gui and mpl backend.
256
256
257 Parameters
257 Parameters
258 ----------
258 ----------
259 gui : str
259 gui : str
260 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
260 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
261 gui_select : str
261 gui_select : str
262 Can be one of ('tk','gtk','wx','qt','qt4','inline').
262 Can be one of ('tk','gtk','wx','qt','qt4','inline').
263 This is any gui already selected by the shell.
263 This is any gui already selected by the shell.
264
264
265 Returns
265 Returns
266 -------
266 -------
267 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
267 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
268 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg').
268 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg').
269 """
269 """
270
270
271 import matplotlib
271 import matplotlib
272
272
273 if gui and gui != 'auto':
273 if gui and gui != 'auto':
274 # select backend based on requested gui
274 # select backend based on requested gui
275 backend = backends[gui]
275 backend = backends[gui]
276 if gui == 'agg':
276 if gui == 'agg':
277 gui = None
277 gui = None
278 else:
278 else:
279 # We need to read the backend from the original data structure, *not*
279 # We need to read the backend from the original data structure, *not*
280 # from mpl.rcParams, since a prior invocation of %matplotlib may have
280 # from mpl.rcParams, since a prior invocation of %matplotlib may have
281 # overwritten that.
281 # overwritten that.
282 # WARNING: this assumes matplotlib 1.1 or newer!!
282 # WARNING: this assumes matplotlib 1.1 or newer!!
283 backend = matplotlib.rcParamsOrig['backend']
283 backend = matplotlib.rcParamsOrig['backend']
284 # In this case, we need to find what the appropriate gui selection call
284 # In this case, we need to find what the appropriate gui selection call
285 # should be for IPython, so we can activate inputhook accordingly
285 # should be for IPython, so we can activate inputhook accordingly
286 gui = backend2gui.get(backend, None)
286 gui = backend2gui.get(backend, None)
287
287
288 # If we have already had a gui active, we need it and inline are the
288 # If we have already had a gui active, we need it and inline are the
289 # ones allowed.
289 # ones allowed.
290 if gui_select and gui != gui_select:
290 if gui_select and gui != gui_select:
291 gui = gui_select
291 gui = gui_select
292 backend = backends[gui]
292 backend = backends[gui]
293
293
294 return gui, backend
294 return gui, backend
295
295
296
296
297 def activate_matplotlib(backend):
297 def activate_matplotlib(backend):
298 """Activate the given backend and set interactive to True."""
298 """Activate the given backend and set interactive to True."""
299
299
300 import matplotlib
300 import matplotlib
301 matplotlib.interactive(True)
301 matplotlib.interactive(True)
302
302
303 # Matplotlib had a bug where even switch_backend could not force
303 # Matplotlib had a bug where even switch_backend could not force
304 # the rcParam to update. This needs to be set *before* the module
304 # the rcParam to update. This needs to be set *before* the module
305 # magic of switch_backend().
305 # magic of switch_backend().
306 matplotlib.rcParams['backend'] = backend
306 matplotlib.rcParams['backend'] = backend
307
307
308 import matplotlib.pyplot
308 import matplotlib.pyplot
309 matplotlib.pyplot.switch_backend(backend)
309 matplotlib.pyplot.switch_backend(backend)
310
310
311 # This must be imported last in the matplotlib series, after
311 # This must be imported last in the matplotlib series, after
312 # backend/interactivity choices have been made
312 # backend/interactivity choices have been made
313 import matplotlib.pyplot as plt
313 import matplotlib.pyplot as plt
314
314
315 plt.show._needmain = False
315 plt.show._needmain = False
316 # We need to detect at runtime whether show() is called by the user.
316 # We need to detect at runtime whether show() is called by the user.
317 # For this, we wrap it into a decorator which adds a 'called' flag.
317 # For this, we wrap it into a decorator which adds a 'called' flag.
318 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
318 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
319
319
320
320
321 def import_pylab(user_ns, import_all=True):
321 def import_pylab(user_ns, import_all=True):
322 """Populate the namespace with pylab-related values.
322 """Populate the namespace with pylab-related values.
323
323
324 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
324 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
325
325
326 Also imports a few names from IPython (figsize, display, getfigs)
326 Also imports a few names from IPython (figsize, display, getfigs)
327
327
328 """
328 """
329
329
330 # Import numpy as np/pyplot as plt are conventions we're trying to
330 # Import numpy as np/pyplot as plt are conventions we're trying to
331 # somewhat standardize on. Making them available to users by default
331 # somewhat standardize on. Making them available to users by default
332 # will greatly help this.
332 # will greatly help this.
333 s = ("import numpy\n"
333 s = ("import numpy\n"
334 "import matplotlib\n"
334 "import matplotlib\n"
335 "from matplotlib import pylab, mlab, pyplot\n"
335 "from matplotlib import pylab, mlab, pyplot\n"
336 "np = numpy\n"
336 "np = numpy\n"
337 "plt = pyplot\n"
337 "plt = pyplot\n"
338 )
338 )
339 exec(s, user_ns)
339 exec(s, user_ns)
340
340
341 if import_all:
341 if import_all:
342 s = ("from matplotlib.pylab import *\n"
342 s = ("from matplotlib.pylab import *\n"
343 "from numpy import *\n")
343 "from numpy import *\n")
344 exec(s, user_ns)
344 exec(s, user_ns)
345
345
346 # IPython symbols to add
346 # IPython symbols to add
347 user_ns['figsize'] = figsize
347 user_ns['figsize'] = figsize
348 from IPython.core.display import display
348 from IPython.core.display import display
349 # Add display and getfigs to the user's namespace
349 # Add display and getfigs to the user's namespace
350 user_ns['display'] = display
350 user_ns['display'] = display
351 user_ns['getfigs'] = getfigs
351 user_ns['getfigs'] = getfigs
352
352
353
353
354 def configure_inline_support(shell, backend):
354 def configure_inline_support(shell, backend):
355 """Configure an IPython shell object for matplotlib use.
355 """Configure an IPython shell object for matplotlib use.
356
356
357 Parameters
357 Parameters
358 ----------
358 ----------
359 shell : InteractiveShell instance
359 shell : InteractiveShell instance
360
360
361 backend : matplotlib backend
361 backend : matplotlib backend
362 """
362 """
363 # If using our svg payload backend, register the post-execution
363 # If using our svg payload backend, register the post-execution
364 # function that will pick up the results for display. This can only be
364 # function that will pick up the results for display. This can only be
365 # done with access to the real shell object.
365 # done with access to the real shell object.
366
366
367 # Note: if we can't load the inline backend, then there's no point
367 # Note: if we can't load the inline backend, then there's no point
368 # continuing (such as in terminal-only shells in environments without
368 # continuing (such as in terminal-only shells in environments without
369 # zeromq available).
369 # zeromq available).
370 try:
370 try:
371 from ipykernel.pylab.backend_inline import InlineBackend
371 from ipykernel.pylab.backend_inline import InlineBackend
372 except ImportError:
372 except ImportError:
373 return
373 return
374 import matplotlib
374 import matplotlib
375
375
376 cfg = InlineBackend.instance(parent=shell)
376 cfg = InlineBackend.instance(parent=shell)
377 cfg.shell = shell
377 cfg.shell = shell
378 if cfg not in shell.configurables:
378 if cfg not in shell.configurables:
379 shell.configurables.append(cfg)
379 shell.configurables.append(cfg)
380
380
381 if backend == backends['inline']:
381 if backend == backends['inline']:
382 from ipykernel.pylab.backend_inline import flush_figures
382 from ipykernel.pylab.backend_inline import flush_figures
383 shell.events.register('post_execute', flush_figures)
383 shell.events.register('post_execute', flush_figures)
384
384
385 # Save rcParams that will be overwrittern
385 # Save rcParams that will be overwrittern
386 shell._saved_rcParams = dict()
386 shell._saved_rcParams = dict()
387 for k in cfg.rc:
387 for k in cfg.rc:
388 shell._saved_rcParams[k] = matplotlib.rcParams[k]
388 shell._saved_rcParams[k] = matplotlib.rcParams[k]
389 # load inline_rc
389 # load inline_rc
390 matplotlib.rcParams.update(cfg.rc)
390 matplotlib.rcParams.update(cfg.rc)
391 new_backend_name = "inline"
391 new_backend_name = "inline"
392 else:
392 else:
393 from ipykernel.pylab.backend_inline import flush_figures
393 from ipykernel.pylab.backend_inline import flush_figures
394 try:
394 try:
395 shell.events.unregister('post_execute', flush_figures)
395 shell.events.unregister('post_execute', flush_figures)
396 except ValueError:
396 except ValueError:
397 pass
397 pass
398 if hasattr(shell, '_saved_rcParams'):
398 if hasattr(shell, '_saved_rcParams'):
399 matplotlib.rcParams.update(shell._saved_rcParams)
399 matplotlib.rcParams.update(shell._saved_rcParams)
400 del shell._saved_rcParams
400 del shell._saved_rcParams
401 new_backend_name = "other"
401 new_backend_name = "other"
402
402
403 # only enable the formats once -> don't change the enabled formats (which the user may
403 # only enable the formats once -> don't change the enabled formats (which the user may
404 # has changed) when getting another "%matplotlib inline" call.
404 # has changed) when getting another "%matplotlib inline" call.
405 # See https://github.com/ipython/ipykernel/issues/29
405 # See https://github.com/ipython/ipykernel/issues/29
406 cur_backend = getattr(configure_inline_support, "current_backend", "unset")
406 cur_backend = getattr(configure_inline_support, "current_backend", "unset")
407 if new_backend_name != cur_backend:
407 if new_backend_name != cur_backend:
408 # Setup the default figure format
408 # Setup the default figure format
409 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
409 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
410 configure_inline_support.current_backend = new_backend_name
410 configure_inline_support.current_backend = new_backend_name
@@ -1,74 +1,74 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for IPython.core.application"""
2 """Tests for IPython.core.application"""
3
3
4 import os
4 import os
5 import tempfile
5 import tempfile
6
6
7 import nose.tools as nt
7 import nose.tools as nt
8
8
9 from traitlets import Unicode
9 from traitlets import Unicode
10
10
11 from IPython.core.application import BaseIPythonApplication
11 from IPython.core.application import BaseIPythonApplication
12 from IPython.testing import decorators as dec
12 from IPython.testing import decorators as dec
13 from IPython.utils import py3compat
13 from IPython.utils import py3compat
14 from IPython.utils.tempdir import TemporaryDirectory
14 from IPython.utils.tempdir import TemporaryDirectory
15
15
16
16
17 @dec.onlyif_unicode_paths
17 @dec.onlyif_unicode_paths
18 def test_unicode_cwd():
18 def test_unicode_cwd():
19 """Check that IPython starts with non-ascii characters in the path."""
19 """Check that IPython starts with non-ascii characters in the path."""
20 wd = tempfile.mkdtemp(suffix=u"€")
20 wd = tempfile.mkdtemp(suffix=u"€")
21
21
22 old_wd = py3compat.getcwd()
22 old_wd = os.getcwd()
23 os.chdir(wd)
23 os.chdir(wd)
24 #raise Exception(repr(py3compat.getcwd()))
24 #raise Exception(repr(os.getcwd()))
25 try:
25 try:
26 app = BaseIPythonApplication()
26 app = BaseIPythonApplication()
27 # The lines below are copied from Application.initialize()
27 # The lines below are copied from Application.initialize()
28 app.init_profile_dir()
28 app.init_profile_dir()
29 app.init_config_files()
29 app.init_config_files()
30 app.load_config_file(suppress_errors=False)
30 app.load_config_file(suppress_errors=False)
31 finally:
31 finally:
32 os.chdir(old_wd)
32 os.chdir(old_wd)
33
33
34 @dec.onlyif_unicode_paths
34 @dec.onlyif_unicode_paths
35 def test_unicode_ipdir():
35 def test_unicode_ipdir():
36 """Check that IPython starts with non-ascii characters in the IP dir."""
36 """Check that IPython starts with non-ascii characters in the IP dir."""
37 ipdir = tempfile.mkdtemp(suffix=u"€")
37 ipdir = tempfile.mkdtemp(suffix=u"€")
38
38
39 # Create the config file, so it tries to load it.
39 # Create the config file, so it tries to load it.
40 with open(os.path.join(ipdir, 'ipython_config.py'), "w") as f:
40 with open(os.path.join(ipdir, 'ipython_config.py'), "w") as f:
41 pass
41 pass
42
42
43 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
43 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
44 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
44 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
45 os.environ["IPYTHONDIR"] = py3compat.unicode_to_str(ipdir, "utf-8")
45 os.environ["IPYTHONDIR"] = ipdir
46 try:
46 try:
47 app = BaseIPythonApplication()
47 app = BaseIPythonApplication()
48 # The lines below are copied from Application.initialize()
48 # The lines below are copied from Application.initialize()
49 app.init_profile_dir()
49 app.init_profile_dir()
50 app.init_config_files()
50 app.init_config_files()
51 app.load_config_file(suppress_errors=False)
51 app.load_config_file(suppress_errors=False)
52 finally:
52 finally:
53 if old_ipdir1:
53 if old_ipdir1:
54 os.environ["IPYTHONDIR"] = old_ipdir1
54 os.environ["IPYTHONDIR"] = old_ipdir1
55 if old_ipdir2:
55 if old_ipdir2:
56 os.environ["IPYTHONDIR"] = old_ipdir2
56 os.environ["IPYTHONDIR"] = old_ipdir2
57
57
58 def test_cli_priority():
58 def test_cli_priority():
59 with TemporaryDirectory() as td:
59 with TemporaryDirectory() as td:
60
60
61 class TestApp(BaseIPythonApplication):
61 class TestApp(BaseIPythonApplication):
62 test = Unicode().tag(config=True)
62 test = Unicode().tag(config=True)
63
63
64 # Create the config file, so it tries to load it.
64 # Create the config file, so it tries to load it.
65 with open(os.path.join(td, 'ipython_config.py'), "w") as f:
65 with open(os.path.join(td, 'ipython_config.py'), "w") as f:
66 f.write("c.TestApp.test = 'config file'")
66 f.write("c.TestApp.test = 'config file'")
67
67
68 app = TestApp()
68 app = TestApp()
69 app.initialize(['--profile-dir', td])
69 app.initialize(['--profile-dir', td])
70 nt.assert_equal(app.test, 'config file')
70 nt.assert_equal(app.test, 'config file')
71 app = TestApp()
71 app = TestApp()
72 app.initialize(['--profile-dir', td, '--TestApp.test=cli'])
72 app.initialize(['--profile-dir', td, '--TestApp.test=cli'])
73 nt.assert_equal(app.test, 'cli')
73 nt.assert_equal(app.test, 'cli')
74
74
@@ -1,739 +1,738 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for the IPython tab-completion machinery."""
2 """Tests for the IPython tab-completion machinery."""
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 sys
8 import sys
9 import unittest
9 import unittest
10
10
11 from contextlib import contextmanager
11 from contextlib import contextmanager
12
12
13 import nose.tools as nt
13 import nose.tools as nt
14
14
15 from traitlets.config.loader import Config
15 from traitlets.config.loader import Config
16 from IPython import get_ipython
16 from IPython import get_ipython
17 from IPython.core import completer
17 from IPython.core import completer
18 from IPython.external.decorators import knownfailureif
18 from IPython.external.decorators import knownfailureif
19 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
19 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
20 from IPython.utils.generics import complete_object
20 from IPython.utils.generics import complete_object
21 from IPython.utils.py3compat import string_types, unicode_type
22 from IPython.testing import decorators as dec
21 from IPython.testing import decorators as dec
23
22
24 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
25 # Test functions
24 # Test functions
26 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
27
26
28 @contextmanager
27 @contextmanager
29 def greedy_completion():
28 def greedy_completion():
30 ip = get_ipython()
29 ip = get_ipython()
31 greedy_original = ip.Completer.greedy
30 greedy_original = ip.Completer.greedy
32 try:
31 try:
33 ip.Completer.greedy = True
32 ip.Completer.greedy = True
34 yield
33 yield
35 finally:
34 finally:
36 ip.Completer.greedy = greedy_original
35 ip.Completer.greedy = greedy_original
37
36
38 def test_protect_filename():
37 def test_protect_filename():
39 if sys.platform == 'win32':
38 if sys.platform == 'win32':
40 pairs = [('abc','abc'),
39 pairs = [('abc','abc'),
41 (' abc','" abc"'),
40 (' abc','" abc"'),
42 ('a bc','"a bc"'),
41 ('a bc','"a bc"'),
43 ('a bc','"a bc"'),
42 ('a bc','"a bc"'),
44 (' bc','" bc"'),
43 (' bc','" bc"'),
45 ]
44 ]
46 else:
45 else:
47 pairs = [('abc','abc'),
46 pairs = [('abc','abc'),
48 (' abc',r'\ abc'),
47 (' abc',r'\ abc'),
49 ('a bc',r'a\ bc'),
48 ('a bc',r'a\ bc'),
50 ('a bc',r'a\ \ bc'),
49 ('a bc',r'a\ \ bc'),
51 (' bc',r'\ \ bc'),
50 (' bc',r'\ \ bc'),
52 # On posix, we also protect parens and other special characters.
51 # On posix, we also protect parens and other special characters.
53 ('a(bc',r'a\(bc'),
52 ('a(bc',r'a\(bc'),
54 ('a)bc',r'a\)bc'),
53 ('a)bc',r'a\)bc'),
55 ('a( )bc',r'a\(\ \)bc'),
54 ('a( )bc',r'a\(\ \)bc'),
56 ('a[1]bc', r'a\[1\]bc'),
55 ('a[1]bc', r'a\[1\]bc'),
57 ('a{1}bc', r'a\{1\}bc'),
56 ('a{1}bc', r'a\{1\}bc'),
58 ('a#bc', r'a\#bc'),
57 ('a#bc', r'a\#bc'),
59 ('a?bc', r'a\?bc'),
58 ('a?bc', r'a\?bc'),
60 ('a=bc', r'a\=bc'),
59 ('a=bc', r'a\=bc'),
61 ('a\\bc', r'a\\bc'),
60 ('a\\bc', r'a\\bc'),
62 ('a|bc', r'a\|bc'),
61 ('a|bc', r'a\|bc'),
63 ('a;bc', r'a\;bc'),
62 ('a;bc', r'a\;bc'),
64 ('a:bc', r'a\:bc'),
63 ('a:bc', r'a\:bc'),
65 ("a'bc", r"a\'bc"),
64 ("a'bc", r"a\'bc"),
66 ('a*bc', r'a\*bc'),
65 ('a*bc', r'a\*bc'),
67 ('a"bc', r'a\"bc'),
66 ('a"bc', r'a\"bc'),
68 ('a^bc', r'a\^bc'),
67 ('a^bc', r'a\^bc'),
69 ('a&bc', r'a\&bc'),
68 ('a&bc', r'a\&bc'),
70 ]
69 ]
71 # run the actual tests
70 # run the actual tests
72 for s1, s2 in pairs:
71 for s1, s2 in pairs:
73 s1p = completer.protect_filename(s1)
72 s1p = completer.protect_filename(s1)
74 nt.assert_equal(s1p, s2)
73 nt.assert_equal(s1p, s2)
75
74
76
75
77 def check_line_split(splitter, test_specs):
76 def check_line_split(splitter, test_specs):
78 for part1, part2, split in test_specs:
77 for part1, part2, split in test_specs:
79 cursor_pos = len(part1)
78 cursor_pos = len(part1)
80 line = part1+part2
79 line = part1+part2
81 out = splitter.split_line(line, cursor_pos)
80 out = splitter.split_line(line, cursor_pos)
82 nt.assert_equal(out, split)
81 nt.assert_equal(out, split)
83
82
84
83
85 def test_line_split():
84 def test_line_split():
86 """Basic line splitter test with default specs."""
85 """Basic line splitter test with default specs."""
87 sp = completer.CompletionSplitter()
86 sp = completer.CompletionSplitter()
88 # The format of the test specs is: part1, part2, expected answer. Parts 1
87 # The format of the test specs is: part1, part2, expected answer. Parts 1
89 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
88 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
90 # was at the end of part1. So an empty part2 represents someone hitting
89 # was at the end of part1. So an empty part2 represents someone hitting
91 # tab at the end of the line, the most common case.
90 # tab at the end of the line, the most common case.
92 t = [('run some/scrip', '', 'some/scrip'),
91 t = [('run some/scrip', '', 'some/scrip'),
93 ('run scripts/er', 'ror.py foo', 'scripts/er'),
92 ('run scripts/er', 'ror.py foo', 'scripts/er'),
94 ('echo $HOM', '', 'HOM'),
93 ('echo $HOM', '', 'HOM'),
95 ('print sys.pa', '', 'sys.pa'),
94 ('print sys.pa', '', 'sys.pa'),
96 ('print(sys.pa', '', 'sys.pa'),
95 ('print(sys.pa', '', 'sys.pa'),
97 ("execfile('scripts/er", '', 'scripts/er'),
96 ("execfile('scripts/er", '', 'scripts/er'),
98 ('a[x.', '', 'x.'),
97 ('a[x.', '', 'x.'),
99 ('a[x.', 'y', 'x.'),
98 ('a[x.', 'y', 'x.'),
100 ('cd "some_file/', '', 'some_file/'),
99 ('cd "some_file/', '', 'some_file/'),
101 ]
100 ]
102 check_line_split(sp, t)
101 check_line_split(sp, t)
103 # Ensure splitting works OK with unicode by re-running the tests with
102 # Ensure splitting works OK with unicode by re-running the tests with
104 # all inputs turned into unicode
103 # all inputs turned into unicode
105 check_line_split(sp, [ map(unicode_type, p) for p in t] )
104 check_line_split(sp, [ map(str, p) for p in t] )
106
105
107
106
108 def test_custom_completion_error():
107 def test_custom_completion_error():
109 """Test that errors from custom attribute completers are silenced."""
108 """Test that errors from custom attribute completers are silenced."""
110 ip = get_ipython()
109 ip = get_ipython()
111 class A(object): pass
110 class A(object): pass
112 ip.user_ns['a'] = A()
111 ip.user_ns['a'] = A()
113
112
114 @complete_object.when_type(A)
113 @complete_object.when_type(A)
115 def complete_A(a, existing_completions):
114 def complete_A(a, existing_completions):
116 raise TypeError("this should be silenced")
115 raise TypeError("this should be silenced")
117
116
118 ip.complete("a.")
117 ip.complete("a.")
119
118
120
119
121 def test_unicode_completions():
120 def test_unicode_completions():
122 ip = get_ipython()
121 ip = get_ipython()
123 # Some strings that trigger different types of completion. Check them both
122 # Some strings that trigger different types of completion. Check them both
124 # in str and unicode forms
123 # in str and unicode forms
125 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
124 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
126 for t in s + list(map(unicode_type, s)):
125 for t in s + list(map(str, s)):
127 # We don't need to check exact completion values (they may change
126 # We don't need to check exact completion values (they may change
128 # depending on the state of the namespace, but at least no exceptions
127 # depending on the state of the namespace, but at least no exceptions
129 # should be thrown and the return value should be a pair of text, list
128 # should be thrown and the return value should be a pair of text, list
130 # values.
129 # values.
131 text, matches = ip.complete(t)
130 text, matches = ip.complete(t)
132 nt.assert_true(isinstance(text, string_types))
131 nt.assert_true(isinstance(text, str))
133 nt.assert_true(isinstance(matches, list))
132 nt.assert_true(isinstance(matches, list))
134
133
135 def test_latex_completions():
134 def test_latex_completions():
136 from IPython.core.latex_symbols import latex_symbols
135 from IPython.core.latex_symbols import latex_symbols
137 import random
136 import random
138 ip = get_ipython()
137 ip = get_ipython()
139 # Test some random unicode symbols
138 # Test some random unicode symbols
140 keys = random.sample(latex_symbols.keys(), 10)
139 keys = random.sample(latex_symbols.keys(), 10)
141 for k in keys:
140 for k in keys:
142 text, matches = ip.complete(k)
141 text, matches = ip.complete(k)
143 nt.assert_equal(len(matches),1)
142 nt.assert_equal(len(matches),1)
144 nt.assert_equal(text, k)
143 nt.assert_equal(text, k)
145 nt.assert_equal(matches[0], latex_symbols[k])
144 nt.assert_equal(matches[0], latex_symbols[k])
146 # Test a more complex line
145 # Test a more complex line
147 text, matches = ip.complete(u'print(\\alpha')
146 text, matches = ip.complete(u'print(\\alpha')
148 nt.assert_equal(text, u'\\alpha')
147 nt.assert_equal(text, u'\\alpha')
149 nt.assert_equal(matches[0], latex_symbols['\\alpha'])
148 nt.assert_equal(matches[0], latex_symbols['\\alpha'])
150 # Test multiple matching latex symbols
149 # Test multiple matching latex symbols
151 text, matches = ip.complete(u'\\al')
150 text, matches = ip.complete(u'\\al')
152 nt.assert_in('\\alpha', matches)
151 nt.assert_in('\\alpha', matches)
153 nt.assert_in('\\aleph', matches)
152 nt.assert_in('\\aleph', matches)
154
153
155
154
156
155
157
156
158 def test_back_latex_completion():
157 def test_back_latex_completion():
159 ip = get_ipython()
158 ip = get_ipython()
160
159
161 # do not return more than 1 matches fro \beta, only the latex one.
160 # do not return more than 1 matches fro \beta, only the latex one.
162 name, matches = ip.complete('\\β')
161 name, matches = ip.complete('\\β')
163 nt.assert_equal(len(matches), 1)
162 nt.assert_equal(len(matches), 1)
164 nt.assert_equal(matches[0], '\\beta')
163 nt.assert_equal(matches[0], '\\beta')
165
164
166 def test_back_unicode_completion():
165 def test_back_unicode_completion():
167 ip = get_ipython()
166 ip = get_ipython()
168
167
169 name, matches = ip.complete('\\â…¤')
168 name, matches = ip.complete('\\â…¤')
170 nt.assert_equal(len(matches), 1)
169 nt.assert_equal(len(matches), 1)
171 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
170 nt.assert_equal(matches[0], '\\ROMAN NUMERAL FIVE')
172
171
173
172
174 def test_forward_unicode_completion():
173 def test_forward_unicode_completion():
175 ip = get_ipython()
174 ip = get_ipython()
176
175
177 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
176 name, matches = ip.complete('\\ROMAN NUMERAL FIVE')
178 nt.assert_equal(len(matches), 1)
177 nt.assert_equal(len(matches), 1)
179 nt.assert_equal(matches[0], 'â…¤')
178 nt.assert_equal(matches[0], 'â…¤')
180
179
181 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
180 @dec.knownfailureif(sys.platform == 'win32', 'Fails if there is a C:\\j... path')
182 def test_no_ascii_back_completion():
181 def test_no_ascii_back_completion():
183 ip = get_ipython()
182 ip = get_ipython()
184 with TemporaryWorkingDirectory(): # Avoid any filename completions
183 with TemporaryWorkingDirectory(): # Avoid any filename completions
185 # single ascii letter that don't have yet completions
184 # single ascii letter that don't have yet completions
186 for letter in 'jJ' :
185 for letter in 'jJ' :
187 name, matches = ip.complete('\\'+letter)
186 name, matches = ip.complete('\\'+letter)
188 nt.assert_equal(matches, [])
187 nt.assert_equal(matches, [])
189
188
190
189
191
190
192
191
193 class CompletionSplitterTestCase(unittest.TestCase):
192 class CompletionSplitterTestCase(unittest.TestCase):
194 def setUp(self):
193 def setUp(self):
195 self.sp = completer.CompletionSplitter()
194 self.sp = completer.CompletionSplitter()
196
195
197 def test_delim_setting(self):
196 def test_delim_setting(self):
198 self.sp.delims = ' '
197 self.sp.delims = ' '
199 nt.assert_equal(self.sp.delims, ' ')
198 nt.assert_equal(self.sp.delims, ' ')
200 nt.assert_equal(self.sp._delim_expr, '[\ ]')
199 nt.assert_equal(self.sp._delim_expr, '[\ ]')
201
200
202 def test_spaces(self):
201 def test_spaces(self):
203 """Test with only spaces as split chars."""
202 """Test with only spaces as split chars."""
204 self.sp.delims = ' '
203 self.sp.delims = ' '
205 t = [('foo', '', 'foo'),
204 t = [('foo', '', 'foo'),
206 ('run foo', '', 'foo'),
205 ('run foo', '', 'foo'),
207 ('run foo', 'bar', 'foo'),
206 ('run foo', 'bar', 'foo'),
208 ]
207 ]
209 check_line_split(self.sp, t)
208 check_line_split(self.sp, t)
210
209
211
210
212 def test_has_open_quotes1():
211 def test_has_open_quotes1():
213 for s in ["'", "'''", "'hi' '"]:
212 for s in ["'", "'''", "'hi' '"]:
214 nt.assert_equal(completer.has_open_quotes(s), "'")
213 nt.assert_equal(completer.has_open_quotes(s), "'")
215
214
216
215
217 def test_has_open_quotes2():
216 def test_has_open_quotes2():
218 for s in ['"', '"""', '"hi" "']:
217 for s in ['"', '"""', '"hi" "']:
219 nt.assert_equal(completer.has_open_quotes(s), '"')
218 nt.assert_equal(completer.has_open_quotes(s), '"')
220
219
221
220
222 def test_has_open_quotes3():
221 def test_has_open_quotes3():
223 for s in ["''", "''' '''", "'hi' 'ipython'"]:
222 for s in ["''", "''' '''", "'hi' 'ipython'"]:
224 nt.assert_false(completer.has_open_quotes(s))
223 nt.assert_false(completer.has_open_quotes(s))
225
224
226
225
227 def test_has_open_quotes4():
226 def test_has_open_quotes4():
228 for s in ['""', '""" """', '"hi" "ipython"']:
227 for s in ['""', '""" """', '"hi" "ipython"']:
229 nt.assert_false(completer.has_open_quotes(s))
228 nt.assert_false(completer.has_open_quotes(s))
230
229
231
230
232 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
231 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
233 def test_abspath_file_completions():
232 def test_abspath_file_completions():
234 ip = get_ipython()
233 ip = get_ipython()
235 with TemporaryDirectory() as tmpdir:
234 with TemporaryDirectory() as tmpdir:
236 prefix = os.path.join(tmpdir, 'foo')
235 prefix = os.path.join(tmpdir, 'foo')
237 suffixes = ['1', '2']
236 suffixes = ['1', '2']
238 names = [prefix+s for s in suffixes]
237 names = [prefix+s for s in suffixes]
239 for n in names:
238 for n in names:
240 open(n, 'w').close()
239 open(n, 'w').close()
241
240
242 # Check simple completion
241 # Check simple completion
243 c = ip.complete(prefix)[1]
242 c = ip.complete(prefix)[1]
244 nt.assert_equal(c, names)
243 nt.assert_equal(c, names)
245
244
246 # Now check with a function call
245 # Now check with a function call
247 cmd = 'a = f("%s' % prefix
246 cmd = 'a = f("%s' % prefix
248 c = ip.complete(prefix, cmd)[1]
247 c = ip.complete(prefix, cmd)[1]
249 comp = [prefix+s for s in suffixes]
248 comp = [prefix+s for s in suffixes]
250 nt.assert_equal(c, comp)
249 nt.assert_equal(c, comp)
251
250
252
251
253 def test_local_file_completions():
252 def test_local_file_completions():
254 ip = get_ipython()
253 ip = get_ipython()
255 with TemporaryWorkingDirectory():
254 with TemporaryWorkingDirectory():
256 prefix = './foo'
255 prefix = './foo'
257 suffixes = ['1', '2']
256 suffixes = ['1', '2']
258 names = [prefix+s for s in suffixes]
257 names = [prefix+s for s in suffixes]
259 for n in names:
258 for n in names:
260 open(n, 'w').close()
259 open(n, 'w').close()
261
260
262 # Check simple completion
261 # Check simple completion
263 c = ip.complete(prefix)[1]
262 c = ip.complete(prefix)[1]
264 nt.assert_equal(c, names)
263 nt.assert_equal(c, names)
265
264
266 # Now check with a function call
265 # Now check with a function call
267 cmd = 'a = f("%s' % prefix
266 cmd = 'a = f("%s' % prefix
268 c = ip.complete(prefix, cmd)[1]
267 c = ip.complete(prefix, cmd)[1]
269 comp = set(prefix+s for s in suffixes)
268 comp = set(prefix+s for s in suffixes)
270 nt.assert_true(comp.issubset(set(c)))
269 nt.assert_true(comp.issubset(set(c)))
271
270
272
271
273 def test_greedy_completions():
272 def test_greedy_completions():
274 ip = get_ipython()
273 ip = get_ipython()
275 ip.ex('a=list(range(5))')
274 ip.ex('a=list(range(5))')
276 _,c = ip.complete('.',line='a[0].')
275 _,c = ip.complete('.',line='a[0].')
277 nt.assert_false('.real' in c,
276 nt.assert_false('.real' in c,
278 "Shouldn't have completed on a[0]: %s"%c)
277 "Shouldn't have completed on a[0]: %s"%c)
279 with greedy_completion():
278 with greedy_completion():
280 def _(line, cursor_pos, expect, message):
279 def _(line, cursor_pos, expect, message):
281 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
280 _,c = ip.complete('.', line=line, cursor_pos=cursor_pos)
282 nt.assert_in(expect, c, message%c)
281 nt.assert_in(expect, c, message%c)
283
282
284 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s"
283 yield _, 'a[0].', 5, 'a[0].real', "Should have completed on a[0].: %s"
285 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s"
284 yield _, 'a[0].r', 6, 'a[0].real', "Should have completed on a[0].r: %s"
286
285
287 if sys.version_info > (3,4):
286 if sys.version_info > (3,4):
288 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s"
287 yield _, 'a[0].from_', 10, 'a[0].from_bytes', "Should have completed on a[0].from_: %s"
289
288
290
289
291
290
292 def test_omit__names():
291 def test_omit__names():
293 # also happens to test IPCompleter as a configurable
292 # also happens to test IPCompleter as a configurable
294 ip = get_ipython()
293 ip = get_ipython()
295 ip._hidden_attr = 1
294 ip._hidden_attr = 1
296 ip._x = {}
295 ip._x = {}
297 c = ip.Completer
296 c = ip.Completer
298 ip.ex('ip=get_ipython()')
297 ip.ex('ip=get_ipython()')
299 cfg = Config()
298 cfg = Config()
300 cfg.IPCompleter.omit__names = 0
299 cfg.IPCompleter.omit__names = 0
301 c.update_config(cfg)
300 c.update_config(cfg)
302 s,matches = c.complete('ip.')
301 s,matches = c.complete('ip.')
303 nt.assert_in('ip.__str__', matches)
302 nt.assert_in('ip.__str__', matches)
304 nt.assert_in('ip._hidden_attr', matches)
303 nt.assert_in('ip._hidden_attr', matches)
305 cfg = Config()
304 cfg = Config()
306 cfg.IPCompleter.omit__names = 1
305 cfg.IPCompleter.omit__names = 1
307 c.update_config(cfg)
306 c.update_config(cfg)
308 s,matches = c.complete('ip.')
307 s,matches = c.complete('ip.')
309 nt.assert_not_in('ip.__str__', matches)
308 nt.assert_not_in('ip.__str__', matches)
310 nt.assert_in('ip._hidden_attr', matches)
309 nt.assert_in('ip._hidden_attr', matches)
311 cfg = Config()
310 cfg = Config()
312 cfg.IPCompleter.omit__names = 2
311 cfg.IPCompleter.omit__names = 2
313 c.update_config(cfg)
312 c.update_config(cfg)
314 s,matches = c.complete('ip.')
313 s,matches = c.complete('ip.')
315 nt.assert_not_in('ip.__str__', matches)
314 nt.assert_not_in('ip.__str__', matches)
316 nt.assert_not_in('ip._hidden_attr', matches)
315 nt.assert_not_in('ip._hidden_attr', matches)
317 s,matches = c.complete('ip._x.')
316 s,matches = c.complete('ip._x.')
318 nt.assert_in('ip._x.keys', matches)
317 nt.assert_in('ip._x.keys', matches)
319 del ip._hidden_attr
318 del ip._hidden_attr
320
319
321
320
322 def test_limit_to__all__False_ok():
321 def test_limit_to__all__False_ok():
323 ip = get_ipython()
322 ip = get_ipython()
324 c = ip.Completer
323 c = ip.Completer
325 ip.ex('class D: x=24')
324 ip.ex('class D: x=24')
326 ip.ex('d=D()')
325 ip.ex('d=D()')
327 cfg = Config()
326 cfg = Config()
328 cfg.IPCompleter.limit_to__all__ = False
327 cfg.IPCompleter.limit_to__all__ = False
329 c.update_config(cfg)
328 c.update_config(cfg)
330 s, matches = c.complete('d.')
329 s, matches = c.complete('d.')
331 nt.assert_in('d.x', matches)
330 nt.assert_in('d.x', matches)
332
331
333
332
334 def test_get__all__entries_ok():
333 def test_get__all__entries_ok():
335 class A(object):
334 class A(object):
336 __all__ = ['x', 1]
335 __all__ = ['x', 1]
337 words = completer.get__all__entries(A())
336 words = completer.get__all__entries(A())
338 nt.assert_equal(words, ['x'])
337 nt.assert_equal(words, ['x'])
339
338
340
339
341 def test_get__all__entries_no__all__ok():
340 def test_get__all__entries_no__all__ok():
342 class A(object):
341 class A(object):
343 pass
342 pass
344 words = completer.get__all__entries(A())
343 words = completer.get__all__entries(A())
345 nt.assert_equal(words, [])
344 nt.assert_equal(words, [])
346
345
347
346
348 def test_func_kw_completions():
347 def test_func_kw_completions():
349 ip = get_ipython()
348 ip = get_ipython()
350 c = ip.Completer
349 c = ip.Completer
351 ip.ex('def myfunc(a=1,b=2): return a+b')
350 ip.ex('def myfunc(a=1,b=2): return a+b')
352 s, matches = c.complete(None, 'myfunc(1,b')
351 s, matches = c.complete(None, 'myfunc(1,b')
353 nt.assert_in('b=', matches)
352 nt.assert_in('b=', matches)
354 # Simulate completing with cursor right after b (pos==10):
353 # Simulate completing with cursor right after b (pos==10):
355 s, matches = c.complete(None, 'myfunc(1,b)', 10)
354 s, matches = c.complete(None, 'myfunc(1,b)', 10)
356 nt.assert_in('b=', matches)
355 nt.assert_in('b=', matches)
357 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
356 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
358 nt.assert_in('b=', matches)
357 nt.assert_in('b=', matches)
359 #builtin function
358 #builtin function
360 s, matches = c.complete(None, 'min(k, k')
359 s, matches = c.complete(None, 'min(k, k')
361 nt.assert_in('key=', matches)
360 nt.assert_in('key=', matches)
362
361
363
362
364 def test_default_arguments_from_docstring():
363 def test_default_arguments_from_docstring():
365 ip = get_ipython()
364 ip = get_ipython()
366 c = ip.Completer
365 c = ip.Completer
367 kwd = c._default_arguments_from_docstring(
366 kwd = c._default_arguments_from_docstring(
368 'min(iterable[, key=func]) -> value')
367 'min(iterable[, key=func]) -> value')
369 nt.assert_equal(kwd, ['key'])
368 nt.assert_equal(kwd, ['key'])
370 #with cython type etc
369 #with cython type etc
371 kwd = c._default_arguments_from_docstring(
370 kwd = c._default_arguments_from_docstring(
372 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
371 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
373 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
372 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
374 #white spaces
373 #white spaces
375 kwd = c._default_arguments_from_docstring(
374 kwd = c._default_arguments_from_docstring(
376 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
375 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
377 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
376 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
378
377
379 def test_line_magics():
378 def test_line_magics():
380 ip = get_ipython()
379 ip = get_ipython()
381 c = ip.Completer
380 c = ip.Completer
382 s, matches = c.complete(None, 'lsmag')
381 s, matches = c.complete(None, 'lsmag')
383 nt.assert_in('%lsmagic', matches)
382 nt.assert_in('%lsmagic', matches)
384 s, matches = c.complete(None, '%lsmag')
383 s, matches = c.complete(None, '%lsmag')
385 nt.assert_in('%lsmagic', matches)
384 nt.assert_in('%lsmagic', matches)
386
385
387
386
388 def test_cell_magics():
387 def test_cell_magics():
389 from IPython.core.magic import register_cell_magic
388 from IPython.core.magic import register_cell_magic
390
389
391 @register_cell_magic
390 @register_cell_magic
392 def _foo_cellm(line, cell):
391 def _foo_cellm(line, cell):
393 pass
392 pass
394
393
395 ip = get_ipython()
394 ip = get_ipython()
396 c = ip.Completer
395 c = ip.Completer
397
396
398 s, matches = c.complete(None, '_foo_ce')
397 s, matches = c.complete(None, '_foo_ce')
399 nt.assert_in('%%_foo_cellm', matches)
398 nt.assert_in('%%_foo_cellm', matches)
400 s, matches = c.complete(None, '%%_foo_ce')
399 s, matches = c.complete(None, '%%_foo_ce')
401 nt.assert_in('%%_foo_cellm', matches)
400 nt.assert_in('%%_foo_cellm', matches)
402
401
403
402
404 def test_line_cell_magics():
403 def test_line_cell_magics():
405 from IPython.core.magic import register_line_cell_magic
404 from IPython.core.magic import register_line_cell_magic
406
405
407 @register_line_cell_magic
406 @register_line_cell_magic
408 def _bar_cellm(line, cell):
407 def _bar_cellm(line, cell):
409 pass
408 pass
410
409
411 ip = get_ipython()
410 ip = get_ipython()
412 c = ip.Completer
411 c = ip.Completer
413
412
414 # The policy here is trickier, see comments in completion code. The
413 # The policy here is trickier, see comments in completion code. The
415 # returned values depend on whether the user passes %% or not explicitly,
414 # returned values depend on whether the user passes %% or not explicitly,
416 # and this will show a difference if the same name is both a line and cell
415 # and this will show a difference if the same name is both a line and cell
417 # magic.
416 # magic.
418 s, matches = c.complete(None, '_bar_ce')
417 s, matches = c.complete(None, '_bar_ce')
419 nt.assert_in('%_bar_cellm', matches)
418 nt.assert_in('%_bar_cellm', matches)
420 nt.assert_in('%%_bar_cellm', matches)
419 nt.assert_in('%%_bar_cellm', matches)
421 s, matches = c.complete(None, '%_bar_ce')
420 s, matches = c.complete(None, '%_bar_ce')
422 nt.assert_in('%_bar_cellm', matches)
421 nt.assert_in('%_bar_cellm', matches)
423 nt.assert_in('%%_bar_cellm', matches)
422 nt.assert_in('%%_bar_cellm', matches)
424 s, matches = c.complete(None, '%%_bar_ce')
423 s, matches = c.complete(None, '%%_bar_ce')
425 nt.assert_not_in('%_bar_cellm', matches)
424 nt.assert_not_in('%_bar_cellm', matches)
426 nt.assert_in('%%_bar_cellm', matches)
425 nt.assert_in('%%_bar_cellm', matches)
427
426
428
427
429 def test_magic_completion_order():
428 def test_magic_completion_order():
430
429
431 ip = get_ipython()
430 ip = get_ipython()
432 c = ip.Completer
431 c = ip.Completer
433
432
434 # Test ordering of magics and non-magics with the same name
433 # Test ordering of magics and non-magics with the same name
435 # We want the non-magic first
434 # We want the non-magic first
436
435
437 # Before importing matplotlib, there should only be one option:
436 # Before importing matplotlib, there should only be one option:
438
437
439 text, matches = c.complete('mat')
438 text, matches = c.complete('mat')
440 nt.assert_equal(matches, ["%matplotlib"])
439 nt.assert_equal(matches, ["%matplotlib"])
441
440
442
441
443 ip.run_cell("matplotlib = 1") # introduce name into namespace
442 ip.run_cell("matplotlib = 1") # introduce name into namespace
444
443
445 # After the import, there should be two options, ordered like this:
444 # After the import, there should be two options, ordered like this:
446 text, matches = c.complete('mat')
445 text, matches = c.complete('mat')
447 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
446 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
448
447
449
448
450 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
449 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
451
450
452 # Order of user variable and line and cell magics with same name:
451 # Order of user variable and line and cell magics with same name:
453 text, matches = c.complete('timeit')
452 text, matches = c.complete('timeit')
454 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
453 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
455
454
456
455
457 def test_dict_key_completion_string():
456 def test_dict_key_completion_string():
458 """Test dictionary key completion for string keys"""
457 """Test dictionary key completion for string keys"""
459 ip = get_ipython()
458 ip = get_ipython()
460 complete = ip.Completer.complete
459 complete = ip.Completer.complete
461
460
462 ip.user_ns['d'] = {'abc': None}
461 ip.user_ns['d'] = {'abc': None}
463
462
464 # check completion at different stages
463 # check completion at different stages
465 _, matches = complete(line_buffer="d[")
464 _, matches = complete(line_buffer="d[")
466 nt.assert_in("'abc'", matches)
465 nt.assert_in("'abc'", matches)
467 nt.assert_not_in("'abc']", matches)
466 nt.assert_not_in("'abc']", matches)
468
467
469 _, matches = complete(line_buffer="d['")
468 _, matches = complete(line_buffer="d['")
470 nt.assert_in("abc", matches)
469 nt.assert_in("abc", matches)
471 nt.assert_not_in("abc']", matches)
470 nt.assert_not_in("abc']", matches)
472
471
473 _, matches = complete(line_buffer="d['a")
472 _, matches = complete(line_buffer="d['a")
474 nt.assert_in("abc", matches)
473 nt.assert_in("abc", matches)
475 nt.assert_not_in("abc']", matches)
474 nt.assert_not_in("abc']", matches)
476
475
477 # check use of different quoting
476 # check use of different quoting
478 _, matches = complete(line_buffer="d[\"")
477 _, matches = complete(line_buffer="d[\"")
479 nt.assert_in("abc", matches)
478 nt.assert_in("abc", matches)
480 nt.assert_not_in('abc\"]', matches)
479 nt.assert_not_in('abc\"]', matches)
481
480
482 _, matches = complete(line_buffer="d[\"a")
481 _, matches = complete(line_buffer="d[\"a")
483 nt.assert_in("abc", matches)
482 nt.assert_in("abc", matches)
484 nt.assert_not_in('abc\"]', matches)
483 nt.assert_not_in('abc\"]', matches)
485
484
486 # check sensitivity to following context
485 # check sensitivity to following context
487 _, matches = complete(line_buffer="d[]", cursor_pos=2)
486 _, matches = complete(line_buffer="d[]", cursor_pos=2)
488 nt.assert_in("'abc'", matches)
487 nt.assert_in("'abc'", matches)
489
488
490 _, matches = complete(line_buffer="d['']", cursor_pos=3)
489 _, matches = complete(line_buffer="d['']", cursor_pos=3)
491 nt.assert_in("abc", matches)
490 nt.assert_in("abc", matches)
492 nt.assert_not_in("abc'", matches)
491 nt.assert_not_in("abc'", matches)
493 nt.assert_not_in("abc']", matches)
492 nt.assert_not_in("abc']", matches)
494
493
495 # check multiple solutions are correctly returned and that noise is not
494 # check multiple solutions are correctly returned and that noise is not
496 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
495 ip.user_ns['d'] = {'abc': None, 'abd': None, 'bad': None, object(): None,
497 5: None}
496 5: None}
498
497
499 _, matches = complete(line_buffer="d['a")
498 _, matches = complete(line_buffer="d['a")
500 nt.assert_in("abc", matches)
499 nt.assert_in("abc", matches)
501 nt.assert_in("abd", matches)
500 nt.assert_in("abd", matches)
502 nt.assert_not_in("bad", matches)
501 nt.assert_not_in("bad", matches)
503 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
502 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
504
503
505 # check escaping and whitespace
504 # check escaping and whitespace
506 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
505 ip.user_ns['d'] = {'a\nb': None, 'a\'b': None, 'a"b': None, 'a word': None}
507 _, matches = complete(line_buffer="d['a")
506 _, matches = complete(line_buffer="d['a")
508 nt.assert_in("a\\nb", matches)
507 nt.assert_in("a\\nb", matches)
509 nt.assert_in("a\\'b", matches)
508 nt.assert_in("a\\'b", matches)
510 nt.assert_in("a\"b", matches)
509 nt.assert_in("a\"b", matches)
511 nt.assert_in("a word", matches)
510 nt.assert_in("a word", matches)
512 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
511 assert not any(m.endswith((']', '"', "'")) for m in matches), matches
513
512
514 # - can complete on non-initial word of the string
513 # - can complete on non-initial word of the string
515 _, matches = complete(line_buffer="d['a w")
514 _, matches = complete(line_buffer="d['a w")
516 nt.assert_in("word", matches)
515 nt.assert_in("word", matches)
517
516
518 # - understands quote escaping
517 # - understands quote escaping
519 _, matches = complete(line_buffer="d['a\\'")
518 _, matches = complete(line_buffer="d['a\\'")
520 nt.assert_in("b", matches)
519 nt.assert_in("b", matches)
521
520
522 # - default quoting should work like repr
521 # - default quoting should work like repr
523 _, matches = complete(line_buffer="d[")
522 _, matches = complete(line_buffer="d[")
524 nt.assert_in("\"a'b\"", matches)
523 nt.assert_in("\"a'b\"", matches)
525
524
526 # - when opening quote with ", possible to match with unescaped apostrophe
525 # - when opening quote with ", possible to match with unescaped apostrophe
527 _, matches = complete(line_buffer="d[\"a'")
526 _, matches = complete(line_buffer="d[\"a'")
528 nt.assert_in("b", matches)
527 nt.assert_in("b", matches)
529
528
530 # need to not split at delims that readline won't split at
529 # need to not split at delims that readline won't split at
531 if '-' not in ip.Completer.splitter.delims:
530 if '-' not in ip.Completer.splitter.delims:
532 ip.user_ns['d'] = {'before-after': None}
531 ip.user_ns['d'] = {'before-after': None}
533 _, matches = complete(line_buffer="d['before-af")
532 _, matches = complete(line_buffer="d['before-af")
534 nt.assert_in('before-after', matches)
533 nt.assert_in('before-after', matches)
535
534
536 def test_dict_key_completion_contexts():
535 def test_dict_key_completion_contexts():
537 """Test expression contexts in which dict key completion occurs"""
536 """Test expression contexts in which dict key completion occurs"""
538 ip = get_ipython()
537 ip = get_ipython()
539 complete = ip.Completer.complete
538 complete = ip.Completer.complete
540 d = {'abc': None}
539 d = {'abc': None}
541 ip.user_ns['d'] = d
540 ip.user_ns['d'] = d
542
541
543 class C:
542 class C:
544 data = d
543 data = d
545 ip.user_ns['C'] = C
544 ip.user_ns['C'] = C
546 ip.user_ns['get'] = lambda: d
545 ip.user_ns['get'] = lambda: d
547
546
548 def assert_no_completion(**kwargs):
547 def assert_no_completion(**kwargs):
549 _, matches = complete(**kwargs)
548 _, matches = complete(**kwargs)
550 nt.assert_not_in('abc', matches)
549 nt.assert_not_in('abc', matches)
551 nt.assert_not_in('abc\'', matches)
550 nt.assert_not_in('abc\'', matches)
552 nt.assert_not_in('abc\']', matches)
551 nt.assert_not_in('abc\']', matches)
553 nt.assert_not_in('\'abc\'', matches)
552 nt.assert_not_in('\'abc\'', matches)
554 nt.assert_not_in('\'abc\']', matches)
553 nt.assert_not_in('\'abc\']', matches)
555
554
556 def assert_completion(**kwargs):
555 def assert_completion(**kwargs):
557 _, matches = complete(**kwargs)
556 _, matches = complete(**kwargs)
558 nt.assert_in("'abc'", matches)
557 nt.assert_in("'abc'", matches)
559 nt.assert_not_in("'abc']", matches)
558 nt.assert_not_in("'abc']", matches)
560
559
561 # no completion after string closed, even if reopened
560 # no completion after string closed, even if reopened
562 assert_no_completion(line_buffer="d['a'")
561 assert_no_completion(line_buffer="d['a'")
563 assert_no_completion(line_buffer="d[\"a\"")
562 assert_no_completion(line_buffer="d[\"a\"")
564 assert_no_completion(line_buffer="d['a' + ")
563 assert_no_completion(line_buffer="d['a' + ")
565 assert_no_completion(line_buffer="d['a' + '")
564 assert_no_completion(line_buffer="d['a' + '")
566
565
567 # completion in non-trivial expressions
566 # completion in non-trivial expressions
568 assert_completion(line_buffer="+ d[")
567 assert_completion(line_buffer="+ d[")
569 assert_completion(line_buffer="(d[")
568 assert_completion(line_buffer="(d[")
570 assert_completion(line_buffer="C.data[")
569 assert_completion(line_buffer="C.data[")
571
570
572 # greedy flag
571 # greedy flag
573 def assert_completion(**kwargs):
572 def assert_completion(**kwargs):
574 _, matches = complete(**kwargs)
573 _, matches = complete(**kwargs)
575 nt.assert_in("get()['abc']", matches)
574 nt.assert_in("get()['abc']", matches)
576
575
577 assert_no_completion(line_buffer="get()[")
576 assert_no_completion(line_buffer="get()[")
578 with greedy_completion():
577 with greedy_completion():
579 assert_completion(line_buffer="get()[")
578 assert_completion(line_buffer="get()[")
580 assert_completion(line_buffer="get()['")
579 assert_completion(line_buffer="get()['")
581 assert_completion(line_buffer="get()['a")
580 assert_completion(line_buffer="get()['a")
582 assert_completion(line_buffer="get()['ab")
581 assert_completion(line_buffer="get()['ab")
583 assert_completion(line_buffer="get()['abc")
582 assert_completion(line_buffer="get()['abc")
584
583
585
584
586
585
587 def test_dict_key_completion_bytes():
586 def test_dict_key_completion_bytes():
588 """Test handling of bytes in dict key completion"""
587 """Test handling of bytes in dict key completion"""
589 ip = get_ipython()
588 ip = get_ipython()
590 complete = ip.Completer.complete
589 complete = ip.Completer.complete
591
590
592 ip.user_ns['d'] = {'abc': None, b'abd': None}
591 ip.user_ns['d'] = {'abc': None, b'abd': None}
593
592
594 _, matches = complete(line_buffer="d[")
593 _, matches = complete(line_buffer="d[")
595 nt.assert_in("'abc'", matches)
594 nt.assert_in("'abc'", matches)
596 nt.assert_in("b'abd'", matches)
595 nt.assert_in("b'abd'", matches)
597
596
598 if False: # not currently implemented
597 if False: # not currently implemented
599 _, matches = complete(line_buffer="d[b")
598 _, matches = complete(line_buffer="d[b")
600 nt.assert_in("b'abd'", matches)
599 nt.assert_in("b'abd'", matches)
601 nt.assert_not_in("b'abc'", matches)
600 nt.assert_not_in("b'abc'", matches)
602
601
603 _, matches = complete(line_buffer="d[b'")
602 _, matches = complete(line_buffer="d[b'")
604 nt.assert_in("abd", matches)
603 nt.assert_in("abd", matches)
605 nt.assert_not_in("abc", matches)
604 nt.assert_not_in("abc", matches)
606
605
607 _, matches = complete(line_buffer="d[B'")
606 _, matches = complete(line_buffer="d[B'")
608 nt.assert_in("abd", matches)
607 nt.assert_in("abd", matches)
609 nt.assert_not_in("abc", matches)
608 nt.assert_not_in("abc", matches)
610
609
611 _, matches = complete(line_buffer="d['")
610 _, matches = complete(line_buffer="d['")
612 nt.assert_in("abc", matches)
611 nt.assert_in("abc", matches)
613 nt.assert_not_in("abd", matches)
612 nt.assert_not_in("abd", matches)
614
613
615
614
616 def test_dict_key_completion_unicode_py3():
615 def test_dict_key_completion_unicode_py3():
617 """Test handling of unicode in dict key completion"""
616 """Test handling of unicode in dict key completion"""
618 ip = get_ipython()
617 ip = get_ipython()
619 complete = ip.Completer.complete
618 complete = ip.Completer.complete
620
619
621 ip.user_ns['d'] = {u'a\u05d0': None}
620 ip.user_ns['d'] = {u'a\u05d0': None}
622
621
623 # query using escape
622 # query using escape
624 if sys.platform != 'win32':
623 if sys.platform != 'win32':
625 # Known failure on Windows
624 # Known failure on Windows
626 _, matches = complete(line_buffer="d['a\\u05d0")
625 _, matches = complete(line_buffer="d['a\\u05d0")
627 nt.assert_in("u05d0", matches) # tokenized after \\
626 nt.assert_in("u05d0", matches) # tokenized after \\
628
627
629 # query using character
628 # query using character
630 _, matches = complete(line_buffer="d['a\u05d0")
629 _, matches = complete(line_buffer="d['a\u05d0")
631 nt.assert_in(u"a\u05d0", matches)
630 nt.assert_in(u"a\u05d0", matches)
632
631
633 with greedy_completion():
632 with greedy_completion():
634 # query using escape
633 # query using escape
635 _, matches = complete(line_buffer="d['a\\u05d0")
634 _, matches = complete(line_buffer="d['a\\u05d0")
636 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
635 nt.assert_in("d['a\\u05d0']", matches) # tokenized after \\
637
636
638 # query using character
637 # query using character
639 _, matches = complete(line_buffer="d['a\u05d0")
638 _, matches = complete(line_buffer="d['a\u05d0")
640 nt.assert_in(u"d['a\u05d0']", matches)
639 nt.assert_in(u"d['a\u05d0']", matches)
641
640
642
641
643
642
644 @dec.skip_without('numpy')
643 @dec.skip_without('numpy')
645 def test_struct_array_key_completion():
644 def test_struct_array_key_completion():
646 """Test dict key completion applies to numpy struct arrays"""
645 """Test dict key completion applies to numpy struct arrays"""
647 import numpy
646 import numpy
648 ip = get_ipython()
647 ip = get_ipython()
649 complete = ip.Completer.complete
648 complete = ip.Completer.complete
650 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
649 ip.user_ns['d'] = numpy.array([], dtype=[('hello', 'f'), ('world', 'f')])
651 _, matches = complete(line_buffer="d['")
650 _, matches = complete(line_buffer="d['")
652 nt.assert_in("hello", matches)
651 nt.assert_in("hello", matches)
653 nt.assert_in("world", matches)
652 nt.assert_in("world", matches)
654 # complete on the numpy struct itself
653 # complete on the numpy struct itself
655 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
654 dt = numpy.dtype([('my_head', [('my_dt', '>u4'), ('my_df', '>u4')]),
656 ('my_data', '>f4', 5)])
655 ('my_data', '>f4', 5)])
657 x = numpy.zeros(2, dtype=dt)
656 x = numpy.zeros(2, dtype=dt)
658 ip.user_ns['d'] = x[1]
657 ip.user_ns['d'] = x[1]
659 _, matches = complete(line_buffer="d['")
658 _, matches = complete(line_buffer="d['")
660 nt.assert_in("my_head", matches)
659 nt.assert_in("my_head", matches)
661 nt.assert_in("my_data", matches)
660 nt.assert_in("my_data", matches)
662 # complete on a nested level
661 # complete on a nested level
663 with greedy_completion():
662 with greedy_completion():
664 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
663 ip.user_ns['d'] = numpy.zeros(2, dtype=dt)
665 _, matches = complete(line_buffer="d[1]['my_head']['")
664 _, matches = complete(line_buffer="d[1]['my_head']['")
666 nt.assert_true(any(["my_dt" in m for m in matches]))
665 nt.assert_true(any(["my_dt" in m for m in matches]))
667 nt.assert_true(any(["my_df" in m for m in matches]))
666 nt.assert_true(any(["my_df" in m for m in matches]))
668
667
669
668
670 @dec.skip_without('pandas')
669 @dec.skip_without('pandas')
671 def test_dataframe_key_completion():
670 def test_dataframe_key_completion():
672 """Test dict key completion applies to pandas DataFrames"""
671 """Test dict key completion applies to pandas DataFrames"""
673 import pandas
672 import pandas
674 ip = get_ipython()
673 ip = get_ipython()
675 complete = ip.Completer.complete
674 complete = ip.Completer.complete
676 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
675 ip.user_ns['d'] = pandas.DataFrame({'hello': [1], 'world': [2]})
677 _, matches = complete(line_buffer="d['")
676 _, matches = complete(line_buffer="d['")
678 nt.assert_in("hello", matches)
677 nt.assert_in("hello", matches)
679 nt.assert_in("world", matches)
678 nt.assert_in("world", matches)
680
679
681
680
682 def test_dict_key_completion_invalids():
681 def test_dict_key_completion_invalids():
683 """Smoke test cases dict key completion can't handle"""
682 """Smoke test cases dict key completion can't handle"""
684 ip = get_ipython()
683 ip = get_ipython()
685 complete = ip.Completer.complete
684 complete = ip.Completer.complete
686
685
687 ip.user_ns['no_getitem'] = None
686 ip.user_ns['no_getitem'] = None
688 ip.user_ns['no_keys'] = []
687 ip.user_ns['no_keys'] = []
689 ip.user_ns['cant_call_keys'] = dict
688 ip.user_ns['cant_call_keys'] = dict
690 ip.user_ns['empty'] = {}
689 ip.user_ns['empty'] = {}
691 ip.user_ns['d'] = {'abc': 5}
690 ip.user_ns['d'] = {'abc': 5}
692
691
693 _, matches = complete(line_buffer="no_getitem['")
692 _, matches = complete(line_buffer="no_getitem['")
694 _, matches = complete(line_buffer="no_keys['")
693 _, matches = complete(line_buffer="no_keys['")
695 _, matches = complete(line_buffer="cant_call_keys['")
694 _, matches = complete(line_buffer="cant_call_keys['")
696 _, matches = complete(line_buffer="empty['")
695 _, matches = complete(line_buffer="empty['")
697 _, matches = complete(line_buffer="name_error['")
696 _, matches = complete(line_buffer="name_error['")
698 _, matches = complete(line_buffer="d['\\") # incomplete escape
697 _, matches = complete(line_buffer="d['\\") # incomplete escape
699
698
700 class KeyCompletable(object):
699 class KeyCompletable(object):
701 def __init__(self, things=()):
700 def __init__(self, things=()):
702 self.things = things
701 self.things = things
703
702
704 def _ipython_key_completions_(self):
703 def _ipython_key_completions_(self):
705 return list(self.things)
704 return list(self.things)
706
705
707 def test_object_key_completion():
706 def test_object_key_completion():
708 ip = get_ipython()
707 ip = get_ipython()
709 ip.user_ns['key_completable'] = KeyCompletable(['qwerty', 'qwick'])
708 ip.user_ns['key_completable'] = KeyCompletable(['qwerty', 'qwick'])
710
709
711 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
710 _, matches = ip.Completer.complete(line_buffer="key_completable['qw")
712 nt.assert_in('qwerty', matches)
711 nt.assert_in('qwerty', matches)
713 nt.assert_in('qwick', matches)
712 nt.assert_in('qwick', matches)
714
713
715
714
716 def test_aimport_module_completer():
715 def test_aimport_module_completer():
717 ip = get_ipython()
716 ip = get_ipython()
718 _, matches = ip.complete('i', '%aimport i')
717 _, matches = ip.complete('i', '%aimport i')
719 nt.assert_in('io', matches)
718 nt.assert_in('io', matches)
720 nt.assert_not_in('int', matches)
719 nt.assert_not_in('int', matches)
721
720
722 def test_nested_import_module_completer():
721 def test_nested_import_module_completer():
723 ip = get_ipython()
722 ip = get_ipython()
724 _, matches = ip.complete(None, 'import IPython.co', 17)
723 _, matches = ip.complete(None, 'import IPython.co', 17)
725 nt.assert_in('IPython.core', matches)
724 nt.assert_in('IPython.core', matches)
726 nt.assert_not_in('import IPython.core', matches)
725 nt.assert_not_in('import IPython.core', matches)
727 nt.assert_not_in('IPython.display', matches)
726 nt.assert_not_in('IPython.display', matches)
728
727
729 def test_import_module_completer():
728 def test_import_module_completer():
730 ip = get_ipython()
729 ip = get_ipython()
731 _, matches = ip.complete('i', 'import i')
730 _, matches = ip.complete('i', 'import i')
732 nt.assert_in('io', matches)
731 nt.assert_in('io', matches)
733 nt.assert_not_in('int', matches)
732 nt.assert_not_in('int', matches)
734
733
735 def test_from_module_completer():
734 def test_from_module_completer():
736 ip = get_ipython()
735 ip = get_ipython()
737 _, matches = ip.complete('B', 'from io import B', 16)
736 _, matches = ip.complete('B', 'from io import B', 16)
738 nt.assert_in('BytesIO', matches)
737 nt.assert_in('BytesIO', matches)
739 nt.assert_not_in('BaseException', matches)
738 nt.assert_not_in('BaseException', matches)
@@ -1,162 +1,162 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for completerlib.
2 """Tests for completerlib.
3
3
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Imports
7 # Imports
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 import os
10 import os
11 import shutil
11 import shutil
12 import sys
12 import sys
13 import tempfile
13 import tempfile
14 import unittest
14 import unittest
15 from os.path import join
15 from os.path import join
16
16
17 import nose.tools as nt
17 import nose.tools as nt
18
18
19 from IPython.core.completerlib import magic_run_completer, module_completion
19 from IPython.core.completerlib import magic_run_completer, module_completion
20 from IPython.utils import py3compat
20 from IPython.utils import py3compat
21 from IPython.utils.tempdir import TemporaryDirectory
21 from IPython.utils.tempdir import TemporaryDirectory
22 from IPython.testing.decorators import onlyif_unicode_paths
22 from IPython.testing.decorators import onlyif_unicode_paths
23
23
24
24
25 class MockEvent(object):
25 class MockEvent(object):
26 def __init__(self, line):
26 def __init__(self, line):
27 self.line = line
27 self.line = line
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Test functions begin
30 # Test functions begin
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 class Test_magic_run_completer(unittest.TestCase):
32 class Test_magic_run_completer(unittest.TestCase):
33 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
33 files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
34 dirs = [u"adir/", "bdir/"]
34 dirs = [u"adir/", "bdir/"]
35
35
36 def setUp(self):
36 def setUp(self):
37 self.BASETESTDIR = tempfile.mkdtemp()
37 self.BASETESTDIR = tempfile.mkdtemp()
38 for fil in self.files:
38 for fil in self.files:
39 with open(join(self.BASETESTDIR, fil), "w") as sfile:
39 with open(join(self.BASETESTDIR, fil), "w") as sfile:
40 sfile.write("pass\n")
40 sfile.write("pass\n")
41 for d in self.dirs:
41 for d in self.dirs:
42 os.mkdir(join(self.BASETESTDIR, d))
42 os.mkdir(join(self.BASETESTDIR, d))
43
43
44 self.oldpath = py3compat.getcwd()
44 self.oldpath = os.getcwd()
45 os.chdir(self.BASETESTDIR)
45 os.chdir(self.BASETESTDIR)
46
46
47 def tearDown(self):
47 def tearDown(self):
48 os.chdir(self.oldpath)
48 os.chdir(self.oldpath)
49 shutil.rmtree(self.BASETESTDIR)
49 shutil.rmtree(self.BASETESTDIR)
50
50
51 def test_1(self):
51 def test_1(self):
52 """Test magic_run_completer, should match two alterntives
52 """Test magic_run_completer, should match two alterntives
53 """
53 """
54 event = MockEvent(u"%run a")
54 event = MockEvent(u"%run a")
55 mockself = None
55 mockself = None
56 match = set(magic_run_completer(mockself, event))
56 match = set(magic_run_completer(mockself, event))
57 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
57 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
58
58
59 def test_2(self):
59 def test_2(self):
60 """Test magic_run_completer, should match one alterntive
60 """Test magic_run_completer, should match one alterntive
61 """
61 """
62 event = MockEvent(u"%run aa")
62 event = MockEvent(u"%run aa")
63 mockself = None
63 mockself = None
64 match = set(magic_run_completer(mockself, event))
64 match = set(magic_run_completer(mockself, event))
65 self.assertEqual(match, {u"aao.py"})
65 self.assertEqual(match, {u"aao.py"})
66
66
67 def test_3(self):
67 def test_3(self):
68 """Test magic_run_completer with unterminated " """
68 """Test magic_run_completer with unterminated " """
69 event = MockEvent(u'%run "a')
69 event = MockEvent(u'%run "a')
70 mockself = None
70 mockself = None
71 match = set(magic_run_completer(mockself, event))
71 match = set(magic_run_completer(mockself, event))
72 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
72 self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
73
73
74 def test_completion_more_args(self):
74 def test_completion_more_args(self):
75 event = MockEvent(u'%run a.py ')
75 event = MockEvent(u'%run a.py ')
76 match = set(magic_run_completer(None, event))
76 match = set(magic_run_completer(None, event))
77 self.assertEqual(match, set(self.files + self.dirs))
77 self.assertEqual(match, set(self.files + self.dirs))
78
78
79 def test_completion_in_dir(self):
79 def test_completion_in_dir(self):
80 # Github issue #3459
80 # Github issue #3459
81 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
81 event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
82 print(repr(event.line))
82 print(repr(event.line))
83 match = set(magic_run_completer(None, event))
83 match = set(magic_run_completer(None, event))
84 # We specifically use replace here rather than normpath, because
84 # We specifically use replace here rather than normpath, because
85 # at one point there were duplicates 'adir' and 'adir/', and normpath
85 # at one point there were duplicates 'adir' and 'adir/', and normpath
86 # would hide the failure for that.
86 # would hide the failure for that.
87 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
87 self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
88 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
88 for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
89
89
90 class Test_magic_run_completer_nonascii(unittest.TestCase):
90 class Test_magic_run_completer_nonascii(unittest.TestCase):
91 @onlyif_unicode_paths
91 @onlyif_unicode_paths
92 def setUp(self):
92 def setUp(self):
93 self.BASETESTDIR = tempfile.mkdtemp()
93 self.BASETESTDIR = tempfile.mkdtemp()
94 for fil in [u"aaø.py", u"a.py", u"b.py"]:
94 for fil in [u"aaø.py", u"a.py", u"b.py"]:
95 with open(join(self.BASETESTDIR, fil), "w") as sfile:
95 with open(join(self.BASETESTDIR, fil), "w") as sfile:
96 sfile.write("pass\n")
96 sfile.write("pass\n")
97 self.oldpath = py3compat.getcwd()
97 self.oldpath = os.getcwd()
98 os.chdir(self.BASETESTDIR)
98 os.chdir(self.BASETESTDIR)
99
99
100 def tearDown(self):
100 def tearDown(self):
101 os.chdir(self.oldpath)
101 os.chdir(self.oldpath)
102 shutil.rmtree(self.BASETESTDIR)
102 shutil.rmtree(self.BASETESTDIR)
103
103
104 @onlyif_unicode_paths
104 @onlyif_unicode_paths
105 def test_1(self):
105 def test_1(self):
106 """Test magic_run_completer, should match two alterntives
106 """Test magic_run_completer, should match two alterntives
107 """
107 """
108 event = MockEvent(u"%run a")
108 event = MockEvent(u"%run a")
109 mockself = None
109 mockself = None
110 match = set(magic_run_completer(mockself, event))
110 match = set(magic_run_completer(mockself, event))
111 self.assertEqual(match, {u"a.py", u"aaø.py"})
111 self.assertEqual(match, {u"a.py", u"aaø.py"})
112
112
113 @onlyif_unicode_paths
113 @onlyif_unicode_paths
114 def test_2(self):
114 def test_2(self):
115 """Test magic_run_completer, should match one alterntive
115 """Test magic_run_completer, should match one alterntive
116 """
116 """
117 event = MockEvent(u"%run aa")
117 event = MockEvent(u"%run aa")
118 mockself = None
118 mockself = None
119 match = set(magic_run_completer(mockself, event))
119 match = set(magic_run_completer(mockself, event))
120 self.assertEqual(match, {u"aaø.py"})
120 self.assertEqual(match, {u"aaø.py"})
121
121
122 @onlyif_unicode_paths
122 @onlyif_unicode_paths
123 def test_3(self):
123 def test_3(self):
124 """Test magic_run_completer with unterminated " """
124 """Test magic_run_completer with unterminated " """
125 event = MockEvent(u'%run "a')
125 event = MockEvent(u'%run "a')
126 mockself = None
126 mockself = None
127 match = set(magic_run_completer(mockself, event))
127 match = set(magic_run_completer(mockself, event))
128 self.assertEqual(match, {u"a.py", u"aaø.py"})
128 self.assertEqual(match, {u"a.py", u"aaø.py"})
129
129
130 # module_completer:
130 # module_completer:
131
131
132 def test_import_invalid_module():
132 def test_import_invalid_module():
133 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
133 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
134 invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
134 invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
135 valid_module_names = {'foobar'}
135 valid_module_names = {'foobar'}
136 with TemporaryDirectory() as tmpdir:
136 with TemporaryDirectory() as tmpdir:
137 sys.path.insert( 0, tmpdir )
137 sys.path.insert( 0, tmpdir )
138 for name in invalid_module_names | valid_module_names:
138 for name in invalid_module_names | valid_module_names:
139 filename = os.path.join(tmpdir, name + '.py')
139 filename = os.path.join(tmpdir, name + '.py')
140 open(filename, 'w').close()
140 open(filename, 'w').close()
141
141
142 s = set( module_completion('import foo') )
142 s = set( module_completion('import foo') )
143 intersection = s.intersection(invalid_module_names)
143 intersection = s.intersection(invalid_module_names)
144 nt.assert_equal(intersection, set())
144 nt.assert_equal(intersection, set())
145
145
146 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
146 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
147
147
148
148
149 def test_bad_module_all():
149 def test_bad_module_all():
150 """Test module with invalid __all__
150 """Test module with invalid __all__
151
151
152 https://github.com/ipython/ipython/issues/9678
152 https://github.com/ipython/ipython/issues/9678
153 """
153 """
154 testsdir = os.path.dirname(__file__)
154 testsdir = os.path.dirname(__file__)
155 sys.path.insert(0, testsdir)
155 sys.path.insert(0, testsdir)
156 try:
156 try:
157 results = module_completion('from bad_all import ')
157 results = module_completion('from bad_all import ')
158 nt.assert_in('puppies', results)
158 nt.assert_in('puppies', results)
159 for r in results:
159 for r in results:
160 nt.assert_is_instance(r, py3compat.string_types)
160 nt.assert_is_instance(r, str)
161 finally:
161 finally:
162 sys.path.remove(testsdir)
162 sys.path.remove(testsdir)
@@ -1,614 +1,614 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the inputsplitter module."""
2 """Tests for the inputsplitter module."""
3
3
4
4
5 # Copyright (c) IPython Development Team.
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7
7
8 import unittest
8 import unittest
9 import sys
9 import sys
10
10
11 import nose.tools as nt
11 import nose.tools as nt
12
12
13 from IPython.core import inputsplitter as isp
13 from IPython.core import inputsplitter as isp
14 from IPython.core.inputtransformer import InputTransformer
14 from IPython.core.inputtransformer import InputTransformer
15 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
15 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
16 from IPython.testing import tools as tt
16 from IPython.testing import tools as tt
17 from IPython.utils import py3compat
17 from IPython.utils import py3compat
18 from IPython.utils.py3compat import string_types, input
18 from IPython.utils.py3compat import input
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Semi-complete examples (also used as tests)
21 # Semi-complete examples (also used as tests)
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 # Note: at the bottom, there's a slightly more complete version of this that
24 # Note: at the bottom, there's a slightly more complete version of this that
25 # can be useful during development of code here.
25 # can be useful during development of code here.
26
26
27 def mini_interactive_loop(input_func):
27 def mini_interactive_loop(input_func):
28 """Minimal example of the logic of an interactive interpreter loop.
28 """Minimal example of the logic of an interactive interpreter loop.
29
29
30 This serves as an example, and it is used by the test system with a fake
30 This serves as an example, and it is used by the test system with a fake
31 raw_input that simulates interactive input."""
31 raw_input that simulates interactive input."""
32
32
33 from IPython.core.inputsplitter import InputSplitter
33 from IPython.core.inputsplitter import InputSplitter
34
34
35 isp = InputSplitter()
35 isp = InputSplitter()
36 # In practice, this input loop would be wrapped in an outside loop to read
36 # In practice, this input loop would be wrapped in an outside loop to read
37 # input indefinitely, until some exit/quit command was issued. Here we
37 # input indefinitely, until some exit/quit command was issued. Here we
38 # only illustrate the basic inner loop.
38 # only illustrate the basic inner loop.
39 while isp.push_accepts_more():
39 while isp.push_accepts_more():
40 indent = ' '*isp.indent_spaces
40 indent = ' '*isp.indent_spaces
41 prompt = '>>> ' + indent
41 prompt = '>>> ' + indent
42 line = indent + input_func(prompt)
42 line = indent + input_func(prompt)
43 isp.push(line)
43 isp.push(line)
44
44
45 # Here we just return input so we can use it in a test suite, but a real
45 # Here we just return input so we can use it in a test suite, but a real
46 # interpreter would instead send it for execution somewhere.
46 # interpreter would instead send it for execution somewhere.
47 src = isp.source_reset()
47 src = isp.source_reset()
48 #print 'Input source was:\n', src # dbg
48 #print 'Input source was:\n', src # dbg
49 return src
49 return src
50
50
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52 # Test utilities, just for local use
52 # Test utilities, just for local use
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54
54
55 def assemble(block):
55 def assemble(block):
56 """Assemble a block into multi-line sub-blocks."""
56 """Assemble a block into multi-line sub-blocks."""
57 return ['\n'.join(sub_block)+'\n' for sub_block in block]
57 return ['\n'.join(sub_block)+'\n' for sub_block in block]
58
58
59
59
60 def pseudo_input(lines):
60 def pseudo_input(lines):
61 """Return a function that acts like raw_input but feeds the input list."""
61 """Return a function that acts like raw_input but feeds the input list."""
62 ilines = iter(lines)
62 ilines = iter(lines)
63 def raw_in(prompt):
63 def raw_in(prompt):
64 try:
64 try:
65 return next(ilines)
65 return next(ilines)
66 except StopIteration:
66 except StopIteration:
67 return ''
67 return ''
68 return raw_in
68 return raw_in
69
69
70 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
71 # Tests
71 # Tests
72 #-----------------------------------------------------------------------------
72 #-----------------------------------------------------------------------------
73 def test_spaces():
73 def test_spaces():
74 tests = [('', 0),
74 tests = [('', 0),
75 (' ', 1),
75 (' ', 1),
76 ('\n', 0),
76 ('\n', 0),
77 (' \n', 1),
77 (' \n', 1),
78 ('x', 0),
78 ('x', 0),
79 (' x', 1),
79 (' x', 1),
80 (' x',2),
80 (' x',2),
81 (' x',4),
81 (' x',4),
82 # Note: tabs are counted as a single whitespace!
82 # Note: tabs are counted as a single whitespace!
83 ('\tx', 1),
83 ('\tx', 1),
84 ('\t x', 2),
84 ('\t x', 2),
85 ]
85 ]
86 tt.check_pairs(isp.num_ini_spaces, tests)
86 tt.check_pairs(isp.num_ini_spaces, tests)
87
87
88
88
89 def test_remove_comments():
89 def test_remove_comments():
90 tests = [('text', 'text'),
90 tests = [('text', 'text'),
91 ('text # comment', 'text '),
91 ('text # comment', 'text '),
92 ('text # comment\n', 'text \n'),
92 ('text # comment\n', 'text \n'),
93 ('text # comment \n', 'text \n'),
93 ('text # comment \n', 'text \n'),
94 ('line # c \nline\n','line \nline\n'),
94 ('line # c \nline\n','line \nline\n'),
95 ('line # c \nline#c2 \nline\nline #c\n\n',
95 ('line # c \nline#c2 \nline\nline #c\n\n',
96 'line \nline\nline\nline \n\n'),
96 'line \nline\nline\nline \n\n'),
97 ]
97 ]
98 tt.check_pairs(isp.remove_comments, tests)
98 tt.check_pairs(isp.remove_comments, tests)
99
99
100
100
101 def test_get_input_encoding():
101 def test_get_input_encoding():
102 encoding = isp.get_input_encoding()
102 encoding = isp.get_input_encoding()
103 nt.assert_true(isinstance(encoding, string_types))
103 nt.assert_true(isinstance(encoding, str))
104 # simple-minded check that at least encoding a simple string works with the
104 # simple-minded check that at least encoding a simple string works with the
105 # encoding we got.
105 # encoding we got.
106 nt.assert_equal(u'test'.encode(encoding), b'test')
106 nt.assert_equal(u'test'.encode(encoding), b'test')
107
107
108
108
109 class NoInputEncodingTestCase(unittest.TestCase):
109 class NoInputEncodingTestCase(unittest.TestCase):
110 def setUp(self):
110 def setUp(self):
111 self.old_stdin = sys.stdin
111 self.old_stdin = sys.stdin
112 class X: pass
112 class X: pass
113 fake_stdin = X()
113 fake_stdin = X()
114 sys.stdin = fake_stdin
114 sys.stdin = fake_stdin
115
115
116 def test(self):
116 def test(self):
117 # Verify that if sys.stdin has no 'encoding' attribute we do the right
117 # Verify that if sys.stdin has no 'encoding' attribute we do the right
118 # thing
118 # thing
119 enc = isp.get_input_encoding()
119 enc = isp.get_input_encoding()
120 self.assertEqual(enc, 'ascii')
120 self.assertEqual(enc, 'ascii')
121
121
122 def tearDown(self):
122 def tearDown(self):
123 sys.stdin = self.old_stdin
123 sys.stdin = self.old_stdin
124
124
125
125
126 class InputSplitterTestCase(unittest.TestCase):
126 class InputSplitterTestCase(unittest.TestCase):
127 def setUp(self):
127 def setUp(self):
128 self.isp = isp.InputSplitter()
128 self.isp = isp.InputSplitter()
129
129
130 def test_reset(self):
130 def test_reset(self):
131 isp = self.isp
131 isp = self.isp
132 isp.push('x=1')
132 isp.push('x=1')
133 isp.reset()
133 isp.reset()
134 self.assertEqual(isp._buffer, [])
134 self.assertEqual(isp._buffer, [])
135 self.assertEqual(isp.indent_spaces, 0)
135 self.assertEqual(isp.indent_spaces, 0)
136 self.assertEqual(isp.source, '')
136 self.assertEqual(isp.source, '')
137 self.assertEqual(isp.code, None)
137 self.assertEqual(isp.code, None)
138 self.assertEqual(isp._is_complete, False)
138 self.assertEqual(isp._is_complete, False)
139
139
140 def test_source(self):
140 def test_source(self):
141 self.isp._store('1')
141 self.isp._store('1')
142 self.isp._store('2')
142 self.isp._store('2')
143 self.assertEqual(self.isp.source, '1\n2\n')
143 self.assertEqual(self.isp.source, '1\n2\n')
144 self.assertEqual(len(self.isp._buffer)>0, True)
144 self.assertEqual(len(self.isp._buffer)>0, True)
145 self.assertEqual(self.isp.source_reset(), '1\n2\n')
145 self.assertEqual(self.isp.source_reset(), '1\n2\n')
146 self.assertEqual(self.isp._buffer, [])
146 self.assertEqual(self.isp._buffer, [])
147 self.assertEqual(self.isp.source, '')
147 self.assertEqual(self.isp.source, '')
148
148
149 def test_indent(self):
149 def test_indent(self):
150 isp = self.isp # shorthand
150 isp = self.isp # shorthand
151 isp.push('x=1')
151 isp.push('x=1')
152 self.assertEqual(isp.indent_spaces, 0)
152 self.assertEqual(isp.indent_spaces, 0)
153 isp.push('if 1:\n x=1')
153 isp.push('if 1:\n x=1')
154 self.assertEqual(isp.indent_spaces, 4)
154 self.assertEqual(isp.indent_spaces, 4)
155 isp.push('y=2\n')
155 isp.push('y=2\n')
156 self.assertEqual(isp.indent_spaces, 0)
156 self.assertEqual(isp.indent_spaces, 0)
157
157
158 def test_indent2(self):
158 def test_indent2(self):
159 isp = self.isp
159 isp = self.isp
160 isp.push('if 1:')
160 isp.push('if 1:')
161 self.assertEqual(isp.indent_spaces, 4)
161 self.assertEqual(isp.indent_spaces, 4)
162 isp.push(' x=1')
162 isp.push(' x=1')
163 self.assertEqual(isp.indent_spaces, 4)
163 self.assertEqual(isp.indent_spaces, 4)
164 # Blank lines shouldn't change the indent level
164 # Blank lines shouldn't change the indent level
165 isp.push(' '*2)
165 isp.push(' '*2)
166 self.assertEqual(isp.indent_spaces, 4)
166 self.assertEqual(isp.indent_spaces, 4)
167
167
168 def test_indent3(self):
168 def test_indent3(self):
169 isp = self.isp
169 isp = self.isp
170 # When a multiline statement contains parens or multiline strings, we
170 # When a multiline statement contains parens or multiline strings, we
171 # shouldn't get confused.
171 # shouldn't get confused.
172 isp.push("if 1:")
172 isp.push("if 1:")
173 isp.push(" x = (1+\n 2)")
173 isp.push(" x = (1+\n 2)")
174 self.assertEqual(isp.indent_spaces, 4)
174 self.assertEqual(isp.indent_spaces, 4)
175
175
176 def test_indent4(self):
176 def test_indent4(self):
177 isp = self.isp
177 isp = self.isp
178 # whitespace after ':' should not screw up indent level
178 # whitespace after ':' should not screw up indent level
179 isp.push('if 1: \n x=1')
179 isp.push('if 1: \n x=1')
180 self.assertEqual(isp.indent_spaces, 4)
180 self.assertEqual(isp.indent_spaces, 4)
181 isp.push('y=2\n')
181 isp.push('y=2\n')
182 self.assertEqual(isp.indent_spaces, 0)
182 self.assertEqual(isp.indent_spaces, 0)
183 isp.push('if 1:\t\n x=1')
183 isp.push('if 1:\t\n x=1')
184 self.assertEqual(isp.indent_spaces, 4)
184 self.assertEqual(isp.indent_spaces, 4)
185 isp.push('y=2\n')
185 isp.push('y=2\n')
186 self.assertEqual(isp.indent_spaces, 0)
186 self.assertEqual(isp.indent_spaces, 0)
187
187
188 def test_dedent_pass(self):
188 def test_dedent_pass(self):
189 isp = self.isp # shorthand
189 isp = self.isp # shorthand
190 # should NOT cause dedent
190 # should NOT cause dedent
191 isp.push('if 1:\n passes = 5')
191 isp.push('if 1:\n passes = 5')
192 self.assertEqual(isp.indent_spaces, 4)
192 self.assertEqual(isp.indent_spaces, 4)
193 isp.push('if 1:\n pass')
193 isp.push('if 1:\n pass')
194 self.assertEqual(isp.indent_spaces, 0)
194 self.assertEqual(isp.indent_spaces, 0)
195 isp.push('if 1:\n pass ')
195 isp.push('if 1:\n pass ')
196 self.assertEqual(isp.indent_spaces, 0)
196 self.assertEqual(isp.indent_spaces, 0)
197
197
198 def test_dedent_break(self):
198 def test_dedent_break(self):
199 isp = self.isp # shorthand
199 isp = self.isp # shorthand
200 # should NOT cause dedent
200 # should NOT cause dedent
201 isp.push('while 1:\n breaks = 5')
201 isp.push('while 1:\n breaks = 5')
202 self.assertEqual(isp.indent_spaces, 4)
202 self.assertEqual(isp.indent_spaces, 4)
203 isp.push('while 1:\n break')
203 isp.push('while 1:\n break')
204 self.assertEqual(isp.indent_spaces, 0)
204 self.assertEqual(isp.indent_spaces, 0)
205 isp.push('while 1:\n break ')
205 isp.push('while 1:\n break ')
206 self.assertEqual(isp.indent_spaces, 0)
206 self.assertEqual(isp.indent_spaces, 0)
207
207
208 def test_dedent_continue(self):
208 def test_dedent_continue(self):
209 isp = self.isp # shorthand
209 isp = self.isp # shorthand
210 # should NOT cause dedent
210 # should NOT cause dedent
211 isp.push('while 1:\n continues = 5')
211 isp.push('while 1:\n continues = 5')
212 self.assertEqual(isp.indent_spaces, 4)
212 self.assertEqual(isp.indent_spaces, 4)
213 isp.push('while 1:\n continue')
213 isp.push('while 1:\n continue')
214 self.assertEqual(isp.indent_spaces, 0)
214 self.assertEqual(isp.indent_spaces, 0)
215 isp.push('while 1:\n continue ')
215 isp.push('while 1:\n continue ')
216 self.assertEqual(isp.indent_spaces, 0)
216 self.assertEqual(isp.indent_spaces, 0)
217
217
218 def test_dedent_raise(self):
218 def test_dedent_raise(self):
219 isp = self.isp # shorthand
219 isp = self.isp # shorthand
220 # should NOT cause dedent
220 # should NOT cause dedent
221 isp.push('if 1:\n raised = 4')
221 isp.push('if 1:\n raised = 4')
222 self.assertEqual(isp.indent_spaces, 4)
222 self.assertEqual(isp.indent_spaces, 4)
223 isp.push('if 1:\n raise TypeError()')
223 isp.push('if 1:\n raise TypeError()')
224 self.assertEqual(isp.indent_spaces, 0)
224 self.assertEqual(isp.indent_spaces, 0)
225 isp.push('if 1:\n raise')
225 isp.push('if 1:\n raise')
226 self.assertEqual(isp.indent_spaces, 0)
226 self.assertEqual(isp.indent_spaces, 0)
227 isp.push('if 1:\n raise ')
227 isp.push('if 1:\n raise ')
228 self.assertEqual(isp.indent_spaces, 0)
228 self.assertEqual(isp.indent_spaces, 0)
229
229
230 def test_dedent_return(self):
230 def test_dedent_return(self):
231 isp = self.isp # shorthand
231 isp = self.isp # shorthand
232 # should NOT cause dedent
232 # should NOT cause dedent
233 isp.push('if 1:\n returning = 4')
233 isp.push('if 1:\n returning = 4')
234 self.assertEqual(isp.indent_spaces, 4)
234 self.assertEqual(isp.indent_spaces, 4)
235 isp.push('if 1:\n return 5 + 493')
235 isp.push('if 1:\n return 5 + 493')
236 self.assertEqual(isp.indent_spaces, 0)
236 self.assertEqual(isp.indent_spaces, 0)
237 isp.push('if 1:\n return')
237 isp.push('if 1:\n return')
238 self.assertEqual(isp.indent_spaces, 0)
238 self.assertEqual(isp.indent_spaces, 0)
239 isp.push('if 1:\n return ')
239 isp.push('if 1:\n return ')
240 self.assertEqual(isp.indent_spaces, 0)
240 self.assertEqual(isp.indent_spaces, 0)
241 isp.push('if 1:\n return(0)')
241 isp.push('if 1:\n return(0)')
242 self.assertEqual(isp.indent_spaces, 0)
242 self.assertEqual(isp.indent_spaces, 0)
243
243
244 def test_push(self):
244 def test_push(self):
245 isp = self.isp
245 isp = self.isp
246 self.assertEqual(isp.push('x=1'), True)
246 self.assertEqual(isp.push('x=1'), True)
247
247
248 def test_push2(self):
248 def test_push2(self):
249 isp = self.isp
249 isp = self.isp
250 self.assertEqual(isp.push('if 1:'), False)
250 self.assertEqual(isp.push('if 1:'), False)
251 for line in [' x=1', '# a comment', ' y=2']:
251 for line in [' x=1', '# a comment', ' y=2']:
252 print(line)
252 print(line)
253 self.assertEqual(isp.push(line), True)
253 self.assertEqual(isp.push(line), True)
254
254
255 def test_push3(self):
255 def test_push3(self):
256 isp = self.isp
256 isp = self.isp
257 isp.push('if True:')
257 isp.push('if True:')
258 isp.push(' a = 1')
258 isp.push(' a = 1')
259 self.assertEqual(isp.push('b = [1,'), False)
259 self.assertEqual(isp.push('b = [1,'), False)
260
260
261 def test_push_accepts_more(self):
261 def test_push_accepts_more(self):
262 isp = self.isp
262 isp = self.isp
263 isp.push('x=1')
263 isp.push('x=1')
264 self.assertEqual(isp.push_accepts_more(), False)
264 self.assertEqual(isp.push_accepts_more(), False)
265
265
266 def test_push_accepts_more2(self):
266 def test_push_accepts_more2(self):
267 isp = self.isp
267 isp = self.isp
268 isp.push('if 1:')
268 isp.push('if 1:')
269 self.assertEqual(isp.push_accepts_more(), True)
269 self.assertEqual(isp.push_accepts_more(), True)
270 isp.push(' x=1')
270 isp.push(' x=1')
271 self.assertEqual(isp.push_accepts_more(), True)
271 self.assertEqual(isp.push_accepts_more(), True)
272 isp.push('')
272 isp.push('')
273 self.assertEqual(isp.push_accepts_more(), False)
273 self.assertEqual(isp.push_accepts_more(), False)
274
274
275 def test_push_accepts_more3(self):
275 def test_push_accepts_more3(self):
276 isp = self.isp
276 isp = self.isp
277 isp.push("x = (2+\n3)")
277 isp.push("x = (2+\n3)")
278 self.assertEqual(isp.push_accepts_more(), False)
278 self.assertEqual(isp.push_accepts_more(), False)
279
279
280 def test_push_accepts_more4(self):
280 def test_push_accepts_more4(self):
281 isp = self.isp
281 isp = self.isp
282 # When a multiline statement contains parens or multiline strings, we
282 # When a multiline statement contains parens or multiline strings, we
283 # shouldn't get confused.
283 # shouldn't get confused.
284 # FIXME: we should be able to better handle de-dents in statements like
284 # FIXME: we should be able to better handle de-dents in statements like
285 # multiline strings and multiline expressions (continued with \ or
285 # multiline strings and multiline expressions (continued with \ or
286 # parens). Right now we aren't handling the indentation tracking quite
286 # parens). Right now we aren't handling the indentation tracking quite
287 # correctly with this, though in practice it may not be too much of a
287 # correctly with this, though in practice it may not be too much of a
288 # problem. We'll need to see.
288 # problem. We'll need to see.
289 isp.push("if 1:")
289 isp.push("if 1:")
290 isp.push(" x = (2+")
290 isp.push(" x = (2+")
291 isp.push(" 3)")
291 isp.push(" 3)")
292 self.assertEqual(isp.push_accepts_more(), True)
292 self.assertEqual(isp.push_accepts_more(), True)
293 isp.push(" y = 3")
293 isp.push(" y = 3")
294 self.assertEqual(isp.push_accepts_more(), True)
294 self.assertEqual(isp.push_accepts_more(), True)
295 isp.push('')
295 isp.push('')
296 self.assertEqual(isp.push_accepts_more(), False)
296 self.assertEqual(isp.push_accepts_more(), False)
297
297
298 def test_push_accepts_more5(self):
298 def test_push_accepts_more5(self):
299 isp = self.isp
299 isp = self.isp
300 isp.push('try:')
300 isp.push('try:')
301 isp.push(' a = 5')
301 isp.push(' a = 5')
302 isp.push('except:')
302 isp.push('except:')
303 isp.push(' raise')
303 isp.push(' raise')
304 # We want to be able to add an else: block at this point, so it should
304 # We want to be able to add an else: block at this point, so it should
305 # wait for a blank line.
305 # wait for a blank line.
306 self.assertEqual(isp.push_accepts_more(), True)
306 self.assertEqual(isp.push_accepts_more(), True)
307
307
308 def test_continuation(self):
308 def test_continuation(self):
309 isp = self.isp
309 isp = self.isp
310 isp.push("import os, \\")
310 isp.push("import os, \\")
311 self.assertEqual(isp.push_accepts_more(), True)
311 self.assertEqual(isp.push_accepts_more(), True)
312 isp.push("sys")
312 isp.push("sys")
313 self.assertEqual(isp.push_accepts_more(), False)
313 self.assertEqual(isp.push_accepts_more(), False)
314
314
315 def test_syntax_error(self):
315 def test_syntax_error(self):
316 isp = self.isp
316 isp = self.isp
317 # Syntax errors immediately produce a 'ready' block, so the invalid
317 # Syntax errors immediately produce a 'ready' block, so the invalid
318 # Python can be sent to the kernel for evaluation with possible ipython
318 # Python can be sent to the kernel for evaluation with possible ipython
319 # special-syntax conversion.
319 # special-syntax conversion.
320 isp.push('run foo')
320 isp.push('run foo')
321 self.assertEqual(isp.push_accepts_more(), False)
321 self.assertEqual(isp.push_accepts_more(), False)
322
322
323 def test_unicode(self):
323 def test_unicode(self):
324 self.isp.push(u"Pérez")
324 self.isp.push(u"Pérez")
325 self.isp.push(u'\xc3\xa9')
325 self.isp.push(u'\xc3\xa9')
326 self.isp.push(u"u'\xc3\xa9'")
326 self.isp.push(u"u'\xc3\xa9'")
327
327
328 def test_line_continuation(self):
328 def test_line_continuation(self):
329 """ Test issue #2108."""
329 """ Test issue #2108."""
330 isp = self.isp
330 isp = self.isp
331 # A blank line after a line continuation should not accept more
331 # A blank line after a line continuation should not accept more
332 isp.push("1 \\\n\n")
332 isp.push("1 \\\n\n")
333 self.assertEqual(isp.push_accepts_more(), False)
333 self.assertEqual(isp.push_accepts_more(), False)
334 # Whitespace after a \ is a SyntaxError. The only way to test that
334 # Whitespace after a \ is a SyntaxError. The only way to test that
335 # here is to test that push doesn't accept more (as with
335 # here is to test that push doesn't accept more (as with
336 # test_syntax_error() above).
336 # test_syntax_error() above).
337 isp.push(r"1 \ ")
337 isp.push(r"1 \ ")
338 self.assertEqual(isp.push_accepts_more(), False)
338 self.assertEqual(isp.push_accepts_more(), False)
339 # Even if the line is continuable (c.f. the regular Python
339 # Even if the line is continuable (c.f. the regular Python
340 # interpreter)
340 # interpreter)
341 isp.push(r"(1 \ ")
341 isp.push(r"(1 \ ")
342 self.assertEqual(isp.push_accepts_more(), False)
342 self.assertEqual(isp.push_accepts_more(), False)
343
343
344 def test_check_complete(self):
344 def test_check_complete(self):
345 isp = self.isp
345 isp = self.isp
346 self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
346 self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
347 self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
347 self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
348 self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
348 self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
349 self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
349 self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
350 self.assertEqual(isp.check_complete("def a():\n x=1\n global x"), ('invalid', None))
350 self.assertEqual(isp.check_complete("def a():\n x=1\n global x"), ('invalid', None))
351
351
352 class InteractiveLoopTestCase(unittest.TestCase):
352 class InteractiveLoopTestCase(unittest.TestCase):
353 """Tests for an interactive loop like a python shell.
353 """Tests for an interactive loop like a python shell.
354 """
354 """
355 def check_ns(self, lines, ns):
355 def check_ns(self, lines, ns):
356 """Validate that the given input lines produce the resulting namespace.
356 """Validate that the given input lines produce the resulting namespace.
357
357
358 Note: the input lines are given exactly as they would be typed in an
358 Note: the input lines are given exactly as they would be typed in an
359 auto-indenting environment, as mini_interactive_loop above already does
359 auto-indenting environment, as mini_interactive_loop above already does
360 auto-indenting and prepends spaces to the input.
360 auto-indenting and prepends spaces to the input.
361 """
361 """
362 src = mini_interactive_loop(pseudo_input(lines))
362 src = mini_interactive_loop(pseudo_input(lines))
363 test_ns = {}
363 test_ns = {}
364 exec(src, test_ns)
364 exec(src, test_ns)
365 # We can't check that the provided ns is identical to the test_ns,
365 # We can't check that the provided ns is identical to the test_ns,
366 # because Python fills test_ns with extra keys (copyright, etc). But
366 # because Python fills test_ns with extra keys (copyright, etc). But
367 # we can check that the given dict is *contained* in test_ns
367 # we can check that the given dict is *contained* in test_ns
368 for k,v in ns.items():
368 for k,v in ns.items():
369 self.assertEqual(test_ns[k], v)
369 self.assertEqual(test_ns[k], v)
370
370
371 def test_simple(self):
371 def test_simple(self):
372 self.check_ns(['x=1'], dict(x=1))
372 self.check_ns(['x=1'], dict(x=1))
373
373
374 def test_simple2(self):
374 def test_simple2(self):
375 self.check_ns(['if 1:', 'x=2'], dict(x=2))
375 self.check_ns(['if 1:', 'x=2'], dict(x=2))
376
376
377 def test_xy(self):
377 def test_xy(self):
378 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
378 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
379
379
380 def test_abc(self):
380 def test_abc(self):
381 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
381 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
382
382
383 def test_multi(self):
383 def test_multi(self):
384 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
384 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
385
385
386
386
387 class IPythonInputTestCase(InputSplitterTestCase):
387 class IPythonInputTestCase(InputSplitterTestCase):
388 """By just creating a new class whose .isp is a different instance, we
388 """By just creating a new class whose .isp is a different instance, we
389 re-run the same test battery on the new input splitter.
389 re-run the same test battery on the new input splitter.
390
390
391 In addition, this runs the tests over the syntax and syntax_ml dicts that
391 In addition, this runs the tests over the syntax and syntax_ml dicts that
392 were tested by individual functions, as part of the OO interface.
392 were tested by individual functions, as part of the OO interface.
393
393
394 It also makes some checks on the raw buffer storage.
394 It also makes some checks on the raw buffer storage.
395 """
395 """
396
396
397 def setUp(self):
397 def setUp(self):
398 self.isp = isp.IPythonInputSplitter()
398 self.isp = isp.IPythonInputSplitter()
399
399
400 def test_syntax(self):
400 def test_syntax(self):
401 """Call all single-line syntax tests from the main object"""
401 """Call all single-line syntax tests from the main object"""
402 isp = self.isp
402 isp = self.isp
403 for example in syntax.values():
403 for example in syntax.values():
404 for raw, out_t in example:
404 for raw, out_t in example:
405 if raw.startswith(' '):
405 if raw.startswith(' '):
406 continue
406 continue
407
407
408 isp.push(raw+'\n')
408 isp.push(raw+'\n')
409 out_raw = isp.source_raw
409 out_raw = isp.source_raw
410 out = isp.source_reset()
410 out = isp.source_reset()
411 self.assertEqual(out.rstrip(), out_t,
411 self.assertEqual(out.rstrip(), out_t,
412 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
412 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
413 self.assertEqual(out_raw.rstrip(), raw.rstrip())
413 self.assertEqual(out_raw.rstrip(), raw.rstrip())
414
414
415 def test_syntax_multiline(self):
415 def test_syntax_multiline(self):
416 isp = self.isp
416 isp = self.isp
417 for example in syntax_ml.values():
417 for example in syntax_ml.values():
418 for line_pairs in example:
418 for line_pairs in example:
419 out_t_parts = []
419 out_t_parts = []
420 raw_parts = []
420 raw_parts = []
421 for lraw, out_t_part in line_pairs:
421 for lraw, out_t_part in line_pairs:
422 if out_t_part is not None:
422 if out_t_part is not None:
423 out_t_parts.append(out_t_part)
423 out_t_parts.append(out_t_part)
424
424
425 if lraw is not None:
425 if lraw is not None:
426 isp.push(lraw)
426 isp.push(lraw)
427 raw_parts.append(lraw)
427 raw_parts.append(lraw)
428
428
429 out_raw = isp.source_raw
429 out_raw = isp.source_raw
430 out = isp.source_reset()
430 out = isp.source_reset()
431 out_t = '\n'.join(out_t_parts).rstrip()
431 out_t = '\n'.join(out_t_parts).rstrip()
432 raw = '\n'.join(raw_parts).rstrip()
432 raw = '\n'.join(raw_parts).rstrip()
433 self.assertEqual(out.rstrip(), out_t)
433 self.assertEqual(out.rstrip(), out_t)
434 self.assertEqual(out_raw.rstrip(), raw)
434 self.assertEqual(out_raw.rstrip(), raw)
435
435
436 def test_syntax_multiline_cell(self):
436 def test_syntax_multiline_cell(self):
437 isp = self.isp
437 isp = self.isp
438 for example in syntax_ml.values():
438 for example in syntax_ml.values():
439
439
440 out_t_parts = []
440 out_t_parts = []
441 for line_pairs in example:
441 for line_pairs in example:
442 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
442 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
443 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
443 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
444 out = isp.transform_cell(raw)
444 out = isp.transform_cell(raw)
445 # Match ignoring trailing whitespace
445 # Match ignoring trailing whitespace
446 self.assertEqual(out.rstrip(), out_t.rstrip())
446 self.assertEqual(out.rstrip(), out_t.rstrip())
447
447
448 def test_cellmagic_preempt(self):
448 def test_cellmagic_preempt(self):
449 isp = self.isp
449 isp = self.isp
450 for raw, name, line, cell in [
450 for raw, name, line, cell in [
451 ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
451 ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
452 ("%%cellm \nline\n>>> hi", u'cellm', u'', u'line\n>>> hi'),
452 ("%%cellm \nline\n>>> hi", u'cellm', u'', u'line\n>>> hi'),
453 (">>> %%cellm \nline\n>>> hi", u'cellm', u'', u'line\nhi'),
453 (">>> %%cellm \nline\n>>> hi", u'cellm', u'', u'line\nhi'),
454 ("%%cellm \n>>> hi", u'cellm', u'', u'>>> hi'),
454 ("%%cellm \n>>> hi", u'cellm', u'', u'>>> hi'),
455 ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
455 ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
456 ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
456 ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
457 ]:
457 ]:
458 expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
458 expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
459 name, line, cell
459 name, line, cell
460 )
460 )
461 out = isp.transform_cell(raw)
461 out = isp.transform_cell(raw)
462 self.assertEqual(out.rstrip(), expected.rstrip())
462 self.assertEqual(out.rstrip(), expected.rstrip())
463
463
464 def test_multiline_passthrough(self):
464 def test_multiline_passthrough(self):
465 isp = self.isp
465 isp = self.isp
466 class CommentTransformer(InputTransformer):
466 class CommentTransformer(InputTransformer):
467 def __init__(self):
467 def __init__(self):
468 self._lines = []
468 self._lines = []
469
469
470 def push(self, line):
470 def push(self, line):
471 self._lines.append(line + '#')
471 self._lines.append(line + '#')
472
472
473 def reset(self):
473 def reset(self):
474 text = '\n'.join(self._lines)
474 text = '\n'.join(self._lines)
475 self._lines = []
475 self._lines = []
476 return text
476 return text
477
477
478 isp.physical_line_transforms.insert(0, CommentTransformer())
478 isp.physical_line_transforms.insert(0, CommentTransformer())
479
479
480 for raw, expected in [
480 for raw, expected in [
481 ("a=5", "a=5#"),
481 ("a=5", "a=5#"),
482 ("%ls foo", "get_ipython().magic(%r)" % u'ls foo#'),
482 ("%ls foo", "get_ipython().magic(%r)" % u'ls foo#'),
483 ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().magic(%r)" % (
483 ("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().magic(%r)" % (
484 u'ls foo#', u'ls bar#'
484 u'ls foo#', u'ls bar#'
485 )),
485 )),
486 ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().magic(%r)\n4#\n5#" % u'ls foo#'),
486 ("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().magic(%r)\n4#\n5#" % u'ls foo#'),
487 ]:
487 ]:
488 out = isp.transform_cell(raw)
488 out = isp.transform_cell(raw)
489 self.assertEqual(out.rstrip(), expected.rstrip())
489 self.assertEqual(out.rstrip(), expected.rstrip())
490
490
491 #-----------------------------------------------------------------------------
491 #-----------------------------------------------------------------------------
492 # Main - use as a script, mostly for developer experiments
492 # Main - use as a script, mostly for developer experiments
493 #-----------------------------------------------------------------------------
493 #-----------------------------------------------------------------------------
494
494
495 if __name__ == '__main__':
495 if __name__ == '__main__':
496 # A simple demo for interactive experimentation. This code will not get
496 # A simple demo for interactive experimentation. This code will not get
497 # picked up by any test suite.
497 # picked up by any test suite.
498 from IPython.core.inputsplitter import IPythonInputSplitter
498 from IPython.core.inputsplitter import IPythonInputSplitter
499
499
500 # configure here the syntax to use, prompt and whether to autoindent
500 # configure here the syntax to use, prompt and whether to autoindent
501 #isp, start_prompt = InputSplitter(), '>>> '
501 #isp, start_prompt = InputSplitter(), '>>> '
502 isp, start_prompt = IPythonInputSplitter(), 'In> '
502 isp, start_prompt = IPythonInputSplitter(), 'In> '
503
503
504 autoindent = True
504 autoindent = True
505 #autoindent = False
505 #autoindent = False
506
506
507 try:
507 try:
508 while True:
508 while True:
509 prompt = start_prompt
509 prompt = start_prompt
510 while isp.push_accepts_more():
510 while isp.push_accepts_more():
511 indent = ' '*isp.indent_spaces
511 indent = ' '*isp.indent_spaces
512 if autoindent:
512 if autoindent:
513 line = indent + input(prompt+indent)
513 line = indent + input(prompt+indent)
514 else:
514 else:
515 line = input(prompt)
515 line = input(prompt)
516 isp.push(line)
516 isp.push(line)
517 prompt = '... '
517 prompt = '... '
518
518
519 # Here we just return input so we can use it in a test suite, but a
519 # Here we just return input so we can use it in a test suite, but a
520 # real interpreter would instead send it for execution somewhere.
520 # real interpreter would instead send it for execution somewhere.
521 #src = isp.source; raise EOFError # dbg
521 #src = isp.source; raise EOFError # dbg
522 raw = isp.source_raw
522 raw = isp.source_raw
523 src = isp.source_reset()
523 src = isp.source_reset()
524 print('Input source was:\n', src)
524 print('Input source was:\n', src)
525 print('Raw source was:\n', raw)
525 print('Raw source was:\n', raw)
526 except EOFError:
526 except EOFError:
527 print('Bye')
527 print('Bye')
528
528
529 # Tests for cell magics support
529 # Tests for cell magics support
530
530
531 def test_last_blank():
531 def test_last_blank():
532 nt.assert_false(isp.last_blank(''))
532 nt.assert_false(isp.last_blank(''))
533 nt.assert_false(isp.last_blank('abc'))
533 nt.assert_false(isp.last_blank('abc'))
534 nt.assert_false(isp.last_blank('abc\n'))
534 nt.assert_false(isp.last_blank('abc\n'))
535 nt.assert_false(isp.last_blank('abc\na'))
535 nt.assert_false(isp.last_blank('abc\na'))
536
536
537 nt.assert_true(isp.last_blank('\n'))
537 nt.assert_true(isp.last_blank('\n'))
538 nt.assert_true(isp.last_blank('\n '))
538 nt.assert_true(isp.last_blank('\n '))
539 nt.assert_true(isp.last_blank('abc\n '))
539 nt.assert_true(isp.last_blank('abc\n '))
540 nt.assert_true(isp.last_blank('abc\n\n'))
540 nt.assert_true(isp.last_blank('abc\n\n'))
541 nt.assert_true(isp.last_blank('abc\nd\n\n'))
541 nt.assert_true(isp.last_blank('abc\nd\n\n'))
542 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
542 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
543 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
543 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
544
544
545
545
546 def test_last_two_blanks():
546 def test_last_two_blanks():
547 nt.assert_false(isp.last_two_blanks(''))
547 nt.assert_false(isp.last_two_blanks(''))
548 nt.assert_false(isp.last_two_blanks('abc'))
548 nt.assert_false(isp.last_two_blanks('abc'))
549 nt.assert_false(isp.last_two_blanks('abc\n'))
549 nt.assert_false(isp.last_two_blanks('abc\n'))
550 nt.assert_false(isp.last_two_blanks('abc\n\na'))
550 nt.assert_false(isp.last_two_blanks('abc\n\na'))
551 nt.assert_false(isp.last_two_blanks('abc\n \n'))
551 nt.assert_false(isp.last_two_blanks('abc\n \n'))
552 nt.assert_false(isp.last_two_blanks('abc\n\n'))
552 nt.assert_false(isp.last_two_blanks('abc\n\n'))
553
553
554 nt.assert_true(isp.last_two_blanks('\n\n'))
554 nt.assert_true(isp.last_two_blanks('\n\n'))
555 nt.assert_true(isp.last_two_blanks('\n\n '))
555 nt.assert_true(isp.last_two_blanks('\n\n '))
556 nt.assert_true(isp.last_two_blanks('\n \n'))
556 nt.assert_true(isp.last_two_blanks('\n \n'))
557 nt.assert_true(isp.last_two_blanks('abc\n\n '))
557 nt.assert_true(isp.last_two_blanks('abc\n\n '))
558 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
558 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
559 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
559 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
560 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
560 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
561 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
561 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
562 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
562 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
563 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
563 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
564
564
565
565
566 class CellMagicsCommon(object):
566 class CellMagicsCommon(object):
567
567
568 def test_whole_cell(self):
568 def test_whole_cell(self):
569 src = "%%cellm line\nbody\n"
569 src = "%%cellm line\nbody\n"
570 out = self.sp.transform_cell(src)
570 out = self.sp.transform_cell(src)
571 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
571 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
572 nt.assert_equal(out, py3compat.u_format(ref))
572 nt.assert_equal(out, py3compat.u_format(ref))
573
573
574 def test_cellmagic_help(self):
574 def test_cellmagic_help(self):
575 self.sp.push('%%cellm?')
575 self.sp.push('%%cellm?')
576 nt.assert_false(self.sp.push_accepts_more())
576 nt.assert_false(self.sp.push_accepts_more())
577
577
578 def tearDown(self):
578 def tearDown(self):
579 self.sp.reset()
579 self.sp.reset()
580
580
581
581
582 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
582 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
583 sp = isp.IPythonInputSplitter(line_input_checker=False)
583 sp = isp.IPythonInputSplitter(line_input_checker=False)
584
584
585 def test_incremental(self):
585 def test_incremental(self):
586 sp = self.sp
586 sp = self.sp
587 sp.push('%%cellm firstline\n')
587 sp.push('%%cellm firstline\n')
588 nt.assert_true(sp.push_accepts_more()) #1
588 nt.assert_true(sp.push_accepts_more()) #1
589 sp.push('line2\n')
589 sp.push('line2\n')
590 nt.assert_true(sp.push_accepts_more()) #2
590 nt.assert_true(sp.push_accepts_more()) #2
591 sp.push('\n')
591 sp.push('\n')
592 # This should accept a blank line and carry on until the cell is reset
592 # This should accept a blank line and carry on until the cell is reset
593 nt.assert_true(sp.push_accepts_more()) #3
593 nt.assert_true(sp.push_accepts_more()) #3
594
594
595 def test_no_strip_coding(self):
595 def test_no_strip_coding(self):
596 src = '\n'.join([
596 src = '\n'.join([
597 '%%writefile foo.py',
597 '%%writefile foo.py',
598 '# coding: utf-8',
598 '# coding: utf-8',
599 'print(u"üñîçø∂é")',
599 'print(u"üñîçø∂é")',
600 ])
600 ])
601 out = self.sp.transform_cell(src)
601 out = self.sp.transform_cell(src)
602 nt.assert_in('# coding: utf-8', out)
602 nt.assert_in('# coding: utf-8', out)
603
603
604
604
605 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
605 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
606 sp = isp.IPythonInputSplitter(line_input_checker=True)
606 sp = isp.IPythonInputSplitter(line_input_checker=True)
607
607
608 def test_incremental(self):
608 def test_incremental(self):
609 sp = self.sp
609 sp = self.sp
610 sp.push('%%cellm line2\n')
610 sp.push('%%cellm line2\n')
611 nt.assert_true(sp.push_accepts_more()) #1
611 nt.assert_true(sp.push_accepts_more()) #1
612 sp.push('\n')
612 sp.push('\n')
613 # In this case, a blank line should end the cell magic
613 # In this case, a blank line should end the cell magic
614 nt.assert_false(sp.push_accepts_more()) #2
614 nt.assert_false(sp.push_accepts_more()) #2
@@ -1,906 +1,906 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import ast
12 import ast
13 import os
13 import os
14 import signal
14 import signal
15 import shutil
15 import shutil
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import unittest
18 import unittest
19 try:
19 try:
20 from unittest import mock
20 from unittest import mock
21 except ImportError:
21 except ImportError:
22 import mock
22 import mock
23 from os.path import join
23 from os.path import join
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from IPython.core.error import InputRejected
27 from IPython.core.error import InputRejected
28 from IPython.core.inputtransformer import InputTransformer
28 from IPython.core.inputtransformer import InputTransformer
29 from IPython.testing.decorators import (
29 from IPython.testing.decorators import (
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
31 )
31 )
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33 from IPython.utils.process import find_cmd
33 from IPython.utils.process import find_cmd
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.py3compat import unicode_type, PY3
35 from IPython.utils.py3compat import PY3
36
36
37 if PY3:
37 if PY3:
38 from io import StringIO
38 from io import StringIO
39 else:
39 else:
40 from StringIO import StringIO
40 from StringIO import StringIO
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals
43 # Globals
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45 # This is used by every single test, no point repeating it ad nauseam
45 # This is used by every single test, no point repeating it ad nauseam
46 ip = get_ipython()
46 ip = get_ipython()
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Tests
49 # Tests
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 class DerivedInterrupt(KeyboardInterrupt):
52 class DerivedInterrupt(KeyboardInterrupt):
53 pass
53 pass
54
54
55 class InteractiveShellTestCase(unittest.TestCase):
55 class InteractiveShellTestCase(unittest.TestCase):
56 def test_naked_string_cells(self):
56 def test_naked_string_cells(self):
57 """Test that cells with only naked strings are fully executed"""
57 """Test that cells with only naked strings are fully executed"""
58 # First, single-line inputs
58 # First, single-line inputs
59 ip.run_cell('"a"\n')
59 ip.run_cell('"a"\n')
60 self.assertEqual(ip.user_ns['_'], 'a')
60 self.assertEqual(ip.user_ns['_'], 'a')
61 # And also multi-line cells
61 # And also multi-line cells
62 ip.run_cell('"""a\nb"""\n')
62 ip.run_cell('"""a\nb"""\n')
63 self.assertEqual(ip.user_ns['_'], 'a\nb')
63 self.assertEqual(ip.user_ns['_'], 'a\nb')
64
64
65 def test_run_empty_cell(self):
65 def test_run_empty_cell(self):
66 """Just make sure we don't get a horrible error with a blank
66 """Just make sure we don't get a horrible error with a blank
67 cell of input. Yes, I did overlook that."""
67 cell of input. Yes, I did overlook that."""
68 old_xc = ip.execution_count
68 old_xc = ip.execution_count
69 res = ip.run_cell('')
69 res = ip.run_cell('')
70 self.assertEqual(ip.execution_count, old_xc)
70 self.assertEqual(ip.execution_count, old_xc)
71 self.assertEqual(res.execution_count, None)
71 self.assertEqual(res.execution_count, None)
72
72
73 def test_run_cell_multiline(self):
73 def test_run_cell_multiline(self):
74 """Multi-block, multi-line cells must execute correctly.
74 """Multi-block, multi-line cells must execute correctly.
75 """
75 """
76 src = '\n'.join(["x=1",
76 src = '\n'.join(["x=1",
77 "y=2",
77 "y=2",
78 "if 1:",
78 "if 1:",
79 " x += 1",
79 " x += 1",
80 " y += 1",])
80 " y += 1",])
81 res = ip.run_cell(src)
81 res = ip.run_cell(src)
82 self.assertEqual(ip.user_ns['x'], 2)
82 self.assertEqual(ip.user_ns['x'], 2)
83 self.assertEqual(ip.user_ns['y'], 3)
83 self.assertEqual(ip.user_ns['y'], 3)
84 self.assertEqual(res.success, True)
84 self.assertEqual(res.success, True)
85 self.assertEqual(res.result, None)
85 self.assertEqual(res.result, None)
86
86
87 def test_multiline_string_cells(self):
87 def test_multiline_string_cells(self):
88 "Code sprinkled with multiline strings should execute (GH-306)"
88 "Code sprinkled with multiline strings should execute (GH-306)"
89 ip.run_cell('tmp=0')
89 ip.run_cell('tmp=0')
90 self.assertEqual(ip.user_ns['tmp'], 0)
90 self.assertEqual(ip.user_ns['tmp'], 0)
91 res = ip.run_cell('tmp=1;"""a\nb"""\n')
91 res = ip.run_cell('tmp=1;"""a\nb"""\n')
92 self.assertEqual(ip.user_ns['tmp'], 1)
92 self.assertEqual(ip.user_ns['tmp'], 1)
93 self.assertEqual(res.success, True)
93 self.assertEqual(res.success, True)
94 self.assertEqual(res.result, "a\nb")
94 self.assertEqual(res.result, "a\nb")
95
95
96 def test_dont_cache_with_semicolon(self):
96 def test_dont_cache_with_semicolon(self):
97 "Ending a line with semicolon should not cache the returned object (GH-307)"
97 "Ending a line with semicolon should not cache the returned object (GH-307)"
98 oldlen = len(ip.user_ns['Out'])
98 oldlen = len(ip.user_ns['Out'])
99 for cell in ['1;', '1;1;']:
99 for cell in ['1;', '1;1;']:
100 res = ip.run_cell(cell, store_history=True)
100 res = ip.run_cell(cell, store_history=True)
101 newlen = len(ip.user_ns['Out'])
101 newlen = len(ip.user_ns['Out'])
102 self.assertEqual(oldlen, newlen)
102 self.assertEqual(oldlen, newlen)
103 self.assertIsNone(res.result)
103 self.assertIsNone(res.result)
104 i = 0
104 i = 0
105 #also test the default caching behavior
105 #also test the default caching behavior
106 for cell in ['1', '1;1']:
106 for cell in ['1', '1;1']:
107 ip.run_cell(cell, store_history=True)
107 ip.run_cell(cell, store_history=True)
108 newlen = len(ip.user_ns['Out'])
108 newlen = len(ip.user_ns['Out'])
109 i += 1
109 i += 1
110 self.assertEqual(oldlen+i, newlen)
110 self.assertEqual(oldlen+i, newlen)
111
111
112 def test_syntax_error(self):
112 def test_syntax_error(self):
113 res = ip.run_cell("raise = 3")
113 res = ip.run_cell("raise = 3")
114 self.assertIsInstance(res.error_before_exec, SyntaxError)
114 self.assertIsInstance(res.error_before_exec, SyntaxError)
115
115
116 def test_In_variable(self):
116 def test_In_variable(self):
117 "Verify that In variable grows with user input (GH-284)"
117 "Verify that In variable grows with user input (GH-284)"
118 oldlen = len(ip.user_ns['In'])
118 oldlen = len(ip.user_ns['In'])
119 ip.run_cell('1;', store_history=True)
119 ip.run_cell('1;', store_history=True)
120 newlen = len(ip.user_ns['In'])
120 newlen = len(ip.user_ns['In'])
121 self.assertEqual(oldlen+1, newlen)
121 self.assertEqual(oldlen+1, newlen)
122 self.assertEqual(ip.user_ns['In'][-1],'1;')
122 self.assertEqual(ip.user_ns['In'][-1],'1;')
123
123
124 def test_magic_names_in_string(self):
124 def test_magic_names_in_string(self):
125 ip.run_cell('a = """\n%exit\n"""')
125 ip.run_cell('a = """\n%exit\n"""')
126 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
126 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
127
127
128 def test_trailing_newline(self):
128 def test_trailing_newline(self):
129 """test that running !(command) does not raise a SyntaxError"""
129 """test that running !(command) does not raise a SyntaxError"""
130 ip.run_cell('!(true)\n', False)
130 ip.run_cell('!(true)\n', False)
131 ip.run_cell('!(true)\n\n\n', False)
131 ip.run_cell('!(true)\n\n\n', False)
132
132
133 def test_gh_597(self):
133 def test_gh_597(self):
134 """Pretty-printing lists of objects with non-ascii reprs may cause
134 """Pretty-printing lists of objects with non-ascii reprs may cause
135 problems."""
135 problems."""
136 class Spam(object):
136 class Spam(object):
137 def __repr__(self):
137 def __repr__(self):
138 return "\xe9"*50
138 return "\xe9"*50
139 import IPython.core.formatters
139 import IPython.core.formatters
140 f = IPython.core.formatters.PlainTextFormatter()
140 f = IPython.core.formatters.PlainTextFormatter()
141 f([Spam(),Spam()])
141 f([Spam(),Spam()])
142
142
143
143
144 def test_future_flags(self):
144 def test_future_flags(self):
145 """Check that future flags are used for parsing code (gh-777)"""
145 """Check that future flags are used for parsing code (gh-777)"""
146 ip.run_cell('from __future__ import barry_as_FLUFL')
146 ip.run_cell('from __future__ import barry_as_FLUFL')
147 try:
147 try:
148 ip.run_cell('prfunc_return_val = 1 <> 2')
148 ip.run_cell('prfunc_return_val = 1 <> 2')
149 assert 'prfunc_return_val' in ip.user_ns
149 assert 'prfunc_return_val' in ip.user_ns
150 finally:
150 finally:
151 # Reset compiler flags so we don't mess up other tests.
151 # Reset compiler flags so we don't mess up other tests.
152 ip.compile.reset_compiler_flags()
152 ip.compile.reset_compiler_flags()
153
153
154 def test_can_pickle(self):
154 def test_can_pickle(self):
155 "Can we pickle objects defined interactively (GH-29)"
155 "Can we pickle objects defined interactively (GH-29)"
156 ip = get_ipython()
156 ip = get_ipython()
157 ip.reset()
157 ip.reset()
158 ip.run_cell(("class Mylist(list):\n"
158 ip.run_cell(("class Mylist(list):\n"
159 " def __init__(self,x=[]):\n"
159 " def __init__(self,x=[]):\n"
160 " list.__init__(self,x)"))
160 " list.__init__(self,x)"))
161 ip.run_cell("w=Mylist([1,2,3])")
161 ip.run_cell("w=Mylist([1,2,3])")
162
162
163 from pickle import dumps
163 from pickle import dumps
164
164
165 # We need to swap in our main module - this is only necessary
165 # We need to swap in our main module - this is only necessary
166 # inside the test framework, because IPython puts the interactive module
166 # inside the test framework, because IPython puts the interactive module
167 # in place (but the test framework undoes this).
167 # in place (but the test framework undoes this).
168 _main = sys.modules['__main__']
168 _main = sys.modules['__main__']
169 sys.modules['__main__'] = ip.user_module
169 sys.modules['__main__'] = ip.user_module
170 try:
170 try:
171 res = dumps(ip.user_ns["w"])
171 res = dumps(ip.user_ns["w"])
172 finally:
172 finally:
173 sys.modules['__main__'] = _main
173 sys.modules['__main__'] = _main
174 self.assertTrue(isinstance(res, bytes))
174 self.assertTrue(isinstance(res, bytes))
175
175
176 def test_global_ns(self):
176 def test_global_ns(self):
177 "Code in functions must be able to access variables outside them."
177 "Code in functions must be able to access variables outside them."
178 ip = get_ipython()
178 ip = get_ipython()
179 ip.run_cell("a = 10")
179 ip.run_cell("a = 10")
180 ip.run_cell(("def f(x):\n"
180 ip.run_cell(("def f(x):\n"
181 " return x + a"))
181 " return x + a"))
182 ip.run_cell("b = f(12)")
182 ip.run_cell("b = f(12)")
183 self.assertEqual(ip.user_ns["b"], 22)
183 self.assertEqual(ip.user_ns["b"], 22)
184
184
185 def test_bad_custom_tb(self):
185 def test_bad_custom_tb(self):
186 """Check that InteractiveShell is protected from bad custom exception handlers"""
186 """Check that InteractiveShell is protected from bad custom exception handlers"""
187 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
187 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
188 self.assertEqual(ip.custom_exceptions, (IOError,))
188 self.assertEqual(ip.custom_exceptions, (IOError,))
189 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
189 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
190 ip.run_cell(u'raise IOError("foo")')
190 ip.run_cell(u'raise IOError("foo")')
191 self.assertEqual(ip.custom_exceptions, ())
191 self.assertEqual(ip.custom_exceptions, ())
192
192
193 def test_bad_custom_tb_return(self):
193 def test_bad_custom_tb_return(self):
194 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
194 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
195 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
195 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
196 self.assertEqual(ip.custom_exceptions, (NameError,))
196 self.assertEqual(ip.custom_exceptions, (NameError,))
197 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
197 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
198 ip.run_cell(u'a=abracadabra')
198 ip.run_cell(u'a=abracadabra')
199 self.assertEqual(ip.custom_exceptions, ())
199 self.assertEqual(ip.custom_exceptions, ())
200
200
201 def test_drop_by_id(self):
201 def test_drop_by_id(self):
202 myvars = {"a":object(), "b":object(), "c": object()}
202 myvars = {"a":object(), "b":object(), "c": object()}
203 ip.push(myvars, interactive=False)
203 ip.push(myvars, interactive=False)
204 for name in myvars:
204 for name in myvars:
205 assert name in ip.user_ns, name
205 assert name in ip.user_ns, name
206 assert name in ip.user_ns_hidden, name
206 assert name in ip.user_ns_hidden, name
207 ip.user_ns['b'] = 12
207 ip.user_ns['b'] = 12
208 ip.drop_by_id(myvars)
208 ip.drop_by_id(myvars)
209 for name in ["a", "c"]:
209 for name in ["a", "c"]:
210 assert name not in ip.user_ns, name
210 assert name not in ip.user_ns, name
211 assert name not in ip.user_ns_hidden, name
211 assert name not in ip.user_ns_hidden, name
212 assert ip.user_ns['b'] == 12
212 assert ip.user_ns['b'] == 12
213 ip.reset()
213 ip.reset()
214
214
215 def test_var_expand(self):
215 def test_var_expand(self):
216 ip.user_ns['f'] = u'Ca\xf1o'
216 ip.user_ns['f'] = u'Ca\xf1o'
217 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
217 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
218 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
218 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
219 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
219 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
220 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
220 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
221
221
222 ip.user_ns['f'] = b'Ca\xc3\xb1o'
222 ip.user_ns['f'] = b'Ca\xc3\xb1o'
223 # This should not raise any exception:
223 # This should not raise any exception:
224 ip.var_expand(u'echo $f')
224 ip.var_expand(u'echo $f')
225
225
226 def test_var_expand_local(self):
226 def test_var_expand_local(self):
227 """Test local variable expansion in !system and %magic calls"""
227 """Test local variable expansion in !system and %magic calls"""
228 # !system
228 # !system
229 ip.run_cell('def test():\n'
229 ip.run_cell('def test():\n'
230 ' lvar = "ttt"\n'
230 ' lvar = "ttt"\n'
231 ' ret = !echo {lvar}\n'
231 ' ret = !echo {lvar}\n'
232 ' return ret[0]\n')
232 ' return ret[0]\n')
233 res = ip.user_ns['test']()
233 res = ip.user_ns['test']()
234 nt.assert_in('ttt', res)
234 nt.assert_in('ttt', res)
235
235
236 # %magic
236 # %magic
237 ip.run_cell('def makemacro():\n'
237 ip.run_cell('def makemacro():\n'
238 ' macroname = "macro_var_expand_locals"\n'
238 ' macroname = "macro_var_expand_locals"\n'
239 ' %macro {macroname} codestr\n')
239 ' %macro {macroname} codestr\n')
240 ip.user_ns['codestr'] = "str(12)"
240 ip.user_ns['codestr'] = "str(12)"
241 ip.run_cell('makemacro()')
241 ip.run_cell('makemacro()')
242 nt.assert_in('macro_var_expand_locals', ip.user_ns)
242 nt.assert_in('macro_var_expand_locals', ip.user_ns)
243
243
244 def test_var_expand_self(self):
244 def test_var_expand_self(self):
245 """Test variable expansion with the name 'self', which was failing.
245 """Test variable expansion with the name 'self', which was failing.
246
246
247 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
247 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
248 """
248 """
249 ip.run_cell('class cTest:\n'
249 ip.run_cell('class cTest:\n'
250 ' classvar="see me"\n'
250 ' classvar="see me"\n'
251 ' def test(self):\n'
251 ' def test(self):\n'
252 ' res = !echo Variable: {self.classvar}\n'
252 ' res = !echo Variable: {self.classvar}\n'
253 ' return res[0]\n')
253 ' return res[0]\n')
254 nt.assert_in('see me', ip.user_ns['cTest']().test())
254 nt.assert_in('see me', ip.user_ns['cTest']().test())
255
255
256 def test_bad_var_expand(self):
256 def test_bad_var_expand(self):
257 """var_expand on invalid formats shouldn't raise"""
257 """var_expand on invalid formats shouldn't raise"""
258 # SyntaxError
258 # SyntaxError
259 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
259 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
260 # NameError
260 # NameError
261 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
261 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
262 # ZeroDivisionError
262 # ZeroDivisionError
263 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
263 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
264
264
265 def test_silent_postexec(self):
265 def test_silent_postexec(self):
266 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
266 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
267 pre_explicit = mock.Mock()
267 pre_explicit = mock.Mock()
268 pre_always = mock.Mock()
268 pre_always = mock.Mock()
269 post_explicit = mock.Mock()
269 post_explicit = mock.Mock()
270 post_always = mock.Mock()
270 post_always = mock.Mock()
271
271
272 ip.events.register('pre_run_cell', pre_explicit)
272 ip.events.register('pre_run_cell', pre_explicit)
273 ip.events.register('pre_execute', pre_always)
273 ip.events.register('pre_execute', pre_always)
274 ip.events.register('post_run_cell', post_explicit)
274 ip.events.register('post_run_cell', post_explicit)
275 ip.events.register('post_execute', post_always)
275 ip.events.register('post_execute', post_always)
276
276
277 try:
277 try:
278 ip.run_cell("1", silent=True)
278 ip.run_cell("1", silent=True)
279 assert pre_always.called
279 assert pre_always.called
280 assert not pre_explicit.called
280 assert not pre_explicit.called
281 assert post_always.called
281 assert post_always.called
282 assert not post_explicit.called
282 assert not post_explicit.called
283 # double-check that non-silent exec did what we expected
283 # double-check that non-silent exec did what we expected
284 # silent to avoid
284 # silent to avoid
285 ip.run_cell("1")
285 ip.run_cell("1")
286 assert pre_explicit.called
286 assert pre_explicit.called
287 assert post_explicit.called
287 assert post_explicit.called
288 finally:
288 finally:
289 # remove post-exec
289 # remove post-exec
290 ip.events.unregister('pre_run_cell', pre_explicit)
290 ip.events.unregister('pre_run_cell', pre_explicit)
291 ip.events.unregister('pre_execute', pre_always)
291 ip.events.unregister('pre_execute', pre_always)
292 ip.events.unregister('post_run_cell', post_explicit)
292 ip.events.unregister('post_run_cell', post_explicit)
293 ip.events.unregister('post_execute', post_always)
293 ip.events.unregister('post_execute', post_always)
294
294
295 def test_silent_noadvance(self):
295 def test_silent_noadvance(self):
296 """run_cell(silent=True) doesn't advance execution_count"""
296 """run_cell(silent=True) doesn't advance execution_count"""
297 ec = ip.execution_count
297 ec = ip.execution_count
298 # silent should force store_history=False
298 # silent should force store_history=False
299 ip.run_cell("1", store_history=True, silent=True)
299 ip.run_cell("1", store_history=True, silent=True)
300
300
301 self.assertEqual(ec, ip.execution_count)
301 self.assertEqual(ec, ip.execution_count)
302 # double-check that non-silent exec did what we expected
302 # double-check that non-silent exec did what we expected
303 # silent to avoid
303 # silent to avoid
304 ip.run_cell("1", store_history=True)
304 ip.run_cell("1", store_history=True)
305 self.assertEqual(ec+1, ip.execution_count)
305 self.assertEqual(ec+1, ip.execution_count)
306
306
307 def test_silent_nodisplayhook(self):
307 def test_silent_nodisplayhook(self):
308 """run_cell(silent=True) doesn't trigger displayhook"""
308 """run_cell(silent=True) doesn't trigger displayhook"""
309 d = dict(called=False)
309 d = dict(called=False)
310
310
311 trap = ip.display_trap
311 trap = ip.display_trap
312 save_hook = trap.hook
312 save_hook = trap.hook
313
313
314 def failing_hook(*args, **kwargs):
314 def failing_hook(*args, **kwargs):
315 d['called'] = True
315 d['called'] = True
316
316
317 try:
317 try:
318 trap.hook = failing_hook
318 trap.hook = failing_hook
319 res = ip.run_cell("1", silent=True)
319 res = ip.run_cell("1", silent=True)
320 self.assertFalse(d['called'])
320 self.assertFalse(d['called'])
321 self.assertIsNone(res.result)
321 self.assertIsNone(res.result)
322 # double-check that non-silent exec did what we expected
322 # double-check that non-silent exec did what we expected
323 # silent to avoid
323 # silent to avoid
324 ip.run_cell("1")
324 ip.run_cell("1")
325 self.assertTrue(d['called'])
325 self.assertTrue(d['called'])
326 finally:
326 finally:
327 trap.hook = save_hook
327 trap.hook = save_hook
328
328
329 def test_ofind_line_magic(self):
329 def test_ofind_line_magic(self):
330 from IPython.core.magic import register_line_magic
330 from IPython.core.magic import register_line_magic
331
331
332 @register_line_magic
332 @register_line_magic
333 def lmagic(line):
333 def lmagic(line):
334 "A line magic"
334 "A line magic"
335
335
336 # Get info on line magic
336 # Get info on line magic
337 lfind = ip._ofind('lmagic')
337 lfind = ip._ofind('lmagic')
338 info = dict(found=True, isalias=False, ismagic=True,
338 info = dict(found=True, isalias=False, ismagic=True,
339 namespace = 'IPython internal', obj= lmagic.__wrapped__,
339 namespace = 'IPython internal', obj= lmagic.__wrapped__,
340 parent = None)
340 parent = None)
341 nt.assert_equal(lfind, info)
341 nt.assert_equal(lfind, info)
342
342
343 def test_ofind_cell_magic(self):
343 def test_ofind_cell_magic(self):
344 from IPython.core.magic import register_cell_magic
344 from IPython.core.magic import register_cell_magic
345
345
346 @register_cell_magic
346 @register_cell_magic
347 def cmagic(line, cell):
347 def cmagic(line, cell):
348 "A cell magic"
348 "A cell magic"
349
349
350 # Get info on cell magic
350 # Get info on cell magic
351 find = ip._ofind('cmagic')
351 find = ip._ofind('cmagic')
352 info = dict(found=True, isalias=False, ismagic=True,
352 info = dict(found=True, isalias=False, ismagic=True,
353 namespace = 'IPython internal', obj= cmagic.__wrapped__,
353 namespace = 'IPython internal', obj= cmagic.__wrapped__,
354 parent = None)
354 parent = None)
355 nt.assert_equal(find, info)
355 nt.assert_equal(find, info)
356
356
357 def test_ofind_property_with_error(self):
357 def test_ofind_property_with_error(self):
358 class A(object):
358 class A(object):
359 @property
359 @property
360 def foo(self):
360 def foo(self):
361 raise NotImplementedError()
361 raise NotImplementedError()
362 a = A()
362 a = A()
363
363
364 found = ip._ofind('a.foo', [('locals', locals())])
364 found = ip._ofind('a.foo', [('locals', locals())])
365 info = dict(found=True, isalias=False, ismagic=False,
365 info = dict(found=True, isalias=False, ismagic=False,
366 namespace='locals', obj=A.foo, parent=a)
366 namespace='locals', obj=A.foo, parent=a)
367 nt.assert_equal(found, info)
367 nt.assert_equal(found, info)
368
368
369 def test_ofind_multiple_attribute_lookups(self):
369 def test_ofind_multiple_attribute_lookups(self):
370 class A(object):
370 class A(object):
371 @property
371 @property
372 def foo(self):
372 def foo(self):
373 raise NotImplementedError()
373 raise NotImplementedError()
374
374
375 a = A()
375 a = A()
376 a.a = A()
376 a.a = A()
377 a.a.a = A()
377 a.a.a = A()
378
378
379 found = ip._ofind('a.a.a.foo', [('locals', locals())])
379 found = ip._ofind('a.a.a.foo', [('locals', locals())])
380 info = dict(found=True, isalias=False, ismagic=False,
380 info = dict(found=True, isalias=False, ismagic=False,
381 namespace='locals', obj=A.foo, parent=a.a.a)
381 namespace='locals', obj=A.foo, parent=a.a.a)
382 nt.assert_equal(found, info)
382 nt.assert_equal(found, info)
383
383
384 def test_ofind_slotted_attributes(self):
384 def test_ofind_slotted_attributes(self):
385 class A(object):
385 class A(object):
386 __slots__ = ['foo']
386 __slots__ = ['foo']
387 def __init__(self):
387 def __init__(self):
388 self.foo = 'bar'
388 self.foo = 'bar'
389
389
390 a = A()
390 a = A()
391 found = ip._ofind('a.foo', [('locals', locals())])
391 found = ip._ofind('a.foo', [('locals', locals())])
392 info = dict(found=True, isalias=False, ismagic=False,
392 info = dict(found=True, isalias=False, ismagic=False,
393 namespace='locals', obj=a.foo, parent=a)
393 namespace='locals', obj=a.foo, parent=a)
394 nt.assert_equal(found, info)
394 nt.assert_equal(found, info)
395
395
396 found = ip._ofind('a.bar', [('locals', locals())])
396 found = ip._ofind('a.bar', [('locals', locals())])
397 info = dict(found=False, isalias=False, ismagic=False,
397 info = dict(found=False, isalias=False, ismagic=False,
398 namespace=None, obj=None, parent=a)
398 namespace=None, obj=None, parent=a)
399 nt.assert_equal(found, info)
399 nt.assert_equal(found, info)
400
400
401 def test_ofind_prefers_property_to_instance_level_attribute(self):
401 def test_ofind_prefers_property_to_instance_level_attribute(self):
402 class A(object):
402 class A(object):
403 @property
403 @property
404 def foo(self):
404 def foo(self):
405 return 'bar'
405 return 'bar'
406 a = A()
406 a = A()
407 a.__dict__['foo'] = 'baz'
407 a.__dict__['foo'] = 'baz'
408 nt.assert_equal(a.foo, 'bar')
408 nt.assert_equal(a.foo, 'bar')
409 found = ip._ofind('a.foo', [('locals', locals())])
409 found = ip._ofind('a.foo', [('locals', locals())])
410 nt.assert_is(found['obj'], A.foo)
410 nt.assert_is(found['obj'], A.foo)
411
411
412 def test_custom_syntaxerror_exception(self):
412 def test_custom_syntaxerror_exception(self):
413 called = []
413 called = []
414 def my_handler(shell, etype, value, tb, tb_offset=None):
414 def my_handler(shell, etype, value, tb, tb_offset=None):
415 called.append(etype)
415 called.append(etype)
416 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
416 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
417
417
418 ip.set_custom_exc((SyntaxError,), my_handler)
418 ip.set_custom_exc((SyntaxError,), my_handler)
419 try:
419 try:
420 ip.run_cell("1f")
420 ip.run_cell("1f")
421 # Check that this was called, and only once.
421 # Check that this was called, and only once.
422 self.assertEqual(called, [SyntaxError])
422 self.assertEqual(called, [SyntaxError])
423 finally:
423 finally:
424 # Reset the custom exception hook
424 # Reset the custom exception hook
425 ip.set_custom_exc((), None)
425 ip.set_custom_exc((), None)
426
426
427 def test_custom_exception(self):
427 def test_custom_exception(self):
428 called = []
428 called = []
429 def my_handler(shell, etype, value, tb, tb_offset=None):
429 def my_handler(shell, etype, value, tb, tb_offset=None):
430 called.append(etype)
430 called.append(etype)
431 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
431 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
432
432
433 ip.set_custom_exc((ValueError,), my_handler)
433 ip.set_custom_exc((ValueError,), my_handler)
434 try:
434 try:
435 res = ip.run_cell("raise ValueError('test')")
435 res = ip.run_cell("raise ValueError('test')")
436 # Check that this was called, and only once.
436 # Check that this was called, and only once.
437 self.assertEqual(called, [ValueError])
437 self.assertEqual(called, [ValueError])
438 # Check that the error is on the result object
438 # Check that the error is on the result object
439 self.assertIsInstance(res.error_in_exec, ValueError)
439 self.assertIsInstance(res.error_in_exec, ValueError)
440 finally:
440 finally:
441 # Reset the custom exception hook
441 # Reset the custom exception hook
442 ip.set_custom_exc((), None)
442 ip.set_custom_exc((), None)
443
443
444 def test_mktempfile(self):
444 def test_mktempfile(self):
445 filename = ip.mktempfile()
445 filename = ip.mktempfile()
446 # Check that we can open the file again on Windows
446 # Check that we can open the file again on Windows
447 with open(filename, 'w') as f:
447 with open(filename, 'w') as f:
448 f.write('abc')
448 f.write('abc')
449
449
450 filename = ip.mktempfile(data='blah')
450 filename = ip.mktempfile(data='blah')
451 with open(filename, 'r') as f:
451 with open(filename, 'r') as f:
452 self.assertEqual(f.read(), 'blah')
452 self.assertEqual(f.read(), 'blah')
453
453
454 def test_new_main_mod(self):
454 def test_new_main_mod(self):
455 # Smoketest to check that this accepts a unicode module name
455 # Smoketest to check that this accepts a unicode module name
456 name = u'jiefmw'
456 name = u'jiefmw'
457 mod = ip.new_main_mod(u'%s.py' % name, name)
457 mod = ip.new_main_mod(u'%s.py' % name, name)
458 self.assertEqual(mod.__name__, name)
458 self.assertEqual(mod.__name__, name)
459
459
460 def test_get_exception_only(self):
460 def test_get_exception_only(self):
461 try:
461 try:
462 raise KeyboardInterrupt
462 raise KeyboardInterrupt
463 except KeyboardInterrupt:
463 except KeyboardInterrupt:
464 msg = ip.get_exception_only()
464 msg = ip.get_exception_only()
465 self.assertEqual(msg, 'KeyboardInterrupt\n')
465 self.assertEqual(msg, 'KeyboardInterrupt\n')
466
466
467 try:
467 try:
468 raise DerivedInterrupt("foo")
468 raise DerivedInterrupt("foo")
469 except KeyboardInterrupt:
469 except KeyboardInterrupt:
470 msg = ip.get_exception_only()
470 msg = ip.get_exception_only()
471 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
471 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
472
472
473 def test_inspect_text(self):
473 def test_inspect_text(self):
474 ip.run_cell('a = 5')
474 ip.run_cell('a = 5')
475 text = ip.object_inspect_text('a')
475 text = ip.object_inspect_text('a')
476 self.assertIsInstance(text, unicode_type)
476 self.assertIsInstance(text, str)
477
477
478
478
479 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
479 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
480
480
481 @onlyif_unicode_paths
481 @onlyif_unicode_paths
482 def setUp(self):
482 def setUp(self):
483 self.BASETESTDIR = tempfile.mkdtemp()
483 self.BASETESTDIR = tempfile.mkdtemp()
484 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
484 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
485 os.mkdir(self.TESTDIR)
485 os.mkdir(self.TESTDIR)
486 with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile:
486 with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile:
487 sfile.write("pass\n")
487 sfile.write("pass\n")
488 self.oldpath = py3compat.getcwd()
488 self.oldpath = os.getcwd()
489 os.chdir(self.TESTDIR)
489 os.chdir(self.TESTDIR)
490 self.fname = u"åäötestscript.py"
490 self.fname = u"åäötestscript.py"
491
491
492 def tearDown(self):
492 def tearDown(self):
493 os.chdir(self.oldpath)
493 os.chdir(self.oldpath)
494 shutil.rmtree(self.BASETESTDIR)
494 shutil.rmtree(self.BASETESTDIR)
495
495
496 @onlyif_unicode_paths
496 @onlyif_unicode_paths
497 def test_1(self):
497 def test_1(self):
498 """Test safe_execfile with non-ascii path
498 """Test safe_execfile with non-ascii path
499 """
499 """
500 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
500 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
501
501
502 class ExitCodeChecks(tt.TempFileMixin):
502 class ExitCodeChecks(tt.TempFileMixin):
503 def test_exit_code_ok(self):
503 def test_exit_code_ok(self):
504 self.system('exit 0')
504 self.system('exit 0')
505 self.assertEqual(ip.user_ns['_exit_code'], 0)
505 self.assertEqual(ip.user_ns['_exit_code'], 0)
506
506
507 def test_exit_code_error(self):
507 def test_exit_code_error(self):
508 self.system('exit 1')
508 self.system('exit 1')
509 self.assertEqual(ip.user_ns['_exit_code'], 1)
509 self.assertEqual(ip.user_ns['_exit_code'], 1)
510
510
511 @skipif(not hasattr(signal, 'SIGALRM'))
511 @skipif(not hasattr(signal, 'SIGALRM'))
512 def test_exit_code_signal(self):
512 def test_exit_code_signal(self):
513 self.mktmp("import signal, time\n"
513 self.mktmp("import signal, time\n"
514 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
514 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
515 "time.sleep(1)\n")
515 "time.sleep(1)\n")
516 self.system("%s %s" % (sys.executable, self.fname))
516 self.system("%s %s" % (sys.executable, self.fname))
517 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
517 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
518
518
519 @onlyif_cmds_exist("csh")
519 @onlyif_cmds_exist("csh")
520 def test_exit_code_signal_csh(self):
520 def test_exit_code_signal_csh(self):
521 SHELL = os.environ.get('SHELL', None)
521 SHELL = os.environ.get('SHELL', None)
522 os.environ['SHELL'] = find_cmd("csh")
522 os.environ['SHELL'] = find_cmd("csh")
523 try:
523 try:
524 self.test_exit_code_signal()
524 self.test_exit_code_signal()
525 finally:
525 finally:
526 if SHELL is not None:
526 if SHELL is not None:
527 os.environ['SHELL'] = SHELL
527 os.environ['SHELL'] = SHELL
528 else:
528 else:
529 del os.environ['SHELL']
529 del os.environ['SHELL']
530
530
531 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
531 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
532 system = ip.system_raw
532 system = ip.system_raw
533
533
534 @onlyif_unicode_paths
534 @onlyif_unicode_paths
535 def test_1(self):
535 def test_1(self):
536 """Test system_raw with non-ascii cmd
536 """Test system_raw with non-ascii cmd
537 """
537 """
538 cmd = u'''python -c "'åäö'" '''
538 cmd = u'''python -c "'åäö'" '''
539 ip.system_raw(cmd)
539 ip.system_raw(cmd)
540
540
541 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
541 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
542 @mock.patch('os.system', side_effect=KeyboardInterrupt)
542 @mock.patch('os.system', side_effect=KeyboardInterrupt)
543 def test_control_c(self, *mocks):
543 def test_control_c(self, *mocks):
544 try:
544 try:
545 self.system("sleep 1 # wont happen")
545 self.system("sleep 1 # wont happen")
546 except KeyboardInterrupt:
546 except KeyboardInterrupt:
547 self.fail("system call should intercept "
547 self.fail("system call should intercept "
548 "keyboard interrupt from subprocess.call")
548 "keyboard interrupt from subprocess.call")
549 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
549 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
550
550
551 # TODO: Exit codes are currently ignored on Windows.
551 # TODO: Exit codes are currently ignored on Windows.
552 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
552 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
553 system = ip.system_piped
553 system = ip.system_piped
554
554
555 @skip_win32
555 @skip_win32
556 def test_exit_code_ok(self):
556 def test_exit_code_ok(self):
557 ExitCodeChecks.test_exit_code_ok(self)
557 ExitCodeChecks.test_exit_code_ok(self)
558
558
559 @skip_win32
559 @skip_win32
560 def test_exit_code_error(self):
560 def test_exit_code_error(self):
561 ExitCodeChecks.test_exit_code_error(self)
561 ExitCodeChecks.test_exit_code_error(self)
562
562
563 @skip_win32
563 @skip_win32
564 def test_exit_code_signal(self):
564 def test_exit_code_signal(self):
565 ExitCodeChecks.test_exit_code_signal(self)
565 ExitCodeChecks.test_exit_code_signal(self)
566
566
567 class TestModules(unittest.TestCase, tt.TempFileMixin):
567 class TestModules(unittest.TestCase, tt.TempFileMixin):
568 def test_extraneous_loads(self):
568 def test_extraneous_loads(self):
569 """Test we're not loading modules on startup that we shouldn't.
569 """Test we're not loading modules on startup that we shouldn't.
570 """
570 """
571 self.mktmp("import sys\n"
571 self.mktmp("import sys\n"
572 "print('numpy' in sys.modules)\n"
572 "print('numpy' in sys.modules)\n"
573 "print('ipyparallel' in sys.modules)\n"
573 "print('ipyparallel' in sys.modules)\n"
574 "print('ipykernel' in sys.modules)\n"
574 "print('ipykernel' in sys.modules)\n"
575 )
575 )
576 out = "False\nFalse\nFalse\n"
576 out = "False\nFalse\nFalse\n"
577 tt.ipexec_validate(self.fname, out)
577 tt.ipexec_validate(self.fname, out)
578
578
579 class Negator(ast.NodeTransformer):
579 class Negator(ast.NodeTransformer):
580 """Negates all number literals in an AST."""
580 """Negates all number literals in an AST."""
581 def visit_Num(self, node):
581 def visit_Num(self, node):
582 node.n = -node.n
582 node.n = -node.n
583 return node
583 return node
584
584
585 class TestAstTransform(unittest.TestCase):
585 class TestAstTransform(unittest.TestCase):
586 def setUp(self):
586 def setUp(self):
587 self.negator = Negator()
587 self.negator = Negator()
588 ip.ast_transformers.append(self.negator)
588 ip.ast_transformers.append(self.negator)
589
589
590 def tearDown(self):
590 def tearDown(self):
591 ip.ast_transformers.remove(self.negator)
591 ip.ast_transformers.remove(self.negator)
592
592
593 def test_run_cell(self):
593 def test_run_cell(self):
594 with tt.AssertPrints('-34'):
594 with tt.AssertPrints('-34'):
595 ip.run_cell('print (12 + 22)')
595 ip.run_cell('print (12 + 22)')
596
596
597 # A named reference to a number shouldn't be transformed.
597 # A named reference to a number shouldn't be transformed.
598 ip.user_ns['n'] = 55
598 ip.user_ns['n'] = 55
599 with tt.AssertNotPrints('-55'):
599 with tt.AssertNotPrints('-55'):
600 ip.run_cell('print (n)')
600 ip.run_cell('print (n)')
601
601
602 def test_timeit(self):
602 def test_timeit(self):
603 called = set()
603 called = set()
604 def f(x):
604 def f(x):
605 called.add(x)
605 called.add(x)
606 ip.push({'f':f})
606 ip.push({'f':f})
607
607
608 with tt.AssertPrints("average of "):
608 with tt.AssertPrints("average of "):
609 ip.run_line_magic("timeit", "-n1 f(1)")
609 ip.run_line_magic("timeit", "-n1 f(1)")
610 self.assertEqual(called, {-1})
610 self.assertEqual(called, {-1})
611 called.clear()
611 called.clear()
612
612
613 with tt.AssertPrints("average of "):
613 with tt.AssertPrints("average of "):
614 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
614 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
615 self.assertEqual(called, {-2, -3})
615 self.assertEqual(called, {-2, -3})
616
616
617 def test_time(self):
617 def test_time(self):
618 called = []
618 called = []
619 def f(x):
619 def f(x):
620 called.append(x)
620 called.append(x)
621 ip.push({'f':f})
621 ip.push({'f':f})
622
622
623 # Test with an expression
623 # Test with an expression
624 with tt.AssertPrints("Wall time: "):
624 with tt.AssertPrints("Wall time: "):
625 ip.run_line_magic("time", "f(5+9)")
625 ip.run_line_magic("time", "f(5+9)")
626 self.assertEqual(called, [-14])
626 self.assertEqual(called, [-14])
627 called[:] = []
627 called[:] = []
628
628
629 # Test with a statement (different code path)
629 # Test with a statement (different code path)
630 with tt.AssertPrints("Wall time: "):
630 with tt.AssertPrints("Wall time: "):
631 ip.run_line_magic("time", "a = f(-3 + -2)")
631 ip.run_line_magic("time", "a = f(-3 + -2)")
632 self.assertEqual(called, [5])
632 self.assertEqual(called, [5])
633
633
634 def test_macro(self):
634 def test_macro(self):
635 ip.push({'a':10})
635 ip.push({'a':10})
636 # The AST transformation makes this do a+=-1
636 # The AST transformation makes this do a+=-1
637 ip.define_macro("amacro", "a+=1\nprint(a)")
637 ip.define_macro("amacro", "a+=1\nprint(a)")
638
638
639 with tt.AssertPrints("9"):
639 with tt.AssertPrints("9"):
640 ip.run_cell("amacro")
640 ip.run_cell("amacro")
641 with tt.AssertPrints("8"):
641 with tt.AssertPrints("8"):
642 ip.run_cell("amacro")
642 ip.run_cell("amacro")
643
643
644 class IntegerWrapper(ast.NodeTransformer):
644 class IntegerWrapper(ast.NodeTransformer):
645 """Wraps all integers in a call to Integer()"""
645 """Wraps all integers in a call to Integer()"""
646 def visit_Num(self, node):
646 def visit_Num(self, node):
647 if isinstance(node.n, int):
647 if isinstance(node.n, int):
648 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
648 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
649 args=[node], keywords=[])
649 args=[node], keywords=[])
650 return node
650 return node
651
651
652 class TestAstTransform2(unittest.TestCase):
652 class TestAstTransform2(unittest.TestCase):
653 def setUp(self):
653 def setUp(self):
654 self.intwrapper = IntegerWrapper()
654 self.intwrapper = IntegerWrapper()
655 ip.ast_transformers.append(self.intwrapper)
655 ip.ast_transformers.append(self.intwrapper)
656
656
657 self.calls = []
657 self.calls = []
658 def Integer(*args):
658 def Integer(*args):
659 self.calls.append(args)
659 self.calls.append(args)
660 return args
660 return args
661 ip.push({"Integer": Integer})
661 ip.push({"Integer": Integer})
662
662
663 def tearDown(self):
663 def tearDown(self):
664 ip.ast_transformers.remove(self.intwrapper)
664 ip.ast_transformers.remove(self.intwrapper)
665 del ip.user_ns['Integer']
665 del ip.user_ns['Integer']
666
666
667 def test_run_cell(self):
667 def test_run_cell(self):
668 ip.run_cell("n = 2")
668 ip.run_cell("n = 2")
669 self.assertEqual(self.calls, [(2,)])
669 self.assertEqual(self.calls, [(2,)])
670
670
671 # This shouldn't throw an error
671 # This shouldn't throw an error
672 ip.run_cell("o = 2.0")
672 ip.run_cell("o = 2.0")
673 self.assertEqual(ip.user_ns['o'], 2.0)
673 self.assertEqual(ip.user_ns['o'], 2.0)
674
674
675 def test_timeit(self):
675 def test_timeit(self):
676 called = set()
676 called = set()
677 def f(x):
677 def f(x):
678 called.add(x)
678 called.add(x)
679 ip.push({'f':f})
679 ip.push({'f':f})
680
680
681 with tt.AssertPrints("average of "):
681 with tt.AssertPrints("average of "):
682 ip.run_line_magic("timeit", "-n1 f(1)")
682 ip.run_line_magic("timeit", "-n1 f(1)")
683 self.assertEqual(called, {(1,)})
683 self.assertEqual(called, {(1,)})
684 called.clear()
684 called.clear()
685
685
686 with tt.AssertPrints("average of "):
686 with tt.AssertPrints("average of "):
687 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
687 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
688 self.assertEqual(called, {(2,), (3,)})
688 self.assertEqual(called, {(2,), (3,)})
689
689
690 class ErrorTransformer(ast.NodeTransformer):
690 class ErrorTransformer(ast.NodeTransformer):
691 """Throws an error when it sees a number."""
691 """Throws an error when it sees a number."""
692 def visit_Num(self, node):
692 def visit_Num(self, node):
693 raise ValueError("test")
693 raise ValueError("test")
694
694
695 class TestAstTransformError(unittest.TestCase):
695 class TestAstTransformError(unittest.TestCase):
696 def test_unregistering(self):
696 def test_unregistering(self):
697 err_transformer = ErrorTransformer()
697 err_transformer = ErrorTransformer()
698 ip.ast_transformers.append(err_transformer)
698 ip.ast_transformers.append(err_transformer)
699
699
700 with tt.AssertPrints("unregister", channel='stderr'):
700 with tt.AssertPrints("unregister", channel='stderr'):
701 ip.run_cell("1 + 2")
701 ip.run_cell("1 + 2")
702
702
703 # This should have been removed.
703 # This should have been removed.
704 nt.assert_not_in(err_transformer, ip.ast_transformers)
704 nt.assert_not_in(err_transformer, ip.ast_transformers)
705
705
706
706
707 class StringRejector(ast.NodeTransformer):
707 class StringRejector(ast.NodeTransformer):
708 """Throws an InputRejected when it sees a string literal.
708 """Throws an InputRejected when it sees a string literal.
709
709
710 Used to verify that NodeTransformers can signal that a piece of code should
710 Used to verify that NodeTransformers can signal that a piece of code should
711 not be executed by throwing an InputRejected.
711 not be executed by throwing an InputRejected.
712 """
712 """
713
713
714 def visit_Str(self, node):
714 def visit_Str(self, node):
715 raise InputRejected("test")
715 raise InputRejected("test")
716
716
717
717
718 class TestAstTransformInputRejection(unittest.TestCase):
718 class TestAstTransformInputRejection(unittest.TestCase):
719
719
720 def setUp(self):
720 def setUp(self):
721 self.transformer = StringRejector()
721 self.transformer = StringRejector()
722 ip.ast_transformers.append(self.transformer)
722 ip.ast_transformers.append(self.transformer)
723
723
724 def tearDown(self):
724 def tearDown(self):
725 ip.ast_transformers.remove(self.transformer)
725 ip.ast_transformers.remove(self.transformer)
726
726
727 def test_input_rejection(self):
727 def test_input_rejection(self):
728 """Check that NodeTransformers can reject input."""
728 """Check that NodeTransformers can reject input."""
729
729
730 expect_exception_tb = tt.AssertPrints("InputRejected: test")
730 expect_exception_tb = tt.AssertPrints("InputRejected: test")
731 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
731 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
732
732
733 # Run the same check twice to verify that the transformer is not
733 # Run the same check twice to verify that the transformer is not
734 # disabled after raising.
734 # disabled after raising.
735 with expect_exception_tb, expect_no_cell_output:
735 with expect_exception_tb, expect_no_cell_output:
736 ip.run_cell("'unsafe'")
736 ip.run_cell("'unsafe'")
737
737
738 with expect_exception_tb, expect_no_cell_output:
738 with expect_exception_tb, expect_no_cell_output:
739 res = ip.run_cell("'unsafe'")
739 res = ip.run_cell("'unsafe'")
740
740
741 self.assertIsInstance(res.error_before_exec, InputRejected)
741 self.assertIsInstance(res.error_before_exec, InputRejected)
742
742
743 def test__IPYTHON__():
743 def test__IPYTHON__():
744 # This shouldn't raise a NameError, that's all
744 # This shouldn't raise a NameError, that's all
745 __IPYTHON__
745 __IPYTHON__
746
746
747
747
748 class DummyRepr(object):
748 class DummyRepr(object):
749 def __repr__(self):
749 def __repr__(self):
750 return "DummyRepr"
750 return "DummyRepr"
751
751
752 def _repr_html_(self):
752 def _repr_html_(self):
753 return "<b>dummy</b>"
753 return "<b>dummy</b>"
754
754
755 def _repr_javascript_(self):
755 def _repr_javascript_(self):
756 return "console.log('hi');", {'key': 'value'}
756 return "console.log('hi');", {'key': 'value'}
757
757
758
758
759 def test_user_variables():
759 def test_user_variables():
760 # enable all formatters
760 # enable all formatters
761 ip.display_formatter.active_types = ip.display_formatter.format_types
761 ip.display_formatter.active_types = ip.display_formatter.format_types
762
762
763 ip.user_ns['dummy'] = d = DummyRepr()
763 ip.user_ns['dummy'] = d = DummyRepr()
764 keys = {'dummy', 'doesnotexist'}
764 keys = {'dummy', 'doesnotexist'}
765 r = ip.user_expressions({ key:key for key in keys})
765 r = ip.user_expressions({ key:key for key in keys})
766
766
767 nt.assert_equal(keys, set(r.keys()))
767 nt.assert_equal(keys, set(r.keys()))
768 dummy = r['dummy']
768 dummy = r['dummy']
769 nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
769 nt.assert_equal({'status', 'data', 'metadata'}, set(dummy.keys()))
770 nt.assert_equal(dummy['status'], 'ok')
770 nt.assert_equal(dummy['status'], 'ok')
771 data = dummy['data']
771 data = dummy['data']
772 metadata = dummy['metadata']
772 metadata = dummy['metadata']
773 nt.assert_equal(data.get('text/html'), d._repr_html_())
773 nt.assert_equal(data.get('text/html'), d._repr_html_())
774 js, jsmd = d._repr_javascript_()
774 js, jsmd = d._repr_javascript_()
775 nt.assert_equal(data.get('application/javascript'), js)
775 nt.assert_equal(data.get('application/javascript'), js)
776 nt.assert_equal(metadata.get('application/javascript'), jsmd)
776 nt.assert_equal(metadata.get('application/javascript'), jsmd)
777
777
778 dne = r['doesnotexist']
778 dne = r['doesnotexist']
779 nt.assert_equal(dne['status'], 'error')
779 nt.assert_equal(dne['status'], 'error')
780 nt.assert_equal(dne['ename'], 'NameError')
780 nt.assert_equal(dne['ename'], 'NameError')
781
781
782 # back to text only
782 # back to text only
783 ip.display_formatter.active_types = ['text/plain']
783 ip.display_formatter.active_types = ['text/plain']
784
784
785 def test_user_expression():
785 def test_user_expression():
786 # enable all formatters
786 # enable all formatters
787 ip.display_formatter.active_types = ip.display_formatter.format_types
787 ip.display_formatter.active_types = ip.display_formatter.format_types
788 query = {
788 query = {
789 'a' : '1 + 2',
789 'a' : '1 + 2',
790 'b' : '1/0',
790 'b' : '1/0',
791 }
791 }
792 r = ip.user_expressions(query)
792 r = ip.user_expressions(query)
793 import pprint
793 import pprint
794 pprint.pprint(r)
794 pprint.pprint(r)
795 nt.assert_equal(set(r.keys()), set(query.keys()))
795 nt.assert_equal(set(r.keys()), set(query.keys()))
796 a = r['a']
796 a = r['a']
797 nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
797 nt.assert_equal({'status', 'data', 'metadata'}, set(a.keys()))
798 nt.assert_equal(a['status'], 'ok')
798 nt.assert_equal(a['status'], 'ok')
799 data = a['data']
799 data = a['data']
800 metadata = a['metadata']
800 metadata = a['metadata']
801 nt.assert_equal(data.get('text/plain'), '3')
801 nt.assert_equal(data.get('text/plain'), '3')
802
802
803 b = r['b']
803 b = r['b']
804 nt.assert_equal(b['status'], 'error')
804 nt.assert_equal(b['status'], 'error')
805 nt.assert_equal(b['ename'], 'ZeroDivisionError')
805 nt.assert_equal(b['ename'], 'ZeroDivisionError')
806
806
807 # back to text only
807 # back to text only
808 ip.display_formatter.active_types = ['text/plain']
808 ip.display_formatter.active_types = ['text/plain']
809
809
810
810
811
811
812
812
813
813
814 class TestSyntaxErrorTransformer(unittest.TestCase):
814 class TestSyntaxErrorTransformer(unittest.TestCase):
815 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
815 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
816
816
817 class SyntaxErrorTransformer(InputTransformer):
817 class SyntaxErrorTransformer(InputTransformer):
818
818
819 def push(self, line):
819 def push(self, line):
820 pos = line.find('syntaxerror')
820 pos = line.find('syntaxerror')
821 if pos >= 0:
821 if pos >= 0:
822 e = SyntaxError('input contains "syntaxerror"')
822 e = SyntaxError('input contains "syntaxerror"')
823 e.text = line
823 e.text = line
824 e.offset = pos + 1
824 e.offset = pos + 1
825 raise e
825 raise e
826 return line
826 return line
827
827
828 def reset(self):
828 def reset(self):
829 pass
829 pass
830
830
831 def setUp(self):
831 def setUp(self):
832 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
832 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
833 ip.input_splitter.python_line_transforms.append(self.transformer)
833 ip.input_splitter.python_line_transforms.append(self.transformer)
834 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
834 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
835
835
836 def tearDown(self):
836 def tearDown(self):
837 ip.input_splitter.python_line_transforms.remove(self.transformer)
837 ip.input_splitter.python_line_transforms.remove(self.transformer)
838 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
838 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
839
839
840 def test_syntaxerror_input_transformer(self):
840 def test_syntaxerror_input_transformer(self):
841 with tt.AssertPrints('1234'):
841 with tt.AssertPrints('1234'):
842 ip.run_cell('1234')
842 ip.run_cell('1234')
843 with tt.AssertPrints('SyntaxError: invalid syntax'):
843 with tt.AssertPrints('SyntaxError: invalid syntax'):
844 ip.run_cell('1 2 3') # plain python syntax error
844 ip.run_cell('1 2 3') # plain python syntax error
845 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
845 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
846 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
846 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
847 with tt.AssertPrints('3456'):
847 with tt.AssertPrints('3456'):
848 ip.run_cell('3456')
848 ip.run_cell('3456')
849
849
850
850
851
851
852 def test_warning_suppression():
852 def test_warning_suppression():
853 ip.run_cell("import warnings")
853 ip.run_cell("import warnings")
854 try:
854 try:
855 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
855 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
856 ip.run_cell("warnings.warn('asdf')")
856 ip.run_cell("warnings.warn('asdf')")
857 # Here's the real test -- if we run that again, we should get the
857 # Here's the real test -- if we run that again, we should get the
858 # warning again. Traditionally, each warning was only issued once per
858 # warning again. Traditionally, each warning was only issued once per
859 # IPython session (approximately), even if the user typed in new and
859 # IPython session (approximately), even if the user typed in new and
860 # different code that should have also triggered the warning, leading
860 # different code that should have also triggered the warning, leading
861 # to much confusion.
861 # to much confusion.
862 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
862 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
863 ip.run_cell("warnings.warn('asdf')")
863 ip.run_cell("warnings.warn('asdf')")
864 finally:
864 finally:
865 ip.run_cell("del warnings")
865 ip.run_cell("del warnings")
866
866
867
867
868 def test_deprecation_warning():
868 def test_deprecation_warning():
869 ip.run_cell("""
869 ip.run_cell("""
870 import warnings
870 import warnings
871 def wrn():
871 def wrn():
872 warnings.warn(
872 warnings.warn(
873 "I AM A WARNING",
873 "I AM A WARNING",
874 DeprecationWarning
874 DeprecationWarning
875 )
875 )
876 """)
876 """)
877 try:
877 try:
878 with tt.AssertPrints("I AM A WARNING", channel="stderr"):
878 with tt.AssertPrints("I AM A WARNING", channel="stderr"):
879 ip.run_cell("wrn()")
879 ip.run_cell("wrn()")
880 finally:
880 finally:
881 ip.run_cell("del warnings")
881 ip.run_cell("del warnings")
882 ip.run_cell("del wrn")
882 ip.run_cell("del wrn")
883
883
884
884
885 class TestImportNoDeprecate(tt.TempFileMixin):
885 class TestImportNoDeprecate(tt.TempFileMixin):
886
886
887 def setup(self):
887 def setup(self):
888 """Make a valid python temp file."""
888 """Make a valid python temp file."""
889 self.mktmp("""
889 self.mktmp("""
890 import warnings
890 import warnings
891 def wrn():
891 def wrn():
892 warnings.warn(
892 warnings.warn(
893 "I AM A WARNING",
893 "I AM A WARNING",
894 DeprecationWarning
894 DeprecationWarning
895 )
895 )
896 """)
896 """)
897
897
898 def test_no_dep(self):
898 def test_no_dep(self):
899 """
899 """
900 No deprecation warning should be raised from imported functions
900 No deprecation warning should be raised from imported functions
901 """
901 """
902 ip.run_cell("from {} import wrn".format(self.fname))
902 ip.run_cell("from {} import wrn".format(self.fname))
903
903
904 with tt.AssertNotPrints("I AM A WARNING"):
904 with tt.AssertNotPrints("I AM A WARNING"):
905 ip.run_cell("wrn()")
905 ip.run_cell("wrn()")
906 ip.run_cell("del wrn")
906 ip.run_cell("del wrn")
@@ -1,987 +1,987 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6
6
7 import io
7 import io
8 import os
8 import os
9 import sys
9 import sys
10 import warnings
10 import warnings
11 from unittest import TestCase
11 from unittest import TestCase
12
12
13 try:
13 try:
14 from importlib import invalidate_caches # Required from Python 3.3
14 from importlib import invalidate_caches # Required from Python 3.3
15 except ImportError:
15 except ImportError:
16 def invalidate_caches():
16 def invalidate_caches():
17 pass
17 pass
18
18
19 import nose.tools as nt
19 import nose.tools as nt
20
20
21 from IPython import get_ipython
21 from IPython import get_ipython
22 from IPython.core import magic
22 from IPython.core import magic
23 from IPython.core.error import UsageError
23 from IPython.core.error import UsageError
24 from IPython.core.magic import (Magics, magics_class, line_magic,
24 from IPython.core.magic import (Magics, magics_class, line_magic,
25 cell_magic,
25 cell_magic,
26 register_line_magic, register_cell_magic)
26 register_line_magic, register_cell_magic)
27 from IPython.core.magics import execution, script, code
27 from IPython.core.magics import execution, script, code
28 from IPython.testing import decorators as dec
28 from IPython.testing import decorators as dec
29 from IPython.testing import tools as tt
29 from IPython.testing import tools as tt
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31 from IPython.utils.io import capture_output
31 from IPython.utils.io import capture_output
32 from IPython.utils.tempdir import TemporaryDirectory
32 from IPython.utils.tempdir import TemporaryDirectory
33 from IPython.utils.process import find_cmd
33 from IPython.utils.process import find_cmd
34
34
35 if py3compat.PY3:
35 if py3compat.PY3:
36 from io import StringIO
36 from io import StringIO
37 else:
37 else:
38 from StringIO import StringIO
38 from StringIO import StringIO
39
39
40
40
41 _ip = get_ipython()
41 _ip = get_ipython()
42
42
43 @magic.magics_class
43 @magic.magics_class
44 class DummyMagics(magic.Magics): pass
44 class DummyMagics(magic.Magics): pass
45
45
46 def test_extract_code_ranges():
46 def test_extract_code_ranges():
47 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
47 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
48 expected = [(0, 1),
48 expected = [(0, 1),
49 (2, 3),
49 (2, 3),
50 (4, 6),
50 (4, 6),
51 (6, 9),
51 (6, 9),
52 (9, 14),
52 (9, 14),
53 (16, None),
53 (16, None),
54 (None, 9),
54 (None, 9),
55 (9, None),
55 (9, None),
56 (None, 13),
56 (None, 13),
57 (None, None)]
57 (None, None)]
58 actual = list(code.extract_code_ranges(instr))
58 actual = list(code.extract_code_ranges(instr))
59 nt.assert_equal(actual, expected)
59 nt.assert_equal(actual, expected)
60
60
61 def test_extract_symbols():
61 def test_extract_symbols():
62 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
62 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
63 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
63 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
64 expected = [([], ['a']),
64 expected = [([], ['a']),
65 (["def b():\n return 42\n"], []),
65 (["def b():\n return 42\n"], []),
66 (["class A: pass\n"], []),
66 (["class A: pass\n"], []),
67 (["class A: pass\n", "def b():\n return 42\n"], []),
67 (["class A: pass\n", "def b():\n return 42\n"], []),
68 (["class A: pass\n"], ['a']),
68 (["class A: pass\n"], ['a']),
69 ([], ['z'])]
69 ([], ['z'])]
70 for symbols, exp in zip(symbols_args, expected):
70 for symbols, exp in zip(symbols_args, expected):
71 nt.assert_equal(code.extract_symbols(source, symbols), exp)
71 nt.assert_equal(code.extract_symbols(source, symbols), exp)
72
72
73
73
74 def test_extract_symbols_raises_exception_with_non_python_code():
74 def test_extract_symbols_raises_exception_with_non_python_code():
75 source = ("=begin A Ruby program :)=end\n"
75 source = ("=begin A Ruby program :)=end\n"
76 "def hello\n"
76 "def hello\n"
77 "puts 'Hello world'\n"
77 "puts 'Hello world'\n"
78 "end")
78 "end")
79 with nt.assert_raises(SyntaxError):
79 with nt.assert_raises(SyntaxError):
80 code.extract_symbols(source, "hello")
80 code.extract_symbols(source, "hello")
81
81
82 def test_config():
82 def test_config():
83 """ test that config magic does not raise
83 """ test that config magic does not raise
84 can happen if Configurable init is moved too early into
84 can happen if Configurable init is moved too early into
85 Magics.__init__ as then a Config object will be registerd as a
85 Magics.__init__ as then a Config object will be registerd as a
86 magic.
86 magic.
87 """
87 """
88 ## should not raise.
88 ## should not raise.
89 _ip.magic('config')
89 _ip.magic('config')
90
90
91 def test_rehashx():
91 def test_rehashx():
92 # clear up everything
92 # clear up everything
93 _ip.alias_manager.clear_aliases()
93 _ip.alias_manager.clear_aliases()
94 del _ip.db['syscmdlist']
94 del _ip.db['syscmdlist']
95
95
96 _ip.magic('rehashx')
96 _ip.magic('rehashx')
97 # Practically ALL ipython development systems will have more than 10 aliases
97 # Practically ALL ipython development systems will have more than 10 aliases
98
98
99 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
99 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
100 for name, cmd in _ip.alias_manager.aliases:
100 for name, cmd in _ip.alias_manager.aliases:
101 # we must strip dots from alias names
101 # we must strip dots from alias names
102 nt.assert_not_in('.', name)
102 nt.assert_not_in('.', name)
103
103
104 # rehashx must fill up syscmdlist
104 # rehashx must fill up syscmdlist
105 scoms = _ip.db['syscmdlist']
105 scoms = _ip.db['syscmdlist']
106 nt.assert_true(len(scoms) > 10)
106 nt.assert_true(len(scoms) > 10)
107
107
108
108
109 def test_magic_parse_options():
109 def test_magic_parse_options():
110 """Test that we don't mangle paths when parsing magic options."""
110 """Test that we don't mangle paths when parsing magic options."""
111 ip = get_ipython()
111 ip = get_ipython()
112 path = 'c:\\x'
112 path = 'c:\\x'
113 m = DummyMagics(ip)
113 m = DummyMagics(ip)
114 opts = m.parse_options('-f %s' % path,'f:')[0]
114 opts = m.parse_options('-f %s' % path,'f:')[0]
115 # argv splitting is os-dependent
115 # argv splitting is os-dependent
116 if os.name == 'posix':
116 if os.name == 'posix':
117 expected = 'c:x'
117 expected = 'c:x'
118 else:
118 else:
119 expected = path
119 expected = path
120 nt.assert_equal(opts['f'], expected)
120 nt.assert_equal(opts['f'], expected)
121
121
122 def test_magic_parse_long_options():
122 def test_magic_parse_long_options():
123 """Magic.parse_options can handle --foo=bar long options"""
123 """Magic.parse_options can handle --foo=bar long options"""
124 ip = get_ipython()
124 ip = get_ipython()
125 m = DummyMagics(ip)
125 m = DummyMagics(ip)
126 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
126 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
127 nt.assert_in('foo', opts)
127 nt.assert_in('foo', opts)
128 nt.assert_in('bar', opts)
128 nt.assert_in('bar', opts)
129 nt.assert_equal(opts['bar'], "bubble")
129 nt.assert_equal(opts['bar'], "bubble")
130
130
131
131
132 @dec.skip_without('sqlite3')
132 @dec.skip_without('sqlite3')
133 def doctest_hist_f():
133 def doctest_hist_f():
134 """Test %hist -f with temporary filename.
134 """Test %hist -f with temporary filename.
135
135
136 In [9]: import tempfile
136 In [9]: import tempfile
137
137
138 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
138 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
139
139
140 In [11]: %hist -nl -f $tfile 3
140 In [11]: %hist -nl -f $tfile 3
141
141
142 In [13]: import os; os.unlink(tfile)
142 In [13]: import os; os.unlink(tfile)
143 """
143 """
144
144
145
145
146 @dec.skip_without('sqlite3')
146 @dec.skip_without('sqlite3')
147 def doctest_hist_r():
147 def doctest_hist_r():
148 """Test %hist -r
148 """Test %hist -r
149
149
150 XXX - This test is not recording the output correctly. For some reason, in
150 XXX - This test is not recording the output correctly. For some reason, in
151 testing mode the raw history isn't getting populated. No idea why.
151 testing mode the raw history isn't getting populated. No idea why.
152 Disabling the output checking for now, though at least we do run it.
152 Disabling the output checking for now, though at least we do run it.
153
153
154 In [1]: 'hist' in _ip.lsmagic()
154 In [1]: 'hist' in _ip.lsmagic()
155 Out[1]: True
155 Out[1]: True
156
156
157 In [2]: x=1
157 In [2]: x=1
158
158
159 In [3]: %hist -rl 2
159 In [3]: %hist -rl 2
160 x=1 # random
160 x=1 # random
161 %hist -r 2
161 %hist -r 2
162 """
162 """
163
163
164
164
165 @dec.skip_without('sqlite3')
165 @dec.skip_without('sqlite3')
166 def doctest_hist_op():
166 def doctest_hist_op():
167 """Test %hist -op
167 """Test %hist -op
168
168
169 In [1]: class b(float):
169 In [1]: class b(float):
170 ...: pass
170 ...: pass
171 ...:
171 ...:
172
172
173 In [2]: class s(object):
173 In [2]: class s(object):
174 ...: def __str__(self):
174 ...: def __str__(self):
175 ...: return 's'
175 ...: return 's'
176 ...:
176 ...:
177
177
178 In [3]:
178 In [3]:
179
179
180 In [4]: class r(b):
180 In [4]: class r(b):
181 ...: def __repr__(self):
181 ...: def __repr__(self):
182 ...: return 'r'
182 ...: return 'r'
183 ...:
183 ...:
184
184
185 In [5]: class sr(s,r): pass
185 In [5]: class sr(s,r): pass
186 ...:
186 ...:
187
187
188 In [6]:
188 In [6]:
189
189
190 In [7]: bb=b()
190 In [7]: bb=b()
191
191
192 In [8]: ss=s()
192 In [8]: ss=s()
193
193
194 In [9]: rr=r()
194 In [9]: rr=r()
195
195
196 In [10]: ssrr=sr()
196 In [10]: ssrr=sr()
197
197
198 In [11]: 4.5
198 In [11]: 4.5
199 Out[11]: 4.5
199 Out[11]: 4.5
200
200
201 In [12]: str(ss)
201 In [12]: str(ss)
202 Out[12]: 's'
202 Out[12]: 's'
203
203
204 In [13]:
204 In [13]:
205
205
206 In [14]: %hist -op
206 In [14]: %hist -op
207 >>> class b:
207 >>> class b:
208 ... pass
208 ... pass
209 ...
209 ...
210 >>> class s(b):
210 >>> class s(b):
211 ... def __str__(self):
211 ... def __str__(self):
212 ... return 's'
212 ... return 's'
213 ...
213 ...
214 >>>
214 >>>
215 >>> class r(b):
215 >>> class r(b):
216 ... def __repr__(self):
216 ... def __repr__(self):
217 ... return 'r'
217 ... return 'r'
218 ...
218 ...
219 >>> class sr(s,r): pass
219 >>> class sr(s,r): pass
220 >>>
220 >>>
221 >>> bb=b()
221 >>> bb=b()
222 >>> ss=s()
222 >>> ss=s()
223 >>> rr=r()
223 >>> rr=r()
224 >>> ssrr=sr()
224 >>> ssrr=sr()
225 >>> 4.5
225 >>> 4.5
226 4.5
226 4.5
227 >>> str(ss)
227 >>> str(ss)
228 's'
228 's'
229 >>>
229 >>>
230 """
230 """
231
231
232 def test_hist_pof():
232 def test_hist_pof():
233 ip = get_ipython()
233 ip = get_ipython()
234 ip.run_cell(u"1+2", store_history=True)
234 ip.run_cell(u"1+2", store_history=True)
235 #raise Exception(ip.history_manager.session_number)
235 #raise Exception(ip.history_manager.session_number)
236 #raise Exception(list(ip.history_manager._get_range_session()))
236 #raise Exception(list(ip.history_manager._get_range_session()))
237 with TemporaryDirectory() as td:
237 with TemporaryDirectory() as td:
238 tf = os.path.join(td, 'hist.py')
238 tf = os.path.join(td, 'hist.py')
239 ip.run_line_magic('history', '-pof %s' % tf)
239 ip.run_line_magic('history', '-pof %s' % tf)
240 assert os.path.isfile(tf)
240 assert os.path.isfile(tf)
241
241
242
242
243 @dec.skip_without('sqlite3')
243 @dec.skip_without('sqlite3')
244 def test_macro():
244 def test_macro():
245 ip = get_ipython()
245 ip = get_ipython()
246 ip.history_manager.reset() # Clear any existing history.
246 ip.history_manager.reset() # Clear any existing history.
247 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
247 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
248 for i, cmd in enumerate(cmds, start=1):
248 for i, cmd in enumerate(cmds, start=1):
249 ip.history_manager.store_inputs(i, cmd)
249 ip.history_manager.store_inputs(i, cmd)
250 ip.magic("macro test 1-3")
250 ip.magic("macro test 1-3")
251 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
251 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
252
252
253 # List macros
253 # List macros
254 nt.assert_in("test", ip.magic("macro"))
254 nt.assert_in("test", ip.magic("macro"))
255
255
256
256
257 @dec.skip_without('sqlite3')
257 @dec.skip_without('sqlite3')
258 def test_macro_run():
258 def test_macro_run():
259 """Test that we can run a multi-line macro successfully."""
259 """Test that we can run a multi-line macro successfully."""
260 ip = get_ipython()
260 ip = get_ipython()
261 ip.history_manager.reset()
261 ip.history_manager.reset()
262 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
262 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
263 "%macro test 2-3"]
263 "%macro test 2-3"]
264 for cmd in cmds:
264 for cmd in cmds:
265 ip.run_cell(cmd, store_history=True)
265 ip.run_cell(cmd, store_history=True)
266 nt.assert_equal(ip.user_ns["test"].value,
266 nt.assert_equal(ip.user_ns["test"].value,
267 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
267 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
268 with tt.AssertPrints("12"):
268 with tt.AssertPrints("12"):
269 ip.run_cell("test")
269 ip.run_cell("test")
270 with tt.AssertPrints("13"):
270 with tt.AssertPrints("13"):
271 ip.run_cell("test")
271 ip.run_cell("test")
272
272
273
273
274 def test_magic_magic():
274 def test_magic_magic():
275 """Test %magic"""
275 """Test %magic"""
276 ip = get_ipython()
276 ip = get_ipython()
277 with capture_output() as captured:
277 with capture_output() as captured:
278 ip.magic("magic")
278 ip.magic("magic")
279
279
280 stdout = captured.stdout
280 stdout = captured.stdout
281 nt.assert_in('%magic', stdout)
281 nt.assert_in('%magic', stdout)
282 nt.assert_in('IPython', stdout)
282 nt.assert_in('IPython', stdout)
283 nt.assert_in('Available', stdout)
283 nt.assert_in('Available', stdout)
284
284
285
285
286 @dec.skipif_not_numpy
286 @dec.skipif_not_numpy
287 def test_numpy_reset_array_undec():
287 def test_numpy_reset_array_undec():
288 "Test '%reset array' functionality"
288 "Test '%reset array' functionality"
289 _ip.ex('import numpy as np')
289 _ip.ex('import numpy as np')
290 _ip.ex('a = np.empty(2)')
290 _ip.ex('a = np.empty(2)')
291 nt.assert_in('a', _ip.user_ns)
291 nt.assert_in('a', _ip.user_ns)
292 _ip.magic('reset -f array')
292 _ip.magic('reset -f array')
293 nt.assert_not_in('a', _ip.user_ns)
293 nt.assert_not_in('a', _ip.user_ns)
294
294
295 def test_reset_out():
295 def test_reset_out():
296 "Test '%reset out' magic"
296 "Test '%reset out' magic"
297 _ip.run_cell("parrot = 'dead'", store_history=True)
297 _ip.run_cell("parrot = 'dead'", store_history=True)
298 # test '%reset -f out', make an Out prompt
298 # test '%reset -f out', make an Out prompt
299 _ip.run_cell("parrot", store_history=True)
299 _ip.run_cell("parrot", store_history=True)
300 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
300 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
301 _ip.magic('reset -f out')
301 _ip.magic('reset -f out')
302 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
302 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
303 nt.assert_equal(len(_ip.user_ns['Out']), 0)
303 nt.assert_equal(len(_ip.user_ns['Out']), 0)
304
304
305 def test_reset_in():
305 def test_reset_in():
306 "Test '%reset in' magic"
306 "Test '%reset in' magic"
307 # test '%reset -f in'
307 # test '%reset -f in'
308 _ip.run_cell("parrot", store_history=True)
308 _ip.run_cell("parrot", store_history=True)
309 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
309 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
310 _ip.magic('%reset -f in')
310 _ip.magic('%reset -f in')
311 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
311 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
312 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
312 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
313
313
314 def test_reset_dhist():
314 def test_reset_dhist():
315 "Test '%reset dhist' magic"
315 "Test '%reset dhist' magic"
316 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
316 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
317 _ip.magic('cd ' + os.path.dirname(nt.__file__))
317 _ip.magic('cd ' + os.path.dirname(nt.__file__))
318 _ip.magic('cd -')
318 _ip.magic('cd -')
319 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
319 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
320 _ip.magic('reset -f dhist')
320 _ip.magic('reset -f dhist')
321 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
321 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
322 _ip.run_cell("_dh = [d for d in tmp]") #restore
322 _ip.run_cell("_dh = [d for d in tmp]") #restore
323
323
324 def test_reset_in_length():
324 def test_reset_in_length():
325 "Test that '%reset in' preserves In[] length"
325 "Test that '%reset in' preserves In[] length"
326 _ip.run_cell("print 'foo'")
326 _ip.run_cell("print 'foo'")
327 _ip.run_cell("reset -f in")
327 _ip.run_cell("reset -f in")
328 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
328 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
329
329
330 def test_tb_syntaxerror():
330 def test_tb_syntaxerror():
331 """test %tb after a SyntaxError"""
331 """test %tb after a SyntaxError"""
332 ip = get_ipython()
332 ip = get_ipython()
333 ip.run_cell("for")
333 ip.run_cell("for")
334
334
335 # trap and validate stdout
335 # trap and validate stdout
336 save_stdout = sys.stdout
336 save_stdout = sys.stdout
337 try:
337 try:
338 sys.stdout = StringIO()
338 sys.stdout = StringIO()
339 ip.run_cell("%tb")
339 ip.run_cell("%tb")
340 out = sys.stdout.getvalue()
340 out = sys.stdout.getvalue()
341 finally:
341 finally:
342 sys.stdout = save_stdout
342 sys.stdout = save_stdout
343 # trim output, and only check the last line
343 # trim output, and only check the last line
344 last_line = out.rstrip().splitlines()[-1].strip()
344 last_line = out.rstrip().splitlines()[-1].strip()
345 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
345 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
346
346
347
347
348 def test_time():
348 def test_time():
349 ip = get_ipython()
349 ip = get_ipython()
350
350
351 with tt.AssertPrints("Wall time: "):
351 with tt.AssertPrints("Wall time: "):
352 ip.run_cell("%time None")
352 ip.run_cell("%time None")
353
353
354 ip.run_cell("def f(kmjy):\n"
354 ip.run_cell("def f(kmjy):\n"
355 " %time print (2*kmjy)")
355 " %time print (2*kmjy)")
356
356
357 with tt.AssertPrints("Wall time: "):
357 with tt.AssertPrints("Wall time: "):
358 with tt.AssertPrints("hihi", suppress=False):
358 with tt.AssertPrints("hihi", suppress=False):
359 ip.run_cell("f('hi')")
359 ip.run_cell("f('hi')")
360
360
361
361
362 @dec.skip_win32
362 @dec.skip_win32
363 def test_time2():
363 def test_time2():
364 ip = get_ipython()
364 ip = get_ipython()
365
365
366 with tt.AssertPrints("CPU times: user "):
366 with tt.AssertPrints("CPU times: user "):
367 ip.run_cell("%time None")
367 ip.run_cell("%time None")
368
368
369 def test_time3():
369 def test_time3():
370 """Erroneous magic function calls, issue gh-3334"""
370 """Erroneous magic function calls, issue gh-3334"""
371 ip = get_ipython()
371 ip = get_ipython()
372 ip.user_ns.pop('run', None)
372 ip.user_ns.pop('run', None)
373
373
374 with tt.AssertNotPrints("not found", channel='stderr'):
374 with tt.AssertNotPrints("not found", channel='stderr'):
375 ip.run_cell("%%time\n"
375 ip.run_cell("%%time\n"
376 "run = 0\n"
376 "run = 0\n"
377 "run += 1")
377 "run += 1")
378
378
379 def test_doctest_mode():
379 def test_doctest_mode():
380 "Toggle doctest_mode twice, it should be a no-op and run without error"
380 "Toggle doctest_mode twice, it should be a no-op and run without error"
381 _ip.magic('doctest_mode')
381 _ip.magic('doctest_mode')
382 _ip.magic('doctest_mode')
382 _ip.magic('doctest_mode')
383
383
384
384
385 def test_parse_options():
385 def test_parse_options():
386 """Tests for basic options parsing in magics."""
386 """Tests for basic options parsing in magics."""
387 # These are only the most minimal of tests, more should be added later. At
387 # These are only the most minimal of tests, more should be added later. At
388 # the very least we check that basic text/unicode calls work OK.
388 # the very least we check that basic text/unicode calls work OK.
389 m = DummyMagics(_ip)
389 m = DummyMagics(_ip)
390 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
390 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
391 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
391 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
392
392
393
393
394 def test_dirops():
394 def test_dirops():
395 """Test various directory handling operations."""
395 """Test various directory handling operations."""
396 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
396 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
397 curpath = py3compat.getcwd
397 curpath = os.getcwd
398 startdir = py3compat.getcwd()
398 startdir = os.getcwd()
399 ipdir = os.path.realpath(_ip.ipython_dir)
399 ipdir = os.path.realpath(_ip.ipython_dir)
400 try:
400 try:
401 _ip.magic('cd "%s"' % ipdir)
401 _ip.magic('cd "%s"' % ipdir)
402 nt.assert_equal(curpath(), ipdir)
402 nt.assert_equal(curpath(), ipdir)
403 _ip.magic('cd -')
403 _ip.magic('cd -')
404 nt.assert_equal(curpath(), startdir)
404 nt.assert_equal(curpath(), startdir)
405 _ip.magic('pushd "%s"' % ipdir)
405 _ip.magic('pushd "%s"' % ipdir)
406 nt.assert_equal(curpath(), ipdir)
406 nt.assert_equal(curpath(), ipdir)
407 _ip.magic('popd')
407 _ip.magic('popd')
408 nt.assert_equal(curpath(), startdir)
408 nt.assert_equal(curpath(), startdir)
409 finally:
409 finally:
410 os.chdir(startdir)
410 os.chdir(startdir)
411
411
412
412
413 def test_xmode():
413 def test_xmode():
414 # Calling xmode three times should be a no-op
414 # Calling xmode three times should be a no-op
415 xmode = _ip.InteractiveTB.mode
415 xmode = _ip.InteractiveTB.mode
416 for i in range(3):
416 for i in range(3):
417 _ip.magic("xmode")
417 _ip.magic("xmode")
418 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
418 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
419
419
420 def test_reset_hard():
420 def test_reset_hard():
421 monitor = []
421 monitor = []
422 class A(object):
422 class A(object):
423 def __del__(self):
423 def __del__(self):
424 monitor.append(1)
424 monitor.append(1)
425 def __repr__(self):
425 def __repr__(self):
426 return "<A instance>"
426 return "<A instance>"
427
427
428 _ip.user_ns["a"] = A()
428 _ip.user_ns["a"] = A()
429 _ip.run_cell("a")
429 _ip.run_cell("a")
430
430
431 nt.assert_equal(monitor, [])
431 nt.assert_equal(monitor, [])
432 _ip.magic("reset -f")
432 _ip.magic("reset -f")
433 nt.assert_equal(monitor, [1])
433 nt.assert_equal(monitor, [1])
434
434
435 class TestXdel(tt.TempFileMixin):
435 class TestXdel(tt.TempFileMixin):
436 def test_xdel(self):
436 def test_xdel(self):
437 """Test that references from %run are cleared by xdel."""
437 """Test that references from %run are cleared by xdel."""
438 src = ("class A(object):\n"
438 src = ("class A(object):\n"
439 " monitor = []\n"
439 " monitor = []\n"
440 " def __del__(self):\n"
440 " def __del__(self):\n"
441 " self.monitor.append(1)\n"
441 " self.monitor.append(1)\n"
442 "a = A()\n")
442 "a = A()\n")
443 self.mktmp(src)
443 self.mktmp(src)
444 # %run creates some hidden references...
444 # %run creates some hidden references...
445 _ip.magic("run %s" % self.fname)
445 _ip.magic("run %s" % self.fname)
446 # ... as does the displayhook.
446 # ... as does the displayhook.
447 _ip.run_cell("a")
447 _ip.run_cell("a")
448
448
449 monitor = _ip.user_ns["A"].monitor
449 monitor = _ip.user_ns["A"].monitor
450 nt.assert_equal(monitor, [])
450 nt.assert_equal(monitor, [])
451
451
452 _ip.magic("xdel a")
452 _ip.magic("xdel a")
453
453
454 # Check that a's __del__ method has been called.
454 # Check that a's __del__ method has been called.
455 nt.assert_equal(monitor, [1])
455 nt.assert_equal(monitor, [1])
456
456
457 def doctest_who():
457 def doctest_who():
458 """doctest for %who
458 """doctest for %who
459
459
460 In [1]: %reset -f
460 In [1]: %reset -f
461
461
462 In [2]: alpha = 123
462 In [2]: alpha = 123
463
463
464 In [3]: beta = 'beta'
464 In [3]: beta = 'beta'
465
465
466 In [4]: %who int
466 In [4]: %who int
467 alpha
467 alpha
468
468
469 In [5]: %who str
469 In [5]: %who str
470 beta
470 beta
471
471
472 In [6]: %whos
472 In [6]: %whos
473 Variable Type Data/Info
473 Variable Type Data/Info
474 ----------------------------
474 ----------------------------
475 alpha int 123
475 alpha int 123
476 beta str beta
476 beta str beta
477
477
478 In [7]: %who_ls
478 In [7]: %who_ls
479 Out[7]: ['alpha', 'beta']
479 Out[7]: ['alpha', 'beta']
480 """
480 """
481
481
482 def test_whos():
482 def test_whos():
483 """Check that whos is protected against objects where repr() fails."""
483 """Check that whos is protected against objects where repr() fails."""
484 class A(object):
484 class A(object):
485 def __repr__(self):
485 def __repr__(self):
486 raise Exception()
486 raise Exception()
487 _ip.user_ns['a'] = A()
487 _ip.user_ns['a'] = A()
488 _ip.magic("whos")
488 _ip.magic("whos")
489
489
490 @py3compat.u_format
490 @py3compat.u_format
491 def doctest_precision():
491 def doctest_precision():
492 """doctest for %precision
492 """doctest for %precision
493
493
494 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
494 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
495
495
496 In [2]: %precision 5
496 In [2]: %precision 5
497 Out[2]: {u}'%.5f'
497 Out[2]: {u}'%.5f'
498
498
499 In [3]: f.float_format
499 In [3]: f.float_format
500 Out[3]: {u}'%.5f'
500 Out[3]: {u}'%.5f'
501
501
502 In [4]: %precision %e
502 In [4]: %precision %e
503 Out[4]: {u}'%e'
503 Out[4]: {u}'%e'
504
504
505 In [5]: f(3.1415927)
505 In [5]: f(3.1415927)
506 Out[5]: {u}'3.141593e+00'
506 Out[5]: {u}'3.141593e+00'
507 """
507 """
508
508
509 def test_psearch():
509 def test_psearch():
510 with tt.AssertPrints("dict.fromkeys"):
510 with tt.AssertPrints("dict.fromkeys"):
511 _ip.run_cell("dict.fr*?")
511 _ip.run_cell("dict.fr*?")
512
512
513 def test_timeit_shlex():
513 def test_timeit_shlex():
514 """test shlex issues with timeit (#1109)"""
514 """test shlex issues with timeit (#1109)"""
515 _ip.ex("def f(*a,**kw): pass")
515 _ip.ex("def f(*a,**kw): pass")
516 _ip.magic('timeit -n1 "this is a bug".count(" ")')
516 _ip.magic('timeit -n1 "this is a bug".count(" ")')
517 _ip.magic('timeit -r1 -n1 f(" ", 1)')
517 _ip.magic('timeit -r1 -n1 f(" ", 1)')
518 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
518 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
519 _ip.magic('timeit -r1 -n1 ("a " + "b")')
519 _ip.magic('timeit -r1 -n1 ("a " + "b")')
520 _ip.magic('timeit -r1 -n1 f("a " + "b")')
520 _ip.magic('timeit -r1 -n1 f("a " + "b")')
521 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
521 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
522
522
523
523
524 def test_timeit_arguments():
524 def test_timeit_arguments():
525 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
525 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
526 _ip.magic("timeit ('#')")
526 _ip.magic("timeit ('#')")
527
527
528
528
529 def test_timeit_special_syntax():
529 def test_timeit_special_syntax():
530 "Test %%timeit with IPython special syntax"
530 "Test %%timeit with IPython special syntax"
531 @register_line_magic
531 @register_line_magic
532 def lmagic(line):
532 def lmagic(line):
533 ip = get_ipython()
533 ip = get_ipython()
534 ip.user_ns['lmagic_out'] = line
534 ip.user_ns['lmagic_out'] = line
535
535
536 # line mode test
536 # line mode test
537 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
537 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
538 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
538 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
539 # cell mode test
539 # cell mode test
540 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
540 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
541 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
541 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
542
542
543 def test_timeit_return():
543 def test_timeit_return():
544 """
544 """
545 test wether timeit -o return object
545 test wether timeit -o return object
546 """
546 """
547
547
548 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
548 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
549 assert(res is not None)
549 assert(res is not None)
550
550
551 def test_timeit_quiet():
551 def test_timeit_quiet():
552 """
552 """
553 test quiet option of timeit magic
553 test quiet option of timeit magic
554 """
554 """
555 with tt.AssertNotPrints("loops"):
555 with tt.AssertNotPrints("loops"):
556 _ip.run_cell("%timeit -n1 -r1 -q 1")
556 _ip.run_cell("%timeit -n1 -r1 -q 1")
557
557
558 def test_timeit_return_quiet():
558 def test_timeit_return_quiet():
559 with tt.AssertNotPrints("loops"):
559 with tt.AssertNotPrints("loops"):
560 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
560 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
561 assert (res is not None)
561 assert (res is not None)
562
562
563 @dec.skipif(execution.profile is None)
563 @dec.skipif(execution.profile is None)
564 def test_prun_special_syntax():
564 def test_prun_special_syntax():
565 "Test %%prun with IPython special syntax"
565 "Test %%prun with IPython special syntax"
566 @register_line_magic
566 @register_line_magic
567 def lmagic(line):
567 def lmagic(line):
568 ip = get_ipython()
568 ip = get_ipython()
569 ip.user_ns['lmagic_out'] = line
569 ip.user_ns['lmagic_out'] = line
570
570
571 # line mode test
571 # line mode test
572 _ip.run_line_magic('prun', '-q %lmagic my line')
572 _ip.run_line_magic('prun', '-q %lmagic my line')
573 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
573 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
574 # cell mode test
574 # cell mode test
575 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
575 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
576 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
576 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
577
577
578 @dec.skipif(execution.profile is None)
578 @dec.skipif(execution.profile is None)
579 def test_prun_quotes():
579 def test_prun_quotes():
580 "Test that prun does not clobber string escapes (GH #1302)"
580 "Test that prun does not clobber string escapes (GH #1302)"
581 _ip.magic(r"prun -q x = '\t'")
581 _ip.magic(r"prun -q x = '\t'")
582 nt.assert_equal(_ip.user_ns['x'], '\t')
582 nt.assert_equal(_ip.user_ns['x'], '\t')
583
583
584 def test_extension():
584 def test_extension():
585 # Debugging information for failures of this test
585 # Debugging information for failures of this test
586 print('sys.path:')
586 print('sys.path:')
587 for p in sys.path:
587 for p in sys.path:
588 print(' ', p)
588 print(' ', p)
589 print('CWD', os.getcwd())
589 print('CWD', os.getcwd())
590
590
591 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
591 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
592 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
592 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
593 sys.path.insert(0, daft_path)
593 sys.path.insert(0, daft_path)
594 try:
594 try:
595 _ip.user_ns.pop('arq', None)
595 _ip.user_ns.pop('arq', None)
596 invalidate_caches() # Clear import caches
596 invalidate_caches() # Clear import caches
597 _ip.magic("load_ext daft_extension")
597 _ip.magic("load_ext daft_extension")
598 nt.assert_equal(_ip.user_ns['arq'], 185)
598 nt.assert_equal(_ip.user_ns['arq'], 185)
599 _ip.magic("unload_ext daft_extension")
599 _ip.magic("unload_ext daft_extension")
600 assert 'arq' not in _ip.user_ns
600 assert 'arq' not in _ip.user_ns
601 finally:
601 finally:
602 sys.path.remove(daft_path)
602 sys.path.remove(daft_path)
603
603
604
604
605 def test_notebook_export_json():
605 def test_notebook_export_json():
606 _ip = get_ipython()
606 _ip = get_ipython()
607 _ip.history_manager.reset() # Clear any existing history.
607 _ip.history_manager.reset() # Clear any existing history.
608 cmds = [u"a=1", u"def b():\n return a**2", u"print('noël, été', b())"]
608 cmds = [u"a=1", u"def b():\n return a**2", u"print('noël, été', b())"]
609 for i, cmd in enumerate(cmds, start=1):
609 for i, cmd in enumerate(cmds, start=1):
610 _ip.history_manager.store_inputs(i, cmd)
610 _ip.history_manager.store_inputs(i, cmd)
611 with TemporaryDirectory() as td:
611 with TemporaryDirectory() as td:
612 outfile = os.path.join(td, "nb.ipynb")
612 outfile = os.path.join(td, "nb.ipynb")
613 _ip.magic("notebook -e %s" % outfile)
613 _ip.magic("notebook -e %s" % outfile)
614
614
615
615
616 class TestEnv(TestCase):
616 class TestEnv(TestCase):
617
617
618 def test_env(self):
618 def test_env(self):
619 env = _ip.magic("env")
619 env = _ip.magic("env")
620 self.assertTrue(isinstance(env, dict))
620 self.assertTrue(isinstance(env, dict))
621
621
622 def test_env_get_set_simple(self):
622 def test_env_get_set_simple(self):
623 env = _ip.magic("env var val1")
623 env = _ip.magic("env var val1")
624 self.assertEqual(env, None)
624 self.assertEqual(env, None)
625 self.assertEqual(os.environ['var'], 'val1')
625 self.assertEqual(os.environ['var'], 'val1')
626 self.assertEqual(_ip.magic("env var"), 'val1')
626 self.assertEqual(_ip.magic("env var"), 'val1')
627 env = _ip.magic("env var=val2")
627 env = _ip.magic("env var=val2")
628 self.assertEqual(env, None)
628 self.assertEqual(env, None)
629 self.assertEqual(os.environ['var'], 'val2')
629 self.assertEqual(os.environ['var'], 'val2')
630
630
631 def test_env_get_set_complex(self):
631 def test_env_get_set_complex(self):
632 env = _ip.magic("env var 'val1 '' 'val2")
632 env = _ip.magic("env var 'val1 '' 'val2")
633 self.assertEqual(env, None)
633 self.assertEqual(env, None)
634 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
634 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
635 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
635 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
636 env = _ip.magic('env var=val2 val3="val4')
636 env = _ip.magic('env var=val2 val3="val4')
637 self.assertEqual(env, None)
637 self.assertEqual(env, None)
638 self.assertEqual(os.environ['var'], 'val2 val3="val4')
638 self.assertEqual(os.environ['var'], 'val2 val3="val4')
639
639
640 def test_env_set_bad_input(self):
640 def test_env_set_bad_input(self):
641 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
641 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
642
642
643 def test_env_set_whitespace(self):
643 def test_env_set_whitespace(self):
644 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
644 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
645
645
646
646
647 class CellMagicTestCase(TestCase):
647 class CellMagicTestCase(TestCase):
648
648
649 def check_ident(self, magic):
649 def check_ident(self, magic):
650 # Manually called, we get the result
650 # Manually called, we get the result
651 out = _ip.run_cell_magic(magic, 'a', 'b')
651 out = _ip.run_cell_magic(magic, 'a', 'b')
652 nt.assert_equal(out, ('a','b'))
652 nt.assert_equal(out, ('a','b'))
653 # Via run_cell, it goes into the user's namespace via displayhook
653 # Via run_cell, it goes into the user's namespace via displayhook
654 _ip.run_cell('%%' + magic +' c\nd')
654 _ip.run_cell('%%' + magic +' c\nd')
655 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
655 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
656
656
657 def test_cell_magic_func_deco(self):
657 def test_cell_magic_func_deco(self):
658 "Cell magic using simple decorator"
658 "Cell magic using simple decorator"
659 @register_cell_magic
659 @register_cell_magic
660 def cellm(line, cell):
660 def cellm(line, cell):
661 return line, cell
661 return line, cell
662
662
663 self.check_ident('cellm')
663 self.check_ident('cellm')
664
664
665 def test_cell_magic_reg(self):
665 def test_cell_magic_reg(self):
666 "Cell magic manually registered"
666 "Cell magic manually registered"
667 def cellm(line, cell):
667 def cellm(line, cell):
668 return line, cell
668 return line, cell
669
669
670 _ip.register_magic_function(cellm, 'cell', 'cellm2')
670 _ip.register_magic_function(cellm, 'cell', 'cellm2')
671 self.check_ident('cellm2')
671 self.check_ident('cellm2')
672
672
673 def test_cell_magic_class(self):
673 def test_cell_magic_class(self):
674 "Cell magics declared via a class"
674 "Cell magics declared via a class"
675 @magics_class
675 @magics_class
676 class MyMagics(Magics):
676 class MyMagics(Magics):
677
677
678 @cell_magic
678 @cell_magic
679 def cellm3(self, line, cell):
679 def cellm3(self, line, cell):
680 return line, cell
680 return line, cell
681
681
682 _ip.register_magics(MyMagics)
682 _ip.register_magics(MyMagics)
683 self.check_ident('cellm3')
683 self.check_ident('cellm3')
684
684
685 def test_cell_magic_class2(self):
685 def test_cell_magic_class2(self):
686 "Cell magics declared via a class, #2"
686 "Cell magics declared via a class, #2"
687 @magics_class
687 @magics_class
688 class MyMagics2(Magics):
688 class MyMagics2(Magics):
689
689
690 @cell_magic('cellm4')
690 @cell_magic('cellm4')
691 def cellm33(self, line, cell):
691 def cellm33(self, line, cell):
692 return line, cell
692 return line, cell
693
693
694 _ip.register_magics(MyMagics2)
694 _ip.register_magics(MyMagics2)
695 self.check_ident('cellm4')
695 self.check_ident('cellm4')
696 # Check that nothing is registered as 'cellm33'
696 # Check that nothing is registered as 'cellm33'
697 c33 = _ip.find_cell_magic('cellm33')
697 c33 = _ip.find_cell_magic('cellm33')
698 nt.assert_equal(c33, None)
698 nt.assert_equal(c33, None)
699
699
700 def test_file():
700 def test_file():
701 """Basic %%file"""
701 """Basic %%file"""
702 ip = get_ipython()
702 ip = get_ipython()
703 with TemporaryDirectory() as td:
703 with TemporaryDirectory() as td:
704 fname = os.path.join(td, 'file1')
704 fname = os.path.join(td, 'file1')
705 ip.run_cell_magic("file", fname, u'\n'.join([
705 ip.run_cell_magic("file", fname, u'\n'.join([
706 'line1',
706 'line1',
707 'line2',
707 'line2',
708 ]))
708 ]))
709 with open(fname) as f:
709 with open(fname) as f:
710 s = f.read()
710 s = f.read()
711 nt.assert_in('line1\n', s)
711 nt.assert_in('line1\n', s)
712 nt.assert_in('line2', s)
712 nt.assert_in('line2', s)
713
713
714 def test_file_var_expand():
714 def test_file_var_expand():
715 """%%file $filename"""
715 """%%file $filename"""
716 ip = get_ipython()
716 ip = get_ipython()
717 with TemporaryDirectory() as td:
717 with TemporaryDirectory() as td:
718 fname = os.path.join(td, 'file1')
718 fname = os.path.join(td, 'file1')
719 ip.user_ns['filename'] = fname
719 ip.user_ns['filename'] = fname
720 ip.run_cell_magic("file", '$filename', u'\n'.join([
720 ip.run_cell_magic("file", '$filename', u'\n'.join([
721 'line1',
721 'line1',
722 'line2',
722 'line2',
723 ]))
723 ]))
724 with open(fname) as f:
724 with open(fname) as f:
725 s = f.read()
725 s = f.read()
726 nt.assert_in('line1\n', s)
726 nt.assert_in('line1\n', s)
727 nt.assert_in('line2', s)
727 nt.assert_in('line2', s)
728
728
729 def test_file_unicode():
729 def test_file_unicode():
730 """%%file with unicode cell"""
730 """%%file with unicode cell"""
731 ip = get_ipython()
731 ip = get_ipython()
732 with TemporaryDirectory() as td:
732 with TemporaryDirectory() as td:
733 fname = os.path.join(td, 'file1')
733 fname = os.path.join(td, 'file1')
734 ip.run_cell_magic("file", fname, u'\n'.join([
734 ip.run_cell_magic("file", fname, u'\n'.join([
735 u'liné1',
735 u'liné1',
736 u'liné2',
736 u'liné2',
737 ]))
737 ]))
738 with io.open(fname, encoding='utf-8') as f:
738 with io.open(fname, encoding='utf-8') as f:
739 s = f.read()
739 s = f.read()
740 nt.assert_in(u'liné1\n', s)
740 nt.assert_in(u'liné1\n', s)
741 nt.assert_in(u'liné2', s)
741 nt.assert_in(u'liné2', s)
742
742
743 def test_file_amend():
743 def test_file_amend():
744 """%%file -a amends files"""
744 """%%file -a amends files"""
745 ip = get_ipython()
745 ip = get_ipython()
746 with TemporaryDirectory() as td:
746 with TemporaryDirectory() as td:
747 fname = os.path.join(td, 'file2')
747 fname = os.path.join(td, 'file2')
748 ip.run_cell_magic("file", fname, u'\n'.join([
748 ip.run_cell_magic("file", fname, u'\n'.join([
749 'line1',
749 'line1',
750 'line2',
750 'line2',
751 ]))
751 ]))
752 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
752 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
753 'line3',
753 'line3',
754 'line4',
754 'line4',
755 ]))
755 ]))
756 with open(fname) as f:
756 with open(fname) as f:
757 s = f.read()
757 s = f.read()
758 nt.assert_in('line1\n', s)
758 nt.assert_in('line1\n', s)
759 nt.assert_in('line3\n', s)
759 nt.assert_in('line3\n', s)
760
760
761
761
762 def test_script_config():
762 def test_script_config():
763 ip = get_ipython()
763 ip = get_ipython()
764 ip.config.ScriptMagics.script_magics = ['whoda']
764 ip.config.ScriptMagics.script_magics = ['whoda']
765 sm = script.ScriptMagics(shell=ip)
765 sm = script.ScriptMagics(shell=ip)
766 nt.assert_in('whoda', sm.magics['cell'])
766 nt.assert_in('whoda', sm.magics['cell'])
767
767
768 @dec.skip_win32
768 @dec.skip_win32
769 def test_script_out():
769 def test_script_out():
770 ip = get_ipython()
770 ip = get_ipython()
771 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
771 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
772 nt.assert_equal(ip.user_ns['output'], 'hi\n')
772 nt.assert_equal(ip.user_ns['output'], 'hi\n')
773
773
774 @dec.skip_win32
774 @dec.skip_win32
775 def test_script_err():
775 def test_script_err():
776 ip = get_ipython()
776 ip = get_ipython()
777 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
777 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
778 nt.assert_equal(ip.user_ns['error'], 'hello\n')
778 nt.assert_equal(ip.user_ns['error'], 'hello\n')
779
779
780 @dec.skip_win32
780 @dec.skip_win32
781 def test_script_out_err():
781 def test_script_out_err():
782 ip = get_ipython()
782 ip = get_ipython()
783 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
783 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
784 nt.assert_equal(ip.user_ns['output'], 'hi\n')
784 nt.assert_equal(ip.user_ns['output'], 'hi\n')
785 nt.assert_equal(ip.user_ns['error'], 'hello\n')
785 nt.assert_equal(ip.user_ns['error'], 'hello\n')
786
786
787 @dec.skip_win32
787 @dec.skip_win32
788 def test_script_bg_out():
788 def test_script_bg_out():
789 ip = get_ipython()
789 ip = get_ipython()
790 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
790 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
791 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
791 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
792
792
793 @dec.skip_win32
793 @dec.skip_win32
794 def test_script_bg_err():
794 def test_script_bg_err():
795 ip = get_ipython()
795 ip = get_ipython()
796 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
796 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
797 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
797 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
798
798
799 @dec.skip_win32
799 @dec.skip_win32
800 def test_script_bg_out_err():
800 def test_script_bg_out_err():
801 ip = get_ipython()
801 ip = get_ipython()
802 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
802 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
803 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
803 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
804 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
804 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
805
805
806 def test_script_defaults():
806 def test_script_defaults():
807 ip = get_ipython()
807 ip = get_ipython()
808 for cmd in ['sh', 'bash', 'perl', 'ruby']:
808 for cmd in ['sh', 'bash', 'perl', 'ruby']:
809 try:
809 try:
810 find_cmd(cmd)
810 find_cmd(cmd)
811 except Exception:
811 except Exception:
812 pass
812 pass
813 else:
813 else:
814 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
814 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
815
815
816
816
817 @magics_class
817 @magics_class
818 class FooFoo(Magics):
818 class FooFoo(Magics):
819 """class with both %foo and %%foo magics"""
819 """class with both %foo and %%foo magics"""
820 @line_magic('foo')
820 @line_magic('foo')
821 def line_foo(self, line):
821 def line_foo(self, line):
822 "I am line foo"
822 "I am line foo"
823 pass
823 pass
824
824
825 @cell_magic("foo")
825 @cell_magic("foo")
826 def cell_foo(self, line, cell):
826 def cell_foo(self, line, cell):
827 "I am cell foo, not line foo"
827 "I am cell foo, not line foo"
828 pass
828 pass
829
829
830 def test_line_cell_info():
830 def test_line_cell_info():
831 """%%foo and %foo magics are distinguishable to inspect"""
831 """%%foo and %foo magics are distinguishable to inspect"""
832 ip = get_ipython()
832 ip = get_ipython()
833 ip.magics_manager.register(FooFoo)
833 ip.magics_manager.register(FooFoo)
834 oinfo = ip.object_inspect('foo')
834 oinfo = ip.object_inspect('foo')
835 nt.assert_true(oinfo['found'])
835 nt.assert_true(oinfo['found'])
836 nt.assert_true(oinfo['ismagic'])
836 nt.assert_true(oinfo['ismagic'])
837
837
838 oinfo = ip.object_inspect('%%foo')
838 oinfo = ip.object_inspect('%%foo')
839 nt.assert_true(oinfo['found'])
839 nt.assert_true(oinfo['found'])
840 nt.assert_true(oinfo['ismagic'])
840 nt.assert_true(oinfo['ismagic'])
841 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
841 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
842
842
843 oinfo = ip.object_inspect('%foo')
843 oinfo = ip.object_inspect('%foo')
844 nt.assert_true(oinfo['found'])
844 nt.assert_true(oinfo['found'])
845 nt.assert_true(oinfo['ismagic'])
845 nt.assert_true(oinfo['ismagic'])
846 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
846 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
847
847
848 def test_multiple_magics():
848 def test_multiple_magics():
849 ip = get_ipython()
849 ip = get_ipython()
850 foo1 = FooFoo(ip)
850 foo1 = FooFoo(ip)
851 foo2 = FooFoo(ip)
851 foo2 = FooFoo(ip)
852 mm = ip.magics_manager
852 mm = ip.magics_manager
853 mm.register(foo1)
853 mm.register(foo1)
854 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
854 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
855 mm.register(foo2)
855 mm.register(foo2)
856 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
856 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
857
857
858 def test_alias_magic():
858 def test_alias_magic():
859 """Test %alias_magic."""
859 """Test %alias_magic."""
860 ip = get_ipython()
860 ip = get_ipython()
861 mm = ip.magics_manager
861 mm = ip.magics_manager
862
862
863 # Basic operation: both cell and line magics are created, if possible.
863 # Basic operation: both cell and line magics are created, if possible.
864 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
864 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
865 nt.assert_in('timeit_alias', mm.magics['line'])
865 nt.assert_in('timeit_alias', mm.magics['line'])
866 nt.assert_in('timeit_alias', mm.magics['cell'])
866 nt.assert_in('timeit_alias', mm.magics['cell'])
867
867
868 # --cell is specified, line magic not created.
868 # --cell is specified, line magic not created.
869 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
869 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
870 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
870 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
871 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
871 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
872
872
873 # Test that line alias is created successfully.
873 # Test that line alias is created successfully.
874 ip.run_line_magic('alias_magic', '--line env_alias env')
874 ip.run_line_magic('alias_magic', '--line env_alias env')
875 nt.assert_equal(ip.run_line_magic('env', ''),
875 nt.assert_equal(ip.run_line_magic('env', ''),
876 ip.run_line_magic('env_alias', ''))
876 ip.run_line_magic('env_alias', ''))
877
877
878 def test_save():
878 def test_save():
879 """Test %save."""
879 """Test %save."""
880 ip = get_ipython()
880 ip = get_ipython()
881 ip.history_manager.reset() # Clear any existing history.
881 ip.history_manager.reset() # Clear any existing history.
882 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
882 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
883 for i, cmd in enumerate(cmds, start=1):
883 for i, cmd in enumerate(cmds, start=1):
884 ip.history_manager.store_inputs(i, cmd)
884 ip.history_manager.store_inputs(i, cmd)
885 with TemporaryDirectory() as tmpdir:
885 with TemporaryDirectory() as tmpdir:
886 file = os.path.join(tmpdir, "testsave.py")
886 file = os.path.join(tmpdir, "testsave.py")
887 ip.run_line_magic("save", "%s 1-10" % file)
887 ip.run_line_magic("save", "%s 1-10" % file)
888 with open(file) as f:
888 with open(file) as f:
889 content = f.read()
889 content = f.read()
890 nt.assert_equal(content.count(cmds[0]), 1)
890 nt.assert_equal(content.count(cmds[0]), 1)
891 nt.assert_in('coding: utf-8', content)
891 nt.assert_in('coding: utf-8', content)
892 ip.run_line_magic("save", "-a %s 1-10" % file)
892 ip.run_line_magic("save", "-a %s 1-10" % file)
893 with open(file) as f:
893 with open(file) as f:
894 content = f.read()
894 content = f.read()
895 nt.assert_equal(content.count(cmds[0]), 2)
895 nt.assert_equal(content.count(cmds[0]), 2)
896 nt.assert_in('coding: utf-8', content)
896 nt.assert_in('coding: utf-8', content)
897
897
898
898
899 def test_store():
899 def test_store():
900 """Test %store."""
900 """Test %store."""
901 ip = get_ipython()
901 ip = get_ipython()
902 ip.run_line_magic('load_ext', 'storemagic')
902 ip.run_line_magic('load_ext', 'storemagic')
903
903
904 # make sure the storage is empty
904 # make sure the storage is empty
905 ip.run_line_magic('store', '-z')
905 ip.run_line_magic('store', '-z')
906 ip.user_ns['var'] = 42
906 ip.user_ns['var'] = 42
907 ip.run_line_magic('store', 'var')
907 ip.run_line_magic('store', 'var')
908 ip.user_ns['var'] = 39
908 ip.user_ns['var'] = 39
909 ip.run_line_magic('store', '-r')
909 ip.run_line_magic('store', '-r')
910 nt.assert_equal(ip.user_ns['var'], 42)
910 nt.assert_equal(ip.user_ns['var'], 42)
911
911
912 ip.run_line_magic('store', '-d var')
912 ip.run_line_magic('store', '-d var')
913 ip.user_ns['var'] = 39
913 ip.user_ns['var'] = 39
914 ip.run_line_magic('store' , '-r')
914 ip.run_line_magic('store' , '-r')
915 nt.assert_equal(ip.user_ns['var'], 39)
915 nt.assert_equal(ip.user_ns['var'], 39)
916
916
917
917
918 def _run_edit_test(arg_s, exp_filename=None,
918 def _run_edit_test(arg_s, exp_filename=None,
919 exp_lineno=-1,
919 exp_lineno=-1,
920 exp_contents=None,
920 exp_contents=None,
921 exp_is_temp=None):
921 exp_is_temp=None):
922 ip = get_ipython()
922 ip = get_ipython()
923 M = code.CodeMagics(ip)
923 M = code.CodeMagics(ip)
924 last_call = ['','']
924 last_call = ['','']
925 opts,args = M.parse_options(arg_s,'prxn:')
925 opts,args = M.parse_options(arg_s,'prxn:')
926 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
926 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
927
927
928 if exp_filename is not None:
928 if exp_filename is not None:
929 nt.assert_equal(exp_filename, filename)
929 nt.assert_equal(exp_filename, filename)
930 if exp_contents is not None:
930 if exp_contents is not None:
931 with io.open(filename, 'r', encoding='utf-8') as f:
931 with io.open(filename, 'r', encoding='utf-8') as f:
932 contents = f.read()
932 contents = f.read()
933 nt.assert_equal(exp_contents, contents)
933 nt.assert_equal(exp_contents, contents)
934 if exp_lineno != -1:
934 if exp_lineno != -1:
935 nt.assert_equal(exp_lineno, lineno)
935 nt.assert_equal(exp_lineno, lineno)
936 if exp_is_temp is not None:
936 if exp_is_temp is not None:
937 nt.assert_equal(exp_is_temp, is_temp)
937 nt.assert_equal(exp_is_temp, is_temp)
938
938
939
939
940 def test_edit_interactive():
940 def test_edit_interactive():
941 """%edit on interactively defined objects"""
941 """%edit on interactively defined objects"""
942 ip = get_ipython()
942 ip = get_ipython()
943 n = ip.execution_count
943 n = ip.execution_count
944 ip.run_cell(u"def foo(): return 1", store_history=True)
944 ip.run_cell(u"def foo(): return 1", store_history=True)
945
945
946 try:
946 try:
947 _run_edit_test("foo")
947 _run_edit_test("foo")
948 except code.InteractivelyDefined as e:
948 except code.InteractivelyDefined as e:
949 nt.assert_equal(e.index, n)
949 nt.assert_equal(e.index, n)
950 else:
950 else:
951 raise AssertionError("Should have raised InteractivelyDefined")
951 raise AssertionError("Should have raised InteractivelyDefined")
952
952
953
953
954 def test_edit_cell():
954 def test_edit_cell():
955 """%edit [cell id]"""
955 """%edit [cell id]"""
956 ip = get_ipython()
956 ip = get_ipython()
957
957
958 ip.run_cell(u"def foo(): return 1", store_history=True)
958 ip.run_cell(u"def foo(): return 1", store_history=True)
959
959
960 # test
960 # test
961 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
961 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
962
962
963 def test_bookmark():
963 def test_bookmark():
964 ip = get_ipython()
964 ip = get_ipython()
965 ip.run_line_magic('bookmark', 'bmname')
965 ip.run_line_magic('bookmark', 'bmname')
966 with tt.AssertPrints('bmname'):
966 with tt.AssertPrints('bmname'):
967 ip.run_line_magic('bookmark', '-l')
967 ip.run_line_magic('bookmark', '-l')
968 ip.run_line_magic('bookmark', '-d bmname')
968 ip.run_line_magic('bookmark', '-d bmname')
969
969
970 def test_ls_magic():
970 def test_ls_magic():
971 ip = get_ipython()
971 ip = get_ipython()
972 json_formatter = ip.display_formatter.formatters['application/json']
972 json_formatter = ip.display_formatter.formatters['application/json']
973 json_formatter.enabled = True
973 json_formatter.enabled = True
974 lsmagic = ip.magic('lsmagic')
974 lsmagic = ip.magic('lsmagic')
975 with warnings.catch_warnings(record=True) as w:
975 with warnings.catch_warnings(record=True) as w:
976 j = json_formatter(lsmagic)
976 j = json_formatter(lsmagic)
977 nt.assert_equal(sorted(j), ['cell', 'line'])
977 nt.assert_equal(sorted(j), ['cell', 'line'])
978 nt.assert_equal(w, []) # no warnings
978 nt.assert_equal(w, []) # no warnings
979
979
980 def test_strip_initial_indent():
980 def test_strip_initial_indent():
981 def sii(s):
981 def sii(s):
982 lines = s.splitlines()
982 lines = s.splitlines()
983 return '\n'.join(code.strip_initial_indent(lines))
983 return '\n'.join(code.strip_initial_indent(lines))
984
984
985 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
985 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
986 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
986 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
987 nt.assert_equal(sii("a\n b"), "a\n b")
987 nt.assert_equal(sii("a\n b"), "a\n b")
@@ -1,164 +1,163 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for profile-related functions.
2 """Tests for profile-related functions.
3
3
4 Currently only the startup-dir functionality is tested, but more tests should
4 Currently only the startup-dir functionality is tested, but more tests should
5 be added for:
5 be added for:
6
6
7 * ipython profile create
7 * ipython profile create
8 * ipython profile list
8 * ipython profile list
9 * ipython profile create --parallel
9 * ipython profile create --parallel
10 * security dir permissions
10 * security dir permissions
11
11
12 Authors
12 Authors
13 -------
13 -------
14
14
15 * MinRK
15 * MinRK
16
16
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import shutil
24 import shutil
25 import sys
25 import sys
26 import tempfile
26 import tempfile
27
27
28 from unittest import TestCase
28 from unittest import TestCase
29
29
30 import nose.tools as nt
30 import nose.tools as nt
31
31
32 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
32 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
33 from IPython.core.profiledir import ProfileDir
33 from IPython.core.profiledir import ProfileDir
34
34
35 from IPython.testing import decorators as dec
35 from IPython.testing import decorators as dec
36 from IPython.testing import tools as tt
36 from IPython.testing import tools as tt
37 from IPython.utils import py3compat
37 from IPython.utils import py3compat
38 from IPython.utils.process import getoutput
38 from IPython.utils.process import getoutput
39 from IPython.utils.tempdir import TemporaryDirectory
39 from IPython.utils.tempdir import TemporaryDirectory
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Globals
42 # Globals
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 TMP_TEST_DIR = tempfile.mkdtemp()
44 TMP_TEST_DIR = tempfile.mkdtemp()
45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
47
47
48 #
48 #
49 # Setup/teardown functions/decorators
49 # Setup/teardown functions/decorators
50 #
50 #
51
51
52 def setup():
52 def setup():
53 """Setup test environment for the module:
53 """Setup test environment for the module:
54
54
55 - Adds dummy home dir tree
55 - Adds dummy home dir tree
56 """
56 """
57 # Do not mask exceptions here. In particular, catching WindowsError is a
57 # Do not mask exceptions here. In particular, catching WindowsError is a
58 # problem because that exception is only defined on Windows...
58 # problem because that exception is only defined on Windows...
59 os.makedirs(IP_TEST_DIR)
59 os.makedirs(IP_TEST_DIR)
60
60
61
61
62 def teardown():
62 def teardown():
63 """Teardown test environment for the module:
63 """Teardown test environment for the module:
64
64
65 - Remove dummy home dir tree
65 - Remove dummy home dir tree
66 """
66 """
67 # Note: we remove the parent test dir, which is the root of all test
67 # Note: we remove the parent test dir, which is the root of all test
68 # subdirs we may have created. Use shutil instead of os.removedirs, so
68 # subdirs we may have created. Use shutil instead of os.removedirs, so
69 # that non-empty directories are all recursively removed.
69 # that non-empty directories are all recursively removed.
70 shutil.rmtree(TMP_TEST_DIR)
70 shutil.rmtree(TMP_TEST_DIR)
71
71
72
72
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 # Test functions
74 # Test functions
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76 def win32_without_pywin32():
76 def win32_without_pywin32():
77 if sys.platform == 'win32':
77 if sys.platform == 'win32':
78 try:
78 try:
79 import pywin32
79 import pywin32
80 except ImportError:
80 except ImportError:
81 return True
81 return True
82 return False
82 return False
83
83
84
84
85 class ProfileStartupTest(TestCase):
85 class ProfileStartupTest(TestCase):
86 def setUp(self):
86 def setUp(self):
87 # create profile dir
87 # create profile dir
88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
91
91
92 def tearDown(self):
92 def tearDown(self):
93 # We must remove this profile right away so its presence doesn't
93 # We must remove this profile right away so its presence doesn't
94 # confuse other tests.
94 # confuse other tests.
95 shutil.rmtree(self.pd.location)
95 shutil.rmtree(self.pd.location)
96
96
97 def init(self, startup_file, startup, test):
97 def init(self, startup_file, startup, test):
98 # write startup python file
98 # write startup python file
99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
100 f.write(startup)
100 f.write(startup)
101 # write simple test file, to check that the startup file was run
101 # write simple test file, to check that the startup file was run
102 with open(self.fname, 'w') as f:
102 with open(self.fname, 'w') as f:
103 f.write(py3compat.doctest_refactor_print(test))
103 f.write(py3compat.doctest_refactor_print(test))
104
104
105 def validate(self, output):
105 def validate(self, output):
106 tt.ipexec_validate(self.fname, output, '', options=self.options)
106 tt.ipexec_validate(self.fname, output, '', options=self.options)
107
107
108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
109 def test_startup_py(self):
109 def test_startup_py(self):
110 self.init('00-start.py', 'zzz=123\n',
110 self.init('00-start.py', 'zzz=123\n',
111 py3compat.doctest_refactor_print('print zzz\n'))
111 py3compat.doctest_refactor_print('print zzz\n'))
112 self.validate('123')
112 self.validate('123')
113
113
114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
115 def test_startup_ipy(self):
115 def test_startup_ipy(self):
116 self.init('00-start.ipy', '%xmode plain\n', '')
116 self.init('00-start.ipy', '%xmode plain\n', '')
117 self.validate('Exception reporting mode: Plain')
117 self.validate('Exception reporting mode: Plain')
118
118
119
119
120 def test_list_profiles_in():
120 def test_list_profiles_in():
121 # No need to remove these directories and files, as they will get nuked in
121 # No need to remove these directories and files, as they will get nuked in
122 # the module-level teardown.
122 # the module-level teardown.
123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
124 td = py3compat.str_to_unicode(td)
125 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
124 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
126 os.mkdir(os.path.join(td, name))
125 os.mkdir(os.path.join(td, name))
127 if dec.unicode_paths:
126 if dec.unicode_paths:
128 os.mkdir(os.path.join(td, u'profile_ünicode'))
127 os.mkdir(os.path.join(td, u'profile_ünicode'))
129
128
130 with open(os.path.join(td, 'profile_file'), 'w') as f:
129 with open(os.path.join(td, 'profile_file'), 'w') as f:
131 f.write("I am not a profile directory")
130 f.write("I am not a profile directory")
132 profiles = list_profiles_in(td)
131 profiles = list_profiles_in(td)
133
132
134 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
133 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
135 # so only check for *nicode, and that creating a ProfileDir from the
134 # so only check for *nicode, and that creating a ProfileDir from the
136 # name remains valid
135 # name remains valid
137 found_unicode = False
136 found_unicode = False
138 for p in list(profiles):
137 for p in list(profiles):
139 if p.endswith('nicode'):
138 if p.endswith('nicode'):
140 pd = ProfileDir.find_profile_dir_by_name(td, p)
139 pd = ProfileDir.find_profile_dir_by_name(td, p)
141 profiles.remove(p)
140 profiles.remove(p)
142 found_unicode = True
141 found_unicode = True
143 break
142 break
144 if dec.unicode_paths:
143 if dec.unicode_paths:
145 nt.assert_true(found_unicode)
144 nt.assert_true(found_unicode)
146 nt.assert_equal(set(profiles), {'foo', 'hello'})
145 nt.assert_equal(set(profiles), {'foo', 'hello'})
147
146
148
147
149 def test_list_bundled_profiles():
148 def test_list_bundled_profiles():
150 # This variable will need to be updated when a new profile gets bundled
149 # This variable will need to be updated when a new profile gets bundled
151 bundled = sorted(list_bundled_profiles())
150 bundled = sorted(list_bundled_profiles())
152 nt.assert_equal(bundled, [])
151 nt.assert_equal(bundled, [])
153
152
154
153
155 def test_profile_create_ipython_dir():
154 def test_profile_create_ipython_dir():
156 """ipython profile create respects --ipython-dir"""
155 """ipython profile create respects --ipython-dir"""
157 with TemporaryDirectory() as td:
156 with TemporaryDirectory() as td:
158 getoutput([sys.executable, '-m', 'IPython', 'profile', 'create',
157 getoutput([sys.executable, '-m', 'IPython', 'profile', 'create',
159 'foo', '--ipython-dir=%s' % td])
158 'foo', '--ipython-dir=%s' % td])
160 profile_dir = os.path.join(td, 'profile_foo')
159 profile_dir = os.path.join(td, 'profile_foo')
161 assert os.path.exists(profile_dir)
160 assert os.path.exists(profile_dir)
162 ipython_config = os.path.join(profile_dir, 'ipython_config.py')
161 ipython_config = os.path.join(profile_dir, 'ipython_config.py')
163 assert os.path.exists(ipython_config)
162 assert os.path.exists(ipython_config)
164
163
@@ -1,37 +1,34 b''
1 # -*- coding: utf-8
1 # -*- coding: utf-8
2 """Tests for prompt generation."""
2 """Tests for prompt generation."""
3
3
4 import unittest
4 import unittest
5
5
6 from IPython.core.prompts import LazyEvaluate
6 from IPython.core.prompts import LazyEvaluate
7 from IPython.testing.globalipapp import get_ipython
7 from IPython.testing.globalipapp import get_ipython
8 from IPython.utils.py3compat import unicode_type
9
8
10 ip = get_ipython()
9 ip = get_ipython()
11
10
12
11
13 class PromptTests(unittest.TestCase):
12 class PromptTests(unittest.TestCase):
14 def test_lazy_eval_unicode(self):
13 def test_lazy_eval_unicode(self):
15 u = u'ünicødé'
14 u = u'ünicødé'
16 lz = LazyEvaluate(lambda : u)
15 lz = LazyEvaluate(lambda : u)
17 # str(lz) would fail
16 self.assertEqual(str(lz), u)
18 self.assertEqual(unicode_type(lz), u)
19 self.assertEqual(format(lz), u)
17 self.assertEqual(format(lz), u)
20
18
21 def test_lazy_eval_nonascii_bytes(self):
19 def test_lazy_eval_nonascii_bytes(self):
22 u = u'ünicødé'
20 u = u'ünicødé'
23 b = u.encode('utf8')
21 b = u.encode('utf8')
24 lz = LazyEvaluate(lambda : b)
22 lz = LazyEvaluate(lambda : b)
25 # unicode(lz) would fail
23 # unicode(lz) would fail
26 self.assertEqual(str(lz), str(b))
24 self.assertEqual(str(lz), str(b))
27 self.assertEqual(format(lz), str(b))
25 self.assertEqual(format(lz), str(b))
28
26
29 def test_lazy_eval_float(self):
27 def test_lazy_eval_float(self):
30 f = 0.503
28 f = 0.503
31 lz = LazyEvaluate(lambda : f)
29 lz = LazyEvaluate(lambda : f)
32
30
33 self.assertEqual(str(lz), str(f))
31 self.assertEqual(str(lz), str(f))
34 self.assertEqual(unicode_type(lz), unicode_type(f))
35 self.assertEqual(format(lz), str(f))
32 self.assertEqual(format(lz), str(f))
36 self.assertEqual(format(lz, '.1'), '0.5')
33 self.assertEqual(format(lz, '.1'), '0.5')
37
34
@@ -1,514 +1,514 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for code execution (%run and related), which is particularly tricky.
2 """Tests for code execution (%run and related), which is particularly tricky.
3
3
4 Because of how %run manages namespaces, and the fact that we are trying here to
4 Because of how %run manages namespaces, and the fact that we are trying here to
5 verify subtle object deletion and reference counting issues, the %run tests
5 verify subtle object deletion and reference counting issues, the %run tests
6 will be kept in this separate file. This makes it easier to aggregate in one
6 will be kept in this separate file. This makes it easier to aggregate in one
7 place the tricks needed to handle it; most other magics are much easier to test
7 place the tricks needed to handle it; most other magics are much easier to test
8 and we do so in a common test_magic file.
8 and we do so in a common test_magic file.
9 """
9 """
10
10
11 # Copyright (c) IPython Development Team.
11 # Copyright (c) IPython Development Team.
12 # Distributed under the terms of the Modified BSD License.
12 # Distributed under the terms of the Modified BSD License.
13
13
14
14
15
15
16 import functools
16 import functools
17 import os
17 import os
18 from os.path import join as pjoin
18 from os.path import join as pjoin
19 import random
19 import random
20 import sys
20 import sys
21 import textwrap
21 import textwrap
22 import unittest
22 import unittest
23
23
24 try:
24 try:
25 from unittest.mock import patch
25 from unittest.mock import patch
26 except ImportError:
26 except ImportError:
27 from mock import patch
27 from mock import patch
28
28
29 import nose.tools as nt
29 import nose.tools as nt
30 from nose import SkipTest
30 from nose import SkipTest
31
31
32 from IPython.testing import decorators as dec
32 from IPython.testing import decorators as dec
33 from IPython.testing import tools as tt
33 from IPython.testing import tools as tt
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.io import capture_output
35 from IPython.utils.io import capture_output
36 from IPython.utils.tempdir import TemporaryDirectory
36 from IPython.utils.tempdir import TemporaryDirectory
37 from IPython.core import debugger
37 from IPython.core import debugger
38
38
39
39
40 def doctest_refbug():
40 def doctest_refbug():
41 """Very nasty problem with references held by multiple runs of a script.
41 """Very nasty problem with references held by multiple runs of a script.
42 See: https://github.com/ipython/ipython/issues/141
42 See: https://github.com/ipython/ipython/issues/141
43
43
44 In [1]: _ip.clear_main_mod_cache()
44 In [1]: _ip.clear_main_mod_cache()
45 # random
45 # random
46
46
47 In [2]: %run refbug
47 In [2]: %run refbug
48
48
49 In [3]: call_f()
49 In [3]: call_f()
50 lowercased: hello
50 lowercased: hello
51
51
52 In [4]: %run refbug
52 In [4]: %run refbug
53
53
54 In [5]: call_f()
54 In [5]: call_f()
55 lowercased: hello
55 lowercased: hello
56 lowercased: hello
56 lowercased: hello
57 """
57 """
58
58
59
59
60 def doctest_run_builtins():
60 def doctest_run_builtins():
61 r"""Check that %run doesn't damage __builtins__.
61 r"""Check that %run doesn't damage __builtins__.
62
62
63 In [1]: import tempfile
63 In [1]: import tempfile
64
64
65 In [2]: bid1 = id(__builtins__)
65 In [2]: bid1 = id(__builtins__)
66
66
67 In [3]: fname = tempfile.mkstemp('.py')[1]
67 In [3]: fname = tempfile.mkstemp('.py')[1]
68
68
69 In [3]: f = open(fname,'w')
69 In [3]: f = open(fname,'w')
70
70
71 In [4]: dummy= f.write('pass\n')
71 In [4]: dummy= f.write('pass\n')
72
72
73 In [5]: f.flush()
73 In [5]: f.flush()
74
74
75 In [6]: t1 = type(__builtins__)
75 In [6]: t1 = type(__builtins__)
76
76
77 In [7]: %run $fname
77 In [7]: %run $fname
78
78
79 In [7]: f.close()
79 In [7]: f.close()
80
80
81 In [8]: bid2 = id(__builtins__)
81 In [8]: bid2 = id(__builtins__)
82
82
83 In [9]: t2 = type(__builtins__)
83 In [9]: t2 = type(__builtins__)
84
84
85 In [10]: t1 == t2
85 In [10]: t1 == t2
86 Out[10]: True
86 Out[10]: True
87
87
88 In [10]: bid1 == bid2
88 In [10]: bid1 == bid2
89 Out[10]: True
89 Out[10]: True
90
90
91 In [12]: try:
91 In [12]: try:
92 ....: os.unlink(fname)
92 ....: os.unlink(fname)
93 ....: except:
93 ....: except:
94 ....: pass
94 ....: pass
95 ....:
95 ....:
96 """
96 """
97
97
98
98
99 def doctest_run_option_parser():
99 def doctest_run_option_parser():
100 r"""Test option parser in %run.
100 r"""Test option parser in %run.
101
101
102 In [1]: %run print_argv.py
102 In [1]: %run print_argv.py
103 []
103 []
104
104
105 In [2]: %run print_argv.py print*.py
105 In [2]: %run print_argv.py print*.py
106 ['print_argv.py']
106 ['print_argv.py']
107
107
108 In [3]: %run -G print_argv.py print*.py
108 In [3]: %run -G print_argv.py print*.py
109 ['print*.py']
109 ['print*.py']
110
110
111 """
111 """
112
112
113
113
114 @dec.skip_win32
114 @dec.skip_win32
115 def doctest_run_option_parser_for_posix():
115 def doctest_run_option_parser_for_posix():
116 r"""Test option parser in %run (Linux/OSX specific).
116 r"""Test option parser in %run (Linux/OSX specific).
117
117
118 You need double quote to escape glob in POSIX systems:
118 You need double quote to escape glob in POSIX systems:
119
119
120 In [1]: %run print_argv.py print\\*.py
120 In [1]: %run print_argv.py print\\*.py
121 ['print*.py']
121 ['print*.py']
122
122
123 You can't use quote to escape glob in POSIX systems:
123 You can't use quote to escape glob in POSIX systems:
124
124
125 In [2]: %run print_argv.py 'print*.py'
125 In [2]: %run print_argv.py 'print*.py'
126 ['print_argv.py']
126 ['print_argv.py']
127
127
128 """
128 """
129
129
130
130
131 @dec.skip_if_not_win32
131 @dec.skip_if_not_win32
132 def doctest_run_option_parser_for_windows():
132 def doctest_run_option_parser_for_windows():
133 r"""Test option parser in %run (Windows specific).
133 r"""Test option parser in %run (Windows specific).
134
134
135 In Windows, you can't escape ``*` `by backslash:
135 In Windows, you can't escape ``*` `by backslash:
136
136
137 In [1]: %run print_argv.py print\\*.py
137 In [1]: %run print_argv.py print\\*.py
138 ['print\\*.py']
138 ['print\\*.py']
139
139
140 You can use quote to escape glob:
140 You can use quote to escape glob:
141
141
142 In [2]: %run print_argv.py 'print*.py'
142 In [2]: %run print_argv.py 'print*.py'
143 ['print*.py']
143 ['print*.py']
144
144
145 """
145 """
146
146
147
147
148 @py3compat.doctest_refactor_print
148 @py3compat.doctest_refactor_print
149 def doctest_reset_del():
149 def doctest_reset_del():
150 """Test that resetting doesn't cause errors in __del__ methods.
150 """Test that resetting doesn't cause errors in __del__ methods.
151
151
152 In [2]: class A(object):
152 In [2]: class A(object):
153 ...: def __del__(self):
153 ...: def __del__(self):
154 ...: print str("Hi")
154 ...: print str("Hi")
155 ...:
155 ...:
156
156
157 In [3]: a = A()
157 In [3]: a = A()
158
158
159 In [4]: get_ipython().reset()
159 In [4]: get_ipython().reset()
160 Hi
160 Hi
161
161
162 In [5]: 1+1
162 In [5]: 1+1
163 Out[5]: 2
163 Out[5]: 2
164 """
164 """
165
165
166 # For some tests, it will be handy to organize them in a class with a common
166 # For some tests, it will be handy to organize them in a class with a common
167 # setup that makes a temp file
167 # setup that makes a temp file
168
168
169 class TestMagicRunPass(tt.TempFileMixin):
169 class TestMagicRunPass(tt.TempFileMixin):
170
170
171 def setup(self):
171 def setup(self):
172 """Make a valid python temp file."""
172 """Make a valid python temp file."""
173 self.mktmp('pass\n')
173 self.mktmp('pass\n')
174
174
175 def run_tmpfile(self):
175 def run_tmpfile(self):
176 _ip = get_ipython()
176 _ip = get_ipython()
177 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
177 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
178 # See below and ticket https://bugs.launchpad.net/bugs/366353
178 # See below and ticket https://bugs.launchpad.net/bugs/366353
179 _ip.magic('run %s' % self.fname)
179 _ip.magic('run %s' % self.fname)
180
180
181 def run_tmpfile_p(self):
181 def run_tmpfile_p(self):
182 _ip = get_ipython()
182 _ip = get_ipython()
183 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
183 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
184 # See below and ticket https://bugs.launchpad.net/bugs/366353
184 # See below and ticket https://bugs.launchpad.net/bugs/366353
185 _ip.magic('run -p %s' % self.fname)
185 _ip.magic('run -p %s' % self.fname)
186
186
187 def test_builtins_id(self):
187 def test_builtins_id(self):
188 """Check that %run doesn't damage __builtins__ """
188 """Check that %run doesn't damage __builtins__ """
189 _ip = get_ipython()
189 _ip = get_ipython()
190 # Test that the id of __builtins__ is not modified by %run
190 # Test that the id of __builtins__ is not modified by %run
191 bid1 = id(_ip.user_ns['__builtins__'])
191 bid1 = id(_ip.user_ns['__builtins__'])
192 self.run_tmpfile()
192 self.run_tmpfile()
193 bid2 = id(_ip.user_ns['__builtins__'])
193 bid2 = id(_ip.user_ns['__builtins__'])
194 nt.assert_equal(bid1, bid2)
194 nt.assert_equal(bid1, bid2)
195
195
196 def test_builtins_type(self):
196 def test_builtins_type(self):
197 """Check that the type of __builtins__ doesn't change with %run.
197 """Check that the type of __builtins__ doesn't change with %run.
198
198
199 However, the above could pass if __builtins__ was already modified to
199 However, the above could pass if __builtins__ was already modified to
200 be a dict (it should be a module) by a previous use of %run. So we
200 be a dict (it should be a module) by a previous use of %run. So we
201 also check explicitly that it really is a module:
201 also check explicitly that it really is a module:
202 """
202 """
203 _ip = get_ipython()
203 _ip = get_ipython()
204 self.run_tmpfile()
204 self.run_tmpfile()
205 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
205 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
206
206
207 def test_run_profile( self ):
207 def test_run_profile( self ):
208 """Test that the option -p, which invokes the profiler, do not
208 """Test that the option -p, which invokes the profiler, do not
209 crash by invoking execfile"""
209 crash by invoking execfile"""
210 self.run_tmpfile_p()
210 self.run_tmpfile_p()
211
211
212 def test_run_debug_twice(self):
212 def test_run_debug_twice(self):
213 # https://github.com/ipython/ipython/issues/10028
213 # https://github.com/ipython/ipython/issues/10028
214 _ip = get_ipython()
214 _ip = get_ipython()
215 with tt.fake_input(['c']):
215 with tt.fake_input(['c']):
216 _ip.magic('run -d %s' % self.fname)
216 _ip.magic('run -d %s' % self.fname)
217 with tt.fake_input(['c']):
217 with tt.fake_input(['c']):
218 _ip.magic('run -d %s' % self.fname)
218 _ip.magic('run -d %s' % self.fname)
219
219
220
220
221 class TestMagicRunSimple(tt.TempFileMixin):
221 class TestMagicRunSimple(tt.TempFileMixin):
222
222
223 def test_simpledef(self):
223 def test_simpledef(self):
224 """Test that simple class definitions work."""
224 """Test that simple class definitions work."""
225 src = ("class foo: pass\n"
225 src = ("class foo: pass\n"
226 "def f(): return foo()")
226 "def f(): return foo()")
227 self.mktmp(src)
227 self.mktmp(src)
228 _ip.magic('run %s' % self.fname)
228 _ip.magic('run %s' % self.fname)
229 _ip.run_cell('t = isinstance(f(), foo)')
229 _ip.run_cell('t = isinstance(f(), foo)')
230 nt.assert_true(_ip.user_ns['t'])
230 nt.assert_true(_ip.user_ns['t'])
231
231
232 def test_obj_del(self):
232 def test_obj_del(self):
233 """Test that object's __del__ methods are called on exit."""
233 """Test that object's __del__ methods are called on exit."""
234 if sys.platform == 'win32':
234 if sys.platform == 'win32':
235 try:
235 try:
236 import win32api
236 import win32api
237 except ImportError:
237 except ImportError:
238 raise SkipTest("Test requires pywin32")
238 raise SkipTest("Test requires pywin32")
239 src = ("class A(object):\n"
239 src = ("class A(object):\n"
240 " def __del__(self):\n"
240 " def __del__(self):\n"
241 " print 'object A deleted'\n"
241 " print 'object A deleted'\n"
242 "a = A()\n")
242 "a = A()\n")
243 self.mktmp(py3compat.doctest_refactor_print(src))
243 self.mktmp(py3compat.doctest_refactor_print(src))
244 if dec.module_not_available('sqlite3'):
244 if dec.module_not_available('sqlite3'):
245 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
245 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
246 else:
246 else:
247 err = None
247 err = None
248 tt.ipexec_validate(self.fname, 'object A deleted', err)
248 tt.ipexec_validate(self.fname, 'object A deleted', err)
249
249
250 def test_aggressive_namespace_cleanup(self):
250 def test_aggressive_namespace_cleanup(self):
251 """Test that namespace cleanup is not too aggressive GH-238
251 """Test that namespace cleanup is not too aggressive GH-238
252
252
253 Returning from another run magic deletes the namespace"""
253 Returning from another run magic deletes the namespace"""
254 # see ticket https://github.com/ipython/ipython/issues/238
254 # see ticket https://github.com/ipython/ipython/issues/238
255
255
256 with tt.TempFileMixin() as empty:
256 with tt.TempFileMixin() as empty:
257 empty.mktmp('')
257 empty.mktmp('')
258 # On Windows, the filename will have \users in it, so we need to use the
258 # On Windows, the filename will have \users in it, so we need to use the
259 # repr so that the \u becomes \\u.
259 # repr so that the \u becomes \\u.
260 src = ("ip = get_ipython()\n"
260 src = ("ip = get_ipython()\n"
261 "for i in range(5):\n"
261 "for i in range(5):\n"
262 " try:\n"
262 " try:\n"
263 " ip.magic(%r)\n"
263 " ip.magic(%r)\n"
264 " except NameError as e:\n"
264 " except NameError as e:\n"
265 " print(i)\n"
265 " print(i)\n"
266 " break\n" % ('run ' + empty.fname))
266 " break\n" % ('run ' + empty.fname))
267 self.mktmp(src)
267 self.mktmp(src)
268 _ip.magic('run %s' % self.fname)
268 _ip.magic('run %s' % self.fname)
269 _ip.run_cell('ip == get_ipython()')
269 _ip.run_cell('ip == get_ipython()')
270 nt.assert_equal(_ip.user_ns['i'], 4)
270 nt.assert_equal(_ip.user_ns['i'], 4)
271
271
272 def test_run_second(self):
272 def test_run_second(self):
273 """Test that running a second file doesn't clobber the first, gh-3547
273 """Test that running a second file doesn't clobber the first, gh-3547
274 """
274 """
275 self.mktmp("avar = 1\n"
275 self.mktmp("avar = 1\n"
276 "def afunc():\n"
276 "def afunc():\n"
277 " return avar\n")
277 " return avar\n")
278
278
279 with tt.TempFileMixin() as empty:
279 with tt.TempFileMixin() as empty:
280 empty.mktmp("")
280 empty.mktmp("")
281
281
282 _ip.magic('run %s' % self.fname)
282 _ip.magic('run %s' % self.fname)
283 _ip.magic('run %s' % empty.fname)
283 _ip.magic('run %s' % empty.fname)
284 nt.assert_equal(_ip.user_ns['afunc'](), 1)
284 nt.assert_equal(_ip.user_ns['afunc'](), 1)
285
285
286 @dec.skip_win32
286 @dec.skip_win32
287 def test_tclass(self):
287 def test_tclass(self):
288 mydir = os.path.dirname(__file__)
288 mydir = os.path.dirname(__file__)
289 tc = os.path.join(mydir, 'tclass')
289 tc = os.path.join(mydir, 'tclass')
290 src = ("%%run '%s' C-first\n"
290 src = ("%%run '%s' C-first\n"
291 "%%run '%s' C-second\n"
291 "%%run '%s' C-second\n"
292 "%%run '%s' C-third\n") % (tc, tc, tc)
292 "%%run '%s' C-third\n") % (tc, tc, tc)
293 self.mktmp(src, '.ipy')
293 self.mktmp(src, '.ipy')
294 out = """\
294 out = """\
295 ARGV 1-: ['C-first']
295 ARGV 1-: ['C-first']
296 ARGV 1-: ['C-second']
296 ARGV 1-: ['C-second']
297 tclass.py: deleting object: C-first
297 tclass.py: deleting object: C-first
298 ARGV 1-: ['C-third']
298 ARGV 1-: ['C-third']
299 tclass.py: deleting object: C-second
299 tclass.py: deleting object: C-second
300 tclass.py: deleting object: C-third
300 tclass.py: deleting object: C-third
301 """
301 """
302 if dec.module_not_available('sqlite3'):
302 if dec.module_not_available('sqlite3'):
303 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
303 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
304 else:
304 else:
305 err = None
305 err = None
306 tt.ipexec_validate(self.fname, out, err)
306 tt.ipexec_validate(self.fname, out, err)
307
307
308 def test_run_i_after_reset(self):
308 def test_run_i_after_reset(self):
309 """Check that %run -i still works after %reset (gh-693)"""
309 """Check that %run -i still works after %reset (gh-693)"""
310 src = "yy = zz\n"
310 src = "yy = zz\n"
311 self.mktmp(src)
311 self.mktmp(src)
312 _ip.run_cell("zz = 23")
312 _ip.run_cell("zz = 23")
313 _ip.magic('run -i %s' % self.fname)
313 _ip.magic('run -i %s' % self.fname)
314 nt.assert_equal(_ip.user_ns['yy'], 23)
314 nt.assert_equal(_ip.user_ns['yy'], 23)
315 _ip.magic('reset -f')
315 _ip.magic('reset -f')
316 _ip.run_cell("zz = 23")
316 _ip.run_cell("zz = 23")
317 _ip.magic('run -i %s' % self.fname)
317 _ip.magic('run -i %s' % self.fname)
318 nt.assert_equal(_ip.user_ns['yy'], 23)
318 nt.assert_equal(_ip.user_ns['yy'], 23)
319
319
320 def test_unicode(self):
320 def test_unicode(self):
321 """Check that files in odd encodings are accepted."""
321 """Check that files in odd encodings are accepted."""
322 mydir = os.path.dirname(__file__)
322 mydir = os.path.dirname(__file__)
323 na = os.path.join(mydir, 'nonascii.py')
323 na = os.path.join(mydir, 'nonascii.py')
324 _ip.magic('run "%s"' % na)
324 _ip.magic('run "%s"' % na)
325 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
325 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
326
326
327 def test_run_py_file_attribute(self):
327 def test_run_py_file_attribute(self):
328 """Test handling of `__file__` attribute in `%run <file>.py`."""
328 """Test handling of `__file__` attribute in `%run <file>.py`."""
329 src = "t = __file__\n"
329 src = "t = __file__\n"
330 self.mktmp(src)
330 self.mktmp(src)
331 _missing = object()
331 _missing = object()
332 file1 = _ip.user_ns.get('__file__', _missing)
332 file1 = _ip.user_ns.get('__file__', _missing)
333 _ip.magic('run %s' % self.fname)
333 _ip.magic('run %s' % self.fname)
334 file2 = _ip.user_ns.get('__file__', _missing)
334 file2 = _ip.user_ns.get('__file__', _missing)
335
335
336 # Check that __file__ was equal to the filename in the script's
336 # Check that __file__ was equal to the filename in the script's
337 # namespace.
337 # namespace.
338 nt.assert_equal(_ip.user_ns['t'], self.fname)
338 nt.assert_equal(_ip.user_ns['t'], self.fname)
339
339
340 # Check that __file__ was not leaked back into user_ns.
340 # Check that __file__ was not leaked back into user_ns.
341 nt.assert_equal(file1, file2)
341 nt.assert_equal(file1, file2)
342
342
343 def test_run_ipy_file_attribute(self):
343 def test_run_ipy_file_attribute(self):
344 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
344 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
345 src = "t = __file__\n"
345 src = "t = __file__\n"
346 self.mktmp(src, ext='.ipy')
346 self.mktmp(src, ext='.ipy')
347 _missing = object()
347 _missing = object()
348 file1 = _ip.user_ns.get('__file__', _missing)
348 file1 = _ip.user_ns.get('__file__', _missing)
349 _ip.magic('run %s' % self.fname)
349 _ip.magic('run %s' % self.fname)
350 file2 = _ip.user_ns.get('__file__', _missing)
350 file2 = _ip.user_ns.get('__file__', _missing)
351
351
352 # Check that __file__ was equal to the filename in the script's
352 # Check that __file__ was equal to the filename in the script's
353 # namespace.
353 # namespace.
354 nt.assert_equal(_ip.user_ns['t'], self.fname)
354 nt.assert_equal(_ip.user_ns['t'], self.fname)
355
355
356 # Check that __file__ was not leaked back into user_ns.
356 # Check that __file__ was not leaked back into user_ns.
357 nt.assert_equal(file1, file2)
357 nt.assert_equal(file1, file2)
358
358
359 def test_run_formatting(self):
359 def test_run_formatting(self):
360 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
360 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
361 src = "pass"
361 src = "pass"
362 self.mktmp(src)
362 self.mktmp(src)
363 _ip.magic('run -t -N 1 %s' % self.fname)
363 _ip.magic('run -t -N 1 %s' % self.fname)
364 _ip.magic('run -t -N 10 %s' % self.fname)
364 _ip.magic('run -t -N 10 %s' % self.fname)
365
365
366 def test_ignore_sys_exit(self):
366 def test_ignore_sys_exit(self):
367 """Test the -e option to ignore sys.exit()"""
367 """Test the -e option to ignore sys.exit()"""
368 src = "import sys; sys.exit(1)"
368 src = "import sys; sys.exit(1)"
369 self.mktmp(src)
369 self.mktmp(src)
370 with tt.AssertPrints('SystemExit'):
370 with tt.AssertPrints('SystemExit'):
371 _ip.magic('run %s' % self.fname)
371 _ip.magic('run %s' % self.fname)
372
372
373 with tt.AssertNotPrints('SystemExit'):
373 with tt.AssertNotPrints('SystemExit'):
374 _ip.magic('run -e %s' % self.fname)
374 _ip.magic('run -e %s' % self.fname)
375
375
376 def test_run_nb(self):
376 def test_run_nb(self):
377 """Test %run notebook.ipynb"""
377 """Test %run notebook.ipynb"""
378 from nbformat import v4, writes
378 from nbformat import v4, writes
379 nb = v4.new_notebook(
379 nb = v4.new_notebook(
380 cells=[
380 cells=[
381 v4.new_markdown_cell("The Ultimate Question of Everything"),
381 v4.new_markdown_cell("The Ultimate Question of Everything"),
382 v4.new_code_cell("answer=42")
382 v4.new_code_cell("answer=42")
383 ]
383 ]
384 )
384 )
385 src = writes(nb, version=4)
385 src = writes(nb, version=4)
386 self.mktmp(src, ext='.ipynb')
386 self.mktmp(src, ext='.ipynb')
387
387
388 _ip.magic("run %s" % self.fname)
388 _ip.magic("run %s" % self.fname)
389
389
390 nt.assert_equal(_ip.user_ns['answer'], 42)
390 nt.assert_equal(_ip.user_ns['answer'], 42)
391
391
392
392
393
393
394 class TestMagicRunWithPackage(unittest.TestCase):
394 class TestMagicRunWithPackage(unittest.TestCase):
395
395
396 def writefile(self, name, content):
396 def writefile(self, name, content):
397 path = os.path.join(self.tempdir.name, name)
397 path = os.path.join(self.tempdir.name, name)
398 d = os.path.dirname(path)
398 d = os.path.dirname(path)
399 if not os.path.isdir(d):
399 if not os.path.isdir(d):
400 os.makedirs(d)
400 os.makedirs(d)
401 with open(path, 'w') as f:
401 with open(path, 'w') as f:
402 f.write(textwrap.dedent(content))
402 f.write(textwrap.dedent(content))
403
403
404 def setUp(self):
404 def setUp(self):
405 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
405 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
406 """Temporary valid python package name."""
406 """Temporary valid python package name."""
407
407
408 self.value = int(random.random() * 10000)
408 self.value = int(random.random() * 10000)
409
409
410 self.tempdir = TemporaryDirectory()
410 self.tempdir = TemporaryDirectory()
411 self.__orig_cwd = py3compat.getcwd()
411 self.__orig_cwd = os.getcwd()
412 sys.path.insert(0, self.tempdir.name)
412 sys.path.insert(0, self.tempdir.name)
413
413
414 self.writefile(os.path.join(package, '__init__.py'), '')
414 self.writefile(os.path.join(package, '__init__.py'), '')
415 self.writefile(os.path.join(package, 'sub.py'), """
415 self.writefile(os.path.join(package, 'sub.py'), """
416 x = {0!r}
416 x = {0!r}
417 """.format(self.value))
417 """.format(self.value))
418 self.writefile(os.path.join(package, 'relative.py'), """
418 self.writefile(os.path.join(package, 'relative.py'), """
419 from .sub import x
419 from .sub import x
420 """)
420 """)
421 self.writefile(os.path.join(package, 'absolute.py'), """
421 self.writefile(os.path.join(package, 'absolute.py'), """
422 from {0}.sub import x
422 from {0}.sub import x
423 """.format(package))
423 """.format(package))
424
424
425 def tearDown(self):
425 def tearDown(self):
426 os.chdir(self.__orig_cwd)
426 os.chdir(self.__orig_cwd)
427 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
427 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
428 self.tempdir.cleanup()
428 self.tempdir.cleanup()
429
429
430 def check_run_submodule(self, submodule, opts=''):
430 def check_run_submodule(self, submodule, opts=''):
431 _ip.user_ns.pop('x', None)
431 _ip.user_ns.pop('x', None)
432 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
432 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
433 self.assertEqual(_ip.user_ns['x'], self.value,
433 self.assertEqual(_ip.user_ns['x'], self.value,
434 'Variable `x` is not loaded from module `{0}`.'
434 'Variable `x` is not loaded from module `{0}`.'
435 .format(submodule))
435 .format(submodule))
436
436
437 def test_run_submodule_with_absolute_import(self):
437 def test_run_submodule_with_absolute_import(self):
438 self.check_run_submodule('absolute')
438 self.check_run_submodule('absolute')
439
439
440 def test_run_submodule_with_relative_import(self):
440 def test_run_submodule_with_relative_import(self):
441 """Run submodule that has a relative import statement (#2727)."""
441 """Run submodule that has a relative import statement (#2727)."""
442 self.check_run_submodule('relative')
442 self.check_run_submodule('relative')
443
443
444 def test_prun_submodule_with_absolute_import(self):
444 def test_prun_submodule_with_absolute_import(self):
445 self.check_run_submodule('absolute', '-p')
445 self.check_run_submodule('absolute', '-p')
446
446
447 def test_prun_submodule_with_relative_import(self):
447 def test_prun_submodule_with_relative_import(self):
448 self.check_run_submodule('relative', '-p')
448 self.check_run_submodule('relative', '-p')
449
449
450 def with_fake_debugger(func):
450 def with_fake_debugger(func):
451 @functools.wraps(func)
451 @functools.wraps(func)
452 def wrapper(*args, **kwds):
452 def wrapper(*args, **kwds):
453 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
453 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
454 return func(*args, **kwds)
454 return func(*args, **kwds)
455 return wrapper
455 return wrapper
456
456
457 @with_fake_debugger
457 @with_fake_debugger
458 def test_debug_run_submodule_with_absolute_import(self):
458 def test_debug_run_submodule_with_absolute_import(self):
459 self.check_run_submodule('absolute', '-d')
459 self.check_run_submodule('absolute', '-d')
460
460
461 @with_fake_debugger
461 @with_fake_debugger
462 def test_debug_run_submodule_with_relative_import(self):
462 def test_debug_run_submodule_with_relative_import(self):
463 self.check_run_submodule('relative', '-d')
463 self.check_run_submodule('relative', '-d')
464
464
465 def test_run__name__():
465 def test_run__name__():
466 with TemporaryDirectory() as td:
466 with TemporaryDirectory() as td:
467 path = pjoin(td, 'foo.py')
467 path = pjoin(td, 'foo.py')
468 with open(path, 'w') as f:
468 with open(path, 'w') as f:
469 f.write("q = __name__")
469 f.write("q = __name__")
470
470
471 _ip.user_ns.pop('q', None)
471 _ip.user_ns.pop('q', None)
472 _ip.magic('run {}'.format(path))
472 _ip.magic('run {}'.format(path))
473 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
473 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
474
474
475 _ip.magic('run -n {}'.format(path))
475 _ip.magic('run -n {}'.format(path))
476 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
476 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
477
477
478 def test_run_tb():
478 def test_run_tb():
479 """Test traceback offset in %run"""
479 """Test traceback offset in %run"""
480 with TemporaryDirectory() as td:
480 with TemporaryDirectory() as td:
481 path = pjoin(td, 'foo.py')
481 path = pjoin(td, 'foo.py')
482 with open(path, 'w') as f:
482 with open(path, 'w') as f:
483 f.write('\n'.join([
483 f.write('\n'.join([
484 "def foo():",
484 "def foo():",
485 " return bar()",
485 " return bar()",
486 "def bar():",
486 "def bar():",
487 " raise RuntimeError('hello!')",
487 " raise RuntimeError('hello!')",
488 "foo()",
488 "foo()",
489 ]))
489 ]))
490 with capture_output() as io:
490 with capture_output() as io:
491 _ip.magic('run {}'.format(path))
491 _ip.magic('run {}'.format(path))
492 out = io.stdout
492 out = io.stdout
493 nt.assert_not_in("execfile", out)
493 nt.assert_not_in("execfile", out)
494 nt.assert_in("RuntimeError", out)
494 nt.assert_in("RuntimeError", out)
495 nt.assert_equal(out.count("---->"), 3)
495 nt.assert_equal(out.count("---->"), 3)
496
496
497 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
497 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
498 def test_script_tb():
498 def test_script_tb():
499 """Test traceback offset in `ipython script.py`"""
499 """Test traceback offset in `ipython script.py`"""
500 with TemporaryDirectory() as td:
500 with TemporaryDirectory() as td:
501 path = pjoin(td, 'foo.py')
501 path = pjoin(td, 'foo.py')
502 with open(path, 'w') as f:
502 with open(path, 'w') as f:
503 f.write('\n'.join([
503 f.write('\n'.join([
504 "def foo():",
504 "def foo():",
505 " return bar()",
505 " return bar()",
506 "def bar():",
506 "def bar():",
507 " raise RuntimeError('hello!')",
507 " raise RuntimeError('hello!')",
508 "foo()",
508 "foo()",
509 ]))
509 ]))
510 out, err = tt.ipexec(path)
510 out, err = tt.ipexec(path)
511 nt.assert_not_in("execfile", out)
511 nt.assert_not_in("execfile", out)
512 nt.assert_in("RuntimeError", out)
512 nt.assert_in("RuntimeError", out)
513 nt.assert_equal(out.count("---->"), 3)
513 nt.assert_equal(out.count("---->"), 3)
514
514
@@ -1,1488 +1,1488 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Verbose and colourful traceback formatting.
3 Verbose and colourful traceback formatting.
4
4
5 **ColorTB**
5 **ColorTB**
6
6
7 I've always found it a bit hard to visually parse tracebacks in Python. The
7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 ColorTB class is a solution to that problem. It colors the different parts of a
8 ColorTB class is a solution to that problem. It colors the different parts of a
9 traceback in a manner similar to what you would expect from a syntax-highlighting
9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 text editor.
10 text editor.
11
11
12 Installation instructions for ColorTB::
12 Installation instructions for ColorTB::
13
13
14 import sys,ultratb
14 import sys,ultratb
15 sys.excepthook = ultratb.ColorTB()
15 sys.excepthook = ultratb.ColorTB()
16
16
17 **VerboseTB**
17 **VerboseTB**
18
18
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 and intended it for CGI programmers, but why should they have all the fun? I
21 and intended it for CGI programmers, but why should they have all the fun? I
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 but kind of neat, and maybe useful for long-running programs that you believe
23 but kind of neat, and maybe useful for long-running programs that you believe
24 are bug-free. If a crash *does* occur in that type of program you want details.
24 are bug-free. If a crash *does* occur in that type of program you want details.
25 Give it a shot--you'll love it or you'll hate it.
25 Give it a shot--you'll love it or you'll hate it.
26
26
27 .. note::
27 .. note::
28
28
29 The Verbose mode prints the variables currently visible where the exception
29 The Verbose mode prints the variables currently visible where the exception
30 happened (shortening their strings if too long). This can potentially be
30 happened (shortening their strings if too long). This can potentially be
31 very slow, if you happen to have a huge data structure whose string
31 very slow, if you happen to have a huge data structure whose string
32 representation is complex to compute. Your computer may appear to freeze for
32 representation is complex to compute. Your computer may appear to freeze for
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 with Ctrl-C (maybe hitting it more than once).
34 with Ctrl-C (maybe hitting it more than once).
35
35
36 If you encounter this kind of situation often, you may want to use the
36 If you encounter this kind of situation often, you may want to use the
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 variables (but otherwise includes the information and context given by
38 variables (but otherwise includes the information and context given by
39 Verbose).
39 Verbose).
40
40
41 .. note::
41 .. note::
42
42
43 The verbose mode print all variables in the stack, which means it can
43 The verbose mode print all variables in the stack, which means it can
44 potentially leak sensitive information like access keys, or unencryted
44 potentially leak sensitive information like access keys, or unencryted
45 password.
45 password.
46
46
47 Installation instructions for VerboseTB::
47 Installation instructions for VerboseTB::
48
48
49 import sys,ultratb
49 import sys,ultratb
50 sys.excepthook = ultratb.VerboseTB()
50 sys.excepthook = ultratb.VerboseTB()
51
51
52 Note: Much of the code in this module was lifted verbatim from the standard
52 Note: Much of the code in this module was lifted verbatim from the standard
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54
54
55 Color schemes
55 Color schemes
56 -------------
56 -------------
57
57
58 The colors are defined in the class TBTools through the use of the
58 The colors are defined in the class TBTools through the use of the
59 ColorSchemeTable class. Currently the following exist:
59 ColorSchemeTable class. Currently the following exist:
60
60
61 - NoColor: allows all of this module to be used in any terminal (the color
61 - NoColor: allows all of this module to be used in any terminal (the color
62 escapes are just dummy blank strings).
62 escapes are just dummy blank strings).
63
63
64 - Linux: is meant to look good in a terminal like the Linux console (black
64 - Linux: is meant to look good in a terminal like the Linux console (black
65 or very dark background).
65 or very dark background).
66
66
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 in light background terminals.
68 in light background terminals.
69
69
70 - Neutral: a neutral color scheme that should be readable on both light and
70 - Neutral: a neutral color scheme that should be readable on both light and
71 dark background
71 dark background
72
72
73 You can implement other color schemes easily, the syntax is fairly
73 You can implement other color schemes easily, the syntax is fairly
74 self-explanatory. Please send back new schemes you develop to the author for
74 self-explanatory. Please send back new schemes you develop to the author for
75 possible inclusion in future releases.
75 possible inclusion in future releases.
76
76
77 Inheritance diagram:
77 Inheritance diagram:
78
78
79 .. inheritance-diagram:: IPython.core.ultratb
79 .. inheritance-diagram:: IPython.core.ultratb
80 :parts: 3
80 :parts: 3
81 """
81 """
82
82
83 #*****************************************************************************
83 #*****************************************************************************
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 #
86 #
87 # Distributed under the terms of the BSD License. The full license is in
87 # Distributed under the terms of the BSD License. The full license is in
88 # the file COPYING, distributed as part of this software.
88 # the file COPYING, distributed as part of this software.
89 #*****************************************************************************
89 #*****************************************************************************
90
90
91
91
92 import dis
92 import dis
93 import inspect
93 import inspect
94 import keyword
94 import keyword
95 import linecache
95 import linecache
96 import os
96 import os
97 import pydoc
97 import pydoc
98 import re
98 import re
99 import sys
99 import sys
100 import time
100 import time
101 import tokenize
101 import tokenize
102 import traceback
102 import traceback
103 import types
103 import types
104
104
105 try: # Python 2
105 try: # Python 2
106 generate_tokens = tokenize.generate_tokens
106 generate_tokens = tokenize.generate_tokens
107 except AttributeError: # Python 3
107 except AttributeError: # Python 3
108 generate_tokens = tokenize.tokenize
108 generate_tokens = tokenize.tokenize
109
109
110 # For purposes of monkeypatching inspect to fix a bug in it.
110 # For purposes of monkeypatching inspect to fix a bug in it.
111 from inspect import getsourcefile, getfile, getmodule, \
111 from inspect import getsourcefile, getfile, getmodule, \
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
113
113
114 # IPython's own modules
114 # IPython's own modules
115 from IPython import get_ipython
115 from IPython import get_ipython
116 from IPython.core import debugger
116 from IPython.core import debugger
117 from IPython.core.display_trap import DisplayTrap
117 from IPython.core.display_trap import DisplayTrap
118 from IPython.core.excolors import exception_colors
118 from IPython.core.excolors import exception_colors
119 from IPython.utils import PyColorize
119 from IPython.utils import PyColorize
120 from IPython.utils import openpy
120 from IPython.utils import openpy
121 from IPython.utils import path as util_path
121 from IPython.utils import path as util_path
122 from IPython.utils import py3compat
122 from IPython.utils import py3compat
123 from IPython.utils import ulinecache
123 from IPython.utils import ulinecache
124 from IPython.utils.data import uniq_stable
124 from IPython.utils.data import uniq_stable
125 from IPython.utils.terminal import get_terminal_size
125 from IPython.utils.terminal import get_terminal_size
126 from logging import info, error
126 from logging import info, error
127
127
128 import IPython.utils.colorable as colorable
128 import IPython.utils.colorable as colorable
129
129
130 # Globals
130 # Globals
131 # amount of space to put line numbers before verbose tracebacks
131 # amount of space to put line numbers before verbose tracebacks
132 INDENT_SIZE = 8
132 INDENT_SIZE = 8
133
133
134 # Default color scheme. This is used, for example, by the traceback
134 # Default color scheme. This is used, for example, by the traceback
135 # formatter. When running in an actual IPython instance, the user's rc.colors
135 # formatter. When running in an actual IPython instance, the user's rc.colors
136 # value is used, but having a module global makes this functionality available
136 # value is used, but having a module global makes this functionality available
137 # to users of ultratb who are NOT running inside ipython.
137 # to users of ultratb who are NOT running inside ipython.
138 DEFAULT_SCHEME = 'NoColor'
138 DEFAULT_SCHEME = 'NoColor'
139
139
140 # ---------------------------------------------------------------------------
140 # ---------------------------------------------------------------------------
141 # Code begins
141 # Code begins
142
142
143 # Utility functions
143 # Utility functions
144 def inspect_error():
144 def inspect_error():
145 """Print a message about internal inspect errors.
145 """Print a message about internal inspect errors.
146
146
147 These are unfortunately quite common."""
147 These are unfortunately quite common."""
148
148
149 error('Internal Python error in the inspect module.\n'
149 error('Internal Python error in the inspect module.\n'
150 'Below is the traceback from this internal error.\n')
150 'Below is the traceback from this internal error.\n')
151
151
152
152
153 # This function is a monkeypatch we apply to the Python inspect module. We have
153 # This function is a monkeypatch we apply to the Python inspect module. We have
154 # now found when it's needed (see discussion on issue gh-1456), and we have a
154 # now found when it's needed (see discussion on issue gh-1456), and we have a
155 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
155 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
156 # the monkeypatch is not applied. TK, Aug 2012.
156 # the monkeypatch is not applied. TK, Aug 2012.
157 def findsource(object):
157 def findsource(object):
158 """Return the entire source file and starting line number for an object.
158 """Return the entire source file and starting line number for an object.
159
159
160 The argument may be a module, class, method, function, traceback, frame,
160 The argument may be a module, class, method, function, traceback, frame,
161 or code object. The source code is returned as a list of all the lines
161 or code object. The source code is returned as a list of all the lines
162 in the file and the line number indexes a line in that list. An IOError
162 in the file and the line number indexes a line in that list. An IOError
163 is raised if the source code cannot be retrieved.
163 is raised if the source code cannot be retrieved.
164
164
165 FIXED version with which we monkeypatch the stdlib to work around a bug."""
165 FIXED version with which we monkeypatch the stdlib to work around a bug."""
166
166
167 file = getsourcefile(object) or getfile(object)
167 file = getsourcefile(object) or getfile(object)
168 # If the object is a frame, then trying to get the globals dict from its
168 # If the object is a frame, then trying to get the globals dict from its
169 # module won't work. Instead, the frame object itself has the globals
169 # module won't work. Instead, the frame object itself has the globals
170 # dictionary.
170 # dictionary.
171 globals_dict = None
171 globals_dict = None
172 if inspect.isframe(object):
172 if inspect.isframe(object):
173 # XXX: can this ever be false?
173 # XXX: can this ever be false?
174 globals_dict = object.f_globals
174 globals_dict = object.f_globals
175 else:
175 else:
176 module = getmodule(object, file)
176 module = getmodule(object, file)
177 if module:
177 if module:
178 globals_dict = module.__dict__
178 globals_dict = module.__dict__
179 lines = linecache.getlines(file, globals_dict)
179 lines = linecache.getlines(file, globals_dict)
180 if not lines:
180 if not lines:
181 raise IOError('could not get source code')
181 raise IOError('could not get source code')
182
182
183 if ismodule(object):
183 if ismodule(object):
184 return lines, 0
184 return lines, 0
185
185
186 if isclass(object):
186 if isclass(object):
187 name = object.__name__
187 name = object.__name__
188 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
188 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
189 # make some effort to find the best matching class definition:
189 # make some effort to find the best matching class definition:
190 # use the one with the least indentation, which is the one
190 # use the one with the least indentation, which is the one
191 # that's most probably not inside a function definition.
191 # that's most probably not inside a function definition.
192 candidates = []
192 candidates = []
193 for i in range(len(lines)):
193 for i in range(len(lines)):
194 match = pat.match(lines[i])
194 match = pat.match(lines[i])
195 if match:
195 if match:
196 # if it's at toplevel, it's already the best one
196 # if it's at toplevel, it's already the best one
197 if lines[i][0] == 'c':
197 if lines[i][0] == 'c':
198 return lines, i
198 return lines, i
199 # else add whitespace to candidate list
199 # else add whitespace to candidate list
200 candidates.append((match.group(1), i))
200 candidates.append((match.group(1), i))
201 if candidates:
201 if candidates:
202 # this will sort by whitespace, and by line number,
202 # this will sort by whitespace, and by line number,
203 # less whitespace first
203 # less whitespace first
204 candidates.sort()
204 candidates.sort()
205 return lines, candidates[0][1]
205 return lines, candidates[0][1]
206 else:
206 else:
207 raise IOError('could not find class definition')
207 raise IOError('could not find class definition')
208
208
209 if ismethod(object):
209 if ismethod(object):
210 object = object.__func__
210 object = object.__func__
211 if isfunction(object):
211 if isfunction(object):
212 object = object.__code__
212 object = object.__code__
213 if istraceback(object):
213 if istraceback(object):
214 object = object.tb_frame
214 object = object.tb_frame
215 if isframe(object):
215 if isframe(object):
216 object = object.f_code
216 object = object.f_code
217 if iscode(object):
217 if iscode(object):
218 if not hasattr(object, 'co_firstlineno'):
218 if not hasattr(object, 'co_firstlineno'):
219 raise IOError('could not find function definition')
219 raise IOError('could not find function definition')
220 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
220 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
221 pmatch = pat.match
221 pmatch = pat.match
222 # fperez - fix: sometimes, co_firstlineno can give a number larger than
222 # fperez - fix: sometimes, co_firstlineno can give a number larger than
223 # the length of lines, which causes an error. Safeguard against that.
223 # the length of lines, which causes an error. Safeguard against that.
224 lnum = min(object.co_firstlineno, len(lines)) - 1
224 lnum = min(object.co_firstlineno, len(lines)) - 1
225 while lnum > 0:
225 while lnum > 0:
226 if pmatch(lines[lnum]):
226 if pmatch(lines[lnum]):
227 break
227 break
228 lnum -= 1
228 lnum -= 1
229
229
230 return lines, lnum
230 return lines, lnum
231 raise IOError('could not find code object')
231 raise IOError('could not find code object')
232
232
233
233
234 # This is a patched version of inspect.getargs that applies the (unmerged)
234 # This is a patched version of inspect.getargs that applies the (unmerged)
235 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
235 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
236 # https://github.com/ipython/ipython/issues/8205 and
236 # https://github.com/ipython/ipython/issues/8205 and
237 # https://github.com/ipython/ipython/issues/8293
237 # https://github.com/ipython/ipython/issues/8293
238 def getargs(co):
238 def getargs(co):
239 """Get information about the arguments accepted by a code object.
239 """Get information about the arguments accepted by a code object.
240
240
241 Three things are returned: (args, varargs, varkw), where 'args' is
241 Three things are returned: (args, varargs, varkw), where 'args' is
242 a list of argument names (possibly containing nested lists), and
242 a list of argument names (possibly containing nested lists), and
243 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
243 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
244 if not iscode(co):
244 if not iscode(co):
245 raise TypeError('{!r} is not a code object'.format(co))
245 raise TypeError('{!r} is not a code object'.format(co))
246
246
247 nargs = co.co_argcount
247 nargs = co.co_argcount
248 names = co.co_varnames
248 names = co.co_varnames
249 args = list(names[:nargs])
249 args = list(names[:nargs])
250 step = 0
250 step = 0
251
251
252 # The following acrobatics are for anonymous (tuple) arguments.
252 # The following acrobatics are for anonymous (tuple) arguments.
253 for i in range(nargs):
253 for i in range(nargs):
254 if args[i][:1] in ('', '.'):
254 if args[i][:1] in ('', '.'):
255 stack, remain, count = [], [], []
255 stack, remain, count = [], [], []
256 while step < len(co.co_code):
256 while step < len(co.co_code):
257 op = ord(co.co_code[step])
257 op = ord(co.co_code[step])
258 step = step + 1
258 step = step + 1
259 if op >= dis.HAVE_ARGUMENT:
259 if op >= dis.HAVE_ARGUMENT:
260 opname = dis.opname[op]
260 opname = dis.opname[op]
261 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
261 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
262 step = step + 2
262 step = step + 2
263 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
263 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
264 remain.append(value)
264 remain.append(value)
265 count.append(value)
265 count.append(value)
266 elif opname in ('STORE_FAST', 'STORE_DEREF'):
266 elif opname in ('STORE_FAST', 'STORE_DEREF'):
267 if op in dis.haslocal:
267 if op in dis.haslocal:
268 stack.append(co.co_varnames[value])
268 stack.append(co.co_varnames[value])
269 elif op in dis.hasfree:
269 elif op in dis.hasfree:
270 stack.append((co.co_cellvars + co.co_freevars)[value])
270 stack.append((co.co_cellvars + co.co_freevars)[value])
271 # Special case for sublists of length 1: def foo((bar))
271 # Special case for sublists of length 1: def foo((bar))
272 # doesn't generate the UNPACK_TUPLE bytecode, so if
272 # doesn't generate the UNPACK_TUPLE bytecode, so if
273 # `remain` is empty here, we have such a sublist.
273 # `remain` is empty here, we have such a sublist.
274 if not remain:
274 if not remain:
275 stack[0] = [stack[0]]
275 stack[0] = [stack[0]]
276 break
276 break
277 else:
277 else:
278 remain[-1] = remain[-1] - 1
278 remain[-1] = remain[-1] - 1
279 while remain[-1] == 0:
279 while remain[-1] == 0:
280 remain.pop()
280 remain.pop()
281 size = count.pop()
281 size = count.pop()
282 stack[-size:] = [stack[-size:]]
282 stack[-size:] = [stack[-size:]]
283 if not remain:
283 if not remain:
284 break
284 break
285 remain[-1] = remain[-1] - 1
285 remain[-1] = remain[-1] - 1
286 if not remain:
286 if not remain:
287 break
287 break
288 args[i] = stack[0]
288 args[i] = stack[0]
289
289
290 varargs = None
290 varargs = None
291 if co.co_flags & inspect.CO_VARARGS:
291 if co.co_flags & inspect.CO_VARARGS:
292 varargs = co.co_varnames[nargs]
292 varargs = co.co_varnames[nargs]
293 nargs = nargs + 1
293 nargs = nargs + 1
294 varkw = None
294 varkw = None
295 if co.co_flags & inspect.CO_VARKEYWORDS:
295 if co.co_flags & inspect.CO_VARKEYWORDS:
296 varkw = co.co_varnames[nargs]
296 varkw = co.co_varnames[nargs]
297 return inspect.Arguments(args, varargs, varkw)
297 return inspect.Arguments(args, varargs, varkw)
298
298
299
299
300 # Monkeypatch inspect to apply our bugfix.
300 # Monkeypatch inspect to apply our bugfix.
301 def with_patch_inspect(f):
301 def with_patch_inspect(f):
302 """decorator for monkeypatching inspect.findsource"""
302 """decorator for monkeypatching inspect.findsource"""
303
303
304 def wrapped(*args, **kwargs):
304 def wrapped(*args, **kwargs):
305 save_findsource = inspect.findsource
305 save_findsource = inspect.findsource
306 save_getargs = inspect.getargs
306 save_getargs = inspect.getargs
307 inspect.findsource = findsource
307 inspect.findsource = findsource
308 inspect.getargs = getargs
308 inspect.getargs = getargs
309 try:
309 try:
310 return f(*args, **kwargs)
310 return f(*args, **kwargs)
311 finally:
311 finally:
312 inspect.findsource = save_findsource
312 inspect.findsource = save_findsource
313 inspect.getargs = save_getargs
313 inspect.getargs = save_getargs
314
314
315 return wrapped
315 return wrapped
316
316
317
317
318 if py3compat.PY3:
318 if py3compat.PY3:
319 fixed_getargvalues = inspect.getargvalues
319 fixed_getargvalues = inspect.getargvalues
320 else:
320 else:
321 # Fixes for https://github.com/ipython/ipython/issues/8293
321 # Fixes for https://github.com/ipython/ipython/issues/8293
322 # and https://github.com/ipython/ipython/issues/8205.
322 # and https://github.com/ipython/ipython/issues/8205.
323 # The relevant bug is caused by failure to correctly handle anonymous tuple
323 # The relevant bug is caused by failure to correctly handle anonymous tuple
324 # unpacking, which only exists in Python 2.
324 # unpacking, which only exists in Python 2.
325 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
325 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
326
326
327
327
328 def fix_frame_records_filenames(records):
328 def fix_frame_records_filenames(records):
329 """Try to fix the filenames in each record from inspect.getinnerframes().
329 """Try to fix the filenames in each record from inspect.getinnerframes().
330
330
331 Particularly, modules loaded from within zip files have useless filenames
331 Particularly, modules loaded from within zip files have useless filenames
332 attached to their code object, and inspect.getinnerframes() just uses it.
332 attached to their code object, and inspect.getinnerframes() just uses it.
333 """
333 """
334 fixed_records = []
334 fixed_records = []
335 for frame, filename, line_no, func_name, lines, index in records:
335 for frame, filename, line_no, func_name, lines, index in records:
336 # Look inside the frame's globals dictionary for __file__,
336 # Look inside the frame's globals dictionary for __file__,
337 # which should be better. However, keep Cython filenames since
337 # which should be better. However, keep Cython filenames since
338 # we prefer the source filenames over the compiled .so file.
338 # we prefer the source filenames over the compiled .so file.
339 filename = py3compat.cast_unicode_py2(filename, "utf-8")
339 filename = py3compat.cast_unicode_py2(filename, "utf-8")
340 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
340 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
341 better_fn = frame.f_globals.get('__file__', None)
341 better_fn = frame.f_globals.get('__file__', None)
342 if isinstance(better_fn, str):
342 if isinstance(better_fn, str):
343 # Check the type just in case someone did something weird with
343 # Check the type just in case someone did something weird with
344 # __file__. It might also be None if the error occurred during
344 # __file__. It might also be None if the error occurred during
345 # import.
345 # import.
346 filename = better_fn
346 filename = better_fn
347 fixed_records.append((frame, filename, line_no, func_name, lines, index))
347 fixed_records.append((frame, filename, line_no, func_name, lines, index))
348 return fixed_records
348 return fixed_records
349
349
350
350
351 @with_patch_inspect
351 @with_patch_inspect
352 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
352 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
353 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
353 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
354
354
355 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
355 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
356 # If the error is at the console, don't build any context, since it would
356 # If the error is at the console, don't build any context, since it would
357 # otherwise produce 5 blank lines printed out (there is no file at the
357 # otherwise produce 5 blank lines printed out (there is no file at the
358 # console)
358 # console)
359 rec_check = records[tb_offset:]
359 rec_check = records[tb_offset:]
360 try:
360 try:
361 rname = rec_check[0][1]
361 rname = rec_check[0][1]
362 if rname == '<ipython console>' or rname.endswith('<string>'):
362 if rname == '<ipython console>' or rname.endswith('<string>'):
363 return rec_check
363 return rec_check
364 except IndexError:
364 except IndexError:
365 pass
365 pass
366
366
367 aux = traceback.extract_tb(etb)
367 aux = traceback.extract_tb(etb)
368 assert len(records) == len(aux)
368 assert len(records) == len(aux)
369 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
369 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
370 maybeStart = lnum - 1 - context // 2
370 maybeStart = lnum - 1 - context // 2
371 start = max(maybeStart, 0)
371 start = max(maybeStart, 0)
372 end = start + context
372 end = start + context
373 lines = ulinecache.getlines(file)[start:end]
373 lines = ulinecache.getlines(file)[start:end]
374 buf = list(records[i])
374 buf = list(records[i])
375 buf[LNUM_POS] = lnum
375 buf[LNUM_POS] = lnum
376 buf[INDEX_POS] = lnum - 1 - start
376 buf[INDEX_POS] = lnum - 1 - start
377 buf[LINES_POS] = lines
377 buf[LINES_POS] = lines
378 records[i] = tuple(buf)
378 records[i] = tuple(buf)
379 return records[tb_offset:]
379 return records[tb_offset:]
380
380
381 # Helper function -- largely belongs to VerboseTB, but we need the same
381 # Helper function -- largely belongs to VerboseTB, but we need the same
382 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
382 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
383 # can be recognized properly by ipython.el's py-traceback-line-re
383 # can be recognized properly by ipython.el's py-traceback-line-re
384 # (SyntaxErrors have to be treated specially because they have no traceback)
384 # (SyntaxErrors have to be treated specially because they have no traceback)
385
385
386
386
387 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
387 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
388 numbers_width = INDENT_SIZE - 1
388 numbers_width = INDENT_SIZE - 1
389 res = []
389 res = []
390 i = lnum - index
390 i = lnum - index
391
391
392 for line in lines:
392 for line in lines:
393 line = py3compat.cast_unicode(line)
393 line = py3compat.cast_unicode(line)
394
394
395 new_line, err = _line_format(line, 'str')
395 new_line, err = _line_format(line, 'str')
396 if not err: line = new_line
396 if not err: line = new_line
397
397
398 if i == lnum:
398 if i == lnum:
399 # This is the line with the error
399 # This is the line with the error
400 pad = numbers_width - len(str(i))
400 pad = numbers_width - len(str(i))
401 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
401 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
402 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
402 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
403 Colors.line, line, Colors.Normal)
403 Colors.line, line, Colors.Normal)
404 else:
404 else:
405 num = '%*s' % (numbers_width, i)
405 num = '%*s' % (numbers_width, i)
406 line = '%s%s%s %s' % (Colors.lineno, num,
406 line = '%s%s%s %s' % (Colors.lineno, num,
407 Colors.Normal, line)
407 Colors.Normal, line)
408
408
409 res.append(line)
409 res.append(line)
410 if lvals and i == lnum:
410 if lvals and i == lnum:
411 res.append(lvals + '\n')
411 res.append(lvals + '\n')
412 i = i + 1
412 i = i + 1
413 return res
413 return res
414
414
415 def is_recursion_error(etype, value, records):
415 def is_recursion_error(etype, value, records):
416 try:
416 try:
417 # RecursionError is new in Python 3.5
417 # RecursionError is new in Python 3.5
418 recursion_error_type = RecursionError
418 recursion_error_type = RecursionError
419 except NameError:
419 except NameError:
420 recursion_error_type = RuntimeError
420 recursion_error_type = RuntimeError
421
421
422 # The default recursion limit is 1000, but some of that will be taken up
422 # The default recursion limit is 1000, but some of that will be taken up
423 # by stack frames in IPython itself. >500 frames probably indicates
423 # by stack frames in IPython itself. >500 frames probably indicates
424 # a recursion error.
424 # a recursion error.
425 return (etype is recursion_error_type) \
425 return (etype is recursion_error_type) \
426 and "recursion" in str(value).lower() \
426 and "recursion" in str(value).lower() \
427 and len(records) > 500
427 and len(records) > 500
428
428
429 def find_recursion(etype, value, records):
429 def find_recursion(etype, value, records):
430 """Identify the repeating stack frames from a RecursionError traceback
430 """Identify the repeating stack frames from a RecursionError traceback
431
431
432 'records' is a list as returned by VerboseTB.get_records()
432 'records' is a list as returned by VerboseTB.get_records()
433
433
434 Returns (last_unique, repeat_length)
434 Returns (last_unique, repeat_length)
435 """
435 """
436 # This involves a bit of guesswork - we want to show enough of the traceback
436 # This involves a bit of guesswork - we want to show enough of the traceback
437 # to indicate where the recursion is occurring. We guess that the innermost
437 # to indicate where the recursion is occurring. We guess that the innermost
438 # quarter of the traceback (250 frames by default) is repeats, and find the
438 # quarter of the traceback (250 frames by default) is repeats, and find the
439 # first frame (from in to out) that looks different.
439 # first frame (from in to out) that looks different.
440 if not is_recursion_error(etype, value, records):
440 if not is_recursion_error(etype, value, records):
441 return len(records), 0
441 return len(records), 0
442
442
443 # Select filename, lineno, func_name to track frames with
443 # Select filename, lineno, func_name to track frames with
444 records = [r[1:4] for r in records]
444 records = [r[1:4] for r in records]
445 inner_frames = records[-(len(records)//4):]
445 inner_frames = records[-(len(records)//4):]
446 frames_repeated = set(inner_frames)
446 frames_repeated = set(inner_frames)
447
447
448 last_seen_at = {}
448 last_seen_at = {}
449 longest_repeat = 0
449 longest_repeat = 0
450 i = len(records)
450 i = len(records)
451 for frame in reversed(records):
451 for frame in reversed(records):
452 i -= 1
452 i -= 1
453 if frame not in frames_repeated:
453 if frame not in frames_repeated:
454 last_unique = i
454 last_unique = i
455 break
455 break
456
456
457 if frame in last_seen_at:
457 if frame in last_seen_at:
458 distance = last_seen_at[frame] - i
458 distance = last_seen_at[frame] - i
459 longest_repeat = max(longest_repeat, distance)
459 longest_repeat = max(longest_repeat, distance)
460
460
461 last_seen_at[frame] = i
461 last_seen_at[frame] = i
462 else:
462 else:
463 last_unique = 0 # The whole traceback was recursion
463 last_unique = 0 # The whole traceback was recursion
464
464
465 return last_unique, longest_repeat
465 return last_unique, longest_repeat
466
466
467 #---------------------------------------------------------------------------
467 #---------------------------------------------------------------------------
468 # Module classes
468 # Module classes
469 class TBTools(colorable.Colorable):
469 class TBTools(colorable.Colorable):
470 """Basic tools used by all traceback printer classes."""
470 """Basic tools used by all traceback printer classes."""
471
471
472 # Number of frames to skip when reporting tracebacks
472 # Number of frames to skip when reporting tracebacks
473 tb_offset = 0
473 tb_offset = 0
474
474
475 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
475 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
476 # Whether to call the interactive pdb debugger after printing
476 # Whether to call the interactive pdb debugger after printing
477 # tracebacks or not
477 # tracebacks or not
478 super(TBTools, self).__init__(parent=parent, config=config)
478 super(TBTools, self).__init__(parent=parent, config=config)
479 self.call_pdb = call_pdb
479 self.call_pdb = call_pdb
480
480
481 # Output stream to write to. Note that we store the original value in
481 # Output stream to write to. Note that we store the original value in
482 # a private attribute and then make the public ostream a property, so
482 # a private attribute and then make the public ostream a property, so
483 # that we can delay accessing sys.stdout until runtime. The way
483 # that we can delay accessing sys.stdout until runtime. The way
484 # things are written now, the sys.stdout object is dynamically managed
484 # things are written now, the sys.stdout object is dynamically managed
485 # so a reference to it should NEVER be stored statically. This
485 # so a reference to it should NEVER be stored statically. This
486 # property approach confines this detail to a single location, and all
486 # property approach confines this detail to a single location, and all
487 # subclasses can simply access self.ostream for writing.
487 # subclasses can simply access self.ostream for writing.
488 self._ostream = ostream
488 self._ostream = ostream
489
489
490 # Create color table
490 # Create color table
491 self.color_scheme_table = exception_colors()
491 self.color_scheme_table = exception_colors()
492
492
493 self.set_colors(color_scheme)
493 self.set_colors(color_scheme)
494 self.old_scheme = color_scheme # save initial value for toggles
494 self.old_scheme = color_scheme # save initial value for toggles
495
495
496 if call_pdb:
496 if call_pdb:
497 self.pdb = debugger.Pdb()
497 self.pdb = debugger.Pdb()
498 else:
498 else:
499 self.pdb = None
499 self.pdb = None
500
500
501 def _get_ostream(self):
501 def _get_ostream(self):
502 """Output stream that exceptions are written to.
502 """Output stream that exceptions are written to.
503
503
504 Valid values are:
504 Valid values are:
505
505
506 - None: the default, which means that IPython will dynamically resolve
506 - None: the default, which means that IPython will dynamically resolve
507 to sys.stdout. This ensures compatibility with most tools, including
507 to sys.stdout. This ensures compatibility with most tools, including
508 Windows (where plain stdout doesn't recognize ANSI escapes).
508 Windows (where plain stdout doesn't recognize ANSI escapes).
509
509
510 - Any object with 'write' and 'flush' attributes.
510 - Any object with 'write' and 'flush' attributes.
511 """
511 """
512 return sys.stdout if self._ostream is None else self._ostream
512 return sys.stdout if self._ostream is None else self._ostream
513
513
514 def _set_ostream(self, val):
514 def _set_ostream(self, val):
515 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
515 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
516 self._ostream = val
516 self._ostream = val
517
517
518 ostream = property(_get_ostream, _set_ostream)
518 ostream = property(_get_ostream, _set_ostream)
519
519
520 def set_colors(self, *args, **kw):
520 def set_colors(self, *args, **kw):
521 """Shorthand access to the color table scheme selector method."""
521 """Shorthand access to the color table scheme selector method."""
522
522
523 # Set own color table
523 # Set own color table
524 self.color_scheme_table.set_active_scheme(*args, **kw)
524 self.color_scheme_table.set_active_scheme(*args, **kw)
525 # for convenience, set Colors to the active scheme
525 # for convenience, set Colors to the active scheme
526 self.Colors = self.color_scheme_table.active_colors
526 self.Colors = self.color_scheme_table.active_colors
527 # Also set colors of debugger
527 # Also set colors of debugger
528 if hasattr(self, 'pdb') and self.pdb is not None:
528 if hasattr(self, 'pdb') and self.pdb is not None:
529 self.pdb.set_colors(*args, **kw)
529 self.pdb.set_colors(*args, **kw)
530
530
531 def color_toggle(self):
531 def color_toggle(self):
532 """Toggle between the currently active color scheme and NoColor."""
532 """Toggle between the currently active color scheme and NoColor."""
533
533
534 if self.color_scheme_table.active_scheme_name == 'NoColor':
534 if self.color_scheme_table.active_scheme_name == 'NoColor':
535 self.color_scheme_table.set_active_scheme(self.old_scheme)
535 self.color_scheme_table.set_active_scheme(self.old_scheme)
536 self.Colors = self.color_scheme_table.active_colors
536 self.Colors = self.color_scheme_table.active_colors
537 else:
537 else:
538 self.old_scheme = self.color_scheme_table.active_scheme_name
538 self.old_scheme = self.color_scheme_table.active_scheme_name
539 self.color_scheme_table.set_active_scheme('NoColor')
539 self.color_scheme_table.set_active_scheme('NoColor')
540 self.Colors = self.color_scheme_table.active_colors
540 self.Colors = self.color_scheme_table.active_colors
541
541
542 def stb2text(self, stb):
542 def stb2text(self, stb):
543 """Convert a structured traceback (a list) to a string."""
543 """Convert a structured traceback (a list) to a string."""
544 return '\n'.join(stb)
544 return '\n'.join(stb)
545
545
546 def text(self, etype, value, tb, tb_offset=None, context=5):
546 def text(self, etype, value, tb, tb_offset=None, context=5):
547 """Return formatted traceback.
547 """Return formatted traceback.
548
548
549 Subclasses may override this if they add extra arguments.
549 Subclasses may override this if they add extra arguments.
550 """
550 """
551 tb_list = self.structured_traceback(etype, value, tb,
551 tb_list = self.structured_traceback(etype, value, tb,
552 tb_offset, context)
552 tb_offset, context)
553 return self.stb2text(tb_list)
553 return self.stb2text(tb_list)
554
554
555 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
555 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
556 context=5, mode=None):
556 context=5, mode=None):
557 """Return a list of traceback frames.
557 """Return a list of traceback frames.
558
558
559 Must be implemented by each class.
559 Must be implemented by each class.
560 """
560 """
561 raise NotImplementedError()
561 raise NotImplementedError()
562
562
563
563
564 #---------------------------------------------------------------------------
564 #---------------------------------------------------------------------------
565 class ListTB(TBTools):
565 class ListTB(TBTools):
566 """Print traceback information from a traceback list, with optional color.
566 """Print traceback information from a traceback list, with optional color.
567
567
568 Calling requires 3 arguments: (etype, evalue, elist)
568 Calling requires 3 arguments: (etype, evalue, elist)
569 as would be obtained by::
569 as would be obtained by::
570
570
571 etype, evalue, tb = sys.exc_info()
571 etype, evalue, tb = sys.exc_info()
572 if tb:
572 if tb:
573 elist = traceback.extract_tb(tb)
573 elist = traceback.extract_tb(tb)
574 else:
574 else:
575 elist = None
575 elist = None
576
576
577 It can thus be used by programs which need to process the traceback before
577 It can thus be used by programs which need to process the traceback before
578 printing (such as console replacements based on the code module from the
578 printing (such as console replacements based on the code module from the
579 standard library).
579 standard library).
580
580
581 Because they are meant to be called without a full traceback (only a
581 Because they are meant to be called without a full traceback (only a
582 list), instances of this class can't call the interactive pdb debugger."""
582 list), instances of this class can't call the interactive pdb debugger."""
583
583
584 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
584 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
585 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
585 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
586 ostream=ostream, parent=parent,config=config)
586 ostream=ostream, parent=parent,config=config)
587
587
588 def __call__(self, etype, value, elist):
588 def __call__(self, etype, value, elist):
589 self.ostream.flush()
589 self.ostream.flush()
590 self.ostream.write(self.text(etype, value, elist))
590 self.ostream.write(self.text(etype, value, elist))
591 self.ostream.write('\n')
591 self.ostream.write('\n')
592
592
593 def structured_traceback(self, etype, value, elist, tb_offset=None,
593 def structured_traceback(self, etype, value, elist, tb_offset=None,
594 context=5):
594 context=5):
595 """Return a color formatted string with the traceback info.
595 """Return a color formatted string with the traceback info.
596
596
597 Parameters
597 Parameters
598 ----------
598 ----------
599 etype : exception type
599 etype : exception type
600 Type of the exception raised.
600 Type of the exception raised.
601
601
602 value : object
602 value : object
603 Data stored in the exception
603 Data stored in the exception
604
604
605 elist : list
605 elist : list
606 List of frames, see class docstring for details.
606 List of frames, see class docstring for details.
607
607
608 tb_offset : int, optional
608 tb_offset : int, optional
609 Number of frames in the traceback to skip. If not given, the
609 Number of frames in the traceback to skip. If not given, the
610 instance value is used (set in constructor).
610 instance value is used (set in constructor).
611
611
612 context : int, optional
612 context : int, optional
613 Number of lines of context information to print.
613 Number of lines of context information to print.
614
614
615 Returns
615 Returns
616 -------
616 -------
617 String with formatted exception.
617 String with formatted exception.
618 """
618 """
619 tb_offset = self.tb_offset if tb_offset is None else tb_offset
619 tb_offset = self.tb_offset if tb_offset is None else tb_offset
620 Colors = self.Colors
620 Colors = self.Colors
621 out_list = []
621 out_list = []
622 if elist:
622 if elist:
623
623
624 if tb_offset and len(elist) > tb_offset:
624 if tb_offset and len(elist) > tb_offset:
625 elist = elist[tb_offset:]
625 elist = elist[tb_offset:]
626
626
627 out_list.append('Traceback %s(most recent call last)%s:' %
627 out_list.append('Traceback %s(most recent call last)%s:' %
628 (Colors.normalEm, Colors.Normal) + '\n')
628 (Colors.normalEm, Colors.Normal) + '\n')
629 out_list.extend(self._format_list(elist))
629 out_list.extend(self._format_list(elist))
630 # The exception info should be a single entry in the list.
630 # The exception info should be a single entry in the list.
631 lines = ''.join(self._format_exception_only(etype, value))
631 lines = ''.join(self._format_exception_only(etype, value))
632 out_list.append(lines)
632 out_list.append(lines)
633
633
634 # Note: this code originally read:
634 # Note: this code originally read:
635
635
636 ## for line in lines[:-1]:
636 ## for line in lines[:-1]:
637 ## out_list.append(" "+line)
637 ## out_list.append(" "+line)
638 ## out_list.append(lines[-1])
638 ## out_list.append(lines[-1])
639
639
640 # This means it was indenting everything but the last line by a little
640 # This means it was indenting everything but the last line by a little
641 # bit. I've disabled this for now, but if we see ugliness somewhere we
641 # bit. I've disabled this for now, but if we see ugliness somewhere we
642 # can restore it.
642 # can restore it.
643
643
644 return out_list
644 return out_list
645
645
646 def _format_list(self, extracted_list):
646 def _format_list(self, extracted_list):
647 """Format a list of traceback entry tuples for printing.
647 """Format a list of traceback entry tuples for printing.
648
648
649 Given a list of tuples as returned by extract_tb() or
649 Given a list of tuples as returned by extract_tb() or
650 extract_stack(), return a list of strings ready for printing.
650 extract_stack(), return a list of strings ready for printing.
651 Each string in the resulting list corresponds to the item with the
651 Each string in the resulting list corresponds to the item with the
652 same index in the argument list. Each string ends in a newline;
652 same index in the argument list. Each string ends in a newline;
653 the strings may contain internal newlines as well, for those items
653 the strings may contain internal newlines as well, for those items
654 whose source text line is not None.
654 whose source text line is not None.
655
655
656 Lifted almost verbatim from traceback.py
656 Lifted almost verbatim from traceback.py
657 """
657 """
658
658
659 Colors = self.Colors
659 Colors = self.Colors
660 list = []
660 list = []
661 for filename, lineno, name, line in extracted_list[:-1]:
661 for filename, lineno, name, line in extracted_list[:-1]:
662 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
662 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
663 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
663 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
664 Colors.lineno, lineno, Colors.Normal,
664 Colors.lineno, lineno, Colors.Normal,
665 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
665 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
666 if line:
666 if line:
667 item += ' %s\n' % line.strip()
667 item += ' %s\n' % line.strip()
668 list.append(item)
668 list.append(item)
669 # Emphasize the last entry
669 # Emphasize the last entry
670 filename, lineno, name, line = extracted_list[-1]
670 filename, lineno, name, line = extracted_list[-1]
671 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
671 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
672 (Colors.normalEm,
672 (Colors.normalEm,
673 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
673 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
674 Colors.linenoEm, lineno, Colors.normalEm,
674 Colors.linenoEm, lineno, Colors.normalEm,
675 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
675 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
676 Colors.Normal)
676 Colors.Normal)
677 if line:
677 if line:
678 item += '%s %s%s\n' % (Colors.line, line.strip(),
678 item += '%s %s%s\n' % (Colors.line, line.strip(),
679 Colors.Normal)
679 Colors.Normal)
680 list.append(item)
680 list.append(item)
681 return list
681 return list
682
682
683 def _format_exception_only(self, etype, value):
683 def _format_exception_only(self, etype, value):
684 """Format the exception part of a traceback.
684 """Format the exception part of a traceback.
685
685
686 The arguments are the exception type and value such as given by
686 The arguments are the exception type and value such as given by
687 sys.exc_info()[:2]. The return value is a list of strings, each ending
687 sys.exc_info()[:2]. The return value is a list of strings, each ending
688 in a newline. Normally, the list contains a single string; however,
688 in a newline. Normally, the list contains a single string; however,
689 for SyntaxError exceptions, it contains several lines that (when
689 for SyntaxError exceptions, it contains several lines that (when
690 printed) display detailed information about where the syntax error
690 printed) display detailed information about where the syntax error
691 occurred. The message indicating which exception occurred is the
691 occurred. The message indicating which exception occurred is the
692 always last string in the list.
692 always last string in the list.
693
693
694 Also lifted nearly verbatim from traceback.py
694 Also lifted nearly verbatim from traceback.py
695 """
695 """
696 have_filedata = False
696 have_filedata = False
697 Colors = self.Colors
697 Colors = self.Colors
698 list = []
698 list = []
699 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
699 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
700 if value is None:
700 if value is None:
701 # Not sure if this can still happen in Python 2.6 and above
701 # Not sure if this can still happen in Python 2.6 and above
702 list.append(stype + '\n')
702 list.append(stype + '\n')
703 else:
703 else:
704 if issubclass(etype, SyntaxError):
704 if issubclass(etype, SyntaxError):
705 have_filedata = True
705 have_filedata = True
706 if not value.filename: value.filename = "<string>"
706 if not value.filename: value.filename = "<string>"
707 if value.lineno:
707 if value.lineno:
708 lineno = value.lineno
708 lineno = value.lineno
709 textline = ulinecache.getline(value.filename, value.lineno)
709 textline = ulinecache.getline(value.filename, value.lineno)
710 else:
710 else:
711 lineno = 'unknown'
711 lineno = 'unknown'
712 textline = ''
712 textline = ''
713 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
713 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
714 (Colors.normalEm,
714 (Colors.normalEm,
715 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
715 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
716 Colors.linenoEm, lineno, Colors.Normal ))
716 Colors.linenoEm, lineno, Colors.Normal ))
717 if textline == '':
717 if textline == '':
718 textline = py3compat.cast_unicode(value.text, "utf-8")
718 textline = py3compat.cast_unicode(value.text, "utf-8")
719
719
720 if textline is not None:
720 if textline is not None:
721 i = 0
721 i = 0
722 while i < len(textline) and textline[i].isspace():
722 while i < len(textline) and textline[i].isspace():
723 i += 1
723 i += 1
724 list.append('%s %s%s\n' % (Colors.line,
724 list.append('%s %s%s\n' % (Colors.line,
725 textline.strip(),
725 textline.strip(),
726 Colors.Normal))
726 Colors.Normal))
727 if value.offset is not None:
727 if value.offset is not None:
728 s = ' '
728 s = ' '
729 for c in textline[i:value.offset - 1]:
729 for c in textline[i:value.offset - 1]:
730 if c.isspace():
730 if c.isspace():
731 s += c
731 s += c
732 else:
732 else:
733 s += ' '
733 s += ' '
734 list.append('%s%s^%s\n' % (Colors.caret, s,
734 list.append('%s%s^%s\n' % (Colors.caret, s,
735 Colors.Normal))
735 Colors.Normal))
736
736
737 try:
737 try:
738 s = value.msg
738 s = value.msg
739 except Exception:
739 except Exception:
740 s = self._some_str(value)
740 s = self._some_str(value)
741 if s:
741 if s:
742 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
742 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
743 Colors.Normal, s))
743 Colors.Normal, s))
744 else:
744 else:
745 list.append('%s\n' % stype)
745 list.append('%s\n' % stype)
746
746
747 # sync with user hooks
747 # sync with user hooks
748 if have_filedata:
748 if have_filedata:
749 ipinst = get_ipython()
749 ipinst = get_ipython()
750 if ipinst is not None:
750 if ipinst is not None:
751 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
751 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
752
752
753 return list
753 return list
754
754
755 def get_exception_only(self, etype, value):
755 def get_exception_only(self, etype, value):
756 """Only print the exception type and message, without a traceback.
756 """Only print the exception type and message, without a traceback.
757
757
758 Parameters
758 Parameters
759 ----------
759 ----------
760 etype : exception type
760 etype : exception type
761 value : exception value
761 value : exception value
762 """
762 """
763 return ListTB.structured_traceback(self, etype, value, [])
763 return ListTB.structured_traceback(self, etype, value, [])
764
764
765 def show_exception_only(self, etype, evalue):
765 def show_exception_only(self, etype, evalue):
766 """Only print the exception type and message, without a traceback.
766 """Only print the exception type and message, without a traceback.
767
767
768 Parameters
768 Parameters
769 ----------
769 ----------
770 etype : exception type
770 etype : exception type
771 value : exception value
771 value : exception value
772 """
772 """
773 # This method needs to use __call__ from *this* class, not the one from
773 # This method needs to use __call__ from *this* class, not the one from
774 # a subclass whose signature or behavior may be different
774 # a subclass whose signature or behavior may be different
775 ostream = self.ostream
775 ostream = self.ostream
776 ostream.flush()
776 ostream.flush()
777 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
777 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
778 ostream.flush()
778 ostream.flush()
779
779
780 def _some_str(self, value):
780 def _some_str(self, value):
781 # Lifted from traceback.py
781 # Lifted from traceback.py
782 try:
782 try:
783 return py3compat.cast_unicode(str(value))
783 return py3compat.cast_unicode(str(value))
784 except:
784 except:
785 return u'<unprintable %s object>' % type(value).__name__
785 return u'<unprintable %s object>' % type(value).__name__
786
786
787
787
788 #----------------------------------------------------------------------------
788 #----------------------------------------------------------------------------
789 class VerboseTB(TBTools):
789 class VerboseTB(TBTools):
790 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
790 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
791 of HTML. Requires inspect and pydoc. Crazy, man.
791 of HTML. Requires inspect and pydoc. Crazy, man.
792
792
793 Modified version which optionally strips the topmost entries from the
793 Modified version which optionally strips the topmost entries from the
794 traceback, to be used with alternate interpreters (because their own code
794 traceback, to be used with alternate interpreters (because their own code
795 would appear in the traceback)."""
795 would appear in the traceback)."""
796
796
797 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
797 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
798 tb_offset=0, long_header=False, include_vars=True,
798 tb_offset=0, long_header=False, include_vars=True,
799 check_cache=None, debugger_cls = None,
799 check_cache=None, debugger_cls = None,
800 parent=None, config=None):
800 parent=None, config=None):
801 """Specify traceback offset, headers and color scheme.
801 """Specify traceback offset, headers and color scheme.
802
802
803 Define how many frames to drop from the tracebacks. Calling it with
803 Define how many frames to drop from the tracebacks. Calling it with
804 tb_offset=1 allows use of this handler in interpreters which will have
804 tb_offset=1 allows use of this handler in interpreters which will have
805 their own code at the top of the traceback (VerboseTB will first
805 their own code at the top of the traceback (VerboseTB will first
806 remove that frame before printing the traceback info)."""
806 remove that frame before printing the traceback info)."""
807 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
807 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
808 ostream=ostream, parent=parent, config=config)
808 ostream=ostream, parent=parent, config=config)
809 self.tb_offset = tb_offset
809 self.tb_offset = tb_offset
810 self.long_header = long_header
810 self.long_header = long_header
811 self.include_vars = include_vars
811 self.include_vars = include_vars
812 # By default we use linecache.checkcache, but the user can provide a
812 # By default we use linecache.checkcache, but the user can provide a
813 # different check_cache implementation. This is used by the IPython
813 # different check_cache implementation. This is used by the IPython
814 # kernel to provide tracebacks for interactive code that is cached,
814 # kernel to provide tracebacks for interactive code that is cached,
815 # by a compiler instance that flushes the linecache but preserves its
815 # by a compiler instance that flushes the linecache but preserves its
816 # own code cache.
816 # own code cache.
817 if check_cache is None:
817 if check_cache is None:
818 check_cache = linecache.checkcache
818 check_cache = linecache.checkcache
819 self.check_cache = check_cache
819 self.check_cache = check_cache
820
820
821 self.debugger_cls = debugger_cls or debugger.Pdb
821 self.debugger_cls = debugger_cls or debugger.Pdb
822
822
823 def format_records(self, records, last_unique, recursion_repeat):
823 def format_records(self, records, last_unique, recursion_repeat):
824 """Format the stack frames of the traceback"""
824 """Format the stack frames of the traceback"""
825 frames = []
825 frames = []
826 for r in records[:last_unique+recursion_repeat+1]:
826 for r in records[:last_unique+recursion_repeat+1]:
827 #print '*** record:',file,lnum,func,lines,index # dbg
827 #print '*** record:',file,lnum,func,lines,index # dbg
828 frames.append(self.format_record(*r))
828 frames.append(self.format_record(*r))
829
829
830 if recursion_repeat:
830 if recursion_repeat:
831 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
831 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
832 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
832 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
833
833
834 return frames
834 return frames
835
835
836 def format_record(self, frame, file, lnum, func, lines, index):
836 def format_record(self, frame, file, lnum, func, lines, index):
837 """Format a single stack frame"""
837 """Format a single stack frame"""
838 Colors = self.Colors # just a shorthand + quicker name lookup
838 Colors = self.Colors # just a shorthand + quicker name lookup
839 ColorsNormal = Colors.Normal # used a lot
839 ColorsNormal = Colors.Normal # used a lot
840 col_scheme = self.color_scheme_table.active_scheme_name
840 col_scheme = self.color_scheme_table.active_scheme_name
841 indent = ' ' * INDENT_SIZE
841 indent = ' ' * INDENT_SIZE
842 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
842 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
843 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
843 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
844 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
844 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
845 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
845 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
846 ColorsNormal)
846 ColorsNormal)
847 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
847 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
848 (Colors.vName, Colors.valEm, ColorsNormal)
848 (Colors.vName, Colors.valEm, ColorsNormal)
849 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
849 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
850 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
850 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
851 Colors.vName, ColorsNormal)
851 Colors.vName, ColorsNormal)
852 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
852 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
853
853
854 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
854 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
855 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
855 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
856 ColorsNormal)
856 ColorsNormal)
857
857
858 abspath = os.path.abspath
858 abspath = os.path.abspath
859
859
860
860
861 if not file:
861 if not file:
862 file = '?'
862 file = '?'
863 elif file.startswith(str("<")) and file.endswith(str(">")):
863 elif file.startswith(str("<")) and file.endswith(str(">")):
864 # Not a real filename, no problem...
864 # Not a real filename, no problem...
865 pass
865 pass
866 elif not os.path.isabs(file):
866 elif not os.path.isabs(file):
867 # Try to make the filename absolute by trying all
867 # Try to make the filename absolute by trying all
868 # sys.path entries (which is also what linecache does)
868 # sys.path entries (which is also what linecache does)
869 for dirname in sys.path:
869 for dirname in sys.path:
870 try:
870 try:
871 fullname = os.path.join(dirname, file)
871 fullname = os.path.join(dirname, file)
872 if os.path.isfile(fullname):
872 if os.path.isfile(fullname):
873 file = os.path.abspath(fullname)
873 file = os.path.abspath(fullname)
874 break
874 break
875 except Exception:
875 except Exception:
876 # Just in case that sys.path contains very
876 # Just in case that sys.path contains very
877 # strange entries...
877 # strange entries...
878 pass
878 pass
879
879
880 file = py3compat.cast_unicode(file, util_path.fs_encoding)
880 file = py3compat.cast_unicode(file, util_path.fs_encoding)
881 link = tpl_link % file
881 link = tpl_link % file
882 args, varargs, varkw, locals = fixed_getargvalues(frame)
882 args, varargs, varkw, locals = fixed_getargvalues(frame)
883
883
884 if func == '?':
884 if func == '?':
885 call = ''
885 call = ''
886 else:
886 else:
887 # Decide whether to include variable details or not
887 # Decide whether to include variable details or not
888 var_repr = self.include_vars and eqrepr or nullrepr
888 var_repr = self.include_vars and eqrepr or nullrepr
889 try:
889 try:
890 call = tpl_call % (func, inspect.formatargvalues(args,
890 call = tpl_call % (func, inspect.formatargvalues(args,
891 varargs, varkw,
891 varargs, varkw,
892 locals, formatvalue=var_repr))
892 locals, formatvalue=var_repr))
893 except KeyError:
893 except KeyError:
894 # This happens in situations like errors inside generator
894 # This happens in situations like errors inside generator
895 # expressions, where local variables are listed in the
895 # expressions, where local variables are listed in the
896 # line, but can't be extracted from the frame. I'm not
896 # line, but can't be extracted from the frame. I'm not
897 # 100% sure this isn't actually a bug in inspect itself,
897 # 100% sure this isn't actually a bug in inspect itself,
898 # but since there's no info for us to compute with, the
898 # but since there's no info for us to compute with, the
899 # best we can do is report the failure and move on. Here
899 # best we can do is report the failure and move on. Here
900 # we must *not* call any traceback construction again,
900 # we must *not* call any traceback construction again,
901 # because that would mess up use of %debug later on. So we
901 # because that would mess up use of %debug later on. So we
902 # simply report the failure and move on. The only
902 # simply report the failure and move on. The only
903 # limitation will be that this frame won't have locals
903 # limitation will be that this frame won't have locals
904 # listed in the call signature. Quite subtle problem...
904 # listed in the call signature. Quite subtle problem...
905 # I can't think of a good way to validate this in a unit
905 # I can't think of a good way to validate this in a unit
906 # test, but running a script consisting of:
906 # test, but running a script consisting of:
907 # dict( (k,v.strip()) for (k,v) in range(10) )
907 # dict( (k,v.strip()) for (k,v) in range(10) )
908 # will illustrate the error, if this exception catch is
908 # will illustrate the error, if this exception catch is
909 # disabled.
909 # disabled.
910 call = tpl_call_fail % func
910 call = tpl_call_fail % func
911
911
912 # Don't attempt to tokenize binary files.
912 # Don't attempt to tokenize binary files.
913 if file.endswith(('.so', '.pyd', '.dll')):
913 if file.endswith(('.so', '.pyd', '.dll')):
914 return '%s %s\n' % (link, call)
914 return '%s %s\n' % (link, call)
915
915
916 elif file.endswith(('.pyc', '.pyo')):
916 elif file.endswith(('.pyc', '.pyo')):
917 # Look up the corresponding source file.
917 # Look up the corresponding source file.
918 try:
918 try:
919 file = openpy.source_from_cache(file)
919 file = openpy.source_from_cache(file)
920 except ValueError:
920 except ValueError:
921 # Failed to get the source file for some reason
921 # Failed to get the source file for some reason
922 # E.g. https://github.com/ipython/ipython/issues/9486
922 # E.g. https://github.com/ipython/ipython/issues/9486
923 return '%s %s\n' % (link, call)
923 return '%s %s\n' % (link, call)
924
924
925 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
925 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
926 line = getline(file, lnum[0])
926 line = getline(file, lnum[0])
927 lnum[0] += 1
927 lnum[0] += 1
928 return line
928 return line
929
929
930 # Build the list of names on this line of code where the exception
930 # Build the list of names on this line of code where the exception
931 # occurred.
931 # occurred.
932 try:
932 try:
933 names = []
933 names = []
934 name_cont = False
934 name_cont = False
935
935
936 for token_type, token, start, end, line in generate_tokens(linereader):
936 for token_type, token, start, end, line in generate_tokens(linereader):
937 # build composite names
937 # build composite names
938 if token_type == tokenize.NAME and token not in keyword.kwlist:
938 if token_type == tokenize.NAME and token not in keyword.kwlist:
939 if name_cont:
939 if name_cont:
940 # Continuation of a dotted name
940 # Continuation of a dotted name
941 try:
941 try:
942 names[-1].append(token)
942 names[-1].append(token)
943 except IndexError:
943 except IndexError:
944 names.append([token])
944 names.append([token])
945 name_cont = False
945 name_cont = False
946 else:
946 else:
947 # Regular new names. We append everything, the caller
947 # Regular new names. We append everything, the caller
948 # will be responsible for pruning the list later. It's
948 # will be responsible for pruning the list later. It's
949 # very tricky to try to prune as we go, b/c composite
949 # very tricky to try to prune as we go, b/c composite
950 # names can fool us. The pruning at the end is easy
950 # names can fool us. The pruning at the end is easy
951 # to do (or the caller can print a list with repeated
951 # to do (or the caller can print a list with repeated
952 # names if so desired.
952 # names if so desired.
953 names.append([token])
953 names.append([token])
954 elif token == '.':
954 elif token == '.':
955 name_cont = True
955 name_cont = True
956 elif token_type == tokenize.NEWLINE:
956 elif token_type == tokenize.NEWLINE:
957 break
957 break
958
958
959 except (IndexError, UnicodeDecodeError, SyntaxError):
959 except (IndexError, UnicodeDecodeError, SyntaxError):
960 # signals exit of tokenizer
960 # signals exit of tokenizer
961 # SyntaxError can occur if the file is not actually Python
961 # SyntaxError can occur if the file is not actually Python
962 # - see gh-6300
962 # - see gh-6300
963 pass
963 pass
964 except tokenize.TokenError as msg:
964 except tokenize.TokenError as msg:
965 _m = ("An unexpected error occurred while tokenizing input\n"
965 _m = ("An unexpected error occurred while tokenizing input\n"
966 "The following traceback may be corrupted or invalid\n"
966 "The following traceback may be corrupted or invalid\n"
967 "The error message is: %s\n" % msg)
967 "The error message is: %s\n" % msg)
968 error(_m)
968 error(_m)
969
969
970 # Join composite names (e.g. "dict.fromkeys")
970 # Join composite names (e.g. "dict.fromkeys")
971 names = ['.'.join(n) for n in names]
971 names = ['.'.join(n) for n in names]
972 # prune names list of duplicates, but keep the right order
972 # prune names list of duplicates, but keep the right order
973 unique_names = uniq_stable(names)
973 unique_names = uniq_stable(names)
974
974
975 # Start loop over vars
975 # Start loop over vars
976 lvals = []
976 lvals = []
977 if self.include_vars:
977 if self.include_vars:
978 for name_full in unique_names:
978 for name_full in unique_names:
979 name_base = name_full.split('.', 1)[0]
979 name_base = name_full.split('.', 1)[0]
980 if name_base in frame.f_code.co_varnames:
980 if name_base in frame.f_code.co_varnames:
981 if name_base in locals:
981 if name_base in locals:
982 try:
982 try:
983 value = repr(eval(name_full, locals))
983 value = repr(eval(name_full, locals))
984 except:
984 except:
985 value = undefined
985 value = undefined
986 else:
986 else:
987 value = undefined
987 value = undefined
988 name = tpl_local_var % name_full
988 name = tpl_local_var % name_full
989 else:
989 else:
990 if name_base in frame.f_globals:
990 if name_base in frame.f_globals:
991 try:
991 try:
992 value = repr(eval(name_full, frame.f_globals))
992 value = repr(eval(name_full, frame.f_globals))
993 except:
993 except:
994 value = undefined
994 value = undefined
995 else:
995 else:
996 value = undefined
996 value = undefined
997 name = tpl_global_var % name_full
997 name = tpl_global_var % name_full
998 lvals.append(tpl_name_val % (name, value))
998 lvals.append(tpl_name_val % (name, value))
999 if lvals:
999 if lvals:
1000 lvals = '%s%s' % (indent, em_normal.join(lvals))
1000 lvals = '%s%s' % (indent, em_normal.join(lvals))
1001 else:
1001 else:
1002 lvals = ''
1002 lvals = ''
1003
1003
1004 level = '%s %s\n' % (link, call)
1004 level = '%s %s\n' % (link, call)
1005
1005
1006 if index is None:
1006 if index is None:
1007 return level
1007 return level
1008 else:
1008 else:
1009 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1009 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1010 return '%s%s' % (level, ''.join(
1010 return '%s%s' % (level, ''.join(
1011 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1011 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1012 _line_format)))
1012 _line_format)))
1013
1013
1014 def prepare_chained_exception_message(self, cause):
1014 def prepare_chained_exception_message(self, cause):
1015 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1015 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1016 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1016 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1017
1017
1018 if cause:
1018 if cause:
1019 message = [[direct_cause]]
1019 message = [[direct_cause]]
1020 else:
1020 else:
1021 message = [[exception_during_handling]]
1021 message = [[exception_during_handling]]
1022 return message
1022 return message
1023
1023
1024 def prepare_header(self, etype, long_version=False):
1024 def prepare_header(self, etype, long_version=False):
1025 colors = self.Colors # just a shorthand + quicker name lookup
1025 colors = self.Colors # just a shorthand + quicker name lookup
1026 colorsnormal = colors.Normal # used a lot
1026 colorsnormal = colors.Normal # used a lot
1027 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1027 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1028 width = min(75, get_terminal_size()[0])
1028 width = min(75, get_terminal_size()[0])
1029 if long_version:
1029 if long_version:
1030 # Header with the exception type, python version, and date
1030 # Header with the exception type, python version, and date
1031 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1031 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1032 date = time.ctime(time.time())
1032 date = time.ctime(time.time())
1033
1033
1034 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1034 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1035 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1035 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1036 pyver, date.rjust(width) )
1036 pyver, date.rjust(width) )
1037 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1037 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1038 "\ncalls leading up to the error, with the most recent (innermost) call last."
1038 "\ncalls leading up to the error, with the most recent (innermost) call last."
1039 else:
1039 else:
1040 # Simplified header
1040 # Simplified header
1041 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1041 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1042 rjust(width - len(str(etype))) )
1042 rjust(width - len(str(etype))) )
1043
1043
1044 return head
1044 return head
1045
1045
1046 def format_exception(self, etype, evalue):
1046 def format_exception(self, etype, evalue):
1047 colors = self.Colors # just a shorthand + quicker name lookup
1047 colors = self.Colors # just a shorthand + quicker name lookup
1048 colorsnormal = colors.Normal # used a lot
1048 colorsnormal = colors.Normal # used a lot
1049 indent = ' ' * INDENT_SIZE
1049 indent = ' ' * INDENT_SIZE
1050 # Get (safely) a string form of the exception info
1050 # Get (safely) a string form of the exception info
1051 try:
1051 try:
1052 etype_str, evalue_str = map(str, (etype, evalue))
1052 etype_str, evalue_str = map(str, (etype, evalue))
1053 except:
1053 except:
1054 # User exception is improperly defined.
1054 # User exception is improperly defined.
1055 etype, evalue = str, sys.exc_info()[:2]
1055 etype, evalue = str, sys.exc_info()[:2]
1056 etype_str, evalue_str = map(str, (etype, evalue))
1056 etype_str, evalue_str = map(str, (etype, evalue))
1057 # ... and format it
1057 # ... and format it
1058 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1058 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1059 colorsnormal, py3compat.cast_unicode(evalue_str))]
1059 colorsnormal, py3compat.cast_unicode(evalue_str))]
1060
1060
1061 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1061 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1062 try:
1062 try:
1063 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1063 names = [w for w in dir(evalue) if isinstance(w, str)]
1064 except:
1064 except:
1065 # Every now and then, an object with funny internals blows up
1065 # Every now and then, an object with funny internals blows up
1066 # when dir() is called on it. We do the best we can to report
1066 # when dir() is called on it. We do the best we can to report
1067 # the problem and continue
1067 # the problem and continue
1068 _m = '%sException reporting error (object with broken dir())%s:'
1068 _m = '%sException reporting error (object with broken dir())%s:'
1069 exception.append(_m % (colors.excName, colorsnormal))
1069 exception.append(_m % (colors.excName, colorsnormal))
1070 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1070 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1071 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1071 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1072 colorsnormal, py3compat.cast_unicode(evalue_str)))
1072 colorsnormal, py3compat.cast_unicode(evalue_str)))
1073 names = []
1073 names = []
1074 for name in names:
1074 for name in names:
1075 value = text_repr(getattr(evalue, name))
1075 value = text_repr(getattr(evalue, name))
1076 exception.append('\n%s%s = %s' % (indent, name, value))
1076 exception.append('\n%s%s = %s' % (indent, name, value))
1077
1077
1078 return exception
1078 return exception
1079
1079
1080 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1080 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1081 """Formats the header, traceback and exception message for a single exception.
1081 """Formats the header, traceback and exception message for a single exception.
1082
1082
1083 This may be called multiple times by Python 3 exception chaining
1083 This may be called multiple times by Python 3 exception chaining
1084 (PEP 3134).
1084 (PEP 3134).
1085 """
1085 """
1086 # some locals
1086 # some locals
1087 orig_etype = etype
1087 orig_etype = etype
1088 try:
1088 try:
1089 etype = etype.__name__
1089 etype = etype.__name__
1090 except AttributeError:
1090 except AttributeError:
1091 pass
1091 pass
1092
1092
1093 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1093 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1094 head = self.prepare_header(etype, self.long_header)
1094 head = self.prepare_header(etype, self.long_header)
1095 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1095 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1096
1096
1097 if records is None:
1097 if records is None:
1098 return ""
1098 return ""
1099
1099
1100 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1100 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1101
1101
1102 frames = self.format_records(records, last_unique, recursion_repeat)
1102 frames = self.format_records(records, last_unique, recursion_repeat)
1103
1103
1104 formatted_exception = self.format_exception(etype, evalue)
1104 formatted_exception = self.format_exception(etype, evalue)
1105 if records:
1105 if records:
1106 filepath, lnum = records[-1][1:3]
1106 filepath, lnum = records[-1][1:3]
1107 filepath = os.path.abspath(filepath)
1107 filepath = os.path.abspath(filepath)
1108 ipinst = get_ipython()
1108 ipinst = get_ipython()
1109 if ipinst is not None:
1109 if ipinst is not None:
1110 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1110 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1111
1111
1112 return [[head] + frames + [''.join(formatted_exception[0])]]
1112 return [[head] + frames + [''.join(formatted_exception[0])]]
1113
1113
1114 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1114 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1115 try:
1115 try:
1116 # Try the default getinnerframes and Alex's: Alex's fixes some
1116 # Try the default getinnerframes and Alex's: Alex's fixes some
1117 # problems, but it generates empty tracebacks for console errors
1117 # problems, but it generates empty tracebacks for console errors
1118 # (5 blanks lines) where none should be returned.
1118 # (5 blanks lines) where none should be returned.
1119 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1119 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1120 except UnicodeDecodeError:
1120 except UnicodeDecodeError:
1121 # This can occur if a file's encoding magic comment is wrong.
1121 # This can occur if a file's encoding magic comment is wrong.
1122 # I can't see a way to recover without duplicating a bunch of code
1122 # I can't see a way to recover without duplicating a bunch of code
1123 # from the stdlib traceback module. --TK
1123 # from the stdlib traceback module. --TK
1124 error('\nUnicodeDecodeError while processing traceback.\n')
1124 error('\nUnicodeDecodeError while processing traceback.\n')
1125 return None
1125 return None
1126 except:
1126 except:
1127 # FIXME: I've been getting many crash reports from python 2.3
1127 # FIXME: I've been getting many crash reports from python 2.3
1128 # users, traceable to inspect.py. If I can find a small test-case
1128 # users, traceable to inspect.py. If I can find a small test-case
1129 # to reproduce this, I should either write a better workaround or
1129 # to reproduce this, I should either write a better workaround or
1130 # file a bug report against inspect (if that's the real problem).
1130 # file a bug report against inspect (if that's the real problem).
1131 # So far, I haven't been able to find an isolated example to
1131 # So far, I haven't been able to find an isolated example to
1132 # reproduce the problem.
1132 # reproduce the problem.
1133 inspect_error()
1133 inspect_error()
1134 traceback.print_exc(file=self.ostream)
1134 traceback.print_exc(file=self.ostream)
1135 info('\nUnfortunately, your original traceback can not be constructed.\n')
1135 info('\nUnfortunately, your original traceback can not be constructed.\n')
1136 return None
1136 return None
1137
1137
1138 def get_parts_of_chained_exception(self, evalue):
1138 def get_parts_of_chained_exception(self, evalue):
1139 def get_chained_exception(exception_value):
1139 def get_chained_exception(exception_value):
1140 cause = getattr(exception_value, '__cause__', None)
1140 cause = getattr(exception_value, '__cause__', None)
1141 if cause:
1141 if cause:
1142 return cause
1142 return cause
1143 if getattr(exception_value, '__suppress_context__', False):
1143 if getattr(exception_value, '__suppress_context__', False):
1144 return None
1144 return None
1145 return getattr(exception_value, '__context__', None)
1145 return getattr(exception_value, '__context__', None)
1146
1146
1147 chained_evalue = get_chained_exception(evalue)
1147 chained_evalue = get_chained_exception(evalue)
1148
1148
1149 if chained_evalue:
1149 if chained_evalue:
1150 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1150 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1151
1151
1152 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1152 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1153 number_of_lines_of_context=5):
1153 number_of_lines_of_context=5):
1154 """Return a nice text document describing the traceback."""
1154 """Return a nice text document describing the traceback."""
1155
1155
1156 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1156 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1157 tb_offset)
1157 tb_offset)
1158
1158
1159 colors = self.Colors # just a shorthand + quicker name lookup
1159 colors = self.Colors # just a shorthand + quicker name lookup
1160 colorsnormal = colors.Normal # used a lot
1160 colorsnormal = colors.Normal # used a lot
1161 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1161 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1162 structured_traceback_parts = [head]
1162 structured_traceback_parts = [head]
1163 if py3compat.PY3:
1163 if py3compat.PY3:
1164 chained_exceptions_tb_offset = 0
1164 chained_exceptions_tb_offset = 0
1165 lines_of_context = 3
1165 lines_of_context = 3
1166 formatted_exceptions = formatted_exception
1166 formatted_exceptions = formatted_exception
1167 exception = self.get_parts_of_chained_exception(evalue)
1167 exception = self.get_parts_of_chained_exception(evalue)
1168 if exception:
1168 if exception:
1169 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1169 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1170 etype, evalue, etb = exception
1170 etype, evalue, etb = exception
1171 else:
1171 else:
1172 evalue = None
1172 evalue = None
1173 chained_exc_ids = set()
1173 chained_exc_ids = set()
1174 while evalue:
1174 while evalue:
1175 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1175 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1176 chained_exceptions_tb_offset)
1176 chained_exceptions_tb_offset)
1177 exception = self.get_parts_of_chained_exception(evalue)
1177 exception = self.get_parts_of_chained_exception(evalue)
1178
1178
1179 if exception and not id(exception[1]) in chained_exc_ids:
1179 if exception and not id(exception[1]) in chained_exc_ids:
1180 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1180 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1181 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1181 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1182 etype, evalue, etb = exception
1182 etype, evalue, etb = exception
1183 else:
1183 else:
1184 evalue = None
1184 evalue = None
1185
1185
1186 # we want to see exceptions in a reversed order:
1186 # we want to see exceptions in a reversed order:
1187 # the first exception should be on top
1187 # the first exception should be on top
1188 for formatted_exception in reversed(formatted_exceptions):
1188 for formatted_exception in reversed(formatted_exceptions):
1189 structured_traceback_parts += formatted_exception
1189 structured_traceback_parts += formatted_exception
1190 else:
1190 else:
1191 structured_traceback_parts += formatted_exception[0]
1191 structured_traceback_parts += formatted_exception[0]
1192
1192
1193 return structured_traceback_parts
1193 return structured_traceback_parts
1194
1194
1195 def debugger(self, force=False):
1195 def debugger(self, force=False):
1196 """Call up the pdb debugger if desired, always clean up the tb
1196 """Call up the pdb debugger if desired, always clean up the tb
1197 reference.
1197 reference.
1198
1198
1199 Keywords:
1199 Keywords:
1200
1200
1201 - force(False): by default, this routine checks the instance call_pdb
1201 - force(False): by default, this routine checks the instance call_pdb
1202 flag and does not actually invoke the debugger if the flag is false.
1202 flag and does not actually invoke the debugger if the flag is false.
1203 The 'force' option forces the debugger to activate even if the flag
1203 The 'force' option forces the debugger to activate even if the flag
1204 is false.
1204 is false.
1205
1205
1206 If the call_pdb flag is set, the pdb interactive debugger is
1206 If the call_pdb flag is set, the pdb interactive debugger is
1207 invoked. In all cases, the self.tb reference to the current traceback
1207 invoked. In all cases, the self.tb reference to the current traceback
1208 is deleted to prevent lingering references which hamper memory
1208 is deleted to prevent lingering references which hamper memory
1209 management.
1209 management.
1210
1210
1211 Note that each call to pdb() does an 'import readline', so if your app
1211 Note that each call to pdb() does an 'import readline', so if your app
1212 requires a special setup for the readline completers, you'll have to
1212 requires a special setup for the readline completers, you'll have to
1213 fix that by hand after invoking the exception handler."""
1213 fix that by hand after invoking the exception handler."""
1214
1214
1215 if force or self.call_pdb:
1215 if force or self.call_pdb:
1216 if self.pdb is None:
1216 if self.pdb is None:
1217 self.pdb = self.debugger_cls()
1217 self.pdb = self.debugger_cls()
1218 # the system displayhook may have changed, restore the original
1218 # the system displayhook may have changed, restore the original
1219 # for pdb
1219 # for pdb
1220 display_trap = DisplayTrap(hook=sys.__displayhook__)
1220 display_trap = DisplayTrap(hook=sys.__displayhook__)
1221 with display_trap:
1221 with display_trap:
1222 self.pdb.reset()
1222 self.pdb.reset()
1223 # Find the right frame so we don't pop up inside ipython itself
1223 # Find the right frame so we don't pop up inside ipython itself
1224 if hasattr(self, 'tb') and self.tb is not None:
1224 if hasattr(self, 'tb') and self.tb is not None:
1225 etb = self.tb
1225 etb = self.tb
1226 else:
1226 else:
1227 etb = self.tb = sys.last_traceback
1227 etb = self.tb = sys.last_traceback
1228 while self.tb is not None and self.tb.tb_next is not None:
1228 while self.tb is not None and self.tb.tb_next is not None:
1229 self.tb = self.tb.tb_next
1229 self.tb = self.tb.tb_next
1230 if etb and etb.tb_next:
1230 if etb and etb.tb_next:
1231 etb = etb.tb_next
1231 etb = etb.tb_next
1232 self.pdb.botframe = etb.tb_frame
1232 self.pdb.botframe = etb.tb_frame
1233 self.pdb.interaction(self.tb.tb_frame, self.tb)
1233 self.pdb.interaction(self.tb.tb_frame, self.tb)
1234
1234
1235 if hasattr(self, 'tb'):
1235 if hasattr(self, 'tb'):
1236 del self.tb
1236 del self.tb
1237
1237
1238 def handler(self, info=None):
1238 def handler(self, info=None):
1239 (etype, evalue, etb) = info or sys.exc_info()
1239 (etype, evalue, etb) = info or sys.exc_info()
1240 self.tb = etb
1240 self.tb = etb
1241 ostream = self.ostream
1241 ostream = self.ostream
1242 ostream.flush()
1242 ostream.flush()
1243 ostream.write(self.text(etype, evalue, etb))
1243 ostream.write(self.text(etype, evalue, etb))
1244 ostream.write('\n')
1244 ostream.write('\n')
1245 ostream.flush()
1245 ostream.flush()
1246
1246
1247 # Changed so an instance can just be called as VerboseTB_inst() and print
1247 # Changed so an instance can just be called as VerboseTB_inst() and print
1248 # out the right info on its own.
1248 # out the right info on its own.
1249 def __call__(self, etype=None, evalue=None, etb=None):
1249 def __call__(self, etype=None, evalue=None, etb=None):
1250 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1250 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1251 if etb is None:
1251 if etb is None:
1252 self.handler()
1252 self.handler()
1253 else:
1253 else:
1254 self.handler((etype, evalue, etb))
1254 self.handler((etype, evalue, etb))
1255 try:
1255 try:
1256 self.debugger()
1256 self.debugger()
1257 except KeyboardInterrupt:
1257 except KeyboardInterrupt:
1258 print("\nKeyboardInterrupt")
1258 print("\nKeyboardInterrupt")
1259
1259
1260
1260
1261 #----------------------------------------------------------------------------
1261 #----------------------------------------------------------------------------
1262 class FormattedTB(VerboseTB, ListTB):
1262 class FormattedTB(VerboseTB, ListTB):
1263 """Subclass ListTB but allow calling with a traceback.
1263 """Subclass ListTB but allow calling with a traceback.
1264
1264
1265 It can thus be used as a sys.excepthook for Python > 2.1.
1265 It can thus be used as a sys.excepthook for Python > 2.1.
1266
1266
1267 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1267 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1268
1268
1269 Allows a tb_offset to be specified. This is useful for situations where
1269 Allows a tb_offset to be specified. This is useful for situations where
1270 one needs to remove a number of topmost frames from the traceback (such as
1270 one needs to remove a number of topmost frames from the traceback (such as
1271 occurs with python programs that themselves execute other python code,
1271 occurs with python programs that themselves execute other python code,
1272 like Python shells). """
1272 like Python shells). """
1273
1273
1274 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1274 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1275 ostream=None,
1275 ostream=None,
1276 tb_offset=0, long_header=False, include_vars=False,
1276 tb_offset=0, long_header=False, include_vars=False,
1277 check_cache=None, debugger_cls=None,
1277 check_cache=None, debugger_cls=None,
1278 parent=None, config=None):
1278 parent=None, config=None):
1279
1279
1280 # NEVER change the order of this list. Put new modes at the end:
1280 # NEVER change the order of this list. Put new modes at the end:
1281 self.valid_modes = ['Plain', 'Context', 'Verbose']
1281 self.valid_modes = ['Plain', 'Context', 'Verbose']
1282 self.verbose_modes = self.valid_modes[1:3]
1282 self.verbose_modes = self.valid_modes[1:3]
1283
1283
1284 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1284 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1285 ostream=ostream, tb_offset=tb_offset,
1285 ostream=ostream, tb_offset=tb_offset,
1286 long_header=long_header, include_vars=include_vars,
1286 long_header=long_header, include_vars=include_vars,
1287 check_cache=check_cache, debugger_cls=debugger_cls,
1287 check_cache=check_cache, debugger_cls=debugger_cls,
1288 parent=parent, config=config)
1288 parent=parent, config=config)
1289
1289
1290 # Different types of tracebacks are joined with different separators to
1290 # Different types of tracebacks are joined with different separators to
1291 # form a single string. They are taken from this dict
1291 # form a single string. They are taken from this dict
1292 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1292 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1293 # set_mode also sets the tb_join_char attribute
1293 # set_mode also sets the tb_join_char attribute
1294 self.set_mode(mode)
1294 self.set_mode(mode)
1295
1295
1296 def _extract_tb(self, tb):
1296 def _extract_tb(self, tb):
1297 if tb:
1297 if tb:
1298 return traceback.extract_tb(tb)
1298 return traceback.extract_tb(tb)
1299 else:
1299 else:
1300 return None
1300 return None
1301
1301
1302 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1302 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1303 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1303 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1304 mode = self.mode
1304 mode = self.mode
1305 if mode in self.verbose_modes:
1305 if mode in self.verbose_modes:
1306 # Verbose modes need a full traceback
1306 # Verbose modes need a full traceback
1307 return VerboseTB.structured_traceback(
1307 return VerboseTB.structured_traceback(
1308 self, etype, value, tb, tb_offset, number_of_lines_of_context
1308 self, etype, value, tb, tb_offset, number_of_lines_of_context
1309 )
1309 )
1310 else:
1310 else:
1311 # We must check the source cache because otherwise we can print
1311 # We must check the source cache because otherwise we can print
1312 # out-of-date source code.
1312 # out-of-date source code.
1313 self.check_cache()
1313 self.check_cache()
1314 # Now we can extract and format the exception
1314 # Now we can extract and format the exception
1315 elist = self._extract_tb(tb)
1315 elist = self._extract_tb(tb)
1316 return ListTB.structured_traceback(
1316 return ListTB.structured_traceback(
1317 self, etype, value, elist, tb_offset, number_of_lines_of_context
1317 self, etype, value, elist, tb_offset, number_of_lines_of_context
1318 )
1318 )
1319
1319
1320 def stb2text(self, stb):
1320 def stb2text(self, stb):
1321 """Convert a structured traceback (a list) to a string."""
1321 """Convert a structured traceback (a list) to a string."""
1322 return self.tb_join_char.join(stb)
1322 return self.tb_join_char.join(stb)
1323
1323
1324
1324
1325 def set_mode(self, mode=None):
1325 def set_mode(self, mode=None):
1326 """Switch to the desired mode.
1326 """Switch to the desired mode.
1327
1327
1328 If mode is not specified, cycles through the available modes."""
1328 If mode is not specified, cycles through the available modes."""
1329
1329
1330 if not mode:
1330 if not mode:
1331 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1331 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1332 len(self.valid_modes)
1332 len(self.valid_modes)
1333 self.mode = self.valid_modes[new_idx]
1333 self.mode = self.valid_modes[new_idx]
1334 elif mode not in self.valid_modes:
1334 elif mode not in self.valid_modes:
1335 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1335 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1336 'Valid modes: ' + str(self.valid_modes))
1336 'Valid modes: ' + str(self.valid_modes))
1337 else:
1337 else:
1338 self.mode = mode
1338 self.mode = mode
1339 # include variable details only in 'Verbose' mode
1339 # include variable details only in 'Verbose' mode
1340 self.include_vars = (self.mode == self.valid_modes[2])
1340 self.include_vars = (self.mode == self.valid_modes[2])
1341 # Set the join character for generating text tracebacks
1341 # Set the join character for generating text tracebacks
1342 self.tb_join_char = self._join_chars[self.mode]
1342 self.tb_join_char = self._join_chars[self.mode]
1343
1343
1344 # some convenient shortcuts
1344 # some convenient shortcuts
1345 def plain(self):
1345 def plain(self):
1346 self.set_mode(self.valid_modes[0])
1346 self.set_mode(self.valid_modes[0])
1347
1347
1348 def context(self):
1348 def context(self):
1349 self.set_mode(self.valid_modes[1])
1349 self.set_mode(self.valid_modes[1])
1350
1350
1351 def verbose(self):
1351 def verbose(self):
1352 self.set_mode(self.valid_modes[2])
1352 self.set_mode(self.valid_modes[2])
1353
1353
1354
1354
1355 #----------------------------------------------------------------------------
1355 #----------------------------------------------------------------------------
1356 class AutoFormattedTB(FormattedTB):
1356 class AutoFormattedTB(FormattedTB):
1357 """A traceback printer which can be called on the fly.
1357 """A traceback printer which can be called on the fly.
1358
1358
1359 It will find out about exceptions by itself.
1359 It will find out about exceptions by itself.
1360
1360
1361 A brief example::
1361 A brief example::
1362
1362
1363 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1363 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1364 try:
1364 try:
1365 ...
1365 ...
1366 except:
1366 except:
1367 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1367 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1368 """
1368 """
1369
1369
1370 def __call__(self, etype=None, evalue=None, etb=None,
1370 def __call__(self, etype=None, evalue=None, etb=None,
1371 out=None, tb_offset=None):
1371 out=None, tb_offset=None):
1372 """Print out a formatted exception traceback.
1372 """Print out a formatted exception traceback.
1373
1373
1374 Optional arguments:
1374 Optional arguments:
1375 - out: an open file-like object to direct output to.
1375 - out: an open file-like object to direct output to.
1376
1376
1377 - tb_offset: the number of frames to skip over in the stack, on a
1377 - tb_offset: the number of frames to skip over in the stack, on a
1378 per-call basis (this overrides temporarily the instance's tb_offset
1378 per-call basis (this overrides temporarily the instance's tb_offset
1379 given at initialization time. """
1379 given at initialization time. """
1380
1380
1381 if out is None:
1381 if out is None:
1382 out = self.ostream
1382 out = self.ostream
1383 out.flush()
1383 out.flush()
1384 out.write(self.text(etype, evalue, etb, tb_offset))
1384 out.write(self.text(etype, evalue, etb, tb_offset))
1385 out.write('\n')
1385 out.write('\n')
1386 out.flush()
1386 out.flush()
1387 # FIXME: we should remove the auto pdb behavior from here and leave
1387 # FIXME: we should remove the auto pdb behavior from here and leave
1388 # that to the clients.
1388 # that to the clients.
1389 try:
1389 try:
1390 self.debugger()
1390 self.debugger()
1391 except KeyboardInterrupt:
1391 except KeyboardInterrupt:
1392 print("\nKeyboardInterrupt")
1392 print("\nKeyboardInterrupt")
1393
1393
1394 def structured_traceback(self, etype=None, value=None, tb=None,
1394 def structured_traceback(self, etype=None, value=None, tb=None,
1395 tb_offset=None, number_of_lines_of_context=5):
1395 tb_offset=None, number_of_lines_of_context=5):
1396 if etype is None:
1396 if etype is None:
1397 etype, value, tb = sys.exc_info()
1397 etype, value, tb = sys.exc_info()
1398 self.tb = tb
1398 self.tb = tb
1399 return FormattedTB.structured_traceback(
1399 return FormattedTB.structured_traceback(
1400 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1400 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1401
1401
1402
1402
1403 #---------------------------------------------------------------------------
1403 #---------------------------------------------------------------------------
1404
1404
1405 # A simple class to preserve Nathan's original functionality.
1405 # A simple class to preserve Nathan's original functionality.
1406 class ColorTB(FormattedTB):
1406 class ColorTB(FormattedTB):
1407 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1407 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1408
1408
1409 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1409 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1410 FormattedTB.__init__(self, color_scheme=color_scheme,
1410 FormattedTB.__init__(self, color_scheme=color_scheme,
1411 call_pdb=call_pdb, **kwargs)
1411 call_pdb=call_pdb, **kwargs)
1412
1412
1413
1413
1414 class SyntaxTB(ListTB):
1414 class SyntaxTB(ListTB):
1415 """Extension which holds some state: the last exception value"""
1415 """Extension which holds some state: the last exception value"""
1416
1416
1417 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1417 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1418 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1418 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1419 self.last_syntax_error = None
1419 self.last_syntax_error = None
1420
1420
1421 def __call__(self, etype, value, elist):
1421 def __call__(self, etype, value, elist):
1422 self.last_syntax_error = value
1422 self.last_syntax_error = value
1423
1423
1424 ListTB.__call__(self, etype, value, elist)
1424 ListTB.__call__(self, etype, value, elist)
1425
1425
1426 def structured_traceback(self, etype, value, elist, tb_offset=None,
1426 def structured_traceback(self, etype, value, elist, tb_offset=None,
1427 context=5):
1427 context=5):
1428 # If the source file has been edited, the line in the syntax error can
1428 # If the source file has been edited, the line in the syntax error can
1429 # be wrong (retrieved from an outdated cache). This replaces it with
1429 # be wrong (retrieved from an outdated cache). This replaces it with
1430 # the current value.
1430 # the current value.
1431 if isinstance(value, SyntaxError) \
1431 if isinstance(value, SyntaxError) \
1432 and isinstance(value.filename, py3compat.string_types) \
1432 and isinstance(value.filename, str) \
1433 and isinstance(value.lineno, int):
1433 and isinstance(value.lineno, int):
1434 linecache.checkcache(value.filename)
1434 linecache.checkcache(value.filename)
1435 newtext = ulinecache.getline(value.filename, value.lineno)
1435 newtext = ulinecache.getline(value.filename, value.lineno)
1436 if newtext:
1436 if newtext:
1437 value.text = newtext
1437 value.text = newtext
1438 self.last_syntax_error = value
1438 self.last_syntax_error = value
1439 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1439 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1440 tb_offset=tb_offset, context=context)
1440 tb_offset=tb_offset, context=context)
1441
1441
1442 def clear_err_state(self):
1442 def clear_err_state(self):
1443 """Return the current error state and clear it"""
1443 """Return the current error state and clear it"""
1444 e = self.last_syntax_error
1444 e = self.last_syntax_error
1445 self.last_syntax_error = None
1445 self.last_syntax_error = None
1446 return e
1446 return e
1447
1447
1448 def stb2text(self, stb):
1448 def stb2text(self, stb):
1449 """Convert a structured traceback (a list) to a string."""
1449 """Convert a structured traceback (a list) to a string."""
1450 return ''.join(stb)
1450 return ''.join(stb)
1451
1451
1452
1452
1453 # some internal-use functions
1453 # some internal-use functions
1454 def text_repr(value):
1454 def text_repr(value):
1455 """Hopefully pretty robust repr equivalent."""
1455 """Hopefully pretty robust repr equivalent."""
1456 # this is pretty horrible but should always return *something*
1456 # this is pretty horrible but should always return *something*
1457 try:
1457 try:
1458 return pydoc.text.repr(value)
1458 return pydoc.text.repr(value)
1459 except KeyboardInterrupt:
1459 except KeyboardInterrupt:
1460 raise
1460 raise
1461 except:
1461 except:
1462 try:
1462 try:
1463 return repr(value)
1463 return repr(value)
1464 except KeyboardInterrupt:
1464 except KeyboardInterrupt:
1465 raise
1465 raise
1466 except:
1466 except:
1467 try:
1467 try:
1468 # all still in an except block so we catch
1468 # all still in an except block so we catch
1469 # getattr raising
1469 # getattr raising
1470 name = getattr(value, '__name__', None)
1470 name = getattr(value, '__name__', None)
1471 if name:
1471 if name:
1472 # ick, recursion
1472 # ick, recursion
1473 return text_repr(name)
1473 return text_repr(name)
1474 klass = getattr(value, '__class__', None)
1474 klass = getattr(value, '__class__', None)
1475 if klass:
1475 if klass:
1476 return '%s instance' % text_repr(klass)
1476 return '%s instance' % text_repr(klass)
1477 except KeyboardInterrupt:
1477 except KeyboardInterrupt:
1478 raise
1478 raise
1479 except:
1479 except:
1480 return 'UNRECOVERABLE REPR FAILURE'
1480 return 'UNRECOVERABLE REPR FAILURE'
1481
1481
1482
1482
1483 def eqrepr(value, repr=text_repr):
1483 def eqrepr(value, repr=text_repr):
1484 return '=%s' % repr(value)
1484 return '=%s' % repr(value)
1485
1485
1486
1486
1487 def nullrepr(value, repr=text_repr):
1487 def nullrepr(value, repr=text_repr):
1488 return ''
1488 return ''
@@ -1,227 +1,226 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
12
13 # Copyright (c) IPython Development Team.
13 # Copyright (c) IPython Development Team.
14 # Distributed under the terms of the Modified BSD License.
14 # Distributed under the terms of the Modified BSD License.
15
15
16 import inspect, os, sys, textwrap
16 import inspect, os, sys, textwrap
17
17
18 from IPython.core.error import UsageError
18 from IPython.core.error import UsageError
19 from IPython.core.magic import Magics, magics_class, line_magic
19 from IPython.core.magic import Magics, magics_class, line_magic
20 from traitlets import Bool
20 from traitlets import Bool
21 from IPython.utils.py3compat import string_types
22
21
23
22
24 def restore_aliases(ip):
23 def restore_aliases(ip):
25 staliases = ip.db.get('stored_aliases', {})
24 staliases = ip.db.get('stored_aliases', {})
26 for k,v in staliases.items():
25 for k,v in staliases.items():
27 #print "restore alias",k,v # dbg
26 #print "restore alias",k,v # dbg
28 #self.alias_table[k] = v
27 #self.alias_table[k] = v
29 ip.alias_manager.define_alias(k,v)
28 ip.alias_manager.define_alias(k,v)
30
29
31
30
32 def refresh_variables(ip):
31 def refresh_variables(ip):
33 db = ip.db
32 db = ip.db
34 for key in db.keys('autorestore/*'):
33 for key in db.keys('autorestore/*'):
35 # strip autorestore
34 # strip autorestore
36 justkey = os.path.basename(key)
35 justkey = os.path.basename(key)
37 try:
36 try:
38 obj = db[key]
37 obj = db[key]
39 except KeyError:
38 except KeyError:
40 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
39 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
41 print("The error was:", sys.exc_info()[0])
40 print("The error was:", sys.exc_info()[0])
42 else:
41 else:
43 #print "restored",justkey,"=",obj #dbg
42 #print "restored",justkey,"=",obj #dbg
44 ip.user_ns[justkey] = obj
43 ip.user_ns[justkey] = obj
45
44
46
45
47 def restore_dhist(ip):
46 def restore_dhist(ip):
48 ip.user_ns['_dh'] = ip.db.get('dhist',[])
47 ip.user_ns['_dh'] = ip.db.get('dhist',[])
49
48
50
49
51 def restore_data(ip):
50 def restore_data(ip):
52 refresh_variables(ip)
51 refresh_variables(ip)
53 restore_aliases(ip)
52 restore_aliases(ip)
54 restore_dhist(ip)
53 restore_dhist(ip)
55
54
56
55
57 @magics_class
56 @magics_class
58 class StoreMagics(Magics):
57 class StoreMagics(Magics):
59 """Lightweight persistence for python variables.
58 """Lightweight persistence for python variables.
60
59
61 Provides the %store magic."""
60 Provides the %store magic."""
62
61
63 autorestore = Bool(False, help=
62 autorestore = Bool(False, help=
64 """If True, any %store-d variables will be automatically restored
63 """If True, any %store-d variables will be automatically restored
65 when IPython starts.
64 when IPython starts.
66 """
65 """
67 ).tag(config=True)
66 ).tag(config=True)
68
67
69 def __init__(self, shell):
68 def __init__(self, shell):
70 super(StoreMagics, self).__init__(shell=shell)
69 super(StoreMagics, self).__init__(shell=shell)
71 self.shell.configurables.append(self)
70 self.shell.configurables.append(self)
72 if self.autorestore:
71 if self.autorestore:
73 restore_data(self.shell)
72 restore_data(self.shell)
74
73
75 @line_magic
74 @line_magic
76 def store(self, parameter_s=''):
75 def store(self, parameter_s=''):
77 """Lightweight persistence for python variables.
76 """Lightweight persistence for python variables.
78
77
79 Example::
78 Example::
80
79
81 In [1]: l = ['hello',10,'world']
80 In [1]: l = ['hello',10,'world']
82 In [2]: %store l
81 In [2]: %store l
83 In [3]: exit
82 In [3]: exit
84
83
85 (IPython session is closed and started again...)
84 (IPython session is closed and started again...)
86
85
87 ville@badger:~$ ipython
86 ville@badger:~$ ipython
88 In [1]: l
87 In [1]: l
89 NameError: name 'l' is not defined
88 NameError: name 'l' is not defined
90 In [2]: %store -r
89 In [2]: %store -r
91 In [3]: l
90 In [3]: l
92 Out[3]: ['hello', 10, 'world']
91 Out[3]: ['hello', 10, 'world']
93
92
94 Usage:
93 Usage:
95
94
96 * ``%store`` - Show list of all variables and their current
95 * ``%store`` - Show list of all variables and their current
97 values
96 values
98 * ``%store spam`` - Store the *current* value of the variable spam
97 * ``%store spam`` - Store the *current* value of the variable spam
99 to disk
98 to disk
100 * ``%store -d spam`` - Remove the variable and its value from storage
99 * ``%store -d spam`` - Remove the variable and its value from storage
101 * ``%store -z`` - Remove all variables from storage
100 * ``%store -z`` - Remove all variables from storage
102 * ``%store -r`` - Refresh all variables from store (overwrite
101 * ``%store -r`` - Refresh all variables from store (overwrite
103 current vals)
102 current vals)
104 * ``%store -r spam bar`` - Refresh specified variables from store
103 * ``%store -r spam bar`` - Refresh specified variables from store
105 (delete current val)
104 (delete current val)
106 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
105 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
107 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
106 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
108
107
109 It should be noted that if you change the value of a variable, you
108 It should be noted that if you change the value of a variable, you
110 need to %store it again if you want to persist the new value.
109 need to %store it again if you want to persist the new value.
111
110
112 Note also that the variables will need to be pickleable; most basic
111 Note also that the variables will need to be pickleable; most basic
113 python types can be safely %store'd.
112 python types can be safely %store'd.
114
113
115 Also aliases can be %store'd across sessions.
114 Also aliases can be %store'd across sessions.
116 """
115 """
117
116
118 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
117 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
119 args = argsl.split(None,1)
118 args = argsl.split(None,1)
120 ip = self.shell
119 ip = self.shell
121 db = ip.db
120 db = ip.db
122 # delete
121 # delete
123 if 'd' in opts:
122 if 'd' in opts:
124 try:
123 try:
125 todel = args[0]
124 todel = args[0]
126 except IndexError:
125 except IndexError:
127 raise UsageError('You must provide the variable to forget')
126 raise UsageError('You must provide the variable to forget')
128 else:
127 else:
129 try:
128 try:
130 del db['autorestore/' + todel]
129 del db['autorestore/' + todel]
131 except:
130 except:
132 raise UsageError("Can't delete variable '%s'" % todel)
131 raise UsageError("Can't delete variable '%s'" % todel)
133 # reset
132 # reset
134 elif 'z' in opts:
133 elif 'z' in opts:
135 for k in db.keys('autorestore/*'):
134 for k in db.keys('autorestore/*'):
136 del db[k]
135 del db[k]
137
136
138 elif 'r' in opts:
137 elif 'r' in opts:
139 if args:
138 if args:
140 for arg in args:
139 for arg in args:
141 try:
140 try:
142 obj = db['autorestore/' + arg]
141 obj = db['autorestore/' + arg]
143 except KeyError:
142 except KeyError:
144 print("no stored variable %s" % arg)
143 print("no stored variable %s" % arg)
145 else:
144 else:
146 ip.user_ns[arg] = obj
145 ip.user_ns[arg] = obj
147 else:
146 else:
148 restore_data(ip)
147 restore_data(ip)
149
148
150 # run without arguments -> list variables & values
149 # run without arguments -> list variables & values
151 elif not args:
150 elif not args:
152 vars = db.keys('autorestore/*')
151 vars = db.keys('autorestore/*')
153 vars.sort()
152 vars.sort()
154 if vars:
153 if vars:
155 size = max(map(len, vars))
154 size = max(map(len, vars))
156 else:
155 else:
157 size = 0
156 size = 0
158
157
159 print('Stored variables and their in-db values:')
158 print('Stored variables and their in-db values:')
160 fmt = '%-'+str(size)+'s -> %s'
159 fmt = '%-'+str(size)+'s -> %s'
161 get = db.get
160 get = db.get
162 for var in vars:
161 for var in vars:
163 justkey = os.path.basename(var)
162 justkey = os.path.basename(var)
164 # print 30 first characters from every var
163 # print 30 first characters from every var
165 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
164 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
166
165
167 # default action - store the variable
166 # default action - store the variable
168 else:
167 else:
169 # %store foo >file.txt or >>file.txt
168 # %store foo >file.txt or >>file.txt
170 if len(args) > 1 and args[1].startswith('>'):
169 if len(args) > 1 and args[1].startswith('>'):
171 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
170 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
172 if args[1].startswith('>>'):
171 if args[1].startswith('>>'):
173 fil = open(fnam, 'a')
172 fil = open(fnam, 'a')
174 else:
173 else:
175 fil = open(fnam, 'w')
174 fil = open(fnam, 'w')
176 obj = ip.ev(args[0])
175 obj = ip.ev(args[0])
177 print("Writing '%s' (%s) to file '%s'." % (args[0],
176 print("Writing '%s' (%s) to file '%s'." % (args[0],
178 obj.__class__.__name__, fnam))
177 obj.__class__.__name__, fnam))
179
178
180
179
181 if not isinstance (obj, string_types):
180 if not isinstance (obj, str):
182 from pprint import pprint
181 from pprint import pprint
183 pprint(obj, fil)
182 pprint(obj, fil)
184 else:
183 else:
185 fil.write(obj)
184 fil.write(obj)
186 if not obj.endswith('\n'):
185 if not obj.endswith('\n'):
187 fil.write('\n')
186 fil.write('\n')
188
187
189 fil.close()
188 fil.close()
190 return
189 return
191
190
192 # %store foo
191 # %store foo
193 try:
192 try:
194 obj = ip.user_ns[args[0]]
193 obj = ip.user_ns[args[0]]
195 except KeyError:
194 except KeyError:
196 # it might be an alias
195 # it might be an alias
197 name = args[0]
196 name = args[0]
198 try:
197 try:
199 cmd = ip.alias_manager.retrieve_alias(name)
198 cmd = ip.alias_manager.retrieve_alias(name)
200 except ValueError:
199 except ValueError:
201 raise UsageError("Unknown variable '%s'" % name)
200 raise UsageError("Unknown variable '%s'" % name)
202
201
203 staliases = db.get('stored_aliases',{})
202 staliases = db.get('stored_aliases',{})
204 staliases[name] = cmd
203 staliases[name] = cmd
205 db['stored_aliases'] = staliases
204 db['stored_aliases'] = staliases
206 print("Alias stored: %s (%s)" % (name, cmd))
205 print("Alias stored: %s (%s)" % (name, cmd))
207 return
206 return
208
207
209 else:
208 else:
210 modname = getattr(inspect.getmodule(obj), '__name__', '')
209 modname = getattr(inspect.getmodule(obj), '__name__', '')
211 if modname == '__main__':
210 if modname == '__main__':
212 print(textwrap.dedent("""\
211 print(textwrap.dedent("""\
213 Warning:%s is %s
212 Warning:%s is %s
214 Proper storage of interactively declared classes (or instances
213 Proper storage of interactively declared classes (or instances
215 of those classes) is not possible! Only instances
214 of those classes) is not possible! Only instances
216 of classes in real modules on file system can be %%store'd.
215 of classes in real modules on file system can be %%store'd.
217 """ % (args[0], obj) ))
216 """ % (args[0], obj) ))
218 return
217 return
219 #pickled = pickle.dumps(obj)
218 #pickled = pickle.dumps(obj)
220 db[ 'autorestore/' + args[0] ] = obj
219 db[ 'autorestore/' + args[0] ] = obj
221 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
220 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
222
221
223
222
224 def load_ipython_extension(ip):
223 def load_ipython_extension(ip):
225 """Load the extension in IPython."""
224 """Load the extension in IPython."""
226 ip.register_magics(StoreMagics)
225 ip.register_magics(StoreMagics)
227
226
@@ -1,490 +1,489 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Manage background (threaded) jobs conveniently from an interactive shell.
2 """Manage background (threaded) jobs conveniently from an interactive shell.
3
3
4 This module provides a BackgroundJobManager class. This is the main class
4 This module provides a BackgroundJobManager class. This is the main class
5 meant for public usage, it implements an object which can create and manage
5 meant for public usage, it implements an object which can create and manage
6 new background jobs.
6 new background jobs.
7
7
8 It also provides the actual job classes managed by these BackgroundJobManager
8 It also provides the actual job classes managed by these BackgroundJobManager
9 objects, see their docstrings below.
9 objects, see their docstrings below.
10
10
11
11
12 This system was inspired by discussions with B. Granger and the
12 This system was inspired by discussions with B. Granger and the
13 BackgroundCommand class described in the book Python Scripting for
13 BackgroundCommand class described in the book Python Scripting for
14 Computational Science, by H. P. Langtangen:
14 Computational Science, by H. P. Langtangen:
15
15
16 http://folk.uio.no/hpl/scripting
16 http://folk.uio.no/hpl/scripting
17
17
18 (although ultimately no code from this text was used, as IPython's system is a
18 (although ultimately no code from this text was used, as IPython's system is a
19 separate implementation).
19 separate implementation).
20
20
21 An example notebook is provided in our documentation illustrating interactive
21 An example notebook is provided in our documentation illustrating interactive
22 use of the system.
22 use of the system.
23 """
23 """
24
24
25 #*****************************************************************************
25 #*****************************************************************************
26 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
26 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
27 #
27 #
28 # Distributed under the terms of the BSD License. The full license is in
28 # Distributed under the terms of the BSD License. The full license is in
29 # the file COPYING, distributed as part of this software.
29 # the file COPYING, distributed as part of this software.
30 #*****************************************************************************
30 #*****************************************************************************
31
31
32 # Code begins
32 # Code begins
33 import sys
33 import sys
34 import threading
34 import threading
35
35
36 from IPython import get_ipython
36 from IPython import get_ipython
37 from IPython.core.ultratb import AutoFormattedTB
37 from IPython.core.ultratb import AutoFormattedTB
38 from logging import error
38 from logging import error
39 from IPython.utils.py3compat import string_types
40
39
41
40
42 class BackgroundJobManager(object):
41 class BackgroundJobManager(object):
43 """Class to manage a pool of backgrounded threaded jobs.
42 """Class to manage a pool of backgrounded threaded jobs.
44
43
45 Below, we assume that 'jobs' is a BackgroundJobManager instance.
44 Below, we assume that 'jobs' is a BackgroundJobManager instance.
46
45
47 Usage summary (see the method docstrings for details):
46 Usage summary (see the method docstrings for details):
48
47
49 jobs.new(...) -> start a new job
48 jobs.new(...) -> start a new job
50
49
51 jobs() or jobs.status() -> print status summary of all jobs
50 jobs() or jobs.status() -> print status summary of all jobs
52
51
53 jobs[N] -> returns job number N.
52 jobs[N] -> returns job number N.
54
53
55 foo = jobs[N].result -> assign to variable foo the result of job N
54 foo = jobs[N].result -> assign to variable foo the result of job N
56
55
57 jobs[N].traceback() -> print the traceback of dead job N
56 jobs[N].traceback() -> print the traceback of dead job N
58
57
59 jobs.remove(N) -> remove (finished) job N
58 jobs.remove(N) -> remove (finished) job N
60
59
61 jobs.flush() -> remove all finished jobs
60 jobs.flush() -> remove all finished jobs
62
61
63 As a convenience feature, BackgroundJobManager instances provide the
62 As a convenience feature, BackgroundJobManager instances provide the
64 utility result and traceback methods which retrieve the corresponding
63 utility result and traceback methods which retrieve the corresponding
65 information from the jobs list:
64 information from the jobs list:
66
65
67 jobs.result(N) <--> jobs[N].result
66 jobs.result(N) <--> jobs[N].result
68 jobs.traceback(N) <--> jobs[N].traceback()
67 jobs.traceback(N) <--> jobs[N].traceback()
69
68
70 While this appears minor, it allows you to use tab completion
69 While this appears minor, it allows you to use tab completion
71 interactively on the job manager instance.
70 interactively on the job manager instance.
72 """
71 """
73
72
74 def __init__(self):
73 def __init__(self):
75 # Lists for job management, accessed via a property to ensure they're
74 # Lists for job management, accessed via a property to ensure they're
76 # up to date.x
75 # up to date.x
77 self._running = []
76 self._running = []
78 self._completed = []
77 self._completed = []
79 self._dead = []
78 self._dead = []
80 # A dict of all jobs, so users can easily access any of them
79 # A dict of all jobs, so users can easily access any of them
81 self.all = {}
80 self.all = {}
82 # For reporting
81 # For reporting
83 self._comp_report = []
82 self._comp_report = []
84 self._dead_report = []
83 self._dead_report = []
85 # Store status codes locally for fast lookups
84 # Store status codes locally for fast lookups
86 self._s_created = BackgroundJobBase.stat_created_c
85 self._s_created = BackgroundJobBase.stat_created_c
87 self._s_running = BackgroundJobBase.stat_running_c
86 self._s_running = BackgroundJobBase.stat_running_c
88 self._s_completed = BackgroundJobBase.stat_completed_c
87 self._s_completed = BackgroundJobBase.stat_completed_c
89 self._s_dead = BackgroundJobBase.stat_dead_c
88 self._s_dead = BackgroundJobBase.stat_dead_c
90
89
91 @property
90 @property
92 def running(self):
91 def running(self):
93 self._update_status()
92 self._update_status()
94 return self._running
93 return self._running
95
94
96 @property
95 @property
97 def dead(self):
96 def dead(self):
98 self._update_status()
97 self._update_status()
99 return self._dead
98 return self._dead
100
99
101 @property
100 @property
102 def completed(self):
101 def completed(self):
103 self._update_status()
102 self._update_status()
104 return self._completed
103 return self._completed
105
104
106 def new(self, func_or_exp, *args, **kwargs):
105 def new(self, func_or_exp, *args, **kwargs):
107 """Add a new background job and start it in a separate thread.
106 """Add a new background job and start it in a separate thread.
108
107
109 There are two types of jobs which can be created:
108 There are two types of jobs which can be created:
110
109
111 1. Jobs based on expressions which can be passed to an eval() call.
110 1. Jobs based on expressions which can be passed to an eval() call.
112 The expression must be given as a string. For example:
111 The expression must be given as a string. For example:
113
112
114 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
113 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
115
114
116 The given expression is passed to eval(), along with the optional
115 The given expression is passed to eval(), along with the optional
117 global/local dicts provided. If no dicts are given, they are
116 global/local dicts provided. If no dicts are given, they are
118 extracted automatically from the caller's frame.
117 extracted automatically from the caller's frame.
119
118
120 A Python statement is NOT a valid eval() expression. Basically, you
119 A Python statement is NOT a valid eval() expression. Basically, you
121 can only use as an eval() argument something which can go on the right
120 can only use as an eval() argument something which can go on the right
122 of an '=' sign and be assigned to a variable.
121 of an '=' sign and be assigned to a variable.
123
122
124 For example,"print 'hello'" is not valid, but '2+3' is.
123 For example,"print 'hello'" is not valid, but '2+3' is.
125
124
126 2. Jobs given a function object, optionally passing additional
125 2. Jobs given a function object, optionally passing additional
127 positional arguments:
126 positional arguments:
128
127
129 job_manager.new(myfunc, x, y)
128 job_manager.new(myfunc, x, y)
130
129
131 The function is called with the given arguments.
130 The function is called with the given arguments.
132
131
133 If you need to pass keyword arguments to your function, you must
132 If you need to pass keyword arguments to your function, you must
134 supply them as a dict named kw:
133 supply them as a dict named kw:
135
134
136 job_manager.new(myfunc, x, y, kw=dict(z=1))
135 job_manager.new(myfunc, x, y, kw=dict(z=1))
137
136
138 The reason for this assymmetry is that the new() method needs to
137 The reason for this assymmetry is that the new() method needs to
139 maintain access to its own keywords, and this prevents name collisions
138 maintain access to its own keywords, and this prevents name collisions
140 between arguments to new() and arguments to your own functions.
139 between arguments to new() and arguments to your own functions.
141
140
142 In both cases, the result is stored in the job.result field of the
141 In both cases, the result is stored in the job.result field of the
143 background job object.
142 background job object.
144
143
145 You can set `daemon` attribute of the thread by giving the keyword
144 You can set `daemon` attribute of the thread by giving the keyword
146 argument `daemon`.
145 argument `daemon`.
147
146
148 Notes and caveats:
147 Notes and caveats:
149
148
150 1. All threads running share the same standard output. Thus, if your
149 1. All threads running share the same standard output. Thus, if your
151 background jobs generate output, it will come out on top of whatever
150 background jobs generate output, it will come out on top of whatever
152 you are currently writing. For this reason, background jobs are best
151 you are currently writing. For this reason, background jobs are best
153 used with silent functions which simply return their output.
152 used with silent functions which simply return their output.
154
153
155 2. Threads also all work within the same global namespace, and this
154 2. Threads also all work within the same global namespace, and this
156 system does not lock interactive variables. So if you send job to the
155 system does not lock interactive variables. So if you send job to the
157 background which operates on a mutable object for a long time, and
156 background which operates on a mutable object for a long time, and
158 start modifying that same mutable object interactively (or in another
157 start modifying that same mutable object interactively (or in another
159 backgrounded job), all sorts of bizarre behaviour will occur.
158 backgrounded job), all sorts of bizarre behaviour will occur.
160
159
161 3. If a background job is spending a lot of time inside a C extension
160 3. If a background job is spending a lot of time inside a C extension
162 module which does not release the Python Global Interpreter Lock
161 module which does not release the Python Global Interpreter Lock
163 (GIL), this will block the IPython prompt. This is simply because the
162 (GIL), this will block the IPython prompt. This is simply because the
164 Python interpreter can only switch between threads at Python
163 Python interpreter can only switch between threads at Python
165 bytecodes. While the execution is inside C code, the interpreter must
164 bytecodes. While the execution is inside C code, the interpreter must
166 simply wait unless the extension module releases the GIL.
165 simply wait unless the extension module releases the GIL.
167
166
168 4. There is no way, due to limitations in the Python threads library,
167 4. There is no way, due to limitations in the Python threads library,
169 to kill a thread once it has started."""
168 to kill a thread once it has started."""
170
169
171 if callable(func_or_exp):
170 if callable(func_or_exp):
172 kw = kwargs.get('kw',{})
171 kw = kwargs.get('kw',{})
173 job = BackgroundJobFunc(func_or_exp,*args,**kw)
172 job = BackgroundJobFunc(func_or_exp,*args,**kw)
174 elif isinstance(func_or_exp, string_types):
173 elif isinstance(func_or_exp, str):
175 if not args:
174 if not args:
176 frame = sys._getframe(1)
175 frame = sys._getframe(1)
177 glob, loc = frame.f_globals, frame.f_locals
176 glob, loc = frame.f_globals, frame.f_locals
178 elif len(args)==1:
177 elif len(args)==1:
179 glob = loc = args[0]
178 glob = loc = args[0]
180 elif len(args)==2:
179 elif len(args)==2:
181 glob,loc = args
180 glob,loc = args
182 else:
181 else:
183 raise ValueError(
182 raise ValueError(
184 'Expression jobs take at most 2 args (globals,locals)')
183 'Expression jobs take at most 2 args (globals,locals)')
185 job = BackgroundJobExpr(func_or_exp, glob, loc)
184 job = BackgroundJobExpr(func_or_exp, glob, loc)
186 else:
185 else:
187 raise TypeError('invalid args for new job')
186 raise TypeError('invalid args for new job')
188
187
189 if kwargs.get('daemon', False):
188 if kwargs.get('daemon', False):
190 job.daemon = True
189 job.daemon = True
191 job.num = len(self.all)+1 if self.all else 0
190 job.num = len(self.all)+1 if self.all else 0
192 self.running.append(job)
191 self.running.append(job)
193 self.all[job.num] = job
192 self.all[job.num] = job
194 print('Starting job # %s in a separate thread.' % job.num)
193 print('Starting job # %s in a separate thread.' % job.num)
195 job.start()
194 job.start()
196 return job
195 return job
197
196
198 def __getitem__(self, job_key):
197 def __getitem__(self, job_key):
199 num = job_key if isinstance(job_key, int) else job_key.num
198 num = job_key if isinstance(job_key, int) else job_key.num
200 return self.all[num]
199 return self.all[num]
201
200
202 def __call__(self):
201 def __call__(self):
203 """An alias to self.status(),
202 """An alias to self.status(),
204
203
205 This allows you to simply call a job manager instance much like the
204 This allows you to simply call a job manager instance much like the
206 Unix `jobs` shell command."""
205 Unix `jobs` shell command."""
207
206
208 return self.status()
207 return self.status()
209
208
210 def _update_status(self):
209 def _update_status(self):
211 """Update the status of the job lists.
210 """Update the status of the job lists.
212
211
213 This method moves finished jobs to one of two lists:
212 This method moves finished jobs to one of two lists:
214 - self.completed: jobs which completed successfully
213 - self.completed: jobs which completed successfully
215 - self.dead: jobs which finished but died.
214 - self.dead: jobs which finished but died.
216
215
217 It also copies those jobs to corresponding _report lists. These lists
216 It also copies those jobs to corresponding _report lists. These lists
218 are used to report jobs completed/dead since the last update, and are
217 are used to report jobs completed/dead since the last update, and are
219 then cleared by the reporting function after each call."""
218 then cleared by the reporting function after each call."""
220
219
221 # Status codes
220 # Status codes
222 srun, scomp, sdead = self._s_running, self._s_completed, self._s_dead
221 srun, scomp, sdead = self._s_running, self._s_completed, self._s_dead
223 # State lists, use the actual lists b/c the public names are properties
222 # State lists, use the actual lists b/c the public names are properties
224 # that call this very function on access
223 # that call this very function on access
225 running, completed, dead = self._running, self._completed, self._dead
224 running, completed, dead = self._running, self._completed, self._dead
226
225
227 # Now, update all state lists
226 # Now, update all state lists
228 for num, job in enumerate(running):
227 for num, job in enumerate(running):
229 stat = job.stat_code
228 stat = job.stat_code
230 if stat == srun:
229 if stat == srun:
231 continue
230 continue
232 elif stat == scomp:
231 elif stat == scomp:
233 completed.append(job)
232 completed.append(job)
234 self._comp_report.append(job)
233 self._comp_report.append(job)
235 running[num] = False
234 running[num] = False
236 elif stat == sdead:
235 elif stat == sdead:
237 dead.append(job)
236 dead.append(job)
238 self._dead_report.append(job)
237 self._dead_report.append(job)
239 running[num] = False
238 running[num] = False
240 # Remove dead/completed jobs from running list
239 # Remove dead/completed jobs from running list
241 running[:] = filter(None, running)
240 running[:] = filter(None, running)
242
241
243 def _group_report(self,group,name):
242 def _group_report(self,group,name):
244 """Report summary for a given job group.
243 """Report summary for a given job group.
245
244
246 Return True if the group had any elements."""
245 Return True if the group had any elements."""
247
246
248 if group:
247 if group:
249 print('%s jobs:' % name)
248 print('%s jobs:' % name)
250 for job in group:
249 for job in group:
251 print('%s : %s' % (job.num,job))
250 print('%s : %s' % (job.num,job))
252 print()
251 print()
253 return True
252 return True
254
253
255 def _group_flush(self,group,name):
254 def _group_flush(self,group,name):
256 """Flush a given job group
255 """Flush a given job group
257
256
258 Return True if the group had any elements."""
257 Return True if the group had any elements."""
259
258
260 njobs = len(group)
259 njobs = len(group)
261 if njobs:
260 if njobs:
262 plural = {1:''}.setdefault(njobs,'s')
261 plural = {1:''}.setdefault(njobs,'s')
263 print('Flushing %s %s job%s.' % (njobs,name,plural))
262 print('Flushing %s %s job%s.' % (njobs,name,plural))
264 group[:] = []
263 group[:] = []
265 return True
264 return True
266
265
267 def _status_new(self):
266 def _status_new(self):
268 """Print the status of newly finished jobs.
267 """Print the status of newly finished jobs.
269
268
270 Return True if any new jobs are reported.
269 Return True if any new jobs are reported.
271
270
272 This call resets its own state every time, so it only reports jobs
271 This call resets its own state every time, so it only reports jobs
273 which have finished since the last time it was called."""
272 which have finished since the last time it was called."""
274
273
275 self._update_status()
274 self._update_status()
276 new_comp = self._group_report(self._comp_report, 'Completed')
275 new_comp = self._group_report(self._comp_report, 'Completed')
277 new_dead = self._group_report(self._dead_report,
276 new_dead = self._group_report(self._dead_report,
278 'Dead, call jobs.traceback() for details')
277 'Dead, call jobs.traceback() for details')
279 self._comp_report[:] = []
278 self._comp_report[:] = []
280 self._dead_report[:] = []
279 self._dead_report[:] = []
281 return new_comp or new_dead
280 return new_comp or new_dead
282
281
283 def status(self,verbose=0):
282 def status(self,verbose=0):
284 """Print a status of all jobs currently being managed."""
283 """Print a status of all jobs currently being managed."""
285
284
286 self._update_status()
285 self._update_status()
287 self._group_report(self.running,'Running')
286 self._group_report(self.running,'Running')
288 self._group_report(self.completed,'Completed')
287 self._group_report(self.completed,'Completed')
289 self._group_report(self.dead,'Dead')
288 self._group_report(self.dead,'Dead')
290 # Also flush the report queues
289 # Also flush the report queues
291 self._comp_report[:] = []
290 self._comp_report[:] = []
292 self._dead_report[:] = []
291 self._dead_report[:] = []
293
292
294 def remove(self,num):
293 def remove(self,num):
295 """Remove a finished (completed or dead) job."""
294 """Remove a finished (completed or dead) job."""
296
295
297 try:
296 try:
298 job = self.all[num]
297 job = self.all[num]
299 except KeyError:
298 except KeyError:
300 error('Job #%s not found' % num)
299 error('Job #%s not found' % num)
301 else:
300 else:
302 stat_code = job.stat_code
301 stat_code = job.stat_code
303 if stat_code == self._s_running:
302 if stat_code == self._s_running:
304 error('Job #%s is still running, it can not be removed.' % num)
303 error('Job #%s is still running, it can not be removed.' % num)
305 return
304 return
306 elif stat_code == self._s_completed:
305 elif stat_code == self._s_completed:
307 self.completed.remove(job)
306 self.completed.remove(job)
308 elif stat_code == self._s_dead:
307 elif stat_code == self._s_dead:
309 self.dead.remove(job)
308 self.dead.remove(job)
310
309
311 def flush(self):
310 def flush(self):
312 """Flush all finished jobs (completed and dead) from lists.
311 """Flush all finished jobs (completed and dead) from lists.
313
312
314 Running jobs are never flushed.
313 Running jobs are never flushed.
315
314
316 It first calls _status_new(), to update info. If any jobs have
315 It first calls _status_new(), to update info. If any jobs have
317 completed since the last _status_new() call, the flush operation
316 completed since the last _status_new() call, the flush operation
318 aborts."""
317 aborts."""
319
318
320 # Remove the finished jobs from the master dict
319 # Remove the finished jobs from the master dict
321 alljobs = self.all
320 alljobs = self.all
322 for job in self.completed+self.dead:
321 for job in self.completed+self.dead:
323 del(alljobs[job.num])
322 del(alljobs[job.num])
324
323
325 # Now flush these lists completely
324 # Now flush these lists completely
326 fl_comp = self._group_flush(self.completed, 'Completed')
325 fl_comp = self._group_flush(self.completed, 'Completed')
327 fl_dead = self._group_flush(self.dead, 'Dead')
326 fl_dead = self._group_flush(self.dead, 'Dead')
328 if not (fl_comp or fl_dead):
327 if not (fl_comp or fl_dead):
329 print('No jobs to flush.')
328 print('No jobs to flush.')
330
329
331 def result(self,num):
330 def result(self,num):
332 """result(N) -> return the result of job N."""
331 """result(N) -> return the result of job N."""
333 try:
332 try:
334 return self.all[num].result
333 return self.all[num].result
335 except KeyError:
334 except KeyError:
336 error('Job #%s not found' % num)
335 error('Job #%s not found' % num)
337
336
338 def _traceback(self, job):
337 def _traceback(self, job):
339 num = job if isinstance(job, int) else job.num
338 num = job if isinstance(job, int) else job.num
340 try:
339 try:
341 self.all[num].traceback()
340 self.all[num].traceback()
342 except KeyError:
341 except KeyError:
343 error('Job #%s not found' % num)
342 error('Job #%s not found' % num)
344
343
345 def traceback(self, job=None):
344 def traceback(self, job=None):
346 if job is None:
345 if job is None:
347 self._update_status()
346 self._update_status()
348 for deadjob in self.dead:
347 for deadjob in self.dead:
349 print("Traceback for: %r" % deadjob)
348 print("Traceback for: %r" % deadjob)
350 self._traceback(deadjob)
349 self._traceback(deadjob)
351 print()
350 print()
352 else:
351 else:
353 self._traceback(job)
352 self._traceback(job)
354
353
355
354
356 class BackgroundJobBase(threading.Thread):
355 class BackgroundJobBase(threading.Thread):
357 """Base class to build BackgroundJob classes.
356 """Base class to build BackgroundJob classes.
358
357
359 The derived classes must implement:
358 The derived classes must implement:
360
359
361 - Their own __init__, since the one here raises NotImplementedError. The
360 - Their own __init__, since the one here raises NotImplementedError. The
362 derived constructor must call self._init() at the end, to provide common
361 derived constructor must call self._init() at the end, to provide common
363 initialization.
362 initialization.
364
363
365 - A strform attribute used in calls to __str__.
364 - A strform attribute used in calls to __str__.
366
365
367 - A call() method, which will make the actual execution call and must
366 - A call() method, which will make the actual execution call and must
368 return a value to be held in the 'result' field of the job object.
367 return a value to be held in the 'result' field of the job object.
369 """
368 """
370
369
371 # Class constants for status, in string and as numerical codes (when
370 # Class constants for status, in string and as numerical codes (when
372 # updating jobs lists, we don't want to do string comparisons). This will
371 # updating jobs lists, we don't want to do string comparisons). This will
373 # be done at every user prompt, so it has to be as fast as possible
372 # be done at every user prompt, so it has to be as fast as possible
374 stat_created = 'Created'; stat_created_c = 0
373 stat_created = 'Created'; stat_created_c = 0
375 stat_running = 'Running'; stat_running_c = 1
374 stat_running = 'Running'; stat_running_c = 1
376 stat_completed = 'Completed'; stat_completed_c = 2
375 stat_completed = 'Completed'; stat_completed_c = 2
377 stat_dead = 'Dead (Exception), call jobs.traceback() for details'
376 stat_dead = 'Dead (Exception), call jobs.traceback() for details'
378 stat_dead_c = -1
377 stat_dead_c = -1
379
378
380 def __init__(self):
379 def __init__(self):
381 """Must be implemented in subclasses.
380 """Must be implemented in subclasses.
382
381
383 Subclasses must call :meth:`_init` for standard initialisation.
382 Subclasses must call :meth:`_init` for standard initialisation.
384 """
383 """
385 raise NotImplementedError("This class can not be instantiated directly.")
384 raise NotImplementedError("This class can not be instantiated directly.")
386
385
387 def _init(self):
386 def _init(self):
388 """Common initialization for all BackgroundJob objects"""
387 """Common initialization for all BackgroundJob objects"""
389
388
390 for attr in ['call','strform']:
389 for attr in ['call','strform']:
391 assert hasattr(self,attr), "Missing attribute <%s>" % attr
390 assert hasattr(self,attr), "Missing attribute <%s>" % attr
392
391
393 # The num tag can be set by an external job manager
392 # The num tag can be set by an external job manager
394 self.num = None
393 self.num = None
395
394
396 self.status = BackgroundJobBase.stat_created
395 self.status = BackgroundJobBase.stat_created
397 self.stat_code = BackgroundJobBase.stat_created_c
396 self.stat_code = BackgroundJobBase.stat_created_c
398 self.finished = False
397 self.finished = False
399 self.result = '<BackgroundJob has not completed>'
398 self.result = '<BackgroundJob has not completed>'
400
399
401 # reuse the ipython traceback handler if we can get to it, otherwise
400 # reuse the ipython traceback handler if we can get to it, otherwise
402 # make a new one
401 # make a new one
403 try:
402 try:
404 make_tb = get_ipython().InteractiveTB.text
403 make_tb = get_ipython().InteractiveTB.text
405 except:
404 except:
406 make_tb = AutoFormattedTB(mode = 'Context',
405 make_tb = AutoFormattedTB(mode = 'Context',
407 color_scheme='NoColor',
406 color_scheme='NoColor',
408 tb_offset = 1).text
407 tb_offset = 1).text
409 # Note that the actual API for text() requires the three args to be
408 # Note that the actual API for text() requires the three args to be
410 # passed in, so we wrap it in a simple lambda.
409 # passed in, so we wrap it in a simple lambda.
411 self._make_tb = lambda : make_tb(None, None, None)
410 self._make_tb = lambda : make_tb(None, None, None)
412
411
413 # Hold a formatted traceback if one is generated.
412 # Hold a formatted traceback if one is generated.
414 self._tb = None
413 self._tb = None
415
414
416 threading.Thread.__init__(self)
415 threading.Thread.__init__(self)
417
416
418 def __str__(self):
417 def __str__(self):
419 return self.strform
418 return self.strform
420
419
421 def __repr__(self):
420 def __repr__(self):
422 return '<BackgroundJob #%d: %s>' % (self.num, self.strform)
421 return '<BackgroundJob #%d: %s>' % (self.num, self.strform)
423
422
424 def traceback(self):
423 def traceback(self):
425 print(self._tb)
424 print(self._tb)
426
425
427 def run(self):
426 def run(self):
428 try:
427 try:
429 self.status = BackgroundJobBase.stat_running
428 self.status = BackgroundJobBase.stat_running
430 self.stat_code = BackgroundJobBase.stat_running_c
429 self.stat_code = BackgroundJobBase.stat_running_c
431 self.result = self.call()
430 self.result = self.call()
432 except:
431 except:
433 self.status = BackgroundJobBase.stat_dead
432 self.status = BackgroundJobBase.stat_dead
434 self.stat_code = BackgroundJobBase.stat_dead_c
433 self.stat_code = BackgroundJobBase.stat_dead_c
435 self.finished = None
434 self.finished = None
436 self.result = ('<BackgroundJob died, call jobs.traceback() for details>')
435 self.result = ('<BackgroundJob died, call jobs.traceback() for details>')
437 self._tb = self._make_tb()
436 self._tb = self._make_tb()
438 else:
437 else:
439 self.status = BackgroundJobBase.stat_completed
438 self.status = BackgroundJobBase.stat_completed
440 self.stat_code = BackgroundJobBase.stat_completed_c
439 self.stat_code = BackgroundJobBase.stat_completed_c
441 self.finished = True
440 self.finished = True
442
441
443
442
444 class BackgroundJobExpr(BackgroundJobBase):
443 class BackgroundJobExpr(BackgroundJobBase):
445 """Evaluate an expression as a background job (uses a separate thread)."""
444 """Evaluate an expression as a background job (uses a separate thread)."""
446
445
447 def __init__(self, expression, glob=None, loc=None):
446 def __init__(self, expression, glob=None, loc=None):
448 """Create a new job from a string which can be fed to eval().
447 """Create a new job from a string which can be fed to eval().
449
448
450 global/locals dicts can be provided, which will be passed to the eval
449 global/locals dicts can be provided, which will be passed to the eval
451 call."""
450 call."""
452
451
453 # fail immediately if the given expression can't be compiled
452 # fail immediately if the given expression can't be compiled
454 self.code = compile(expression,'<BackgroundJob compilation>','eval')
453 self.code = compile(expression,'<BackgroundJob compilation>','eval')
455
454
456 glob = {} if glob is None else glob
455 glob = {} if glob is None else glob
457 loc = {} if loc is None else loc
456 loc = {} if loc is None else loc
458 self.expression = self.strform = expression
457 self.expression = self.strform = expression
459 self.glob = glob
458 self.glob = glob
460 self.loc = loc
459 self.loc = loc
461 self._init()
460 self._init()
462
461
463 def call(self):
462 def call(self):
464 return eval(self.code,self.glob,self.loc)
463 return eval(self.code,self.glob,self.loc)
465
464
466
465
467 class BackgroundJobFunc(BackgroundJobBase):
466 class BackgroundJobFunc(BackgroundJobBase):
468 """Run a function call as a background job (uses a separate thread)."""
467 """Run a function call as a background job (uses a separate thread)."""
469
468
470 def __init__(self, func, *args, **kwargs):
469 def __init__(self, func, *args, **kwargs):
471 """Create a new job from a callable object.
470 """Create a new job from a callable object.
472
471
473 Any positional arguments and keyword args given to this constructor
472 Any positional arguments and keyword args given to this constructor
474 after the initial callable are passed directly to it."""
473 after the initial callable are passed directly to it."""
475
474
476 if not callable(func):
475 if not callable(func):
477 raise TypeError(
476 raise TypeError(
478 'first argument to BackgroundJobFunc must be callable')
477 'first argument to BackgroundJobFunc must be callable')
479
478
480 self.func = func
479 self.func = func
481 self.args = args
480 self.args = args
482 self.kwargs = kwargs
481 self.kwargs = kwargs
483 # The string form will only include the function passed, because
482 # The string form will only include the function passed, because
484 # generating string representations of the arguments is a potentially
483 # generating string representations of the arguments is a potentially
485 # _very_ expensive operation (e.g. with large arrays).
484 # _very_ expensive operation (e.g. with large arrays).
486 self.strform = str(func)
485 self.strform = str(func)
487 self._init()
486 self._init()
488
487
489 def call(self):
488 def call(self):
490 return self.func(*self.args, **self.kwargs)
489 return self.func(*self.args, **self.kwargs)
@@ -1,867 +1,866 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Python advanced pretty printer. This pretty printer is intended to
3 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
4 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
5 to provide their own pretty print callbacks.
6
6
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
8
9
9
10 Example Usage
10 Example Usage
11 -------------
11 -------------
12
12
13 To directly print the representation of an object use `pprint`::
13 To directly print the representation of an object use `pprint`::
14
14
15 from pretty import pprint
15 from pretty import pprint
16 pprint(complex_object)
16 pprint(complex_object)
17
17
18 To get a string of the output use `pretty`::
18 To get a string of the output use `pretty`::
19
19
20 from pretty import pretty
20 from pretty import pretty
21 string = pretty(complex_object)
21 string = pretty(complex_object)
22
22
23
23
24 Extending
24 Extending
25 ---------
25 ---------
26
26
27 The pretty library allows developers to add pretty printing rules for their
27 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
28 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
29 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
30 pretty printer passed::
31
31
32 class MyObject(object):
32 class MyObject(object):
33
33
34 def _repr_pretty_(self, p, cycle):
34 def _repr_pretty_(self, p, cycle):
35 ...
35 ...
36
36
37 Here is an example implementation of a `_repr_pretty_` method for a list
37 Here is an example implementation of a `_repr_pretty_` method for a list
38 subclass::
38 subclass::
39
39
40 class MyList(list):
40 class MyList(list):
41
41
42 def _repr_pretty_(self, p, cycle):
42 def _repr_pretty_(self, p, cycle):
43 if cycle:
43 if cycle:
44 p.text('MyList(...)')
44 p.text('MyList(...)')
45 else:
45 else:
46 with p.group(8, 'MyList([', '])'):
46 with p.group(8, 'MyList([', '])'):
47 for idx, item in enumerate(self):
47 for idx, item in enumerate(self):
48 if idx:
48 if idx:
49 p.text(',')
49 p.text(',')
50 p.breakable()
50 p.breakable()
51 p.pretty(item)
51 p.pretty(item)
52
52
53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
54 react to that or the result is an infinite loop. `p.text()` just adds
54 react to that or the result is an infinite loop. `p.text()` just adds
55 non breaking text to the output, `p.breakable()` either adds a whitespace
55 non breaking text to the output, `p.breakable()` either adds a whitespace
56 or breaks here. If you pass it an argument it's used instead of the
56 or breaks here. If you pass it an argument it's used instead of the
57 default space. `p.pretty` prettyprints another object using the pretty print
57 default space. `p.pretty` prettyprints another object using the pretty print
58 method.
58 method.
59
59
60 The first parameter to the `group` function specifies the extra indentation
60 The first parameter to the `group` function specifies the extra indentation
61 of the next line. In this example the next item will either be on the same
61 of the next line. In this example the next item will either be on the same
62 line (if the items are short enough) or aligned with the right edge of the
62 line (if the items are short enough) or aligned with the right edge of the
63 opening bracket of `MyList`.
63 opening bracket of `MyList`.
64
64
65 If you just want to indent something you can use the group function
65 If you just want to indent something you can use the group function
66 without open / close parameters. You can also use this code::
66 without open / close parameters. You can also use this code::
67
67
68 with p.indent(2):
68 with p.indent(2):
69 ...
69 ...
70
70
71 Inheritance diagram:
71 Inheritance diagram:
72
72
73 .. inheritance-diagram:: IPython.lib.pretty
73 .. inheritance-diagram:: IPython.lib.pretty
74 :parts: 3
74 :parts: 3
75
75
76 :copyright: 2007 by Armin Ronacher.
76 :copyright: 2007 by Armin Ronacher.
77 Portions (c) 2009 by Robert Kern.
77 Portions (c) 2009 by Robert Kern.
78 :license: BSD License.
78 :license: BSD License.
79 """
79 """
80 from contextlib import contextmanager
80 from contextlib import contextmanager
81 import sys
81 import sys
82 import types
82 import types
83 import re
83 import re
84 import datetime
84 import datetime
85 from collections import deque
85 from collections import deque
86
86
87 from IPython.utils.py3compat import PY3, PYPY, cast_unicode, string_types
87 from IPython.utils.py3compat import PY3, PYPY, cast_unicode
88 from IPython.utils.encoding import get_stream_enc
88 from IPython.utils.encoding import get_stream_enc
89
89
90 from io import StringIO
90 from io import StringIO
91
91
92
92
93 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
93 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
94 'for_type', 'for_type_by_name']
94 'for_type', 'for_type_by_name']
95
95
96
96
97 MAX_SEQ_LENGTH = 1000
97 MAX_SEQ_LENGTH = 1000
98 _re_pattern_type = type(re.compile(''))
98 _re_pattern_type = type(re.compile(''))
99
99
100 def _safe_getattr(obj, attr, default=None):
100 def _safe_getattr(obj, attr, default=None):
101 """Safe version of getattr.
101 """Safe version of getattr.
102
102
103 Same as getattr, but will return ``default`` on any Exception,
103 Same as getattr, but will return ``default`` on any Exception,
104 rather than raising.
104 rather than raising.
105 """
105 """
106 try:
106 try:
107 return getattr(obj, attr, default)
107 return getattr(obj, attr, default)
108 except Exception:
108 except Exception:
109 return default
109 return default
110
110
111 if PY3:
111 if PY3:
112 CUnicodeIO = StringIO
112 CUnicodeIO = StringIO
113 else:
113 else:
114 class CUnicodeIO(StringIO):
114 class CUnicodeIO(StringIO):
115 """StringIO that casts str to unicode on Python 2"""
115 """StringIO that casts str to unicode on Python 2"""
116 def write(self, text):
116 def write(self, text):
117 return super(CUnicodeIO, self).write(
117 return super(CUnicodeIO, self).write(
118 cast_unicode(text, encoding=get_stream_enc(sys.stdout)))
118 cast_unicode(text, encoding=get_stream_enc(sys.stdout)))
119
119
120
120
121 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
121 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
122 """
122 """
123 Pretty print the object's representation.
123 Pretty print the object's representation.
124 """
124 """
125 stream = CUnicodeIO()
125 stream = CUnicodeIO()
126 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
126 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
127 printer.pretty(obj)
127 printer.pretty(obj)
128 printer.flush()
128 printer.flush()
129 return stream.getvalue()
129 return stream.getvalue()
130
130
131
131
132 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
132 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
133 """
133 """
134 Like `pretty` but print to stdout.
134 Like `pretty` but print to stdout.
135 """
135 """
136 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
136 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
137 printer.pretty(obj)
137 printer.pretty(obj)
138 printer.flush()
138 printer.flush()
139 sys.stdout.write(newline)
139 sys.stdout.write(newline)
140 sys.stdout.flush()
140 sys.stdout.flush()
141
141
142 class _PrettyPrinterBase(object):
142 class _PrettyPrinterBase(object):
143
143
144 @contextmanager
144 @contextmanager
145 def indent(self, indent):
145 def indent(self, indent):
146 """with statement support for indenting/dedenting."""
146 """with statement support for indenting/dedenting."""
147 self.indentation += indent
147 self.indentation += indent
148 try:
148 try:
149 yield
149 yield
150 finally:
150 finally:
151 self.indentation -= indent
151 self.indentation -= indent
152
152
153 @contextmanager
153 @contextmanager
154 def group(self, indent=0, open='', close=''):
154 def group(self, indent=0, open='', close=''):
155 """like begin_group / end_group but for the with statement."""
155 """like begin_group / end_group but for the with statement."""
156 self.begin_group(indent, open)
156 self.begin_group(indent, open)
157 try:
157 try:
158 yield
158 yield
159 finally:
159 finally:
160 self.end_group(indent, close)
160 self.end_group(indent, close)
161
161
162 class PrettyPrinter(_PrettyPrinterBase):
162 class PrettyPrinter(_PrettyPrinterBase):
163 """
163 """
164 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
164 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
165 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
165 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
166 this printer knows nothing about the default pprinters or the `_repr_pretty_`
166 this printer knows nothing about the default pprinters or the `_repr_pretty_`
167 callback method.
167 callback method.
168 """
168 """
169
169
170 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
170 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
171 self.output = output
171 self.output = output
172 self.max_width = max_width
172 self.max_width = max_width
173 self.newline = newline
173 self.newline = newline
174 self.max_seq_length = max_seq_length
174 self.max_seq_length = max_seq_length
175 self.output_width = 0
175 self.output_width = 0
176 self.buffer_width = 0
176 self.buffer_width = 0
177 self.buffer = deque()
177 self.buffer = deque()
178
178
179 root_group = Group(0)
179 root_group = Group(0)
180 self.group_stack = [root_group]
180 self.group_stack = [root_group]
181 self.group_queue = GroupQueue(root_group)
181 self.group_queue = GroupQueue(root_group)
182 self.indentation = 0
182 self.indentation = 0
183
183
184 def _break_outer_groups(self):
184 def _break_outer_groups(self):
185 while self.max_width < self.output_width + self.buffer_width:
185 while self.max_width < self.output_width + self.buffer_width:
186 group = self.group_queue.deq()
186 group = self.group_queue.deq()
187 if not group:
187 if not group:
188 return
188 return
189 while group.breakables:
189 while group.breakables:
190 x = self.buffer.popleft()
190 x = self.buffer.popleft()
191 self.output_width = x.output(self.output, self.output_width)
191 self.output_width = x.output(self.output, self.output_width)
192 self.buffer_width -= x.width
192 self.buffer_width -= x.width
193 while self.buffer and isinstance(self.buffer[0], Text):
193 while self.buffer and isinstance(self.buffer[0], Text):
194 x = self.buffer.popleft()
194 x = self.buffer.popleft()
195 self.output_width = x.output(self.output, self.output_width)
195 self.output_width = x.output(self.output, self.output_width)
196 self.buffer_width -= x.width
196 self.buffer_width -= x.width
197
197
198 def text(self, obj):
198 def text(self, obj):
199 """Add literal text to the output."""
199 """Add literal text to the output."""
200 width = len(obj)
200 width = len(obj)
201 if self.buffer:
201 if self.buffer:
202 text = self.buffer[-1]
202 text = self.buffer[-1]
203 if not isinstance(text, Text):
203 if not isinstance(text, Text):
204 text = Text()
204 text = Text()
205 self.buffer.append(text)
205 self.buffer.append(text)
206 text.add(obj, width)
206 text.add(obj, width)
207 self.buffer_width += width
207 self.buffer_width += width
208 self._break_outer_groups()
208 self._break_outer_groups()
209 else:
209 else:
210 self.output.write(obj)
210 self.output.write(obj)
211 self.output_width += width
211 self.output_width += width
212
212
213 def breakable(self, sep=' '):
213 def breakable(self, sep=' '):
214 """
214 """
215 Add a breakable separator to the output. This does not mean that it
215 Add a breakable separator to the output. This does not mean that it
216 will automatically break here. If no breaking on this position takes
216 will automatically break here. If no breaking on this position takes
217 place the `sep` is inserted which default to one space.
217 place the `sep` is inserted which default to one space.
218 """
218 """
219 width = len(sep)
219 width = len(sep)
220 group = self.group_stack[-1]
220 group = self.group_stack[-1]
221 if group.want_break:
221 if group.want_break:
222 self.flush()
222 self.flush()
223 self.output.write(self.newline)
223 self.output.write(self.newline)
224 self.output.write(' ' * self.indentation)
224 self.output.write(' ' * self.indentation)
225 self.output_width = self.indentation
225 self.output_width = self.indentation
226 self.buffer_width = 0
226 self.buffer_width = 0
227 else:
227 else:
228 self.buffer.append(Breakable(sep, width, self))
228 self.buffer.append(Breakable(sep, width, self))
229 self.buffer_width += width
229 self.buffer_width += width
230 self._break_outer_groups()
230 self._break_outer_groups()
231
231
232 def break_(self):
232 def break_(self):
233 """
233 """
234 Explicitly insert a newline into the output, maintaining correct indentation.
234 Explicitly insert a newline into the output, maintaining correct indentation.
235 """
235 """
236 self.flush()
236 self.flush()
237 self.output.write(self.newline)
237 self.output.write(self.newline)
238 self.output.write(' ' * self.indentation)
238 self.output.write(' ' * self.indentation)
239 self.output_width = self.indentation
239 self.output_width = self.indentation
240 self.buffer_width = 0
240 self.buffer_width = 0
241
241
242
242
243 def begin_group(self, indent=0, open=''):
243 def begin_group(self, indent=0, open=''):
244 """
244 """
245 Begin a group. If you want support for python < 2.5 which doesn't has
245 Begin a group. If you want support for python < 2.5 which doesn't has
246 the with statement this is the preferred way:
246 the with statement this is the preferred way:
247
247
248 p.begin_group(1, '{')
248 p.begin_group(1, '{')
249 ...
249 ...
250 p.end_group(1, '}')
250 p.end_group(1, '}')
251
251
252 The python 2.5 expression would be this:
252 The python 2.5 expression would be this:
253
253
254 with p.group(1, '{', '}'):
254 with p.group(1, '{', '}'):
255 ...
255 ...
256
256
257 The first parameter specifies the indentation for the next line (usually
257 The first parameter specifies the indentation for the next line (usually
258 the width of the opening text), the second the opening text. All
258 the width of the opening text), the second the opening text. All
259 parameters are optional.
259 parameters are optional.
260 """
260 """
261 if open:
261 if open:
262 self.text(open)
262 self.text(open)
263 group = Group(self.group_stack[-1].depth + 1)
263 group = Group(self.group_stack[-1].depth + 1)
264 self.group_stack.append(group)
264 self.group_stack.append(group)
265 self.group_queue.enq(group)
265 self.group_queue.enq(group)
266 self.indentation += indent
266 self.indentation += indent
267
267
268 def _enumerate(self, seq):
268 def _enumerate(self, seq):
269 """like enumerate, but with an upper limit on the number of items"""
269 """like enumerate, but with an upper limit on the number of items"""
270 for idx, x in enumerate(seq):
270 for idx, x in enumerate(seq):
271 if self.max_seq_length and idx >= self.max_seq_length:
271 if self.max_seq_length and idx >= self.max_seq_length:
272 self.text(',')
272 self.text(',')
273 self.breakable()
273 self.breakable()
274 self.text('...')
274 self.text('...')
275 return
275 return
276 yield idx, x
276 yield idx, x
277
277
278 def end_group(self, dedent=0, close=''):
278 def end_group(self, dedent=0, close=''):
279 """End a group. See `begin_group` for more details."""
279 """End a group. See `begin_group` for more details."""
280 self.indentation -= dedent
280 self.indentation -= dedent
281 group = self.group_stack.pop()
281 group = self.group_stack.pop()
282 if not group.breakables:
282 if not group.breakables:
283 self.group_queue.remove(group)
283 self.group_queue.remove(group)
284 if close:
284 if close:
285 self.text(close)
285 self.text(close)
286
286
287 def flush(self):
287 def flush(self):
288 """Flush data that is left in the buffer."""
288 """Flush data that is left in the buffer."""
289 for data in self.buffer:
289 for data in self.buffer:
290 self.output_width += data.output(self.output, self.output_width)
290 self.output_width += data.output(self.output, self.output_width)
291 self.buffer.clear()
291 self.buffer.clear()
292 self.buffer_width = 0
292 self.buffer_width = 0
293
293
294
294
295 def _get_mro(obj_class):
295 def _get_mro(obj_class):
296 """ Get a reasonable method resolution order of a class and its superclasses
296 """ Get a reasonable method resolution order of a class and its superclasses
297 for both old-style and new-style classes.
297 for both old-style and new-style classes.
298 """
298 """
299 if not hasattr(obj_class, '__mro__'):
299 if not hasattr(obj_class, '__mro__'):
300 # Old-style class. Mix in object to make a fake new-style class.
300 # Old-style class. Mix in object to make a fake new-style class.
301 try:
301 try:
302 obj_class = type(obj_class.__name__, (obj_class, object), {})
302 obj_class = type(obj_class.__name__, (obj_class, object), {})
303 except TypeError:
303 except TypeError:
304 # Old-style extension type that does not descend from object.
304 # Old-style extension type that does not descend from object.
305 # FIXME: try to construct a more thorough MRO.
305 # FIXME: try to construct a more thorough MRO.
306 mro = [obj_class]
306 mro = [obj_class]
307 else:
307 else:
308 mro = obj_class.__mro__[1:-1]
308 mro = obj_class.__mro__[1:-1]
309 else:
309 else:
310 mro = obj_class.__mro__
310 mro = obj_class.__mro__
311 return mro
311 return mro
312
312
313
313
314 class RepresentationPrinter(PrettyPrinter):
314 class RepresentationPrinter(PrettyPrinter):
315 """
315 """
316 Special pretty printer that has a `pretty` method that calls the pretty
316 Special pretty printer that has a `pretty` method that calls the pretty
317 printer for a python object.
317 printer for a python object.
318
318
319 This class stores processing data on `self` so you must *never* use
319 This class stores processing data on `self` so you must *never* use
320 this class in a threaded environment. Always lock it or reinstanciate
320 this class in a threaded environment. Always lock it or reinstanciate
321 it.
321 it.
322
322
323 Instances also have a verbose flag callbacks can access to control their
323 Instances also have a verbose flag callbacks can access to control their
324 output. For example the default instance repr prints all attributes and
324 output. For example the default instance repr prints all attributes and
325 methods that are not prefixed by an underscore if the printer is in
325 methods that are not prefixed by an underscore if the printer is in
326 verbose mode.
326 verbose mode.
327 """
327 """
328
328
329 def __init__(self, output, verbose=False, max_width=79, newline='\n',
329 def __init__(self, output, verbose=False, max_width=79, newline='\n',
330 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
330 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
331 max_seq_length=MAX_SEQ_LENGTH):
331 max_seq_length=MAX_SEQ_LENGTH):
332
332
333 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
333 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
334 self.verbose = verbose
334 self.verbose = verbose
335 self.stack = []
335 self.stack = []
336 if singleton_pprinters is None:
336 if singleton_pprinters is None:
337 singleton_pprinters = _singleton_pprinters.copy()
337 singleton_pprinters = _singleton_pprinters.copy()
338 self.singleton_pprinters = singleton_pprinters
338 self.singleton_pprinters = singleton_pprinters
339 if type_pprinters is None:
339 if type_pprinters is None:
340 type_pprinters = _type_pprinters.copy()
340 type_pprinters = _type_pprinters.copy()
341 self.type_pprinters = type_pprinters
341 self.type_pprinters = type_pprinters
342 if deferred_pprinters is None:
342 if deferred_pprinters is None:
343 deferred_pprinters = _deferred_type_pprinters.copy()
343 deferred_pprinters = _deferred_type_pprinters.copy()
344 self.deferred_pprinters = deferred_pprinters
344 self.deferred_pprinters = deferred_pprinters
345
345
346 def pretty(self, obj):
346 def pretty(self, obj):
347 """Pretty print the given object."""
347 """Pretty print the given object."""
348 obj_id = id(obj)
348 obj_id = id(obj)
349 cycle = obj_id in self.stack
349 cycle = obj_id in self.stack
350 self.stack.append(obj_id)
350 self.stack.append(obj_id)
351 self.begin_group()
351 self.begin_group()
352 try:
352 try:
353 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
353 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
354 # First try to find registered singleton printers for the type.
354 # First try to find registered singleton printers for the type.
355 try:
355 try:
356 printer = self.singleton_pprinters[obj_id]
356 printer = self.singleton_pprinters[obj_id]
357 except (TypeError, KeyError):
357 except (TypeError, KeyError):
358 pass
358 pass
359 else:
359 else:
360 return printer(obj, self, cycle)
360 return printer(obj, self, cycle)
361 # Next walk the mro and check for either:
361 # Next walk the mro and check for either:
362 # 1) a registered printer
362 # 1) a registered printer
363 # 2) a _repr_pretty_ method
363 # 2) a _repr_pretty_ method
364 for cls in _get_mro(obj_class):
364 for cls in _get_mro(obj_class):
365 if cls in self.type_pprinters:
365 if cls in self.type_pprinters:
366 # printer registered in self.type_pprinters
366 # printer registered in self.type_pprinters
367 return self.type_pprinters[cls](obj, self, cycle)
367 return self.type_pprinters[cls](obj, self, cycle)
368 else:
368 else:
369 # deferred printer
369 # deferred printer
370 printer = self._in_deferred_types(cls)
370 printer = self._in_deferred_types(cls)
371 if printer is not None:
371 if printer is not None:
372 return printer(obj, self, cycle)
372 return printer(obj, self, cycle)
373 else:
373 else:
374 # Finally look for special method names.
374 # Finally look for special method names.
375 # Some objects automatically create any requested
375 # Some objects automatically create any requested
376 # attribute. Try to ignore most of them by checking for
376 # attribute. Try to ignore most of them by checking for
377 # callability.
377 # callability.
378 if '_repr_pretty_' in cls.__dict__:
378 if '_repr_pretty_' in cls.__dict__:
379 meth = cls._repr_pretty_
379 meth = cls._repr_pretty_
380 if callable(meth):
380 if callable(meth):
381 return meth(obj, self, cycle)
381 return meth(obj, self, cycle)
382 return _default_pprint(obj, self, cycle)
382 return _default_pprint(obj, self, cycle)
383 finally:
383 finally:
384 self.end_group()
384 self.end_group()
385 self.stack.pop()
385 self.stack.pop()
386
386
387 def _in_deferred_types(self, cls):
387 def _in_deferred_types(self, cls):
388 """
388 """
389 Check if the given class is specified in the deferred type registry.
389 Check if the given class is specified in the deferred type registry.
390
390
391 Returns the printer from the registry if it exists, and None if the
391 Returns the printer from the registry if it exists, and None if the
392 class is not in the registry. Successful matches will be moved to the
392 class is not in the registry. Successful matches will be moved to the
393 regular type registry for future use.
393 regular type registry for future use.
394 """
394 """
395 mod = _safe_getattr(cls, '__module__', None)
395 mod = _safe_getattr(cls, '__module__', None)
396 name = _safe_getattr(cls, '__name__', None)
396 name = _safe_getattr(cls, '__name__', None)
397 key = (mod, name)
397 key = (mod, name)
398 printer = None
398 printer = None
399 if key in self.deferred_pprinters:
399 if key in self.deferred_pprinters:
400 # Move the printer over to the regular registry.
400 # Move the printer over to the regular registry.
401 printer = self.deferred_pprinters.pop(key)
401 printer = self.deferred_pprinters.pop(key)
402 self.type_pprinters[cls] = printer
402 self.type_pprinters[cls] = printer
403 return printer
403 return printer
404
404
405
405
406 class Printable(object):
406 class Printable(object):
407
407
408 def output(self, stream, output_width):
408 def output(self, stream, output_width):
409 return output_width
409 return output_width
410
410
411
411
412 class Text(Printable):
412 class Text(Printable):
413
413
414 def __init__(self):
414 def __init__(self):
415 self.objs = []
415 self.objs = []
416 self.width = 0
416 self.width = 0
417
417
418 def output(self, stream, output_width):
418 def output(self, stream, output_width):
419 for obj in self.objs:
419 for obj in self.objs:
420 stream.write(obj)
420 stream.write(obj)
421 return output_width + self.width
421 return output_width + self.width
422
422
423 def add(self, obj, width):
423 def add(self, obj, width):
424 self.objs.append(obj)
424 self.objs.append(obj)
425 self.width += width
425 self.width += width
426
426
427
427
428 class Breakable(Printable):
428 class Breakable(Printable):
429
429
430 def __init__(self, seq, width, pretty):
430 def __init__(self, seq, width, pretty):
431 self.obj = seq
431 self.obj = seq
432 self.width = width
432 self.width = width
433 self.pretty = pretty
433 self.pretty = pretty
434 self.indentation = pretty.indentation
434 self.indentation = pretty.indentation
435 self.group = pretty.group_stack[-1]
435 self.group = pretty.group_stack[-1]
436 self.group.breakables.append(self)
436 self.group.breakables.append(self)
437
437
438 def output(self, stream, output_width):
438 def output(self, stream, output_width):
439 self.group.breakables.popleft()
439 self.group.breakables.popleft()
440 if self.group.want_break:
440 if self.group.want_break:
441 stream.write(self.pretty.newline)
441 stream.write(self.pretty.newline)
442 stream.write(' ' * self.indentation)
442 stream.write(' ' * self.indentation)
443 return self.indentation
443 return self.indentation
444 if not self.group.breakables:
444 if not self.group.breakables:
445 self.pretty.group_queue.remove(self.group)
445 self.pretty.group_queue.remove(self.group)
446 stream.write(self.obj)
446 stream.write(self.obj)
447 return output_width + self.width
447 return output_width + self.width
448
448
449
449
450 class Group(Printable):
450 class Group(Printable):
451
451
452 def __init__(self, depth):
452 def __init__(self, depth):
453 self.depth = depth
453 self.depth = depth
454 self.breakables = deque()
454 self.breakables = deque()
455 self.want_break = False
455 self.want_break = False
456
456
457
457
458 class GroupQueue(object):
458 class GroupQueue(object):
459
459
460 def __init__(self, *groups):
460 def __init__(self, *groups):
461 self.queue = []
461 self.queue = []
462 for group in groups:
462 for group in groups:
463 self.enq(group)
463 self.enq(group)
464
464
465 def enq(self, group):
465 def enq(self, group):
466 depth = group.depth
466 depth = group.depth
467 while depth > len(self.queue) - 1:
467 while depth > len(self.queue) - 1:
468 self.queue.append([])
468 self.queue.append([])
469 self.queue[depth].append(group)
469 self.queue[depth].append(group)
470
470
471 def deq(self):
471 def deq(self):
472 for stack in self.queue:
472 for stack in self.queue:
473 for idx, group in enumerate(reversed(stack)):
473 for idx, group in enumerate(reversed(stack)):
474 if group.breakables:
474 if group.breakables:
475 del stack[idx]
475 del stack[idx]
476 group.want_break = True
476 group.want_break = True
477 return group
477 return group
478 for group in stack:
478 for group in stack:
479 group.want_break = True
479 group.want_break = True
480 del stack[:]
480 del stack[:]
481
481
482 def remove(self, group):
482 def remove(self, group):
483 try:
483 try:
484 self.queue[group.depth].remove(group)
484 self.queue[group.depth].remove(group)
485 except ValueError:
485 except ValueError:
486 pass
486 pass
487
487
488 try:
488 try:
489 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
489 _baseclass_reprs = (object.__repr__, types.InstanceType.__repr__)
490 except AttributeError: # Python 3
490 except AttributeError: # Python 3
491 _baseclass_reprs = (object.__repr__,)
491 _baseclass_reprs = (object.__repr__,)
492
492
493
493
494 def _default_pprint(obj, p, cycle):
494 def _default_pprint(obj, p, cycle):
495 """
495 """
496 The default print function. Used if an object does not provide one and
496 The default print function. Used if an object does not provide one and
497 it's none of the builtin objects.
497 it's none of the builtin objects.
498 """
498 """
499 klass = _safe_getattr(obj, '__class__', None) or type(obj)
499 klass = _safe_getattr(obj, '__class__', None) or type(obj)
500 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
500 if _safe_getattr(klass, '__repr__', None) not in _baseclass_reprs:
501 # A user-provided repr. Find newlines and replace them with p.break_()
501 # A user-provided repr. Find newlines and replace them with p.break_()
502 _repr_pprint(obj, p, cycle)
502 _repr_pprint(obj, p, cycle)
503 return
503 return
504 p.begin_group(1, '<')
504 p.begin_group(1, '<')
505 p.pretty(klass)
505 p.pretty(klass)
506 p.text(' at 0x%x' % id(obj))
506 p.text(' at 0x%x' % id(obj))
507 if cycle:
507 if cycle:
508 p.text(' ...')
508 p.text(' ...')
509 elif p.verbose:
509 elif p.verbose:
510 first = True
510 first = True
511 for key in dir(obj):
511 for key in dir(obj):
512 if not key.startswith('_'):
512 if not key.startswith('_'):
513 try:
513 try:
514 value = getattr(obj, key)
514 value = getattr(obj, key)
515 except AttributeError:
515 except AttributeError:
516 continue
516 continue
517 if isinstance(value, types.MethodType):
517 if isinstance(value, types.MethodType):
518 continue
518 continue
519 if not first:
519 if not first:
520 p.text(',')
520 p.text(',')
521 p.breakable()
521 p.breakable()
522 p.text(key)
522 p.text(key)
523 p.text('=')
523 p.text('=')
524 step = len(key) + 1
524 step = len(key) + 1
525 p.indentation += step
525 p.indentation += step
526 p.pretty(value)
526 p.pretty(value)
527 p.indentation -= step
527 p.indentation -= step
528 first = False
528 first = False
529 p.end_group(1, '>')
529 p.end_group(1, '>')
530
530
531
531
532 def _seq_pprinter_factory(start, end, basetype):
532 def _seq_pprinter_factory(start, end, basetype):
533 """
533 """
534 Factory that returns a pprint function useful for sequences. Used by
534 Factory that returns a pprint function useful for sequences. Used by
535 the default pprint for tuples, dicts, and lists.
535 the default pprint for tuples, dicts, and lists.
536 """
536 """
537 def inner(obj, p, cycle):
537 def inner(obj, p, cycle):
538 typ = type(obj)
538 typ = type(obj)
539 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
539 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
540 # If the subclass provides its own repr, use it instead.
540 # If the subclass provides its own repr, use it instead.
541 return p.text(typ.__repr__(obj))
541 return p.text(typ.__repr__(obj))
542
542
543 if cycle:
543 if cycle:
544 return p.text(start + '...' + end)
544 return p.text(start + '...' + end)
545 step = len(start)
545 step = len(start)
546 p.begin_group(step, start)
546 p.begin_group(step, start)
547 for idx, x in p._enumerate(obj):
547 for idx, x in p._enumerate(obj):
548 if idx:
548 if idx:
549 p.text(',')
549 p.text(',')
550 p.breakable()
550 p.breakable()
551 p.pretty(x)
551 p.pretty(x)
552 if len(obj) == 1 and type(obj) is tuple:
552 if len(obj) == 1 and type(obj) is tuple:
553 # Special case for 1-item tuples.
553 # Special case for 1-item tuples.
554 p.text(',')
554 p.text(',')
555 p.end_group(step, end)
555 p.end_group(step, end)
556 return inner
556 return inner
557
557
558
558
559 def _set_pprinter_factory(start, end, basetype):
559 def _set_pprinter_factory(start, end, basetype):
560 """
560 """
561 Factory that returns a pprint function useful for sets and frozensets.
561 Factory that returns a pprint function useful for sets and frozensets.
562 """
562 """
563 def inner(obj, p, cycle):
563 def inner(obj, p, cycle):
564 typ = type(obj)
564 typ = type(obj)
565 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
565 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
566 # If the subclass provides its own repr, use it instead.
566 # If the subclass provides its own repr, use it instead.
567 return p.text(typ.__repr__(obj))
567 return p.text(typ.__repr__(obj))
568
568
569 if cycle:
569 if cycle:
570 return p.text(start + '...' + end)
570 return p.text(start + '...' + end)
571 if len(obj) == 0:
571 if len(obj) == 0:
572 # Special case.
572 # Special case.
573 p.text(basetype.__name__ + '()')
573 p.text(basetype.__name__ + '()')
574 else:
574 else:
575 step = len(start)
575 step = len(start)
576 p.begin_group(step, start)
576 p.begin_group(step, start)
577 # Like dictionary keys, we will try to sort the items if there aren't too many
577 # Like dictionary keys, we will try to sort the items if there aren't too many
578 items = obj
578 items = obj
579 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
579 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
580 try:
580 try:
581 items = sorted(obj)
581 items = sorted(obj)
582 except Exception:
582 except Exception:
583 # Sometimes the items don't sort.
583 # Sometimes the items don't sort.
584 pass
584 pass
585 for idx, x in p._enumerate(items):
585 for idx, x in p._enumerate(items):
586 if idx:
586 if idx:
587 p.text(',')
587 p.text(',')
588 p.breakable()
588 p.breakable()
589 p.pretty(x)
589 p.pretty(x)
590 p.end_group(step, end)
590 p.end_group(step, end)
591 return inner
591 return inner
592
592
593
593
594 def _dict_pprinter_factory(start, end, basetype=None):
594 def _dict_pprinter_factory(start, end, basetype=None):
595 """
595 """
596 Factory that returns a pprint function used by the default pprint of
596 Factory that returns a pprint function used by the default pprint of
597 dicts and dict proxies.
597 dicts and dict proxies.
598 """
598 """
599 def inner(obj, p, cycle):
599 def inner(obj, p, cycle):
600 typ = type(obj)
600 typ = type(obj)
601 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
601 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
602 # If the subclass provides its own repr, use it instead.
602 # If the subclass provides its own repr, use it instead.
603 return p.text(typ.__repr__(obj))
603 return p.text(typ.__repr__(obj))
604
604
605 if cycle:
605 if cycle:
606 return p.text('{...}')
606 return p.text('{...}')
607 step = len(start)
607 step = len(start)
608 p.begin_group(step, start)
608 p.begin_group(step, start)
609 keys = obj.keys()
609 keys = obj.keys()
610 # if dict isn't large enough to be truncated, sort keys before displaying
610 # if dict isn't large enough to be truncated, sort keys before displaying
611 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
611 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
612 try:
612 try:
613 keys = sorted(keys)
613 keys = sorted(keys)
614 except Exception:
614 except Exception:
615 # Sometimes the keys don't sort.
615 # Sometimes the keys don't sort.
616 pass
616 pass
617 for idx, key in p._enumerate(keys):
617 for idx, key in p._enumerate(keys):
618 if idx:
618 if idx:
619 p.text(',')
619 p.text(',')
620 p.breakable()
620 p.breakable()
621 p.pretty(key)
621 p.pretty(key)
622 p.text(': ')
622 p.text(': ')
623 p.pretty(obj[key])
623 p.pretty(obj[key])
624 p.end_group(step, end)
624 p.end_group(step, end)
625 return inner
625 return inner
626
626
627
627
628 def _super_pprint(obj, p, cycle):
628 def _super_pprint(obj, p, cycle):
629 """The pprint for the super type."""
629 """The pprint for the super type."""
630 p.begin_group(8, '<super: ')
630 p.begin_group(8, '<super: ')
631 p.pretty(obj.__thisclass__)
631 p.pretty(obj.__thisclass__)
632 p.text(',')
632 p.text(',')
633 p.breakable()
633 p.breakable()
634 if PYPY: # In PyPy, super() objects don't have __self__ attributes
634 if PYPY: # In PyPy, super() objects don't have __self__ attributes
635 dself = obj.__repr__.__self__
635 dself = obj.__repr__.__self__
636 p.pretty(None if dself is obj else dself)
636 p.pretty(None if dself is obj else dself)
637 else:
637 else:
638 p.pretty(obj.__self__)
638 p.pretty(obj.__self__)
639 p.end_group(8, '>')
639 p.end_group(8, '>')
640
640
641
641
642 def _re_pattern_pprint(obj, p, cycle):
642 def _re_pattern_pprint(obj, p, cycle):
643 """The pprint function for regular expression patterns."""
643 """The pprint function for regular expression patterns."""
644 p.text('re.compile(')
644 p.text('re.compile(')
645 pattern = repr(obj.pattern)
645 pattern = repr(obj.pattern)
646 if pattern[:1] in 'uU':
646 if pattern[:1] in 'uU':
647 pattern = pattern[1:]
647 pattern = pattern[1:]
648 prefix = 'ur'
648 prefix = 'ur'
649 else:
649 else:
650 prefix = 'r'
650 prefix = 'r'
651 pattern = prefix + pattern.replace('\\\\', '\\')
651 pattern = prefix + pattern.replace('\\\\', '\\')
652 p.text(pattern)
652 p.text(pattern)
653 if obj.flags:
653 if obj.flags:
654 p.text(',')
654 p.text(',')
655 p.breakable()
655 p.breakable()
656 done_one = False
656 done_one = False
657 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
657 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
658 'UNICODE', 'VERBOSE', 'DEBUG'):
658 'UNICODE', 'VERBOSE', 'DEBUG'):
659 if obj.flags & getattr(re, flag):
659 if obj.flags & getattr(re, flag):
660 if done_one:
660 if done_one:
661 p.text('|')
661 p.text('|')
662 p.text('re.' + flag)
662 p.text('re.' + flag)
663 done_one = True
663 done_one = True
664 p.text(')')
664 p.text(')')
665
665
666
666
667 def _type_pprint(obj, p, cycle):
667 def _type_pprint(obj, p, cycle):
668 """The pprint for classes and types."""
668 """The pprint for classes and types."""
669 # Heap allocated types might not have the module attribute,
669 # Heap allocated types might not have the module attribute,
670 # and others may set it to None.
670 # and others may set it to None.
671
671
672 # Checks for a __repr__ override in the metaclass. Can't compare the
672 # Checks for a __repr__ override in the metaclass. Can't compare the
673 # type(obj).__repr__ directly because in PyPy the representation function
673 # type(obj).__repr__ directly because in PyPy the representation function
674 # inherited from type isn't the same type.__repr__
674 # inherited from type isn't the same type.__repr__
675 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
675 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
676 _repr_pprint(obj, p, cycle)
676 _repr_pprint(obj, p, cycle)
677 return
677 return
678
678
679 mod = _safe_getattr(obj, '__module__', None)
679 mod = _safe_getattr(obj, '__module__', None)
680 try:
680 try:
681 name = obj.__qualname__
681 name = obj.__qualname__
682 if not isinstance(name, string_types):
682 if not isinstance(name, str):
683 # This can happen if the type implements __qualname__ as a property
683 # This can happen if the type implements __qualname__ as a property
684 # or other descriptor in Python 2.
684 # or other descriptor in Python 2.
685 raise Exception("Try __name__")
685 raise Exception("Try __name__")
686 except Exception:
686 except Exception:
687 name = obj.__name__
687 name = obj.__name__
688 if not isinstance(name, string_types):
688 if not isinstance(name, str):
689 name = '<unknown type>'
689 name = '<unknown type>'
690
690
691 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
691 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
692 p.text(name)
692 p.text(name)
693 else:
693 else:
694 p.text(mod + '.' + name)
694 p.text(mod + '.' + name)
695
695
696
696
697 def _repr_pprint(obj, p, cycle):
697 def _repr_pprint(obj, p, cycle):
698 """A pprint that just redirects to the normal repr function."""
698 """A pprint that just redirects to the normal repr function."""
699 # Find newlines and replace them with p.break_()
699 # Find newlines and replace them with p.break_()
700 output = repr(obj)
700 output = repr(obj)
701 for idx,output_line in enumerate(output.splitlines()):
701 for idx,output_line in enumerate(output.splitlines()):
702 if idx:
702 if idx:
703 p.break_()
703 p.break_()
704 p.text(output_line)
704 p.text(output_line)
705
705
706
706
707 def _function_pprint(obj, p, cycle):
707 def _function_pprint(obj, p, cycle):
708 """Base pprint for all functions and builtin functions."""
708 """Base pprint for all functions and builtin functions."""
709 name = _safe_getattr(obj, '__qualname__', obj.__name__)
709 name = _safe_getattr(obj, '__qualname__', obj.__name__)
710 mod = obj.__module__
710 mod = obj.__module__
711 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
711 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
712 name = mod + '.' + name
712 name = mod + '.' + name
713 p.text('<function %s>' % name)
713 p.text('<function %s>' % name)
714
714
715
715
716 def _exception_pprint(obj, p, cycle):
716 def _exception_pprint(obj, p, cycle):
717 """Base pprint for all exceptions."""
717 """Base pprint for all exceptions."""
718 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
718 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
719 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
719 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
720 name = '%s.%s' % (obj.__class__.__module__, name)
720 name = '%s.%s' % (obj.__class__.__module__, name)
721 step = len(name) + 1
721 step = len(name) + 1
722 p.begin_group(step, name + '(')
722 p.begin_group(step, name + '(')
723 for idx, arg in enumerate(getattr(obj, 'args', ())):
723 for idx, arg in enumerate(getattr(obj, 'args', ())):
724 if idx:
724 if idx:
725 p.text(',')
725 p.text(',')
726 p.breakable()
726 p.breakable()
727 p.pretty(arg)
727 p.pretty(arg)
728 p.end_group(step, ')')
728 p.end_group(step, ')')
729
729
730
730
731 #: the exception base
731 #: the exception base
732 try:
732 try:
733 _exception_base = BaseException
733 _exception_base = BaseException
734 except NameError:
734 except NameError:
735 _exception_base = Exception
735 _exception_base = Exception
736
736
737
737
738 #: printers for builtin types
738 #: printers for builtin types
739 _type_pprinters = {
739 _type_pprinters = {
740 int: _repr_pprint,
740 int: _repr_pprint,
741 float: _repr_pprint,
741 float: _repr_pprint,
742 str: _repr_pprint,
742 str: _repr_pprint,
743 tuple: _seq_pprinter_factory('(', ')', tuple),
743 tuple: _seq_pprinter_factory('(', ')', tuple),
744 list: _seq_pprinter_factory('[', ']', list),
744 list: _seq_pprinter_factory('[', ']', list),
745 dict: _dict_pprinter_factory('{', '}', dict),
745 dict: _dict_pprinter_factory('{', '}', dict),
746
746
747 set: _set_pprinter_factory('{', '}', set),
747 set: _set_pprinter_factory('{', '}', set),
748 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
748 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
749 super: _super_pprint,
749 super: _super_pprint,
750 _re_pattern_type: _re_pattern_pprint,
750 _re_pattern_type: _re_pattern_pprint,
751 type: _type_pprint,
751 type: _type_pprint,
752 types.FunctionType: _function_pprint,
752 types.FunctionType: _function_pprint,
753 types.BuiltinFunctionType: _function_pprint,
753 types.BuiltinFunctionType: _function_pprint,
754 types.MethodType: _repr_pprint,
754 types.MethodType: _repr_pprint,
755
755
756 datetime.datetime: _repr_pprint,
756 datetime.datetime: _repr_pprint,
757 datetime.timedelta: _repr_pprint,
757 datetime.timedelta: _repr_pprint,
758 _exception_base: _exception_pprint
758 _exception_base: _exception_pprint
759 }
759 }
760
760
761 try:
761 try:
762 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
762 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
763 # using dict.setdefault avoids overwritting the dict printer
763 # using dict.setdefault avoids overwritting the dict printer
764 _type_pprinters.setdefault(types.DictProxyType,
764 _type_pprinters.setdefault(types.DictProxyType,
765 _dict_pprinter_factory('dict_proxy({', '})'))
765 _dict_pprinter_factory('dict_proxy({', '})'))
766 _type_pprinters[types.ClassType] = _type_pprint
766 _type_pprinters[types.ClassType] = _type_pprint
767 _type_pprinters[types.SliceType] = _repr_pprint
767 _type_pprinters[types.SliceType] = _repr_pprint
768 except AttributeError: # Python 3
768 except AttributeError: # Python 3
769 _type_pprinters[types.MappingProxyType] = \
769 _type_pprinters[types.MappingProxyType] = \
770 _dict_pprinter_factory('mappingproxy({', '})')
770 _dict_pprinter_factory('mappingproxy({', '})')
771 _type_pprinters[slice] = _repr_pprint
771 _type_pprinters[slice] = _repr_pprint
772
772
773 try:
773 try:
774 _type_pprinters[xrange] = _repr_pprint
775 _type_pprinters[long] = _repr_pprint
774 _type_pprinters[long] = _repr_pprint
776 _type_pprinters[unicode] = _repr_pprint
775 _type_pprinters[unicode] = _repr_pprint
777 except NameError:
776 except NameError:
778 _type_pprinters[range] = _repr_pprint
777 _type_pprinters[range] = _repr_pprint
779 _type_pprinters[bytes] = _repr_pprint
778 _type_pprinters[bytes] = _repr_pprint
780
779
781 #: printers for types specified by name
780 #: printers for types specified by name
782 _deferred_type_pprinters = {
781 _deferred_type_pprinters = {
783 }
782 }
784
783
785 def for_type(typ, func):
784 def for_type(typ, func):
786 """
785 """
787 Add a pretty printer for a given type.
786 Add a pretty printer for a given type.
788 """
787 """
789 oldfunc = _type_pprinters.get(typ, None)
788 oldfunc = _type_pprinters.get(typ, None)
790 if func is not None:
789 if func is not None:
791 # To support easy restoration of old pprinters, we need to ignore Nones.
790 # To support easy restoration of old pprinters, we need to ignore Nones.
792 _type_pprinters[typ] = func
791 _type_pprinters[typ] = func
793 return oldfunc
792 return oldfunc
794
793
795 def for_type_by_name(type_module, type_name, func):
794 def for_type_by_name(type_module, type_name, func):
796 """
795 """
797 Add a pretty printer for a type specified by the module and name of a type
796 Add a pretty printer for a type specified by the module and name of a type
798 rather than the type object itself.
797 rather than the type object itself.
799 """
798 """
800 key = (type_module, type_name)
799 key = (type_module, type_name)
801 oldfunc = _deferred_type_pprinters.get(key, None)
800 oldfunc = _deferred_type_pprinters.get(key, None)
802 if func is not None:
801 if func is not None:
803 # To support easy restoration of old pprinters, we need to ignore Nones.
802 # To support easy restoration of old pprinters, we need to ignore Nones.
804 _deferred_type_pprinters[key] = func
803 _deferred_type_pprinters[key] = func
805 return oldfunc
804 return oldfunc
806
805
807
806
808 #: printers for the default singletons
807 #: printers for the default singletons
809 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
808 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
810 NotImplemented]), _repr_pprint)
809 NotImplemented]), _repr_pprint)
811
810
812
811
813 def _defaultdict_pprint(obj, p, cycle):
812 def _defaultdict_pprint(obj, p, cycle):
814 name = obj.__class__.__name__
813 name = obj.__class__.__name__
815 with p.group(len(name) + 1, name + '(', ')'):
814 with p.group(len(name) + 1, name + '(', ')'):
816 if cycle:
815 if cycle:
817 p.text('...')
816 p.text('...')
818 else:
817 else:
819 p.pretty(obj.default_factory)
818 p.pretty(obj.default_factory)
820 p.text(',')
819 p.text(',')
821 p.breakable()
820 p.breakable()
822 p.pretty(dict(obj))
821 p.pretty(dict(obj))
823
822
824 def _ordereddict_pprint(obj, p, cycle):
823 def _ordereddict_pprint(obj, p, cycle):
825 name = obj.__class__.__name__
824 name = obj.__class__.__name__
826 with p.group(len(name) + 1, name + '(', ')'):
825 with p.group(len(name) + 1, name + '(', ')'):
827 if cycle:
826 if cycle:
828 p.text('...')
827 p.text('...')
829 elif len(obj):
828 elif len(obj):
830 p.pretty(list(obj.items()))
829 p.pretty(list(obj.items()))
831
830
832 def _deque_pprint(obj, p, cycle):
831 def _deque_pprint(obj, p, cycle):
833 name = obj.__class__.__name__
832 name = obj.__class__.__name__
834 with p.group(len(name) + 1, name + '(', ')'):
833 with p.group(len(name) + 1, name + '(', ')'):
835 if cycle:
834 if cycle:
836 p.text('...')
835 p.text('...')
837 else:
836 else:
838 p.pretty(list(obj))
837 p.pretty(list(obj))
839
838
840
839
841 def _counter_pprint(obj, p, cycle):
840 def _counter_pprint(obj, p, cycle):
842 name = obj.__class__.__name__
841 name = obj.__class__.__name__
843 with p.group(len(name) + 1, name + '(', ')'):
842 with p.group(len(name) + 1, name + '(', ')'):
844 if cycle:
843 if cycle:
845 p.text('...')
844 p.text('...')
846 elif len(obj):
845 elif len(obj):
847 p.pretty(dict(obj))
846 p.pretty(dict(obj))
848
847
849 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
848 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
850 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
849 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
851 for_type_by_name('collections', 'deque', _deque_pprint)
850 for_type_by_name('collections', 'deque', _deque_pprint)
852 for_type_by_name('collections', 'Counter', _counter_pprint)
851 for_type_by_name('collections', 'Counter', _counter_pprint)
853
852
854 if __name__ == '__main__':
853 if __name__ == '__main__':
855 from random import randrange
854 from random import randrange
856 class Foo(object):
855 class Foo(object):
857 def __init__(self):
856 def __init__(self):
858 self.foo = 1
857 self.foo = 1
859 self.bar = re.compile(r'\s+')
858 self.bar = re.compile(r'\s+')
860 self.blub = dict.fromkeys(range(30), randrange(1, 40))
859 self.blub = dict.fromkeys(range(30), randrange(1, 40))
861 self.hehe = 23424.234234
860 self.hehe = 23424.234234
862 self.list = ["blub", "blah", self]
861 self.list = ["blub", "blah", self]
863
862
864 def get_foo(self):
863 def get_foo(self):
865 print("foo")
864 print("foo")
866
865
867 pprint(Foo(), verbose=True)
866 pprint(Foo(), verbose=True)
@@ -1,22 +1,21 b''
1 import nose.tools as nt
1 import nose.tools as nt
2
2
3 from IPython.core.error import TryNext
3 from IPython.core.error import TryNext
4 from IPython.lib.clipboard import ClipboardEmpty
4 from IPython.lib.clipboard import ClipboardEmpty
5 from IPython.testing.decorators import skip_if_no_x11
5 from IPython.testing.decorators import skip_if_no_x11
6 from IPython.utils.py3compat import unicode_type
7
6
8 @skip_if_no_x11
7 @skip_if_no_x11
9 def test_clipboard_get():
8 def test_clipboard_get():
10 # Smoketest for clipboard access - we can't easily guarantee that the
9 # Smoketest for clipboard access - we can't easily guarantee that the
11 # clipboard is accessible and has something on it, but this tries to
10 # clipboard is accessible and has something on it, but this tries to
12 # exercise the relevant code anyway.
11 # exercise the relevant code anyway.
13 try:
12 try:
14 a = get_ipython().hooks.clipboard_get()
13 a = get_ipython().hooks.clipboard_get()
15 except ClipboardEmpty:
14 except ClipboardEmpty:
16 # Nothing in clipboard to get
15 # Nothing in clipboard to get
17 pass
16 pass
18 except TryNext:
17 except TryNext:
19 # No clipboard access API available
18 # No clipboard access API available
20 pass
19 pass
21 else:
20 else:
22 nt.assert_is_instance(a, unicode_type)
21 nt.assert_is_instance(a, str)
@@ -1,500 +1,500 b''
1 """IPython terminal interface using prompt_toolkit"""
1 """IPython terminal interface using prompt_toolkit"""
2
2
3 import os
3 import os
4 import sys
4 import sys
5 import warnings
5 import warnings
6 from warnings import warn
6 from warnings import warn
7
7
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
9 from IPython.utils import io
9 from IPython.utils import io
10 from IPython.utils.py3compat import PY3, cast_unicode_py2, input, string_types
10 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.process import abbrev_cwd
12 from IPython.utils.process import abbrev_cwd
13 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
13 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
14
14
15 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
15 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
16 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
16 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
17 from prompt_toolkit.history import InMemoryHistory
17 from prompt_toolkit.history import InMemoryHistory
18 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
18 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
19 from prompt_toolkit.interface import CommandLineInterface
19 from prompt_toolkit.interface import CommandLineInterface
20 from prompt_toolkit.key_binding.manager import KeyBindingManager
20 from prompt_toolkit.key_binding.manager import KeyBindingManager
21 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
21 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
22 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
22 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
23
23
24 from pygments.styles import get_style_by_name, get_all_styles
24 from pygments.styles import get_style_by_name, get_all_styles
25 from pygments.style import Style
25 from pygments.style import Style
26 from pygments.token import Token
26 from pygments.token import Token
27
27
28 from .debugger import TerminalPdb, Pdb
28 from .debugger import TerminalPdb, Pdb
29 from .magics import TerminalMagics
29 from .magics import TerminalMagics
30 from .pt_inputhooks import get_inputhook_name_and_func
30 from .pt_inputhooks import get_inputhook_name_and_func
31 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
31 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
32 from .ptutils import IPythonPTCompleter, IPythonPTLexer
32 from .ptutils import IPythonPTCompleter, IPythonPTLexer
33 from .shortcuts import register_ipython_shortcuts
33 from .shortcuts import register_ipython_shortcuts
34
34
35 DISPLAY_BANNER_DEPRECATED = object()
35 DISPLAY_BANNER_DEPRECATED = object()
36
36
37
37
38 from pygments.style import Style
38 from pygments.style import Style
39
39
40 class _NoStyle(Style): pass
40 class _NoStyle(Style): pass
41
41
42
42
43
43
44 _style_overrides_light_bg = {
44 _style_overrides_light_bg = {
45 Token.Prompt: '#0000ff',
45 Token.Prompt: '#0000ff',
46 Token.PromptNum: '#0000ee bold',
46 Token.PromptNum: '#0000ee bold',
47 Token.OutPrompt: '#cc0000',
47 Token.OutPrompt: '#cc0000',
48 Token.OutPromptNum: '#bb0000 bold',
48 Token.OutPromptNum: '#bb0000 bold',
49 }
49 }
50
50
51 _style_overrides_linux = {
51 _style_overrides_linux = {
52 Token.Prompt: '#00cc00',
52 Token.Prompt: '#00cc00',
53 Token.PromptNum: '#00bb00 bold',
53 Token.PromptNum: '#00bb00 bold',
54 Token.OutPrompt: '#cc0000',
54 Token.OutPrompt: '#cc0000',
55 Token.OutPromptNum: '#bb0000 bold',
55 Token.OutPromptNum: '#bb0000 bold',
56 }
56 }
57
57
58
58
59
59
60 def get_default_editor():
60 def get_default_editor():
61 try:
61 try:
62 ed = os.environ['EDITOR']
62 ed = os.environ['EDITOR']
63 if not PY3:
63 if not PY3:
64 ed = ed.decode()
64 ed = ed.decode()
65 return ed
65 return ed
66 except KeyError:
66 except KeyError:
67 pass
67 pass
68 except UnicodeError:
68 except UnicodeError:
69 warn("$EDITOR environment variable is not pure ASCII. Using platform "
69 warn("$EDITOR environment variable is not pure ASCII. Using platform "
70 "default editor.")
70 "default editor.")
71
71
72 if os.name == 'posix':
72 if os.name == 'posix':
73 return 'vi' # the only one guaranteed to be there!
73 return 'vi' # the only one guaranteed to be there!
74 else:
74 else:
75 return 'notepad' # same in Windows!
75 return 'notepad' # same in Windows!
76
76
77 # conservatively check for tty
77 # conservatively check for tty
78 # overridden streams can result in things like:
78 # overridden streams can result in things like:
79 # - sys.stdin = None
79 # - sys.stdin = None
80 # - no isatty method
80 # - no isatty method
81 for _name in ('stdin', 'stdout', 'stderr'):
81 for _name in ('stdin', 'stdout', 'stderr'):
82 _stream = getattr(sys, _name)
82 _stream = getattr(sys, _name)
83 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
83 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
84 _is_tty = False
84 _is_tty = False
85 break
85 break
86 else:
86 else:
87 _is_tty = True
87 _is_tty = True
88
88
89
89
90 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
90 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
91
91
92 class TerminalInteractiveShell(InteractiveShell):
92 class TerminalInteractiveShell(InteractiveShell):
93 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
93 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
94 'to reserve for the completion menu'
94 'to reserve for the completion menu'
95 ).tag(config=True)
95 ).tag(config=True)
96
96
97 def _space_for_menu_changed(self, old, new):
97 def _space_for_menu_changed(self, old, new):
98 self._update_layout()
98 self._update_layout()
99
99
100 pt_cli = None
100 pt_cli = None
101 debugger_history = None
101 debugger_history = None
102 _pt_app = None
102 _pt_app = None
103
103
104 simple_prompt = Bool(_use_simple_prompt,
104 simple_prompt = Bool(_use_simple_prompt,
105 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
105 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
106
106
107 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
107 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
108 IPython own testing machinery, and emacs inferior-shell integration through elpy.
108 IPython own testing machinery, and emacs inferior-shell integration through elpy.
109
109
110 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
110 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
111 environment variable is set, or the current terminal is not a tty.
111 environment variable is set, or the current terminal is not a tty.
112
112
113 """
113 """
114 ).tag(config=True)
114 ).tag(config=True)
115
115
116 @property
116 @property
117 def debugger_cls(self):
117 def debugger_cls(self):
118 return Pdb if self.simple_prompt else TerminalPdb
118 return Pdb if self.simple_prompt else TerminalPdb
119
119
120 confirm_exit = Bool(True,
120 confirm_exit = Bool(True,
121 help="""
121 help="""
122 Set to confirm when you try to exit IPython with an EOF (Control-D
122 Set to confirm when you try to exit IPython with an EOF (Control-D
123 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
123 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
124 you can force a direct exit without any confirmation.""",
124 you can force a direct exit without any confirmation.""",
125 ).tag(config=True)
125 ).tag(config=True)
126
126
127 editing_mode = Unicode('emacs',
127 editing_mode = Unicode('emacs',
128 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
128 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
129 ).tag(config=True)
129 ).tag(config=True)
130
130
131 mouse_support = Bool(False,
131 mouse_support = Bool(False,
132 help="Enable mouse support in the prompt"
132 help="Enable mouse support in the prompt"
133 ).tag(config=True)
133 ).tag(config=True)
134
134
135 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
135 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
136 help="""The name or class of a Pygments style to use for syntax
136 help="""The name or class of a Pygments style to use for syntax
137 highlighting: \n %s""" % ', '.join(get_all_styles())
137 highlighting: \n %s""" % ', '.join(get_all_styles())
138 ).tag(config=True)
138 ).tag(config=True)
139
139
140
140
141 @observe('highlighting_style')
141 @observe('highlighting_style')
142 @observe('colors')
142 @observe('colors')
143 def _highlighting_style_changed(self, change):
143 def _highlighting_style_changed(self, change):
144 self.refresh_style()
144 self.refresh_style()
145
145
146 def refresh_style(self):
146 def refresh_style(self):
147 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
147 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
148
148
149
149
150 highlighting_style_overrides = Dict(
150 highlighting_style_overrides = Dict(
151 help="Override highlighting format for specific tokens"
151 help="Override highlighting format for specific tokens"
152 ).tag(config=True)
152 ).tag(config=True)
153
153
154 true_color = Bool(False,
154 true_color = Bool(False,
155 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
155 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
156 "If your terminal supports true color, the following command "
156 "If your terminal supports true color, the following command "
157 "should print 'TRUECOLOR' in orange: "
157 "should print 'TRUECOLOR' in orange: "
158 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
158 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
159 ).tag(config=True)
159 ).tag(config=True)
160
160
161 editor = Unicode(get_default_editor(),
161 editor = Unicode(get_default_editor(),
162 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
162 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
163 ).tag(config=True)
163 ).tag(config=True)
164
164
165 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
165 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
166
166
167 prompts = Instance(Prompts)
167 prompts = Instance(Prompts)
168
168
169 @default('prompts')
169 @default('prompts')
170 def _prompts_default(self):
170 def _prompts_default(self):
171 return self.prompts_class(self)
171 return self.prompts_class(self)
172
172
173 @observe('prompts')
173 @observe('prompts')
174 def _(self, change):
174 def _(self, change):
175 self._update_layout()
175 self._update_layout()
176
176
177 @default('displayhook_class')
177 @default('displayhook_class')
178 def _displayhook_class_default(self):
178 def _displayhook_class_default(self):
179 return RichPromptDisplayHook
179 return RichPromptDisplayHook
180
180
181 term_title = Bool(True,
181 term_title = Bool(True,
182 help="Automatically set the terminal title"
182 help="Automatically set the terminal title"
183 ).tag(config=True)
183 ).tag(config=True)
184
184
185 display_completions = Enum(('column', 'multicolumn','readlinelike'),
185 display_completions = Enum(('column', 'multicolumn','readlinelike'),
186 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
186 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
187 "'readlinelike'. These options are for `prompt_toolkit`, see "
187 "'readlinelike'. These options are for `prompt_toolkit`, see "
188 "`prompt_toolkit` documentation for more information."
188 "`prompt_toolkit` documentation for more information."
189 ),
189 ),
190 default_value='multicolumn').tag(config=True)
190 default_value='multicolumn').tag(config=True)
191
191
192 highlight_matching_brackets = Bool(True,
192 highlight_matching_brackets = Bool(True,
193 help="Highlight matching brackets .",
193 help="Highlight matching brackets .",
194 ).tag(config=True)
194 ).tag(config=True)
195
195
196 @observe('term_title')
196 @observe('term_title')
197 def init_term_title(self, change=None):
197 def init_term_title(self, change=None):
198 # Enable or disable the terminal title.
198 # Enable or disable the terminal title.
199 if self.term_title:
199 if self.term_title:
200 toggle_set_term_title(True)
200 toggle_set_term_title(True)
201 set_term_title('IPython: ' + abbrev_cwd())
201 set_term_title('IPython: ' + abbrev_cwd())
202 else:
202 else:
203 toggle_set_term_title(False)
203 toggle_set_term_title(False)
204
204
205 def init_display_formatter(self):
205 def init_display_formatter(self):
206 super(TerminalInteractiveShell, self).init_display_formatter()
206 super(TerminalInteractiveShell, self).init_display_formatter()
207 # terminal only supports plain text
207 # terminal only supports plain text
208 self.display_formatter.active_types = ['text/plain']
208 self.display_formatter.active_types = ['text/plain']
209
209
210 def init_prompt_toolkit_cli(self):
210 def init_prompt_toolkit_cli(self):
211 if self.simple_prompt:
211 if self.simple_prompt:
212 # Fall back to plain non-interactive output for tests.
212 # Fall back to plain non-interactive output for tests.
213 # This is very limited, and only accepts a single line.
213 # This is very limited, and only accepts a single line.
214 def prompt():
214 def prompt():
215 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
215 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
216 self.prompt_for_code = prompt
216 self.prompt_for_code = prompt
217 return
217 return
218
218
219 # Set up keyboard shortcuts
219 # Set up keyboard shortcuts
220 kbmanager = KeyBindingManager.for_prompt()
220 kbmanager = KeyBindingManager.for_prompt()
221 register_ipython_shortcuts(kbmanager.registry, self)
221 register_ipython_shortcuts(kbmanager.registry, self)
222
222
223 # Pre-populate history from IPython's history database
223 # Pre-populate history from IPython's history database
224 history = InMemoryHistory()
224 history = InMemoryHistory()
225 last_cell = u""
225 last_cell = u""
226 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
226 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
227 include_latest=True):
227 include_latest=True):
228 # Ignore blank lines and consecutive duplicates
228 # Ignore blank lines and consecutive duplicates
229 cell = cell.rstrip()
229 cell = cell.rstrip()
230 if cell and (cell != last_cell):
230 if cell and (cell != last_cell):
231 history.append(cell)
231 history.append(cell)
232 last_cell = cell
232 last_cell = cell
233
233
234 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
234 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
235 style = DynamicStyle(lambda: self._style)
235 style = DynamicStyle(lambda: self._style)
236
236
237 editing_mode = getattr(EditingMode, self.editing_mode.upper())
237 editing_mode = getattr(EditingMode, self.editing_mode.upper())
238
238
239 self._pt_app = create_prompt_application(
239 self._pt_app = create_prompt_application(
240 editing_mode=editing_mode,
240 editing_mode=editing_mode,
241 key_bindings_registry=kbmanager.registry,
241 key_bindings_registry=kbmanager.registry,
242 history=history,
242 history=history,
243 completer=IPythonPTCompleter(shell=self),
243 completer=IPythonPTCompleter(shell=self),
244 enable_history_search=True,
244 enable_history_search=True,
245 style=style,
245 style=style,
246 mouse_support=self.mouse_support,
246 mouse_support=self.mouse_support,
247 **self._layout_options()
247 **self._layout_options()
248 )
248 )
249 self._eventloop = create_eventloop(self.inputhook)
249 self._eventloop = create_eventloop(self.inputhook)
250 self.pt_cli = CommandLineInterface(
250 self.pt_cli = CommandLineInterface(
251 self._pt_app, eventloop=self._eventloop,
251 self._pt_app, eventloop=self._eventloop,
252 output=create_output(true_color=self.true_color))
252 output=create_output(true_color=self.true_color))
253
253
254 def _make_style_from_name_or_cls(self, name_or_cls):
254 def _make_style_from_name_or_cls(self, name_or_cls):
255 """
255 """
256 Small wrapper that make an IPython compatible style from a style name
256 Small wrapper that make an IPython compatible style from a style name
257
257
258 We need that to add style for prompt ... etc.
258 We need that to add style for prompt ... etc.
259 """
259 """
260 style_overrides = {}
260 style_overrides = {}
261 if name_or_cls == 'legacy':
261 if name_or_cls == 'legacy':
262 legacy = self.colors.lower()
262 legacy = self.colors.lower()
263 if legacy == 'linux':
263 if legacy == 'linux':
264 style_cls = get_style_by_name('monokai')
264 style_cls = get_style_by_name('monokai')
265 style_overrides = _style_overrides_linux
265 style_overrides = _style_overrides_linux
266 elif legacy == 'lightbg':
266 elif legacy == 'lightbg':
267 style_overrides = _style_overrides_light_bg
267 style_overrides = _style_overrides_light_bg
268 style_cls = get_style_by_name('pastie')
268 style_cls = get_style_by_name('pastie')
269 elif legacy == 'neutral':
269 elif legacy == 'neutral':
270 # The default theme needs to be visible on both a dark background
270 # The default theme needs to be visible on both a dark background
271 # and a light background, because we can't tell what the terminal
271 # and a light background, because we can't tell what the terminal
272 # looks like. These tweaks to the default theme help with that.
272 # looks like. These tweaks to the default theme help with that.
273 style_cls = get_style_by_name('default')
273 style_cls = get_style_by_name('default')
274 style_overrides.update({
274 style_overrides.update({
275 Token.Number: '#007700',
275 Token.Number: '#007700',
276 Token.Operator: 'noinherit',
276 Token.Operator: 'noinherit',
277 Token.String: '#BB6622',
277 Token.String: '#BB6622',
278 Token.Name.Function: '#2080D0',
278 Token.Name.Function: '#2080D0',
279 Token.Name.Class: 'bold #2080D0',
279 Token.Name.Class: 'bold #2080D0',
280 Token.Name.Namespace: 'bold #2080D0',
280 Token.Name.Namespace: 'bold #2080D0',
281 Token.Prompt: '#009900',
281 Token.Prompt: '#009900',
282 Token.PromptNum: '#00ff00 bold',
282 Token.PromptNum: '#00ff00 bold',
283 Token.OutPrompt: '#990000',
283 Token.OutPrompt: '#990000',
284 Token.OutPromptNum: '#ff0000 bold',
284 Token.OutPromptNum: '#ff0000 bold',
285 })
285 })
286 elif legacy =='nocolor':
286 elif legacy =='nocolor':
287 style_cls=_NoStyle
287 style_cls=_NoStyle
288 style_overrides = {}
288 style_overrides = {}
289 else :
289 else :
290 raise ValueError('Got unknown colors: ', legacy)
290 raise ValueError('Got unknown colors: ', legacy)
291 else :
291 else :
292 if isinstance(name_or_cls, string_types):
292 if isinstance(name_or_cls, str):
293 style_cls = get_style_by_name(name_or_cls)
293 style_cls = get_style_by_name(name_or_cls)
294 else:
294 else:
295 style_cls = name_or_cls
295 style_cls = name_or_cls
296 style_overrides = {
296 style_overrides = {
297 Token.Prompt: '#009900',
297 Token.Prompt: '#009900',
298 Token.PromptNum: '#00ff00 bold',
298 Token.PromptNum: '#00ff00 bold',
299 Token.OutPrompt: '#990000',
299 Token.OutPrompt: '#990000',
300 Token.OutPromptNum: '#ff0000 bold',
300 Token.OutPromptNum: '#ff0000 bold',
301 }
301 }
302 style_overrides.update(self.highlighting_style_overrides)
302 style_overrides.update(self.highlighting_style_overrides)
303 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
303 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
304 style_dict=style_overrides)
304 style_dict=style_overrides)
305
305
306 return style
306 return style
307
307
308 def _layout_options(self):
308 def _layout_options(self):
309 """
309 """
310 Return the current layout option for the current Terminal InteractiveShell
310 Return the current layout option for the current Terminal InteractiveShell
311 """
311 """
312 return {
312 return {
313 'lexer':IPythonPTLexer(),
313 'lexer':IPythonPTLexer(),
314 'reserve_space_for_menu':self.space_for_menu,
314 'reserve_space_for_menu':self.space_for_menu,
315 'get_prompt_tokens':self.prompts.in_prompt_tokens,
315 'get_prompt_tokens':self.prompts.in_prompt_tokens,
316 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
316 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
317 'multiline':True,
317 'multiline':True,
318 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
318 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
319
319
320 # Highlight matching brackets, but only when this setting is
320 # Highlight matching brackets, but only when this setting is
321 # enabled, and only when the DEFAULT_BUFFER has the focus.
321 # enabled, and only when the DEFAULT_BUFFER has the focus.
322 'extra_input_processors': [ConditionalProcessor(
322 'extra_input_processors': [ConditionalProcessor(
323 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
323 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
324 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
324 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
325 Condition(lambda cli: self.highlight_matching_brackets))],
325 Condition(lambda cli: self.highlight_matching_brackets))],
326 }
326 }
327
327
328 def _update_layout(self):
328 def _update_layout(self):
329 """
329 """
330 Ask for a re computation of the application layout, if for example ,
330 Ask for a re computation of the application layout, if for example ,
331 some configuration options have changed.
331 some configuration options have changed.
332 """
332 """
333 if self._pt_app:
333 if self._pt_app:
334 self._pt_app.layout = create_prompt_layout(**self._layout_options())
334 self._pt_app.layout = create_prompt_layout(**self._layout_options())
335
335
336 def prompt_for_code(self):
336 def prompt_for_code(self):
337 document = self.pt_cli.run(
337 document = self.pt_cli.run(
338 pre_run=self.pre_prompt, reset_current_buffer=True)
338 pre_run=self.pre_prompt, reset_current_buffer=True)
339 return document.text
339 return document.text
340
340
341 def enable_win_unicode_console(self):
341 def enable_win_unicode_console(self):
342 if sys.version_info >= (3, 6):
342 if sys.version_info >= (3, 6):
343 # Since PEP 528, Python uses the unicode APIs for the Windows
343 # Since PEP 528, Python uses the unicode APIs for the Windows
344 # console by default, so WUC shouldn't be needed.
344 # console by default, so WUC shouldn't be needed.
345 return
345 return
346
346
347 import win_unicode_console
347 import win_unicode_console
348
348
349 if PY3:
349 if PY3:
350 win_unicode_console.enable()
350 win_unicode_console.enable()
351 else:
351 else:
352 # https://github.com/ipython/ipython/issues/9768
352 # https://github.com/ipython/ipython/issues/9768
353 from win_unicode_console.streams import (TextStreamWrapper,
353 from win_unicode_console.streams import (TextStreamWrapper,
354 stdout_text_transcoded, stderr_text_transcoded)
354 stdout_text_transcoded, stderr_text_transcoded)
355
355
356 class LenientStrStreamWrapper(TextStreamWrapper):
356 class LenientStrStreamWrapper(TextStreamWrapper):
357 def write(self, s):
357 def write(self, s):
358 if isinstance(s, bytes):
358 if isinstance(s, bytes):
359 s = s.decode(self.encoding, 'replace')
359 s = s.decode(self.encoding, 'replace')
360
360
361 self.base.write(s)
361 self.base.write(s)
362
362
363 stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded)
363 stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded)
364 stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded)
364 stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded)
365
365
366 win_unicode_console.enable(stdout=stdout_text_str,
366 win_unicode_console.enable(stdout=stdout_text_str,
367 stderr=stderr_text_str)
367 stderr=stderr_text_str)
368
368
369 def init_io(self):
369 def init_io(self):
370 if sys.platform not in {'win32', 'cli'}:
370 if sys.platform not in {'win32', 'cli'}:
371 return
371 return
372
372
373 self.enable_win_unicode_console()
373 self.enable_win_unicode_console()
374
374
375 import colorama
375 import colorama
376 colorama.init()
376 colorama.init()
377
377
378 # For some reason we make these wrappers around stdout/stderr.
378 # For some reason we make these wrappers around stdout/stderr.
379 # For now, we need to reset them so all output gets coloured.
379 # For now, we need to reset them so all output gets coloured.
380 # https://github.com/ipython/ipython/issues/8669
380 # https://github.com/ipython/ipython/issues/8669
381 # io.std* are deprecated, but don't show our own deprecation warnings
381 # io.std* are deprecated, but don't show our own deprecation warnings
382 # during initialization of the deprecated API.
382 # during initialization of the deprecated API.
383 with warnings.catch_warnings():
383 with warnings.catch_warnings():
384 warnings.simplefilter('ignore', DeprecationWarning)
384 warnings.simplefilter('ignore', DeprecationWarning)
385 io.stdout = io.IOStream(sys.stdout)
385 io.stdout = io.IOStream(sys.stdout)
386 io.stderr = io.IOStream(sys.stderr)
386 io.stderr = io.IOStream(sys.stderr)
387
387
388 def init_magics(self):
388 def init_magics(self):
389 super(TerminalInteractiveShell, self).init_magics()
389 super(TerminalInteractiveShell, self).init_magics()
390 self.register_magics(TerminalMagics)
390 self.register_magics(TerminalMagics)
391
391
392 def init_alias(self):
392 def init_alias(self):
393 # The parent class defines aliases that can be safely used with any
393 # The parent class defines aliases that can be safely used with any
394 # frontend.
394 # frontend.
395 super(TerminalInteractiveShell, self).init_alias()
395 super(TerminalInteractiveShell, self).init_alias()
396
396
397 # Now define aliases that only make sense on the terminal, because they
397 # Now define aliases that only make sense on the terminal, because they
398 # need direct access to the console in a way that we can't emulate in
398 # need direct access to the console in a way that we can't emulate in
399 # GUI or web frontend
399 # GUI or web frontend
400 if os.name == 'posix':
400 if os.name == 'posix':
401 for cmd in ['clear', 'more', 'less', 'man']:
401 for cmd in ['clear', 'more', 'less', 'man']:
402 self.alias_manager.soft_define_alias(cmd, cmd)
402 self.alias_manager.soft_define_alias(cmd, cmd)
403
403
404
404
405 def __init__(self, *args, **kwargs):
405 def __init__(self, *args, **kwargs):
406 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
406 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
407 self.init_prompt_toolkit_cli()
407 self.init_prompt_toolkit_cli()
408 self.init_term_title()
408 self.init_term_title()
409 self.keep_running = True
409 self.keep_running = True
410
410
411 self.debugger_history = InMemoryHistory()
411 self.debugger_history = InMemoryHistory()
412
412
413 def ask_exit(self):
413 def ask_exit(self):
414 self.keep_running = False
414 self.keep_running = False
415
415
416 rl_next_input = None
416 rl_next_input = None
417
417
418 def pre_prompt(self):
418 def pre_prompt(self):
419 if self.rl_next_input:
419 if self.rl_next_input:
420 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
420 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
421 self.rl_next_input = None
421 self.rl_next_input = None
422
422
423 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
423 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
424
424
425 if display_banner is not DISPLAY_BANNER_DEPRECATED:
425 if display_banner is not DISPLAY_BANNER_DEPRECATED:
426 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
426 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
427
427
428 self.keep_running = True
428 self.keep_running = True
429 while self.keep_running:
429 while self.keep_running:
430 print(self.separate_in, end='')
430 print(self.separate_in, end='')
431
431
432 try:
432 try:
433 code = self.prompt_for_code()
433 code = self.prompt_for_code()
434 except EOFError:
434 except EOFError:
435 if (not self.confirm_exit) \
435 if (not self.confirm_exit) \
436 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
436 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
437 self.ask_exit()
437 self.ask_exit()
438
438
439 else:
439 else:
440 if code:
440 if code:
441 self.run_cell(code, store_history=True)
441 self.run_cell(code, store_history=True)
442
442
443 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
443 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
444 # An extra layer of protection in case someone mashing Ctrl-C breaks
444 # An extra layer of protection in case someone mashing Ctrl-C breaks
445 # out of our internal code.
445 # out of our internal code.
446 if display_banner is not DISPLAY_BANNER_DEPRECATED:
446 if display_banner is not DISPLAY_BANNER_DEPRECATED:
447 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
447 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
448 while True:
448 while True:
449 try:
449 try:
450 self.interact()
450 self.interact()
451 break
451 break
452 except KeyboardInterrupt:
452 except KeyboardInterrupt:
453 print("\nKeyboardInterrupt escaped interact()\n")
453 print("\nKeyboardInterrupt escaped interact()\n")
454
454
455 _inputhook = None
455 _inputhook = None
456 def inputhook(self, context):
456 def inputhook(self, context):
457 if self._inputhook is not None:
457 if self._inputhook is not None:
458 self._inputhook(context)
458 self._inputhook(context)
459
459
460 active_eventloop = None
460 active_eventloop = None
461 def enable_gui(self, gui=None):
461 def enable_gui(self, gui=None):
462 if gui:
462 if gui:
463 self.active_eventloop, self._inputhook =\
463 self.active_eventloop, self._inputhook =\
464 get_inputhook_name_and_func(gui)
464 get_inputhook_name_and_func(gui)
465 else:
465 else:
466 self.active_eventloop = self._inputhook = None
466 self.active_eventloop = self._inputhook = None
467
467
468 # Run !system commands directly, not through pipes, so terminal programs
468 # Run !system commands directly, not through pipes, so terminal programs
469 # work correctly.
469 # work correctly.
470 system = InteractiveShell.system_raw
470 system = InteractiveShell.system_raw
471
471
472 def auto_rewrite_input(self, cmd):
472 def auto_rewrite_input(self, cmd):
473 """Overridden from the parent class to use fancy rewriting prompt"""
473 """Overridden from the parent class to use fancy rewriting prompt"""
474 if not self.show_rewritten_input:
474 if not self.show_rewritten_input:
475 return
475 return
476
476
477 tokens = self.prompts.rewrite_prompt_tokens()
477 tokens = self.prompts.rewrite_prompt_tokens()
478 if self.pt_cli:
478 if self.pt_cli:
479 self.pt_cli.print_tokens(tokens)
479 self.pt_cli.print_tokens(tokens)
480 print(cmd)
480 print(cmd)
481 else:
481 else:
482 prompt = ''.join(s for t, s in tokens)
482 prompt = ''.join(s for t, s in tokens)
483 print(prompt, cmd, sep='')
483 print(prompt, cmd, sep='')
484
484
485 _prompts_before = None
485 _prompts_before = None
486 def switch_doctest_mode(self, mode):
486 def switch_doctest_mode(self, mode):
487 """Switch prompts to classic for %doctest_mode"""
487 """Switch prompts to classic for %doctest_mode"""
488 if mode:
488 if mode:
489 self._prompts_before = self.prompts
489 self._prompts_before = self.prompts
490 self.prompts = ClassicPrompts(self)
490 self.prompts = ClassicPrompts(self)
491 elif self._prompts_before:
491 elif self._prompts_before:
492 self.prompts = self._prompts_before
492 self.prompts = self._prompts_before
493 self._prompts_before = None
493 self._prompts_before = None
494 self._update_layout()
494 self._update_layout()
495
495
496
496
497 InteractiveShellABC.register(TerminalInteractiveShell)
497 InteractiveShellABC.register(TerminalInteractiveShell)
498
498
499 if __name__ == '__main__':
499 if __name__ == '__main__':
500 TerminalInteractiveShell.instance().interact()
500 TerminalInteractiveShell.instance().interact()
@@ -1,206 +1,206 b''
1 """Extra magics for terminal use."""
1 """Extra magics for terminal use."""
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
6
7 from logging import error
7 from logging import error
8 import os
8 import os
9 import sys
9 import sys
10
10
11 from IPython.core.error import TryNext, UsageError
11 from IPython.core.error import TryNext, UsageError
12 from IPython.core.inputsplitter import IPythonInputSplitter
12 from IPython.core.inputsplitter import IPythonInputSplitter
13 from IPython.core.magic import Magics, magics_class, line_magic
13 from IPython.core.magic import Magics, magics_class, line_magic
14 from IPython.lib.clipboard import ClipboardEmpty
14 from IPython.lib.clipboard import ClipboardEmpty
15 from IPython.utils.text import SList, strip_email_quotes
15 from IPython.utils.text import SList, strip_email_quotes
16 from IPython.utils import py3compat
16 from IPython.utils import py3compat
17
17
18 def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
18 def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
19 """ Yield pasted lines until the user enters the given sentinel value.
19 """ Yield pasted lines until the user enters the given sentinel value.
20 """
20 """
21 if not quiet:
21 if not quiet:
22 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
22 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
23 % sentinel)
23 % sentinel)
24 prompt = ":"
24 prompt = ":"
25 else:
25 else:
26 prompt = ""
26 prompt = ""
27 while True:
27 while True:
28 try:
28 try:
29 l = py3compat.str_to_unicode(l_input(prompt))
29 l = l_input(prompt)
30 if l == sentinel:
30 if l == sentinel:
31 return
31 return
32 else:
32 else:
33 yield l
33 yield l
34 except EOFError:
34 except EOFError:
35 print('<EOF>')
35 print('<EOF>')
36 return
36 return
37
37
38
38
39 @magics_class
39 @magics_class
40 class TerminalMagics(Magics):
40 class TerminalMagics(Magics):
41 def __init__(self, shell):
41 def __init__(self, shell):
42 super(TerminalMagics, self).__init__(shell)
42 super(TerminalMagics, self).__init__(shell)
43 self.input_splitter = IPythonInputSplitter()
43 self.input_splitter = IPythonInputSplitter()
44
44
45 def store_or_execute(self, block, name):
45 def store_or_execute(self, block, name):
46 """ Execute a block, or store it in a variable, per the user's request.
46 """ Execute a block, or store it in a variable, per the user's request.
47 """
47 """
48 if name:
48 if name:
49 # If storing it for further editing
49 # If storing it for further editing
50 self.shell.user_ns[name] = SList(block.splitlines())
50 self.shell.user_ns[name] = SList(block.splitlines())
51 print("Block assigned to '%s'" % name)
51 print("Block assigned to '%s'" % name)
52 else:
52 else:
53 b = self.preclean_input(block)
53 b = self.preclean_input(block)
54 self.shell.user_ns['pasted_block'] = b
54 self.shell.user_ns['pasted_block'] = b
55 self.shell.using_paste_magics = True
55 self.shell.using_paste_magics = True
56 try:
56 try:
57 self.shell.run_cell(b)
57 self.shell.run_cell(b)
58 finally:
58 finally:
59 self.shell.using_paste_magics = False
59 self.shell.using_paste_magics = False
60
60
61 def preclean_input(self, block):
61 def preclean_input(self, block):
62 lines = block.splitlines()
62 lines = block.splitlines()
63 while lines and not lines[0].strip():
63 while lines and not lines[0].strip():
64 lines = lines[1:]
64 lines = lines[1:]
65 return strip_email_quotes('\n'.join(lines))
65 return strip_email_quotes('\n'.join(lines))
66
66
67 def rerun_pasted(self, name='pasted_block'):
67 def rerun_pasted(self, name='pasted_block'):
68 """ Rerun a previously pasted command.
68 """ Rerun a previously pasted command.
69 """
69 """
70 b = self.shell.user_ns.get(name)
70 b = self.shell.user_ns.get(name)
71
71
72 # Sanity checks
72 # Sanity checks
73 if b is None:
73 if b is None:
74 raise UsageError('No previous pasted block available')
74 raise UsageError('No previous pasted block available')
75 if not isinstance(b, py3compat.string_types):
75 if not isinstance(b, str):
76 raise UsageError(
76 raise UsageError(
77 "Variable 'pasted_block' is not a string, can't execute")
77 "Variable 'pasted_block' is not a string, can't execute")
78
78
79 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
79 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
80 self.shell.run_cell(b)
80 self.shell.run_cell(b)
81
81
82 @line_magic
82 @line_magic
83 def autoindent(self, parameter_s = ''):
83 def autoindent(self, parameter_s = ''):
84 """Toggle autoindent on/off (if available)."""
84 """Toggle autoindent on/off (if available)."""
85
85
86 self.shell.set_autoindent()
86 self.shell.set_autoindent()
87 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
87 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
88
88
89 @line_magic
89 @line_magic
90 def cpaste(self, parameter_s=''):
90 def cpaste(self, parameter_s=''):
91 """Paste & execute a pre-formatted code block from clipboard.
91 """Paste & execute a pre-formatted code block from clipboard.
92
92
93 You must terminate the block with '--' (two minus-signs) or Ctrl-D
93 You must terminate the block with '--' (two minus-signs) or Ctrl-D
94 alone on the line. You can also provide your own sentinel with '%paste
94 alone on the line. You can also provide your own sentinel with '%paste
95 -s %%' ('%%' is the new sentinel for this operation).
95 -s %%' ('%%' is the new sentinel for this operation).
96
96
97 The block is dedented prior to execution to enable execution of method
97 The block is dedented prior to execution to enable execution of method
98 definitions. '>' and '+' characters at the beginning of a line are
98 definitions. '>' and '+' characters at the beginning of a line are
99 ignored, to allow pasting directly from e-mails, diff files and
99 ignored, to allow pasting directly from e-mails, diff files and
100 doctests (the '...' continuation prompt is also stripped). The
100 doctests (the '...' continuation prompt is also stripped). The
101 executed block is also assigned to variable named 'pasted_block' for
101 executed block is also assigned to variable named 'pasted_block' for
102 later editing with '%edit pasted_block'.
102 later editing with '%edit pasted_block'.
103
103
104 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
104 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
105 This assigns the pasted block to variable 'foo' as string, without
105 This assigns the pasted block to variable 'foo' as string, without
106 dedenting or executing it (preceding >>> and + is still stripped)
106 dedenting or executing it (preceding >>> and + is still stripped)
107
107
108 '%cpaste -r' re-executes the block previously entered by cpaste.
108 '%cpaste -r' re-executes the block previously entered by cpaste.
109 '%cpaste -q' suppresses any additional output messages.
109 '%cpaste -q' suppresses any additional output messages.
110
110
111 Do not be alarmed by garbled output on Windows (it's a readline bug).
111 Do not be alarmed by garbled output on Windows (it's a readline bug).
112 Just press enter and type -- (and press enter again) and the block
112 Just press enter and type -- (and press enter again) and the block
113 will be what was just pasted.
113 will be what was just pasted.
114
114
115 IPython statements (magics, shell escapes) are not supported (yet).
115 IPython statements (magics, shell escapes) are not supported (yet).
116
116
117 See also
117 See also
118 --------
118 --------
119 paste: automatically pull code from clipboard.
119 paste: automatically pull code from clipboard.
120
120
121 Examples
121 Examples
122 --------
122 --------
123 ::
123 ::
124
124
125 In [8]: %cpaste
125 In [8]: %cpaste
126 Pasting code; enter '--' alone on the line to stop.
126 Pasting code; enter '--' alone on the line to stop.
127 :>>> a = ["world!", "Hello"]
127 :>>> a = ["world!", "Hello"]
128 :>>> print " ".join(sorted(a))
128 :>>> print " ".join(sorted(a))
129 :--
129 :--
130 Hello world!
130 Hello world!
131 """
131 """
132 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
132 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
133 if 'r' in opts:
133 if 'r' in opts:
134 self.rerun_pasted()
134 self.rerun_pasted()
135 return
135 return
136
136
137 quiet = ('q' in opts)
137 quiet = ('q' in opts)
138
138
139 sentinel = opts.get('s', u'--')
139 sentinel = opts.get('s', u'--')
140 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
140 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
141 self.store_or_execute(block, name)
141 self.store_or_execute(block, name)
142
142
143 @line_magic
143 @line_magic
144 def paste(self, parameter_s=''):
144 def paste(self, parameter_s=''):
145 """Paste & execute a pre-formatted code block from clipboard.
145 """Paste & execute a pre-formatted code block from clipboard.
146
146
147 The text is pulled directly from the clipboard without user
147 The text is pulled directly from the clipboard without user
148 intervention and printed back on the screen before execution (unless
148 intervention and printed back on the screen before execution (unless
149 the -q flag is given to force quiet mode).
149 the -q flag is given to force quiet mode).
150
150
151 The block is dedented prior to execution to enable execution of method
151 The block is dedented prior to execution to enable execution of method
152 definitions. '>' and '+' characters at the beginning of a line are
152 definitions. '>' and '+' characters at the beginning of a line are
153 ignored, to allow pasting directly from e-mails, diff files and
153 ignored, to allow pasting directly from e-mails, diff files and
154 doctests (the '...' continuation prompt is also stripped). The
154 doctests (the '...' continuation prompt is also stripped). The
155 executed block is also assigned to variable named 'pasted_block' for
155 executed block is also assigned to variable named 'pasted_block' for
156 later editing with '%edit pasted_block'.
156 later editing with '%edit pasted_block'.
157
157
158 You can also pass a variable name as an argument, e.g. '%paste foo'.
158 You can also pass a variable name as an argument, e.g. '%paste foo'.
159 This assigns the pasted block to variable 'foo' as string, without
159 This assigns the pasted block to variable 'foo' as string, without
160 executing it (preceding >>> and + is still stripped).
160 executing it (preceding >>> and + is still stripped).
161
161
162 Options:
162 Options:
163
163
164 -r: re-executes the block previously entered by cpaste.
164 -r: re-executes the block previously entered by cpaste.
165
165
166 -q: quiet mode: do not echo the pasted text back to the terminal.
166 -q: quiet mode: do not echo the pasted text back to the terminal.
167
167
168 IPython statements (magics, shell escapes) are not supported (yet).
168 IPython statements (magics, shell escapes) are not supported (yet).
169
169
170 See also
170 See also
171 --------
171 --------
172 cpaste: manually paste code into terminal until you mark its end.
172 cpaste: manually paste code into terminal until you mark its end.
173 """
173 """
174 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
174 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
175 if 'r' in opts:
175 if 'r' in opts:
176 self.rerun_pasted()
176 self.rerun_pasted()
177 return
177 return
178 try:
178 try:
179 block = self.shell.hooks.clipboard_get()
179 block = self.shell.hooks.clipboard_get()
180 except TryNext as clipboard_exc:
180 except TryNext as clipboard_exc:
181 message = getattr(clipboard_exc, 'args')
181 message = getattr(clipboard_exc, 'args')
182 if message:
182 if message:
183 error(message[0])
183 error(message[0])
184 else:
184 else:
185 error('Could not get text from the clipboard.')
185 error('Could not get text from the clipboard.')
186 return
186 return
187 except ClipboardEmpty:
187 except ClipboardEmpty:
188 raise UsageError("The clipboard appears to be empty")
188 raise UsageError("The clipboard appears to be empty")
189
189
190 # By default, echo back to terminal unless quiet mode is requested
190 # By default, echo back to terminal unless quiet mode is requested
191 if 'q' not in opts:
191 if 'q' not in opts:
192 write = self.shell.write
192 write = self.shell.write
193 write(self.shell.pycolorize(block))
193 write(self.shell.pycolorize(block))
194 if not block.endswith('\n'):
194 if not block.endswith('\n'):
195 write('\n')
195 write('\n')
196 write("## -- End pasted text --\n")
196 write("## -- End pasted text --\n")
197
197
198 self.store_or_execute(block, name)
198 self.store_or_execute(block, name)
199
199
200 # Class-level: add a '%cls' magic only on Windows
200 # Class-level: add a '%cls' magic only on Windows
201 if sys.platform == 'win32':
201 if sys.platform == 'win32':
202 @line_magic
202 @line_magic
203 def cls(self, s):
203 def cls(self, s):
204 """Clear screen.
204 """Clear screen.
205 """
205 """
206 os.system("cls")
206 os.system("cls")
@@ -1,378 +1,378 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Decorators for labeling test objects.
2 """Decorators for labeling test objects.
3
3
4 Decorators that merely return a modified version of the original function
4 Decorators that merely return a modified version of the original function
5 object are straightforward. Decorators that return a new function object need
5 object are straightforward. Decorators that return a new function object need
6 to use nose.tools.make_decorator(original_function)(decorator) in returning the
6 to use nose.tools.make_decorator(original_function)(decorator) in returning the
7 decorator, in order to preserve metadata such as function name, setup and
7 decorator, in order to preserve metadata such as function name, setup and
8 teardown functions and so on - see nose.tools for more information.
8 teardown functions and so on - see nose.tools for more information.
9
9
10 This module provides a set of useful decorators meant to be ready to use in
10 This module provides a set of useful decorators meant to be ready to use in
11 your own tests. See the bottom of the file for the ready-made ones, and if you
11 your own tests. See the bottom of the file for the ready-made ones, and if you
12 find yourself writing a new one that may be of generic use, add it here.
12 find yourself writing a new one that may be of generic use, add it here.
13
13
14 Included decorators:
14 Included decorators:
15
15
16
16
17 Lightweight testing that remains unittest-compatible.
17 Lightweight testing that remains unittest-compatible.
18
18
19 - An @as_unittest decorator can be used to tag any normal parameter-less
19 - An @as_unittest decorator can be used to tag any normal parameter-less
20 function as a unittest TestCase. Then, both nose and normal unittest will
20 function as a unittest TestCase. Then, both nose and normal unittest will
21 recognize it as such. This will make it easier to migrate away from Nose if
21 recognize it as such. This will make it easier to migrate away from Nose if
22 we ever need/want to while maintaining very lightweight tests.
22 we ever need/want to while maintaining very lightweight tests.
23
23
24 NOTE: This file contains IPython-specific decorators. Using the machinery in
24 NOTE: This file contains IPython-specific decorators. Using the machinery in
25 IPython.external.decorators, we import either numpy.testing.decorators if numpy is
25 IPython.external.decorators, we import either numpy.testing.decorators if numpy is
26 available, OR use equivalent code in IPython.external._decorators, which
26 available, OR use equivalent code in IPython.external._decorators, which
27 we've copied verbatim from numpy.
27 we've copied verbatim from numpy.
28
28
29 """
29 """
30
30
31 # Copyright (c) IPython Development Team.
31 # Copyright (c) IPython Development Team.
32 # Distributed under the terms of the Modified BSD License.
32 # Distributed under the terms of the Modified BSD License.
33
33
34 import sys
34 import sys
35 import os
35 import os
36 import tempfile
36 import tempfile
37 import unittest
37 import unittest
38 import warnings
38 import warnings
39 from importlib import import_module
39 from importlib import import_module
40
40
41 from decorator import decorator
41 from decorator import decorator
42
42
43 # Expose the unittest-driven decorators
43 # Expose the unittest-driven decorators
44 from .ipunittest import ipdoctest, ipdocstring
44 from .ipunittest import ipdoctest, ipdocstring
45
45
46 # Grab the numpy-specific decorators which we keep in a file that we
46 # Grab the numpy-specific decorators which we keep in a file that we
47 # occasionally update from upstream: decorators.py is a copy of
47 # occasionally update from upstream: decorators.py is a copy of
48 # numpy.testing.decorators, we expose all of it here.
48 # numpy.testing.decorators, we expose all of it here.
49 from IPython.external.decorators import *
49 from IPython.external.decorators import *
50
50
51 # For onlyif_cmd_exists decorator
51 # For onlyif_cmd_exists decorator
52 from IPython.utils.py3compat import string_types, which, PY2, PY3, PYPY
52 from IPython.utils.py3compat import which, PY2, PY3, PYPY
53
53
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55 # Classes and functions
55 # Classes and functions
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57
57
58 # Simple example of the basic idea
58 # Simple example of the basic idea
59 def as_unittest(func):
59 def as_unittest(func):
60 """Decorator to make a simple function into a normal test via unittest."""
60 """Decorator to make a simple function into a normal test via unittest."""
61 class Tester(unittest.TestCase):
61 class Tester(unittest.TestCase):
62 def test(self):
62 def test(self):
63 func()
63 func()
64
64
65 Tester.__name__ = func.__name__
65 Tester.__name__ = func.__name__
66
66
67 return Tester
67 return Tester
68
68
69 # Utility functions
69 # Utility functions
70
70
71 def apply_wrapper(wrapper, func):
71 def apply_wrapper(wrapper, func):
72 """Apply a wrapper to a function for decoration.
72 """Apply a wrapper to a function for decoration.
73
73
74 This mixes Michele Simionato's decorator tool with nose's make_decorator,
74 This mixes Michele Simionato's decorator tool with nose's make_decorator,
75 to apply a wrapper in a decorator so that all nose attributes, as well as
75 to apply a wrapper in a decorator so that all nose attributes, as well as
76 function signature and other properties, survive the decoration cleanly.
76 function signature and other properties, survive the decoration cleanly.
77 This will ensure that wrapped functions can still be well introspected via
77 This will ensure that wrapped functions can still be well introspected via
78 IPython, for example.
78 IPython, for example.
79 """
79 """
80 warnings.warn("The function `apply_wrapper` is deprecated since IPython 4.0",
80 warnings.warn("The function `apply_wrapper` is deprecated since IPython 4.0",
81 DeprecationWarning, stacklevel=2)
81 DeprecationWarning, stacklevel=2)
82 import nose.tools
82 import nose.tools
83
83
84 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
84 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
85
85
86
86
87 def make_label_dec(label, ds=None):
87 def make_label_dec(label, ds=None):
88 """Factory function to create a decorator that applies one or more labels.
88 """Factory function to create a decorator that applies one or more labels.
89
89
90 Parameters
90 Parameters
91 ----------
91 ----------
92 label : string or sequence
92 label : string or sequence
93 One or more labels that will be applied by the decorator to the functions
93 One or more labels that will be applied by the decorator to the functions
94 it decorates. Labels are attributes of the decorated function with their
94 it decorates. Labels are attributes of the decorated function with their
95 value set to True.
95 value set to True.
96
96
97 ds : string
97 ds : string
98 An optional docstring for the resulting decorator. If not given, a
98 An optional docstring for the resulting decorator. If not given, a
99 default docstring is auto-generated.
99 default docstring is auto-generated.
100
100
101 Returns
101 Returns
102 -------
102 -------
103 A decorator.
103 A decorator.
104
104
105 Examples
105 Examples
106 --------
106 --------
107
107
108 A simple labeling decorator:
108 A simple labeling decorator:
109
109
110 >>> slow = make_label_dec('slow')
110 >>> slow = make_label_dec('slow')
111 >>> slow.__doc__
111 >>> slow.__doc__
112 "Labels a test as 'slow'."
112 "Labels a test as 'slow'."
113
113
114 And one that uses multiple labels and a custom docstring:
114 And one that uses multiple labels and a custom docstring:
115
115
116 >>> rare = make_label_dec(['slow','hard'],
116 >>> rare = make_label_dec(['slow','hard'],
117 ... "Mix labels 'slow' and 'hard' for rare tests.")
117 ... "Mix labels 'slow' and 'hard' for rare tests.")
118 >>> rare.__doc__
118 >>> rare.__doc__
119 "Mix labels 'slow' and 'hard' for rare tests."
119 "Mix labels 'slow' and 'hard' for rare tests."
120
120
121 Now, let's test using this one:
121 Now, let's test using this one:
122 >>> @rare
122 >>> @rare
123 ... def f(): pass
123 ... def f(): pass
124 ...
124 ...
125 >>>
125 >>>
126 >>> f.slow
126 >>> f.slow
127 True
127 True
128 >>> f.hard
128 >>> f.hard
129 True
129 True
130 """
130 """
131
131
132 warnings.warn("The function `make_label_dec` is deprecated since IPython 4.0",
132 warnings.warn("The function `make_label_dec` is deprecated since IPython 4.0",
133 DeprecationWarning, stacklevel=2)
133 DeprecationWarning, stacklevel=2)
134 if isinstance(label, string_types):
134 if isinstance(label, str):
135 labels = [label]
135 labels = [label]
136 else:
136 else:
137 labels = label
137 labels = label
138
138
139 # Validate that the given label(s) are OK for use in setattr() by doing a
139 # Validate that the given label(s) are OK for use in setattr() by doing a
140 # dry run on a dummy function.
140 # dry run on a dummy function.
141 tmp = lambda : None
141 tmp = lambda : None
142 for label in labels:
142 for label in labels:
143 setattr(tmp,label,True)
143 setattr(tmp,label,True)
144
144
145 # This is the actual decorator we'll return
145 # This is the actual decorator we'll return
146 def decor(f):
146 def decor(f):
147 for label in labels:
147 for label in labels:
148 setattr(f,label,True)
148 setattr(f,label,True)
149 return f
149 return f
150
150
151 # Apply the user's docstring, or autogenerate a basic one
151 # Apply the user's docstring, or autogenerate a basic one
152 if ds is None:
152 if ds is None:
153 ds = "Labels a test as %r." % label
153 ds = "Labels a test as %r." % label
154 decor.__doc__ = ds
154 decor.__doc__ = ds
155
155
156 return decor
156 return decor
157
157
158
158
159 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
159 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
160 # preserve function metadata better and allows the skip condition to be a
160 # preserve function metadata better and allows the skip condition to be a
161 # callable.
161 # callable.
162 def skipif(skip_condition, msg=None):
162 def skipif(skip_condition, msg=None):
163 ''' Make function raise SkipTest exception if skip_condition is true
163 ''' Make function raise SkipTest exception if skip_condition is true
164
164
165 Parameters
165 Parameters
166 ----------
166 ----------
167
167
168 skip_condition : bool or callable
168 skip_condition : bool or callable
169 Flag to determine whether to skip test. If the condition is a
169 Flag to determine whether to skip test. If the condition is a
170 callable, it is used at runtime to dynamically make the decision. This
170 callable, it is used at runtime to dynamically make the decision. This
171 is useful for tests that may require costly imports, to delay the cost
171 is useful for tests that may require costly imports, to delay the cost
172 until the test suite is actually executed.
172 until the test suite is actually executed.
173 msg : string
173 msg : string
174 Message to give on raising a SkipTest exception.
174 Message to give on raising a SkipTest exception.
175
175
176 Returns
176 Returns
177 -------
177 -------
178 decorator : function
178 decorator : function
179 Decorator, which, when applied to a function, causes SkipTest
179 Decorator, which, when applied to a function, causes SkipTest
180 to be raised when the skip_condition was True, and the function
180 to be raised when the skip_condition was True, and the function
181 to be called normally otherwise.
181 to be called normally otherwise.
182
182
183 Notes
183 Notes
184 -----
184 -----
185 You will see from the code that we had to further decorate the
185 You will see from the code that we had to further decorate the
186 decorator with the nose.tools.make_decorator function in order to
186 decorator with the nose.tools.make_decorator function in order to
187 transmit function name, and various other metadata.
187 transmit function name, and various other metadata.
188 '''
188 '''
189
189
190 def skip_decorator(f):
190 def skip_decorator(f):
191 # Local import to avoid a hard nose dependency and only incur the
191 # Local import to avoid a hard nose dependency and only incur the
192 # import time overhead at actual test-time.
192 # import time overhead at actual test-time.
193 import nose
193 import nose
194
194
195 # Allow for both boolean or callable skip conditions.
195 # Allow for both boolean or callable skip conditions.
196 if callable(skip_condition):
196 if callable(skip_condition):
197 skip_val = skip_condition
197 skip_val = skip_condition
198 else:
198 else:
199 skip_val = lambda : skip_condition
199 skip_val = lambda : skip_condition
200
200
201 def get_msg(func,msg=None):
201 def get_msg(func,msg=None):
202 """Skip message with information about function being skipped."""
202 """Skip message with information about function being skipped."""
203 if msg is None: out = 'Test skipped due to test condition.'
203 if msg is None: out = 'Test skipped due to test condition.'
204 else: out = msg
204 else: out = msg
205 return "Skipping test: %s. %s" % (func.__name__,out)
205 return "Skipping test: %s. %s" % (func.__name__,out)
206
206
207 # We need to define *two* skippers because Python doesn't allow both
207 # We need to define *two* skippers because Python doesn't allow both
208 # return with value and yield inside the same function.
208 # return with value and yield inside the same function.
209 def skipper_func(*args, **kwargs):
209 def skipper_func(*args, **kwargs):
210 """Skipper for normal test functions."""
210 """Skipper for normal test functions."""
211 if skip_val():
211 if skip_val():
212 raise nose.SkipTest(get_msg(f,msg))
212 raise nose.SkipTest(get_msg(f,msg))
213 else:
213 else:
214 return f(*args, **kwargs)
214 return f(*args, **kwargs)
215
215
216 def skipper_gen(*args, **kwargs):
216 def skipper_gen(*args, **kwargs):
217 """Skipper for test generators."""
217 """Skipper for test generators."""
218 if skip_val():
218 if skip_val():
219 raise nose.SkipTest(get_msg(f,msg))
219 raise nose.SkipTest(get_msg(f,msg))
220 else:
220 else:
221 for x in f(*args, **kwargs):
221 for x in f(*args, **kwargs):
222 yield x
222 yield x
223
223
224 # Choose the right skipper to use when building the actual generator.
224 # Choose the right skipper to use when building the actual generator.
225 if nose.util.isgenerator(f):
225 if nose.util.isgenerator(f):
226 skipper = skipper_gen
226 skipper = skipper_gen
227 else:
227 else:
228 skipper = skipper_func
228 skipper = skipper_func
229
229
230 return nose.tools.make_decorator(f)(skipper)
230 return nose.tools.make_decorator(f)(skipper)
231
231
232 return skip_decorator
232 return skip_decorator
233
233
234 # A version with the condition set to true, common case just to attach a message
234 # A version with the condition set to true, common case just to attach a message
235 # to a skip decorator
235 # to a skip decorator
236 def skip(msg=None):
236 def skip(msg=None):
237 """Decorator factory - mark a test function for skipping from test suite.
237 """Decorator factory - mark a test function for skipping from test suite.
238
238
239 Parameters
239 Parameters
240 ----------
240 ----------
241 msg : string
241 msg : string
242 Optional message to be added.
242 Optional message to be added.
243
243
244 Returns
244 Returns
245 -------
245 -------
246 decorator : function
246 decorator : function
247 Decorator, which, when applied to a function, causes SkipTest
247 Decorator, which, when applied to a function, causes SkipTest
248 to be raised, with the optional message added.
248 to be raised, with the optional message added.
249 """
249 """
250
250
251 return skipif(True,msg)
251 return skipif(True,msg)
252
252
253
253
254 def onlyif(condition, msg):
254 def onlyif(condition, msg):
255 """The reverse from skipif, see skipif for details."""
255 """The reverse from skipif, see skipif for details."""
256
256
257 if callable(condition):
257 if callable(condition):
258 skip_condition = lambda : not condition()
258 skip_condition = lambda : not condition()
259 else:
259 else:
260 skip_condition = lambda : not condition
260 skip_condition = lambda : not condition
261
261
262 return skipif(skip_condition, msg)
262 return skipif(skip_condition, msg)
263
263
264 #-----------------------------------------------------------------------------
264 #-----------------------------------------------------------------------------
265 # Utility functions for decorators
265 # Utility functions for decorators
266 def module_not_available(module):
266 def module_not_available(module):
267 """Can module be imported? Returns true if module does NOT import.
267 """Can module be imported? Returns true if module does NOT import.
268
268
269 This is used to make a decorator to skip tests that require module to be
269 This is used to make a decorator to skip tests that require module to be
270 available, but delay the 'import numpy' to test execution time.
270 available, but delay the 'import numpy' to test execution time.
271 """
271 """
272 try:
272 try:
273 mod = import_module(module)
273 mod = import_module(module)
274 mod_not_avail = False
274 mod_not_avail = False
275 except ImportError:
275 except ImportError:
276 mod_not_avail = True
276 mod_not_avail = True
277
277
278 return mod_not_avail
278 return mod_not_avail
279
279
280
280
281 def decorated_dummy(dec, name):
281 def decorated_dummy(dec, name):
282 """Return a dummy function decorated with dec, with the given name.
282 """Return a dummy function decorated with dec, with the given name.
283
283
284 Examples
284 Examples
285 --------
285 --------
286 import IPython.testing.decorators as dec
286 import IPython.testing.decorators as dec
287 setup = dec.decorated_dummy(dec.skip_if_no_x11, __name__)
287 setup = dec.decorated_dummy(dec.skip_if_no_x11, __name__)
288 """
288 """
289 warnings.warn("The function `decorated_dummy` is deprecated since IPython 4.0",
289 warnings.warn("The function `decorated_dummy` is deprecated since IPython 4.0",
290 DeprecationWarning, stacklevel=2)
290 DeprecationWarning, stacklevel=2)
291 dummy = lambda: None
291 dummy = lambda: None
292 dummy.__name__ = name
292 dummy.__name__ = name
293 return dec(dummy)
293 return dec(dummy)
294
294
295 #-----------------------------------------------------------------------------
295 #-----------------------------------------------------------------------------
296 # Decorators for public use
296 # Decorators for public use
297
297
298 # Decorators to skip certain tests on specific platforms.
298 # Decorators to skip certain tests on specific platforms.
299 skip_win32 = skipif(sys.platform == 'win32',
299 skip_win32 = skipif(sys.platform == 'win32',
300 "This test does not run under Windows")
300 "This test does not run under Windows")
301 skip_linux = skipif(sys.platform.startswith('linux'),
301 skip_linux = skipif(sys.platform.startswith('linux'),
302 "This test does not run under Linux")
302 "This test does not run under Linux")
303 skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X")
303 skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X")
304
304
305
305
306 # Decorators to skip tests if not on specific platforms.
306 # Decorators to skip tests if not on specific platforms.
307 skip_if_not_win32 = skipif(sys.platform != 'win32',
307 skip_if_not_win32 = skipif(sys.platform != 'win32',
308 "This test only runs under Windows")
308 "This test only runs under Windows")
309 skip_if_not_linux = skipif(not sys.platform.startswith('linux'),
309 skip_if_not_linux = skipif(not sys.platform.startswith('linux'),
310 "This test only runs under Linux")
310 "This test only runs under Linux")
311 skip_if_not_osx = skipif(sys.platform != 'darwin',
311 skip_if_not_osx = skipif(sys.platform != 'darwin',
312 "This test only runs under OSX")
312 "This test only runs under OSX")
313
313
314
314
315 _x11_skip_cond = (sys.platform not in ('darwin', 'win32') and
315 _x11_skip_cond = (sys.platform not in ('darwin', 'win32') and
316 os.environ.get('DISPLAY', '') == '')
316 os.environ.get('DISPLAY', '') == '')
317 _x11_skip_msg = "Skipped under *nix when X11/XOrg not available"
317 _x11_skip_msg = "Skipped under *nix when X11/XOrg not available"
318
318
319 skip_if_no_x11 = skipif(_x11_skip_cond, _x11_skip_msg)
319 skip_if_no_x11 = skipif(_x11_skip_cond, _x11_skip_msg)
320
320
321 # not a decorator itself, returns a dummy function to be used as setup
321 # not a decorator itself, returns a dummy function to be used as setup
322 def skip_file_no_x11(name):
322 def skip_file_no_x11(name):
323 warnings.warn("The function `skip_file_no_x11` is deprecated since IPython 4.0",
323 warnings.warn("The function `skip_file_no_x11` is deprecated since IPython 4.0",
324 DeprecationWarning, stacklevel=2)
324 DeprecationWarning, stacklevel=2)
325 return decorated_dummy(skip_if_no_x11, name) if _x11_skip_cond else None
325 return decorated_dummy(skip_if_no_x11, name) if _x11_skip_cond else None
326
326
327 # Other skip decorators
327 # Other skip decorators
328
328
329 # generic skip without module
329 # generic skip without module
330 skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod)
330 skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod)
331
331
332 skipif_not_numpy = skip_without('numpy')
332 skipif_not_numpy = skip_without('numpy')
333
333
334 skipif_not_matplotlib = skip_without('matplotlib')
334 skipif_not_matplotlib = skip_without('matplotlib')
335
335
336 skipif_not_sympy = skip_without('sympy')
336 skipif_not_sympy = skip_without('sympy')
337
337
338 skip_known_failure = knownfailureif(True,'This test is known to fail')
338 skip_known_failure = knownfailureif(True,'This test is known to fail')
339
339
340 # A null 'decorator', useful to make more readable code that needs to pick
340 # A null 'decorator', useful to make more readable code that needs to pick
341 # between different decorators based on OS or other conditions
341 # between different decorators based on OS or other conditions
342 null_deco = lambda f: f
342 null_deco = lambda f: f
343
343
344 # Some tests only run where we can use unicode paths. Note that we can't just
344 # Some tests only run where we can use unicode paths. Note that we can't just
345 # check os.path.supports_unicode_filenames, which is always False on Linux.
345 # check os.path.supports_unicode_filenames, which is always False on Linux.
346 try:
346 try:
347 f = tempfile.NamedTemporaryFile(prefix=u"tmp€")
347 f = tempfile.NamedTemporaryFile(prefix=u"tmp€")
348 except UnicodeEncodeError:
348 except UnicodeEncodeError:
349 unicode_paths = False
349 unicode_paths = False
350 else:
350 else:
351 unicode_paths = True
351 unicode_paths = True
352 f.close()
352 f.close()
353
353
354 onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable "
354 onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable "
355 "where we can use unicode in filenames."))
355 "where we can use unicode in filenames."))
356
356
357
357
358 def onlyif_cmds_exist(*commands):
358 def onlyif_cmds_exist(*commands):
359 """
359 """
360 Decorator to skip test when at least one of `commands` is not found.
360 Decorator to skip test when at least one of `commands` is not found.
361 """
361 """
362 for cmd in commands:
362 for cmd in commands:
363 if not which(cmd):
363 if not which(cmd):
364 return skip("This test runs only if command '{0}' "
364 return skip("This test runs only if command '{0}' "
365 "is installed".format(cmd))
365 "is installed".format(cmd))
366 return null_deco
366 return null_deco
367
367
368 def onlyif_any_cmd_exists(*commands):
368 def onlyif_any_cmd_exists(*commands):
369 """
369 """
370 Decorator to skip test unless at least one of `commands` is found.
370 Decorator to skip test unless at least one of `commands` is found.
371 """
371 """
372 warnings.warn("The function `onlyif_any_cmd_exists` is deprecated since IPython 4.0",
372 warnings.warn("The function `onlyif_any_cmd_exists` is deprecated since IPython 4.0",
373 DeprecationWarning, stacklevel=2)
373 DeprecationWarning, stacklevel=2)
374 for cmd in commands:
374 for cmd in commands:
375 if which(cmd):
375 if which(cmd):
376 return null_deco
376 return null_deco
377 return skip("This test runs only if one of the commands {0} "
377 return skip("This test runs only if one of the commands {0} "
378 "is installed".format(commands))
378 "is installed".format(commands))
@@ -1,770 +1,770 b''
1 """Nose Plugin that supports IPython doctests.
1 """Nose Plugin that supports IPython doctests.
2
2
3 Limitations:
3 Limitations:
4
4
5 - When generating examples for use as doctests, make sure that you have
5 - When generating examples for use as doctests, make sure that you have
6 pretty-printing OFF. This can be done either by setting the
6 pretty-printing OFF. This can be done either by setting the
7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
8 by interactively disabling it with %Pprint. This is required so that IPython
8 by interactively disabling it with %Pprint. This is required so that IPython
9 output matches that of normal Python, which is used by doctest for internal
9 output matches that of normal Python, which is used by doctest for internal
10 execution.
10 execution.
11
11
12 - Do not rely on specific prompt numbers for results (such as using
12 - Do not rely on specific prompt numbers for results (such as using
13 '_34==True', for example). For IPython tests run via an external process the
13 '_34==True', for example). For IPython tests run via an external process the
14 prompt numbers may be different, and IPython tests run as normal python code
14 prompt numbers may be different, and IPython tests run as normal python code
15 won't even have these special _NN variables set at all.
15 won't even have these special _NN variables set at all.
16 """
16 """
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Module imports
19 # Module imports
20
20
21 # From the standard library
21 # From the standard library
22 import doctest
22 import doctest
23 import inspect
23 import inspect
24 import logging
24 import logging
25 import os
25 import os
26 import re
26 import re
27 import sys
27 import sys
28 from importlib import import_module
28 from importlib import import_module
29
29
30 from testpath import modified_env
30 from testpath import modified_env
31
31
32 from inspect import getmodule
32 from inspect import getmodule
33
33
34 # We are overriding the default doctest runner, so we need to import a few
34 # We are overriding the default doctest runner, so we need to import a few
35 # things from doctest directly
35 # things from doctest directly
36 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
36 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
37 _unittest_reportflags, DocTestRunner,
37 _unittest_reportflags, DocTestRunner,
38 _extract_future_flags, pdb, _OutputRedirectingPdb,
38 _extract_future_flags, pdb, _OutputRedirectingPdb,
39 _exception_traceback,
39 _exception_traceback,
40 linecache)
40 linecache)
41
41
42 # Third-party modules
42 # Third-party modules
43
43
44 from nose.plugins import doctests, Plugin
44 from nose.plugins import doctests, Plugin
45 from nose.util import anyp, tolist
45 from nose.util import anyp, tolist
46
46
47 # Our own imports
47 # Our own imports
48 from IPython.utils.py3compat import builtin_mod, PY3, getcwd
48 from IPython.utils.py3compat import builtin_mod, PY3
49
49
50 if PY3:
50 if PY3:
51 from io import StringIO
51 from io import StringIO
52 else:
52 else:
53 from StringIO import StringIO
53 from StringIO import StringIO
54
54
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 # Module globals and other constants
56 # Module globals and other constants
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58
58
59 log = logging.getLogger(__name__)
59 log = logging.getLogger(__name__)
60
60
61
61
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63 # Classes and functions
63 # Classes and functions
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65
65
66 def is_extension_module(filename):
66 def is_extension_module(filename):
67 """Return whether the given filename is an extension module.
67 """Return whether the given filename is an extension module.
68
68
69 This simply checks that the extension is either .so or .pyd.
69 This simply checks that the extension is either .so or .pyd.
70 """
70 """
71 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
71 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
72
72
73
73
74 class DocTestSkip(object):
74 class DocTestSkip(object):
75 """Object wrapper for doctests to be skipped."""
75 """Object wrapper for doctests to be skipped."""
76
76
77 ds_skip = """Doctest to skip.
77 ds_skip = """Doctest to skip.
78 >>> 1 #doctest: +SKIP
78 >>> 1 #doctest: +SKIP
79 """
79 """
80
80
81 def __init__(self,obj):
81 def __init__(self,obj):
82 self.obj = obj
82 self.obj = obj
83
83
84 def __getattribute__(self,key):
84 def __getattribute__(self,key):
85 if key == '__doc__':
85 if key == '__doc__':
86 return DocTestSkip.ds_skip
86 return DocTestSkip.ds_skip
87 else:
87 else:
88 return getattr(object.__getattribute__(self,'obj'),key)
88 return getattr(object.__getattribute__(self,'obj'),key)
89
89
90 # Modified version of the one in the stdlib, that fixes a python bug (doctests
90 # Modified version of the one in the stdlib, that fixes a python bug (doctests
91 # not found in extension modules, http://bugs.python.org/issue3158)
91 # not found in extension modules, http://bugs.python.org/issue3158)
92 class DocTestFinder(doctest.DocTestFinder):
92 class DocTestFinder(doctest.DocTestFinder):
93
93
94 def _from_module(self, module, object):
94 def _from_module(self, module, object):
95 """
95 """
96 Return true if the given object is defined in the given
96 Return true if the given object is defined in the given
97 module.
97 module.
98 """
98 """
99 if module is None:
99 if module is None:
100 return True
100 return True
101 elif inspect.isfunction(object):
101 elif inspect.isfunction(object):
102 return module.__dict__ is object.__globals__
102 return module.__dict__ is object.__globals__
103 elif inspect.isbuiltin(object):
103 elif inspect.isbuiltin(object):
104 return module.__name__ == object.__module__
104 return module.__name__ == object.__module__
105 elif inspect.isclass(object):
105 elif inspect.isclass(object):
106 return module.__name__ == object.__module__
106 return module.__name__ == object.__module__
107 elif inspect.ismethod(object):
107 elif inspect.ismethod(object):
108 # This one may be a bug in cython that fails to correctly set the
108 # This one may be a bug in cython that fails to correctly set the
109 # __module__ attribute of methods, but since the same error is easy
109 # __module__ attribute of methods, but since the same error is easy
110 # to make by extension code writers, having this safety in place
110 # to make by extension code writers, having this safety in place
111 # isn't such a bad idea
111 # isn't such a bad idea
112 return module.__name__ == object.__self__.__class__.__module__
112 return module.__name__ == object.__self__.__class__.__module__
113 elif inspect.getmodule(object) is not None:
113 elif inspect.getmodule(object) is not None:
114 return module is inspect.getmodule(object)
114 return module is inspect.getmodule(object)
115 elif hasattr(object, '__module__'):
115 elif hasattr(object, '__module__'):
116 return module.__name__ == object.__module__
116 return module.__name__ == object.__module__
117 elif isinstance(object, property):
117 elif isinstance(object, property):
118 return True # [XX] no way not be sure.
118 return True # [XX] no way not be sure.
119 elif inspect.ismethoddescriptor(object):
119 elif inspect.ismethoddescriptor(object):
120 # Unbound PyQt signals reach this point in Python 3.4b3, and we want
120 # Unbound PyQt signals reach this point in Python 3.4b3, and we want
121 # to avoid throwing an error. See also http://bugs.python.org/issue3158
121 # to avoid throwing an error. See also http://bugs.python.org/issue3158
122 return False
122 return False
123 else:
123 else:
124 raise ValueError("object must be a class or function, got %r" % object)
124 raise ValueError("object must be a class or function, got %r" % object)
125
125
126 def _find(self, tests, obj, name, module, source_lines, globs, seen):
126 def _find(self, tests, obj, name, module, source_lines, globs, seen):
127 """
127 """
128 Find tests for the given object and any contained objects, and
128 Find tests for the given object and any contained objects, and
129 add them to `tests`.
129 add them to `tests`.
130 """
130 """
131 print('_find for:', obj, name, module) # dbg
131 print('_find for:', obj, name, module) # dbg
132 if hasattr(obj,"skip_doctest"):
132 if hasattr(obj,"skip_doctest"):
133 #print 'SKIPPING DOCTEST FOR:',obj # dbg
133 #print 'SKIPPING DOCTEST FOR:',obj # dbg
134 obj = DocTestSkip(obj)
134 obj = DocTestSkip(obj)
135
135
136 doctest.DocTestFinder._find(self,tests, obj, name, module,
136 doctest.DocTestFinder._find(self,tests, obj, name, module,
137 source_lines, globs, seen)
137 source_lines, globs, seen)
138
138
139 # Below we re-run pieces of the above method with manual modifications,
139 # Below we re-run pieces of the above method with manual modifications,
140 # because the original code is buggy and fails to correctly identify
140 # because the original code is buggy and fails to correctly identify
141 # doctests in extension modules.
141 # doctests in extension modules.
142
142
143 # Local shorthands
143 # Local shorthands
144 from inspect import isroutine, isclass
144 from inspect import isroutine, isclass
145
145
146 # Look for tests in a module's contained objects.
146 # Look for tests in a module's contained objects.
147 if inspect.ismodule(obj) and self._recurse:
147 if inspect.ismodule(obj) and self._recurse:
148 for valname, val in obj.__dict__.items():
148 for valname, val in obj.__dict__.items():
149 valname1 = '%s.%s' % (name, valname)
149 valname1 = '%s.%s' % (name, valname)
150 if ( (isroutine(val) or isclass(val))
150 if ( (isroutine(val) or isclass(val))
151 and self._from_module(module, val) ):
151 and self._from_module(module, val) ):
152
152
153 self._find(tests, val, valname1, module, source_lines,
153 self._find(tests, val, valname1, module, source_lines,
154 globs, seen)
154 globs, seen)
155
155
156 # Look for tests in a class's contained objects.
156 # Look for tests in a class's contained objects.
157 if inspect.isclass(obj) and self._recurse:
157 if inspect.isclass(obj) and self._recurse:
158 #print 'RECURSE into class:',obj # dbg
158 #print 'RECURSE into class:',obj # dbg
159 for valname, val in obj.__dict__.items():
159 for valname, val in obj.__dict__.items():
160 # Special handling for staticmethod/classmethod.
160 # Special handling for staticmethod/classmethod.
161 if isinstance(val, staticmethod):
161 if isinstance(val, staticmethod):
162 val = getattr(obj, valname)
162 val = getattr(obj, valname)
163 if isinstance(val, classmethod):
163 if isinstance(val, classmethod):
164 val = getattr(obj, valname).__func__
164 val = getattr(obj, valname).__func__
165
165
166 # Recurse to methods, properties, and nested classes.
166 # Recurse to methods, properties, and nested classes.
167 if ((inspect.isfunction(val) or inspect.isclass(val) or
167 if ((inspect.isfunction(val) or inspect.isclass(val) or
168 inspect.ismethod(val) or
168 inspect.ismethod(val) or
169 isinstance(val, property)) and
169 isinstance(val, property)) and
170 self._from_module(module, val)):
170 self._from_module(module, val)):
171 valname = '%s.%s' % (name, valname)
171 valname = '%s.%s' % (name, valname)
172 self._find(tests, val, valname, module, source_lines,
172 self._find(tests, val, valname, module, source_lines,
173 globs, seen)
173 globs, seen)
174
174
175
175
176 class IPDoctestOutputChecker(doctest.OutputChecker):
176 class IPDoctestOutputChecker(doctest.OutputChecker):
177 """Second-chance checker with support for random tests.
177 """Second-chance checker with support for random tests.
178
178
179 If the default comparison doesn't pass, this checker looks in the expected
179 If the default comparison doesn't pass, this checker looks in the expected
180 output string for flags that tell us to ignore the output.
180 output string for flags that tell us to ignore the output.
181 """
181 """
182
182
183 random_re = re.compile(r'#\s*random\s+')
183 random_re = re.compile(r'#\s*random\s+')
184
184
185 def check_output(self, want, got, optionflags):
185 def check_output(self, want, got, optionflags):
186 """Check output, accepting special markers embedded in the output.
186 """Check output, accepting special markers embedded in the output.
187
187
188 If the output didn't pass the default validation but the special string
188 If the output didn't pass the default validation but the special string
189 '#random' is included, we accept it."""
189 '#random' is included, we accept it."""
190
190
191 # Let the original tester verify first, in case people have valid tests
191 # Let the original tester verify first, in case people have valid tests
192 # that happen to have a comment saying '#random' embedded in.
192 # that happen to have a comment saying '#random' embedded in.
193 ret = doctest.OutputChecker.check_output(self, want, got,
193 ret = doctest.OutputChecker.check_output(self, want, got,
194 optionflags)
194 optionflags)
195 if not ret and self.random_re.search(want):
195 if not ret and self.random_re.search(want):
196 #print >> sys.stderr, 'RANDOM OK:',want # dbg
196 #print >> sys.stderr, 'RANDOM OK:',want # dbg
197 return True
197 return True
198
198
199 return ret
199 return ret
200
200
201
201
202 class DocTestCase(doctests.DocTestCase):
202 class DocTestCase(doctests.DocTestCase):
203 """Proxy for DocTestCase: provides an address() method that
203 """Proxy for DocTestCase: provides an address() method that
204 returns the correct address for the doctest case. Otherwise
204 returns the correct address for the doctest case. Otherwise
205 acts as a proxy to the test case. To provide hints for address(),
205 acts as a proxy to the test case. To provide hints for address(),
206 an obj may also be passed -- this will be used as the test object
206 an obj may also be passed -- this will be used as the test object
207 for purposes of determining the test address, if it is provided.
207 for purposes of determining the test address, if it is provided.
208 """
208 """
209
209
210 # Note: this method was taken from numpy's nosetester module.
210 # Note: this method was taken from numpy's nosetester module.
211
211
212 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
212 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
213 # its constructor that blocks non-default arguments from being passed
213 # its constructor that blocks non-default arguments from being passed
214 # down into doctest.DocTestCase
214 # down into doctest.DocTestCase
215
215
216 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
216 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
217 checker=None, obj=None, result_var='_'):
217 checker=None, obj=None, result_var='_'):
218 self._result_var = result_var
218 self._result_var = result_var
219 doctests.DocTestCase.__init__(self, test,
219 doctests.DocTestCase.__init__(self, test,
220 optionflags=optionflags,
220 optionflags=optionflags,
221 setUp=setUp, tearDown=tearDown,
221 setUp=setUp, tearDown=tearDown,
222 checker=checker)
222 checker=checker)
223 # Now we must actually copy the original constructor from the stdlib
223 # Now we must actually copy the original constructor from the stdlib
224 # doctest class, because we can't call it directly and a bug in nose
224 # doctest class, because we can't call it directly and a bug in nose
225 # means it never gets passed the right arguments.
225 # means it never gets passed the right arguments.
226
226
227 self._dt_optionflags = optionflags
227 self._dt_optionflags = optionflags
228 self._dt_checker = checker
228 self._dt_checker = checker
229 self._dt_test = test
229 self._dt_test = test
230 self._dt_test_globs_ori = test.globs
230 self._dt_test_globs_ori = test.globs
231 self._dt_setUp = setUp
231 self._dt_setUp = setUp
232 self._dt_tearDown = tearDown
232 self._dt_tearDown = tearDown
233
233
234 # XXX - store this runner once in the object!
234 # XXX - store this runner once in the object!
235 runner = IPDocTestRunner(optionflags=optionflags,
235 runner = IPDocTestRunner(optionflags=optionflags,
236 checker=checker, verbose=False)
236 checker=checker, verbose=False)
237 self._dt_runner = runner
237 self._dt_runner = runner
238
238
239
239
240 # Each doctest should remember the directory it was loaded from, so
240 # Each doctest should remember the directory it was loaded from, so
241 # things like %run work without too many contortions
241 # things like %run work without too many contortions
242 self._ori_dir = os.path.dirname(test.filename)
242 self._ori_dir = os.path.dirname(test.filename)
243
243
244 # Modified runTest from the default stdlib
244 # Modified runTest from the default stdlib
245 def runTest(self):
245 def runTest(self):
246 test = self._dt_test
246 test = self._dt_test
247 runner = self._dt_runner
247 runner = self._dt_runner
248
248
249 old = sys.stdout
249 old = sys.stdout
250 new = StringIO()
250 new = StringIO()
251 optionflags = self._dt_optionflags
251 optionflags = self._dt_optionflags
252
252
253 if not (optionflags & REPORTING_FLAGS):
253 if not (optionflags & REPORTING_FLAGS):
254 # The option flags don't include any reporting flags,
254 # The option flags don't include any reporting flags,
255 # so add the default reporting flags
255 # so add the default reporting flags
256 optionflags |= _unittest_reportflags
256 optionflags |= _unittest_reportflags
257
257
258 try:
258 try:
259 # Save our current directory and switch out to the one where the
259 # Save our current directory and switch out to the one where the
260 # test was originally created, in case another doctest did a
260 # test was originally created, in case another doctest did a
261 # directory change. We'll restore this in the finally clause.
261 # directory change. We'll restore this in the finally clause.
262 curdir = getcwd()
262 curdir = os.getcwd()
263 #print 'runTest in dir:', self._ori_dir # dbg
263 #print 'runTest in dir:', self._ori_dir # dbg
264 os.chdir(self._ori_dir)
264 os.chdir(self._ori_dir)
265
265
266 runner.DIVIDER = "-"*70
266 runner.DIVIDER = "-"*70
267 failures, tries = runner.run(test,out=new.write,
267 failures, tries = runner.run(test,out=new.write,
268 clear_globs=False)
268 clear_globs=False)
269 finally:
269 finally:
270 sys.stdout = old
270 sys.stdout = old
271 os.chdir(curdir)
271 os.chdir(curdir)
272
272
273 if failures:
273 if failures:
274 raise self.failureException(self.format_failure(new.getvalue()))
274 raise self.failureException(self.format_failure(new.getvalue()))
275
275
276 def setUp(self):
276 def setUp(self):
277 """Modified test setup that syncs with ipython namespace"""
277 """Modified test setup that syncs with ipython namespace"""
278 #print "setUp test", self._dt_test.examples # dbg
278 #print "setUp test", self._dt_test.examples # dbg
279 if isinstance(self._dt_test.examples[0], IPExample):
279 if isinstance(self._dt_test.examples[0], IPExample):
280 # for IPython examples *only*, we swap the globals with the ipython
280 # for IPython examples *only*, we swap the globals with the ipython
281 # namespace, after updating it with the globals (which doctest
281 # namespace, after updating it with the globals (which doctest
282 # fills with the necessary info from the module being tested).
282 # fills with the necessary info from the module being tested).
283 self.user_ns_orig = {}
283 self.user_ns_orig = {}
284 self.user_ns_orig.update(_ip.user_ns)
284 self.user_ns_orig.update(_ip.user_ns)
285 _ip.user_ns.update(self._dt_test.globs)
285 _ip.user_ns.update(self._dt_test.globs)
286 # We must remove the _ key in the namespace, so that Python's
286 # We must remove the _ key in the namespace, so that Python's
287 # doctest code sets it naturally
287 # doctest code sets it naturally
288 _ip.user_ns.pop('_', None)
288 _ip.user_ns.pop('_', None)
289 _ip.user_ns['__builtins__'] = builtin_mod
289 _ip.user_ns['__builtins__'] = builtin_mod
290 self._dt_test.globs = _ip.user_ns
290 self._dt_test.globs = _ip.user_ns
291
291
292 super(DocTestCase, self).setUp()
292 super(DocTestCase, self).setUp()
293
293
294 def tearDown(self):
294 def tearDown(self):
295
295
296 # Undo the test.globs reassignment we made, so that the parent class
296 # Undo the test.globs reassignment we made, so that the parent class
297 # teardown doesn't destroy the ipython namespace
297 # teardown doesn't destroy the ipython namespace
298 if isinstance(self._dt_test.examples[0], IPExample):
298 if isinstance(self._dt_test.examples[0], IPExample):
299 self._dt_test.globs = self._dt_test_globs_ori
299 self._dt_test.globs = self._dt_test_globs_ori
300 _ip.user_ns.clear()
300 _ip.user_ns.clear()
301 _ip.user_ns.update(self.user_ns_orig)
301 _ip.user_ns.update(self.user_ns_orig)
302
302
303 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
303 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
304 # it does look like one to me: its tearDown method tries to run
304 # it does look like one to me: its tearDown method tries to run
305 #
305 #
306 # delattr(builtin_mod, self._result_var)
306 # delattr(builtin_mod, self._result_var)
307 #
307 #
308 # without checking that the attribute really is there; it implicitly
308 # without checking that the attribute really is there; it implicitly
309 # assumes it should have been set via displayhook. But if the
309 # assumes it should have been set via displayhook. But if the
310 # displayhook was never called, this doesn't necessarily happen. I
310 # displayhook was never called, this doesn't necessarily happen. I
311 # haven't been able to find a little self-contained example outside of
311 # haven't been able to find a little self-contained example outside of
312 # ipython that would show the problem so I can report it to the nose
312 # ipython that would show the problem so I can report it to the nose
313 # team, but it does happen a lot in our code.
313 # team, but it does happen a lot in our code.
314 #
314 #
315 # So here, we just protect as narrowly as possible by trapping an
315 # So here, we just protect as narrowly as possible by trapping an
316 # attribute error whose message would be the name of self._result_var,
316 # attribute error whose message would be the name of self._result_var,
317 # and letting any other error propagate.
317 # and letting any other error propagate.
318 try:
318 try:
319 super(DocTestCase, self).tearDown()
319 super(DocTestCase, self).tearDown()
320 except AttributeError as exc:
320 except AttributeError as exc:
321 if exc.args[0] != self._result_var:
321 if exc.args[0] != self._result_var:
322 raise
322 raise
323
323
324
324
325 # A simple subclassing of the original with a different class name, so we can
325 # A simple subclassing of the original with a different class name, so we can
326 # distinguish and treat differently IPython examples from pure python ones.
326 # distinguish and treat differently IPython examples from pure python ones.
327 class IPExample(doctest.Example): pass
327 class IPExample(doctest.Example): pass
328
328
329
329
330 class IPExternalExample(doctest.Example):
330 class IPExternalExample(doctest.Example):
331 """Doctest examples to be run in an external process."""
331 """Doctest examples to be run in an external process."""
332
332
333 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
333 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
334 options=None):
334 options=None):
335 # Parent constructor
335 # Parent constructor
336 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
336 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
337
337
338 # An EXTRA newline is needed to prevent pexpect hangs
338 # An EXTRA newline is needed to prevent pexpect hangs
339 self.source += '\n'
339 self.source += '\n'
340
340
341
341
342 class IPDocTestParser(doctest.DocTestParser):
342 class IPDocTestParser(doctest.DocTestParser):
343 """
343 """
344 A class used to parse strings containing doctest examples.
344 A class used to parse strings containing doctest examples.
345
345
346 Note: This is a version modified to properly recognize IPython input and
346 Note: This is a version modified to properly recognize IPython input and
347 convert any IPython examples into valid Python ones.
347 convert any IPython examples into valid Python ones.
348 """
348 """
349 # This regular expression is used to find doctest examples in a
349 # This regular expression is used to find doctest examples in a
350 # string. It defines three groups: `source` is the source code
350 # string. It defines three groups: `source` is the source code
351 # (including leading indentation and prompts); `indent` is the
351 # (including leading indentation and prompts); `indent` is the
352 # indentation of the first (PS1) line of the source code; and
352 # indentation of the first (PS1) line of the source code; and
353 # `want` is the expected output (including leading indentation).
353 # `want` is the expected output (including leading indentation).
354
354
355 # Classic Python prompts or default IPython ones
355 # Classic Python prompts or default IPython ones
356 _PS1_PY = r'>>>'
356 _PS1_PY = r'>>>'
357 _PS2_PY = r'\.\.\.'
357 _PS2_PY = r'\.\.\.'
358
358
359 _PS1_IP = r'In\ \[\d+\]:'
359 _PS1_IP = r'In\ \[\d+\]:'
360 _PS2_IP = r'\ \ \ \.\.\.+:'
360 _PS2_IP = r'\ \ \ \.\.\.+:'
361
361
362 _RE_TPL = r'''
362 _RE_TPL = r'''
363 # Source consists of a PS1 line followed by zero or more PS2 lines.
363 # Source consists of a PS1 line followed by zero or more PS2 lines.
364 (?P<source>
364 (?P<source>
365 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
365 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
366 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
366 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
367 \n? # a newline
367 \n? # a newline
368 # Want consists of any non-blank lines that do not start with PS1.
368 # Want consists of any non-blank lines that do not start with PS1.
369 (?P<want> (?:(?![ ]*$) # Not a blank line
369 (?P<want> (?:(?![ ]*$) # Not a blank line
370 (?![ ]*%s) # Not a line starting with PS1
370 (?![ ]*%s) # Not a line starting with PS1
371 (?![ ]*%s) # Not a line starting with PS2
371 (?![ ]*%s) # Not a line starting with PS2
372 .*$\n? # But any other line
372 .*$\n? # But any other line
373 )*)
373 )*)
374 '''
374 '''
375
375
376 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
376 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
377 re.MULTILINE | re.VERBOSE)
377 re.MULTILINE | re.VERBOSE)
378
378
379 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
379 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
380 re.MULTILINE | re.VERBOSE)
380 re.MULTILINE | re.VERBOSE)
381
381
382 # Mark a test as being fully random. In this case, we simply append the
382 # Mark a test as being fully random. In this case, we simply append the
383 # random marker ('#random') to each individual example's output. This way
383 # random marker ('#random') to each individual example's output. This way
384 # we don't need to modify any other code.
384 # we don't need to modify any other code.
385 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
385 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
386
386
387 # Mark tests to be executed in an external process - currently unsupported.
387 # Mark tests to be executed in an external process - currently unsupported.
388 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
388 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
389
389
390 def ip2py(self,source):
390 def ip2py(self,source):
391 """Convert input IPython source into valid Python."""
391 """Convert input IPython source into valid Python."""
392 block = _ip.input_transformer_manager.transform_cell(source)
392 block = _ip.input_transformer_manager.transform_cell(source)
393 if len(block.splitlines()) == 1:
393 if len(block.splitlines()) == 1:
394 return _ip.prefilter(block)
394 return _ip.prefilter(block)
395 else:
395 else:
396 return block
396 return block
397
397
398 def parse(self, string, name='<string>'):
398 def parse(self, string, name='<string>'):
399 """
399 """
400 Divide the given string into examples and intervening text,
400 Divide the given string into examples and intervening text,
401 and return them as a list of alternating Examples and strings.
401 and return them as a list of alternating Examples and strings.
402 Line numbers for the Examples are 0-based. The optional
402 Line numbers for the Examples are 0-based. The optional
403 argument `name` is a name identifying this string, and is only
403 argument `name` is a name identifying this string, and is only
404 used for error messages.
404 used for error messages.
405 """
405 """
406
406
407 #print 'Parse string:\n',string # dbg
407 #print 'Parse string:\n',string # dbg
408
408
409 string = string.expandtabs()
409 string = string.expandtabs()
410 # If all lines begin with the same indentation, then strip it.
410 # If all lines begin with the same indentation, then strip it.
411 min_indent = self._min_indent(string)
411 min_indent = self._min_indent(string)
412 if min_indent > 0:
412 if min_indent > 0:
413 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
413 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
414
414
415 output = []
415 output = []
416 charno, lineno = 0, 0
416 charno, lineno = 0, 0
417
417
418 # We make 'all random' tests by adding the '# random' mark to every
418 # We make 'all random' tests by adding the '# random' mark to every
419 # block of output in the test.
419 # block of output in the test.
420 if self._RANDOM_TEST.search(string):
420 if self._RANDOM_TEST.search(string):
421 random_marker = '\n# random'
421 random_marker = '\n# random'
422 else:
422 else:
423 random_marker = ''
423 random_marker = ''
424
424
425 # Whether to convert the input from ipython to python syntax
425 # Whether to convert the input from ipython to python syntax
426 ip2py = False
426 ip2py = False
427 # Find all doctest examples in the string. First, try them as Python
427 # Find all doctest examples in the string. First, try them as Python
428 # examples, then as IPython ones
428 # examples, then as IPython ones
429 terms = list(self._EXAMPLE_RE_PY.finditer(string))
429 terms = list(self._EXAMPLE_RE_PY.finditer(string))
430 if terms:
430 if terms:
431 # Normal Python example
431 # Normal Python example
432 #print '-'*70 # dbg
432 #print '-'*70 # dbg
433 #print 'PyExample, Source:\n',string # dbg
433 #print 'PyExample, Source:\n',string # dbg
434 #print '-'*70 # dbg
434 #print '-'*70 # dbg
435 Example = doctest.Example
435 Example = doctest.Example
436 else:
436 else:
437 # It's an ipython example. Note that IPExamples are run
437 # It's an ipython example. Note that IPExamples are run
438 # in-process, so their syntax must be turned into valid python.
438 # in-process, so their syntax must be turned into valid python.
439 # IPExternalExamples are run out-of-process (via pexpect) so they
439 # IPExternalExamples are run out-of-process (via pexpect) so they
440 # don't need any filtering (a real ipython will be executing them).
440 # don't need any filtering (a real ipython will be executing them).
441 terms = list(self._EXAMPLE_RE_IP.finditer(string))
441 terms = list(self._EXAMPLE_RE_IP.finditer(string))
442 if self._EXTERNAL_IP.search(string):
442 if self._EXTERNAL_IP.search(string):
443 #print '-'*70 # dbg
443 #print '-'*70 # dbg
444 #print 'IPExternalExample, Source:\n',string # dbg
444 #print 'IPExternalExample, Source:\n',string # dbg
445 #print '-'*70 # dbg
445 #print '-'*70 # dbg
446 Example = IPExternalExample
446 Example = IPExternalExample
447 else:
447 else:
448 #print '-'*70 # dbg
448 #print '-'*70 # dbg
449 #print 'IPExample, Source:\n',string # dbg
449 #print 'IPExample, Source:\n',string # dbg
450 #print '-'*70 # dbg
450 #print '-'*70 # dbg
451 Example = IPExample
451 Example = IPExample
452 ip2py = True
452 ip2py = True
453
453
454 for m in terms:
454 for m in terms:
455 # Add the pre-example text to `output`.
455 # Add the pre-example text to `output`.
456 output.append(string[charno:m.start()])
456 output.append(string[charno:m.start()])
457 # Update lineno (lines before this example)
457 # Update lineno (lines before this example)
458 lineno += string.count('\n', charno, m.start())
458 lineno += string.count('\n', charno, m.start())
459 # Extract info from the regexp match.
459 # Extract info from the regexp match.
460 (source, options, want, exc_msg) = \
460 (source, options, want, exc_msg) = \
461 self._parse_example(m, name, lineno,ip2py)
461 self._parse_example(m, name, lineno,ip2py)
462
462
463 # Append the random-output marker (it defaults to empty in most
463 # Append the random-output marker (it defaults to empty in most
464 # cases, it's only non-empty for 'all-random' tests):
464 # cases, it's only non-empty for 'all-random' tests):
465 want += random_marker
465 want += random_marker
466
466
467 if Example is IPExternalExample:
467 if Example is IPExternalExample:
468 options[doctest.NORMALIZE_WHITESPACE] = True
468 options[doctest.NORMALIZE_WHITESPACE] = True
469 want += '\n'
469 want += '\n'
470
470
471 # Create an Example, and add it to the list.
471 # Create an Example, and add it to the list.
472 if not self._IS_BLANK_OR_COMMENT(source):
472 if not self._IS_BLANK_OR_COMMENT(source):
473 output.append(Example(source, want, exc_msg,
473 output.append(Example(source, want, exc_msg,
474 lineno=lineno,
474 lineno=lineno,
475 indent=min_indent+len(m.group('indent')),
475 indent=min_indent+len(m.group('indent')),
476 options=options))
476 options=options))
477 # Update lineno (lines inside this example)
477 # Update lineno (lines inside this example)
478 lineno += string.count('\n', m.start(), m.end())
478 lineno += string.count('\n', m.start(), m.end())
479 # Update charno.
479 # Update charno.
480 charno = m.end()
480 charno = m.end()
481 # Add any remaining post-example text to `output`.
481 # Add any remaining post-example text to `output`.
482 output.append(string[charno:])
482 output.append(string[charno:])
483 return output
483 return output
484
484
485 def _parse_example(self, m, name, lineno,ip2py=False):
485 def _parse_example(self, m, name, lineno,ip2py=False):
486 """
486 """
487 Given a regular expression match from `_EXAMPLE_RE` (`m`),
487 Given a regular expression match from `_EXAMPLE_RE` (`m`),
488 return a pair `(source, want)`, where `source` is the matched
488 return a pair `(source, want)`, where `source` is the matched
489 example's source code (with prompts and indentation stripped);
489 example's source code (with prompts and indentation stripped);
490 and `want` is the example's expected output (with indentation
490 and `want` is the example's expected output (with indentation
491 stripped).
491 stripped).
492
492
493 `name` is the string's name, and `lineno` is the line number
493 `name` is the string's name, and `lineno` is the line number
494 where the example starts; both are used for error messages.
494 where the example starts; both are used for error messages.
495
495
496 Optional:
496 Optional:
497 `ip2py`: if true, filter the input via IPython to convert the syntax
497 `ip2py`: if true, filter the input via IPython to convert the syntax
498 into valid python.
498 into valid python.
499 """
499 """
500
500
501 # Get the example's indentation level.
501 # Get the example's indentation level.
502 indent = len(m.group('indent'))
502 indent = len(m.group('indent'))
503
503
504 # Divide source into lines; check that they're properly
504 # Divide source into lines; check that they're properly
505 # indented; and then strip their indentation & prompts.
505 # indented; and then strip their indentation & prompts.
506 source_lines = m.group('source').split('\n')
506 source_lines = m.group('source').split('\n')
507
507
508 # We're using variable-length input prompts
508 # We're using variable-length input prompts
509 ps1 = m.group('ps1')
509 ps1 = m.group('ps1')
510 ps2 = m.group('ps2')
510 ps2 = m.group('ps2')
511 ps1_len = len(ps1)
511 ps1_len = len(ps1)
512
512
513 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
513 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
514 if ps2:
514 if ps2:
515 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
515 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
516
516
517 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
517 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
518
518
519 if ip2py:
519 if ip2py:
520 # Convert source input from IPython into valid Python syntax
520 # Convert source input from IPython into valid Python syntax
521 source = self.ip2py(source)
521 source = self.ip2py(source)
522
522
523 # Divide want into lines; check that it's properly indented; and
523 # Divide want into lines; check that it's properly indented; and
524 # then strip the indentation. Spaces before the last newline should
524 # then strip the indentation. Spaces before the last newline should
525 # be preserved, so plain rstrip() isn't good enough.
525 # be preserved, so plain rstrip() isn't good enough.
526 want = m.group('want')
526 want = m.group('want')
527 want_lines = want.split('\n')
527 want_lines = want.split('\n')
528 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
528 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
529 del want_lines[-1] # forget final newline & spaces after it
529 del want_lines[-1] # forget final newline & spaces after it
530 self._check_prefix(want_lines, ' '*indent, name,
530 self._check_prefix(want_lines, ' '*indent, name,
531 lineno + len(source_lines))
531 lineno + len(source_lines))
532
532
533 # Remove ipython output prompt that might be present in the first line
533 # Remove ipython output prompt that might be present in the first line
534 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
534 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
535
535
536 want = '\n'.join([wl[indent:] for wl in want_lines])
536 want = '\n'.join([wl[indent:] for wl in want_lines])
537
537
538 # If `want` contains a traceback message, then extract it.
538 # If `want` contains a traceback message, then extract it.
539 m = self._EXCEPTION_RE.match(want)
539 m = self._EXCEPTION_RE.match(want)
540 if m:
540 if m:
541 exc_msg = m.group('msg')
541 exc_msg = m.group('msg')
542 else:
542 else:
543 exc_msg = None
543 exc_msg = None
544
544
545 # Extract options from the source.
545 # Extract options from the source.
546 options = self._find_options(source, name, lineno)
546 options = self._find_options(source, name, lineno)
547
547
548 return source, options, want, exc_msg
548 return source, options, want, exc_msg
549
549
550 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
550 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
551 """
551 """
552 Given the lines of a source string (including prompts and
552 Given the lines of a source string (including prompts and
553 leading indentation), check to make sure that every prompt is
553 leading indentation), check to make sure that every prompt is
554 followed by a space character. If any line is not followed by
554 followed by a space character. If any line is not followed by
555 a space character, then raise ValueError.
555 a space character, then raise ValueError.
556
556
557 Note: IPython-modified version which takes the input prompt length as a
557 Note: IPython-modified version which takes the input prompt length as a
558 parameter, so that prompts of variable length can be dealt with.
558 parameter, so that prompts of variable length can be dealt with.
559 """
559 """
560 space_idx = indent+ps1_len
560 space_idx = indent+ps1_len
561 min_len = space_idx+1
561 min_len = space_idx+1
562 for i, line in enumerate(lines):
562 for i, line in enumerate(lines):
563 if len(line) >= min_len and line[space_idx] != ' ':
563 if len(line) >= min_len and line[space_idx] != ' ':
564 raise ValueError('line %r of the docstring for %s '
564 raise ValueError('line %r of the docstring for %s '
565 'lacks blank after %s: %r' %
565 'lacks blank after %s: %r' %
566 (lineno+i+1, name,
566 (lineno+i+1, name,
567 line[indent:space_idx], line))
567 line[indent:space_idx], line))
568
568
569
569
570 SKIP = doctest.register_optionflag('SKIP')
570 SKIP = doctest.register_optionflag('SKIP')
571
571
572
572
573 class IPDocTestRunner(doctest.DocTestRunner,object):
573 class IPDocTestRunner(doctest.DocTestRunner,object):
574 """Test runner that synchronizes the IPython namespace with test globals.
574 """Test runner that synchronizes the IPython namespace with test globals.
575 """
575 """
576
576
577 def run(self, test, compileflags=None, out=None, clear_globs=True):
577 def run(self, test, compileflags=None, out=None, clear_globs=True):
578
578
579 # Hack: ipython needs access to the execution context of the example,
579 # Hack: ipython needs access to the execution context of the example,
580 # so that it can propagate user variables loaded by %run into
580 # so that it can propagate user variables loaded by %run into
581 # test.globs. We put them here into our modified %run as a function
581 # test.globs. We put them here into our modified %run as a function
582 # attribute. Our new %run will then only make the namespace update
582 # attribute. Our new %run will then only make the namespace update
583 # when called (rather than unconconditionally updating test.globs here
583 # when called (rather than unconconditionally updating test.globs here
584 # for all examples, most of which won't be calling %run anyway).
584 # for all examples, most of which won't be calling %run anyway).
585 #_ip._ipdoctest_test_globs = test.globs
585 #_ip._ipdoctest_test_globs = test.globs
586 #_ip._ipdoctest_test_filename = test.filename
586 #_ip._ipdoctest_test_filename = test.filename
587
587
588 test.globs.update(_ip.user_ns)
588 test.globs.update(_ip.user_ns)
589
589
590 # Override terminal size to standardise traceback format
590 # Override terminal size to standardise traceback format
591 with modified_env({'COLUMNS': '80', 'LINES': '24'}):
591 with modified_env({'COLUMNS': '80', 'LINES': '24'}):
592 return super(IPDocTestRunner,self).run(test,
592 return super(IPDocTestRunner,self).run(test,
593 compileflags,out,clear_globs)
593 compileflags,out,clear_globs)
594
594
595
595
596 class DocFileCase(doctest.DocFileCase):
596 class DocFileCase(doctest.DocFileCase):
597 """Overrides to provide filename
597 """Overrides to provide filename
598 """
598 """
599 def address(self):
599 def address(self):
600 return (self._dt_test.filename, None, None)
600 return (self._dt_test.filename, None, None)
601
601
602
602
603 class ExtensionDoctest(doctests.Doctest):
603 class ExtensionDoctest(doctests.Doctest):
604 """Nose Plugin that supports doctests in extension modules.
604 """Nose Plugin that supports doctests in extension modules.
605 """
605 """
606 name = 'extdoctest' # call nosetests with --with-extdoctest
606 name = 'extdoctest' # call nosetests with --with-extdoctest
607 enabled = True
607 enabled = True
608
608
609 def options(self, parser, env=os.environ):
609 def options(self, parser, env=os.environ):
610 Plugin.options(self, parser, env)
610 Plugin.options(self, parser, env)
611 parser.add_option('--doctest-tests', action='store_true',
611 parser.add_option('--doctest-tests', action='store_true',
612 dest='doctest_tests',
612 dest='doctest_tests',
613 default=env.get('NOSE_DOCTEST_TESTS',True),
613 default=env.get('NOSE_DOCTEST_TESTS',True),
614 help="Also look for doctests in test modules. "
614 help="Also look for doctests in test modules. "
615 "Note that classes, methods and functions should "
615 "Note that classes, methods and functions should "
616 "have either doctests or non-doctest tests, "
616 "have either doctests or non-doctest tests, "
617 "not both. [NOSE_DOCTEST_TESTS]")
617 "not both. [NOSE_DOCTEST_TESTS]")
618 parser.add_option('--doctest-extension', action="append",
618 parser.add_option('--doctest-extension', action="append",
619 dest="doctestExtension",
619 dest="doctestExtension",
620 help="Also look for doctests in files with "
620 help="Also look for doctests in files with "
621 "this extension [NOSE_DOCTEST_EXTENSION]")
621 "this extension [NOSE_DOCTEST_EXTENSION]")
622 # Set the default as a list, if given in env; otherwise
622 # Set the default as a list, if given in env; otherwise
623 # an additional value set on the command line will cause
623 # an additional value set on the command line will cause
624 # an error.
624 # an error.
625 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
625 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
626 if env_setting is not None:
626 if env_setting is not None:
627 parser.set_defaults(doctestExtension=tolist(env_setting))
627 parser.set_defaults(doctestExtension=tolist(env_setting))
628
628
629
629
630 def configure(self, options, config):
630 def configure(self, options, config):
631 Plugin.configure(self, options, config)
631 Plugin.configure(self, options, config)
632 # Pull standard doctest plugin out of config; we will do doctesting
632 # Pull standard doctest plugin out of config; we will do doctesting
633 config.plugins.plugins = [p for p in config.plugins.plugins
633 config.plugins.plugins = [p for p in config.plugins.plugins
634 if p.name != 'doctest']
634 if p.name != 'doctest']
635 self.doctest_tests = options.doctest_tests
635 self.doctest_tests = options.doctest_tests
636 self.extension = tolist(options.doctestExtension)
636 self.extension = tolist(options.doctestExtension)
637
637
638 self.parser = doctest.DocTestParser()
638 self.parser = doctest.DocTestParser()
639 self.finder = DocTestFinder()
639 self.finder = DocTestFinder()
640 self.checker = IPDoctestOutputChecker()
640 self.checker = IPDoctestOutputChecker()
641 self.globs = None
641 self.globs = None
642 self.extraglobs = None
642 self.extraglobs = None
643
643
644
644
645 def loadTestsFromExtensionModule(self,filename):
645 def loadTestsFromExtensionModule(self,filename):
646 bpath,mod = os.path.split(filename)
646 bpath,mod = os.path.split(filename)
647 modname = os.path.splitext(mod)[0]
647 modname = os.path.splitext(mod)[0]
648 try:
648 try:
649 sys.path.append(bpath)
649 sys.path.append(bpath)
650 module = import_module(modname)
650 module = import_module(modname)
651 tests = list(self.loadTestsFromModule(module))
651 tests = list(self.loadTestsFromModule(module))
652 finally:
652 finally:
653 sys.path.pop()
653 sys.path.pop()
654 return tests
654 return tests
655
655
656 # NOTE: the method below is almost a copy of the original one in nose, with
656 # NOTE: the method below is almost a copy of the original one in nose, with
657 # a few modifications to control output checking.
657 # a few modifications to control output checking.
658
658
659 def loadTestsFromModule(self, module):
659 def loadTestsFromModule(self, module):
660 #print '*** ipdoctest - lTM',module # dbg
660 #print '*** ipdoctest - lTM',module # dbg
661
661
662 if not self.matches(module.__name__):
662 if not self.matches(module.__name__):
663 log.debug("Doctest doesn't want module %s", module)
663 log.debug("Doctest doesn't want module %s", module)
664 return
664 return
665
665
666 tests = self.finder.find(module,globs=self.globs,
666 tests = self.finder.find(module,globs=self.globs,
667 extraglobs=self.extraglobs)
667 extraglobs=self.extraglobs)
668 if not tests:
668 if not tests:
669 return
669 return
670
670
671 # always use whitespace and ellipsis options
671 # always use whitespace and ellipsis options
672 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
672 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
673
673
674 tests.sort()
674 tests.sort()
675 module_file = module.__file__
675 module_file = module.__file__
676 if module_file[-4:] in ('.pyc', '.pyo'):
676 if module_file[-4:] in ('.pyc', '.pyo'):
677 module_file = module_file[:-1]
677 module_file = module_file[:-1]
678 for test in tests:
678 for test in tests:
679 if not test.examples:
679 if not test.examples:
680 continue
680 continue
681 if not test.filename:
681 if not test.filename:
682 test.filename = module_file
682 test.filename = module_file
683
683
684 yield DocTestCase(test,
684 yield DocTestCase(test,
685 optionflags=optionflags,
685 optionflags=optionflags,
686 checker=self.checker)
686 checker=self.checker)
687
687
688
688
689 def loadTestsFromFile(self, filename):
689 def loadTestsFromFile(self, filename):
690 #print "ipdoctest - from file", filename # dbg
690 #print "ipdoctest - from file", filename # dbg
691 if is_extension_module(filename):
691 if is_extension_module(filename):
692 for t in self.loadTestsFromExtensionModule(filename):
692 for t in self.loadTestsFromExtensionModule(filename):
693 yield t
693 yield t
694 else:
694 else:
695 if self.extension and anyp(filename.endswith, self.extension):
695 if self.extension and anyp(filename.endswith, self.extension):
696 name = os.path.basename(filename)
696 name = os.path.basename(filename)
697 dh = open(filename)
697 dh = open(filename)
698 try:
698 try:
699 doc = dh.read()
699 doc = dh.read()
700 finally:
700 finally:
701 dh.close()
701 dh.close()
702 test = self.parser.get_doctest(
702 test = self.parser.get_doctest(
703 doc, globs={'__file__': filename}, name=name,
703 doc, globs={'__file__': filename}, name=name,
704 filename=filename, lineno=0)
704 filename=filename, lineno=0)
705 if test.examples:
705 if test.examples:
706 #print 'FileCase:',test.examples # dbg
706 #print 'FileCase:',test.examples # dbg
707 yield DocFileCase(test)
707 yield DocFileCase(test)
708 else:
708 else:
709 yield False # no tests to load
709 yield False # no tests to load
710
710
711
711
712 class IPythonDoctest(ExtensionDoctest):
712 class IPythonDoctest(ExtensionDoctest):
713 """Nose Plugin that supports doctests in extension modules.
713 """Nose Plugin that supports doctests in extension modules.
714 """
714 """
715 name = 'ipdoctest' # call nosetests with --with-ipdoctest
715 name = 'ipdoctest' # call nosetests with --with-ipdoctest
716 enabled = True
716 enabled = True
717
717
718 def makeTest(self, obj, parent):
718 def makeTest(self, obj, parent):
719 """Look for doctests in the given object, which will be a
719 """Look for doctests in the given object, which will be a
720 function, method or class.
720 function, method or class.
721 """
721 """
722 #print 'Plugin analyzing:', obj, parent # dbg
722 #print 'Plugin analyzing:', obj, parent # dbg
723 # always use whitespace and ellipsis options
723 # always use whitespace and ellipsis options
724 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
724 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
725
725
726 doctests = self.finder.find(obj, module=getmodule(parent))
726 doctests = self.finder.find(obj, module=getmodule(parent))
727 if doctests:
727 if doctests:
728 for test in doctests:
728 for test in doctests:
729 if len(test.examples) == 0:
729 if len(test.examples) == 0:
730 continue
730 continue
731
731
732 yield DocTestCase(test, obj=obj,
732 yield DocTestCase(test, obj=obj,
733 optionflags=optionflags,
733 optionflags=optionflags,
734 checker=self.checker)
734 checker=self.checker)
735
735
736 def options(self, parser, env=os.environ):
736 def options(self, parser, env=os.environ):
737 #print "Options for nose plugin:", self.name # dbg
737 #print "Options for nose plugin:", self.name # dbg
738 Plugin.options(self, parser, env)
738 Plugin.options(self, parser, env)
739 parser.add_option('--ipdoctest-tests', action='store_true',
739 parser.add_option('--ipdoctest-tests', action='store_true',
740 dest='ipdoctest_tests',
740 dest='ipdoctest_tests',
741 default=env.get('NOSE_IPDOCTEST_TESTS',True),
741 default=env.get('NOSE_IPDOCTEST_TESTS',True),
742 help="Also look for doctests in test modules. "
742 help="Also look for doctests in test modules. "
743 "Note that classes, methods and functions should "
743 "Note that classes, methods and functions should "
744 "have either doctests or non-doctest tests, "
744 "have either doctests or non-doctest tests, "
745 "not both. [NOSE_IPDOCTEST_TESTS]")
745 "not both. [NOSE_IPDOCTEST_TESTS]")
746 parser.add_option('--ipdoctest-extension', action="append",
746 parser.add_option('--ipdoctest-extension', action="append",
747 dest="ipdoctest_extension",
747 dest="ipdoctest_extension",
748 help="Also look for doctests in files with "
748 help="Also look for doctests in files with "
749 "this extension [NOSE_IPDOCTEST_EXTENSION]")
749 "this extension [NOSE_IPDOCTEST_EXTENSION]")
750 # Set the default as a list, if given in env; otherwise
750 # Set the default as a list, if given in env; otherwise
751 # an additional value set on the command line will cause
751 # an additional value set on the command line will cause
752 # an error.
752 # an error.
753 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
753 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
754 if env_setting is not None:
754 if env_setting is not None:
755 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
755 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
756
756
757 def configure(self, options, config):
757 def configure(self, options, config):
758 #print "Configuring nose plugin:", self.name # dbg
758 #print "Configuring nose plugin:", self.name # dbg
759 Plugin.configure(self, options, config)
759 Plugin.configure(self, options, config)
760 # Pull standard doctest plugin out of config; we will do doctesting
760 # Pull standard doctest plugin out of config; we will do doctesting
761 config.plugins.plugins = [p for p in config.plugins.plugins
761 config.plugins.plugins = [p for p in config.plugins.plugins
762 if p.name != 'doctest']
762 if p.name != 'doctest']
763 self.doctest_tests = options.ipdoctest_tests
763 self.doctest_tests = options.ipdoctest_tests
764 self.extension = tolist(options.ipdoctest_extension)
764 self.extension = tolist(options.ipdoctest_extension)
765
765
766 self.parser = IPDocTestParser()
766 self.parser = IPDocTestParser()
767 self.finder = DocTestFinder(parser=self.parser)
767 self.finder = DocTestFinder(parser=self.parser)
768 self.checker = IPDoctestOutputChecker()
768 self.checker = IPDoctestOutputChecker()
769 self.globs = None
769 self.globs = None
770 self.extraglobs = None
770 self.extraglobs = None
@@ -1,476 +1,476 b''
1 """Generic testing tools.
1 """Generic testing tools.
2
2
3 Authors
3 Authors
4 -------
4 -------
5 - Fernando Perez <Fernando.Perez@berkeley.edu>
5 - Fernando Perez <Fernando.Perez@berkeley.edu>
6 """
6 """
7
7
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import os
12 import os
13 import re
13 import re
14 import sys
14 import sys
15 import tempfile
15 import tempfile
16
16
17 from contextlib import contextmanager
17 from contextlib import contextmanager
18 from io import StringIO
18 from io import StringIO
19 from subprocess import Popen, PIPE
19 from subprocess import Popen, PIPE
20 from unittest.mock import patch
20 from unittest.mock import patch
21
21
22 try:
22 try:
23 # These tools are used by parts of the runtime, so we make the nose
23 # These tools are used by parts of the runtime, so we make the nose
24 # dependency optional at this point. Nose is a hard dependency to run the
24 # dependency optional at this point. Nose is a hard dependency to run the
25 # test suite, but NOT to use ipython itself.
25 # test suite, but NOT to use ipython itself.
26 import nose.tools as nt
26 import nose.tools as nt
27 has_nose = True
27 has_nose = True
28 except ImportError:
28 except ImportError:
29 has_nose = False
29 has_nose = False
30
30
31 from traitlets.config.loader import Config
31 from traitlets.config.loader import Config
32 from IPython.utils.process import get_output_error_code
32 from IPython.utils.process import get_output_error_code
33 from IPython.utils.text import list_strings
33 from IPython.utils.text import list_strings
34 from IPython.utils.io import temp_pyfile, Tee
34 from IPython.utils.io import temp_pyfile, Tee
35 from IPython.utils import py3compat
35 from IPython.utils import py3compat
36 from IPython.utils.encoding import DEFAULT_ENCODING
36 from IPython.utils.encoding import DEFAULT_ENCODING
37
37
38 from . import decorators as dec
38 from . import decorators as dec
39 from . import skipdoctest
39 from . import skipdoctest
40
40
41
41
42 # The docstring for full_path doctests differently on win32 (different path
42 # The docstring for full_path doctests differently on win32 (different path
43 # separator) so just skip the doctest there. The example remains informative.
43 # separator) so just skip the doctest there. The example remains informative.
44 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
44 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
45
45
46 @doctest_deco
46 @doctest_deco
47 def full_path(startPath,files):
47 def full_path(startPath,files):
48 """Make full paths for all the listed files, based on startPath.
48 """Make full paths for all the listed files, based on startPath.
49
49
50 Only the base part of startPath is kept, since this routine is typically
50 Only the base part of startPath is kept, since this routine is typically
51 used with a script's ``__file__`` variable as startPath. The base of startPath
51 used with a script's ``__file__`` variable as startPath. The base of startPath
52 is then prepended to all the listed files, forming the output list.
52 is then prepended to all the listed files, forming the output list.
53
53
54 Parameters
54 Parameters
55 ----------
55 ----------
56 startPath : string
56 startPath : string
57 Initial path to use as the base for the results. This path is split
57 Initial path to use as the base for the results. This path is split
58 using os.path.split() and only its first component is kept.
58 using os.path.split() and only its first component is kept.
59
59
60 files : string or list
60 files : string or list
61 One or more files.
61 One or more files.
62
62
63 Examples
63 Examples
64 --------
64 --------
65
65
66 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
66 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
67 ['/foo/a.txt', '/foo/b.txt']
67 ['/foo/a.txt', '/foo/b.txt']
68
68
69 >>> full_path('/foo',['a.txt','b.txt'])
69 >>> full_path('/foo',['a.txt','b.txt'])
70 ['/a.txt', '/b.txt']
70 ['/a.txt', '/b.txt']
71
71
72 If a single file is given, the output is still a list::
72 If a single file is given, the output is still a list::
73
73
74 >>> full_path('/foo','a.txt')
74 >>> full_path('/foo','a.txt')
75 ['/a.txt']
75 ['/a.txt']
76 """
76 """
77
77
78 files = list_strings(files)
78 files = list_strings(files)
79 base = os.path.split(startPath)[0]
79 base = os.path.split(startPath)[0]
80 return [ os.path.join(base,f) for f in files ]
80 return [ os.path.join(base,f) for f in files ]
81
81
82
82
83 def parse_test_output(txt):
83 def parse_test_output(txt):
84 """Parse the output of a test run and return errors, failures.
84 """Parse the output of a test run and return errors, failures.
85
85
86 Parameters
86 Parameters
87 ----------
87 ----------
88 txt : str
88 txt : str
89 Text output of a test run, assumed to contain a line of one of the
89 Text output of a test run, assumed to contain a line of one of the
90 following forms::
90 following forms::
91
91
92 'FAILED (errors=1)'
92 'FAILED (errors=1)'
93 'FAILED (failures=1)'
93 'FAILED (failures=1)'
94 'FAILED (errors=1, failures=1)'
94 'FAILED (errors=1, failures=1)'
95
95
96 Returns
96 Returns
97 -------
97 -------
98 nerr, nfail
98 nerr, nfail
99 number of errors and failures.
99 number of errors and failures.
100 """
100 """
101
101
102 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
102 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
103 if err_m:
103 if err_m:
104 nerr = int(err_m.group(1))
104 nerr = int(err_m.group(1))
105 nfail = 0
105 nfail = 0
106 return nerr, nfail
106 return nerr, nfail
107
107
108 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
108 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
109 if fail_m:
109 if fail_m:
110 nerr = 0
110 nerr = 0
111 nfail = int(fail_m.group(1))
111 nfail = int(fail_m.group(1))
112 return nerr, nfail
112 return nerr, nfail
113
113
114 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
114 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
115 re.MULTILINE)
115 re.MULTILINE)
116 if both_m:
116 if both_m:
117 nerr = int(both_m.group(1))
117 nerr = int(both_m.group(1))
118 nfail = int(both_m.group(2))
118 nfail = int(both_m.group(2))
119 return nerr, nfail
119 return nerr, nfail
120
120
121 # If the input didn't match any of these forms, assume no error/failures
121 # If the input didn't match any of these forms, assume no error/failures
122 return 0, 0
122 return 0, 0
123
123
124
124
125 # So nose doesn't think this is a test
125 # So nose doesn't think this is a test
126 parse_test_output.__test__ = False
126 parse_test_output.__test__ = False
127
127
128
128
129 def default_argv():
129 def default_argv():
130 """Return a valid default argv for creating testing instances of ipython"""
130 """Return a valid default argv for creating testing instances of ipython"""
131
131
132 return ['--quick', # so no config file is loaded
132 return ['--quick', # so no config file is loaded
133 # Other defaults to minimize side effects on stdout
133 # Other defaults to minimize side effects on stdout
134 '--colors=NoColor', '--no-term-title','--no-banner',
134 '--colors=NoColor', '--no-term-title','--no-banner',
135 '--autocall=0']
135 '--autocall=0']
136
136
137
137
138 def default_config():
138 def default_config():
139 """Return a config object with good defaults for testing."""
139 """Return a config object with good defaults for testing."""
140 config = Config()
140 config = Config()
141 config.TerminalInteractiveShell.colors = 'NoColor'
141 config.TerminalInteractiveShell.colors = 'NoColor'
142 config.TerminalTerminalInteractiveShell.term_title = False,
142 config.TerminalTerminalInteractiveShell.term_title = False,
143 config.TerminalInteractiveShell.autocall = 0
143 config.TerminalInteractiveShell.autocall = 0
144 f = tempfile.NamedTemporaryFile(suffix=u'test_hist.sqlite', delete=False)
144 f = tempfile.NamedTemporaryFile(suffix=u'test_hist.sqlite', delete=False)
145 config.HistoryManager.hist_file = f.name
145 config.HistoryManager.hist_file = f.name
146 f.close()
146 f.close()
147 config.HistoryManager.db_cache_size = 10000
147 config.HistoryManager.db_cache_size = 10000
148 return config
148 return config
149
149
150
150
151 def get_ipython_cmd(as_string=False):
151 def get_ipython_cmd(as_string=False):
152 """
152 """
153 Return appropriate IPython command line name. By default, this will return
153 Return appropriate IPython command line name. By default, this will return
154 a list that can be used with subprocess.Popen, for example, but passing
154 a list that can be used with subprocess.Popen, for example, but passing
155 `as_string=True` allows for returning the IPython command as a string.
155 `as_string=True` allows for returning the IPython command as a string.
156
156
157 Parameters
157 Parameters
158 ----------
158 ----------
159 as_string: bool
159 as_string: bool
160 Flag to allow to return the command as a string.
160 Flag to allow to return the command as a string.
161 """
161 """
162 ipython_cmd = [sys.executable, "-m", "IPython"]
162 ipython_cmd = [sys.executable, "-m", "IPython"]
163
163
164 if as_string:
164 if as_string:
165 ipython_cmd = " ".join(ipython_cmd)
165 ipython_cmd = " ".join(ipython_cmd)
166
166
167 return ipython_cmd
167 return ipython_cmd
168
168
169 def ipexec(fname, options=None, commands=()):
169 def ipexec(fname, options=None, commands=()):
170 """Utility to call 'ipython filename'.
170 """Utility to call 'ipython filename'.
171
171
172 Starts IPython with a minimal and safe configuration to make startup as fast
172 Starts IPython with a minimal and safe configuration to make startup as fast
173 as possible.
173 as possible.
174
174
175 Note that this starts IPython in a subprocess!
175 Note that this starts IPython in a subprocess!
176
176
177 Parameters
177 Parameters
178 ----------
178 ----------
179 fname : str
179 fname : str
180 Name of file to be executed (should have .py or .ipy extension).
180 Name of file to be executed (should have .py or .ipy extension).
181
181
182 options : optional, list
182 options : optional, list
183 Extra command-line flags to be passed to IPython.
183 Extra command-line flags to be passed to IPython.
184
184
185 commands : optional, list
185 commands : optional, list
186 Commands to send in on stdin
186 Commands to send in on stdin
187
187
188 Returns
188 Returns
189 -------
189 -------
190 (stdout, stderr) of ipython subprocess.
190 (stdout, stderr) of ipython subprocess.
191 """
191 """
192 if options is None: options = []
192 if options is None: options = []
193
193
194 cmdargs = default_argv() + options
194 cmdargs = default_argv() + options
195
195
196 test_dir = os.path.dirname(__file__)
196 test_dir = os.path.dirname(__file__)
197
197
198 ipython_cmd = get_ipython_cmd()
198 ipython_cmd = get_ipython_cmd()
199 # Absolute path for filename
199 # Absolute path for filename
200 full_fname = os.path.join(test_dir, fname)
200 full_fname = os.path.join(test_dir, fname)
201 full_cmd = ipython_cmd + cmdargs + [full_fname]
201 full_cmd = ipython_cmd + cmdargs + [full_fname]
202 env = os.environ.copy()
202 env = os.environ.copy()
203 # FIXME: ignore all warnings in ipexec while we have shims
203 # FIXME: ignore all warnings in ipexec while we have shims
204 # should we keep suppressing warnings here, even after removing shims?
204 # should we keep suppressing warnings here, even after removing shims?
205 env['PYTHONWARNINGS'] = 'ignore'
205 env['PYTHONWARNINGS'] = 'ignore'
206 # env.pop('PYTHONWARNINGS', None) # Avoid extraneous warnings appearing on stderr
206 # env.pop('PYTHONWARNINGS', None) # Avoid extraneous warnings appearing on stderr
207 for k, v in env.items():
207 for k, v in env.items():
208 # Debug a bizarre failure we've seen on Windows:
208 # Debug a bizarre failure we've seen on Windows:
209 # TypeError: environment can only contain strings
209 # TypeError: environment can only contain strings
210 if not isinstance(v, str):
210 if not isinstance(v, str):
211 print(k, v)
211 print(k, v)
212 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env)
212 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env)
213 out, err = p.communicate(input=py3compat.str_to_bytes('\n'.join(commands)) or None)
213 out, err = p.communicate(input=py3compat.str_to_bytes('\n'.join(commands)) or None)
214 out, err = py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
214 out, err = py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
215 # `import readline` causes 'ESC[?1034h' to be output sometimes,
215 # `import readline` causes 'ESC[?1034h' to be output sometimes,
216 # so strip that out before doing comparisons
216 # so strip that out before doing comparisons
217 if out:
217 if out:
218 out = re.sub(r'\x1b\[[^h]+h', '', out)
218 out = re.sub(r'\x1b\[[^h]+h', '', out)
219 return out, err
219 return out, err
220
220
221
221
222 def ipexec_validate(fname, expected_out, expected_err='',
222 def ipexec_validate(fname, expected_out, expected_err='',
223 options=None, commands=()):
223 options=None, commands=()):
224 """Utility to call 'ipython filename' and validate output/error.
224 """Utility to call 'ipython filename' and validate output/error.
225
225
226 This function raises an AssertionError if the validation fails.
226 This function raises an AssertionError if the validation fails.
227
227
228 Note that this starts IPython in a subprocess!
228 Note that this starts IPython in a subprocess!
229
229
230 Parameters
230 Parameters
231 ----------
231 ----------
232 fname : str
232 fname : str
233 Name of the file to be executed (should have .py or .ipy extension).
233 Name of the file to be executed (should have .py or .ipy extension).
234
234
235 expected_out : str
235 expected_out : str
236 Expected stdout of the process.
236 Expected stdout of the process.
237
237
238 expected_err : optional, str
238 expected_err : optional, str
239 Expected stderr of the process.
239 Expected stderr of the process.
240
240
241 options : optional, list
241 options : optional, list
242 Extra command-line flags to be passed to IPython.
242 Extra command-line flags to be passed to IPython.
243
243
244 Returns
244 Returns
245 -------
245 -------
246 None
246 None
247 """
247 """
248
248
249 import nose.tools as nt
249 import nose.tools as nt
250
250
251 out, err = ipexec(fname, options, commands)
251 out, err = ipexec(fname, options, commands)
252 #print 'OUT', out # dbg
252 #print 'OUT', out # dbg
253 #print 'ERR', err # dbg
253 #print 'ERR', err # dbg
254 # If there are any errors, we must check those befor stdout, as they may be
254 # If there are any errors, we must check those befor stdout, as they may be
255 # more informative than simply having an empty stdout.
255 # more informative than simply having an empty stdout.
256 if err:
256 if err:
257 if expected_err:
257 if expected_err:
258 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
258 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
259 else:
259 else:
260 raise ValueError('Running file %r produced error: %r' %
260 raise ValueError('Running file %r produced error: %r' %
261 (fname, err))
261 (fname, err))
262 # If no errors or output on stderr was expected, match stdout
262 # If no errors or output on stderr was expected, match stdout
263 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
263 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
264
264
265
265
266 class TempFileMixin(object):
266 class TempFileMixin(object):
267 """Utility class to create temporary Python/IPython files.
267 """Utility class to create temporary Python/IPython files.
268
268
269 Meant as a mixin class for test cases."""
269 Meant as a mixin class for test cases."""
270
270
271 def mktmp(self, src, ext='.py'):
271 def mktmp(self, src, ext='.py'):
272 """Make a valid python temp file."""
272 """Make a valid python temp file."""
273 fname, f = temp_pyfile(src, ext)
273 fname, f = temp_pyfile(src, ext)
274 self.tmpfile = f
274 self.tmpfile = f
275 self.fname = fname
275 self.fname = fname
276
276
277 def tearDown(self):
277 def tearDown(self):
278 if hasattr(self, 'tmpfile'):
278 if hasattr(self, 'tmpfile'):
279 # If the tmpfile wasn't made because of skipped tests, like in
279 # If the tmpfile wasn't made because of skipped tests, like in
280 # win32, there's nothing to cleanup.
280 # win32, there's nothing to cleanup.
281 self.tmpfile.close()
281 self.tmpfile.close()
282 try:
282 try:
283 os.unlink(self.fname)
283 os.unlink(self.fname)
284 except:
284 except:
285 # On Windows, even though we close the file, we still can't
285 # On Windows, even though we close the file, we still can't
286 # delete it. I have no clue why
286 # delete it. I have no clue why
287 pass
287 pass
288
288
289 def __enter__(self):
289 def __enter__(self):
290 return self
290 return self
291
291
292 def __exit__(self, exc_type, exc_value, traceback):
292 def __exit__(self, exc_type, exc_value, traceback):
293 self.tearDown()
293 self.tearDown()
294
294
295
295
296 pair_fail_msg = ("Testing {0}\n\n"
296 pair_fail_msg = ("Testing {0}\n\n"
297 "In:\n"
297 "In:\n"
298 " {1!r}\n"
298 " {1!r}\n"
299 "Expected:\n"
299 "Expected:\n"
300 " {2!r}\n"
300 " {2!r}\n"
301 "Got:\n"
301 "Got:\n"
302 " {3!r}\n")
302 " {3!r}\n")
303 def check_pairs(func, pairs):
303 def check_pairs(func, pairs):
304 """Utility function for the common case of checking a function with a
304 """Utility function for the common case of checking a function with a
305 sequence of input/output pairs.
305 sequence of input/output pairs.
306
306
307 Parameters
307 Parameters
308 ----------
308 ----------
309 func : callable
309 func : callable
310 The function to be tested. Should accept a single argument.
310 The function to be tested. Should accept a single argument.
311 pairs : iterable
311 pairs : iterable
312 A list of (input, expected_output) tuples.
312 A list of (input, expected_output) tuples.
313
313
314 Returns
314 Returns
315 -------
315 -------
316 None. Raises an AssertionError if any output does not match the expected
316 None. Raises an AssertionError if any output does not match the expected
317 value.
317 value.
318 """
318 """
319 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
319 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
320 for inp, expected in pairs:
320 for inp, expected in pairs:
321 out = func(inp)
321 out = func(inp)
322 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
322 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
323
323
324
324
325 if py3compat.PY3:
325 if py3compat.PY3:
326 MyStringIO = StringIO
326 MyStringIO = StringIO
327 else:
327 else:
328 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
328 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
329 # so we need a class that can handle both.
329 # so we need a class that can handle both.
330 class MyStringIO(StringIO):
330 class MyStringIO(StringIO):
331 def write(self, s):
331 def write(self, s):
332 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
332 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
333 super(MyStringIO, self).write(s)
333 super(MyStringIO, self).write(s)
334
334
335 _re_type = type(re.compile(r''))
335 _re_type = type(re.compile(r''))
336
336
337 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
337 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
338 -------
338 -------
339 {2!s}
339 {2!s}
340 -------
340 -------
341 """
341 """
342
342
343 class AssertPrints(object):
343 class AssertPrints(object):
344 """Context manager for testing that code prints certain text.
344 """Context manager for testing that code prints certain text.
345
345
346 Examples
346 Examples
347 --------
347 --------
348 >>> with AssertPrints("abc", suppress=False):
348 >>> with AssertPrints("abc", suppress=False):
349 ... print("abcd")
349 ... print("abcd")
350 ... print("def")
350 ... print("def")
351 ...
351 ...
352 abcd
352 abcd
353 def
353 def
354 """
354 """
355 def __init__(self, s, channel='stdout', suppress=True):
355 def __init__(self, s, channel='stdout', suppress=True):
356 self.s = s
356 self.s = s
357 if isinstance(self.s, (py3compat.string_types, _re_type)):
357 if isinstance(self.s, (str, _re_type)):
358 self.s = [self.s]
358 self.s = [self.s]
359 self.channel = channel
359 self.channel = channel
360 self.suppress = suppress
360 self.suppress = suppress
361
361
362 def __enter__(self):
362 def __enter__(self):
363 self.orig_stream = getattr(sys, self.channel)
363 self.orig_stream = getattr(sys, self.channel)
364 self.buffer = MyStringIO()
364 self.buffer = MyStringIO()
365 self.tee = Tee(self.buffer, channel=self.channel)
365 self.tee = Tee(self.buffer, channel=self.channel)
366 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
366 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
367
367
368 def __exit__(self, etype, value, traceback):
368 def __exit__(self, etype, value, traceback):
369 try:
369 try:
370 if value is not None:
370 if value is not None:
371 # If an error was raised, don't check anything else
371 # If an error was raised, don't check anything else
372 return False
372 return False
373 self.tee.flush()
373 self.tee.flush()
374 setattr(sys, self.channel, self.orig_stream)
374 setattr(sys, self.channel, self.orig_stream)
375 printed = self.buffer.getvalue()
375 printed = self.buffer.getvalue()
376 for s in self.s:
376 for s in self.s:
377 if isinstance(s, _re_type):
377 if isinstance(s, _re_type):
378 assert s.search(printed), notprinted_msg.format(s.pattern, self.channel, printed)
378 assert s.search(printed), notprinted_msg.format(s.pattern, self.channel, printed)
379 else:
379 else:
380 assert s in printed, notprinted_msg.format(s, self.channel, printed)
380 assert s in printed, notprinted_msg.format(s, self.channel, printed)
381 return False
381 return False
382 finally:
382 finally:
383 self.tee.close()
383 self.tee.close()
384
384
385 printed_msg = """Found {0!r} in printed output (on {1}):
385 printed_msg = """Found {0!r} in printed output (on {1}):
386 -------
386 -------
387 {2!s}
387 {2!s}
388 -------
388 -------
389 """
389 """
390
390
391 class AssertNotPrints(AssertPrints):
391 class AssertNotPrints(AssertPrints):
392 """Context manager for checking that certain output *isn't* produced.
392 """Context manager for checking that certain output *isn't* produced.
393
393
394 Counterpart of AssertPrints"""
394 Counterpart of AssertPrints"""
395 def __exit__(self, etype, value, traceback):
395 def __exit__(self, etype, value, traceback):
396 try:
396 try:
397 if value is not None:
397 if value is not None:
398 # If an error was raised, don't check anything else
398 # If an error was raised, don't check anything else
399 self.tee.close()
399 self.tee.close()
400 return False
400 return False
401 self.tee.flush()
401 self.tee.flush()
402 setattr(sys, self.channel, self.orig_stream)
402 setattr(sys, self.channel, self.orig_stream)
403 printed = self.buffer.getvalue()
403 printed = self.buffer.getvalue()
404 for s in self.s:
404 for s in self.s:
405 if isinstance(s, _re_type):
405 if isinstance(s, _re_type):
406 assert not s.search(printed),printed_msg.format(
406 assert not s.search(printed),printed_msg.format(
407 s.pattern, self.channel, printed)
407 s.pattern, self.channel, printed)
408 else:
408 else:
409 assert s not in printed, printed_msg.format(
409 assert s not in printed, printed_msg.format(
410 s, self.channel, printed)
410 s, self.channel, printed)
411 return False
411 return False
412 finally:
412 finally:
413 self.tee.close()
413 self.tee.close()
414
414
415 @contextmanager
415 @contextmanager
416 def mute_warn():
416 def mute_warn():
417 from IPython.utils import warn
417 from IPython.utils import warn
418 save_warn = warn.warn
418 save_warn = warn.warn
419 warn.warn = lambda *a, **kw: None
419 warn.warn = lambda *a, **kw: None
420 try:
420 try:
421 yield
421 yield
422 finally:
422 finally:
423 warn.warn = save_warn
423 warn.warn = save_warn
424
424
425 @contextmanager
425 @contextmanager
426 def make_tempfile(name):
426 def make_tempfile(name):
427 """ Create an empty, named, temporary file for the duration of the context.
427 """ Create an empty, named, temporary file for the duration of the context.
428 """
428 """
429 f = open(name, 'w')
429 f = open(name, 'w')
430 f.close()
430 f.close()
431 try:
431 try:
432 yield
432 yield
433 finally:
433 finally:
434 os.unlink(name)
434 os.unlink(name)
435
435
436 def fake_input(inputs):
436 def fake_input(inputs):
437 """Temporarily replace the input() function to return the given values
437 """Temporarily replace the input() function to return the given values
438
438
439 Use as a context manager:
439 Use as a context manager:
440
440
441 with fake_input(['result1', 'result2']):
441 with fake_input(['result1', 'result2']):
442 ...
442 ...
443
443
444 Values are returned in order. If input() is called again after the last value
444 Values are returned in order. If input() is called again after the last value
445 was used, EOFError is raised.
445 was used, EOFError is raised.
446 """
446 """
447 it = iter(inputs)
447 it = iter(inputs)
448 def mock_input(prompt=''):
448 def mock_input(prompt=''):
449 try:
449 try:
450 return next(it)
450 return next(it)
451 except StopIteration:
451 except StopIteration:
452 raise EOFError('No more inputs given')
452 raise EOFError('No more inputs given')
453
453
454 return patch('builtins.input', mock_input)
454 return patch('builtins.input', mock_input)
455
455
456 def help_output_test(subcommand=''):
456 def help_output_test(subcommand=''):
457 """test that `ipython [subcommand] -h` works"""
457 """test that `ipython [subcommand] -h` works"""
458 cmd = get_ipython_cmd() + [subcommand, '-h']
458 cmd = get_ipython_cmd() + [subcommand, '-h']
459 out, err, rc = get_output_error_code(cmd)
459 out, err, rc = get_output_error_code(cmd)
460 nt.assert_equal(rc, 0, err)
460 nt.assert_equal(rc, 0, err)
461 nt.assert_not_in("Traceback", err)
461 nt.assert_not_in("Traceback", err)
462 nt.assert_in("Options", out)
462 nt.assert_in("Options", out)
463 nt.assert_in("--help-all", out)
463 nt.assert_in("--help-all", out)
464 return out, err
464 return out, err
465
465
466
466
467 def help_all_output_test(subcommand=''):
467 def help_all_output_test(subcommand=''):
468 """test that `ipython [subcommand] --help-all` works"""
468 """test that `ipython [subcommand] --help-all` works"""
469 cmd = get_ipython_cmd() + [subcommand, '--help-all']
469 cmd = get_ipython_cmd() + [subcommand, '--help-all']
470 out, err, rc = get_output_error_code(cmd)
470 out, err, rc = get_output_error_code(cmd)
471 nt.assert_equal(rc, 0, err)
471 nt.assert_equal(rc, 0, err)
472 nt.assert_not_in("Traceback", err)
472 nt.assert_not_in("Traceback", err)
473 nt.assert_in("Options", out)
473 nt.assert_in("Options", out)
474 nt.assert_in("Class parameters", out)
474 nt.assert_in("Class parameters", out)
475 return out, err
475 return out, err
476
476
@@ -1,223 +1,223 b''
1 """Common utilities for the various process_* implementations.
1 """Common utilities for the various process_* implementations.
2
2
3 This file is only meant to be imported by the platform-specific implementations
3 This file is only meant to be imported by the platform-specific implementations
4 of subprocess utilities, and it contains tools that are common to all of them.
4 of subprocess utilities, and it contains tools that are common to all of them.
5 """
5 """
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2010-2011 The IPython Development Team
8 # Copyright (C) 2010-2011 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 import subprocess
17 import subprocess
18 import shlex
18 import shlex
19 import sys
19 import sys
20 import os
20 import os
21
21
22 from IPython.utils import py3compat
22 from IPython.utils import py3compat
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Function definitions
25 # Function definitions
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 def read_no_interrupt(p):
28 def read_no_interrupt(p):
29 """Read from a pipe ignoring EINTR errors.
29 """Read from a pipe ignoring EINTR errors.
30
30
31 This is necessary because when reading from pipes with GUI event loops
31 This is necessary because when reading from pipes with GUI event loops
32 running in the background, often interrupts are raised that stop the
32 running in the background, often interrupts are raised that stop the
33 command from completing."""
33 command from completing."""
34 import errno
34 import errno
35
35
36 try:
36 try:
37 return p.read()
37 return p.read()
38 except IOError as err:
38 except IOError as err:
39 if err.errno != errno.EINTR:
39 if err.errno != errno.EINTR:
40 raise
40 raise
41
41
42
42
43 def process_handler(cmd, callback, stderr=subprocess.PIPE):
43 def process_handler(cmd, callback, stderr=subprocess.PIPE):
44 """Open a command in a shell subprocess and execute a callback.
44 """Open a command in a shell subprocess and execute a callback.
45
45
46 This function provides common scaffolding for creating subprocess.Popen()
46 This function provides common scaffolding for creating subprocess.Popen()
47 calls. It creates a Popen object and then calls the callback with it.
47 calls. It creates a Popen object and then calls the callback with it.
48
48
49 Parameters
49 Parameters
50 ----------
50 ----------
51 cmd : str or list
51 cmd : str or list
52 A command to be executed by the system, using :class:`subprocess.Popen`.
52 A command to be executed by the system, using :class:`subprocess.Popen`.
53 If a string is passed, it will be run in the system shell. If a list is
53 If a string is passed, it will be run in the system shell. If a list is
54 passed, it will be used directly as arguments.
54 passed, it will be used directly as arguments.
55
55
56 callback : callable
56 callback : callable
57 A one-argument function that will be called with the Popen object.
57 A one-argument function that will be called with the Popen object.
58
58
59 stderr : file descriptor number, optional
59 stderr : file descriptor number, optional
60 By default this is set to ``subprocess.PIPE``, but you can also pass the
60 By default this is set to ``subprocess.PIPE``, but you can also pass the
61 value ``subprocess.STDOUT`` to force the subprocess' stderr to go into
61 value ``subprocess.STDOUT`` to force the subprocess' stderr to go into
62 the same file descriptor as its stdout. This is useful to read stdout
62 the same file descriptor as its stdout. This is useful to read stdout
63 and stderr combined in the order they are generated.
63 and stderr combined in the order they are generated.
64
64
65 Returns
65 Returns
66 -------
66 -------
67 The return value of the provided callback is returned.
67 The return value of the provided callback is returned.
68 """
68 """
69 sys.stdout.flush()
69 sys.stdout.flush()
70 sys.stderr.flush()
70 sys.stderr.flush()
71 # On win32, close_fds can't be true when using pipes for stdin/out/err
71 # On win32, close_fds can't be true when using pipes for stdin/out/err
72 close_fds = sys.platform != 'win32'
72 close_fds = sys.platform != 'win32'
73 # Determine if cmd should be run with system shell.
73 # Determine if cmd should be run with system shell.
74 shell = isinstance(cmd, py3compat.string_types)
74 shell = isinstance(cmd, str)
75 # On POSIX systems run shell commands with user-preferred shell.
75 # On POSIX systems run shell commands with user-preferred shell.
76 executable = None
76 executable = None
77 if shell and os.name == 'posix' and 'SHELL' in os.environ:
77 if shell and os.name == 'posix' and 'SHELL' in os.environ:
78 executable = os.environ['SHELL']
78 executable = os.environ['SHELL']
79 p = subprocess.Popen(cmd, shell=shell,
79 p = subprocess.Popen(cmd, shell=shell,
80 executable=executable,
80 executable=executable,
81 stdin=subprocess.PIPE,
81 stdin=subprocess.PIPE,
82 stdout=subprocess.PIPE,
82 stdout=subprocess.PIPE,
83 stderr=stderr,
83 stderr=stderr,
84 close_fds=close_fds)
84 close_fds=close_fds)
85
85
86 try:
86 try:
87 out = callback(p)
87 out = callback(p)
88 except KeyboardInterrupt:
88 except KeyboardInterrupt:
89 print('^C')
89 print('^C')
90 sys.stdout.flush()
90 sys.stdout.flush()
91 sys.stderr.flush()
91 sys.stderr.flush()
92 out = None
92 out = None
93 finally:
93 finally:
94 # Make really sure that we don't leave processes behind, in case the
94 # Make really sure that we don't leave processes behind, in case the
95 # call above raises an exception
95 # call above raises an exception
96 # We start by assuming the subprocess finished (to avoid NameErrors
96 # We start by assuming the subprocess finished (to avoid NameErrors
97 # later depending on the path taken)
97 # later depending on the path taken)
98 if p.returncode is None:
98 if p.returncode is None:
99 try:
99 try:
100 p.terminate()
100 p.terminate()
101 p.poll()
101 p.poll()
102 except OSError:
102 except OSError:
103 pass
103 pass
104 # One last try on our way out
104 # One last try on our way out
105 if p.returncode is None:
105 if p.returncode is None:
106 try:
106 try:
107 p.kill()
107 p.kill()
108 except OSError:
108 except OSError:
109 pass
109 pass
110
110
111 return out
111 return out
112
112
113
113
114 def getoutput(cmd):
114 def getoutput(cmd):
115 """Run a command and return its stdout/stderr as a string.
115 """Run a command and return its stdout/stderr as a string.
116
116
117 Parameters
117 Parameters
118 ----------
118 ----------
119 cmd : str or list
119 cmd : str or list
120 A command to be executed in the system shell.
120 A command to be executed in the system shell.
121
121
122 Returns
122 Returns
123 -------
123 -------
124 output : str
124 output : str
125 A string containing the combination of stdout and stderr from the
125 A string containing the combination of stdout and stderr from the
126 subprocess, in whatever order the subprocess originally wrote to its
126 subprocess, in whatever order the subprocess originally wrote to its
127 file descriptors (so the order of the information in this string is the
127 file descriptors (so the order of the information in this string is the
128 correct order as would be seen if running the command in a terminal).
128 correct order as would be seen if running the command in a terminal).
129 """
129 """
130 out = process_handler(cmd, lambda p: p.communicate()[0], subprocess.STDOUT)
130 out = process_handler(cmd, lambda p: p.communicate()[0], subprocess.STDOUT)
131 if out is None:
131 if out is None:
132 return ''
132 return ''
133 return py3compat.bytes_to_str(out)
133 return py3compat.bytes_to_str(out)
134
134
135
135
136 def getoutputerror(cmd):
136 def getoutputerror(cmd):
137 """Return (standard output, standard error) of executing cmd in a shell.
137 """Return (standard output, standard error) of executing cmd in a shell.
138
138
139 Accepts the same arguments as os.system().
139 Accepts the same arguments as os.system().
140
140
141 Parameters
141 Parameters
142 ----------
142 ----------
143 cmd : str or list
143 cmd : str or list
144 A command to be executed in the system shell.
144 A command to be executed in the system shell.
145
145
146 Returns
146 Returns
147 -------
147 -------
148 stdout : str
148 stdout : str
149 stderr : str
149 stderr : str
150 """
150 """
151 return get_output_error_code(cmd)[:2]
151 return get_output_error_code(cmd)[:2]
152
152
153 def get_output_error_code(cmd):
153 def get_output_error_code(cmd):
154 """Return (standard output, standard error, return code) of executing cmd
154 """Return (standard output, standard error, return code) of executing cmd
155 in a shell.
155 in a shell.
156
156
157 Accepts the same arguments as os.system().
157 Accepts the same arguments as os.system().
158
158
159 Parameters
159 Parameters
160 ----------
160 ----------
161 cmd : str or list
161 cmd : str or list
162 A command to be executed in the system shell.
162 A command to be executed in the system shell.
163
163
164 Returns
164 Returns
165 -------
165 -------
166 stdout : str
166 stdout : str
167 stderr : str
167 stderr : str
168 returncode: int
168 returncode: int
169 """
169 """
170
170
171 out_err, p = process_handler(cmd, lambda p: (p.communicate(), p))
171 out_err, p = process_handler(cmd, lambda p: (p.communicate(), p))
172 if out_err is None:
172 if out_err is None:
173 return '', '', p.returncode
173 return '', '', p.returncode
174 out, err = out_err
174 out, err = out_err
175 return py3compat.bytes_to_str(out), py3compat.bytes_to_str(err), p.returncode
175 return py3compat.bytes_to_str(out), py3compat.bytes_to_str(err), p.returncode
176
176
177 def arg_split(s, posix=False, strict=True):
177 def arg_split(s, posix=False, strict=True):
178 """Split a command line's arguments in a shell-like manner.
178 """Split a command line's arguments in a shell-like manner.
179
179
180 This is a modified version of the standard library's shlex.split()
180 This is a modified version of the standard library's shlex.split()
181 function, but with a default of posix=False for splitting, so that quotes
181 function, but with a default of posix=False for splitting, so that quotes
182 in inputs are respected.
182 in inputs are respected.
183
183
184 if strict=False, then any errors shlex.split would raise will result in the
184 if strict=False, then any errors shlex.split would raise will result in the
185 unparsed remainder being the last element of the list, rather than raising.
185 unparsed remainder being the last element of the list, rather than raising.
186 This is because we sometimes use arg_split to parse things other than
186 This is because we sometimes use arg_split to parse things other than
187 command-line args.
187 command-line args.
188 """
188 """
189
189
190 # Unfortunately, python's shlex module is buggy with unicode input:
190 # Unfortunately, python's shlex module is buggy with unicode input:
191 # http://bugs.python.org/issue1170
191 # http://bugs.python.org/issue1170
192 # At least encoding the input when it's unicode seems to help, but there
192 # At least encoding the input when it's unicode seems to help, but there
193 # may be more problems lurking. Apparently this is fixed in python3.
193 # may be more problems lurking. Apparently this is fixed in python3.
194 is_unicode = False
194 is_unicode = False
195 if (not py3compat.PY3) and isinstance(s, unicode):
195 if (not py3compat.PY3) and isinstance(s, unicode):
196 is_unicode = True
196 is_unicode = True
197 s = s.encode('utf-8')
197 s = s.encode('utf-8')
198 lex = shlex.shlex(s, posix=posix)
198 lex = shlex.shlex(s, posix=posix)
199 lex.whitespace_split = True
199 lex.whitespace_split = True
200 # Extract tokens, ensuring that things like leaving open quotes
200 # Extract tokens, ensuring that things like leaving open quotes
201 # does not cause this to raise. This is important, because we
201 # does not cause this to raise. This is important, because we
202 # sometimes pass Python source through this (e.g. %timeit f(" ")),
202 # sometimes pass Python source through this (e.g. %timeit f(" ")),
203 # and it shouldn't raise an exception.
203 # and it shouldn't raise an exception.
204 # It may be a bad idea to parse things that are not command-line args
204 # It may be a bad idea to parse things that are not command-line args
205 # through this function, but we do, so let's be safe about it.
205 # through this function, but we do, so let's be safe about it.
206 lex.commenters='' #fix for GH-1269
206 lex.commenters='' #fix for GH-1269
207 tokens = []
207 tokens = []
208 while True:
208 while True:
209 try:
209 try:
210 tokens.append(next(lex))
210 tokens.append(next(lex))
211 except StopIteration:
211 except StopIteration:
212 break
212 break
213 except ValueError:
213 except ValueError:
214 if strict:
214 if strict:
215 raise
215 raise
216 # couldn't parse, get remaining blob as last token
216 # couldn't parse, get remaining blob as last token
217 tokens.append(lex.token)
217 tokens.append(lex.token)
218 break
218 break
219
219
220 if is_unicode:
220 if is_unicode:
221 # Convert the tokens back to unicode.
221 # Convert the tokens back to unicode.
222 tokens = [x.decode('utf-8') for x in tokens]
222 tokens = [x.decode('utf-8') for x in tokens]
223 return tokens
223 return tokens
@@ -1,191 +1,191 b''
1 """Windows-specific implementation of process utilities.
1 """Windows-specific implementation of process utilities.
2
2
3 This file is only meant to be imported by process.py, not by end-users.
3 This file is only meant to be imported by process.py, not by end-users.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2010-2011 The IPython Development Team
7 # Copyright (C) 2010-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 # stdlib
17 # stdlib
18 import os
18 import os
19 import sys
19 import sys
20 import ctypes
20 import ctypes
21
21
22 from ctypes import c_int, POINTER
22 from ctypes import c_int, POINTER
23 from ctypes.wintypes import LPCWSTR, HLOCAL
23 from ctypes.wintypes import LPCWSTR, HLOCAL
24 from subprocess import STDOUT
24 from subprocess import STDOUT
25
25
26 # our own imports
26 # our own imports
27 from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
27 from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
28 from . import py3compat
28 from . import py3compat
29 from .encoding import DEFAULT_ENCODING
29 from .encoding import DEFAULT_ENCODING
30
30
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 # Function definitions
32 # Function definitions
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34
34
35 class AvoidUNCPath(object):
35 class AvoidUNCPath(object):
36 """A context manager to protect command execution from UNC paths.
36 """A context manager to protect command execution from UNC paths.
37
37
38 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
38 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
39 This context manager temporarily changes directory to the 'C:' drive on
39 This context manager temporarily changes directory to the 'C:' drive on
40 entering, and restores the original working directory on exit.
40 entering, and restores the original working directory on exit.
41
41
42 The context manager returns the starting working directory *if* it made a
42 The context manager returns the starting working directory *if* it made a
43 change and None otherwise, so that users can apply the necessary adjustment
43 change and None otherwise, so that users can apply the necessary adjustment
44 to their system calls in the event of a change.
44 to their system calls in the event of a change.
45
45
46 Examples
46 Examples
47 --------
47 --------
48 ::
48 ::
49 cmd = 'dir'
49 cmd = 'dir'
50 with AvoidUNCPath() as path:
50 with AvoidUNCPath() as path:
51 if path is not None:
51 if path is not None:
52 cmd = '"pushd %s &&"%s' % (path, cmd)
52 cmd = '"pushd %s &&"%s' % (path, cmd)
53 os.system(cmd)
53 os.system(cmd)
54 """
54 """
55 def __enter__(self):
55 def __enter__(self):
56 self.path = py3compat.getcwd()
56 self.path = os.getcwd()
57 self.is_unc_path = self.path.startswith(r"\\")
57 self.is_unc_path = self.path.startswith(r"\\")
58 if self.is_unc_path:
58 if self.is_unc_path:
59 # change to c drive (as cmd.exe cannot handle UNC addresses)
59 # change to c drive (as cmd.exe cannot handle UNC addresses)
60 os.chdir("C:")
60 os.chdir("C:")
61 return self.path
61 return self.path
62 else:
62 else:
63 # We return None to signal that there was no change in the working
63 # We return None to signal that there was no change in the working
64 # directory
64 # directory
65 return None
65 return None
66
66
67 def __exit__(self, exc_type, exc_value, traceback):
67 def __exit__(self, exc_type, exc_value, traceback):
68 if self.is_unc_path:
68 if self.is_unc_path:
69 os.chdir(self.path)
69 os.chdir(self.path)
70
70
71
71
72 def _find_cmd(cmd):
72 def _find_cmd(cmd):
73 """Find the full path to a .bat or .exe using the win32api module."""
73 """Find the full path to a .bat or .exe using the win32api module."""
74 try:
74 try:
75 from win32api import SearchPath
75 from win32api import SearchPath
76 except ImportError:
76 except ImportError:
77 raise ImportError('you need to have pywin32 installed for this to work')
77 raise ImportError('you need to have pywin32 installed for this to work')
78 else:
78 else:
79 PATH = os.environ['PATH']
79 PATH = os.environ['PATH']
80 extensions = ['.exe', '.com', '.bat', '.py']
80 extensions = ['.exe', '.com', '.bat', '.py']
81 path = None
81 path = None
82 for ext in extensions:
82 for ext in extensions:
83 try:
83 try:
84 path = SearchPath(PATH, cmd, ext)[0]
84 path = SearchPath(PATH, cmd, ext)[0]
85 except:
85 except:
86 pass
86 pass
87 if path is None:
87 if path is None:
88 raise OSError("command %r not found" % cmd)
88 raise OSError("command %r not found" % cmd)
89 else:
89 else:
90 return path
90 return path
91
91
92
92
93 def _system_body(p):
93 def _system_body(p):
94 """Callback for _system."""
94 """Callback for _system."""
95 enc = DEFAULT_ENCODING
95 enc = DEFAULT_ENCODING
96 for line in read_no_interrupt(p.stdout).splitlines():
96 for line in read_no_interrupt(p.stdout).splitlines():
97 line = line.decode(enc, 'replace')
97 line = line.decode(enc, 'replace')
98 print(line, file=sys.stdout)
98 print(line, file=sys.stdout)
99 for line in read_no_interrupt(p.stderr).splitlines():
99 for line in read_no_interrupt(p.stderr).splitlines():
100 line = line.decode(enc, 'replace')
100 line = line.decode(enc, 'replace')
101 print(line, file=sys.stderr)
101 print(line, file=sys.stderr)
102
102
103 # Wait to finish for returncode
103 # Wait to finish for returncode
104 return p.wait()
104 return p.wait()
105
105
106
106
107 def system(cmd):
107 def system(cmd):
108 """Win32 version of os.system() that works with network shares.
108 """Win32 version of os.system() that works with network shares.
109
109
110 Note that this implementation returns None, as meant for use in IPython.
110 Note that this implementation returns None, as meant for use in IPython.
111
111
112 Parameters
112 Parameters
113 ----------
113 ----------
114 cmd : str or list
114 cmd : str or list
115 A command to be executed in the system shell.
115 A command to be executed in the system shell.
116
116
117 Returns
117 Returns
118 -------
118 -------
119 None : we explicitly do NOT return the subprocess status code, as this
119 None : we explicitly do NOT return the subprocess status code, as this
120 utility is meant to be used extensively in IPython, where any return value
120 utility is meant to be used extensively in IPython, where any return value
121 would trigger :func:`sys.displayhook` calls.
121 would trigger :func:`sys.displayhook` calls.
122 """
122 """
123 # The controller provides interactivity with both
123 # The controller provides interactivity with both
124 # stdin and stdout
124 # stdin and stdout
125 #import _process_win32_controller
125 #import _process_win32_controller
126 #_process_win32_controller.system(cmd)
126 #_process_win32_controller.system(cmd)
127
127
128 with AvoidUNCPath() as path:
128 with AvoidUNCPath() as path:
129 if path is not None:
129 if path is not None:
130 cmd = '"pushd %s &&"%s' % (path, cmd)
130 cmd = '"pushd %s &&"%s' % (path, cmd)
131 return process_handler(cmd, _system_body)
131 return process_handler(cmd, _system_body)
132
132
133 def getoutput(cmd):
133 def getoutput(cmd):
134 """Return standard output of executing cmd in a shell.
134 """Return standard output of executing cmd in a shell.
135
135
136 Accepts the same arguments as os.system().
136 Accepts the same arguments as os.system().
137
137
138 Parameters
138 Parameters
139 ----------
139 ----------
140 cmd : str or list
140 cmd : str or list
141 A command to be executed in the system shell.
141 A command to be executed in the system shell.
142
142
143 Returns
143 Returns
144 -------
144 -------
145 stdout : str
145 stdout : str
146 """
146 """
147
147
148 with AvoidUNCPath() as path:
148 with AvoidUNCPath() as path:
149 if path is not None:
149 if path is not None:
150 cmd = '"pushd %s &&"%s' % (path, cmd)
150 cmd = '"pushd %s &&"%s' % (path, cmd)
151 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
151 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
152
152
153 if out is None:
153 if out is None:
154 out = b''
154 out = b''
155 return py3compat.bytes_to_str(out)
155 return py3compat.bytes_to_str(out)
156
156
157 try:
157 try:
158 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
158 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
159 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
159 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
160 CommandLineToArgvW.restype = POINTER(LPCWSTR)
160 CommandLineToArgvW.restype = POINTER(LPCWSTR)
161 LocalFree = ctypes.windll.kernel32.LocalFree
161 LocalFree = ctypes.windll.kernel32.LocalFree
162 LocalFree.res_type = HLOCAL
162 LocalFree.res_type = HLOCAL
163 LocalFree.arg_types = [HLOCAL]
163 LocalFree.arg_types = [HLOCAL]
164
164
165 def arg_split(commandline, posix=False, strict=True):
165 def arg_split(commandline, posix=False, strict=True):
166 """Split a command line's arguments in a shell-like manner.
166 """Split a command line's arguments in a shell-like manner.
167
167
168 This is a special version for windows that use a ctypes call to CommandLineToArgvW
168 This is a special version for windows that use a ctypes call to CommandLineToArgvW
169 to do the argv splitting. The posix paramter is ignored.
169 to do the argv splitting. The posix paramter is ignored.
170
170
171 If strict=False, process_common.arg_split(...strict=False) is used instead.
171 If strict=False, process_common.arg_split(...strict=False) is used instead.
172 """
172 """
173 #CommandLineToArgvW returns path to executable if called with empty string.
173 #CommandLineToArgvW returns path to executable if called with empty string.
174 if commandline.strip() == "":
174 if commandline.strip() == "":
175 return []
175 return []
176 if not strict:
176 if not strict:
177 # not really a cl-arg, fallback on _process_common
177 # not really a cl-arg, fallback on _process_common
178 return py_arg_split(commandline, posix=posix, strict=strict)
178 return py_arg_split(commandline, posix=posix, strict=strict)
179 argvn = c_int()
179 argvn = c_int()
180 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
180 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
181 result_array_type = LPCWSTR * argvn.value
181 result_array_type = LPCWSTR * argvn.value
182 result = [arg for arg in result_array_type.from_address(ctypes.addressof(result_pointer.contents))]
182 result = [arg for arg in result_array_type.from_address(ctypes.addressof(result_pointer.contents))]
183 retval = LocalFree(result_pointer)
183 retval = LocalFree(result_pointer)
184 return result
184 return result
185 except AttributeError:
185 except AttributeError:
186 arg_split = py_arg_split
186 arg_split = py_arg_split
187
187
188 def check_pid(pid):
188 def check_pid(pid):
189 # OpenProcess returns 0 if no such process (of ours) exists
189 # OpenProcess returns 0 if no such process (of ours) exists
190 # positive int otherwise
190 # positive int otherwise
191 return bool(ctypes.windll.kernel32.OpenProcess(1,0,pid))
191 return bool(ctypes.windll.kernel32.OpenProcess(1,0,pid))
@@ -1,576 +1,576 b''
1 """Windows-specific implementation of process utilities with direct WinAPI.
1 """Windows-specific implementation of process utilities with direct WinAPI.
2
2
3 This file is meant to be used by process.py
3 This file is meant to be used by process.py
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2010-2011 The IPython Development Team
7 # Copyright (C) 2010-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13
13
14 # stdlib
14 # stdlib
15 import os, sys, threading
15 import os, sys, threading
16 import ctypes, msvcrt
16 import ctypes, msvcrt
17
17
18 # local imports
18 # local imports
19 from . import py3compat
19 from . import py3compat
20
20
21 # Win32 API types needed for the API calls
21 # Win32 API types needed for the API calls
22 from ctypes import POINTER
22 from ctypes import POINTER
23 from ctypes.wintypes import HANDLE, HLOCAL, LPVOID, WORD, DWORD, BOOL, \
23 from ctypes.wintypes import HANDLE, HLOCAL, LPVOID, WORD, DWORD, BOOL, \
24 ULONG, LPCWSTR
24 ULONG, LPCWSTR
25 LPDWORD = POINTER(DWORD)
25 LPDWORD = POINTER(DWORD)
26 LPHANDLE = POINTER(HANDLE)
26 LPHANDLE = POINTER(HANDLE)
27 ULONG_PTR = POINTER(ULONG)
27 ULONG_PTR = POINTER(ULONG)
28 class SECURITY_ATTRIBUTES(ctypes.Structure):
28 class SECURITY_ATTRIBUTES(ctypes.Structure):
29 _fields_ = [("nLength", DWORD),
29 _fields_ = [("nLength", DWORD),
30 ("lpSecurityDescriptor", LPVOID),
30 ("lpSecurityDescriptor", LPVOID),
31 ("bInheritHandle", BOOL)]
31 ("bInheritHandle", BOOL)]
32 LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
32 LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
33 class STARTUPINFO(ctypes.Structure):
33 class STARTUPINFO(ctypes.Structure):
34 _fields_ = [("cb", DWORD),
34 _fields_ = [("cb", DWORD),
35 ("lpReserved", LPCWSTR),
35 ("lpReserved", LPCWSTR),
36 ("lpDesktop", LPCWSTR),
36 ("lpDesktop", LPCWSTR),
37 ("lpTitle", LPCWSTR),
37 ("lpTitle", LPCWSTR),
38 ("dwX", DWORD),
38 ("dwX", DWORD),
39 ("dwY", DWORD),
39 ("dwY", DWORD),
40 ("dwXSize", DWORD),
40 ("dwXSize", DWORD),
41 ("dwYSize", DWORD),
41 ("dwYSize", DWORD),
42 ("dwXCountChars", DWORD),
42 ("dwXCountChars", DWORD),
43 ("dwYCountChars", DWORD),
43 ("dwYCountChars", DWORD),
44 ("dwFillAttribute", DWORD),
44 ("dwFillAttribute", DWORD),
45 ("dwFlags", DWORD),
45 ("dwFlags", DWORD),
46 ("wShowWindow", WORD),
46 ("wShowWindow", WORD),
47 ("cbReserved2", WORD),
47 ("cbReserved2", WORD),
48 ("lpReserved2", LPVOID),
48 ("lpReserved2", LPVOID),
49 ("hStdInput", HANDLE),
49 ("hStdInput", HANDLE),
50 ("hStdOutput", HANDLE),
50 ("hStdOutput", HANDLE),
51 ("hStdError", HANDLE)]
51 ("hStdError", HANDLE)]
52 LPSTARTUPINFO = POINTER(STARTUPINFO)
52 LPSTARTUPINFO = POINTER(STARTUPINFO)
53 class PROCESS_INFORMATION(ctypes.Structure):
53 class PROCESS_INFORMATION(ctypes.Structure):
54 _fields_ = [("hProcess", HANDLE),
54 _fields_ = [("hProcess", HANDLE),
55 ("hThread", HANDLE),
55 ("hThread", HANDLE),
56 ("dwProcessId", DWORD),
56 ("dwProcessId", DWORD),
57 ("dwThreadId", DWORD)]
57 ("dwThreadId", DWORD)]
58 LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
58 LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
59
59
60 # Win32 API constants needed
60 # Win32 API constants needed
61 ERROR_HANDLE_EOF = 38
61 ERROR_HANDLE_EOF = 38
62 ERROR_BROKEN_PIPE = 109
62 ERROR_BROKEN_PIPE = 109
63 ERROR_NO_DATA = 232
63 ERROR_NO_DATA = 232
64 HANDLE_FLAG_INHERIT = 0x0001
64 HANDLE_FLAG_INHERIT = 0x0001
65 STARTF_USESTDHANDLES = 0x0100
65 STARTF_USESTDHANDLES = 0x0100
66 CREATE_SUSPENDED = 0x0004
66 CREATE_SUSPENDED = 0x0004
67 CREATE_NEW_CONSOLE = 0x0010
67 CREATE_NEW_CONSOLE = 0x0010
68 CREATE_NO_WINDOW = 0x08000000
68 CREATE_NO_WINDOW = 0x08000000
69 STILL_ACTIVE = 259
69 STILL_ACTIVE = 259
70 WAIT_TIMEOUT = 0x0102
70 WAIT_TIMEOUT = 0x0102
71 WAIT_FAILED = 0xFFFFFFFF
71 WAIT_FAILED = 0xFFFFFFFF
72 INFINITE = 0xFFFFFFFF
72 INFINITE = 0xFFFFFFFF
73 DUPLICATE_SAME_ACCESS = 0x00000002
73 DUPLICATE_SAME_ACCESS = 0x00000002
74 ENABLE_ECHO_INPUT = 0x0004
74 ENABLE_ECHO_INPUT = 0x0004
75 ENABLE_LINE_INPUT = 0x0002
75 ENABLE_LINE_INPUT = 0x0002
76 ENABLE_PROCESSED_INPUT = 0x0001
76 ENABLE_PROCESSED_INPUT = 0x0001
77
77
78 # Win32 API functions needed
78 # Win32 API functions needed
79 GetLastError = ctypes.windll.kernel32.GetLastError
79 GetLastError = ctypes.windll.kernel32.GetLastError
80 GetLastError.argtypes = []
80 GetLastError.argtypes = []
81 GetLastError.restype = DWORD
81 GetLastError.restype = DWORD
82
82
83 CreateFile = ctypes.windll.kernel32.CreateFileW
83 CreateFile = ctypes.windll.kernel32.CreateFileW
84 CreateFile.argtypes = [LPCWSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE]
84 CreateFile.argtypes = [LPCWSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE]
85 CreateFile.restype = HANDLE
85 CreateFile.restype = HANDLE
86
86
87 CreatePipe = ctypes.windll.kernel32.CreatePipe
87 CreatePipe = ctypes.windll.kernel32.CreatePipe
88 CreatePipe.argtypes = [POINTER(HANDLE), POINTER(HANDLE),
88 CreatePipe.argtypes = [POINTER(HANDLE), POINTER(HANDLE),
89 LPSECURITY_ATTRIBUTES, DWORD]
89 LPSECURITY_ATTRIBUTES, DWORD]
90 CreatePipe.restype = BOOL
90 CreatePipe.restype = BOOL
91
91
92 CreateProcess = ctypes.windll.kernel32.CreateProcessW
92 CreateProcess = ctypes.windll.kernel32.CreateProcessW
93 CreateProcess.argtypes = [LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES,
93 CreateProcess.argtypes = [LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES,
94 LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFO,
94 LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFO,
95 LPPROCESS_INFORMATION]
95 LPPROCESS_INFORMATION]
96 CreateProcess.restype = BOOL
96 CreateProcess.restype = BOOL
97
97
98 GetExitCodeProcess = ctypes.windll.kernel32.GetExitCodeProcess
98 GetExitCodeProcess = ctypes.windll.kernel32.GetExitCodeProcess
99 GetExitCodeProcess.argtypes = [HANDLE, LPDWORD]
99 GetExitCodeProcess.argtypes = [HANDLE, LPDWORD]
100 GetExitCodeProcess.restype = BOOL
100 GetExitCodeProcess.restype = BOOL
101
101
102 GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
102 GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
103 GetCurrentProcess.argtypes = []
103 GetCurrentProcess.argtypes = []
104 GetCurrentProcess.restype = HANDLE
104 GetCurrentProcess.restype = HANDLE
105
105
106 ResumeThread = ctypes.windll.kernel32.ResumeThread
106 ResumeThread = ctypes.windll.kernel32.ResumeThread
107 ResumeThread.argtypes = [HANDLE]
107 ResumeThread.argtypes = [HANDLE]
108 ResumeThread.restype = DWORD
108 ResumeThread.restype = DWORD
109
109
110 ReadFile = ctypes.windll.kernel32.ReadFile
110 ReadFile = ctypes.windll.kernel32.ReadFile
111 ReadFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID]
111 ReadFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID]
112 ReadFile.restype = BOOL
112 ReadFile.restype = BOOL
113
113
114 WriteFile = ctypes.windll.kernel32.WriteFile
114 WriteFile = ctypes.windll.kernel32.WriteFile
115 WriteFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID]
115 WriteFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID]
116 WriteFile.restype = BOOL
116 WriteFile.restype = BOOL
117
117
118 GetConsoleMode = ctypes.windll.kernel32.GetConsoleMode
118 GetConsoleMode = ctypes.windll.kernel32.GetConsoleMode
119 GetConsoleMode.argtypes = [HANDLE, LPDWORD]
119 GetConsoleMode.argtypes = [HANDLE, LPDWORD]
120 GetConsoleMode.restype = BOOL
120 GetConsoleMode.restype = BOOL
121
121
122 SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode
122 SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode
123 SetConsoleMode.argtypes = [HANDLE, DWORD]
123 SetConsoleMode.argtypes = [HANDLE, DWORD]
124 SetConsoleMode.restype = BOOL
124 SetConsoleMode.restype = BOOL
125
125
126 FlushConsoleInputBuffer = ctypes.windll.kernel32.FlushConsoleInputBuffer
126 FlushConsoleInputBuffer = ctypes.windll.kernel32.FlushConsoleInputBuffer
127 FlushConsoleInputBuffer.argtypes = [HANDLE]
127 FlushConsoleInputBuffer.argtypes = [HANDLE]
128 FlushConsoleInputBuffer.restype = BOOL
128 FlushConsoleInputBuffer.restype = BOOL
129
129
130 WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
130 WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
131 WaitForSingleObject.argtypes = [HANDLE, DWORD]
131 WaitForSingleObject.argtypes = [HANDLE, DWORD]
132 WaitForSingleObject.restype = DWORD
132 WaitForSingleObject.restype = DWORD
133
133
134 DuplicateHandle = ctypes.windll.kernel32.DuplicateHandle
134 DuplicateHandle = ctypes.windll.kernel32.DuplicateHandle
135 DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPHANDLE,
135 DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPHANDLE,
136 DWORD, BOOL, DWORD]
136 DWORD, BOOL, DWORD]
137 DuplicateHandle.restype = BOOL
137 DuplicateHandle.restype = BOOL
138
138
139 SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
139 SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
140 SetHandleInformation.argtypes = [HANDLE, DWORD, DWORD]
140 SetHandleInformation.argtypes = [HANDLE, DWORD, DWORD]
141 SetHandleInformation.restype = BOOL
141 SetHandleInformation.restype = BOOL
142
142
143 CloseHandle = ctypes.windll.kernel32.CloseHandle
143 CloseHandle = ctypes.windll.kernel32.CloseHandle
144 CloseHandle.argtypes = [HANDLE]
144 CloseHandle.argtypes = [HANDLE]
145 CloseHandle.restype = BOOL
145 CloseHandle.restype = BOOL
146
146
147 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
147 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
148 CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(ctypes.c_int)]
148 CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(ctypes.c_int)]
149 CommandLineToArgvW.restype = POINTER(LPCWSTR)
149 CommandLineToArgvW.restype = POINTER(LPCWSTR)
150
150
151 LocalFree = ctypes.windll.kernel32.LocalFree
151 LocalFree = ctypes.windll.kernel32.LocalFree
152 LocalFree.argtypes = [HLOCAL]
152 LocalFree.argtypes = [HLOCAL]
153 LocalFree.restype = HLOCAL
153 LocalFree.restype = HLOCAL
154
154
155 class AvoidUNCPath(object):
155 class AvoidUNCPath(object):
156 """A context manager to protect command execution from UNC paths.
156 """A context manager to protect command execution from UNC paths.
157
157
158 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
158 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
159 This context manager temporarily changes directory to the 'C:' drive on
159 This context manager temporarily changes directory to the 'C:' drive on
160 entering, and restores the original working directory on exit.
160 entering, and restores the original working directory on exit.
161
161
162 The context manager returns the starting working directory *if* it made a
162 The context manager returns the starting working directory *if* it made a
163 change and None otherwise, so that users can apply the necessary adjustment
163 change and None otherwise, so that users can apply the necessary adjustment
164 to their system calls in the event of a change.
164 to their system calls in the event of a change.
165
165
166 Examples
166 Examples
167 --------
167 --------
168 ::
168 ::
169 cmd = 'dir'
169 cmd = 'dir'
170 with AvoidUNCPath() as path:
170 with AvoidUNCPath() as path:
171 if path is not None:
171 if path is not None:
172 cmd = '"pushd %s &&"%s' % (path, cmd)
172 cmd = '"pushd %s &&"%s' % (path, cmd)
173 os.system(cmd)
173 os.system(cmd)
174 """
174 """
175 def __enter__(self):
175 def __enter__(self):
176 self.path = py3compat.getcwd()
176 self.path = os.getcwd()
177 self.is_unc_path = self.path.startswith(r"\\")
177 self.is_unc_path = self.path.startswith(r"\\")
178 if self.is_unc_path:
178 if self.is_unc_path:
179 # change to c drive (as cmd.exe cannot handle UNC addresses)
179 # change to c drive (as cmd.exe cannot handle UNC addresses)
180 os.chdir("C:")
180 os.chdir("C:")
181 return self.path
181 return self.path
182 else:
182 else:
183 # We return None to signal that there was no change in the working
183 # We return None to signal that there was no change in the working
184 # directory
184 # directory
185 return None
185 return None
186
186
187 def __exit__(self, exc_type, exc_value, traceback):
187 def __exit__(self, exc_type, exc_value, traceback):
188 if self.is_unc_path:
188 if self.is_unc_path:
189 os.chdir(self.path)
189 os.chdir(self.path)
190
190
191
191
192 class Win32ShellCommandController(object):
192 class Win32ShellCommandController(object):
193 """Runs a shell command in a 'with' context.
193 """Runs a shell command in a 'with' context.
194
194
195 This implementation is Win32-specific.
195 This implementation is Win32-specific.
196
196
197 Example:
197 Example:
198 # Runs the command interactively with default console stdin/stdout
198 # Runs the command interactively with default console stdin/stdout
199 with ShellCommandController('python -i') as scc:
199 with ShellCommandController('python -i') as scc:
200 scc.run()
200 scc.run()
201
201
202 # Runs the command using the provided functions for stdin/stdout
202 # Runs the command using the provided functions for stdin/stdout
203 def my_stdout_func(s):
203 def my_stdout_func(s):
204 # print or save the string 's'
204 # print or save the string 's'
205 write_to_stdout(s)
205 write_to_stdout(s)
206 def my_stdin_func():
206 def my_stdin_func():
207 # If input is available, return it as a string.
207 # If input is available, return it as a string.
208 if input_available():
208 if input_available():
209 return get_input()
209 return get_input()
210 # If no input available, return None after a short delay to
210 # If no input available, return None after a short delay to
211 # keep from blocking.
211 # keep from blocking.
212 else:
212 else:
213 time.sleep(0.01)
213 time.sleep(0.01)
214 return None
214 return None
215
215
216 with ShellCommandController('python -i') as scc:
216 with ShellCommandController('python -i') as scc:
217 scc.run(my_stdout_func, my_stdin_func)
217 scc.run(my_stdout_func, my_stdin_func)
218 """
218 """
219
219
220 def __init__(self, cmd, mergeout = True):
220 def __init__(self, cmd, mergeout = True):
221 """Initializes the shell command controller.
221 """Initializes the shell command controller.
222
222
223 The cmd is the program to execute, and mergeout is
223 The cmd is the program to execute, and mergeout is
224 whether to blend stdout and stderr into one output
224 whether to blend stdout and stderr into one output
225 in stdout. Merging them together in this fashion more
225 in stdout. Merging them together in this fashion more
226 reliably keeps stdout and stderr in the correct order
226 reliably keeps stdout and stderr in the correct order
227 especially for interactive shell usage.
227 especially for interactive shell usage.
228 """
228 """
229 self.cmd = cmd
229 self.cmd = cmd
230 self.mergeout = mergeout
230 self.mergeout = mergeout
231
231
232 def __enter__(self):
232 def __enter__(self):
233 cmd = self.cmd
233 cmd = self.cmd
234 mergeout = self.mergeout
234 mergeout = self.mergeout
235
235
236 self.hstdout, self.hstdin, self.hstderr = None, None, None
236 self.hstdout, self.hstdin, self.hstderr = None, None, None
237 self.piProcInfo = None
237 self.piProcInfo = None
238 try:
238 try:
239 p_hstdout, c_hstdout, p_hstderr, \
239 p_hstdout, c_hstdout, p_hstderr, \
240 c_hstderr, p_hstdin, c_hstdin = [None]*6
240 c_hstderr, p_hstdin, c_hstdin = [None]*6
241
241
242 # SECURITY_ATTRIBUTES with inherit handle set to True
242 # SECURITY_ATTRIBUTES with inherit handle set to True
243 saAttr = SECURITY_ATTRIBUTES()
243 saAttr = SECURITY_ATTRIBUTES()
244 saAttr.nLength = ctypes.sizeof(saAttr)
244 saAttr.nLength = ctypes.sizeof(saAttr)
245 saAttr.bInheritHandle = True
245 saAttr.bInheritHandle = True
246 saAttr.lpSecurityDescriptor = None
246 saAttr.lpSecurityDescriptor = None
247
247
248 def create_pipe(uninherit):
248 def create_pipe(uninherit):
249 """Creates a Windows pipe, which consists of two handles.
249 """Creates a Windows pipe, which consists of two handles.
250
250
251 The 'uninherit' parameter controls which handle is not
251 The 'uninherit' parameter controls which handle is not
252 inherited by the child process.
252 inherited by the child process.
253 """
253 """
254 handles = HANDLE(), HANDLE()
254 handles = HANDLE(), HANDLE()
255 if not CreatePipe(ctypes.byref(handles[0]),
255 if not CreatePipe(ctypes.byref(handles[0]),
256 ctypes.byref(handles[1]), ctypes.byref(saAttr), 0):
256 ctypes.byref(handles[1]), ctypes.byref(saAttr), 0):
257 raise ctypes.WinError()
257 raise ctypes.WinError()
258 if not SetHandleInformation(handles[uninherit],
258 if not SetHandleInformation(handles[uninherit],
259 HANDLE_FLAG_INHERIT, 0):
259 HANDLE_FLAG_INHERIT, 0):
260 raise ctypes.WinError()
260 raise ctypes.WinError()
261 return handles[0].value, handles[1].value
261 return handles[0].value, handles[1].value
262
262
263 p_hstdout, c_hstdout = create_pipe(uninherit=0)
263 p_hstdout, c_hstdout = create_pipe(uninherit=0)
264 # 'mergeout' signals that stdout and stderr should be merged.
264 # 'mergeout' signals that stdout and stderr should be merged.
265 # We do that by using one pipe for both of them.
265 # We do that by using one pipe for both of them.
266 if mergeout:
266 if mergeout:
267 c_hstderr = HANDLE()
267 c_hstderr = HANDLE()
268 if not DuplicateHandle(GetCurrentProcess(), c_hstdout,
268 if not DuplicateHandle(GetCurrentProcess(), c_hstdout,
269 GetCurrentProcess(), ctypes.byref(c_hstderr),
269 GetCurrentProcess(), ctypes.byref(c_hstderr),
270 0, True, DUPLICATE_SAME_ACCESS):
270 0, True, DUPLICATE_SAME_ACCESS):
271 raise ctypes.WinError()
271 raise ctypes.WinError()
272 else:
272 else:
273 p_hstderr, c_hstderr = create_pipe(uninherit=0)
273 p_hstderr, c_hstderr = create_pipe(uninherit=0)
274 c_hstdin, p_hstdin = create_pipe(uninherit=1)
274 c_hstdin, p_hstdin = create_pipe(uninherit=1)
275
275
276 # Create the process object
276 # Create the process object
277 piProcInfo = PROCESS_INFORMATION()
277 piProcInfo = PROCESS_INFORMATION()
278 siStartInfo = STARTUPINFO()
278 siStartInfo = STARTUPINFO()
279 siStartInfo.cb = ctypes.sizeof(siStartInfo)
279 siStartInfo.cb = ctypes.sizeof(siStartInfo)
280 siStartInfo.hStdInput = c_hstdin
280 siStartInfo.hStdInput = c_hstdin
281 siStartInfo.hStdOutput = c_hstdout
281 siStartInfo.hStdOutput = c_hstdout
282 siStartInfo.hStdError = c_hstderr
282 siStartInfo.hStdError = c_hstderr
283 siStartInfo.dwFlags = STARTF_USESTDHANDLES
283 siStartInfo.dwFlags = STARTF_USESTDHANDLES
284 dwCreationFlags = CREATE_SUSPENDED | CREATE_NO_WINDOW # | CREATE_NEW_CONSOLE
284 dwCreationFlags = CREATE_SUSPENDED | CREATE_NO_WINDOW # | CREATE_NEW_CONSOLE
285
285
286 if not CreateProcess(None,
286 if not CreateProcess(None,
287 u"cmd.exe /c " + cmd,
287 u"cmd.exe /c " + cmd,
288 None, None, True, dwCreationFlags,
288 None, None, True, dwCreationFlags,
289 None, None, ctypes.byref(siStartInfo),
289 None, None, ctypes.byref(siStartInfo),
290 ctypes.byref(piProcInfo)):
290 ctypes.byref(piProcInfo)):
291 raise ctypes.WinError()
291 raise ctypes.WinError()
292
292
293 # Close this process's versions of the child handles
293 # Close this process's versions of the child handles
294 CloseHandle(c_hstdin)
294 CloseHandle(c_hstdin)
295 c_hstdin = None
295 c_hstdin = None
296 CloseHandle(c_hstdout)
296 CloseHandle(c_hstdout)
297 c_hstdout = None
297 c_hstdout = None
298 if c_hstderr is not None:
298 if c_hstderr is not None:
299 CloseHandle(c_hstderr)
299 CloseHandle(c_hstderr)
300 c_hstderr = None
300 c_hstderr = None
301
301
302 # Transfer ownership of the parent handles to the object
302 # Transfer ownership of the parent handles to the object
303 self.hstdin = p_hstdin
303 self.hstdin = p_hstdin
304 p_hstdin = None
304 p_hstdin = None
305 self.hstdout = p_hstdout
305 self.hstdout = p_hstdout
306 p_hstdout = None
306 p_hstdout = None
307 if not mergeout:
307 if not mergeout:
308 self.hstderr = p_hstderr
308 self.hstderr = p_hstderr
309 p_hstderr = None
309 p_hstderr = None
310 self.piProcInfo = piProcInfo
310 self.piProcInfo = piProcInfo
311
311
312 finally:
312 finally:
313 if p_hstdin:
313 if p_hstdin:
314 CloseHandle(p_hstdin)
314 CloseHandle(p_hstdin)
315 if c_hstdin:
315 if c_hstdin:
316 CloseHandle(c_hstdin)
316 CloseHandle(c_hstdin)
317 if p_hstdout:
317 if p_hstdout:
318 CloseHandle(p_hstdout)
318 CloseHandle(p_hstdout)
319 if c_hstdout:
319 if c_hstdout:
320 CloseHandle(c_hstdout)
320 CloseHandle(c_hstdout)
321 if p_hstderr:
321 if p_hstderr:
322 CloseHandle(p_hstderr)
322 CloseHandle(p_hstderr)
323 if c_hstderr:
323 if c_hstderr:
324 CloseHandle(c_hstderr)
324 CloseHandle(c_hstderr)
325
325
326 return self
326 return self
327
327
328 def _stdin_thread(self, handle, hprocess, func, stdout_func):
328 def _stdin_thread(self, handle, hprocess, func, stdout_func):
329 exitCode = DWORD()
329 exitCode = DWORD()
330 bytesWritten = DWORD(0)
330 bytesWritten = DWORD(0)
331 while True:
331 while True:
332 #print("stdin thread loop start")
332 #print("stdin thread loop start")
333 # Get the input string (may be bytes or unicode)
333 # Get the input string (may be bytes or unicode)
334 data = func()
334 data = func()
335
335
336 # None signals to poll whether the process has exited
336 # None signals to poll whether the process has exited
337 if data is None:
337 if data is None:
338 #print("checking for process completion")
338 #print("checking for process completion")
339 if not GetExitCodeProcess(hprocess, ctypes.byref(exitCode)):
339 if not GetExitCodeProcess(hprocess, ctypes.byref(exitCode)):
340 raise ctypes.WinError()
340 raise ctypes.WinError()
341 if exitCode.value != STILL_ACTIVE:
341 if exitCode.value != STILL_ACTIVE:
342 return
342 return
343 # TESTING: Does zero-sized writefile help?
343 # TESTING: Does zero-sized writefile help?
344 if not WriteFile(handle, "", 0,
344 if not WriteFile(handle, "", 0,
345 ctypes.byref(bytesWritten), None):
345 ctypes.byref(bytesWritten), None):
346 raise ctypes.WinError()
346 raise ctypes.WinError()
347 continue
347 continue
348 #print("\nGot str %s\n" % repr(data), file=sys.stderr)
348 #print("\nGot str %s\n" % repr(data), file=sys.stderr)
349
349
350 # Encode the string to the console encoding
350 # Encode the string to the console encoding
351 if isinstance(data, unicode): #FIXME: Python3
351 if isinstance(data, unicode): #FIXME: Python3
352 data = data.encode('utf_8')
352 data = data.encode('utf_8')
353
353
354 # What we have now must be a string of bytes
354 # What we have now must be a string of bytes
355 if not isinstance(data, str): #FIXME: Python3
355 if not isinstance(data, str): #FIXME: Python3
356 raise RuntimeError("internal stdin function string error")
356 raise RuntimeError("internal stdin function string error")
357
357
358 # An empty string signals EOF
358 # An empty string signals EOF
359 if len(data) == 0:
359 if len(data) == 0:
360 return
360 return
361
361
362 # In a windows console, sometimes the input is echoed,
362 # In a windows console, sometimes the input is echoed,
363 # but sometimes not. How do we determine when to do this?
363 # but sometimes not. How do we determine when to do this?
364 stdout_func(data)
364 stdout_func(data)
365 # WriteFile may not accept all the data at once.
365 # WriteFile may not accept all the data at once.
366 # Loop until everything is processed
366 # Loop until everything is processed
367 while len(data) != 0:
367 while len(data) != 0:
368 #print("Calling writefile")
368 #print("Calling writefile")
369 if not WriteFile(handle, data, len(data),
369 if not WriteFile(handle, data, len(data),
370 ctypes.byref(bytesWritten), None):
370 ctypes.byref(bytesWritten), None):
371 # This occurs at exit
371 # This occurs at exit
372 if GetLastError() == ERROR_NO_DATA:
372 if GetLastError() == ERROR_NO_DATA:
373 return
373 return
374 raise ctypes.WinError()
374 raise ctypes.WinError()
375 #print("Called writefile")
375 #print("Called writefile")
376 data = data[bytesWritten.value:]
376 data = data[bytesWritten.value:]
377
377
378 def _stdout_thread(self, handle, func):
378 def _stdout_thread(self, handle, func):
379 # Allocate the output buffer
379 # Allocate the output buffer
380 data = ctypes.create_string_buffer(4096)
380 data = ctypes.create_string_buffer(4096)
381 while True:
381 while True:
382 bytesRead = DWORD(0)
382 bytesRead = DWORD(0)
383 if not ReadFile(handle, data, 4096,
383 if not ReadFile(handle, data, 4096,
384 ctypes.byref(bytesRead), None):
384 ctypes.byref(bytesRead), None):
385 le = GetLastError()
385 le = GetLastError()
386 if le == ERROR_BROKEN_PIPE:
386 if le == ERROR_BROKEN_PIPE:
387 return
387 return
388 else:
388 else:
389 raise ctypes.WinError()
389 raise ctypes.WinError()
390 # FIXME: Python3
390 # FIXME: Python3
391 s = data.value[0:bytesRead.value]
391 s = data.value[0:bytesRead.value]
392 #print("\nv: %s" % repr(s), file=sys.stderr)
392 #print("\nv: %s" % repr(s), file=sys.stderr)
393 func(s.decode('utf_8', 'replace'))
393 func(s.decode('utf_8', 'replace'))
394
394
395 def run(self, stdout_func = None, stdin_func = None, stderr_func = None):
395 def run(self, stdout_func = None, stdin_func = None, stderr_func = None):
396 """Runs the process, using the provided functions for I/O.
396 """Runs the process, using the provided functions for I/O.
397
397
398 The function stdin_func should return strings whenever a
398 The function stdin_func should return strings whenever a
399 character or characters become available.
399 character or characters become available.
400 The functions stdout_func and stderr_func are called whenever
400 The functions stdout_func and stderr_func are called whenever
401 something is printed to stdout or stderr, respectively.
401 something is printed to stdout or stderr, respectively.
402 These functions are called from different threads (but not
402 These functions are called from different threads (but not
403 concurrently, because of the GIL).
403 concurrently, because of the GIL).
404 """
404 """
405 if stdout_func is None and stdin_func is None and stderr_func is None:
405 if stdout_func is None and stdin_func is None and stderr_func is None:
406 return self._run_stdio()
406 return self._run_stdio()
407
407
408 if stderr_func is not None and self.mergeout:
408 if stderr_func is not None and self.mergeout:
409 raise RuntimeError("Shell command was initiated with "
409 raise RuntimeError("Shell command was initiated with "
410 "merged stdin/stdout, but a separate stderr_func "
410 "merged stdin/stdout, but a separate stderr_func "
411 "was provided to the run() method")
411 "was provided to the run() method")
412
412
413 # Create a thread for each input/output handle
413 # Create a thread for each input/output handle
414 stdin_thread = None
414 stdin_thread = None
415 threads = []
415 threads = []
416 if stdin_func:
416 if stdin_func:
417 stdin_thread = threading.Thread(target=self._stdin_thread,
417 stdin_thread = threading.Thread(target=self._stdin_thread,
418 args=(self.hstdin, self.piProcInfo.hProcess,
418 args=(self.hstdin, self.piProcInfo.hProcess,
419 stdin_func, stdout_func))
419 stdin_func, stdout_func))
420 threads.append(threading.Thread(target=self._stdout_thread,
420 threads.append(threading.Thread(target=self._stdout_thread,
421 args=(self.hstdout, stdout_func)))
421 args=(self.hstdout, stdout_func)))
422 if not self.mergeout:
422 if not self.mergeout:
423 if stderr_func is None:
423 if stderr_func is None:
424 stderr_func = stdout_func
424 stderr_func = stdout_func
425 threads.append(threading.Thread(target=self._stdout_thread,
425 threads.append(threading.Thread(target=self._stdout_thread,
426 args=(self.hstderr, stderr_func)))
426 args=(self.hstderr, stderr_func)))
427 # Start the I/O threads and the process
427 # Start the I/O threads and the process
428 if ResumeThread(self.piProcInfo.hThread) == 0xFFFFFFFF:
428 if ResumeThread(self.piProcInfo.hThread) == 0xFFFFFFFF:
429 raise ctypes.WinError()
429 raise ctypes.WinError()
430 if stdin_thread is not None:
430 if stdin_thread is not None:
431 stdin_thread.start()
431 stdin_thread.start()
432 for thread in threads:
432 for thread in threads:
433 thread.start()
433 thread.start()
434 # Wait for the process to complete
434 # Wait for the process to complete
435 if WaitForSingleObject(self.piProcInfo.hProcess, INFINITE) == \
435 if WaitForSingleObject(self.piProcInfo.hProcess, INFINITE) == \
436 WAIT_FAILED:
436 WAIT_FAILED:
437 raise ctypes.WinError()
437 raise ctypes.WinError()
438 # Wait for the I/O threads to complete
438 # Wait for the I/O threads to complete
439 for thread in threads:
439 for thread in threads:
440 thread.join()
440 thread.join()
441
441
442 # Wait for the stdin thread to complete
442 # Wait for the stdin thread to complete
443 if stdin_thread is not None:
443 if stdin_thread is not None:
444 stdin_thread.join()
444 stdin_thread.join()
445
445
446 def _stdin_raw_nonblock(self):
446 def _stdin_raw_nonblock(self):
447 """Use the raw Win32 handle of sys.stdin to do non-blocking reads"""
447 """Use the raw Win32 handle of sys.stdin to do non-blocking reads"""
448 # WARNING: This is experimental, and produces inconsistent results.
448 # WARNING: This is experimental, and produces inconsistent results.
449 # It's possible for the handle not to be appropriate for use
449 # It's possible for the handle not to be appropriate for use
450 # with WaitForSingleObject, among other things.
450 # with WaitForSingleObject, among other things.
451 handle = msvcrt.get_osfhandle(sys.stdin.fileno())
451 handle = msvcrt.get_osfhandle(sys.stdin.fileno())
452 result = WaitForSingleObject(handle, 100)
452 result = WaitForSingleObject(handle, 100)
453 if result == WAIT_FAILED:
453 if result == WAIT_FAILED:
454 raise ctypes.WinError()
454 raise ctypes.WinError()
455 elif result == WAIT_TIMEOUT:
455 elif result == WAIT_TIMEOUT:
456 print(".", end='')
456 print(".", end='')
457 return None
457 return None
458 else:
458 else:
459 data = ctypes.create_string_buffer(256)
459 data = ctypes.create_string_buffer(256)
460 bytesRead = DWORD(0)
460 bytesRead = DWORD(0)
461 print('?', end='')
461 print('?', end='')
462
462
463 if not ReadFile(handle, data, 256,
463 if not ReadFile(handle, data, 256,
464 ctypes.byref(bytesRead), None):
464 ctypes.byref(bytesRead), None):
465 raise ctypes.WinError()
465 raise ctypes.WinError()
466 # This ensures the non-blocking works with an actual console
466 # This ensures the non-blocking works with an actual console
467 # Not checking the error, so the processing will still work with
467 # Not checking the error, so the processing will still work with
468 # other handle types
468 # other handle types
469 FlushConsoleInputBuffer(handle)
469 FlushConsoleInputBuffer(handle)
470
470
471 data = data.value
471 data = data.value
472 data = data.replace('\r\n', '\n')
472 data = data.replace('\r\n', '\n')
473 data = data.replace('\r', '\n')
473 data = data.replace('\r', '\n')
474 print(repr(data) + " ", end='')
474 print(repr(data) + " ", end='')
475 return data
475 return data
476
476
477 def _stdin_raw_block(self):
477 def _stdin_raw_block(self):
478 """Use a blocking stdin read"""
478 """Use a blocking stdin read"""
479 # The big problem with the blocking read is that it doesn't
479 # The big problem with the blocking read is that it doesn't
480 # exit when it's supposed to in all contexts. An extra
480 # exit when it's supposed to in all contexts. An extra
481 # key-press may be required to trigger the exit.
481 # key-press may be required to trigger the exit.
482 try:
482 try:
483 data = sys.stdin.read(1)
483 data = sys.stdin.read(1)
484 data = data.replace('\r', '\n')
484 data = data.replace('\r', '\n')
485 return data
485 return data
486 except WindowsError as we:
486 except WindowsError as we:
487 if we.winerror == ERROR_NO_DATA:
487 if we.winerror == ERROR_NO_DATA:
488 # This error occurs when the pipe is closed
488 # This error occurs when the pipe is closed
489 return None
489 return None
490 else:
490 else:
491 # Otherwise let the error propagate
491 # Otherwise let the error propagate
492 raise we
492 raise we
493
493
494 def _stdout_raw(self, s):
494 def _stdout_raw(self, s):
495 """Writes the string to stdout"""
495 """Writes the string to stdout"""
496 print(s, end='', file=sys.stdout)
496 print(s, end='', file=sys.stdout)
497 sys.stdout.flush()
497 sys.stdout.flush()
498
498
499 def _stderr_raw(self, s):
499 def _stderr_raw(self, s):
500 """Writes the string to stdout"""
500 """Writes the string to stdout"""
501 print(s, end='', file=sys.stderr)
501 print(s, end='', file=sys.stderr)
502 sys.stderr.flush()
502 sys.stderr.flush()
503
503
504 def _run_stdio(self):
504 def _run_stdio(self):
505 """Runs the process using the system standard I/O.
505 """Runs the process using the system standard I/O.
506
506
507 IMPORTANT: stdin needs to be asynchronous, so the Python
507 IMPORTANT: stdin needs to be asynchronous, so the Python
508 sys.stdin object is not used. Instead,
508 sys.stdin object is not used. Instead,
509 msvcrt.kbhit/getwch are used asynchronously.
509 msvcrt.kbhit/getwch are used asynchronously.
510 """
510 """
511 # Disable Line and Echo mode
511 # Disable Line and Echo mode
512 #lpMode = DWORD()
512 #lpMode = DWORD()
513 #handle = msvcrt.get_osfhandle(sys.stdin.fileno())
513 #handle = msvcrt.get_osfhandle(sys.stdin.fileno())
514 #if GetConsoleMode(handle, ctypes.byref(lpMode)):
514 #if GetConsoleMode(handle, ctypes.byref(lpMode)):
515 # set_console_mode = True
515 # set_console_mode = True
516 # if not SetConsoleMode(handle, lpMode.value &
516 # if not SetConsoleMode(handle, lpMode.value &
517 # ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)):
517 # ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)):
518 # raise ctypes.WinError()
518 # raise ctypes.WinError()
519
519
520 if self.mergeout:
520 if self.mergeout:
521 return self.run(stdout_func = self._stdout_raw,
521 return self.run(stdout_func = self._stdout_raw,
522 stdin_func = self._stdin_raw_block)
522 stdin_func = self._stdin_raw_block)
523 else:
523 else:
524 return self.run(stdout_func = self._stdout_raw,
524 return self.run(stdout_func = self._stdout_raw,
525 stdin_func = self._stdin_raw_block,
525 stdin_func = self._stdin_raw_block,
526 stderr_func = self._stderr_raw)
526 stderr_func = self._stderr_raw)
527
527
528 # Restore the previous console mode
528 # Restore the previous console mode
529 #if set_console_mode:
529 #if set_console_mode:
530 # if not SetConsoleMode(handle, lpMode.value):
530 # if not SetConsoleMode(handle, lpMode.value):
531 # raise ctypes.WinError()
531 # raise ctypes.WinError()
532
532
533 def __exit__(self, exc_type, exc_value, traceback):
533 def __exit__(self, exc_type, exc_value, traceback):
534 if self.hstdin:
534 if self.hstdin:
535 CloseHandle(self.hstdin)
535 CloseHandle(self.hstdin)
536 self.hstdin = None
536 self.hstdin = None
537 if self.hstdout:
537 if self.hstdout:
538 CloseHandle(self.hstdout)
538 CloseHandle(self.hstdout)
539 self.hstdout = None
539 self.hstdout = None
540 if self.hstderr:
540 if self.hstderr:
541 CloseHandle(self.hstderr)
541 CloseHandle(self.hstderr)
542 self.hstderr = None
542 self.hstderr = None
543 if self.piProcInfo is not None:
543 if self.piProcInfo is not None:
544 CloseHandle(self.piProcInfo.hProcess)
544 CloseHandle(self.piProcInfo.hProcess)
545 CloseHandle(self.piProcInfo.hThread)
545 CloseHandle(self.piProcInfo.hThread)
546 self.piProcInfo = None
546 self.piProcInfo = None
547
547
548
548
549 def system(cmd):
549 def system(cmd):
550 """Win32 version of os.system() that works with network shares.
550 """Win32 version of os.system() that works with network shares.
551
551
552 Note that this implementation returns None, as meant for use in IPython.
552 Note that this implementation returns None, as meant for use in IPython.
553
553
554 Parameters
554 Parameters
555 ----------
555 ----------
556 cmd : str
556 cmd : str
557 A command to be executed in the system shell.
557 A command to be executed in the system shell.
558
558
559 Returns
559 Returns
560 -------
560 -------
561 None : we explicitly do NOT return the subprocess status code, as this
561 None : we explicitly do NOT return the subprocess status code, as this
562 utility is meant to be used extensively in IPython, where any return value
562 utility is meant to be used extensively in IPython, where any return value
563 would trigger :func:`sys.displayhook` calls.
563 would trigger :func:`sys.displayhook` calls.
564 """
564 """
565 with AvoidUNCPath() as path:
565 with AvoidUNCPath() as path:
566 if path is not None:
566 if path is not None:
567 cmd = '"pushd %s &&"%s' % (path, cmd)
567 cmd = '"pushd %s &&"%s' % (path, cmd)
568 with Win32ShellCommandController(cmd) as scc:
568 with Win32ShellCommandController(cmd) as scc:
569 scc.run()
569 scc.run()
570
570
571
571
572 if __name__ == "__main__":
572 if __name__ == "__main__":
573 print("Test starting!")
573 print("Test starting!")
574 #system("cmd")
574 #system("cmd")
575 system("python -i")
575 system("python -i")
576 print("Test finished!")
576 print("Test finished!")
@@ -1,37 +1,36 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Utilities for working with data structures like lists, dicts and tuples.
2 """Utilities for working with data structures like lists, dicts and tuples.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2008-2011 The IPython Development Team
6 # Copyright (C) 2008-2011 The IPython Development Team
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 from .py3compat import xrange
13
12
14 def uniq_stable(elems):
13 def uniq_stable(elems):
15 """uniq_stable(elems) -> list
14 """uniq_stable(elems) -> list
16
15
17 Return from an iterable, a list of all the unique elements in the input,
16 Return from an iterable, a list of all the unique elements in the input,
18 but maintaining the order in which they first appear.
17 but maintaining the order in which they first appear.
19
18
20 Note: All elements in the input must be hashable for this routine
19 Note: All elements in the input must be hashable for this routine
21 to work, as it internally uses a set for efficiency reasons.
20 to work, as it internally uses a set for efficiency reasons.
22 """
21 """
23 seen = set()
22 seen = set()
24 return [x for x in elems if x not in seen and not seen.add(x)]
23 return [x for x in elems if x not in seen and not seen.add(x)]
25
24
26
25
27 def flatten(seq):
26 def flatten(seq):
28 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
27 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
29
28
30 return [x for subseq in seq for x in subseq]
29 return [x for subseq in seq for x in subseq]
31
30
32
31
33 def chop(seq, size):
32 def chop(seq, size):
34 """Chop a sequence into chunks of the given size."""
33 """Chop a sequence into chunks of the given size."""
35 return [seq[i:i+size] for i in xrange(0,len(seq),size)]
34 return [seq[i:i+size] for i in range(0,len(seq),size)]
36
35
37
36
@@ -1,81 +1,80 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A fancy version of Python's builtin :func:`dir` function.
2 """A fancy version of Python's builtin :func:`dir` function.
3 """
3 """
4
4
5 # Copyright (c) IPython Development Team.
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7
7
8 import inspect
8 import inspect
9 from .py3compat import string_types
10
9
11
10
12 def safe_hasattr(obj, attr):
11 def safe_hasattr(obj, attr):
13 """In recent versions of Python, hasattr() only catches AttributeError.
12 """In recent versions of Python, hasattr() only catches AttributeError.
14 This catches all errors.
13 This catches all errors.
15 """
14 """
16 try:
15 try:
17 getattr(obj, attr)
16 getattr(obj, attr)
18 return True
17 return True
19 except:
18 except:
20 return False
19 return False
21
20
22
21
23 def dir2(obj):
22 def dir2(obj):
24 """dir2(obj) -> list of strings
23 """dir2(obj) -> list of strings
25
24
26 Extended version of the Python builtin dir(), which does a few extra
25 Extended version of the Python builtin dir(), which does a few extra
27 checks.
26 checks.
28
27
29 This version is guaranteed to return only a list of true strings, whereas
28 This version is guaranteed to return only a list of true strings, whereas
30 dir() returns anything that objects inject into themselves, even if they
29 dir() returns anything that objects inject into themselves, even if they
31 are later not really valid for attribute access (many extension libraries
30 are later not really valid for attribute access (many extension libraries
32 have such bugs).
31 have such bugs).
33 """
32 """
34
33
35 # Start building the attribute list via dir(), and then complete it
34 # Start building the attribute list via dir(), and then complete it
36 # with a few extra special-purpose calls.
35 # with a few extra special-purpose calls.
37
36
38 try:
37 try:
39 words = set(dir(obj))
38 words = set(dir(obj))
40 except Exception:
39 except Exception:
41 # TypeError: dir(obj) does not return a list
40 # TypeError: dir(obj) does not return a list
42 words = set()
41 words = set()
43
42
44 # filter out non-string attributes which may be stuffed by dir() calls
43 # filter out non-string attributes which may be stuffed by dir() calls
45 # and poor coding in third-party modules
44 # and poor coding in third-party modules
46
45
47 words = [w for w in words if isinstance(w, string_types)]
46 words = [w for w in words if isinstance(w, str)]
48 return sorted(words)
47 return sorted(words)
49
48
50
49
51 def get_real_method(obj, name):
50 def get_real_method(obj, name):
52 """Like getattr, but with a few extra sanity checks:
51 """Like getattr, but with a few extra sanity checks:
53
52
54 - If obj is a class, ignore its methods
53 - If obj is a class, ignore its methods
55 - Check if obj is a proxy that claims to have all attributes
54 - Check if obj is a proxy that claims to have all attributes
56 - Catch attribute access failing with any exception
55 - Catch attribute access failing with any exception
57 - Check that the attribute is a callable object
56 - Check that the attribute is a callable object
58
57
59 Returns the method or None.
58 Returns the method or None.
60 """
59 """
61 if inspect.isclass(obj):
60 if inspect.isclass(obj):
62 return None
61 return None
63
62
64 try:
63 try:
65 canary = getattr(obj, '_ipython_canary_method_should_not_exist_', None)
64 canary = getattr(obj, '_ipython_canary_method_should_not_exist_', None)
66 except Exception:
65 except Exception:
67 return None
66 return None
68
67
69 if canary is not None:
68 if canary is not None:
70 # It claimed to have an attribute it should never have
69 # It claimed to have an attribute it should never have
71 return None
70 return None
72
71
73 try:
72 try:
74 m = getattr(obj, name, None)
73 m = getattr(obj, name, None)
75 except Exception:
74 except Exception:
76 return None
75 return None
77
76
78 if callable(m):
77 if callable(m):
79 return m
78 return m
80
79
81 return None
80 return None
@@ -1,240 +1,240 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IO related utilities.
3 IO related utilities.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9
9
10
10
11 import atexit
11 import atexit
12 import os
12 import os
13 import sys
13 import sys
14 import tempfile
14 import tempfile
15 import warnings
15 import warnings
16 from warnings import warn
16 from warnings import warn
17
17
18 from IPython.utils.decorators import undoc
18 from IPython.utils.decorators import undoc
19 from .capture import CapturedIO, capture_output
19 from .capture import CapturedIO, capture_output
20 from .py3compat import string_types, input, PY3
20 from .py3compat import input, PY3
21
21
22 @undoc
22 @undoc
23 class IOStream:
23 class IOStream:
24
24
25 def __init__(self, stream, fallback=None):
25 def __init__(self, stream, fallback=None):
26 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
26 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
27 DeprecationWarning, stacklevel=2)
27 DeprecationWarning, stacklevel=2)
28 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
28 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
29 if fallback is not None:
29 if fallback is not None:
30 stream = fallback
30 stream = fallback
31 else:
31 else:
32 raise ValueError("fallback required, but not specified")
32 raise ValueError("fallback required, but not specified")
33 self.stream = stream
33 self.stream = stream
34 self._swrite = stream.write
34 self._swrite = stream.write
35
35
36 # clone all methods not overridden:
36 # clone all methods not overridden:
37 def clone(meth):
37 def clone(meth):
38 return not hasattr(self, meth) and not meth.startswith('_')
38 return not hasattr(self, meth) and not meth.startswith('_')
39 for meth in filter(clone, dir(stream)):
39 for meth in filter(clone, dir(stream)):
40 setattr(self, meth, getattr(stream, meth))
40 setattr(self, meth, getattr(stream, meth))
41
41
42 def __repr__(self):
42 def __repr__(self):
43 cls = self.__class__
43 cls = self.__class__
44 tpl = '{mod}.{cls}({args})'
44 tpl = '{mod}.{cls}({args})'
45 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
45 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
46
46
47 def write(self,data):
47 def write(self,data):
48 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
48 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
49 DeprecationWarning, stacklevel=2)
49 DeprecationWarning, stacklevel=2)
50 try:
50 try:
51 self._swrite(data)
51 self._swrite(data)
52 except:
52 except:
53 try:
53 try:
54 # print handles some unicode issues which may trip a plain
54 # print handles some unicode issues which may trip a plain
55 # write() call. Emulate write() by using an empty end
55 # write() call. Emulate write() by using an empty end
56 # argument.
56 # argument.
57 print(data, end='', file=self.stream)
57 print(data, end='', file=self.stream)
58 except:
58 except:
59 # if we get here, something is seriously broken.
59 # if we get here, something is seriously broken.
60 print('ERROR - failed to write data to stream:', self.stream,
60 print('ERROR - failed to write data to stream:', self.stream,
61 file=sys.stderr)
61 file=sys.stderr)
62
62
63 def writelines(self, lines):
63 def writelines(self, lines):
64 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
64 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
65 DeprecationWarning, stacklevel=2)
65 DeprecationWarning, stacklevel=2)
66 if isinstance(lines, string_types):
66 if isinstance(lines, str):
67 lines = [lines]
67 lines = [lines]
68 for line in lines:
68 for line in lines:
69 self.write(line)
69 self.write(line)
70
70
71 # This class used to have a writeln method, but regular files and streams
71 # This class used to have a writeln method, but regular files and streams
72 # in Python don't have this method. We need to keep this completely
72 # in Python don't have this method. We need to keep this completely
73 # compatible so we removed it.
73 # compatible so we removed it.
74
74
75 @property
75 @property
76 def closed(self):
76 def closed(self):
77 return self.stream.closed
77 return self.stream.closed
78
78
79 def close(self):
79 def close(self):
80 pass
80 pass
81
81
82 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
82 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
83 devnull = open(os.devnull, 'w')
83 devnull = open(os.devnull, 'w')
84 atexit.register(devnull.close)
84 atexit.register(devnull.close)
85
85
86 # io.std* are deprecated, but don't show our own deprecation warnings
86 # io.std* are deprecated, but don't show our own deprecation warnings
87 # during initialization of the deprecated API.
87 # during initialization of the deprecated API.
88 with warnings.catch_warnings():
88 with warnings.catch_warnings():
89 warnings.simplefilter('ignore', DeprecationWarning)
89 warnings.simplefilter('ignore', DeprecationWarning)
90 stdin = IOStream(sys.stdin, fallback=devnull)
90 stdin = IOStream(sys.stdin, fallback=devnull)
91 stdout = IOStream(sys.stdout, fallback=devnull)
91 stdout = IOStream(sys.stdout, fallback=devnull)
92 stderr = IOStream(sys.stderr, fallback=devnull)
92 stderr = IOStream(sys.stderr, fallback=devnull)
93
93
94 class Tee(object):
94 class Tee(object):
95 """A class to duplicate an output stream to stdout/err.
95 """A class to duplicate an output stream to stdout/err.
96
96
97 This works in a manner very similar to the Unix 'tee' command.
97 This works in a manner very similar to the Unix 'tee' command.
98
98
99 When the object is closed or deleted, it closes the original file given to
99 When the object is closed or deleted, it closes the original file given to
100 it for duplication.
100 it for duplication.
101 """
101 """
102 # Inspired by:
102 # Inspired by:
103 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
103 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
104
104
105 def __init__(self, file_or_name, mode="w", channel='stdout'):
105 def __init__(self, file_or_name, mode="w", channel='stdout'):
106 """Construct a new Tee object.
106 """Construct a new Tee object.
107
107
108 Parameters
108 Parameters
109 ----------
109 ----------
110 file_or_name : filename or open filehandle (writable)
110 file_or_name : filename or open filehandle (writable)
111 File that will be duplicated
111 File that will be duplicated
112
112
113 mode : optional, valid mode for open().
113 mode : optional, valid mode for open().
114 If a filename was give, open with this mode.
114 If a filename was give, open with this mode.
115
115
116 channel : str, one of ['stdout', 'stderr']
116 channel : str, one of ['stdout', 'stderr']
117 """
117 """
118 if channel not in ['stdout', 'stderr']:
118 if channel not in ['stdout', 'stderr']:
119 raise ValueError('Invalid channel spec %s' % channel)
119 raise ValueError('Invalid channel spec %s' % channel)
120
120
121 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
121 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
122 self.file = file_or_name
122 self.file = file_or_name
123 else:
123 else:
124 self.file = open(file_or_name, mode)
124 self.file = open(file_or_name, mode)
125 self.channel = channel
125 self.channel = channel
126 self.ostream = getattr(sys, channel)
126 self.ostream = getattr(sys, channel)
127 setattr(sys, channel, self)
127 setattr(sys, channel, self)
128 self._closed = False
128 self._closed = False
129
129
130 def close(self):
130 def close(self):
131 """Close the file and restore the channel."""
131 """Close the file and restore the channel."""
132 self.flush()
132 self.flush()
133 setattr(sys, self.channel, self.ostream)
133 setattr(sys, self.channel, self.ostream)
134 self.file.close()
134 self.file.close()
135 self._closed = True
135 self._closed = True
136
136
137 def write(self, data):
137 def write(self, data):
138 """Write data to both channels."""
138 """Write data to both channels."""
139 self.file.write(data)
139 self.file.write(data)
140 self.ostream.write(data)
140 self.ostream.write(data)
141 self.ostream.flush()
141 self.ostream.flush()
142
142
143 def flush(self):
143 def flush(self):
144 """Flush both channels."""
144 """Flush both channels."""
145 self.file.flush()
145 self.file.flush()
146 self.ostream.flush()
146 self.ostream.flush()
147
147
148 def __del__(self):
148 def __del__(self):
149 if not self._closed:
149 if not self._closed:
150 self.close()
150 self.close()
151
151
152
152
153 def ask_yes_no(prompt, default=None, interrupt=None):
153 def ask_yes_no(prompt, default=None, interrupt=None):
154 """Asks a question and returns a boolean (y/n) answer.
154 """Asks a question and returns a boolean (y/n) answer.
155
155
156 If default is given (one of 'y','n'), it is used if the user input is
156 If default is given (one of 'y','n'), it is used if the user input is
157 empty. If interrupt is given (one of 'y','n'), it is used if the user
157 empty. If interrupt is given (one of 'y','n'), it is used if the user
158 presses Ctrl-C. Otherwise the question is repeated until an answer is
158 presses Ctrl-C. Otherwise the question is repeated until an answer is
159 given.
159 given.
160
160
161 An EOF is treated as the default answer. If there is no default, an
161 An EOF is treated as the default answer. If there is no default, an
162 exception is raised to prevent infinite loops.
162 exception is raised to prevent infinite loops.
163
163
164 Valid answers are: y/yes/n/no (match is not case sensitive)."""
164 Valid answers are: y/yes/n/no (match is not case sensitive)."""
165
165
166 answers = {'y':True,'n':False,'yes':True,'no':False}
166 answers = {'y':True,'n':False,'yes':True,'no':False}
167 ans = None
167 ans = None
168 while ans not in answers.keys():
168 while ans not in answers.keys():
169 try:
169 try:
170 ans = input(prompt+' ').lower()
170 ans = input(prompt+' ').lower()
171 if not ans: # response was an empty string
171 if not ans: # response was an empty string
172 ans = default
172 ans = default
173 except KeyboardInterrupt:
173 except KeyboardInterrupt:
174 if interrupt:
174 if interrupt:
175 ans = interrupt
175 ans = interrupt
176 print("\r")
176 print("\r")
177 except EOFError:
177 except EOFError:
178 if default in answers.keys():
178 if default in answers.keys():
179 ans = default
179 ans = default
180 print()
180 print()
181 else:
181 else:
182 raise
182 raise
183
183
184 return answers[ans]
184 return answers[ans]
185
185
186
186
187 def temp_pyfile(src, ext='.py'):
187 def temp_pyfile(src, ext='.py'):
188 """Make a temporary python file, return filename and filehandle.
188 """Make a temporary python file, return filename and filehandle.
189
189
190 Parameters
190 Parameters
191 ----------
191 ----------
192 src : string or list of strings (no need for ending newlines if list)
192 src : string or list of strings (no need for ending newlines if list)
193 Source code to be written to the file.
193 Source code to be written to the file.
194
194
195 ext : optional, string
195 ext : optional, string
196 Extension for the generated file.
196 Extension for the generated file.
197
197
198 Returns
198 Returns
199 -------
199 -------
200 (filename, open filehandle)
200 (filename, open filehandle)
201 It is the caller's responsibility to close the open file and unlink it.
201 It is the caller's responsibility to close the open file and unlink it.
202 """
202 """
203 fname = tempfile.mkstemp(ext)[1]
203 fname = tempfile.mkstemp(ext)[1]
204 f = open(fname,'w')
204 f = open(fname,'w')
205 f.write(src)
205 f.write(src)
206 f.flush()
206 f.flush()
207 return fname, f
207 return fname, f
208
208
209 def atomic_writing(*args, **kwargs):
209 def atomic_writing(*args, **kwargs):
210 """DEPRECATED: moved to notebook.services.contents.fileio"""
210 """DEPRECATED: moved to notebook.services.contents.fileio"""
211 warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio", stacklevel=2)
211 warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio", stacklevel=2)
212 from notebook.services.contents.fileio import atomic_writing
212 from notebook.services.contents.fileio import atomic_writing
213 return atomic_writing(*args, **kwargs)
213 return atomic_writing(*args, **kwargs)
214
214
215 def raw_print(*args, **kw):
215 def raw_print(*args, **kw):
216 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
216 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
217
217
218 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
218 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
219 file=sys.__stdout__)
219 file=sys.__stdout__)
220 sys.__stdout__.flush()
220 sys.__stdout__.flush()
221
221
222
222
223 def raw_print_err(*args, **kw):
223 def raw_print_err(*args, **kw):
224 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
224 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
225
225
226 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
226 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
227 file=sys.__stderr__)
227 file=sys.__stderr__)
228 sys.__stderr__.flush()
228 sys.__stderr__.flush()
229
229
230
230
231 # Short aliases for quick debugging, do NOT use these in production code.
231 # Short aliases for quick debugging, do NOT use these in production code.
232 rprint = raw_print
232 rprint = raw_print
233 rprinte = raw_print_err
233 rprinte = raw_print_err
234
234
235
235
236 def unicode_std_stream(stream='stdout'):
236 def unicode_std_stream(stream='stdout'):
237 """DEPRECATED, moved to nbconvert.utils.io"""
237 """DEPRECATED, moved to nbconvert.utils.io"""
238 warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io", stacklevel=2)
238 warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io", stacklevel=2)
239 from nbconvert.utils.io import unicode_std_stream
239 from nbconvert.utils.io import unicode_std_stream
240 return unicode_std_stream(stream)
240 return unicode_std_stream(stream)
@@ -1,248 +1,247 b''
1 """
1 """
2 Tools to open .py files as Unicode, using the encoding specified within the file,
2 Tools to open .py files as Unicode, using the encoding specified within the file,
3 as per PEP 263.
3 as per PEP 263.
4
4
5 Much of the code is taken from the tokenize module in Python 3.2.
5 Much of the code is taken from the tokenize module in Python 3.2.
6 """
6 """
7
7
8 import io
8 import io
9 from io import TextIOWrapper, BytesIO
9 from io import TextIOWrapper, BytesIO
10 import os.path
10 import os.path
11 import re
11 import re
12
12
13 from .py3compat import unicode_type
14
13
15 cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
14 cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)", re.UNICODE)
16 cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
15 cookie_comment_re = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
17
16
18 try:
17 try:
19 # Available in Python 3
18 # Available in Python 3
20 from tokenize import detect_encoding
19 from tokenize import detect_encoding
21 except ImportError:
20 except ImportError:
22 from codecs import lookup, BOM_UTF8
21 from codecs import lookup, BOM_UTF8
23
22
24 # Copied from Python 3.2 tokenize
23 # Copied from Python 3.2 tokenize
25 def _get_normal_name(orig_enc):
24 def _get_normal_name(orig_enc):
26 """Imitates get_normal_name in tokenizer.c."""
25 """Imitates get_normal_name in tokenizer.c."""
27 # Only care about the first 12 characters.
26 # Only care about the first 12 characters.
28 enc = orig_enc[:12].lower().replace("_", "-")
27 enc = orig_enc[:12].lower().replace("_", "-")
29 if enc == "utf-8" or enc.startswith("utf-8-"):
28 if enc == "utf-8" or enc.startswith("utf-8-"):
30 return "utf-8"
29 return "utf-8"
31 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
30 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
32 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
31 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
33 return "iso-8859-1"
32 return "iso-8859-1"
34 return orig_enc
33 return orig_enc
35
34
36 # Copied from Python 3.2 tokenize
35 # Copied from Python 3.2 tokenize
37 def detect_encoding(readline):
36 def detect_encoding(readline):
38 """
37 """
39 The detect_encoding() function is used to detect the encoding that should
38 The detect_encoding() function is used to detect the encoding that should
40 be used to decode a Python source file. It requires one argment, readline,
39 be used to decode a Python source file. It requires one argment, readline,
41 in the same way as the tokenize() generator.
40 in the same way as the tokenize() generator.
42
41
43 It will call readline a maximum of twice, and return the encoding used
42 It will call readline a maximum of twice, and return the encoding used
44 (as a string) and a list of any lines (left as bytes) it has read in.
43 (as a string) and a list of any lines (left as bytes) it has read in.
45
44
46 It detects the encoding from the presence of a utf-8 bom or an encoding
45 It detects the encoding from the presence of a utf-8 bom or an encoding
47 cookie as specified in pep-0263. If both a bom and a cookie are present,
46 cookie as specified in pep-0263. If both a bom and a cookie are present,
48 but disagree, a SyntaxError will be raised. If the encoding cookie is an
47 but disagree, a SyntaxError will be raised. If the encoding cookie is an
49 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
48 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
50 'utf-8-sig' is returned.
49 'utf-8-sig' is returned.
51
50
52 If no encoding is specified, then the default of 'utf-8' will be returned.
51 If no encoding is specified, then the default of 'utf-8' will be returned.
53 """
52 """
54 bom_found = False
53 bom_found = False
55 encoding = None
54 encoding = None
56 default = 'utf-8'
55 default = 'utf-8'
57 def read_or_stop():
56 def read_or_stop():
58 try:
57 try:
59 return readline()
58 return readline()
60 except StopIteration:
59 except StopIteration:
61 return b''
60 return b''
62
61
63 def find_cookie(line):
62 def find_cookie(line):
64 try:
63 try:
65 line_string = line.decode('ascii')
64 line_string = line.decode('ascii')
66 except UnicodeDecodeError:
65 except UnicodeDecodeError:
67 return None
66 return None
68
67
69 matches = cookie_re.findall(line_string)
68 matches = cookie_re.findall(line_string)
70 if not matches:
69 if not matches:
71 return None
70 return None
72 encoding = _get_normal_name(matches[0])
71 encoding = _get_normal_name(matches[0])
73 try:
72 try:
74 codec = lookup(encoding)
73 codec = lookup(encoding)
75 except LookupError:
74 except LookupError:
76 # This behaviour mimics the Python interpreter
75 # This behaviour mimics the Python interpreter
77 raise SyntaxError("unknown encoding: " + encoding)
76 raise SyntaxError("unknown encoding: " + encoding)
78
77
79 if bom_found:
78 if bom_found:
80 if codec.name != 'utf-8':
79 if codec.name != 'utf-8':
81 # This behaviour mimics the Python interpreter
80 # This behaviour mimics the Python interpreter
82 raise SyntaxError('encoding problem: utf-8')
81 raise SyntaxError('encoding problem: utf-8')
83 encoding += '-sig'
82 encoding += '-sig'
84 return encoding
83 return encoding
85
84
86 first = read_or_stop()
85 first = read_or_stop()
87 if first.startswith(BOM_UTF8):
86 if first.startswith(BOM_UTF8):
88 bom_found = True
87 bom_found = True
89 first = first[3:]
88 first = first[3:]
90 default = 'utf-8-sig'
89 default = 'utf-8-sig'
91 if not first:
90 if not first:
92 return default, []
91 return default, []
93
92
94 encoding = find_cookie(first)
93 encoding = find_cookie(first)
95 if encoding:
94 if encoding:
96 return encoding, [first]
95 return encoding, [first]
97
96
98 second = read_or_stop()
97 second = read_or_stop()
99 if not second:
98 if not second:
100 return default, [first]
99 return default, [first]
101
100
102 encoding = find_cookie(second)
101 encoding = find_cookie(second)
103 if encoding:
102 if encoding:
104 return encoding, [first, second]
103 return encoding, [first, second]
105
104
106 return default, [first, second]
105 return default, [first, second]
107
106
108 try:
107 try:
109 # Available in Python 3.2 and above.
108 # Available in Python 3.2 and above.
110 from tokenize import open
109 from tokenize import open
111 except ImportError:
110 except ImportError:
112 # Copied from Python 3.2 tokenize
111 # Copied from Python 3.2 tokenize
113 def open(filename):
112 def open(filename):
114 """Open a file in read only mode using the encoding detected by
113 """Open a file in read only mode using the encoding detected by
115 detect_encoding().
114 detect_encoding().
116 """
115 """
117 buffer = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
116 buffer = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
118 encoding, lines = detect_encoding(buffer.readline)
117 encoding, lines = detect_encoding(buffer.readline)
119 buffer.seek(0)
118 buffer.seek(0)
120 text = TextIOWrapper(buffer, encoding, line_buffering=True)
119 text = TextIOWrapper(buffer, encoding, line_buffering=True)
121 text.mode = 'r'
120 text.mode = 'r'
122 return text
121 return text
123
122
124 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
123 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
125 """Converts a bytes string with python source code to unicode.
124 """Converts a bytes string with python source code to unicode.
126
125
127 Unicode strings are passed through unchanged. Byte strings are checked
126 Unicode strings are passed through unchanged. Byte strings are checked
128 for the python source file encoding cookie to determine encoding.
127 for the python source file encoding cookie to determine encoding.
129 txt can be either a bytes buffer or a string containing the source
128 txt can be either a bytes buffer or a string containing the source
130 code.
129 code.
131 """
130 """
132 if isinstance(txt, unicode_type):
131 if isinstance(txt, str):
133 return txt
132 return txt
134 if isinstance(txt, bytes):
133 if isinstance(txt, bytes):
135 buffer = BytesIO(txt)
134 buffer = BytesIO(txt)
136 else:
135 else:
137 buffer = txt
136 buffer = txt
138 try:
137 try:
139 encoding, _ = detect_encoding(buffer.readline)
138 encoding, _ = detect_encoding(buffer.readline)
140 except SyntaxError:
139 except SyntaxError:
141 encoding = "ascii"
140 encoding = "ascii"
142 buffer.seek(0)
141 buffer.seek(0)
143 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
142 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
144 text.mode = 'r'
143 text.mode = 'r'
145 if skip_encoding_cookie:
144 if skip_encoding_cookie:
146 return u"".join(strip_encoding_cookie(text))
145 return u"".join(strip_encoding_cookie(text))
147 else:
146 else:
148 return text.read()
147 return text.read()
149
148
150 def strip_encoding_cookie(filelike):
149 def strip_encoding_cookie(filelike):
151 """Generator to pull lines from a text-mode file, skipping the encoding
150 """Generator to pull lines from a text-mode file, skipping the encoding
152 cookie if it is found in the first two lines.
151 cookie if it is found in the first two lines.
153 """
152 """
154 it = iter(filelike)
153 it = iter(filelike)
155 try:
154 try:
156 first = next(it)
155 first = next(it)
157 if not cookie_comment_re.match(first):
156 if not cookie_comment_re.match(first):
158 yield first
157 yield first
159 second = next(it)
158 second = next(it)
160 if not cookie_comment_re.match(second):
159 if not cookie_comment_re.match(second):
161 yield second
160 yield second
162 except StopIteration:
161 except StopIteration:
163 return
162 return
164
163
165 for line in it:
164 for line in it:
166 yield line
165 yield line
167
166
168 def read_py_file(filename, skip_encoding_cookie=True):
167 def read_py_file(filename, skip_encoding_cookie=True):
169 """Read a Python file, using the encoding declared inside the file.
168 """Read a Python file, using the encoding declared inside the file.
170
169
171 Parameters
170 Parameters
172 ----------
171 ----------
173 filename : str
172 filename : str
174 The path to the file to read.
173 The path to the file to read.
175 skip_encoding_cookie : bool
174 skip_encoding_cookie : bool
176 If True (the default), and the encoding declaration is found in the first
175 If True (the default), and the encoding declaration is found in the first
177 two lines, that line will be excluded from the output - compiling a
176 two lines, that line will be excluded from the output - compiling a
178 unicode string with an encoding declaration is a SyntaxError in Python 2.
177 unicode string with an encoding declaration is a SyntaxError in Python 2.
179
178
180 Returns
179 Returns
181 -------
180 -------
182 A unicode string containing the contents of the file.
181 A unicode string containing the contents of the file.
183 """
182 """
184 with open(filename) as f: # the open function defined in this module.
183 with open(filename) as f: # the open function defined in this module.
185 if skip_encoding_cookie:
184 if skip_encoding_cookie:
186 return "".join(strip_encoding_cookie(f))
185 return "".join(strip_encoding_cookie(f))
187 else:
186 else:
188 return f.read()
187 return f.read()
189
188
190 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
189 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
191 """Read a Python file from a URL, using the encoding declared inside the file.
190 """Read a Python file from a URL, using the encoding declared inside the file.
192
191
193 Parameters
192 Parameters
194 ----------
193 ----------
195 url : str
194 url : str
196 The URL from which to fetch the file.
195 The URL from which to fetch the file.
197 errors : str
196 errors : str
198 How to handle decoding errors in the file. Options are the same as for
197 How to handle decoding errors in the file. Options are the same as for
199 bytes.decode(), but here 'replace' is the default.
198 bytes.decode(), but here 'replace' is the default.
200 skip_encoding_cookie : bool
199 skip_encoding_cookie : bool
201 If True (the default), and the encoding declaration is found in the first
200 If True (the default), and the encoding declaration is found in the first
202 two lines, that line will be excluded from the output - compiling a
201 two lines, that line will be excluded from the output - compiling a
203 unicode string with an encoding declaration is a SyntaxError in Python 2.
202 unicode string with an encoding declaration is a SyntaxError in Python 2.
204
203
205 Returns
204 Returns
206 -------
205 -------
207 A unicode string containing the contents of the file.
206 A unicode string containing the contents of the file.
208 """
207 """
209 # Deferred import for faster start
208 # Deferred import for faster start
210 try:
209 try:
211 from urllib.request import urlopen # Py 3
210 from urllib.request import urlopen # Py 3
212 except ImportError:
211 except ImportError:
213 from urllib import urlopen
212 from urllib import urlopen
214 response = urlopen(url)
213 response = urlopen(url)
215 buffer = io.BytesIO(response.read())
214 buffer = io.BytesIO(response.read())
216 return source_to_unicode(buffer, errors, skip_encoding_cookie)
215 return source_to_unicode(buffer, errors, skip_encoding_cookie)
217
216
218 def _list_readline(x):
217 def _list_readline(x):
219 """Given a list, returns a readline() function that returns the next element
218 """Given a list, returns a readline() function that returns the next element
220 with each call.
219 with each call.
221 """
220 """
222 x = iter(x)
221 x = iter(x)
223 def readline():
222 def readline():
224 return next(x)
223 return next(x)
225 return readline
224 return readline
226
225
227 # Code for going between .py files and cached .pyc files ----------------------
226 # Code for going between .py files and cached .pyc files ----------------------
228
227
229 try: # Python 3.2, see PEP 3147
228 try: # Python 3.2, see PEP 3147
230 try:
229 try:
231 from importlib.util import source_from_cache, cache_from_source
230 from importlib.util import source_from_cache, cache_from_source
232 except ImportError :
231 except ImportError :
233 ## deprecated since 3.4
232 ## deprecated since 3.4
234 from imp import source_from_cache, cache_from_source
233 from imp import source_from_cache, cache_from_source
235 except ImportError:
234 except ImportError:
236 # Python <= 3.1: .pyc files go next to .py
235 # Python <= 3.1: .pyc files go next to .py
237 def source_from_cache(path):
236 def source_from_cache(path):
238 basename, ext = os.path.splitext(path)
237 basename, ext = os.path.splitext(path)
239 if ext not in ('.pyc', '.pyo'):
238 if ext not in ('.pyc', '.pyo'):
240 raise ValueError('Not a cached Python file extension', ext)
239 raise ValueError('Not a cached Python file extension', ext)
241 # Should we look for .pyw files?
240 # Should we look for .pyw files?
242 return basename + '.py'
241 return basename + '.py'
243
242
244 def cache_from_source(path, debug_override=None):
243 def cache_from_source(path, debug_override=None):
245 if debug_override is None:
244 if debug_override is None:
246 debug_override = __debug__
245 debug_override = __debug__
247 basename, ext = os.path.splitext(path)
246 basename, ext = os.path.splitext(path)
248 return basename + '.pyc' if debug_override else '.pyo'
247 return basename + '.pyc' if debug_override else '.pyo'
@@ -1,447 +1,446 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for path handling.
3 Utilities for path handling.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import errno
11 import errno
12 import shutil
12 import shutil
13 import random
13 import random
14 import glob
14 import glob
15 from warnings import warn
15 from warnings import warn
16 from hashlib import md5
16 from hashlib import md5
17
17
18 from IPython.utils.process import system
18 from IPython.utils.process import system
19 from IPython.utils import py3compat
19 from IPython.utils import py3compat
20 from IPython.utils.decorators import undoc
20 from IPython.utils.decorators import undoc
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Code
23 # Code
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 fs_encoding = sys.getfilesystemencoding()
26 fs_encoding = sys.getfilesystemencoding()
27
27
28 def _writable_dir(path):
28 def _writable_dir(path):
29 """Whether `path` is a directory, to which the user has write access."""
29 """Whether `path` is a directory, to which the user has write access."""
30 return os.path.isdir(path) and os.access(path, os.W_OK)
30 return os.path.isdir(path) and os.access(path, os.W_OK)
31
31
32 if sys.platform == 'win32':
32 if sys.platform == 'win32':
33 def _get_long_path_name(path):
33 def _get_long_path_name(path):
34 """Get a long path name (expand ~) on Windows using ctypes.
34 """Get a long path name (expand ~) on Windows using ctypes.
35
35
36 Examples
36 Examples
37 --------
37 --------
38
38
39 >>> get_long_path_name('c:\\docume~1')
39 >>> get_long_path_name('c:\\docume~1')
40 u'c:\\\\Documents and Settings'
40 u'c:\\\\Documents and Settings'
41
41
42 """
42 """
43 try:
43 try:
44 import ctypes
44 import ctypes
45 except ImportError:
45 except ImportError:
46 raise ImportError('you need to have ctypes installed for this to work')
46 raise ImportError('you need to have ctypes installed for this to work')
47 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
47 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
48 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
48 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
49 ctypes.c_uint ]
49 ctypes.c_uint ]
50
50
51 buf = ctypes.create_unicode_buffer(260)
51 buf = ctypes.create_unicode_buffer(260)
52 rv = _GetLongPathName(path, buf, 260)
52 rv = _GetLongPathName(path, buf, 260)
53 if rv == 0 or rv > 260:
53 if rv == 0 or rv > 260:
54 return path
54 return path
55 else:
55 else:
56 return buf.value
56 return buf.value
57 else:
57 else:
58 def _get_long_path_name(path):
58 def _get_long_path_name(path):
59 """Dummy no-op."""
59 """Dummy no-op."""
60 return path
60 return path
61
61
62
62
63
63
64 def get_long_path_name(path):
64 def get_long_path_name(path):
65 """Expand a path into its long form.
65 """Expand a path into its long form.
66
66
67 On Windows this expands any ~ in the paths. On other platforms, it is
67 On Windows this expands any ~ in the paths. On other platforms, it is
68 a null operation.
68 a null operation.
69 """
69 """
70 return _get_long_path_name(path)
70 return _get_long_path_name(path)
71
71
72
72
73 def unquote_filename(name, win32=(sys.platform=='win32')):
73 def unquote_filename(name, win32=(sys.platform=='win32')):
74 """ On Windows, remove leading and trailing quotes from filenames.
74 """ On Windows, remove leading and trailing quotes from filenames.
75
75
76 This function has been deprecated and should not be used any more:
76 This function has been deprecated and should not be used any more:
77 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
77 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
78 """
78 """
79 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
79 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
80 "be used anymore", DeprecationWarning, stacklevel=2)
80 "be used anymore", DeprecationWarning, stacklevel=2)
81 if win32:
81 if win32:
82 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
82 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
83 name = name[1:-1]
83 name = name[1:-1]
84 return name
84 return name
85
85
86
86
87 def compress_user(path):
87 def compress_user(path):
88 """Reverse of :func:`os.path.expanduser`
88 """Reverse of :func:`os.path.expanduser`
89 """
89 """
90 path = py3compat.unicode_to_str(path, sys.getfilesystemencoding())
91 home = os.path.expanduser('~')
90 home = os.path.expanduser('~')
92 if path.startswith(home):
91 if path.startswith(home):
93 path = "~" + path[len(home):]
92 path = "~" + path[len(home):]
94 return path
93 return path
95
94
96 def get_py_filename(name, force_win32=None):
95 def get_py_filename(name, force_win32=None):
97 """Return a valid python filename in the current directory.
96 """Return a valid python filename in the current directory.
98
97
99 If the given name is not a file, it adds '.py' and searches again.
98 If the given name is not a file, it adds '.py' and searches again.
100 Raises IOError with an informative message if the file isn't found.
99 Raises IOError with an informative message if the file isn't found.
101 """
100 """
102
101
103 name = os.path.expanduser(name)
102 name = os.path.expanduser(name)
104 if force_win32 is not None:
103 if force_win32 is not None:
105 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
104 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
106 "since IPython 5.0 and should not be used anymore",
105 "since IPython 5.0 and should not be used anymore",
107 DeprecationWarning, stacklevel=2)
106 DeprecationWarning, stacklevel=2)
108 if not os.path.isfile(name) and not name.endswith('.py'):
107 if not os.path.isfile(name) and not name.endswith('.py'):
109 name += '.py'
108 name += '.py'
110 if os.path.isfile(name):
109 if os.path.isfile(name):
111 return name
110 return name
112 else:
111 else:
113 raise IOError('File `%r` not found.' % name)
112 raise IOError('File `%r` not found.' % name)
114
113
115
114
116 def filefind(filename, path_dirs=None):
115 def filefind(filename, path_dirs=None):
117 """Find a file by looking through a sequence of paths.
116 """Find a file by looking through a sequence of paths.
118
117
119 This iterates through a sequence of paths looking for a file and returns
118 This iterates through a sequence of paths looking for a file and returns
120 the full, absolute path of the first occurence of the file. If no set of
119 the full, absolute path of the first occurence of the file. If no set of
121 path dirs is given, the filename is tested as is, after running through
120 path dirs is given, the filename is tested as is, after running through
122 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
121 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
123
122
124 filefind('myfile.txt')
123 filefind('myfile.txt')
125
124
126 will find the file in the current working dir, but::
125 will find the file in the current working dir, but::
127
126
128 filefind('~/myfile.txt')
127 filefind('~/myfile.txt')
129
128
130 Will find the file in the users home directory. This function does not
129 Will find the file in the users home directory. This function does not
131 automatically try any paths, such as the cwd or the user's home directory.
130 automatically try any paths, such as the cwd or the user's home directory.
132
131
133 Parameters
132 Parameters
134 ----------
133 ----------
135 filename : str
134 filename : str
136 The filename to look for.
135 The filename to look for.
137 path_dirs : str, None or sequence of str
136 path_dirs : str, None or sequence of str
138 The sequence of paths to look for the file in. If None, the filename
137 The sequence of paths to look for the file in. If None, the filename
139 need to be absolute or be in the cwd. If a string, the string is
138 need to be absolute or be in the cwd. If a string, the string is
140 put into a sequence and the searched. If a sequence, walk through
139 put into a sequence and the searched. If a sequence, walk through
141 each element and join with ``filename``, calling :func:`expandvars`
140 each element and join with ``filename``, calling :func:`expandvars`
142 and :func:`expanduser` before testing for existence.
141 and :func:`expanduser` before testing for existence.
143
142
144 Returns
143 Returns
145 -------
144 -------
146 Raises :exc:`IOError` or returns absolute path to file.
145 Raises :exc:`IOError` or returns absolute path to file.
147 """
146 """
148
147
149 # If paths are quoted, abspath gets confused, strip them...
148 # If paths are quoted, abspath gets confused, strip them...
150 filename = filename.strip('"').strip("'")
149 filename = filename.strip('"').strip("'")
151 # If the input is an absolute path, just check it exists
150 # If the input is an absolute path, just check it exists
152 if os.path.isabs(filename) and os.path.isfile(filename):
151 if os.path.isabs(filename) and os.path.isfile(filename):
153 return filename
152 return filename
154
153
155 if path_dirs is None:
154 if path_dirs is None:
156 path_dirs = ("",)
155 path_dirs = ("",)
157 elif isinstance(path_dirs, py3compat.string_types):
156 elif isinstance(path_dirs, str):
158 path_dirs = (path_dirs,)
157 path_dirs = (path_dirs,)
159
158
160 for path in path_dirs:
159 for path in path_dirs:
161 if path == '.': path = py3compat.getcwd()
160 if path == '.': path = os.getcwd()
162 testname = expand_path(os.path.join(path, filename))
161 testname = expand_path(os.path.join(path, filename))
163 if os.path.isfile(testname):
162 if os.path.isfile(testname):
164 return os.path.abspath(testname)
163 return os.path.abspath(testname)
165
164
166 raise IOError("File %r does not exist in any of the search paths: %r" %
165 raise IOError("File %r does not exist in any of the search paths: %r" %
167 (filename, path_dirs) )
166 (filename, path_dirs) )
168
167
169
168
170 class HomeDirError(Exception):
169 class HomeDirError(Exception):
171 pass
170 pass
172
171
173
172
174 def get_home_dir(require_writable=False):
173 def get_home_dir(require_writable=False):
175 """Return the 'home' directory, as a unicode string.
174 """Return the 'home' directory, as a unicode string.
176
175
177 Uses os.path.expanduser('~'), and checks for writability.
176 Uses os.path.expanduser('~'), and checks for writability.
178
177
179 See stdlib docs for how this is determined.
178 See stdlib docs for how this is determined.
180 $HOME is first priority on *ALL* platforms.
179 $HOME is first priority on *ALL* platforms.
181
180
182 Parameters
181 Parameters
183 ----------
182 ----------
184
183
185 require_writable : bool [default: False]
184 require_writable : bool [default: False]
186 if True:
185 if True:
187 guarantees the return value is a writable directory, otherwise
186 guarantees the return value is a writable directory, otherwise
188 raises HomeDirError
187 raises HomeDirError
189 if False:
188 if False:
190 The path is resolved, but it is not guaranteed to exist or be writable.
189 The path is resolved, but it is not guaranteed to exist or be writable.
191 """
190 """
192
191
193 homedir = os.path.expanduser('~')
192 homedir = os.path.expanduser('~')
194 # Next line will make things work even when /home/ is a symlink to
193 # Next line will make things work even when /home/ is a symlink to
195 # /usr/home as it is on FreeBSD, for example
194 # /usr/home as it is on FreeBSD, for example
196 homedir = os.path.realpath(homedir)
195 homedir = os.path.realpath(homedir)
197
196
198 if not _writable_dir(homedir) and os.name == 'nt':
197 if not _writable_dir(homedir) and os.name == 'nt':
199 # expanduser failed, use the registry to get the 'My Documents' folder.
198 # expanduser failed, use the registry to get the 'My Documents' folder.
200 try:
199 try:
201 try:
200 try:
202 import winreg as wreg # Py 3
201 import winreg as wreg # Py 3
203 except ImportError:
202 except ImportError:
204 import _winreg as wreg # Py 2
203 import _winreg as wreg # Py 2
205 key = wreg.OpenKey(
204 key = wreg.OpenKey(
206 wreg.HKEY_CURRENT_USER,
205 wreg.HKEY_CURRENT_USER,
207 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
206 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
208 )
207 )
209 homedir = wreg.QueryValueEx(key,'Personal')[0]
208 homedir = wreg.QueryValueEx(key,'Personal')[0]
210 key.Close()
209 key.Close()
211 except:
210 except:
212 pass
211 pass
213
212
214 if (not require_writable) or _writable_dir(homedir):
213 if (not require_writable) or _writable_dir(homedir):
215 return py3compat.cast_unicode(homedir, fs_encoding)
214 return py3compat.cast_unicode(homedir, fs_encoding)
216 else:
215 else:
217 raise HomeDirError('%s is not a writable dir, '
216 raise HomeDirError('%s is not a writable dir, '
218 'set $HOME environment variable to override' % homedir)
217 'set $HOME environment variable to override' % homedir)
219
218
220 def get_xdg_dir():
219 def get_xdg_dir():
221 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
220 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
222
221
223 This is only for non-OS X posix (Linux,Unix,etc.) systems.
222 This is only for non-OS X posix (Linux,Unix,etc.) systems.
224 """
223 """
225
224
226 env = os.environ
225 env = os.environ
227
226
228 if os.name == 'posix' and sys.platform != 'darwin':
227 if os.name == 'posix' and sys.platform != 'darwin':
229 # Linux, Unix, AIX, etc.
228 # Linux, Unix, AIX, etc.
230 # use ~/.config if empty OR not set
229 # use ~/.config if empty OR not set
231 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
230 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
232 if xdg and _writable_dir(xdg):
231 if xdg and _writable_dir(xdg):
233 return py3compat.cast_unicode(xdg, fs_encoding)
232 return py3compat.cast_unicode(xdg, fs_encoding)
234
233
235 return None
234 return None
236
235
237
236
238 def get_xdg_cache_dir():
237 def get_xdg_cache_dir():
239 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
238 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
240
239
241 This is only for non-OS X posix (Linux,Unix,etc.) systems.
240 This is only for non-OS X posix (Linux,Unix,etc.) systems.
242 """
241 """
243
242
244 env = os.environ
243 env = os.environ
245
244
246 if os.name == 'posix' and sys.platform != 'darwin':
245 if os.name == 'posix' and sys.platform != 'darwin':
247 # Linux, Unix, AIX, etc.
246 # Linux, Unix, AIX, etc.
248 # use ~/.cache if empty OR not set
247 # use ~/.cache if empty OR not set
249 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
248 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
250 if xdg and _writable_dir(xdg):
249 if xdg and _writable_dir(xdg):
251 return py3compat.cast_unicode(xdg, fs_encoding)
250 return py3compat.cast_unicode(xdg, fs_encoding)
252
251
253 return None
252 return None
254
253
255
254
256 @undoc
255 @undoc
257 def get_ipython_dir():
256 def get_ipython_dir():
258 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
257 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
259 from IPython.paths import get_ipython_dir
258 from IPython.paths import get_ipython_dir
260 return get_ipython_dir()
259 return get_ipython_dir()
261
260
262 @undoc
261 @undoc
263 def get_ipython_cache_dir():
262 def get_ipython_cache_dir():
264 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
263 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
265 from IPython.paths import get_ipython_cache_dir
264 from IPython.paths import get_ipython_cache_dir
266 return get_ipython_cache_dir()
265 return get_ipython_cache_dir()
267
266
268 @undoc
267 @undoc
269 def get_ipython_package_dir():
268 def get_ipython_package_dir():
270 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
269 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
271 from IPython.paths import get_ipython_package_dir
270 from IPython.paths import get_ipython_package_dir
272 return get_ipython_package_dir()
271 return get_ipython_package_dir()
273
272
274 @undoc
273 @undoc
275 def get_ipython_module_path(module_str):
274 def get_ipython_module_path(module_str):
276 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
275 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
277 from IPython.paths import get_ipython_module_path
276 from IPython.paths import get_ipython_module_path
278 return get_ipython_module_path(module_str)
277 return get_ipython_module_path(module_str)
279
278
280 @undoc
279 @undoc
281 def locate_profile(profile='default'):
280 def locate_profile(profile='default'):
282 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
281 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
283 from IPython.paths import locate_profile
282 from IPython.paths import locate_profile
284 return locate_profile(profile=profile)
283 return locate_profile(profile=profile)
285
284
286 def expand_path(s):
285 def expand_path(s):
287 """Expand $VARS and ~names in a string, like a shell
286 """Expand $VARS and ~names in a string, like a shell
288
287
289 :Examples:
288 :Examples:
290
289
291 In [2]: os.environ['FOO']='test'
290 In [2]: os.environ['FOO']='test'
292
291
293 In [3]: expand_path('variable FOO is $FOO')
292 In [3]: expand_path('variable FOO is $FOO')
294 Out[3]: 'variable FOO is test'
293 Out[3]: 'variable FOO is test'
295 """
294 """
296 # This is a pretty subtle hack. When expand user is given a UNC path
295 # This is a pretty subtle hack. When expand user is given a UNC path
297 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
296 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
298 # the $ to get (\\server\share\%username%). I think it considered $
297 # the $ to get (\\server\share\%username%). I think it considered $
299 # alone an empty var. But, we need the $ to remains there (it indicates
298 # alone an empty var. But, we need the $ to remains there (it indicates
300 # a hidden share).
299 # a hidden share).
301 if os.name=='nt':
300 if os.name=='nt':
302 s = s.replace('$\\', 'IPYTHON_TEMP')
301 s = s.replace('$\\', 'IPYTHON_TEMP')
303 s = os.path.expandvars(os.path.expanduser(s))
302 s = os.path.expandvars(os.path.expanduser(s))
304 if os.name=='nt':
303 if os.name=='nt':
305 s = s.replace('IPYTHON_TEMP', '$\\')
304 s = s.replace('IPYTHON_TEMP', '$\\')
306 return s
305 return s
307
306
308
307
309 def unescape_glob(string):
308 def unescape_glob(string):
310 """Unescape glob pattern in `string`."""
309 """Unescape glob pattern in `string`."""
311 def unescape(s):
310 def unescape(s):
312 for pattern in '*[]!?':
311 for pattern in '*[]!?':
313 s = s.replace(r'\{0}'.format(pattern), pattern)
312 s = s.replace(r'\{0}'.format(pattern), pattern)
314 return s
313 return s
315 return '\\'.join(map(unescape, string.split('\\\\')))
314 return '\\'.join(map(unescape, string.split('\\\\')))
316
315
317
316
318 def shellglob(args):
317 def shellglob(args):
319 """
318 """
320 Do glob expansion for each element in `args` and return a flattened list.
319 Do glob expansion for each element in `args` and return a flattened list.
321
320
322 Unmatched glob pattern will remain as-is in the returned list.
321 Unmatched glob pattern will remain as-is in the returned list.
323
322
324 """
323 """
325 expanded = []
324 expanded = []
326 # Do not unescape backslash in Windows as it is interpreted as
325 # Do not unescape backslash in Windows as it is interpreted as
327 # path separator:
326 # path separator:
328 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
327 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
329 for a in args:
328 for a in args:
330 expanded.extend(glob.glob(a) or [unescape(a)])
329 expanded.extend(glob.glob(a) or [unescape(a)])
331 return expanded
330 return expanded
332
331
333
332
334 def target_outdated(target,deps):
333 def target_outdated(target,deps):
335 """Determine whether a target is out of date.
334 """Determine whether a target is out of date.
336
335
337 target_outdated(target,deps) -> 1/0
336 target_outdated(target,deps) -> 1/0
338
337
339 deps: list of filenames which MUST exist.
338 deps: list of filenames which MUST exist.
340 target: single filename which may or may not exist.
339 target: single filename which may or may not exist.
341
340
342 If target doesn't exist or is older than any file listed in deps, return
341 If target doesn't exist or is older than any file listed in deps, return
343 true, otherwise return false.
342 true, otherwise return false.
344 """
343 """
345 try:
344 try:
346 target_time = os.path.getmtime(target)
345 target_time = os.path.getmtime(target)
347 except os.error:
346 except os.error:
348 return 1
347 return 1
349 for dep in deps:
348 for dep in deps:
350 dep_time = os.path.getmtime(dep)
349 dep_time = os.path.getmtime(dep)
351 if dep_time > target_time:
350 if dep_time > target_time:
352 #print "For target",target,"Dep failed:",dep # dbg
351 #print "For target",target,"Dep failed:",dep # dbg
353 #print "times (dep,tar):",dep_time,target_time # dbg
352 #print "times (dep,tar):",dep_time,target_time # dbg
354 return 1
353 return 1
355 return 0
354 return 0
356
355
357
356
358 def target_update(target,deps,cmd):
357 def target_update(target,deps,cmd):
359 """Update a target with a given command given a list of dependencies.
358 """Update a target with a given command given a list of dependencies.
360
359
361 target_update(target,deps,cmd) -> runs cmd if target is outdated.
360 target_update(target,deps,cmd) -> runs cmd if target is outdated.
362
361
363 This is just a wrapper around target_outdated() which calls the given
362 This is just a wrapper around target_outdated() which calls the given
364 command if target is outdated."""
363 command if target is outdated."""
365
364
366 if target_outdated(target,deps):
365 if target_outdated(target,deps):
367 system(cmd)
366 system(cmd)
368
367
369 @undoc
368 @undoc
370 def filehash(path):
369 def filehash(path):
371 """Make an MD5 hash of a file, ignoring any differences in line
370 """Make an MD5 hash of a file, ignoring any differences in line
372 ending characters."""
371 ending characters."""
373 warn("filehash() is deprecated since IPython 4.0", DeprecationWarning, stacklevel=2)
372 warn("filehash() is deprecated since IPython 4.0", DeprecationWarning, stacklevel=2)
374 with open(path, "rU") as f:
373 with open(path, "rU") as f:
375 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
374 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
376
375
377 ENOLINK = 1998
376 ENOLINK = 1998
378
377
379 def link(src, dst):
378 def link(src, dst):
380 """Hard links ``src`` to ``dst``, returning 0 or errno.
379 """Hard links ``src`` to ``dst``, returning 0 or errno.
381
380
382 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
381 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
383 supported by the operating system.
382 supported by the operating system.
384 """
383 """
385
384
386 if not hasattr(os, "link"):
385 if not hasattr(os, "link"):
387 return ENOLINK
386 return ENOLINK
388 link_errno = 0
387 link_errno = 0
389 try:
388 try:
390 os.link(src, dst)
389 os.link(src, dst)
391 except OSError as e:
390 except OSError as e:
392 link_errno = e.errno
391 link_errno = e.errno
393 return link_errno
392 return link_errno
394
393
395
394
396 def link_or_copy(src, dst):
395 def link_or_copy(src, dst):
397 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
396 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
398
397
399 Attempts to maintain the semantics of ``shutil.copy``.
398 Attempts to maintain the semantics of ``shutil.copy``.
400
399
401 Because ``os.link`` does not overwrite files, a unique temporary file
400 Because ``os.link`` does not overwrite files, a unique temporary file
402 will be used if the target already exists, then that file will be moved
401 will be used if the target already exists, then that file will be moved
403 into place.
402 into place.
404 """
403 """
405
404
406 if os.path.isdir(dst):
405 if os.path.isdir(dst):
407 dst = os.path.join(dst, os.path.basename(src))
406 dst = os.path.join(dst, os.path.basename(src))
408
407
409 link_errno = link(src, dst)
408 link_errno = link(src, dst)
410 if link_errno == errno.EEXIST:
409 if link_errno == errno.EEXIST:
411 if os.stat(src).st_ino == os.stat(dst).st_ino:
410 if os.stat(src).st_ino == os.stat(dst).st_ino:
412 # dst is already a hard link to the correct file, so we don't need
411 # dst is already a hard link to the correct file, so we don't need
413 # to do anything else. If we try to link and rename the file
412 # to do anything else. If we try to link and rename the file
414 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
413 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
415 return
414 return
416
415
417 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
416 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
418 try:
417 try:
419 link_or_copy(src, new_dst)
418 link_or_copy(src, new_dst)
420 except:
419 except:
421 try:
420 try:
422 os.remove(new_dst)
421 os.remove(new_dst)
423 except OSError:
422 except OSError:
424 pass
423 pass
425 raise
424 raise
426 os.rename(new_dst, dst)
425 os.rename(new_dst, dst)
427 elif link_errno != 0:
426 elif link_errno != 0:
428 # Either link isn't supported, or the filesystem doesn't support
427 # Either link isn't supported, or the filesystem doesn't support
429 # linking, or 'src' and 'dst' are on different filesystems.
428 # linking, or 'src' and 'dst' are on different filesystems.
430 shutil.copy(src, dst)
429 shutil.copy(src, dst)
431
430
432 def ensure_dir_exists(path, mode=0o755):
431 def ensure_dir_exists(path, mode=0o755):
433 """ensure that a directory exists
432 """ensure that a directory exists
434
433
435 If it doesn't exist, try to create it and protect against a race condition
434 If it doesn't exist, try to create it and protect against a race condition
436 if another process is doing the same.
435 if another process is doing the same.
437
436
438 The default permissions are 755, which differ from os.makedirs default of 777.
437 The default permissions are 755, which differ from os.makedirs default of 777.
439 """
438 """
440 if not os.path.exists(path):
439 if not os.path.exists(path):
441 try:
440 try:
442 os.makedirs(path, mode=mode)
441 os.makedirs(path, mode=mode)
443 except OSError as e:
442 except OSError as e:
444 if e.errno != errno.EEXIST:
443 if e.errno != errno.EEXIST:
445 raise
444 raise
446 elif not os.path.isdir(path):
445 elif not os.path.isdir(path):
447 raise IOError("%r exists but is not a directory" % path)
446 raise IOError("%r exists but is not a directory" % path)
@@ -1,69 +1,69 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with external processes.
3 Utilities for working with external processes.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9
9
10 import os
10 import os
11 import sys
11 import sys
12
12
13 if sys.platform == 'win32':
13 if sys.platform == 'win32':
14 from ._process_win32 import system, getoutput, arg_split, check_pid
14 from ._process_win32 import system, getoutput, arg_split, check_pid
15 elif sys.platform == 'cli':
15 elif sys.platform == 'cli':
16 from ._process_cli import system, getoutput, arg_split, check_pid
16 from ._process_cli import system, getoutput, arg_split, check_pid
17 else:
17 else:
18 from ._process_posix import system, getoutput, arg_split, check_pid
18 from ._process_posix import system, getoutput, arg_split, check_pid
19
19
20 from ._process_common import getoutputerror, get_output_error_code, process_handler
20 from ._process_common import getoutputerror, get_output_error_code, process_handler
21 from . import py3compat
21 from . import py3compat
22
22
23
23
24 class FindCmdError(Exception):
24 class FindCmdError(Exception):
25 pass
25 pass
26
26
27
27
28 def find_cmd(cmd):
28 def find_cmd(cmd):
29 """Find absolute path to executable cmd in a cross platform manner.
29 """Find absolute path to executable cmd in a cross platform manner.
30
30
31 This function tries to determine the full path to a command line program
31 This function tries to determine the full path to a command line program
32 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
32 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
33 time it will use the version that is first on the users `PATH`.
33 time it will use the version that is first on the users `PATH`.
34
34
35 Warning, don't use this to find IPython command line programs as there
35 Warning, don't use this to find IPython command line programs as there
36 is a risk you will find the wrong one. Instead find those using the
36 is a risk you will find the wrong one. Instead find those using the
37 following code and looking for the application itself::
37 following code and looking for the application itself::
38
38
39 import sys
39 import sys
40 argv = [sys.executable, '-m', 'IPython']
40 argv = [sys.executable, '-m', 'IPython']
41
41
42 Parameters
42 Parameters
43 ----------
43 ----------
44 cmd : str
44 cmd : str
45 The command line program to look for.
45 The command line program to look for.
46 """
46 """
47 path = py3compat.which(cmd)
47 path = py3compat.which(cmd)
48 if path is None:
48 if path is None:
49 raise FindCmdError('command could not be found: %s' % cmd)
49 raise FindCmdError('command could not be found: %s' % cmd)
50 return path
50 return path
51
51
52
52
53 def abbrev_cwd():
53 def abbrev_cwd():
54 """ Return abbreviated version of cwd, e.g. d:mydir """
54 """ Return abbreviated version of cwd, e.g. d:mydir """
55 cwd = py3compat.getcwd().replace('\\','/')
55 cwd = os.getcwd().replace('\\','/')
56 drivepart = ''
56 drivepart = ''
57 tail = cwd
57 tail = cwd
58 if sys.platform == 'win32':
58 if sys.platform == 'win32':
59 if len(cwd) < 4:
59 if len(cwd) < 4:
60 return cwd
60 return cwd
61 drivepart,tail = os.path.splitdrive(cwd)
61 drivepart,tail = os.path.splitdrive(cwd)
62
62
63
63
64 parts = tail.split('/')
64 parts = tail.split('/')
65 if len(parts) > 2:
65 if len(parts) > 2:
66 tail = '/'.join(parts[-2:])
66 tail = '/'.join(parts[-2:])
67
67
68 return (drivepart + (
68 return (drivepart + (
69 cwd == '/' and '/' or tail))
69 cwd == '/' and '/' or tail))
@@ -1,120 +1,120 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with terminals.
3 Utilities for working with terminals.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian E. Granger
7 * Brian E. Granger
8 * Fernando Perez
8 * Fernando Perez
9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
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 os
15 import os
16 import sys
16 import sys
17 import warnings
17 import warnings
18 try:
18 try:
19 from shutil import get_terminal_size as _get_terminal_size
19 from shutil import get_terminal_size as _get_terminal_size
20 except ImportError:
20 except ImportError:
21 # use backport on Python 2
21 # use backport on Python 2
22 from backports.shutil_get_terminal_size import get_terminal_size as _get_terminal_size
22 from backports.shutil_get_terminal_size import get_terminal_size as _get_terminal_size
23
23
24 from . import py3compat
24 from . import py3compat
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Code
27 # Code
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 # This variable is part of the expected API of the module:
30 # This variable is part of the expected API of the module:
31 ignore_termtitle = True
31 ignore_termtitle = True
32
32
33
33
34
34
35 if os.name == 'posix':
35 if os.name == 'posix':
36 def _term_clear():
36 def _term_clear():
37 os.system('clear')
37 os.system('clear')
38 elif sys.platform == 'win32':
38 elif sys.platform == 'win32':
39 def _term_clear():
39 def _term_clear():
40 os.system('cls')
40 os.system('cls')
41 else:
41 else:
42 def _term_clear():
42 def _term_clear():
43 pass
43 pass
44
44
45
45
46
46
47 def toggle_set_term_title(val):
47 def toggle_set_term_title(val):
48 """Control whether set_term_title is active or not.
48 """Control whether set_term_title is active or not.
49
49
50 set_term_title() allows writing to the console titlebar. In embedded
50 set_term_title() allows writing to the console titlebar. In embedded
51 widgets this can cause problems, so this call can be used to toggle it on
51 widgets this can cause problems, so this call can be used to toggle it on
52 or off as needed.
52 or off as needed.
53
53
54 The default state of the module is for the function to be disabled.
54 The default state of the module is for the function to be disabled.
55
55
56 Parameters
56 Parameters
57 ----------
57 ----------
58 val : bool
58 val : bool
59 If True, set_term_title() actually writes to the terminal (using the
59 If True, set_term_title() actually writes to the terminal (using the
60 appropriate platform-specific module). If False, it is a no-op.
60 appropriate platform-specific module). If False, it is a no-op.
61 """
61 """
62 global ignore_termtitle
62 global ignore_termtitle
63 ignore_termtitle = not(val)
63 ignore_termtitle = not(val)
64
64
65
65
66 def _set_term_title(*args,**kw):
66 def _set_term_title(*args,**kw):
67 """Dummy no-op."""
67 """Dummy no-op."""
68 pass
68 pass
69
69
70
70
71 def _set_term_title_xterm(title):
71 def _set_term_title_xterm(title):
72 """ Change virtual terminal title in xterm-workalikes """
72 """ Change virtual terminal title in xterm-workalikes """
73 sys.stdout.write('\033]0;%s\007' % title)
73 sys.stdout.write('\033]0;%s\007' % title)
74
74
75 if os.name == 'posix':
75 if os.name == 'posix':
76 TERM = os.environ.get('TERM','')
76 TERM = os.environ.get('TERM','')
77 if TERM.startswith('xterm'):
77 if TERM.startswith('xterm'):
78 _set_term_title = _set_term_title_xterm
78 _set_term_title = _set_term_title_xterm
79 elif sys.platform == 'win32':
79 elif sys.platform == 'win32':
80 try:
80 try:
81 import ctypes
81 import ctypes
82
82
83 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
83 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
84 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
84 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
85
85
86 def _set_term_title(title):
86 def _set_term_title(title):
87 """Set terminal title using ctypes to access the Win32 APIs."""
87 """Set terminal title using ctypes to access the Win32 APIs."""
88 SetConsoleTitleW(title)
88 SetConsoleTitleW(title)
89 except ImportError:
89 except ImportError:
90 def _set_term_title(title):
90 def _set_term_title(title):
91 """Set terminal title using the 'title' command."""
91 """Set terminal title using the 'title' command."""
92 global ignore_termtitle
92 global ignore_termtitle
93
93
94 try:
94 try:
95 # Cannot be on network share when issuing system commands
95 # Cannot be on network share when issuing system commands
96 curr = py3compat.getcwd()
96 curr = os.getcwd()
97 os.chdir("C:")
97 os.chdir("C:")
98 ret = os.system("title " + title)
98 ret = os.system("title " + title)
99 finally:
99 finally:
100 os.chdir(curr)
100 os.chdir(curr)
101 if ret:
101 if ret:
102 # non-zero return code signals error, don't try again
102 # non-zero return code signals error, don't try again
103 ignore_termtitle = True
103 ignore_termtitle = True
104
104
105
105
106 def set_term_title(title):
106 def set_term_title(title):
107 """Set terminal title using the necessary platform-dependent calls."""
107 """Set terminal title using the necessary platform-dependent calls."""
108 if ignore_termtitle:
108 if ignore_termtitle:
109 return
109 return
110 _set_term_title(title)
110 _set_term_title(title)
111
111
112
112
113 def freeze_term_title():
113 def freeze_term_title():
114 warnings.warn("This function is deprecated, use toggle_set_term_title()")
114 warnings.warn("This function is deprecated, use toggle_set_term_title()")
115 global ignore_termtitle
115 global ignore_termtitle
116 ignore_termtitle = True
116 ignore_termtitle = True
117
117
118
118
119 def get_terminal_size(defaultx=80, defaulty=25):
119 def get_terminal_size(defaultx=80, defaulty=25):
120 return _get_terminal_size((defaultx, defaulty))
120 return _get_terminal_size((defaultx, defaulty))
@@ -1,496 +1,496 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
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 errno
7 import errno
8 import os
8 import os
9 import shutil
9 import shutil
10 import sys
10 import sys
11 import tempfile
11 import tempfile
12 import warnings
12 import warnings
13 from contextlib import contextmanager
13 from contextlib import contextmanager
14
14
15 try: # Python 3.3+
15 try: # Python 3.3+
16 from unittest.mock import patch
16 from unittest.mock import patch
17 except ImportError:
17 except ImportError:
18 from mock import patch
18 from mock import patch
19
19
20 from os.path import join, abspath, split
20 from os.path import join, abspath, split
21
21
22 from nose import SkipTest
22 from nose import SkipTest
23 import nose.tools as nt
23 import nose.tools as nt
24
24
25 from nose import with_setup
25 from nose import with_setup
26
26
27 import IPython
27 import IPython
28 from IPython import paths
28 from IPython import paths
29 from IPython.testing import decorators as dec
29 from IPython.testing import decorators as dec
30 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
30 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
31 onlyif_unicode_paths,)
31 onlyif_unicode_paths,)
32 from IPython.testing.tools import make_tempfile, AssertPrints
32 from IPython.testing.tools import make_tempfile, AssertPrints
33 from IPython.utils import path
33 from IPython.utils import path
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.tempdir import TemporaryDirectory
35 from IPython.utils.tempdir import TemporaryDirectory
36
36
37 # Platform-dependent imports
37 # Platform-dependent imports
38 try:
38 try:
39 import winreg as wreg # Py 3
39 import winreg as wreg # Py 3
40 except ImportError:
40 except ImportError:
41 try:
41 try:
42 import _winreg as wreg # Py 2
42 import _winreg as wreg # Py 2
43 except ImportError:
43 except ImportError:
44 #Fake _winreg module on none windows platforms
44 #Fake _winreg module on none windows platforms
45 import types
45 import types
46 wr_name = "winreg" if py3compat.PY3 else "_winreg"
46 wr_name = "winreg" if py3compat.PY3 else "_winreg"
47 sys.modules[wr_name] = types.ModuleType(wr_name)
47 sys.modules[wr_name] = types.ModuleType(wr_name)
48 try:
48 try:
49 import winreg as wreg
49 import winreg as wreg
50 except ImportError:
50 except ImportError:
51 import _winreg as wreg
51 import _winreg as wreg
52 #Add entries that needs to be stubbed by the testing code
52 #Add entries that needs to be stubbed by the testing code
53 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
53 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
54
54
55 try:
55 try:
56 reload
56 reload
57 except NameError: # Python 3
57 except NameError: # Python 3
58 from imp import reload
58 from imp import reload
59
59
60 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
61 # Globals
61 # Globals
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63 env = os.environ
63 env = os.environ
64 TMP_TEST_DIR = tempfile.mkdtemp()
64 TMP_TEST_DIR = tempfile.mkdtemp()
65 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
65 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
66 #
66 #
67 # Setup/teardown functions/decorators
67 # Setup/teardown functions/decorators
68 #
68 #
69
69
70 def setup():
70 def setup():
71 """Setup testenvironment for the module:
71 """Setup testenvironment for the module:
72
72
73 - Adds dummy home dir tree
73 - Adds dummy home dir tree
74 """
74 """
75 # Do not mask exceptions here. In particular, catching WindowsError is a
75 # Do not mask exceptions here. In particular, catching WindowsError is a
76 # problem because that exception is only defined on Windows...
76 # problem because that exception is only defined on Windows...
77 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
77 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
78
78
79
79
80 def teardown():
80 def teardown():
81 """Teardown testenvironment for the module:
81 """Teardown testenvironment for the module:
82
82
83 - Remove dummy home dir tree
83 - Remove dummy home dir tree
84 """
84 """
85 # Note: we remove the parent test dir, which is the root of all test
85 # Note: we remove the parent test dir, which is the root of all test
86 # subdirs we may have created. Use shutil instead of os.removedirs, so
86 # subdirs we may have created. Use shutil instead of os.removedirs, so
87 # that non-empty directories are all recursively removed.
87 # that non-empty directories are all recursively removed.
88 shutil.rmtree(TMP_TEST_DIR)
88 shutil.rmtree(TMP_TEST_DIR)
89
89
90
90
91 def setup_environment():
91 def setup_environment():
92 """Setup testenvironment for some functions that are tested
92 """Setup testenvironment for some functions that are tested
93 in this module. In particular this functions stores attributes
93 in this module. In particular this functions stores attributes
94 and other things that we need to stub in some test functions.
94 and other things that we need to stub in some test functions.
95 This needs to be done on a function level and not module level because
95 This needs to be done on a function level and not module level because
96 each testfunction needs a pristine environment.
96 each testfunction needs a pristine environment.
97 """
97 """
98 global oldstuff, platformstuff
98 global oldstuff, platformstuff
99 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
99 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
100
100
101 def teardown_environment():
101 def teardown_environment():
102 """Restore things that were remembered by the setup_environment function
102 """Restore things that were remembered by the setup_environment function
103 """
103 """
104 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
104 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
105 os.chdir(old_wd)
105 os.chdir(old_wd)
106 reload(path)
106 reload(path)
107
107
108 for key in list(env):
108 for key in list(env):
109 if key not in oldenv:
109 if key not in oldenv:
110 del env[key]
110 del env[key]
111 env.update(oldenv)
111 env.update(oldenv)
112 if hasattr(sys, 'frozen'):
112 if hasattr(sys, 'frozen'):
113 del sys.frozen
113 del sys.frozen
114
114
115 # Build decorator that uses the setup_environment/setup_environment
115 # Build decorator that uses the setup_environment/setup_environment
116 with_environment = with_setup(setup_environment, teardown_environment)
116 with_environment = with_setup(setup_environment, teardown_environment)
117
117
118 @skip_if_not_win32
118 @skip_if_not_win32
119 @with_environment
119 @with_environment
120 def test_get_home_dir_1():
120 def test_get_home_dir_1():
121 """Testcase for py2exe logic, un-compressed lib
121 """Testcase for py2exe logic, un-compressed lib
122 """
122 """
123 unfrozen = path.get_home_dir()
123 unfrozen = path.get_home_dir()
124 sys.frozen = True
124 sys.frozen = True
125
125
126 #fake filename for IPython.__init__
126 #fake filename for IPython.__init__
127 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
127 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
128
128
129 home_dir = path.get_home_dir()
129 home_dir = path.get_home_dir()
130 nt.assert_equal(home_dir, unfrozen)
130 nt.assert_equal(home_dir, unfrozen)
131
131
132
132
133 @skip_if_not_win32
133 @skip_if_not_win32
134 @with_environment
134 @with_environment
135 def test_get_home_dir_2():
135 def test_get_home_dir_2():
136 """Testcase for py2exe logic, compressed lib
136 """Testcase for py2exe logic, compressed lib
137 """
137 """
138 unfrozen = path.get_home_dir()
138 unfrozen = path.get_home_dir()
139 sys.frozen = True
139 sys.frozen = True
140 #fake filename for IPython.__init__
140 #fake filename for IPython.__init__
141 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
141 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
142
142
143 home_dir = path.get_home_dir(True)
143 home_dir = path.get_home_dir(True)
144 nt.assert_equal(home_dir, unfrozen)
144 nt.assert_equal(home_dir, unfrozen)
145
145
146
146
147 @with_environment
147 @with_environment
148 def test_get_home_dir_3():
148 def test_get_home_dir_3():
149 """get_home_dir() uses $HOME if set"""
149 """get_home_dir() uses $HOME if set"""
150 env["HOME"] = HOME_TEST_DIR
150 env["HOME"] = HOME_TEST_DIR
151 home_dir = path.get_home_dir(True)
151 home_dir = path.get_home_dir(True)
152 # get_home_dir expands symlinks
152 # get_home_dir expands symlinks
153 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
153 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
154
154
155
155
156 @with_environment
156 @with_environment
157 def test_get_home_dir_4():
157 def test_get_home_dir_4():
158 """get_home_dir() still works if $HOME is not set"""
158 """get_home_dir() still works if $HOME is not set"""
159
159
160 if 'HOME' in env: del env['HOME']
160 if 'HOME' in env: del env['HOME']
161 # this should still succeed, but we don't care what the answer is
161 # this should still succeed, but we don't care what the answer is
162 home = path.get_home_dir(False)
162 home = path.get_home_dir(False)
163
163
164 @with_environment
164 @with_environment
165 def test_get_home_dir_5():
165 def test_get_home_dir_5():
166 """raise HomeDirError if $HOME is specified, but not a writable dir"""
166 """raise HomeDirError if $HOME is specified, but not a writable dir"""
167 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
167 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
168 # set os.name = posix, to prevent My Documents fallback on Windows
168 # set os.name = posix, to prevent My Documents fallback on Windows
169 os.name = 'posix'
169 os.name = 'posix'
170 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
170 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
171
171
172 # Should we stub wreg fully so we can run the test on all platforms?
172 # Should we stub wreg fully so we can run the test on all platforms?
173 @skip_if_not_win32
173 @skip_if_not_win32
174 @with_environment
174 @with_environment
175 def test_get_home_dir_8():
175 def test_get_home_dir_8():
176 """Using registry hack for 'My Documents', os=='nt'
176 """Using registry hack for 'My Documents', os=='nt'
177
177
178 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
178 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
179 """
179 """
180 os.name = 'nt'
180 os.name = 'nt'
181 # Remove from stub environment all keys that may be set
181 # Remove from stub environment all keys that may be set
182 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
182 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
183 env.pop(key, None)
183 env.pop(key, None)
184
184
185 class key:
185 class key:
186 def Close(self):
186 def Close(self):
187 pass
187 pass
188
188
189 with patch.object(wreg, 'OpenKey', return_value=key()), \
189 with patch.object(wreg, 'OpenKey', return_value=key()), \
190 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
190 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
191 home_dir = path.get_home_dir()
191 home_dir = path.get_home_dir()
192 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
192 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
193
193
194 @with_environment
194 @with_environment
195 def test_get_xdg_dir_0():
195 def test_get_xdg_dir_0():
196 """test_get_xdg_dir_0, check xdg_dir"""
196 """test_get_xdg_dir_0, check xdg_dir"""
197 reload(path)
197 reload(path)
198 path._writable_dir = lambda path: True
198 path._writable_dir = lambda path: True
199 path.get_home_dir = lambda : 'somewhere'
199 path.get_home_dir = lambda : 'somewhere'
200 os.name = "posix"
200 os.name = "posix"
201 sys.platform = "linux2"
201 sys.platform = "linux2"
202 env.pop('IPYTHON_DIR', None)
202 env.pop('IPYTHON_DIR', None)
203 env.pop('IPYTHONDIR', None)
203 env.pop('IPYTHONDIR', None)
204 env.pop('XDG_CONFIG_HOME', None)
204 env.pop('XDG_CONFIG_HOME', None)
205
205
206 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
206 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
207
207
208
208
209 @with_environment
209 @with_environment
210 def test_get_xdg_dir_1():
210 def test_get_xdg_dir_1():
211 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
211 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
212 reload(path)
212 reload(path)
213 path.get_home_dir = lambda : HOME_TEST_DIR
213 path.get_home_dir = lambda : HOME_TEST_DIR
214 os.name = "posix"
214 os.name = "posix"
215 sys.platform = "linux2"
215 sys.platform = "linux2"
216 env.pop('IPYTHON_DIR', None)
216 env.pop('IPYTHON_DIR', None)
217 env.pop('IPYTHONDIR', None)
217 env.pop('IPYTHONDIR', None)
218 env.pop('XDG_CONFIG_HOME', None)
218 env.pop('XDG_CONFIG_HOME', None)
219 nt.assert_equal(path.get_xdg_dir(), None)
219 nt.assert_equal(path.get_xdg_dir(), None)
220
220
221 @with_environment
221 @with_environment
222 def test_get_xdg_dir_2():
222 def test_get_xdg_dir_2():
223 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
223 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
224 reload(path)
224 reload(path)
225 path.get_home_dir = lambda : HOME_TEST_DIR
225 path.get_home_dir = lambda : HOME_TEST_DIR
226 os.name = "posix"
226 os.name = "posix"
227 sys.platform = "linux2"
227 sys.platform = "linux2"
228 env.pop('IPYTHON_DIR', None)
228 env.pop('IPYTHON_DIR', None)
229 env.pop('IPYTHONDIR', None)
229 env.pop('IPYTHONDIR', None)
230 env.pop('XDG_CONFIG_HOME', None)
230 env.pop('XDG_CONFIG_HOME', None)
231 cfgdir=os.path.join(path.get_home_dir(), '.config')
231 cfgdir=os.path.join(path.get_home_dir(), '.config')
232 if not os.path.exists(cfgdir):
232 if not os.path.exists(cfgdir):
233 os.makedirs(cfgdir)
233 os.makedirs(cfgdir)
234
234
235 nt.assert_equal(path.get_xdg_dir(), cfgdir)
235 nt.assert_equal(path.get_xdg_dir(), cfgdir)
236
236
237 @with_environment
237 @with_environment
238 def test_get_xdg_dir_3():
238 def test_get_xdg_dir_3():
239 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
239 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
240 reload(path)
240 reload(path)
241 path.get_home_dir = lambda : HOME_TEST_DIR
241 path.get_home_dir = lambda : HOME_TEST_DIR
242 os.name = "posix"
242 os.name = "posix"
243 sys.platform = "darwin"
243 sys.platform = "darwin"
244 env.pop('IPYTHON_DIR', None)
244 env.pop('IPYTHON_DIR', None)
245 env.pop('IPYTHONDIR', None)
245 env.pop('IPYTHONDIR', None)
246 env.pop('XDG_CONFIG_HOME', None)
246 env.pop('XDG_CONFIG_HOME', None)
247 cfgdir=os.path.join(path.get_home_dir(), '.config')
247 cfgdir=os.path.join(path.get_home_dir(), '.config')
248 if not os.path.exists(cfgdir):
248 if not os.path.exists(cfgdir):
249 os.makedirs(cfgdir)
249 os.makedirs(cfgdir)
250
250
251 nt.assert_equal(path.get_xdg_dir(), None)
251 nt.assert_equal(path.get_xdg_dir(), None)
252
252
253 def test_filefind():
253 def test_filefind():
254 """Various tests for filefind"""
254 """Various tests for filefind"""
255 f = tempfile.NamedTemporaryFile()
255 f = tempfile.NamedTemporaryFile()
256 # print 'fname:',f.name
256 # print 'fname:',f.name
257 alt_dirs = paths.get_ipython_dir()
257 alt_dirs = paths.get_ipython_dir()
258 t = path.filefind(f.name, alt_dirs)
258 t = path.filefind(f.name, alt_dirs)
259 # print 'found:',t
259 # print 'found:',t
260
260
261
261
262 @dec.skip_if_not_win32
262 @dec.skip_if_not_win32
263 def test_get_long_path_name_win32():
263 def test_get_long_path_name_win32():
264 with TemporaryDirectory() as tmpdir:
264 with TemporaryDirectory() as tmpdir:
265
265
266 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
266 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
267 # path component, so ensure we include the long form of it
267 # path component, so ensure we include the long form of it
268 long_path = os.path.join(path.get_long_path_name(tmpdir), u'this is my long path name')
268 long_path = os.path.join(path.get_long_path_name(tmpdir), u'this is my long path name')
269 os.makedirs(long_path)
269 os.makedirs(long_path)
270
270
271 # Test to see if the short path evaluates correctly.
271 # Test to see if the short path evaluates correctly.
272 short_path = os.path.join(tmpdir, u'THISIS~1')
272 short_path = os.path.join(tmpdir, u'THISIS~1')
273 evaluated_path = path.get_long_path_name(short_path)
273 evaluated_path = path.get_long_path_name(short_path)
274 nt.assert_equal(evaluated_path.lower(), long_path.lower())
274 nt.assert_equal(evaluated_path.lower(), long_path.lower())
275
275
276
276
277 @dec.skip_win32
277 @dec.skip_win32
278 def test_get_long_path_name():
278 def test_get_long_path_name():
279 p = path.get_long_path_name('/usr/local')
279 p = path.get_long_path_name('/usr/local')
280 nt.assert_equal(p,'/usr/local')
280 nt.assert_equal(p,'/usr/local')
281
281
282 @dec.skip_win32 # can't create not-user-writable dir on win
282 @dec.skip_win32 # can't create not-user-writable dir on win
283 @with_environment
283 @with_environment
284 def test_not_writable_ipdir():
284 def test_not_writable_ipdir():
285 tmpdir = tempfile.mkdtemp()
285 tmpdir = tempfile.mkdtemp()
286 os.name = "posix"
286 os.name = "posix"
287 env.pop('IPYTHON_DIR', None)
287 env.pop('IPYTHON_DIR', None)
288 env.pop('IPYTHONDIR', None)
288 env.pop('IPYTHONDIR', None)
289 env.pop('XDG_CONFIG_HOME', None)
289 env.pop('XDG_CONFIG_HOME', None)
290 env['HOME'] = tmpdir
290 env['HOME'] = tmpdir
291 ipdir = os.path.join(tmpdir, '.ipython')
291 ipdir = os.path.join(tmpdir, '.ipython')
292 os.mkdir(ipdir, 0o555)
292 os.mkdir(ipdir, 0o555)
293 try:
293 try:
294 open(os.path.join(ipdir, "_foo_"), 'w').close()
294 open(os.path.join(ipdir, "_foo_"), 'w').close()
295 except IOError:
295 except IOError:
296 pass
296 pass
297 else:
297 else:
298 # I can still write to an unwritable dir,
298 # I can still write to an unwritable dir,
299 # assume I'm root and skip the test
299 # assume I'm root and skip the test
300 raise SkipTest("I can't create directories that I can't write to")
300 raise SkipTest("I can't create directories that I can't write to")
301 with AssertPrints('is not a writable location', channel='stderr'):
301 with AssertPrints('is not a writable location', channel='stderr'):
302 ipdir = paths.get_ipython_dir()
302 ipdir = paths.get_ipython_dir()
303 env.pop('IPYTHON_DIR', None)
303 env.pop('IPYTHON_DIR', None)
304
304
305 @with_environment
305 @with_environment
306 def test_get_py_filename():
306 def test_get_py_filename():
307 os.chdir(TMP_TEST_DIR)
307 os.chdir(TMP_TEST_DIR)
308 with make_tempfile('foo.py'):
308 with make_tempfile('foo.py'):
309 nt.assert_equal(path.get_py_filename('foo.py'), 'foo.py')
309 nt.assert_equal(path.get_py_filename('foo.py'), 'foo.py')
310 nt.assert_equal(path.get_py_filename('foo'), 'foo.py')
310 nt.assert_equal(path.get_py_filename('foo'), 'foo.py')
311 with make_tempfile('foo'):
311 with make_tempfile('foo'):
312 nt.assert_equal(path.get_py_filename('foo'), 'foo')
312 nt.assert_equal(path.get_py_filename('foo'), 'foo')
313 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
313 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
314 nt.assert_raises(IOError, path.get_py_filename, 'foo')
314 nt.assert_raises(IOError, path.get_py_filename, 'foo')
315 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
315 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
316 true_fn = 'foo with spaces.py'
316 true_fn = 'foo with spaces.py'
317 with make_tempfile(true_fn):
317 with make_tempfile(true_fn):
318 nt.assert_equal(path.get_py_filename('foo with spaces'), true_fn)
318 nt.assert_equal(path.get_py_filename('foo with spaces'), true_fn)
319 nt.assert_equal(path.get_py_filename('foo with spaces.py'), true_fn)
319 nt.assert_equal(path.get_py_filename('foo with spaces.py'), true_fn)
320 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
320 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
321 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
321 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
322
322
323 @onlyif_unicode_paths
323 @onlyif_unicode_paths
324 def test_unicode_in_filename():
324 def test_unicode_in_filename():
325 """When a file doesn't exist, the exception raised should be safe to call
325 """When a file doesn't exist, the exception raised should be safe to call
326 str() on - i.e. in Python 2 it must only have ASCII characters.
326 str() on - i.e. in Python 2 it must only have ASCII characters.
327
327
328 https://github.com/ipython/ipython/issues/875
328 https://github.com/ipython/ipython/issues/875
329 """
329 """
330 try:
330 try:
331 # these calls should not throw unicode encode exceptions
331 # these calls should not throw unicode encode exceptions
332 path.get_py_filename(u'fooéè.py', force_win32=False)
332 path.get_py_filename(u'fooéè.py', force_win32=False)
333 except IOError as ex:
333 except IOError as ex:
334 str(ex)
334 str(ex)
335
335
336
336
337 class TestShellGlob(object):
337 class TestShellGlob(object):
338
338
339 @classmethod
339 @classmethod
340 def setUpClass(cls):
340 def setUpClass(cls):
341 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
341 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
342 cls.filenames_end_with_b = ['0b', '1b', '2b']
342 cls.filenames_end_with_b = ['0b', '1b', '2b']
343 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
343 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
344 cls.tempdir = TemporaryDirectory()
344 cls.tempdir = TemporaryDirectory()
345 td = cls.tempdir.name
345 td = cls.tempdir.name
346
346
347 with cls.in_tempdir():
347 with cls.in_tempdir():
348 # Create empty files
348 # Create empty files
349 for fname in cls.filenames:
349 for fname in cls.filenames:
350 open(os.path.join(td, fname), 'w').close()
350 open(os.path.join(td, fname), 'w').close()
351
351
352 @classmethod
352 @classmethod
353 def tearDownClass(cls):
353 def tearDownClass(cls):
354 cls.tempdir.cleanup()
354 cls.tempdir.cleanup()
355
355
356 @classmethod
356 @classmethod
357 @contextmanager
357 @contextmanager
358 def in_tempdir(cls):
358 def in_tempdir(cls):
359 save = py3compat.getcwd()
359 save = os.getcwd()
360 try:
360 try:
361 os.chdir(cls.tempdir.name)
361 os.chdir(cls.tempdir.name)
362 yield
362 yield
363 finally:
363 finally:
364 os.chdir(save)
364 os.chdir(save)
365
365
366 def check_match(self, patterns, matches):
366 def check_match(self, patterns, matches):
367 with self.in_tempdir():
367 with self.in_tempdir():
368 # glob returns unordered list. that's why sorted is required.
368 # glob returns unordered list. that's why sorted is required.
369 nt.assert_equal(sorted(path.shellglob(patterns)),
369 nt.assert_equal(sorted(path.shellglob(patterns)),
370 sorted(matches))
370 sorted(matches))
371
371
372 def common_cases(self):
372 def common_cases(self):
373 return [
373 return [
374 (['*'], self.filenames),
374 (['*'], self.filenames),
375 (['a*'], self.filenames_start_with_a),
375 (['a*'], self.filenames_start_with_a),
376 (['*c'], ['*c']),
376 (['*c'], ['*c']),
377 (['*', 'a*', '*b', '*c'], self.filenames
377 (['*', 'a*', '*b', '*c'], self.filenames
378 + self.filenames_start_with_a
378 + self.filenames_start_with_a
379 + self.filenames_end_with_b
379 + self.filenames_end_with_b
380 + ['*c']),
380 + ['*c']),
381 (['a[012]'], self.filenames_start_with_a),
381 (['a[012]'], self.filenames_start_with_a),
382 ]
382 ]
383
383
384 @skip_win32
384 @skip_win32
385 def test_match_posix(self):
385 def test_match_posix(self):
386 for (patterns, matches) in self.common_cases() + [
386 for (patterns, matches) in self.common_cases() + [
387 ([r'\*'], ['*']),
387 ([r'\*'], ['*']),
388 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
388 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
389 ([r'a\[012]'], ['a[012]']),
389 ([r'a\[012]'], ['a[012]']),
390 ]:
390 ]:
391 yield (self.check_match, patterns, matches)
391 yield (self.check_match, patterns, matches)
392
392
393 @skip_if_not_win32
393 @skip_if_not_win32
394 def test_match_windows(self):
394 def test_match_windows(self):
395 for (patterns, matches) in self.common_cases() + [
395 for (patterns, matches) in self.common_cases() + [
396 # In windows, backslash is interpreted as path
396 # In windows, backslash is interpreted as path
397 # separator. Therefore, you can't escape glob
397 # separator. Therefore, you can't escape glob
398 # using it.
398 # using it.
399 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
399 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
400 ([r'a\[012]'], [r'a\[012]']),
400 ([r'a\[012]'], [r'a\[012]']),
401 ]:
401 ]:
402 yield (self.check_match, patterns, matches)
402 yield (self.check_match, patterns, matches)
403
403
404
404
405 def test_unescape_glob():
405 def test_unescape_glob():
406 nt.assert_equal(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
406 nt.assert_equal(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
407 nt.assert_equal(path.unescape_glob(r'\\*'), r'\*')
407 nt.assert_equal(path.unescape_glob(r'\\*'), r'\*')
408 nt.assert_equal(path.unescape_glob(r'\\\*'), r'\*')
408 nt.assert_equal(path.unescape_glob(r'\\\*'), r'\*')
409 nt.assert_equal(path.unescape_glob(r'\\a'), r'\a')
409 nt.assert_equal(path.unescape_glob(r'\\a'), r'\a')
410 nt.assert_equal(path.unescape_glob(r'\a'), r'\a')
410 nt.assert_equal(path.unescape_glob(r'\a'), r'\a')
411
411
412
412
413 def test_ensure_dir_exists():
413 def test_ensure_dir_exists():
414 with TemporaryDirectory() as td:
414 with TemporaryDirectory() as td:
415 d = os.path.join(td, u'∂ir')
415 d = os.path.join(td, u'∂ir')
416 path.ensure_dir_exists(d) # create it
416 path.ensure_dir_exists(d) # create it
417 assert os.path.isdir(d)
417 assert os.path.isdir(d)
418 path.ensure_dir_exists(d) # no-op
418 path.ensure_dir_exists(d) # no-op
419 f = os.path.join(td, u'Æ’ile')
419 f = os.path.join(td, u'Æ’ile')
420 open(f, 'w').close() # touch
420 open(f, 'w').close() # touch
421 with nt.assert_raises(IOError):
421 with nt.assert_raises(IOError):
422 path.ensure_dir_exists(f)
422 path.ensure_dir_exists(f)
423
423
424 class TestLinkOrCopy(object):
424 class TestLinkOrCopy(object):
425 def setUp(self):
425 def setUp(self):
426 self.tempdir = TemporaryDirectory()
426 self.tempdir = TemporaryDirectory()
427 self.src = self.dst("src")
427 self.src = self.dst("src")
428 with open(self.src, "w") as f:
428 with open(self.src, "w") as f:
429 f.write("Hello, world!")
429 f.write("Hello, world!")
430
430
431 def tearDown(self):
431 def tearDown(self):
432 self.tempdir.cleanup()
432 self.tempdir.cleanup()
433
433
434 def dst(self, *args):
434 def dst(self, *args):
435 return os.path.join(self.tempdir.name, *args)
435 return os.path.join(self.tempdir.name, *args)
436
436
437 def assert_inode_not_equal(self, a, b):
437 def assert_inode_not_equal(self, a, b):
438 nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
438 nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
439 "%r and %r do reference the same indoes" %(a, b))
439 "%r and %r do reference the same indoes" %(a, b))
440
440
441 def assert_inode_equal(self, a, b):
441 def assert_inode_equal(self, a, b):
442 nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
442 nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
443 "%r and %r do not reference the same indoes" %(a, b))
443 "%r and %r do not reference the same indoes" %(a, b))
444
444
445 def assert_content_equal(self, a, b):
445 def assert_content_equal(self, a, b):
446 with open(a) as a_f:
446 with open(a) as a_f:
447 with open(b) as b_f:
447 with open(b) as b_f:
448 nt.assert_equal(a_f.read(), b_f.read())
448 nt.assert_equal(a_f.read(), b_f.read())
449
449
450 @skip_win32
450 @skip_win32
451 def test_link_successful(self):
451 def test_link_successful(self):
452 dst = self.dst("target")
452 dst = self.dst("target")
453 path.link_or_copy(self.src, dst)
453 path.link_or_copy(self.src, dst)
454 self.assert_inode_equal(self.src, dst)
454 self.assert_inode_equal(self.src, dst)
455
455
456 @skip_win32
456 @skip_win32
457 def test_link_into_dir(self):
457 def test_link_into_dir(self):
458 dst = self.dst("some_dir")
458 dst = self.dst("some_dir")
459 os.mkdir(dst)
459 os.mkdir(dst)
460 path.link_or_copy(self.src, dst)
460 path.link_or_copy(self.src, dst)
461 expected_dst = self.dst("some_dir", os.path.basename(self.src))
461 expected_dst = self.dst("some_dir", os.path.basename(self.src))
462 self.assert_inode_equal(self.src, expected_dst)
462 self.assert_inode_equal(self.src, expected_dst)
463
463
464 @skip_win32
464 @skip_win32
465 def test_target_exists(self):
465 def test_target_exists(self):
466 dst = self.dst("target")
466 dst = self.dst("target")
467 open(dst, "w").close()
467 open(dst, "w").close()
468 path.link_or_copy(self.src, dst)
468 path.link_or_copy(self.src, dst)
469 self.assert_inode_equal(self.src, dst)
469 self.assert_inode_equal(self.src, dst)
470
470
471 @skip_win32
471 @skip_win32
472 def test_no_link(self):
472 def test_no_link(self):
473 real_link = os.link
473 real_link = os.link
474 try:
474 try:
475 del os.link
475 del os.link
476 dst = self.dst("target")
476 dst = self.dst("target")
477 path.link_or_copy(self.src, dst)
477 path.link_or_copy(self.src, dst)
478 self.assert_content_equal(self.src, dst)
478 self.assert_content_equal(self.src, dst)
479 self.assert_inode_not_equal(self.src, dst)
479 self.assert_inode_not_equal(self.src, dst)
480 finally:
480 finally:
481 os.link = real_link
481 os.link = real_link
482
482
483 @skip_if_not_win32
483 @skip_if_not_win32
484 def test_windows(self):
484 def test_windows(self):
485 dst = self.dst("target")
485 dst = self.dst("target")
486 path.link_or_copy(self.src, dst)
486 path.link_or_copy(self.src, dst)
487 self.assert_content_equal(self.src, dst)
487 self.assert_content_equal(self.src, dst)
488
488
489 def test_link_twice(self):
489 def test_link_twice(self):
490 # Linking the same file twice shouldn't leave duplicates around.
490 # Linking the same file twice shouldn't leave duplicates around.
491 # See https://github.com/ipython/ipython/issues/6450
491 # See https://github.com/ipython/ipython/issues/6450
492 dst = self.dst('target')
492 dst = self.dst('target')
493 path.link_or_copy(self.src, dst)
493 path.link_or_copy(self.src, dst)
494 path.link_or_copy(self.src, dst)
494 path.link_or_copy(self.src, dst)
495 self.assert_inode_equal(self.src, dst)
495 self.assert_inode_equal(self.src, dst)
496 nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
496 nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
@@ -1,774 +1,776 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with strings and text.
3 Utilities for working with strings and text.
4
4
5 Inheritance diagram:
5 Inheritance diagram:
6
6
7 .. inheritance-diagram:: IPython.utils.text
7 .. inheritance-diagram:: IPython.utils.text
8 :parts: 3
8 :parts: 3
9 """
9 """
10
10
11 import os
11 import os
12 import re
12 import re
13 import sys
13 import sys
14 import textwrap
14 import textwrap
15 from string import Formatter
15 from string import Formatter
16 try:
16 try:
17 from pathlib import Path
17 from pathlib import Path
18 except ImportError:
18 except ImportError:
19 # Python 2 backport
19 # Python 2 backport
20 from pathlib2 import Path
20 from pathlib2 import Path
21
21
22 from IPython.utils import py3compat
22 from IPython.utils import py3compat
23
23
24 # datetime.strftime date format for ipython
24 # datetime.strftime date format for ipython
25 if sys.platform == 'win32':
25 if sys.platform == 'win32':
26 date_format = "%B %d, %Y"
26 date_format = "%B %d, %Y"
27 else:
27 else:
28 date_format = "%B %-d, %Y"
28 date_format = "%B %-d, %Y"
29
29
30 class LSString(str):
30 class LSString(str):
31 """String derivative with a special access attributes.
31 """String derivative with a special access attributes.
32
32
33 These are normal strings, but with the special attributes:
33 These are normal strings, but with the special attributes:
34
34
35 .l (or .list) : value as list (split on newlines).
35 .l (or .list) : value as list (split on newlines).
36 .n (or .nlstr): original value (the string itself).
36 .n (or .nlstr): original value (the string itself).
37 .s (or .spstr): value as whitespace-separated string.
37 .s (or .spstr): value as whitespace-separated string.
38 .p (or .paths): list of path objects (requires path.py package)
38 .p (or .paths): list of path objects (requires path.py package)
39
39
40 Any values which require transformations are computed only once and
40 Any values which require transformations are computed only once and
41 cached.
41 cached.
42
42
43 Such strings are very useful to efficiently interact with the shell, which
43 Such strings are very useful to efficiently interact with the shell, which
44 typically only understands whitespace-separated options for commands."""
44 typically only understands whitespace-separated options for commands."""
45
45
46 def get_list(self):
46 def get_list(self):
47 try:
47 try:
48 return self.__list
48 return self.__list
49 except AttributeError:
49 except AttributeError:
50 self.__list = self.split('\n')
50 self.__list = self.split('\n')
51 return self.__list
51 return self.__list
52
52
53 l = list = property(get_list)
53 l = list = property(get_list)
54
54
55 def get_spstr(self):
55 def get_spstr(self):
56 try:
56 try:
57 return self.__spstr
57 return self.__spstr
58 except AttributeError:
58 except AttributeError:
59 self.__spstr = self.replace('\n',' ')
59 self.__spstr = self.replace('\n',' ')
60 return self.__spstr
60 return self.__spstr
61
61
62 s = spstr = property(get_spstr)
62 s = spstr = property(get_spstr)
63
63
64 def get_nlstr(self):
64 def get_nlstr(self):
65 return self
65 return self
66
66
67 n = nlstr = property(get_nlstr)
67 n = nlstr = property(get_nlstr)
68
68
69 def get_paths(self):
69 def get_paths(self):
70 try:
70 try:
71 return self.__paths
71 return self.__paths
72 except AttributeError:
72 except AttributeError:
73 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
73 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
74 return self.__paths
74 return self.__paths
75
75
76 p = paths = property(get_paths)
76 p = paths = property(get_paths)
77
77
78 # FIXME: We need to reimplement type specific displayhook and then add this
78 # FIXME: We need to reimplement type specific displayhook and then add this
79 # back as a custom printer. This should also be moved outside utils into the
79 # back as a custom printer. This should also be moved outside utils into the
80 # core.
80 # core.
81
81
82 # def print_lsstring(arg):
82 # def print_lsstring(arg):
83 # """ Prettier (non-repr-like) and more informative printer for LSString """
83 # """ Prettier (non-repr-like) and more informative printer for LSString """
84 # print "LSString (.p, .n, .l, .s available). Value:"
84 # print "LSString (.p, .n, .l, .s available). Value:"
85 # print arg
85 # print arg
86 #
86 #
87 #
87 #
88 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
88 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
89
89
90
90
91 class SList(list):
91 class SList(list):
92 """List derivative with a special access attributes.
92 """List derivative with a special access attributes.
93
93
94 These are normal lists, but with the special attributes:
94 These are normal lists, but with the special attributes:
95
95
96 * .l (or .list) : value as list (the list itself).
96 * .l (or .list) : value as list (the list itself).
97 * .n (or .nlstr): value as a string, joined on newlines.
97 * .n (or .nlstr): value as a string, joined on newlines.
98 * .s (or .spstr): value as a string, joined on spaces.
98 * .s (or .spstr): value as a string, joined on spaces.
99 * .p (or .paths): list of path objects (requires path.py package)
99 * .p (or .paths): list of path objects (requires path.py package)
100
100
101 Any values which require transformations are computed only once and
101 Any values which require transformations are computed only once and
102 cached."""
102 cached."""
103
103
104 def get_list(self):
104 def get_list(self):
105 return self
105 return self
106
106
107 l = list = property(get_list)
107 l = list = property(get_list)
108
108
109 def get_spstr(self):
109 def get_spstr(self):
110 try:
110 try:
111 return self.__spstr
111 return self.__spstr
112 except AttributeError:
112 except AttributeError:
113 self.__spstr = ' '.join(self)
113 self.__spstr = ' '.join(self)
114 return self.__spstr
114 return self.__spstr
115
115
116 s = spstr = property(get_spstr)
116 s = spstr = property(get_spstr)
117
117
118 def get_nlstr(self):
118 def get_nlstr(self):
119 try:
119 try:
120 return self.__nlstr
120 return self.__nlstr
121 except AttributeError:
121 except AttributeError:
122 self.__nlstr = '\n'.join(self)
122 self.__nlstr = '\n'.join(self)
123 return self.__nlstr
123 return self.__nlstr
124
124
125 n = nlstr = property(get_nlstr)
125 n = nlstr = property(get_nlstr)
126
126
127 def get_paths(self):
127 def get_paths(self):
128 try:
128 try:
129 return self.__paths
129 return self.__paths
130 except AttributeError:
130 except AttributeError:
131 self.__paths = [Path(p) for p in self if os.path.exists(p)]
131 self.__paths = [Path(p) for p in self if os.path.exists(p)]
132 return self.__paths
132 return self.__paths
133
133
134 p = paths = property(get_paths)
134 p = paths = property(get_paths)
135
135
136 def grep(self, pattern, prune = False, field = None):
136 def grep(self, pattern, prune = False, field = None):
137 """ Return all strings matching 'pattern' (a regex or callable)
137 """ Return all strings matching 'pattern' (a regex or callable)
138
138
139 This is case-insensitive. If prune is true, return all items
139 This is case-insensitive. If prune is true, return all items
140 NOT matching the pattern.
140 NOT matching the pattern.
141
141
142 If field is specified, the match must occur in the specified
142 If field is specified, the match must occur in the specified
143 whitespace-separated field.
143 whitespace-separated field.
144
144
145 Examples::
145 Examples::
146
146
147 a.grep( lambda x: x.startswith('C') )
147 a.grep( lambda x: x.startswith('C') )
148 a.grep('Cha.*log', prune=1)
148 a.grep('Cha.*log', prune=1)
149 a.grep('chm', field=-1)
149 a.grep('chm', field=-1)
150 """
150 """
151
151
152 def match_target(s):
152 def match_target(s):
153 if field is None:
153 if field is None:
154 return s
154 return s
155 parts = s.split()
155 parts = s.split()
156 try:
156 try:
157 tgt = parts[field]
157 tgt = parts[field]
158 return tgt
158 return tgt
159 except IndexError:
159 except IndexError:
160 return ""
160 return ""
161
161
162 if isinstance(pattern, py3compat.string_types):
162 if isinstance(pattern, str):
163 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
163 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
164 else:
164 else:
165 pred = pattern
165 pred = pattern
166 if not prune:
166 if not prune:
167 return SList([el for el in self if pred(match_target(el))])
167 return SList([el for el in self if pred(match_target(el))])
168 else:
168 else:
169 return SList([el for el in self if not pred(match_target(el))])
169 return SList([el for el in self if not pred(match_target(el))])
170
170
171 def fields(self, *fields):
171 def fields(self, *fields):
172 """ Collect whitespace-separated fields from string list
172 """ Collect whitespace-separated fields from string list
173
173
174 Allows quick awk-like usage of string lists.
174 Allows quick awk-like usage of string lists.
175
175
176 Example data (in var a, created by 'a = !ls -l')::
176 Example data (in var a, created by 'a = !ls -l')::
177
177
178 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
178 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
179 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
179 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
180
180
181 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
181 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
182 * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
182 * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
183 (note the joining by space).
183 (note the joining by space).
184 * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
184 * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
185
185
186 IndexErrors are ignored.
186 IndexErrors are ignored.
187
187
188 Without args, fields() just split()'s the strings.
188 Without args, fields() just split()'s the strings.
189 """
189 """
190 if len(fields) == 0:
190 if len(fields) == 0:
191 return [el.split() for el in self]
191 return [el.split() for el in self]
192
192
193 res = SList()
193 res = SList()
194 for el in [f.split() for f in self]:
194 for el in [f.split() for f in self]:
195 lineparts = []
195 lineparts = []
196
196
197 for fd in fields:
197 for fd in fields:
198 try:
198 try:
199 lineparts.append(el[fd])
199 lineparts.append(el[fd])
200 except IndexError:
200 except IndexError:
201 pass
201 pass
202 if lineparts:
202 if lineparts:
203 res.append(" ".join(lineparts))
203 res.append(" ".join(lineparts))
204
204
205 return res
205 return res
206
206
207 def sort(self,field= None, nums = False):
207 def sort(self,field= None, nums = False):
208 """ sort by specified fields (see fields())
208 """ sort by specified fields (see fields())
209
209
210 Example::
210 Example::
211
211
212 a.sort(1, nums = True)
212 a.sort(1, nums = True)
213
213
214 Sorts a by second field, in numerical order (so that 21 > 3)
214 Sorts a by second field, in numerical order (so that 21 > 3)
215
215
216 """
216 """
217
217
218 #decorate, sort, undecorate
218 #decorate, sort, undecorate
219 if field is not None:
219 if field is not None:
220 dsu = [[SList([line]).fields(field), line] for line in self]
220 dsu = [[SList([line]).fields(field), line] for line in self]
221 else:
221 else:
222 dsu = [[line, line] for line in self]
222 dsu = [[line, line] for line in self]
223 if nums:
223 if nums:
224 for i in range(len(dsu)):
224 for i in range(len(dsu)):
225 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
225 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
226 try:
226 try:
227 n = int(numstr)
227 n = int(numstr)
228 except ValueError:
228 except ValueError:
229 n = 0
229 n = 0
230 dsu[i][0] = n
230 dsu[i][0] = n
231
231
232
232
233 dsu.sort()
233 dsu.sort()
234 return SList([t[1] for t in dsu])
234 return SList([t[1] for t in dsu])
235
235
236
236
237 # FIXME: We need to reimplement type specific displayhook and then add this
237 # FIXME: We need to reimplement type specific displayhook and then add this
238 # back as a custom printer. This should also be moved outside utils into the
238 # back as a custom printer. This should also be moved outside utils into the
239 # core.
239 # core.
240
240
241 # def print_slist(arg):
241 # def print_slist(arg):
242 # """ Prettier (non-repr-like) and more informative printer for SList """
242 # """ Prettier (non-repr-like) and more informative printer for SList """
243 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
243 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
244 # if hasattr(arg, 'hideonce') and arg.hideonce:
244 # if hasattr(arg, 'hideonce') and arg.hideonce:
245 # arg.hideonce = False
245 # arg.hideonce = False
246 # return
246 # return
247 #
247 #
248 # nlprint(arg) # This was a nested list printer, now removed.
248 # nlprint(arg) # This was a nested list printer, now removed.
249 #
249 #
250 # print_slist = result_display.when_type(SList)(print_slist)
250 # print_slist = result_display.when_type(SList)(print_slist)
251
251
252
252
253 def indent(instr,nspaces=4, ntabs=0, flatten=False):
253 def indent(instr,nspaces=4, ntabs=0, flatten=False):
254 """Indent a string a given number of spaces or tabstops.
254 """Indent a string a given number of spaces or tabstops.
255
255
256 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
256 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
257
257
258 Parameters
258 Parameters
259 ----------
259 ----------
260
260
261 instr : basestring
261 instr : basestring
262 The string to be indented.
262 The string to be indented.
263 nspaces : int (default: 4)
263 nspaces : int (default: 4)
264 The number of spaces to be indented.
264 The number of spaces to be indented.
265 ntabs : int (default: 0)
265 ntabs : int (default: 0)
266 The number of tabs to be indented.
266 The number of tabs to be indented.
267 flatten : bool (default: False)
267 flatten : bool (default: False)
268 Whether to scrub existing indentation. If True, all lines will be
268 Whether to scrub existing indentation. If True, all lines will be
269 aligned to the same indentation. If False, existing indentation will
269 aligned to the same indentation. If False, existing indentation will
270 be strictly increased.
270 be strictly increased.
271
271
272 Returns
272 Returns
273 -------
273 -------
274
274
275 str|unicode : string indented by ntabs and nspaces.
275 str|unicode : string indented by ntabs and nspaces.
276
276
277 """
277 """
278 if instr is None:
278 if instr is None:
279 return
279 return
280 ind = '\t'*ntabs+' '*nspaces
280 ind = '\t'*ntabs+' '*nspaces
281 if flatten:
281 if flatten:
282 pat = re.compile(r'^\s*', re.MULTILINE)
282 pat = re.compile(r'^\s*', re.MULTILINE)
283 else:
283 else:
284 pat = re.compile(r'^', re.MULTILINE)
284 pat = re.compile(r'^', re.MULTILINE)
285 outstr = re.sub(pat, ind, instr)
285 outstr = re.sub(pat, ind, instr)
286 if outstr.endswith(os.linesep+ind):
286 if outstr.endswith(os.linesep+ind):
287 return outstr[:-len(ind)]
287 return outstr[:-len(ind)]
288 else:
288 else:
289 return outstr
289 return outstr
290
290
291
291
292 def list_strings(arg):
292 def list_strings(arg):
293 """Always return a list of strings, given a string or list of strings
293 """Always return a list of strings, given a string or list of strings
294 as input.
294 as input.
295
295
296 Examples
296 Examples
297 --------
297 --------
298 ::
298 ::
299
299
300 In [7]: list_strings('A single string')
300 In [7]: list_strings('A single string')
301 Out[7]: ['A single string']
301 Out[7]: ['A single string']
302
302
303 In [8]: list_strings(['A single string in a list'])
303 In [8]: list_strings(['A single string in a list'])
304 Out[8]: ['A single string in a list']
304 Out[8]: ['A single string in a list']
305
305
306 In [9]: list_strings(['A','list','of','strings'])
306 In [9]: list_strings(['A','list','of','strings'])
307 Out[9]: ['A', 'list', 'of', 'strings']
307 Out[9]: ['A', 'list', 'of', 'strings']
308 """
308 """
309
309
310 if isinstance(arg, py3compat.string_types): return [arg]
310 if isinstance(arg, str):
311 else: return arg
311 return [arg]
312 else:
313 return arg
312
314
313
315
314 def marquee(txt='',width=78,mark='*'):
316 def marquee(txt='',width=78,mark='*'):
315 """Return the input string centered in a 'marquee'.
317 """Return the input string centered in a 'marquee'.
316
318
317 Examples
319 Examples
318 --------
320 --------
319 ::
321 ::
320
322
321 In [16]: marquee('A test',40)
323 In [16]: marquee('A test',40)
322 Out[16]: '**************** A test ****************'
324 Out[16]: '**************** A test ****************'
323
325
324 In [17]: marquee('A test',40,'-')
326 In [17]: marquee('A test',40,'-')
325 Out[17]: '---------------- A test ----------------'
327 Out[17]: '---------------- A test ----------------'
326
328
327 In [18]: marquee('A test',40,' ')
329 In [18]: marquee('A test',40,' ')
328 Out[18]: ' A test '
330 Out[18]: ' A test '
329
331
330 """
332 """
331 if not txt:
333 if not txt:
332 return (mark*width)[:width]
334 return (mark*width)[:width]
333 nmark = (width-len(txt)-2)//len(mark)//2
335 nmark = (width-len(txt)-2)//len(mark)//2
334 if nmark < 0: nmark =0
336 if nmark < 0: nmark =0
335 marks = mark*nmark
337 marks = mark*nmark
336 return '%s %s %s' % (marks,txt,marks)
338 return '%s %s %s' % (marks,txt,marks)
337
339
338
340
339 ini_spaces_re = re.compile(r'^(\s+)')
341 ini_spaces_re = re.compile(r'^(\s+)')
340
342
341 def num_ini_spaces(strng):
343 def num_ini_spaces(strng):
342 """Return the number of initial spaces in a string"""
344 """Return the number of initial spaces in a string"""
343
345
344 ini_spaces = ini_spaces_re.match(strng)
346 ini_spaces = ini_spaces_re.match(strng)
345 if ini_spaces:
347 if ini_spaces:
346 return ini_spaces.end()
348 return ini_spaces.end()
347 else:
349 else:
348 return 0
350 return 0
349
351
350
352
351 def format_screen(strng):
353 def format_screen(strng):
352 """Format a string for screen printing.
354 """Format a string for screen printing.
353
355
354 This removes some latex-type format codes."""
356 This removes some latex-type format codes."""
355 # Paragraph continue
357 # Paragraph continue
356 par_re = re.compile(r'\\$',re.MULTILINE)
358 par_re = re.compile(r'\\$',re.MULTILINE)
357 strng = par_re.sub('',strng)
359 strng = par_re.sub('',strng)
358 return strng
360 return strng
359
361
360
362
361 def dedent(text):
363 def dedent(text):
362 """Equivalent of textwrap.dedent that ignores unindented first line.
364 """Equivalent of textwrap.dedent that ignores unindented first line.
363
365
364 This means it will still dedent strings like:
366 This means it will still dedent strings like:
365 '''foo
367 '''foo
366 is a bar
368 is a bar
367 '''
369 '''
368
370
369 For use in wrap_paragraphs.
371 For use in wrap_paragraphs.
370 """
372 """
371
373
372 if text.startswith('\n'):
374 if text.startswith('\n'):
373 # text starts with blank line, don't ignore the first line
375 # text starts with blank line, don't ignore the first line
374 return textwrap.dedent(text)
376 return textwrap.dedent(text)
375
377
376 # split first line
378 # split first line
377 splits = text.split('\n',1)
379 splits = text.split('\n',1)
378 if len(splits) == 1:
380 if len(splits) == 1:
379 # only one line
381 # only one line
380 return textwrap.dedent(text)
382 return textwrap.dedent(text)
381
383
382 first, rest = splits
384 first, rest = splits
383 # dedent everything but the first line
385 # dedent everything but the first line
384 rest = textwrap.dedent(rest)
386 rest = textwrap.dedent(rest)
385 return '\n'.join([first, rest])
387 return '\n'.join([first, rest])
386
388
387
389
388 def wrap_paragraphs(text, ncols=80):
390 def wrap_paragraphs(text, ncols=80):
389 """Wrap multiple paragraphs to fit a specified width.
391 """Wrap multiple paragraphs to fit a specified width.
390
392
391 This is equivalent to textwrap.wrap, but with support for multiple
393 This is equivalent to textwrap.wrap, but with support for multiple
392 paragraphs, as separated by empty lines.
394 paragraphs, as separated by empty lines.
393
395
394 Returns
396 Returns
395 -------
397 -------
396
398
397 list of complete paragraphs, wrapped to fill `ncols` columns.
399 list of complete paragraphs, wrapped to fill `ncols` columns.
398 """
400 """
399 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
401 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
400 text = dedent(text).strip()
402 text = dedent(text).strip()
401 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
403 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
402 out_ps = []
404 out_ps = []
403 indent_re = re.compile(r'\n\s+', re.MULTILINE)
405 indent_re = re.compile(r'\n\s+', re.MULTILINE)
404 for p in paragraphs:
406 for p in paragraphs:
405 # presume indentation that survives dedent is meaningful formatting,
407 # presume indentation that survives dedent is meaningful formatting,
406 # so don't fill unless text is flush.
408 # so don't fill unless text is flush.
407 if indent_re.search(p) is None:
409 if indent_re.search(p) is None:
408 # wrap paragraph
410 # wrap paragraph
409 p = textwrap.fill(p, ncols)
411 p = textwrap.fill(p, ncols)
410 out_ps.append(p)
412 out_ps.append(p)
411 return out_ps
413 return out_ps
412
414
413
415
414 def long_substr(data):
416 def long_substr(data):
415 """Return the longest common substring in a list of strings.
417 """Return the longest common substring in a list of strings.
416
418
417 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
419 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
418 """
420 """
419 substr = ''
421 substr = ''
420 if len(data) > 1 and len(data[0]) > 0:
422 if len(data) > 1 and len(data[0]) > 0:
421 for i in range(len(data[0])):
423 for i in range(len(data[0])):
422 for j in range(len(data[0])-i+1):
424 for j in range(len(data[0])-i+1):
423 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
425 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
424 substr = data[0][i:i+j]
426 substr = data[0][i:i+j]
425 elif len(data) == 1:
427 elif len(data) == 1:
426 substr = data[0]
428 substr = data[0]
427 return substr
429 return substr
428
430
429
431
430 def strip_email_quotes(text):
432 def strip_email_quotes(text):
431 """Strip leading email quotation characters ('>').
433 """Strip leading email quotation characters ('>').
432
434
433 Removes any combination of leading '>' interspersed with whitespace that
435 Removes any combination of leading '>' interspersed with whitespace that
434 appears *identically* in all lines of the input text.
436 appears *identically* in all lines of the input text.
435
437
436 Parameters
438 Parameters
437 ----------
439 ----------
438 text : str
440 text : str
439
441
440 Examples
442 Examples
441 --------
443 --------
442
444
443 Simple uses::
445 Simple uses::
444
446
445 In [2]: strip_email_quotes('> > text')
447 In [2]: strip_email_quotes('> > text')
446 Out[2]: 'text'
448 Out[2]: 'text'
447
449
448 In [3]: strip_email_quotes('> > text\\n> > more')
450 In [3]: strip_email_quotes('> > text\\n> > more')
449 Out[3]: 'text\\nmore'
451 Out[3]: 'text\\nmore'
450
452
451 Note how only the common prefix that appears in all lines is stripped::
453 Note how only the common prefix that appears in all lines is stripped::
452
454
453 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
455 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
454 Out[4]: '> text\\n> more\\nmore...'
456 Out[4]: '> text\\n> more\\nmore...'
455
457
456 So if any line has no quote marks ('>') , then none are stripped from any
458 So if any line has no quote marks ('>') , then none are stripped from any
457 of them ::
459 of them ::
458
460
459 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
461 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
460 Out[5]: '> > text\\n> > more\\nlast different'
462 Out[5]: '> > text\\n> > more\\nlast different'
461 """
463 """
462 lines = text.splitlines()
464 lines = text.splitlines()
463 matches = set()
465 matches = set()
464 for line in lines:
466 for line in lines:
465 prefix = re.match(r'^(\s*>[ >]*)', line)
467 prefix = re.match(r'^(\s*>[ >]*)', line)
466 if prefix:
468 if prefix:
467 matches.add(prefix.group(1))
469 matches.add(prefix.group(1))
468 else:
470 else:
469 break
471 break
470 else:
472 else:
471 prefix = long_substr(list(matches))
473 prefix = long_substr(list(matches))
472 if prefix:
474 if prefix:
473 strip = len(prefix)
475 strip = len(prefix)
474 text = '\n'.join([ ln[strip:] for ln in lines])
476 text = '\n'.join([ ln[strip:] for ln in lines])
475 return text
477 return text
476
478
477 def strip_ansi(source):
479 def strip_ansi(source):
478 """
480 """
479 Remove ansi escape codes from text.
481 Remove ansi escape codes from text.
480
482
481 Parameters
483 Parameters
482 ----------
484 ----------
483 source : str
485 source : str
484 Source to remove the ansi from
486 Source to remove the ansi from
485 """
487 """
486 return re.sub(r'\033\[(\d|;)+?m', '', source)
488 return re.sub(r'\033\[(\d|;)+?m', '', source)
487
489
488
490
489 class EvalFormatter(Formatter):
491 class EvalFormatter(Formatter):
490 """A String Formatter that allows evaluation of simple expressions.
492 """A String Formatter that allows evaluation of simple expressions.
491
493
492 Note that this version interprets a : as specifying a format string (as per
494 Note that this version interprets a : as specifying a format string (as per
493 standard string formatting), so if slicing is required, you must explicitly
495 standard string formatting), so if slicing is required, you must explicitly
494 create a slice.
496 create a slice.
495
497
496 This is to be used in templating cases, such as the parallel batch
498 This is to be used in templating cases, such as the parallel batch
497 script templates, where simple arithmetic on arguments is useful.
499 script templates, where simple arithmetic on arguments is useful.
498
500
499 Examples
501 Examples
500 --------
502 --------
501 ::
503 ::
502
504
503 In [1]: f = EvalFormatter()
505 In [1]: f = EvalFormatter()
504 In [2]: f.format('{n//4}', n=8)
506 In [2]: f.format('{n//4}', n=8)
505 Out[2]: '2'
507 Out[2]: '2'
506
508
507 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
509 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
508 Out[3]: 'll'
510 Out[3]: 'll'
509 """
511 """
510 def get_field(self, name, args, kwargs):
512 def get_field(self, name, args, kwargs):
511 v = eval(name, kwargs)
513 v = eval(name, kwargs)
512 return v, name
514 return v, name
513
515
514 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
516 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
515 # inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
517 # inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
516 # above, it should be possible to remove FullEvalFormatter.
518 # above, it should be possible to remove FullEvalFormatter.
517
519
518 class FullEvalFormatter(Formatter):
520 class FullEvalFormatter(Formatter):
519 """A String Formatter that allows evaluation of simple expressions.
521 """A String Formatter that allows evaluation of simple expressions.
520
522
521 Any time a format key is not found in the kwargs,
523 Any time a format key is not found in the kwargs,
522 it will be tried as an expression in the kwargs namespace.
524 it will be tried as an expression in the kwargs namespace.
523
525
524 Note that this version allows slicing using [1:2], so you cannot specify
526 Note that this version allows slicing using [1:2], so you cannot specify
525 a format string. Use :class:`EvalFormatter` to permit format strings.
527 a format string. Use :class:`EvalFormatter` to permit format strings.
526
528
527 Examples
529 Examples
528 --------
530 --------
529 ::
531 ::
530
532
531 In [1]: f = FullEvalFormatter()
533 In [1]: f = FullEvalFormatter()
532 In [2]: f.format('{n//4}', n=8)
534 In [2]: f.format('{n//4}', n=8)
533 Out[2]: '2'
535 Out[2]: '2'
534
536
535 In [3]: f.format('{list(range(5))[2:4]}')
537 In [3]: f.format('{list(range(5))[2:4]}')
536 Out[3]: '[2, 3]'
538 Out[3]: '[2, 3]'
537
539
538 In [4]: f.format('{3*2}')
540 In [4]: f.format('{3*2}')
539 Out[4]: '6'
541 Out[4]: '6'
540 """
542 """
541 # copied from Formatter._vformat with minor changes to allow eval
543 # copied from Formatter._vformat with minor changes to allow eval
542 # and replace the format_spec code with slicing
544 # and replace the format_spec code with slicing
543 def vformat(self, format_string, args, kwargs):
545 def vformat(self, format_string, args, kwargs):
544 result = []
546 result = []
545 for literal_text, field_name, format_spec, conversion in \
547 for literal_text, field_name, format_spec, conversion in \
546 self.parse(format_string):
548 self.parse(format_string):
547
549
548 # output the literal text
550 # output the literal text
549 if literal_text:
551 if literal_text:
550 result.append(literal_text)
552 result.append(literal_text)
551
553
552 # if there's a field, output it
554 # if there's a field, output it
553 if field_name is not None:
555 if field_name is not None:
554 # this is some markup, find the object and do
556 # this is some markup, find the object and do
555 # the formatting
557 # the formatting
556
558
557 if format_spec:
559 if format_spec:
558 # override format spec, to allow slicing:
560 # override format spec, to allow slicing:
559 field_name = ':'.join([field_name, format_spec])
561 field_name = ':'.join([field_name, format_spec])
560
562
561 # eval the contents of the field for the object
563 # eval the contents of the field for the object
562 # to be formatted
564 # to be formatted
563 obj = eval(field_name, kwargs)
565 obj = eval(field_name, kwargs)
564
566
565 # do any conversion on the resulting object
567 # do any conversion on the resulting object
566 obj = self.convert_field(obj, conversion)
568 obj = self.convert_field(obj, conversion)
567
569
568 # format the object and append to the result
570 # format the object and append to the result
569 result.append(self.format_field(obj, ''))
571 result.append(self.format_field(obj, ''))
570
572
571 return u''.join(py3compat.cast_unicode(s) for s in result)
573 return u''.join(py3compat.cast_unicode(s) for s in result)
572
574
573
575
574 class DollarFormatter(FullEvalFormatter):
576 class DollarFormatter(FullEvalFormatter):
575 """Formatter allowing Itpl style $foo replacement, for names and attribute
577 """Formatter allowing Itpl style $foo replacement, for names and attribute
576 access only. Standard {foo} replacement also works, and allows full
578 access only. Standard {foo} replacement also works, and allows full
577 evaluation of its arguments.
579 evaluation of its arguments.
578
580
579 Examples
581 Examples
580 --------
582 --------
581 ::
583 ::
582
584
583 In [1]: f = DollarFormatter()
585 In [1]: f = DollarFormatter()
584 In [2]: f.format('{n//4}', n=8)
586 In [2]: f.format('{n//4}', n=8)
585 Out[2]: '2'
587 Out[2]: '2'
586
588
587 In [3]: f.format('23 * 76 is $result', result=23*76)
589 In [3]: f.format('23 * 76 is $result', result=23*76)
588 Out[3]: '23 * 76 is 1748'
590 Out[3]: '23 * 76 is 1748'
589
591
590 In [4]: f.format('$a or {b}', a=1, b=2)
592 In [4]: f.format('$a or {b}', a=1, b=2)
591 Out[4]: '1 or 2'
593 Out[4]: '1 or 2'
592 """
594 """
593 _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
595 _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
594 def parse(self, fmt_string):
596 def parse(self, fmt_string):
595 for literal_txt, field_name, format_spec, conversion \
597 for literal_txt, field_name, format_spec, conversion \
596 in Formatter.parse(self, fmt_string):
598 in Formatter.parse(self, fmt_string):
597
599
598 # Find $foo patterns in the literal text.
600 # Find $foo patterns in the literal text.
599 continue_from = 0
601 continue_from = 0
600 txt = ""
602 txt = ""
601 for m in self._dollar_pattern.finditer(literal_txt):
603 for m in self._dollar_pattern.finditer(literal_txt):
602 new_txt, new_field = m.group(1,2)
604 new_txt, new_field = m.group(1,2)
603 # $$foo --> $foo
605 # $$foo --> $foo
604 if new_field.startswith("$"):
606 if new_field.startswith("$"):
605 txt += new_txt + new_field
607 txt += new_txt + new_field
606 else:
608 else:
607 yield (txt + new_txt, new_field, "", None)
609 yield (txt + new_txt, new_field, "", None)
608 txt = ""
610 txt = ""
609 continue_from = m.end()
611 continue_from = m.end()
610
612
611 # Re-yield the {foo} style pattern
613 # Re-yield the {foo} style pattern
612 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
614 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
613
615
614 #-----------------------------------------------------------------------------
616 #-----------------------------------------------------------------------------
615 # Utils to columnize a list of string
617 # Utils to columnize a list of string
616 #-----------------------------------------------------------------------------
618 #-----------------------------------------------------------------------------
617
619
618 def _col_chunks(l, max_rows, row_first=False):
620 def _col_chunks(l, max_rows, row_first=False):
619 """Yield successive max_rows-sized column chunks from l."""
621 """Yield successive max_rows-sized column chunks from l."""
620 if row_first:
622 if row_first:
621 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
623 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
622 for i in py3compat.xrange(ncols):
624 for i in range(ncols):
623 yield [l[j] for j in py3compat.xrange(i, len(l), ncols)]
625 yield [l[j] for j in range(i, len(l), ncols)]
624 else:
626 else:
625 for i in py3compat.xrange(0, len(l), max_rows):
627 for i in range(0, len(l), max_rows):
626 yield l[i:(i + max_rows)]
628 yield l[i:(i + max_rows)]
627
629
628
630
629 def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
631 def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
630 """Calculate optimal info to columnize a list of string"""
632 """Calculate optimal info to columnize a list of string"""
631 for max_rows in range(1, len(rlist) + 1):
633 for max_rows in range(1, len(rlist) + 1):
632 col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
634 col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
633 sumlength = sum(col_widths)
635 sumlength = sum(col_widths)
634 ncols = len(col_widths)
636 ncols = len(col_widths)
635 if sumlength + separator_size * (ncols - 1) <= displaywidth:
637 if sumlength + separator_size * (ncols - 1) <= displaywidth:
636 break
638 break
637 return {'num_columns': ncols,
639 return {'num_columns': ncols,
638 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0,
640 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0,
639 'max_rows': max_rows,
641 'max_rows': max_rows,
640 'column_widths': col_widths
642 'column_widths': col_widths
641 }
643 }
642
644
643
645
644 def _get_or_default(mylist, i, default=None):
646 def _get_or_default(mylist, i, default=None):
645 """return list item number, or default if don't exist"""
647 """return list item number, or default if don't exist"""
646 if i >= len(mylist):
648 if i >= len(mylist):
647 return default
649 return default
648 else :
650 else :
649 return mylist[i]
651 return mylist[i]
650
652
651
653
652 def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :
654 def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :
653 """Returns a nested list, and info to columnize items
655 """Returns a nested list, and info to columnize items
654
656
655 Parameters
657 Parameters
656 ----------
658 ----------
657
659
658 items
660 items
659 list of strings to columize
661 list of strings to columize
660 row_first : (default False)
662 row_first : (default False)
661 Whether to compute columns for a row-first matrix instead of
663 Whether to compute columns for a row-first matrix instead of
662 column-first (default).
664 column-first (default).
663 empty : (default None)
665 empty : (default None)
664 default value to fill list if needed
666 default value to fill list if needed
665 separator_size : int (default=2)
667 separator_size : int (default=2)
666 How much caracters will be used as a separation between each columns.
668 How much caracters will be used as a separation between each columns.
667 displaywidth : int (default=80)
669 displaywidth : int (default=80)
668 The width of the area onto wich the columns should enter
670 The width of the area onto wich the columns should enter
669
671
670 Returns
672 Returns
671 -------
673 -------
672
674
673 strings_matrix
675 strings_matrix
674
676
675 nested list of string, the outer most list contains as many list as
677 nested list of string, the outer most list contains as many list as
676 rows, the innermost lists have each as many element as colums. If the
678 rows, the innermost lists have each as many element as colums. If the
677 total number of elements in `items` does not equal the product of
679 total number of elements in `items` does not equal the product of
678 rows*columns, the last element of some lists are filled with `None`.
680 rows*columns, the last element of some lists are filled with `None`.
679
681
680 dict_info
682 dict_info
681 some info to make columnize easier:
683 some info to make columnize easier:
682
684
683 num_columns
685 num_columns
684 number of columns
686 number of columns
685 max_rows
687 max_rows
686 maximum number of rows (final number may be less)
688 maximum number of rows (final number may be less)
687 column_widths
689 column_widths
688 list of with of each columns
690 list of with of each columns
689 optimal_separator_width
691 optimal_separator_width
690 best separator width between columns
692 best separator width between columns
691
693
692 Examples
694 Examples
693 --------
695 --------
694 ::
696 ::
695
697
696 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
698 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
697 In [2]: list, info = compute_item_matrix(l, displaywidth=12)
699 In [2]: list, info = compute_item_matrix(l, displaywidth=12)
698 In [3]: list
700 In [3]: list
699 Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
701 Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
700 In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
702 In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
701 In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
703 In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
702 Out[5]: True
704 Out[5]: True
703 """
705 """
704 info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
706 info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
705 nrow, ncol = info['max_rows'], info['num_columns']
707 nrow, ncol = info['max_rows'], info['num_columns']
706 if row_first:
708 if row_first:
707 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
709 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
708 else:
710 else:
709 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
711 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
710
712
711
713
712 def columnize(items, row_first=False, separator=' ', displaywidth=80, spread=False):
714 def columnize(items, row_first=False, separator=' ', displaywidth=80, spread=False):
713 """ Transform a list of strings into a single string with columns.
715 """ Transform a list of strings into a single string with columns.
714
716
715 Parameters
717 Parameters
716 ----------
718 ----------
717 items : sequence of strings
719 items : sequence of strings
718 The strings to process.
720 The strings to process.
719
721
720 row_first : (default False)
722 row_first : (default False)
721 Whether to compute columns for a row-first matrix instead of
723 Whether to compute columns for a row-first matrix instead of
722 column-first (default).
724 column-first (default).
723
725
724 separator : str, optional [default is two spaces]
726 separator : str, optional [default is two spaces]
725 The string that separates columns.
727 The string that separates columns.
726
728
727 displaywidth : int, optional [default is 80]
729 displaywidth : int, optional [default is 80]
728 Width of the display in number of characters.
730 Width of the display in number of characters.
729
731
730 Returns
732 Returns
731 -------
733 -------
732 The formatted string.
734 The formatted string.
733 """
735 """
734 if not items:
736 if not items:
735 return '\n'
737 return '\n'
736 matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth)
738 matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth)
737 if spread:
739 if spread:
738 separator = separator.ljust(int(info['optimal_separator_width']))
740 separator = separator.ljust(int(info['optimal_separator_width']))
739 fmatrix = [filter(None, x) for x in matrix]
741 fmatrix = [filter(None, x) for x in matrix]
740 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])])
742 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])])
741 return '\n'.join(map(sjoin, fmatrix))+'\n'
743 return '\n'.join(map(sjoin, fmatrix))+'\n'
742
744
743
745
744 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
746 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
745 """
747 """
746 Return a string with a natural enumeration of items
748 Return a string with a natural enumeration of items
747
749
748 >>> get_text_list(['a', 'b', 'c', 'd'])
750 >>> get_text_list(['a', 'b', 'c', 'd'])
749 'a, b, c and d'
751 'a, b, c and d'
750 >>> get_text_list(['a', 'b', 'c'], ' or ')
752 >>> get_text_list(['a', 'b', 'c'], ' or ')
751 'a, b or c'
753 'a, b or c'
752 >>> get_text_list(['a', 'b', 'c'], ', ')
754 >>> get_text_list(['a', 'b', 'c'], ', ')
753 'a, b, c'
755 'a, b, c'
754 >>> get_text_list(['a', 'b'], ' or ')
756 >>> get_text_list(['a', 'b'], ' or ')
755 'a or b'
757 'a or b'
756 >>> get_text_list(['a'])
758 >>> get_text_list(['a'])
757 'a'
759 'a'
758 >>> get_text_list([])
760 >>> get_text_list([])
759 ''
761 ''
760 >>> get_text_list(['a', 'b'], wrap_item_with="`")
762 >>> get_text_list(['a', 'b'], wrap_item_with="`")
761 '`a` and `b`'
763 '`a` and `b`'
762 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
764 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
763 'a + b + c = d'
765 'a + b + c = d'
764 """
766 """
765 if len(list_) == 0:
767 if len(list_) == 0:
766 return ''
768 return ''
767 if wrap_item_with:
769 if wrap_item_with:
768 list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
770 list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
769 item in list_]
771 item in list_]
770 if len(list_) == 1:
772 if len(list_) == 1:
771 return list_[0]
773 return list_[0]
772 return '%s%s%s' % (
774 return '%s%s%s' % (
773 sep.join(i for i in list_[:-1]),
775 sep.join(i for i in list_[:-1]),
774 last_sep, list_[-1])
776 last_sep, list_[-1])
@@ -1,118 +1,116 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for timing code execution.
3 Utilities for timing code execution.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import time
17 import time
18
18
19 from .py3compat import xrange
20
21 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
22 # Code
20 # Code
23 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
24
22
25 # If possible (Unix), use the resource module instead of time.clock()
23 # If possible (Unix), use the resource module instead of time.clock()
26 try:
24 try:
27 import resource
25 import resource
28 def clocku():
26 def clocku():
29 """clocku() -> floating point number
27 """clocku() -> floating point number
30
28
31 Return the *USER* CPU time in seconds since the start of the process.
29 Return the *USER* CPU time in seconds since the start of the process.
32 This is done via a call to resource.getrusage, so it avoids the
30 This is done via a call to resource.getrusage, so it avoids the
33 wraparound problems in time.clock()."""
31 wraparound problems in time.clock()."""
34
32
35 return resource.getrusage(resource.RUSAGE_SELF)[0]
33 return resource.getrusage(resource.RUSAGE_SELF)[0]
36
34
37 def clocks():
35 def clocks():
38 """clocks() -> floating point number
36 """clocks() -> floating point number
39
37
40 Return the *SYSTEM* CPU time in seconds since the start of the process.
38 Return the *SYSTEM* CPU time in seconds since the start of the process.
41 This is done via a call to resource.getrusage, so it avoids the
39 This is done via a call to resource.getrusage, so it avoids the
42 wraparound problems in time.clock()."""
40 wraparound problems in time.clock()."""
43
41
44 return resource.getrusage(resource.RUSAGE_SELF)[1]
42 return resource.getrusage(resource.RUSAGE_SELF)[1]
45
43
46 def clock():
44 def clock():
47 """clock() -> floating point number
45 """clock() -> floating point number
48
46
49 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
47 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
50 the process. This is done via a call to resource.getrusage, so it
48 the process. This is done via a call to resource.getrusage, so it
51 avoids the wraparound problems in time.clock()."""
49 avoids the wraparound problems in time.clock()."""
52
50
53 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
51 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
54 return u+s
52 return u+s
55
53
56 def clock2():
54 def clock2():
57 """clock2() -> (t_user,t_system)
55 """clock2() -> (t_user,t_system)
58
56
59 Similar to clock(), but return a tuple of user/system times."""
57 Similar to clock(), but return a tuple of user/system times."""
60 return resource.getrusage(resource.RUSAGE_SELF)[:2]
58 return resource.getrusage(resource.RUSAGE_SELF)[:2]
61 except ImportError:
59 except ImportError:
62 # There is no distinction of user/system time under windows, so we just use
60 # There is no distinction of user/system time under windows, so we just use
63 # time.clock() for everything...
61 # time.clock() for everything...
64 clocku = clocks = clock = time.clock
62 clocku = clocks = clock = time.clock
65 def clock2():
63 def clock2():
66 """Under windows, system CPU time can't be measured.
64 """Under windows, system CPU time can't be measured.
67
65
68 This just returns clock() and zero."""
66 This just returns clock() and zero."""
69 return time.clock(),0.0
67 return time.clock(),0.0
70
68
71
69
72 def timings_out(reps,func,*args,**kw):
70 def timings_out(reps,func,*args,**kw):
73 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
71 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
74
72
75 Execute a function reps times, return a tuple with the elapsed total
73 Execute a function reps times, return a tuple with the elapsed total
76 CPU time in seconds, the time per call and the function's output.
74 CPU time in seconds, the time per call and the function's output.
77
75
78 Under Unix, the return value is the sum of user+system time consumed by
76 Under Unix, the return value is the sum of user+system time consumed by
79 the process, computed via the resource module. This prevents problems
77 the process, computed via the resource module. This prevents problems
80 related to the wraparound effect which the time.clock() function has.
78 related to the wraparound effect which the time.clock() function has.
81
79
82 Under Windows the return value is in wall clock seconds. See the
80 Under Windows the return value is in wall clock seconds. See the
83 documentation for the time module for more details."""
81 documentation for the time module for more details."""
84
82
85 reps = int(reps)
83 reps = int(reps)
86 assert reps >=1, 'reps must be >= 1'
84 assert reps >=1, 'reps must be >= 1'
87 if reps==1:
85 if reps==1:
88 start = clock()
86 start = clock()
89 out = func(*args,**kw)
87 out = func(*args,**kw)
90 tot_time = clock()-start
88 tot_time = clock()-start
91 else:
89 else:
92 rng = xrange(reps-1) # the last time is executed separately to store output
90 rng = range(reps-1) # the last time is executed separately to store output
93 start = clock()
91 start = clock()
94 for dummy in rng: func(*args,**kw)
92 for dummy in rng: func(*args,**kw)
95 out = func(*args,**kw) # one last time
93 out = func(*args,**kw) # one last time
96 tot_time = clock()-start
94 tot_time = clock()-start
97 av_time = tot_time / reps
95 av_time = tot_time / reps
98 return tot_time,av_time,out
96 return tot_time,av_time,out
99
97
100
98
101 def timings(reps,func,*args,**kw):
99 def timings(reps,func,*args,**kw):
102 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
100 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
103
101
104 Execute a function reps times, return a tuple with the elapsed total CPU
102 Execute a function reps times, return a tuple with the elapsed total CPU
105 time in seconds and the time per call. These are just the first two values
103 time in seconds and the time per call. These are just the first two values
106 in timings_out()."""
104 in timings_out()."""
107
105
108 return timings_out(reps,func,*args,**kw)[0:2]
106 return timings_out(reps,func,*args,**kw)[0:2]
109
107
110
108
111 def timing(func,*args,**kw):
109 def timing(func,*args,**kw):
112 """timing(func,*args,**kw) -> t_total
110 """timing(func,*args,**kw) -> t_total
113
111
114 Execute a function once, return the elapsed total CPU time in
112 Execute a function once, return the elapsed total CPU time in
115 seconds. This is just the first value in timings_out()."""
113 seconds. This is just the first value in timings_out()."""
116
114
117 return timings_out(1,func,*args,**kw)[0]
115 return timings_out(1,func,*args,**kw)[0]
118
116
@@ -1,45 +1,44 b''
1 """Wrapper around linecache which decodes files to unicode according to PEP 263.
1 """Wrapper around linecache which decodes files to unicode according to PEP 263.
2
2
3 This is only needed for Python 2 - linecache in Python 3 does the same thing
3 This is only needed for Python 2 - linecache in Python 3 does the same thing
4 itself.
4 itself.
5 """
5 """
6 import functools
6 import functools
7 import linecache
7 import linecache
8 import sys
8 import sys
9
9
10 from IPython.utils import py3compat
10 from IPython.utils import py3compat
11 from IPython.utils import openpy
11 from IPython.utils import openpy
12
12
13 if py3compat.PY3:
13 if py3compat.PY3:
14 getline = linecache.getline
14 getline = linecache.getline
15
15
16 # getlines has to be looked up at runtime, because doctests monkeypatch it.
16 # getlines has to be looked up at runtime, because doctests monkeypatch it.
17 @functools.wraps(linecache.getlines)
17 @functools.wraps(linecache.getlines)
18 def getlines(filename, module_globals=None):
18 def getlines(filename, module_globals=None):
19 return linecache.getlines(filename, module_globals=module_globals)
19 return linecache.getlines(filename, module_globals=module_globals)
20
20
21 else:
21 else:
22 def getlines(filename, module_globals=None):
22 def getlines(filename, module_globals=None):
23 """Get the lines (as unicode) for a file from the cache.
23 """Get the lines (as unicode) for a file from the cache.
24 Update the cache if it doesn't contain an entry for this file already."""
24 Update the cache if it doesn't contain an entry for this file already."""
25 filename = py3compat.cast_bytes(filename, sys.getfilesystemencoding())
25 filename = py3compat.cast_bytes(filename, sys.getfilesystemencoding())
26 lines = linecache.getlines(filename, module_globals=module_globals)
26 lines = linecache.getlines(filename, module_globals=module_globals)
27
27
28 # The bits we cache ourselves can be unicode.
28 if (not lines) or isinstance(lines[0], str):
29 if (not lines) or isinstance(lines[0], py3compat.unicode_type):
30 return lines
29 return lines
31
30
32 readline = openpy._list_readline(lines)
31 readline = openpy._list_readline(lines)
33 try:
32 try:
34 encoding, _ = openpy.detect_encoding(readline)
33 encoding, _ = openpy.detect_encoding(readline)
35 except SyntaxError:
34 except SyntaxError:
36 encoding = 'ascii'
35 encoding = 'ascii'
37 return [l.decode(encoding, 'replace') for l in lines]
36 return [l.decode(encoding, 'replace') for l in lines]
38
37
39 # This is a straight copy of linecache.getline
38 # This is a straight copy of linecache.getline
40 def getline(filename, lineno, module_globals=None):
39 def getline(filename, lineno, module_globals=None):
41 lines = getlines(filename, module_globals)
40 lines = getlines(filename, module_globals)
42 if 1 <= lineno <= len(lines):
41 if 1 <= lineno <= len(lines):
43 return lines[lineno-1]
42 return lines[lineno-1]
44 else:
43 else:
45 return ''
44 return ''
@@ -1,112 +1,111 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Support for wildcard pattern matching in object inspection.
2 """Support for wildcard pattern matching in object inspection.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 - Jörgen Stenarson <jorgen.stenarson@bostream.nu>
6 - Jörgen Stenarson <jorgen.stenarson@bostream.nu>
7 - Thomas Kluyver
7 - Thomas Kluyver
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2005 Jörgen Stenarson <jorgen.stenarson@bostream.nu>
11 # Copyright (C) 2005 Jörgen Stenarson <jorgen.stenarson@bostream.nu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 import re
17 import re
18 import types
18 import types
19
19
20 from IPython.utils.dir2 import dir2
20 from IPython.utils.dir2 import dir2
21 from .py3compat import iteritems
22
21
23 def create_typestr2type_dicts(dont_include_in_type2typestr=["lambda"]):
22 def create_typestr2type_dicts(dont_include_in_type2typestr=["lambda"]):
24 """Return dictionaries mapping lower case typename (e.g. 'tuple') to type
23 """Return dictionaries mapping lower case typename (e.g. 'tuple') to type
25 objects from the types package, and vice versa."""
24 objects from the types package, and vice versa."""
26 typenamelist = [tname for tname in dir(types) if tname.endswith("Type")]
25 typenamelist = [tname for tname in dir(types) if tname.endswith("Type")]
27 typestr2type, type2typestr = {}, {}
26 typestr2type, type2typestr = {}, {}
28
27
29 for tname in typenamelist:
28 for tname in typenamelist:
30 name = tname[:-4].lower() # Cut 'Type' off the end of the name
29 name = tname[:-4].lower() # Cut 'Type' off the end of the name
31 obj = getattr(types, tname)
30 obj = getattr(types, tname)
32 typestr2type[name] = obj
31 typestr2type[name] = obj
33 if name not in dont_include_in_type2typestr:
32 if name not in dont_include_in_type2typestr:
34 type2typestr[obj] = name
33 type2typestr[obj] = name
35 return typestr2type, type2typestr
34 return typestr2type, type2typestr
36
35
37 typestr2type, type2typestr = create_typestr2type_dicts()
36 typestr2type, type2typestr = create_typestr2type_dicts()
38
37
39 def is_type(obj, typestr_or_type):
38 def is_type(obj, typestr_or_type):
40 """is_type(obj, typestr_or_type) verifies if obj is of a certain type. It
39 """is_type(obj, typestr_or_type) verifies if obj is of a certain type. It
41 can take strings or actual python types for the second argument, i.e.
40 can take strings or actual python types for the second argument, i.e.
42 'tuple'<->TupleType. 'all' matches all types.
41 'tuple'<->TupleType. 'all' matches all types.
43
42
44 TODO: Should be extended for choosing more than one type."""
43 TODO: Should be extended for choosing more than one type."""
45 if typestr_or_type == "all":
44 if typestr_or_type == "all":
46 return True
45 return True
47 if type(typestr_or_type) == type:
46 if type(typestr_or_type) == type:
48 test_type = typestr_or_type
47 test_type = typestr_or_type
49 else:
48 else:
50 test_type = typestr2type.get(typestr_or_type, False)
49 test_type = typestr2type.get(typestr_or_type, False)
51 if test_type:
50 if test_type:
52 return isinstance(obj, test_type)
51 return isinstance(obj, test_type)
53 return False
52 return False
54
53
55 def show_hidden(str, show_all=False):
54 def show_hidden(str, show_all=False):
56 """Return true for strings starting with single _ if show_all is true."""
55 """Return true for strings starting with single _ if show_all is true."""
57 return show_all or str.startswith("__") or not str.startswith("_")
56 return show_all or str.startswith("__") or not str.startswith("_")
58
57
59 def dict_dir(obj):
58 def dict_dir(obj):
60 """Produce a dictionary of an object's attributes. Builds on dir2 by
59 """Produce a dictionary of an object's attributes. Builds on dir2 by
61 checking that a getattr() call actually succeeds."""
60 checking that a getattr() call actually succeeds."""
62 ns = {}
61 ns = {}
63 for key in dir2(obj):
62 for key in dir2(obj):
64 # This seemingly unnecessary try/except is actually needed
63 # This seemingly unnecessary try/except is actually needed
65 # because there is code out there with metaclasses that
64 # because there is code out there with metaclasses that
66 # create 'write only' attributes, where a getattr() call
65 # create 'write only' attributes, where a getattr() call
67 # will fail even if the attribute appears listed in the
66 # will fail even if the attribute appears listed in the
68 # object's dictionary. Properties can actually do the same
67 # object's dictionary. Properties can actually do the same
69 # thing. In particular, Traits use this pattern
68 # thing. In particular, Traits use this pattern
70 try:
69 try:
71 ns[key] = getattr(obj, key)
70 ns[key] = getattr(obj, key)
72 except AttributeError:
71 except AttributeError:
73 pass
72 pass
74 return ns
73 return ns
75
74
76 def filter_ns(ns, name_pattern="*", type_pattern="all", ignore_case=True,
75 def filter_ns(ns, name_pattern="*", type_pattern="all", ignore_case=True,
77 show_all=True):
76 show_all=True):
78 """Filter a namespace dictionary by name pattern and item type."""
77 """Filter a namespace dictionary by name pattern and item type."""
79 pattern = name_pattern.replace("*",".*").replace("?",".")
78 pattern = name_pattern.replace("*",".*").replace("?",".")
80 if ignore_case:
79 if ignore_case:
81 reg = re.compile(pattern+"$", re.I)
80 reg = re.compile(pattern+"$", re.I)
82 else:
81 else:
83 reg = re.compile(pattern+"$")
82 reg = re.compile(pattern+"$")
84
83
85 # Check each one matches regex; shouldn't be hidden; of correct type.
84 # Check each one matches regex; shouldn't be hidden; of correct type.
86 return dict((key,obj) for key, obj in iteritems(ns) if reg.match(key) \
85 return dict((key,obj) for key, obj in ns.items() if reg.match(key) \
87 and show_hidden(key, show_all) \
86 and show_hidden(key, show_all) \
88 and is_type(obj, type_pattern) )
87 and is_type(obj, type_pattern) )
89
88
90 def list_namespace(namespace, type_pattern, filter, ignore_case=False, show_all=False):
89 def list_namespace(namespace, type_pattern, filter, ignore_case=False, show_all=False):
91 """Return dictionary of all objects in a namespace dictionary that match
90 """Return dictionary of all objects in a namespace dictionary that match
92 type_pattern and filter."""
91 type_pattern and filter."""
93 pattern_list=filter.split(".")
92 pattern_list=filter.split(".")
94 if len(pattern_list) == 1:
93 if len(pattern_list) == 1:
95 return filter_ns(namespace, name_pattern=pattern_list[0],
94 return filter_ns(namespace, name_pattern=pattern_list[0],
96 type_pattern=type_pattern,
95 type_pattern=type_pattern,
97 ignore_case=ignore_case, show_all=show_all)
96 ignore_case=ignore_case, show_all=show_all)
98 else:
97 else:
99 # This is where we can change if all objects should be searched or
98 # This is where we can change if all objects should be searched or
100 # only modules. Just change the type_pattern to module to search only
99 # only modules. Just change the type_pattern to module to search only
101 # modules
100 # modules
102 filtered = filter_ns(namespace, name_pattern=pattern_list[0],
101 filtered = filter_ns(namespace, name_pattern=pattern_list[0],
103 type_pattern="all",
102 type_pattern="all",
104 ignore_case=ignore_case, show_all=show_all)
103 ignore_case=ignore_case, show_all=show_all)
105 results = {}
104 results = {}
106 for name, obj in iteritems(filtered):
105 for name, obj in filtered.items():
107 ns = list_namespace(dict_dir(obj), type_pattern,
106 ns = list_namespace(dict_dir(obj), type_pattern,
108 ".".join(pattern_list[1:]),
107 ".".join(pattern_list[1:]),
109 ignore_case=ignore_case, show_all=show_all)
108 ignore_case=ignore_case, show_all=show_all)
110 for inner_name, inner_obj in iteritems(ns):
109 for inner_name, inner_obj in ns.items():
111 results["%s.%s"%(name,inner_name)] = inner_obj
110 results["%s.%s"%(name,inner_name)] = inner_obj
112 return results
111 return results
General Comments 0
You need to be logged in to leave comments. Login now