##// END OF EJS Templates
Backport PR #12868: Misc CI warning and error.
Matthias Bussonnier -
Show More
@@ -1,459 +1,459 b''
1 1 # Copyright (c) IPython Development Team.
2 2 # Distributed under the terms of the Modified BSD License.
3 3
4 4 import json
5 5 import os
6 6 import warnings
7 7
8 8 from unittest import mock
9 9
10 10 import nose.tools as nt
11 11
12 12 from IPython.core import display
13 13 from IPython.core.getipython import get_ipython
14 14 from IPython.utils.io import capture_output
15 15 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
16 16 from IPython import paths as ipath
17 17 from IPython.testing.tools import AssertNotPrints
18 18
19 19 import IPython.testing.decorators as dec
20 20
21 21 def test_image_size():
22 22 """Simple test for display.Image(args, width=x,height=y)"""
23 23 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
24 24 img = display.Image(url=thisurl, width=200, height=200)
25 25 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
26 26 img = display.Image(url=thisurl, metadata={'width':200, 'height':200})
27 27 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
28 28 img = display.Image(url=thisurl, width=200)
29 29 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
30 30 img = display.Image(url=thisurl)
31 31 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
32 32 img = display.Image(url=thisurl, unconfined=True)
33 33 nt.assert_equal(u'<img src="%s" class="unconfined"/>' % (thisurl), img._repr_html_())
34 34
35 35
36 36 def test_image_mimes():
37 37 fmt = get_ipython().display_formatter.format
38 38 for format in display.Image._ACCEPTABLE_EMBEDDINGS:
39 39 mime = display.Image._MIMETYPES[format]
40 40 img = display.Image(b'garbage', format=format)
41 41 data, metadata = fmt(img)
42 42 nt.assert_equal(sorted(data), sorted([mime, 'text/plain']))
43 43
44 44
45 45 def test_geojson():
46 46
47 47 gj = display.GeoJSON(data={
48 48 "type": "Feature",
49 49 "geometry": {
50 50 "type": "Point",
51 51 "coordinates": [-81.327, 296.038]
52 52 },
53 53 "properties": {
54 54 "name": "Inca City"
55 55 }
56 56 },
57 57 url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
58 58 layer_options={
59 59 "basemap_id": "celestia_mars-shaded-16k_global",
60 60 "attribution": "Celestia/praesepe",
61 61 "minZoom": 0,
62 62 "maxZoom": 18,
63 63 })
64 64 nt.assert_equal(u'<IPython.core.display.GeoJSON object>', str(gj))
65 65
66 66 def test_retina_png():
67 67 here = os.path.dirname(__file__)
68 68 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
69 69 nt.assert_equal(img.height, 1)
70 70 nt.assert_equal(img.width, 1)
71 71 data, md = img._repr_png_()
72 72 nt.assert_equal(md['width'], 1)
73 73 nt.assert_equal(md['height'], 1)
74 74
75 75 def test_embed_svg_url():
76 76 import gzip
77 77 from io import BytesIO
78 78 svg_data = b'<svg><circle x="0" y="0" r="1"/></svg>'
79 79 url = 'http://test.com/circle.svg'
80 80
81 81 gzip_svg = BytesIO()
82 82 with gzip.open(gzip_svg, 'wb') as fp:
83 83 fp.write(svg_data)
84 84 gzip_svg = gzip_svg.getvalue()
85 85
86 86 def mocked_urlopen(*args, **kwargs):
87 87 class MockResponse:
88 88 def __init__(self, svg):
89 89 self._svg_data = svg
90 90 self.headers = {'content-type': 'image/svg+xml'}
91 91
92 92 def read(self):
93 93 return self._svg_data
94 94
95 95 if args[0] == url:
96 96 return MockResponse(svg_data)
97 97 elif args[0] == url + 'z':
98 98 ret= MockResponse(gzip_svg)
99 99 ret.headers['content-encoding']= 'gzip'
100 100 return ret
101 101 return MockResponse(None)
102 102
103 103 with mock.patch('urllib.request.urlopen', side_effect=mocked_urlopen):
104 104 svg = display.SVG(url=url)
105 105 nt.assert_true(svg._repr_svg_().startswith('<svg'))
106 106 svg = display.SVG(url=url + 'z')
107 107 nt.assert_true(svg._repr_svg_().startswith('<svg'))
108 108
109 109 def test_retina_jpeg():
110 110 here = os.path.dirname(__file__)
111 111 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
112 112 nt.assert_equal(img.height, 1)
113 113 nt.assert_equal(img.width, 1)
114 114 data, md = img._repr_jpeg_()
115 115 nt.assert_equal(md['width'], 1)
116 116 nt.assert_equal(md['height'], 1)
117 117
118 118 def test_base64image():
119 119 display.Image("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BCRQnOqNu0b4AAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC")
120 120
121 121 def test_image_filename_defaults():
122 122 '''test format constraint, and validity of jpeg and png'''
123 123 tpath = ipath.get_ipython_package_dir()
124 124 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.zip'),
125 125 embed=True)
126 126 nt.assert_raises(ValueError, display.Image)
127 127 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
128 128 # check boths paths to allow packages to test at build and install time
129 129 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
130 130 img = display.Image(filename=imgfile)
131 131 nt.assert_equal('png', img.format)
132 132 nt.assert_is_not_none(img._repr_png_())
133 133 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
134 134 nt.assert_equal('jpeg', img.format)
135 135 nt.assert_is_none(img._repr_jpeg_())
136 136
137 137 def _get_inline_config():
138 138 from ipykernel.pylab.config import InlineBackend
139 139 return InlineBackend.instance()
140 140
141 141
142 142 @dec.skip_without("ipykernel")
143 143 @dec.skip_without("matplotlib")
144 144 def test_set_matplotlib_close():
145 145 cfg = _get_inline_config()
146 146 cfg.close_figures = False
147 147 display.set_matplotlib_close()
148 148 assert cfg.close_figures
149 149 display.set_matplotlib_close(False)
150 150 assert not cfg.close_figures
151 151
152 152 _fmt_mime_map = {
153 153 'png': 'image/png',
154 154 'jpeg': 'image/jpeg',
155 155 'pdf': 'application/pdf',
156 156 'retina': 'image/png',
157 157 'svg': 'image/svg+xml',
158 158 }
159 159
160 160 @dec.skip_without('matplotlib')
161 161 def test_set_matplotlib_formats():
162 162 from matplotlib.figure import Figure
163 163 formatters = get_ipython().display_formatter.formatters
164 164 for formats in [
165 165 ('png',),
166 166 ('pdf', 'svg'),
167 167 ('jpeg', 'retina', 'png'),
168 168 (),
169 169 ]:
170 170 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
171 171 display.set_matplotlib_formats(*formats)
172 172 for mime, f in formatters.items():
173 173 if mime in active_mimes:
174 174 nt.assert_in(Figure, f)
175 175 else:
176 176 nt.assert_not_in(Figure, f)
177 177
178 178
179 179 @dec.skip_without("ipykernel")
180 180 @dec.skip_without("matplotlib")
181 181 def test_set_matplotlib_formats_kwargs():
182 182 from matplotlib.figure import Figure
183 183 ip = get_ipython()
184 184 cfg = _get_inline_config()
185 185 cfg.print_figure_kwargs.update(dict(foo='bar'))
186 kwargs = dict(quality=10)
186 kwargs = dict(dpi=150)
187 187 display.set_matplotlib_formats('png', **kwargs)
188 188 formatter = ip.display_formatter.formatters['image/png']
189 189 f = formatter.lookup_by_type(Figure)
190 190 cell = f.__closure__[0].cell_contents
191 191 expected = kwargs
192 192 expected.update(cfg.print_figure_kwargs)
193 193 nt.assert_equal(cell, expected)
194 194
195 195 def test_display_available():
196 196 """
197 197 Test that display is available without import
198 198
199 199 We don't really care if it's in builtin or anything else, but it should
200 200 always be available.
201 201 """
202 202 ip = get_ipython()
203 203 with AssertNotPrints('NameError'):
204 204 ip.run_cell('display')
205 205 try:
206 206 ip.run_cell('del display')
207 207 except NameError:
208 208 pass # it's ok, it might be in builtins
209 209 # even if deleted it should be back
210 210 with AssertNotPrints('NameError'):
211 211 ip.run_cell('display')
212 212
213 213 def test_textdisplayobj_pretty_repr():
214 214 p = display.Pretty("This is a simple test")
215 215 nt.assert_equal(repr(p), '<IPython.core.display.Pretty object>')
216 216 nt.assert_equal(p.data, 'This is a simple test')
217 217
218 218 p._show_mem_addr = True
219 219 nt.assert_equal(repr(p), object.__repr__(p))
220 220
221 221 def test_displayobject_repr():
222 222 h = display.HTML('<br />')
223 223 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
224 224 h._show_mem_addr = True
225 225 nt.assert_equal(repr(h), object.__repr__(h))
226 226 h._show_mem_addr = False
227 227 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
228 228
229 229 j = display.Javascript('')
230 230 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
231 231 j._show_mem_addr = True
232 232 nt.assert_equal(repr(j), object.__repr__(j))
233 233 j._show_mem_addr = False
234 234 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
235 235
236 236 @mock.patch('warnings.warn')
237 237 def test_encourage_iframe_over_html(m_warn):
238 238 display.HTML()
239 239 m_warn.assert_not_called()
240 240
241 241 display.HTML('<br />')
242 242 m_warn.assert_not_called()
243 243
244 244 display.HTML('<html><p>Lots of content here</p><iframe src="http://a.com"></iframe>')
245 245 m_warn.assert_not_called()
246 246
247 247 display.HTML('<iframe src="http://a.com"></iframe>')
248 248 m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
249 249
250 250 m_warn.reset_mock()
251 251 display.HTML('<IFRAME SRC="http://a.com"></IFRAME>')
252 252 m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
253 253
254 254 def test_progress():
255 255 p = display.ProgressBar(10)
256 256 nt.assert_in('0/10',repr(p))
257 257 p.html_width = '100%'
258 258 p.progress = 5
259 259 nt.assert_equal(p._repr_html_(), "<progress style='width:100%' max='10' value='5'></progress>")
260 260
261 261 def test_progress_iter():
262 262 with capture_output(display=False) as captured:
263 263 for i in display.ProgressBar(5):
264 264 out = captured.stdout
265 265 nt.assert_in('{0}/5'.format(i), out)
266 266 out = captured.stdout
267 267 nt.assert_in('5/5', out)
268 268
269 269 def test_json():
270 270 d = {'a': 5}
271 271 lis = [d]
272 272 metadata = [
273 273 {'expanded': False, 'root': 'root'},
274 274 {'expanded': True, 'root': 'root'},
275 275 {'expanded': False, 'root': 'custom'},
276 276 {'expanded': True, 'root': 'custom'},
277 277 ]
278 278 json_objs = [
279 279 display.JSON(d),
280 280 display.JSON(d, expanded=True),
281 281 display.JSON(d, root='custom'),
282 282 display.JSON(d, expanded=True, root='custom'),
283 283 ]
284 284 for j, md in zip(json_objs, metadata):
285 285 nt.assert_equal(j._repr_json_(), (d, md))
286 286
287 287 with warnings.catch_warnings(record=True) as w:
288 288 warnings.simplefilter("always")
289 289 j = display.JSON(json.dumps(d))
290 290 nt.assert_equal(len(w), 1)
291 291 nt.assert_equal(j._repr_json_(), (d, metadata[0]))
292 292
293 293 json_objs = [
294 294 display.JSON(lis),
295 295 display.JSON(lis, expanded=True),
296 296 display.JSON(lis, root='custom'),
297 297 display.JSON(lis, expanded=True, root='custom'),
298 298 ]
299 299 for j, md in zip(json_objs, metadata):
300 300 nt.assert_equal(j._repr_json_(), (lis, md))
301 301
302 302 with warnings.catch_warnings(record=True) as w:
303 303 warnings.simplefilter("always")
304 304 j = display.JSON(json.dumps(lis))
305 305 nt.assert_equal(len(w), 1)
306 306 nt.assert_equal(j._repr_json_(), (lis, metadata[0]))
307 307
308 308 def test_video_embedding():
309 309 """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash"""
310 310 v = display.Video("http://ignored")
311 311 assert not v.embed
312 312 html = v._repr_html_()
313 313 nt.assert_not_in('src="data:', html)
314 314 nt.assert_in('src="http://ignored"', html)
315 315
316 316 with nt.assert_raises(ValueError):
317 317 v = display.Video(b'abc')
318 318
319 319 with NamedFileInTemporaryDirectory('test.mp4') as f:
320 320 f.write(b'abc')
321 321 f.close()
322 322
323 323 v = display.Video(f.name)
324 324 assert not v.embed
325 325 html = v._repr_html_()
326 326 nt.assert_not_in('src="data:', html)
327 327
328 328 v = display.Video(f.name, embed=True)
329 329 html = v._repr_html_()
330 330 nt.assert_in('src="data:video/mp4;base64,YWJj"',html)
331 331
332 332 v = display.Video(f.name, embed=True, mimetype='video/other')
333 333 html = v._repr_html_()
334 334 nt.assert_in('src="data:video/other;base64,YWJj"',html)
335 335
336 336 v = display.Video(b'abc', embed=True, mimetype='video/mp4')
337 337 html = v._repr_html_()
338 338 nt.assert_in('src="data:video/mp4;base64,YWJj"',html)
339 339
340 340 v = display.Video(u'YWJj', embed=True, mimetype='video/xyz')
341 341 html = v._repr_html_()
342 342 nt.assert_in('src="data:video/xyz;base64,YWJj"',html)
343 343
344 344 def test_html_metadata():
345 345 s = "<h1>Test</h1>"
346 346 h = display.HTML(s, metadata={"isolated": True})
347 347 nt.assert_equal(h._repr_html_(), (s, {"isolated": True}))
348 348
349 349 def test_display_id():
350 350 ip = get_ipython()
351 351 with mock.patch.object(ip.display_pub, 'publish') as pub:
352 352 handle = display.display('x')
353 353 nt.assert_is(handle, None)
354 354 handle = display.display('y', display_id='secret')
355 355 nt.assert_is_instance(handle, display.DisplayHandle)
356 356 handle2 = display.display('z', display_id=True)
357 357 nt.assert_is_instance(handle2, display.DisplayHandle)
358 358 nt.assert_not_equal(handle.display_id, handle2.display_id)
359 359
360 360 nt.assert_equal(pub.call_count, 3)
361 361 args, kwargs = pub.call_args_list[0]
362 362 nt.assert_equal(args, ())
363 363 nt.assert_equal(kwargs, {
364 364 'data': {
365 365 'text/plain': repr('x')
366 366 },
367 367 'metadata': {},
368 368 })
369 369 args, kwargs = pub.call_args_list[1]
370 370 nt.assert_equal(args, ())
371 371 nt.assert_equal(kwargs, {
372 372 'data': {
373 373 'text/plain': repr('y')
374 374 },
375 375 'metadata': {},
376 376 'transient': {
377 377 'display_id': handle.display_id,
378 378 },
379 379 })
380 380 args, kwargs = pub.call_args_list[2]
381 381 nt.assert_equal(args, ())
382 382 nt.assert_equal(kwargs, {
383 383 'data': {
384 384 'text/plain': repr('z')
385 385 },
386 386 'metadata': {},
387 387 'transient': {
388 388 'display_id': handle2.display_id,
389 389 },
390 390 })
391 391
392 392
393 393 def test_update_display():
394 394 ip = get_ipython()
395 395 with mock.patch.object(ip.display_pub, 'publish') as pub:
396 396 with nt.assert_raises(TypeError):
397 397 display.update_display('x')
398 398 display.update_display('x', display_id='1')
399 399 display.update_display('y', display_id='2')
400 400 args, kwargs = pub.call_args_list[0]
401 401 nt.assert_equal(args, ())
402 402 nt.assert_equal(kwargs, {
403 403 'data': {
404 404 'text/plain': repr('x')
405 405 },
406 406 'metadata': {},
407 407 'transient': {
408 408 'display_id': '1',
409 409 },
410 410 'update': True,
411 411 })
412 412 args, kwargs = pub.call_args_list[1]
413 413 nt.assert_equal(args, ())
414 414 nt.assert_equal(kwargs, {
415 415 'data': {
416 416 'text/plain': repr('y')
417 417 },
418 418 'metadata': {},
419 419 'transient': {
420 420 'display_id': '2',
421 421 },
422 422 'update': True,
423 423 })
424 424
425 425
426 426 def test_display_handle():
427 427 ip = get_ipython()
428 428 handle = display.DisplayHandle()
429 429 nt.assert_is_instance(handle.display_id, str)
430 430 handle = display.DisplayHandle('my-id')
431 431 nt.assert_equal(handle.display_id, 'my-id')
432 432 with mock.patch.object(ip.display_pub, 'publish') as pub:
433 433 handle.display('x')
434 434 handle.update('y')
435 435
436 436 args, kwargs = pub.call_args_list[0]
437 437 nt.assert_equal(args, ())
438 438 nt.assert_equal(kwargs, {
439 439 'data': {
440 440 'text/plain': repr('x')
441 441 },
442 442 'metadata': {},
443 443 'transient': {
444 444 'display_id': handle.display_id,
445 445 }
446 446 })
447 447 args, kwargs = pub.call_args_list[1]
448 448 nt.assert_equal(args, ())
449 449 nt.assert_equal(kwargs, {
450 450 'data': {
451 451 'text/plain': repr('y')
452 452 },
453 453 'metadata': {},
454 454 'transient': {
455 455 'display_id': handle.display_id,
456 456 },
457 457 'update': True,
458 458 })
459 459
@@ -1,654 +1,655 b''
1 1 """Various display related classes.
2 2
3 3 Authors : MinRK, gregcaporaso, dannystaple
4 4 """
5 5 from html import escape as html_escape
6 6 from os.path import exists, isfile, splitext, abspath, join, isdir
7 7 from os import walk, sep, fsdecode
8 8
9 9 from IPython.core.display import DisplayObject, TextDisplayObject
10 10
11 from typing import Tuple
12
11 13 __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument',
12 14 'FileLink', 'FileLinks', 'Code']
13 15
14 16
15 17 class Audio(DisplayObject):
16 18 """Create an audio object.
17 19
18 20 When this object is returned by an input cell or passed to the
19 21 display function, it will result in Audio controls being displayed
20 22 in the frontend (only works in the notebook).
21 23
22 24 Parameters
23 25 ----------
24 26 data : numpy array, list, unicode, str or bytes
25 27 Can be one of
26 28
27 29 * Numpy 1d array containing the desired waveform (mono)
28 30 * Numpy 2d array containing waveforms for each channel.
29 31 Shape=(NCHAN, NSAMPLES). For the standard channel order, see
30 32 http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
31 33 * List of float or integer representing the waveform (mono)
32 34 * String containing the filename
33 35 * Bytestring containing raw PCM data or
34 36 * URL pointing to a file on the web.
35 37
36 38 If the array option is used, the waveform will be normalized.
37 39
38 40 If a filename or url is used, the format support will be browser
39 41 dependent.
40 42 url : unicode
41 43 A URL to download the data from.
42 44 filename : unicode
43 45 Path to a local file to load the data from.
44 46 embed : boolean
45 47 Should the audio data be embedded using a data URI (True) or should
46 48 the original source be referenced. Set this to True if you want the
47 49 audio to playable later with no internet connection in the notebook.
48 50
49 51 Default is `True`, unless the keyword argument `url` is set, then
50 52 default value is `False`.
51 53 rate : integer
52 54 The sampling rate of the raw data.
53 55 Only required when data parameter is being used as an array
54 56 autoplay : bool
55 57 Set to True if the audio should immediately start playing.
56 58 Default is `False`.
57 59 normalize : bool
58 60 Whether audio should be normalized (rescaled) to the maximum possible
59 61 range. Default is `True`. When set to `False`, `data` must be between
60 62 -1 and 1 (inclusive), otherwise an error is raised.
61 63 Applies only when `data` is a list or array of samples; other types of
62 64 audio are never normalized.
63 65
64 66 Examples
65 67 --------
66 68 ::
67 69
68 70 # Generate a sound
69 71 import numpy as np
70 72 framerate = 44100
71 73 t = np.linspace(0,5,framerate*5)
72 74 data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t)
73 75 Audio(data,rate=framerate)
74 76
75 77 # Can also do stereo or more channels
76 78 dataleft = np.sin(2*np.pi*220*t)
77 79 dataright = np.sin(2*np.pi*224*t)
78 80 Audio([dataleft, dataright],rate=framerate)
79 81
80 82 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # From URL
81 83 Audio(url="http://www.w3schools.com/html/horse.ogg")
82 84
83 85 Audio('/path/to/sound.wav') # From file
84 86 Audio(filename='/path/to/sound.ogg')
85 87
86 88 Audio(b'RAW_WAV_DATA..) # From bytes
87 89 Audio(data=b'RAW_WAV_DATA..)
88 90
89 91 See Also
90 92 --------
91 93
92 94 See also the ``Audio`` widgets form the ``ipywidget`` package for more flexibility and options.
93 95
94 96 """
95 97 _read_flags = 'rb'
96 98
97 99 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False, normalize=True, *,
98 100 element_id=None):
99 101 if filename is None and url is None and data is None:
100 102 raise ValueError("No audio data found. Expecting filename, url, or data.")
101 103 if embed is False and url is None:
102 104 raise ValueError("No url found. Expecting url when embed=False")
103 105
104 106 if url is not None and embed is not True:
105 107 self.embed = False
106 108 else:
107 109 self.embed = True
108 110 self.autoplay = autoplay
109 111 self.element_id = element_id
110 112 super(Audio, self).__init__(data=data, url=url, filename=filename)
111 113
112 114 if self.data is not None and not isinstance(self.data, bytes):
113 115 if rate is None:
114 116 raise ValueError("rate must be specified when data is a numpy array or list of audio samples.")
115 117 self.data = Audio._make_wav(data, rate, normalize)
116 118
117 119 def reload(self):
118 120 """Reload the raw data from file or URL."""
119 121 import mimetypes
120 122 if self.embed:
121 123 super(Audio, self).reload()
122 124
123 125 if self.filename is not None:
124 126 self.mimetype = mimetypes.guess_type(self.filename)[0]
125 127 elif self.url is not None:
126 128 self.mimetype = mimetypes.guess_type(self.url)[0]
127 129 else:
128 130 self.mimetype = "audio/wav"
129 131
130 132 @staticmethod
131 133 def _make_wav(data, rate, normalize):
132 134 """ Transform a numpy array to a PCM bytestring """
133 135 from io import BytesIO
134 136 import wave
135 137
136 138 try:
137 139 scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize)
138 140 except ImportError:
139 141 scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize)
140 142
141 143 fp = BytesIO()
142 144 waveobj = wave.open(fp,mode='wb')
143 145 waveobj.setnchannels(nchan)
144 146 waveobj.setframerate(rate)
145 147 waveobj.setsampwidth(2)
146 148 waveobj.setcomptype('NONE','NONE')
147 149 waveobj.writeframes(scaled)
148 150 val = fp.getvalue()
149 151 waveobj.close()
150 152
151 153 return val
152 154
153 155 @staticmethod
154 def _validate_and_normalize_with_numpy(data, normalize):
156 def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
155 157 import numpy as np
156 158
157 159 data = np.array(data, dtype=float)
158 160 if len(data.shape) == 1:
159 161 nchan = 1
160 162 elif len(data.shape) == 2:
161 163 # In wave files,channels are interleaved. E.g.,
162 164 # "L1R1L2R2..." for stereo. See
163 165 # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
164 166 # for channel ordering
165 167 nchan = data.shape[0]
166 168 data = data.T.ravel()
167 169 else:
168 170 raise ValueError('Array audio input must be a 1D or 2D array')
169 171
170 172 max_abs_value = np.max(np.abs(data))
171 173 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
172 174 scaled = data / normalization_factor * 32767
173 return scaled.astype('<h').tostring(), nchan
174
175 return scaled.astype("<h").tobytes(), nchan
175 176
176 177 @staticmethod
177 178 def _validate_and_normalize_without_numpy(data, normalize):
178 179 import array
179 180 import sys
180 181
181 182 data = array.array('f', data)
182 183
183 184 try:
184 185 max_abs_value = float(max([abs(x) for x in data]))
185 186 except TypeError:
186 187 raise TypeError('Only lists of mono audio are '
187 188 'supported if numpy is not installed')
188 189
189 190 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
190 191 scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
191 192 if sys.byteorder == 'big':
192 193 scaled.byteswap()
193 194 nchan = 1
194 195 return scaled.tobytes(), nchan
195 196
196 197 @staticmethod
197 198 def _get_normalization_factor(max_abs_value, normalize):
198 199 if not normalize and max_abs_value > 1:
199 200 raise ValueError('Audio data must be between -1 and 1 when normalize=False.')
200 201 return max_abs_value if normalize else 1
201 202
202 203 def _data_and_metadata(self):
203 204 """shortcut for returning metadata with url information, if defined"""
204 205 md = {}
205 206 if self.url:
206 207 md['url'] = self.url
207 208 if md:
208 209 return self.data, md
209 210 else:
210 211 return self.data
211 212
212 213 def _repr_html_(self):
213 214 src = """
214 215 <audio {element_id} controls="controls" {autoplay}>
215 216 <source src="{src}" type="{type}" />
216 217 Your browser does not support the audio element.
217 218 </audio>
218 219 """
219 220 return src.format(src=self.src_attr(), type=self.mimetype, autoplay=self.autoplay_attr(),
220 221 element_id=self.element_id_attr())
221 222
222 223 def src_attr(self):
223 224 import base64
224 225 if self.embed and (self.data is not None):
225 226 data = base64=base64.b64encode(self.data).decode('ascii')
226 227 return """data:{type};base64,{base64}""".format(type=self.mimetype,
227 228 base64=data)
228 229 elif self.url is not None:
229 230 return self.url
230 231 else:
231 232 return ""
232 233
233 234 def autoplay_attr(self):
234 235 if(self.autoplay):
235 236 return 'autoplay="autoplay"'
236 237 else:
237 238 return ''
238 239
239 240 def element_id_attr(self):
240 241 if (self.element_id):
241 242 return 'id="{element_id}"'.format(element_id=self.element_id)
242 243 else:
243 244 return ''
244 245
245 246 class IFrame(object):
246 247 """
247 248 Generic class to embed an iframe in an IPython notebook
248 249 """
249 250
250 251 iframe = """
251 252 <iframe
252 253 width="{width}"
253 254 height="{height}"
254 255 src="{src}{params}"
255 256 frameborder="0"
256 257 allowfullscreen
257 258 ></iframe>
258 259 """
259 260
260 261 def __init__(self, src, width, height, **kwargs):
261 262 self.src = src
262 263 self.width = width
263 264 self.height = height
264 265 self.params = kwargs
265 266
266 267 def _repr_html_(self):
267 268 """return the embed iframe"""
268 269 if self.params:
269 270 try:
270 271 from urllib.parse import urlencode # Py 3
271 272 except ImportError:
272 273 from urllib import urlencode
273 274 params = "?" + urlencode(self.params)
274 275 else:
275 276 params = ""
276 277 return self.iframe.format(src=self.src,
277 278 width=self.width,
278 279 height=self.height,
279 280 params=params)
280 281
281 282 class YouTubeVideo(IFrame):
282 283 """Class for embedding a YouTube Video in an IPython session, based on its video id.
283 284
284 285 e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would
285 286 do::
286 287
287 288 vid = YouTubeVideo("foo")
288 289 display(vid)
289 290
290 291 To start from 30 seconds::
291 292
292 293 vid = YouTubeVideo("abc", start=30)
293 294 display(vid)
294 295
295 296 To calculate seconds from time as hours, minutes, seconds use
296 297 :class:`datetime.timedelta`::
297 298
298 299 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
299 300
300 301 Other parameters can be provided as documented at
301 302 https://developers.google.com/youtube/player_parameters#Parameters
302 303
303 304 When converting the notebook using nbconvert, a jpeg representation of the video
304 305 will be inserted in the document.
305 306 """
306 307
307 308 def __init__(self, id, width=400, height=300, **kwargs):
308 309 self.id=id
309 310 src = "https://www.youtube.com/embed/{0}".format(id)
310 311 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
311 312
312 313 def _repr_jpeg_(self):
313 314 # Deferred import
314 315 from urllib.request import urlopen
315 316
316 317 try:
317 318 return urlopen("https://img.youtube.com/vi/{id}/hqdefault.jpg".format(id=self.id)).read()
318 319 except IOError:
319 320 return None
320 321
321 322 class VimeoVideo(IFrame):
322 323 """
323 324 Class for embedding a Vimeo video in an IPython session, based on its video id.
324 325 """
325 326
326 327 def __init__(self, id, width=400, height=300, **kwargs):
327 328 src="https://player.vimeo.com/video/{0}".format(id)
328 329 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
329 330
330 331 class ScribdDocument(IFrame):
331 332 """
332 333 Class for embedding a Scribd document in an IPython session
333 334
334 335 Use the start_page params to specify a starting point in the document
335 336 Use the view_mode params to specify display type one off scroll | slideshow | book
336 337
337 338 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
338 339
339 340 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
340 341 """
341 342
342 343 def __init__(self, id, width=400, height=300, **kwargs):
343 344 src="https://www.scribd.com/embeds/{0}/content".format(id)
344 345 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
345 346
346 347 class FileLink(object):
347 348 """Class for embedding a local file link in an IPython session, based on path
348 349
349 350 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
350 351
351 352 you would do::
352 353
353 354 local_file = FileLink("my/data.txt")
354 355 display(local_file)
355 356
356 357 or in the HTML notebook, just::
357 358
358 359 FileLink("my/data.txt")
359 360 """
360 361
361 362 html_link_str = "<a href='%s' target='_blank'>%s</a>"
362 363
363 364 def __init__(self,
364 365 path,
365 366 url_prefix='',
366 367 result_html_prefix='',
367 368 result_html_suffix='<br>'):
368 369 """
369 370 Parameters
370 371 ----------
371 372 path : str
372 373 path to the file or directory that should be formatted
373 374 url_prefix : str
374 375 prefix to be prepended to all files to form a working link [default:
375 376 '']
376 377 result_html_prefix : str
377 378 text to append to beginning to link [default: '']
378 379 result_html_suffix : str
379 380 text to append at the end of link [default: '<br>']
380 381 """
381 382 if isdir(path):
382 383 raise ValueError("Cannot display a directory using FileLink. "
383 384 "Use FileLinks to display '%s'." % path)
384 385 self.path = fsdecode(path)
385 386 self.url_prefix = url_prefix
386 387 self.result_html_prefix = result_html_prefix
387 388 self.result_html_suffix = result_html_suffix
388 389
389 390 def _format_path(self):
390 391 fp = ''.join([self.url_prefix, html_escape(self.path)])
391 392 return ''.join([self.result_html_prefix,
392 393 self.html_link_str % \
393 394 (fp, html_escape(self.path, quote=False)),
394 395 self.result_html_suffix])
395 396
396 397 def _repr_html_(self):
397 398 """return html link to file
398 399 """
399 400 if not exists(self.path):
400 401 return ("Path (<tt>%s</tt>) doesn't exist. "
401 402 "It may still be in the process of "
402 403 "being generated, or you may have the "
403 404 "incorrect path." % self.path)
404 405
405 406 return self._format_path()
406 407
407 408 def __repr__(self):
408 409 """return absolute path to file
409 410 """
410 411 return abspath(self.path)
411 412
412 413 class FileLinks(FileLink):
413 414 """Class for embedding local file links in an IPython session, based on path
414 415
415 416 e.g. to embed links to files that were generated in the IPython notebook
416 417 under ``my/data``, you would do::
417 418
418 419 local_files = FileLinks("my/data")
419 420 display(local_files)
420 421
421 422 or in the HTML notebook, just::
422 423
423 424 FileLinks("my/data")
424 425 """
425 426 def __init__(self,
426 427 path,
427 428 url_prefix='',
428 429 included_suffixes=None,
429 430 result_html_prefix='',
430 431 result_html_suffix='<br>',
431 432 notebook_display_formatter=None,
432 433 terminal_display_formatter=None,
433 434 recursive=True):
434 435 """
435 436 See :class:`FileLink` for the ``path``, ``url_prefix``,
436 437 ``result_html_prefix`` and ``result_html_suffix`` parameters.
437 438
438 439 included_suffixes : list
439 440 Filename suffixes to include when formatting output [default: include
440 441 all files]
441 442
442 443 notebook_display_formatter : function
443 444 Used to format links for display in the notebook. See discussion of
444 445 formatter functions below.
445 446
446 447 terminal_display_formatter : function
447 448 Used to format links for display in the terminal. See discussion of
448 449 formatter functions below.
449 450
450 451 Formatter functions must be of the form::
451 452
452 453 f(dirname, fnames, included_suffixes)
453 454
454 455 dirname : str
455 456 The name of a directory
456 457 fnames : list
457 458 The files in that directory
458 459 included_suffixes : list
459 460 The file suffixes that should be included in the output (passing None
460 461 meansto include all suffixes in the output in the built-in formatters)
461 462 recursive : boolean
462 463 Whether to recurse into subdirectories. Default is True.
463 464
464 465 The function should return a list of lines that will be printed in the
465 466 notebook (if passing notebook_display_formatter) or the terminal (if
466 467 passing terminal_display_formatter). This function is iterated over for
467 468 each directory in self.path. Default formatters are in place, can be
468 469 passed here to support alternative formatting.
469 470
470 471 """
471 472 if isfile(path):
472 473 raise ValueError("Cannot display a file using FileLinks. "
473 474 "Use FileLink to display '%s'." % path)
474 475 self.included_suffixes = included_suffixes
475 476 # remove trailing slashes for more consistent output formatting
476 477 path = path.rstrip('/')
477 478
478 479 self.path = path
479 480 self.url_prefix = url_prefix
480 481 self.result_html_prefix = result_html_prefix
481 482 self.result_html_suffix = result_html_suffix
482 483
483 484 self.notebook_display_formatter = \
484 485 notebook_display_formatter or self._get_notebook_display_formatter()
485 486 self.terminal_display_formatter = \
486 487 terminal_display_formatter or self._get_terminal_display_formatter()
487 488
488 489 self.recursive = recursive
489 490
490 491 def _get_display_formatter(self,
491 492 dirname_output_format,
492 493 fname_output_format,
493 494 fp_format,
494 495 fp_cleaner=None):
495 496 """ generate built-in formatter function
496 497
497 498 this is used to define both the notebook and terminal built-in
498 499 formatters as they only differ by some wrapper text for each entry
499 500
500 501 dirname_output_format: string to use for formatting directory
501 502 names, dirname will be substituted for a single "%s" which
502 503 must appear in this string
503 504 fname_output_format: string to use for formatting file names,
504 505 if a single "%s" appears in the string, fname will be substituted
505 506 if two "%s" appear in the string, the path to fname will be
506 507 substituted for the first and fname will be substituted for the
507 508 second
508 509 fp_format: string to use for formatting filepaths, must contain
509 510 exactly two "%s" and the dirname will be substituted for the first
510 511 and fname will be substituted for the second
511 512 """
512 513 def f(dirname, fnames, included_suffixes=None):
513 514 result = []
514 515 # begin by figuring out which filenames, if any,
515 516 # are going to be displayed
516 517 display_fnames = []
517 518 for fname in fnames:
518 519 if (isfile(join(dirname,fname)) and
519 520 (included_suffixes is None or
520 521 splitext(fname)[1] in included_suffixes)):
521 522 display_fnames.append(fname)
522 523
523 524 if len(display_fnames) == 0:
524 525 # if there are no filenames to display, don't print anything
525 526 # (not even the directory name)
526 527 pass
527 528 else:
528 529 # otherwise print the formatted directory name followed by
529 530 # the formatted filenames
530 531 dirname_output_line = dirname_output_format % dirname
531 532 result.append(dirname_output_line)
532 533 for fname in display_fnames:
533 534 fp = fp_format % (dirname,fname)
534 535 if fp_cleaner is not None:
535 536 fp = fp_cleaner(fp)
536 537 try:
537 538 # output can include both a filepath and a filename...
538 539 fname_output_line = fname_output_format % (fp, fname)
539 540 except TypeError:
540 541 # ... or just a single filepath
541 542 fname_output_line = fname_output_format % fname
542 543 result.append(fname_output_line)
543 544 return result
544 545 return f
545 546
546 547 def _get_notebook_display_formatter(self,
547 548 spacer="&nbsp;&nbsp;"):
548 549 """ generate function to use for notebook formatting
549 550 """
550 551 dirname_output_format = \
551 552 self.result_html_prefix + "%s/" + self.result_html_suffix
552 553 fname_output_format = \
553 554 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
554 555 fp_format = self.url_prefix + '%s/%s'
555 556 if sep == "\\":
556 557 # Working on a platform where the path separator is "\", so
557 558 # must convert these to "/" for generating a URI
558 559 def fp_cleaner(fp):
559 560 # Replace all occurrences of backslash ("\") with a forward
560 561 # slash ("/") - this is necessary on windows when a path is
561 562 # provided as input, but we must link to a URI
562 563 return fp.replace('\\','/')
563 564 else:
564 565 fp_cleaner = None
565 566
566 567 return self._get_display_formatter(dirname_output_format,
567 568 fname_output_format,
568 569 fp_format,
569 570 fp_cleaner)
570 571
571 572 def _get_terminal_display_formatter(self,
572 573 spacer=" "):
573 574 """ generate function to use for terminal formatting
574 575 """
575 576 dirname_output_format = "%s/"
576 577 fname_output_format = spacer + "%s"
577 578 fp_format = '%s/%s'
578 579
579 580 return self._get_display_formatter(dirname_output_format,
580 581 fname_output_format,
581 582 fp_format)
582 583
583 584 def _format_path(self):
584 585 result_lines = []
585 586 if self.recursive:
586 587 walked_dir = list(walk(self.path))
587 588 else:
588 589 walked_dir = [next(walk(self.path))]
589 590 walked_dir.sort()
590 591 for dirname, subdirs, fnames in walked_dir:
591 592 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
592 593 return '\n'.join(result_lines)
593 594
594 595 def __repr__(self):
595 596 """return newline-separated absolute paths
596 597 """
597 598 result_lines = []
598 599 if self.recursive:
599 600 walked_dir = list(walk(self.path))
600 601 else:
601 602 walked_dir = [next(walk(self.path))]
602 603 walked_dir.sort()
603 604 for dirname, subdirs, fnames in walked_dir:
604 605 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
605 606 return '\n'.join(result_lines)
606 607
607 608
608 609 class Code(TextDisplayObject):
609 610 """Display syntax-highlighted source code.
610 611
611 612 This uses Pygments to highlight the code for HTML and Latex output.
612 613
613 614 Parameters
614 615 ----------
615 616 data : str
616 617 The code as a string
617 618 url : str
618 619 A URL to fetch the code from
619 620 filename : str
620 621 A local filename to load the code from
621 622 language : str
622 623 The short name of a Pygments lexer to use for highlighting.
623 624 If not specified, it will guess the lexer based on the filename
624 625 or the code. Available lexers: http://pygments.org/docs/lexers/
625 626 """
626 627 def __init__(self, data=None, url=None, filename=None, language=None):
627 628 self.language = language
628 629 super().__init__(data=data, url=url, filename=filename)
629 630
630 631 def _get_lexer(self):
631 632 if self.language:
632 633 from pygments.lexers import get_lexer_by_name
633 634 return get_lexer_by_name(self.language)
634 635 elif self.filename:
635 636 from pygments.lexers import get_lexer_for_filename
636 637 return get_lexer_for_filename(self.filename)
637 638 else:
638 639 from pygments.lexers import guess_lexer
639 640 return guess_lexer(self.data)
640 641
641 642 def __repr__(self):
642 643 return self.data
643 644
644 645 def _repr_html_(self):
645 646 from pygments import highlight
646 647 from pygments.formatters import HtmlFormatter
647 648 fmt = HtmlFormatter()
648 649 style = '<style>{}</style>'.format(fmt.get_style_defs('.output_html'))
649 650 return style + highlight(self.data, self._get_lexer(), fmt)
650 651
651 652 def _repr_latex_(self):
652 653 from pygments import highlight
653 654 from pygments.formatters import LatexFormatter
654 655 return highlight(self.data, self._get_lexer(), LatexFormatter())
@@ -1,1280 +1,1282 b''
1 1 ============
2 2 7.x Series
3 3 ============
4 4
5 5 .. _version 7.22:
6 =================
6
7 IPython 7.22
8 ============
7 9
8 10
9 11 Thanks
10 12 ------
11 13
12 14 We have a new team member that you should see more often on the IPython
13 15 repository, BΕ‚aΕΌej Michalik (@MrMino) have been doing regular contributions to
14 16 IPython, and spent time replying to many issues and guiding new users to the
15 17 codebase; they now have triage permissions to the IPython repository and we'll
16 18 work toward giving them more permission in the future.
17 19
18 20 Many thanks to all the contributors to this release you can find all individual
19 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/XX>`_.
21 contributions to this milestone `on github <https://github.com/ipython/ipython/milestone/XX>`__.
20 22
21 23 Thanks as well to organisations, QuantStack for working on debugger
22 24 compatibility for Xeus_python, and the `D. E. Shaw group
23 25 <https://deshaw.com/>` for sponsoring work on IPython and related libraries.
24 26
25 27 .. _version 721:
26 28
27 29 IPython 7.21
28 30 ============
29 31
30 32 IPython 7.21 is the first release we have back on schedule of one release every
31 33 month; it contains a number of minor fixes and improvements, notably, the new
32 34 context command for ipdb
33 35
34 36
35 37 New "context" command in ipdb
36 38 -----------------------------
37 39
38 40 It is now possible to change the number of lines shown in the backtrace
39 41 information in ipdb using "context" command. :ghpull:`12826`
40 42
41 43 (thanks @MrMino, there are other improvement from them on master).
42 44
43 45 Other notable changes in IPython 7.21
44 46 -------------------------------------
45 47
46 48 - Fix some issues on new osx-arm64 :ghpull:`12804`, :ghpull:`12807`.
47 49 - Compatibility with Xeus-Python for debugger protocol, :ghpull:`12809`
48 50 - Misc docs fixes for compatibility and uniformity with Numpydoc.
49 51 :ghpull:`12824`
50 52
51 53
52 54 Thanks
53 55 ------
54 56
55 57 Many thanks to all the contributors to this release you can find all individual
56 contribution to this milestone `on github <https://github.com/ipython/ipython/milestone/83>`_.
58 contribution to this milestone `on github <https://github.com/ipython/ipython/milestone/83>`__.
57 59
58 60
59 61 .. _version 720:
60 62
61 63 IPython 7.20
62 64 ============
63 65
64 66 IPython 7.20 is the accumulation of 3 month of work on IPython, spacing between
65 67 IPython release have been increased from the usual once a month for various
66 68 reason.
67 69
68 70 - Mainly as I'm too busy and the effectively sole maintainer, and
69 71 - Second because not much changes happened before mid December.
70 72
71 73 The main driver for this release was the new version of Jedi 0.18 breaking API;
72 74 which was taken care of in the master branch early in 2020 but not in 7.x as I
73 75 though that by now 8.0 would be out.
74 76
75 77 The inclusion of a resolver in pip did not help and actually made things worse.
76 78 If usually I would have simply pinned Jedi to ``<0.18``; this is not a solution
77 79 anymore as now pip is free to install Jedi 0.18, and downgrade IPython.
78 80
79 81 I'll do my best to keep the regular release, but as the 8.0-dev branch and 7.x
80 82 are starting to diverge this is becoming difficult in particular with my limited
81 83 time, so if you have any cycles to spare I'll appreciate your help to respond to
82 84 issues and pushing 8.0 forward.
83 85
84 86 Here are thus some of the changes for IPython 7.20.
85 87
86 88 - Support for PyQt5 >= 5.11 :ghpull:`12715`
87 89 - ``%reset`` remove imports more agressively :ghpull:`12718`
88 90 - fix the ``%conda`` magic :ghpull:`12739`
89 91 - compatibility with Jedi 0.18, and bump minimum Jedi version. :ghpull:`12793`
90 92
91 93
92 94 .. _version 719:
93 95
94 96 IPython 7.19
95 97 ============
96 98
97 99 IPython 7.19 accumulative two month of works, bug fixes and improvements, there
98 100 was exceptionally no release last month.
99 101
100 102 - Fix to restore the ability to specify more than one extension using command
101 103 line flags when using traitlets 5.0 :ghpull:`12543`
102 104 - Docs docs formatting that make the install commands work on zsh
103 105 :ghpull:`12587`
104 106 - Always display the last frame in tracebacks even if hidden with
105 107 ``__traceback_hide__`` :ghpull:`12601`
106 108 - Avoid an issue where a callback can be registered multiple times.
107 109 :ghpull:`12625`
108 110 - Avoid an issue in debugger mode where frames changes could be lost.
109 111 :ghpull:`12627`
110 112
111 113 - Never hide the frames that invoke a debugger, even if marked as hidden by
112 114 ``__traceback_hide__`` :ghpull:`12631`
113 115 - Fix calling the debugger in a recursive manner :ghpull:`12659`
114 116
115 117
116 118 A number of code changes have landed on master and we are getting close to
117 119 enough new features and codebase improvement that a 8.0 start to make sens.
118 120 For downstream packages, please start working on migrating downstream testing
119 121 away from iptest and using pytest, as nose will not work on Python 3.10 and we
120 122 will likely start removing it as a dependency for testing.
121 123
122 124 .. _version 718:
123 125
124 126 IPython 7.18
125 127 ============
126 128
127 129 IPython 7.18 is a minor release that mostly contains bugfixes.
128 130
129 131 - ``CRLF`` is now handled by magics my default; solving some issues due to copy
130 132 pasting on windows. :ghpull:`12475`
131 133
132 134 - Requiring pexpect ``>=4.3`` as we are Python 3.7+ only and earlier version of
133 135 pexpect will be incompatible. :ghpull:`12510`
134 136
135 137 - Minimum jedi version is now 0.16. :ghpull:`12488`
136 138
137 139
138 140
139 141 .. _version 717:
140 142
141 143 IPython 7.17
142 144 ============
143 145
144 146 IPython 7.17 brings a couple of new improvements to API and a couple of user
145 147 facing changes to make the terminal experience more user friendly.
146 148
147 149 :ghpull:`12407` introduces the ability to pass extra argument to the IPython
148 150 debugger class; this is to help a new project from ``kmaork``
149 151 (https://github.com/kmaork/madbg) to feature a fully remote debugger.
150 152
151 153 :ghpull:`12410` finally remove support for 3.6, while the codebase is still
152 154 technically compatible; IPython will not install on Python 3.6.
153 155
154 156 lots of work on the debugger and hidden frames from ``@impact27`` in
155 157 :ghpull:`12437`, :ghpull:`12445`, :ghpull:`12460` and in particular
156 158 :ghpull:`12453` which make the debug magic more robust at handling spaces.
157 159
158 160 Biggest API addition is code transformation which is done before code execution;
159 161 IPython allows a number of hooks to catch non-valid Python syntax (magic, prompt
160 162 stripping...etc). Transformers are usually called many time; typically:
161 163
162 164 - When trying to figure out whether the code is complete and valid (should we
163 165 insert a new line or execute ?)
164 166 - During actual code execution pass before giving the code to Python's
165 167 ``exec``.
166 168
167 169 This lead to issues when transformer might have had side effects; or do external
168 170 queries. Starting with IPython 7.17 you can expect your transformer to be called
169 171 less time.
170 172
171 173 Input transformers are now called only once in the execution path of
172 174 `InteractiveShell`, allowing to register transformer that potentially have side
173 175 effects (note that this is not recommended). Internal methods `should_run_async`, and
174 176 `run_cell_async` now take a recommended optional `transformed_cell`, and
175 177 `preprocessing_exc_tuple` parameters that will become mandatory at some point in
176 178 the future; that is to say cells need to be explicitly transformed to be valid
177 179 Python syntax ahead of trying to run them. :ghpull:`12440`;
178 180
179 181 ``input_transformers`` can now also have an attribute ``has_side_effects`` set
180 182 to `True`, when this attribute is present; this will prevent the transformers
181 183 from being ran when IPython is trying to guess whether the user input is
182 184 complete. Note that this may means you will need to explicitly execute in some
183 185 case where your transformations are now not ran; but will not affect users with
184 186 no custom extensions.
185 187
186 188
187 189 API Changes
188 190 -----------
189 191
190 192 Change of API and exposed objects automatically detected using `frappuccino
191 193 <https://pypi.org/project/frappuccino/>`_
192 194
193 195
194 196 The following items are new since 7.16.0::
195 197
196 198 + IPython.core.interactiveshell.InteractiveShell.get_local_scope(self, stack_depth)
197 199
198 200 The following signatures differ since 7.16.0::
199 201
200 202 - IPython.core.interactiveshell.InteractiveShell.run_cell_async(self, raw_cell, store_history=False, silent=False, shell_futures=True)
201 203 + 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)
202 204
203 205 - IPython.core.interactiveshell.InteractiveShell.should_run_async(self, raw_cell)
204 206 + IPython.core.interactiveshell.InteractiveShell.should_run_async(self, raw_cell, *, transformed_cell=None, preprocessing_exc_tuple=None)
205 207
206 208 - IPython.terminal.debugger.TerminalPdb.pt_init(self)
207 209 + IPython.terminal.debugger.TerminalPdb.pt_init(self, pt_session_options=None)
208 210
209 211 This method was added::
210 212
211 213 + IPython.core.interactiveshell.InteractiveShell.get_local_scope
212 214
213 215 Which is now also present on subclasses::
214 216
215 217 + IPython.terminal.embed.InteractiveShellEmbed.get_local_scope
216 218 + IPython.terminal.interactiveshell.TerminalInteractiveShell.get_local_scope
217 219
218 220
219 221 .. _version 716:
220 222
221 223 IPython 7.16
222 224 ============
223 225
224 226
225 227 The default traceback mode will now skip frames that are marked with
226 228 ``__tracebackhide__ = True`` and show how many traceback frames have been
227 229 skipped. This can be toggled by using :magic:`xmode` with the ``--show`` or
228 230 ``--hide`` attribute. It will have no effect on non verbose traceback modes.
229 231
230 232 The ipython debugger also now understands ``__tracebackhide__`` as well and will
231 233 skip hidden frames when displaying. Movement up and down the stack will skip the
232 234 hidden frames and will show how many frames were hidden. Internal IPython frames
233 235 are also now hidden by default. The behavior can be changed with the
234 236 ``skip_hidden`` while in the debugger, command and accepts "yes", "no", "true"
235 237 and "false" case insensitive parameters.
236 238
237 239
238 240 Misc Noticeable changes:
239 241 ------------------------
240 242
241 243 - Exceptions are now (re)raised when running notebooks via the :magic:`%run`, helping to catch issues in workflows and
242 244 pipelines. :ghpull:`12301`
243 245 - Fix inputhook for qt 5.15.0 :ghpull:`12355`
244 246 - Fix wx inputhook :ghpull:`12375`
245 247 - Add handling for malformed pathext env var (Windows) :ghpull:`12367`
246 248 - use $SHELL in system_piped :ghpull:`12360` for uniform behavior with
247 249 ipykernel.
248 250
249 251 Reproducible Build
250 252 ------------------
251 253
252 254 IPython 7.15 reproducible build did not work, so we try again this month
253 255 :ghpull:`12358`.
254 256
255 257
256 258 API Changes
257 259 -----------
258 260
259 261 Change of API and exposed objects automatically detected using `frappuccino
260 262 <https://pypi.org/project/frappuccino/>`_ (still in beta):
261 263
262 264
263 265 The following items are new and mostly related to understanding ``__tracebackbhide__``::
264 266
265 267 + IPython.core.debugger.Pdb.do_down(self, arg)
266 268 + IPython.core.debugger.Pdb.do_skip_hidden(self, arg)
267 269 + IPython.core.debugger.Pdb.do_up(self, arg)
268 270 + IPython.core.debugger.Pdb.hidden_frames(self, stack)
269 271 + IPython.core.debugger.Pdb.stop_here(self, frame)
270 272
271 273
272 274 The following items have been removed::
273 275
274 276 - IPython.core.debugger.Pdb.new_do_down
275 277 - IPython.core.debugger.Pdb.new_do_up
276 278
277 279 Those were implementation details.
278 280
279 281
280 282 .. _version 715:
281 283
282 284 IPython 7.15
283 285 ============
284 286
285 287 IPython 7.15 brings a number of bug fixes and user facing improvements.
286 288
287 289 Misc Noticeable changes:
288 290 ------------------------
289 291
290 292 - Long completion name have better elision in terminal :ghpull:`12284`
291 293 - I've started to test on Python 3.9 :ghpull:`12307` and fix some errors.
292 294 - Hi DPI scaling of figures when using qt eventloop :ghpull:`12314`
293 295 - Document the ability to have systemwide configuration for IPython.
294 296 :ghpull:`12328`
295 297 - Fix issues with input autoformatting :ghpull:`12336`
296 298 - ``IPython.core.debugger.Pdb`` is now interruptible (:ghpull:`12168`, in 7.14
297 299 but forgotten in release notes)
298 300 - Video HTML attributes (:ghpull:`12212`, in 7.14 but forgotten in release
299 301 notes)
300 302
301 303 Reproducible Build
302 304 ------------------
303 305
304 306 Starting with IPython 7.15, I am attempting to provide reproducible builds,
305 307 that is to say you should be able from the source tree to generate an sdist
306 308 and wheel that are identical byte for byte with the publish version on PyPI.
307 309
308 310 I've only tested on a couple of machines so far and the process is relatively
309 311 straightforward, so this mean that IPython not only have a deterministic build
310 312 process, but also I have either removed, or put under control all effects of
311 313 the build environments on the final artifact. I encourage you to attempt the
312 314 build process on your machine as documented in :ref:`core_developer_guide`
313 315 and let me know if you do not obtain an identical artifact.
314 316
315 317 While reproducible builds is critical to check that the supply chain of (open
316 318 source) software has not been compromised, it can also help to speedup many
317 319 of the build processes in large environment (conda, apt...) by allowing
318 320 better caching of intermediate build steps.
319 321
320 322 Learn more on `<https://reproducible-builds.org/>`_. `Reflections on trusting
321 323 trust <https://dl.acm.org/doi/10.1145/358198.358210>`_ is also one of the
322 324 cornerstone and recommended reads on this subject.
323 325
324 326 .. note::
325 327
326 328 The build commit from which the sdist is generated is also `signed
327 329 <https://en.wikipedia.org/wiki/Digital_signature>`_, so you should be able to
328 330 check it has not been compromised, and the git repository is a `merkle-tree
329 331 <https://en.wikipedia.org/wiki/Merkle_tree>`_, you can check the consistency
330 332 with `git-fsck <https://git-scm.com/docs/git-fsck>`_ which you likely `want
331 333 to enable by default
332 334 <https://gist.github.com/mbbx6spp/14b86437e794bffb4120>`_.
333 335
334 336 NEP29: Last version to support Python 3.6
335 337 -----------------------------------------
336 338
337 339 IPython 7.15 will be the Last IPython version to officially support Python
338 340 3.6, as stated by `NumPy Enhancement Proposal 29
339 341 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_. Starting with
340 342 next minor version of IPython I may stop testing on Python 3.6 and may stop
341 343 publishing release artifacts that install on Python 3.6
342 344
343 345 Highlighted features
344 346 --------------------
345 347
346 348 Highlighted features are not new, but seem to not be widely known, this
347 349 section will help you discover in more narrative form what you can do with
348 350 IPython.
349 351
350 352 Increase Tab Completion Menu Height
351 353 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
352 354
353 355 In terminal IPython it is possible to increase the hight of the tab-completion
354 356 menu. To do so set the value of
355 357 :configtrait:`TerminalInteractiveShell.space_for_menu`, this will reserve more
356 358 space at the bottom of the screen for various kind of menus in IPython including
357 359 tab completion and searching in history.
358 360
359 361 Autoformat Code in the terminal
360 362 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
361 363
362 364 If you have a preferred code formatter, you can configure IPython to
363 365 reformat your code. Set the value of
364 366 :configtrait:`TerminalInteractiveShell.autoformatter` to for example ``'black'``
365 367 and IPython will auto format your code when possible.
366 368
367 369
368 370 .. _version 714:
369 371
370 372 IPython 7.14
371 373 ============
372 374
373 375 IPython 7.14 is a minor release that fix a couple of bugs and prepare
374 376 compatibility with new or future versions of some libraries.
375 377
376 378 Important changes:
377 379 ------------------
378 380
379 381 - Fix compatibility with Sphinx 3+ :ghpull:`12235`
380 382 - Remove deprecated matplotlib parameter usage, compatibility with matplotlib
381 383 3.3+ :`122250`
382 384
383 385 Misc Changes
384 386 ------------
385 387
386 388 - set ``.py`` extension when editing current buffer in vi/emacs. :ghpull:`12167`
387 389 - support for unicode identifiers in ``?``/``??`` :ghpull:`12208`
388 390 - add extra options to the ``Video`` Rich objects :ghpull:`12212`
389 391 - add pretty-printing to ``SimpleNamespace`` :ghpull:`12230`
390 392
391 393 IPython.core.debugger.Pdb is now interruptible
392 394 ----------------------------------------------
393 395
394 396 A ``KeyboardInterrupt`` will now interrupt IPython's extended debugger, in order to make Jupyter able to interrupt it. (:ghpull:`12168`)
395 397
396 398 Video HTML attributes
397 399 ---------------------
398 400
399 401 Add an option to `IPython.display.Video` to change the attributes of the HTML display of the video (:ghpull:`12212`)
400 402
401 403
402 404 Pending deprecated imports
403 405 --------------------------
404 406
405 407 Many object present in ``IPython.core.display`` are there for internal use only,
406 408 and should already been imported from ``IPython.display`` by users and external
407 409 libraries. Trying to import those from ``IPython.core.display`` is still possible
408 410 but will trigger a
409 411 deprecation warning in later versions of IPython and will become errors in the
410 412 future.
411 413
412 414 This will simplify compatibility with other Python kernels (like Xeus-Python),
413 415 and simplify code base.
414 416
415 417
416 418
417 419
418 420 .. _version 713:
419 421
420 422 IPython 7.13
421 423 ============
422 424
423 425 IPython 7.13 is the final release of the 7.x branch since master is diverging
424 426 toward an 8.0. Exiting new features have already been merged in 8.0 and will
425 427 not be available on the 7.x branch. All the changes below have been backported
426 428 from the master branch.
427 429
428 430
429 431 - Fix inability to run PDB when inside an event loop :ghpull:`12141`
430 432 - Fix ability to interrupt some processes on windows :ghpull:`12137`
431 433 - Fix debugger shortcuts :ghpull:`12132`
432 434 - improve tab completion when inside a string by removing irrelevant elements :ghpull:`12128`
433 435 - Fix display of filename tab completion when the path is long :ghpull:`12122`
434 436 - Many removal of Python 2 specific code path :ghpull:`12110`
435 437 - displaying wav files do not require NumPy anymore, and is 5x to 30x faster :ghpull:`12113`
436 438
437 439 See the list of all closed issues and pull request on `github
438 440 <https://github.com/ipython/ipython/pulls?q=is%3Aclosed+milestone%3A7.13>`_.
439 441
440 442 .. _version 712:
441 443
442 444 IPython 7.12
443 445 ============
444 446
445 447 IPython 7.12 is a minor update that mostly brings code cleanup, removal of
446 448 longtime deprecated function and a couple update to documentation cleanup as well.
447 449
448 450 Notable changes are the following:
449 451
450 452 - Exit non-zero when ipython is given a file path to run that doesn't exist :ghpull:`12074`
451 453 - Test PR on ARM64 with Travis-CI :ghpull:`12073`
452 454 - Update CI to work with latest Pytest :ghpull:`12086`
453 455 - Add infrastructure to run ipykernel eventloop via trio :ghpull:`12097`
454 456 - Support git blame ignore revs :ghpull:`12091`
455 457 - Start multi-line ``__repr__`` s on their own line :ghpull:`12099`
456 458
457 459 .. _version 7111:
458 460
459 461 IPython 7.11.1
460 462 ==============
461 463
462 464 A couple of deprecated functions (no-op) have been reintroduces in py3compat as
463 465 Cython was still relying on them, and will be removed in a couple of versions.
464 466
465 467 .. _version 711:
466 468
467 469 IPython 7.11
468 470 ============
469 471
470 472 IPython 7.11 received a couple of compatibility fixes and code cleanup.
471 473
472 474 A number of function in the ``py3compat`` have been removed; a number of types
473 475 in the IPython code base are now non-ambiguous and now always ``unicode``
474 476 instead of ``Union[Unicode,bytes]``; many of the relevant code path have thus
475 477 been simplified/cleaned and types annotation added.
476 478
477 479 IPython support several verbosity level from exceptions. ``xmode plain`` now
478 480 support chained exceptions. :ghpull:`11999`
479 481
480 482 We are starting to remove ``shell=True`` in some usages of subprocess. While not directly
481 483 a security issue (as IPython is made to run arbitrary code anyway) it is not good
482 484 practice and we'd like to show the example. :ghissue:`12023`. This discussion
483 485 was started by ``@mschwager`` thanks to a new auditing tool they are working on
484 486 with duo-labs (`dlint <https://github.com/duo-labs/dlint>`_).
485 487
486 488 Work around some bugs in Python 3.9 tokenizer :ghpull:`12057`
487 489
488 490 IPython will now print its version after a crash. :ghpull:`11986`
489 491
490 492 This is likely the last release from the 7.x series that will see new feature.
491 493 The master branch will soon accept large code changes and thrilling new
492 494 features; the 7.x branch will only start to accept critical bug fixes, and
493 495 update dependencies.
494 496
495 497 .. _version 7102:
496 498
497 499 IPython 7.10.2
498 500 ==============
499 501
500 502 IPython 7.10.2 fix a couple of extra incompatibility between IPython, ipdb,
501 503 asyncio and Prompt Toolkit 3.
502 504
503 505 .. _version 7101:
504 506
505 507 IPython 7.10.1
506 508 ==============
507 509
508 510 IPython 7.10.1 fix a couple of incompatibilities with Prompt toolkit 3 (please
509 511 update Prompt toolkit to 3.0.2 at least), and fixes some interaction with
510 512 headless IPython.
511 513
512 514 .. _version 7100:
513 515
514 516 IPython 7.10.0
515 517 ==============
516 518
517 519 IPython 7.10 is the first double digit minor release in the last decade, and
518 520 first since the release of IPython 1.0, previous double digit minor release was
519 521 in August 2009.
520 522
521 523 We've been trying to give you regular release on the last Friday of every month
522 524 for a guaranty of rapid access to bug fixes and new features.
523 525
524 526 Unlike the previous first few releases that have seen only a couple of code
525 527 changes, 7.10 bring a number of changes, new features and bugfixes.
526 528
527 529 Stop Support for Python 3.5 – Adopt NEP 29
528 530 ------------------------------------------
529 531
530 532 IPython has decided to follow the informational `NEP 29
531 533 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_ which layout a clear
532 534 policy as to which version of (C)Python and NumPy are supported.
533 535
534 536 We thus dropped support for Python 3.5, and cleaned up a number of code path
535 537 that were Python-version dependant. If you are on 3.5 or earlier pip should
536 538 automatically give you the latest compatible version of IPython so you do not
537 539 need to pin to a given version.
538 540
539 541 Support for Prompt Toolkit 3.0
540 542 ------------------------------
541 543
542 544 Prompt Toolkit 3.0 was release a week before IPython 7.10 and introduces a few
543 545 breaking changes. We believe IPython 7.10 should be compatible with both Prompt
544 546 Toolkit 2.x and 3.x, though it has not been extensively tested with 3.x so
545 547 please report any issues.
546 548
547 549
548 550 Prompt Rendering Performance improvements
549 551 -----------------------------------------
550 552
551 553 Pull Request :ghpull:`11933` introduced an optimisation in the prompt rendering
552 554 logic that should decrease the resource usage of IPython when using the
553 555 _default_ configuration but could potentially introduce a regression of
554 556 functionalities if you are using a custom prompt.
555 557
556 558 We know assume if you haven't changed the default keybindings that the prompt
557 559 **will not change** during the duration of your input – which is for example
558 560 not true when using vi insert mode that switches between `[ins]` and `[nor]`
559 561 for the current mode.
560 562
561 563 If you are experiencing any issue let us know.
562 564
563 565 Code autoformatting
564 566 -------------------
565 567
566 568 The IPython terminal can now auto format your code just before entering a new
567 569 line or executing a command. To do so use the
568 570 ``--TerminalInteractiveShell.autoformatter`` option and set it to ``'black'``;
569 571 if black is installed IPython will use black to format your code when possible.
570 572
571 573 IPython cannot always properly format your code; in particular it will
572 574 auto formatting with *black* will only work if:
573 575
574 576 - Your code does not contains magics or special python syntax.
575 577
576 578 - There is no code after your cursor.
577 579
578 580 The Black API is also still in motion; so this may not work with all versions of
579 581 black.
580 582
581 583 It should be possible to register custom formatter, though the API is till in
582 584 flux.
583 585
584 586 Arbitrary Mimetypes Handing in Terminal (Aka inline images in terminal)
585 587 -----------------------------------------------------------------------
586 588
587 589 When using IPython terminal it is now possible to register function to handle
588 590 arbitrary mimetypes. While rendering non-text based representation was possible in
589 591 many jupyter frontend; it was not possible in terminal IPython, as usually
590 592 terminal are limited to displaying text. As many terminal these days provide
591 593 escape sequences to display non-text; bringing this loved feature to IPython CLI
592 594 made a lot of sens. This functionality will not only allow inline images; but
593 595 allow opening of external program; for example ``mplayer`` to "display" sound
594 596 files.
595 597
596 598 So far only the hooks necessary for this are in place, but no default mime
597 599 renderers added; so inline images will only be available via extensions. We will
598 600 progressively enable these features by default in the next few releases, and
599 601 contribution is welcomed.
600 602
601 603 We welcome any feedback on the API. See :ref:`shell_mimerenderer` for more
602 604 informations.
603 605
604 606 This is originally based on work form in :ghpull:`10610` from @stephanh42
605 607 started over two years ago, and still a lot need to be done.
606 608
607 609 MISC
608 610 ----
609 611
610 612 - Completions can define their own ordering :ghpull:`11855`
611 613 - Enable Plotting in the same cell than the one that import matplotlib
612 614 :ghpull:`11916`
613 615 - Allow to store and restore multiple variables at once :ghpull:`11930`
614 616
615 617 You can see `all pull-requests <https://github.com/ipython/ipython/pulls?q=is%3Apr+milestone%3A7.10+is%3Aclosed>`_ for this release.
616 618
617 619 API Changes
618 620 -----------
619 621
620 622 Change of API and exposed objects automatically detected using `frappuccino <https://pypi.org/project/frappuccino/>`_ (still in beta):
621 623
622 624 The following items are new in IPython 7.10::
623 625
624 626 + IPython.terminal.shortcuts.reformat_text_before_cursor(buffer, document, shell)
625 627 + IPython.terminal.interactiveshell.PTK3
626 628 + IPython.terminal.interactiveshell.black_reformat_handler(text_before_cursor)
627 629 + IPython.terminal.prompts.RichPromptDisplayHook.write_format_data(self, format_dict, md_dict='None')
628 630
629 631 The following items have been removed in 7.10::
630 632
631 633 - IPython.lib.pretty.DICT_IS_ORDERED
632 634
633 635 The following signatures differ between versions::
634 636
635 637 - IPython.extensions.storemagic.restore_aliases(ip)
636 638 + IPython.extensions.storemagic.restore_aliases(ip, alias='None')
637 639
638 640 Special Thanks
639 641 --------------
640 642
641 643 - @stephanh42 who started the work on inline images in terminal 2 years ago
642 644 - @augustogoulart who spent a lot of time triaging issues and responding to
643 645 users.
644 646 - @con-f-use who is my (@Carreau) first sponsor on GitHub, as a reminder if you
645 647 like IPython, Jupyter and many other library of the SciPy stack you can
646 648 donate to numfocus.org non profit
647 649
648 650 .. _version 790:
649 651
650 652 IPython 7.9.0
651 653 =============
652 654
653 655 IPython 7.9 is a small release with a couple of improvement and bug fixes.
654 656
655 657 - Xterm terminal title should be restored on exit :ghpull:`11910`
656 658 - special variables ``_``,``__``, ``___`` are not set anymore when cache size
657 659 is 0 or less. :ghpull:`11877`
658 660 - Autoreload should have regained some speed by using a new heuristic logic to
659 661 find all objects needing reload. This should avoid large objects traversal
660 662 like pandas dataframes. :ghpull:`11876`
661 663 - Get ready for Python 4. :ghpull:`11874`
662 664 - `%env` Magic now has heuristic to hide potentially sensitive values :ghpull:`11896`
663 665
664 666 This is a small release despite a number of Pull Request Pending that need to
665 667 be reviewed/worked on. Many of the core developers have been busy outside of
666 668 IPython/Jupyter and we thanks all contributor for their patience; we'll work on
667 669 these as soon as we have time.
668 670
669 671
670 672 .. _version780:
671 673
672 674 IPython 7.8.0
673 675 =============
674 676
675 677 IPython 7.8.0 contain a few bugfix and 2 new APIs:
676 678
677 679 - Enable changing the font color for LaTeX rendering :ghpull:`11840`
678 680 - and Re-Expose some PDB API (see below)
679 681
680 682 Expose Pdb API
681 683 --------------
682 684
683 685 Expose the built-in ``pdb.Pdb`` API. ``Pdb`` constructor arguments are generically
684 686 exposed, regardless of python version.
685 687 Newly exposed arguments:
686 688
687 689 - ``skip`` - Python 3.1+
688 690 - ``nosiginnt`` - Python 3.2+
689 691 - ``readrc`` - Python 3.6+
690 692
691 693 Try it out::
692 694
693 695 from IPython.terminal.debugger import TerminalPdb
694 696 pdb = TerminalPdb(skip=["skipthismodule"])
695 697
696 698
697 699 See :ghpull:`11840`
698 700
699 701 .. _version770:
700 702
701 703 IPython 7.7.0
702 704 =============
703 705
704 706 IPython 7.7.0 contain multiple bug fixes and documentation updates; Here are a
705 707 few of the outstanding issue fixed:
706 708
707 709 - Fix a bug introduced in 7.6 where the ``%matplotlib`` magic would fail on
708 710 previously acceptable arguments :ghpull:`11814`.
709 711 - Fix the manage location on freebsd :ghpull:`11808`.
710 712 - Fix error message about aliases after ``%reset`` call in ipykernel
711 713 :ghpull:`11806`
712 714 - Fix Duplication completions in emacs :ghpull:`11803`
713 715
714 716 We are planning to adopt `NEP29 <https://github.com/numpy/numpy/pull/14086>`_
715 717 (still currently in draft) which may make this minor version of IPython the
716 718 last one to support Python 3.5 and will make the code base more aggressive
717 719 toward removing compatibility with older versions of Python.
718 720
719 721 GitHub now support to give only "Triage" permissions to users; if you'd like to
720 722 help close stale issues and labels issues please reach to us with your GitHub
721 723 Username and we'll add you to the triage team. It is a great way to start
722 724 contributing and a path toward getting commit rights.
723 725
724 726 .. _version761:
725 727
726 728 IPython 7.6.1
727 729 =============
728 730
729 731 IPython 7.6.1 contain a critical bugfix in the ``%timeit`` magic, which would
730 732 crash on some inputs as a side effect of :ghpull:`11716`. See :ghpull:`11812`
731 733
732 734
733 735 .. _whatsnew760:
734 736
735 737 IPython 7.6.0
736 738 =============
737 739
738 740 IPython 7.6.0 contains a couple of bug fixes and number of small features
739 741 additions as well as some compatibility with the current development version of
740 742 Python 3.8.
741 743
742 744 - Add a ``-l`` option to :magic:`psearch` to list the available search
743 745 types. :ghpull:`11672`
744 746 - Support ``PathLike`` for ``DisplayObject`` and ``Image``. :ghpull:`11764`
745 747 - Configurability of timeout in the test suite for slow platforms.
746 748 :ghpull:`11756`
747 749 - Accept any casing for matplotlib backend. :ghpull:`121748`
748 750 - Properly skip test that requires numpy to be installed :ghpull:`11723`
749 751 - More support for Python 3.8 and positional only arguments (pep570)
750 752 :ghpull:`11720`
751 753 - Unicode names for the completion are loaded lazily on first use which
752 754 should decrease startup time. :ghpull:`11693`
753 755 - Autoreload now update the types of reloaded objects; this for example allow
754 756 pickling of reloaded objects. :ghpull:`11644`
755 757 - Fix a bug where ``%%time`` magic would suppress cell output. :ghpull:`11716`
756 758
757 759
758 760 Prepare migration to pytest (instead of nose) for testing
759 761 ---------------------------------------------------------
760 762
761 763 Most of the work between 7.5 and 7.6 was to prepare the migration from our
762 764 testing framework to pytest. Most of the test suite should now work by simply
763 765 issuing ``pytest`` from the root of the repository.
764 766
765 767 The migration to pytest is just at its beginning. Many of our test still rely
766 768 on IPython-specific plugins for nose using pytest (doctest using IPython syntax
767 769 is one example of this where test appear as "passing", while no code has been
768 770 ran). Many test also need to be updated like ``yield-test`` to be properly
769 771 parametrized tests.
770 772
771 773 Migration to pytest allowed me to discover a number of issues in our test
772 774 suite; which was hiding a number of subtle issues – or not actually running
773 775 some of the tests in our test suite – I have thus corrected many of those; like
774 776 improperly closed resources; or used of deprecated features. I also made use of
775 777 the ``pytest --durations=...`` to find some of our slowest test and speed them
776 778 up (our test suite can now be up to 10% faster). Pytest as also a variety of
777 779 plugins and flags which will make the code quality of IPython and the testing
778 780 experience better.
779 781
780 782 Misc
781 783 ----
782 784
783 785 We skipped the release of 7.6 at the end of May, but will attempt to get back
784 786 on schedule. We are starting to think about making introducing backward
785 787 incompatible change and start the 8.0 series.
786 788
787 789 Special Thanks to Gabriel (@gpotter2 on GitHub), who among other took care many
788 790 of the remaining task for 7.4 and 7.5, like updating the website.
789 791
790 792 .. _whatsnew750:
791 793
792 794 IPython 7.5.0
793 795 =============
794 796
795 797 IPython 7.5.0 consist mostly of bug-fixes, and documentation updates, with one
796 798 minor new feature. The `Audio` display element can now be assigned an element
797 799 id when displayed in browser. See :ghpull:`11670`
798 800
799 801 The major outstanding bug fix correct a change of behavior that was introduce
800 802 in 7.4.0 where some cell magics would not be able to access or modify global
801 803 scope when using the ``@needs_local_scope`` decorator. This was typically
802 804 encountered with the ``%%time`` and ``%%timeit`` magics. See :ghissue:`11659`
803 805 and :ghpull:`11698`.
804 806
805 807 .. _whatsnew740:
806 808
807 809 IPython 7.4.0
808 810 =============
809 811
810 812 Unicode name completions
811 813 ------------------------
812 814
813 815 Previously, we provided completion for a unicode name with its relative symbol.
814 816 With this, now IPython provides complete suggestions to unicode name symbols.
815 817
816 818 As on the PR, if user types ``\LAT<tab>``, IPython provides a list of
817 819 possible completions. In this case, it would be something like::
818 820
819 821 'LATIN CAPITAL LETTER A',
820 822 'LATIN CAPITAL LETTER B',
821 823 'LATIN CAPITAL LETTER C',
822 824 'LATIN CAPITAL LETTER D',
823 825 ....
824 826
825 827 This help to type unicode character that do not have short latex aliases, and
826 828 have long unicode names. for example ``Ν°``, ``\GREEK CAPITAL LETTER HETA``.
827 829
828 830 This feature was contributed by Luciana Marques :ghpull:`11583`.
829 831
830 832 Make audio normalization optional
831 833 ---------------------------------
832 834
833 835 Added 'normalize' argument to `IPython.display.Audio`. This argument applies
834 836 when audio data is given as an array of samples. The default of `normalize=True`
835 837 preserves prior behavior of normalizing the audio to the maximum possible range.
836 838 Setting to `False` disables normalization.
837 839
838 840
839 841 Miscellaneous
840 842 -------------
841 843
842 844 - Fix improper acceptation of ``return`` outside of functions. :ghpull:`11641`.
843 845 - Fixed PyQt 5.11 backwards incompatibility causing sip import failure.
844 846 :ghpull:`11613`.
845 847 - Fix Bug where ``type?`` would crash IPython. :ghpull:`1608`.
846 848 - Allow to apply ``@needs_local_scope`` to cell magics for convenience.
847 849 :ghpull:`11542`.
848 850
849 851 .. _whatsnew730:
850 852
851 853 IPython 7.3.0
852 854 =============
853 855
854 856 .. _whatsnew720:
855 857
856 858 IPython 7.3.0 bring several bug fixes and small improvements that you will
857 859 described bellow.
858 860
859 861 The biggest change to this release is the implementation of the ``%conda`` and
860 862 ``%pip`` magics, that will attempt to install packages in the **current
861 863 environment**. You may still need to restart your interpreter or kernel for the
862 864 change to be taken into account, but it should simplify installation of packages
863 865 into remote environment. Installing using pip/conda from the command line is
864 866 still the prefer method.
865 867
866 868 The ``%pip`` magic was already present, but was only printing a warning; now it
867 869 will actually forward commands to pip.
868 870
869 871 Misc bug fixes and improvements:
870 872
871 873 - Compatibility with Python 3.8.
872 874 - Do not expand shell variable in execution magics, and added the
873 875 ``no_var_expand`` decorator for magic requiring a similar functionality
874 876 :ghpull:`11516`
875 877 - Add ``%pip`` and ``%conda`` magic :ghpull:`11524`
876 878 - Re-initialize posix aliases after a ``%reset`` :ghpull:`11528`
877 879 - Allow the IPython command line to run ``*.ipynb`` files :ghpull:`11529`
878 880
879 881 IPython 7.2.0
880 882 =============
881 883
882 884 IPython 7.2.0 brings minor bugfixes, improvements, and new configuration options:
883 885
884 886 - Fix a bug preventing PySide2 GUI integration from working :ghpull:`11464`
885 887 - Run CI on Mac OS ! :ghpull:`11471`
886 888 - Fix IPython "Demo" mode. :ghpull:`11498`
887 889 - Fix ``%run`` magic with path in name :ghpull:`11499`
888 890 - Fix: add CWD to sys.path *after* stdlib :ghpull:`11502`
889 891 - Better rendering of signatures, especially long ones. :ghpull:`11505`
890 892 - Re-enable jedi by default if it's installed :ghpull:`11506`
891 893 - Add New ``minimal`` exception reporting mode (useful for educational purpose). See :ghpull:`11509`
892 894
893 895
894 896 Added ability to show subclasses when using pinfo and other utilities
895 897 ---------------------------------------------------------------------
896 898
897 899 When using ``?``/``??`` on a class, IPython will now list the first 10 subclasses.
898 900
899 901 Special Thanks to Chris Mentzel of the Moore Foundation for this feature. Chris
900 902 is one of the people who played a critical role in IPython/Jupyter getting
901 903 funding.
902 904
903 905 We are grateful for all the help Chris has given us over the years,
904 906 and we're now proud to have code contributed by Chris in IPython.
905 907
906 908 OSMagics.cd_force_quiet configuration option
907 909 --------------------------------------------
908 910
909 911 You can set this option to force the %cd magic to behave as if ``-q`` was passed:
910 912 ::
911 913
912 914 In [1]: cd /
913 915 /
914 916
915 917 In [2]: %config OSMagics.cd_force_quiet = True
916 918
917 919 In [3]: cd /tmp
918 920
919 921 In [4]:
920 922
921 923 See :ghpull:`11491`
922 924
923 925 In vi editing mode, whether the prompt includes the current vi mode can now be configured
924 926 -----------------------------------------------------------------------------------------
925 927
926 928 Set the ``TerminalInteractiveShell.prompt_includes_vi_mode`` to a boolean value
927 929 (default: True) to control this feature. See :ghpull:`11492`
928 930
929 931 .. _whatsnew710:
930 932
931 933 IPython 7.1.0
932 934 =============
933 935
934 936 IPython 7.1.0 is the first minor release after 7.0.0 and mostly brings fixes to
935 937 new features, internal refactoring, and fixes for regressions that happened during the 6.x->7.x
936 938 transition. It also brings **Compatibility with Python 3.7.1**, as we're
937 939 unwillingly relying on a bug in CPython.
938 940
939 941 New Core Dev:
940 942
941 943 - We welcome Jonathan Slenders to the commiters. Jonathan has done a fantastic
942 944 work on prompt_toolkit, and we'd like to recognise his impact by giving him
943 945 commit rights. :ghissue:`11397`
944 946
945 947 Notable Changes
946 948
947 949 - Major update of "latex to unicode" tab completion map (see below)
948 950
949 951 Notable New Features:
950 952
951 953 - Restore functionality and documentation of the **sphinx directive**, which
952 954 is now stricter (fail on error by daefault), has new configuration options,
953 955 has a brand new documentation page :ref:`ipython_directive` (which needs
954 956 some cleanup). It is also now *tested* so we hope to have less regressions.
955 957 :ghpull:`11402`
956 958
957 959 - ``IPython.display.Video`` now supports ``width`` and ``height`` arguments,
958 960 allowing a custom width and height to be set instead of using the video's
959 961 width and height. :ghpull:`11353`
960 962
961 963 - Warn when using ``HTML('<iframe>')`` instead of ``IFrame`` :ghpull:`11350`
962 964
963 965 - Allow Dynamic switching of editing mode between vi/emacs and show
964 966 normal/input mode in prompt when using vi. :ghpull:`11390`. Use ``%config
965 967 TerminalInteractiveShell.editing_mode = 'vi'`` or ``%config
966 968 TerminalInteractiveShell.editing_mode = 'emacs'`` to dynamically switch
967 969 between modes.
968 970
969 971
970 972 Notable Fixes:
971 973
972 974 - Fix entering of **multi-line blocks in terminal** IPython, and various
973 975 crashes in the new input transformation machinery :ghpull:`11354`,
974 976 :ghpull:`11356`, :ghpull:`11358`. These also fix a **Compatibility bug
975 977 with Python 3.7.1**.
976 978
977 979 - Fix moving through generator stack in ipdb :ghpull:`11266`
978 980
979 981 - %Magic command arguments now support quoting. :ghpull:`11330`
980 982
981 983 - Re-add ``rprint`` and ``rprinte`` aliases. :ghpull:`11331`
982 984
983 985 - Remove implicit dependency on ``ipython_genutils`` :ghpull:`11317`
984 986
985 987 - Make ``nonlocal`` raise ``SyntaxError`` instead of silently failing in async
986 988 mode. :ghpull:`11382`
987 989
988 990 - Fix mishandling of magics and ``= !`` assignment just after a dedent in
989 991 nested code blocks :ghpull:`11418`
990 992
991 993 - Fix instructions for custom shortcuts :ghpull:`11426`
992 994
993 995
994 996 Notable Internals improvements:
995 997
996 998 - Use of ``os.scandir`` (Python 3 only) to speed up some file system operations.
997 999 :ghpull:`11365`
998 1000
999 1001 - use ``perf_counter`` instead of ``clock`` for more precise
1000 1002 timing results with ``%time`` :ghpull:`11376`
1001 1003
1002 1004 Many thanks to all the contributors and in particular to ``bartskowron`` and
1003 1005 ``tonyfast`` who handled some pretty complicated bugs in the input machinery. We
1004 1006 had a number of first time contributors and maybe hacktoberfest participants that
1005 1007 made significant contributions and helped us free some time to focus on more
1006 1008 complicated bugs.
1007 1009
1008 1010 You
1009 1011 can see all the closed issues and Merged PR, new features and fixes `here
1010 1012 <https://github.com/ipython/ipython/issues?utf8=%E2%9C%93&q=+is%3Aclosed+milestone%3A7.1+>`_.
1011 1013
1012 1014 Unicode Completion update
1013 1015 -------------------------
1014 1016
1015 1017 In IPython 7.1 the Unicode completion map has been updated and synchronized with
1016 1018 the Julia language.
1017 1019
1018 1020 Added and removed character characters:
1019 1021
1020 1022 ``\jmath`` (``Θ·``), ``\\underleftrightarrow`` (U+034D, combining) have been
1021 1023 added, while ``\\textasciicaron`` have been removed
1022 1024
1023 1025 Some sequences have seen their prefix removed:
1024 1026
1025 1027 - 6 characters ``\text...<tab>`` should now be inputed with ``\...<tab>`` directly,
1026 1028 - 45 characters ``\Elz...<tab>`` should now be inputed with ``\...<tab>`` directly,
1027 1029 - 65 characters ``\B...<tab>`` should now be inputed with ``\...<tab>`` directly,
1028 1030 - 450 characters ``\m...<tab>`` should now be inputed with ``\...<tab>`` directly,
1029 1031
1030 1032 Some sequences have seen their prefix shortened:
1031 1033
1032 1034 - 5 characters ``\mitBbb...<tab>`` should now be inputed with ``\bbi...<tab>`` directly,
1033 1035 - 52 characters ``\mit...<tab>`` should now be inputed with ``\i...<tab>`` directly,
1034 1036 - 216 characters ``\mbfit...<tab>`` should now be inputed with ``\bi...<tab>`` directly,
1035 1037 - 222 characters ``\mbf...<tab>`` should now be inputed with ``\b...<tab>`` directly,
1036 1038
1037 1039 A couple of characters had their sequence simplified:
1038 1040
1039 1041 - ``Γ°``, type ``\dh<tab>``, instead of ``\eth<tab>``
1040 1042 - ``Δ§``, type ``\hbar<tab>``, instead of ``\Elzxh<tab>``
1041 1043 - ``ΙΈ``, type ``\ltphi<tab>``, instead of ``\textphi<tab>``
1042 1044 - ``Ο΄``, type ``\varTheta<tab>``, instead of ``\textTheta<tab>``
1043 1045 - ``ℇ``, type ``\eulermascheroni<tab>``, instead of ``\Eulerconst<tab>``
1044 1046 - ``β„Ž``, type ``\planck<tab>``, instead of ``\Planckconst<tab>``
1045 1047
1046 1048 - U+0336 (COMBINING LONG STROKE OVERLAY), type ``\strike<tab>``, instead of ``\Elzbar<tab>``.
1047 1049
1048 1050 A couple of sequences have been updated:
1049 1051
1050 1052 - ``\varepsilon`` now gives ``Ι›`` (GREEK SMALL LETTER EPSILON) instead of ``Ξ΅`` (GREEK LUNATE EPSILON SYMBOL),
1051 1053 - ``\underbar`` now gives U+0331 (COMBINING MACRON BELOW) instead of U+0332 (COMBINING LOW LINE).
1052 1054
1053 1055
1054 1056 .. _whatsnew700:
1055 1057
1056 1058 IPython 7.0.0
1057 1059 =============
1058 1060
1059 1061 Released Thursday September 27th, 2018
1060 1062
1061 1063 IPython 7 includes major feature improvements.
1062 1064 This is also the second major version of IPython to support only
1063 1065 Python 3 – starting at Python 3.4. Python 2 is still community-supported
1064 1066 on the bugfix only 5.x branch, but we remind you that Python 2 "end of life"
1065 1067 is on Jan 1st 2020.
1066 1068
1067 1069 We were able to backport bug fixes to the 5.x branch thanks to our backport bot which
1068 1070 backported more than `70 Pull-Requests
1069 1071 <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>`_
1070 1072
1071 1073 The IPython 6.x branch will likely not see any further release unless critical
1072 1074 bugs are found.
1073 1075
1074 1076 Make sure you have pip > 9.0 before upgrading. You should be able to update by running:
1075 1077
1076 1078 .. code::
1077 1079
1078 1080 pip install ipython --upgrade
1079 1081
1080 1082 .. only:: ipydev
1081 1083
1082 1084 If you are trying to install or update an ``alpha``, ``beta``, or ``rc``
1083 1085 version, use pip ``--pre`` flag.
1084 1086
1085 1087 .. code::
1086 1088
1087 1089 pip install ipython --upgrade --pre
1088 1090
1089 1091
1090 1092 Or, if you have conda installed:
1091 1093
1092 1094 .. code::
1093 1095
1094 1096 conda install ipython
1095 1097
1096 1098
1097 1099
1098 1100 Prompt Toolkit 2.0
1099 1101 ------------------
1100 1102
1101 1103 IPython 7.0+ now uses ``prompt_toolkit 2.0``. If you still need to use an earlier
1102 1104 ``prompt_toolkit`` version, you may need to pin IPython to ``<7.0``.
1103 1105
1104 1106 Autowait: Asynchronous REPL
1105 1107 ---------------------------
1106 1108
1107 1109 Staring with IPython 7.0 on Python 3.6+, IPython can automatically ``await``
1108 1110 top level code. You should not need to access an event loop or runner
1109 1111 yourself. To learn more, read the :ref:`autoawait` section of our docs, see
1110 1112 :ghpull:`11265`, or try the following code::
1111 1113
1112 1114 Python 3.6.0
1113 1115 Type 'copyright', 'credits' or 'license' for more information
1114 1116 IPython 7.0.0 -- An enhanced Interactive Python. Type '?' for help.
1115 1117
1116 1118 In [1]: import aiohttp
1117 1119 ...: result = aiohttp.get('https://api.github.com')
1118 1120
1119 1121 In [2]: response = await result
1120 1122 <pause for a few 100s ms>
1121 1123
1122 1124 In [3]: await response.json()
1123 1125 Out[3]:
1124 1126 {'authorizations_url': 'https://api.github.com/authorizations',
1125 1127 'code_search_url': 'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}',
1126 1128 ...
1127 1129 }
1128 1130
1129 1131 .. note::
1130 1132
1131 1133 Async integration is experimental code, behavior may change or be removed
1132 1134 between Python and IPython versions without warnings.
1133 1135
1134 1136 Integration is by default with `asyncio`, but other libraries can be configured --
1135 1137 like ``curio`` or ``trio`` -- to improve concurrency in the REPL::
1136 1138
1137 1139 In [1]: %autoawait trio
1138 1140
1139 1141 In [2]: import trio
1140 1142
1141 1143 In [3]: async def child(i):
1142 1144 ...: print(" child %s goes to sleep"%i)
1143 1145 ...: await trio.sleep(2)
1144 1146 ...: print(" child %s wakes up"%i)
1145 1147
1146 1148 In [4]: print('parent start')
1147 1149 ...: async with trio.open_nursery() as n:
1148 1150 ...: for i in range(3):
1149 1151 ...: n.spawn(child, i)
1150 1152 ...: print('parent end')
1151 1153 parent start
1152 1154 child 2 goes to sleep
1153 1155 child 0 goes to sleep
1154 1156 child 1 goes to sleep
1155 1157 <about 2 seconds pause>
1156 1158 child 2 wakes up
1157 1159 child 1 wakes up
1158 1160 child 0 wakes up
1159 1161 parent end
1160 1162
1161 1163 See :ref:`autoawait` for more information.
1162 1164
1163 1165
1164 1166 Asynchronous code in a Notebook interface or any other frontend using the
1165 1167 Jupyter Protocol will require further updates to the IPykernel package.
1166 1168
1167 1169 Non-Asynchronous code
1168 1170 ~~~~~~~~~~~~~~~~~~~~~
1169 1171
1170 1172 As the internal API of IPython is now asynchronous, IPython needs to run under
1171 1173 an event loop. In order to allow many workflows, (like using the :magic:`%run`
1172 1174 magic, or copy-pasting code that explicitly starts/stop event loop), when
1173 1175 top-level code is detected as not being asynchronous, IPython code is advanced
1174 1176 via a pseudo-synchronous runner, and may not advance pending tasks.
1175 1177
1176 1178 Change to Nested Embed
1177 1179 ~~~~~~~~~~~~~~~~~~~~~~
1178 1180
1179 1181 The introduction of the ability to run async code had some effect on the
1180 1182 ``IPython.embed()`` API. By default, embed will not allow you to run asynchronous
1181 1183 code unless an event loop is specified.
1182 1184
1183 1185 Effects on Magics
1184 1186 ~~~~~~~~~~~~~~~~~
1185 1187
1186 1188 Some magics will not work with async until they're updated.
1187 1189 Contributions welcome.
1188 1190
1189 1191 Expected Future changes
1190 1192 ~~~~~~~~~~~~~~~~~~~~~~~
1191 1193
1192 1194 We expect more internal but public IPython functions to become ``async``, and
1193 1195 will likely end up having a persistent event loop while IPython is running.
1194 1196
1195 1197 Thanks
1196 1198 ~~~~~~
1197 1199
1198 1200 This release took more than a year in the making.
1199 1201 The code was rebased a number of
1200 1202 times; leading to commit authorship that may have been lost in the final
1201 1203 Pull-Request. Huge thanks to many people for contribution, discussion, code,
1202 1204 documentation, use-cases: dalejung, danielballan, ellisonbg, fperez, gnestor,
1203 1205 minrk, njsmith, pganssle, tacaswell, takluyver , vidartf ... And many others.
1204 1206
1205 1207
1206 1208 Autoreload Improvement
1207 1209 ----------------------
1208 1210
1209 1211 The magic :magic:`%autoreload 2 <autoreload>` now captures new methods added to
1210 1212 classes. Earlier, only methods existing as of the initial import were being
1211 1213 tracked and updated.
1212 1214
1213 1215 This new feature helps dual environment development - Jupyter+IDE - where the
1214 1216 code gradually moves from notebook cells to package files as it gets
1215 1217 structured.
1216 1218
1217 1219 **Example**: An instance of the class ``MyClass`` will be able to access the
1218 1220 method ``cube()`` after it is uncommented and the file ``file1.py`` is saved on
1219 1221 disk.
1220 1222
1221 1223
1222 1224 .. code::
1223 1225
1224 1226 # notebook
1225 1227
1226 1228 from mymodule import MyClass
1227 1229 first = MyClass(5)
1228 1230
1229 1231 .. code::
1230 1232
1231 1233 # mymodule/file1.py
1232 1234
1233 1235 class MyClass:
1234 1236
1235 1237 def __init__(self, a=10):
1236 1238 self.a = a
1237 1239
1238 1240 def square(self):
1239 1241 print('compute square')
1240 1242 return self.a*self.a
1241 1243
1242 1244 # def cube(self):
1243 1245 # print('compute cube')
1244 1246 # return self.a*self.a*self.a
1245 1247
1246 1248
1247 1249
1248 1250
1249 1251 Misc
1250 1252 ----
1251 1253
1252 1254 The autoindent feature that was deprecated in 5.x was re-enabled and
1253 1255 un-deprecated in :ghpull:`11257`
1254 1256
1255 1257 Make :magic:`%run -n -i ... <run>` work correctly. Earlier, if :magic:`%run` was
1256 1258 passed both arguments, ``-n`` would be silently ignored. See :ghpull:`10308`
1257 1259
1258 1260
1259 1261 The :cellmagic:`%%script` (as well as :cellmagic:`%%bash`,
1260 1262 :cellmagic:`%%ruby`... ) cell magics now raise by default if the return code of
1261 1263 the given code is non-zero (thus halting execution of further cells in a
1262 1264 notebook). The behavior can be disable by passing the ``--no-raise-error`` flag.
1263 1265
1264 1266
1265 1267 Deprecations
1266 1268 ------------
1267 1269
1268 1270 A couple of unused functions and methods have been deprecated and will be removed
1269 1271 in future versions:
1270 1272
1271 1273 - ``IPython.utils.io.raw_print_err``
1272 1274 - ``IPython.utils.io.raw_print``
1273 1275
1274 1276
1275 1277 Backwards incompatible changes
1276 1278 ------------------------------
1277 1279
1278 1280 * The API for transforming input before it is parsed as Python code has been
1279 1281 completely redesigned: any custom input transformations will need to be
1280 1282 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