##// END OF EJS Templates
FIX CVE-2022-21699...
Matthias Bussonnier -
r27463:c306d208 5.x
parent child Browse files
Show More
@@ -1,146 +1,150 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IPython: tools for interactive and parallel computing in Python.
3 IPython: tools for interactive and parallel computing in Python.
4
4
5 http://ipython.org
5 http://ipython.org
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2008-2011, IPython Development Team.
8 # Copyright (c) 2008-2011, IPython Development Team.
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
12 #
12 #
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14 #
14 #
15 # The full license is in the file COPYING.txt, distributed with this software.
15 # The full license is in the file COPYING.txt, distributed with this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 from __future__ import absolute_import
21 from __future__ import absolute_import
22
22
23 import os
23 import os
24 import sys
24 import sys
25 import warnings
25 import warnings
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Setup everything
28 # Setup everything
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 # Don't forget to also update setup.py when this changes!
31 # Don't forget to also update setup.py when this changes!
32 v = sys.version_info
32 v = sys.version_info
33 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
33 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
34 raise ImportError('IPython requires Python version 2.7 or 3.3 or above.')
34 raise ImportError('IPython requires Python version 2.7 or 3.3 or above.')
35 del v
35 del v
36
36
37 # Make it easy to import extensions - they are always directly on pythonpath.
37 # Make it easy to import extensions - they are always directly on pythonpath.
38 # Therefore, non-IPython modules can be added to extensions directory.
38 # Therefore, non-IPython modules can be added to extensions directory.
39 # This should probably be in ipapp.py.
39 # This should probably be in ipapp.py.
40 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
40 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Setup the top level names
43 # Setup the top level names
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 from .core.getipython import get_ipython
46 from .core.getipython import get_ipython
47 from .core import release
47 from .core import release
48 from .core.application import Application
48 from .core.application import Application
49 from .terminal.embed import embed
49 from .terminal.embed import embed
50
50
51 from .core.interactiveshell import InteractiveShell
51 from .core.interactiveshell import InteractiveShell
52 from .testing import test
52 from .testing import test
53 from .utils.sysinfo import sys_info
53 from .utils.sysinfo import sys_info
54 from .utils.frame import extract_module_locals
54 from .utils.frame import extract_module_locals
55
55
56 # Release data
56 # Release data
57 __author__ = '%s <%s>' % (release.author, release.author_email)
57 __author__ = '%s <%s>' % (release.author, release.author_email)
58 __license__ = release.license
58 __license__ = release.license
59 __version__ = release.version
59 __version__ = release.version
60 version_info = release.version_info
60 version_info = release.version_info
61 # list of CVEs that should have been patched in this release.
62 # this is informational and should not be relied upon.
63 __patched_cves__ = {"CVE-2022-21699"}
64
61
65
62 def embed_kernel(module=None, local_ns=None, **kwargs):
66 def embed_kernel(module=None, local_ns=None, **kwargs):
63 """Embed and start an IPython kernel in a given scope.
67 """Embed and start an IPython kernel in a given scope.
64
68
65 If you don't want the kernel to initialize the namespace
69 If you don't want the kernel to initialize the namespace
66 from the scope of the surrounding function,
70 from the scope of the surrounding function,
67 and/or you want to load full IPython configuration,
71 and/or you want to load full IPython configuration,
68 you probably want `IPython.start_kernel()` instead.
72 you probably want `IPython.start_kernel()` instead.
69
73
70 Parameters
74 Parameters
71 ----------
75 ----------
72 module : ModuleType, optional
76 module : ModuleType, optional
73 The module to load into IPython globals (default: caller)
77 The module to load into IPython globals (default: caller)
74 local_ns : dict, optional
78 local_ns : dict, optional
75 The namespace to load into IPython user namespace (default: caller)
79 The namespace to load into IPython user namespace (default: caller)
76
80
77 kwargs : various, optional
81 kwargs : various, optional
78 Further keyword args are relayed to the IPKernelApp constructor,
82 Further keyword args are relayed to the IPKernelApp constructor,
79 allowing configuration of the Kernel. Will only have an effect
83 allowing configuration of the Kernel. Will only have an effect
80 on the first embed_kernel call for a given process.
84 on the first embed_kernel call for a given process.
81 """
85 """
82
86
83 (caller_module, caller_locals) = extract_module_locals(1)
87 (caller_module, caller_locals) = extract_module_locals(1)
84 if module is None:
88 if module is None:
85 module = caller_module
89 module = caller_module
86 if local_ns is None:
90 if local_ns is None:
87 local_ns = caller_locals
91 local_ns = caller_locals
88
92
89 # Only import .zmq when we really need it
93 # Only import .zmq when we really need it
90 from ipykernel.embed import embed_kernel as real_embed_kernel
94 from ipykernel.embed import embed_kernel as real_embed_kernel
91 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
95 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
92
96
93 def start_ipython(argv=None, **kwargs):
97 def start_ipython(argv=None, **kwargs):
94 """Launch a normal IPython instance (as opposed to embedded)
98 """Launch a normal IPython instance (as opposed to embedded)
95
99
96 `IPython.embed()` puts a shell in a particular calling scope,
100 `IPython.embed()` puts a shell in a particular calling scope,
97 such as a function or method for debugging purposes,
101 such as a function or method for debugging purposes,
98 which is often not desirable.
102 which is often not desirable.
99
103
100 `start_ipython()` does full, regular IPython initialization,
104 `start_ipython()` does full, regular IPython initialization,
101 including loading startup files, configuration, etc.
105 including loading startup files, configuration, etc.
102 much of which is skipped by `embed()`.
106 much of which is skipped by `embed()`.
103
107
104 This is a public API method, and will survive implementation changes.
108 This is a public API method, and will survive implementation changes.
105
109
106 Parameters
110 Parameters
107 ----------
111 ----------
108
112
109 argv : list or None, optional
113 argv : list or None, optional
110 If unspecified or None, IPython will parse command-line options from sys.argv.
114 If unspecified or None, IPython will parse command-line options from sys.argv.
111 To prevent any command-line parsing, pass an empty list: `argv=[]`.
115 To prevent any command-line parsing, pass an empty list: `argv=[]`.
112 user_ns : dict, optional
116 user_ns : dict, optional
113 specify this dictionary to initialize the IPython user namespace with particular values.
117 specify this dictionary to initialize the IPython user namespace with particular values.
114 kwargs : various, optional
118 kwargs : various, optional
115 Any other kwargs will be passed to the Application constructor,
119 Any other kwargs will be passed to the Application constructor,
116 such as `config`.
120 such as `config`.
117 """
121 """
118 from IPython.terminal.ipapp import launch_new_instance
122 from IPython.terminal.ipapp import launch_new_instance
119 return launch_new_instance(argv=argv, **kwargs)
123 return launch_new_instance(argv=argv, **kwargs)
120
124
121 def start_kernel(argv=None, **kwargs):
125 def start_kernel(argv=None, **kwargs):
122 """Launch a normal IPython kernel instance (as opposed to embedded)
126 """Launch a normal IPython kernel instance (as opposed to embedded)
123
127
124 `IPython.embed_kernel()` puts a shell in a particular calling scope,
128 `IPython.embed_kernel()` puts a shell in a particular calling scope,
125 such as a function or method for debugging purposes,
129 such as a function or method for debugging purposes,
126 which is often not desirable.
130 which is often not desirable.
127
131
128 `start_kernel()` does full, regular IPython initialization,
132 `start_kernel()` does full, regular IPython initialization,
129 including loading startup files, configuration, etc.
133 including loading startup files, configuration, etc.
130 much of which is skipped by `embed()`.
134 much of which is skipped by `embed()`.
131
135
132 Parameters
136 Parameters
133 ----------
137 ----------
134
138
135 argv : list or None, optional
139 argv : list or None, optional
136 If unspecified or None, IPython will parse command-line options from sys.argv.
140 If unspecified or None, IPython will parse command-line options from sys.argv.
137 To prevent any command-line parsing, pass an empty list: `argv=[]`.
141 To prevent any command-line parsing, pass an empty list: `argv=[]`.
138 user_ns : dict, optional
142 user_ns : dict, optional
139 specify this dictionary to initialize the IPython user namespace with particular values.
143 specify this dictionary to initialize the IPython user namespace with particular values.
140 kwargs : various, optional
144 kwargs : various, optional
141 Any other kwargs will be passed to the Application constructor,
145 Any other kwargs will be passed to the Application constructor,
142 such as `config`.
146 such as `config`.
143 """
147 """
144 from IPython.kernel.zmq.kernelapp import launch_new_instance
148 from IPython.kernel.zmq.kernelapp import launch_new_instance
145 return launch_new_instance(argv=argv, **kwargs)
149 return launch_new_instance(argv=argv, **kwargs)
146
150
@@ -1,467 +1,467 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
47
48 ENV_CONFIG_DIRS = []
48 ENV_CONFIG_DIRS = []
49 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
49 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
50 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
50 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
51 # only add ENV_CONFIG if sys.prefix is not already included
51 # only add ENV_CONFIG if sys.prefix is not already included
52 ENV_CONFIG_DIRS.append(_env_config_dir)
52 ENV_CONFIG_DIRS.append(_env_config_dir)
53
53
54
54
55 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
55 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
56 if _envvar in {None, ''}:
56 if _envvar in {None, ''}:
57 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
57 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
58 else:
58 else:
59 if _envvar.lower() in {'1','true'}:
59 if _envvar.lower() in {'1','true'}:
60 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
60 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
61 elif _envvar.lower() in {'0','false'} :
61 elif _envvar.lower() in {'0','false'} :
62 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
62 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
63 else:
63 else:
64 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
64 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
65
65
66 # aliases and flags
66 # aliases and flags
67
67
68 base_aliases = {
68 base_aliases = {
69 'profile-dir' : 'ProfileDir.location',
69 'profile-dir' : 'ProfileDir.location',
70 'profile' : 'BaseIPythonApplication.profile',
70 'profile' : 'BaseIPythonApplication.profile',
71 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
71 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
72 'log-level' : 'Application.log_level',
72 'log-level' : 'Application.log_level',
73 'config' : 'BaseIPythonApplication.extra_config_file',
73 'config' : 'BaseIPythonApplication.extra_config_file',
74 }
74 }
75
75
76 base_flags = dict(
76 base_flags = dict(
77 debug = ({'Application' : {'log_level' : logging.DEBUG}},
77 debug = ({'Application' : {'log_level' : logging.DEBUG}},
78 "set log level to logging.DEBUG (maximize logging output)"),
78 "set log level to logging.DEBUG (maximize logging output)"),
79 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
79 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
80 "set log level to logging.CRITICAL (minimize logging output)"),
80 "set log level to logging.CRITICAL (minimize logging output)"),
81 init = ({'BaseIPythonApplication' : {
81 init = ({'BaseIPythonApplication' : {
82 'copy_config_files' : True,
82 'copy_config_files' : True,
83 'auto_create' : True}
83 'auto_create' : True}
84 }, """Initialize profile with default config files. This is equivalent
84 }, """Initialize profile with default config files. This is equivalent
85 to running `ipython profile create <profile>` prior to startup.
85 to running `ipython profile create <profile>` prior to startup.
86 """)
86 """)
87 )
87 )
88
88
89 class ProfileAwareConfigLoader(PyFileConfigLoader):
89 class ProfileAwareConfigLoader(PyFileConfigLoader):
90 """A Python file config loader that is aware of IPython profiles."""
90 """A Python file config loader that is aware of IPython profiles."""
91 def load_subconfig(self, fname, path=None, profile=None):
91 def load_subconfig(self, fname, path=None, profile=None):
92 if profile is not None:
92 if profile is not None:
93 try:
93 try:
94 profile_dir = ProfileDir.find_profile_dir_by_name(
94 profile_dir = ProfileDir.find_profile_dir_by_name(
95 get_ipython_dir(),
95 get_ipython_dir(),
96 profile,
96 profile,
97 )
97 )
98 except ProfileDirError:
98 except ProfileDirError:
99 return
99 return
100 path = profile_dir.location
100 path = profile_dir.location
101 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
101 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
102
102
103 class BaseIPythonApplication(Application):
103 class BaseIPythonApplication(Application):
104
104
105 name = Unicode(u'ipython')
105 name = Unicode(u'ipython')
106 description = Unicode(u'IPython: an enhanced interactive Python shell.')
106 description = Unicode(u'IPython: an enhanced interactive Python shell.')
107 version = Unicode(release.version)
107 version = Unicode(release.version)
108
108
109 aliases = Dict(base_aliases)
109 aliases = Dict(base_aliases)
110 flags = Dict(base_flags)
110 flags = Dict(base_flags)
111 classes = List([ProfileDir])
111 classes = List([ProfileDir])
112
112
113 # enable `load_subconfig('cfg.py', profile='name')`
113 # enable `load_subconfig('cfg.py', profile='name')`
114 python_config_loader_class = ProfileAwareConfigLoader
114 python_config_loader_class = ProfileAwareConfigLoader
115
115
116 # Track whether the config_file has changed,
116 # Track whether the config_file has changed,
117 # because some logic happens only if we aren't using the default.
117 # because some logic happens only if we aren't using the default.
118 config_file_specified = Set()
118 config_file_specified = Set()
119
119
120 config_file_name = Unicode()
120 config_file_name = Unicode()
121 @default('config_file_name')
121 @default('config_file_name')
122 def _config_file_name_default(self):
122 def _config_file_name_default(self):
123 return self.name.replace('-','_') + u'_config.py'
123 return self.name.replace('-','_') + u'_config.py'
124 @observe('config_file_name')
124 @observe('config_file_name')
125 def _config_file_name_changed(self, change):
125 def _config_file_name_changed(self, change):
126 if change['new'] != change['old']:
126 if change['new'] != change['old']:
127 self.config_file_specified.add(change['new'])
127 self.config_file_specified.add(change['new'])
128
128
129 # The directory that contains IPython's builtin profiles.
129 # The directory that contains IPython's builtin profiles.
130 builtin_profile_dir = Unicode(
130 builtin_profile_dir = Unicode(
131 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
131 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
132 )
132 )
133
133
134 config_file_paths = List(Unicode())
134 config_file_paths = List(Unicode())
135 @default('config_file_paths')
135 @default('config_file_paths')
136 def _config_file_paths_default(self):
136 def _config_file_paths_default(self):
137 return [py3compat.getcwd()]
137 return []
138
138
139 extra_config_file = Unicode(
139 extra_config_file = Unicode(
140 help="""Path to an extra config file to load.
140 help="""Path to an extra config file to load.
141
141
142 If specified, load this config file in addition to any other IPython config.
142 If specified, load this config file in addition to any other IPython config.
143 """).tag(config=True)
143 """).tag(config=True)
144 @observe('extra_config_file')
144 @observe('extra_config_file')
145 def _extra_config_file_changed(self, change):
145 def _extra_config_file_changed(self, change):
146 old = change['old']
146 old = change['old']
147 new = change['new']
147 new = change['new']
148 try:
148 try:
149 self.config_files.remove(old)
149 self.config_files.remove(old)
150 except ValueError:
150 except ValueError:
151 pass
151 pass
152 self.config_file_specified.add(new)
152 self.config_file_specified.add(new)
153 self.config_files.append(new)
153 self.config_files.append(new)
154
154
155 profile = Unicode(u'default',
155 profile = Unicode(u'default',
156 help="""The IPython profile to use."""
156 help="""The IPython profile to use."""
157 ).tag(config=True)
157 ).tag(config=True)
158
158
159 @observe('profile')
159 @observe('profile')
160 def _profile_changed(self, change):
160 def _profile_changed(self, change):
161 self.builtin_profile_dir = os.path.join(
161 self.builtin_profile_dir = os.path.join(
162 get_ipython_package_dir(), u'config', u'profile', change['new']
162 get_ipython_package_dir(), u'config', u'profile', change['new']
163 )
163 )
164
164
165 ipython_dir = Unicode(
165 ipython_dir = Unicode(
166 help="""
166 help="""
167 The name of the IPython directory. This directory is used for logging
167 The name of the IPython directory. This directory is used for logging
168 configuration (through profiles), history storage, etc. The default
168 configuration (through profiles), history storage, etc. The default
169 is usually $HOME/.ipython. This option can also be specified through
169 is usually $HOME/.ipython. This option can also be specified through
170 the environment variable IPYTHONDIR.
170 the environment variable IPYTHONDIR.
171 """
171 """
172 ).tag(config=True)
172 ).tag(config=True)
173 @default('ipython_dir')
173 @default('ipython_dir')
174 def _ipython_dir_default(self):
174 def _ipython_dir_default(self):
175 d = get_ipython_dir()
175 d = get_ipython_dir()
176 self._ipython_dir_changed({
176 self._ipython_dir_changed({
177 'name': 'ipython_dir',
177 'name': 'ipython_dir',
178 'old': d,
178 'old': d,
179 'new': d,
179 'new': d,
180 })
180 })
181 return d
181 return d
182
182
183 _in_init_profile_dir = False
183 _in_init_profile_dir = False
184 profile_dir = Instance(ProfileDir, allow_none=True)
184 profile_dir = Instance(ProfileDir, allow_none=True)
185 @default('profile_dir')
185 @default('profile_dir')
186 def _profile_dir_default(self):
186 def _profile_dir_default(self):
187 # avoid recursion
187 # avoid recursion
188 if self._in_init_profile_dir:
188 if self._in_init_profile_dir:
189 return
189 return
190 # profile_dir requested early, force initialization
190 # profile_dir requested early, force initialization
191 self.init_profile_dir()
191 self.init_profile_dir()
192 return self.profile_dir
192 return self.profile_dir
193
193
194 overwrite = Bool(False,
194 overwrite = Bool(False,
195 help="""Whether to overwrite existing config files when copying"""
195 help="""Whether to overwrite existing config files when copying"""
196 ).tag(config=True)
196 ).tag(config=True)
197 auto_create = Bool(False,
197 auto_create = Bool(False,
198 help="""Whether to create profile dir if it doesn't exist"""
198 help="""Whether to create profile dir if it doesn't exist"""
199 ).tag(config=True)
199 ).tag(config=True)
200
200
201 config_files = List(Unicode())
201 config_files = List(Unicode())
202 @default('config_files')
202 @default('config_files')
203 def _config_files_default(self):
203 def _config_files_default(self):
204 return [self.config_file_name]
204 return [self.config_file_name]
205
205
206 copy_config_files = Bool(False,
206 copy_config_files = Bool(False,
207 help="""Whether to install the default config files into the profile dir.
207 help="""Whether to install the default config files into the profile dir.
208 If a new profile is being created, and IPython contains config files for that
208 If a new profile is being created, and IPython contains config files for that
209 profile, then they will be staged into the new directory. Otherwise,
209 profile, then they will be staged into the new directory. Otherwise,
210 default config files will be automatically generated.
210 default config files will be automatically generated.
211 """).tag(config=True)
211 """).tag(config=True)
212
212
213 verbose_crash = Bool(False,
213 verbose_crash = Bool(False,
214 help="""Create a massive crash report when IPython encounters what may be an
214 help="""Create a massive crash report when IPython encounters what may be an
215 internal error. The default is to append a short message to the
215 internal error. The default is to append a short message to the
216 usual traceback""").tag(config=True)
216 usual traceback""").tag(config=True)
217
217
218 # The class to use as the crash handler.
218 # The class to use as the crash handler.
219 crash_handler_class = Type(crashhandler.CrashHandler)
219 crash_handler_class = Type(crashhandler.CrashHandler)
220
220
221 @catch_config_error
221 @catch_config_error
222 def __init__(self, **kwargs):
222 def __init__(self, **kwargs):
223 super(BaseIPythonApplication, self).__init__(**kwargs)
223 super(BaseIPythonApplication, self).__init__(**kwargs)
224 # ensure current working directory exists
224 # ensure current working directory exists
225 try:
225 try:
226 py3compat.getcwd()
226 py3compat.getcwd()
227 except:
227 except:
228 # exit if cwd doesn't exist
228 # exit if cwd doesn't exist
229 self.log.error("Current working directory doesn't exist.")
229 self.log.error("Current working directory doesn't exist.")
230 self.exit(1)
230 self.exit(1)
231
231
232 #-------------------------------------------------------------------------
232 #-------------------------------------------------------------------------
233 # Various stages of Application creation
233 # Various stages of Application creation
234 #-------------------------------------------------------------------------
234 #-------------------------------------------------------------------------
235
235
236 deprecated_subcommands = {}
236 deprecated_subcommands = {}
237
237
238 def initialize_subcommand(self, subc, argv=None):
238 def initialize_subcommand(self, subc, argv=None):
239 if subc in self.deprecated_subcommands:
239 if subc in self.deprecated_subcommands:
240 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
240 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
241 "in future versions.".format(sub=subc))
241 "in future versions.".format(sub=subc))
242 self.log.warning("You likely want to use `jupyter {sub}` in the "
242 self.log.warning("You likely want to use `jupyter {sub}` in the "
243 "future".format(sub=subc))
243 "future".format(sub=subc))
244 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
244 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
245
245
246 def init_crash_handler(self):
246 def init_crash_handler(self):
247 """Create a crash handler, typically setting sys.excepthook to it."""
247 """Create a crash handler, typically setting sys.excepthook to it."""
248 self.crash_handler = self.crash_handler_class(self)
248 self.crash_handler = self.crash_handler_class(self)
249 sys.excepthook = self.excepthook
249 sys.excepthook = self.excepthook
250 def unset_crashhandler():
250 def unset_crashhandler():
251 sys.excepthook = sys.__excepthook__
251 sys.excepthook = sys.__excepthook__
252 atexit.register(unset_crashhandler)
252 atexit.register(unset_crashhandler)
253
253
254 def excepthook(self, etype, evalue, tb):
254 def excepthook(self, etype, evalue, tb):
255 """this is sys.excepthook after init_crashhandler
255 """this is sys.excepthook after init_crashhandler
256
256
257 set self.verbose_crash=True to use our full crashhandler, instead of
257 set self.verbose_crash=True to use our full crashhandler, instead of
258 a regular traceback with a short message (crash_handler_lite)
258 a regular traceback with a short message (crash_handler_lite)
259 """
259 """
260
260
261 if self.verbose_crash:
261 if self.verbose_crash:
262 return self.crash_handler(etype, evalue, tb)
262 return self.crash_handler(etype, evalue, tb)
263 else:
263 else:
264 return crashhandler.crash_handler_lite(etype, evalue, tb)
264 return crashhandler.crash_handler_lite(etype, evalue, tb)
265
265
266 @observe('ipython_dir')
266 @observe('ipython_dir')
267 def _ipython_dir_changed(self, change):
267 def _ipython_dir_changed(self, change):
268 old = change['old']
268 old = change['old']
269 new = change['new']
269 new = change['new']
270 if old is not Undefined:
270 if old is not Undefined:
271 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
271 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
272 sys.getfilesystemencoding()
272 sys.getfilesystemencoding()
273 )
273 )
274 if str_old in sys.path:
274 if str_old in sys.path:
275 sys.path.remove(str_old)
275 sys.path.remove(str_old)
276 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
276 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
277 sys.getfilesystemencoding()
277 sys.getfilesystemencoding()
278 )
278 )
279 sys.path.append(str_path)
279 sys.path.append(str_path)
280 ensure_dir_exists(new)
280 ensure_dir_exists(new)
281 readme = os.path.join(new, 'README')
281 readme = os.path.join(new, 'README')
282 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
282 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
283 if not os.path.exists(readme) and os.path.exists(readme_src):
283 if not os.path.exists(readme) and os.path.exists(readme_src):
284 shutil.copy(readme_src, readme)
284 shutil.copy(readme_src, readme)
285 for d in ('extensions', 'nbextensions'):
285 for d in ('extensions', 'nbextensions'):
286 path = os.path.join(new, d)
286 path = os.path.join(new, d)
287 try:
287 try:
288 ensure_dir_exists(path)
288 ensure_dir_exists(path)
289 except OSError as e:
289 except OSError as e:
290 # this will not be EEXIST
290 # this will not be EEXIST
291 self.log.error("couldn't create path %s: %s", path, e)
291 self.log.error("couldn't create path %s: %s", path, e)
292 self.log.debug("IPYTHONDIR set to: %s" % new)
292 self.log.debug("IPYTHONDIR set to: %s" % new)
293
293
294 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
294 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
295 """Load the config file.
295 """Load the config file.
296
296
297 By default, errors in loading config are handled, and a warning
297 By default, errors in loading config are handled, and a warning
298 printed on screen. For testing, the suppress_errors option is set
298 printed on screen. For testing, the suppress_errors option is set
299 to False, so errors will make tests fail.
299 to False, so errors will make tests fail.
300
300
301 `supress_errors` default value is to be `None` in which case the
301 `supress_errors` default value is to be `None` in which case the
302 behavior default to the one of `traitlets.Application`.
302 behavior default to the one of `traitlets.Application`.
303
303
304 The default value can be set :
304 The default value can be set :
305 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
305 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
306 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
306 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
307 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
307 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
308
308
309 Any other value are invalid, and will make IPython exit with a non-zero return code.
309 Any other value are invalid, and will make IPython exit with a non-zero return code.
310 """
310 """
311
311
312
312
313 self.log.debug("Searching path %s for config files", self.config_file_paths)
313 self.log.debug("Searching path %s for config files", self.config_file_paths)
314 base_config = 'ipython_config.py'
314 base_config = 'ipython_config.py'
315 self.log.debug("Attempting to load config file: %s" %
315 self.log.debug("Attempting to load config file: %s" %
316 base_config)
316 base_config)
317 try:
317 try:
318 if suppress_errors is not None:
318 if suppress_errors is not None:
319 old_value = Application.raise_config_file_errors
319 old_value = Application.raise_config_file_errors
320 Application.raise_config_file_errors = not suppress_errors;
320 Application.raise_config_file_errors = not suppress_errors;
321 Application.load_config_file(
321 Application.load_config_file(
322 self,
322 self,
323 base_config,
323 base_config,
324 path=self.config_file_paths
324 path=self.config_file_paths
325 )
325 )
326 except ConfigFileNotFound:
326 except ConfigFileNotFound:
327 # ignore errors loading parent
327 # ignore errors loading parent
328 self.log.debug("Config file %s not found", base_config)
328 self.log.debug("Config file %s not found", base_config)
329 pass
329 pass
330 if suppress_errors is not None:
330 if suppress_errors is not None:
331 Application.raise_config_file_errors = old_value
331 Application.raise_config_file_errors = old_value
332
332
333 for config_file_name in self.config_files:
333 for config_file_name in self.config_files:
334 if not config_file_name or config_file_name == base_config:
334 if not config_file_name or config_file_name == base_config:
335 continue
335 continue
336 self.log.debug("Attempting to load config file: %s" %
336 self.log.debug("Attempting to load config file: %s" %
337 self.config_file_name)
337 self.config_file_name)
338 try:
338 try:
339 Application.load_config_file(
339 Application.load_config_file(
340 self,
340 self,
341 config_file_name,
341 config_file_name,
342 path=self.config_file_paths
342 path=self.config_file_paths
343 )
343 )
344 except ConfigFileNotFound:
344 except ConfigFileNotFound:
345 # Only warn if the default config file was NOT being used.
345 # Only warn if the default config file was NOT being used.
346 if config_file_name in self.config_file_specified:
346 if config_file_name in self.config_file_specified:
347 msg = self.log.warning
347 msg = self.log.warning
348 else:
348 else:
349 msg = self.log.debug
349 msg = self.log.debug
350 msg("Config file not found, skipping: %s", config_file_name)
350 msg("Config file not found, skipping: %s", config_file_name)
351 except Exception:
351 except Exception:
352 # For testing purposes.
352 # For testing purposes.
353 if not suppress_errors:
353 if not suppress_errors:
354 raise
354 raise
355 self.log.warning("Error loading config file: %s" %
355 self.log.warning("Error loading config file: %s" %
356 self.config_file_name, exc_info=True)
356 self.config_file_name, exc_info=True)
357
357
358 def init_profile_dir(self):
358 def init_profile_dir(self):
359 """initialize the profile dir"""
359 """initialize the profile dir"""
360 self._in_init_profile_dir = True
360 self._in_init_profile_dir = True
361 if self.profile_dir is not None:
361 if self.profile_dir is not None:
362 # already ran
362 # already ran
363 return
363 return
364 if 'ProfileDir.location' not in self.config:
364 if 'ProfileDir.location' not in self.config:
365 # location not specified, find by profile name
365 # location not specified, find by profile name
366 try:
366 try:
367 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
367 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
368 except ProfileDirError:
368 except ProfileDirError:
369 # not found, maybe create it (always create default profile)
369 # not found, maybe create it (always create default profile)
370 if self.auto_create or self.profile == 'default':
370 if self.auto_create or self.profile == 'default':
371 try:
371 try:
372 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
372 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
373 except ProfileDirError:
373 except ProfileDirError:
374 self.log.fatal("Could not create profile: %r"%self.profile)
374 self.log.fatal("Could not create profile: %r"%self.profile)
375 self.exit(1)
375 self.exit(1)
376 else:
376 else:
377 self.log.info("Created profile dir: %r"%p.location)
377 self.log.info("Created profile dir: %r"%p.location)
378 else:
378 else:
379 self.log.fatal("Profile %r not found."%self.profile)
379 self.log.fatal("Profile %r not found."%self.profile)
380 self.exit(1)
380 self.exit(1)
381 else:
381 else:
382 self.log.debug("Using existing profile dir: %r"%p.location)
382 self.log.debug("Using existing profile dir: %r"%p.location)
383 else:
383 else:
384 location = self.config.ProfileDir.location
384 location = self.config.ProfileDir.location
385 # location is fully specified
385 # location is fully specified
386 try:
386 try:
387 p = ProfileDir.find_profile_dir(location, self.config)
387 p = ProfileDir.find_profile_dir(location, self.config)
388 except ProfileDirError:
388 except ProfileDirError:
389 # not found, maybe create it
389 # not found, maybe create it
390 if self.auto_create:
390 if self.auto_create:
391 try:
391 try:
392 p = ProfileDir.create_profile_dir(location, self.config)
392 p = ProfileDir.create_profile_dir(location, self.config)
393 except ProfileDirError:
393 except ProfileDirError:
394 self.log.fatal("Could not create profile directory: %r"%location)
394 self.log.fatal("Could not create profile directory: %r"%location)
395 self.exit(1)
395 self.exit(1)
396 else:
396 else:
397 self.log.debug("Creating new profile dir: %r"%location)
397 self.log.debug("Creating new profile dir: %r"%location)
398 else:
398 else:
399 self.log.fatal("Profile directory %r not found."%location)
399 self.log.fatal("Profile directory %r not found."%location)
400 self.exit(1)
400 self.exit(1)
401 else:
401 else:
402 self.log.info("Using existing profile dir: %r"%location)
402 self.log.info("Using existing profile dir: %r"%location)
403 # if profile_dir is specified explicitly, set profile name
403 # if profile_dir is specified explicitly, set profile name
404 dir_name = os.path.basename(p.location)
404 dir_name = os.path.basename(p.location)
405 if dir_name.startswith('profile_'):
405 if dir_name.startswith('profile_'):
406 self.profile = dir_name[8:]
406 self.profile = dir_name[8:]
407
407
408 self.profile_dir = p
408 self.profile_dir = p
409 self.config_file_paths.append(p.location)
409 self.config_file_paths.append(p.location)
410 self._in_init_profile_dir = False
410 self._in_init_profile_dir = False
411
411
412 def init_config_files(self):
412 def init_config_files(self):
413 """[optionally] copy default config files into profile dir."""
413 """[optionally] copy default config files into profile dir."""
414 self.config_file_paths.extend(ENV_CONFIG_DIRS)
414 self.config_file_paths.extend(ENV_CONFIG_DIRS)
415 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
415 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
416 # copy config files
416 # copy config files
417 path = self.builtin_profile_dir
417 path = self.builtin_profile_dir
418 if self.copy_config_files:
418 if self.copy_config_files:
419 src = self.profile
419 src = self.profile
420
420
421 cfg = self.config_file_name
421 cfg = self.config_file_name
422 if path and os.path.exists(os.path.join(path, cfg)):
422 if path and os.path.exists(os.path.join(path, cfg)):
423 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
423 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
424 cfg, src, self.profile_dir.location, self.overwrite)
424 cfg, src, self.profile_dir.location, self.overwrite)
425 )
425 )
426 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
426 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
427 else:
427 else:
428 self.stage_default_config_file()
428 self.stage_default_config_file()
429 else:
429 else:
430 # Still stage *bundled* config files, but not generated ones
430 # Still stage *bundled* config files, but not generated ones
431 # This is necessary for `ipython profile=sympy` to load the profile
431 # This is necessary for `ipython profile=sympy` to load the profile
432 # on the first go
432 # on the first go
433 files = glob.glob(os.path.join(path, '*.py'))
433 files = glob.glob(os.path.join(path, '*.py'))
434 for fullpath in files:
434 for fullpath in files:
435 cfg = os.path.basename(fullpath)
435 cfg = os.path.basename(fullpath)
436 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
436 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
437 # file was copied
437 # file was copied
438 self.log.warning("Staging bundled %s from %s into %r"%(
438 self.log.warning("Staging bundled %s from %s into %r"%(
439 cfg, self.profile, self.profile_dir.location)
439 cfg, self.profile, self.profile_dir.location)
440 )
440 )
441
441
442
442
443 def stage_default_config_file(self):
443 def stage_default_config_file(self):
444 """auto generate default config file, and stage it into the profile."""
444 """auto generate default config file, and stage it into the profile."""
445 s = self.generate_config_file()
445 s = self.generate_config_file()
446 fname = os.path.join(self.profile_dir.location, self.config_file_name)
446 fname = os.path.join(self.profile_dir.location, self.config_file_name)
447 if self.overwrite or not os.path.exists(fname):
447 if self.overwrite or not os.path.exists(fname):
448 self.log.warning("Generating default config file: %r"%(fname))
448 self.log.warning("Generating default config file: %r"%(fname))
449 with open(fname, 'w') as f:
449 with open(fname, 'w') as f:
450 f.write(s)
450 f.write(s)
451
451
452 @catch_config_error
452 @catch_config_error
453 def initialize(self, argv=None):
453 def initialize(self, argv=None):
454 # don't hook up crash handler before parsing command-line
454 # don't hook up crash handler before parsing command-line
455 self.parse_command_line(argv)
455 self.parse_command_line(argv)
456 self.init_crash_handler()
456 self.init_crash_handler()
457 if self.subapp is not None:
457 if self.subapp is not None:
458 # stop here if subapp is taking over
458 # stop here if subapp is taking over
459 return
459 return
460 # save a copy of CLI config to re-load after config files
460 # save a copy of CLI config to re-load after config files
461 # so that it has highest priority
461 # so that it has highest priority
462 cl_config = deepcopy(self.config)
462 cl_config = deepcopy(self.config)
463 self.init_profile_dir()
463 self.init_profile_dir()
464 self.init_config_files()
464 self.init_config_files()
465 self.load_config_file()
465 self.load_config_file()
466 # enforce cl-opts override configfile opts:
466 # enforce cl-opts override configfile opts:
467 self.update_config(cl_config)
467 self.update_config(cl_config)
@@ -1,314 +1,314 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 from __future__ import print_function
12 from __future__ import print_function
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 import os
25 import os
26
26
27 from traitlets.config.application import Application
27 from traitlets.config.application import Application
28 from IPython.core.application import (
28 from IPython.core.application import (
29 BaseIPythonApplication, base_flags
29 BaseIPythonApplication, base_flags
30 )
30 )
31 from IPython.core.profiledir import ProfileDir
31 from IPython.core.profiledir import ProfileDir
32 from IPython.utils.importstring import import_item
32 from IPython.utils.importstring import import_item
33 from IPython.paths import get_ipython_dir, get_ipython_package_dir
33 from IPython.paths import get_ipython_dir, get_ipython_package_dir
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from traitlets import Unicode, Bool, Dict, observe
35 from traitlets import Unicode, Bool, Dict, observe
36
36
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 # Constants
38 # Constants
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40
40
41 create_help = """Create an IPython profile by name
41 create_help = """Create an IPython profile by name
42
42
43 Create an ipython profile directory by its name or
43 Create an ipython profile directory by its name or
44 profile directory path. Profile directories contain
44 profile directory path. Profile directories contain
45 configuration, log and security related files and are named
45 configuration, log and security related files and are named
46 using the convention 'profile_<name>'. By default they are
46 using the convention 'profile_<name>'. By default they are
47 located in your ipython directory. Once created, you will
47 located in your ipython directory. Once created, you will
48 can edit the configuration files in the profile
48 can edit the configuration files in the profile
49 directory to configure IPython. Most users will create a
49 directory to configure IPython. Most users will create a
50 profile directory by name,
50 profile directory by name,
51 `ipython profile create myprofile`, which will put the directory
51 `ipython profile create myprofile`, which will put the directory
52 in `<ipython_dir>/profile_myprofile`.
52 in `<ipython_dir>/profile_myprofile`.
53 """
53 """
54 list_help = """List available IPython profiles
54 list_help = """List available IPython profiles
55
55
56 List all available profiles, by profile location, that can
56 List all available profiles, by profile location, that can
57 be found in the current working directly or in the ipython
57 be found in the current working directly or in the ipython
58 directory. Profile directories are named using the convention
58 directory. Profile directories are named using the convention
59 'profile_<profile>'.
59 'profile_<profile>'.
60 """
60 """
61 profile_help = """Manage IPython profiles
61 profile_help = """Manage IPython profiles
62
62
63 Profile directories contain
63 Profile directories contain
64 configuration, log and security related files and are named
64 configuration, log and security related files and are named
65 using the convention 'profile_<name>'. By default they are
65 using the convention 'profile_<name>'. By default they are
66 located in your ipython directory. You can create profiles
66 located in your ipython directory. You can create profiles
67 with `ipython profile create <name>`, or see the profiles you
67 with `ipython profile create <name>`, or see the profiles you
68 already have with `ipython profile list`
68 already have with `ipython profile list`
69
69
70 To get started configuring IPython, simply do:
70 To get started configuring IPython, simply do:
71
71
72 $> ipython profile create
72 $> ipython profile create
73
73
74 and IPython will create the default profile in <ipython_dir>/profile_default,
74 and IPython will create the default profile in <ipython_dir>/profile_default,
75 where you can edit ipython_config.py to start configuring IPython.
75 where you can edit ipython_config.py to start configuring IPython.
76
76
77 """
77 """
78
78
79 _list_examples = "ipython profile list # list all profiles"
79 _list_examples = "ipython profile list # list all profiles"
80
80
81 _create_examples = """
81 _create_examples = """
82 ipython profile create foo # create profile foo w/ default config files
82 ipython profile create foo # create profile foo w/ default config files
83 ipython profile create foo --reset # restage default config files over current
83 ipython profile create foo --reset # restage default config files over current
84 ipython profile create foo --parallel # also stage parallel config files
84 ipython profile create foo --parallel # also stage parallel config files
85 """
85 """
86
86
87 _main_examples = """
87 _main_examples = """
88 ipython profile create -h # show the help string for the create subcommand
88 ipython profile create -h # show the help string for the create subcommand
89 ipython profile list -h # show the help string for the list subcommand
89 ipython profile list -h # show the help string for the list subcommand
90
90
91 ipython locate profile foo # print the path to the directory for profile 'foo'
91 ipython locate profile foo # print the path to the directory for profile 'foo'
92 """
92 """
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Profile Application Class (for `ipython profile` subcommand)
95 # Profile Application Class (for `ipython profile` subcommand)
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98
98
99 def list_profiles_in(path):
99 def list_profiles_in(path):
100 """list profiles in a given root directory"""
100 """list profiles in a given root directory"""
101 files = os.listdir(path)
101 files = os.listdir(path)
102 profiles = []
102 profiles = []
103 for f in files:
103 for f in files:
104 try:
104 try:
105 full_path = os.path.join(path, f)
105 full_path = os.path.join(path, f)
106 except UnicodeError:
106 except UnicodeError:
107 continue
107 continue
108 if os.path.isdir(full_path) and f.startswith('profile_'):
108 if os.path.isdir(full_path) and f.startswith('profile_'):
109 profiles.append(f.split('_',1)[-1])
109 profiles.append(f.split('_',1)[-1])
110 return profiles
110 return profiles
111
111
112
112
113 def list_bundled_profiles():
113 def list_bundled_profiles():
114 """list profiles that are bundled with IPython."""
114 """list profiles that are bundled with IPython."""
115 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
115 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
116 files = os.listdir(path)
116 files = os.listdir(path)
117 profiles = []
117 profiles = []
118 for profile in files:
118 for profile in files:
119 full_path = os.path.join(path, profile)
119 full_path = os.path.join(path, profile)
120 if os.path.isdir(full_path) and profile != "__pycache__":
120 if os.path.isdir(full_path) and profile != "__pycache__":
121 profiles.append(profile)
121 profiles.append(profile)
122 return profiles
122 return profiles
123
123
124
124
125 class ProfileLocate(BaseIPythonApplication):
125 class ProfileLocate(BaseIPythonApplication):
126 description = """print the path to an IPython profile dir"""
126 description = """print the path to an IPython profile dir"""
127
127
128 def parse_command_line(self, argv=None):
128 def parse_command_line(self, argv=None):
129 super(ProfileLocate, self).parse_command_line(argv)
129 super(ProfileLocate, self).parse_command_line(argv)
130 if self.extra_args:
130 if self.extra_args:
131 self.profile = self.extra_args[0]
131 self.profile = self.extra_args[0]
132
132
133 def start(self):
133 def start(self):
134 print(self.profile_dir.location)
134 print(self.profile_dir.location)
135
135
136
136
137 class ProfileList(Application):
137 class ProfileList(Application):
138 name = u'ipython-profile'
138 name = u'ipython-profile'
139 description = list_help
139 description = list_help
140 examples = _list_examples
140 examples = _list_examples
141
141
142 aliases = Dict({
142 aliases = Dict({
143 'ipython-dir' : 'ProfileList.ipython_dir',
143 'ipython-dir' : 'ProfileList.ipython_dir',
144 'log-level' : 'Application.log_level',
144 'log-level' : 'Application.log_level',
145 })
145 })
146 flags = Dict(dict(
146 flags = Dict(dict(
147 debug = ({'Application' : {'log_level' : 0}},
147 debug = ({'Application' : {'log_level' : 0}},
148 "Set Application.log_level to 0, maximizing log output."
148 "Set Application.log_level to 0, maximizing log output."
149 )
149 )
150 ))
150 ))
151
151
152 ipython_dir = Unicode(get_ipython_dir(),
152 ipython_dir = Unicode(get_ipython_dir(),
153 help="""
153 help="""
154 The name of the IPython directory. This directory is used for logging
154 The name of the IPython directory. This directory is used for logging
155 configuration (through profiles), history storage, etc. The default
155 configuration (through profiles), history storage, etc. The default
156 is usually $HOME/.ipython. This options can also be specified through
156 is usually $HOME/.ipython. This options can also be specified through
157 the environment variable IPYTHONDIR.
157 the environment variable IPYTHONDIR.
158 """
158 """
159 ).tag(config=True)
159 ).tag(config=True)
160
160
161
161
162 def _print_profiles(self, profiles):
162 def _print_profiles(self, profiles):
163 """print list of profiles, indented."""
163 """print list of profiles, indented."""
164 for profile in profiles:
164 for profile in profiles:
165 print(' %s' % profile)
165 print(' %s' % profile)
166
166
167 def list_profile_dirs(self):
167 def list_profile_dirs(self):
168 profiles = list_bundled_profiles()
168 profiles = list_bundled_profiles()
169 if profiles:
169 if profiles:
170 print()
170 print()
171 print("Available profiles in IPython:")
171 print("Available profiles in IPython:")
172 self._print_profiles(profiles)
172 self._print_profiles(profiles)
173 print()
173 print()
174 print(" The first request for a bundled profile will copy it")
174 print(" The first request for a bundled profile will copy it")
175 print(" into your IPython directory (%s)," % self.ipython_dir)
175 print(" into your IPython directory (%s)," % self.ipython_dir)
176 print(" where you can customize it.")
176 print(" where you can customize it.")
177
177
178 profiles = list_profiles_in(self.ipython_dir)
178 profiles = list_profiles_in(self.ipython_dir)
179 if profiles:
179 if profiles:
180 print()
180 print()
181 print("Available profiles in %s:" % self.ipython_dir)
181 print("Available profiles in %s:" % self.ipython_dir)
182 self._print_profiles(profiles)
182 self._print_profiles(profiles)
183
183
184 profiles = list_profiles_in(py3compat.getcwd())
184 profiles = list_profiles_in(py3compat.getcwd())
185 if profiles:
185 if profiles:
186 print()
186 print()
187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
187 print(
188 self._print_profiles(profiles)
188 "Profiles from CWD have been removed for security reason, see CVE-2022-21699:"
189
189 )
190 print()
190 print()
191 print("To use any of the above profiles, start IPython with:")
191 print("To use any of the above profiles, start IPython with:")
192 print(" ipython --profile=<name>")
192 print(" ipython --profile=<name>")
193 print()
193 print()
194
194
195 def start(self):
195 def start(self):
196 self.list_profile_dirs()
196 self.list_profile_dirs()
197
197
198
198
199 create_flags = {}
199 create_flags = {}
200 create_flags.update(base_flags)
200 create_flags.update(base_flags)
201 # don't include '--init' flag, which implies running profile create in other apps
201 # don't include '--init' flag, which implies running profile create in other apps
202 create_flags.pop('init')
202 create_flags.pop('init')
203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
204 "reset config files in this profile to the defaults.")
204 "reset config files in this profile to the defaults.")
205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
206 "Include the config files for parallel "
206 "Include the config files for parallel "
207 "computing apps (ipengine, ipcontroller, etc.)")
207 "computing apps (ipengine, ipcontroller, etc.)")
208
208
209
209
210 class ProfileCreate(BaseIPythonApplication):
210 class ProfileCreate(BaseIPythonApplication):
211 name = u'ipython-profile'
211 name = u'ipython-profile'
212 description = create_help
212 description = create_help
213 examples = _create_examples
213 examples = _create_examples
214 auto_create = Bool(True)
214 auto_create = Bool(True)
215 def _log_format_default(self):
215 def _log_format_default(self):
216 return "[%(name)s] %(message)s"
216 return "[%(name)s] %(message)s"
217
217
218 def _copy_config_files_default(self):
218 def _copy_config_files_default(self):
219 return True
219 return True
220
220
221 parallel = Bool(False,
221 parallel = Bool(False,
222 help="whether to include parallel computing config files"
222 help="whether to include parallel computing config files"
223 ).tag(config=True)
223 ).tag(config=True)
224
224
225 @observe('parallel')
225 @observe('parallel')
226 def _parallel_changed(self, change):
226 def _parallel_changed(self, change):
227 parallel_files = [ 'ipcontroller_config.py',
227 parallel_files = [ 'ipcontroller_config.py',
228 'ipengine_config.py',
228 'ipengine_config.py',
229 'ipcluster_config.py'
229 'ipcluster_config.py'
230 ]
230 ]
231 if change['new']:
231 if change['new']:
232 for cf in parallel_files:
232 for cf in parallel_files:
233 self.config_files.append(cf)
233 self.config_files.append(cf)
234 else:
234 else:
235 for cf in parallel_files:
235 for cf in parallel_files:
236 if cf in self.config_files:
236 if cf in self.config_files:
237 self.config_files.remove(cf)
237 self.config_files.remove(cf)
238
238
239 def parse_command_line(self, argv):
239 def parse_command_line(self, argv):
240 super(ProfileCreate, self).parse_command_line(argv)
240 super(ProfileCreate, self).parse_command_line(argv)
241 # accept positional arg as profile name
241 # accept positional arg as profile name
242 if self.extra_args:
242 if self.extra_args:
243 self.profile = self.extra_args[0]
243 self.profile = self.extra_args[0]
244
244
245 flags = Dict(create_flags)
245 flags = Dict(create_flags)
246
246
247 classes = [ProfileDir]
247 classes = [ProfileDir]
248
248
249 def _import_app(self, app_path):
249 def _import_app(self, app_path):
250 """import an app class"""
250 """import an app class"""
251 app = None
251 app = None
252 name = app_path.rsplit('.', 1)[-1]
252 name = app_path.rsplit('.', 1)[-1]
253 try:
253 try:
254 app = import_item(app_path)
254 app = import_item(app_path)
255 except ImportError:
255 except ImportError:
256 self.log.info("Couldn't import %s, config file will be excluded", name)
256 self.log.info("Couldn't import %s, config file will be excluded", name)
257 except Exception:
257 except Exception:
258 self.log.warning('Unexpected error importing %s', name, exc_info=True)
258 self.log.warning('Unexpected error importing %s', name, exc_info=True)
259 return app
259 return app
260
260
261 def init_config_files(self):
261 def init_config_files(self):
262 super(ProfileCreate, self).init_config_files()
262 super(ProfileCreate, self).init_config_files()
263 # use local imports, since these classes may import from here
263 # use local imports, since these classes may import from here
264 from IPython.terminal.ipapp import TerminalIPythonApp
264 from IPython.terminal.ipapp import TerminalIPythonApp
265 apps = [TerminalIPythonApp]
265 apps = [TerminalIPythonApp]
266 for app_path in (
266 for app_path in (
267 'ipykernel.kernelapp.IPKernelApp',
267 'ipykernel.kernelapp.IPKernelApp',
268 ):
268 ):
269 app = self._import_app(app_path)
269 app = self._import_app(app_path)
270 if app is not None:
270 if app is not None:
271 apps.append(app)
271 apps.append(app)
272 if self.parallel:
272 if self.parallel:
273 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
273 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
274 from ipyparallel.apps.ipengineapp import IPEngineApp
274 from ipyparallel.apps.ipengineapp import IPEngineApp
275 from ipyparallel.apps.ipclusterapp import IPClusterStart
275 from ipyparallel.apps.ipclusterapp import IPClusterStart
276 apps.extend([
276 apps.extend([
277 IPControllerApp,
277 IPControllerApp,
278 IPEngineApp,
278 IPEngineApp,
279 IPClusterStart,
279 IPClusterStart,
280 ])
280 ])
281 for App in apps:
281 for App in apps:
282 app = App()
282 app = App()
283 app.config.update(self.config)
283 app.config.update(self.config)
284 app.log = self.log
284 app.log = self.log
285 app.overwrite = self.overwrite
285 app.overwrite = self.overwrite
286 app.copy_config_files=True
286 app.copy_config_files=True
287 app.ipython_dir=self.ipython_dir
287 app.ipython_dir=self.ipython_dir
288 app.profile_dir=self.profile_dir
288 app.profile_dir=self.profile_dir
289 app.init_config_files()
289 app.init_config_files()
290
290
291 def stage_default_config_file(self):
291 def stage_default_config_file(self):
292 pass
292 pass
293
293
294
294
295 class ProfileApp(Application):
295 class ProfileApp(Application):
296 name = u'ipython profile'
296 name = u'ipython profile'
297 description = profile_help
297 description = profile_help
298 examples = _main_examples
298 examples = _main_examples
299
299
300 subcommands = Dict(dict(
300 subcommands = Dict(dict(
301 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
301 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
302 list = (ProfileList, ProfileList.description.splitlines()[0]),
302 list = (ProfileList, ProfileList.description.splitlines()[0]),
303 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
303 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
304 ))
304 ))
305
305
306 def start(self):
306 def start(self):
307 if self.subapp is None:
307 if self.subapp is None:
308 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
308 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
309 print()
309 print()
310 self.print_description()
310 self.print_description()
311 self.print_subcommands()
311 self.print_subcommands()
312 self.exit(1)
312 self.exit(1)
313 else:
313 else:
314 return self.subapp.start()
314 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()`` # removed for security reason.
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 = [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,461 +1,469 b''
1 ============
1 ============
2 5.x Series
2 5.x Series
3 ============
3 ============
4
4
5
6 .. _whatsnew5101
7
8 IPython 5.10.1 (CVE-2022-21699)
9 ===============================
10
11 Fix CVE-2022-21699, see IPython 8.0.1 release notes.
12
5 .. _whatsnew5100
13 .. _whatsnew5100
6
14
7 IPython 5.10.0
15 IPython 5.10.0
8 ==============
16 ==============
9
17
10 IPython 5.10 pins Pygments dependencies to version lower than ``2.6``, as it is
18 IPython 5.10 pins Pygments dependencies to version lower than ``2.6``, as it is
11 not compatible Python 2. See :ghpull:`12174`
19 not compatible Python 2. See :ghpull:`12174`
12
20
13 .. _whatsnew590
21 .. _whatsnew590
14
22
15 IPython 5.9.0
23 IPython 5.9.0
16 =============
24 =============
17
25
18 IPython 5.9 is a release that accumulated fixes for Python 2 over the past 18
26 IPython 5.9 is a release that accumulated fixes for Python 2 over the past 18
19 month. Please see source and version control history for more informations.
27 month. Please see source and version control history for more informations.
20
28
21 .. _whatsnew580
29 .. _whatsnew580
22
30
23 IPython 5.8.0
31 IPython 5.8.0
24 =============
32 =============
25
33
26 * Update inspecting function/methods for future-proofing. :ghpull:`11139`
34 * Update inspecting function/methods for future-proofing. :ghpull:`11139`
27
35
28 .. _whatsnew570:
36 .. _whatsnew570:
29
37
30 IPython 5.7
38 IPython 5.7
31 ===========
39 ===========
32
40
33 * Fix IPython trying to import non-existing matplotlib backends :ghpull:`11087`
41 * Fix IPython trying to import non-existing matplotlib backends :ghpull:`11087`
34 * fix for display hook not publishing object metadata :ghpull:`11101`
42 * fix for display hook not publishing object metadata :ghpull:`11101`
35
43
36 .. _whatsnew560:
44 .. _whatsnew560:
37
45
38 IPython 5.6
46 IPython 5.6
39 ===========
47 ===========
40
48
41 * In Python 3.6 and above, dictionaries preserve the order items were added to
49 * In Python 3.6 and above, dictionaries preserve the order items were added to
42 them. On these versions, IPython will display dictionaries in their native
50 them. On these versions, IPython will display dictionaries in their native
43 order, rather than sorting by the keys (:ghpull:`10958`).
51 order, rather than sorting by the keys (:ghpull:`10958`).
44 * :class:`~.IPython.display.ProgressBar` can now be used as an iterator
52 * :class:`~.IPython.display.ProgressBar` can now be used as an iterator
45 (:ghpull:`10813`).
53 (:ghpull:`10813`).
46 * The shell object gains a :meth:`~.InteractiveShell.check_complete` method,
54 * The shell object gains a :meth:`~.InteractiveShell.check_complete` method,
47 to allow a smoother transition to new input processing machinery planned for
55 to allow a smoother transition to new input processing machinery planned for
48 IPython 7 (:ghpull:`11044`).
56 IPython 7 (:ghpull:`11044`).
49 * IPython should start faster, as it no longer looks for all available pygments
57 * IPython should start faster, as it no longer looks for all available pygments
50 styles on startup (:ghpull:`10859`).
58 styles on startup (:ghpull:`10859`).
51
59
52 You can see all the PR marked for the `5.6. milestone <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.6+is%3Aclosed+NOT+%22Backport+PR%22+>`_,
60 You can see all the PR marked for the `5.6. milestone <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A5.6+is%3Aclosed+NOT+%22Backport+PR%22+>`_,
53 and all the `backport versions <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr%20milestone%3A5.6%20is%3Aclosed%20%22Backport%20PR%22%20>`__.
61 and all the `backport versions <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr%20milestone%3A5.6%20is%3Aclosed%20%22Backport%20PR%22%20>`__.
54
62
55 .. _whatsnew550:
63 .. _whatsnew550:
56
64
57 IPython 5.5
65 IPython 5.5
58 ===========
66 ===========
59
67
60 System Wide config
68 System Wide config
61 ------------------
69 ------------------
62
70
63 - IPython now looks for config files in ``{sys.prefix}/etc/ipython``
71 - IPython now looks for config files in ``{sys.prefix}/etc/ipython``
64 for environment-specific configuration.
72 for environment-specific configuration.
65 - Startup files can be found in ``/etc/ipython/startup`` or ``{sys.prefix}/etc/ipython/startup``
73 - Startup files can be found in ``/etc/ipython/startup`` or ``{sys.prefix}/etc/ipython/startup``
66 in addition to the profile directory, for system-wide or env-specific startup files.
74 in addition to the profile directory, for system-wide or env-specific startup files.
67
75
68 See :ghpull:`10644`
76 See :ghpull:`10644`
69
77
70 ProgressBar
78 ProgressBar
71 -----------
79 -----------
72
80
73
81
74 IPython now has built-in support for progressbars::
82 IPython now has built-in support for progressbars::
75
83
76 In[1]: from IPython.display import ProgressBar
84 In[1]: from IPython.display import ProgressBar
77 ... : pb = ProgressBar(100)
85 ... : pb = ProgressBar(100)
78 ... : pb
86 ... : pb
79
87
80 In[2]: pb.progress = 50
88 In[2]: pb.progress = 50
81
89
82 # progress bar in cell 1 updates.
90 # progress bar in cell 1 updates.
83
91
84 See :ghpull:`10755`
92 See :ghpull:`10755`
85
93
86
94
87 Misc
95 Misc
88 ----
96 ----
89
97
90 - Fix ``IPython.core.display:Pretty._repr_pretty_`` had the wrong signature.
98 - Fix ``IPython.core.display:Pretty._repr_pretty_`` had the wrong signature.
91 (:ghpull:`10625`)
99 (:ghpull:`10625`)
92 - :magic:`timeit` now give a correct ``SyntaxError`` if naked ``return`` used.
100 - :magic:`timeit` now give a correct ``SyntaxError`` if naked ``return`` used.
93 (:ghpull:`10637`)
101 (:ghpull:`10637`)
94 - Prepare the ``:ipython:`` directive to be compatible with Sphinx 1.7.
102 - Prepare the ``:ipython:`` directive to be compatible with Sphinx 1.7.
95 (:ghpull:`10668`)
103 (:ghpull:`10668`)
96 - Make IPython work with OpenSSL in FIPS mode; change hash algorithm of input
104 - Make IPython work with OpenSSL in FIPS mode; change hash algorithm of input
97 from md5 to sha1. (:ghpull:`10696`)
105 from md5 to sha1. (:ghpull:`10696`)
98 - Clear breakpoints before running any script with debugger. (:ghpull:`10699`)
106 - Clear breakpoints before running any script with debugger. (:ghpull:`10699`)
99 - Document that :magic:`profile` is deprecated, not to be confused with :magic:`prun`. (:ghpull:`10707`)
107 - Document that :magic:`profile` is deprecated, not to be confused with :magic:`prun`. (:ghpull:`10707`)
100 - Limit default number of returned completions to 500. (:ghpull:`10743`)
108 - Limit default number of returned completions to 500. (:ghpull:`10743`)
101
109
102 You can see all the PR marked for the `5.5. milestone <https://github.com/ipython/ipython/pulls?q=is%3Apr%20milestone%3A5.5%20is%3Aclosed%20NOT%20%22Backport%20PR%22>`_,
110 You can see all the PR marked for the `5.5. milestone <https://github.com/ipython/ipython/pulls?q=is%3Apr%20milestone%3A5.5%20is%3Aclosed%20NOT%20%22Backport%20PR%22>`_,
103 and all the `backport versions <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr%20milestone%3A5.5%20is%3Aclosed%20%22Backport%20PR%22%20>`_.
111 and all the `backport versions <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr%20milestone%3A5.5%20is%3Aclosed%20%22Backport%20PR%22%20>`_.
104
112
105 IPython 5.4.1
113 IPython 5.4.1
106 =============
114 =============
107 Released a few hours after 5.4, fix a crash when
115 Released a few hours after 5.4, fix a crash when
108 ``backports.shutil-get-terminal-size`` is not installed. :ghissue:`10629`
116 ``backports.shutil-get-terminal-size`` is not installed. :ghissue:`10629`
109
117
110 .. _whatsnew540:
118 .. _whatsnew540:
111
119
112 IPython 5.4
120 IPython 5.4
113 ===========
121 ===========
114
122
115 IPython 5.4-LTS is the first release of IPython after the release of the 6.x
123 IPython 5.4-LTS is the first release of IPython after the release of the 6.x
116 series which is Python 3 only. It backports most of the new exposed API
124 series which is Python 3 only. It backports most of the new exposed API
117 additions made in IPython 6.0 and 6.1 and avoid having to write conditional
125 additions made in IPython 6.0 and 6.1 and avoid having to write conditional
118 logics depending of the version of IPython.
126 logics depending of the version of IPython.
119
127
120 Please upgrade to pip 9 or greater before upgrading IPython.
128 Please upgrade to pip 9 or greater before upgrading IPython.
121 Failing to do so on Python 2 may lead to a broken IPython install.
129 Failing to do so on Python 2 may lead to a broken IPython install.
122
130
123 Configurable TerminalInteractiveShell
131 Configurable TerminalInteractiveShell
124 -------------------------------------
132 -------------------------------------
125
133
126 Backported from the 6.x branch as an exceptional new feature. See
134 Backported from the 6.x branch as an exceptional new feature. See
127 :ghpull:`10373` and :ghissue:`10364`
135 :ghpull:`10373` and :ghissue:`10364`
128
136
129 IPython gained a new ``c.TerminalIPythonApp.interactive_shell_class`` option
137 IPython gained a new ``c.TerminalIPythonApp.interactive_shell_class`` option
130 that allow to customize the class used to start the terminal frontend. This
138 that allow to customize the class used to start the terminal frontend. This
131 should allow user to use custom interfaces, like reviving the former readline
139 should allow user to use custom interfaces, like reviving the former readline
132 interface which is now a separate package not maintained by the core team.
140 interface which is now a separate package not maintained by the core team.
133
141
134 Define ``_repr_mimebundle_``
142 Define ``_repr_mimebundle_``
135 ----------------------------
143 ----------------------------
136
144
137 Object can now define `_repr_mimebundle_` in place of multiple `_repr_*_`
145 Object can now define `_repr_mimebundle_` in place of multiple `_repr_*_`
138 methods and return a full mimebundle. This greatly simplify many implementation
146 methods and return a full mimebundle. This greatly simplify many implementation
139 and allow to publish custom mimetypes (like geojson, plotly, dataframes....).
147 and allow to publish custom mimetypes (like geojson, plotly, dataframes....).
140 See the ``Cutom Display Logic`` example notebook for more informations.
148 See the ``Cutom Display Logic`` example notebook for more informations.
141
149
142 Execution Heuristics
150 Execution Heuristics
143 --------------------
151 --------------------
144
152
145 The heuristic for execution in the command line interface is now more biased
153 The heuristic for execution in the command line interface is now more biased
146 toward executing for single statement. While in IPython 4.x and before a single
154 toward executing for single statement. While in IPython 4.x and before a single
147 line would be executed when enter is pressed, IPython 5.x would insert a new
155 line would be executed when enter is pressed, IPython 5.x would insert a new
148 line. For single line statement this is not true anymore and if a single line is
156 line. For single line statement this is not true anymore and if a single line is
149 valid Python, IPython will execute it regardless of the cursor position. Use
157 valid Python, IPython will execute it regardless of the cursor position. Use
150 :kbd:`Ctrl-O` to insert a new line. :ghpull:`10489`
158 :kbd:`Ctrl-O` to insert a new line. :ghpull:`10489`
151
159
152
160
153 Implement Display IDs
161 Implement Display IDs
154 ---------------------
162 ---------------------
155
163
156 Implement display id and ability to update a given display. This should greatly
164 Implement display id and ability to update a given display. This should greatly
157 simplify a lot of code by removing the need for widgets and allow other frontend
165 simplify a lot of code by removing the need for widgets and allow other frontend
158 to implement things like progress-bars. See :ghpull:`10048`
166 to implement things like progress-bars. See :ghpull:`10048`
159
167
160 Display function
168 Display function
161 ----------------
169 ----------------
162
170
163 The :func:`display() <IPython.display.display>` function is now available by
171 The :func:`display() <IPython.display.display>` function is now available by
164 default in an IPython session, meaning users can call it on any object to see
172 default in an IPython session, meaning users can call it on any object to see
165 their rich representation. This should allow for better interactivity both at
173 their rich representation. This should allow for better interactivity both at
166 the REPL and in notebook environment.
174 the REPL and in notebook environment.
167
175
168 Scripts and library that rely on display and may be run outside of IPython still
176 Scripts and library that rely on display and may be run outside of IPython still
169 need to import the display function using ``from IPython.display import
177 need to import the display function using ``from IPython.display import
170 display``. See :ghpull:`10596`
178 display``. See :ghpull:`10596`
171
179
172
180
173 Miscs
181 Miscs
174 -----
182 -----
175
183
176 * ``_mp_main_`` is not reloaded which fixes issues with multiprocessing.
184 * ``_mp_main_`` is not reloaded which fixes issues with multiprocessing.
177 :ghpull:`10523`
185 :ghpull:`10523`
178 * Use user colorscheme in Pdb as well :ghpull:`10479`
186 * Use user colorscheme in Pdb as well :ghpull:`10479`
179 * Faster shutdown. :ghpull:`10408`
187 * Faster shutdown. :ghpull:`10408`
180 * Fix a crash in reverse search. :ghpull:`10371`
188 * Fix a crash in reverse search. :ghpull:`10371`
181 * added ``Completer.backslash_combining_completions`` boolean option to
189 * added ``Completer.backslash_combining_completions`` boolean option to
182 deactivate backslash-tab completion that may conflict with windows path.
190 deactivate backslash-tab completion that may conflict with windows path.
183
191
184 IPython 5.3
192 IPython 5.3
185 ===========
193 ===========
186
194
187 Released on February 24th, 2017. Remarkable changes and fixes:
195 Released on February 24th, 2017. Remarkable changes and fixes:
188
196
189 * Fix a bug in ``set_next_input`` leading to a crash of terminal IPython.
197 * Fix a bug in ``set_next_input`` leading to a crash of terminal IPython.
190 :ghpull:`10231`, :ghissue:`10296`, :ghissue:`10229`
198 :ghpull:`10231`, :ghissue:`10296`, :ghissue:`10229`
191 * Always wait for editor inputhook for terminal IPython :ghpull:`10239`,
199 * Always wait for editor inputhook for terminal IPython :ghpull:`10239`,
192 :ghpull:`10240`
200 :ghpull:`10240`
193 * Disable ``_ipython_display_`` in terminal :ghpull:`10249`, :ghpull:`10274`
201 * Disable ``_ipython_display_`` in terminal :ghpull:`10249`, :ghpull:`10274`
194 * Update terminal colors to be more visible by default on windows
202 * Update terminal colors to be more visible by default on windows
195 :ghpull:`10260`, :ghpull:`10238`, :ghissue:`10281`
203 :ghpull:`10260`, :ghpull:`10238`, :ghissue:`10281`
196 * Add Ctrl-Z shortcut (suspend) in terminal debugger :ghpull:`10254`,
204 * Add Ctrl-Z shortcut (suspend) in terminal debugger :ghpull:`10254`,
197 :ghissue:`10273`
205 :ghissue:`10273`
198 * Indent on new line by looking at the text before the cursor :ghpull:`10264`,
206 * Indent on new line by looking at the text before the cursor :ghpull:`10264`,
199 :ghpull:`10275`, :ghissue:`9283`
207 :ghpull:`10275`, :ghissue:`9283`
200 * Update QtEventloop integration to fix some matplotlib integration issues
208 * Update QtEventloop integration to fix some matplotlib integration issues
201 :ghpull:`10201`, :ghpull:`10311`, :ghissue:`10201`
209 :ghpull:`10201`, :ghpull:`10311`, :ghissue:`10201`
202 * Respect completions display style in terminal debugger :ghpull:`10305`,
210 * Respect completions display style in terminal debugger :ghpull:`10305`,
203 :ghpull:`10313`
211 :ghpull:`10313`
204 * Add a config option ``TerminalInteractiveShell.extra_open_editor_shortcuts``
212 * Add a config option ``TerminalInteractiveShell.extra_open_editor_shortcuts``
205 to enable extra shortcuts to open the input in an editor. These are :kbd:`v`
213 to enable extra shortcuts to open the input in an editor. These are :kbd:`v`
206 in vi mode, and :kbd:`C-X C-E` in emacs mode (:ghpull:`10330`).
214 in vi mode, and :kbd:`C-X C-E` in emacs mode (:ghpull:`10330`).
207 The :kbd:`F2` shortcut is always enabled.
215 The :kbd:`F2` shortcut is always enabled.
208
216
209 IPython 5.2.2
217 IPython 5.2.2
210 =============
218 =============
211
219
212 * Fix error when starting with ``IPCompleter.limit_to__all__`` configured.
220 * Fix error when starting with ``IPCompleter.limit_to__all__`` configured.
213
221
214 IPython 5.2.1
222 IPython 5.2.1
215 =============
223 =============
216
224
217 * Fix tab completion in the debugger. :ghpull:`10223`
225 * Fix tab completion in the debugger. :ghpull:`10223`
218
226
219 IPython 5.2
227 IPython 5.2
220 ===========
228 ===========
221
229
222 Released on January 29th, 2017. Remarkable changes and fixes:
230 Released on January 29th, 2017. Remarkable changes and fixes:
223
231
224 * restore IPython's debugger to raise on quit. :ghpull:`10009`
232 * restore IPython's debugger to raise on quit. :ghpull:`10009`
225 * The configuration value ``c.TerminalInteractiveShell.highlighting_style`` can
233 * The configuration value ``c.TerminalInteractiveShell.highlighting_style`` can
226 now directly take a class argument for custom color style. :ghpull:`9848`
234 now directly take a class argument for custom color style. :ghpull:`9848`
227 * Correctly handle matplotlib figures dpi :ghpull:`9868`
235 * Correctly handle matplotlib figures dpi :ghpull:`9868`
228 * Deprecate ``-e`` flag for the ``%notebook`` magic that had no effects.
236 * Deprecate ``-e`` flag for the ``%notebook`` magic that had no effects.
229 :ghpull:`9872`
237 :ghpull:`9872`
230 * You can now press F2 while typing at a terminal prompt to edit the contents
238 * You can now press F2 while typing at a terminal prompt to edit the contents
231 in your favourite terminal editor. Set the :envvar:`EDITOR` environment
239 in your favourite terminal editor. Set the :envvar:`EDITOR` environment
232 variable to pick which editor is used. :ghpull:`9929`
240 variable to pick which editor is used. :ghpull:`9929`
233 * sdists will now only be ``.tar.gz`` as per upstream PyPI requirements.
241 * sdists will now only be ``.tar.gz`` as per upstream PyPI requirements.
234 :ghpull:`9925`
242 :ghpull:`9925`
235 * :any:`IPython.core.debugger` have gained a ``set_trace()`` method for
243 * :any:`IPython.core.debugger` have gained a ``set_trace()`` method for
236 convenience. :ghpull:`9947`
244 convenience. :ghpull:`9947`
237 * The 'smart command mode' added to the debugger in 5.0 was removed, as more
245 * The 'smart command mode' added to the debugger in 5.0 was removed, as more
238 people preferred the previous behaviour. Therefore, debugger commands such as
246 people preferred the previous behaviour. Therefore, debugger commands such as
239 ``c`` will act as debugger commands even when ``c`` is defined as a variable.
247 ``c`` will act as debugger commands even when ``c`` is defined as a variable.
240 :ghpull:`10050`
248 :ghpull:`10050`
241 * Fixes OS X event loop issues at startup, :ghpull:`10150`
249 * Fixes OS X event loop issues at startup, :ghpull:`10150`
242 * Deprecate the ``%autoindent`` magic. :ghpull:`10176`
250 * Deprecate the ``%autoindent`` magic. :ghpull:`10176`
243 * Emit a :any:`DeprecationWarning` when setting the deprecated
251 * Emit a :any:`DeprecationWarning` when setting the deprecated
244 ``limit_to_all`` option of the completer. :ghpull:`10198`
252 ``limit_to_all`` option of the completer. :ghpull:`10198`
245 * The :cellmagic:`capture` magic can now capture the result of a cell (from an
253 * The :cellmagic:`capture` magic can now capture the result of a cell (from an
246 expression on the last line), as well as printed and displayed output.
254 expression on the last line), as well as printed and displayed output.
247 :ghpull:`9851`.
255 :ghpull:`9851`.
248
256
249
257
250 Changes of behavior to :any:`InteractiveShellEmbed`.
258 Changes of behavior to :any:`InteractiveShellEmbed`.
251
259
252 :any:`InteractiveShellEmbed` interactive behavior have changed a bit in between
260 :any:`InteractiveShellEmbed` interactive behavior have changed a bit in between
253 5.1 and 5.2. By default ``%kill_embedded`` magic will prevent further invocation
261 5.1 and 5.2. By default ``%kill_embedded`` magic will prevent further invocation
254 of the current ``call location`` instead of preventing further invocation of
262 of the current ``call location`` instead of preventing further invocation of
255 the current instance creation location. For most use case this will not change
263 the current instance creation location. For most use case this will not change
256 much for you, though previous behavior was confusing and less consistent with
264 much for you, though previous behavior was confusing and less consistent with
257 previous IPython versions.
265 previous IPython versions.
258
266
259 You can now deactivate instances by using ``%kill_embedded --instance`` flag,
267 You can now deactivate instances by using ``%kill_embedded --instance`` flag,
260 (or ``-i`` in short). The ``%kill_embedded`` magic also gained a
268 (or ``-i`` in short). The ``%kill_embedded`` magic also gained a
261 ``--yes``/``-y`` option which skip confirmation step, and ``-x``/``--exit``
269 ``--yes``/``-y`` option which skip confirmation step, and ``-x``/``--exit``
262 which also exit the current embedded call without asking for confirmation.
270 which also exit the current embedded call without asking for confirmation.
263
271
264 See :ghpull:`10207`.
272 See :ghpull:`10207`.
265
273
266
274
267
275
268 IPython 5.1
276 IPython 5.1
269 ===========
277 ===========
270
278
271 * Broken ``%timeit`` on Python2 due to the use of ``__qualname__``. :ghpull:`9804`
279 * Broken ``%timeit`` on Python2 due to the use of ``__qualname__``. :ghpull:`9804`
272 * Restore ``%gui qt`` to create and return a ``QApplication`` if necessary. :ghpull:`9789`
280 * Restore ``%gui qt`` to create and return a ``QApplication`` if necessary. :ghpull:`9789`
273 * Don't set terminal title by default. :ghpull:`9801`
281 * Don't set terminal title by default. :ghpull:`9801`
274 * Preserve indentation when inserting newlines with ``Ctrl-O``. :ghpull:`9770`
282 * Preserve indentation when inserting newlines with ``Ctrl-O``. :ghpull:`9770`
275 * Restore completion in debugger. :ghpull:`9785`
283 * Restore completion in debugger. :ghpull:`9785`
276 * Deprecate ``IPython.core.debugger.Tracer()`` in favor of simpler, newer, APIs. :ghpull:`9731`
284 * Deprecate ``IPython.core.debugger.Tracer()`` in favor of simpler, newer, APIs. :ghpull:`9731`
277 * Restore ``NoOpContext`` context manager removed by mistake, and add `DeprecationWarning`. :ghpull:`9765`
285 * Restore ``NoOpContext`` context manager removed by mistake, and add `DeprecationWarning`. :ghpull:`9765`
278 * Add option allowing ``Prompt_toolkit`` to use 24bits colors. :ghpull:`9736`
286 * Add option allowing ``Prompt_toolkit`` to use 24bits colors. :ghpull:`9736`
279 * Fix for closing interactive matplotlib windows on OS X. :ghpull:`9854`
287 * Fix for closing interactive matplotlib windows on OS X. :ghpull:`9854`
280 * An embedded interactive shell instance can be used more than once. :ghpull:`9843`
288 * An embedded interactive shell instance can be used more than once. :ghpull:`9843`
281 * More robust check for whether IPython is in a terminal. :ghpull:`9833`
289 * More robust check for whether IPython is in a terminal. :ghpull:`9833`
282 * Better pretty-printing of dicts on PyPy. :ghpull:`9827`
290 * Better pretty-printing of dicts on PyPy. :ghpull:`9827`
283 * Some coloured output now looks better on dark background command prompts in Windows.
291 * Some coloured output now looks better on dark background command prompts in Windows.
284 :ghpull:`9838`
292 :ghpull:`9838`
285 * Improved tab completion of paths on Windows . :ghpull:`9826`
293 * Improved tab completion of paths on Windows . :ghpull:`9826`
286 * Fix tkinter event loop integration on Python 2 with ``future`` installed. :ghpull:`9824`
294 * Fix tkinter event loop integration on Python 2 with ``future`` installed. :ghpull:`9824`
287 * Restore ``Ctrl-\`` as a shortcut to quit IPython.
295 * Restore ``Ctrl-\`` as a shortcut to quit IPython.
288 * Make ``get_ipython()`` accessible when modules are imported by startup files. :ghpull:`9818`
296 * Make ``get_ipython()`` accessible when modules are imported by startup files. :ghpull:`9818`
289 * Add support for running directories containing a ``__main__.py`` file with the
297 * Add support for running directories containing a ``__main__.py`` file with the
290 ``ipython`` command. :ghpull:`9813`
298 ``ipython`` command. :ghpull:`9813`
291
299
292
300
293 True Color feature
301 True Color feature
294 ------------------
302 ------------------
295
303
296 ``prompt_toolkit`` uses pygments styles for syntax highlighting. By default, the
304 ``prompt_toolkit`` uses pygments styles for syntax highlighting. By default, the
297 colors specified in the style are approximated using a standard 256-color
305 colors specified in the style are approximated using a standard 256-color
298 palette. ``prompt_toolkit`` also supports 24bit, a.k.a. "true", a.k.a. 16-million
306 palette. ``prompt_toolkit`` also supports 24bit, a.k.a. "true", a.k.a. 16-million
299 color escape sequences which enable compatible terminals to display the exact
307 color escape sequences which enable compatible terminals to display the exact
300 colors specified instead of an approximation. This true_color option exposes
308 colors specified instead of an approximation. This true_color option exposes
301 that capability in prompt_toolkit to the IPython shell.
309 that capability in prompt_toolkit to the IPython shell.
302
310
303 Here is a good source for the current state of true color support in various
311 Here is a good source for the current state of true color support in various
304 terminal emulators and software projects: https://gist.github.com/XVilka/8346728
312 terminal emulators and software projects: https://gist.github.com/XVilka/8346728
305
313
306
314
307
315
308 IPython 5.0
316 IPython 5.0
309 ===========
317 ===========
310
318
311 Released July 7, 2016
319 Released July 7, 2016
312
320
313 New terminal interface
321 New terminal interface
314 ----------------------
322 ----------------------
315
323
316 IPython 5 features a major upgrade to the terminal interface, bringing live
324 IPython 5 features a major upgrade to the terminal interface, bringing live
317 syntax highlighting as you type, proper multiline editing and multiline paste,
325 syntax highlighting as you type, proper multiline editing and multiline paste,
318 and tab completions that don't clutter up your history.
326 and tab completions that don't clutter up your history.
319
327
320 .. image:: ../_images/ptshell_features.png
328 .. image:: ../_images/ptshell_features.png
321 :alt: New terminal interface features
329 :alt: New terminal interface features
322 :align: center
330 :align: center
323 :target: ../_images/ptshell_features.png
331 :target: ../_images/ptshell_features.png
324
332
325 These features are provided by the Python library `prompt_toolkit
333 These features are provided by the Python library `prompt_toolkit
326 <http://python-prompt-toolkit.readthedocs.io/en/stable/>`__, which replaces
334 <http://python-prompt-toolkit.readthedocs.io/en/stable/>`__, which replaces
327 ``readline`` throughout our terminal interface.
335 ``readline`` throughout our terminal interface.
328
336
329 Relying on this pure-Python, cross platform module also makes it simpler to
337 Relying on this pure-Python, cross platform module also makes it simpler to
330 install IPython. We have removed dependencies on ``pyreadline`` for Windows and
338 install IPython. We have removed dependencies on ``pyreadline`` for Windows and
331 ``gnureadline`` for Mac.
339 ``gnureadline`` for Mac.
332
340
333 Backwards incompatible changes
341 Backwards incompatible changes
334 ------------------------------
342 ------------------------------
335
343
336 - The ``%install_ext`` magic function, deprecated since 4.0, has now been deleted.
344 - The ``%install_ext`` magic function, deprecated since 4.0, has now been deleted.
337 You can distribute and install extensions as packages on PyPI.
345 You can distribute and install extensions as packages on PyPI.
338 - Callbacks registered while an event is being handled will now only be called
346 - Callbacks registered while an event is being handled will now only be called
339 for subsequent events; previously they could be called for the current event.
347 for subsequent events; previously they could be called for the current event.
340 Similarly, callbacks removed while handling an event *will* always get that
348 Similarly, callbacks removed while handling an event *will* always get that
341 event. See :ghissue:`9447` and :ghpull:`9453`.
349 event. See :ghissue:`9447` and :ghpull:`9453`.
342 - Integration with pydb has been removed since pydb development has been stopped
350 - Integration with pydb has been removed since pydb development has been stopped
343 since 2012, and pydb is not installable from PyPI.
351 since 2012, and pydb is not installable from PyPI.
344 - The ``autoedit_syntax`` option has apparently been broken for many years.
352 - The ``autoedit_syntax`` option has apparently been broken for many years.
345 It has been removed.
353 It has been removed.
346
354
347 New terminal interface
355 New terminal interface
348 ~~~~~~~~~~~~~~~~~~~~~~
356 ~~~~~~~~~~~~~~~~~~~~~~
349
357
350 The overhaul of the terminal interface will probably cause a range of minor
358 The overhaul of the terminal interface will probably cause a range of minor
351 issues for existing users.
359 issues for existing users.
352 This is inevitable for such a significant change, and we've done our best to
360 This is inevitable for such a significant change, and we've done our best to
353 minimise these issues.
361 minimise these issues.
354 Some changes that we're aware of, with suggestions on how to handle them:
362 Some changes that we're aware of, with suggestions on how to handle them:
355
363
356 IPython no longer uses readline configuration (``~/.inputrc``). We hope that
364 IPython no longer uses readline configuration (``~/.inputrc``). We hope that
357 the functionality you want (e.g. vi input mode) will be available by configuring
365 the functionality you want (e.g. vi input mode) will be available by configuring
358 IPython directly (see :doc:`/config/options/terminal`).
366 IPython directly (see :doc:`/config/options/terminal`).
359 If something's missing, please file an issue.
367 If something's missing, please file an issue.
360
368
361 The ``PromptManager`` class has been removed, and the prompt machinery simplified.
369 The ``PromptManager`` class has been removed, and the prompt machinery simplified.
362 See :ref:`custom_prompts` to customise prompts with the new machinery.
370 See :ref:`custom_prompts` to customise prompts with the new machinery.
363
371
364 :mod:`IPython.core.debugger` now provides a plainer interface.
372 :mod:`IPython.core.debugger` now provides a plainer interface.
365 :mod:`IPython.terminal.debugger` contains the terminal debugger using
373 :mod:`IPython.terminal.debugger` contains the terminal debugger using
366 prompt_toolkit.
374 prompt_toolkit.
367
375
368 There are new options to configure the colours used in syntax highlighting.
376 There are new options to configure the colours used in syntax highlighting.
369 We have tried to integrate them with our classic ``--colors`` option and
377 We have tried to integrate them with our classic ``--colors`` option and
370 ``%colors`` magic, but there's a mismatch in possibilities, so some configurations
378 ``%colors`` magic, but there's a mismatch in possibilities, so some configurations
371 may produce unexpected results. See :ref:`termcolour` for more information.
379 may produce unexpected results. See :ref:`termcolour` for more information.
372
380
373 The new interface is not compatible with Emacs 'inferior-shell' feature. To
381 The new interface is not compatible with Emacs 'inferior-shell' feature. To
374 continue using this, add the ``--simple-prompt`` flag to the command Emacs
382 continue using this, add the ``--simple-prompt`` flag to the command Emacs
375 runs. This flag disables most IPython features, relying on Emacs to provide
383 runs. This flag disables most IPython features, relying on Emacs to provide
376 things like tab completion.
384 things like tab completion.
377
385
378 Provisional Changes
386 Provisional Changes
379 -------------------
387 -------------------
380
388
381 Provisional changes are experimental functionality that may, or may not, make
389 Provisional changes are experimental functionality that may, or may not, make
382 it into a future version of IPython, and which API may change without warnings.
390 it into a future version of IPython, and which API may change without warnings.
383 Activating these features and using these API are at your own risk, and may have
391 Activating these features and using these API are at your own risk, and may have
384 security implication for your system, especially if used with the Jupyter notebook,
392 security implication for your system, especially if used with the Jupyter notebook,
385
393
386 When running via the Jupyter notebook interfaces, or other compatible client,
394 When running via the Jupyter notebook interfaces, or other compatible client,
387 you can enable rich documentation experimental functionality:
395 you can enable rich documentation experimental functionality:
388
396
389 When the ``docrepr`` package is installed setting the boolean flag
397 When the ``docrepr`` package is installed setting the boolean flag
390 ``InteractiveShell.sphinxify_docstring`` to ``True``, will process the various
398 ``InteractiveShell.sphinxify_docstring`` to ``True``, will process the various
391 object through sphinx before displaying them (see the ``docrepr`` package
399 object through sphinx before displaying them (see the ``docrepr`` package
392 documentation for more information.
400 documentation for more information.
393
401
394 You need to also enable the IPython pager display rich HTML representation
402 You need to also enable the IPython pager display rich HTML representation
395 using the ``InteractiveShell.enable_html_pager`` boolean configuration option.
403 using the ``InteractiveShell.enable_html_pager`` boolean configuration option.
396 As usual you can set these configuration options globally in your configuration
404 As usual you can set these configuration options globally in your configuration
397 files, alternatively you can turn them on dynamically using the following
405 files, alternatively you can turn them on dynamically using the following
398 snippet:
406 snippet:
399
407
400 .. code-block:: python
408 .. code-block:: python
401
409
402 ip = get_ipython()
410 ip = get_ipython()
403 ip.sphinxify_docstring = True
411 ip.sphinxify_docstring = True
404 ip.enable_html_pager = True
412 ip.enable_html_pager = True
405
413
406
414
407 You can test the effect of various combinations of the above configuration in
415 You can test the effect of various combinations of the above configuration in
408 the Jupyter notebook, with things example like :
416 the Jupyter notebook, with things example like :
409
417
410 .. code-block:: ipython
418 .. code-block:: ipython
411
419
412 import numpy as np
420 import numpy as np
413 np.histogram?
421 np.histogram?
414
422
415
423
416 This is part of an effort to make Documentation in Python richer and provide in
424 This is part of an effort to make Documentation in Python richer and provide in
417 the long term if possible dynamic examples that can contain math, images,
425 the long term if possible dynamic examples that can contain math, images,
418 widgets... As stated above this is nightly experimental feature with a lot of
426 widgets... As stated above this is nightly experimental feature with a lot of
419 (fun) problem to solve. We would be happy to get your feedback and expertise on
427 (fun) problem to solve. We would be happy to get your feedback and expertise on
420 it.
428 it.
421
429
422
430
423
431
424 Deprecated Features
432 Deprecated Features
425 -------------------
433 -------------------
426
434
427 Some deprecated features are listed in this section. Don't forget to enable
435 Some deprecated features are listed in this section. Don't forget to enable
428 ``DeprecationWarning`` as an error if you are using IPython in a Continuous
436 ``DeprecationWarning`` as an error if you are using IPython in a Continuous
429 Integration setup or in your testing in general:
437 Integration setup or in your testing in general:
430
438
431 .. code-block:: python
439 .. code-block:: python
432
440
433 import warnings
441 import warnings
434 warnings.filterwarnings('error', '.*', DeprecationWarning, module='yourmodule.*')
442 warnings.filterwarnings('error', '.*', DeprecationWarning, module='yourmodule.*')
435
443
436
444
437 - ``hooks.fix_error_editor`` seems unused and is pending deprecation.
445 - ``hooks.fix_error_editor`` seems unused and is pending deprecation.
438 - `IPython/core/excolors.py:ExceptionColors` is deprecated.
446 - `IPython/core/excolors.py:ExceptionColors` is deprecated.
439 - `IPython.core.InteractiveShell:write()` is deprecated; use `sys.stdout` instead.
447 - `IPython.core.InteractiveShell:write()` is deprecated; use `sys.stdout` instead.
440 - `IPython.core.InteractiveShell:write_err()` is deprecated; use `sys.stderr` instead.
448 - `IPython.core.InteractiveShell:write_err()` is deprecated; use `sys.stderr` instead.
441 - The `formatter` keyword argument to `Inspector.info` in `IPython.core.oinspec` has no effect.
449 - The `formatter` keyword argument to `Inspector.info` in `IPython.core.oinspec` has no effect.
442 - The `global_ns` keyword argument of IPython Embed was deprecated, and has no effect. Use `module` keyword argument instead.
450 - The `global_ns` keyword argument of IPython Embed was deprecated, and has no effect. Use `module` keyword argument instead.
443
451
444
452
445 Known Issues:
453 Known Issues:
446 -------------
454 -------------
447
455
448 - ``<Esc>`` Key does not dismiss the completer and does not clear the current
456 - ``<Esc>`` Key does not dismiss the completer and does not clear the current
449 buffer. This is an on purpose modification due to current technical
457 buffer. This is an on purpose modification due to current technical
450 limitation. Cf :ghpull:`9572`. Escape the control character which is used
458 limitation. Cf :ghpull:`9572`. Escape the control character which is used
451 for other shortcut, and there is no practical way to distinguish. Use Ctr-G
459 for other shortcut, and there is no practical way to distinguish. Use Ctr-G
452 or Ctrl-C as an alternative.
460 or Ctrl-C as an alternative.
453
461
454 - Cannot use ``Shift-Enter`` and ``Ctrl-Enter`` to submit code in terminal. cf
462 - Cannot use ``Shift-Enter`` and ``Ctrl-Enter`` to submit code in terminal. cf
455 :ghissue:`9587` and :ghissue:`9401`. In terminal there is no practical way to
463 :ghissue:`9587` and :ghissue:`9401`. In terminal there is no practical way to
456 distinguish these key sequences from a normal new line return.
464 distinguish these key sequences from a normal new line return.
457
465
458 - ``PageUp`` and ``pageDown`` do not move through completion menu.
466 - ``PageUp`` and ``pageDown`` do not move through completion menu.
459
467
460 - Color styles might not adapt to terminal emulator themes. This will need new
468 - Color styles might not adapt to terminal emulator themes. This will need new
461 version of Pygments to be released, and can be mitigated with custom themes.
469 version of Pygments to be released, and can be mitigated with custom themes.
General Comments 0
You need to be logged in to leave comments. Login now