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