##// END OF EJS Templates
Allow to configure lazy loadable magics....
Matthias Bussonnier -
Show More

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

1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,700 +1,746 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9
9
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import os
14 import os
15 import re
15 import re
16 import sys
16 import sys
17 from getopt import getopt, GetoptError
17 from getopt import getopt, GetoptError
18
18
19 from traitlets.config.configurable import Configurable
19 from traitlets.config.configurable import Configurable
20 from . import oinspect
20 from . import oinspect
21 from .error import UsageError
21 from .error import UsageError
22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
23 from ..utils.ipstruct import Struct
23 from ..utils.ipstruct import Struct
24 from ..utils.process import arg_split
24 from ..utils.process import arg_split
25 from ..utils.text import dedent
25 from ..utils.text import dedent
26 from traitlets import Bool, Dict, Instance, observe
26 from traitlets import Bool, Dict, Instance, observe
27 from logging import error
27 from logging import error
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Globals
30 # Globals
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 # A dict we'll use for each class that has magics, used as temporary storage to
33 # A dict we'll use for each class that has magics, used as temporary storage to
34 # pass information between the @line/cell_magic method decorators and the
34 # pass information between the @line/cell_magic method decorators and the
35 # @magics_class class decorator, because the method decorators have no
35 # @magics_class class decorator, because the method decorators have no
36 # access to the class when they run. See for more details:
36 # access to the class when they run. See for more details:
37 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
37 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
38
38
39 magics = dict(line={}, cell={})
39 magics = dict(line={}, cell={})
40
40
41 magic_kinds = ('line', 'cell')
41 magic_kinds = ('line', 'cell')
42 magic_spec = ('line', 'cell', 'line_cell')
42 magic_spec = ('line', 'cell', 'line_cell')
43 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
43 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # Utility classes and functions
46 # Utility classes and functions
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48
48
49 class Bunch: pass
49 class Bunch: pass
50
50
51
51
52 def on_off(tag):
52 def on_off(tag):
53 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
53 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
54 return ['OFF','ON'][tag]
54 return ['OFF','ON'][tag]
55
55
56
56
57 def compress_dhist(dh):
57 def compress_dhist(dh):
58 """Compress a directory history into a new one with at most 20 entries.
58 """Compress a directory history into a new one with at most 20 entries.
59
59
60 Return a new list made from the first and last 10 elements of dhist after
60 Return a new list made from the first and last 10 elements of dhist after
61 removal of duplicates.
61 removal of duplicates.
62 """
62 """
63 head, tail = dh[:-10], dh[-10:]
63 head, tail = dh[:-10], dh[-10:]
64
64
65 newhead = []
65 newhead = []
66 done = set()
66 done = set()
67 for h in head:
67 for h in head:
68 if h in done:
68 if h in done:
69 continue
69 continue
70 newhead.append(h)
70 newhead.append(h)
71 done.add(h)
71 done.add(h)
72
72
73 return newhead + tail
73 return newhead + tail
74
74
75
75
76 def needs_local_scope(func):
76 def needs_local_scope(func):
77 """Decorator to mark magic functions which need to local scope to run."""
77 """Decorator to mark magic functions which need to local scope to run."""
78 func.needs_local_scope = True
78 func.needs_local_scope = True
79 return func
79 return func
80
80
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82 # Class and method decorators for registering magics
82 # Class and method decorators for registering magics
83 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
84
84
85 def magics_class(cls):
85 def magics_class(cls):
86 """Class decorator for all subclasses of the main Magics class.
86 """Class decorator for all subclasses of the main Magics class.
87
87
88 Any class that subclasses Magics *must* also apply this decorator, to
88 Any class that subclasses Magics *must* also apply this decorator, to
89 ensure that all the methods that have been decorated as line/cell magics
89 ensure that all the methods that have been decorated as line/cell magics
90 get correctly registered in the class instance. This is necessary because
90 get correctly registered in the class instance. This is necessary because
91 when method decorators run, the class does not exist yet, so they
91 when method decorators run, the class does not exist yet, so they
92 temporarily store their information into a module global. Application of
92 temporarily store their information into a module global. Application of
93 this class decorator copies that global data to the class instance and
93 this class decorator copies that global data to the class instance and
94 clears the global.
94 clears the global.
95
95
96 Obviously, this mechanism is not thread-safe, which means that the
96 Obviously, this mechanism is not thread-safe, which means that the
97 *creation* of subclasses of Magic should only be done in a single-thread
97 *creation* of subclasses of Magic should only be done in a single-thread
98 context. Instantiation of the classes has no restrictions. Given that
98 context. Instantiation of the classes has no restrictions. Given that
99 these classes are typically created at IPython startup time and before user
99 these classes are typically created at IPython startup time and before user
100 application code becomes active, in practice this should not pose any
100 application code becomes active, in practice this should not pose any
101 problems.
101 problems.
102 """
102 """
103 cls.registered = True
103 cls.registered = True
104 cls.magics = dict(line = magics['line'],
104 cls.magics = dict(line = magics['line'],
105 cell = magics['cell'])
105 cell = magics['cell'])
106 magics['line'] = {}
106 magics['line'] = {}
107 magics['cell'] = {}
107 magics['cell'] = {}
108 return cls
108 return cls
109
109
110
110
111 def record_magic(dct, magic_kind, magic_name, func):
111 def record_magic(dct, magic_kind, magic_name, func):
112 """Utility function to store a function as a magic of a specific kind.
112 """Utility function to store a function as a magic of a specific kind.
113
113
114 Parameters
114 Parameters
115 ----------
115 ----------
116 dct : dict
116 dct : dict
117 A dictionary with 'line' and 'cell' subdicts.
117 A dictionary with 'line' and 'cell' subdicts.
118 magic_kind : str
118 magic_kind : str
119 Kind of magic to be stored.
119 Kind of magic to be stored.
120 magic_name : str
120 magic_name : str
121 Key to store the magic as.
121 Key to store the magic as.
122 func : function
122 func : function
123 Callable object to store.
123 Callable object to store.
124 """
124 """
125 if magic_kind == 'line_cell':
125 if magic_kind == 'line_cell':
126 dct['line'][magic_name] = dct['cell'][magic_name] = func
126 dct['line'][magic_name] = dct['cell'][magic_name] = func
127 else:
127 else:
128 dct[magic_kind][magic_name] = func
128 dct[magic_kind][magic_name] = func
129
129
130
130
131 def validate_type(magic_kind):
131 def validate_type(magic_kind):
132 """Ensure that the given magic_kind is valid.
132 """Ensure that the given magic_kind is valid.
133
133
134 Check that the given magic_kind is one of the accepted spec types (stored
134 Check that the given magic_kind is one of the accepted spec types (stored
135 in the global `magic_spec`), raise ValueError otherwise.
135 in the global `magic_spec`), raise ValueError otherwise.
136 """
136 """
137 if magic_kind not in magic_spec:
137 if magic_kind not in magic_spec:
138 raise ValueError('magic_kind must be one of %s, %s given' %
138 raise ValueError('magic_kind must be one of %s, %s given' %
139 magic_kinds, magic_kind)
139 magic_kinds, magic_kind)
140
140
141
141
142 # The docstrings for the decorator below will be fairly similar for the two
142 # The docstrings for the decorator below will be fairly similar for the two
143 # types (method and function), so we generate them here once and reuse the
143 # types (method and function), so we generate them here once and reuse the
144 # templates below.
144 # templates below.
145 _docstring_template = \
145 _docstring_template = \
146 """Decorate the given {0} as {1} magic.
146 """Decorate the given {0} as {1} magic.
147
147
148 The decorator can be used with or without arguments, as follows.
148 The decorator can be used with or without arguments, as follows.
149
149
150 i) without arguments: it will create a {1} magic named as the {0} being
150 i) without arguments: it will create a {1} magic named as the {0} being
151 decorated::
151 decorated::
152
152
153 @deco
153 @deco
154 def foo(...)
154 def foo(...)
155
155
156 will create a {1} magic named `foo`.
156 will create a {1} magic named `foo`.
157
157
158 ii) with one string argument: which will be used as the actual name of the
158 ii) with one string argument: which will be used as the actual name of the
159 resulting magic::
159 resulting magic::
160
160
161 @deco('bar')
161 @deco('bar')
162 def foo(...)
162 def foo(...)
163
163
164 will create a {1} magic named `bar`.
164 will create a {1} magic named `bar`.
165
165
166 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
166 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
167 """
167 """
168
168
169 # These two are decorator factories. While they are conceptually very similar,
169 # These two are decorator factories. While they are conceptually very similar,
170 # there are enough differences in the details that it's simpler to have them
170 # there are enough differences in the details that it's simpler to have them
171 # written as completely standalone functions rather than trying to share code
171 # written as completely standalone functions rather than trying to share code
172 # and make a single one with convoluted logic.
172 # and make a single one with convoluted logic.
173
173
174 def _method_magic_marker(magic_kind):
174 def _method_magic_marker(magic_kind):
175 """Decorator factory for methods in Magics subclasses.
175 """Decorator factory for methods in Magics subclasses.
176 """
176 """
177
177
178 validate_type(magic_kind)
178 validate_type(magic_kind)
179
179
180 # This is a closure to capture the magic_kind. We could also use a class,
180 # This is a closure to capture the magic_kind. We could also use a class,
181 # but it's overkill for just that one bit of state.
181 # but it's overkill for just that one bit of state.
182 def magic_deco(arg):
182 def magic_deco(arg):
183 if callable(arg):
183 if callable(arg):
184 # "Naked" decorator call (just @foo, no args)
184 # "Naked" decorator call (just @foo, no args)
185 func = arg
185 func = arg
186 name = func.__name__
186 name = func.__name__
187 retval = arg
187 retval = arg
188 record_magic(magics, magic_kind, name, name)
188 record_magic(magics, magic_kind, name, name)
189 elif isinstance(arg, str):
189 elif isinstance(arg, str):
190 # Decorator called with arguments (@foo('bar'))
190 # Decorator called with arguments (@foo('bar'))
191 name = arg
191 name = arg
192 def mark(func, *a, **kw):
192 def mark(func, *a, **kw):
193 record_magic(magics, magic_kind, name, func.__name__)
193 record_magic(magics, magic_kind, name, func.__name__)
194 return func
194 return func
195 retval = mark
195 retval = mark
196 else:
196 else:
197 raise TypeError("Decorator can only be called with "
197 raise TypeError("Decorator can only be called with "
198 "string or function")
198 "string or function")
199 return retval
199 return retval
200
200
201 # Ensure the resulting decorator has a usable docstring
201 # Ensure the resulting decorator has a usable docstring
202 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
202 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
203 return magic_deco
203 return magic_deco
204
204
205
205
206 def _function_magic_marker(magic_kind):
206 def _function_magic_marker(magic_kind):
207 """Decorator factory for standalone functions.
207 """Decorator factory for standalone functions.
208 """
208 """
209 validate_type(magic_kind)
209 validate_type(magic_kind)
210
210
211 # This is a closure to capture the magic_kind. We could also use a class,
211 # This is a closure to capture the magic_kind. We could also use a class,
212 # but it's overkill for just that one bit of state.
212 # but it's overkill for just that one bit of state.
213 def magic_deco(arg):
213 def magic_deco(arg):
214 # Find get_ipython() in the caller's namespace
214 # Find get_ipython() in the caller's namespace
215 caller = sys._getframe(1)
215 caller = sys._getframe(1)
216 for ns in ['f_locals', 'f_globals', 'f_builtins']:
216 for ns in ['f_locals', 'f_globals', 'f_builtins']:
217 get_ipython = getattr(caller, ns).get('get_ipython')
217 get_ipython = getattr(caller, ns).get('get_ipython')
218 if get_ipython is not None:
218 if get_ipython is not None:
219 break
219 break
220 else:
220 else:
221 raise NameError('Decorator can only run in context where '
221 raise NameError('Decorator can only run in context where '
222 '`get_ipython` exists')
222 '`get_ipython` exists')
223
223
224 ip = get_ipython()
224 ip = get_ipython()
225
225
226 if callable(arg):
226 if callable(arg):
227 # "Naked" decorator call (just @foo, no args)
227 # "Naked" decorator call (just @foo, no args)
228 func = arg
228 func = arg
229 name = func.__name__
229 name = func.__name__
230 ip.register_magic_function(func, magic_kind, name)
230 ip.register_magic_function(func, magic_kind, name)
231 retval = arg
231 retval = arg
232 elif isinstance(arg, str):
232 elif isinstance(arg, str):
233 # Decorator called with arguments (@foo('bar'))
233 # Decorator called with arguments (@foo('bar'))
234 name = arg
234 name = arg
235 def mark(func, *a, **kw):
235 def mark(func, *a, **kw):
236 ip.register_magic_function(func, magic_kind, name)
236 ip.register_magic_function(func, magic_kind, name)
237 return func
237 return func
238 retval = mark
238 retval = mark
239 else:
239 else:
240 raise TypeError("Decorator can only be called with "
240 raise TypeError("Decorator can only be called with "
241 "string or function")
241 "string or function")
242 return retval
242 return retval
243
243
244 # Ensure the resulting decorator has a usable docstring
244 # Ensure the resulting decorator has a usable docstring
245 ds = _docstring_template.format('function', magic_kind)
245 ds = _docstring_template.format('function', magic_kind)
246
246
247 ds += dedent("""
247 ds += dedent("""
248 Note: this decorator can only be used in a context where IPython is already
248 Note: this decorator can only be used in a context where IPython is already
249 active, so that the `get_ipython()` call succeeds. You can therefore use
249 active, so that the `get_ipython()` call succeeds. You can therefore use
250 it in your startup files loaded after IPython initializes, but *not* in the
250 it in your startup files loaded after IPython initializes, but *not* in the
251 IPython configuration file itself, which is executed before IPython is
251 IPython configuration file itself, which is executed before IPython is
252 fully up and running. Any file located in the `startup` subdirectory of
252 fully up and running. Any file located in the `startup` subdirectory of
253 your configuration profile will be OK in this sense.
253 your configuration profile will be OK in this sense.
254 """)
254 """)
255
255
256 magic_deco.__doc__ = ds
256 magic_deco.__doc__ = ds
257 return magic_deco
257 return magic_deco
258
258
259
259
260 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
260 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
261
261
262
262
263 def no_var_expand(magic_func):
263 def no_var_expand(magic_func):
264 """Mark a magic function as not needing variable expansion
264 """Mark a magic function as not needing variable expansion
265
265
266 By default, IPython interprets `{a}` or `$a` in the line passed to magics
266 By default, IPython interprets `{a}` or `$a` in the line passed to magics
267 as variables that should be interpolated from the interactive namespace
267 as variables that should be interpolated from the interactive namespace
268 before passing the line to the magic function.
268 before passing the line to the magic function.
269 This is not always desirable, e.g. when the magic executes Python code
269 This is not always desirable, e.g. when the magic executes Python code
270 (%timeit, %time, etc.).
270 (%timeit, %time, etc.).
271 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
271 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
272
272
273 .. versionadded:: 7.3
273 .. versionadded:: 7.3
274 """
274 """
275 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
275 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
276 return magic_func
276 return magic_func
277
277
278
278
279 # Create the actual decorators for public use
279 # Create the actual decorators for public use
280
280
281 # These three are used to decorate methods in class definitions
281 # These three are used to decorate methods in class definitions
282 line_magic = _method_magic_marker('line')
282 line_magic = _method_magic_marker('line')
283 cell_magic = _method_magic_marker('cell')
283 cell_magic = _method_magic_marker('cell')
284 line_cell_magic = _method_magic_marker('line_cell')
284 line_cell_magic = _method_magic_marker('line_cell')
285
285
286 # These three decorate standalone functions and perform the decoration
286 # These three decorate standalone functions and perform the decoration
287 # immediately. They can only run where get_ipython() works
287 # immediately. They can only run where get_ipython() works
288 register_line_magic = _function_magic_marker('line')
288 register_line_magic = _function_magic_marker('line')
289 register_cell_magic = _function_magic_marker('cell')
289 register_cell_magic = _function_magic_marker('cell')
290 register_line_cell_magic = _function_magic_marker('line_cell')
290 register_line_cell_magic = _function_magic_marker('line_cell')
291
291
292 #-----------------------------------------------------------------------------
292 #-----------------------------------------------------------------------------
293 # Core Magic classes
293 # Core Magic classes
294 #-----------------------------------------------------------------------------
294 #-----------------------------------------------------------------------------
295
295
296 class MagicsManager(Configurable):
296 class MagicsManager(Configurable):
297 """Object that handles all magic-related functionality for IPython.
297 """Object that handles all magic-related functionality for IPython.
298 """
298 """
299 # Non-configurable class attributes
299 # Non-configurable class attributes
300
300
301 # A two-level dict, first keyed by magic type, then by magic function, and
301 # A two-level dict, first keyed by magic type, then by magic function, and
302 # holding the actual callable object as value. This is the dict used for
302 # holding the actual callable object as value. This is the dict used for
303 # magic function dispatch
303 # magic function dispatch
304 magics = Dict()
304 magics = Dict()
305 lazy_magics = Dict(
306 help="""
307 Mapping from magic names to modules to load.
308
309 This can be used in IPython/IPykernel configuration to declare lazy magics
310 that will only be imported/registered on first use.
311
312 For example::
313
314 c.MagicsManger.lazy_magics = {
315 "my_magic": "slow.to.import",
316 "my_other_magic": "also.slow",
317 }
318
319 On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or
320 `%%my_other_magic`, the corresponding module will be loaded as an ipython
321 extensions as if you had previously done `%load_ext ipython`.
322
323 Magics names should be without percent(s) as magics can be both cell
324 and line magics.
325
326 Lazy loading happen relatively late in execution process, and
327 complex extensions that manipulate Python/IPython internal state or global state
328 might not support lazy loading.
329 """
330 ).tag(
331 config=True,
332 )
305
333
306 # A registry of the original objects that we've been given holding magics.
334 # A registry of the original objects that we've been given holding magics.
307 registry = Dict()
335 registry = Dict()
308
336
309 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
337 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
310
338
311 auto_magic = Bool(True, help=
339 auto_magic = Bool(True, help=
312 "Automatically call line magics without requiring explicit % prefix"
340 "Automatically call line magics without requiring explicit % prefix"
313 ).tag(config=True)
341 ).tag(config=True)
314 @observe('auto_magic')
342 @observe('auto_magic')
315 def _auto_magic_changed(self, change):
343 def _auto_magic_changed(self, change):
316 self.shell.automagic = change['new']
344 self.shell.automagic = change['new']
317
345
318 _auto_status = [
346 _auto_status = [
319 'Automagic is OFF, % prefix IS needed for line magics.',
347 'Automagic is OFF, % prefix IS needed for line magics.',
320 'Automagic is ON, % prefix IS NOT needed for line magics.']
348 'Automagic is ON, % prefix IS NOT needed for line magics.']
321
349
322 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
350 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
323
351
324 def __init__(self, shell=None, config=None, user_magics=None, **traits):
352 def __init__(self, shell=None, config=None, user_magics=None, **traits):
325
353
326 super(MagicsManager, self).__init__(shell=shell, config=config,
354 super(MagicsManager, self).__init__(shell=shell, config=config,
327 user_magics=user_magics, **traits)
355 user_magics=user_magics, **traits)
328 self.magics = dict(line={}, cell={})
356 self.magics = dict(line={}, cell={})
329 # Let's add the user_magics to the registry for uniformity, so *all*
357 # Let's add the user_magics to the registry for uniformity, so *all*
330 # registered magic containers can be found there.
358 # registered magic containers can be found there.
331 self.registry[user_magics.__class__.__name__] = user_magics
359 self.registry[user_magics.__class__.__name__] = user_magics
332
360
333 def auto_status(self):
361 def auto_status(self):
334 """Return descriptive string with automagic status."""
362 """Return descriptive string with automagic status."""
335 return self._auto_status[self.auto_magic]
363 return self._auto_status[self.auto_magic]
336
364
337 def lsmagic(self):
365 def lsmagic(self):
338 """Return a dict of currently available magic functions.
366 """Return a dict of currently available magic functions.
339
367
340 The return dict has the keys 'line' and 'cell', corresponding to the
368 The return dict has the keys 'line' and 'cell', corresponding to the
341 two types of magics we support. Each value is a list of names.
369 two types of magics we support. Each value is a list of names.
342 """
370 """
343 return self.magics
371 return self.magics
344
372
345 def lsmagic_docs(self, brief=False, missing=''):
373 def lsmagic_docs(self, brief=False, missing=''):
346 """Return dict of documentation of magic functions.
374 """Return dict of documentation of magic functions.
347
375
348 The return dict has the keys 'line' and 'cell', corresponding to the
376 The return dict has the keys 'line' and 'cell', corresponding to the
349 two types of magics we support. Each value is a dict keyed by magic
377 two types of magics we support. Each value is a dict keyed by magic
350 name whose value is the function docstring. If a docstring is
378 name whose value is the function docstring. If a docstring is
351 unavailable, the value of `missing` is used instead.
379 unavailable, the value of `missing` is used instead.
352
380
353 If brief is True, only the first line of each docstring will be returned.
381 If brief is True, only the first line of each docstring will be returned.
354 """
382 """
355 docs = {}
383 docs = {}
356 for m_type in self.magics:
384 for m_type in self.magics:
357 m_docs = {}
385 m_docs = {}
358 for m_name, m_func in self.magics[m_type].items():
386 for m_name, m_func in self.magics[m_type].items():
359 if m_func.__doc__:
387 if m_func.__doc__:
360 if brief:
388 if brief:
361 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
389 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
362 else:
390 else:
363 m_docs[m_name] = m_func.__doc__.rstrip()
391 m_docs[m_name] = m_func.__doc__.rstrip()
364 else:
392 else:
365 m_docs[m_name] = missing
393 m_docs[m_name] = missing
366 docs[m_type] = m_docs
394 docs[m_type] = m_docs
367 return docs
395 return docs
368
396
397 def register_lazy(self, name: str, fully_qualified_name: str):
398 """
399 Lazily register a magic via an extension.
400
401
402 Parameters
403 ----------
404 name : str
405 Name of the magic you wish to register.
406 fully_qualified_name :
407 Fully qualified name of the module/submodule that should be loaded
408 as an extensions when the magic is first called.
409 It is assumed that loading this extensions will register the given
410 magic.
411 """
412
413 self.lazy_magics[name] = fully_qualified_name
414
369 def register(self, *magic_objects):
415 def register(self, *magic_objects):
370 """Register one or more instances of Magics.
416 """Register one or more instances of Magics.
371
417
372 Take one or more classes or instances of classes that subclass the main
418 Take one or more classes or instances of classes that subclass the main
373 `core.Magic` class, and register them with IPython to use the magic
419 `core.Magic` class, and register them with IPython to use the magic
374 functions they provide. The registration process will then ensure that
420 functions they provide. The registration process will then ensure that
375 any methods that have decorated to provide line and/or cell magics will
421 any methods that have decorated to provide line and/or cell magics will
376 be recognized with the `%x`/`%%x` syntax as a line/cell magic
422 be recognized with the `%x`/`%%x` syntax as a line/cell magic
377 respectively.
423 respectively.
378
424
379 If classes are given, they will be instantiated with the default
425 If classes are given, they will be instantiated with the default
380 constructor. If your classes need a custom constructor, you should
426 constructor. If your classes need a custom constructor, you should
381 instanitate them first and pass the instance.
427 instanitate them first and pass the instance.
382
428
383 The provided arguments can be an arbitrary mix of classes and instances.
429 The provided arguments can be an arbitrary mix of classes and instances.
384
430
385 Parameters
431 Parameters
386 ----------
432 ----------
387 *magic_objects : one or more classes or instances
433 *magic_objects : one or more classes or instances
388 """
434 """
389 # Start by validating them to ensure they have all had their magic
435 # Start by validating them to ensure they have all had their magic
390 # methods registered at the instance level
436 # methods registered at the instance level
391 for m in magic_objects:
437 for m in magic_objects:
392 if not m.registered:
438 if not m.registered:
393 raise ValueError("Class of magics %r was constructed without "
439 raise ValueError("Class of magics %r was constructed without "
394 "the @register_magics class decorator")
440 "the @register_magics class decorator")
395 if isinstance(m, type):
441 if isinstance(m, type):
396 # If we're given an uninstantiated class
442 # If we're given an uninstantiated class
397 m = m(shell=self.shell)
443 m = m(shell=self.shell)
398
444
399 # Now that we have an instance, we can register it and update the
445 # Now that we have an instance, we can register it and update the
400 # table of callables
446 # table of callables
401 self.registry[m.__class__.__name__] = m
447 self.registry[m.__class__.__name__] = m
402 for mtype in magic_kinds:
448 for mtype in magic_kinds:
403 self.magics[mtype].update(m.magics[mtype])
449 self.magics[mtype].update(m.magics[mtype])
404
450
405 def register_function(self, func, magic_kind='line', magic_name=None):
451 def register_function(self, func, magic_kind='line', magic_name=None):
406 """Expose a standalone function as magic function for IPython.
452 """Expose a standalone function as magic function for IPython.
407
453
408 This will create an IPython magic (line, cell or both) from a
454 This will create an IPython magic (line, cell or both) from a
409 standalone function. The functions should have the following
455 standalone function. The functions should have the following
410 signatures:
456 signatures:
411
457
412 * For line magics: `def f(line)`
458 * For line magics: `def f(line)`
413 * For cell magics: `def f(line, cell)`
459 * For cell magics: `def f(line, cell)`
414 * For a function that does both: `def f(line, cell=None)`
460 * For a function that does both: `def f(line, cell=None)`
415
461
416 In the latter case, the function will be called with `cell==None` when
462 In the latter case, the function will be called with `cell==None` when
417 invoked as `%f`, and with cell as a string when invoked as `%%f`.
463 invoked as `%f`, and with cell as a string when invoked as `%%f`.
418
464
419 Parameters
465 Parameters
420 ----------
466 ----------
421 func : callable
467 func : callable
422 Function to be registered as a magic.
468 Function to be registered as a magic.
423 magic_kind : str
469 magic_kind : str
424 Kind of magic, one of 'line', 'cell' or 'line_cell'
470 Kind of magic, one of 'line', 'cell' or 'line_cell'
425 magic_name : optional str
471 magic_name : optional str
426 If given, the name the magic will have in the IPython namespace. By
472 If given, the name the magic will have in the IPython namespace. By
427 default, the name of the function itself is used.
473 default, the name of the function itself is used.
428 """
474 """
429
475
430 # Create the new method in the user_magics and register it in the
476 # Create the new method in the user_magics and register it in the
431 # global table
477 # global table
432 validate_type(magic_kind)
478 validate_type(magic_kind)
433 magic_name = func.__name__ if magic_name is None else magic_name
479 magic_name = func.__name__ if magic_name is None else magic_name
434 setattr(self.user_magics, magic_name, func)
480 setattr(self.user_magics, magic_name, func)
435 record_magic(self.magics, magic_kind, magic_name, func)
481 record_magic(self.magics, magic_kind, magic_name, func)
436
482
437 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
483 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
438 """Register an alias to a magic function.
484 """Register an alias to a magic function.
439
485
440 The alias is an instance of :class:`MagicAlias`, which holds the
486 The alias is an instance of :class:`MagicAlias`, which holds the
441 name and kind of the magic it should call. Binding is done at
487 name and kind of the magic it should call. Binding is done at
442 call time, so if the underlying magic function is changed the alias
488 call time, so if the underlying magic function is changed the alias
443 will call the new function.
489 will call the new function.
444
490
445 Parameters
491 Parameters
446 ----------
492 ----------
447 alias_name : str
493 alias_name : str
448 The name of the magic to be registered.
494 The name of the magic to be registered.
449 magic_name : str
495 magic_name : str
450 The name of an existing magic.
496 The name of an existing magic.
451 magic_kind : str
497 magic_kind : str
452 Kind of magic, one of 'line' or 'cell'
498 Kind of magic, one of 'line' or 'cell'
453 """
499 """
454
500
455 # `validate_type` is too permissive, as it allows 'line_cell'
501 # `validate_type` is too permissive, as it allows 'line_cell'
456 # which we do not handle.
502 # which we do not handle.
457 if magic_kind not in magic_kinds:
503 if magic_kind not in magic_kinds:
458 raise ValueError('magic_kind must be one of %s, %s given' %
504 raise ValueError('magic_kind must be one of %s, %s given' %
459 magic_kinds, magic_kind)
505 magic_kinds, magic_kind)
460
506
461 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
507 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
462 setattr(self.user_magics, alias_name, alias)
508 setattr(self.user_magics, alias_name, alias)
463 record_magic(self.magics, magic_kind, alias_name, alias)
509 record_magic(self.magics, magic_kind, alias_name, alias)
464
510
465 # Key base class that provides the central functionality for magics.
511 # Key base class that provides the central functionality for magics.
466
512
467
513
468 class Magics(Configurable):
514 class Magics(Configurable):
469 """Base class for implementing magic functions.
515 """Base class for implementing magic functions.
470
516
471 Shell functions which can be reached as %function_name. All magic
517 Shell functions which can be reached as %function_name. All magic
472 functions should accept a string, which they can parse for their own
518 functions should accept a string, which they can parse for their own
473 needs. This can make some functions easier to type, eg `%cd ../`
519 needs. This can make some functions easier to type, eg `%cd ../`
474 vs. `%cd("../")`
520 vs. `%cd("../")`
475
521
476 Classes providing magic functions need to subclass this class, and they
522 Classes providing magic functions need to subclass this class, and they
477 MUST:
523 MUST:
478
524
479 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
525 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
480 individual methods as magic functions, AND
526 individual methods as magic functions, AND
481
527
482 - Use the class decorator `@magics_class` to ensure that the magic
528 - Use the class decorator `@magics_class` to ensure that the magic
483 methods are properly registered at the instance level upon instance
529 methods are properly registered at the instance level upon instance
484 initialization.
530 initialization.
485
531
486 See :mod:`magic_functions` for examples of actual implementation classes.
532 See :mod:`magic_functions` for examples of actual implementation classes.
487 """
533 """
488 # Dict holding all command-line options for each magic.
534 # Dict holding all command-line options for each magic.
489 options_table = None
535 options_table = None
490 # Dict for the mapping of magic names to methods, set by class decorator
536 # Dict for the mapping of magic names to methods, set by class decorator
491 magics = None
537 magics = None
492 # Flag to check that the class decorator was properly applied
538 # Flag to check that the class decorator was properly applied
493 registered = False
539 registered = False
494 # Instance of IPython shell
540 # Instance of IPython shell
495 shell = None
541 shell = None
496
542
497 def __init__(self, shell=None, **kwargs):
543 def __init__(self, shell=None, **kwargs):
498 if not(self.__class__.registered):
544 if not(self.__class__.registered):
499 raise ValueError('Magics subclass without registration - '
545 raise ValueError('Magics subclass without registration - '
500 'did you forget to apply @magics_class?')
546 'did you forget to apply @magics_class?')
501 if shell is not None:
547 if shell is not None:
502 if hasattr(shell, 'configurables'):
548 if hasattr(shell, 'configurables'):
503 shell.configurables.append(self)
549 shell.configurables.append(self)
504 if hasattr(shell, 'config'):
550 if hasattr(shell, 'config'):
505 kwargs.setdefault('parent', shell)
551 kwargs.setdefault('parent', shell)
506
552
507 self.shell = shell
553 self.shell = shell
508 self.options_table = {}
554 self.options_table = {}
509 # The method decorators are run when the instance doesn't exist yet, so
555 # The method decorators are run when the instance doesn't exist yet, so
510 # they can only record the names of the methods they are supposed to
556 # they can only record the names of the methods they are supposed to
511 # grab. Only now, that the instance exists, can we create the proper
557 # grab. Only now, that the instance exists, can we create the proper
512 # mapping to bound methods. So we read the info off the original names
558 # mapping to bound methods. So we read the info off the original names
513 # table and replace each method name by the actual bound method.
559 # table and replace each method name by the actual bound method.
514 # But we mustn't clobber the *class* mapping, in case of multiple instances.
560 # But we mustn't clobber the *class* mapping, in case of multiple instances.
515 class_magics = self.magics
561 class_magics = self.magics
516 self.magics = {}
562 self.magics = {}
517 for mtype in magic_kinds:
563 for mtype in magic_kinds:
518 tab = self.magics[mtype] = {}
564 tab = self.magics[mtype] = {}
519 cls_tab = class_magics[mtype]
565 cls_tab = class_magics[mtype]
520 for magic_name, meth_name in cls_tab.items():
566 for magic_name, meth_name in cls_tab.items():
521 if isinstance(meth_name, str):
567 if isinstance(meth_name, str):
522 # it's a method name, grab it
568 # it's a method name, grab it
523 tab[magic_name] = getattr(self, meth_name)
569 tab[magic_name] = getattr(self, meth_name)
524 else:
570 else:
525 # it's the real thing
571 # it's the real thing
526 tab[magic_name] = meth_name
572 tab[magic_name] = meth_name
527 # Configurable **needs** to be initiated at the end or the config
573 # Configurable **needs** to be initiated at the end or the config
528 # magics get screwed up.
574 # magics get screwed up.
529 super(Magics, self).__init__(**kwargs)
575 super(Magics, self).__init__(**kwargs)
530
576
531 def arg_err(self,func):
577 def arg_err(self,func):
532 """Print docstring if incorrect arguments were passed"""
578 """Print docstring if incorrect arguments were passed"""
533 print('Error in arguments:')
579 print('Error in arguments:')
534 print(oinspect.getdoc(func))
580 print(oinspect.getdoc(func))
535
581
536 def format_latex(self, strng):
582 def format_latex(self, strng):
537 """Format a string for latex inclusion."""
583 """Format a string for latex inclusion."""
538
584
539 # Characters that need to be escaped for latex:
585 # Characters that need to be escaped for latex:
540 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
586 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
541 # Magic command names as headers:
587 # Magic command names as headers:
542 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
588 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
543 re.MULTILINE)
589 re.MULTILINE)
544 # Magic commands
590 # Magic commands
545 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
591 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
546 re.MULTILINE)
592 re.MULTILINE)
547 # Paragraph continue
593 # Paragraph continue
548 par_re = re.compile(r'\\$',re.MULTILINE)
594 par_re = re.compile(r'\\$',re.MULTILINE)
549
595
550 # The "\n" symbol
596 # The "\n" symbol
551 newline_re = re.compile(r'\\n')
597 newline_re = re.compile(r'\\n')
552
598
553 # Now build the string for output:
599 # Now build the string for output:
554 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
600 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
555 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
601 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
556 strng)
602 strng)
557 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
603 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
558 strng = par_re.sub(r'\\\\',strng)
604 strng = par_re.sub(r'\\\\',strng)
559 strng = escape_re.sub(r'\\\1',strng)
605 strng = escape_re.sub(r'\\\1',strng)
560 strng = newline_re.sub(r'\\textbackslash{}n',strng)
606 strng = newline_re.sub(r'\\textbackslash{}n',strng)
561 return strng
607 return strng
562
608
563 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
609 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
564 """Parse options passed to an argument string.
610 """Parse options passed to an argument string.
565
611
566 The interface is similar to that of :func:`getopt.getopt`, but it
612 The interface is similar to that of :func:`getopt.getopt`, but it
567 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
613 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
568 and the stripped argument string still as a string.
614 and the stripped argument string still as a string.
569
615
570 arg_str is quoted as a true sys.argv vector by using shlex.split.
616 arg_str is quoted as a true sys.argv vector by using shlex.split.
571 This allows us to easily expand variables, glob files, quote
617 This allows us to easily expand variables, glob files, quote
572 arguments, etc.
618 arguments, etc.
573
619
574 Parameters
620 Parameters
575 ----------
621 ----------
576 arg_str : str
622 arg_str : str
577 The arguments to parse.
623 The arguments to parse.
578 opt_str : str
624 opt_str : str
579 The options specification.
625 The options specification.
580 mode : str, default 'string'
626 mode : str, default 'string'
581 If given as 'list', the argument string is returned as a list (split
627 If given as 'list', the argument string is returned as a list (split
582 on whitespace) instead of a string.
628 on whitespace) instead of a string.
583 list_all : bool, default False
629 list_all : bool, default False
584 Put all option values in lists. Normally only options
630 Put all option values in lists. Normally only options
585 appearing more than once are put in a list.
631 appearing more than once are put in a list.
586 posix : bool, default True
632 posix : bool, default True
587 Whether to split the input line in POSIX mode or not, as per the
633 Whether to split the input line in POSIX mode or not, as per the
588 conventions outlined in the :mod:`shlex` module from the standard
634 conventions outlined in the :mod:`shlex` module from the standard
589 library.
635 library.
590 """
636 """
591
637
592 # inject default options at the beginning of the input line
638 # inject default options at the beginning of the input line
593 caller = sys._getframe(1).f_code.co_name
639 caller = sys._getframe(1).f_code.co_name
594 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
640 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
595
641
596 mode = kw.get('mode','string')
642 mode = kw.get('mode','string')
597 if mode not in ['string','list']:
643 if mode not in ['string','list']:
598 raise ValueError('incorrect mode given: %s' % mode)
644 raise ValueError('incorrect mode given: %s' % mode)
599 # Get options
645 # Get options
600 list_all = kw.get('list_all',0)
646 list_all = kw.get('list_all',0)
601 posix = kw.get('posix', os.name == 'posix')
647 posix = kw.get('posix', os.name == 'posix')
602 strict = kw.get('strict', True)
648 strict = kw.get('strict', True)
603
649
604 preserve_non_opts = kw.get("preserve_non_opts", False)
650 preserve_non_opts = kw.get("preserve_non_opts", False)
605 remainder_arg_str = arg_str
651 remainder_arg_str = arg_str
606
652
607 # Check if we have more than one argument to warrant extra processing:
653 # Check if we have more than one argument to warrant extra processing:
608 odict = {} # Dictionary with options
654 odict = {} # Dictionary with options
609 args = arg_str.split()
655 args = arg_str.split()
610 if len(args) >= 1:
656 if len(args) >= 1:
611 # If the list of inputs only has 0 or 1 thing in it, there's no
657 # If the list of inputs only has 0 or 1 thing in it, there's no
612 # need to look for options
658 # need to look for options
613 argv = arg_split(arg_str, posix, strict)
659 argv = arg_split(arg_str, posix, strict)
614 # Do regular option processing
660 # Do regular option processing
615 try:
661 try:
616 opts,args = getopt(argv, opt_str, long_opts)
662 opts,args = getopt(argv, opt_str, long_opts)
617 except GetoptError as e:
663 except GetoptError as e:
618 raise UsageError(
664 raise UsageError(
619 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
665 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
620 ) from e
666 ) from e
621 for o, a in opts:
667 for o, a in opts:
622 if mode == "string" and preserve_non_opts:
668 if mode == "string" and preserve_non_opts:
623 # remove option-parts from the original args-string and preserve remaining-part.
669 # remove option-parts from the original args-string and preserve remaining-part.
624 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
670 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
625 # returned in the original order.
671 # returned in the original order.
626 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
672 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
627 a, "", 1
673 a, "", 1
628 )
674 )
629 if o.startswith("--"):
675 if o.startswith("--"):
630 o = o[2:]
676 o = o[2:]
631 else:
677 else:
632 o = o[1:]
678 o = o[1:]
633 try:
679 try:
634 odict[o].append(a)
680 odict[o].append(a)
635 except AttributeError:
681 except AttributeError:
636 odict[o] = [odict[o],a]
682 odict[o] = [odict[o],a]
637 except KeyError:
683 except KeyError:
638 if list_all:
684 if list_all:
639 odict[o] = [a]
685 odict[o] = [a]
640 else:
686 else:
641 odict[o] = a
687 odict[o] = a
642
688
643 # Prepare opts,args for return
689 # Prepare opts,args for return
644 opts = Struct(odict)
690 opts = Struct(odict)
645 if mode == 'string':
691 if mode == 'string':
646 if preserve_non_opts:
692 if preserve_non_opts:
647 args = remainder_arg_str.lstrip()
693 args = remainder_arg_str.lstrip()
648 else:
694 else:
649 args = " ".join(args)
695 args = " ".join(args)
650
696
651 return opts,args
697 return opts,args
652
698
653 def default_option(self, fn, optstr):
699 def default_option(self, fn, optstr):
654 """Make an entry in the options_table for fn, with value optstr"""
700 """Make an entry in the options_table for fn, with value optstr"""
655
701
656 if fn not in self.lsmagic():
702 if fn not in self.lsmagic():
657 error("%s is not a magic function" % fn)
703 error("%s is not a magic function" % fn)
658 self.options_table[fn] = optstr
704 self.options_table[fn] = optstr
659
705
660
706
661 class MagicAlias(object):
707 class MagicAlias(object):
662 """An alias to another magic function.
708 """An alias to another magic function.
663
709
664 An alias is determined by its magic name and magic kind. Lookup
710 An alias is determined by its magic name and magic kind. Lookup
665 is done at call time, so if the underlying magic changes the alias
711 is done at call time, so if the underlying magic changes the alias
666 will call the new function.
712 will call the new function.
667
713
668 Use the :meth:`MagicsManager.register_alias` method or the
714 Use the :meth:`MagicsManager.register_alias` method or the
669 `%alias_magic` magic function to create and register a new alias.
715 `%alias_magic` magic function to create and register a new alias.
670 """
716 """
671 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
717 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
672 self.shell = shell
718 self.shell = shell
673 self.magic_name = magic_name
719 self.magic_name = magic_name
674 self.magic_params = magic_params
720 self.magic_params = magic_params
675 self.magic_kind = magic_kind
721 self.magic_kind = magic_kind
676
722
677 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
723 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
678 self.__doc__ = "Alias for `%s`." % self.pretty_target
724 self.__doc__ = "Alias for `%s`." % self.pretty_target
679
725
680 self._in_call = False
726 self._in_call = False
681
727
682 def __call__(self, *args, **kwargs):
728 def __call__(self, *args, **kwargs):
683 """Call the magic alias."""
729 """Call the magic alias."""
684 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
730 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
685 if fn is None:
731 if fn is None:
686 raise UsageError("Magic `%s` not found." % self.pretty_target)
732 raise UsageError("Magic `%s` not found." % self.pretty_target)
687
733
688 # Protect against infinite recursion.
734 # Protect against infinite recursion.
689 if self._in_call:
735 if self._in_call:
690 raise UsageError("Infinite recursion detected; "
736 raise UsageError("Infinite recursion detected; "
691 "magic aliases cannot call themselves.")
737 "magic aliases cannot call themselves.")
692 self._in_call = True
738 self._in_call = True
693 try:
739 try:
694 if self.magic_params:
740 if self.magic_params:
695 args_list = list(args)
741 args_list = list(args)
696 args_list[0] = self.magic_params + " " + args[0]
742 args_list[0] = self.magic_params + " " + args[0]
697 args = tuple(args_list)
743 args = tuple(args_list)
698 return fn(*args, **kwargs)
744 return fn(*args, **kwargs)
699 finally:
745 finally:
700 self._in_call = False
746 self._in_call = False
@@ -1,1366 +1,1408 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions."""
2 """Tests for various magic functions."""
3
3
4 import asyncio
4 import asyncio
5 import gc
5 import gc
6 import io
6 import io
7 import os
7 import os
8 import re
8 import re
9 import shlex
9 import shlex
10 import sys
10 import sys
11 import warnings
11 import warnings
12 from importlib import invalidate_caches
12 from importlib import invalidate_caches
13 from io import StringIO
13 from io import StringIO
14 from pathlib import Path
14 from pathlib import Path
15 from textwrap import dedent
15 from textwrap import dedent
16 from unittest import TestCase, mock
16 from unittest import TestCase, mock
17
17
18 import pytest
18 import pytest
19
19
20 from IPython import get_ipython
20 from IPython import get_ipython
21 from IPython.core import magic
21 from IPython.core import magic
22 from IPython.core.error import UsageError
22 from IPython.core.error import UsageError
23 from IPython.core.magic import (
23 from IPython.core.magic import (
24 Magics,
24 Magics,
25 cell_magic,
25 cell_magic,
26 line_magic,
26 line_magic,
27 magics_class,
27 magics_class,
28 register_cell_magic,
28 register_cell_magic,
29 register_line_magic,
29 register_line_magic,
30 )
30 )
31 from IPython.core.magics import code, execution, logging, osm, script
31 from IPython.core.magics import code, execution, logging, osm, script
32 from IPython.testing import decorators as dec
32 from IPython.testing import decorators as dec
33 from IPython.testing import tools as tt
33 from IPython.testing import tools as tt
34 from IPython.utils.io import capture_output
34 from IPython.utils.io import capture_output
35 from IPython.utils.process import find_cmd
35 from IPython.utils.process import find_cmd
36 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
36 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
37 from IPython.utils.syspathcontext import prepended_to_syspath
37
38
38 from .test_debugger import PdbTestInput
39 from .test_debugger import PdbTestInput
39
40
41 from tempfile import NamedTemporaryFile
40
42
41 @magic.magics_class
43 @magic.magics_class
42 class DummyMagics(magic.Magics): pass
44 class DummyMagics(magic.Magics): pass
43
45
44 def test_extract_code_ranges():
46 def test_extract_code_ranges():
45 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
47 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
46 expected = [
48 expected = [
47 (0, 1),
49 (0, 1),
48 (2, 3),
50 (2, 3),
49 (4, 6),
51 (4, 6),
50 (6, 9),
52 (6, 9),
51 (9, 14),
53 (9, 14),
52 (16, None),
54 (16, None),
53 (None, 9),
55 (None, 9),
54 (9, None),
56 (9, None),
55 (None, 13),
57 (None, 13),
56 (None, None),
58 (None, None),
57 ]
59 ]
58 actual = list(code.extract_code_ranges(instr))
60 actual = list(code.extract_code_ranges(instr))
59 assert actual == expected
61 assert actual == expected
60
62
61 def test_extract_symbols():
63 def test_extract_symbols():
62 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
64 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
63 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
65 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
64 expected = [([], ['a']),
66 expected = [([], ['a']),
65 (["def b():\n return 42\n"], []),
67 (["def b():\n return 42\n"], []),
66 (["class A: pass\n"], []),
68 (["class A: pass\n"], []),
67 (["class A: pass\n", "def b():\n return 42\n"], []),
69 (["class A: pass\n", "def b():\n return 42\n"], []),
68 (["class A: pass\n"], ['a']),
70 (["class A: pass\n"], ['a']),
69 ([], ['z'])]
71 ([], ['z'])]
70 for symbols, exp in zip(symbols_args, expected):
72 for symbols, exp in zip(symbols_args, expected):
71 assert code.extract_symbols(source, symbols) == exp
73 assert code.extract_symbols(source, symbols) == exp
72
74
73
75
74 def test_extract_symbols_raises_exception_with_non_python_code():
76 def test_extract_symbols_raises_exception_with_non_python_code():
75 source = ("=begin A Ruby program :)=end\n"
77 source = ("=begin A Ruby program :)=end\n"
76 "def hello\n"
78 "def hello\n"
77 "puts 'Hello world'\n"
79 "puts 'Hello world'\n"
78 "end")
80 "end")
79 with pytest.raises(SyntaxError):
81 with pytest.raises(SyntaxError):
80 code.extract_symbols(source, "hello")
82 code.extract_symbols(source, "hello")
81
83
82
84
83 def test_magic_not_found():
85 def test_magic_not_found():
84 # magic not found raises UsageError
86 # magic not found raises UsageError
85 with pytest.raises(UsageError):
87 with pytest.raises(UsageError):
86 _ip.magic('doesntexist')
88 _ip.magic('doesntexist')
87
89
88 # ensure result isn't success when a magic isn't found
90 # ensure result isn't success when a magic isn't found
89 result = _ip.run_cell('%doesntexist')
91 result = _ip.run_cell('%doesntexist')
90 assert isinstance(result.error_in_exec, UsageError)
92 assert isinstance(result.error_in_exec, UsageError)
91
93
92
94
93 def test_cell_magic_not_found():
95 def test_cell_magic_not_found():
94 # magic not found raises UsageError
96 # magic not found raises UsageError
95 with pytest.raises(UsageError):
97 with pytest.raises(UsageError):
96 _ip.run_cell_magic('doesntexist', 'line', 'cell')
98 _ip.run_cell_magic('doesntexist', 'line', 'cell')
97
99
98 # ensure result isn't success when a magic isn't found
100 # ensure result isn't success when a magic isn't found
99 result = _ip.run_cell('%%doesntexist')
101 result = _ip.run_cell('%%doesntexist')
100 assert isinstance(result.error_in_exec, UsageError)
102 assert isinstance(result.error_in_exec, UsageError)
101
103
102
104
103 def test_magic_error_status():
105 def test_magic_error_status():
104 def fail(shell):
106 def fail(shell):
105 1/0
107 1/0
106 _ip.register_magic_function(fail)
108 _ip.register_magic_function(fail)
107 result = _ip.run_cell('%fail')
109 result = _ip.run_cell('%fail')
108 assert isinstance(result.error_in_exec, ZeroDivisionError)
110 assert isinstance(result.error_in_exec, ZeroDivisionError)
109
111
110
112
111 def test_config():
113 def test_config():
112 """ test that config magic does not raise
114 """ test that config magic does not raise
113 can happen if Configurable init is moved too early into
115 can happen if Configurable init is moved too early into
114 Magics.__init__ as then a Config object will be registered as a
116 Magics.__init__ as then a Config object will be registered as a
115 magic.
117 magic.
116 """
118 """
117 ## should not raise.
119 ## should not raise.
118 _ip.magic('config')
120 _ip.magic('config')
119
121
120 def test_config_available_configs():
122 def test_config_available_configs():
121 """ test that config magic prints available configs in unique and
123 """ test that config magic prints available configs in unique and
122 sorted order. """
124 sorted order. """
123 with capture_output() as captured:
125 with capture_output() as captured:
124 _ip.magic('config')
126 _ip.magic('config')
125
127
126 stdout = captured.stdout
128 stdout = captured.stdout
127 config_classes = stdout.strip().split('\n')[1:]
129 config_classes = stdout.strip().split('\n')[1:]
128 assert config_classes == sorted(set(config_classes))
130 assert config_classes == sorted(set(config_classes))
129
131
130 def test_config_print_class():
132 def test_config_print_class():
131 """ test that config with a classname prints the class's options. """
133 """ test that config with a classname prints the class's options. """
132 with capture_output() as captured:
134 with capture_output() as captured:
133 _ip.magic('config TerminalInteractiveShell')
135 _ip.magic('config TerminalInteractiveShell')
134
136
135 stdout = captured.stdout
137 stdout = captured.stdout
136 assert re.match(
138 assert re.match(
137 "TerminalInteractiveShell.* options", stdout.splitlines()[0]
139 "TerminalInteractiveShell.* options", stdout.splitlines()[0]
138 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'"
140 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'"
139
141
140
142
141 def test_rehashx():
143 def test_rehashx():
142 # clear up everything
144 # clear up everything
143 _ip.alias_manager.clear_aliases()
145 _ip.alias_manager.clear_aliases()
144 del _ip.db['syscmdlist']
146 del _ip.db['syscmdlist']
145
147
146 _ip.magic('rehashx')
148 _ip.magic('rehashx')
147 # Practically ALL ipython development systems will have more than 10 aliases
149 # Practically ALL ipython development systems will have more than 10 aliases
148
150
149 assert len(_ip.alias_manager.aliases) > 10
151 assert len(_ip.alias_manager.aliases) > 10
150 for name, cmd in _ip.alias_manager.aliases:
152 for name, cmd in _ip.alias_manager.aliases:
151 # we must strip dots from alias names
153 # we must strip dots from alias names
152 assert "." not in name
154 assert "." not in name
153
155
154 # rehashx must fill up syscmdlist
156 # rehashx must fill up syscmdlist
155 scoms = _ip.db['syscmdlist']
157 scoms = _ip.db['syscmdlist']
156 assert len(scoms) > 10
158 assert len(scoms) > 10
157
159
158
160
159 def test_magic_parse_options():
161 def test_magic_parse_options():
160 """Test that we don't mangle paths when parsing magic options."""
162 """Test that we don't mangle paths when parsing magic options."""
161 ip = get_ipython()
163 ip = get_ipython()
162 path = 'c:\\x'
164 path = 'c:\\x'
163 m = DummyMagics(ip)
165 m = DummyMagics(ip)
164 opts = m.parse_options('-f %s' % path,'f:')[0]
166 opts = m.parse_options('-f %s' % path,'f:')[0]
165 # argv splitting is os-dependent
167 # argv splitting is os-dependent
166 if os.name == 'posix':
168 if os.name == 'posix':
167 expected = 'c:x'
169 expected = 'c:x'
168 else:
170 else:
169 expected = path
171 expected = path
170 assert opts["f"] == expected
172 assert opts["f"] == expected
171
173
172
174
173 def test_magic_parse_long_options():
175 def test_magic_parse_long_options():
174 """Magic.parse_options can handle --foo=bar long options"""
176 """Magic.parse_options can handle --foo=bar long options"""
175 ip = get_ipython()
177 ip = get_ipython()
176 m = DummyMagics(ip)
178 m = DummyMagics(ip)
177 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=")
179 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=")
178 assert "foo" in opts
180 assert "foo" in opts
179 assert "bar" in opts
181 assert "bar" in opts
180 assert opts["bar"] == "bubble"
182 assert opts["bar"] == "bubble"
181
183
182
184
183 def doctest_hist_f():
185 def doctest_hist_f():
184 """Test %hist -f with temporary filename.
186 """Test %hist -f with temporary filename.
185
187
186 In [9]: import tempfile
188 In [9]: import tempfile
187
189
188 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
190 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
189
191
190 In [11]: %hist -nl -f $tfile 3
192 In [11]: %hist -nl -f $tfile 3
191
193
192 In [13]: import os; os.unlink(tfile)
194 In [13]: import os; os.unlink(tfile)
193 """
195 """
194
196
195
197
196 def doctest_hist_op():
198 def doctest_hist_op():
197 """Test %hist -op
199 """Test %hist -op
198
200
199 In [1]: class b(float):
201 In [1]: class b(float):
200 ...: pass
202 ...: pass
201 ...:
203 ...:
202
204
203 In [2]: class s(object):
205 In [2]: class s(object):
204 ...: def __str__(self):
206 ...: def __str__(self):
205 ...: return 's'
207 ...: return 's'
206 ...:
208 ...:
207
209
208 In [3]:
210 In [3]:
209
211
210 In [4]: class r(b):
212 In [4]: class r(b):
211 ...: def __repr__(self):
213 ...: def __repr__(self):
212 ...: return 'r'
214 ...: return 'r'
213 ...:
215 ...:
214
216
215 In [5]: class sr(s,r): pass
217 In [5]: class sr(s,r): pass
216 ...:
218 ...:
217
219
218 In [6]:
220 In [6]:
219
221
220 In [7]: bb=b()
222 In [7]: bb=b()
221
223
222 In [8]: ss=s()
224 In [8]: ss=s()
223
225
224 In [9]: rr=r()
226 In [9]: rr=r()
225
227
226 In [10]: ssrr=sr()
228 In [10]: ssrr=sr()
227
229
228 In [11]: 4.5
230 In [11]: 4.5
229 Out[11]: 4.5
231 Out[11]: 4.5
230
232
231 In [12]: str(ss)
233 In [12]: str(ss)
232 Out[12]: 's'
234 Out[12]: 's'
233
235
234 In [13]:
236 In [13]:
235
237
236 In [14]: %hist -op
238 In [14]: %hist -op
237 >>> class b:
239 >>> class b:
238 ... pass
240 ... pass
239 ...
241 ...
240 >>> class s(b):
242 >>> class s(b):
241 ... def __str__(self):
243 ... def __str__(self):
242 ... return 's'
244 ... return 's'
243 ...
245 ...
244 >>>
246 >>>
245 >>> class r(b):
247 >>> class r(b):
246 ... def __repr__(self):
248 ... def __repr__(self):
247 ... return 'r'
249 ... return 'r'
248 ...
250 ...
249 >>> class sr(s,r): pass
251 >>> class sr(s,r): pass
250 >>>
252 >>>
251 >>> bb=b()
253 >>> bb=b()
252 >>> ss=s()
254 >>> ss=s()
253 >>> rr=r()
255 >>> rr=r()
254 >>> ssrr=sr()
256 >>> ssrr=sr()
255 >>> 4.5
257 >>> 4.5
256 4.5
258 4.5
257 >>> str(ss)
259 >>> str(ss)
258 's'
260 's'
259 >>>
261 >>>
260 """
262 """
261
263
262 def test_hist_pof():
264 def test_hist_pof():
263 ip = get_ipython()
265 ip = get_ipython()
264 ip.run_cell("1+2", store_history=True)
266 ip.run_cell("1+2", store_history=True)
265 #raise Exception(ip.history_manager.session_number)
267 #raise Exception(ip.history_manager.session_number)
266 #raise Exception(list(ip.history_manager._get_range_session()))
268 #raise Exception(list(ip.history_manager._get_range_session()))
267 with TemporaryDirectory() as td:
269 with TemporaryDirectory() as td:
268 tf = os.path.join(td, 'hist.py')
270 tf = os.path.join(td, 'hist.py')
269 ip.run_line_magic('history', '-pof %s' % tf)
271 ip.run_line_magic('history', '-pof %s' % tf)
270 assert os.path.isfile(tf)
272 assert os.path.isfile(tf)
271
273
272
274
273 def test_macro():
275 def test_macro():
274 ip = get_ipython()
276 ip = get_ipython()
275 ip.history_manager.reset() # Clear any existing history.
277 ip.history_manager.reset() # Clear any existing history.
276 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
278 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
277 for i, cmd in enumerate(cmds, start=1):
279 for i, cmd in enumerate(cmds, start=1):
278 ip.history_manager.store_inputs(i, cmd)
280 ip.history_manager.store_inputs(i, cmd)
279 ip.magic("macro test 1-3")
281 ip.magic("macro test 1-3")
280 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n"
282 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n"
281
283
282 # List macros
284 # List macros
283 assert "test" in ip.magic("macro")
285 assert "test" in ip.magic("macro")
284
286
285
287
286 def test_macro_run():
288 def test_macro_run():
287 """Test that we can run a multi-line macro successfully."""
289 """Test that we can run a multi-line macro successfully."""
288 ip = get_ipython()
290 ip = get_ipython()
289 ip.history_manager.reset()
291 ip.history_manager.reset()
290 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
292 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
291 for cmd in cmds:
293 for cmd in cmds:
292 ip.run_cell(cmd, store_history=True)
294 ip.run_cell(cmd, store_history=True)
293 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n"
295 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n"
294 with tt.AssertPrints("12"):
296 with tt.AssertPrints("12"):
295 ip.run_cell("test")
297 ip.run_cell("test")
296 with tt.AssertPrints("13"):
298 with tt.AssertPrints("13"):
297 ip.run_cell("test")
299 ip.run_cell("test")
298
300
299
301
300 def test_magic_magic():
302 def test_magic_magic():
301 """Test %magic"""
303 """Test %magic"""
302 ip = get_ipython()
304 ip = get_ipython()
303 with capture_output() as captured:
305 with capture_output() as captured:
304 ip.magic("magic")
306 ip.magic("magic")
305
307
306 stdout = captured.stdout
308 stdout = captured.stdout
307 assert "%magic" in stdout
309 assert "%magic" in stdout
308 assert "IPython" in stdout
310 assert "IPython" in stdout
309 assert "Available" in stdout
311 assert "Available" in stdout
310
312
311
313
312 @dec.skipif_not_numpy
314 @dec.skipif_not_numpy
313 def test_numpy_reset_array_undec():
315 def test_numpy_reset_array_undec():
314 "Test '%reset array' functionality"
316 "Test '%reset array' functionality"
315 _ip.ex("import numpy as np")
317 _ip.ex("import numpy as np")
316 _ip.ex("a = np.empty(2)")
318 _ip.ex("a = np.empty(2)")
317 assert "a" in _ip.user_ns
319 assert "a" in _ip.user_ns
318 _ip.magic("reset -f array")
320 _ip.magic("reset -f array")
319 assert "a" not in _ip.user_ns
321 assert "a" not in _ip.user_ns
320
322
321
323
322 def test_reset_out():
324 def test_reset_out():
323 "Test '%reset out' magic"
325 "Test '%reset out' magic"
324 _ip.run_cell("parrot = 'dead'", store_history=True)
326 _ip.run_cell("parrot = 'dead'", store_history=True)
325 # test '%reset -f out', make an Out prompt
327 # test '%reset -f out', make an Out prompt
326 _ip.run_cell("parrot", store_history=True)
328 _ip.run_cell("parrot", store_history=True)
327 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")]
329 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")]
328 _ip.magic("reset -f out")
330 _ip.magic("reset -f out")
329 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")]
331 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")]
330 assert len(_ip.user_ns["Out"]) == 0
332 assert len(_ip.user_ns["Out"]) == 0
331
333
332
334
333 def test_reset_in():
335 def test_reset_in():
334 "Test '%reset in' magic"
336 "Test '%reset in' magic"
335 # test '%reset -f in'
337 # test '%reset -f in'
336 _ip.run_cell("parrot", store_history=True)
338 _ip.run_cell("parrot", store_history=True)
337 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
339 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
338 _ip.magic("%reset -f in")
340 _ip.magic("%reset -f in")
339 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
341 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
340 assert len(set(_ip.user_ns["In"])) == 1
342 assert len(set(_ip.user_ns["In"])) == 1
341
343
342
344
343 def test_reset_dhist():
345 def test_reset_dhist():
344 "Test '%reset dhist' magic"
346 "Test '%reset dhist' magic"
345 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
347 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
346 _ip.magic("cd " + os.path.dirname(pytest.__file__))
348 _ip.magic("cd " + os.path.dirname(pytest.__file__))
347 _ip.magic("cd -")
349 _ip.magic("cd -")
348 assert len(_ip.user_ns["_dh"]) > 0
350 assert len(_ip.user_ns["_dh"]) > 0
349 _ip.magic("reset -f dhist")
351 _ip.magic("reset -f dhist")
350 assert len(_ip.user_ns["_dh"]) == 0
352 assert len(_ip.user_ns["_dh"]) == 0
351 _ip.run_cell("_dh = [d for d in tmp]") # restore
353 _ip.run_cell("_dh = [d for d in tmp]") # restore
352
354
353
355
354 def test_reset_in_length():
356 def test_reset_in_length():
355 "Test that '%reset in' preserves In[] length"
357 "Test that '%reset in' preserves In[] length"
356 _ip.run_cell("print 'foo'")
358 _ip.run_cell("print 'foo'")
357 _ip.run_cell("reset -f in")
359 _ip.run_cell("reset -f in")
358 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1
360 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1
359
361
360
362
361 class TestResetErrors(TestCase):
363 class TestResetErrors(TestCase):
362
364
363 def test_reset_redefine(self):
365 def test_reset_redefine(self):
364
366
365 @magics_class
367 @magics_class
366 class KernelMagics(Magics):
368 class KernelMagics(Magics):
367 @line_magic
369 @line_magic
368 def less(self, shell): pass
370 def less(self, shell): pass
369
371
370 _ip.register_magics(KernelMagics)
372 _ip.register_magics(KernelMagics)
371
373
372 with self.assertLogs() as cm:
374 with self.assertLogs() as cm:
373 # hack, we want to just capture logs, but assertLogs fails if not
375 # hack, we want to just capture logs, but assertLogs fails if not
374 # logs get produce.
376 # logs get produce.
375 # so log one things we ignore.
377 # so log one things we ignore.
376 import logging as log_mod
378 import logging as log_mod
377 log = log_mod.getLogger()
379 log = log_mod.getLogger()
378 log.info('Nothing')
380 log.info('Nothing')
379 # end hack.
381 # end hack.
380 _ip.run_cell("reset -f")
382 _ip.run_cell("reset -f")
381
383
382 assert len(cm.output) == 1
384 assert len(cm.output) == 1
383 for out in cm.output:
385 for out in cm.output:
384 assert "Invalid alias" not in out
386 assert "Invalid alias" not in out
385
387
386 def test_tb_syntaxerror():
388 def test_tb_syntaxerror():
387 """test %tb after a SyntaxError"""
389 """test %tb after a SyntaxError"""
388 ip = get_ipython()
390 ip = get_ipython()
389 ip.run_cell("for")
391 ip.run_cell("for")
390
392
391 # trap and validate stdout
393 # trap and validate stdout
392 save_stdout = sys.stdout
394 save_stdout = sys.stdout
393 try:
395 try:
394 sys.stdout = StringIO()
396 sys.stdout = StringIO()
395 ip.run_cell("%tb")
397 ip.run_cell("%tb")
396 out = sys.stdout.getvalue()
398 out = sys.stdout.getvalue()
397 finally:
399 finally:
398 sys.stdout = save_stdout
400 sys.stdout = save_stdout
399 # trim output, and only check the last line
401 # trim output, and only check the last line
400 last_line = out.rstrip().splitlines()[-1].strip()
402 last_line = out.rstrip().splitlines()[-1].strip()
401 assert last_line == "SyntaxError: invalid syntax"
403 assert last_line == "SyntaxError: invalid syntax"
402
404
403
405
404 def test_time():
406 def test_time():
405 ip = get_ipython()
407 ip = get_ipython()
406
408
407 with tt.AssertPrints("Wall time: "):
409 with tt.AssertPrints("Wall time: "):
408 ip.run_cell("%time None")
410 ip.run_cell("%time None")
409
411
410 ip.run_cell("def f(kmjy):\n"
412 ip.run_cell("def f(kmjy):\n"
411 " %time print (2*kmjy)")
413 " %time print (2*kmjy)")
412
414
413 with tt.AssertPrints("Wall time: "):
415 with tt.AssertPrints("Wall time: "):
414 with tt.AssertPrints("hihi", suppress=False):
416 with tt.AssertPrints("hihi", suppress=False):
415 ip.run_cell("f('hi')")
417 ip.run_cell("f('hi')")
416
418
417 def test_time_last_not_expression():
419 def test_time_last_not_expression():
418 ip.run_cell("%%time\n"
420 ip.run_cell("%%time\n"
419 "var_1 = 1\n"
421 "var_1 = 1\n"
420 "var_2 = 2\n")
422 "var_2 = 2\n")
421 assert ip.user_ns['var_1'] == 1
423 assert ip.user_ns['var_1'] == 1
422 del ip.user_ns['var_1']
424 del ip.user_ns['var_1']
423 assert ip.user_ns['var_2'] == 2
425 assert ip.user_ns['var_2'] == 2
424 del ip.user_ns['var_2']
426 del ip.user_ns['var_2']
425
427
426
428
427 @dec.skip_win32
429 @dec.skip_win32
428 def test_time2():
430 def test_time2():
429 ip = get_ipython()
431 ip = get_ipython()
430
432
431 with tt.AssertPrints("CPU times: user "):
433 with tt.AssertPrints("CPU times: user "):
432 ip.run_cell("%time None")
434 ip.run_cell("%time None")
433
435
434 def test_time3():
436 def test_time3():
435 """Erroneous magic function calls, issue gh-3334"""
437 """Erroneous magic function calls, issue gh-3334"""
436 ip = get_ipython()
438 ip = get_ipython()
437 ip.user_ns.pop('run', None)
439 ip.user_ns.pop('run', None)
438
440
439 with tt.AssertNotPrints("not found", channel='stderr'):
441 with tt.AssertNotPrints("not found", channel='stderr'):
440 ip.run_cell("%%time\n"
442 ip.run_cell("%%time\n"
441 "run = 0\n"
443 "run = 0\n"
442 "run += 1")
444 "run += 1")
443
445
444 def test_multiline_time():
446 def test_multiline_time():
445 """Make sure last statement from time return a value."""
447 """Make sure last statement from time return a value."""
446 ip = get_ipython()
448 ip = get_ipython()
447 ip.user_ns.pop('run', None)
449 ip.user_ns.pop('run', None)
448
450
449 ip.run_cell(dedent("""\
451 ip.run_cell(dedent("""\
450 %%time
452 %%time
451 a = "ho"
453 a = "ho"
452 b = "hey"
454 b = "hey"
453 a+b
455 a+b
454 """
456 """
455 )
457 )
456 )
458 )
457 assert ip.user_ns_hidden["_"] == "hohey"
459 assert ip.user_ns_hidden["_"] == "hohey"
458
460
459
461
460 def test_time_local_ns():
462 def test_time_local_ns():
461 """
463 """
462 Test that local_ns is actually global_ns when running a cell magic
464 Test that local_ns is actually global_ns when running a cell magic
463 """
465 """
464 ip = get_ipython()
466 ip = get_ipython()
465 ip.run_cell("%%time\n" "myvar = 1")
467 ip.run_cell("%%time\n" "myvar = 1")
466 assert ip.user_ns["myvar"] == 1
468 assert ip.user_ns["myvar"] == 1
467 del ip.user_ns["myvar"]
469 del ip.user_ns["myvar"]
468
470
469
471
470 def test_doctest_mode():
472 def test_doctest_mode():
471 "Toggle doctest_mode twice, it should be a no-op and run without error"
473 "Toggle doctest_mode twice, it should be a no-op and run without error"
472 _ip.magic('doctest_mode')
474 _ip.magic('doctest_mode')
473 _ip.magic('doctest_mode')
475 _ip.magic('doctest_mode')
474
476
475
477
476 def test_parse_options():
478 def test_parse_options():
477 """Tests for basic options parsing in magics."""
479 """Tests for basic options parsing in magics."""
478 # These are only the most minimal of tests, more should be added later. At
480 # These are only the most minimal of tests, more should be added later. At
479 # the very least we check that basic text/unicode calls work OK.
481 # the very least we check that basic text/unicode calls work OK.
480 m = DummyMagics(_ip)
482 m = DummyMagics(_ip)
481 assert m.parse_options("foo", "")[1] == "foo"
483 assert m.parse_options("foo", "")[1] == "foo"
482 assert m.parse_options("foo", "")[1] == "foo"
484 assert m.parse_options("foo", "")[1] == "foo"
483
485
484
486
485 def test_parse_options_preserve_non_option_string():
487 def test_parse_options_preserve_non_option_string():
486 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
488 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
487 m = DummyMagics(_ip)
489 m = DummyMagics(_ip)
488 opts, stmt = m.parse_options(
490 opts, stmt = m.parse_options(
489 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
491 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
490 )
492 )
491 assert opts == {"n": "1", "r": "13"}
493 assert opts == {"n": "1", "r": "13"}
492 assert stmt == "_ = 314 + foo"
494 assert stmt == "_ = 314 + foo"
493
495
494
496
495 def test_run_magic_preserve_code_block():
497 def test_run_magic_preserve_code_block():
496 """Test to assert preservation of non-option part of magic-block, while running magic."""
498 """Test to assert preservation of non-option part of magic-block, while running magic."""
497 _ip.user_ns["spaces"] = []
499 _ip.user_ns["spaces"] = []
498 _ip.magic("timeit -n1 -r1 spaces.append([s.count(' ') for s in ['document']])")
500 _ip.magic("timeit -n1 -r1 spaces.append([s.count(' ') for s in ['document']])")
499 assert _ip.user_ns["spaces"] == [[0]]
501 assert _ip.user_ns["spaces"] == [[0]]
500
502
501
503
502 def test_dirops():
504 def test_dirops():
503 """Test various directory handling operations."""
505 """Test various directory handling operations."""
504 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
506 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
505 curpath = os.getcwd
507 curpath = os.getcwd
506 startdir = os.getcwd()
508 startdir = os.getcwd()
507 ipdir = os.path.realpath(_ip.ipython_dir)
509 ipdir = os.path.realpath(_ip.ipython_dir)
508 try:
510 try:
509 _ip.magic('cd "%s"' % ipdir)
511 _ip.magic('cd "%s"' % ipdir)
510 assert curpath() == ipdir
512 assert curpath() == ipdir
511 _ip.magic('cd -')
513 _ip.magic('cd -')
512 assert curpath() == startdir
514 assert curpath() == startdir
513 _ip.magic('pushd "%s"' % ipdir)
515 _ip.magic('pushd "%s"' % ipdir)
514 assert curpath() == ipdir
516 assert curpath() == ipdir
515 _ip.magic('popd')
517 _ip.magic('popd')
516 assert curpath() == startdir
518 assert curpath() == startdir
517 finally:
519 finally:
518 os.chdir(startdir)
520 os.chdir(startdir)
519
521
520
522
521 def test_cd_force_quiet():
523 def test_cd_force_quiet():
522 """Test OSMagics.cd_force_quiet option"""
524 """Test OSMagics.cd_force_quiet option"""
523 _ip.config.OSMagics.cd_force_quiet = True
525 _ip.config.OSMagics.cd_force_quiet = True
524 osmagics = osm.OSMagics(shell=_ip)
526 osmagics = osm.OSMagics(shell=_ip)
525
527
526 startdir = os.getcwd()
528 startdir = os.getcwd()
527 ipdir = os.path.realpath(_ip.ipython_dir)
529 ipdir = os.path.realpath(_ip.ipython_dir)
528
530
529 try:
531 try:
530 with tt.AssertNotPrints(ipdir):
532 with tt.AssertNotPrints(ipdir):
531 osmagics.cd('"%s"' % ipdir)
533 osmagics.cd('"%s"' % ipdir)
532 with tt.AssertNotPrints(startdir):
534 with tt.AssertNotPrints(startdir):
533 osmagics.cd('-')
535 osmagics.cd('-')
534 finally:
536 finally:
535 os.chdir(startdir)
537 os.chdir(startdir)
536
538
537
539
538 def test_xmode():
540 def test_xmode():
539 # Calling xmode three times should be a no-op
541 # Calling xmode three times should be a no-op
540 xmode = _ip.InteractiveTB.mode
542 xmode = _ip.InteractiveTB.mode
541 for i in range(4):
543 for i in range(4):
542 _ip.magic("xmode")
544 _ip.magic("xmode")
543 assert _ip.InteractiveTB.mode == xmode
545 assert _ip.InteractiveTB.mode == xmode
544
546
545 def test_reset_hard():
547 def test_reset_hard():
546 monitor = []
548 monitor = []
547 class A(object):
549 class A(object):
548 def __del__(self):
550 def __del__(self):
549 monitor.append(1)
551 monitor.append(1)
550 def __repr__(self):
552 def __repr__(self):
551 return "<A instance>"
553 return "<A instance>"
552
554
553 _ip.user_ns["a"] = A()
555 _ip.user_ns["a"] = A()
554 _ip.run_cell("a")
556 _ip.run_cell("a")
555
557
556 assert monitor == []
558 assert monitor == []
557 _ip.magic("reset -f")
559 _ip.magic("reset -f")
558 assert monitor == [1]
560 assert monitor == [1]
559
561
560 class TestXdel(tt.TempFileMixin):
562 class TestXdel(tt.TempFileMixin):
561 def test_xdel(self):
563 def test_xdel(self):
562 """Test that references from %run are cleared by xdel."""
564 """Test that references from %run are cleared by xdel."""
563 src = ("class A(object):\n"
565 src = ("class A(object):\n"
564 " monitor = []\n"
566 " monitor = []\n"
565 " def __del__(self):\n"
567 " def __del__(self):\n"
566 " self.monitor.append(1)\n"
568 " self.monitor.append(1)\n"
567 "a = A()\n")
569 "a = A()\n")
568 self.mktmp(src)
570 self.mktmp(src)
569 # %run creates some hidden references...
571 # %run creates some hidden references...
570 _ip.magic("run %s" % self.fname)
572 _ip.magic("run %s" % self.fname)
571 # ... as does the displayhook.
573 # ... as does the displayhook.
572 _ip.run_cell("a")
574 _ip.run_cell("a")
573
575
574 monitor = _ip.user_ns["A"].monitor
576 monitor = _ip.user_ns["A"].monitor
575 assert monitor == []
577 assert monitor == []
576
578
577 _ip.magic("xdel a")
579 _ip.magic("xdel a")
578
580
579 # Check that a's __del__ method has been called.
581 # Check that a's __del__ method has been called.
580 gc.collect(0)
582 gc.collect(0)
581 assert monitor == [1]
583 assert monitor == [1]
582
584
583 def doctest_who():
585 def doctest_who():
584 """doctest for %who
586 """doctest for %who
585
587
586 In [1]: %reset -sf
588 In [1]: %reset -sf
587
589
588 In [2]: alpha = 123
590 In [2]: alpha = 123
589
591
590 In [3]: beta = 'beta'
592 In [3]: beta = 'beta'
591
593
592 In [4]: %who int
594 In [4]: %who int
593 alpha
595 alpha
594
596
595 In [5]: %who str
597 In [5]: %who str
596 beta
598 beta
597
599
598 In [6]: %whos
600 In [6]: %whos
599 Variable Type Data/Info
601 Variable Type Data/Info
600 ----------------------------
602 ----------------------------
601 alpha int 123
603 alpha int 123
602 beta str beta
604 beta str beta
603
605
604 In [7]: %who_ls
606 In [7]: %who_ls
605 Out[7]: ['alpha', 'beta']
607 Out[7]: ['alpha', 'beta']
606 """
608 """
607
609
608 def test_whos():
610 def test_whos():
609 """Check that whos is protected against objects where repr() fails."""
611 """Check that whos is protected against objects where repr() fails."""
610 class A(object):
612 class A(object):
611 def __repr__(self):
613 def __repr__(self):
612 raise Exception()
614 raise Exception()
613 _ip.user_ns['a'] = A()
615 _ip.user_ns['a'] = A()
614 _ip.magic("whos")
616 _ip.magic("whos")
615
617
616 def doctest_precision():
618 def doctest_precision():
617 """doctest for %precision
619 """doctest for %precision
618
620
619 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
621 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
620
622
621 In [2]: %precision 5
623 In [2]: %precision 5
622 Out[2]: '%.5f'
624 Out[2]: '%.5f'
623
625
624 In [3]: f.float_format
626 In [3]: f.float_format
625 Out[3]: '%.5f'
627 Out[3]: '%.5f'
626
628
627 In [4]: %precision %e
629 In [4]: %precision %e
628 Out[4]: '%e'
630 Out[4]: '%e'
629
631
630 In [5]: f(3.1415927)
632 In [5]: f(3.1415927)
631 Out[5]: '3.141593e+00'
633 Out[5]: '3.141593e+00'
632 """
634 """
633
635
634 def test_debug_magic():
636 def test_debug_magic():
635 """Test debugging a small code with %debug
637 """Test debugging a small code with %debug
636
638
637 In [1]: with PdbTestInput(['c']):
639 In [1]: with PdbTestInput(['c']):
638 ...: %debug print("a b") #doctest: +ELLIPSIS
640 ...: %debug print("a b") #doctest: +ELLIPSIS
639 ...:
641 ...:
640 ...
642 ...
641 ipdb> c
643 ipdb> c
642 a b
644 a b
643 In [2]:
645 In [2]:
644 """
646 """
645
647
646 def test_psearch():
648 def test_psearch():
647 with tt.AssertPrints("dict.fromkeys"):
649 with tt.AssertPrints("dict.fromkeys"):
648 _ip.run_cell("dict.fr*?")
650 _ip.run_cell("dict.fr*?")
649 with tt.AssertPrints("π.is_integer"):
651 with tt.AssertPrints("π.is_integer"):
650 _ip.run_cell("π = 3.14;\nπ.is_integ*?")
652 _ip.run_cell("π = 3.14;\nπ.is_integ*?")
651
653
652 def test_timeit_shlex():
654 def test_timeit_shlex():
653 """test shlex issues with timeit (#1109)"""
655 """test shlex issues with timeit (#1109)"""
654 _ip.ex("def f(*a,**kw): pass")
656 _ip.ex("def f(*a,**kw): pass")
655 _ip.magic('timeit -n1 "this is a bug".count(" ")')
657 _ip.magic('timeit -n1 "this is a bug".count(" ")')
656 _ip.magic('timeit -r1 -n1 f(" ", 1)')
658 _ip.magic('timeit -r1 -n1 f(" ", 1)')
657 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
659 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
658 _ip.magic('timeit -r1 -n1 ("a " + "b")')
660 _ip.magic('timeit -r1 -n1 ("a " + "b")')
659 _ip.magic('timeit -r1 -n1 f("a " + "b")')
661 _ip.magic('timeit -r1 -n1 f("a " + "b")')
660 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
662 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
661
663
662
664
663 def test_timeit_special_syntax():
665 def test_timeit_special_syntax():
664 "Test %%timeit with IPython special syntax"
666 "Test %%timeit with IPython special syntax"
665 @register_line_magic
667 @register_line_magic
666 def lmagic(line):
668 def lmagic(line):
667 ip = get_ipython()
669 ip = get_ipython()
668 ip.user_ns['lmagic_out'] = line
670 ip.user_ns['lmagic_out'] = line
669
671
670 # line mode test
672 # line mode test
671 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
673 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
672 assert _ip.user_ns["lmagic_out"] == "my line"
674 assert _ip.user_ns["lmagic_out"] == "my line"
673 # cell mode test
675 # cell mode test
674 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
676 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
675 assert _ip.user_ns["lmagic_out"] == "my line2"
677 assert _ip.user_ns["lmagic_out"] == "my line2"
676
678
677
679
678 def test_timeit_return():
680 def test_timeit_return():
679 """
681 """
680 test whether timeit -o return object
682 test whether timeit -o return object
681 """
683 """
682
684
683 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
685 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
684 assert(res is not None)
686 assert(res is not None)
685
687
686 def test_timeit_quiet():
688 def test_timeit_quiet():
687 """
689 """
688 test quiet option of timeit magic
690 test quiet option of timeit magic
689 """
691 """
690 with tt.AssertNotPrints("loops"):
692 with tt.AssertNotPrints("loops"):
691 _ip.run_cell("%timeit -n1 -r1 -q 1")
693 _ip.run_cell("%timeit -n1 -r1 -q 1")
692
694
693 def test_timeit_return_quiet():
695 def test_timeit_return_quiet():
694 with tt.AssertNotPrints("loops"):
696 with tt.AssertNotPrints("loops"):
695 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
697 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
696 assert (res is not None)
698 assert (res is not None)
697
699
698 def test_timeit_invalid_return():
700 def test_timeit_invalid_return():
699 with pytest.raises(SyntaxError):
701 with pytest.raises(SyntaxError):
700 _ip.run_line_magic('timeit', 'return')
702 _ip.run_line_magic('timeit', 'return')
701
703
702 @dec.skipif(execution.profile is None)
704 @dec.skipif(execution.profile is None)
703 def test_prun_special_syntax():
705 def test_prun_special_syntax():
704 "Test %%prun with IPython special syntax"
706 "Test %%prun with IPython special syntax"
705 @register_line_magic
707 @register_line_magic
706 def lmagic(line):
708 def lmagic(line):
707 ip = get_ipython()
709 ip = get_ipython()
708 ip.user_ns['lmagic_out'] = line
710 ip.user_ns['lmagic_out'] = line
709
711
710 # line mode test
712 # line mode test
711 _ip.run_line_magic("prun", "-q %lmagic my line")
713 _ip.run_line_magic("prun", "-q %lmagic my line")
712 assert _ip.user_ns["lmagic_out"] == "my line"
714 assert _ip.user_ns["lmagic_out"] == "my line"
713 # cell mode test
715 # cell mode test
714 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
716 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
715 assert _ip.user_ns["lmagic_out"] == "my line2"
717 assert _ip.user_ns["lmagic_out"] == "my line2"
716
718
717
719
718 @dec.skipif(execution.profile is None)
720 @dec.skipif(execution.profile is None)
719 def test_prun_quotes():
721 def test_prun_quotes():
720 "Test that prun does not clobber string escapes (GH #1302)"
722 "Test that prun does not clobber string escapes (GH #1302)"
721 _ip.magic(r"prun -q x = '\t'")
723 _ip.magic(r"prun -q x = '\t'")
722 assert _ip.user_ns["x"] == "\t"
724 assert _ip.user_ns["x"] == "\t"
723
725
724
726
725 def test_extension():
727 def test_extension():
726 # Debugging information for failures of this test
728 # Debugging information for failures of this test
727 print('sys.path:')
729 print('sys.path:')
728 for p in sys.path:
730 for p in sys.path:
729 print(' ', p)
731 print(' ', p)
730 print('CWD', os.getcwd())
732 print('CWD', os.getcwd())
731
733
732 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
734 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
733 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
735 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
734 sys.path.insert(0, daft_path)
736 sys.path.insert(0, daft_path)
735 try:
737 try:
736 _ip.user_ns.pop('arq', None)
738 _ip.user_ns.pop('arq', None)
737 invalidate_caches() # Clear import caches
739 invalidate_caches() # Clear import caches
738 _ip.magic("load_ext daft_extension")
740 _ip.magic("load_ext daft_extension")
739 assert _ip.user_ns["arq"] == 185
741 assert _ip.user_ns["arq"] == 185
740 _ip.magic("unload_ext daft_extension")
742 _ip.magic("unload_ext daft_extension")
741 assert 'arq' not in _ip.user_ns
743 assert 'arq' not in _ip.user_ns
742 finally:
744 finally:
743 sys.path.remove(daft_path)
745 sys.path.remove(daft_path)
744
746
745
747
746 def test_notebook_export_json():
748 def test_notebook_export_json():
747 pytest.importorskip("nbformat")
749 pytest.importorskip("nbformat")
748 _ip = get_ipython()
750 _ip = get_ipython()
749 _ip.history_manager.reset() # Clear any existing history.
751 _ip.history_manager.reset() # Clear any existing history.
750 cmds = ["a=1", "def b():\n return a**2", "print('noël, été', b())"]
752 cmds = ["a=1", "def b():\n return a**2", "print('noël, été', b())"]
751 for i, cmd in enumerate(cmds, start=1):
753 for i, cmd in enumerate(cmds, start=1):
752 _ip.history_manager.store_inputs(i, cmd)
754 _ip.history_manager.store_inputs(i, cmd)
753 with TemporaryDirectory() as td:
755 with TemporaryDirectory() as td:
754 outfile = os.path.join(td, "nb.ipynb")
756 outfile = os.path.join(td, "nb.ipynb")
755 _ip.magic("notebook %s" % outfile)
757 _ip.magic("notebook %s" % outfile)
756
758
757
759
758 class TestEnv(TestCase):
760 class TestEnv(TestCase):
759
761
760 def test_env(self):
762 def test_env(self):
761 env = _ip.magic("env")
763 env = _ip.magic("env")
762 self.assertTrue(isinstance(env, dict))
764 self.assertTrue(isinstance(env, dict))
763
765
764 def test_env_secret(self):
766 def test_env_secret(self):
765 env = _ip.magic("env")
767 env = _ip.magic("env")
766 hidden = "<hidden>"
768 hidden = "<hidden>"
767 with mock.patch.dict(
769 with mock.patch.dict(
768 os.environ,
770 os.environ,
769 {
771 {
770 "API_KEY": "abc123",
772 "API_KEY": "abc123",
771 "SECRET_THING": "ssshhh",
773 "SECRET_THING": "ssshhh",
772 "JUPYTER_TOKEN": "",
774 "JUPYTER_TOKEN": "",
773 "VAR": "abc"
775 "VAR": "abc"
774 }
776 }
775 ):
777 ):
776 env = _ip.magic("env")
778 env = _ip.magic("env")
777 assert env["API_KEY"] == hidden
779 assert env["API_KEY"] == hidden
778 assert env["SECRET_THING"] == hidden
780 assert env["SECRET_THING"] == hidden
779 assert env["JUPYTER_TOKEN"] == hidden
781 assert env["JUPYTER_TOKEN"] == hidden
780 assert env["VAR"] == "abc"
782 assert env["VAR"] == "abc"
781
783
782 def test_env_get_set_simple(self):
784 def test_env_get_set_simple(self):
783 env = _ip.magic("env var val1")
785 env = _ip.magic("env var val1")
784 self.assertEqual(env, None)
786 self.assertEqual(env, None)
785 self.assertEqual(os.environ['var'], 'val1')
787 self.assertEqual(os.environ['var'], 'val1')
786 self.assertEqual(_ip.magic("env var"), 'val1')
788 self.assertEqual(_ip.magic("env var"), 'val1')
787 env = _ip.magic("env var=val2")
789 env = _ip.magic("env var=val2")
788 self.assertEqual(env, None)
790 self.assertEqual(env, None)
789 self.assertEqual(os.environ['var'], 'val2')
791 self.assertEqual(os.environ['var'], 'val2')
790
792
791 def test_env_get_set_complex(self):
793 def test_env_get_set_complex(self):
792 env = _ip.magic("env var 'val1 '' 'val2")
794 env = _ip.magic("env var 'val1 '' 'val2")
793 self.assertEqual(env, None)
795 self.assertEqual(env, None)
794 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
796 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
795 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
797 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
796 env = _ip.magic('env var=val2 val3="val4')
798 env = _ip.magic('env var=val2 val3="val4')
797 self.assertEqual(env, None)
799 self.assertEqual(env, None)
798 self.assertEqual(os.environ['var'], 'val2 val3="val4')
800 self.assertEqual(os.environ['var'], 'val2 val3="val4')
799
801
800 def test_env_set_bad_input(self):
802 def test_env_set_bad_input(self):
801 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
803 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
802
804
803 def test_env_set_whitespace(self):
805 def test_env_set_whitespace(self):
804 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
806 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
805
807
806
808
807 class CellMagicTestCase(TestCase):
809 class CellMagicTestCase(TestCase):
808
810
809 def check_ident(self, magic):
811 def check_ident(self, magic):
810 # Manually called, we get the result
812 # Manually called, we get the result
811 out = _ip.run_cell_magic(magic, "a", "b")
813 out = _ip.run_cell_magic(magic, "a", "b")
812 assert out == ("a", "b")
814 assert out == ("a", "b")
813 # Via run_cell, it goes into the user's namespace via displayhook
815 # Via run_cell, it goes into the user's namespace via displayhook
814 _ip.run_cell("%%" + magic + " c\nd\n")
816 _ip.run_cell("%%" + magic + " c\nd\n")
815 assert _ip.user_ns["_"] == ("c", "d\n")
817 assert _ip.user_ns["_"] == ("c", "d\n")
816
818
817 def test_cell_magic_func_deco(self):
819 def test_cell_magic_func_deco(self):
818 "Cell magic using simple decorator"
820 "Cell magic using simple decorator"
819 @register_cell_magic
821 @register_cell_magic
820 def cellm(line, cell):
822 def cellm(line, cell):
821 return line, cell
823 return line, cell
822
824
823 self.check_ident('cellm')
825 self.check_ident('cellm')
824
826
825 def test_cell_magic_reg(self):
827 def test_cell_magic_reg(self):
826 "Cell magic manually registered"
828 "Cell magic manually registered"
827 def cellm(line, cell):
829 def cellm(line, cell):
828 return line, cell
830 return line, cell
829
831
830 _ip.register_magic_function(cellm, 'cell', 'cellm2')
832 _ip.register_magic_function(cellm, 'cell', 'cellm2')
831 self.check_ident('cellm2')
833 self.check_ident('cellm2')
832
834
833 def test_cell_magic_class(self):
835 def test_cell_magic_class(self):
834 "Cell magics declared via a class"
836 "Cell magics declared via a class"
835 @magics_class
837 @magics_class
836 class MyMagics(Magics):
838 class MyMagics(Magics):
837
839
838 @cell_magic
840 @cell_magic
839 def cellm3(self, line, cell):
841 def cellm3(self, line, cell):
840 return line, cell
842 return line, cell
841
843
842 _ip.register_magics(MyMagics)
844 _ip.register_magics(MyMagics)
843 self.check_ident('cellm3')
845 self.check_ident('cellm3')
844
846
845 def test_cell_magic_class2(self):
847 def test_cell_magic_class2(self):
846 "Cell magics declared via a class, #2"
848 "Cell magics declared via a class, #2"
847 @magics_class
849 @magics_class
848 class MyMagics2(Magics):
850 class MyMagics2(Magics):
849
851
850 @cell_magic('cellm4')
852 @cell_magic('cellm4')
851 def cellm33(self, line, cell):
853 def cellm33(self, line, cell):
852 return line, cell
854 return line, cell
853
855
854 _ip.register_magics(MyMagics2)
856 _ip.register_magics(MyMagics2)
855 self.check_ident('cellm4')
857 self.check_ident('cellm4')
856 # Check that nothing is registered as 'cellm33'
858 # Check that nothing is registered as 'cellm33'
857 c33 = _ip.find_cell_magic('cellm33')
859 c33 = _ip.find_cell_magic('cellm33')
858 assert c33 == None
860 assert c33 == None
859
861
860 def test_file():
862 def test_file():
861 """Basic %%writefile"""
863 """Basic %%writefile"""
862 ip = get_ipython()
864 ip = get_ipython()
863 with TemporaryDirectory() as td:
865 with TemporaryDirectory() as td:
864 fname = os.path.join(td, 'file1')
866 fname = os.path.join(td, 'file1')
865 ip.run_cell_magic("writefile", fname, u'\n'.join([
867 ip.run_cell_magic("writefile", fname, u'\n'.join([
866 'line1',
868 'line1',
867 'line2',
869 'line2',
868 ]))
870 ]))
869 s = Path(fname).read_text()
871 s = Path(fname).read_text()
870 assert "line1\n" in s
872 assert "line1\n" in s
871 assert "line2" in s
873 assert "line2" in s
872
874
873
875
874 @dec.skip_win32
876 @dec.skip_win32
875 def test_file_single_quote():
877 def test_file_single_quote():
876 """Basic %%writefile with embedded single quotes"""
878 """Basic %%writefile with embedded single quotes"""
877 ip = get_ipython()
879 ip = get_ipython()
878 with TemporaryDirectory() as td:
880 with TemporaryDirectory() as td:
879 fname = os.path.join(td, '\'file1\'')
881 fname = os.path.join(td, '\'file1\'')
880 ip.run_cell_magic("writefile", fname, u'\n'.join([
882 ip.run_cell_magic("writefile", fname, u'\n'.join([
881 'line1',
883 'line1',
882 'line2',
884 'line2',
883 ]))
885 ]))
884 s = Path(fname).read_text()
886 s = Path(fname).read_text()
885 assert "line1\n" in s
887 assert "line1\n" in s
886 assert "line2" in s
888 assert "line2" in s
887
889
888
890
889 @dec.skip_win32
891 @dec.skip_win32
890 def test_file_double_quote():
892 def test_file_double_quote():
891 """Basic %%writefile with embedded double quotes"""
893 """Basic %%writefile with embedded double quotes"""
892 ip = get_ipython()
894 ip = get_ipython()
893 with TemporaryDirectory() as td:
895 with TemporaryDirectory() as td:
894 fname = os.path.join(td, '"file1"')
896 fname = os.path.join(td, '"file1"')
895 ip.run_cell_magic("writefile", fname, u'\n'.join([
897 ip.run_cell_magic("writefile", fname, u'\n'.join([
896 'line1',
898 'line1',
897 'line2',
899 'line2',
898 ]))
900 ]))
899 s = Path(fname).read_text()
901 s = Path(fname).read_text()
900 assert "line1\n" in s
902 assert "line1\n" in s
901 assert "line2" in s
903 assert "line2" in s
902
904
903
905
904 def test_file_var_expand():
906 def test_file_var_expand():
905 """%%writefile $filename"""
907 """%%writefile $filename"""
906 ip = get_ipython()
908 ip = get_ipython()
907 with TemporaryDirectory() as td:
909 with TemporaryDirectory() as td:
908 fname = os.path.join(td, 'file1')
910 fname = os.path.join(td, 'file1')
909 ip.user_ns['filename'] = fname
911 ip.user_ns['filename'] = fname
910 ip.run_cell_magic("writefile", '$filename', u'\n'.join([
912 ip.run_cell_magic("writefile", '$filename', u'\n'.join([
911 'line1',
913 'line1',
912 'line2',
914 'line2',
913 ]))
915 ]))
914 s = Path(fname).read_text()
916 s = Path(fname).read_text()
915 assert "line1\n" in s
917 assert "line1\n" in s
916 assert "line2" in s
918 assert "line2" in s
917
919
918
920
919 def test_file_unicode():
921 def test_file_unicode():
920 """%%writefile with unicode cell"""
922 """%%writefile with unicode cell"""
921 ip = get_ipython()
923 ip = get_ipython()
922 with TemporaryDirectory() as td:
924 with TemporaryDirectory() as td:
923 fname = os.path.join(td, 'file1')
925 fname = os.path.join(td, 'file1')
924 ip.run_cell_magic("writefile", fname, u'\n'.join([
926 ip.run_cell_magic("writefile", fname, u'\n'.join([
925 u'liné1',
927 u'liné1',
926 u'liné2',
928 u'liné2',
927 ]))
929 ]))
928 with io.open(fname, encoding='utf-8') as f:
930 with io.open(fname, encoding='utf-8') as f:
929 s = f.read()
931 s = f.read()
930 assert "liné1\n" in s
932 assert "liné1\n" in s
931 assert "liné2" in s
933 assert "liné2" in s
932
934
933
935
934 def test_file_amend():
936 def test_file_amend():
935 """%%writefile -a amends files"""
937 """%%writefile -a amends files"""
936 ip = get_ipython()
938 ip = get_ipython()
937 with TemporaryDirectory() as td:
939 with TemporaryDirectory() as td:
938 fname = os.path.join(td, 'file2')
940 fname = os.path.join(td, 'file2')
939 ip.run_cell_magic("writefile", fname, u'\n'.join([
941 ip.run_cell_magic("writefile", fname, u'\n'.join([
940 'line1',
942 'line1',
941 'line2',
943 'line2',
942 ]))
944 ]))
943 ip.run_cell_magic("writefile", "-a %s" % fname, u'\n'.join([
945 ip.run_cell_magic("writefile", "-a %s" % fname, u'\n'.join([
944 'line3',
946 'line3',
945 'line4',
947 'line4',
946 ]))
948 ]))
947 s = Path(fname).read_text()
949 s = Path(fname).read_text()
948 assert "line1\n" in s
950 assert "line1\n" in s
949 assert "line3\n" in s
951 assert "line3\n" in s
950
952
951
953
952 def test_file_spaces():
954 def test_file_spaces():
953 """%%file with spaces in filename"""
955 """%%file with spaces in filename"""
954 ip = get_ipython()
956 ip = get_ipython()
955 with TemporaryWorkingDirectory() as td:
957 with TemporaryWorkingDirectory() as td:
956 fname = "file name"
958 fname = "file name"
957 ip.run_cell_magic("file", '"%s"'%fname, u'\n'.join([
959 ip.run_cell_magic("file", '"%s"'%fname, u'\n'.join([
958 'line1',
960 'line1',
959 'line2',
961 'line2',
960 ]))
962 ]))
961 s = Path(fname).read_text()
963 s = Path(fname).read_text()
962 assert "line1\n" in s
964 assert "line1\n" in s
963 assert "line2" in s
965 assert "line2" in s
964
966
965
967
966 def test_script_config():
968 def test_script_config():
967 ip = get_ipython()
969 ip = get_ipython()
968 ip.config.ScriptMagics.script_magics = ['whoda']
970 ip.config.ScriptMagics.script_magics = ['whoda']
969 sm = script.ScriptMagics(shell=ip)
971 sm = script.ScriptMagics(shell=ip)
970 assert "whoda" in sm.magics["cell"]
972 assert "whoda" in sm.magics["cell"]
971
973
972
974
973 def test_script_out():
975 def test_script_out():
974 ip = get_ipython()
976 ip = get_ipython()
975 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
977 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
976 assert ip.user_ns["output"].strip() == "hi"
978 assert ip.user_ns["output"].strip() == "hi"
977
979
978
980
979 def test_script_err():
981 def test_script_err():
980 ip = get_ipython()
982 ip = get_ipython()
981 ip.run_cell_magic(
983 ip.run_cell_magic(
982 "script",
984 "script",
983 f"--err error {sys.executable}",
985 f"--err error {sys.executable}",
984 "import sys; print('hello', file=sys.stderr)",
986 "import sys; print('hello', file=sys.stderr)",
985 )
987 )
986 assert ip.user_ns["error"].strip() == "hello"
988 assert ip.user_ns["error"].strip() == "hello"
987
989
988
990
989 def test_script_out_err():
991 def test_script_out_err():
990
992
991 ip = get_ipython()
993 ip = get_ipython()
992 ip.run_cell_magic(
994 ip.run_cell_magic(
993 "script",
995 "script",
994 f"--out output --err error {sys.executable}",
996 f"--out output --err error {sys.executable}",
995 "\n".join(
997 "\n".join(
996 [
998 [
997 "import sys",
999 "import sys",
998 "print('hi')",
1000 "print('hi')",
999 "print('hello', file=sys.stderr)",
1001 "print('hello', file=sys.stderr)",
1000 ]
1002 ]
1001 ),
1003 ),
1002 )
1004 )
1003 assert ip.user_ns["output"].strip() == "hi"
1005 assert ip.user_ns["output"].strip() == "hi"
1004 assert ip.user_ns["error"].strip() == "hello"
1006 assert ip.user_ns["error"].strip() == "hello"
1005
1007
1006
1008
1007 async def test_script_bg_out():
1009 async def test_script_bg_out():
1008 ip = get_ipython()
1010 ip = get_ipython()
1009 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1011 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1010 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1012 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1011 assert ip.user_ns["output"].at_eof()
1013 assert ip.user_ns["output"].at_eof()
1012
1014
1013
1015
1014 async def test_script_bg_err():
1016 async def test_script_bg_err():
1015 ip = get_ipython()
1017 ip = get_ipython()
1016 ip.run_cell_magic(
1018 ip.run_cell_magic(
1017 "script",
1019 "script",
1018 f"--bg --err error {sys.executable}",
1020 f"--bg --err error {sys.executable}",
1019 "import sys; print('hello', file=sys.stderr)",
1021 "import sys; print('hello', file=sys.stderr)",
1020 )
1022 )
1021 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1023 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1022 assert ip.user_ns["error"].at_eof()
1024 assert ip.user_ns["error"].at_eof()
1023
1025
1024
1026
1025 async def test_script_bg_out_err():
1027 async def test_script_bg_out_err():
1026 ip = get_ipython()
1028 ip = get_ipython()
1027 ip.run_cell_magic(
1029 ip.run_cell_magic(
1028 "script",
1030 "script",
1029 f"--bg --out output --err error {sys.executable}",
1031 f"--bg --out output --err error {sys.executable}",
1030 "\n".join(
1032 "\n".join(
1031 [
1033 [
1032 "import sys",
1034 "import sys",
1033 "print('hi')",
1035 "print('hi')",
1034 "print('hello', file=sys.stderr)",
1036 "print('hello', file=sys.stderr)",
1035 ]
1037 ]
1036 ),
1038 ),
1037 )
1039 )
1038 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1040 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1039 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1041 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1040 assert ip.user_ns["output"].at_eof()
1042 assert ip.user_ns["output"].at_eof()
1041 assert ip.user_ns["error"].at_eof()
1043 assert ip.user_ns["error"].at_eof()
1042
1044
1043
1045
1044 async def test_script_bg_proc():
1046 async def test_script_bg_proc():
1045 ip = get_ipython()
1047 ip = get_ipython()
1046 ip.run_cell_magic(
1048 ip.run_cell_magic(
1047 "script",
1049 "script",
1048 f"--bg --out output --proc p {sys.executable}",
1050 f"--bg --out output --proc p {sys.executable}",
1049 "\n".join(
1051 "\n".join(
1050 [
1052 [
1051 "import sys",
1053 "import sys",
1052 "print('hi')",
1054 "print('hi')",
1053 "print('hello', file=sys.stderr)",
1055 "print('hello', file=sys.stderr)",
1054 ]
1056 ]
1055 ),
1057 ),
1056 )
1058 )
1057 p = ip.user_ns["p"]
1059 p = ip.user_ns["p"]
1058 await p.wait()
1060 await p.wait()
1059 assert p.returncode == 0
1061 assert p.returncode == 0
1060 assert (await p.stdout.read()).strip() == b"hi"
1062 assert (await p.stdout.read()).strip() == b"hi"
1061 # not captured, so empty
1063 # not captured, so empty
1062 assert (await p.stderr.read()) == b""
1064 assert (await p.stderr.read()) == b""
1063 assert p.stdout.at_eof()
1065 assert p.stdout.at_eof()
1064 assert p.stderr.at_eof()
1066 assert p.stderr.at_eof()
1065
1067
1066
1068
1067 def test_script_defaults():
1069 def test_script_defaults():
1068 ip = get_ipython()
1070 ip = get_ipython()
1069 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1071 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1070 try:
1072 try:
1071 find_cmd(cmd)
1073 find_cmd(cmd)
1072 except Exception:
1074 except Exception:
1073 pass
1075 pass
1074 else:
1076 else:
1075 assert cmd in ip.magics_manager.magics["cell"]
1077 assert cmd in ip.magics_manager.magics["cell"]
1076
1078
1077
1079
1078 @magics_class
1080 @magics_class
1079 class FooFoo(Magics):
1081 class FooFoo(Magics):
1080 """class with both %foo and %%foo magics"""
1082 """class with both %foo and %%foo magics"""
1081 @line_magic('foo')
1083 @line_magic('foo')
1082 def line_foo(self, line):
1084 def line_foo(self, line):
1083 "I am line foo"
1085 "I am line foo"
1084 pass
1086 pass
1085
1087
1086 @cell_magic("foo")
1088 @cell_magic("foo")
1087 def cell_foo(self, line, cell):
1089 def cell_foo(self, line, cell):
1088 "I am cell foo, not line foo"
1090 "I am cell foo, not line foo"
1089 pass
1091 pass
1090
1092
1091 def test_line_cell_info():
1093 def test_line_cell_info():
1092 """%%foo and %foo magics are distinguishable to inspect"""
1094 """%%foo and %foo magics are distinguishable to inspect"""
1093 ip = get_ipython()
1095 ip = get_ipython()
1094 ip.magics_manager.register(FooFoo)
1096 ip.magics_manager.register(FooFoo)
1095 oinfo = ip.object_inspect("foo")
1097 oinfo = ip.object_inspect("foo")
1096 assert oinfo["found"] is True
1098 assert oinfo["found"] is True
1097 assert oinfo["ismagic"] is True
1099 assert oinfo["ismagic"] is True
1098
1100
1099 oinfo = ip.object_inspect("%%foo")
1101 oinfo = ip.object_inspect("%%foo")
1100 assert oinfo["found"] is True
1102 assert oinfo["found"] is True
1101 assert oinfo["ismagic"] is True
1103 assert oinfo["ismagic"] is True
1102 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1104 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1103
1105
1104 oinfo = ip.object_inspect("%foo")
1106 oinfo = ip.object_inspect("%foo")
1105 assert oinfo["found"] is True
1107 assert oinfo["found"] is True
1106 assert oinfo["ismagic"] is True
1108 assert oinfo["ismagic"] is True
1107 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1109 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1108
1110
1109
1111
1110 def test_multiple_magics():
1112 def test_multiple_magics():
1111 ip = get_ipython()
1113 ip = get_ipython()
1112 foo1 = FooFoo(ip)
1114 foo1 = FooFoo(ip)
1113 foo2 = FooFoo(ip)
1115 foo2 = FooFoo(ip)
1114 mm = ip.magics_manager
1116 mm = ip.magics_manager
1115 mm.register(foo1)
1117 mm.register(foo1)
1116 assert mm.magics["line"]["foo"].__self__ is foo1
1118 assert mm.magics["line"]["foo"].__self__ is foo1
1117 mm.register(foo2)
1119 mm.register(foo2)
1118 assert mm.magics["line"]["foo"].__self__ is foo2
1120 assert mm.magics["line"]["foo"].__self__ is foo2
1119
1121
1120
1122
1121 def test_alias_magic():
1123 def test_alias_magic():
1122 """Test %alias_magic."""
1124 """Test %alias_magic."""
1123 ip = get_ipython()
1125 ip = get_ipython()
1124 mm = ip.magics_manager
1126 mm = ip.magics_manager
1125
1127
1126 # Basic operation: both cell and line magics are created, if possible.
1128 # Basic operation: both cell and line magics are created, if possible.
1127 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1129 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1128 assert "timeit_alias" in mm.magics["line"]
1130 assert "timeit_alias" in mm.magics["line"]
1129 assert "timeit_alias" in mm.magics["cell"]
1131 assert "timeit_alias" in mm.magics["cell"]
1130
1132
1131 # --cell is specified, line magic not created.
1133 # --cell is specified, line magic not created.
1132 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1134 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1133 assert "timeit_cell_alias" not in mm.magics["line"]
1135 assert "timeit_cell_alias" not in mm.magics["line"]
1134 assert "timeit_cell_alias" in mm.magics["cell"]
1136 assert "timeit_cell_alias" in mm.magics["cell"]
1135
1137
1136 # Test that line alias is created successfully.
1138 # Test that line alias is created successfully.
1137 ip.run_line_magic("alias_magic", "--line env_alias env")
1139 ip.run_line_magic("alias_magic", "--line env_alias env")
1138 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1140 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1139
1141
1140 # Test that line alias with parameters passed in is created successfully.
1142 # Test that line alias with parameters passed in is created successfully.
1141 ip.run_line_magic(
1143 ip.run_line_magic(
1142 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1144 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1143 )
1145 )
1144 assert "history_alias" in mm.magics["line"]
1146 assert "history_alias" in mm.magics["line"]
1145
1147
1146
1148
1147 def test_save():
1149 def test_save():
1148 """Test %save."""
1150 """Test %save."""
1149 ip = get_ipython()
1151 ip = get_ipython()
1150 ip.history_manager.reset() # Clear any existing history.
1152 ip.history_manager.reset() # Clear any existing history.
1151 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1153 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1152 for i, cmd in enumerate(cmds, start=1):
1154 for i, cmd in enumerate(cmds, start=1):
1153 ip.history_manager.store_inputs(i, cmd)
1155 ip.history_manager.store_inputs(i, cmd)
1154 with TemporaryDirectory() as tmpdir:
1156 with TemporaryDirectory() as tmpdir:
1155 file = os.path.join(tmpdir, "testsave.py")
1157 file = os.path.join(tmpdir, "testsave.py")
1156 ip.run_line_magic("save", "%s 1-10" % file)
1158 ip.run_line_magic("save", "%s 1-10" % file)
1157 content = Path(file).read_text()
1159 content = Path(file).read_text()
1158 assert content.count(cmds[0]) == 1
1160 assert content.count(cmds[0]) == 1
1159 assert "coding: utf-8" in content
1161 assert "coding: utf-8" in content
1160 ip.run_line_magic("save", "-a %s 1-10" % file)
1162 ip.run_line_magic("save", "-a %s 1-10" % file)
1161 content = Path(file).read_text()
1163 content = Path(file).read_text()
1162 assert content.count(cmds[0]) == 2
1164 assert content.count(cmds[0]) == 2
1163 assert "coding: utf-8" in content
1165 assert "coding: utf-8" in content
1164
1166
1165
1167
1166 def test_save_with_no_args():
1168 def test_save_with_no_args():
1167 ip = get_ipython()
1169 ip = get_ipython()
1168 ip.history_manager.reset() # Clear any existing history.
1170 ip.history_manager.reset() # Clear any existing history.
1169 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1171 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1170 for i, cmd in enumerate(cmds, start=1):
1172 for i, cmd in enumerate(cmds, start=1):
1171 ip.history_manager.store_inputs(i, cmd)
1173 ip.history_manager.store_inputs(i, cmd)
1172
1174
1173 with TemporaryDirectory() as tmpdir:
1175 with TemporaryDirectory() as tmpdir:
1174 path = os.path.join(tmpdir, "testsave.py")
1176 path = os.path.join(tmpdir, "testsave.py")
1175 ip.run_line_magic("save", path)
1177 ip.run_line_magic("save", path)
1176 content = Path(path).read_text()
1178 content = Path(path).read_text()
1177 expected_content = dedent(
1179 expected_content = dedent(
1178 """\
1180 """\
1179 # coding: utf-8
1181 # coding: utf-8
1180 a=1
1182 a=1
1181 def b():
1183 def b():
1182 return a**2
1184 return a**2
1183 print(a, b())
1185 print(a, b())
1184 """
1186 """
1185 )
1187 )
1186 assert content == expected_content
1188 assert content == expected_content
1187
1189
1188
1190
1189 def test_store():
1191 def test_store():
1190 """Test %store."""
1192 """Test %store."""
1191 ip = get_ipython()
1193 ip = get_ipython()
1192 ip.run_line_magic('load_ext', 'storemagic')
1194 ip.run_line_magic('load_ext', 'storemagic')
1193
1195
1194 # make sure the storage is empty
1196 # make sure the storage is empty
1195 ip.run_line_magic("store", "-z")
1197 ip.run_line_magic("store", "-z")
1196 ip.user_ns["var"] = 42
1198 ip.user_ns["var"] = 42
1197 ip.run_line_magic("store", "var")
1199 ip.run_line_magic("store", "var")
1198 ip.user_ns["var"] = 39
1200 ip.user_ns["var"] = 39
1199 ip.run_line_magic("store", "-r")
1201 ip.run_line_magic("store", "-r")
1200 assert ip.user_ns["var"] == 42
1202 assert ip.user_ns["var"] == 42
1201
1203
1202 ip.run_line_magic("store", "-d var")
1204 ip.run_line_magic("store", "-d var")
1203 ip.user_ns["var"] = 39
1205 ip.user_ns["var"] = 39
1204 ip.run_line_magic("store", "-r")
1206 ip.run_line_magic("store", "-r")
1205 assert ip.user_ns["var"] == 39
1207 assert ip.user_ns["var"] == 39
1206
1208
1207
1209
1208 def _run_edit_test(arg_s, exp_filename=None,
1210 def _run_edit_test(arg_s, exp_filename=None,
1209 exp_lineno=-1,
1211 exp_lineno=-1,
1210 exp_contents=None,
1212 exp_contents=None,
1211 exp_is_temp=None):
1213 exp_is_temp=None):
1212 ip = get_ipython()
1214 ip = get_ipython()
1213 M = code.CodeMagics(ip)
1215 M = code.CodeMagics(ip)
1214 last_call = ['','']
1216 last_call = ['','']
1215 opts,args = M.parse_options(arg_s,'prxn:')
1217 opts,args = M.parse_options(arg_s,'prxn:')
1216 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1218 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1217
1219
1218 if exp_filename is not None:
1220 if exp_filename is not None:
1219 assert exp_filename == filename
1221 assert exp_filename == filename
1220 if exp_contents is not None:
1222 if exp_contents is not None:
1221 with io.open(filename, 'r', encoding='utf-8') as f:
1223 with io.open(filename, 'r', encoding='utf-8') as f:
1222 contents = f.read()
1224 contents = f.read()
1223 assert exp_contents == contents
1225 assert exp_contents == contents
1224 if exp_lineno != -1:
1226 if exp_lineno != -1:
1225 assert exp_lineno == lineno
1227 assert exp_lineno == lineno
1226 if exp_is_temp is not None:
1228 if exp_is_temp is not None:
1227 assert exp_is_temp == is_temp
1229 assert exp_is_temp == is_temp
1228
1230
1229
1231
1230 def test_edit_interactive():
1232 def test_edit_interactive():
1231 """%edit on interactively defined objects"""
1233 """%edit on interactively defined objects"""
1232 ip = get_ipython()
1234 ip = get_ipython()
1233 n = ip.execution_count
1235 n = ip.execution_count
1234 ip.run_cell("def foo(): return 1", store_history=True)
1236 ip.run_cell("def foo(): return 1", store_history=True)
1235
1237
1236 with pytest.raises(code.InteractivelyDefined) as e:
1238 with pytest.raises(code.InteractivelyDefined) as e:
1237 _run_edit_test("foo")
1239 _run_edit_test("foo")
1238 assert e.value.index == n
1240 assert e.value.index == n
1239
1241
1240
1242
1241 def test_edit_cell():
1243 def test_edit_cell():
1242 """%edit [cell id]"""
1244 """%edit [cell id]"""
1243 ip = get_ipython()
1245 ip = get_ipython()
1244
1246
1245 ip.run_cell("def foo(): return 1", store_history=True)
1247 ip.run_cell("def foo(): return 1", store_history=True)
1246
1248
1247 # test
1249 # test
1248 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1250 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1249
1251
1250 def test_edit_fname():
1252 def test_edit_fname():
1251 """%edit file"""
1253 """%edit file"""
1252 # test
1254 # test
1253 _run_edit_test("test file.py", exp_filename="test file.py")
1255 _run_edit_test("test file.py", exp_filename="test file.py")
1254
1256
1255 def test_bookmark():
1257 def test_bookmark():
1256 ip = get_ipython()
1258 ip = get_ipython()
1257 ip.run_line_magic('bookmark', 'bmname')
1259 ip.run_line_magic('bookmark', 'bmname')
1258 with tt.AssertPrints('bmname'):
1260 with tt.AssertPrints('bmname'):
1259 ip.run_line_magic('bookmark', '-l')
1261 ip.run_line_magic('bookmark', '-l')
1260 ip.run_line_magic('bookmark', '-d bmname')
1262 ip.run_line_magic('bookmark', '-d bmname')
1261
1263
1262 def test_ls_magic():
1264 def test_ls_magic():
1263 ip = get_ipython()
1265 ip = get_ipython()
1264 json_formatter = ip.display_formatter.formatters['application/json']
1266 json_formatter = ip.display_formatter.formatters['application/json']
1265 json_formatter.enabled = True
1267 json_formatter.enabled = True
1266 lsmagic = ip.magic('lsmagic')
1268 lsmagic = ip.magic('lsmagic')
1267 with warnings.catch_warnings(record=True) as w:
1269 with warnings.catch_warnings(record=True) as w:
1268 j = json_formatter(lsmagic)
1270 j = json_formatter(lsmagic)
1269 assert sorted(j) == ["cell", "line"]
1271 assert sorted(j) == ["cell", "line"]
1270 assert w == [] # no warnings
1272 assert w == [] # no warnings
1271
1273
1272
1274
1273 def test_strip_initial_indent():
1275 def test_strip_initial_indent():
1274 def sii(s):
1276 def sii(s):
1275 lines = s.splitlines()
1277 lines = s.splitlines()
1276 return '\n'.join(code.strip_initial_indent(lines))
1278 return '\n'.join(code.strip_initial_indent(lines))
1277
1279
1278 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1280 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1279 assert sii(" a\n b\nc") == "a\n b\nc"
1281 assert sii(" a\n b\nc") == "a\n b\nc"
1280 assert sii("a\n b") == "a\n b"
1282 assert sii("a\n b") == "a\n b"
1281
1283
1282 def test_logging_magic_quiet_from_arg():
1284 def test_logging_magic_quiet_from_arg():
1283 _ip.config.LoggingMagics.quiet = False
1285 _ip.config.LoggingMagics.quiet = False
1284 lm = logging.LoggingMagics(shell=_ip)
1286 lm = logging.LoggingMagics(shell=_ip)
1285 with TemporaryDirectory() as td:
1287 with TemporaryDirectory() as td:
1286 try:
1288 try:
1287 with tt.AssertNotPrints(re.compile("Activating.*")):
1289 with tt.AssertNotPrints(re.compile("Activating.*")):
1288 lm.logstart('-q {}'.format(
1290 lm.logstart('-q {}'.format(
1289 os.path.join(td, "quiet_from_arg.log")))
1291 os.path.join(td, "quiet_from_arg.log")))
1290 finally:
1292 finally:
1291 _ip.logger.logstop()
1293 _ip.logger.logstop()
1292
1294
1293 def test_logging_magic_quiet_from_config():
1295 def test_logging_magic_quiet_from_config():
1294 _ip.config.LoggingMagics.quiet = True
1296 _ip.config.LoggingMagics.quiet = True
1295 lm = logging.LoggingMagics(shell=_ip)
1297 lm = logging.LoggingMagics(shell=_ip)
1296 with TemporaryDirectory() as td:
1298 with TemporaryDirectory() as td:
1297 try:
1299 try:
1298 with tt.AssertNotPrints(re.compile("Activating.*")):
1300 with tt.AssertNotPrints(re.compile("Activating.*")):
1299 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1301 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1300 finally:
1302 finally:
1301 _ip.logger.logstop()
1303 _ip.logger.logstop()
1302
1304
1303
1305
1304 def test_logging_magic_not_quiet():
1306 def test_logging_magic_not_quiet():
1305 _ip.config.LoggingMagics.quiet = False
1307 _ip.config.LoggingMagics.quiet = False
1306 lm = logging.LoggingMagics(shell=_ip)
1308 lm = logging.LoggingMagics(shell=_ip)
1307 with TemporaryDirectory() as td:
1309 with TemporaryDirectory() as td:
1308 try:
1310 try:
1309 with tt.AssertPrints(re.compile("Activating.*")):
1311 with tt.AssertPrints(re.compile("Activating.*")):
1310 lm.logstart(os.path.join(td, "not_quiet.log"))
1312 lm.logstart(os.path.join(td, "not_quiet.log"))
1311 finally:
1313 finally:
1312 _ip.logger.logstop()
1314 _ip.logger.logstop()
1313
1315
1314
1316
1315 def test_time_no_var_expand():
1317 def test_time_no_var_expand():
1316 _ip.user_ns['a'] = 5
1318 _ip.user_ns['a'] = 5
1317 _ip.user_ns['b'] = []
1319 _ip.user_ns['b'] = []
1318 _ip.magic('time b.append("{a}")')
1320 _ip.magic('time b.append("{a}")')
1319 assert _ip.user_ns['b'] == ['{a}']
1321 assert _ip.user_ns['b'] == ['{a}']
1320
1322
1321
1323
1322 # this is slow, put at the end for local testing.
1324 # this is slow, put at the end for local testing.
1323 def test_timeit_arguments():
1325 def test_timeit_arguments():
1324 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1326 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1325 _ip.magic("timeit -n1 -r1 a=('#')")
1327 _ip.magic("timeit -n1 -r1 a=('#')")
1326
1328
1327
1329
1330 MINIMAL_LAZY_MAGIC = """
1331 from IPython.core.magic import (
1332 Magics,
1333 magics_class,
1334 line_magic,
1335 cell_magic,
1336 )
1337
1338
1339 @magics_class
1340 class LazyMagics(Magics):
1341 @line_magic
1342 def lazy_line(self, line):
1343 print("Lazy Line")
1344
1345 @cell_magic
1346 def lazy_cell(self, line, cell):
1347 print("Lazy Cell")
1348
1349
1350 def load_ipython_extension(ipython):
1351 ipython.register_magics(LazyMagics)
1352 """
1353
1354
1355 def test_lazy_magics():
1356 with pytest.raises(UsageError):
1357 ip.run_line_magic("lazy_line", "")
1358
1359 startdir = os.getcwd()
1360
1361 with TemporaryDirectory() as tmpdir:
1362 with prepended_to_syspath(tmpdir):
1363 ptempdir = Path(tmpdir)
1364 tf = ptempdir / "lazy_magic_module.py"
1365 tf.write_text(MINIMAL_LAZY_MAGIC)
1366 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1367 with tt.AssertPrints("Lazy Line"):
1368 ip.run_line_magic("lazy_line", "")
1369
1370
1328 TEST_MODULE = """
1371 TEST_MODULE = """
1329 print('Loaded my_tmp')
1372 print('Loaded my_tmp')
1330 if __name__ == "__main__":
1373 if __name__ == "__main__":
1331 print('I just ran a script')
1374 print('I just ran a script')
1332 """
1375 """
1333
1376
1334
1335 def test_run_module_from_import_hook():
1377 def test_run_module_from_import_hook():
1336 "Test that a module can be loaded via an import hook"
1378 "Test that a module can be loaded via an import hook"
1337 with TemporaryDirectory() as tmpdir:
1379 with TemporaryDirectory() as tmpdir:
1338 fullpath = os.path.join(tmpdir, 'my_tmp.py')
1380 fullpath = os.path.join(tmpdir, 'my_tmp.py')
1339 Path(fullpath).write_text(TEST_MODULE)
1381 Path(fullpath).write_text(TEST_MODULE)
1340
1382
1341 import importlib.abc
1383 import importlib.abc
1342 import importlib.util
1384 import importlib.util
1343
1385
1344 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1386 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1345 def find_spec(self, fullname, path, target=None):
1387 def find_spec(self, fullname, path, target=None):
1346 if fullname == "my_tmp":
1388 if fullname == "my_tmp":
1347 return importlib.util.spec_from_loader(fullname, self)
1389 return importlib.util.spec_from_loader(fullname, self)
1348
1390
1349 def get_filename(self, fullname):
1391 def get_filename(self, fullname):
1350 assert fullname == "my_tmp"
1392 assert fullname == "my_tmp"
1351 return fullpath
1393 return fullpath
1352
1394
1353 def get_data(self, path):
1395 def get_data(self, path):
1354 assert Path(path).samefile(fullpath)
1396 assert Path(path).samefile(fullpath)
1355 return Path(fullpath).read_text()
1397 return Path(fullpath).read_text()
1356
1398
1357 sys.meta_path.insert(0, MyTempImporter())
1399 sys.meta_path.insert(0, MyTempImporter())
1358
1400
1359 with capture_output() as captured:
1401 with capture_output() as captured:
1360 _ip.magic("run -m my_tmp")
1402 _ip.magic("run -m my_tmp")
1361 _ip.run_cell("import my_tmp")
1403 _ip.run_cell("import my_tmp")
1362
1404
1363 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1405 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1364 assert output == captured.stdout
1406 assert output == captured.stdout
1365
1407
1366 sys.meta_path.pop(0)
1408 sys.meta_path.pop(0)
@@ -1,187 +1,212 b''
1 """Tests for various magic functions specific to the terminal frontend."""
1 """Tests for various magic functions specific to the terminal frontend."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Imports
4 # Imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6
6
7 import sys
7 import sys
8 from io import StringIO
8 from io import StringIO
9 from unittest import TestCase
9 from unittest import TestCase
10
10
11 from IPython.testing import tools as tt
11 from IPython.testing import tools as tt
12
13 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
14 # Test functions begin
13 # Test functions begin
15 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
16
15
16
17 MINIMAL_LAZY_MAGIC = """
18 from IPython.core.magic import (
19 Magics,
20 magics_class,
21 line_magic,
22 cell_magic,
23 )
24
25
26 @magics_class
27 class LazyMagics(Magics):
28 @line_magic
29 def lazy_line(self, line):
30 print("Lazy Line")
31
32 @cell_magic
33 def lazy_cell(self, line, cell):
34 print("Lazy Cell")
35
36
37 def load_ipython_extension(ipython):
38 ipython.register_magics(LazyMagics)
39 """
40
17 def check_cpaste(code, should_fail=False):
41 def check_cpaste(code, should_fail=False):
18 """Execute code via 'cpaste' and ensure it was executed, unless
42 """Execute code via 'cpaste' and ensure it was executed, unless
19 should_fail is set.
43 should_fail is set.
20 """
44 """
21 ip.user_ns['code_ran'] = False
45 ip.user_ns['code_ran'] = False
22
46
23 src = StringIO()
47 src = StringIO()
24 src.write(code)
48 src.write(code)
25 src.write('\n--\n')
49 src.write('\n--\n')
26 src.seek(0)
50 src.seek(0)
27
51
28 stdin_save = sys.stdin
52 stdin_save = sys.stdin
29 sys.stdin = src
53 sys.stdin = src
30
54
31 try:
55 try:
32 context = tt.AssertPrints if should_fail else tt.AssertNotPrints
56 context = tt.AssertPrints if should_fail else tt.AssertNotPrints
33 with context("Traceback (most recent call last)"):
57 with context("Traceback (most recent call last)"):
34 ip.magic('cpaste')
58 ip.run_line_magic("cpaste", "")
35
59
36 if not should_fail:
60 if not should_fail:
37 assert ip.user_ns['code_ran'], "%r failed" % code
61 assert ip.user_ns['code_ran'], "%r failed" % code
38 finally:
62 finally:
39 sys.stdin = stdin_save
63 sys.stdin = stdin_save
40
64
41 def test_cpaste():
65 def test_cpaste():
42 """Test cpaste magic"""
66 """Test cpaste magic"""
43
67
44 def runf():
68 def runf():
45 """Marker function: sets a flag when executed.
69 """Marker function: sets a flag when executed.
46 """
70 """
47 ip.user_ns['code_ran'] = True
71 ip.user_ns['code_ran'] = True
48 return 'runf' # return string so '+ runf()' doesn't result in success
72 return 'runf' # return string so '+ runf()' doesn't result in success
49
73
50 tests = {'pass': ["runf()",
74 tests = {'pass': ["runf()",
51 "In [1]: runf()",
75 "In [1]: runf()",
52 "In [1]: if 1:\n ...: runf()",
76 "In [1]: if 1:\n ...: runf()",
53 "> > > runf()",
77 "> > > runf()",
54 ">>> runf()",
78 ">>> runf()",
55 " >>> runf()",
79 " >>> runf()",
56 ],
80 ],
57
81
58 'fail': ["1 + runf()",
82 'fail': ["1 + runf()",
59 "++ runf()",
83 "++ runf()",
60 ]}
84 ]}
61
85
62 ip.user_ns['runf'] = runf
86 ip.user_ns['runf'] = runf
63
87
64 for code in tests['pass']:
88 for code in tests['pass']:
65 check_cpaste(code)
89 check_cpaste(code)
66
90
67 for code in tests['fail']:
91 for code in tests['fail']:
68 check_cpaste(code, should_fail=True)
92 check_cpaste(code, should_fail=True)
69
93
70
94
95
71 class PasteTestCase(TestCase):
96 class PasteTestCase(TestCase):
72 """Multiple tests for clipboard pasting"""
97 """Multiple tests for clipboard pasting"""
73
98
74 def paste(self, txt, flags='-q'):
99 def paste(self, txt, flags='-q'):
75 """Paste input text, by default in quiet mode"""
100 """Paste input text, by default in quiet mode"""
76 ip.hooks.clipboard_get = lambda : txt
101 ip.hooks.clipboard_get = lambda: txt
77 ip.magic('paste '+flags)
102 ip.run_line_magic("paste", flags)
78
103
79 def setUp(self):
104 def setUp(self):
80 # Inject fake clipboard hook but save original so we can restore it later
105 # Inject fake clipboard hook but save original so we can restore it later
81 self.original_clip = ip.hooks.clipboard_get
106 self.original_clip = ip.hooks.clipboard_get
82
107
83 def tearDown(self):
108 def tearDown(self):
84 # Restore original hook
109 # Restore original hook
85 ip.hooks.clipboard_get = self.original_clip
110 ip.hooks.clipboard_get = self.original_clip
86
111
87 def test_paste(self):
112 def test_paste(self):
88 ip.user_ns.pop("x", None)
113 ip.user_ns.pop("x", None)
89 self.paste("x = 1")
114 self.paste("x = 1")
90 self.assertEqual(ip.user_ns["x"], 1)
115 self.assertEqual(ip.user_ns["x"], 1)
91 ip.user_ns.pop("x")
116 ip.user_ns.pop("x")
92
117
93 def test_paste_pyprompt(self):
118 def test_paste_pyprompt(self):
94 ip.user_ns.pop("x", None)
119 ip.user_ns.pop("x", None)
95 self.paste(">>> x=2")
120 self.paste(">>> x=2")
96 self.assertEqual(ip.user_ns["x"], 2)
121 self.assertEqual(ip.user_ns["x"], 2)
97 ip.user_ns.pop("x")
122 ip.user_ns.pop("x")
98
123
99 def test_paste_py_multi(self):
124 def test_paste_py_multi(self):
100 self.paste("""
125 self.paste("""
101 >>> x = [1,2,3]
126 >>> x = [1,2,3]
102 >>> y = []
127 >>> y = []
103 >>> for i in x:
128 >>> for i in x:
104 ... y.append(i**2)
129 ... y.append(i**2)
105 ...
130 ...
106 """
131 """
107 )
132 )
108 self.assertEqual(ip.user_ns["x"], [1, 2, 3])
133 self.assertEqual(ip.user_ns["x"], [1, 2, 3])
109 self.assertEqual(ip.user_ns["y"], [1, 4, 9])
134 self.assertEqual(ip.user_ns["y"], [1, 4, 9])
110
135
111 def test_paste_py_multi_r(self):
136 def test_paste_py_multi_r(self):
112 "Now, test that self.paste -r works"
137 "Now, test that self.paste -r works"
113 self.test_paste_py_multi()
138 self.test_paste_py_multi()
114 self.assertEqual(ip.user_ns.pop("x"), [1, 2, 3])
139 self.assertEqual(ip.user_ns.pop("x"), [1, 2, 3])
115 self.assertEqual(ip.user_ns.pop("y"), [1, 4, 9])
140 self.assertEqual(ip.user_ns.pop("y"), [1, 4, 9])
116 self.assertFalse("x" in ip.user_ns)
141 self.assertFalse("x" in ip.user_ns)
117 ip.magic("paste -r")
142 ip.run_line_magic("paste", "-r")
118 self.assertEqual(ip.user_ns["x"], [1, 2, 3])
143 self.assertEqual(ip.user_ns["x"], [1, 2, 3])
119 self.assertEqual(ip.user_ns["y"], [1, 4, 9])
144 self.assertEqual(ip.user_ns["y"], [1, 4, 9])
120
145
121 def test_paste_email(self):
146 def test_paste_email(self):
122 "Test pasting of email-quoted contents"
147 "Test pasting of email-quoted contents"
123 self.paste("""\
148 self.paste("""\
124 >> def foo(x):
149 >> def foo(x):
125 >> return x + 1
150 >> return x + 1
126 >> xx = foo(1.1)"""
151 >> xx = foo(1.1)"""
127 )
152 )
128 self.assertEqual(ip.user_ns["xx"], 2.1)
153 self.assertEqual(ip.user_ns["xx"], 2.1)
129
154
130 def test_paste_email2(self):
155 def test_paste_email2(self):
131 "Email again; some programs add a space also at each quoting level"
156 "Email again; some programs add a space also at each quoting level"
132 self.paste("""\
157 self.paste("""\
133 > > def foo(x):
158 > > def foo(x):
134 > > return x + 1
159 > > return x + 1
135 > > yy = foo(2.1) """
160 > > yy = foo(2.1) """
136 )
161 )
137 self.assertEqual(ip.user_ns["yy"], 3.1)
162 self.assertEqual(ip.user_ns["yy"], 3.1)
138
163
139 def test_paste_email_py(self):
164 def test_paste_email_py(self):
140 "Email quoting of interactive input"
165 "Email quoting of interactive input"
141 self.paste("""\
166 self.paste("""\
142 >> >>> def f(x):
167 >> >>> def f(x):
143 >> ... return x+1
168 >> ... return x+1
144 >> ...
169 >> ...
145 >> >>> zz = f(2.5) """
170 >> >>> zz = f(2.5) """
146 )
171 )
147 self.assertEqual(ip.user_ns["zz"], 3.5)
172 self.assertEqual(ip.user_ns["zz"], 3.5)
148
173
149 def test_paste_echo(self):
174 def test_paste_echo(self):
150 "Also test self.paste echoing, by temporarily faking the writer"
175 "Also test self.paste echoing, by temporarily faking the writer"
151 w = StringIO()
176 w = StringIO()
152 old_write = sys.stdout.write
177 old_write = sys.stdout.write
153 sys.stdout.write = w.write
178 sys.stdout.write = w.write
154 code = """
179 code = """
155 a = 100
180 a = 100
156 b = 200"""
181 b = 200"""
157 try:
182 try:
158 self.paste(code,'')
183 self.paste(code,'')
159 out = w.getvalue()
184 out = w.getvalue()
160 finally:
185 finally:
161 sys.stdout.write = old_write
186 sys.stdout.write = old_write
162 self.assertEqual(ip.user_ns["a"], 100)
187 self.assertEqual(ip.user_ns["a"], 100)
163 self.assertEqual(ip.user_ns["b"], 200)
188 self.assertEqual(ip.user_ns["b"], 200)
164 assert out == code + "\n## -- End pasted text --\n"
189 assert out == code + "\n## -- End pasted text --\n"
165
190
166 def test_paste_leading_commas(self):
191 def test_paste_leading_commas(self):
167 "Test multiline strings with leading commas"
192 "Test multiline strings with leading commas"
168 tm = ip.magics_manager.registry['TerminalMagics']
193 tm = ip.magics_manager.registry['TerminalMagics']
169 s = '''\
194 s = '''\
170 a = """
195 a = """
171 ,1,2,3
196 ,1,2,3
172 """'''
197 """'''
173 ip.user_ns.pop("foo", None)
198 ip.user_ns.pop("foo", None)
174 tm.store_or_execute(s, "foo")
199 tm.store_or_execute(s, "foo")
175 self.assertIn("foo", ip.user_ns)
200 self.assertIn("foo", ip.user_ns)
176
201
177 def test_paste_trailing_question(self):
202 def test_paste_trailing_question(self):
178 "Test pasting sources with trailing question marks"
203 "Test pasting sources with trailing question marks"
179 tm = ip.magics_manager.registry['TerminalMagics']
204 tm = ip.magics_manager.registry['TerminalMagics']
180 s = '''\
205 s = '''\
181 def funcfoo():
206 def funcfoo():
182 if True: #am i true?
207 if True: #am i true?
183 return 'fooresult'
208 return 'fooresult'
184 '''
209 '''
185 ip.user_ns.pop('funcfoo', None)
210 ip.user_ns.pop('funcfoo', None)
186 self.paste(s)
211 self.paste(s)
187 self.assertEqual(ip.user_ns["funcfoo"](), "fooresult")
212 self.assertEqual(ip.user_ns["funcfoo"](), "fooresult")
@@ -1,340 +1,342 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6 """
6 """
7
7
8 # Copyright (c) IPython Development Team.
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10
10
11
11
12 import logging
12 import logging
13 import os
13 import os
14 import sys
14 import sys
15 import warnings
15 import warnings
16
16
17 from traitlets.config.loader import Config
17 from traitlets.config.loader import Config
18 from traitlets.config.application import boolean_flag, catch_config_error
18 from traitlets.config.application import boolean_flag, catch_config_error
19 from IPython.core import release
19 from IPython.core import release
20 from IPython.core import usage
20 from IPython.core import usage
21 from IPython.core.completer import IPCompleter
21 from IPython.core.completer import IPCompleter
22 from IPython.core.crashhandler import CrashHandler
22 from IPython.core.crashhandler import CrashHandler
23 from IPython.core.formatters import PlainTextFormatter
23 from IPython.core.formatters import PlainTextFormatter
24 from IPython.core.history import HistoryManager
24 from IPython.core.history import HistoryManager
25 from IPython.core.application import (
25 from IPython.core.application import (
26 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
26 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
27 )
27 )
28 from IPython.core.magic import MagicsManager
28 from IPython.core.magics import (
29 from IPython.core.magics import (
29 ScriptMagics, LoggingMagics
30 ScriptMagics, LoggingMagics
30 )
31 )
31 from IPython.core.shellapp import (
32 from IPython.core.shellapp import (
32 InteractiveShellApp, shell_flags, shell_aliases
33 InteractiveShellApp, shell_flags, shell_aliases
33 )
34 )
34 from IPython.extensions.storemagic import StoreMagics
35 from IPython.extensions.storemagic import StoreMagics
35 from .interactiveshell import TerminalInteractiveShell
36 from .interactiveshell import TerminalInteractiveShell
36 from IPython.paths import get_ipython_dir
37 from IPython.paths import get_ipython_dir
37 from traitlets import (
38 from traitlets import (
38 Bool, List, default, observe, Type
39 Bool, List, default, observe, Type
39 )
40 )
40
41
41 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
42 # Globals, utilities and helpers
43 # Globals, utilities and helpers
43 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
44
45
45 _examples = """
46 _examples = """
46 ipython --matplotlib # enable matplotlib integration
47 ipython --matplotlib # enable matplotlib integration
47 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
48
49
49 ipython --log-level=DEBUG # set logging to DEBUG
50 ipython --log-level=DEBUG # set logging to DEBUG
50 ipython --profile=foo # start with profile foo
51 ipython --profile=foo # start with profile foo
51
52
52 ipython profile create foo # create profile foo w/ default config files
53 ipython profile create foo # create profile foo w/ default config files
53 ipython help profile # show the help for the profile subcmd
54 ipython help profile # show the help for the profile subcmd
54
55
55 ipython locate # print the path to the IPython directory
56 ipython locate # print the path to the IPython directory
56 ipython locate profile foo # print the path to the directory for profile `foo`
57 ipython locate profile foo # print the path to the directory for profile `foo`
57 """
58 """
58
59
59 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
60 # Crash handler for this application
61 # Crash handler for this application
61 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
62
63
63 class IPAppCrashHandler(CrashHandler):
64 class IPAppCrashHandler(CrashHandler):
64 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
65 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
65
66
66 def __init__(self, app):
67 def __init__(self, app):
67 contact_name = release.author
68 contact_name = release.author
68 contact_email = release.author_email
69 contact_email = release.author_email
69 bug_tracker = 'https://github.com/ipython/ipython/issues'
70 bug_tracker = 'https://github.com/ipython/ipython/issues'
70 super(IPAppCrashHandler,self).__init__(
71 super(IPAppCrashHandler,self).__init__(
71 app, contact_name, contact_email, bug_tracker
72 app, contact_name, contact_email, bug_tracker
72 )
73 )
73
74
74 def make_report(self,traceback):
75 def make_report(self,traceback):
75 """Return a string containing a crash report."""
76 """Return a string containing a crash report."""
76
77
77 sec_sep = self.section_sep
78 sec_sep = self.section_sep
78 # Start with parent report
79 # Start with parent report
79 report = [super(IPAppCrashHandler, self).make_report(traceback)]
80 report = [super(IPAppCrashHandler, self).make_report(traceback)]
80 # Add interactive-specific info we may have
81 # Add interactive-specific info we may have
81 rpt_add = report.append
82 rpt_add = report.append
82 try:
83 try:
83 rpt_add(sec_sep+"History of session input:")
84 rpt_add(sec_sep+"History of session input:")
84 for line in self.app.shell.user_ns['_ih']:
85 for line in self.app.shell.user_ns['_ih']:
85 rpt_add(line)
86 rpt_add(line)
86 rpt_add('\n*** Last line of input (may not be in above history):\n')
87 rpt_add('\n*** Last line of input (may not be in above history):\n')
87 rpt_add(self.app.shell._last_input_line+'\n')
88 rpt_add(self.app.shell._last_input_line+'\n')
88 except:
89 except:
89 pass
90 pass
90
91
91 return ''.join(report)
92 return ''.join(report)
92
93
93 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
94 # Aliases and Flags
95 # Aliases and Flags
95 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
96 flags = dict(base_flags)
97 flags = dict(base_flags)
97 flags.update(shell_flags)
98 flags.update(shell_flags)
98 frontend_flags = {}
99 frontend_flags = {}
99 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
100 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
100 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
101 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
101 'Turn on auto editing of files with syntax errors.',
102 'Turn on auto editing of files with syntax errors.',
102 'Turn off auto editing of files with syntax errors.'
103 'Turn off auto editing of files with syntax errors.'
103 )
104 )
104 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
105 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
105 "Force simple minimal prompt using `raw_input`",
106 "Force simple minimal prompt using `raw_input`",
106 "Use a rich interactive prompt with prompt_toolkit",
107 "Use a rich interactive prompt with prompt_toolkit",
107 )
108 )
108
109
109 addflag('banner', 'TerminalIPythonApp.display_banner',
110 addflag('banner', 'TerminalIPythonApp.display_banner',
110 "Display a banner upon starting IPython.",
111 "Display a banner upon starting IPython.",
111 "Don't display a banner upon starting IPython."
112 "Don't display a banner upon starting IPython."
112 )
113 )
113 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
114 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
114 """Set to confirm when you try to exit IPython with an EOF (Control-D
115 """Set to confirm when you try to exit IPython with an EOF (Control-D
115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
116 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
116 you can force a direct exit without any confirmation.""",
117 you can force a direct exit without any confirmation.""",
117 "Don't prompt the user when exiting."
118 "Don't prompt the user when exiting."
118 )
119 )
119 addflag('term-title', 'TerminalInteractiveShell.term_title',
120 addflag('term-title', 'TerminalInteractiveShell.term_title',
120 "Enable auto setting the terminal title.",
121 "Enable auto setting the terminal title.",
121 "Disable auto setting the terminal title."
122 "Disable auto setting the terminal title."
122 )
123 )
123 classic_config = Config()
124 classic_config = Config()
124 classic_config.InteractiveShell.cache_size = 0
125 classic_config.InteractiveShell.cache_size = 0
125 classic_config.PlainTextFormatter.pprint = False
126 classic_config.PlainTextFormatter.pprint = False
126 classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts'
127 classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts'
127 classic_config.InteractiveShell.separate_in = ''
128 classic_config.InteractiveShell.separate_in = ''
128 classic_config.InteractiveShell.separate_out = ''
129 classic_config.InteractiveShell.separate_out = ''
129 classic_config.InteractiveShell.separate_out2 = ''
130 classic_config.InteractiveShell.separate_out2 = ''
130 classic_config.InteractiveShell.colors = 'NoColor'
131 classic_config.InteractiveShell.colors = 'NoColor'
131 classic_config.InteractiveShell.xmode = 'Plain'
132 classic_config.InteractiveShell.xmode = 'Plain'
132
133
133 frontend_flags['classic']=(
134 frontend_flags['classic']=(
134 classic_config,
135 classic_config,
135 "Gives IPython a similar feel to the classic Python prompt."
136 "Gives IPython a similar feel to the classic Python prompt."
136 )
137 )
137 # # log doesn't make so much sense this way anymore
138 # # log doesn't make so much sense this way anymore
138 # paa('--log','-l',
139 # paa('--log','-l',
139 # action='store_true', dest='InteractiveShell.logstart',
140 # action='store_true', dest='InteractiveShell.logstart',
140 # help="Start logging to the default log file (./ipython_log.py).")
141 # help="Start logging to the default log file (./ipython_log.py).")
141 #
142 #
142 # # quick is harder to implement
143 # # quick is harder to implement
143 frontend_flags['quick']=(
144 frontend_flags['quick']=(
144 {'TerminalIPythonApp' : {'quick' : True}},
145 {'TerminalIPythonApp' : {'quick' : True}},
145 "Enable quick startup with no config files."
146 "Enable quick startup with no config files."
146 )
147 )
147
148
148 frontend_flags['i'] = (
149 frontend_flags['i'] = (
149 {'TerminalIPythonApp' : {'force_interact' : True}},
150 {'TerminalIPythonApp' : {'force_interact' : True}},
150 """If running code from the command line, become interactive afterwards.
151 """If running code from the command line, become interactive afterwards.
151 It is often useful to follow this with `--` to treat remaining flags as
152 It is often useful to follow this with `--` to treat remaining flags as
152 script arguments.
153 script arguments.
153 """
154 """
154 )
155 )
155 flags.update(frontend_flags)
156 flags.update(frontend_flags)
156
157
157 aliases = dict(base_aliases)
158 aliases = dict(base_aliases)
158 aliases.update(shell_aliases)
159 aliases.update(shell_aliases)
159
160
160 #-----------------------------------------------------------------------------
161 #-----------------------------------------------------------------------------
161 # Main classes and functions
162 # Main classes and functions
162 #-----------------------------------------------------------------------------
163 #-----------------------------------------------------------------------------
163
164
164
165
165 class LocateIPythonApp(BaseIPythonApplication):
166 class LocateIPythonApp(BaseIPythonApplication):
166 description = """print the path to the IPython dir"""
167 description = """print the path to the IPython dir"""
167 subcommands = dict(
168 subcommands = dict(
168 profile=('IPython.core.profileapp.ProfileLocate',
169 profile=('IPython.core.profileapp.ProfileLocate',
169 "print the path to an IPython profile directory",
170 "print the path to an IPython profile directory",
170 ),
171 ),
171 )
172 )
172 def start(self):
173 def start(self):
173 if self.subapp is not None:
174 if self.subapp is not None:
174 return self.subapp.start()
175 return self.subapp.start()
175 else:
176 else:
176 print(self.ipython_dir)
177 print(self.ipython_dir)
177
178
178
179
179 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
180 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
180 name = u'ipython'
181 name = u'ipython'
181 description = usage.cl_usage
182 description = usage.cl_usage
182 crash_handler_class = IPAppCrashHandler
183 crash_handler_class = IPAppCrashHandler
183 examples = _examples
184 examples = _examples
184
185
185 flags = flags
186 flags = flags
186 aliases = aliases
187 aliases = aliases
187 classes = List()
188 classes = List()
188
189
189 interactive_shell_class = Type(
190 interactive_shell_class = Type(
190 klass=object, # use default_value otherwise which only allow subclasses.
191 klass=object, # use default_value otherwise which only allow subclasses.
191 default_value=TerminalInteractiveShell,
192 default_value=TerminalInteractiveShell,
192 help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
193 help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
193 ).tag(config=True)
194 ).tag(config=True)
194
195
195 @default('classes')
196 @default('classes')
196 def _classes_default(self):
197 def _classes_default(self):
197 """This has to be in a method, for TerminalIPythonApp to be available."""
198 """This has to be in a method, for TerminalIPythonApp to be available."""
198 return [
199 return [
199 InteractiveShellApp, # ShellApp comes before TerminalApp, because
200 InteractiveShellApp, # ShellApp comes before TerminalApp, because
200 self.__class__, # it will also affect subclasses (e.g. QtConsole)
201 self.__class__, # it will also affect subclasses (e.g. QtConsole)
201 TerminalInteractiveShell,
202 TerminalInteractiveShell,
202 HistoryManager,
203 HistoryManager,
204 MagicsManager,
203 ProfileDir,
205 ProfileDir,
204 PlainTextFormatter,
206 PlainTextFormatter,
205 IPCompleter,
207 IPCompleter,
206 ScriptMagics,
208 ScriptMagics,
207 LoggingMagics,
209 LoggingMagics,
208 StoreMagics,
210 StoreMagics,
209 ]
211 ]
210
212
211 subcommands = dict(
213 subcommands = dict(
212 profile = ("IPython.core.profileapp.ProfileApp",
214 profile = ("IPython.core.profileapp.ProfileApp",
213 "Create and manage IPython profiles."
215 "Create and manage IPython profiles."
214 ),
216 ),
215 kernel = ("ipykernel.kernelapp.IPKernelApp",
217 kernel = ("ipykernel.kernelapp.IPKernelApp",
216 "Start a kernel without an attached frontend."
218 "Start a kernel without an attached frontend."
217 ),
219 ),
218 locate=('IPython.terminal.ipapp.LocateIPythonApp',
220 locate=('IPython.terminal.ipapp.LocateIPythonApp',
219 LocateIPythonApp.description
221 LocateIPythonApp.description
220 ),
222 ),
221 history=('IPython.core.historyapp.HistoryApp',
223 history=('IPython.core.historyapp.HistoryApp',
222 "Manage the IPython history database."
224 "Manage the IPython history database."
223 ),
225 ),
224 )
226 )
225
227
226
228
227 # *do* autocreate requested profile, but don't create the config file.
229 # *do* autocreate requested profile, but don't create the config file.
228 auto_create=Bool(True)
230 auto_create=Bool(True)
229 # configurables
231 # configurables
230 quick = Bool(False,
232 quick = Bool(False,
231 help="""Start IPython quickly by skipping the loading of config files."""
233 help="""Start IPython quickly by skipping the loading of config files."""
232 ).tag(config=True)
234 ).tag(config=True)
233 @observe('quick')
235 @observe('quick')
234 def _quick_changed(self, change):
236 def _quick_changed(self, change):
235 if change['new']:
237 if change['new']:
236 self.load_config_file = lambda *a, **kw: None
238 self.load_config_file = lambda *a, **kw: None
237
239
238 display_banner = Bool(True,
240 display_banner = Bool(True,
239 help="Whether to display a banner upon starting IPython."
241 help="Whether to display a banner upon starting IPython."
240 ).tag(config=True)
242 ).tag(config=True)
241
243
242 # if there is code of files to run from the cmd line, don't interact
244 # if there is code of files to run from the cmd line, don't interact
243 # unless the --i flag (App.force_interact) is true.
245 # unless the --i flag (App.force_interact) is true.
244 force_interact = Bool(False,
246 force_interact = Bool(False,
245 help="""If a command or file is given via the command-line,
247 help="""If a command or file is given via the command-line,
246 e.g. 'ipython foo.py', start an interactive shell after executing the
248 e.g. 'ipython foo.py', start an interactive shell after executing the
247 file or command."""
249 file or command."""
248 ).tag(config=True)
250 ).tag(config=True)
249 @observe('force_interact')
251 @observe('force_interact')
250 def _force_interact_changed(self, change):
252 def _force_interact_changed(self, change):
251 if change['new']:
253 if change['new']:
252 self.interact = True
254 self.interact = True
253
255
254 @observe('file_to_run', 'code_to_run', 'module_to_run')
256 @observe('file_to_run', 'code_to_run', 'module_to_run')
255 def _file_to_run_changed(self, change):
257 def _file_to_run_changed(self, change):
256 new = change['new']
258 new = change['new']
257 if new:
259 if new:
258 self.something_to_run = True
260 self.something_to_run = True
259 if new and not self.force_interact:
261 if new and not self.force_interact:
260 self.interact = False
262 self.interact = False
261
263
262 # internal, not-configurable
264 # internal, not-configurable
263 something_to_run=Bool(False)
265 something_to_run=Bool(False)
264
266
265 @catch_config_error
267 @catch_config_error
266 def initialize(self, argv=None):
268 def initialize(self, argv=None):
267 """Do actions after construct, but before starting the app."""
269 """Do actions after construct, but before starting the app."""
268 super(TerminalIPythonApp, self).initialize(argv)
270 super(TerminalIPythonApp, self).initialize(argv)
269 if self.subapp is not None:
271 if self.subapp is not None:
270 # don't bother initializing further, starting subapp
272 # don't bother initializing further, starting subapp
271 return
273 return
272 # print self.extra_args
274 # print self.extra_args
273 if self.extra_args and not self.something_to_run:
275 if self.extra_args and not self.something_to_run:
274 self.file_to_run = self.extra_args[0]
276 self.file_to_run = self.extra_args[0]
275 self.init_path()
277 self.init_path()
276 # create the shell
278 # create the shell
277 self.init_shell()
279 self.init_shell()
278 # and draw the banner
280 # and draw the banner
279 self.init_banner()
281 self.init_banner()
280 # Now a variety of things that happen after the banner is printed.
282 # Now a variety of things that happen after the banner is printed.
281 self.init_gui_pylab()
283 self.init_gui_pylab()
282 self.init_extensions()
284 self.init_extensions()
283 self.init_code()
285 self.init_code()
284
286
285 def init_shell(self):
287 def init_shell(self):
286 """initialize the InteractiveShell instance"""
288 """initialize the InteractiveShell instance"""
287 # Create an InteractiveShell instance.
289 # Create an InteractiveShell instance.
288 # shell.display_banner should always be False for the terminal
290 # shell.display_banner should always be False for the terminal
289 # based app, because we call shell.show_banner() by hand below
291 # based app, because we call shell.show_banner() by hand below
290 # so the banner shows *before* all extension loading stuff.
292 # so the banner shows *before* all extension loading stuff.
291 self.shell = self.interactive_shell_class.instance(parent=self,
293 self.shell = self.interactive_shell_class.instance(parent=self,
292 profile_dir=self.profile_dir,
294 profile_dir=self.profile_dir,
293 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
295 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
294 self.shell.configurables.append(self)
296 self.shell.configurables.append(self)
295
297
296 def init_banner(self):
298 def init_banner(self):
297 """optionally display the banner"""
299 """optionally display the banner"""
298 if self.display_banner and self.interact:
300 if self.display_banner and self.interact:
299 self.shell.show_banner()
301 self.shell.show_banner()
300 # Make sure there is a space below the banner.
302 # Make sure there is a space below the banner.
301 if self.log_level <= logging.INFO: print()
303 if self.log_level <= logging.INFO: print()
302
304
303 def _pylab_changed(self, name, old, new):
305 def _pylab_changed(self, name, old, new):
304 """Replace --pylab='inline' with --pylab='auto'"""
306 """Replace --pylab='inline' with --pylab='auto'"""
305 if new == 'inline':
307 if new == 'inline':
306 warnings.warn("'inline' not available as pylab backend, "
308 warnings.warn("'inline' not available as pylab backend, "
307 "using 'auto' instead.")
309 "using 'auto' instead.")
308 self.pylab = 'auto'
310 self.pylab = 'auto'
309
311
310 def start(self):
312 def start(self):
311 if self.subapp is not None:
313 if self.subapp is not None:
312 return self.subapp.start()
314 return self.subapp.start()
313 # perform any prexec steps:
315 # perform any prexec steps:
314 if self.interact:
316 if self.interact:
315 self.log.debug("Starting IPython's mainloop...")
317 self.log.debug("Starting IPython's mainloop...")
316 self.shell.mainloop()
318 self.shell.mainloop()
317 else:
319 else:
318 self.log.debug("IPython not interactive...")
320 self.log.debug("IPython not interactive...")
319 if not self.shell.last_execution_succeeded:
321 if not self.shell.last_execution_succeeded:
320 sys.exit(1)
322 sys.exit(1)
321
323
322 def load_default_config(ipython_dir=None):
324 def load_default_config(ipython_dir=None):
323 """Load the default config file from the default ipython_dir.
325 """Load the default config file from the default ipython_dir.
324
326
325 This is useful for embedded shells.
327 This is useful for embedded shells.
326 """
328 """
327 if ipython_dir is None:
329 if ipython_dir is None:
328 ipython_dir = get_ipython_dir()
330 ipython_dir = get_ipython_dir()
329
331
330 profile_dir = os.path.join(ipython_dir, 'profile_default')
332 profile_dir = os.path.join(ipython_dir, 'profile_default')
331 app = TerminalIPythonApp()
333 app = TerminalIPythonApp()
332 app.config_file_paths.append(profile_dir)
334 app.config_file_paths.append(profile_dir)
333 app.load_config_file()
335 app.load_config_file()
334 return app.config
336 return app.config
335
337
336 launch_new_instance = TerminalIPythonApp.launch_instance
338 launch_new_instance = TerminalIPythonApp.launch_instance
337
339
338
340
339 if __name__ == '__main__':
341 if __name__ == '__main__':
340 launch_new_instance()
342 launch_new_instance()
@@ -1,1740 +1,1758 b''
1 ============
1 ============
2 7.x Series
2 7.x Series
3 ============
3 ============
4
4
5
5
6 .. _version 7.32:
7
8 IPython 7.32
9 ============
10
11
12 The ability to configure magics to be lazily loaded has been added to IPython.
13 See the ``ipython --help-all`` section on ``MagicsManager.lazy_magic``.
14 One can now use::
15
16 c.MagicsManger.lazy_magics = {
17 "my_magic": "slow.to.import",
18 "my_other_magic": "also.slow",
19 }
20
21 And on first use of ``%my_magic``, or corresponding cell magic, or other line magic,
22 the corresponding ``load_ext`` will be called just before trying to invoke the magic.
23
6 .. _version 7.31:
24 .. _version 7.31:
7
25
8 IPython 7.31
26 IPython 7.31
9 ============
27 ============
10
28
11 IPython 7.31 brings a couple of backports and fixes from the 8.0 branches,
29 IPython 7.31 brings a couple of backports and fixes from the 8.0 branches,
12 it is likely one of the last releases of the 7.x series, as 8.0 will probably be released
30 it is likely one of the last releases of the 7.x series, as 8.0 will probably be released
13 between this release and what would have been 7.32.
31 between this release and what would have been 7.32.
14
32
15 Please test 8.0 beta/rc releases in addition to this release.
33 Please test 8.0 beta/rc releases in addition to this release.
16
34
17 This Releases:
35 This Releases:
18 - Backport some fixes for Python 3.10 (:ghpull:`13412`)
36 - Backport some fixes for Python 3.10 (:ghpull:`13412`)
19 - use full-alpha transparency on dvipng rendered LaTeX (:ghpull:`13372`)
37 - use full-alpha transparency on dvipng rendered LaTeX (:ghpull:`13372`)
20
38
21 Many thanks to all the contributors to this release. You can find all individual
39 Many thanks to all the contributors to this release. You can find all individual
22 contributions to this milestone `on github
40 contributions to this milestone `on github
23 <https://github.com/ipython/ipython/milestone/95>`__.
41 <https://github.com/ipython/ipython/milestone/95>`__.
24
42
25 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
43 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
26 work on IPython and related libraries.
44 work on IPython and related libraries.
27
45
28
46
29 .. _version 7.30:
47 .. _version 7.30:
30
48
31 IPython 7.30
49 IPython 7.30
32 ============
50 ============
33
51
34 IPython 7.30 fixes a couple of bugs introduce in previous releases (in
52 IPython 7.30 fixes a couple of bugs introduce in previous releases (in
35 particular with respect to path handling), and introduce a few features and
53 particular with respect to path handling), and introduce a few features and
36 improvements:
54 improvements:
37
55
38 Notably we will highlight :ghpull:`13267` "Document that ``%run`` can execute
56 Notably we will highlight :ghpull:`13267` "Document that ``%run`` can execute
39 notebooks and ipy scripts.", which is the first commit of Fernando Pérez since
57 notebooks and ipy scripts.", which is the first commit of Fernando Pérez since
40 mid 2016 (IPython 5.1). If you are new to IPython, Fernando created IPython in
58 mid 2016 (IPython 5.1). If you are new to IPython, Fernando created IPython in
41 2001. The other most recent contribution of Fernando to IPython itself was
59 2001. The other most recent contribution of Fernando to IPython itself was
42 May 2018, by reviewing and merging PRs. I want to note that Fernando is still
60 May 2018, by reviewing and merging PRs. I want to note that Fernando is still
43 active but mostly as a mentor and leader of the whole Jupyter organisation, but
61 active but mostly as a mentor and leader of the whole Jupyter organisation, but
44 we're still happy to see him contribute code !
62 we're still happy to see him contribute code !
45
63
46 :ghpull:`13290` "Use sphinxify (if available) in object_inspect_mime path"
64 :ghpull:`13290` "Use sphinxify (if available) in object_inspect_mime path"
47 should allow richer Repr of docstrings when using jupyterlab inspector.
65 should allow richer Repr of docstrings when using jupyterlab inspector.
48
66
49 :ghpull:`13311` make the debugger use ``ThreadPoolExecutor`` for debugger cmdloop.
67 :ghpull:`13311` make the debugger use ``ThreadPoolExecutor`` for debugger cmdloop.
50 This should fix some issues/infinite loop, but let us know if you come across
68 This should fix some issues/infinite loop, but let us know if you come across
51 any regressions. In particular this fixes issues with `kmaork/madbg <https://github.com/kmaork/madbg>`_,
69 any regressions. In particular this fixes issues with `kmaork/madbg <https://github.com/kmaork/madbg>`_,
52 a remote debugger for IPython.
70 a remote debugger for IPython.
53
71
54 Note that this is likely the ante-penultimate release of IPython 7.x as a stable
72 Note that this is likely the ante-penultimate release of IPython 7.x as a stable
55 branch, as I hope to release IPython 8.0 as well as IPython 7.31 next
73 branch, as I hope to release IPython 8.0 as well as IPython 7.31 next
56 month/early 2022.
74 month/early 2022.
57
75
58 IPython 8.0 will drop support for Python 3.7, removed nose as a dependency, and
76 IPython 8.0 will drop support for Python 3.7, removed nose as a dependency, and
59 7.x will only get critical bug fixes with 8.x becoming the new stable. This will
77 7.x will only get critical bug fixes with 8.x becoming the new stable. This will
60 not be possible without `NumFOCUS Small Development Grants
78 not be possible without `NumFOCUS Small Development Grants
61 <https://numfocus.org/programs/small-development-grants>`_ Which allowed us to
79 <https://numfocus.org/programs/small-development-grants>`_ Which allowed us to
62 hire `Nikita Kniazev <https://github.com/Kojoley>`_ who provide Python and C++
80 hire `Nikita Kniazev <https://github.com/Kojoley>`_ who provide Python and C++
63 help and contracting work.
81 help and contracting work.
64
82
65
83
66 Many thanks to all the contributors to this release. You can find all individual
84 Many thanks to all the contributors to this release. You can find all individual
67 contributions to this milestone `on github
85 contributions to this milestone `on github
68 <https://github.com/ipython/ipython/milestone/94?closed=1>`__.
86 <https://github.com/ipython/ipython/milestone/94?closed=1>`__.
69
87
70 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
88 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
71 work on IPython and related libraries.
89 work on IPython and related libraries.
72
90
73
91
74 .. _version 7.29:
92 .. _version 7.29:
75
93
76 IPython 7.29
94 IPython 7.29
77 ============
95 ============
78
96
79
97
80 IPython 7.29 brings a couple of new functionalities to IPython and a number of bugfixes.
98 IPython 7.29 brings a couple of new functionalities to IPython and a number of bugfixes.
81 It is one of the largest recent release, relatively speaking, with close to 15 Pull Requests.
99 It is one of the largest recent release, relatively speaking, with close to 15 Pull Requests.
82
100
83
101
84 - fix an issue where base64 was returned instead of bytes when showing figures :ghpull:`13162`
102 - fix an issue where base64 was returned instead of bytes when showing figures :ghpull:`13162`
85 - fix compatibility with PyQt6, PySide 6 :ghpull:`13172`. This may be of
103 - fix compatibility with PyQt6, PySide 6 :ghpull:`13172`. This may be of
86 interest if you are running on Apple Silicon as only qt6.2+ is natively
104 interest if you are running on Apple Silicon as only qt6.2+ is natively
87 compatible.
105 compatible.
88 - fix matplotlib qtagg eventloop :ghpull:`13179`
106 - fix matplotlib qtagg eventloop :ghpull:`13179`
89 - Multiple docs fixes, typos, ... etc.
107 - Multiple docs fixes, typos, ... etc.
90 - Debugger will now exit by default on SigInt :ghpull:`13218`, this will be
108 - Debugger will now exit by default on SigInt :ghpull:`13218`, this will be
91 useful in notebook/lab if you forgot to exit the debugger. "Interrupt Kernel"
109 useful in notebook/lab if you forgot to exit the debugger. "Interrupt Kernel"
92 will now exist the debugger.
110 will now exist the debugger.
93
111
94 It give Pdb the ability to skip code in decorators. If functions contain a
112 It give Pdb the ability to skip code in decorators. If functions contain a
95 special value names ``__debuggerskip__ = True|False``, the function will not be
113 special value names ``__debuggerskip__ = True|False``, the function will not be
96 stepped into, and Pdb will step into lower frames only if the value is set to
114 stepped into, and Pdb will step into lower frames only if the value is set to
97 ``False``. The exact behavior is still likely to have corner cases and will be
115 ``False``. The exact behavior is still likely to have corner cases and will be
98 refined in subsequent releases. Feedback welcome. See the debugger module
116 refined in subsequent releases. Feedback welcome. See the debugger module
99 documentation for more info. Thanks to the `D. E. Shaw
117 documentation for more info. Thanks to the `D. E. Shaw
100 group <https://deshaw.com/>`__ for funding this feature.
118 group <https://deshaw.com/>`__ for funding this feature.
101
119
102 The main branch of IPython is receiving a number of changes as we received a
120 The main branch of IPython is receiving a number of changes as we received a
103 `NumFOCUS SDG <https://numfocus.org/programs/small-development-grants>`__
121 `NumFOCUS SDG <https://numfocus.org/programs/small-development-grants>`__
104 ($4800), to help us finish replacing ``nose`` by ``pytest``, and make IPython
122 ($4800), to help us finish replacing ``nose`` by ``pytest``, and make IPython
105 future proof with an 8.0 release.
123 future proof with an 8.0 release.
106
124
107
125
108 Many thanks to all the contributors to this release. You can find all individual
126 Many thanks to all the contributors to this release. You can find all individual
109 contributions to this milestone `on github
127 contributions to this milestone `on github
110 <https://github.com/ipython/ipython/milestone/93>`__.
128 <https://github.com/ipython/ipython/milestone/93>`__.
111
129
112 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
130 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
113 work on IPython and related libraries.
131 work on IPython and related libraries.
114
132
115
133
116 .. _version 7.28:
134 .. _version 7.28:
117
135
118 IPython 7.28
136 IPython 7.28
119 ============
137 ============
120
138
121
139
122 IPython 7.28 is again a minor release that mostly bring bugfixes, and couple of
140 IPython 7.28 is again a minor release that mostly bring bugfixes, and couple of
123 improvement. Many thanks to MrMino, who again did all the work this month, and
141 improvement. Many thanks to MrMino, who again did all the work this month, and
124 made a number of documentation improvements.
142 made a number of documentation improvements.
125
143
126 Here is a non-exhaustive list of changes,
144 Here is a non-exhaustive list of changes,
127
145
128 Fixes:
146 Fixes:
129
147
130 - async with doesn't allow newlines :ghpull:`13090`
148 - async with doesn't allow newlines :ghpull:`13090`
131 - Dynamically changing to vi mode via %config magic) :ghpull:`13091`
149 - Dynamically changing to vi mode via %config magic) :ghpull:`13091`
132
150
133 Virtualenv handling fixes:
151 Virtualenv handling fixes:
134
152
135 - init_virtualenv now uses Pathlib :ghpull:`12548`
153 - init_virtualenv now uses Pathlib :ghpull:`12548`
136 - Fix Improper path comparison of virtualenv directories :ghpull:`13140`
154 - Fix Improper path comparison of virtualenv directories :ghpull:`13140`
137 - Fix virtual environment user warning for lower case pathes :ghpull:`13094`
155 - Fix virtual environment user warning for lower case pathes :ghpull:`13094`
138 - Adapt to all sorts of drive names for cygwin :ghpull:`13153`
156 - Adapt to all sorts of drive names for cygwin :ghpull:`13153`
139
157
140 New Features:
158 New Features:
141
159
142 - enable autoplay in embed YouTube player :ghpull:`13133`
160 - enable autoplay in embed YouTube player :ghpull:`13133`
143
161
144 Documentation:
162 Documentation:
145
163
146 - Fix formatting for the core.interactiveshell documentation :ghpull:`13118`
164 - Fix formatting for the core.interactiveshell documentation :ghpull:`13118`
147 - Fix broken ipyparallel's refs :ghpull:`13138`
165 - Fix broken ipyparallel's refs :ghpull:`13138`
148 - Improve formatting of %time documentation :ghpull:`13125`
166 - Improve formatting of %time documentation :ghpull:`13125`
149 - Reword the YouTubeVideo autoplay WN :ghpull:`13147`
167 - Reword the YouTubeVideo autoplay WN :ghpull:`13147`
150
168
151
169
152 Highlighted features
170 Highlighted features
153 --------------------
171 --------------------
154
172
155
173
156 ``YouTubeVideo`` autoplay and the ability to add extra attributes to ``IFrame``
174 ``YouTubeVideo`` autoplay and the ability to add extra attributes to ``IFrame``
157 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
158
176
159 You can add any extra attributes to the ``<iframe>`` tag using the new
177 You can add any extra attributes to the ``<iframe>`` tag using the new
160 ``extras`` argument in the ``IFrame`` class. For example::
178 ``extras`` argument in the ``IFrame`` class. For example::
161
179
162 In [1]: from IPython.display import IFrame
180 In [1]: from IPython.display import IFrame
163
181
164 In [2]: IFrame(src="src", width=300, height=300, extras=['loading="eager"'])
182 In [2]: IFrame(src="src", width=300, height=300, extras=['loading="eager"'])
165
183
166 The above cells will result in the following HTML code being displayed in a
184 The above cells will result in the following HTML code being displayed in a
167 notebook::
185 notebook::
168
186
169 <iframe
187 <iframe
170 width="300"
188 width="300"
171 height="300"
189 height="300"
172 src="src"
190 src="src"
173 frameborder="0"
191 frameborder="0"
174 allowfullscreen
192 allowfullscreen
175 loading="eager"
193 loading="eager"
176 ></iframe>
194 ></iframe>
177
195
178 Related to the above, the ``YouTubeVideo`` class now takes an
196 Related to the above, the ``YouTubeVideo`` class now takes an
179 ``allow_autoplay`` flag, which sets up the iframe of the embedded YouTube video
197 ``allow_autoplay`` flag, which sets up the iframe of the embedded YouTube video
180 such that it allows autoplay.
198 such that it allows autoplay.
181
199
182 .. note::
200 .. note::
183 Whether this works depends on the autoplay policy of the browser rendering
201 Whether this works depends on the autoplay policy of the browser rendering
184 the HTML allowing it. It also could get blocked by some browser extensions.
202 the HTML allowing it. It also could get blocked by some browser extensions.
185
203
186 Try it out!
204 Try it out!
187 ::
205 ::
188
206
189 In [1]: from IPython.display import YouTubeVideo
207 In [1]: from IPython.display import YouTubeVideo
190
208
191 In [2]: YouTubeVideo("dQw4w9WgXcQ", allow_autoplay=True)
209 In [2]: YouTubeVideo("dQw4w9WgXcQ", allow_autoplay=True)
192
210
193
211
194
212
195 Thanks
213 Thanks
196 ------
214 ------
197
215
198 Many thanks to all the contributors to this release. You can find all individual
216 Many thanks to all the contributors to this release. You can find all individual
199 contributions to this milestone `on github
217 contributions to this milestone `on github
200 <https://github.com/ipython/ipython/milestone/92>`__.
218 <https://github.com/ipython/ipython/milestone/92>`__.
201
219
202 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
220 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
203 work on IPython and related libraries.
221 work on IPython and related libraries.
204
222
205
223
206 .. _version 7.27:
224 .. _version 7.27:
207
225
208 IPython 7.27
226 IPython 7.27
209 ============
227 ============
210
228
211 IPython 7.27 is a minor release that fixes a couple of issues and compatibility.
229 IPython 7.27 is a minor release that fixes a couple of issues and compatibility.
212
230
213 - Add support for GTK4 :ghpull:`131011`
231 - Add support for GTK4 :ghpull:`131011`
214 - Add support for Qt6 :ghpull:`13085`
232 - Add support for Qt6 :ghpull:`13085`
215 - Fix an issue with pip magic on windows :ghpull:`13093`
233 - Fix an issue with pip magic on windows :ghpull:`13093`
216
234
217 Thanks
235 Thanks
218 ------
236 ------
219
237
220 Many thanks to all the contributors to this release. You can find all individual
238 Many thanks to all the contributors to this release. You can find all individual
221 contributions to this milestone `on github
239 contributions to this milestone `on github
222 <https://github.com/ipython/ipython/milestone/91>`__.
240 <https://github.com/ipython/ipython/milestone/91>`__.
223
241
224 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
242 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
225 work on IPython and related libraries.
243 work on IPython and related libraries.
226
244
227 .. _version 7.26:
245 .. _version 7.26:
228
246
229 IPython 7.26
247 IPython 7.26
230 ============
248 ============
231
249
232 IPython 7.26 is a minor release that fixes a couple of issues, updates in API
250 IPython 7.26 is a minor release that fixes a couple of issues, updates in API
233 and Copyright/Licenses issues around various part of the codebase.
251 and Copyright/Licenses issues around various part of the codebase.
234
252
235 We'll highlight `this issue <https://github.com/ipython/ipython/issues/13039>`
253 We'll highlight `this issue <https://github.com/ipython/ipython/issues/13039>`
236 pointing out we were including and refereeing to code from Stack Overflow which
254 pointing out we were including and refereeing to code from Stack Overflow which
237 was CC-BY-SA, hence incompatible with the BSD license of IPython. This lead us
255 was CC-BY-SA, hence incompatible with the BSD license of IPython. This lead us
238 to a rewriting of the corresponding logic which in our case was done in a more
256 to a rewriting of the corresponding logic which in our case was done in a more
239 efficient way (in our case we were searching string prefixes instead of full
257 efficient way (in our case we were searching string prefixes instead of full
240 strings).
258 strings).
241
259
242 You will notice also a number of documentation improvements and cleanup.
260 You will notice also a number of documentation improvements and cleanup.
243
261
244 Of particular interest are the following Pull-requests:
262 Of particular interest are the following Pull-requests:
245
263
246
264
247 - The IPython directive now uses Sphinx logging for warnings. :ghpull:`13030`.
265 - The IPython directive now uses Sphinx logging for warnings. :ghpull:`13030`.
248 - Add expiry days option to pastebin magic and change http protocol to https.
266 - Add expiry days option to pastebin magic and change http protocol to https.
249 :ghpull:`13056`
267 :ghpull:`13056`
250 - Make Ipython.utils.timing work with jupyterlite :ghpull:`13050`.
268 - Make Ipython.utils.timing work with jupyterlite :ghpull:`13050`.
251
269
252 Pastebin magic expiry days option
270 Pastebin magic expiry days option
253 ---------------------------------
271 ---------------------------------
254
272
255 The Pastebin magic now has ``-e`` option to determine
273 The Pastebin magic now has ``-e`` option to determine
256 the number of days for paste expiration. For example
274 the number of days for paste expiration. For example
257 the paste that created with ``%pastebin -e 20 1`` magic will
275 the paste that created with ``%pastebin -e 20 1`` magic will
258 be available for next 20 days.
276 be available for next 20 days.
259
277
260
278
261
279
262
280
263
281
264 Thanks
282 Thanks
265 ------
283 ------
266
284
267 Many thanks to all the contributors to this release and in particular MrMino who
285 Many thanks to all the contributors to this release and in particular MrMino who
268 is doing most of the work those days. You can find all individual contributions
286 is doing most of the work those days. You can find all individual contributions
269 to this milestone `on github <https://github.com/ipython/ipython/milestone/90>`__.
287 to this milestone `on github <https://github.com/ipython/ipython/milestone/90>`__.
270
288
271 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
289 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
272 work on IPython and related libraries.
290 work on IPython and related libraries.
273
291
274
292
275 .. _version 7.25:
293 .. _version 7.25:
276
294
277 IPython 7.25
295 IPython 7.25
278 ============
296 ============
279
297
280 IPython 7.25 is a minor release that contains a single bugfix, which is highly
298 IPython 7.25 is a minor release that contains a single bugfix, which is highly
281 recommended for all users of ipdb, ipython debugger %debug magic and similar.
299 recommended for all users of ipdb, ipython debugger %debug magic and similar.
282
300
283 Issuing commands like ``where`` from within the debugger would reset the
301 Issuing commands like ``where`` from within the debugger would reset the
284 local variables changes made by the user. It is interesting to look at the root
302 local variables changes made by the user. It is interesting to look at the root
285 cause of the issue as accessing an attribute (``frame.f_locals``) would trigger
303 cause of the issue as accessing an attribute (``frame.f_locals``) would trigger
286 this side effects.
304 this side effects.
287
305
288 Thanks in particular to the patience from the reporters at D.E. Shaw for their
306 Thanks in particular to the patience from the reporters at D.E. Shaw for their
289 initial bug report that was due to a similar coding oversight in an extension,
307 initial bug report that was due to a similar coding oversight in an extension,
290 and who took time to debug and narrow down the problem.
308 and who took time to debug and narrow down the problem.
291
309
292 Thanks
310 Thanks
293 ------
311 ------
294
312
295 Many thanks to all the contributors to this release you can find all individual
313 Many thanks to all the contributors to this release you can find all individual
296 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/89>`__.
314 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/89>`__.
297
315
298 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
316 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
299 work on IPython and related libraries.
317 work on IPython and related libraries.
300
318
301
319
302 .. _version 7.24:
320 .. _version 7.24:
303
321
304 IPython 7.24
322 IPython 7.24
305 ============
323 ============
306
324
307 Third release of IPython for 2021, mostly containing bug fixes. A couple of not
325 Third release of IPython for 2021, mostly containing bug fixes. A couple of not
308 typical updates:
326 typical updates:
309
327
310 Misc
328 Misc
311 ----
329 ----
312
330
313
331
314 - Fix an issue where ``%recall`` would both succeeded and print an error message
332 - Fix an issue where ``%recall`` would both succeeded and print an error message
315 it failed. :ghpull:`12952`
333 it failed. :ghpull:`12952`
316 - Drop support for NumPy 1.16 – practically has no effect beyond indicating in
334 - Drop support for NumPy 1.16 – practically has no effect beyond indicating in
317 package metadata that we do not support it. :ghpull:`12937`
335 package metadata that we do not support it. :ghpull:`12937`
318
336
319 Debugger improvements
337 Debugger improvements
320 ---------------------
338 ---------------------
321
339
322 The debugger (and ``%debug`` magic) have been improved and can skip or hide frames
340 The debugger (and ``%debug`` magic) have been improved and can skip or hide frames
323 originating from files that are not writable to the user, as these are less
341 originating from files that are not writable to the user, as these are less
324 likely to be the source of errors, or be part of system files this can be a useful
342 likely to be the source of errors, or be part of system files this can be a useful
325 addition when debugging long errors.
343 addition when debugging long errors.
326
344
327 In addition to the global ``skip_hidden True|False`` command, the debugger has
345 In addition to the global ``skip_hidden True|False`` command, the debugger has
328 gained finer grained control of predicates as to whether to a frame should be
346 gained finer grained control of predicates as to whether to a frame should be
329 considered hidden. So far 3 predicates are available :
347 considered hidden. So far 3 predicates are available :
330
348
331 - ``tbhide``: frames containing the local variable ``__tracebackhide__`` set to
349 - ``tbhide``: frames containing the local variable ``__tracebackhide__`` set to
332 True.
350 True.
333 - ``readonly``: frames originating from readonly files, set to False.
351 - ``readonly``: frames originating from readonly files, set to False.
334 - ``ipython_internal``: frames that are likely to be from IPython internal
352 - ``ipython_internal``: frames that are likely to be from IPython internal
335 code, set to True.
353 code, set to True.
336
354
337 You can toggle individual predicates during a session with
355 You can toggle individual predicates during a session with
338
356
339 .. code-block::
357 .. code-block::
340
358
341 ipdb> skip_predicates readonly True
359 ipdb> skip_predicates readonly True
342
360
343 Read-only files will now be considered hidden frames.
361 Read-only files will now be considered hidden frames.
344
362
345
363
346 You can call ``skip_predicates`` without arguments to see the states of current
364 You can call ``skip_predicates`` without arguments to see the states of current
347 predicates:
365 predicates:
348
366
349 .. code-block::
367 .. code-block::
350
368
351 ipdb> skip_predicates
369 ipdb> skip_predicates
352 current predicates:
370 current predicates:
353 tbhide : True
371 tbhide : True
354 readonly : False
372 readonly : False
355 ipython_internal : True
373 ipython_internal : True
356
374
357 If all predicates are set to ``False``, ``skip_hidden`` will practically have
375 If all predicates are set to ``False``, ``skip_hidden`` will practically have
358 no effect. We attempt to warn you when all predicates are False.
376 no effect. We attempt to warn you when all predicates are False.
359
377
360 Note that the ``readonly`` predicate may increase disk access as we check for
378 Note that the ``readonly`` predicate may increase disk access as we check for
361 file access permission for all frames on many command invocation, but is usually
379 file access permission for all frames on many command invocation, but is usually
362 cached by operating systems. Let us know if you encounter any issues.
380 cached by operating systems. Let us know if you encounter any issues.
363
381
364 As the IPython debugger does not use the traitlets infrastructure for
382 As the IPython debugger does not use the traitlets infrastructure for
365 configuration, by editing your ``.pdbrc`` files and appending commands you would
383 configuration, by editing your ``.pdbrc`` files and appending commands you would
366 like to be executed just before entering the interactive prompt. For example:
384 like to be executed just before entering the interactive prompt. For example:
367
385
368
386
369 .. code::
387 .. code::
370
388
371 # file : ~/.pdbrc
389 # file : ~/.pdbrc
372 skip_predicates readonly True
390 skip_predicates readonly True
373 skip_predicates tbhide False
391 skip_predicates tbhide False
374
392
375 Will hide read only frames by default and show frames marked with
393 Will hide read only frames by default and show frames marked with
376 ``__tracebackhide__``.
394 ``__tracebackhide__``.
377
395
378
396
379
397
380
398
381 Thanks
399 Thanks
382 ------
400 ------
383
401
384 Many thanks to all the contributors to this release you can find all individual
402 Many thanks to all the contributors to this release you can find all individual
385 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/87>`__.
403 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/87>`__.
386
404
387 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
405 Thanks as well to the `D. E. Shaw group <https://deshaw.com/>`__ for sponsoring
388 work on IPython and related libraries, in particular above mentioned
406 work on IPython and related libraries, in particular above mentioned
389 improvements to the debugger.
407 improvements to the debugger.
390
408
391
409
392
410
393
411
394 .. _version 7.23:
412 .. _version 7.23:
395
413
396 IPython 7.23 and 7.23.1
414 IPython 7.23 and 7.23.1
397 =======================
415 =======================
398
416
399
417
400 Third release of IPython for 2021, mostly containing bug fixes. A couple of not
418 Third release of IPython for 2021, mostly containing bug fixes. A couple of not
401 typical updates:
419 typical updates:
402
420
403 - We moved to GitHub actions away from Travis-CI, the transition may not be
421 - We moved to GitHub actions away from Travis-CI, the transition may not be
404 100% complete (not testing on nightly anymore), but as we ran out of
422 100% complete (not testing on nightly anymore), but as we ran out of
405 Travis-Ci hours on the IPython organisation that was a necessary step.
423 Travis-Ci hours on the IPython organisation that was a necessary step.
406 :ghpull:`12900`.
424 :ghpull:`12900`.
407
425
408 - We have a new dependency: ``matplotlib-inline``, which try to extract
426 - We have a new dependency: ``matplotlib-inline``, which try to extract
409 matplotlib inline backend specific behavior. It is available on PyPI and
427 matplotlib inline backend specific behavior. It is available on PyPI and
410 conda-forge thus should not be a problem to upgrade to this version. If you
428 conda-forge thus should not be a problem to upgrade to this version. If you
411 are a package maintainer that might be an extra dependency to package first.
429 are a package maintainer that might be an extra dependency to package first.
412 :ghpull:`12817` (IPython 7.23.1 fix a typo that made this change fail)
430 :ghpull:`12817` (IPython 7.23.1 fix a typo that made this change fail)
413
431
414 In the addition/new feature category, ``display()`` now have a ``clear=True``
432 In the addition/new feature category, ``display()`` now have a ``clear=True``
415 option to clear the display if any further outputs arrives, allowing users to
433 option to clear the display if any further outputs arrives, allowing users to
416 avoid having to use ``clear_output()`` directly. :ghpull:`12823`.
434 avoid having to use ``clear_output()`` directly. :ghpull:`12823`.
417
435
418 In bug fixes category, this release fix an issue when printing tracebacks
436 In bug fixes category, this release fix an issue when printing tracebacks
419 containing Unicode characters :ghpull:`12758`.
437 containing Unicode characters :ghpull:`12758`.
420
438
421 In code cleanup category :ghpull:`12932` remove usage of some deprecated
439 In code cleanup category :ghpull:`12932` remove usage of some deprecated
422 functionality for compatibility with Python 3.10.
440 functionality for compatibility with Python 3.10.
423
441
424
442
425
443
426 Thanks
444 Thanks
427 ------
445 ------
428
446
429 Many thanks to all the contributors to this release you can find all individual
447 Many thanks to all the contributors to this release you can find all individual
430 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/86>`__.
448 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/86>`__.
431 In particular MrMino for responding to almost all new issues, and triaging many
449 In particular MrMino for responding to almost all new issues, and triaging many
432 of the old ones, as well as takluyver, minrk, willingc for reacting quikly when
450 of the old ones, as well as takluyver, minrk, willingc for reacting quikly when
433 we ran out of CI Hours.
451 we ran out of CI Hours.
434
452
435 Thanks as well to organisations, QuantStack (martinRenou and SylvainCorlay) for
453 Thanks as well to organisations, QuantStack (martinRenou and SylvainCorlay) for
436 extracting matplotlib inline backend into its own package, and the `D. E. Shaw group
454 extracting matplotlib inline backend into its own package, and the `D. E. Shaw group
437 <https://deshaw.com/>`__ for sponsoring work on IPython and related libraries.
455 <https://deshaw.com/>`__ for sponsoring work on IPython and related libraries.
438
456
439
457
440 .. _version 7.22:
458 .. _version 7.22:
441
459
442 IPython 7.22
460 IPython 7.22
443 ============
461 ============
444
462
445 Second release of IPython for 2021, mostly containing bug fixes. Here is a quick
463 Second release of IPython for 2021, mostly containing bug fixes. Here is a quick
446 rundown of the few changes.
464 rundown of the few changes.
447
465
448 - Fix some ``sys.excepthook`` shenanigan when embedding with qt, recommended if
466 - Fix some ``sys.excepthook`` shenanigan when embedding with qt, recommended if
449 you – for example – use `napari <https://napari.org>`__. :ghpull:`12842`.
467 you – for example – use `napari <https://napari.org>`__. :ghpull:`12842`.
450 - Fix bug when using the new ipdb ``%context`` magic :ghpull:`12844`
468 - Fix bug when using the new ipdb ``%context`` magic :ghpull:`12844`
451 - Couples of deprecation cleanup :ghpull:`12868`
469 - Couples of deprecation cleanup :ghpull:`12868`
452 - Update for new dpast.com api if you use the ``%pastbin`` magic. :ghpull:`12712`
470 - Update for new dpast.com api if you use the ``%pastbin`` magic. :ghpull:`12712`
453 - Remove support for numpy before 1.16. :ghpull:`12836`
471 - Remove support for numpy before 1.16. :ghpull:`12836`
454
472
455
473
456 Thanks
474 Thanks
457 ------
475 ------
458
476
459 We have a new team member that you should see more often on the IPython
477 We have a new team member that you should see more often on the IPython
460 repository, Błażej Michalik (@MrMino) have been doing regular contributions to
478 repository, Błażej Michalik (@MrMino) have been doing regular contributions to
461 IPython, and spent time replying to many issues and guiding new users to the
479 IPython, and spent time replying to many issues and guiding new users to the
462 codebase; they now have triage permissions to the IPython repository and we'll
480 codebase; they now have triage permissions to the IPython repository and we'll
463 work toward giving them more permission in the future.
481 work toward giving them more permission in the future.
464
482
465 Many thanks to all the contributors to this release you can find all individual
483 Many thanks to all the contributors to this release you can find all individual
466 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/84>`__.
484 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/84>`__.
467
485
468 Thanks as well to organisations, QuantStack for working on debugger
486 Thanks as well to organisations, QuantStack for working on debugger
469 compatibility for Xeus_python, and the `D. E. Shaw group
487 compatibility for Xeus_python, and the `D. E. Shaw group
470 <https://deshaw.com/>`__ for sponsoring work on IPython and related libraries.
488 <https://deshaw.com/>`__ for sponsoring work on IPython and related libraries.
471
489
472 .. _version 721:
490 .. _version 721:
473
491
474 IPython 7.21
492 IPython 7.21
475 ============
493 ============
476
494
477 IPython 7.21 is the first release we have back on schedule of one release every
495 IPython 7.21 is the first release we have back on schedule of one release every
478 month; it contains a number of minor fixes and improvements, notably, the new
496 month; it contains a number of minor fixes and improvements, notably, the new
479 context command for ipdb
497 context command for ipdb
480
498
481
499
482 New "context" command in ipdb
500 New "context" command in ipdb
483 -----------------------------
501 -----------------------------
484
502
485 It is now possible to change the number of lines shown in the backtrace
503 It is now possible to change the number of lines shown in the backtrace
486 information in ipdb using "context" command. :ghpull:`12826`
504 information in ipdb using "context" command. :ghpull:`12826`
487
505
488 (thanks @MrMino, there are other improvement from them on master).
506 (thanks @MrMino, there are other improvement from them on master).
489
507
490 Other notable changes in IPython 7.21
508 Other notable changes in IPython 7.21
491 -------------------------------------
509 -------------------------------------
492
510
493 - Fix some issues on new osx-arm64 :ghpull:`12804`, :ghpull:`12807`.
511 - Fix some issues on new osx-arm64 :ghpull:`12804`, :ghpull:`12807`.
494 - Compatibility with Xeus-Python for debugger protocol, :ghpull:`12809`
512 - Compatibility with Xeus-Python for debugger protocol, :ghpull:`12809`
495 - Misc docs fixes for compatibility and uniformity with Numpydoc.
513 - Misc docs fixes for compatibility and uniformity with Numpydoc.
496 :ghpull:`12824`
514 :ghpull:`12824`
497
515
498
516
499 Thanks
517 Thanks
500 ------
518 ------
501
519
502 Many thanks to all the contributors to this release you can find all individual
520 Many thanks to all the contributors to this release you can find all individual
503 contribution to this milestone `on github <https://github.com/ipython/ipython/milestone/83>`__.
521 contribution to this milestone `on github <https://github.com/ipython/ipython/milestone/83>`__.
504
522
505
523
506 .. _version 720:
524 .. _version 720:
507
525
508 IPython 7.20
526 IPython 7.20
509 ============
527 ============
510
528
511 IPython 7.20 is the accumulation of 3 month of work on IPython, spacing between
529 IPython 7.20 is the accumulation of 3 month of work on IPython, spacing between
512 IPython release have been increased from the usual once a month for various
530 IPython release have been increased from the usual once a month for various
513 reason.
531 reason.
514
532
515 - Mainly as I'm too busy and the effectively sole maintainer, and
533 - Mainly as I'm too busy and the effectively sole maintainer, and
516 - Second because not much changes happened before mid December.
534 - Second because not much changes happened before mid December.
517
535
518 The main driver for this release was the new version of Jedi 0.18 breaking API;
536 The main driver for this release was the new version of Jedi 0.18 breaking API;
519 which was taken care of in the master branch early in 2020 but not in 7.x as I
537 which was taken care of in the master branch early in 2020 but not in 7.x as I
520 though that by now 8.0 would be out.
538 though that by now 8.0 would be out.
521
539
522 The inclusion of a resolver in pip did not help and actually made things worse.
540 The inclusion of a resolver in pip did not help and actually made things worse.
523 If usually I would have simply pinned Jedi to ``<0.18``; this is not a solution
541 If usually I would have simply pinned Jedi to ``<0.18``; this is not a solution
524 anymore as now pip is free to install Jedi 0.18, and downgrade IPython.
542 anymore as now pip is free to install Jedi 0.18, and downgrade IPython.
525
543
526 I'll do my best to keep the regular release, but as the 8.0-dev branch and 7.x
544 I'll do my best to keep the regular release, but as the 8.0-dev branch and 7.x
527 are starting to diverge this is becoming difficult in particular with my limited
545 are starting to diverge this is becoming difficult in particular with my limited
528 time, so if you have any cycles to spare I'll appreciate your help to respond to
546 time, so if you have any cycles to spare I'll appreciate your help to respond to
529 issues and pushing 8.0 forward.
547 issues and pushing 8.0 forward.
530
548
531 Here are thus some of the changes for IPython 7.20.
549 Here are thus some of the changes for IPython 7.20.
532
550
533 - Support for PyQt5 >= 5.11 :ghpull:`12715`
551 - Support for PyQt5 >= 5.11 :ghpull:`12715`
534 - ``%reset`` remove imports more agressively :ghpull:`12718`
552 - ``%reset`` remove imports more agressively :ghpull:`12718`
535 - fix the ``%conda`` magic :ghpull:`12739`
553 - fix the ``%conda`` magic :ghpull:`12739`
536 - compatibility with Jedi 0.18, and bump minimum Jedi version. :ghpull:`12793`
554 - compatibility with Jedi 0.18, and bump minimum Jedi version. :ghpull:`12793`
537
555
538
556
539 .. _version 719:
557 .. _version 719:
540
558
541 IPython 7.19
559 IPython 7.19
542 ============
560 ============
543
561
544 IPython 7.19 accumulative two month of works, bug fixes and improvements, there
562 IPython 7.19 accumulative two month of works, bug fixes and improvements, there
545 was exceptionally no release last month.
563 was exceptionally no release last month.
546
564
547 - Fix to restore the ability to specify more than one extension using command
565 - Fix to restore the ability to specify more than one extension using command
548 line flags when using traitlets 5.0 :ghpull:`12543`
566 line flags when using traitlets 5.0 :ghpull:`12543`
549 - Docs docs formatting that make the install commands work on zsh
567 - Docs docs formatting that make the install commands work on zsh
550 :ghpull:`12587`
568 :ghpull:`12587`
551 - Always display the last frame in tracebacks even if hidden with
569 - Always display the last frame in tracebacks even if hidden with
552 ``__tracebackhide__`` :ghpull:`12601`
570 ``__tracebackhide__`` :ghpull:`12601`
553 - Avoid an issue where a callback can be registered multiple times.
571 - Avoid an issue where a callback can be registered multiple times.
554 :ghpull:`12625`
572 :ghpull:`12625`
555 - Avoid an issue in debugger mode where frames changes could be lost.
573 - Avoid an issue in debugger mode where frames changes could be lost.
556 :ghpull:`12627`
574 :ghpull:`12627`
557
575
558 - Never hide the frames that invoke a debugger, even if marked as hidden by
576 - Never hide the frames that invoke a debugger, even if marked as hidden by
559 ``__tracebackhide__`` :ghpull:`12631`
577 ``__tracebackhide__`` :ghpull:`12631`
560 - Fix calling the debugger in a recursive manner :ghpull:`12659`
578 - Fix calling the debugger in a recursive manner :ghpull:`12659`
561
579
562
580
563 A number of code changes have landed on master and we are getting close to
581 A number of code changes have landed on master and we are getting close to
564 enough new features and codebase improvement that a 8.0 start to make sens.
582 enough new features and codebase improvement that a 8.0 start to make sens.
565 For downstream packages, please start working on migrating downstream testing
583 For downstream packages, please start working on migrating downstream testing
566 away from iptest and using pytest, as nose will not work on Python 3.10 and we
584 away from iptest and using pytest, as nose will not work on Python 3.10 and we
567 will likely start removing it as a dependency for testing.
585 will likely start removing it as a dependency for testing.
568
586
569 .. _version 718:
587 .. _version 718:
570
588
571 IPython 7.18
589 IPython 7.18
572 ============
590 ============
573
591
574 IPython 7.18 is a minor release that mostly contains bugfixes.
592 IPython 7.18 is a minor release that mostly contains bugfixes.
575
593
576 - ``CRLF`` is now handled by magics my default; solving some issues due to copy
594 - ``CRLF`` is now handled by magics my default; solving some issues due to copy
577 pasting on windows. :ghpull:`12475`
595 pasting on windows. :ghpull:`12475`
578
596
579 - Requiring pexpect ``>=4.3`` as we are Python 3.7+ only and earlier version of
597 - Requiring pexpect ``>=4.3`` as we are Python 3.7+ only and earlier version of
580 pexpect will be incompatible. :ghpull:`12510`
598 pexpect will be incompatible. :ghpull:`12510`
581
599
582 - Minimum jedi version is now 0.16. :ghpull:`12488`
600 - Minimum jedi version is now 0.16. :ghpull:`12488`
583
601
584
602
585
603
586 .. _version 717:
604 .. _version 717:
587
605
588 IPython 7.17
606 IPython 7.17
589 ============
607 ============
590
608
591 IPython 7.17 brings a couple of new improvements to API and a couple of user
609 IPython 7.17 brings a couple of new improvements to API and a couple of user
592 facing changes to make the terminal experience more user friendly.
610 facing changes to make the terminal experience more user friendly.
593
611
594 :ghpull:`12407` introduces the ability to pass extra argument to the IPython
612 :ghpull:`12407` introduces the ability to pass extra argument to the IPython
595 debugger class; this is to help a new project from ``kmaork``
613 debugger class; this is to help a new project from ``kmaork``
596 (https://github.com/kmaork/madbg) to feature a fully remote debugger.
614 (https://github.com/kmaork/madbg) to feature a fully remote debugger.
597
615
598 :ghpull:`12410` finally remove support for 3.6, while the codebase is still
616 :ghpull:`12410` finally remove support for 3.6, while the codebase is still
599 technically compatible; IPython will not install on Python 3.6.
617 technically compatible; IPython will not install on Python 3.6.
600
618
601 lots of work on the debugger and hidden frames from ``@impact27`` in
619 lots of work on the debugger and hidden frames from ``@impact27`` in
602 :ghpull:`12437`, :ghpull:`12445`, :ghpull:`12460` and in particular
620 :ghpull:`12437`, :ghpull:`12445`, :ghpull:`12460` and in particular
603 :ghpull:`12453` which make the debug magic more robust at handling spaces.
621 :ghpull:`12453` which make the debug magic more robust at handling spaces.
604
622
605 Biggest API addition is code transformation which is done before code execution;
623 Biggest API addition is code transformation which is done before code execution;
606 IPython allows a number of hooks to catch non-valid Python syntax (magic, prompt
624 IPython allows a number of hooks to catch non-valid Python syntax (magic, prompt
607 stripping...etc). Transformers are usually called many time; typically:
625 stripping...etc). Transformers are usually called many time; typically:
608
626
609 - When trying to figure out whether the code is complete and valid (should we
627 - When trying to figure out whether the code is complete and valid (should we
610 insert a new line or execute ?)
628 insert a new line or execute ?)
611 - During actual code execution pass before giving the code to Python's
629 - During actual code execution pass before giving the code to Python's
612 ``exec``.
630 ``exec``.
613
631
614 This lead to issues when transformer might have had side effects; or do external
632 This lead to issues when transformer might have had side effects; or do external
615 queries. Starting with IPython 7.17 you can expect your transformer to be called
633 queries. Starting with IPython 7.17 you can expect your transformer to be called
616 less time.
634 less time.
617
635
618 Input transformers are now called only once in the execution path of
636 Input transformers are now called only once in the execution path of
619 `InteractiveShell`, allowing to register transformer that potentially have side
637 `InteractiveShell`, allowing to register transformer that potentially have side
620 effects (note that this is not recommended). Internal methods `should_run_async`, and
638 effects (note that this is not recommended). Internal methods `should_run_async`, and
621 `run_cell_async` now take a recommended optional `transformed_cell`, and
639 `run_cell_async` now take a recommended optional `transformed_cell`, and
622 `preprocessing_exc_tuple` parameters that will become mandatory at some point in
640 `preprocessing_exc_tuple` parameters that will become mandatory at some point in
623 the future; that is to say cells need to be explicitly transformed to be valid
641 the future; that is to say cells need to be explicitly transformed to be valid
624 Python syntax ahead of trying to run them. :ghpull:`12440`;
642 Python syntax ahead of trying to run them. :ghpull:`12440`;
625
643
626 ``input_transformers`` can now also have an attribute ``has_side_effects`` set
644 ``input_transformers`` can now also have an attribute ``has_side_effects`` set
627 to `True`, when this attribute is present; this will prevent the transformers
645 to `True`, when this attribute is present; this will prevent the transformers
628 from being ran when IPython is trying to guess whether the user input is
646 from being ran when IPython is trying to guess whether the user input is
629 complete. Note that this may means you will need to explicitly execute in some
647 complete. Note that this may means you will need to explicitly execute in some
630 case where your transformations are now not ran; but will not affect users with
648 case where your transformations are now not ran; but will not affect users with
631 no custom extensions.
649 no custom extensions.
632
650
633
651
634 API Changes
652 API Changes
635 -----------
653 -----------
636
654
637 Change of API and exposed objects automatically detected using `frappuccino
655 Change of API and exposed objects automatically detected using `frappuccino
638 <https://pypi.org/project/frappuccino/>`_
656 <https://pypi.org/project/frappuccino/>`_
639
657
640
658
641 The following items are new since 7.16.0::
659 The following items are new since 7.16.0::
642
660
643 + IPython.core.interactiveshell.InteractiveShell.get_local_scope(self, stack_depth)
661 + IPython.core.interactiveshell.InteractiveShell.get_local_scope(self, stack_depth)
644
662
645 The following signatures differ since 7.16.0::
663 The following signatures differ since 7.16.0::
646
664
647 - IPython.core.interactiveshell.InteractiveShell.run_cell_async(self, raw_cell, store_history=False, silent=False, shell_futures=True)
665 - IPython.core.interactiveshell.InteractiveShell.run_cell_async(self, raw_cell, store_history=False, silent=False, shell_futures=True)
648 + IPython.core.interactiveshell.InteractiveShell.run_cell_async(self, raw_cell, store_history=False, silent=False, shell_futures=True, *, transformed_cell=None, preprocessing_exc_tuple=None)
666 + IPython.core.interactiveshell.InteractiveShell.run_cell_async(self, raw_cell, store_history=False, silent=False, shell_futures=True, *, transformed_cell=None, preprocessing_exc_tuple=None)
649
667
650 - IPython.core.interactiveshell.InteractiveShell.should_run_async(self, raw_cell)
668 - IPython.core.interactiveshell.InteractiveShell.should_run_async(self, raw_cell)
651 + IPython.core.interactiveshell.InteractiveShell.should_run_async(self, raw_cell, *, transformed_cell=None, preprocessing_exc_tuple=None)
669 + IPython.core.interactiveshell.InteractiveShell.should_run_async(self, raw_cell, *, transformed_cell=None, preprocessing_exc_tuple=None)
652
670
653 - IPython.terminal.debugger.TerminalPdb.pt_init(self)
671 - IPython.terminal.debugger.TerminalPdb.pt_init(self)
654 + IPython.terminal.debugger.TerminalPdb.pt_init(self, pt_session_options=None)
672 + IPython.terminal.debugger.TerminalPdb.pt_init(self, pt_session_options=None)
655
673
656 This method was added::
674 This method was added::
657
675
658 + IPython.core.interactiveshell.InteractiveShell.get_local_scope
676 + IPython.core.interactiveshell.InteractiveShell.get_local_scope
659
677
660 Which is now also present on subclasses::
678 Which is now also present on subclasses::
661
679
662 + IPython.terminal.embed.InteractiveShellEmbed.get_local_scope
680 + IPython.terminal.embed.InteractiveShellEmbed.get_local_scope
663 + IPython.terminal.interactiveshell.TerminalInteractiveShell.get_local_scope
681 + IPython.terminal.interactiveshell.TerminalInteractiveShell.get_local_scope
664
682
665
683
666 .. _version 716:
684 .. _version 716:
667
685
668 IPython 7.16.1, 7.16.2
686 IPython 7.16.1, 7.16.2
669 ======================
687 ======================
670
688
671 IPython 7.16.1 was release immediately after 7.16.0 to fix a conda packaging issue.
689 IPython 7.16.1 was release immediately after 7.16.0 to fix a conda packaging issue.
672 The source is identical to 7.16.0 but the file permissions in the tar are different.
690 The source is identical to 7.16.0 but the file permissions in the tar are different.
673
691
674 IPython 7.16.2 pins jedi dependency to "<=0.17.2" which should prevent some
692 IPython 7.16.2 pins jedi dependency to "<=0.17.2" which should prevent some
675 issues for users still on python 3.6. This may not be sufficient as pip may
693 issues for users still on python 3.6. This may not be sufficient as pip may
676 still allow to downgrade IPython.
694 still allow to downgrade IPython.
677
695
678 Compatibility with Jedi > 0.17.2 was not added as this would have meant bumping
696 Compatibility with Jedi > 0.17.2 was not added as this would have meant bumping
679 the minimal version to >0.16.
697 the minimal version to >0.16.
680
698
681 IPython 7.16
699 IPython 7.16
682 ============
700 ============
683
701
684
702
685 The default traceback mode will now skip frames that are marked with
703 The default traceback mode will now skip frames that are marked with
686 ``__tracebackhide__ = True`` and show how many traceback frames have been
704 ``__tracebackhide__ = True`` and show how many traceback frames have been
687 skipped. This can be toggled by using :magic:`xmode` with the ``--show`` or
705 skipped. This can be toggled by using :magic:`xmode` with the ``--show`` or
688 ``--hide`` attribute. It will have no effect on non verbose traceback modes.
706 ``--hide`` attribute. It will have no effect on non verbose traceback modes.
689
707
690 The ipython debugger also now understands ``__tracebackhide__`` as well and will
708 The ipython debugger also now understands ``__tracebackhide__`` as well and will
691 skip hidden frames when displaying. Movement up and down the stack will skip the
709 skip hidden frames when displaying. Movement up and down the stack will skip the
692 hidden frames and will show how many frames were hidden. Internal IPython frames
710 hidden frames and will show how many frames were hidden. Internal IPython frames
693 are also now hidden by default. The behavior can be changed with the
711 are also now hidden by default. The behavior can be changed with the
694 ``skip_hidden`` while in the debugger, command and accepts "yes", "no", "true"
712 ``skip_hidden`` while in the debugger, command and accepts "yes", "no", "true"
695 and "false" case insensitive parameters.
713 and "false" case insensitive parameters.
696
714
697
715
698 Misc Noticeable changes:
716 Misc Noticeable changes:
699 ------------------------
717 ------------------------
700
718
701 - Exceptions are now (re)raised when running notebooks via the :magic:`%run`, helping to catch issues in workflows and
719 - Exceptions are now (re)raised when running notebooks via the :magic:`%run`, helping to catch issues in workflows and
702 pipelines. :ghpull:`12301`
720 pipelines. :ghpull:`12301`
703 - Fix inputhook for qt 5.15.0 :ghpull:`12355`
721 - Fix inputhook for qt 5.15.0 :ghpull:`12355`
704 - Fix wx inputhook :ghpull:`12375`
722 - Fix wx inputhook :ghpull:`12375`
705 - Add handling for malformed pathext env var (Windows) :ghpull:`12367`
723 - Add handling for malformed pathext env var (Windows) :ghpull:`12367`
706 - use $SHELL in system_piped :ghpull:`12360` for uniform behavior with
724 - use $SHELL in system_piped :ghpull:`12360` for uniform behavior with
707 ipykernel.
725 ipykernel.
708
726
709 Reproducible Build
727 Reproducible Build
710 ------------------
728 ------------------
711
729
712 IPython 7.15 reproducible build did not work, so we try again this month
730 IPython 7.15 reproducible build did not work, so we try again this month
713 :ghpull:`12358`.
731 :ghpull:`12358`.
714
732
715
733
716 API Changes
734 API Changes
717 -----------
735 -----------
718
736
719 Change of API and exposed objects automatically detected using `frappuccino
737 Change of API and exposed objects automatically detected using `frappuccino
720 <https://pypi.org/project/frappuccino/>`_ (still in beta):
738 <https://pypi.org/project/frappuccino/>`_ (still in beta):
721
739
722
740
723 The following items are new and mostly related to understanding ``__tracebackhide__``::
741 The following items are new and mostly related to understanding ``__tracebackhide__``::
724
742
725 + IPython.core.debugger.Pdb.do_down(self, arg)
743 + IPython.core.debugger.Pdb.do_down(self, arg)
726 + IPython.core.debugger.Pdb.do_skip_hidden(self, arg)
744 + IPython.core.debugger.Pdb.do_skip_hidden(self, arg)
727 + IPython.core.debugger.Pdb.do_up(self, arg)
745 + IPython.core.debugger.Pdb.do_up(self, arg)
728 + IPython.core.debugger.Pdb.hidden_frames(self, stack)
746 + IPython.core.debugger.Pdb.hidden_frames(self, stack)
729 + IPython.core.debugger.Pdb.stop_here(self, frame)
747 + IPython.core.debugger.Pdb.stop_here(self, frame)
730
748
731
749
732 The following items have been removed::
750 The following items have been removed::
733
751
734 - IPython.core.debugger.Pdb.new_do_down
752 - IPython.core.debugger.Pdb.new_do_down
735 - IPython.core.debugger.Pdb.new_do_up
753 - IPython.core.debugger.Pdb.new_do_up
736
754
737 Those were implementation details.
755 Those were implementation details.
738
756
739
757
740 .. _version 715:
758 .. _version 715:
741
759
742 IPython 7.15
760 IPython 7.15
743 ============
761 ============
744
762
745 IPython 7.15 brings a number of bug fixes and user facing improvements.
763 IPython 7.15 brings a number of bug fixes and user facing improvements.
746
764
747 Misc Noticeable changes:
765 Misc Noticeable changes:
748 ------------------------
766 ------------------------
749
767
750 - Long completion name have better elision in terminal :ghpull:`12284`
768 - Long completion name have better elision in terminal :ghpull:`12284`
751 - I've started to test on Python 3.9 :ghpull:`12307` and fix some errors.
769 - I've started to test on Python 3.9 :ghpull:`12307` and fix some errors.
752 - Hi DPI scaling of figures when using qt eventloop :ghpull:`12314`
770 - Hi DPI scaling of figures when using qt eventloop :ghpull:`12314`
753 - Document the ability to have systemwide configuration for IPython.
771 - Document the ability to have systemwide configuration for IPython.
754 :ghpull:`12328`
772 :ghpull:`12328`
755 - Fix issues with input autoformatting :ghpull:`12336`
773 - Fix issues with input autoformatting :ghpull:`12336`
756 - ``IPython.core.debugger.Pdb`` is now interruptible (:ghpull:`12168`, in 7.14
774 - ``IPython.core.debugger.Pdb`` is now interruptible (:ghpull:`12168`, in 7.14
757 but forgotten in release notes)
775 but forgotten in release notes)
758 - Video HTML attributes (:ghpull:`12212`, in 7.14 but forgotten in release
776 - Video HTML attributes (:ghpull:`12212`, in 7.14 but forgotten in release
759 notes)
777 notes)
760
778
761 Reproducible Build
779 Reproducible Build
762 ------------------
780 ------------------
763
781
764 Starting with IPython 7.15, I am attempting to provide reproducible builds,
782 Starting with IPython 7.15, I am attempting to provide reproducible builds,
765 that is to say you should be able from the source tree to generate an sdist
783 that is to say you should be able from the source tree to generate an sdist
766 and wheel that are identical byte for byte with the publish version on PyPI.
784 and wheel that are identical byte for byte with the publish version on PyPI.
767
785
768 I've only tested on a couple of machines so far and the process is relatively
786 I've only tested on a couple of machines so far and the process is relatively
769 straightforward, so this mean that IPython not only have a deterministic build
787 straightforward, so this mean that IPython not only have a deterministic build
770 process, but also I have either removed, or put under control all effects of
788 process, but also I have either removed, or put under control all effects of
771 the build environments on the final artifact. I encourage you to attempt the
789 the build environments on the final artifact. I encourage you to attempt the
772 build process on your machine as documented in :ref:`core_developer_guide`
790 build process on your machine as documented in :ref:`core_developer_guide`
773 and let me know if you do not obtain an identical artifact.
791 and let me know if you do not obtain an identical artifact.
774
792
775 While reproducible builds is critical to check that the supply chain of (open
793 While reproducible builds is critical to check that the supply chain of (open
776 source) software has not been compromised, it can also help to speedup many
794 source) software has not been compromised, it can also help to speedup many
777 of the build processes in large environment (conda, apt...) by allowing
795 of the build processes in large environment (conda, apt...) by allowing
778 better caching of intermediate build steps.
796 better caching of intermediate build steps.
779
797
780 Learn more on `<https://reproducible-builds.org/>`_. `Reflections on trusting
798 Learn more on `<https://reproducible-builds.org/>`_. `Reflections on trusting
781 trust <https://dl.acm.org/doi/10.1145/358198.358210>`_ is also one of the
799 trust <https://dl.acm.org/doi/10.1145/358198.358210>`_ is also one of the
782 cornerstone and recommended reads on this subject.
800 cornerstone and recommended reads on this subject.
783
801
784 .. note::
802 .. note::
785
803
786 The build commit from which the sdist is generated is also `signed
804 The build commit from which the sdist is generated is also `signed
787 <https://en.wikipedia.org/wiki/Digital_signature>`_, so you should be able to
805 <https://en.wikipedia.org/wiki/Digital_signature>`_, so you should be able to
788 check it has not been compromised, and the git repository is a `merkle-tree
806 check it has not been compromised, and the git repository is a `merkle-tree
789 <https://en.wikipedia.org/wiki/Merkle_tree>`_, you can check the consistency
807 <https://en.wikipedia.org/wiki/Merkle_tree>`_, you can check the consistency
790 with `git-fsck <https://git-scm.com/docs/git-fsck>`_ which you likely `want
808 with `git-fsck <https://git-scm.com/docs/git-fsck>`_ which you likely `want
791 to enable by default
809 to enable by default
792 <https://gist.github.com/mbbx6spp/14b86437e794bffb4120>`_.
810 <https://gist.github.com/mbbx6spp/14b86437e794bffb4120>`_.
793
811
794 NEP29: Last version to support Python 3.6
812 NEP29: Last version to support Python 3.6
795 -----------------------------------------
813 -----------------------------------------
796
814
797 IPython 7.15 will be the Last IPython version to officially support Python
815 IPython 7.15 will be the Last IPython version to officially support Python
798 3.6, as stated by `NumPy Enhancement Proposal 29
816 3.6, as stated by `NumPy Enhancement Proposal 29
799 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_. Starting with
817 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_. Starting with
800 next minor version of IPython I may stop testing on Python 3.6 and may stop
818 next minor version of IPython I may stop testing on Python 3.6 and may stop
801 publishing release artifacts that install on Python 3.6
819 publishing release artifacts that install on Python 3.6
802
820
803 Highlighted features
821 Highlighted features
804 --------------------
822 --------------------
805
823
806 Highlighted features are not new, but seem to not be widely known, this
824 Highlighted features are not new, but seem to not be widely known, this
807 section will help you discover in more narrative form what you can do with
825 section will help you discover in more narrative form what you can do with
808 IPython.
826 IPython.
809
827
810 Increase Tab Completion Menu Height
828 Increase Tab Completion Menu Height
811 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
829 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
812
830
813 In terminal IPython it is possible to increase the hight of the tab-completion
831 In terminal IPython it is possible to increase the hight of the tab-completion
814 menu. To do so set the value of
832 menu. To do so set the value of
815 :configtrait:`TerminalInteractiveShell.space_for_menu`, this will reserve more
833 :configtrait:`TerminalInteractiveShell.space_for_menu`, this will reserve more
816 space at the bottom of the screen for various kind of menus in IPython including
834 space at the bottom of the screen for various kind of menus in IPython including
817 tab completion and searching in history.
835 tab completion and searching in history.
818
836
819 Autoformat Code in the terminal
837 Autoformat Code in the terminal
820 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
838 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
821
839
822 If you have a preferred code formatter, you can configure IPython to
840 If you have a preferred code formatter, you can configure IPython to
823 reformat your code. Set the value of
841 reformat your code. Set the value of
824 :configtrait:`TerminalInteractiveShell.autoformatter` to for example ``'black'``
842 :configtrait:`TerminalInteractiveShell.autoformatter` to for example ``'black'``
825 and IPython will auto format your code when possible.
843 and IPython will auto format your code when possible.
826
844
827
845
828 .. _version 714:
846 .. _version 714:
829
847
830 IPython 7.14
848 IPython 7.14
831 ============
849 ============
832
850
833 IPython 7.14 is a minor release that fix a couple of bugs and prepare
851 IPython 7.14 is a minor release that fix a couple of bugs and prepare
834 compatibility with new or future versions of some libraries.
852 compatibility with new or future versions of some libraries.
835
853
836 Important changes:
854 Important changes:
837 ------------------
855 ------------------
838
856
839 - Fix compatibility with Sphinx 3+ :ghpull:`12235`
857 - Fix compatibility with Sphinx 3+ :ghpull:`12235`
840 - Remove deprecated matplotlib parameter usage, compatibility with matplotlib
858 - Remove deprecated matplotlib parameter usage, compatibility with matplotlib
841 3.3+ :`122250`
859 3.3+ :`122250`
842
860
843 Misc Changes
861 Misc Changes
844 ------------
862 ------------
845
863
846 - set ``.py`` extension when editing current buffer in vi/emacs. :ghpull:`12167`
864 - set ``.py`` extension when editing current buffer in vi/emacs. :ghpull:`12167`
847 - support for unicode identifiers in ``?``/``??`` :ghpull:`12208`
865 - support for unicode identifiers in ``?``/``??`` :ghpull:`12208`
848 - add extra options to the ``Video`` Rich objects :ghpull:`12212`
866 - add extra options to the ``Video`` Rich objects :ghpull:`12212`
849 - add pretty-printing to ``SimpleNamespace`` :ghpull:`12230`
867 - add pretty-printing to ``SimpleNamespace`` :ghpull:`12230`
850
868
851 IPython.core.debugger.Pdb is now interruptible
869 IPython.core.debugger.Pdb is now interruptible
852 ----------------------------------------------
870 ----------------------------------------------
853
871
854 A ``KeyboardInterrupt`` will now interrupt IPython's extended debugger, in order to make Jupyter able to interrupt it. (:ghpull:`12168`)
872 A ``KeyboardInterrupt`` will now interrupt IPython's extended debugger, in order to make Jupyter able to interrupt it. (:ghpull:`12168`)
855
873
856 Video HTML attributes
874 Video HTML attributes
857 ---------------------
875 ---------------------
858
876
859 Add an option to `IPython.display.Video` to change the attributes of the HTML display of the video (:ghpull:`12212`)
877 Add an option to `IPython.display.Video` to change the attributes of the HTML display of the video (:ghpull:`12212`)
860
878
861
879
862 Pending deprecated imports
880 Pending deprecated imports
863 --------------------------
881 --------------------------
864
882
865 Many object present in ``IPython.core.display`` are there for internal use only,
883 Many object present in ``IPython.core.display`` are there for internal use only,
866 and should already been imported from ``IPython.display`` by users and external
884 and should already been imported from ``IPython.display`` by users and external
867 libraries. Trying to import those from ``IPython.core.display`` is still possible
885 libraries. Trying to import those from ``IPython.core.display`` is still possible
868 but will trigger a
886 but will trigger a
869 deprecation warning in later versions of IPython and will become errors in the
887 deprecation warning in later versions of IPython and will become errors in the
870 future.
888 future.
871
889
872 This will simplify compatibility with other Python kernels (like Xeus-Python),
890 This will simplify compatibility with other Python kernels (like Xeus-Python),
873 and simplify code base.
891 and simplify code base.
874
892
875
893
876
894
877
895
878 .. _version 713:
896 .. _version 713:
879
897
880 IPython 7.13
898 IPython 7.13
881 ============
899 ============
882
900
883 IPython 7.13 is the final release of the 7.x branch since master is diverging
901 IPython 7.13 is the final release of the 7.x branch since master is diverging
884 toward an 8.0. Exiting new features have already been merged in 8.0 and will
902 toward an 8.0. Exiting new features have already been merged in 8.0 and will
885 not be available on the 7.x branch. All the changes below have been backported
903 not be available on the 7.x branch. All the changes below have been backported
886 from the master branch.
904 from the master branch.
887
905
888
906
889 - Fix inability to run PDB when inside an event loop :ghpull:`12141`
907 - Fix inability to run PDB when inside an event loop :ghpull:`12141`
890 - Fix ability to interrupt some processes on windows :ghpull:`12137`
908 - Fix ability to interrupt some processes on windows :ghpull:`12137`
891 - Fix debugger shortcuts :ghpull:`12132`
909 - Fix debugger shortcuts :ghpull:`12132`
892 - improve tab completion when inside a string by removing irrelevant elements :ghpull:`12128`
910 - improve tab completion when inside a string by removing irrelevant elements :ghpull:`12128`
893 - Fix display of filename tab completion when the path is long :ghpull:`12122`
911 - Fix display of filename tab completion when the path is long :ghpull:`12122`
894 - Many removal of Python 2 specific code path :ghpull:`12110`
912 - Many removal of Python 2 specific code path :ghpull:`12110`
895 - displaying wav files do not require NumPy anymore, and is 5x to 30x faster :ghpull:`12113`
913 - displaying wav files do not require NumPy anymore, and is 5x to 30x faster :ghpull:`12113`
896
914
897 See the list of all closed issues and pull request on `github
915 See the list of all closed issues and pull request on `github
898 <https://github.com/ipython/ipython/pulls?q=is%3Aclosed+milestone%3A7.13>`_.
916 <https://github.com/ipython/ipython/pulls?q=is%3Aclosed+milestone%3A7.13>`_.
899
917
900 .. _version 712:
918 .. _version 712:
901
919
902 IPython 7.12
920 IPython 7.12
903 ============
921 ============
904
922
905 IPython 7.12 is a minor update that mostly brings code cleanup, removal of
923 IPython 7.12 is a minor update that mostly brings code cleanup, removal of
906 longtime deprecated function and a couple update to documentation cleanup as well.
924 longtime deprecated function and a couple update to documentation cleanup as well.
907
925
908 Notable changes are the following:
926 Notable changes are the following:
909
927
910 - Exit non-zero when ipython is given a file path to run that doesn't exist :ghpull:`12074`
928 - Exit non-zero when ipython is given a file path to run that doesn't exist :ghpull:`12074`
911 - Test PR on ARM64 with Travis-CI :ghpull:`12073`
929 - Test PR on ARM64 with Travis-CI :ghpull:`12073`
912 - Update CI to work with latest Pytest :ghpull:`12086`
930 - Update CI to work with latest Pytest :ghpull:`12086`
913 - Add infrastructure to run ipykernel eventloop via trio :ghpull:`12097`
931 - Add infrastructure to run ipykernel eventloop via trio :ghpull:`12097`
914 - Support git blame ignore revs :ghpull:`12091`
932 - Support git blame ignore revs :ghpull:`12091`
915 - Start multi-line ``__repr__`` s on their own line :ghpull:`12099`
933 - Start multi-line ``__repr__`` s on their own line :ghpull:`12099`
916
934
917 .. _version 7111:
935 .. _version 7111:
918
936
919 IPython 7.11.1
937 IPython 7.11.1
920 ==============
938 ==============
921
939
922 A couple of deprecated functions (no-op) have been reintroduces in py3compat as
940 A couple of deprecated functions (no-op) have been reintroduces in py3compat as
923 Cython was still relying on them, and will be removed in a couple of versions.
941 Cython was still relying on them, and will be removed in a couple of versions.
924
942
925 .. _version 711:
943 .. _version 711:
926
944
927 IPython 7.11
945 IPython 7.11
928 ============
946 ============
929
947
930 IPython 7.11 received a couple of compatibility fixes and code cleanup.
948 IPython 7.11 received a couple of compatibility fixes and code cleanup.
931
949
932 A number of function in the ``py3compat`` have been removed; a number of types
950 A number of function in the ``py3compat`` have been removed; a number of types
933 in the IPython code base are now non-ambiguous and now always ``unicode``
951 in the IPython code base are now non-ambiguous and now always ``unicode``
934 instead of ``Union[Unicode,bytes]``; many of the relevant code path have thus
952 instead of ``Union[Unicode,bytes]``; many of the relevant code path have thus
935 been simplified/cleaned and types annotation added.
953 been simplified/cleaned and types annotation added.
936
954
937 IPython support several verbosity level from exceptions. ``xmode plain`` now
955 IPython support several verbosity level from exceptions. ``xmode plain`` now
938 support chained exceptions. :ghpull:`11999`
956 support chained exceptions. :ghpull:`11999`
939
957
940 We are starting to remove ``shell=True`` in some usages of subprocess. While not directly
958 We are starting to remove ``shell=True`` in some usages of subprocess. While not directly
941 a security issue (as IPython is made to run arbitrary code anyway) it is not good
959 a security issue (as IPython is made to run arbitrary code anyway) it is not good
942 practice and we'd like to show the example. :ghissue:`12023`. This discussion
960 practice and we'd like to show the example. :ghissue:`12023`. This discussion
943 was started by ``@mschwager`` thanks to a new auditing tool they are working on
961 was started by ``@mschwager`` thanks to a new auditing tool they are working on
944 with duo-labs (`dlint <https://github.com/duo-labs/dlint>`_).
962 with duo-labs (`dlint <https://github.com/duo-labs/dlint>`_).
945
963
946 Work around some bugs in Python 3.9 tokenizer :ghpull:`12057`
964 Work around some bugs in Python 3.9 tokenizer :ghpull:`12057`
947
965
948 IPython will now print its version after a crash. :ghpull:`11986`
966 IPython will now print its version after a crash. :ghpull:`11986`
949
967
950 This is likely the last release from the 7.x series that will see new feature.
968 This is likely the last release from the 7.x series that will see new feature.
951 The master branch will soon accept large code changes and thrilling new
969 The master branch will soon accept large code changes and thrilling new
952 features; the 7.x branch will only start to accept critical bug fixes, and
970 features; the 7.x branch will only start to accept critical bug fixes, and
953 update dependencies.
971 update dependencies.
954
972
955 .. _version 7102:
973 .. _version 7102:
956
974
957 IPython 7.10.2
975 IPython 7.10.2
958 ==============
976 ==============
959
977
960 IPython 7.10.2 fix a couple of extra incompatibility between IPython, ipdb,
978 IPython 7.10.2 fix a couple of extra incompatibility between IPython, ipdb,
961 asyncio and Prompt Toolkit 3.
979 asyncio and Prompt Toolkit 3.
962
980
963 .. _version 7101:
981 .. _version 7101:
964
982
965 IPython 7.10.1
983 IPython 7.10.1
966 ==============
984 ==============
967
985
968 IPython 7.10.1 fix a couple of incompatibilities with Prompt toolkit 3 (please
986 IPython 7.10.1 fix a couple of incompatibilities with Prompt toolkit 3 (please
969 update Prompt toolkit to 3.0.2 at least), and fixes some interaction with
987 update Prompt toolkit to 3.0.2 at least), and fixes some interaction with
970 headless IPython.
988 headless IPython.
971
989
972 .. _version 7100:
990 .. _version 7100:
973
991
974 IPython 7.10.0
992 IPython 7.10.0
975 ==============
993 ==============
976
994
977 IPython 7.10 is the first double digit minor release in the last decade, and
995 IPython 7.10 is the first double digit minor release in the last decade, and
978 first since the release of IPython 1.0, previous double digit minor release was
996 first since the release of IPython 1.0, previous double digit minor release was
979 in August 2009.
997 in August 2009.
980
998
981 We've been trying to give you regular release on the last Friday of every month
999 We've been trying to give you regular release on the last Friday of every month
982 for a guaranty of rapid access to bug fixes and new features.
1000 for a guaranty of rapid access to bug fixes and new features.
983
1001
984 Unlike the previous first few releases that have seen only a couple of code
1002 Unlike the previous first few releases that have seen only a couple of code
985 changes, 7.10 bring a number of changes, new features and bugfixes.
1003 changes, 7.10 bring a number of changes, new features and bugfixes.
986
1004
987 Stop Support for Python 3.5 – Adopt NEP 29
1005 Stop Support for Python 3.5 – Adopt NEP 29
988 ------------------------------------------
1006 ------------------------------------------
989
1007
990 IPython has decided to follow the informational `NEP 29
1008 IPython has decided to follow the informational `NEP 29
991 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_ which layout a clear
1009 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_ which layout a clear
992 policy as to which version of (C)Python and NumPy are supported.
1010 policy as to which version of (C)Python and NumPy are supported.
993
1011
994 We thus dropped support for Python 3.5, and cleaned up a number of code path
1012 We thus dropped support for Python 3.5, and cleaned up a number of code path
995 that were Python-version dependant. If you are on 3.5 or earlier pip should
1013 that were Python-version dependant. If you are on 3.5 or earlier pip should
996 automatically give you the latest compatible version of IPython so you do not
1014 automatically give you the latest compatible version of IPython so you do not
997 need to pin to a given version.
1015 need to pin to a given version.
998
1016
999 Support for Prompt Toolkit 3.0
1017 Support for Prompt Toolkit 3.0
1000 ------------------------------
1018 ------------------------------
1001
1019
1002 Prompt Toolkit 3.0 was release a week before IPython 7.10 and introduces a few
1020 Prompt Toolkit 3.0 was release a week before IPython 7.10 and introduces a few
1003 breaking changes. We believe IPython 7.10 should be compatible with both Prompt
1021 breaking changes. We believe IPython 7.10 should be compatible with both Prompt
1004 Toolkit 2.x and 3.x, though it has not been extensively tested with 3.x so
1022 Toolkit 2.x and 3.x, though it has not been extensively tested with 3.x so
1005 please report any issues.
1023 please report any issues.
1006
1024
1007
1025
1008 Prompt Rendering Performance improvements
1026 Prompt Rendering Performance improvements
1009 -----------------------------------------
1027 -----------------------------------------
1010
1028
1011 Pull Request :ghpull:`11933` introduced an optimisation in the prompt rendering
1029 Pull Request :ghpull:`11933` introduced an optimisation in the prompt rendering
1012 logic that should decrease the resource usage of IPython when using the
1030 logic that should decrease the resource usage of IPython when using the
1013 _default_ configuration but could potentially introduce a regression of
1031 _default_ configuration but could potentially introduce a regression of
1014 functionalities if you are using a custom prompt.
1032 functionalities if you are using a custom prompt.
1015
1033
1016 We know assume if you haven't changed the default keybindings that the prompt
1034 We know assume if you haven't changed the default keybindings that the prompt
1017 **will not change** during the duration of your input – which is for example
1035 **will not change** during the duration of your input – which is for example
1018 not true when using vi insert mode that switches between `[ins]` and `[nor]`
1036 not true when using vi insert mode that switches between `[ins]` and `[nor]`
1019 for the current mode.
1037 for the current mode.
1020
1038
1021 If you are experiencing any issue let us know.
1039 If you are experiencing any issue let us know.
1022
1040
1023 Code autoformatting
1041 Code autoformatting
1024 -------------------
1042 -------------------
1025
1043
1026 The IPython terminal can now auto format your code just before entering a new
1044 The IPython terminal can now auto format your code just before entering a new
1027 line or executing a command. To do so use the
1045 line or executing a command. To do so use the
1028 ``--TerminalInteractiveShell.autoformatter`` option and set it to ``'black'``;
1046 ``--TerminalInteractiveShell.autoformatter`` option and set it to ``'black'``;
1029 if black is installed IPython will use black to format your code when possible.
1047 if black is installed IPython will use black to format your code when possible.
1030
1048
1031 IPython cannot always properly format your code; in particular it will
1049 IPython cannot always properly format your code; in particular it will
1032 auto formatting with *black* will only work if:
1050 auto formatting with *black* will only work if:
1033
1051
1034 - Your code does not contains magics or special python syntax.
1052 - Your code does not contains magics or special python syntax.
1035
1053
1036 - There is no code after your cursor.
1054 - There is no code after your cursor.
1037
1055
1038 The Black API is also still in motion; so this may not work with all versions of
1056 The Black API is also still in motion; so this may not work with all versions of
1039 black.
1057 black.
1040
1058
1041 It should be possible to register custom formatter, though the API is till in
1059 It should be possible to register custom formatter, though the API is till in
1042 flux.
1060 flux.
1043
1061
1044 Arbitrary Mimetypes Handing in Terminal (Aka inline images in terminal)
1062 Arbitrary Mimetypes Handing in Terminal (Aka inline images in terminal)
1045 -----------------------------------------------------------------------
1063 -----------------------------------------------------------------------
1046
1064
1047 When using IPython terminal it is now possible to register function to handle
1065 When using IPython terminal it is now possible to register function to handle
1048 arbitrary mimetypes. While rendering non-text based representation was possible in
1066 arbitrary mimetypes. While rendering non-text based representation was possible in
1049 many jupyter frontend; it was not possible in terminal IPython, as usually
1067 many jupyter frontend; it was not possible in terminal IPython, as usually
1050 terminal are limited to displaying text. As many terminal these days provide
1068 terminal are limited to displaying text. As many terminal these days provide
1051 escape sequences to display non-text; bringing this loved feature to IPython CLI
1069 escape sequences to display non-text; bringing this loved feature to IPython CLI
1052 made a lot of sens. This functionality will not only allow inline images; but
1070 made a lot of sens. This functionality will not only allow inline images; but
1053 allow opening of external program; for example ``mplayer`` to "display" sound
1071 allow opening of external program; for example ``mplayer`` to "display" sound
1054 files.
1072 files.
1055
1073
1056 So far only the hooks necessary for this are in place, but no default mime
1074 So far only the hooks necessary for this are in place, but no default mime
1057 renderers added; so inline images will only be available via extensions. We will
1075 renderers added; so inline images will only be available via extensions. We will
1058 progressively enable these features by default in the next few releases, and
1076 progressively enable these features by default in the next few releases, and
1059 contribution is welcomed.
1077 contribution is welcomed.
1060
1078
1061 We welcome any feedback on the API. See :ref:`shell_mimerenderer` for more
1079 We welcome any feedback on the API. See :ref:`shell_mimerenderer` for more
1062 informations.
1080 informations.
1063
1081
1064 This is originally based on work form in :ghpull:`10610` from @stephanh42
1082 This is originally based on work form in :ghpull:`10610` from @stephanh42
1065 started over two years ago, and still a lot need to be done.
1083 started over two years ago, and still a lot need to be done.
1066
1084
1067 MISC
1085 MISC
1068 ----
1086 ----
1069
1087
1070 - Completions can define their own ordering :ghpull:`11855`
1088 - Completions can define their own ordering :ghpull:`11855`
1071 - Enable Plotting in the same cell than the one that import matplotlib
1089 - Enable Plotting in the same cell than the one that import matplotlib
1072 :ghpull:`11916`
1090 :ghpull:`11916`
1073 - Allow to store and restore multiple variables at once :ghpull:`11930`
1091 - Allow to store and restore multiple variables at once :ghpull:`11930`
1074
1092
1075 You can see `all pull-requests <https://github.com/ipython/ipython/pulls?q=is%3Apr+milestone%3A7.10+is%3Aclosed>`_ for this release.
1093 You can see `all pull-requests <https://github.com/ipython/ipython/pulls?q=is%3Apr+milestone%3A7.10+is%3Aclosed>`_ for this release.
1076
1094
1077 API Changes
1095 API Changes
1078 -----------
1096 -----------
1079
1097
1080 Change of API and exposed objects automatically detected using `frappuccino <https://pypi.org/project/frappuccino/>`_ (still in beta):
1098 Change of API and exposed objects automatically detected using `frappuccino <https://pypi.org/project/frappuccino/>`_ (still in beta):
1081
1099
1082 The following items are new in IPython 7.10::
1100 The following items are new in IPython 7.10::
1083
1101
1084 + IPython.terminal.shortcuts.reformat_text_before_cursor(buffer, document, shell)
1102 + IPython.terminal.shortcuts.reformat_text_before_cursor(buffer, document, shell)
1085 + IPython.terminal.interactiveshell.PTK3
1103 + IPython.terminal.interactiveshell.PTK3
1086 + IPython.terminal.interactiveshell.black_reformat_handler(text_before_cursor)
1104 + IPython.terminal.interactiveshell.black_reformat_handler(text_before_cursor)
1087 + IPython.terminal.prompts.RichPromptDisplayHook.write_format_data(self, format_dict, md_dict='None')
1105 + IPython.terminal.prompts.RichPromptDisplayHook.write_format_data(self, format_dict, md_dict='None')
1088
1106
1089 The following items have been removed in 7.10::
1107 The following items have been removed in 7.10::
1090
1108
1091 - IPython.lib.pretty.DICT_IS_ORDERED
1109 - IPython.lib.pretty.DICT_IS_ORDERED
1092
1110
1093 The following signatures differ between versions::
1111 The following signatures differ between versions::
1094
1112
1095 - IPython.extensions.storemagic.restore_aliases(ip)
1113 - IPython.extensions.storemagic.restore_aliases(ip)
1096 + IPython.extensions.storemagic.restore_aliases(ip, alias='None')
1114 + IPython.extensions.storemagic.restore_aliases(ip, alias='None')
1097
1115
1098 Special Thanks
1116 Special Thanks
1099 --------------
1117 --------------
1100
1118
1101 - @stephanh42 who started the work on inline images in terminal 2 years ago
1119 - @stephanh42 who started the work on inline images in terminal 2 years ago
1102 - @augustogoulart who spent a lot of time triaging issues and responding to
1120 - @augustogoulart who spent a lot of time triaging issues and responding to
1103 users.
1121 users.
1104 - @con-f-use who is my (@Carreau) first sponsor on GitHub, as a reminder if you
1122 - @con-f-use who is my (@Carreau) first sponsor on GitHub, as a reminder if you
1105 like IPython, Jupyter and many other library of the SciPy stack you can
1123 like IPython, Jupyter and many other library of the SciPy stack you can
1106 donate to numfocus.org non profit
1124 donate to numfocus.org non profit
1107
1125
1108 .. _version 790:
1126 .. _version 790:
1109
1127
1110 IPython 7.9.0
1128 IPython 7.9.0
1111 =============
1129 =============
1112
1130
1113 IPython 7.9 is a small release with a couple of improvement and bug fixes.
1131 IPython 7.9 is a small release with a couple of improvement and bug fixes.
1114
1132
1115 - Xterm terminal title should be restored on exit :ghpull:`11910`
1133 - Xterm terminal title should be restored on exit :ghpull:`11910`
1116 - special variables ``_``,``__``, ``___`` are not set anymore when cache size
1134 - special variables ``_``,``__``, ``___`` are not set anymore when cache size
1117 is 0 or less. :ghpull:`11877`
1135 is 0 or less. :ghpull:`11877`
1118 - Autoreload should have regained some speed by using a new heuristic logic to
1136 - Autoreload should have regained some speed by using a new heuristic logic to
1119 find all objects needing reload. This should avoid large objects traversal
1137 find all objects needing reload. This should avoid large objects traversal
1120 like pandas dataframes. :ghpull:`11876`
1138 like pandas dataframes. :ghpull:`11876`
1121 - Get ready for Python 4. :ghpull:`11874`
1139 - Get ready for Python 4. :ghpull:`11874`
1122 - `%env` Magic now has heuristic to hide potentially sensitive values :ghpull:`11896`
1140 - `%env` Magic now has heuristic to hide potentially sensitive values :ghpull:`11896`
1123
1141
1124 This is a small release despite a number of Pull Request Pending that need to
1142 This is a small release despite a number of Pull Request Pending that need to
1125 be reviewed/worked on. Many of the core developers have been busy outside of
1143 be reviewed/worked on. Many of the core developers have been busy outside of
1126 IPython/Jupyter and we thanks all contributor for their patience; we'll work on
1144 IPython/Jupyter and we thanks all contributor for their patience; we'll work on
1127 these as soon as we have time.
1145 these as soon as we have time.
1128
1146
1129
1147
1130 .. _version780:
1148 .. _version780:
1131
1149
1132 IPython 7.8.0
1150 IPython 7.8.0
1133 =============
1151 =============
1134
1152
1135 IPython 7.8.0 contain a few bugfix and 2 new APIs:
1153 IPython 7.8.0 contain a few bugfix and 2 new APIs:
1136
1154
1137 - Enable changing the font color for LaTeX rendering :ghpull:`11840`
1155 - Enable changing the font color for LaTeX rendering :ghpull:`11840`
1138 - and Re-Expose some PDB API (see below)
1156 - and Re-Expose some PDB API (see below)
1139
1157
1140 Expose Pdb API
1158 Expose Pdb API
1141 --------------
1159 --------------
1142
1160
1143 Expose the built-in ``pdb.Pdb`` API. ``Pdb`` constructor arguments are generically
1161 Expose the built-in ``pdb.Pdb`` API. ``Pdb`` constructor arguments are generically
1144 exposed, regardless of python version.
1162 exposed, regardless of python version.
1145 Newly exposed arguments:
1163 Newly exposed arguments:
1146
1164
1147 - ``skip`` - Python 3.1+
1165 - ``skip`` - Python 3.1+
1148 - ``nosiginnt`` - Python 3.2+
1166 - ``nosiginnt`` - Python 3.2+
1149 - ``readrc`` - Python 3.6+
1167 - ``readrc`` - Python 3.6+
1150
1168
1151 Try it out::
1169 Try it out::
1152
1170
1153 from IPython.terminal.debugger import TerminalPdb
1171 from IPython.terminal.debugger import TerminalPdb
1154 pdb = TerminalPdb(skip=["skipthismodule"])
1172 pdb = TerminalPdb(skip=["skipthismodule"])
1155
1173
1156
1174
1157 See :ghpull:`11840`
1175 See :ghpull:`11840`
1158
1176
1159 .. _version770:
1177 .. _version770:
1160
1178
1161 IPython 7.7.0
1179 IPython 7.7.0
1162 =============
1180 =============
1163
1181
1164 IPython 7.7.0 contain multiple bug fixes and documentation updates; Here are a
1182 IPython 7.7.0 contain multiple bug fixes and documentation updates; Here are a
1165 few of the outstanding issue fixed:
1183 few of the outstanding issue fixed:
1166
1184
1167 - Fix a bug introduced in 7.6 where the ``%matplotlib`` magic would fail on
1185 - Fix a bug introduced in 7.6 where the ``%matplotlib`` magic would fail on
1168 previously acceptable arguments :ghpull:`11814`.
1186 previously acceptable arguments :ghpull:`11814`.
1169 - Fix the manage location on freebsd :ghpull:`11808`.
1187 - Fix the manage location on freebsd :ghpull:`11808`.
1170 - Fix error message about aliases after ``%reset`` call in ipykernel
1188 - Fix error message about aliases after ``%reset`` call in ipykernel
1171 :ghpull:`11806`
1189 :ghpull:`11806`
1172 - Fix Duplication completions in emacs :ghpull:`11803`
1190 - Fix Duplication completions in emacs :ghpull:`11803`
1173
1191
1174 We are planning to adopt `NEP29 <https://github.com/numpy/numpy/pull/14086>`_
1192 We are planning to adopt `NEP29 <https://github.com/numpy/numpy/pull/14086>`_
1175 (still currently in draft) which may make this minor version of IPython the
1193 (still currently in draft) which may make this minor version of IPython the
1176 last one to support Python 3.5 and will make the code base more aggressive
1194 last one to support Python 3.5 and will make the code base more aggressive
1177 toward removing compatibility with older versions of Python.
1195 toward removing compatibility with older versions of Python.
1178
1196
1179 GitHub now support to give only "Triage" permissions to users; if you'd like to
1197 GitHub now support to give only "Triage" permissions to users; if you'd like to
1180 help close stale issues and labels issues please reach to us with your GitHub
1198 help close stale issues and labels issues please reach to us with your GitHub
1181 Username and we'll add you to the triage team. It is a great way to start
1199 Username and we'll add you to the triage team. It is a great way to start
1182 contributing and a path toward getting commit rights.
1200 contributing and a path toward getting commit rights.
1183
1201
1184 .. _version761:
1202 .. _version761:
1185
1203
1186 IPython 7.6.1
1204 IPython 7.6.1
1187 =============
1205 =============
1188
1206
1189 IPython 7.6.1 contain a critical bugfix in the ``%timeit`` magic, which would
1207 IPython 7.6.1 contain a critical bugfix in the ``%timeit`` magic, which would
1190 crash on some inputs as a side effect of :ghpull:`11716`. See :ghpull:`11812`
1208 crash on some inputs as a side effect of :ghpull:`11716`. See :ghpull:`11812`
1191
1209
1192
1210
1193 .. _whatsnew760:
1211 .. _whatsnew760:
1194
1212
1195 IPython 7.6.0
1213 IPython 7.6.0
1196 =============
1214 =============
1197
1215
1198 IPython 7.6.0 contains a couple of bug fixes and number of small features
1216 IPython 7.6.0 contains a couple of bug fixes and number of small features
1199 additions as well as some compatibility with the current development version of
1217 additions as well as some compatibility with the current development version of
1200 Python 3.8.
1218 Python 3.8.
1201
1219
1202 - Add a ``-l`` option to :magic:`psearch` to list the available search
1220 - Add a ``-l`` option to :magic:`psearch` to list the available search
1203 types. :ghpull:`11672`
1221 types. :ghpull:`11672`
1204 - Support ``PathLike`` for ``DisplayObject`` and ``Image``. :ghpull:`11764`
1222 - Support ``PathLike`` for ``DisplayObject`` and ``Image``. :ghpull:`11764`
1205 - Configurability of timeout in the test suite for slow platforms.
1223 - Configurability of timeout in the test suite for slow platforms.
1206 :ghpull:`11756`
1224 :ghpull:`11756`
1207 - Accept any casing for matplotlib backend. :ghpull:`121748`
1225 - Accept any casing for matplotlib backend. :ghpull:`121748`
1208 - Properly skip test that requires numpy to be installed :ghpull:`11723`
1226 - Properly skip test that requires numpy to be installed :ghpull:`11723`
1209 - More support for Python 3.8 and positional only arguments (pep570)
1227 - More support for Python 3.8 and positional only arguments (pep570)
1210 :ghpull:`11720`
1228 :ghpull:`11720`
1211 - Unicode names for the completion are loaded lazily on first use which
1229 - Unicode names for the completion are loaded lazily on first use which
1212 should decrease startup time. :ghpull:`11693`
1230 should decrease startup time. :ghpull:`11693`
1213 - Autoreload now update the types of reloaded objects; this for example allow
1231 - Autoreload now update the types of reloaded objects; this for example allow
1214 pickling of reloaded objects. :ghpull:`11644`
1232 pickling of reloaded objects. :ghpull:`11644`
1215 - Fix a bug where ``%%time`` magic would suppress cell output. :ghpull:`11716`
1233 - Fix a bug where ``%%time`` magic would suppress cell output. :ghpull:`11716`
1216
1234
1217
1235
1218 Prepare migration to pytest (instead of nose) for testing
1236 Prepare migration to pytest (instead of nose) for testing
1219 ---------------------------------------------------------
1237 ---------------------------------------------------------
1220
1238
1221 Most of the work between 7.5 and 7.6 was to prepare the migration from our
1239 Most of the work between 7.5 and 7.6 was to prepare the migration from our
1222 testing framework to pytest. Most of the test suite should now work by simply
1240 testing framework to pytest. Most of the test suite should now work by simply
1223 issuing ``pytest`` from the root of the repository.
1241 issuing ``pytest`` from the root of the repository.
1224
1242
1225 The migration to pytest is just at its beginning. Many of our test still rely
1243 The migration to pytest is just at its beginning. Many of our test still rely
1226 on IPython-specific plugins for nose using pytest (doctest using IPython syntax
1244 on IPython-specific plugins for nose using pytest (doctest using IPython syntax
1227 is one example of this where test appear as "passing", while no code has been
1245 is one example of this where test appear as "passing", while no code has been
1228 ran). Many test also need to be updated like ``yield-test`` to be properly
1246 ran). Many test also need to be updated like ``yield-test`` to be properly
1229 parametrized tests.
1247 parametrized tests.
1230
1248
1231 Migration to pytest allowed me to discover a number of issues in our test
1249 Migration to pytest allowed me to discover a number of issues in our test
1232 suite; which was hiding a number of subtle issues – or not actually running
1250 suite; which was hiding a number of subtle issues – or not actually running
1233 some of the tests in our test suite – I have thus corrected many of those; like
1251 some of the tests in our test suite – I have thus corrected many of those; like
1234 improperly closed resources; or used of deprecated features. I also made use of
1252 improperly closed resources; or used of deprecated features. I also made use of
1235 the ``pytest --durations=...`` to find some of our slowest test and speed them
1253 the ``pytest --durations=...`` to find some of our slowest test and speed them
1236 up (our test suite can now be up to 10% faster). Pytest as also a variety of
1254 up (our test suite can now be up to 10% faster). Pytest as also a variety of
1237 plugins and flags which will make the code quality of IPython and the testing
1255 plugins and flags which will make the code quality of IPython and the testing
1238 experience better.
1256 experience better.
1239
1257
1240 Misc
1258 Misc
1241 ----
1259 ----
1242
1260
1243 We skipped the release of 7.6 at the end of May, but will attempt to get back
1261 We skipped the release of 7.6 at the end of May, but will attempt to get back
1244 on schedule. We are starting to think about making introducing backward
1262 on schedule. We are starting to think about making introducing backward
1245 incompatible change and start the 8.0 series.
1263 incompatible change and start the 8.0 series.
1246
1264
1247 Special Thanks to Gabriel (@gpotter2 on GitHub), who among other took care many
1265 Special Thanks to Gabriel (@gpotter2 on GitHub), who among other took care many
1248 of the remaining task for 7.4 and 7.5, like updating the website.
1266 of the remaining task for 7.4 and 7.5, like updating the website.
1249
1267
1250 .. _whatsnew750:
1268 .. _whatsnew750:
1251
1269
1252 IPython 7.5.0
1270 IPython 7.5.0
1253 =============
1271 =============
1254
1272
1255 IPython 7.5.0 consist mostly of bug-fixes, and documentation updates, with one
1273 IPython 7.5.0 consist mostly of bug-fixes, and documentation updates, with one
1256 minor new feature. The `Audio` display element can now be assigned an element
1274 minor new feature. The `Audio` display element can now be assigned an element
1257 id when displayed in browser. See :ghpull:`11670`
1275 id when displayed in browser. See :ghpull:`11670`
1258
1276
1259 The major outstanding bug fix correct a change of behavior that was introduce
1277 The major outstanding bug fix correct a change of behavior that was introduce
1260 in 7.4.0 where some cell magics would not be able to access or modify global
1278 in 7.4.0 where some cell magics would not be able to access or modify global
1261 scope when using the ``@needs_local_scope`` decorator. This was typically
1279 scope when using the ``@needs_local_scope`` decorator. This was typically
1262 encountered with the ``%%time`` and ``%%timeit`` magics. See :ghissue:`11659`
1280 encountered with the ``%%time`` and ``%%timeit`` magics. See :ghissue:`11659`
1263 and :ghpull:`11698`.
1281 and :ghpull:`11698`.
1264
1282
1265 .. _whatsnew740:
1283 .. _whatsnew740:
1266
1284
1267 IPython 7.4.0
1285 IPython 7.4.0
1268 =============
1286 =============
1269
1287
1270 Unicode name completions
1288 Unicode name completions
1271 ------------------------
1289 ------------------------
1272
1290
1273 Previously, we provided completion for a unicode name with its relative symbol.
1291 Previously, we provided completion for a unicode name with its relative symbol.
1274 With this, now IPython provides complete suggestions to unicode name symbols.
1292 With this, now IPython provides complete suggestions to unicode name symbols.
1275
1293
1276 As on the PR, if user types ``\LAT<tab>``, IPython provides a list of
1294 As on the PR, if user types ``\LAT<tab>``, IPython provides a list of
1277 possible completions. In this case, it would be something like::
1295 possible completions. In this case, it would be something like::
1278
1296
1279 'LATIN CAPITAL LETTER A',
1297 'LATIN CAPITAL LETTER A',
1280 'LATIN CAPITAL LETTER B',
1298 'LATIN CAPITAL LETTER B',
1281 'LATIN CAPITAL LETTER C',
1299 'LATIN CAPITAL LETTER C',
1282 'LATIN CAPITAL LETTER D',
1300 'LATIN CAPITAL LETTER D',
1283 ....
1301 ....
1284
1302
1285 This help to type unicode character that do not have short latex aliases, and
1303 This help to type unicode character that do not have short latex aliases, and
1286 have long unicode names. for example ``Ͱ``, ``\GREEK CAPITAL LETTER HETA``.
1304 have long unicode names. for example ``Ͱ``, ``\GREEK CAPITAL LETTER HETA``.
1287
1305
1288 This feature was contributed by Luciana Marques :ghpull:`11583`.
1306 This feature was contributed by Luciana Marques :ghpull:`11583`.
1289
1307
1290 Make audio normalization optional
1308 Make audio normalization optional
1291 ---------------------------------
1309 ---------------------------------
1292
1310
1293 Added 'normalize' argument to `IPython.display.Audio`. This argument applies
1311 Added 'normalize' argument to `IPython.display.Audio`. This argument applies
1294 when audio data is given as an array of samples. The default of `normalize=True`
1312 when audio data is given as an array of samples. The default of `normalize=True`
1295 preserves prior behavior of normalizing the audio to the maximum possible range.
1313 preserves prior behavior of normalizing the audio to the maximum possible range.
1296 Setting to `False` disables normalization.
1314 Setting to `False` disables normalization.
1297
1315
1298
1316
1299 Miscellaneous
1317 Miscellaneous
1300 -------------
1318 -------------
1301
1319
1302 - Fix improper acceptation of ``return`` outside of functions. :ghpull:`11641`.
1320 - Fix improper acceptation of ``return`` outside of functions. :ghpull:`11641`.
1303 - Fixed PyQt 5.11 backwards incompatibility causing sip import failure.
1321 - Fixed PyQt 5.11 backwards incompatibility causing sip import failure.
1304 :ghpull:`11613`.
1322 :ghpull:`11613`.
1305 - Fix Bug where ``type?`` would crash IPython. :ghpull:`1608`.
1323 - Fix Bug where ``type?`` would crash IPython. :ghpull:`1608`.
1306 - Allow to apply ``@needs_local_scope`` to cell magics for convenience.
1324 - Allow to apply ``@needs_local_scope`` to cell magics for convenience.
1307 :ghpull:`11542`.
1325 :ghpull:`11542`.
1308
1326
1309 .. _whatsnew730:
1327 .. _whatsnew730:
1310
1328
1311 IPython 7.3.0
1329 IPython 7.3.0
1312 =============
1330 =============
1313
1331
1314 .. _whatsnew720:
1332 .. _whatsnew720:
1315
1333
1316 IPython 7.3.0 bring several bug fixes and small improvements that you will
1334 IPython 7.3.0 bring several bug fixes and small improvements that you will
1317 described bellow.
1335 described bellow.
1318
1336
1319 The biggest change to this release is the implementation of the ``%conda`` and
1337 The biggest change to this release is the implementation of the ``%conda`` and
1320 ``%pip`` magics, that will attempt to install packages in the **current
1338 ``%pip`` magics, that will attempt to install packages in the **current
1321 environment**. You may still need to restart your interpreter or kernel for the
1339 environment**. You may still need to restart your interpreter or kernel for the
1322 change to be taken into account, but it should simplify installation of packages
1340 change to be taken into account, but it should simplify installation of packages
1323 into remote environment. Installing using pip/conda from the command line is
1341 into remote environment. Installing using pip/conda from the command line is
1324 still the prefer method.
1342 still the prefer method.
1325
1343
1326 The ``%pip`` magic was already present, but was only printing a warning; now it
1344 The ``%pip`` magic was already present, but was only printing a warning; now it
1327 will actually forward commands to pip.
1345 will actually forward commands to pip.
1328
1346
1329 Misc bug fixes and improvements:
1347 Misc bug fixes and improvements:
1330
1348
1331 - Compatibility with Python 3.8.
1349 - Compatibility with Python 3.8.
1332 - Do not expand shell variable in execution magics, and added the
1350 - Do not expand shell variable in execution magics, and added the
1333 ``no_var_expand`` decorator for magic requiring a similar functionality
1351 ``no_var_expand`` decorator for magic requiring a similar functionality
1334 :ghpull:`11516`
1352 :ghpull:`11516`
1335 - Add ``%pip`` and ``%conda`` magic :ghpull:`11524`
1353 - Add ``%pip`` and ``%conda`` magic :ghpull:`11524`
1336 - Re-initialize posix aliases after a ``%reset`` :ghpull:`11528`
1354 - Re-initialize posix aliases after a ``%reset`` :ghpull:`11528`
1337 - Allow the IPython command line to run ``*.ipynb`` files :ghpull:`11529`
1355 - Allow the IPython command line to run ``*.ipynb`` files :ghpull:`11529`
1338
1356
1339 IPython 7.2.0
1357 IPython 7.2.0
1340 =============
1358 =============
1341
1359
1342 IPython 7.2.0 brings minor bugfixes, improvements, and new configuration options:
1360 IPython 7.2.0 brings minor bugfixes, improvements, and new configuration options:
1343
1361
1344 - Fix a bug preventing PySide2 GUI integration from working :ghpull:`11464`
1362 - Fix a bug preventing PySide2 GUI integration from working :ghpull:`11464`
1345 - Run CI on Mac OS ! :ghpull:`11471`
1363 - Run CI on Mac OS ! :ghpull:`11471`
1346 - Fix IPython "Demo" mode. :ghpull:`11498`
1364 - Fix IPython "Demo" mode. :ghpull:`11498`
1347 - Fix ``%run`` magic with path in name :ghpull:`11499`
1365 - Fix ``%run`` magic with path in name :ghpull:`11499`
1348 - Fix: add CWD to sys.path *after* stdlib :ghpull:`11502`
1366 - Fix: add CWD to sys.path *after* stdlib :ghpull:`11502`
1349 - Better rendering of signatures, especially long ones. :ghpull:`11505`
1367 - Better rendering of signatures, especially long ones. :ghpull:`11505`
1350 - Re-enable jedi by default if it's installed :ghpull:`11506`
1368 - Re-enable jedi by default if it's installed :ghpull:`11506`
1351 - Add New ``minimal`` exception reporting mode (useful for educational purpose). See :ghpull:`11509`
1369 - Add New ``minimal`` exception reporting mode (useful for educational purpose). See :ghpull:`11509`
1352
1370
1353
1371
1354 Added ability to show subclasses when using pinfo and other utilities
1372 Added ability to show subclasses when using pinfo and other utilities
1355 ---------------------------------------------------------------------
1373 ---------------------------------------------------------------------
1356
1374
1357 When using ``?``/``??`` on a class, IPython will now list the first 10 subclasses.
1375 When using ``?``/``??`` on a class, IPython will now list the first 10 subclasses.
1358
1376
1359 Special Thanks to Chris Mentzel of the Moore Foundation for this feature. Chris
1377 Special Thanks to Chris Mentzel of the Moore Foundation for this feature. Chris
1360 is one of the people who played a critical role in IPython/Jupyter getting
1378 is one of the people who played a critical role in IPython/Jupyter getting
1361 funding.
1379 funding.
1362
1380
1363 We are grateful for all the help Chris has given us over the years,
1381 We are grateful for all the help Chris has given us over the years,
1364 and we're now proud to have code contributed by Chris in IPython.
1382 and we're now proud to have code contributed by Chris in IPython.
1365
1383
1366 OSMagics.cd_force_quiet configuration option
1384 OSMagics.cd_force_quiet configuration option
1367 --------------------------------------------
1385 --------------------------------------------
1368
1386
1369 You can set this option to force the %cd magic to behave as if ``-q`` was passed:
1387 You can set this option to force the %cd magic to behave as if ``-q`` was passed:
1370 ::
1388 ::
1371
1389
1372 In [1]: cd /
1390 In [1]: cd /
1373 /
1391 /
1374
1392
1375 In [2]: %config OSMagics.cd_force_quiet = True
1393 In [2]: %config OSMagics.cd_force_quiet = True
1376
1394
1377 In [3]: cd /tmp
1395 In [3]: cd /tmp
1378
1396
1379 In [4]:
1397 In [4]:
1380
1398
1381 See :ghpull:`11491`
1399 See :ghpull:`11491`
1382
1400
1383 In vi editing mode, whether the prompt includes the current vi mode can now be configured
1401 In vi editing mode, whether the prompt includes the current vi mode can now be configured
1384 -----------------------------------------------------------------------------------------
1402 -----------------------------------------------------------------------------------------
1385
1403
1386 Set the ``TerminalInteractiveShell.prompt_includes_vi_mode`` to a boolean value
1404 Set the ``TerminalInteractiveShell.prompt_includes_vi_mode`` to a boolean value
1387 (default: True) to control this feature. See :ghpull:`11492`
1405 (default: True) to control this feature. See :ghpull:`11492`
1388
1406
1389 .. _whatsnew710:
1407 .. _whatsnew710:
1390
1408
1391 IPython 7.1.0
1409 IPython 7.1.0
1392 =============
1410 =============
1393
1411
1394 IPython 7.1.0 is the first minor release after 7.0.0 and mostly brings fixes to
1412 IPython 7.1.0 is the first minor release after 7.0.0 and mostly brings fixes to
1395 new features, internal refactoring, and fixes for regressions that happened during the 6.x->7.x
1413 new features, internal refactoring, and fixes for regressions that happened during the 6.x->7.x
1396 transition. It also brings **Compatibility with Python 3.7.1**, as we're
1414 transition. It also brings **Compatibility with Python 3.7.1**, as we're
1397 unwillingly relying on a bug in CPython.
1415 unwillingly relying on a bug in CPython.
1398
1416
1399 New Core Dev:
1417 New Core Dev:
1400
1418
1401 - We welcome Jonathan Slenders to the commiters. Jonathan has done a fantastic
1419 - We welcome Jonathan Slenders to the commiters. Jonathan has done a fantastic
1402 work on prompt_toolkit, and we'd like to recognise his impact by giving him
1420 work on prompt_toolkit, and we'd like to recognise his impact by giving him
1403 commit rights. :ghissue:`11397`
1421 commit rights. :ghissue:`11397`
1404
1422
1405 Notable Changes
1423 Notable Changes
1406
1424
1407 - Major update of "latex to unicode" tab completion map (see below)
1425 - Major update of "latex to unicode" tab completion map (see below)
1408
1426
1409 Notable New Features:
1427 Notable New Features:
1410
1428
1411 - Restore functionality and documentation of the **sphinx directive**, which
1429 - Restore functionality and documentation of the **sphinx directive**, which
1412 is now stricter (fail on error by daefault), has new configuration options,
1430 is now stricter (fail on error by daefault), has new configuration options,
1413 has a brand new documentation page :ref:`ipython_directive` (which needs
1431 has a brand new documentation page :ref:`ipython_directive` (which needs
1414 some cleanup). It is also now *tested* so we hope to have less regressions.
1432 some cleanup). It is also now *tested* so we hope to have less regressions.
1415 :ghpull:`11402`
1433 :ghpull:`11402`
1416
1434
1417 - ``IPython.display.Video`` now supports ``width`` and ``height`` arguments,
1435 - ``IPython.display.Video`` now supports ``width`` and ``height`` arguments,
1418 allowing a custom width and height to be set instead of using the video's
1436 allowing a custom width and height to be set instead of using the video's
1419 width and height. :ghpull:`11353`
1437 width and height. :ghpull:`11353`
1420
1438
1421 - Warn when using ``HTML('<iframe>')`` instead of ``IFrame`` :ghpull:`11350`
1439 - Warn when using ``HTML('<iframe>')`` instead of ``IFrame`` :ghpull:`11350`
1422
1440
1423 - Allow Dynamic switching of editing mode between vi/emacs and show
1441 - Allow Dynamic switching of editing mode between vi/emacs and show
1424 normal/input mode in prompt when using vi. :ghpull:`11390`. Use ``%config
1442 normal/input mode in prompt when using vi. :ghpull:`11390`. Use ``%config
1425 TerminalInteractiveShell.editing_mode = 'vi'`` or ``%config
1443 TerminalInteractiveShell.editing_mode = 'vi'`` or ``%config
1426 TerminalInteractiveShell.editing_mode = 'emacs'`` to dynamically switch
1444 TerminalInteractiveShell.editing_mode = 'emacs'`` to dynamically switch
1427 between modes.
1445 between modes.
1428
1446
1429
1447
1430 Notable Fixes:
1448 Notable Fixes:
1431
1449
1432 - Fix entering of **multi-line blocks in terminal** IPython, and various
1450 - Fix entering of **multi-line blocks in terminal** IPython, and various
1433 crashes in the new input transformation machinery :ghpull:`11354`,
1451 crashes in the new input transformation machinery :ghpull:`11354`,
1434 :ghpull:`11356`, :ghpull:`11358`. These also fix a **Compatibility bug
1452 :ghpull:`11356`, :ghpull:`11358`. These also fix a **Compatibility bug
1435 with Python 3.7.1**.
1453 with Python 3.7.1**.
1436
1454
1437 - Fix moving through generator stack in ipdb :ghpull:`11266`
1455 - Fix moving through generator stack in ipdb :ghpull:`11266`
1438
1456
1439 - %Magic command arguments now support quoting. :ghpull:`11330`
1457 - %Magic command arguments now support quoting. :ghpull:`11330`
1440
1458
1441 - Re-add ``rprint`` and ``rprinte`` aliases. :ghpull:`11331`
1459 - Re-add ``rprint`` and ``rprinte`` aliases. :ghpull:`11331`
1442
1460
1443 - Remove implicit dependency on ``ipython_genutils`` :ghpull:`11317`
1461 - Remove implicit dependency on ``ipython_genutils`` :ghpull:`11317`
1444
1462
1445 - Make ``nonlocal`` raise ``SyntaxError`` instead of silently failing in async
1463 - Make ``nonlocal`` raise ``SyntaxError`` instead of silently failing in async
1446 mode. :ghpull:`11382`
1464 mode. :ghpull:`11382`
1447
1465
1448 - Fix mishandling of magics and ``= !`` assignment just after a dedent in
1466 - Fix mishandling of magics and ``= !`` assignment just after a dedent in
1449 nested code blocks :ghpull:`11418`
1467 nested code blocks :ghpull:`11418`
1450
1468
1451 - Fix instructions for custom shortcuts :ghpull:`11426`
1469 - Fix instructions for custom shortcuts :ghpull:`11426`
1452
1470
1453
1471
1454 Notable Internals improvements:
1472 Notable Internals improvements:
1455
1473
1456 - Use of ``os.scandir`` (Python 3 only) to speed up some file system operations.
1474 - Use of ``os.scandir`` (Python 3 only) to speed up some file system operations.
1457 :ghpull:`11365`
1475 :ghpull:`11365`
1458
1476
1459 - use ``perf_counter`` instead of ``clock`` for more precise
1477 - use ``perf_counter`` instead of ``clock`` for more precise
1460 timing results with ``%time`` :ghpull:`11376`
1478 timing results with ``%time`` :ghpull:`11376`
1461
1479
1462 Many thanks to all the contributors and in particular to ``bartskowron`` and
1480 Many thanks to all the contributors and in particular to ``bartskowron`` and
1463 ``tonyfast`` who handled some pretty complicated bugs in the input machinery. We
1481 ``tonyfast`` who handled some pretty complicated bugs in the input machinery. We
1464 had a number of first time contributors and maybe hacktoberfest participants that
1482 had a number of first time contributors and maybe hacktoberfest participants that
1465 made significant contributions and helped us free some time to focus on more
1483 made significant contributions and helped us free some time to focus on more
1466 complicated bugs.
1484 complicated bugs.
1467
1485
1468 You
1486 You
1469 can see all the closed issues and Merged PR, new features and fixes `here
1487 can see all the closed issues and Merged PR, new features and fixes `here
1470 <https://github.com/ipython/ipython/issues?utf8=%E2%9C%93&q=+is%3Aclosed+milestone%3A7.1+>`_.
1488 <https://github.com/ipython/ipython/issues?utf8=%E2%9C%93&q=+is%3Aclosed+milestone%3A7.1+>`_.
1471
1489
1472 Unicode Completion update
1490 Unicode Completion update
1473 -------------------------
1491 -------------------------
1474
1492
1475 In IPython 7.1 the Unicode completion map has been updated and synchronized with
1493 In IPython 7.1 the Unicode completion map has been updated and synchronized with
1476 the Julia language.
1494 the Julia language.
1477
1495
1478 Added and removed character characters:
1496 Added and removed character characters:
1479
1497
1480 ``\jmath`` (``ȷ``), ``\\underleftrightarrow`` (U+034D, combining) have been
1498 ``\jmath`` (``ȷ``), ``\\underleftrightarrow`` (U+034D, combining) have been
1481 added, while ``\\textasciicaron`` have been removed
1499 added, while ``\\textasciicaron`` have been removed
1482
1500
1483 Some sequences have seen their prefix removed:
1501 Some sequences have seen their prefix removed:
1484
1502
1485 - 6 characters ``\text...<tab>`` should now be inputed with ``\...<tab>`` directly,
1503 - 6 characters ``\text...<tab>`` should now be inputed with ``\...<tab>`` directly,
1486 - 45 characters ``\Elz...<tab>`` should now be inputed with ``\...<tab>`` directly,
1504 - 45 characters ``\Elz...<tab>`` should now be inputed with ``\...<tab>`` directly,
1487 - 65 characters ``\B...<tab>`` should now be inputed with ``\...<tab>`` directly,
1505 - 65 characters ``\B...<tab>`` should now be inputed with ``\...<tab>`` directly,
1488 - 450 characters ``\m...<tab>`` should now be inputed with ``\...<tab>`` directly,
1506 - 450 characters ``\m...<tab>`` should now be inputed with ``\...<tab>`` directly,
1489
1507
1490 Some sequences have seen their prefix shortened:
1508 Some sequences have seen their prefix shortened:
1491
1509
1492 - 5 characters ``\mitBbb...<tab>`` should now be inputed with ``\bbi...<tab>`` directly,
1510 - 5 characters ``\mitBbb...<tab>`` should now be inputed with ``\bbi...<tab>`` directly,
1493 - 52 characters ``\mit...<tab>`` should now be inputed with ``\i...<tab>`` directly,
1511 - 52 characters ``\mit...<tab>`` should now be inputed with ``\i...<tab>`` directly,
1494 - 216 characters ``\mbfit...<tab>`` should now be inputed with ``\bi...<tab>`` directly,
1512 - 216 characters ``\mbfit...<tab>`` should now be inputed with ``\bi...<tab>`` directly,
1495 - 222 characters ``\mbf...<tab>`` should now be inputed with ``\b...<tab>`` directly,
1513 - 222 characters ``\mbf...<tab>`` should now be inputed with ``\b...<tab>`` directly,
1496
1514
1497 A couple of characters had their sequence simplified:
1515 A couple of characters had their sequence simplified:
1498
1516
1499 - ``ð``, type ``\dh<tab>``, instead of ``\eth<tab>``
1517 - ``ð``, type ``\dh<tab>``, instead of ``\eth<tab>``
1500 - ``ħ``, type ``\hbar<tab>``, instead of ``\Elzxh<tab>``
1518 - ``ħ``, type ``\hbar<tab>``, instead of ``\Elzxh<tab>``
1501 - ``ɸ``, type ``\ltphi<tab>``, instead of ``\textphi<tab>``
1519 - ``ɸ``, type ``\ltphi<tab>``, instead of ``\textphi<tab>``
1502 - ``ϴ``, type ``\varTheta<tab>``, instead of ``\textTheta<tab>``
1520 - ``ϴ``, type ``\varTheta<tab>``, instead of ``\textTheta<tab>``
1503 - ``ℇ``, type ``\eulermascheroni<tab>``, instead of ``\Eulerconst<tab>``
1521 - ``ℇ``, type ``\eulermascheroni<tab>``, instead of ``\Eulerconst<tab>``
1504 - ``ℎ``, type ``\planck<tab>``, instead of ``\Planckconst<tab>``
1522 - ``ℎ``, type ``\planck<tab>``, instead of ``\Planckconst<tab>``
1505
1523
1506 - U+0336 (COMBINING LONG STROKE OVERLAY), type ``\strike<tab>``, instead of ``\Elzbar<tab>``.
1524 - U+0336 (COMBINING LONG STROKE OVERLAY), type ``\strike<tab>``, instead of ``\Elzbar<tab>``.
1507
1525
1508 A couple of sequences have been updated:
1526 A couple of sequences have been updated:
1509
1527
1510 - ``\varepsilon`` now gives ``ɛ`` (GREEK SMALL LETTER EPSILON) instead of ``ε`` (GREEK LUNATE EPSILON SYMBOL),
1528 - ``\varepsilon`` now gives ``ɛ`` (GREEK SMALL LETTER EPSILON) instead of ``ε`` (GREEK LUNATE EPSILON SYMBOL),
1511 - ``\underbar`` now gives U+0331 (COMBINING MACRON BELOW) instead of U+0332 (COMBINING LOW LINE).
1529 - ``\underbar`` now gives U+0331 (COMBINING MACRON BELOW) instead of U+0332 (COMBINING LOW LINE).
1512
1530
1513
1531
1514 .. _whatsnew700:
1532 .. _whatsnew700:
1515
1533
1516 IPython 7.0.0
1534 IPython 7.0.0
1517 =============
1535 =============
1518
1536
1519 Released Thursday September 27th, 2018
1537 Released Thursday September 27th, 2018
1520
1538
1521 IPython 7 includes major feature improvements.
1539 IPython 7 includes major feature improvements.
1522 This is also the second major version of IPython to support only
1540 This is also the second major version of IPython to support only
1523 Python 3 – starting at Python 3.4. Python 2 is still community-supported
1541 Python 3 – starting at Python 3.4. Python 2 is still community-supported
1524 on the bugfix only 5.x branch, but we remind you that Python 2 "end of life"
1542 on the bugfix only 5.x branch, but we remind you that Python 2 "end of life"
1525 is on Jan 1st 2020.
1543 is on Jan 1st 2020.
1526
1544
1527 We were able to backport bug fixes to the 5.x branch thanks to our backport bot which
1545 We were able to backport bug fixes to the 5.x branch thanks to our backport bot which
1528 backported more than `70 Pull-Requests
1546 backported more than `70 Pull-Requests
1529 <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>`_
1547 <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>`_
1530
1548
1531 The IPython 6.x branch will likely not see any further release unless critical
1549 The IPython 6.x branch will likely not see any further release unless critical
1532 bugs are found.
1550 bugs are found.
1533
1551
1534 Make sure you have pip > 9.0 before upgrading. You should be able to update by running:
1552 Make sure you have pip > 9.0 before upgrading. You should be able to update by running:
1535
1553
1536 .. code::
1554 .. code::
1537
1555
1538 pip install ipython --upgrade
1556 pip install ipython --upgrade
1539
1557
1540 .. only:: ipydev
1558 .. only:: ipydev
1541
1559
1542 If you are trying to install or update an ``alpha``, ``beta``, or ``rc``
1560 If you are trying to install or update an ``alpha``, ``beta``, or ``rc``
1543 version, use pip ``--pre`` flag.
1561 version, use pip ``--pre`` flag.
1544
1562
1545 .. code::
1563 .. code::
1546
1564
1547 pip install ipython --upgrade --pre
1565 pip install ipython --upgrade --pre
1548
1566
1549
1567
1550 Or, if you have conda installed:
1568 Or, if you have conda installed:
1551
1569
1552 .. code::
1570 .. code::
1553
1571
1554 conda install ipython
1572 conda install ipython
1555
1573
1556
1574
1557
1575
1558 Prompt Toolkit 2.0
1576 Prompt Toolkit 2.0
1559 ------------------
1577 ------------------
1560
1578
1561 IPython 7.0+ now uses ``prompt_toolkit 2.0``. If you still need to use an earlier
1579 IPython 7.0+ now uses ``prompt_toolkit 2.0``. If you still need to use an earlier
1562 ``prompt_toolkit`` version, you may need to pin IPython to ``<7.0``.
1580 ``prompt_toolkit`` version, you may need to pin IPython to ``<7.0``.
1563
1581
1564 Autowait: Asynchronous REPL
1582 Autowait: Asynchronous REPL
1565 ---------------------------
1583 ---------------------------
1566
1584
1567 Staring with IPython 7.0 on Python 3.6+, IPython can automatically ``await``
1585 Staring with IPython 7.0 on Python 3.6+, IPython can automatically ``await``
1568 top level code. You should not need to access an event loop or runner
1586 top level code. You should not need to access an event loop or runner
1569 yourself. To learn more, read the :ref:`autoawait` section of our docs, see
1587 yourself. To learn more, read the :ref:`autoawait` section of our docs, see
1570 :ghpull:`11265`, or try the following code::
1588 :ghpull:`11265`, or try the following code::
1571
1589
1572 Python 3.6.0
1590 Python 3.6.0
1573 Type 'copyright', 'credits' or 'license' for more information
1591 Type 'copyright', 'credits' or 'license' for more information
1574 IPython 7.0.0 -- An enhanced Interactive Python. Type '?' for help.
1592 IPython 7.0.0 -- An enhanced Interactive Python. Type '?' for help.
1575
1593
1576 In [1]: import aiohttp
1594 In [1]: import aiohttp
1577 ...: result = aiohttp.get('https://api.github.com')
1595 ...: result = aiohttp.get('https://api.github.com')
1578
1596
1579 In [2]: response = await result
1597 In [2]: response = await result
1580 <pause for a few 100s ms>
1598 <pause for a few 100s ms>
1581
1599
1582 In [3]: await response.json()
1600 In [3]: await response.json()
1583 Out[3]:
1601 Out[3]:
1584 {'authorizations_url': 'https://api.github.com/authorizations',
1602 {'authorizations_url': 'https://api.github.com/authorizations',
1585 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
1603 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
1586 ...
1604 ...
1587 }
1605 }
1588
1606
1589 .. note::
1607 .. note::
1590
1608
1591 Async integration is experimental code, behavior may change or be removed
1609 Async integration is experimental code, behavior may change or be removed
1592 between Python and IPython versions without warnings.
1610 between Python and IPython versions without warnings.
1593
1611
1594 Integration is by default with `asyncio`, but other libraries can be configured --
1612 Integration is by default with `asyncio`, but other libraries can be configured --
1595 like ``curio`` or ``trio`` -- to improve concurrency in the REPL::
1613 like ``curio`` or ``trio`` -- to improve concurrency in the REPL::
1596
1614
1597 In [1]: %autoawait trio
1615 In [1]: %autoawait trio
1598
1616
1599 In [2]: import trio
1617 In [2]: import trio
1600
1618
1601 In [3]: async def child(i):
1619 In [3]: async def child(i):
1602 ...: print(" child %s goes to sleep"%i)
1620 ...: print(" child %s goes to sleep"%i)
1603 ...: await trio.sleep(2)
1621 ...: await trio.sleep(2)
1604 ...: print(" child %s wakes up"%i)
1622 ...: print(" child %s wakes up"%i)
1605
1623
1606 In [4]: print('parent start')
1624 In [4]: print('parent start')
1607 ...: async with trio.open_nursery() as n:
1625 ...: async with trio.open_nursery() as n:
1608 ...: for i in range(3):
1626 ...: for i in range(3):
1609 ...: n.spawn(child, i)
1627 ...: n.spawn(child, i)
1610 ...: print('parent end')
1628 ...: print('parent end')
1611 parent start
1629 parent start
1612 child 2 goes to sleep
1630 child 2 goes to sleep
1613 child 0 goes to sleep
1631 child 0 goes to sleep
1614 child 1 goes to sleep
1632 child 1 goes to sleep
1615 <about 2 seconds pause>
1633 <about 2 seconds pause>
1616 child 2 wakes up
1634 child 2 wakes up
1617 child 1 wakes up
1635 child 1 wakes up
1618 child 0 wakes up
1636 child 0 wakes up
1619 parent end
1637 parent end
1620
1638
1621 See :ref:`autoawait` for more information.
1639 See :ref:`autoawait` for more information.
1622
1640
1623
1641
1624 Asynchronous code in a Notebook interface or any other frontend using the
1642 Asynchronous code in a Notebook interface or any other frontend using the
1625 Jupyter Protocol will require further updates to the IPykernel package.
1643 Jupyter Protocol will require further updates to the IPykernel package.
1626
1644
1627 Non-Asynchronous code
1645 Non-Asynchronous code
1628 ~~~~~~~~~~~~~~~~~~~~~
1646 ~~~~~~~~~~~~~~~~~~~~~
1629
1647
1630 As the internal API of IPython is now asynchronous, IPython needs to run under
1648 As the internal API of IPython is now asynchronous, IPython needs to run under
1631 an event loop. In order to allow many workflows, (like using the :magic:`%run`
1649 an event loop. In order to allow many workflows, (like using the :magic:`%run`
1632 magic, or copy-pasting code that explicitly starts/stop event loop), when
1650 magic, or copy-pasting code that explicitly starts/stop event loop), when
1633 top-level code is detected as not being asynchronous, IPython code is advanced
1651 top-level code is detected as not being asynchronous, IPython code is advanced
1634 via a pseudo-synchronous runner, and may not advance pending tasks.
1652 via a pseudo-synchronous runner, and may not advance pending tasks.
1635
1653
1636 Change to Nested Embed
1654 Change to Nested Embed
1637 ~~~~~~~~~~~~~~~~~~~~~~
1655 ~~~~~~~~~~~~~~~~~~~~~~
1638
1656
1639 The introduction of the ability to run async code had some effect on the
1657 The introduction of the ability to run async code had some effect on the
1640 ``IPython.embed()`` API. By default, embed will not allow you to run asynchronous
1658 ``IPython.embed()`` API. By default, embed will not allow you to run asynchronous
1641 code unless an event loop is specified.
1659 code unless an event loop is specified.
1642
1660
1643 Effects on Magics
1661 Effects on Magics
1644 ~~~~~~~~~~~~~~~~~
1662 ~~~~~~~~~~~~~~~~~
1645
1663
1646 Some magics will not work with async until they're updated.
1664 Some magics will not work with async until they're updated.
1647 Contributions welcome.
1665 Contributions welcome.
1648
1666
1649 Expected Future changes
1667 Expected Future changes
1650 ~~~~~~~~~~~~~~~~~~~~~~~
1668 ~~~~~~~~~~~~~~~~~~~~~~~
1651
1669
1652 We expect more internal but public IPython functions to become ``async``, and
1670 We expect more internal but public IPython functions to become ``async``, and
1653 will likely end up having a persistent event loop while IPython is running.
1671 will likely end up having a persistent event loop while IPython is running.
1654
1672
1655 Thanks
1673 Thanks
1656 ~~~~~~
1674 ~~~~~~
1657
1675
1658 This release took more than a year in the making.
1676 This release took more than a year in the making.
1659 The code was rebased a number of
1677 The code was rebased a number of
1660 times; leading to commit authorship that may have been lost in the final
1678 times; leading to commit authorship that may have been lost in the final
1661 Pull-Request. Huge thanks to many people for contribution, discussion, code,
1679 Pull-Request. Huge thanks to many people for contribution, discussion, code,
1662 documentation, use-cases: dalejung, danielballan, ellisonbg, fperez, gnestor,
1680 documentation, use-cases: dalejung, danielballan, ellisonbg, fperez, gnestor,
1663 minrk, njsmith, pganssle, tacaswell, takluyver , vidartf ... And many others.
1681 minrk, njsmith, pganssle, tacaswell, takluyver , vidartf ... And many others.
1664
1682
1665
1683
1666 Autoreload Improvement
1684 Autoreload Improvement
1667 ----------------------
1685 ----------------------
1668
1686
1669 The magic :magic:`%autoreload 2 <autoreload>` now captures new methods added to
1687 The magic :magic:`%autoreload 2 <autoreload>` now captures new methods added to
1670 classes. Earlier, only methods existing as of the initial import were being
1688 classes. Earlier, only methods existing as of the initial import were being
1671 tracked and updated.
1689 tracked and updated.
1672
1690
1673 This new feature helps dual environment development - Jupyter+IDE - where the
1691 This new feature helps dual environment development - Jupyter+IDE - where the
1674 code gradually moves from notebook cells to package files as it gets
1692 code gradually moves from notebook cells to package files as it gets
1675 structured.
1693 structured.
1676
1694
1677 **Example**: An instance of the class ``MyClass`` will be able to access the
1695 **Example**: An instance of the class ``MyClass`` will be able to access the
1678 method ``cube()`` after it is uncommented and the file ``file1.py`` is saved on
1696 method ``cube()`` after it is uncommented and the file ``file1.py`` is saved on
1679 disk.
1697 disk.
1680
1698
1681
1699
1682 .. code::
1700 .. code::
1683
1701
1684 # notebook
1702 # notebook
1685
1703
1686 from mymodule import MyClass
1704 from mymodule import MyClass
1687 first = MyClass(5)
1705 first = MyClass(5)
1688
1706
1689 .. code::
1707 .. code::
1690
1708
1691 # mymodule/file1.py
1709 # mymodule/file1.py
1692
1710
1693 class MyClass:
1711 class MyClass:
1694
1712
1695 def __init__(self, a=10):
1713 def __init__(self, a=10):
1696 self.a = a
1714 self.a = a
1697
1715
1698 def square(self):
1716 def square(self):
1699 print('compute square')
1717 print('compute square')
1700 return self.a*self.a
1718 return self.a*self.a
1701
1719
1702 # def cube(self):
1720 # def cube(self):
1703 # print('compute cube')
1721 # print('compute cube')
1704 # return self.a*self.a*self.a
1722 # return self.a*self.a*self.a
1705
1723
1706
1724
1707
1725
1708
1726
1709 Misc
1727 Misc
1710 ----
1728 ----
1711
1729
1712 The autoindent feature that was deprecated in 5.x was re-enabled and
1730 The autoindent feature that was deprecated in 5.x was re-enabled and
1713 un-deprecated in :ghpull:`11257`
1731 un-deprecated in :ghpull:`11257`
1714
1732
1715 Make :magic:`%run -n -i ... <run>` work correctly. Earlier, if :magic:`%run` was
1733 Make :magic:`%run -n -i ... <run>` work correctly. Earlier, if :magic:`%run` was
1716 passed both arguments, ``-n`` would be silently ignored. See :ghpull:`10308`
1734 passed both arguments, ``-n`` would be silently ignored. See :ghpull:`10308`
1717
1735
1718
1736
1719 The :cellmagic:`%%script` (as well as :cellmagic:`%%bash`,
1737 The :cellmagic:`%%script` (as well as :cellmagic:`%%bash`,
1720 :cellmagic:`%%ruby`... ) cell magics now raise by default if the return code of
1738 :cellmagic:`%%ruby`... ) cell magics now raise by default if the return code of
1721 the given code is non-zero (thus halting execution of further cells in a
1739 the given code is non-zero (thus halting execution of further cells in a
1722 notebook). The behavior can be disable by passing the ``--no-raise-error`` flag.
1740 notebook). The behavior can be disable by passing the ``--no-raise-error`` flag.
1723
1741
1724
1742
1725 Deprecations
1743 Deprecations
1726 ------------
1744 ------------
1727
1745
1728 A couple of unused functions and methods have been deprecated and will be removed
1746 A couple of unused functions and methods have been deprecated and will be removed
1729 in future versions:
1747 in future versions:
1730
1748
1731 - ``IPython.utils.io.raw_print_err``
1749 - ``IPython.utils.io.raw_print_err``
1732 - ``IPython.utils.io.raw_print``
1750 - ``IPython.utils.io.raw_print``
1733
1751
1734
1752
1735 Backwards incompatible changes
1753 Backwards incompatible changes
1736 ------------------------------
1754 ------------------------------
1737
1755
1738 * The API for transforming input before it is parsed as Python code has been
1756 * The API for transforming input before it is parsed as Python code has been
1739 completely redesigned: any custom input transformations will need to be
1757 completely redesigned: any custom input transformations will need to be
1740 rewritten. See :doc:`/config/inputtransforms` for details of the new API.
1758 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