##// END OF EJS Templates
Merge pull request from GHSA-pq7m-3gw7-gq5x...
Matthias Bussonnier -
Show More
@@ -0,0 +1,56 b''
1 """
2 Test that CVEs stay fixed.
3 """
4
5 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
6 from pathlib import Path
7 import random
8 import sys
9 import os
10 import string
11 import subprocess
12 import time
13
14 def test_cve_2022_21699():
15 """
16 Here we test CVE-2022-21699.
17
18 We create a temporary directory, cd into it.
19 Make a profile file that should not be executed and start IPython in a subprocess,
20 checking for the value.
21
22
23
24 """
25
26 dangerous_profile_dir = Path('profile_default')
27
28 dangerous_startup_dir = dangerous_profile_dir / 'startup'
29 dangerous_expected = 'CVE-2022-21699-'+''.join([random.choice(string.ascii_letters) for i in range(10)])
30
31 with TemporaryWorkingDirectory() as t:
32 dangerous_startup_dir.mkdir(parents=True)
33 (dangerous_startup_dir/ 'foo.py').write_text(f'print("{dangerous_expected}")')
34 # 1 sec to make sure FS is flushed.
35 #time.sleep(1)
36 cmd = [sys.executable,'-m', 'IPython']
37 env = os.environ.copy()
38 env['IPY_TEST_SIMPLE_PROMPT'] = '1'
39
40
41 # First we fake old behavior, making sure the profile is/was actually dangerous
42 p_dangerous = subprocess.Popen(cmd + [f'--profile-dir={dangerous_profile_dir}'], env=env, stdin=subprocess.PIPE,
43 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
44 out_dangerous, err_dangerouns = p_dangerous.communicate(b"exit\r")
45 assert dangerous_expected in out_dangerous.decode()
46
47 # Now that we know it _would_ have been dangerous, we test it's not loaded
48 p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE,
49 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
50 out, err = p.communicate(b"exit\r")
51 assert b'IPython' in out
52 assert dangerous_expected not in out.decode()
53 assert err == b''
54
55
56
@@ -1,152 +1,156 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 https://ipython.org
5 https://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
21
22 import os
22 import os
23 import sys
23 import sys
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Setup everything
26 # Setup everything
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 # Don't forget to also update setup.py when this changes!
29 # Don't forget to also update setup.py when this changes!
30 if sys.version_info < (3, 6):
30 if sys.version_info < (3, 6):
31 raise ImportError(
31 raise ImportError(
32 """
32 """
33 IPython 7.10+ supports Python 3.6 and above.
33 IPython 7.10+ supports Python 3.6 and above.
34 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
34 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
35 Python 3.3 and 3.4 were supported up to IPython 6.x.
35 Python 3.3 and 3.4 were supported up to IPython 6.x.
36 Python 3.5 was supported with IPython 7.0 to 7.9.
36 Python 3.5 was supported with IPython 7.0 to 7.9.
37
37
38 See IPython `README.rst` file for more information:
38 See IPython `README.rst` file for more information:
39
39
40 https://github.com/ipython/ipython/blob/master/README.rst
40 https://github.com/ipython/ipython/blob/master/README.rst
41
41
42 """)
42 """)
43
43
44 # Make it easy to import extensions - they are always directly on pythonpath.
44 # Make it easy to import extensions - they are always directly on pythonpath.
45 # Therefore, non-IPython modules can be added to extensions directory.
45 # Therefore, non-IPython modules can be added to extensions directory.
46 # This should probably be in ipapp.py.
46 # This should probably be in ipapp.py.
47 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
47 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Setup the top level names
50 # Setup the top level names
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 from .core.getipython import get_ipython
53 from .core.getipython import get_ipython
54 from .core import release
54 from .core import release
55 from .core.application import Application
55 from .core.application import Application
56 from .terminal.embed import embed
56 from .terminal.embed import embed
57
57
58 from .core.interactiveshell import InteractiveShell
58 from .core.interactiveshell import InteractiveShell
59 from .testing import test
59 from .testing import test
60 from .utils.sysinfo import sys_info
60 from .utils.sysinfo import sys_info
61 from .utils.frame import extract_module_locals
61 from .utils.frame import extract_module_locals
62
62
63 # Release data
63 # Release data
64 __author__ = '%s <%s>' % (release.author, release.author_email)
64 __author__ = '%s <%s>' % (release.author, release.author_email)
65 __license__ = release.license
65 __license__ = release.license
66 __version__ = release.version
66 __version__ = release.version
67 version_info = release.version_info
67 version_info = release.version_info
68 # list of CVEs that should have been patched in this release.
69 # this is informational and should not be relied upon.
70 __patched_cves__ = {"CVE-2022-21699"}
71
68
72
69 def embed_kernel(module=None, local_ns=None, **kwargs):
73 def embed_kernel(module=None, local_ns=None, **kwargs):
70 """Embed and start an IPython kernel in a given scope.
74 """Embed and start an IPython kernel in a given scope.
71
75
72 If you don't want the kernel to initialize the namespace
76 If you don't want the kernel to initialize the namespace
73 from the scope of the surrounding function,
77 from the scope of the surrounding function,
74 and/or you want to load full IPython configuration,
78 and/or you want to load full IPython configuration,
75 you probably want `IPython.start_kernel()` instead.
79 you probably want `IPython.start_kernel()` instead.
76
80
77 Parameters
81 Parameters
78 ----------
82 ----------
79 module : types.ModuleType, optional
83 module : types.ModuleType, optional
80 The module to load into IPython globals (default: caller)
84 The module to load into IPython globals (default: caller)
81 local_ns : dict, optional
85 local_ns : dict, optional
82 The namespace to load into IPython user namespace (default: caller)
86 The namespace to load into IPython user namespace (default: caller)
83
87
84 kwargs : various, optional
88 kwargs : various, optional
85 Further keyword args are relayed to the IPKernelApp constructor,
89 Further keyword args are relayed to the IPKernelApp constructor,
86 allowing configuration of the Kernel. Will only have an effect
90 allowing configuration of the Kernel. Will only have an effect
87 on the first embed_kernel call for a given process.
91 on the first embed_kernel call for a given process.
88 """
92 """
89
93
90 (caller_module, caller_locals) = extract_module_locals(1)
94 (caller_module, caller_locals) = extract_module_locals(1)
91 if module is None:
95 if module is None:
92 module = caller_module
96 module = caller_module
93 if local_ns is None:
97 if local_ns is None:
94 local_ns = caller_locals
98 local_ns = caller_locals
95
99
96 # Only import .zmq when we really need it
100 # Only import .zmq when we really need it
97 from ipykernel.embed import embed_kernel as real_embed_kernel
101 from ipykernel.embed import embed_kernel as real_embed_kernel
98 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
102 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
99
103
100 def start_ipython(argv=None, **kwargs):
104 def start_ipython(argv=None, **kwargs):
101 """Launch a normal IPython instance (as opposed to embedded)
105 """Launch a normal IPython instance (as opposed to embedded)
102
106
103 `IPython.embed()` puts a shell in a particular calling scope,
107 `IPython.embed()` puts a shell in a particular calling scope,
104 such as a function or method for debugging purposes,
108 such as a function or method for debugging purposes,
105 which is often not desirable.
109 which is often not desirable.
106
110
107 `start_ipython()` does full, regular IPython initialization,
111 `start_ipython()` does full, regular IPython initialization,
108 including loading startup files, configuration, etc.
112 including loading startup files, configuration, etc.
109 much of which is skipped by `embed()`.
113 much of which is skipped by `embed()`.
110
114
111 This is a public API method, and will survive implementation changes.
115 This is a public API method, and will survive implementation changes.
112
116
113 Parameters
117 Parameters
114 ----------
118 ----------
115
119
116 argv : list or None, optional
120 argv : list or None, optional
117 If unspecified or None, IPython will parse command-line options from sys.argv.
121 If unspecified or None, IPython will parse command-line options from sys.argv.
118 To prevent any command-line parsing, pass an empty list: `argv=[]`.
122 To prevent any command-line parsing, pass an empty list: `argv=[]`.
119 user_ns : dict, optional
123 user_ns : dict, optional
120 specify this dictionary to initialize the IPython user namespace with particular values.
124 specify this dictionary to initialize the IPython user namespace with particular values.
121 kwargs : various, optional
125 kwargs : various, optional
122 Any other kwargs will be passed to the Application constructor,
126 Any other kwargs will be passed to the Application constructor,
123 such as `config`.
127 such as `config`.
124 """
128 """
125 from IPython.terminal.ipapp import launch_new_instance
129 from IPython.terminal.ipapp import launch_new_instance
126 return launch_new_instance(argv=argv, **kwargs)
130 return launch_new_instance(argv=argv, **kwargs)
127
131
128 def start_kernel(argv=None, **kwargs):
132 def start_kernel(argv=None, **kwargs):
129 """Launch a normal IPython kernel instance (as opposed to embedded)
133 """Launch a normal IPython kernel instance (as opposed to embedded)
130
134
131 `IPython.embed_kernel()` puts a shell in a particular calling scope,
135 `IPython.embed_kernel()` puts a shell in a particular calling scope,
132 such as a function or method for debugging purposes,
136 such as a function or method for debugging purposes,
133 which is often not desirable.
137 which is often not desirable.
134
138
135 `start_kernel()` does full, regular IPython initialization,
139 `start_kernel()` does full, regular IPython initialization,
136 including loading startup files, configuration, etc.
140 including loading startup files, configuration, etc.
137 much of which is skipped by `embed()`.
141 much of which is skipped by `embed()`.
138
142
139 Parameters
143 Parameters
140 ----------
144 ----------
141
145
142 argv : list or None, optional
146 argv : list or None, optional
143 If unspecified or None, IPython will parse command-line options from sys.argv.
147 If unspecified or None, IPython will parse command-line options from sys.argv.
144 To prevent any command-line parsing, pass an empty list: `argv=[]`.
148 To prevent any command-line parsing, pass an empty list: `argv=[]`.
145 user_ns : dict, optional
149 user_ns : dict, optional
146 specify this dictionary to initialize the IPython user namespace with particular values.
150 specify this dictionary to initialize the IPython user namespace with particular values.
147 kwargs : various, optional
151 kwargs : various, optional
148 Any other kwargs will be passed to the Application constructor,
152 Any other kwargs will be passed to the Application constructor,
149 such as `config`.
153 such as `config`.
150 """
154 """
151 from IPython.kernel.zmq.kernelapp import launch_new_instance
155 from IPython.kernel.zmq.kernelapp import launch_new_instance
152 return launch_new_instance(argv=argv, **kwargs)
156 return launch_new_instance(argv=argv, **kwargs)
@@ -1,462 +1,462 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 traitlets import (
29 from traitlets import (
30 List, Unicode, Type, Bool, Set, Instance, Undefined,
30 List, Unicode, Type, Bool, Set, Instance, Undefined,
31 default, observe,
31 default, observe,
32 )
32 )
33
33
34 if os.name == 'nt':
34 if os.name == 'nt':
35 programdata = os.environ.get('PROGRAMDATA', None)
35 programdata = os.environ.get('PROGRAMDATA', None)
36 if programdata:
36 if programdata:
37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
38 else: # PROGRAMDATA is not defined by default on XP.
38 else: # PROGRAMDATA is not defined by default on XP.
39 SYSTEM_CONFIG_DIRS = []
39 SYSTEM_CONFIG_DIRS = []
40 else:
40 else:
41 SYSTEM_CONFIG_DIRS = [
41 SYSTEM_CONFIG_DIRS = [
42 "/usr/local/etc/ipython",
42 "/usr/local/etc/ipython",
43 "/etc/ipython",
43 "/etc/ipython",
44 ]
44 ]
45
45
46
46
47 ENV_CONFIG_DIRS = []
47 ENV_CONFIG_DIRS = []
48 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
48 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
49 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
49 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
50 # only add ENV_CONFIG if sys.prefix is not already included
50 # only add ENV_CONFIG if sys.prefix is not already included
51 ENV_CONFIG_DIRS.append(_env_config_dir)
51 ENV_CONFIG_DIRS.append(_env_config_dir)
52
52
53
53
54 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
54 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
55 if _envvar in {None, ''}:
55 if _envvar in {None, ''}:
56 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
56 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
57 else:
57 else:
58 if _envvar.lower() in {'1','true'}:
58 if _envvar.lower() in {'1','true'}:
59 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
59 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
60 elif _envvar.lower() in {'0','false'} :
60 elif _envvar.lower() in {'0','false'} :
61 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
61 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
62 else:
62 else:
63 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
63 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
64
65 # aliases and flags
65 # aliases and flags
66
66
67 base_aliases = {
67 base_aliases = {
68 'profile-dir' : 'ProfileDir.location',
68 'profile-dir' : 'ProfileDir.location',
69 'profile' : 'BaseIPythonApplication.profile',
69 'profile' : 'BaseIPythonApplication.profile',
70 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
70 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
71 'log-level' : 'Application.log_level',
71 'log-level' : 'Application.log_level',
72 'config' : 'BaseIPythonApplication.extra_config_file',
72 'config' : 'BaseIPythonApplication.extra_config_file',
73 }
73 }
74
74
75 base_flags = dict(
75 base_flags = dict(
76 debug = ({'Application' : {'log_level' : logging.DEBUG}},
76 debug = ({'Application' : {'log_level' : logging.DEBUG}},
77 "set log level to logging.DEBUG (maximize logging output)"),
77 "set log level to logging.DEBUG (maximize logging output)"),
78 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
78 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
79 "set log level to logging.CRITICAL (minimize logging output)"),
79 "set log level to logging.CRITICAL (minimize logging output)"),
80 init = ({'BaseIPythonApplication' : {
80 init = ({'BaseIPythonApplication' : {
81 'copy_config_files' : True,
81 'copy_config_files' : True,
82 'auto_create' : True}
82 'auto_create' : True}
83 }, """Initialize profile with default config files. This is equivalent
83 }, """Initialize profile with default config files. This is equivalent
84 to running `ipython profile create <profile>` prior to startup.
84 to running `ipython profile create <profile>` prior to startup.
85 """)
85 """)
86 )
86 )
87
87
88 class ProfileAwareConfigLoader(PyFileConfigLoader):
88 class ProfileAwareConfigLoader(PyFileConfigLoader):
89 """A Python file config loader that is aware of IPython profiles."""
89 """A Python file config loader that is aware of IPython profiles."""
90 def load_subconfig(self, fname, path=None, profile=None):
90 def load_subconfig(self, fname, path=None, profile=None):
91 if profile is not None:
91 if profile is not None:
92 try:
92 try:
93 profile_dir = ProfileDir.find_profile_dir_by_name(
93 profile_dir = ProfileDir.find_profile_dir_by_name(
94 get_ipython_dir(),
94 get_ipython_dir(),
95 profile,
95 profile,
96 )
96 )
97 except ProfileDirError:
97 except ProfileDirError:
98 return
98 return
99 path = profile_dir.location
99 path = profile_dir.location
100 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
100 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
101
101
102 class BaseIPythonApplication(Application):
102 class BaseIPythonApplication(Application):
103
103
104 name = u'ipython'
104 name = u'ipython'
105 description = Unicode(u'IPython: an enhanced interactive Python shell.')
105 description = Unicode(u'IPython: an enhanced interactive Python shell.')
106 version = Unicode(release.version)
106 version = Unicode(release.version)
107
107
108 aliases = base_aliases
108 aliases = base_aliases
109 flags = base_flags
109 flags = base_flags
110 classes = List([ProfileDir])
110 classes = List([ProfileDir])
111
111
112 # enable `load_subconfig('cfg.py', profile='name')`
112 # enable `load_subconfig('cfg.py', profile='name')`
113 python_config_loader_class = ProfileAwareConfigLoader
113 python_config_loader_class = ProfileAwareConfigLoader
114
114
115 # Track whether the config_file has changed,
115 # Track whether the config_file has changed,
116 # because some logic happens only if we aren't using the default.
116 # because some logic happens only if we aren't using the default.
117 config_file_specified = Set()
117 config_file_specified = Set()
118
118
119 config_file_name = Unicode()
119 config_file_name = Unicode()
120 @default('config_file_name')
120 @default('config_file_name')
121 def _config_file_name_default(self):
121 def _config_file_name_default(self):
122 return self.name.replace('-','_') + u'_config.py'
122 return self.name.replace('-','_') + u'_config.py'
123 @observe('config_file_name')
123 @observe('config_file_name')
124 def _config_file_name_changed(self, change):
124 def _config_file_name_changed(self, change):
125 if change['new'] != change['old']:
125 if change['new'] != change['old']:
126 self.config_file_specified.add(change['new'])
126 self.config_file_specified.add(change['new'])
127
127
128 # The directory that contains IPython's builtin profiles.
128 # The directory that contains IPython's builtin profiles.
129 builtin_profile_dir = Unicode(
129 builtin_profile_dir = Unicode(
130 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
130 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
131 )
131 )
132
132
133 config_file_paths = List(Unicode())
133 config_file_paths = List(Unicode())
134 @default('config_file_paths')
134 @default('config_file_paths')
135 def _config_file_paths_default(self):
135 def _config_file_paths_default(self):
136 return [os.getcwd()]
136 return []
137
137
138 extra_config_file = Unicode(
138 extra_config_file = Unicode(
139 help="""Path to an extra config file to load.
139 help="""Path to an extra config file to load.
140
140
141 If specified, load this config file in addition to any other IPython config.
141 If specified, load this config file in addition to any other IPython config.
142 """).tag(config=True)
142 """).tag(config=True)
143 @observe('extra_config_file')
143 @observe('extra_config_file')
144 def _extra_config_file_changed(self, change):
144 def _extra_config_file_changed(self, change):
145 old = change['old']
145 old = change['old']
146 new = change['new']
146 new = change['new']
147 try:
147 try:
148 self.config_files.remove(old)
148 self.config_files.remove(old)
149 except ValueError:
149 except ValueError:
150 pass
150 pass
151 self.config_file_specified.add(new)
151 self.config_file_specified.add(new)
152 self.config_files.append(new)
152 self.config_files.append(new)
153
153
154 profile = Unicode(u'default',
154 profile = Unicode(u'default',
155 help="""The IPython profile to use."""
155 help="""The IPython profile to use."""
156 ).tag(config=True)
156 ).tag(config=True)
157
157
158 @observe('profile')
158 @observe('profile')
159 def _profile_changed(self, change):
159 def _profile_changed(self, change):
160 self.builtin_profile_dir = os.path.join(
160 self.builtin_profile_dir = os.path.join(
161 get_ipython_package_dir(), u'config', u'profile', change['new']
161 get_ipython_package_dir(), u'config', u'profile', change['new']
162 )
162 )
163
163
164 ipython_dir = Unicode(
164 ipython_dir = Unicode(
165 help="""
165 help="""
166 The name of the IPython directory. This directory is used for logging
166 The name of the IPython directory. This directory is used for logging
167 configuration (through profiles), history storage, etc. The default
167 configuration (through profiles), history storage, etc. The default
168 is usually $HOME/.ipython. This option can also be specified through
168 is usually $HOME/.ipython. This option can also be specified through
169 the environment variable IPYTHONDIR.
169 the environment variable IPYTHONDIR.
170 """
170 """
171 ).tag(config=True)
171 ).tag(config=True)
172 @default('ipython_dir')
172 @default('ipython_dir')
173 def _ipython_dir_default(self):
173 def _ipython_dir_default(self):
174 d = get_ipython_dir()
174 d = get_ipython_dir()
175 self._ipython_dir_changed({
175 self._ipython_dir_changed({
176 'name': 'ipython_dir',
176 'name': 'ipython_dir',
177 'old': d,
177 'old': d,
178 'new': d,
178 'new': d,
179 })
179 })
180 return d
180 return d
181
181
182 _in_init_profile_dir = False
182 _in_init_profile_dir = False
183 profile_dir = Instance(ProfileDir, allow_none=True)
183 profile_dir = Instance(ProfileDir, allow_none=True)
184 @default('profile_dir')
184 @default('profile_dir')
185 def _profile_dir_default(self):
185 def _profile_dir_default(self):
186 # avoid recursion
186 # avoid recursion
187 if self._in_init_profile_dir:
187 if self._in_init_profile_dir:
188 return
188 return
189 # profile_dir requested early, force initialization
189 # profile_dir requested early, force initialization
190 self.init_profile_dir()
190 self.init_profile_dir()
191 return self.profile_dir
191 return self.profile_dir
192
192
193 overwrite = Bool(False,
193 overwrite = Bool(False,
194 help="""Whether to overwrite existing config files when copying"""
194 help="""Whether to overwrite existing config files when copying"""
195 ).tag(config=True)
195 ).tag(config=True)
196 auto_create = Bool(False,
196 auto_create = Bool(False,
197 help="""Whether to create profile dir if it doesn't exist"""
197 help="""Whether to create profile dir if it doesn't exist"""
198 ).tag(config=True)
198 ).tag(config=True)
199
199
200 config_files = List(Unicode())
200 config_files = List(Unicode())
201 @default('config_files')
201 @default('config_files')
202 def _config_files_default(self):
202 def _config_files_default(self):
203 return [self.config_file_name]
203 return [self.config_file_name]
204
204
205 copy_config_files = Bool(False,
205 copy_config_files = Bool(False,
206 help="""Whether to install the default config files into the profile dir.
206 help="""Whether to install the default config files into the profile dir.
207 If a new profile is being created, and IPython contains config files for that
207 If a new profile is being created, and IPython contains config files for that
208 profile, then they will be staged into the new directory. Otherwise,
208 profile, then they will be staged into the new directory. Otherwise,
209 default config files will be automatically generated.
209 default config files will be automatically generated.
210 """).tag(config=True)
210 """).tag(config=True)
211
211
212 verbose_crash = Bool(False,
212 verbose_crash = Bool(False,
213 help="""Create a massive crash report when IPython encounters what may be an
213 help="""Create a massive crash report when IPython encounters what may be an
214 internal error. The default is to append a short message to the
214 internal error. The default is to append a short message to the
215 usual traceback""").tag(config=True)
215 usual traceback""").tag(config=True)
216
216
217 # The class to use as the crash handler.
217 # The class to use as the crash handler.
218 crash_handler_class = Type(crashhandler.CrashHandler)
218 crash_handler_class = Type(crashhandler.CrashHandler)
219
219
220 @catch_config_error
220 @catch_config_error
221 def __init__(self, **kwargs):
221 def __init__(self, **kwargs):
222 super(BaseIPythonApplication, self).__init__(**kwargs)
222 super(BaseIPythonApplication, self).__init__(**kwargs)
223 # ensure current working directory exists
223 # ensure current working directory exists
224 try:
224 try:
225 os.getcwd()
225 os.getcwd()
226 except:
226 except:
227 # exit if cwd doesn't exist
227 # exit if cwd doesn't exist
228 self.log.error("Current working directory doesn't exist.")
228 self.log.error("Current working directory doesn't exist.")
229 self.exit(1)
229 self.exit(1)
230
230
231 #-------------------------------------------------------------------------
231 #-------------------------------------------------------------------------
232 # Various stages of Application creation
232 # Various stages of Application creation
233 #-------------------------------------------------------------------------
233 #-------------------------------------------------------------------------
234
234
235 deprecated_subcommands = {}
235 deprecated_subcommands = {}
236
236
237 def initialize_subcommand(self, subc, argv=None):
237 def initialize_subcommand(self, subc, argv=None):
238 if subc in self.deprecated_subcommands:
238 if subc in self.deprecated_subcommands:
239 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
239 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
240 "in future versions.".format(sub=subc))
240 "in future versions.".format(sub=subc))
241 self.log.warning("You likely want to use `jupyter {sub}` in the "
241 self.log.warning("You likely want to use `jupyter {sub}` in the "
242 "future".format(sub=subc))
242 "future".format(sub=subc))
243 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
243 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
244
244
245 def init_crash_handler(self):
245 def init_crash_handler(self):
246 """Create a crash handler, typically setting sys.excepthook to it."""
246 """Create a crash handler, typically setting sys.excepthook to it."""
247 self.crash_handler = self.crash_handler_class(self)
247 self.crash_handler = self.crash_handler_class(self)
248 sys.excepthook = self.excepthook
248 sys.excepthook = self.excepthook
249 def unset_crashhandler():
249 def unset_crashhandler():
250 sys.excepthook = sys.__excepthook__
250 sys.excepthook = sys.__excepthook__
251 atexit.register(unset_crashhandler)
251 atexit.register(unset_crashhandler)
252
252
253 def excepthook(self, etype, evalue, tb):
253 def excepthook(self, etype, evalue, tb):
254 """this is sys.excepthook after init_crashhandler
254 """this is sys.excepthook after init_crashhandler
255
255
256 set self.verbose_crash=True to use our full crashhandler, instead of
256 set self.verbose_crash=True to use our full crashhandler, instead of
257 a regular traceback with a short message (crash_handler_lite)
257 a regular traceback with a short message (crash_handler_lite)
258 """
258 """
259
259
260 if self.verbose_crash:
260 if self.verbose_crash:
261 return self.crash_handler(etype, evalue, tb)
261 return self.crash_handler(etype, evalue, tb)
262 else:
262 else:
263 return crashhandler.crash_handler_lite(etype, evalue, tb)
263 return crashhandler.crash_handler_lite(etype, evalue, tb)
264
264
265 @observe('ipython_dir')
265 @observe('ipython_dir')
266 def _ipython_dir_changed(self, change):
266 def _ipython_dir_changed(self, change):
267 old = change['old']
267 old = change['old']
268 new = change['new']
268 new = change['new']
269 if old is not Undefined:
269 if old is not Undefined:
270 str_old = os.path.abspath(old)
270 str_old = os.path.abspath(old)
271 if str_old in sys.path:
271 if str_old in sys.path:
272 sys.path.remove(str_old)
272 sys.path.remove(str_old)
273 str_path = os.path.abspath(new)
273 str_path = os.path.abspath(new)
274 sys.path.append(str_path)
274 sys.path.append(str_path)
275 ensure_dir_exists(new)
275 ensure_dir_exists(new)
276 readme = os.path.join(new, 'README')
276 readme = os.path.join(new, 'README')
277 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
277 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
278 if not os.path.exists(readme) and os.path.exists(readme_src):
278 if not os.path.exists(readme) and os.path.exists(readme_src):
279 shutil.copy(readme_src, readme)
279 shutil.copy(readme_src, readme)
280 for d in ('extensions', 'nbextensions'):
280 for d in ('extensions', 'nbextensions'):
281 path = os.path.join(new, d)
281 path = os.path.join(new, d)
282 try:
282 try:
283 ensure_dir_exists(path)
283 ensure_dir_exists(path)
284 except OSError as e:
284 except OSError as e:
285 # this will not be EEXIST
285 # this will not be EEXIST
286 self.log.error("couldn't create path %s: %s", path, e)
286 self.log.error("couldn't create path %s: %s", path, e)
287 self.log.debug("IPYTHONDIR set to: %s" % new)
287 self.log.debug("IPYTHONDIR set to: %s" % new)
288
288
289 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
289 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
290 """Load the config file.
290 """Load the config file.
291
291
292 By default, errors in loading config are handled, and a warning
292 By default, errors in loading config are handled, and a warning
293 printed on screen. For testing, the suppress_errors option is set
293 printed on screen. For testing, the suppress_errors option is set
294 to False, so errors will make tests fail.
294 to False, so errors will make tests fail.
295
295
296 `suppress_errors` default value is to be `None` in which case the
296 `suppress_errors` default value is to be `None` in which case the
297 behavior default to the one of `traitlets.Application`.
297 behavior default to the one of `traitlets.Application`.
298
298
299 The default value can be set :
299 The default value can be set :
300 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
300 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
301 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
301 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
302 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
302 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
303
303
304 Any other value are invalid, and will make IPython exit with a non-zero return code.
304 Any other value are invalid, and will make IPython exit with a non-zero return code.
305 """
305 """
306
306
307
307
308 self.log.debug("Searching path %s for config files", self.config_file_paths)
308 self.log.debug("Searching path %s for config files", self.config_file_paths)
309 base_config = 'ipython_config.py'
309 base_config = 'ipython_config.py'
310 self.log.debug("Attempting to load config file: %s" %
310 self.log.debug("Attempting to load config file: %s" %
311 base_config)
311 base_config)
312 try:
312 try:
313 if suppress_errors is not None:
313 if suppress_errors is not None:
314 old_value = Application.raise_config_file_errors
314 old_value = Application.raise_config_file_errors
315 Application.raise_config_file_errors = not suppress_errors;
315 Application.raise_config_file_errors = not suppress_errors;
316 Application.load_config_file(
316 Application.load_config_file(
317 self,
317 self,
318 base_config,
318 base_config,
319 path=self.config_file_paths
319 path=self.config_file_paths
320 )
320 )
321 except ConfigFileNotFound:
321 except ConfigFileNotFound:
322 # ignore errors loading parent
322 # ignore errors loading parent
323 self.log.debug("Config file %s not found", base_config)
323 self.log.debug("Config file %s not found", base_config)
324 pass
324 pass
325 if suppress_errors is not None:
325 if suppress_errors is not None:
326 Application.raise_config_file_errors = old_value
326 Application.raise_config_file_errors = old_value
327
327
328 for config_file_name in self.config_files:
328 for config_file_name in self.config_files:
329 if not config_file_name or config_file_name == base_config:
329 if not config_file_name or config_file_name == base_config:
330 continue
330 continue
331 self.log.debug("Attempting to load config file: %s" %
331 self.log.debug("Attempting to load config file: %s" %
332 self.config_file_name)
332 self.config_file_name)
333 try:
333 try:
334 Application.load_config_file(
334 Application.load_config_file(
335 self,
335 self,
336 config_file_name,
336 config_file_name,
337 path=self.config_file_paths
337 path=self.config_file_paths
338 )
338 )
339 except ConfigFileNotFound:
339 except ConfigFileNotFound:
340 # Only warn if the default config file was NOT being used.
340 # Only warn if the default config file was NOT being used.
341 if config_file_name in self.config_file_specified:
341 if config_file_name in self.config_file_specified:
342 msg = self.log.warning
342 msg = self.log.warning
343 else:
343 else:
344 msg = self.log.debug
344 msg = self.log.debug
345 msg("Config file not found, skipping: %s", config_file_name)
345 msg("Config file not found, skipping: %s", config_file_name)
346 except Exception:
346 except Exception:
347 # For testing purposes.
347 # For testing purposes.
348 if not suppress_errors:
348 if not suppress_errors:
349 raise
349 raise
350 self.log.warning("Error loading config file: %s" %
350 self.log.warning("Error loading config file: %s" %
351 self.config_file_name, exc_info=True)
351 self.config_file_name, exc_info=True)
352
352
353 def init_profile_dir(self):
353 def init_profile_dir(self):
354 """initialize the profile dir"""
354 """initialize the profile dir"""
355 self._in_init_profile_dir = True
355 self._in_init_profile_dir = True
356 if self.profile_dir is not None:
356 if self.profile_dir is not None:
357 # already ran
357 # already ran
358 return
358 return
359 if 'ProfileDir.location' not in self.config:
359 if 'ProfileDir.location' not in self.config:
360 # location not specified, find by profile name
360 # location not specified, find by profile name
361 try:
361 try:
362 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
362 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
363 except ProfileDirError:
363 except ProfileDirError:
364 # not found, maybe create it (always create default profile)
364 # not found, maybe create it (always create default profile)
365 if self.auto_create or self.profile == 'default':
365 if self.auto_create or self.profile == 'default':
366 try:
366 try:
367 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
367 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
368 except ProfileDirError:
368 except ProfileDirError:
369 self.log.fatal("Could not create profile: %r"%self.profile)
369 self.log.fatal("Could not create profile: %r"%self.profile)
370 self.exit(1)
370 self.exit(1)
371 else:
371 else:
372 self.log.info("Created profile dir: %r"%p.location)
372 self.log.info("Created profile dir: %r"%p.location)
373 else:
373 else:
374 self.log.fatal("Profile %r not found."%self.profile)
374 self.log.fatal("Profile %r not found."%self.profile)
375 self.exit(1)
375 self.exit(1)
376 else:
376 else:
377 self.log.debug("Using existing profile dir: %r"%p.location)
377 self.log.debug("Using existing profile dir: %r"%p.location)
378 else:
378 else:
379 location = self.config.ProfileDir.location
379 location = self.config.ProfileDir.location
380 # location is fully specified
380 # location is fully specified
381 try:
381 try:
382 p = ProfileDir.find_profile_dir(location, self.config)
382 p = ProfileDir.find_profile_dir(location, self.config)
383 except ProfileDirError:
383 except ProfileDirError:
384 # not found, maybe create it
384 # not found, maybe create it
385 if self.auto_create:
385 if self.auto_create:
386 try:
386 try:
387 p = ProfileDir.create_profile_dir(location, self.config)
387 p = ProfileDir.create_profile_dir(location, self.config)
388 except ProfileDirError:
388 except ProfileDirError:
389 self.log.fatal("Could not create profile directory: %r"%location)
389 self.log.fatal("Could not create profile directory: %r"%location)
390 self.exit(1)
390 self.exit(1)
391 else:
391 else:
392 self.log.debug("Creating new profile dir: %r"%location)
392 self.log.debug("Creating new profile dir: %r"%location)
393 else:
393 else:
394 self.log.fatal("Profile directory %r not found."%location)
394 self.log.fatal("Profile directory %r not found."%location)
395 self.exit(1)
395 self.exit(1)
396 else:
396 else:
397 self.log.info("Using existing profile dir: %r"%location)
397 self.log.info("Using existing profile dir: %r"%location)
398 # if profile_dir is specified explicitly, set profile name
398 # if profile_dir is specified explicitly, set profile name
399 dir_name = os.path.basename(p.location)
399 dir_name = os.path.basename(p.location)
400 if dir_name.startswith('profile_'):
400 if dir_name.startswith('profile_'):
401 self.profile = dir_name[8:]
401 self.profile = dir_name[8:]
402
402
403 self.profile_dir = p
403 self.profile_dir = p
404 self.config_file_paths.append(p.location)
404 self.config_file_paths.append(p.location)
405 self._in_init_profile_dir = False
405 self._in_init_profile_dir = False
406
406
407 def init_config_files(self):
407 def init_config_files(self):
408 """[optionally] copy default config files into profile dir."""
408 """[optionally] copy default config files into profile dir."""
409 self.config_file_paths.extend(ENV_CONFIG_DIRS)
409 self.config_file_paths.extend(ENV_CONFIG_DIRS)
410 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
410 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
411 # copy config files
411 # copy config files
412 path = self.builtin_profile_dir
412 path = self.builtin_profile_dir
413 if self.copy_config_files:
413 if self.copy_config_files:
414 src = self.profile
414 src = self.profile
415
415
416 cfg = self.config_file_name
416 cfg = self.config_file_name
417 if path and os.path.exists(os.path.join(path, cfg)):
417 if path and os.path.exists(os.path.join(path, cfg)):
418 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
418 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
419 cfg, src, self.profile_dir.location, self.overwrite)
419 cfg, src, self.profile_dir.location, self.overwrite)
420 )
420 )
421 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
421 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
422 else:
422 else:
423 self.stage_default_config_file()
423 self.stage_default_config_file()
424 else:
424 else:
425 # Still stage *bundled* config files, but not generated ones
425 # Still stage *bundled* config files, but not generated ones
426 # This is necessary for `ipython profile=sympy` to load the profile
426 # This is necessary for `ipython profile=sympy` to load the profile
427 # on the first go
427 # on the first go
428 files = glob.glob(os.path.join(path, '*.py'))
428 files = glob.glob(os.path.join(path, '*.py'))
429 for fullpath in files:
429 for fullpath in files:
430 cfg = os.path.basename(fullpath)
430 cfg = os.path.basename(fullpath)
431 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
431 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
432 # file was copied
432 # file was copied
433 self.log.warning("Staging bundled %s from %s into %r"%(
433 self.log.warning("Staging bundled %s from %s into %r"%(
434 cfg, self.profile, self.profile_dir.location)
434 cfg, self.profile, self.profile_dir.location)
435 )
435 )
436
436
437
437
438 def stage_default_config_file(self):
438 def stage_default_config_file(self):
439 """auto generate default config file, and stage it into the profile."""
439 """auto generate default config file, and stage it into the profile."""
440 s = self.generate_config_file()
440 s = self.generate_config_file()
441 fname = os.path.join(self.profile_dir.location, self.config_file_name)
441 fname = os.path.join(self.profile_dir.location, self.config_file_name)
442 if self.overwrite or not os.path.exists(fname):
442 if self.overwrite or not os.path.exists(fname):
443 self.log.warning("Generating default config file: %r"%(fname))
443 self.log.warning("Generating default config file: %r"%(fname))
444 with open(fname, 'w') as f:
444 with open(fname, 'w') as f:
445 f.write(s)
445 f.write(s)
446
446
447 @catch_config_error
447 @catch_config_error
448 def initialize(self, argv=None):
448 def initialize(self, argv=None):
449 # don't hook up crash handler before parsing command-line
449 # don't hook up crash handler before parsing command-line
450 self.parse_command_line(argv)
450 self.parse_command_line(argv)
451 self.init_crash_handler()
451 self.init_crash_handler()
452 if self.subapp is not None:
452 if self.subapp is not None:
453 # stop here if subapp is taking over
453 # stop here if subapp is taking over
454 return
454 return
455 # save a copy of CLI config to re-load after config files
455 # save a copy of CLI config to re-load after config files
456 # so that it has highest priority
456 # so that it has highest priority
457 cl_config = deepcopy(self.config)
457 cl_config = deepcopy(self.config)
458 self.init_profile_dir()
458 self.init_profile_dir()
459 self.init_config_files()
459 self.init_config_files()
460 self.load_config_file()
460 self.load_config_file()
461 # enforce cl-opts override configfile opts:
461 # enforce cl-opts override configfile opts:
462 self.update_config(cl_config)
462 self.update_config(cl_config)
@@ -1,311 +1,312 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25
25
26 from traitlets.config.application import Application
26 from traitlets.config.application import Application
27 from IPython.core.application import (
27 from IPython.core.application import (
28 BaseIPythonApplication, base_flags
28 BaseIPythonApplication, base_flags
29 )
29 )
30 from IPython.core.profiledir import ProfileDir
30 from IPython.core.profiledir import ProfileDir
31 from IPython.utils.importstring import import_item
31 from IPython.utils.importstring import import_item
32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
33 from traitlets import Unicode, Bool, Dict, observe
33 from traitlets import Unicode, Bool, Dict, observe
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Constants
36 # Constants
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 create_help = """Create an IPython profile by name
39 create_help = """Create an IPython profile by name
40
40
41 Create an ipython profile directory by its name or
41 Create an ipython profile directory by its name or
42 profile directory path. Profile directories contain
42 profile directory path. Profile directories contain
43 configuration, log and security related files and are named
43 configuration, log and security related files and are named
44 using the convention 'profile_<name>'. By default they are
44 using the convention 'profile_<name>'. By default they are
45 located in your ipython directory. Once created, you will
45 located in your ipython directory. Once created, you will
46 can edit the configuration files in the profile
46 can edit the configuration files in the profile
47 directory to configure IPython. Most users will create a
47 directory to configure IPython. Most users will create a
48 profile directory by name,
48 profile directory by name,
49 `ipython profile create myprofile`, which will put the directory
49 `ipython profile create myprofile`, which will put the directory
50 in `<ipython_dir>/profile_myprofile`.
50 in `<ipython_dir>/profile_myprofile`.
51 """
51 """
52 list_help = """List available IPython profiles
52 list_help = """List available IPython profiles
53
53
54 List all available profiles, by profile location, that can
54 List all available profiles, by profile location, that can
55 be found in the current working directly or in the ipython
55 be found in the current working directly or in the ipython
56 directory. Profile directories are named using the convention
56 directory. Profile directories are named using the convention
57 'profile_<profile>'.
57 'profile_<profile>'.
58 """
58 """
59 profile_help = """Manage IPython profiles
59 profile_help = """Manage IPython profiles
60
60
61 Profile directories contain
61 Profile directories contain
62 configuration, log and security related files and are named
62 configuration, log and security related files and are named
63 using the convention 'profile_<name>'. By default they are
63 using the convention 'profile_<name>'. By default they are
64 located in your ipython directory. You can create profiles
64 located in your ipython directory. You can create profiles
65 with `ipython profile create <name>`, or see the profiles you
65 with `ipython profile create <name>`, or see the profiles you
66 already have with `ipython profile list`
66 already have with `ipython profile list`
67
67
68 To get started configuring IPython, simply do:
68 To get started configuring IPython, simply do:
69
69
70 $> ipython profile create
70 $> ipython profile create
71
71
72 and IPython will create the default profile in <ipython_dir>/profile_default,
72 and IPython will create the default profile in <ipython_dir>/profile_default,
73 where you can edit ipython_config.py to start configuring IPython.
73 where you can edit ipython_config.py to start configuring IPython.
74
74
75 """
75 """
76
76
77 _list_examples = "ipython profile list # list all profiles"
77 _list_examples = "ipython profile list # list all profiles"
78
78
79 _create_examples = """
79 _create_examples = """
80 ipython profile create foo # create profile foo w/ default config files
80 ipython profile create foo # create profile foo w/ default config files
81 ipython profile create foo --reset # restage default config files over current
81 ipython profile create foo --reset # restage default config files over current
82 ipython profile create foo --parallel # also stage parallel config files
82 ipython profile create foo --parallel # also stage parallel config files
83 """
83 """
84
84
85 _main_examples = """
85 _main_examples = """
86 ipython profile create -h # show the help string for the create subcommand
86 ipython profile create -h # show the help string for the create subcommand
87 ipython profile list -h # show the help string for the list subcommand
87 ipython profile list -h # show the help string for the list subcommand
88
88
89 ipython locate profile foo # print the path to the directory for profile 'foo'
89 ipython locate profile foo # print the path to the directory for profile 'foo'
90 """
90 """
91
91
92 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
93 # Profile Application Class (for `ipython profile` subcommand)
93 # Profile Application Class (for `ipython profile` subcommand)
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95
95
96
96
97 def list_profiles_in(path):
97 def list_profiles_in(path):
98 """list profiles in a given root directory"""
98 """list profiles in a given root directory"""
99 profiles = []
99 profiles = []
100
100
101 # for python 3.6+ rewrite to: with os.scandir(path) as dirlist:
101 # for python 3.6+ rewrite to: with os.scandir(path) as dirlist:
102 files = os.scandir(path)
102 files = os.scandir(path)
103 for f in files:
103 for f in files:
104 if f.is_dir() and f.name.startswith('profile_'):
104 if f.is_dir() and f.name.startswith('profile_'):
105 profiles.append(f.name.split('_', 1)[-1])
105 profiles.append(f.name.split('_', 1)[-1])
106 return profiles
106 return profiles
107
107
108
108
109 def list_bundled_profiles():
109 def list_bundled_profiles():
110 """list profiles that are bundled with IPython."""
110 """list profiles that are bundled with IPython."""
111 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
111 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
112 profiles = []
112 profiles = []
113
113
114 # for python 3.6+ rewrite to: with os.scandir(path) as dirlist:
114 # for python 3.6+ rewrite to: with os.scandir(path) as dirlist:
115 files = os.scandir(path)
115 files = os.scandir(path)
116 for profile in files:
116 for profile in files:
117 if profile.is_dir() and profile.name != "__pycache__":
117 if profile.is_dir() and profile.name != "__pycache__":
118 profiles.append(profile.name)
118 profiles.append(profile.name)
119 return profiles
119 return profiles
120
120
121
121
122 class ProfileLocate(BaseIPythonApplication):
122 class ProfileLocate(BaseIPythonApplication):
123 description = """print the path to an IPython profile dir"""
123 description = """print the path to an IPython profile dir"""
124
124
125 def parse_command_line(self, argv=None):
125 def parse_command_line(self, argv=None):
126 super(ProfileLocate, self).parse_command_line(argv)
126 super(ProfileLocate, self).parse_command_line(argv)
127 if self.extra_args:
127 if self.extra_args:
128 self.profile = self.extra_args[0]
128 self.profile = self.extra_args[0]
129
129
130 def start(self):
130 def start(self):
131 print(self.profile_dir.location)
131 print(self.profile_dir.location)
132
132
133
133
134 class ProfileList(Application):
134 class ProfileList(Application):
135 name = u'ipython-profile'
135 name = u'ipython-profile'
136 description = list_help
136 description = list_help
137 examples = _list_examples
137 examples = _list_examples
138
138
139 aliases = Dict({
139 aliases = Dict({
140 'ipython-dir' : 'ProfileList.ipython_dir',
140 'ipython-dir' : 'ProfileList.ipython_dir',
141 'log-level' : 'Application.log_level',
141 'log-level' : 'Application.log_level',
142 })
142 })
143 flags = Dict(dict(
143 flags = Dict(dict(
144 debug = ({'Application' : {'log_level' : 0}},
144 debug = ({'Application' : {'log_level' : 0}},
145 "Set Application.log_level to 0, maximizing log output."
145 "Set Application.log_level to 0, maximizing log output."
146 )
146 )
147 ))
147 ))
148
148
149 ipython_dir = Unicode(get_ipython_dir(),
149 ipython_dir = Unicode(get_ipython_dir(),
150 help="""
150 help="""
151 The name of the IPython directory. This directory is used for logging
151 The name of the IPython directory. This directory is used for logging
152 configuration (through profiles), history storage, etc. The default
152 configuration (through profiles), history storage, etc. The default
153 is usually $HOME/.ipython. This options can also be specified through
153 is usually $HOME/.ipython. This options can also be specified through
154 the environment variable IPYTHONDIR.
154 the environment variable IPYTHONDIR.
155 """
155 """
156 ).tag(config=True)
156 ).tag(config=True)
157
157
158
158
159 def _print_profiles(self, profiles):
159 def _print_profiles(self, profiles):
160 """print list of profiles, indented."""
160 """print list of profiles, indented."""
161 for profile in profiles:
161 for profile in profiles:
162 print(' %s' % profile)
162 print(' %s' % profile)
163
163
164 def list_profile_dirs(self):
164 def list_profile_dirs(self):
165 profiles = list_bundled_profiles()
165 profiles = list_bundled_profiles()
166 if profiles:
166 if profiles:
167 print()
167 print()
168 print("Available profiles in IPython:")
168 print("Available profiles in IPython:")
169 self._print_profiles(profiles)
169 self._print_profiles(profiles)
170 print()
170 print()
171 print(" The first request for a bundled profile will copy it")
171 print(" The first request for a bundled profile will copy it")
172 print(" into your IPython directory (%s)," % self.ipython_dir)
172 print(" into your IPython directory (%s)," % self.ipython_dir)
173 print(" where you can customize it.")
173 print(" where you can customize it.")
174
174
175 profiles = list_profiles_in(self.ipython_dir)
175 profiles = list_profiles_in(self.ipython_dir)
176 if profiles:
176 if profiles:
177 print()
177 print()
178 print("Available profiles in %s:" % self.ipython_dir)
178 print("Available profiles in %s:" % self.ipython_dir)
179 self._print_profiles(profiles)
179 self._print_profiles(profiles)
180
180
181 profiles = list_profiles_in(os.getcwd())
181 profiles = list_profiles_in(os.getcwd())
182 if profiles:
182 if profiles:
183 print()
183 print()
184 print("Available profiles in current directory (%s):" % os.getcwd())
184 print(
185 self._print_profiles(profiles)
185 "Profiles from CWD have been removed for security reason, see CVE-2022-21699:"
186
186 )
187
187 print()
188 print()
188 print("To use any of the above profiles, start IPython with:")
189 print("To use any of the above profiles, start IPython with:")
189 print(" ipython --profile=<name>")
190 print(" ipython --profile=<name>")
190 print()
191 print()
191
192
192 def start(self):
193 def start(self):
193 self.list_profile_dirs()
194 self.list_profile_dirs()
194
195
195
196
196 create_flags = {}
197 create_flags = {}
197 create_flags.update(base_flags)
198 create_flags.update(base_flags)
198 # don't include '--init' flag, which implies running profile create in other apps
199 # don't include '--init' flag, which implies running profile create in other apps
199 create_flags.pop('init')
200 create_flags.pop('init')
200 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
201 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
201 "reset config files in this profile to the defaults.")
202 "reset config files in this profile to the defaults.")
202 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
203 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
203 "Include the config files for parallel "
204 "Include the config files for parallel "
204 "computing apps (ipengine, ipcontroller, etc.)")
205 "computing apps (ipengine, ipcontroller, etc.)")
205
206
206
207
207 class ProfileCreate(BaseIPythonApplication):
208 class ProfileCreate(BaseIPythonApplication):
208 name = u'ipython-profile'
209 name = u'ipython-profile'
209 description = create_help
210 description = create_help
210 examples = _create_examples
211 examples = _create_examples
211 auto_create = Bool(True)
212 auto_create = Bool(True)
212 def _log_format_default(self):
213 def _log_format_default(self):
213 return "[%(name)s] %(message)s"
214 return "[%(name)s] %(message)s"
214
215
215 def _copy_config_files_default(self):
216 def _copy_config_files_default(self):
216 return True
217 return True
217
218
218 parallel = Bool(False,
219 parallel = Bool(False,
219 help="whether to include parallel computing config files"
220 help="whether to include parallel computing config files"
220 ).tag(config=True)
221 ).tag(config=True)
221
222
222 @observe('parallel')
223 @observe('parallel')
223 def _parallel_changed(self, change):
224 def _parallel_changed(self, change):
224 parallel_files = [ 'ipcontroller_config.py',
225 parallel_files = [ 'ipcontroller_config.py',
225 'ipengine_config.py',
226 'ipengine_config.py',
226 'ipcluster_config.py'
227 'ipcluster_config.py'
227 ]
228 ]
228 if change['new']:
229 if change['new']:
229 for cf in parallel_files:
230 for cf in parallel_files:
230 self.config_files.append(cf)
231 self.config_files.append(cf)
231 else:
232 else:
232 for cf in parallel_files:
233 for cf in parallel_files:
233 if cf in self.config_files:
234 if cf in self.config_files:
234 self.config_files.remove(cf)
235 self.config_files.remove(cf)
235
236
236 def parse_command_line(self, argv):
237 def parse_command_line(self, argv):
237 super(ProfileCreate, self).parse_command_line(argv)
238 super(ProfileCreate, self).parse_command_line(argv)
238 # accept positional arg as profile name
239 # accept positional arg as profile name
239 if self.extra_args:
240 if self.extra_args:
240 self.profile = self.extra_args[0]
241 self.profile = self.extra_args[0]
241
242
242 flags = Dict(create_flags)
243 flags = Dict(create_flags)
243
244
244 classes = [ProfileDir]
245 classes = [ProfileDir]
245
246
246 def _import_app(self, app_path):
247 def _import_app(self, app_path):
247 """import an app class"""
248 """import an app class"""
248 app = None
249 app = None
249 name = app_path.rsplit('.', 1)[-1]
250 name = app_path.rsplit('.', 1)[-1]
250 try:
251 try:
251 app = import_item(app_path)
252 app = import_item(app_path)
252 except ImportError:
253 except ImportError:
253 self.log.info("Couldn't import %s, config file will be excluded", name)
254 self.log.info("Couldn't import %s, config file will be excluded", name)
254 except Exception:
255 except Exception:
255 self.log.warning('Unexpected error importing %s', name, exc_info=True)
256 self.log.warning('Unexpected error importing %s', name, exc_info=True)
256 return app
257 return app
257
258
258 def init_config_files(self):
259 def init_config_files(self):
259 super(ProfileCreate, self).init_config_files()
260 super(ProfileCreate, self).init_config_files()
260 # use local imports, since these classes may import from here
261 # use local imports, since these classes may import from here
261 from IPython.terminal.ipapp import TerminalIPythonApp
262 from IPython.terminal.ipapp import TerminalIPythonApp
262 apps = [TerminalIPythonApp]
263 apps = [TerminalIPythonApp]
263 for app_path in (
264 for app_path in (
264 'ipykernel.kernelapp.IPKernelApp',
265 'ipykernel.kernelapp.IPKernelApp',
265 ):
266 ):
266 app = self._import_app(app_path)
267 app = self._import_app(app_path)
267 if app is not None:
268 if app is not None:
268 apps.append(app)
269 apps.append(app)
269 if self.parallel:
270 if self.parallel:
270 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
271 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
271 from ipyparallel.apps.ipengineapp import IPEngineApp
272 from ipyparallel.apps.ipengineapp import IPEngineApp
272 from ipyparallel.apps.ipclusterapp import IPClusterStart
273 from ipyparallel.apps.ipclusterapp import IPClusterStart
273 apps.extend([
274 apps.extend([
274 IPControllerApp,
275 IPControllerApp,
275 IPEngineApp,
276 IPEngineApp,
276 IPClusterStart,
277 IPClusterStart,
277 ])
278 ])
278 for App in apps:
279 for App in apps:
279 app = App()
280 app = App()
280 app.config.update(self.config)
281 app.config.update(self.config)
281 app.log = self.log
282 app.log = self.log
282 app.overwrite = self.overwrite
283 app.overwrite = self.overwrite
283 app.copy_config_files=True
284 app.copy_config_files=True
284 app.ipython_dir=self.ipython_dir
285 app.ipython_dir=self.ipython_dir
285 app.profile_dir=self.profile_dir
286 app.profile_dir=self.profile_dir
286 app.init_config_files()
287 app.init_config_files()
287
288
288 def stage_default_config_file(self):
289 def stage_default_config_file(self):
289 pass
290 pass
290
291
291
292
292 class ProfileApp(Application):
293 class ProfileApp(Application):
293 name = u'ipython profile'
294 name = u'ipython profile'
294 description = profile_help
295 description = profile_help
295 examples = _main_examples
296 examples = _main_examples
296
297
297 subcommands = Dict(dict(
298 subcommands = Dict(dict(
298 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
299 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
299 list = (ProfileList, ProfileList.description.splitlines()[0]),
300 list = (ProfileList, ProfileList.description.splitlines()[0]),
300 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
301 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
301 ))
302 ))
302
303
303 def start(self):
304 def start(self):
304 if self.subapp is None:
305 if self.subapp is None:
305 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
306 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
306 print()
307 print()
307 self.print_description()
308 self.print_description()
308 self.print_subcommands()
309 self.print_subcommands()
309 self.exit(1)
310 self.exit(1)
310 else:
311 else:
311 return self.subapp.start()
312 return self.subapp.start()
@@ -1,223 +1,223 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 ..paths import get_ipython_package_dir
12 from ..paths import get_ipython_package_dir
13 from ..utils.path import expand_path, ensure_dir_exists
13 from ..utils.path import expand_path, ensure_dir_exists
14 from traitlets import Unicode, Bool, observe
14 from traitlets import Unicode, Bool, observe
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Module errors
17 # Module errors
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 class ProfileDirError(Exception):
20 class ProfileDirError(Exception):
21 pass
21 pass
22
22
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Class for managing profile directories
25 # Class for managing profile directories
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 class ProfileDir(LoggingConfigurable):
28 class ProfileDir(LoggingConfigurable):
29 """An object to manage the profile directory and its resources.
29 """An object to manage the profile directory and its resources.
30
30
31 The profile directory is used by all IPython applications, to manage
31 The profile directory is used by all IPython applications, to manage
32 configuration, logging and security.
32 configuration, logging and security.
33
33
34 This object knows how to find, create and manage these directories. This
34 This object knows how to find, create and manage these directories. This
35 should be used by any code that wants to handle profiles.
35 should be used by any code that wants to handle profiles.
36 """
36 """
37
37
38 security_dir_name = Unicode('security')
38 security_dir_name = Unicode('security')
39 log_dir_name = Unicode('log')
39 log_dir_name = Unicode('log')
40 startup_dir_name = Unicode('startup')
40 startup_dir_name = Unicode('startup')
41 pid_dir_name = Unicode('pid')
41 pid_dir_name = Unicode('pid')
42 static_dir_name = Unicode('static')
42 static_dir_name = Unicode('static')
43 security_dir = Unicode(u'')
43 security_dir = Unicode(u'')
44 log_dir = Unicode(u'')
44 log_dir = Unicode(u'')
45 startup_dir = Unicode(u'')
45 startup_dir = Unicode(u'')
46 pid_dir = Unicode(u'')
46 pid_dir = Unicode(u'')
47 static_dir = Unicode(u'')
47 static_dir = Unicode(u'')
48
48
49 location = Unicode(u'',
49 location = Unicode(u'',
50 help="""Set the profile location directly. This overrides the logic used by the
50 help="""Set the profile location directly. This overrides the logic used by the
51 `profile` option.""",
51 `profile` option.""",
52 ).tag(config=True)
52 ).tag(config=True)
53
53
54 _location_isset = Bool(False) # flag for detecting multiply set location
54 _location_isset = Bool(False) # flag for detecting multiply set location
55 @observe('location')
55 @observe('location')
56 def _location_changed(self, change):
56 def _location_changed(self, change):
57 if self._location_isset:
57 if self._location_isset:
58 raise RuntimeError("Cannot set profile location more than once.")
58 raise RuntimeError("Cannot set profile location more than once.")
59 self._location_isset = True
59 self._location_isset = True
60 new = change['new']
60 new = change['new']
61 ensure_dir_exists(new)
61 ensure_dir_exists(new)
62
62
63 # ensure config files exist:
63 # ensure config files exist:
64 self.security_dir = os.path.join(new, self.security_dir_name)
64 self.security_dir = os.path.join(new, self.security_dir_name)
65 self.log_dir = os.path.join(new, self.log_dir_name)
65 self.log_dir = os.path.join(new, self.log_dir_name)
66 self.startup_dir = os.path.join(new, self.startup_dir_name)
66 self.startup_dir = os.path.join(new, self.startup_dir_name)
67 self.pid_dir = os.path.join(new, self.pid_dir_name)
67 self.pid_dir = os.path.join(new, self.pid_dir_name)
68 self.static_dir = os.path.join(new, self.static_dir_name)
68 self.static_dir = os.path.join(new, self.static_dir_name)
69 self.check_dirs()
69 self.check_dirs()
70
70
71 def _mkdir(self, path, mode=None):
71 def _mkdir(self, path, mode=None):
72 """ensure a directory exists at a given path
72 """ensure a directory exists at a given path
73
73
74 This is a version of os.mkdir, with the following differences:
74 This is a version of os.mkdir, with the following differences:
75
75
76 - returns True if it created the directory, False otherwise
76 - returns True if it created the directory, False otherwise
77 - ignores EEXIST, protecting against race conditions where
77 - ignores EEXIST, protecting against race conditions where
78 the dir may have been created in between the check and
78 the dir may have been created in between the check and
79 the creation
79 the creation
80 - sets permissions if requested and the dir already exists
80 - sets permissions if requested and the dir already exists
81 """
81 """
82 if os.path.exists(path):
82 if os.path.exists(path):
83 if mode and os.stat(path).st_mode != mode:
83 if mode and os.stat(path).st_mode != mode:
84 try:
84 try:
85 os.chmod(path, mode)
85 os.chmod(path, mode)
86 except OSError:
86 except OSError:
87 self.log.warning(
87 self.log.warning(
88 "Could not set permissions on %s",
88 "Could not set permissions on %s",
89 path
89 path
90 )
90 )
91 return False
91 return False
92 try:
92 try:
93 if mode:
93 if mode:
94 os.mkdir(path, mode)
94 os.mkdir(path, mode)
95 else:
95 else:
96 os.mkdir(path)
96 os.mkdir(path)
97 except OSError as e:
97 except OSError as e:
98 if e.errno == errno.EEXIST:
98 if e.errno == errno.EEXIST:
99 return False
99 return False
100 else:
100 else:
101 raise
101 raise
102
102
103 return True
103 return True
104
104
105 @observe('log_dir')
105 @observe('log_dir')
106 def check_log_dir(self, change=None):
106 def check_log_dir(self, change=None):
107 self._mkdir(self.log_dir)
107 self._mkdir(self.log_dir)
108
108
109 @observe('startup_dir')
109 @observe('startup_dir')
110 def check_startup_dir(self, change=None):
110 def check_startup_dir(self, change=None):
111 self._mkdir(self.startup_dir)
111 self._mkdir(self.startup_dir)
112
112
113 readme = os.path.join(self.startup_dir, 'README')
113 readme = os.path.join(self.startup_dir, 'README')
114 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
114 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
115
115
116 if not os.path.exists(src):
116 if not os.path.exists(src):
117 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
117 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
118
118
119 if os.path.exists(src) and not os.path.exists(readme):
119 if os.path.exists(src) and not os.path.exists(readme):
120 shutil.copy(src, readme)
120 shutil.copy(src, readme)
121
121
122 @observe('security_dir')
122 @observe('security_dir')
123 def check_security_dir(self, change=None):
123 def check_security_dir(self, change=None):
124 self._mkdir(self.security_dir, 0o40700)
124 self._mkdir(self.security_dir, 0o40700)
125
125
126 @observe('pid_dir')
126 @observe('pid_dir')
127 def check_pid_dir(self, change=None):
127 def check_pid_dir(self, change=None):
128 self._mkdir(self.pid_dir, 0o40700)
128 self._mkdir(self.pid_dir, 0o40700)
129
129
130 def check_dirs(self):
130 def check_dirs(self):
131 self.check_security_dir()
131 self.check_security_dir()
132 self.check_log_dir()
132 self.check_log_dir()
133 self.check_pid_dir()
133 self.check_pid_dir()
134 self.check_startup_dir()
134 self.check_startup_dir()
135
135
136 def copy_config_file(self, config_file, path=None, overwrite=False):
136 def copy_config_file(self, config_file, path=None, overwrite=False):
137 """Copy a default config file into the active profile directory.
137 """Copy a default config file into the active profile directory.
138
138
139 Default configuration files are kept in :mod:`IPython.core.profile`.
139 Default configuration files are kept in :mod:`IPython.core.profile`.
140 This function moves these from that location to the working profile
140 This function moves these from that location to the working profile
141 directory.
141 directory.
142 """
142 """
143 dst = os.path.join(self.location, config_file)
143 dst = os.path.join(self.location, config_file)
144 if os.path.isfile(dst) and not overwrite:
144 if os.path.isfile(dst) and not overwrite:
145 return False
145 return False
146 if path is None:
146 if path is None:
147 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
147 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
148 src = os.path.join(path, config_file)
148 src = os.path.join(path, config_file)
149 shutil.copy(src, dst)
149 shutil.copy(src, dst)
150 return True
150 return True
151
151
152 @classmethod
152 @classmethod
153 def create_profile_dir(cls, profile_dir, config=None):
153 def create_profile_dir(cls, profile_dir, config=None):
154 """Create a new profile directory given a full path.
154 """Create a new profile directory given a full path.
155
155
156 Parameters
156 Parameters
157 ----------
157 ----------
158 profile_dir : str
158 profile_dir : str
159 The full path to the profile directory. If it does exist, it will
159 The full path to the profile directory. If it does exist, it will
160 be used. If not, it will be created.
160 be used. If not, it will be created.
161 """
161 """
162 return cls(location=profile_dir, config=config)
162 return cls(location=profile_dir, config=config)
163
163
164 @classmethod
164 @classmethod
165 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
165 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
166 """Create a profile dir by profile name and path.
166 """Create a profile dir by profile name and path.
167
167
168 Parameters
168 Parameters
169 ----------
169 ----------
170 path : unicode
170 path : unicode
171 The path (directory) to put the profile directory in.
171 The path (directory) to put the profile directory in.
172 name : unicode
172 name : unicode
173 The name of the profile. The name of the profile directory will
173 The name of the profile. The name of the profile directory will
174 be "profile_<profile>".
174 be "profile_<profile>".
175 """
175 """
176 if not os.path.isdir(path):
176 if not os.path.isdir(path):
177 raise ProfileDirError('Directory not found: %s' % path)
177 raise ProfileDirError('Directory not found: %s' % path)
178 profile_dir = os.path.join(path, u'profile_' + name)
178 profile_dir = os.path.join(path, u'profile_' + name)
179 return cls(location=profile_dir, config=config)
179 return cls(location=profile_dir, config=config)
180
180
181 @classmethod
181 @classmethod
182 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
182 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
183 """Find an existing profile dir by profile name, return its ProfileDir.
183 """Find an existing profile dir by profile name, return its ProfileDir.
184
184
185 This searches through a sequence of paths for a profile dir. If it
185 This searches through a sequence of paths for a profile dir. If it
186 is not found, a :class:`ProfileDirError` exception will be raised.
186 is not found, a :class:`ProfileDirError` exception will be raised.
187
187
188 The search path algorithm is:
188 The search path algorithm is:
189 1. ``os.getcwd()``
189 1. ``os.getcwd()`` # removed for security reason.
190 2. ``ipython_dir``
190 2. ``ipython_dir``
191
191
192 Parameters
192 Parameters
193 ----------
193 ----------
194 ipython_dir : unicode or str
194 ipython_dir : unicode or str
195 The IPython directory to use.
195 The IPython directory to use.
196 name : unicode or str
196 name : unicode or str
197 The name of the profile. The name of the profile directory
197 The name of the profile. The name of the profile directory
198 will be "profile_<profile>".
198 will be "profile_<profile>".
199 """
199 """
200 dirname = u'profile_' + name
200 dirname = u'profile_' + name
201 paths = [os.getcwd(), ipython_dir]
201 paths = [ipython_dir]
202 for p in paths:
202 for p in paths:
203 profile_dir = os.path.join(p, dirname)
203 profile_dir = os.path.join(p, dirname)
204 if os.path.isdir(profile_dir):
204 if os.path.isdir(profile_dir):
205 return cls(location=profile_dir, config=config)
205 return cls(location=profile_dir, config=config)
206 else:
206 else:
207 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
207 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
208
208
209 @classmethod
209 @classmethod
210 def find_profile_dir(cls, profile_dir, config=None):
210 def find_profile_dir(cls, profile_dir, config=None):
211 """Find/create a profile dir and return its ProfileDir.
211 """Find/create a profile dir and return its ProfileDir.
212
212
213 This will create the profile directory if it doesn't exist.
213 This will create the profile directory if it doesn't exist.
214
214
215 Parameters
215 Parameters
216 ----------
216 ----------
217 profile_dir : unicode or str
217 profile_dir : unicode or str
218 The path of the profile directory.
218 The path of the profile directory.
219 """
219 """
220 profile_dir = expand_path(profile_dir)
220 profile_dir = expand_path(profile_dir)
221 if not os.path.isdir(profile_dir):
221 if not os.path.isdir(profile_dir):
222 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
222 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
223 return cls(location=profile_dir, config=config)
223 return cls(location=profile_dir, config=config)
@@ -1,1079 +1,1087 b''
1 ============
1 ============
2 7.x Series
2 7.x Series
3 ============
3 ============
4
4
5 =======
6 .. _version 7.16.3:
7
8 IPython 7.16.3 (CVE-2022-21699)
9 ===============================
10
11 Fixed CVE-2022-21699, see IPython 8.0.1 release notes for informations.
12
5 .. _version 716:
13 .. _version 716:
6
14
7 IPython 7.16.1, 7.16.2
15 IPython 7.16.1, 7.16.2
8 ======================
16 ======================
9
17
10 IPython 7.16.1 was release immediately after 7.16.0 to fix a conda packaging issue.
18 IPython 7.16.1 was release immediately after 7.16.0 to fix a conda packaging issue.
11 The source is identical to 7.16.0 but the file permissions in the tar are different.
19 The source is identical to 7.16.0 but the file permissions in the tar are different.
12
20
13 IPython 7.16.2 pins jedi dependency to "<=0.17.2" which should prevent some
21 IPython 7.16.2 pins jedi dependency to "<=0.17.2" which should prevent some
14 issues for users still on python 3.6. This may not be sufficient as pip may
22 issues for users still on python 3.6. This may not be sufficient as pip may
15 still allow to downgrade IPython.
23 still allow to downgrade IPython.
16
24
17 Compatibility with Jedi > 0.17.2 was not added as this would have meant bumping
25 Compatibility with Jedi > 0.17.2 was not added as this would have meant bumping
18 the minimal version to >0.16.
26 the minimal version to >0.16.
19
27
20 IPython 7.16
28 IPython 7.16
21 ============
29 ============
22
30
23
31
24 The default traceback mode will now skip frames that are marked with
32 The default traceback mode will now skip frames that are marked with
25 ``__tracebackhide__ = True`` and show how many traceback frames have been
33 ``__tracebackhide__ = True`` and show how many traceback frames have been
26 skipped. This can be toggled by using :magic:`xmode` with the ``--show`` or
34 skipped. This can be toggled by using :magic:`xmode` with the ``--show`` or
27 ``--hide`` attribute. It will have no effect on non verbose traceback modes.
35 ``--hide`` attribute. It will have no effect on non verbose traceback modes.
28
36
29 The ipython debugger also now understands ``__tracebackhide__`` as well and will
37 The ipython debugger also now understands ``__tracebackhide__`` as well and will
30 skip hidden frames when displaying. Movement up and down the stack will skip the
38 skip hidden frames when displaying. Movement up and down the stack will skip the
31 hidden frames and will show how many frames were hidden. Internal IPython frames
39 hidden frames and will show how many frames were hidden. Internal IPython frames
32 are also now hidden by default. The behavior can be changed with the
40 are also now hidden by default. The behavior can be changed with the
33 ``skip_hidden`` while in the debugger, command and accepts "yes", "no", "true"
41 ``skip_hidden`` while in the debugger, command and accepts "yes", "no", "true"
34 and "false" case insensitive parameters.
42 and "false" case insensitive parameters.
35
43
36
44
37 Misc Noticeable changes:
45 Misc Noticeable changes:
38 ------------------------
46 ------------------------
39
47
40 - Exceptions are now (re)raised when running notebooks via the :magic:`%run`, helping to catch issues in workflows and
48 - Exceptions are now (re)raised when running notebooks via the :magic:`%run`, helping to catch issues in workflows and
41 pipelines. :ghpull:`12301`
49 pipelines. :ghpull:`12301`
42 - Fix inputhook for qt 5.15.0 :ghpull:`12355`
50 - Fix inputhook for qt 5.15.0 :ghpull:`12355`
43 - Fix wx inputhook :ghpull:`12375`
51 - Fix wx inputhook :ghpull:`12375`
44 - Add handling for malformed pathext env var (Windows) :ghpull:`12367`
52 - Add handling for malformed pathext env var (Windows) :ghpull:`12367`
45 - use $SHELL in system_piped :ghpull:`12360` for uniform behavior with
53 - use $SHELL in system_piped :ghpull:`12360` for uniform behavior with
46 ipykernel.
54 ipykernel.
47
55
48 Reproducible Build
56 Reproducible Build
49 ------------------
57 ------------------
50
58
51 IPython 7.15 reproducible build did not work, so we try again this month
59 IPython 7.15 reproducible build did not work, so we try again this month
52 :ghpull:`12358`.
60 :ghpull:`12358`.
53
61
54
62
55 API Changes
63 API Changes
56 -----------
64 -----------
57
65
58 Change of API and exposed objects automatically detected using `frappuccino
66 Change of API and exposed objects automatically detected using `frappuccino
59 <https://pypi.org/project/frappuccino/>`_ (still in beta):
67 <https://pypi.org/project/frappuccino/>`_ (still in beta):
60
68
61
69
62 The following items are new and mostly related to understanding ``__tracebackbhide__``::
70 The following items are new and mostly related to understanding ``__tracebackbhide__``::
63
71
64 + IPython.core.debugger.Pdb.do_down(self, arg)
72 + IPython.core.debugger.Pdb.do_down(self, arg)
65 + IPython.core.debugger.Pdb.do_skip_hidden(self, arg)
73 + IPython.core.debugger.Pdb.do_skip_hidden(self, arg)
66 + IPython.core.debugger.Pdb.do_up(self, arg)
74 + IPython.core.debugger.Pdb.do_up(self, arg)
67 + IPython.core.debugger.Pdb.hidden_frames(self, stack)
75 + IPython.core.debugger.Pdb.hidden_frames(self, stack)
68 + IPython.core.debugger.Pdb.stop_here(self, frame)
76 + IPython.core.debugger.Pdb.stop_here(self, frame)
69
77
70
78
71 The following items have been removed::
79 The following items have been removed::
72
80
73 - IPython.core.debugger.Pdb.new_do_down
81 - IPython.core.debugger.Pdb.new_do_down
74 - IPython.core.debugger.Pdb.new_do_up
82 - IPython.core.debugger.Pdb.new_do_up
75
83
76 Those were implementation details.
84 Those were implementation details.
77
85
78
86
79 .. _version 715:
87 .. _version 715:
80
88
81 IPython 7.15
89 IPython 7.15
82 ============
90 ============
83
91
84 IPython 7.15 brings a number of bug fixes and user facing improvements.
92 IPython 7.15 brings a number of bug fixes and user facing improvements.
85
93
86 Misc Noticeable changes:
94 Misc Noticeable changes:
87 ------------------------
95 ------------------------
88
96
89 - Long completion name have better elision in terminal :ghpull:`12284`
97 - Long completion name have better elision in terminal :ghpull:`12284`
90 - I've started to test on Python 3.9 :ghpull:`12307` and fix some errors.
98 - I've started to test on Python 3.9 :ghpull:`12307` and fix some errors.
91 - Hi DPI scaling of figures when using qt eventloop :ghpull:`12314`
99 - Hi DPI scaling of figures when using qt eventloop :ghpull:`12314`
92 - Document the ability to have systemwide configuration for IPython.
100 - Document the ability to have systemwide configuration for IPython.
93 :ghpull:`12328`
101 :ghpull:`12328`
94 - Fix issues with input autoformatting :ghpull:`12336`
102 - Fix issues with input autoformatting :ghpull:`12336`
95 - ``IPython.core.debugger.Pdb`` is now interruptible (:ghpull:`12168`, in 7.14
103 - ``IPython.core.debugger.Pdb`` is now interruptible (:ghpull:`12168`, in 7.14
96 but forgotten in release notes)
104 but forgotten in release notes)
97 - Video HTML attributes (:ghpull:`12212`, in 7.14 but forgotten in release
105 - Video HTML attributes (:ghpull:`12212`, in 7.14 but forgotten in release
98 notes)
106 notes)
99
107
100 Reproducible Build
108 Reproducible Build
101 ------------------
109 ------------------
102
110
103 Starting with IPython 7.15, I am attempting to provide reproducible builds,
111 Starting with IPython 7.15, I am attempting to provide reproducible builds,
104 that is to say you should be able from the source tree to generate an sdist
112 that is to say you should be able from the source tree to generate an sdist
105 and wheel that are identical byte for byte with the publish version on PyPI.
113 and wheel that are identical byte for byte with the publish version on PyPI.
106
114
107 I've only tested on a couple of machines so far and the process is relatively
115 I've only tested on a couple of machines so far and the process is relatively
108 straightforward, so this mean that IPython not only have a deterministic build
116 straightforward, so this mean that IPython not only have a deterministic build
109 process, but also I have either removed, or put under control all effects of
117 process, but also I have either removed, or put under control all effects of
110 the build environments on the final artifact. I encourage you to attempt the
118 the build environments on the final artifact. I encourage you to attempt the
111 build process on your machine as documented in :ref:`core_developer_guide`
119 build process on your machine as documented in :ref:`core_developer_guide`
112 and let me know if you do not obtain an identical artifact.
120 and let me know if you do not obtain an identical artifact.
113
121
114 While reproducible builds is critical to check that the supply chain of (open
122 While reproducible builds is critical to check that the supply chain of (open
115 source) software has not been compromised, it can also help to speedup many
123 source) software has not been compromised, it can also help to speedup many
116 of the build processes in large environment (conda, apt...) by allowing
124 of the build processes in large environment (conda, apt...) by allowing
117 better caching of intermediate build steps.
125 better caching of intermediate build steps.
118
126
119 Learn more on `<https://reproducible-builds.org/>`_. `Reflections on trusting
127 Learn more on `<https://reproducible-builds.org/>`_. `Reflections on trusting
120 trust <https://dl.acm.org/doi/10.1145/358198.358210>`_ is also one of the
128 trust <https://dl.acm.org/doi/10.1145/358198.358210>`_ is also one of the
121 cornerstone and recommended reads on this subject.
129 cornerstone and recommended reads on this subject.
122
130
123 .. note::
131 .. note::
124
132
125 The build commit from which the sdist is generated is also `signed
133 The build commit from which the sdist is generated is also `signed
126 <https://en.wikipedia.org/wiki/Digital_signature>`_, so you should be able to
134 <https://en.wikipedia.org/wiki/Digital_signature>`_, so you should be able to
127 check it has not been compromised, and the git repository is a `merkle-tree
135 check it has not been compromised, and the git repository is a `merkle-tree
128 <https://en.wikipedia.org/wiki/Merkle_tree>`_, you can check the consistency
136 <https://en.wikipedia.org/wiki/Merkle_tree>`_, you can check the consistency
129 with `git-fsck <https://git-scm.com/docs/git-fsck>`_ which you likely `want
137 with `git-fsck <https://git-scm.com/docs/git-fsck>`_ which you likely `want
130 to enable by default
138 to enable by default
131 <https://gist.github.com/mbbx6spp/14b86437e794bffb4120>`_.
139 <https://gist.github.com/mbbx6spp/14b86437e794bffb4120>`_.
132
140
133 NEP29: Last version to support Python 3.6
141 NEP29: Last version to support Python 3.6
134 -----------------------------------------
142 -----------------------------------------
135
143
136 IPython 7.15 will be the Last IPython version to officially support Python
144 IPython 7.15 will be the Last IPython version to officially support Python
137 3.6, as stated by `NumPy Enhancement Proposal 29
145 3.6, as stated by `NumPy Enhancement Proposal 29
138 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_. Starting with
146 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_. Starting with
139 next minor version of IPython I may stop testing on Python 3.6 and may stop
147 next minor version of IPython I may stop testing on Python 3.6 and may stop
140 publishing release artifacts that install on Python 3.6
148 publishing release artifacts that install on Python 3.6
141
149
142 Highlighted features
150 Highlighted features
143 --------------------
151 --------------------
144
152
145 Highlighted features are not new, but seem to not be widely known, this
153 Highlighted features are not new, but seem to not be widely known, this
146 section will help you discover in more narrative form what you can do with
154 section will help you discover in more narrative form what you can do with
147 IPython.
155 IPython.
148
156
149 Increase Tab Completion Menu Height
157 Increase Tab Completion Menu Height
150 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
158 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
151
159
152 In terminal IPython it is possible to increase the hight of the tab-completion
160 In terminal IPython it is possible to increase the hight of the tab-completion
153 menu. To do so set the value of
161 menu. To do so set the value of
154 :configtrait:`TerminalInteractiveShell.space_for_menu`, this will reserve more
162 :configtrait:`TerminalInteractiveShell.space_for_menu`, this will reserve more
155 space at the bottom of the screen for various kind of menus in IPython including
163 space at the bottom of the screen for various kind of menus in IPython including
156 tab completion and searching in history.
164 tab completion and searching in history.
157
165
158 Autoformat Code in the terminal
166 Autoformat Code in the terminal
159 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160
168
161 If you have a preferred code formatter, you can configure IPython to
169 If you have a preferred code formatter, you can configure IPython to
162 reformat your code. Set the value of
170 reformat your code. Set the value of
163 :configtrait:`TerminalInteractiveShell.autoformatter` to for example ``'black'``
171 :configtrait:`TerminalInteractiveShell.autoformatter` to for example ``'black'``
164 and IPython will auto format your code when possible.
172 and IPython will auto format your code when possible.
165
173
166
174
167 .. _version 714:
175 .. _version 714:
168
176
169 IPython 7.14
177 IPython 7.14
170 ============
178 ============
171
179
172 IPython 7.14 is a minor release that fix a couple of bugs and prepare
180 IPython 7.14 is a minor release that fix a couple of bugs and prepare
173 compatibility with new or future versions of some libraries.
181 compatibility with new or future versions of some libraries.
174
182
175 Important changes:
183 Important changes:
176 ------------------
184 ------------------
177
185
178 - Fix compatibility with Sphinx 3+ :ghpull:`12235`
186 - Fix compatibility with Sphinx 3+ :ghpull:`12235`
179 - Remove deprecated matplotlib parameter usage, compatibility with matplotlib
187 - Remove deprecated matplotlib parameter usage, compatibility with matplotlib
180 3.3+ :`122250`
188 3.3+ :`122250`
181
189
182 Misc Changes
190 Misc Changes
183 ------------
191 ------------
184
192
185 - set ``.py`` extension when editing current buffer in vi/emacs. :ghpull:`12167`
193 - set ``.py`` extension when editing current buffer in vi/emacs. :ghpull:`12167`
186 - support for unicode identifiers in ``?``/``??`` :ghpull:`12208`
194 - support for unicode identifiers in ``?``/``??`` :ghpull:`12208`
187 - add extra options to the ``Video`` Rich objects :ghpull:`12212`
195 - add extra options to the ``Video`` Rich objects :ghpull:`12212`
188 - add pretty-printing to ``SimpleNamespace`` :ghpull:`12230`
196 - add pretty-printing to ``SimpleNamespace`` :ghpull:`12230`
189
197
190 IPython.core.debugger.Pdb is now interruptible
198 IPython.core.debugger.Pdb is now interruptible
191 ----------------------------------------------
199 ----------------------------------------------
192
200
193 A ``KeyboardInterrupt`` will now interrupt IPython's extended debugger, in order to make Jupyter able to interrupt it. (:ghpull:`12168`)
201 A ``KeyboardInterrupt`` will now interrupt IPython's extended debugger, in order to make Jupyter able to interrupt it. (:ghpull:`12168`)
194
202
195 Video HTML attributes
203 Video HTML attributes
196 ---------------------
204 ---------------------
197
205
198 Add an option to `IPython.display.Video` to change the attributes of the HTML display of the video (:ghpull:`12212`)
206 Add an option to `IPython.display.Video` to change the attributes of the HTML display of the video (:ghpull:`12212`)
199
207
200
208
201 Pending deprecated imports
209 Pending deprecated imports
202 --------------------------
210 --------------------------
203
211
204 Many object present in ``IPython.core.display`` are there for internal use only,
212 Many object present in ``IPython.core.display`` are there for internal use only,
205 and should already been imported from ``IPython.display`` by users and external
213 and should already been imported from ``IPython.display`` by users and external
206 libraries. Trying to import those from ``IPython.core.display`` is still possible
214 libraries. Trying to import those from ``IPython.core.display`` is still possible
207 but will trigger a
215 but will trigger a
208 deprecation warning in later versions of IPython and will become errors in the
216 deprecation warning in later versions of IPython and will become errors in the
209 future.
217 future.
210
218
211 This will simplify compatibility with other Python kernels (like Xeus-Python),
219 This will simplify compatibility with other Python kernels (like Xeus-Python),
212 and simplify code base.
220 and simplify code base.
213
221
214
222
215
223
216
224
217 .. _version 713:
225 .. _version 713:
218
226
219 IPython 7.13
227 IPython 7.13
220 ============
228 ============
221
229
222 IPython 7.13 is the final release of the 7.x branch since master is diverging
230 IPython 7.13 is the final release of the 7.x branch since master is diverging
223 toward an 8.0. Exiting new features have already been merged in 8.0 and will
231 toward an 8.0. Exiting new features have already been merged in 8.0 and will
224 not be available on the 7.x branch. All the changes below have been backported
232 not be available on the 7.x branch. All the changes below have been backported
225 from the master branch.
233 from the master branch.
226
234
227
235
228 - Fix inability to run PDB when inside an event loop :ghpull:`12141`
236 - Fix inability to run PDB when inside an event loop :ghpull:`12141`
229 - Fix ability to interrupt some processes on windows :ghpull:`12137`
237 - Fix ability to interrupt some processes on windows :ghpull:`12137`
230 - Fix debugger shortcuts :ghpull:`12132`
238 - Fix debugger shortcuts :ghpull:`12132`
231 - improve tab completion when inside a string by removing irrelevant elements :ghpull:`12128`
239 - improve tab completion when inside a string by removing irrelevant elements :ghpull:`12128`
232 - Fix display of filename tab completion when the path is long :ghpull:`12122`
240 - Fix display of filename tab completion when the path is long :ghpull:`12122`
233 - Many removal of Python 2 specific code path :ghpull:`12110`
241 - Many removal of Python 2 specific code path :ghpull:`12110`
234 - displaying wav files do not require NumPy anymore, and is 5x to 30x faster :ghpull:`12113`
242 - displaying wav files do not require NumPy anymore, and is 5x to 30x faster :ghpull:`12113`
235
243
236 See the list of all closed issues and pull request on `github
244 See the list of all closed issues and pull request on `github
237 <https://github.com/ipython/ipython/pulls?q=is%3Aclosed+milestone%3A7.13>`_.
245 <https://github.com/ipython/ipython/pulls?q=is%3Aclosed+milestone%3A7.13>`_.
238
246
239 .. _version 712:
247 .. _version 712:
240
248
241 IPython 7.12
249 IPython 7.12
242 ============
250 ============
243
251
244 IPython 7.12 is a minor update that mostly brings code cleanup, removal of
252 IPython 7.12 is a minor update that mostly brings code cleanup, removal of
245 longtime deprecated function and a couple update to documentation cleanup as well.
253 longtime deprecated function and a couple update to documentation cleanup as well.
246
254
247 Notable changes are the following:
255 Notable changes are the following:
248
256
249 - Exit non-zero when ipython is given a file path to run that doesn't exist :ghpull:`12074`
257 - Exit non-zero when ipython is given a file path to run that doesn't exist :ghpull:`12074`
250 - Test PR on ARM64 with Travis-CI :ghpull:`12073`
258 - Test PR on ARM64 with Travis-CI :ghpull:`12073`
251 - Update CI to work with latest Pytest :ghpull:`12086`
259 - Update CI to work with latest Pytest :ghpull:`12086`
252 - Add infrastructure to run ipykernel eventloop via trio :ghpull:`12097`
260 - Add infrastructure to run ipykernel eventloop via trio :ghpull:`12097`
253 - Support git blame ignore revs :ghpull:`12091`
261 - Support git blame ignore revs :ghpull:`12091`
254 - Start multi-line ``__repr__`` s on their own line :ghpull:`12099`
262 - Start multi-line ``__repr__`` s on their own line :ghpull:`12099`
255
263
256 .. _version 7111:
264 .. _version 7111:
257
265
258 IPython 7.11.1
266 IPython 7.11.1
259 ==============
267 ==============
260
268
261 A couple of deprecated functions (no-op) have been reintroduces in py3compat as
269 A couple of deprecated functions (no-op) have been reintroduces in py3compat as
262 Cython was still relying on them, and will be removed in a couple of versions.
270 Cython was still relying on them, and will be removed in a couple of versions.
263
271
264 .. _version 711:
272 .. _version 711:
265
273
266 IPython 7.11
274 IPython 7.11
267 ============
275 ============
268
276
269 IPython 7.11 received a couple of compatibility fixes and code cleanup.
277 IPython 7.11 received a couple of compatibility fixes and code cleanup.
270
278
271 A number of function in the ``py3compat`` have been removed; a number of types
279 A number of function in the ``py3compat`` have been removed; a number of types
272 in the IPython code base are now non-ambiguous and now always ``unicode``
280 in the IPython code base are now non-ambiguous and now always ``unicode``
273 instead of ``Union[Unicode,bytes]``; many of the relevant code path have thus
281 instead of ``Union[Unicode,bytes]``; many of the relevant code path have thus
274 been simplified/cleaned and types annotation added.
282 been simplified/cleaned and types annotation added.
275
283
276 IPython support several verbosity level from exceptions. ``xmode plain`` now
284 IPython support several verbosity level from exceptions. ``xmode plain`` now
277 support chained exceptions. :ghpull:`11999`
285 support chained exceptions. :ghpull:`11999`
278
286
279 We are starting to remove ``shell=True`` in some usages of subprocess. While not directly
287 We are starting to remove ``shell=True`` in some usages of subprocess. While not directly
280 a security issue (as IPython is made to run arbitrary code anyway) it is not good
288 a security issue (as IPython is made to run arbitrary code anyway) it is not good
281 practice and we'd like to show the example. :ghissue:`12023`. This discussion
289 practice and we'd like to show the example. :ghissue:`12023`. This discussion
282 was started by ``@mschwager`` thanks to a new auditing tool they are working on
290 was started by ``@mschwager`` thanks to a new auditing tool they are working on
283 with duo-labs (`dlint <https://github.com/duo-labs/dlint>`_).
291 with duo-labs (`dlint <https://github.com/duo-labs/dlint>`_).
284
292
285 Work around some bugs in Python 3.9 tokenizer :ghpull:`12057`
293 Work around some bugs in Python 3.9 tokenizer :ghpull:`12057`
286
294
287 IPython will now print its version after a crash. :ghpull:`11986`
295 IPython will now print its version after a crash. :ghpull:`11986`
288
296
289 This is likely the last release from the 7.x series that will see new feature.
297 This is likely the last release from the 7.x series that will see new feature.
290 The master branch will soon accept large code changes and thrilling new
298 The master branch will soon accept large code changes and thrilling new
291 features; the 7.x branch will only start to accept critical bug fixes, and
299 features; the 7.x branch will only start to accept critical bug fixes, and
292 update dependencies.
300 update dependencies.
293
301
294 .. _version 7102:
302 .. _version 7102:
295
303
296 IPython 7.10.2
304 IPython 7.10.2
297 ==============
305 ==============
298
306
299 IPython 7.10.2 fix a couple of extra incompatibility between IPython, ipdb,
307 IPython 7.10.2 fix a couple of extra incompatibility between IPython, ipdb,
300 asyncio and Prompt Toolkit 3.
308 asyncio and Prompt Toolkit 3.
301
309
302 .. _version 7101:
310 .. _version 7101:
303
311
304 IPython 7.10.1
312 IPython 7.10.1
305 ==============
313 ==============
306
314
307 IPython 7.10.1 fix a couple of incompatibilities with Prompt toolkit 3 (please
315 IPython 7.10.1 fix a couple of incompatibilities with Prompt toolkit 3 (please
308 update Prompt toolkit to 3.0.2 at least), and fixes some interaction with
316 update Prompt toolkit to 3.0.2 at least), and fixes some interaction with
309 headless IPython.
317 headless IPython.
310
318
311 .. _version 7100:
319 .. _version 7100:
312
320
313 IPython 7.10.0
321 IPython 7.10.0
314 ==============
322 ==============
315
323
316 IPython 7.10 is the first double digit minor release in the last decade, and
324 IPython 7.10 is the first double digit minor release in the last decade, and
317 first since the release of IPython 1.0, previous double digit minor release was
325 first since the release of IPython 1.0, previous double digit minor release was
318 in August 2009.
326 in August 2009.
319
327
320 We've been trying to give you regular release on the last Friday of every month
328 We've been trying to give you regular release on the last Friday of every month
321 for a guaranty of rapid access to bug fixes and new features.
329 for a guaranty of rapid access to bug fixes and new features.
322
330
323 Unlike the previous first few releases that have seen only a couple of code
331 Unlike the previous first few releases that have seen only a couple of code
324 changes, 7.10 bring a number of changes, new features and bugfixes.
332 changes, 7.10 bring a number of changes, new features and bugfixes.
325
333
326 Stop Support for Python 3.5 – Adopt NEP 29
334 Stop Support for Python 3.5 – Adopt NEP 29
327 ------------------------------------------
335 ------------------------------------------
328
336
329 IPython has decided to follow the informational `NEP 29
337 IPython has decided to follow the informational `NEP 29
330 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_ which layout a clear
338 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_ which layout a clear
331 policy as to which version of (C)Python and NumPy are supported.
339 policy as to which version of (C)Python and NumPy are supported.
332
340
333 We thus dropped support for Python 3.5, and cleaned up a number of code path
341 We thus dropped support for Python 3.5, and cleaned up a number of code path
334 that were Python-version dependant. If you are on 3.5 or earlier pip should
342 that were Python-version dependant. If you are on 3.5 or earlier pip should
335 automatically give you the latest compatible version of IPython so you do not
343 automatically give you the latest compatible version of IPython so you do not
336 need to pin to a given version.
344 need to pin to a given version.
337
345
338 Support for Prompt Toolkit 3.0
346 Support for Prompt Toolkit 3.0
339 ------------------------------
347 ------------------------------
340
348
341 Prompt Toolkit 3.0 was release a week before IPython 7.10 and introduces a few
349 Prompt Toolkit 3.0 was release a week before IPython 7.10 and introduces a few
342 breaking changes. We believe IPython 7.10 should be compatible with both Prompt
350 breaking changes. We believe IPython 7.10 should be compatible with both Prompt
343 Toolkit 2.x and 3.x, though it has not been extensively tested with 3.x so
351 Toolkit 2.x and 3.x, though it has not been extensively tested with 3.x so
344 please report any issues.
352 please report any issues.
345
353
346
354
347 Prompt Rendering Performance improvements
355 Prompt Rendering Performance improvements
348 -----------------------------------------
356 -----------------------------------------
349
357
350 Pull Request :ghpull:`11933` introduced an optimisation in the prompt rendering
358 Pull Request :ghpull:`11933` introduced an optimisation in the prompt rendering
351 logic that should decrease the resource usage of IPython when using the
359 logic that should decrease the resource usage of IPython when using the
352 _default_ configuration but could potentially introduce a regression of
360 _default_ configuration but could potentially introduce a regression of
353 functionalities if you are using a custom prompt.
361 functionalities if you are using a custom prompt.
354
362
355 We know assume if you haven't changed the default keybindings that the prompt
363 We know assume if you haven't changed the default keybindings that the prompt
356 **will not change** during the duration of your input – which is for example
364 **will not change** during the duration of your input – which is for example
357 not true when using vi insert mode that switches between `[ins]` and `[nor]`
365 not true when using vi insert mode that switches between `[ins]` and `[nor]`
358 for the current mode.
366 for the current mode.
359
367
360 If you are experiencing any issue let us know.
368 If you are experiencing any issue let us know.
361
369
362 Code autoformatting
370 Code autoformatting
363 -------------------
371 -------------------
364
372
365 The IPython terminal can now auto format your code just before entering a new
373 The IPython terminal can now auto format your code just before entering a new
366 line or executing a command. To do so use the
374 line or executing a command. To do so use the
367 ``--TerminalInteractiveShell.autoformatter`` option and set it to ``'black'``;
375 ``--TerminalInteractiveShell.autoformatter`` option and set it to ``'black'``;
368 if black is installed IPython will use black to format your code when possible.
376 if black is installed IPython will use black to format your code when possible.
369
377
370 IPython cannot always properly format your code; in particular it will
378 IPython cannot always properly format your code; in particular it will
371 auto formatting with *black* will only work if:
379 auto formatting with *black* will only work if:
372
380
373 - Your code does not contains magics or special python syntax.
381 - Your code does not contains magics or special python syntax.
374
382
375 - There is no code after your cursor.
383 - There is no code after your cursor.
376
384
377 The Black API is also still in motion; so this may not work with all versions of
385 The Black API is also still in motion; so this may not work with all versions of
378 black.
386 black.
379
387
380 It should be possible to register custom formatter, though the API is till in
388 It should be possible to register custom formatter, though the API is till in
381 flux.
389 flux.
382
390
383 Arbitrary Mimetypes Handing in Terminal (Aka inline images in terminal)
391 Arbitrary Mimetypes Handing in Terminal (Aka inline images in terminal)
384 -----------------------------------------------------------------------
392 -----------------------------------------------------------------------
385
393
386 When using IPython terminal it is now possible to register function to handle
394 When using IPython terminal it is now possible to register function to handle
387 arbitrary mimetypes. While rendering non-text based representation was possible in
395 arbitrary mimetypes. While rendering non-text based representation was possible in
388 many jupyter frontend; it was not possible in terminal IPython, as usually
396 many jupyter frontend; it was not possible in terminal IPython, as usually
389 terminal are limited to displaying text. As many terminal these days provide
397 terminal are limited to displaying text. As many terminal these days provide
390 escape sequences to display non-text; bringing this loved feature to IPython CLI
398 escape sequences to display non-text; bringing this loved feature to IPython CLI
391 made a lot of sens. This functionality will not only allow inline images; but
399 made a lot of sens. This functionality will not only allow inline images; but
392 allow opening of external program; for example ``mplayer`` to "display" sound
400 allow opening of external program; for example ``mplayer`` to "display" sound
393 files.
401 files.
394
402
395 So far only the hooks necessary for this are in place, but no default mime
403 So far only the hooks necessary for this are in place, but no default mime
396 renderers added; so inline images will only be available via extensions. We will
404 renderers added; so inline images will only be available via extensions. We will
397 progressively enable these features by default in the next few releases, and
405 progressively enable these features by default in the next few releases, and
398 contribution is welcomed.
406 contribution is welcomed.
399
407
400 We welcome any feedback on the API. See :ref:`shell_mimerenderer` for more
408 We welcome any feedback on the API. See :ref:`shell_mimerenderer` for more
401 informations.
409 informations.
402
410
403 This is originally based on work form in :ghpull:`10610` from @stephanh42
411 This is originally based on work form in :ghpull:`10610` from @stephanh42
404 started over two years ago, and still a lot need to be done.
412 started over two years ago, and still a lot need to be done.
405
413
406 MISC
414 MISC
407 ----
415 ----
408
416
409 - Completions can define their own ordering :ghpull:`11855`
417 - Completions can define their own ordering :ghpull:`11855`
410 - Enable Plotting in the same cell than the one that import matplotlib
418 - Enable Plotting in the same cell than the one that import matplotlib
411 :ghpull:`11916`
419 :ghpull:`11916`
412 - Allow to store and restore multiple variables at once :ghpull:`11930`
420 - Allow to store and restore multiple variables at once :ghpull:`11930`
413
421
414 You can see `all pull-requests <https://github.com/ipython/ipython/pulls?q=is%3Apr+milestone%3A7.10+is%3Aclosed>`_ for this release.
422 You can see `all pull-requests <https://github.com/ipython/ipython/pulls?q=is%3Apr+milestone%3A7.10+is%3Aclosed>`_ for this release.
415
423
416 API Changes
424 API Changes
417 -----------
425 -----------
418
426
419 Change of API and exposed objects automatically detected using `frappuccino <https://pypi.org/project/frappuccino/>`_ (still in beta):
427 Change of API and exposed objects automatically detected using `frappuccino <https://pypi.org/project/frappuccino/>`_ (still in beta):
420
428
421 The following items are new in IPython 7.10::
429 The following items are new in IPython 7.10::
422
430
423 + IPython.terminal.shortcuts.reformat_text_before_cursor(buffer, document, shell)
431 + IPython.terminal.shortcuts.reformat_text_before_cursor(buffer, document, shell)
424 + IPython.terminal.interactiveshell.PTK3
432 + IPython.terminal.interactiveshell.PTK3
425 + IPython.terminal.interactiveshell.black_reformat_handler(text_before_cursor)
433 + IPython.terminal.interactiveshell.black_reformat_handler(text_before_cursor)
426 + IPython.terminal.prompts.RichPromptDisplayHook.write_format_data(self, format_dict, md_dict='None')
434 + IPython.terminal.prompts.RichPromptDisplayHook.write_format_data(self, format_dict, md_dict='None')
427
435
428 The following items have been removed in 7.10::
436 The following items have been removed in 7.10::
429
437
430 - IPython.lib.pretty.DICT_IS_ORDERED
438 - IPython.lib.pretty.DICT_IS_ORDERED
431
439
432 The following signatures differ between versions::
440 The following signatures differ between versions::
433
441
434 - IPython.extensions.storemagic.restore_aliases(ip)
442 - IPython.extensions.storemagic.restore_aliases(ip)
435 + IPython.extensions.storemagic.restore_aliases(ip, alias='None')
443 + IPython.extensions.storemagic.restore_aliases(ip, alias='None')
436
444
437 Special Thanks
445 Special Thanks
438 --------------
446 --------------
439
447
440 - @stephanh42 who started the work on inline images in terminal 2 years ago
448 - @stephanh42 who started the work on inline images in terminal 2 years ago
441 - @augustogoulart who spent a lot of time triaging issues and responding to
449 - @augustogoulart who spent a lot of time triaging issues and responding to
442 users.
450 users.
443 - @con-f-use who is my (@Carreau) first sponsor on GitHub, as a reminder if you
451 - @con-f-use who is my (@Carreau) first sponsor on GitHub, as a reminder if you
444 like IPython, Jupyter and many other library of the SciPy stack you can
452 like IPython, Jupyter and many other library of the SciPy stack you can
445 donate to numfocus.org non profit
453 donate to numfocus.org non profit
446
454
447 .. _version 790:
455 .. _version 790:
448
456
449 IPython 7.9.0
457 IPython 7.9.0
450 =============
458 =============
451
459
452 IPython 7.9 is a small release with a couple of improvement and bug fixes.
460 IPython 7.9 is a small release with a couple of improvement and bug fixes.
453
461
454 - Xterm terminal title should be restored on exit :ghpull:`11910`
462 - Xterm terminal title should be restored on exit :ghpull:`11910`
455 - special variables ``_``,``__``, ``___`` are not set anymore when cache size
463 - special variables ``_``,``__``, ``___`` are not set anymore when cache size
456 is 0 or less. :ghpull:`11877`
464 is 0 or less. :ghpull:`11877`
457 - Autoreload should have regained some speed by using a new heuristic logic to
465 - Autoreload should have regained some speed by using a new heuristic logic to
458 find all objects needing reload. This should avoid large objects traversal
466 find all objects needing reload. This should avoid large objects traversal
459 like pandas dataframes. :ghpull:`11876`
467 like pandas dataframes. :ghpull:`11876`
460 - Get ready for Python 4. :ghpull:`11874`
468 - Get ready for Python 4. :ghpull:`11874`
461 - `%env` Magic now has heuristic to hide potentially sensitive values :ghpull:`11896`
469 - `%env` Magic now has heuristic to hide potentially sensitive values :ghpull:`11896`
462
470
463 This is a small release despite a number of Pull Request Pending that need to
471 This is a small release despite a number of Pull Request Pending that need to
464 be reviewed/worked on. Many of the core developers have been busy outside of
472 be reviewed/worked on. Many of the core developers have been busy outside of
465 IPython/Jupyter and we thanks all contributor for their patience; we'll work on
473 IPython/Jupyter and we thanks all contributor for their patience; we'll work on
466 these as soon as we have time.
474 these as soon as we have time.
467
475
468
476
469 .. _version780:
477 .. _version780:
470
478
471 IPython 7.8.0
479 IPython 7.8.0
472 =============
480 =============
473
481
474 IPython 7.8.0 contain a few bugfix and 2 new APIs:
482 IPython 7.8.0 contain a few bugfix and 2 new APIs:
475
483
476 - Enable changing the font color for LaTeX rendering :ghpull:`11840`
484 - Enable changing the font color for LaTeX rendering :ghpull:`11840`
477 - and Re-Expose some PDB API (see below)
485 - and Re-Expose some PDB API (see below)
478
486
479 Expose Pdb API
487 Expose Pdb API
480 --------------
488 --------------
481
489
482 Expose the built-in ``pdb.Pdb`` API. ``Pdb`` constructor arguments are generically
490 Expose the built-in ``pdb.Pdb`` API. ``Pdb`` constructor arguments are generically
483 exposed, regardless of python version.
491 exposed, regardless of python version.
484 Newly exposed arguments:
492 Newly exposed arguments:
485
493
486 - ``skip`` - Python 3.1+
494 - ``skip`` - Python 3.1+
487 - ``nosiginnt`` - Python 3.2+
495 - ``nosiginnt`` - Python 3.2+
488 - ``readrc`` - Python 3.6+
496 - ``readrc`` - Python 3.6+
489
497
490 Try it out::
498 Try it out::
491
499
492 from IPython.terminal.debugger import TerminalPdb
500 from IPython.terminal.debugger import TerminalPdb
493 pdb = TerminalPdb(skip=["skipthismodule"])
501 pdb = TerminalPdb(skip=["skipthismodule"])
494
502
495
503
496 See :ghpull:`11840`
504 See :ghpull:`11840`
497
505
498 .. _version770:
506 .. _version770:
499
507
500 IPython 7.7.0
508 IPython 7.7.0
501 =============
509 =============
502
510
503 IPython 7.7.0 contain multiple bug fixes and documentation updates; Here are a
511 IPython 7.7.0 contain multiple bug fixes and documentation updates; Here are a
504 few of the outstanding issue fixed:
512 few of the outstanding issue fixed:
505
513
506 - Fix a bug introduced in 7.6 where the ``%matplotlib`` magic would fail on
514 - Fix a bug introduced in 7.6 where the ``%matplotlib`` magic would fail on
507 previously acceptable arguments :ghpull:`11814`.
515 previously acceptable arguments :ghpull:`11814`.
508 - Fix the manage location on freebsd :ghpull:`11808`.
516 - Fix the manage location on freebsd :ghpull:`11808`.
509 - Fix error message about aliases after ``%reset`` call in ipykernel
517 - Fix error message about aliases after ``%reset`` call in ipykernel
510 :ghpull:`11806`
518 :ghpull:`11806`
511 - Fix Duplication completions in emacs :ghpull:`11803`
519 - Fix Duplication completions in emacs :ghpull:`11803`
512
520
513 We are planning to adopt `NEP29 <https://github.com/numpy/numpy/pull/14086>`_
521 We are planning to adopt `NEP29 <https://github.com/numpy/numpy/pull/14086>`_
514 (still currently in draft) which may make this minor version of IPython the
522 (still currently in draft) which may make this minor version of IPython the
515 last one to support Python 3.5 and will make the code base more aggressive
523 last one to support Python 3.5 and will make the code base more aggressive
516 toward removing compatibility with older versions of Python.
524 toward removing compatibility with older versions of Python.
517
525
518 GitHub now support to give only "Triage" permissions to users; if you'd like to
526 GitHub now support to give only "Triage" permissions to users; if you'd like to
519 help close stale issues and labels issues please reach to us with your GitHub
527 help close stale issues and labels issues please reach to us with your GitHub
520 Username and we'll add you to the triage team. It is a great way to start
528 Username and we'll add you to the triage team. It is a great way to start
521 contributing and a path toward getting commit rights.
529 contributing and a path toward getting commit rights.
522
530
523 .. _version761:
531 .. _version761:
524
532
525 IPython 7.6.1
533 IPython 7.6.1
526 =============
534 =============
527
535
528 IPython 7.6.1 contain a critical bugfix in the ``%timeit`` magic, which would
536 IPython 7.6.1 contain a critical bugfix in the ``%timeit`` magic, which would
529 crash on some inputs as a side effect of :ghpull:`11716`. See :ghpull:`11812`
537 crash on some inputs as a side effect of :ghpull:`11716`. See :ghpull:`11812`
530
538
531
539
532 .. _whatsnew760:
540 .. _whatsnew760:
533
541
534 IPython 7.6.0
542 IPython 7.6.0
535 =============
543 =============
536
544
537 IPython 7.6.0 contains a couple of bug fixes and number of small features
545 IPython 7.6.0 contains a couple of bug fixes and number of small features
538 additions as well as some compatibility with the current development version of
546 additions as well as some compatibility with the current development version of
539 Python 3.8.
547 Python 3.8.
540
548
541 - Add a ``-l`` option to :magic:`psearch` to list the available search
549 - Add a ``-l`` option to :magic:`psearch` to list the available search
542 types. :ghpull:`11672`
550 types. :ghpull:`11672`
543 - Support ``PathLike`` for ``DisplayObject`` and ``Image``. :ghpull:`11764`
551 - Support ``PathLike`` for ``DisplayObject`` and ``Image``. :ghpull:`11764`
544 - Configurability of timeout in the test suite for slow platforms.
552 - Configurability of timeout in the test suite for slow platforms.
545 :ghpull:`11756`
553 :ghpull:`11756`
546 - Accept any casing for matplotlib backend. :ghpull:`121748`
554 - Accept any casing for matplotlib backend. :ghpull:`121748`
547 - Properly skip test that requires numpy to be installed :ghpull:`11723`
555 - Properly skip test that requires numpy to be installed :ghpull:`11723`
548 - More support for Python 3.8 and positional only arguments (pep570)
556 - More support for Python 3.8 and positional only arguments (pep570)
549 :ghpull:`11720`
557 :ghpull:`11720`
550 - Unicode names for the completion are loaded lazily on first use which
558 - Unicode names for the completion are loaded lazily on first use which
551 should decrease startup time. :ghpull:`11693`
559 should decrease startup time. :ghpull:`11693`
552 - Autoreload now update the types of reloaded objects; this for example allow
560 - Autoreload now update the types of reloaded objects; this for example allow
553 pickling of reloaded objects. :ghpull:`11644`
561 pickling of reloaded objects. :ghpull:`11644`
554 - Fix a bug where ``%%time`` magic would suppress cell output. :ghpull:`11716`
562 - Fix a bug where ``%%time`` magic would suppress cell output. :ghpull:`11716`
555
563
556
564
557 Prepare migration to pytest (instead of nose) for testing
565 Prepare migration to pytest (instead of nose) for testing
558 ---------------------------------------------------------
566 ---------------------------------------------------------
559
567
560 Most of the work between 7.5 and 7.6 was to prepare the migration from our
568 Most of the work between 7.5 and 7.6 was to prepare the migration from our
561 testing framework to pytest. Most of the test suite should now work by simply
569 testing framework to pytest. Most of the test suite should now work by simply
562 issuing ``pytest`` from the root of the repository.
570 issuing ``pytest`` from the root of the repository.
563
571
564 The migration to pytest is just at its beginning. Many of our test still rely
572 The migration to pytest is just at its beginning. Many of our test still rely
565 on IPython-specific plugins for nose using pytest (doctest using IPython syntax
573 on IPython-specific plugins for nose using pytest (doctest using IPython syntax
566 is one example of this where test appear as "passing", while no code has been
574 is one example of this where test appear as "passing", while no code has been
567 ran). Many test also need to be updated like ``yield-test`` to be properly
575 ran). Many test also need to be updated like ``yield-test`` to be properly
568 parametrized tests.
576 parametrized tests.
569
577
570 Migration to pytest allowed me to discover a number of issues in our test
578 Migration to pytest allowed me to discover a number of issues in our test
571 suite; which was hiding a number of subtle issues – or not actually running
579 suite; which was hiding a number of subtle issues – or not actually running
572 some of the tests in our test suite – I have thus corrected many of those; like
580 some of the tests in our test suite – I have thus corrected many of those; like
573 improperly closed resources; or used of deprecated features. I also made use of
581 improperly closed resources; or used of deprecated features. I also made use of
574 the ``pytest --durations=...`` to find some of our slowest test and speed them
582 the ``pytest --durations=...`` to find some of our slowest test and speed them
575 up (our test suite can now be up to 10% faster). Pytest as also a variety of
583 up (our test suite can now be up to 10% faster). Pytest as also a variety of
576 plugins and flags which will make the code quality of IPython and the testing
584 plugins and flags which will make the code quality of IPython and the testing
577 experience better.
585 experience better.
578
586
579 Misc
587 Misc
580 ----
588 ----
581
589
582 We skipped the release of 7.6 at the end of May, but will attempt to get back
590 We skipped the release of 7.6 at the end of May, but will attempt to get back
583 on schedule. We are starting to think about making introducing backward
591 on schedule. We are starting to think about making introducing backward
584 incompatible change and start the 8.0 series.
592 incompatible change and start the 8.0 series.
585
593
586 Special Thanks to Gabriel (@gpotter2 on GitHub), who among other took care many
594 Special Thanks to Gabriel (@gpotter2 on GitHub), who among other took care many
587 of the remaining task for 7.4 and 7.5, like updating the website.
595 of the remaining task for 7.4 and 7.5, like updating the website.
588
596
589 .. _whatsnew750:
597 .. _whatsnew750:
590
598
591 IPython 7.5.0
599 IPython 7.5.0
592 =============
600 =============
593
601
594 IPython 7.5.0 consist mostly of bug-fixes, and documentation updates, with one
602 IPython 7.5.0 consist mostly of bug-fixes, and documentation updates, with one
595 minor new feature. The `Audio` display element can now be assigned an element
603 minor new feature. The `Audio` display element can now be assigned an element
596 id when displayed in browser. See :ghpull:`11670`
604 id when displayed in browser. See :ghpull:`11670`
597
605
598 The major outstanding bug fix correct a change of behavior that was introduce
606 The major outstanding bug fix correct a change of behavior that was introduce
599 in 7.4.0 where some cell magics would not be able to access or modify global
607 in 7.4.0 where some cell magics would not be able to access or modify global
600 scope when using the ``@needs_local_scope`` decorator. This was typically
608 scope when using the ``@needs_local_scope`` decorator. This was typically
601 encountered with the ``%%time`` and ``%%timeit`` magics. See :ghissue:`11659`
609 encountered with the ``%%time`` and ``%%timeit`` magics. See :ghissue:`11659`
602 and :ghpull:`11698`.
610 and :ghpull:`11698`.
603
611
604 .. _whatsnew740:
612 .. _whatsnew740:
605
613
606 IPython 7.4.0
614 IPython 7.4.0
607 =============
615 =============
608
616
609 Unicode name completions
617 Unicode name completions
610 ------------------------
618 ------------------------
611
619
612 Previously, we provided completion for a unicode name with its relative symbol.
620 Previously, we provided completion for a unicode name with its relative symbol.
613 With this, now IPython provides complete suggestions to unicode name symbols.
621 With this, now IPython provides complete suggestions to unicode name symbols.
614
622
615 As on the PR, if user types ``\LAT<tab>``, IPython provides a list of
623 As on the PR, if user types ``\LAT<tab>``, IPython provides a list of
616 possible completions. In this case, it would be something like::
624 possible completions. In this case, it would be something like::
617
625
618 'LATIN CAPITAL LETTER A',
626 'LATIN CAPITAL LETTER A',
619 'LATIN CAPITAL LETTER B',
627 'LATIN CAPITAL LETTER B',
620 'LATIN CAPITAL LETTER C',
628 'LATIN CAPITAL LETTER C',
621 'LATIN CAPITAL LETTER D',
629 'LATIN CAPITAL LETTER D',
622 ....
630 ....
623
631
624 This help to type unicode character that do not have short latex aliases, and
632 This help to type unicode character that do not have short latex aliases, and
625 have long unicode names. for example ``Ν°``, ``\GREEK CAPITAL LETTER HETA``.
633 have long unicode names. for example ``Ν°``, ``\GREEK CAPITAL LETTER HETA``.
626
634
627 This feature was contributed by Luciana Marques :ghpull:`11583`.
635 This feature was contributed by Luciana Marques :ghpull:`11583`.
628
636
629 Make audio normalization optional
637 Make audio normalization optional
630 ---------------------------------
638 ---------------------------------
631
639
632 Added 'normalize' argument to `IPython.display.Audio`. This argument applies
640 Added 'normalize' argument to `IPython.display.Audio`. This argument applies
633 when audio data is given as an array of samples. The default of `normalize=True`
641 when audio data is given as an array of samples. The default of `normalize=True`
634 preserves prior behavior of normalizing the audio to the maximum possible range.
642 preserves prior behavior of normalizing the audio to the maximum possible range.
635 Setting to `False` disables normalization.
643 Setting to `False` disables normalization.
636
644
637
645
638 Miscellaneous
646 Miscellaneous
639 -------------
647 -------------
640
648
641 - Fix improper acceptation of ``return`` outside of functions. :ghpull:`11641`.
649 - Fix improper acceptation of ``return`` outside of functions. :ghpull:`11641`.
642 - Fixed PyQt 5.11 backwards incompatibility causing sip import failure.
650 - Fixed PyQt 5.11 backwards incompatibility causing sip import failure.
643 :ghpull:`11613`.
651 :ghpull:`11613`.
644 - Fix Bug where ``type?`` would crash IPython. :ghpull:`1608`.
652 - Fix Bug where ``type?`` would crash IPython. :ghpull:`1608`.
645 - Allow to apply ``@needs_local_scope`` to cell magics for convenience.
653 - Allow to apply ``@needs_local_scope`` to cell magics for convenience.
646 :ghpull:`11542`.
654 :ghpull:`11542`.
647
655
648 .. _whatsnew730:
656 .. _whatsnew730:
649
657
650 IPython 7.3.0
658 IPython 7.3.0
651 =============
659 =============
652
660
653 .. _whatsnew720:
661 .. _whatsnew720:
654
662
655 IPython 7.3.0 bring several bug fixes and small improvements that you will
663 IPython 7.3.0 bring several bug fixes and small improvements that you will
656 described bellow.
664 described bellow.
657
665
658 The biggest change to this release is the implementation of the ``%conda`` and
666 The biggest change to this release is the implementation of the ``%conda`` and
659 ``%pip`` magics, that will attempt to install packages in the **current
667 ``%pip`` magics, that will attempt to install packages in the **current
660 environment**. You may still need to restart your interpreter or kernel for the
668 environment**. You may still need to restart your interpreter or kernel for the
661 change to be taken into account, but it should simplify installation of packages
669 change to be taken into account, but it should simplify installation of packages
662 into remote environment. Installing using pip/conda from the command line is
670 into remote environment. Installing using pip/conda from the command line is
663 still the prefer method.
671 still the prefer method.
664
672
665 The ``%pip`` magic was already present, but was only printing a warning; now it
673 The ``%pip`` magic was already present, but was only printing a warning; now it
666 will actually forward commands to pip.
674 will actually forward commands to pip.
667
675
668 Misc bug fixes and improvements:
676 Misc bug fixes and improvements:
669
677
670 - Compatibility with Python 3.8.
678 - Compatibility with Python 3.8.
671 - Do not expand shell variable in execution magics, and added the
679 - Do not expand shell variable in execution magics, and added the
672 ``no_var_expand`` decorator for magic requiring a similar functionality
680 ``no_var_expand`` decorator for magic requiring a similar functionality
673 :ghpull:`11516`
681 :ghpull:`11516`
674 - Add ``%pip`` and ``%conda`` magic :ghpull:`11524`
682 - Add ``%pip`` and ``%conda`` magic :ghpull:`11524`
675 - Re-initialize posix aliases after a ``%reset`` :ghpull:`11528`
683 - Re-initialize posix aliases after a ``%reset`` :ghpull:`11528`
676 - Allow the IPython command line to run ``*.ipynb`` files :ghpull:`11529`
684 - Allow the IPython command line to run ``*.ipynb`` files :ghpull:`11529`
677
685
678 IPython 7.2.0
686 IPython 7.2.0
679 =============
687 =============
680
688
681 IPython 7.2.0 brings minor bugfixes, improvements, and new configuration options:
689 IPython 7.2.0 brings minor bugfixes, improvements, and new configuration options:
682
690
683 - Fix a bug preventing PySide2 GUI integration from working :ghpull:`11464`
691 - Fix a bug preventing PySide2 GUI integration from working :ghpull:`11464`
684 - Run CI on Mac OS ! :ghpull:`11471`
692 - Run CI on Mac OS ! :ghpull:`11471`
685 - Fix IPython "Demo" mode. :ghpull:`11498`
693 - Fix IPython "Demo" mode. :ghpull:`11498`
686 - Fix ``%run`` magic with path in name :ghpull:`11499`
694 - Fix ``%run`` magic with path in name :ghpull:`11499`
687 - Fix: add CWD to sys.path *after* stdlib :ghpull:`11502`
695 - Fix: add CWD to sys.path *after* stdlib :ghpull:`11502`
688 - Better rendering of signatures, especially long ones. :ghpull:`11505`
696 - Better rendering of signatures, especially long ones. :ghpull:`11505`
689 - Re-enable jedi by default if it's installed :ghpull:`11506`
697 - Re-enable jedi by default if it's installed :ghpull:`11506`
690 - Add New ``minimal`` exception reporting mode (useful for educational purpose). See :ghpull:`11509`
698 - Add New ``minimal`` exception reporting mode (useful for educational purpose). See :ghpull:`11509`
691
699
692
700
693 Added ability to show subclasses when using pinfo and other utilities
701 Added ability to show subclasses when using pinfo and other utilities
694 ---------------------------------------------------------------------
702 ---------------------------------------------------------------------
695
703
696 When using ``?``/``??`` on a class, IPython will now list the first 10 subclasses.
704 When using ``?``/``??`` on a class, IPython will now list the first 10 subclasses.
697
705
698 Special Thanks to Chris Mentzel of the Moore Foundation for this feature. Chris
706 Special Thanks to Chris Mentzel of the Moore Foundation for this feature. Chris
699 is one of the people who played a critical role in IPython/Jupyter getting
707 is one of the people who played a critical role in IPython/Jupyter getting
700 funding.
708 funding.
701
709
702 We are grateful for all the help Chris has given us over the years,
710 We are grateful for all the help Chris has given us over the years,
703 and we're now proud to have code contributed by Chris in IPython.
711 and we're now proud to have code contributed by Chris in IPython.
704
712
705 OSMagics.cd_force_quiet configuration option
713 OSMagics.cd_force_quiet configuration option
706 --------------------------------------------
714 --------------------------------------------
707
715
708 You can set this option to force the %cd magic to behave as if ``-q`` was passed:
716 You can set this option to force the %cd magic to behave as if ``-q`` was passed:
709 ::
717 ::
710
718
711 In [1]: cd /
719 In [1]: cd /
712 /
720 /
713
721
714 In [2]: %config OSMagics.cd_force_quiet = True
722 In [2]: %config OSMagics.cd_force_quiet = True
715
723
716 In [3]: cd /tmp
724 In [3]: cd /tmp
717
725
718 In [4]:
726 In [4]:
719
727
720 See :ghpull:`11491`
728 See :ghpull:`11491`
721
729
722 In vi editing mode, whether the prompt includes the current vi mode can now be configured
730 In vi editing mode, whether the prompt includes the current vi mode can now be configured
723 -----------------------------------------------------------------------------------------
731 -----------------------------------------------------------------------------------------
724
732
725 Set the ``TerminalInteractiveShell.prompt_includes_vi_mode`` to a boolean value
733 Set the ``TerminalInteractiveShell.prompt_includes_vi_mode`` to a boolean value
726 (default: True) to control this feature. See :ghpull:`11492`
734 (default: True) to control this feature. See :ghpull:`11492`
727
735
728 .. _whatsnew710:
736 .. _whatsnew710:
729
737
730 IPython 7.1.0
738 IPython 7.1.0
731 =============
739 =============
732
740
733 IPython 7.1.0 is the first minor release after 7.0.0 and mostly brings fixes to
741 IPython 7.1.0 is the first minor release after 7.0.0 and mostly brings fixes to
734 new features, internal refactoring, and fixes for regressions that happened during the 6.x->7.x
742 new features, internal refactoring, and fixes for regressions that happened during the 6.x->7.x
735 transition. It also brings **Compatibility with Python 3.7.1**, as we're
743 transition. It also brings **Compatibility with Python 3.7.1**, as we're
736 unwillingly relying on a bug in CPython.
744 unwillingly relying on a bug in CPython.
737
745
738 New Core Dev:
746 New Core Dev:
739
747
740 - We welcome Jonathan Slenders to the commiters. Jonathan has done a fantastic
748 - We welcome Jonathan Slenders to the commiters. Jonathan has done a fantastic
741 work on prompt_toolkit, and we'd like to recognise his impact by giving him
749 work on prompt_toolkit, and we'd like to recognise his impact by giving him
742 commit rights. :ghissue:`11397`
750 commit rights. :ghissue:`11397`
743
751
744 Notable Changes
752 Notable Changes
745
753
746 - Major update of "latex to unicode" tab completion map (see below)
754 - Major update of "latex to unicode" tab completion map (see below)
747
755
748 Notable New Features:
756 Notable New Features:
749
757
750 - Restore functionality and documentation of the **sphinx directive**, which
758 - Restore functionality and documentation of the **sphinx directive**, which
751 is now stricter (fail on error by daefault), has new configuration options,
759 is now stricter (fail on error by daefault), has new configuration options,
752 has a brand new documentation page :ref:`ipython_directive` (which needs
760 has a brand new documentation page :ref:`ipython_directive` (which needs
753 some cleanup). It is also now *tested* so we hope to have less regressions.
761 some cleanup). It is also now *tested* so we hope to have less regressions.
754 :ghpull:`11402`
762 :ghpull:`11402`
755
763
756 - ``IPython.display.Video`` now supports ``width`` and ``height`` arguments,
764 - ``IPython.display.Video`` now supports ``width`` and ``height`` arguments,
757 allowing a custom width and height to be set instead of using the video's
765 allowing a custom width and height to be set instead of using the video's
758 width and height. :ghpull:`11353`
766 width and height. :ghpull:`11353`
759
767
760 - Warn when using ``HTML('<iframe>')`` instead of ``IFrame`` :ghpull:`11350`
768 - Warn when using ``HTML('<iframe>')`` instead of ``IFrame`` :ghpull:`11350`
761
769
762 - Allow Dynamic switching of editing mode between vi/emacs and show
770 - Allow Dynamic switching of editing mode between vi/emacs and show
763 normal/input mode in prompt when using vi. :ghpull:`11390`. Use ``%config
771 normal/input mode in prompt when using vi. :ghpull:`11390`. Use ``%config
764 TerminalInteractiveShell.editing_mode = 'vi'`` or ``%config
772 TerminalInteractiveShell.editing_mode = 'vi'`` or ``%config
765 TerminalInteractiveShell.editing_mode = 'emacs'`` to dynamically switch
773 TerminalInteractiveShell.editing_mode = 'emacs'`` to dynamically switch
766 between modes.
774 between modes.
767
775
768
776
769 Notable Fixes:
777 Notable Fixes:
770
778
771 - Fix entering of **multi-line blocks in terminal** IPython, and various
779 - Fix entering of **multi-line blocks in terminal** IPython, and various
772 crashes in the new input transformation machinery :ghpull:`11354`,
780 crashes in the new input transformation machinery :ghpull:`11354`,
773 :ghpull:`11356`, :ghpull:`11358`. These also fix a **Compatibility bug
781 :ghpull:`11356`, :ghpull:`11358`. These also fix a **Compatibility bug
774 with Python 3.7.1**.
782 with Python 3.7.1**.
775
783
776 - Fix moving through generator stack in ipdb :ghpull:`11266`
784 - Fix moving through generator stack in ipdb :ghpull:`11266`
777
785
778 - %Magic command arguments now support quoting. :ghpull:`11330`
786 - %Magic command arguments now support quoting. :ghpull:`11330`
779
787
780 - Re-add ``rprint`` and ``rprinte`` aliases. :ghpull:`11331`
788 - Re-add ``rprint`` and ``rprinte`` aliases. :ghpull:`11331`
781
789
782 - Remove implicit dependency on ``ipython_genutils`` :ghpull:`11317`
790 - Remove implicit dependency on ``ipython_genutils`` :ghpull:`11317`
783
791
784 - Make ``nonlocal`` raise ``SyntaxError`` instead of silently failing in async
792 - Make ``nonlocal`` raise ``SyntaxError`` instead of silently failing in async
785 mode. :ghpull:`11382`
793 mode. :ghpull:`11382`
786
794
787 - Fix mishandling of magics and ``= !`` assignment just after a dedent in
795 - Fix mishandling of magics and ``= !`` assignment just after a dedent in
788 nested code blocks :ghpull:`11418`
796 nested code blocks :ghpull:`11418`
789
797
790 - Fix instructions for custom shortcuts :ghpull:`11426`
798 - Fix instructions for custom shortcuts :ghpull:`11426`
791
799
792
800
793 Notable Internals improvements:
801 Notable Internals improvements:
794
802
795 - Use of ``os.scandir`` (Python 3 only) to speed up some file system operations.
803 - Use of ``os.scandir`` (Python 3 only) to speed up some file system operations.
796 :ghpull:`11365`
804 :ghpull:`11365`
797
805
798 - use ``perf_counter`` instead of ``clock`` for more precise
806 - use ``perf_counter`` instead of ``clock`` for more precise
799 timing results with ``%time`` :ghpull:`11376`
807 timing results with ``%time`` :ghpull:`11376`
800
808
801 Many thanks to all the contributors and in particular to ``bartskowron`` and
809 Many thanks to all the contributors and in particular to ``bartskowron`` and
802 ``tonyfast`` who handled some pretty complicated bugs in the input machinery. We
810 ``tonyfast`` who handled some pretty complicated bugs in the input machinery. We
803 had a number of first time contributors and maybe hacktoberfest participants that
811 had a number of first time contributors and maybe hacktoberfest participants that
804 made significant contributions and helped us free some time to focus on more
812 made significant contributions and helped us free some time to focus on more
805 complicated bugs.
813 complicated bugs.
806
814
807 You
815 You
808 can see all the closed issues and Merged PR, new features and fixes `here
816 can see all the closed issues and Merged PR, new features and fixes `here
809 <https://github.com/ipython/ipython/issues?utf8=%E2%9C%93&q=+is%3Aclosed+milestone%3A7.1+>`_.
817 <https://github.com/ipython/ipython/issues?utf8=%E2%9C%93&q=+is%3Aclosed+milestone%3A7.1+>`_.
810
818
811 Unicode Completion update
819 Unicode Completion update
812 -------------------------
820 -------------------------
813
821
814 In IPython 7.1 the Unicode completion map has been updated and synchronized with
822 In IPython 7.1 the Unicode completion map has been updated and synchronized with
815 the Julia language.
823 the Julia language.
816
824
817 Added and removed character characters:
825 Added and removed character characters:
818
826
819 ``\jmath`` (``Θ·``), ``\\underleftrightarrow`` (U+034D, combining) have been
827 ``\jmath`` (``Θ·``), ``\\underleftrightarrow`` (U+034D, combining) have been
820 added, while ``\\textasciicaron`` have been removed
828 added, while ``\\textasciicaron`` have been removed
821
829
822 Some sequences have seen their prefix removed:
830 Some sequences have seen their prefix removed:
823
831
824 - 6 characters ``\text...<tab>`` should now be inputed with ``\...<tab>`` directly,
832 - 6 characters ``\text...<tab>`` should now be inputed with ``\...<tab>`` directly,
825 - 45 characters ``\Elz...<tab>`` should now be inputed with ``\...<tab>`` directly,
833 - 45 characters ``\Elz...<tab>`` should now be inputed with ``\...<tab>`` directly,
826 - 65 characters ``\B...<tab>`` should now be inputed with ``\...<tab>`` directly,
834 - 65 characters ``\B...<tab>`` should now be inputed with ``\...<tab>`` directly,
827 - 450 characters ``\m...<tab>`` should now be inputed with ``\...<tab>`` directly,
835 - 450 characters ``\m...<tab>`` should now be inputed with ``\...<tab>`` directly,
828
836
829 Some sequences have seen their prefix shortened:
837 Some sequences have seen their prefix shortened:
830
838
831 - 5 characters ``\mitBbb...<tab>`` should now be inputed with ``\bbi...<tab>`` directly,
839 - 5 characters ``\mitBbb...<tab>`` should now be inputed with ``\bbi...<tab>`` directly,
832 - 52 characters ``\mit...<tab>`` should now be inputed with ``\i...<tab>`` directly,
840 - 52 characters ``\mit...<tab>`` should now be inputed with ``\i...<tab>`` directly,
833 - 216 characters ``\mbfit...<tab>`` should now be inputed with ``\bi...<tab>`` directly,
841 - 216 characters ``\mbfit...<tab>`` should now be inputed with ``\bi...<tab>`` directly,
834 - 222 characters ``\mbf...<tab>`` should now be inputed with ``\b...<tab>`` directly,
842 - 222 characters ``\mbf...<tab>`` should now be inputed with ``\b...<tab>`` directly,
835
843
836 A couple of characters had their sequence simplified:
844 A couple of characters had their sequence simplified:
837
845
838 - ``Γ°``, type ``\dh<tab>``, instead of ``\eth<tab>``
846 - ``Γ°``, type ``\dh<tab>``, instead of ``\eth<tab>``
839 - ``Δ§``, type ``\hbar<tab>``, instead of ``\Elzxh<tab>``
847 - ``Δ§``, type ``\hbar<tab>``, instead of ``\Elzxh<tab>``
840 - ``ΙΈ``, type ``\ltphi<tab>``, instead of ``\textphi<tab>``
848 - ``ΙΈ``, type ``\ltphi<tab>``, instead of ``\textphi<tab>``
841 - ``Ο΄``, type ``\varTheta<tab>``, instead of ``\textTheta<tab>``
849 - ``Ο΄``, type ``\varTheta<tab>``, instead of ``\textTheta<tab>``
842 - ``ℇ``, type ``\eulermascheroni<tab>``, instead of ``\Eulerconst<tab>``
850 - ``ℇ``, type ``\eulermascheroni<tab>``, instead of ``\Eulerconst<tab>``
843 - ``β„Ž``, type ``\planck<tab>``, instead of ``\Planckconst<tab>``
851 - ``β„Ž``, type ``\planck<tab>``, instead of ``\Planckconst<tab>``
844
852
845 - U+0336 (COMBINING LONG STROKE OVERLAY), type ``\strike<tab>``, instead of ``\Elzbar<tab>``.
853 - U+0336 (COMBINING LONG STROKE OVERLAY), type ``\strike<tab>``, instead of ``\Elzbar<tab>``.
846
854
847 A couple of sequences have been updated:
855 A couple of sequences have been updated:
848
856
849 - ``\varepsilon`` now gives ``Ι›`` (GREEK SMALL LETTER EPSILON) instead of ``Ξ΅`` (GREEK LUNATE EPSILON SYMBOL),
857 - ``\varepsilon`` now gives ``Ι›`` (GREEK SMALL LETTER EPSILON) instead of ``Ξ΅`` (GREEK LUNATE EPSILON SYMBOL),
850 - ``\underbar`` now gives U+0331 (COMBINING MACRON BELOW) instead of U+0332 (COMBINING LOW LINE).
858 - ``\underbar`` now gives U+0331 (COMBINING MACRON BELOW) instead of U+0332 (COMBINING LOW LINE).
851
859
852
860
853 .. _whatsnew700:
861 .. _whatsnew700:
854
862
855 IPython 7.0.0
863 IPython 7.0.0
856 =============
864 =============
857
865
858 Released Thursday September 27th, 2018
866 Released Thursday September 27th, 2018
859
867
860 IPython 7 includes major feature improvements.
868 IPython 7 includes major feature improvements.
861 This is also the second major version of IPython to support only
869 This is also the second major version of IPython to support only
862 Python 3 – starting at Python 3.4. Python 2 is still community-supported
870 Python 3 – starting at Python 3.4. Python 2 is still community-supported
863 on the bugfix only 5.x branch, but we remind you that Python 2 "end of life"
871 on the bugfix only 5.x branch, but we remind you that Python 2 "end of life"
864 is on Jan 1st 2020.
872 is on Jan 1st 2020.
865
873
866 We were able to backport bug fixes to the 5.x branch thanks to our backport bot which
874 We were able to backport bug fixes to the 5.x branch thanks to our backport bot which
867 backported more than `70 Pull-Requests
875 backported more than `70 Pull-Requests
868 <https://github.com/ipython/ipython/pulls?page=3&q=is%3Apr+sort%3Aupdated-desc+author%3Aapp%2Fmeeseeksdev++5.x&utf8=%E2%9C%93>`_, but there are still many PRs that required manual work. This is an area of the project where you can easily contribute by looking for `PRs that still need manual backport <https://github.com/ipython/ipython/issues?q=label%3A%22Still+Needs+Manual+Backport%22+is%3Aclosed+sort%3Aupdated-desc>`_
876 <https://github.com/ipython/ipython/pulls?page=3&q=is%3Apr+sort%3Aupdated-desc+author%3Aapp%2Fmeeseeksdev++5.x&utf8=%E2%9C%93>`_, but there are still many PRs that required manual work. This is an area of the project where you can easily contribute by looking for `PRs that still need manual backport <https://github.com/ipython/ipython/issues?q=label%3A%22Still+Needs+Manual+Backport%22+is%3Aclosed+sort%3Aupdated-desc>`_
869
877
870 The IPython 6.x branch will likely not see any further release unless critical
878 The IPython 6.x branch will likely not see any further release unless critical
871 bugs are found.
879 bugs are found.
872
880
873 Make sure you have pip > 9.0 before upgrading. You should be able to update by running:
881 Make sure you have pip > 9.0 before upgrading. You should be able to update by running:
874
882
875 .. code::
883 .. code::
876
884
877 pip install ipython --upgrade
885 pip install ipython --upgrade
878
886
879 .. only:: ipydev
887 .. only:: ipydev
880
888
881 If you are trying to install or update an ``alpha``, ``beta``, or ``rc``
889 If you are trying to install or update an ``alpha``, ``beta``, or ``rc``
882 version, use pip ``--pre`` flag.
890 version, use pip ``--pre`` flag.
883
891
884 .. code::
892 .. code::
885
893
886 pip install ipython --upgrade --pre
894 pip install ipython --upgrade --pre
887
895
888
896
889 Or, if you have conda installed:
897 Or, if you have conda installed:
890
898
891 .. code::
899 .. code::
892
900
893 conda install ipython
901 conda install ipython
894
902
895
903
896
904
897 Prompt Toolkit 2.0
905 Prompt Toolkit 2.0
898 ------------------
906 ------------------
899
907
900 IPython 7.0+ now uses ``prompt_toolkit 2.0``. If you still need to use an earlier
908 IPython 7.0+ now uses ``prompt_toolkit 2.0``. If you still need to use an earlier
901 ``prompt_toolkit`` version, you may need to pin IPython to ``<7.0``.
909 ``prompt_toolkit`` version, you may need to pin IPython to ``<7.0``.
902
910
903 Autowait: Asynchronous REPL
911 Autowait: Asynchronous REPL
904 ---------------------------
912 ---------------------------
905
913
906 Staring with IPython 7.0 on Python 3.6+, IPython can automatically ``await``
914 Staring with IPython 7.0 on Python 3.6+, IPython can automatically ``await``
907 top level code. You should not need to access an event loop or runner
915 top level code. You should not need to access an event loop or runner
908 yourself. To learn more, read the :ref:`autoawait` section of our docs, see
916 yourself. To learn more, read the :ref:`autoawait` section of our docs, see
909 :ghpull:`11265`, or try the following code::
917 :ghpull:`11265`, or try the following code::
910
918
911 Python 3.6.0
919 Python 3.6.0
912 Type 'copyright', 'credits' or 'license' for more information
920 Type 'copyright', 'credits' or 'license' for more information
913 IPython 7.0.0 -- An enhanced Interactive Python. Type '?' for help.
921 IPython 7.0.0 -- An enhanced Interactive Python. Type '?' for help.
914
922
915 In [1]: import aiohttp
923 In [1]: import aiohttp
916 ...: result = aiohttp.get('https://api.github.com')
924 ...: result = aiohttp.get('https://api.github.com')
917
925
918 In [2]: response = await result
926 In [2]: response = await result
919 <pause for a few 100s ms>
927 <pause for a few 100s ms>
920
928
921 In [3]: await response.json()
929 In [3]: await response.json()
922 Out[3]:
930 Out[3]:
923 {'authorizations_url': 'https://api.github.com/authorizations',
931 {'authorizations_url': 'https://api.github.com/authorizations',
924 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
932 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
925 ...
933 ...
926 }
934 }
927
935
928 .. note::
936 .. note::
929
937
930 Async integration is experimental code, behavior may change or be removed
938 Async integration is experimental code, behavior may change or be removed
931 between Python and IPython versions without warnings.
939 between Python and IPython versions without warnings.
932
940
933 Integration is by default with `asyncio`, but other libraries can be configured --
941 Integration is by default with `asyncio`, but other libraries can be configured --
934 like ``curio`` or ``trio`` -- to improve concurrency in the REPL::
942 like ``curio`` or ``trio`` -- to improve concurrency in the REPL::
935
943
936 In [1]: %autoawait trio
944 In [1]: %autoawait trio
937
945
938 In [2]: import trio
946 In [2]: import trio
939
947
940 In [3]: async def child(i):
948 In [3]: async def child(i):
941 ...: print(" child %s goes to sleep"%i)
949 ...: print(" child %s goes to sleep"%i)
942 ...: await trio.sleep(2)
950 ...: await trio.sleep(2)
943 ...: print(" child %s wakes up"%i)
951 ...: print(" child %s wakes up"%i)
944
952
945 In [4]: print('parent start')
953 In [4]: print('parent start')
946 ...: async with trio.open_nursery() as n:
954 ...: async with trio.open_nursery() as n:
947 ...: for i in range(3):
955 ...: for i in range(3):
948 ...: n.spawn(child, i)
956 ...: n.spawn(child, i)
949 ...: print('parent end')
957 ...: print('parent end')
950 parent start
958 parent start
951 child 2 goes to sleep
959 child 2 goes to sleep
952 child 0 goes to sleep
960 child 0 goes to sleep
953 child 1 goes to sleep
961 child 1 goes to sleep
954 <about 2 seconds pause>
962 <about 2 seconds pause>
955 child 2 wakes up
963 child 2 wakes up
956 child 1 wakes up
964 child 1 wakes up
957 child 0 wakes up
965 child 0 wakes up
958 parent end
966 parent end
959
967
960 See :ref:`autoawait` for more information.
968 See :ref:`autoawait` for more information.
961
969
962
970
963 Asynchronous code in a Notebook interface or any other frontend using the
971 Asynchronous code in a Notebook interface or any other frontend using the
964 Jupyter Protocol will require further updates to the IPykernel package.
972 Jupyter Protocol will require further updates to the IPykernel package.
965
973
966 Non-Asynchronous code
974 Non-Asynchronous code
967 ~~~~~~~~~~~~~~~~~~~~~
975 ~~~~~~~~~~~~~~~~~~~~~
968
976
969 As the internal API of IPython is now asynchronous, IPython needs to run under
977 As the internal API of IPython is now asynchronous, IPython needs to run under
970 an event loop. In order to allow many workflows, (like using the :magic:`%run`
978 an event loop. In order to allow many workflows, (like using the :magic:`%run`
971 magic, or copy-pasting code that explicitly starts/stop event loop), when
979 magic, or copy-pasting code that explicitly starts/stop event loop), when
972 top-level code is detected as not being asynchronous, IPython code is advanced
980 top-level code is detected as not being asynchronous, IPython code is advanced
973 via a pseudo-synchronous runner, and may not advance pending tasks.
981 via a pseudo-synchronous runner, and may not advance pending tasks.
974
982
975 Change to Nested Embed
983 Change to Nested Embed
976 ~~~~~~~~~~~~~~~~~~~~~~
984 ~~~~~~~~~~~~~~~~~~~~~~
977
985
978 The introduction of the ability to run async code had some effect on the
986 The introduction of the ability to run async code had some effect on the
979 ``IPython.embed()`` API. By default, embed will not allow you to run asynchronous
987 ``IPython.embed()`` API. By default, embed will not allow you to run asynchronous
980 code unless an event loop is specified.
988 code unless an event loop is specified.
981
989
982 Effects on Magics
990 Effects on Magics
983 ~~~~~~~~~~~~~~~~~
991 ~~~~~~~~~~~~~~~~~
984
992
985 Some magics will not work with async until they're updated.
993 Some magics will not work with async until they're updated.
986 Contributions welcome.
994 Contributions welcome.
987
995
988 Expected Future changes
996 Expected Future changes
989 ~~~~~~~~~~~~~~~~~~~~~~~
997 ~~~~~~~~~~~~~~~~~~~~~~~
990
998
991 We expect more internal but public IPython functions to become ``async``, and
999 We expect more internal but public IPython functions to become ``async``, and
992 will likely end up having a persistent event loop while IPython is running.
1000 will likely end up having a persistent event loop while IPython is running.
993
1001
994 Thanks
1002 Thanks
995 ~~~~~~
1003 ~~~~~~
996
1004
997 This release took more than a year in the making.
1005 This release took more than a year in the making.
998 The code was rebased a number of
1006 The code was rebased a number of
999 times; leading to commit authorship that may have been lost in the final
1007 times; leading to commit authorship that may have been lost in the final
1000 Pull-Request. Huge thanks to many people for contribution, discussion, code,
1008 Pull-Request. Huge thanks to many people for contribution, discussion, code,
1001 documentation, use-cases: dalejung, danielballan, ellisonbg, fperez, gnestor,
1009 documentation, use-cases: dalejung, danielballan, ellisonbg, fperez, gnestor,
1002 minrk, njsmith, pganssle, tacaswell, takluyver , vidartf ... And many others.
1010 minrk, njsmith, pganssle, tacaswell, takluyver , vidartf ... And many others.
1003
1011
1004
1012
1005 Autoreload Improvement
1013 Autoreload Improvement
1006 ----------------------
1014 ----------------------
1007
1015
1008 The magic :magic:`%autoreload 2 <autoreload>` now captures new methods added to
1016 The magic :magic:`%autoreload 2 <autoreload>` now captures new methods added to
1009 classes. Earlier, only methods existing as of the initial import were being
1017 classes. Earlier, only methods existing as of the initial import were being
1010 tracked and updated.
1018 tracked and updated.
1011
1019
1012 This new feature helps dual environment development - Jupyter+IDE - where the
1020 This new feature helps dual environment development - Jupyter+IDE - where the
1013 code gradually moves from notebook cells to package files as it gets
1021 code gradually moves from notebook cells to package files as it gets
1014 structured.
1022 structured.
1015
1023
1016 **Example**: An instance of the class ``MyClass`` will be able to access the
1024 **Example**: An instance of the class ``MyClass`` will be able to access the
1017 method ``cube()`` after it is uncommented and the file ``file1.py`` is saved on
1025 method ``cube()`` after it is uncommented and the file ``file1.py`` is saved on
1018 disk.
1026 disk.
1019
1027
1020
1028
1021 .. code::
1029 .. code::
1022
1030
1023 # notebook
1031 # notebook
1024
1032
1025 from mymodule import MyClass
1033 from mymodule import MyClass
1026 first = MyClass(5)
1034 first = MyClass(5)
1027
1035
1028 .. code::
1036 .. code::
1029
1037
1030 # mymodule/file1.py
1038 # mymodule/file1.py
1031
1039
1032 class MyClass:
1040 class MyClass:
1033
1041
1034 def __init__(self, a=10):
1042 def __init__(self, a=10):
1035 self.a = a
1043 self.a = a
1036
1044
1037 def square(self):
1045 def square(self):
1038 print('compute square')
1046 print('compute square')
1039 return self.a*self.a
1047 return self.a*self.a
1040
1048
1041 # def cube(self):
1049 # def cube(self):
1042 # print('compute cube')
1050 # print('compute cube')
1043 # return self.a*self.a*self.a
1051 # return self.a*self.a*self.a
1044
1052
1045
1053
1046
1054
1047
1055
1048 Misc
1056 Misc
1049 ----
1057 ----
1050
1058
1051 The autoindent feature that was deprecated in 5.x was re-enabled and
1059 The autoindent feature that was deprecated in 5.x was re-enabled and
1052 un-deprecated in :ghpull:`11257`
1060 un-deprecated in :ghpull:`11257`
1053
1061
1054 Make :magic:`%run -n -i ... <run>` work correctly. Earlier, if :magic:`%run` was
1062 Make :magic:`%run -n -i ... <run>` work correctly. Earlier, if :magic:`%run` was
1055 passed both arguments, ``-n`` would be silently ignored. See :ghpull:`10308`
1063 passed both arguments, ``-n`` would be silently ignored. See :ghpull:`10308`
1056
1064
1057
1065
1058 The :cellmagic:`%%script` (as well as :cellmagic:`%%bash`,
1066 The :cellmagic:`%%script` (as well as :cellmagic:`%%bash`,
1059 :cellmagic:`%%ruby`... ) cell magics now raise by default if the return code of
1067 :cellmagic:`%%ruby`... ) cell magics now raise by default if the return code of
1060 the given code is non-zero (thus halting execution of further cells in a
1068 the given code is non-zero (thus halting execution of further cells in a
1061 notebook). The behavior can be disable by passing the ``--no-raise-error`` flag.
1069 notebook). The behavior can be disable by passing the ``--no-raise-error`` flag.
1062
1070
1063
1071
1064 Deprecations
1072 Deprecations
1065 ------------
1073 ------------
1066
1074
1067 A couple of unused functions and methods have been deprecated and will be removed
1075 A couple of unused functions and methods have been deprecated and will be removed
1068 in future versions:
1076 in future versions:
1069
1077
1070 - ``IPython.utils.io.raw_print_err``
1078 - ``IPython.utils.io.raw_print_err``
1071 - ``IPython.utils.io.raw_print``
1079 - ``IPython.utils.io.raw_print``
1072
1080
1073
1081
1074 Backwards incompatible changes
1082 Backwards incompatible changes
1075 ------------------------------
1083 ------------------------------
1076
1084
1077 * The API for transforming input before it is parsed as Python code has been
1085 * The API for transforming input before it is parsed as Python code has been
1078 completely redesigned: any custom input transformations will need to be
1086 completely redesigned: any custom input transformations will need to be
1079 rewritten. See :doc:`/config/inputtransforms` for details of the new API.
1087 rewritten. See :doc:`/config/inputtransforms` for details of the new API.
General Comments 0
You need to be logged in to leave comments. Login now