##// END OF EJS Templates
JSON formatter expects JSONable dict/list...
Min RK -
Show More
@@ -1,937 +1,948 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats.
2 """Top-level display functions for displaying object in different formats."""
3
3
4 Authors:
4 # Copyright (c) IPython Development Team.
5
5 # Distributed under the terms of the Modified BSD License.
6 * Brian Granger
7 """
8
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2013 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
6
20 from __future__ import print_function
7 from __future__ import print_function
21
8
9 import json
10 import mimetypes
22 import os
11 import os
23 import struct
12 import struct
24 import mimetypes
13 import warnings
25
14
26 from IPython.core.formatters import _safe_get_formatter_method
15 from IPython.core.formatters import _safe_get_formatter_method
27 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
16 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
28 unicode_type)
17 unicode_type)
29 from IPython.testing.skipdoctest import skip_doctest
18 from IPython.testing.skipdoctest import skip_doctest
30
19
31 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
32 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
33 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
34 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
35 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
24 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
36 'publish_display_data']
25 'publish_display_data']
37
26
38 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
39 # utility functions
28 # utility functions
40 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
41
30
42 def _safe_exists(path):
31 def _safe_exists(path):
43 """Check path, but don't let exceptions raise"""
32 """Check path, but don't let exceptions raise"""
44 try:
33 try:
45 return os.path.exists(path)
34 return os.path.exists(path)
46 except Exception:
35 except Exception:
47 return False
36 return False
48
37
49 def _merge(d1, d2):
38 def _merge(d1, d2):
50 """Like update, but merges sub-dicts instead of clobbering at the top level.
39 """Like update, but merges sub-dicts instead of clobbering at the top level.
51
40
52 Updates d1 in-place
41 Updates d1 in-place
53 """
42 """
54
43
55 if not isinstance(d2, dict) or not isinstance(d1, dict):
44 if not isinstance(d2, dict) or not isinstance(d1, dict):
56 return d2
45 return d2
57 for key, value in d2.items():
46 for key, value in d2.items():
58 d1[key] = _merge(d1.get(key), value)
47 d1[key] = _merge(d1.get(key), value)
59 return d1
48 return d1
60
49
61 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
50 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
62 """internal implementation of all display_foo methods
51 """internal implementation of all display_foo methods
63
52
64 Parameters
53 Parameters
65 ----------
54 ----------
66 mimetype : str
55 mimetype : str
67 The mimetype to be published (e.g. 'image/png')
56 The mimetype to be published (e.g. 'image/png')
68 objs : tuple of objects
57 objs : tuple of objects
69 The Python objects to display, or if raw=True raw text data to
58 The Python objects to display, or if raw=True raw text data to
70 display.
59 display.
71 raw : bool
60 raw : bool
72 Are the data objects raw data or Python objects that need to be
61 Are the data objects raw data or Python objects that need to be
73 formatted before display? [default: False]
62 formatted before display? [default: False]
74 metadata : dict (optional)
63 metadata : dict (optional)
75 Metadata to be associated with the specific mimetype output.
64 Metadata to be associated with the specific mimetype output.
76 """
65 """
77 if metadata:
66 if metadata:
78 metadata = {mimetype: metadata}
67 metadata = {mimetype: metadata}
79 if raw:
68 if raw:
80 # turn list of pngdata into list of { 'image/png': pngdata }
69 # turn list of pngdata into list of { 'image/png': pngdata }
81 objs = [ {mimetype: obj} for obj in objs ]
70 objs = [ {mimetype: obj} for obj in objs ]
82 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
71 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
83
72
84 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
85 # Main functions
74 # Main functions
86 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
87
76
88 def publish_display_data(data, metadata=None, source=None):
77 def publish_display_data(data, metadata=None, source=None):
89 """Publish data and metadata to all frontends.
78 """Publish data and metadata to all frontends.
90
79
91 See the ``display_data`` message in the messaging documentation for
80 See the ``display_data`` message in the messaging documentation for
92 more details about this message type.
81 more details about this message type.
93
82
94 The following MIME types are currently implemented:
83 The following MIME types are currently implemented:
95
84
96 * text/plain
85 * text/plain
97 * text/html
86 * text/html
98 * text/markdown
87 * text/markdown
99 * text/latex
88 * text/latex
100 * application/json
89 * application/json
101 * application/javascript
90 * application/javascript
102 * image/png
91 * image/png
103 * image/jpeg
92 * image/jpeg
104 * image/svg+xml
93 * image/svg+xml
105
94
106 Parameters
95 Parameters
107 ----------
96 ----------
108 data : dict
97 data : dict
109 A dictionary having keys that are valid MIME types (like
98 A dictionary having keys that are valid MIME types (like
110 'text/plain' or 'image/svg+xml') and values that are the data for
99 'text/plain' or 'image/svg+xml') and values that are the data for
111 that MIME type. The data itself must be a JSON'able data
100 that MIME type. The data itself must be a JSON'able data
112 structure. Minimally all data should have the 'text/plain' data,
101 structure. Minimally all data should have the 'text/plain' data,
113 which can be displayed by all frontends. If more than the plain
102 which can be displayed by all frontends. If more than the plain
114 text is given, it is up to the frontend to decide which
103 text is given, it is up to the frontend to decide which
115 representation to use.
104 representation to use.
116 metadata : dict
105 metadata : dict
117 A dictionary for metadata related to the data. This can contain
106 A dictionary for metadata related to the data. This can contain
118 arbitrary key, value pairs that frontends can use to interpret
107 arbitrary key, value pairs that frontends can use to interpret
119 the data. mime-type keys matching those in data can be used
108 the data. mime-type keys matching those in data can be used
120 to specify metadata about particular representations.
109 to specify metadata about particular representations.
121 source : str, deprecated
110 source : str, deprecated
122 Unused.
111 Unused.
123 """
112 """
124 from IPython.core.interactiveshell import InteractiveShell
113 from IPython.core.interactiveshell import InteractiveShell
125 InteractiveShell.instance().display_pub.publish(
114 InteractiveShell.instance().display_pub.publish(
126 data=data,
115 data=data,
127 metadata=metadata,
116 metadata=metadata,
128 )
117 )
129
118
130 def display(*objs, **kwargs):
119 def display(*objs, **kwargs):
131 """Display a Python object in all frontends.
120 """Display a Python object in all frontends.
132
121
133 By default all representations will be computed and sent to the frontends.
122 By default all representations will be computed and sent to the frontends.
134 Frontends can decide which representation is used and how.
123 Frontends can decide which representation is used and how.
135
124
136 Parameters
125 Parameters
137 ----------
126 ----------
138 objs : tuple of objects
127 objs : tuple of objects
139 The Python objects to display.
128 The Python objects to display.
140 raw : bool, optional
129 raw : bool, optional
141 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
130 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
142 or Python objects that need to be formatted before display? [default: False]
131 or Python objects that need to be formatted before display? [default: False]
143 include : list or tuple, optional
132 include : list or tuple, optional
144 A list of format type strings (MIME types) to include in the
133 A list of format type strings (MIME types) to include in the
145 format data dict. If this is set *only* the format types included
134 format data dict. If this is set *only* the format types included
146 in this list will be computed.
135 in this list will be computed.
147 exclude : list or tuple, optional
136 exclude : list or tuple, optional
148 A list of format type strings (MIME types) to exclude in the format
137 A list of format type strings (MIME types) to exclude in the format
149 data dict. If this is set all format types will be computed,
138 data dict. If this is set all format types will be computed,
150 except for those included in this argument.
139 except for those included in this argument.
151 metadata : dict, optional
140 metadata : dict, optional
152 A dictionary of metadata to associate with the output.
141 A dictionary of metadata to associate with the output.
153 mime-type keys in this dictionary will be associated with the individual
142 mime-type keys in this dictionary will be associated with the individual
154 representation formats, if they exist.
143 representation formats, if they exist.
155 """
144 """
156 raw = kwargs.get('raw', False)
145 raw = kwargs.get('raw', False)
157 include = kwargs.get('include')
146 include = kwargs.get('include')
158 exclude = kwargs.get('exclude')
147 exclude = kwargs.get('exclude')
159 metadata = kwargs.get('metadata')
148 metadata = kwargs.get('metadata')
160
149
161 from IPython.core.interactiveshell import InteractiveShell
150 from IPython.core.interactiveshell import InteractiveShell
162
151
163 if not raw:
152 if not raw:
164 format = InteractiveShell.instance().display_formatter.format
153 format = InteractiveShell.instance().display_formatter.format
165
154
166 for obj in objs:
155 for obj in objs:
167 if raw:
156 if raw:
168 publish_display_data(data=obj, metadata=metadata)
157 publish_display_data(data=obj, metadata=metadata)
169 else:
158 else:
170 format_dict, md_dict = format(obj, include=include, exclude=exclude)
159 format_dict, md_dict = format(obj, include=include, exclude=exclude)
171 if not format_dict:
160 if not format_dict:
172 # nothing to display (e.g. _ipython_display_ took over)
161 # nothing to display (e.g. _ipython_display_ took over)
173 continue
162 continue
174 if metadata:
163 if metadata:
175 # kwarg-specified metadata gets precedence
164 # kwarg-specified metadata gets precedence
176 _merge(md_dict, metadata)
165 _merge(md_dict, metadata)
177 publish_display_data(data=format_dict, metadata=md_dict)
166 publish_display_data(data=format_dict, metadata=md_dict)
178
167
179
168
180 def display_pretty(*objs, **kwargs):
169 def display_pretty(*objs, **kwargs):
181 """Display the pretty (default) representation of an object.
170 """Display the pretty (default) representation of an object.
182
171
183 Parameters
172 Parameters
184 ----------
173 ----------
185 objs : tuple of objects
174 objs : tuple of objects
186 The Python objects to display, or if raw=True raw text data to
175 The Python objects to display, or if raw=True raw text data to
187 display.
176 display.
188 raw : bool
177 raw : bool
189 Are the data objects raw data or Python objects that need to be
178 Are the data objects raw data or Python objects that need to be
190 formatted before display? [default: False]
179 formatted before display? [default: False]
191 metadata : dict (optional)
180 metadata : dict (optional)
192 Metadata to be associated with the specific mimetype output.
181 Metadata to be associated with the specific mimetype output.
193 """
182 """
194 _display_mimetype('text/plain', objs, **kwargs)
183 _display_mimetype('text/plain', objs, **kwargs)
195
184
196
185
197 def display_html(*objs, **kwargs):
186 def display_html(*objs, **kwargs):
198 """Display the HTML representation of an object.
187 """Display the HTML representation of an object.
199
188
200 Parameters
189 Parameters
201 ----------
190 ----------
202 objs : tuple of objects
191 objs : tuple of objects
203 The Python objects to display, or if raw=True raw HTML data to
192 The Python objects to display, or if raw=True raw HTML data to
204 display.
193 display.
205 raw : bool
194 raw : bool
206 Are the data objects raw data or Python objects that need to be
195 Are the data objects raw data or Python objects that need to be
207 formatted before display? [default: False]
196 formatted before display? [default: False]
208 metadata : dict (optional)
197 metadata : dict (optional)
209 Metadata to be associated with the specific mimetype output.
198 Metadata to be associated with the specific mimetype output.
210 """
199 """
211 _display_mimetype('text/html', objs, **kwargs)
200 _display_mimetype('text/html', objs, **kwargs)
212
201
213
202
214 def display_markdown(*objs, **kwargs):
203 def display_markdown(*objs, **kwargs):
215 """Displays the Markdown representation of an object.
204 """Displays the Markdown representation of an object.
216
205
217 Parameters
206 Parameters
218 ----------
207 ----------
219 objs : tuple of objects
208 objs : tuple of objects
220 The Python objects to display, or if raw=True raw markdown data to
209 The Python objects to display, or if raw=True raw markdown data to
221 display.
210 display.
222 raw : bool
211 raw : bool
223 Are the data objects raw data or Python objects that need to be
212 Are the data objects raw data or Python objects that need to be
224 formatted before display? [default: False]
213 formatted before display? [default: False]
225 metadata : dict (optional)
214 metadata : dict (optional)
226 Metadata to be associated with the specific mimetype output.
215 Metadata to be associated with the specific mimetype output.
227 """
216 """
228
217
229 _display_mimetype('text/markdown', objs, **kwargs)
218 _display_mimetype('text/markdown', objs, **kwargs)
230
219
231
220
232 def display_svg(*objs, **kwargs):
221 def display_svg(*objs, **kwargs):
233 """Display the SVG representation of an object.
222 """Display the SVG representation of an object.
234
223
235 Parameters
224 Parameters
236 ----------
225 ----------
237 objs : tuple of objects
226 objs : tuple of objects
238 The Python objects to display, or if raw=True raw svg data to
227 The Python objects to display, or if raw=True raw svg data to
239 display.
228 display.
240 raw : bool
229 raw : bool
241 Are the data objects raw data or Python objects that need to be
230 Are the data objects raw data or Python objects that need to be
242 formatted before display? [default: False]
231 formatted before display? [default: False]
243 metadata : dict (optional)
232 metadata : dict (optional)
244 Metadata to be associated with the specific mimetype output.
233 Metadata to be associated with the specific mimetype output.
245 """
234 """
246 _display_mimetype('image/svg+xml', objs, **kwargs)
235 _display_mimetype('image/svg+xml', objs, **kwargs)
247
236
248
237
249 def display_png(*objs, **kwargs):
238 def display_png(*objs, **kwargs):
250 """Display the PNG representation of an object.
239 """Display the PNG representation of an object.
251
240
252 Parameters
241 Parameters
253 ----------
242 ----------
254 objs : tuple of objects
243 objs : tuple of objects
255 The Python objects to display, or if raw=True raw png data to
244 The Python objects to display, or if raw=True raw png data to
256 display.
245 display.
257 raw : bool
246 raw : bool
258 Are the data objects raw data or Python objects that need to be
247 Are the data objects raw data or Python objects that need to be
259 formatted before display? [default: False]
248 formatted before display? [default: False]
260 metadata : dict (optional)
249 metadata : dict (optional)
261 Metadata to be associated with the specific mimetype output.
250 Metadata to be associated with the specific mimetype output.
262 """
251 """
263 _display_mimetype('image/png', objs, **kwargs)
252 _display_mimetype('image/png', objs, **kwargs)
264
253
265
254
266 def display_jpeg(*objs, **kwargs):
255 def display_jpeg(*objs, **kwargs):
267 """Display the JPEG representation of an object.
256 """Display the JPEG representation of an object.
268
257
269 Parameters
258 Parameters
270 ----------
259 ----------
271 objs : tuple of objects
260 objs : tuple of objects
272 The Python objects to display, or if raw=True raw JPEG data to
261 The Python objects to display, or if raw=True raw JPEG data to
273 display.
262 display.
274 raw : bool
263 raw : bool
275 Are the data objects raw data or Python objects that need to be
264 Are the data objects raw data or Python objects that need to be
276 formatted before display? [default: False]
265 formatted before display? [default: False]
277 metadata : dict (optional)
266 metadata : dict (optional)
278 Metadata to be associated with the specific mimetype output.
267 Metadata to be associated with the specific mimetype output.
279 """
268 """
280 _display_mimetype('image/jpeg', objs, **kwargs)
269 _display_mimetype('image/jpeg', objs, **kwargs)
281
270
282
271
283 def display_latex(*objs, **kwargs):
272 def display_latex(*objs, **kwargs):
284 """Display the LaTeX representation of an object.
273 """Display the LaTeX representation of an object.
285
274
286 Parameters
275 Parameters
287 ----------
276 ----------
288 objs : tuple of objects
277 objs : tuple of objects
289 The Python objects to display, or if raw=True raw latex data to
278 The Python objects to display, or if raw=True raw latex data to
290 display.
279 display.
291 raw : bool
280 raw : bool
292 Are the data objects raw data or Python objects that need to be
281 Are the data objects raw data or Python objects that need to be
293 formatted before display? [default: False]
282 formatted before display? [default: False]
294 metadata : dict (optional)
283 metadata : dict (optional)
295 Metadata to be associated with the specific mimetype output.
284 Metadata to be associated with the specific mimetype output.
296 """
285 """
297 _display_mimetype('text/latex', objs, **kwargs)
286 _display_mimetype('text/latex', objs, **kwargs)
298
287
299
288
300 def display_json(*objs, **kwargs):
289 def display_json(*objs, **kwargs):
301 """Display the JSON representation of an object.
290 """Display the JSON representation of an object.
302
291
303 Note that not many frontends support displaying JSON.
292 Note that not many frontends support displaying JSON.
304
293
305 Parameters
294 Parameters
306 ----------
295 ----------
307 objs : tuple of objects
296 objs : tuple of objects
308 The Python objects to display, or if raw=True raw json data to
297 The Python objects to display, or if raw=True raw json data to
309 display.
298 display.
310 raw : bool
299 raw : bool
311 Are the data objects raw data or Python objects that need to be
300 Are the data objects raw data or Python objects that need to be
312 formatted before display? [default: False]
301 formatted before display? [default: False]
313 metadata : dict (optional)
302 metadata : dict (optional)
314 Metadata to be associated with the specific mimetype output.
303 Metadata to be associated with the specific mimetype output.
315 """
304 """
316 _display_mimetype('application/json', objs, **kwargs)
305 _display_mimetype('application/json', objs, **kwargs)
317
306
318
307
319 def display_javascript(*objs, **kwargs):
308 def display_javascript(*objs, **kwargs):
320 """Display the Javascript representation of an object.
309 """Display the Javascript representation of an object.
321
310
322 Parameters
311 Parameters
323 ----------
312 ----------
324 objs : tuple of objects
313 objs : tuple of objects
325 The Python objects to display, or if raw=True raw javascript data to
314 The Python objects to display, or if raw=True raw javascript data to
326 display.
315 display.
327 raw : bool
316 raw : bool
328 Are the data objects raw data or Python objects that need to be
317 Are the data objects raw data or Python objects that need to be
329 formatted before display? [default: False]
318 formatted before display? [default: False]
330 metadata : dict (optional)
319 metadata : dict (optional)
331 Metadata to be associated with the specific mimetype output.
320 Metadata to be associated with the specific mimetype output.
332 """
321 """
333 _display_mimetype('application/javascript', objs, **kwargs)
322 _display_mimetype('application/javascript', objs, **kwargs)
334
323
335
324
336 def display_pdf(*objs, **kwargs):
325 def display_pdf(*objs, **kwargs):
337 """Display the PDF representation of an object.
326 """Display the PDF representation of an object.
338
327
339 Parameters
328 Parameters
340 ----------
329 ----------
341 objs : tuple of objects
330 objs : tuple of objects
342 The Python objects to display, or if raw=True raw javascript data to
331 The Python objects to display, or if raw=True raw javascript data to
343 display.
332 display.
344 raw : bool
333 raw : bool
345 Are the data objects raw data or Python objects that need to be
334 Are the data objects raw data or Python objects that need to be
346 formatted before display? [default: False]
335 formatted before display? [default: False]
347 metadata : dict (optional)
336 metadata : dict (optional)
348 Metadata to be associated with the specific mimetype output.
337 Metadata to be associated with the specific mimetype output.
349 """
338 """
350 _display_mimetype('application/pdf', objs, **kwargs)
339 _display_mimetype('application/pdf', objs, **kwargs)
351
340
352
341
353 #-----------------------------------------------------------------------------
342 #-----------------------------------------------------------------------------
354 # Smart classes
343 # Smart classes
355 #-----------------------------------------------------------------------------
344 #-----------------------------------------------------------------------------
356
345
357
346
358 class DisplayObject(object):
347 class DisplayObject(object):
359 """An object that wraps data to be displayed."""
348 """An object that wraps data to be displayed."""
360
349
361 _read_flags = 'r'
350 _read_flags = 'r'
362 _show_mem_addr = False
351 _show_mem_addr = False
363
352
364 def __init__(self, data=None, url=None, filename=None):
353 def __init__(self, data=None, url=None, filename=None):
365 """Create a display object given raw data.
354 """Create a display object given raw data.
366
355
367 When this object is returned by an expression or passed to the
356 When this object is returned by an expression or passed to the
368 display function, it will result in the data being displayed
357 display function, it will result in the data being displayed
369 in the frontend. The MIME type of the data should match the
358 in the frontend. The MIME type of the data should match the
370 subclasses used, so the Png subclass should be used for 'image/png'
359 subclasses used, so the Png subclass should be used for 'image/png'
371 data. If the data is a URL, the data will first be downloaded
360 data. If the data is a URL, the data will first be downloaded
372 and then displayed. If
361 and then displayed. If
373
362
374 Parameters
363 Parameters
375 ----------
364 ----------
376 data : unicode, str or bytes
365 data : unicode, str or bytes
377 The raw data or a URL or file to load the data from
366 The raw data or a URL or file to load the data from
378 url : unicode
367 url : unicode
379 A URL to download the data from.
368 A URL to download the data from.
380 filename : unicode
369 filename : unicode
381 Path to a local file to load the data from.
370 Path to a local file to load the data from.
382 """
371 """
383 if data is not None and isinstance(data, string_types):
372 if data is not None and isinstance(data, string_types):
384 if data.startswith('http') and url is None:
373 if data.startswith('http') and url is None:
385 url = data
374 url = data
386 filename = None
375 filename = None
387 data = None
376 data = None
388 elif _safe_exists(data) and filename is None:
377 elif _safe_exists(data) and filename is None:
389 url = None
378 url = None
390 filename = data
379 filename = data
391 data = None
380 data = None
392
381
393 self.data = data
382 self.data = data
394 self.url = url
383 self.url = url
395 self.filename = None if filename is None else unicode_type(filename)
384 self.filename = None if filename is None else unicode_type(filename)
396
385
397 self.reload()
386 self.reload()
398 self._check_data()
387 self._check_data()
399
388
400 def __repr__(self):
389 def __repr__(self):
401 if not self._show_mem_addr:
390 if not self._show_mem_addr:
402 cls = self.__class__
391 cls = self.__class__
403 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
392 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
404 else:
393 else:
405 r = super(DisplayObject, self).__repr__()
394 r = super(DisplayObject, self).__repr__()
406 return r
395 return r
407
396
408 def _check_data(self):
397 def _check_data(self):
409 """Override in subclasses if there's something to check."""
398 """Override in subclasses if there's something to check."""
410 pass
399 pass
411
400
412 def reload(self):
401 def reload(self):
413 """Reload the raw data from file or URL."""
402 """Reload the raw data from file or URL."""
414 if self.filename is not None:
403 if self.filename is not None:
415 with open(self.filename, self._read_flags) as f:
404 with open(self.filename, self._read_flags) as f:
416 self.data = f.read()
405 self.data = f.read()
417 elif self.url is not None:
406 elif self.url is not None:
418 try:
407 try:
419 try:
408 try:
420 from urllib.request import urlopen # Py3
409 from urllib.request import urlopen # Py3
421 except ImportError:
410 except ImportError:
422 from urllib2 import urlopen
411 from urllib2 import urlopen
423 response = urlopen(self.url)
412 response = urlopen(self.url)
424 self.data = response.read()
413 self.data = response.read()
425 # extract encoding from header, if there is one:
414 # extract encoding from header, if there is one:
426 encoding = None
415 encoding = None
427 for sub in response.headers['content-type'].split(';'):
416 for sub in response.headers['content-type'].split(';'):
428 sub = sub.strip()
417 sub = sub.strip()
429 if sub.startswith('charset'):
418 if sub.startswith('charset'):
430 encoding = sub.split('=')[-1].strip()
419 encoding = sub.split('=')[-1].strip()
431 break
420 break
432 # decode data, if an encoding was specified
421 # decode data, if an encoding was specified
433 if encoding:
422 if encoding:
434 self.data = self.data.decode(encoding, 'replace')
423 self.data = self.data.decode(encoding, 'replace')
435 except:
424 except:
436 self.data = None
425 self.data = None
437
426
438 class TextDisplayObject(DisplayObject):
427 class TextDisplayObject(DisplayObject):
439 """Validate that display data is text"""
428 """Validate that display data is text"""
440 def _check_data(self):
429 def _check_data(self):
441 if self.data is not None and not isinstance(self.data, string_types):
430 if self.data is not None and not isinstance(self.data, string_types):
442 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
431 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
443
432
444 class Pretty(TextDisplayObject):
433 class Pretty(TextDisplayObject):
445
434
446 def _repr_pretty_(self):
435 def _repr_pretty_(self):
447 return self.data
436 return self.data
448
437
449
438
450 class HTML(TextDisplayObject):
439 class HTML(TextDisplayObject):
451
440
452 def _repr_html_(self):
441 def _repr_html_(self):
453 return self.data
442 return self.data
454
443
455 def __html__(self):
444 def __html__(self):
456 """
445 """
457 This method exists to inform other HTML-using modules (e.g. Markupsafe,
446 This method exists to inform other HTML-using modules (e.g. Markupsafe,
458 htmltag, etc) that this object is HTML and does not need things like
447 htmltag, etc) that this object is HTML and does not need things like
459 special characters (<>&) escaped.
448 special characters (<>&) escaped.
460 """
449 """
461 return self._repr_html_()
450 return self._repr_html_()
462
451
463
452
464 class Markdown(TextDisplayObject):
453 class Markdown(TextDisplayObject):
465
454
466 def _repr_markdown_(self):
455 def _repr_markdown_(self):
467 return self.data
456 return self.data
468
457
469
458
470 class Math(TextDisplayObject):
459 class Math(TextDisplayObject):
471
460
472 def _repr_latex_(self):
461 def _repr_latex_(self):
473 s = self.data.strip('$')
462 s = self.data.strip('$')
474 return "$$%s$$" % s
463 return "$$%s$$" % s
475
464
476
465
477 class Latex(TextDisplayObject):
466 class Latex(TextDisplayObject):
478
467
479 def _repr_latex_(self):
468 def _repr_latex_(self):
480 return self.data
469 return self.data
481
470
482
471
483 class SVG(DisplayObject):
472 class SVG(DisplayObject):
484
473
485 # wrap data in a property, which extracts the <svg> tag, discarding
474 # wrap data in a property, which extracts the <svg> tag, discarding
486 # document headers
475 # document headers
487 _data = None
476 _data = None
488
477
489 @property
478 @property
490 def data(self):
479 def data(self):
491 return self._data
480 return self._data
492
481
493 @data.setter
482 @data.setter
494 def data(self, svg):
483 def data(self, svg):
495 if svg is None:
484 if svg is None:
496 self._data = None
485 self._data = None
497 return
486 return
498 # parse into dom object
487 # parse into dom object
499 from xml.dom import minidom
488 from xml.dom import minidom
500 svg = cast_bytes_py2(svg)
489 svg = cast_bytes_py2(svg)
501 x = minidom.parseString(svg)
490 x = minidom.parseString(svg)
502 # get svg tag (should be 1)
491 # get svg tag (should be 1)
503 found_svg = x.getElementsByTagName('svg')
492 found_svg = x.getElementsByTagName('svg')
504 if found_svg:
493 if found_svg:
505 svg = found_svg[0].toxml()
494 svg = found_svg[0].toxml()
506 else:
495 else:
507 # fallback on the input, trust the user
496 # fallback on the input, trust the user
508 # but this is probably an error.
497 # but this is probably an error.
509 pass
498 pass
510 svg = cast_unicode(svg)
499 svg = cast_unicode(svg)
511 self._data = svg
500 self._data = svg
512
501
513 def _repr_svg_(self):
502 def _repr_svg_(self):
514 return self.data
503 return self.data
515
504
516
505
517 class JSON(TextDisplayObject):
506 class JSON(DisplayObject):
507 """JSON expects a JSON-able dict or list
508
509 not an already-serialized JSON string.
510
511 Scalar types (None, number, string) are not allowed, only dict or list containers.
512 """
513 # wrap data in a property, which warns about passing already-serialized JSON
514 _data = None
515 def _check_data(self):
516 if self.data is not None and not isinstance(self.data, (dict, list)):
517 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
518
519 @property
520 def data(self):
521 return self._data
522
523 @data.setter
524 def data(self, data):
525 if isinstance(data, string_types):
526 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
527 data = json.loads(data)
528 self._data = data
518
529
519 def _repr_json_(self):
530 def _repr_json_(self):
520 return self.data
531 return self.data
521
532
522 css_t = """$("head").append($("<link/>").attr({
533 css_t = """$("head").append($("<link/>").attr({
523 rel: "stylesheet",
534 rel: "stylesheet",
524 type: "text/css",
535 type: "text/css",
525 href: "%s"
536 href: "%s"
526 }));
537 }));
527 """
538 """
528
539
529 lib_t1 = """$.getScript("%s", function () {
540 lib_t1 = """$.getScript("%s", function () {
530 """
541 """
531 lib_t2 = """});
542 lib_t2 = """});
532 """
543 """
533
544
534 class Javascript(TextDisplayObject):
545 class Javascript(TextDisplayObject):
535
546
536 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
547 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
537 """Create a Javascript display object given raw data.
548 """Create a Javascript display object given raw data.
538
549
539 When this object is returned by an expression or passed to the
550 When this object is returned by an expression or passed to the
540 display function, it will result in the data being displayed
551 display function, it will result in the data being displayed
541 in the frontend. If the data is a URL, the data will first be
552 in the frontend. If the data is a URL, the data will first be
542 downloaded and then displayed.
553 downloaded and then displayed.
543
554
544 In the Notebook, the containing element will be available as `element`,
555 In the Notebook, the containing element will be available as `element`,
545 and jQuery will be available. Content appended to `element` will be
556 and jQuery will be available. Content appended to `element` will be
546 visible in the output area.
557 visible in the output area.
547
558
548 Parameters
559 Parameters
549 ----------
560 ----------
550 data : unicode, str or bytes
561 data : unicode, str or bytes
551 The Javascript source code or a URL to download it from.
562 The Javascript source code or a URL to download it from.
552 url : unicode
563 url : unicode
553 A URL to download the data from.
564 A URL to download the data from.
554 filename : unicode
565 filename : unicode
555 Path to a local file to load the data from.
566 Path to a local file to load the data from.
556 lib : list or str
567 lib : list or str
557 A sequence of Javascript library URLs to load asynchronously before
568 A sequence of Javascript library URLs to load asynchronously before
558 running the source code. The full URLs of the libraries should
569 running the source code. The full URLs of the libraries should
559 be given. A single Javascript library URL can also be given as a
570 be given. A single Javascript library URL can also be given as a
560 string.
571 string.
561 css: : list or str
572 css: : list or str
562 A sequence of css files to load before running the source code.
573 A sequence of css files to load before running the source code.
563 The full URLs of the css files should be given. A single css URL
574 The full URLs of the css files should be given. A single css URL
564 can also be given as a string.
575 can also be given as a string.
565 """
576 """
566 if isinstance(lib, string_types):
577 if isinstance(lib, string_types):
567 lib = [lib]
578 lib = [lib]
568 elif lib is None:
579 elif lib is None:
569 lib = []
580 lib = []
570 if isinstance(css, string_types):
581 if isinstance(css, string_types):
571 css = [css]
582 css = [css]
572 elif css is None:
583 elif css is None:
573 css = []
584 css = []
574 if not isinstance(lib, (list,tuple)):
585 if not isinstance(lib, (list,tuple)):
575 raise TypeError('expected sequence, got: %r' % lib)
586 raise TypeError('expected sequence, got: %r' % lib)
576 if not isinstance(css, (list,tuple)):
587 if not isinstance(css, (list,tuple)):
577 raise TypeError('expected sequence, got: %r' % css)
588 raise TypeError('expected sequence, got: %r' % css)
578 self.lib = lib
589 self.lib = lib
579 self.css = css
590 self.css = css
580 super(Javascript, self).__init__(data=data, url=url, filename=filename)
591 super(Javascript, self).__init__(data=data, url=url, filename=filename)
581
592
582 def _repr_javascript_(self):
593 def _repr_javascript_(self):
583 r = ''
594 r = ''
584 for c in self.css:
595 for c in self.css:
585 r += css_t % c
596 r += css_t % c
586 for l in self.lib:
597 for l in self.lib:
587 r += lib_t1 % l
598 r += lib_t1 % l
588 r += self.data
599 r += self.data
589 r += lib_t2*len(self.lib)
600 r += lib_t2*len(self.lib)
590 return r
601 return r
591
602
592 # constants for identifying png/jpeg data
603 # constants for identifying png/jpeg data
593 _PNG = b'\x89PNG\r\n\x1a\n'
604 _PNG = b'\x89PNG\r\n\x1a\n'
594 _JPEG = b'\xff\xd8'
605 _JPEG = b'\xff\xd8'
595
606
596 def _pngxy(data):
607 def _pngxy(data):
597 """read the (width, height) from a PNG header"""
608 """read the (width, height) from a PNG header"""
598 ihdr = data.index(b'IHDR')
609 ihdr = data.index(b'IHDR')
599 # next 8 bytes are width/height
610 # next 8 bytes are width/height
600 w4h4 = data[ihdr+4:ihdr+12]
611 w4h4 = data[ihdr+4:ihdr+12]
601 return struct.unpack('>ii', w4h4)
612 return struct.unpack('>ii', w4h4)
602
613
603 def _jpegxy(data):
614 def _jpegxy(data):
604 """read the (width, height) from a JPEG header"""
615 """read the (width, height) from a JPEG header"""
605 # adapted from http://www.64lines.com/jpeg-width-height
616 # adapted from http://www.64lines.com/jpeg-width-height
606
617
607 idx = 4
618 idx = 4
608 while True:
619 while True:
609 block_size = struct.unpack('>H', data[idx:idx+2])[0]
620 block_size = struct.unpack('>H', data[idx:idx+2])[0]
610 idx = idx + block_size
621 idx = idx + block_size
611 if data[idx:idx+2] == b'\xFF\xC0':
622 if data[idx:idx+2] == b'\xFF\xC0':
612 # found Start of Frame
623 # found Start of Frame
613 iSOF = idx
624 iSOF = idx
614 break
625 break
615 else:
626 else:
616 # read another block
627 # read another block
617 idx += 2
628 idx += 2
618
629
619 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
630 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
620 return w, h
631 return w, h
621
632
622 class Image(DisplayObject):
633 class Image(DisplayObject):
623
634
624 _read_flags = 'rb'
635 _read_flags = 'rb'
625 _FMT_JPEG = u'jpeg'
636 _FMT_JPEG = u'jpeg'
626 _FMT_PNG = u'png'
637 _FMT_PNG = u'png'
627 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
638 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
628
639
629 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
640 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
630 """Create a PNG/JPEG image object given raw data.
641 """Create a PNG/JPEG image object given raw data.
631
642
632 When this object is returned by an input cell or passed to the
643 When this object is returned by an input cell or passed to the
633 display function, it will result in the image being displayed
644 display function, it will result in the image being displayed
634 in the frontend.
645 in the frontend.
635
646
636 Parameters
647 Parameters
637 ----------
648 ----------
638 data : unicode, str or bytes
649 data : unicode, str or bytes
639 The raw image data or a URL or filename to load the data from.
650 The raw image data or a URL or filename to load the data from.
640 This always results in embedded image data.
651 This always results in embedded image data.
641 url : unicode
652 url : unicode
642 A URL to download the data from. If you specify `url=`,
653 A URL to download the data from. If you specify `url=`,
643 the image data will not be embedded unless you also specify `embed=True`.
654 the image data will not be embedded unless you also specify `embed=True`.
644 filename : unicode
655 filename : unicode
645 Path to a local file to load the data from.
656 Path to a local file to load the data from.
646 Images from a file are always embedded.
657 Images from a file are always embedded.
647 format : unicode
658 format : unicode
648 The format of the image data (png/jpeg/jpg). If a filename or URL is given
659 The format of the image data (png/jpeg/jpg). If a filename or URL is given
649 for format will be inferred from the filename extension.
660 for format will be inferred from the filename extension.
650 embed : bool
661 embed : bool
651 Should the image data be embedded using a data URI (True) or be
662 Should the image data be embedded using a data URI (True) or be
652 loaded using an <img> tag. Set this to True if you want the image
663 loaded using an <img> tag. Set this to True if you want the image
653 to be viewable later with no internet connection in the notebook.
664 to be viewable later with no internet connection in the notebook.
654
665
655 Default is `True`, unless the keyword argument `url` is set, then
666 Default is `True`, unless the keyword argument `url` is set, then
656 default value is `False`.
667 default value is `False`.
657
668
658 Note that QtConsole is not able to display images if `embed` is set to `False`
669 Note that QtConsole is not able to display images if `embed` is set to `False`
659 width : int
670 width : int
660 Width to which to constrain the image in html
671 Width to which to constrain the image in html
661 height : int
672 height : int
662 Height to which to constrain the image in html
673 Height to which to constrain the image in html
663 retina : bool
674 retina : bool
664 Automatically set the width and height to half of the measured
675 Automatically set the width and height to half of the measured
665 width and height.
676 width and height.
666 This only works for embedded images because it reads the width/height
677 This only works for embedded images because it reads the width/height
667 from image data.
678 from image data.
668 For non-embedded images, you can just set the desired display width
679 For non-embedded images, you can just set the desired display width
669 and height directly.
680 and height directly.
670
681
671 Examples
682 Examples
672 --------
683 --------
673 # embedded image data, works in qtconsole and notebook
684 # embedded image data, works in qtconsole and notebook
674 # when passed positionally, the first arg can be any of raw image data,
685 # when passed positionally, the first arg can be any of raw image data,
675 # a URL, or a filename from which to load image data.
686 # a URL, or a filename from which to load image data.
676 # The result is always embedding image data for inline images.
687 # The result is always embedding image data for inline images.
677 Image('http://www.google.fr/images/srpr/logo3w.png')
688 Image('http://www.google.fr/images/srpr/logo3w.png')
678 Image('/path/to/image.jpg')
689 Image('/path/to/image.jpg')
679 Image(b'RAW_PNG_DATA...')
690 Image(b'RAW_PNG_DATA...')
680
691
681 # Specifying Image(url=...) does not embed the image data,
692 # Specifying Image(url=...) does not embed the image data,
682 # it only generates `<img>` tag with a link to the source.
693 # it only generates `<img>` tag with a link to the source.
683 # This will not work in the qtconsole or offline.
694 # This will not work in the qtconsole or offline.
684 Image(url='http://www.google.fr/images/srpr/logo3w.png')
695 Image(url='http://www.google.fr/images/srpr/logo3w.png')
685
696
686 """
697 """
687 if filename is not None:
698 if filename is not None:
688 ext = self._find_ext(filename)
699 ext = self._find_ext(filename)
689 elif url is not None:
700 elif url is not None:
690 ext = self._find_ext(url)
701 ext = self._find_ext(url)
691 elif data is None:
702 elif data is None:
692 raise ValueError("No image data found. Expecting filename, url, or data.")
703 raise ValueError("No image data found. Expecting filename, url, or data.")
693 elif isinstance(data, string_types) and (
704 elif isinstance(data, string_types) and (
694 data.startswith('http') or _safe_exists(data)
705 data.startswith('http') or _safe_exists(data)
695 ):
706 ):
696 ext = self._find_ext(data)
707 ext = self._find_ext(data)
697 else:
708 else:
698 ext = None
709 ext = None
699
710
700 if ext is not None:
711 if ext is not None:
701 format = ext.lower()
712 format = ext.lower()
702 if ext == u'jpg' or ext == u'jpeg':
713 if ext == u'jpg' or ext == u'jpeg':
703 format = self._FMT_JPEG
714 format = self._FMT_JPEG
704 if ext == u'png':
715 if ext == u'png':
705 format = self._FMT_PNG
716 format = self._FMT_PNG
706 elif isinstance(data, bytes) and format == 'png':
717 elif isinstance(data, bytes) and format == 'png':
707 # infer image type from image data header,
718 # infer image type from image data header,
708 # only if format might not have been specified.
719 # only if format might not have been specified.
709 if data[:2] == _JPEG:
720 if data[:2] == _JPEG:
710 format = 'jpeg'
721 format = 'jpeg'
711
722
712 self.format = unicode_type(format).lower()
723 self.format = unicode_type(format).lower()
713 self.embed = embed if embed is not None else (url is None)
724 self.embed = embed if embed is not None else (url is None)
714
725
715 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
726 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
716 raise ValueError("Cannot embed the '%s' image format" % (self.format))
727 raise ValueError("Cannot embed the '%s' image format" % (self.format))
717 self.width = width
728 self.width = width
718 self.height = height
729 self.height = height
719 self.retina = retina
730 self.retina = retina
720 super(Image, self).__init__(data=data, url=url, filename=filename)
731 super(Image, self).__init__(data=data, url=url, filename=filename)
721
732
722 if retina:
733 if retina:
723 self._retina_shape()
734 self._retina_shape()
724
735
725 def _retina_shape(self):
736 def _retina_shape(self):
726 """load pixel-doubled width and height from image data"""
737 """load pixel-doubled width and height from image data"""
727 if not self.embed:
738 if not self.embed:
728 return
739 return
729 if self.format == 'png':
740 if self.format == 'png':
730 w, h = _pngxy(self.data)
741 w, h = _pngxy(self.data)
731 elif self.format == 'jpeg':
742 elif self.format == 'jpeg':
732 w, h = _jpegxy(self.data)
743 w, h = _jpegxy(self.data)
733 else:
744 else:
734 # retina only supports png
745 # retina only supports png
735 return
746 return
736 self.width = w // 2
747 self.width = w // 2
737 self.height = h // 2
748 self.height = h // 2
738
749
739 def reload(self):
750 def reload(self):
740 """Reload the raw data from file or URL."""
751 """Reload the raw data from file or URL."""
741 if self.embed:
752 if self.embed:
742 super(Image,self).reload()
753 super(Image,self).reload()
743 if self.retina:
754 if self.retina:
744 self._retina_shape()
755 self._retina_shape()
745
756
746 def _repr_html_(self):
757 def _repr_html_(self):
747 if not self.embed:
758 if not self.embed:
748 width = height = ''
759 width = height = ''
749 if self.width:
760 if self.width:
750 width = ' width="%d"' % self.width
761 width = ' width="%d"' % self.width
751 if self.height:
762 if self.height:
752 height = ' height="%d"' % self.height
763 height = ' height="%d"' % self.height
753 return u'<img src="%s"%s%s/>' % (self.url, width, height)
764 return u'<img src="%s"%s%s/>' % (self.url, width, height)
754
765
755 def _data_and_metadata(self):
766 def _data_and_metadata(self):
756 """shortcut for returning metadata with shape information, if defined"""
767 """shortcut for returning metadata with shape information, if defined"""
757 md = {}
768 md = {}
758 if self.width:
769 if self.width:
759 md['width'] = self.width
770 md['width'] = self.width
760 if self.height:
771 if self.height:
761 md['height'] = self.height
772 md['height'] = self.height
762 if md:
773 if md:
763 return self.data, md
774 return self.data, md
764 else:
775 else:
765 return self.data
776 return self.data
766
777
767 def _repr_png_(self):
778 def _repr_png_(self):
768 if self.embed and self.format == u'png':
779 if self.embed and self.format == u'png':
769 return self._data_and_metadata()
780 return self._data_and_metadata()
770
781
771 def _repr_jpeg_(self):
782 def _repr_jpeg_(self):
772 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
783 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
773 return self._data_and_metadata()
784 return self._data_and_metadata()
774
785
775 def _find_ext(self, s):
786 def _find_ext(self, s):
776 return unicode_type(s.split('.')[-1].lower())
787 return unicode_type(s.split('.')[-1].lower())
777
788
778 class Video(DisplayObject):
789 class Video(DisplayObject):
779
790
780 def __init__(self, data=None, url=None, filename=None, embed=None, mimetype=None):
791 def __init__(self, data=None, url=None, filename=None, embed=None, mimetype=None):
781 """Create a video object given raw data or an URL.
792 """Create a video object given raw data or an URL.
782
793
783 When this object is returned by an input cell or passed to the
794 When this object is returned by an input cell or passed to the
784 display function, it will result in the video being displayed
795 display function, it will result in the video being displayed
785 in the frontend.
796 in the frontend.
786
797
787 Parameters
798 Parameters
788 ----------
799 ----------
789 data : unicode, str or bytes
800 data : unicode, str or bytes
790 The raw image data or a URL or filename to load the data from.
801 The raw image data or a URL or filename to load the data from.
791 This always results in embedded image data.
802 This always results in embedded image data.
792 url : unicode
803 url : unicode
793 A URL to download the data from. If you specify `url=`,
804 A URL to download the data from. If you specify `url=`,
794 the image data will not be embedded unless you also specify `embed=True`.
805 the image data will not be embedded unless you also specify `embed=True`.
795 filename : unicode
806 filename : unicode
796 Path to a local file to load the data from.
807 Path to a local file to load the data from.
797 Videos from a file are always embedded.
808 Videos from a file are always embedded.
798 embed : bool
809 embed : bool
799 Should the image data be embedded using a data URI (True) or be
810 Should the image data be embedded using a data URI (True) or be
800 loaded using an <img> tag. Set this to True if you want the image
811 loaded using an <img> tag. Set this to True if you want the image
801 to be viewable later with no internet connection in the notebook.
812 to be viewable later with no internet connection in the notebook.
802
813
803 Default is `True`, unless the keyword argument `url` is set, then
814 Default is `True`, unless the keyword argument `url` is set, then
804 default value is `False`.
815 default value is `False`.
805
816
806 Note that QtConsole is not able to display images if `embed` is set to `False`
817 Note that QtConsole is not able to display images if `embed` is set to `False`
807 mimetype: unicode
818 mimetype: unicode
808 Specify the mimetype in case you load in a encoded video.
819 Specify the mimetype in case you load in a encoded video.
809 Examples
820 Examples
810 --------
821 --------
811 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
822 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
812 Video('path/to/video.mp4')
823 Video('path/to/video.mp4')
813 Video('path/to/video.mp4', embed=False)
824 Video('path/to/video.mp4', embed=False)
814 """
825 """
815 if url is None and (data.startswith('http') or data.startswith('https')):
826 if url is None and (data.startswith('http') or data.startswith('https')):
816 url = data
827 url = data
817 data = None
828 data = None
818 embed = False
829 embed = False
819 elif os.path.exists(data):
830 elif os.path.exists(data):
820 filename = data
831 filename = data
821 data = None
832 data = None
822
833
823 self.mimetype = mimetype
834 self.mimetype = mimetype
824 self.embed = embed if embed is not None else (filename is not None)
835 self.embed = embed if embed is not None else (filename is not None)
825 super(Video, self).__init__(data=data, url=url, filename=filename)
836 super(Video, self).__init__(data=data, url=url, filename=filename)
826
837
827 def _repr_html_(self):
838 def _repr_html_(self):
828 # External URLs and potentially local files are not embedded into the
839 # External URLs and potentially local files are not embedded into the
829 # notebook output.
840 # notebook output.
830 if not self.embed:
841 if not self.embed:
831 url = self.url if self.url is not None else self.filename
842 url = self.url if self.url is not None else self.filename
832 output = """<video src="{0}" controls>
843 output = """<video src="{0}" controls>
833 Your browser does not support the <code>video</code> element.
844 Your browser does not support the <code>video</code> element.
834 </video>""".format(url)
845 </video>""".format(url)
835 return output
846 return output
836 # Embedded videos uses base64 encoded videos.
847 # Embedded videos uses base64 encoded videos.
837 if self.filename is not None:
848 if self.filename is not None:
838 mimetypes.init()
849 mimetypes.init()
839 mimetype, encoding = mimetypes.guess_type(self.filename)
850 mimetype, encoding = mimetypes.guess_type(self.filename)
840
851
841 video = open(self.filename, 'rb').read()
852 video = open(self.filename, 'rb').read()
842 video_encoded = video.encode('base64')
853 video_encoded = video.encode('base64')
843 else:
854 else:
844 video_encoded = self.data
855 video_encoded = self.data
845 mimetype = self.mimetype
856 mimetype = self.mimetype
846 output = """<video controls>
857 output = """<video controls>
847 <source src="data:{0};base64,{1}" type="{0}">
858 <source src="data:{0};base64,{1}" type="{0}">
848 Your browser does not support the video tag.
859 Your browser does not support the video tag.
849 </video>""".format(mimetype, video_encoded)
860 </video>""".format(mimetype, video_encoded)
850 return output
861 return output
851
862
852 def reload(self):
863 def reload(self):
853 # TODO
864 # TODO
854 pass
865 pass
855
866
856 def _repr_png_(self):
867 def _repr_png_(self):
857 # TODO
868 # TODO
858 pass
869 pass
859 def _repr_jpeg_(self):
870 def _repr_jpeg_(self):
860 # TODO
871 # TODO
861 pass
872 pass
862
873
863 def clear_output(wait=False):
874 def clear_output(wait=False):
864 """Clear the output of the current cell receiving output.
875 """Clear the output of the current cell receiving output.
865
876
866 Parameters
877 Parameters
867 ----------
878 ----------
868 wait : bool [default: false]
879 wait : bool [default: false]
869 Wait to clear the output until new output is available to replace it."""
880 Wait to clear the output until new output is available to replace it."""
870 from IPython.core.interactiveshell import InteractiveShell
881 from IPython.core.interactiveshell import InteractiveShell
871 if InteractiveShell.initialized():
882 if InteractiveShell.initialized():
872 InteractiveShell.instance().display_pub.clear_output(wait)
883 InteractiveShell.instance().display_pub.clear_output(wait)
873 else:
884 else:
874 from IPython.utils import io
885 from IPython.utils import io
875 print('\033[2K\r', file=io.stdout, end='')
886 print('\033[2K\r', file=io.stdout, end='')
876 io.stdout.flush()
887 io.stdout.flush()
877 print('\033[2K\r', file=io.stderr, end='')
888 print('\033[2K\r', file=io.stderr, end='')
878 io.stderr.flush()
889 io.stderr.flush()
879
890
880
891
881 @skip_doctest
892 @skip_doctest
882 def set_matplotlib_formats(*formats, **kwargs):
893 def set_matplotlib_formats(*formats, **kwargs):
883 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
894 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
884
895
885 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
896 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
886
897
887 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
898 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
888
899
889 To set this in your config files use the following::
900 To set this in your config files use the following::
890
901
891 c.InlineBackend.figure_formats = {'png', 'jpeg'}
902 c.InlineBackend.figure_formats = {'png', 'jpeg'}
892 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
903 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
893
904
894 Parameters
905 Parameters
895 ----------
906 ----------
896 *formats : strs
907 *formats : strs
897 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
908 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
898 **kwargs :
909 **kwargs :
899 Keyword args will be relayed to ``figure.canvas.print_figure``.
910 Keyword args will be relayed to ``figure.canvas.print_figure``.
900 """
911 """
901 from IPython.core.interactiveshell import InteractiveShell
912 from IPython.core.interactiveshell import InteractiveShell
902 from IPython.core.pylabtools import select_figure_formats
913 from IPython.core.pylabtools import select_figure_formats
903 from IPython.kernel.zmq.pylab.config import InlineBackend
914 from IPython.kernel.zmq.pylab.config import InlineBackend
904 # build kwargs, starting with InlineBackend config
915 # build kwargs, starting with InlineBackend config
905 kw = {}
916 kw = {}
906 cfg = InlineBackend.instance()
917 cfg = InlineBackend.instance()
907 kw.update(cfg.print_figure_kwargs)
918 kw.update(cfg.print_figure_kwargs)
908 kw.update(**kwargs)
919 kw.update(**kwargs)
909 shell = InteractiveShell.instance()
920 shell = InteractiveShell.instance()
910 select_figure_formats(shell, formats, **kw)
921 select_figure_formats(shell, formats, **kw)
911
922
912 @skip_doctest
923 @skip_doctest
913 def set_matplotlib_close(close=True):
924 def set_matplotlib_close(close=True):
914 """Set whether the inline backend closes all figures automatically or not.
925 """Set whether the inline backend closes all figures automatically or not.
915
926
916 By default, the inline backend used in the IPython Notebook will close all
927 By default, the inline backend used in the IPython Notebook will close all
917 matplotlib figures automatically after each cell is run. This means that
928 matplotlib figures automatically after each cell is run. This means that
918 plots in different cells won't interfere. Sometimes, you may want to make
929 plots in different cells won't interfere. Sometimes, you may want to make
919 a plot in one cell and then refine it in later cells. This can be accomplished
930 a plot in one cell and then refine it in later cells. This can be accomplished
920 by::
931 by::
921
932
922 In [1]: set_matplotlib_close(False)
933 In [1]: set_matplotlib_close(False)
923
934
924 To set this in your config files use the following::
935 To set this in your config files use the following::
925
936
926 c.InlineBackend.close_figures = False
937 c.InlineBackend.close_figures = False
927
938
928 Parameters
939 Parameters
929 ----------
940 ----------
930 close : bool
941 close : bool
931 Should all matplotlib figures be automatically closed after each cell is
942 Should all matplotlib figures be automatically closed after each cell is
932 run?
943 run?
933 """
944 """
934 from IPython.kernel.zmq.pylab.config import InlineBackend
945 from IPython.kernel.zmq.pylab.config import InlineBackend
935 cfg = InlineBackend.instance()
946 cfg = InlineBackend.instance()
936 cfg.close_figures = close
947 cfg.close_figures = close
937
948
@@ -1,938 +1,970 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Display formatters.
2 """Display formatters.
3
3
4 Inheritance diagram:
4 Inheritance diagram:
5
5
6 .. inheritance-diagram:: IPython.core.formatters
6 .. inheritance-diagram:: IPython.core.formatters
7 :parts: 3
7 :parts: 3
8 """
8 """
9
9
10 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12
12
13 import abc
13 import abc
14 import inspect
14 import inspect
15 import json
15 import sys
16 import sys
16 import traceback
17 import traceback
17 import warnings
18 import warnings
18
19
19 from IPython.external.decorator import decorator
20 from IPython.external.decorator import decorator
20
21
21 from IPython.config.configurable import Configurable
22 from IPython.config.configurable import Configurable
22 from IPython.core.getipython import get_ipython
23 from IPython.core.getipython import get_ipython
23 from IPython.lib import pretty
24 from IPython.lib import pretty
24 from IPython.utils.traitlets import (
25 from IPython.utils.traitlets import (
25 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
26 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
26 ForwardDeclaredInstance,
27 ForwardDeclaredInstance,
27 )
28 )
28 from IPython.utils.py3compat import (
29 from IPython.utils.py3compat import (
29 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
30 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
30 )
31 )
31
32
32 if PY3:
33 if PY3:
33 from io import StringIO
34 from io import StringIO
34 else:
35 else:
35 from StringIO import StringIO
36 from StringIO import StringIO
36
37
37
38
38 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
39 # The main DisplayFormatter class
40 # The main DisplayFormatter class
40 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
41
42
42
43
43 def _safe_get_formatter_method(obj, name):
44 def _safe_get_formatter_method(obj, name):
44 """Safely get a formatter method
45 """Safely get a formatter method
45
46
46 - Classes cannot have formatter methods, only instance
47 - Classes cannot have formatter methods, only instance
47 - protect against proxy objects that claim to have everything
48 - protect against proxy objects that claim to have everything
48 """
49 """
49 if inspect.isclass(obj):
50 if inspect.isclass(obj):
50 # repr methods only make sense on instances, not classes
51 # repr methods only make sense on instances, not classes
51 return None
52 return None
52 method = pretty._safe_getattr(obj, name, None)
53 method = pretty._safe_getattr(obj, name, None)
53 if callable(method):
54 if callable(method):
54 # obj claims to have repr method...
55 # obj claims to have repr method...
55 if callable(pretty._safe_getattr(obj, '_ipython_canary_method_should_not_exist_', None)):
56 if callable(pretty._safe_getattr(obj, '_ipython_canary_method_should_not_exist_', None)):
56 # ...but don't trust proxy objects that claim to have everything
57 # ...but don't trust proxy objects that claim to have everything
57 return None
58 return None
58 return method
59 return method
59
60
60
61
61 class DisplayFormatter(Configurable):
62 class DisplayFormatter(Configurable):
62
63
63 # When set to true only the default plain text formatter will be used.
64 # When set to true only the default plain text formatter will be used.
64 plain_text_only = Bool(False, config=True)
65 plain_text_only = Bool(False, config=True)
65 def _plain_text_only_changed(self, name, old, new):
66 def _plain_text_only_changed(self, name, old, new):
66 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
67 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
67
68
68 Use DisplayFormatter.active_types = ['text/plain']
69 Use DisplayFormatter.active_types = ['text/plain']
69 for the same effect.
70 for the same effect.
70 """, DeprecationWarning)
71 """, DeprecationWarning)
71 if new:
72 if new:
72 self.active_types = ['text/plain']
73 self.active_types = ['text/plain']
73 else:
74 else:
74 self.active_types = self.format_types
75 self.active_types = self.format_types
75
76
76 active_types = List(Unicode, config=True,
77 active_types = List(Unicode, config=True,
77 help="""List of currently active mime-types to display.
78 help="""List of currently active mime-types to display.
78 You can use this to set a white-list for formats to display.
79 You can use this to set a white-list for formats to display.
79
80
80 Most users will not need to change this value.
81 Most users will not need to change this value.
81 """)
82 """)
82 def _active_types_default(self):
83 def _active_types_default(self):
83 return self.format_types
84 return self.format_types
84
85
85 def _active_types_changed(self, name, old, new):
86 def _active_types_changed(self, name, old, new):
86 for key, formatter in self.formatters.items():
87 for key, formatter in self.formatters.items():
87 if key in new:
88 if key in new:
88 formatter.enabled = True
89 formatter.enabled = True
89 else:
90 else:
90 formatter.enabled = False
91 formatter.enabled = False
91
92
92 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
93 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
93 def _ipython_display_formatter_default(self):
94 def _ipython_display_formatter_default(self):
94 return IPythonDisplayFormatter(parent=self)
95 return IPythonDisplayFormatter(parent=self)
95
96
96 # A dict of formatter whose keys are format types (MIME types) and whose
97 # A dict of formatter whose keys are format types (MIME types) and whose
97 # values are subclasses of BaseFormatter.
98 # values are subclasses of BaseFormatter.
98 formatters = Dict()
99 formatters = Dict()
99 def _formatters_default(self):
100 def _formatters_default(self):
100 """Activate the default formatters."""
101 """Activate the default formatters."""
101 formatter_classes = [
102 formatter_classes = [
102 PlainTextFormatter,
103 PlainTextFormatter,
103 HTMLFormatter,
104 HTMLFormatter,
104 MarkdownFormatter,
105 MarkdownFormatter,
105 SVGFormatter,
106 SVGFormatter,
106 PNGFormatter,
107 PNGFormatter,
107 PDFFormatter,
108 PDFFormatter,
108 JPEGFormatter,
109 JPEGFormatter,
109 LatexFormatter,
110 LatexFormatter,
110 JSONFormatter,
111 JSONFormatter,
111 JavascriptFormatter
112 JavascriptFormatter
112 ]
113 ]
113 d = {}
114 d = {}
114 for cls in formatter_classes:
115 for cls in formatter_classes:
115 f = cls(parent=self)
116 f = cls(parent=self)
116 d[f.format_type] = f
117 d[f.format_type] = f
117 return d
118 return d
118
119
119 def format(self, obj, include=None, exclude=None):
120 def format(self, obj, include=None, exclude=None):
120 """Return a format data dict for an object.
121 """Return a format data dict for an object.
121
122
122 By default all format types will be computed.
123 By default all format types will be computed.
123
124
124 The following MIME types are currently implemented:
125 The following MIME types are currently implemented:
125
126
126 * text/plain
127 * text/plain
127 * text/html
128 * text/html
128 * text/markdown
129 * text/markdown
129 * text/latex
130 * text/latex
130 * application/json
131 * application/json
131 * application/javascript
132 * application/javascript
132 * application/pdf
133 * application/pdf
133 * image/png
134 * image/png
134 * image/jpeg
135 * image/jpeg
135 * image/svg+xml
136 * image/svg+xml
136
137
137 Parameters
138 Parameters
138 ----------
139 ----------
139 obj : object
140 obj : object
140 The Python object whose format data will be computed.
141 The Python object whose format data will be computed.
141 include : list or tuple, optional
142 include : list or tuple, optional
142 A list of format type strings (MIME types) to include in the
143 A list of format type strings (MIME types) to include in the
143 format data dict. If this is set *only* the format types included
144 format data dict. If this is set *only* the format types included
144 in this list will be computed.
145 in this list will be computed.
145 exclude : list or tuple, optional
146 exclude : list or tuple, optional
146 A list of format type string (MIME types) to exclude in the format
147 A list of format type string (MIME types) to exclude in the format
147 data dict. If this is set all format types will be computed,
148 data dict. If this is set all format types will be computed,
148 except for those included in this argument.
149 except for those included in this argument.
149
150
150 Returns
151 Returns
151 -------
152 -------
152 (format_dict, metadata_dict) : tuple of two dicts
153 (format_dict, metadata_dict) : tuple of two dicts
153
154
154 format_dict is a dictionary of key/value pairs, one of each format that was
155 format_dict is a dictionary of key/value pairs, one of each format that was
155 generated for the object. The keys are the format types, which
156 generated for the object. The keys are the format types, which
156 will usually be MIME type strings and the values and JSON'able
157 will usually be MIME type strings and the values and JSON'able
157 data structure containing the raw data for the representation in
158 data structure containing the raw data for the representation in
158 that format.
159 that format.
159
160
160 metadata_dict is a dictionary of metadata about each mime-type output.
161 metadata_dict is a dictionary of metadata about each mime-type output.
161 Its keys will be a strict subset of the keys in format_dict.
162 Its keys will be a strict subset of the keys in format_dict.
162 """
163 """
163 format_dict = {}
164 format_dict = {}
164 md_dict = {}
165 md_dict = {}
165
166
166 if self.ipython_display_formatter(obj):
167 if self.ipython_display_formatter(obj):
167 # object handled itself, don't proceed
168 # object handled itself, don't proceed
168 return {}, {}
169 return {}, {}
169
170
170 for format_type, formatter in self.formatters.items():
171 for format_type, formatter in self.formatters.items():
171 if include and format_type not in include:
172 if include and format_type not in include:
172 continue
173 continue
173 if exclude and format_type in exclude:
174 if exclude and format_type in exclude:
174 continue
175 continue
175
176
176 md = None
177 md = None
177 try:
178 try:
178 data = formatter(obj)
179 data = formatter(obj)
179 except:
180 except:
180 # FIXME: log the exception
181 # FIXME: log the exception
181 raise
182 raise
182
183
183 # formatters can return raw data or (data, metadata)
184 # formatters can return raw data or (data, metadata)
184 if isinstance(data, tuple) and len(data) == 2:
185 if isinstance(data, tuple) and len(data) == 2:
185 data, md = data
186 data, md = data
186
187
187 if data is not None:
188 if data is not None:
188 format_dict[format_type] = data
189 format_dict[format_type] = data
189 if md is not None:
190 if md is not None:
190 md_dict[format_type] = md
191 md_dict[format_type] = md
191
192
192 return format_dict, md_dict
193 return format_dict, md_dict
193
194
194 @property
195 @property
195 def format_types(self):
196 def format_types(self):
196 """Return the format types (MIME types) of the active formatters."""
197 """Return the format types (MIME types) of the active formatters."""
197 return list(self.formatters.keys())
198 return list(self.formatters.keys())
198
199
199
200
200 #-----------------------------------------------------------------------------
201 #-----------------------------------------------------------------------------
201 # Formatters for specific format types (text, html, svg, etc.)
202 # Formatters for specific format types (text, html, svg, etc.)
202 #-----------------------------------------------------------------------------
203 #-----------------------------------------------------------------------------
203
204
204
205
205 def _safe_repr(obj):
206 def _safe_repr(obj):
206 """Try to return a repr of an object
207 """Try to return a repr of an object
207
208
208 always returns a string, at least.
209 always returns a string, at least.
209 """
210 """
210 try:
211 try:
211 return repr(obj)
212 return repr(obj)
212 except Exception as e:
213 except Exception as e:
213 return "un-repr-able object (%r)" % e
214 return "un-repr-able object (%r)" % e
214
215
215
216
216 class FormatterWarning(UserWarning):
217 class FormatterWarning(UserWarning):
217 """Warning class for errors in formatters"""
218 """Warning class for errors in formatters"""
218
219
219 @decorator
220 @decorator
220 def warn_format_error(method, self, *args, **kwargs):
221 def warn_format_error(method, self, *args, **kwargs):
221 """decorator for warning on failed format call"""
222 """decorator for warning on failed format call"""
222 try:
223 try:
223 r = method(self, *args, **kwargs)
224 r = method(self, *args, **kwargs)
224 except NotImplementedError:
225 except NotImplementedError:
225 # don't warn on NotImplementedErrors
226 # don't warn on NotImplementedErrors
226 return None
227 return None
227 except Exception:
228 except Exception:
228 exc_info = sys.exc_info()
229 exc_info = sys.exc_info()
229 ip = get_ipython()
230 ip = get_ipython()
230 if ip is not None:
231 if ip is not None:
231 ip.showtraceback(exc_info)
232 ip.showtraceback(exc_info)
232 else:
233 else:
233 traceback.print_exception(*exc_info)
234 traceback.print_exception(*exc_info)
234 return None
235 return None
235 if r is None or isinstance(r, self._return_type) or \
236 return self._check_return(r, args[0])
236 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
237 return r
238 else:
239 warnings.warn(
240 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
241 (self.format_type, type(r), self._return_type, _safe_repr(args[0])),
242 FormatterWarning
243 )
244
237
245
238
246 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
239 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
247 """ Abstract base class for Formatters.
240 """ Abstract base class for Formatters.
248
241
249 A formatter is a callable class that is responsible for computing the
242 A formatter is a callable class that is responsible for computing the
250 raw format data for a particular format type (MIME type). For example,
243 raw format data for a particular format type (MIME type). For example,
251 an HTML formatter would have a format type of `text/html` and would return
244 an HTML formatter would have a format type of `text/html` and would return
252 the HTML representation of the object when called.
245 the HTML representation of the object when called.
253 """
246 """
254
247
255 # The format type of the data returned, usually a MIME type.
248 # The format type of the data returned, usually a MIME type.
256 format_type = 'text/plain'
249 format_type = 'text/plain'
257
250
258 # Is the formatter enabled...
251 # Is the formatter enabled...
259 enabled = True
252 enabled = True
260
253
261 @abc.abstractmethod
254 @abc.abstractmethod
262 @warn_format_error
263 def __call__(self, obj):
255 def __call__(self, obj):
264 """Return a JSON'able representation of the object.
256 """Return a JSON'able representation of the object.
265
257
266 If the object cannot be formatted by this formatter,
258 If the object cannot be formatted by this formatter,
267 warn and return None.
259 warn and return None.
268 """
260 """
269 return repr(obj)
261 return repr(obj)
270
262
271
263
272 def _mod_name_key(typ):
264 def _mod_name_key(typ):
273 """Return a (__module__, __name__) tuple for a type.
265 """Return a (__module__, __name__) tuple for a type.
274
266
275 Used as key in Formatter.deferred_printers.
267 Used as key in Formatter.deferred_printers.
276 """
268 """
277 module = getattr(typ, '__module__', None)
269 module = getattr(typ, '__module__', None)
278 name = getattr(typ, '__name__', None)
270 name = getattr(typ, '__name__', None)
279 return (module, name)
271 return (module, name)
280
272
281
273
282 def _get_type(obj):
274 def _get_type(obj):
283 """Return the type of an instance (old and new-style)"""
275 """Return the type of an instance (old and new-style)"""
284 return getattr(obj, '__class__', None) or type(obj)
276 return getattr(obj, '__class__', None) or type(obj)
285
277
286 _raise_key_error = object()
278 _raise_key_error = object()
287
279
288
280
289 class BaseFormatter(Configurable):
281 class BaseFormatter(Configurable):
290 """A base formatter class that is configurable.
282 """A base formatter class that is configurable.
291
283
292 This formatter should usually be used as the base class of all formatters.
284 This formatter should usually be used as the base class of all formatters.
293 It is a traited :class:`Configurable` class and includes an extensible
285 It is a traited :class:`Configurable` class and includes an extensible
294 API for users to determine how their objects are formatted. The following
286 API for users to determine how their objects are formatted. The following
295 logic is used to find a function to format an given object.
287 logic is used to find a function to format an given object.
296
288
297 1. The object is introspected to see if it has a method with the name
289 1. The object is introspected to see if it has a method with the name
298 :attr:`print_method`. If is does, that object is passed to that method
290 :attr:`print_method`. If is does, that object is passed to that method
299 for formatting.
291 for formatting.
300 2. If no print method is found, three internal dictionaries are consulted
292 2. If no print method is found, three internal dictionaries are consulted
301 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
293 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
302 and :attr:`deferred_printers`.
294 and :attr:`deferred_printers`.
303
295
304 Users should use these dictionaries to register functions that will be
296 Users should use these dictionaries to register functions that will be
305 used to compute the format data for their objects (if those objects don't
297 used to compute the format data for their objects (if those objects don't
306 have the special print methods). The easiest way of using these
298 have the special print methods). The easiest way of using these
307 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
299 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
308 methods.
300 methods.
309
301
310 If no function/callable is found to compute the format data, ``None`` is
302 If no function/callable is found to compute the format data, ``None`` is
311 returned and this format type is not used.
303 returned and this format type is not used.
312 """
304 """
313
305
314 format_type = Unicode('text/plain')
306 format_type = Unicode('text/plain')
315 _return_type = string_types
307 _return_type = string_types
316
308
317 enabled = Bool(True, config=True)
309 enabled = Bool(True, config=True)
318
310
319 print_method = ObjectName('__repr__')
311 print_method = ObjectName('__repr__')
320
312
321 # The singleton printers.
313 # The singleton printers.
322 # Maps the IDs of the builtin singleton objects to the format functions.
314 # Maps the IDs of the builtin singleton objects to the format functions.
323 singleton_printers = Dict(config=True)
315 singleton_printers = Dict(config=True)
324
316
325 # The type-specific printers.
317 # The type-specific printers.
326 # Map type objects to the format functions.
318 # Map type objects to the format functions.
327 type_printers = Dict(config=True)
319 type_printers = Dict(config=True)
328
320
329 # The deferred-import type-specific printers.
321 # The deferred-import type-specific printers.
330 # Map (modulename, classname) pairs to the format functions.
322 # Map (modulename, classname) pairs to the format functions.
331 deferred_printers = Dict(config=True)
323 deferred_printers = Dict(config=True)
332
324
333 @warn_format_error
325 @warn_format_error
334 def __call__(self, obj):
326 def __call__(self, obj):
335 """Compute the format for an object."""
327 """Compute the format for an object."""
336 if self.enabled:
328 if self.enabled:
337 # lookup registered printer
329 # lookup registered printer
338 try:
330 try:
339 printer = self.lookup(obj)
331 printer = self.lookup(obj)
340 except KeyError:
332 except KeyError:
341 pass
333 pass
342 else:
334 else:
343 return printer(obj)
335 return printer(obj)
344 # Finally look for special method names
336 # Finally look for special method names
345 method = _safe_get_formatter_method(obj, self.print_method)
337 method = _safe_get_formatter_method(obj, self.print_method)
346 if method is not None:
338 if method is not None:
347 return method()
339 return method()
348 return None
340 return None
349 else:
341 else:
350 return None
342 return None
351
343
352 def __contains__(self, typ):
344 def __contains__(self, typ):
353 """map in to lookup_by_type"""
345 """map in to lookup_by_type"""
354 try:
346 try:
355 self.lookup_by_type(typ)
347 self.lookup_by_type(typ)
356 except KeyError:
348 except KeyError:
357 return False
349 return False
358 else:
350 else:
359 return True
351 return True
360
352
353 def _check_return(self, r, obj):
354 """Check that a return value is appropriate
355
356 Return the value if so, None otherwise, warning if invalid.
357 """
358 if r is None or isinstance(r, self._return_type) or \
359 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
360 return r
361 else:
362 warnings.warn(
363 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
364 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
365 FormatterWarning
366 )
367
361 def lookup(self, obj):
368 def lookup(self, obj):
362 """Look up the formatter for a given instance.
369 """Look up the formatter for a given instance.
363
370
364 Parameters
371 Parameters
365 ----------
372 ----------
366 obj : object instance
373 obj : object instance
367
374
368 Returns
375 Returns
369 -------
376 -------
370 f : callable
377 f : callable
371 The registered formatting callable for the type.
378 The registered formatting callable for the type.
372
379
373 Raises
380 Raises
374 ------
381 ------
375 KeyError if the type has not been registered.
382 KeyError if the type has not been registered.
376 """
383 """
377 # look for singleton first
384 # look for singleton first
378 obj_id = id(obj)
385 obj_id = id(obj)
379 if obj_id in self.singleton_printers:
386 if obj_id in self.singleton_printers:
380 return self.singleton_printers[obj_id]
387 return self.singleton_printers[obj_id]
381 # then lookup by type
388 # then lookup by type
382 return self.lookup_by_type(_get_type(obj))
389 return self.lookup_by_type(_get_type(obj))
383
390
384 def lookup_by_type(self, typ):
391 def lookup_by_type(self, typ):
385 """Look up the registered formatter for a type.
392 """Look up the registered formatter for a type.
386
393
387 Parameters
394 Parameters
388 ----------
395 ----------
389 typ : type or '__module__.__name__' string for a type
396 typ : type or '__module__.__name__' string for a type
390
397
391 Returns
398 Returns
392 -------
399 -------
393 f : callable
400 f : callable
394 The registered formatting callable for the type.
401 The registered formatting callable for the type.
395
402
396 Raises
403 Raises
397 ------
404 ------
398 KeyError if the type has not been registered.
405 KeyError if the type has not been registered.
399 """
406 """
400 if isinstance(typ, string_types):
407 if isinstance(typ, string_types):
401 typ_key = tuple(typ.rsplit('.',1))
408 typ_key = tuple(typ.rsplit('.',1))
402 if typ_key not in self.deferred_printers:
409 if typ_key not in self.deferred_printers:
403 # We may have it cached in the type map. We will have to
410 # We may have it cached in the type map. We will have to
404 # iterate over all of the types to check.
411 # iterate over all of the types to check.
405 for cls in self.type_printers:
412 for cls in self.type_printers:
406 if _mod_name_key(cls) == typ_key:
413 if _mod_name_key(cls) == typ_key:
407 return self.type_printers[cls]
414 return self.type_printers[cls]
408 else:
415 else:
409 return self.deferred_printers[typ_key]
416 return self.deferred_printers[typ_key]
410 else:
417 else:
411 for cls in pretty._get_mro(typ):
418 for cls in pretty._get_mro(typ):
412 if cls in self.type_printers or self._in_deferred_types(cls):
419 if cls in self.type_printers or self._in_deferred_types(cls):
413 return self.type_printers[cls]
420 return self.type_printers[cls]
414
421
415 # If we have reached here, the lookup failed.
422 # If we have reached here, the lookup failed.
416 raise KeyError("No registered printer for {0!r}".format(typ))
423 raise KeyError("No registered printer for {0!r}".format(typ))
417
424
418 def for_type(self, typ, func=None):
425 def for_type(self, typ, func=None):
419 """Add a format function for a given type.
426 """Add a format function for a given type.
420
427
421 Parameters
428 Parameters
422 -----------
429 -----------
423 typ : type or '__module__.__name__' string for a type
430 typ : type or '__module__.__name__' string for a type
424 The class of the object that will be formatted using `func`.
431 The class of the object that will be formatted using `func`.
425 func : callable
432 func : callable
426 A callable for computing the format data.
433 A callable for computing the format data.
427 `func` will be called with the object to be formatted,
434 `func` will be called with the object to be formatted,
428 and will return the raw data in this formatter's format.
435 and will return the raw data in this formatter's format.
429 Subclasses may use a different call signature for the
436 Subclasses may use a different call signature for the
430 `func` argument.
437 `func` argument.
431
438
432 If `func` is None or not specified, there will be no change,
439 If `func` is None or not specified, there will be no change,
433 only returning the current value.
440 only returning the current value.
434
441
435 Returns
442 Returns
436 -------
443 -------
437 oldfunc : callable
444 oldfunc : callable
438 The currently registered callable.
445 The currently registered callable.
439 If you are registering a new formatter,
446 If you are registering a new formatter,
440 this will be the previous value (to enable restoring later).
447 this will be the previous value (to enable restoring later).
441 """
448 """
442 # if string given, interpret as 'pkg.module.class_name'
449 # if string given, interpret as 'pkg.module.class_name'
443 if isinstance(typ, string_types):
450 if isinstance(typ, string_types):
444 type_module, type_name = typ.rsplit('.', 1)
451 type_module, type_name = typ.rsplit('.', 1)
445 return self.for_type_by_name(type_module, type_name, func)
452 return self.for_type_by_name(type_module, type_name, func)
446
453
447 try:
454 try:
448 oldfunc = self.lookup_by_type(typ)
455 oldfunc = self.lookup_by_type(typ)
449 except KeyError:
456 except KeyError:
450 oldfunc = None
457 oldfunc = None
451
458
452 if func is not None:
459 if func is not None:
453 self.type_printers[typ] = func
460 self.type_printers[typ] = func
454
461
455 return oldfunc
462 return oldfunc
456
463
457 def for_type_by_name(self, type_module, type_name, func=None):
464 def for_type_by_name(self, type_module, type_name, func=None):
458 """Add a format function for a type specified by the full dotted
465 """Add a format function for a type specified by the full dotted
459 module and name of the type, rather than the type of the object.
466 module and name of the type, rather than the type of the object.
460
467
461 Parameters
468 Parameters
462 ----------
469 ----------
463 type_module : str
470 type_module : str
464 The full dotted name of the module the type is defined in, like
471 The full dotted name of the module the type is defined in, like
465 ``numpy``.
472 ``numpy``.
466 type_name : str
473 type_name : str
467 The name of the type (the class name), like ``dtype``
474 The name of the type (the class name), like ``dtype``
468 func : callable
475 func : callable
469 A callable for computing the format data.
476 A callable for computing the format data.
470 `func` will be called with the object to be formatted,
477 `func` will be called with the object to be formatted,
471 and will return the raw data in this formatter's format.
478 and will return the raw data in this formatter's format.
472 Subclasses may use a different call signature for the
479 Subclasses may use a different call signature for the
473 `func` argument.
480 `func` argument.
474
481
475 If `func` is None or unspecified, there will be no change,
482 If `func` is None or unspecified, there will be no change,
476 only returning the current value.
483 only returning the current value.
477
484
478 Returns
485 Returns
479 -------
486 -------
480 oldfunc : callable
487 oldfunc : callable
481 The currently registered callable.
488 The currently registered callable.
482 If you are registering a new formatter,
489 If you are registering a new formatter,
483 this will be the previous value (to enable restoring later).
490 this will be the previous value (to enable restoring later).
484 """
491 """
485 key = (type_module, type_name)
492 key = (type_module, type_name)
486
493
487 try:
494 try:
488 oldfunc = self.lookup_by_type("%s.%s" % key)
495 oldfunc = self.lookup_by_type("%s.%s" % key)
489 except KeyError:
496 except KeyError:
490 oldfunc = None
497 oldfunc = None
491
498
492 if func is not None:
499 if func is not None:
493 self.deferred_printers[key] = func
500 self.deferred_printers[key] = func
494 return oldfunc
501 return oldfunc
495
502
496 def pop(self, typ, default=_raise_key_error):
503 def pop(self, typ, default=_raise_key_error):
497 """Pop a formatter for the given type.
504 """Pop a formatter for the given type.
498
505
499 Parameters
506 Parameters
500 ----------
507 ----------
501 typ : type or '__module__.__name__' string for a type
508 typ : type or '__module__.__name__' string for a type
502 default : object
509 default : object
503 value to be returned if no formatter is registered for typ.
510 value to be returned if no formatter is registered for typ.
504
511
505 Returns
512 Returns
506 -------
513 -------
507 obj : object
514 obj : object
508 The last registered object for the type.
515 The last registered object for the type.
509
516
510 Raises
517 Raises
511 ------
518 ------
512 KeyError if the type is not registered and default is not specified.
519 KeyError if the type is not registered and default is not specified.
513 """
520 """
514
521
515 if isinstance(typ, string_types):
522 if isinstance(typ, string_types):
516 typ_key = tuple(typ.rsplit('.',1))
523 typ_key = tuple(typ.rsplit('.',1))
517 if typ_key not in self.deferred_printers:
524 if typ_key not in self.deferred_printers:
518 # We may have it cached in the type map. We will have to
525 # We may have it cached in the type map. We will have to
519 # iterate over all of the types to check.
526 # iterate over all of the types to check.
520 for cls in self.type_printers:
527 for cls in self.type_printers:
521 if _mod_name_key(cls) == typ_key:
528 if _mod_name_key(cls) == typ_key:
522 old = self.type_printers.pop(cls)
529 old = self.type_printers.pop(cls)
523 break
530 break
524 else:
531 else:
525 old = default
532 old = default
526 else:
533 else:
527 old = self.deferred_printers.pop(typ_key)
534 old = self.deferred_printers.pop(typ_key)
528 else:
535 else:
529 if typ in self.type_printers:
536 if typ in self.type_printers:
530 old = self.type_printers.pop(typ)
537 old = self.type_printers.pop(typ)
531 else:
538 else:
532 old = self.deferred_printers.pop(_mod_name_key(typ), default)
539 old = self.deferred_printers.pop(_mod_name_key(typ), default)
533 if old is _raise_key_error:
540 if old is _raise_key_error:
534 raise KeyError("No registered value for {0!r}".format(typ))
541 raise KeyError("No registered value for {0!r}".format(typ))
535 return old
542 return old
536
543
537 def _in_deferred_types(self, cls):
544 def _in_deferred_types(self, cls):
538 """
545 """
539 Check if the given class is specified in the deferred type registry.
546 Check if the given class is specified in the deferred type registry.
540
547
541 Successful matches will be moved to the regular type registry for future use.
548 Successful matches will be moved to the regular type registry for future use.
542 """
549 """
543 mod = getattr(cls, '__module__', None)
550 mod = getattr(cls, '__module__', None)
544 name = getattr(cls, '__name__', None)
551 name = getattr(cls, '__name__', None)
545 key = (mod, name)
552 key = (mod, name)
546 if key in self.deferred_printers:
553 if key in self.deferred_printers:
547 # Move the printer over to the regular registry.
554 # Move the printer over to the regular registry.
548 printer = self.deferred_printers.pop(key)
555 printer = self.deferred_printers.pop(key)
549 self.type_printers[cls] = printer
556 self.type_printers[cls] = printer
550 return True
557 return True
551 return False
558 return False
552
559
553
560
554 class PlainTextFormatter(BaseFormatter):
561 class PlainTextFormatter(BaseFormatter):
555 """The default pretty-printer.
562 """The default pretty-printer.
556
563
557 This uses :mod:`IPython.lib.pretty` to compute the format data of
564 This uses :mod:`IPython.lib.pretty` to compute the format data of
558 the object. If the object cannot be pretty printed, :func:`repr` is used.
565 the object. If the object cannot be pretty printed, :func:`repr` is used.
559 See the documentation of :mod:`IPython.lib.pretty` for details on
566 See the documentation of :mod:`IPython.lib.pretty` for details on
560 how to write pretty printers. Here is a simple example::
567 how to write pretty printers. Here is a simple example::
561
568
562 def dtype_pprinter(obj, p, cycle):
569 def dtype_pprinter(obj, p, cycle):
563 if cycle:
570 if cycle:
564 return p.text('dtype(...)')
571 return p.text('dtype(...)')
565 if hasattr(obj, 'fields'):
572 if hasattr(obj, 'fields'):
566 if obj.fields is None:
573 if obj.fields is None:
567 p.text(repr(obj))
574 p.text(repr(obj))
568 else:
575 else:
569 p.begin_group(7, 'dtype([')
576 p.begin_group(7, 'dtype([')
570 for i, field in enumerate(obj.descr):
577 for i, field in enumerate(obj.descr):
571 if i > 0:
578 if i > 0:
572 p.text(',')
579 p.text(',')
573 p.breakable()
580 p.breakable()
574 p.pretty(field)
581 p.pretty(field)
575 p.end_group(7, '])')
582 p.end_group(7, '])')
576 """
583 """
577
584
578 # The format type of data returned.
585 # The format type of data returned.
579 format_type = Unicode('text/plain')
586 format_type = Unicode('text/plain')
580
587
581 # This subclass ignores this attribute as it always need to return
588 # This subclass ignores this attribute as it always need to return
582 # something.
589 # something.
583 enabled = Bool(True, config=False)
590 enabled = Bool(True, config=False)
584
591
585 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, config=True,
592 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, config=True,
586 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
593 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
587
594
588 Set to 0 to disable truncation.
595 Set to 0 to disable truncation.
589 """
596 """
590 )
597 )
591
598
592 # Look for a _repr_pretty_ methods to use for pretty printing.
599 # Look for a _repr_pretty_ methods to use for pretty printing.
593 print_method = ObjectName('_repr_pretty_')
600 print_method = ObjectName('_repr_pretty_')
594
601
595 # Whether to pretty-print or not.
602 # Whether to pretty-print or not.
596 pprint = Bool(True, config=True)
603 pprint = Bool(True, config=True)
597
604
598 # Whether to be verbose or not.
605 # Whether to be verbose or not.
599 verbose = Bool(False, config=True)
606 verbose = Bool(False, config=True)
600
607
601 # The maximum width.
608 # The maximum width.
602 max_width = Integer(79, config=True)
609 max_width = Integer(79, config=True)
603
610
604 # The newline character.
611 # The newline character.
605 newline = Unicode('\n', config=True)
612 newline = Unicode('\n', config=True)
606
613
607 # format-string for pprinting floats
614 # format-string for pprinting floats
608 float_format = Unicode('%r')
615 float_format = Unicode('%r')
609 # setter for float precision, either int or direct format-string
616 # setter for float precision, either int or direct format-string
610 float_precision = CUnicode('', config=True)
617 float_precision = CUnicode('', config=True)
611
618
612 def _float_precision_changed(self, name, old, new):
619 def _float_precision_changed(self, name, old, new):
613 """float_precision changed, set float_format accordingly.
620 """float_precision changed, set float_format accordingly.
614
621
615 float_precision can be set by int or str.
622 float_precision can be set by int or str.
616 This will set float_format, after interpreting input.
623 This will set float_format, after interpreting input.
617 If numpy has been imported, numpy print precision will also be set.
624 If numpy has been imported, numpy print precision will also be set.
618
625
619 integer `n` sets format to '%.nf', otherwise, format set directly.
626 integer `n` sets format to '%.nf', otherwise, format set directly.
620
627
621 An empty string returns to defaults (repr for float, 8 for numpy).
628 An empty string returns to defaults (repr for float, 8 for numpy).
622
629
623 This parameter can be set via the '%precision' magic.
630 This parameter can be set via the '%precision' magic.
624 """
631 """
625
632
626 if '%' in new:
633 if '%' in new:
627 # got explicit format string
634 # got explicit format string
628 fmt = new
635 fmt = new
629 try:
636 try:
630 fmt%3.14159
637 fmt%3.14159
631 except Exception:
638 except Exception:
632 raise ValueError("Precision must be int or format string, not %r"%new)
639 raise ValueError("Precision must be int or format string, not %r"%new)
633 elif new:
640 elif new:
634 # otherwise, should be an int
641 # otherwise, should be an int
635 try:
642 try:
636 i = int(new)
643 i = int(new)
637 assert i >= 0
644 assert i >= 0
638 except ValueError:
645 except ValueError:
639 raise ValueError("Precision must be int or format string, not %r"%new)
646 raise ValueError("Precision must be int or format string, not %r"%new)
640 except AssertionError:
647 except AssertionError:
641 raise ValueError("int precision must be non-negative, not %r"%i)
648 raise ValueError("int precision must be non-negative, not %r"%i)
642
649
643 fmt = '%%.%if'%i
650 fmt = '%%.%if'%i
644 if 'numpy' in sys.modules:
651 if 'numpy' in sys.modules:
645 # set numpy precision if it has been imported
652 # set numpy precision if it has been imported
646 import numpy
653 import numpy
647 numpy.set_printoptions(precision=i)
654 numpy.set_printoptions(precision=i)
648 else:
655 else:
649 # default back to repr
656 # default back to repr
650 fmt = '%r'
657 fmt = '%r'
651 if 'numpy' in sys.modules:
658 if 'numpy' in sys.modules:
652 import numpy
659 import numpy
653 # numpy default is 8
660 # numpy default is 8
654 numpy.set_printoptions(precision=8)
661 numpy.set_printoptions(precision=8)
655 self.float_format = fmt
662 self.float_format = fmt
656
663
657 # Use the default pretty printers from IPython.lib.pretty.
664 # Use the default pretty printers from IPython.lib.pretty.
658 def _singleton_printers_default(self):
665 def _singleton_printers_default(self):
659 return pretty._singleton_pprinters.copy()
666 return pretty._singleton_pprinters.copy()
660
667
661 def _type_printers_default(self):
668 def _type_printers_default(self):
662 d = pretty._type_pprinters.copy()
669 d = pretty._type_pprinters.copy()
663 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
670 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
664 return d
671 return d
665
672
666 def _deferred_printers_default(self):
673 def _deferred_printers_default(self):
667 return pretty._deferred_type_pprinters.copy()
674 return pretty._deferred_type_pprinters.copy()
668
675
669 #### FormatterABC interface ####
676 #### FormatterABC interface ####
670
677
671 @warn_format_error
678 @warn_format_error
672 def __call__(self, obj):
679 def __call__(self, obj):
673 """Compute the pretty representation of the object."""
680 """Compute the pretty representation of the object."""
674 if not self.pprint:
681 if not self.pprint:
675 return repr(obj)
682 return repr(obj)
676 else:
683 else:
677 # This uses use StringIO, as cStringIO doesn't handle unicode.
684 # This uses use StringIO, as cStringIO doesn't handle unicode.
678 stream = StringIO()
685 stream = StringIO()
679 # self.newline.encode() is a quick fix for issue gh-597. We need to
686 # self.newline.encode() is a quick fix for issue gh-597. We need to
680 # ensure that stream does not get a mix of unicode and bytestrings,
687 # ensure that stream does not get a mix of unicode and bytestrings,
681 # or it will cause trouble.
688 # or it will cause trouble.
682 printer = pretty.RepresentationPrinter(stream, self.verbose,
689 printer = pretty.RepresentationPrinter(stream, self.verbose,
683 self.max_width, unicode_to_str(self.newline),
690 self.max_width, unicode_to_str(self.newline),
684 max_seq_length=self.max_seq_length,
691 max_seq_length=self.max_seq_length,
685 singleton_pprinters=self.singleton_printers,
692 singleton_pprinters=self.singleton_printers,
686 type_pprinters=self.type_printers,
693 type_pprinters=self.type_printers,
687 deferred_pprinters=self.deferred_printers)
694 deferred_pprinters=self.deferred_printers)
688 printer.pretty(obj)
695 printer.pretty(obj)
689 printer.flush()
696 printer.flush()
690 return stream.getvalue()
697 return stream.getvalue()
691
698
692
699
693 class HTMLFormatter(BaseFormatter):
700 class HTMLFormatter(BaseFormatter):
694 """An HTML formatter.
701 """An HTML formatter.
695
702
696 To define the callables that compute the HTML representation of your
703 To define the callables that compute the HTML representation of your
697 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
704 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
698 or :meth:`for_type_by_name` methods to register functions that handle
705 or :meth:`for_type_by_name` methods to register functions that handle
699 this.
706 this.
700
707
701 The return value of this formatter should be a valid HTML snippet that
708 The return value of this formatter should be a valid HTML snippet that
702 could be injected into an existing DOM. It should *not* include the
709 could be injected into an existing DOM. It should *not* include the
703 ```<html>`` or ```<body>`` tags.
710 ```<html>`` or ```<body>`` tags.
704 """
711 """
705 format_type = Unicode('text/html')
712 format_type = Unicode('text/html')
706
713
707 print_method = ObjectName('_repr_html_')
714 print_method = ObjectName('_repr_html_')
708
715
709
716
710 class MarkdownFormatter(BaseFormatter):
717 class MarkdownFormatter(BaseFormatter):
711 """A Markdown formatter.
718 """A Markdown formatter.
712
719
713 To define the callables that compute the Markdown representation of your
720 To define the callables that compute the Markdown representation of your
714 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
721 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
715 or :meth:`for_type_by_name` methods to register functions that handle
722 or :meth:`for_type_by_name` methods to register functions that handle
716 this.
723 this.
717
724
718 The return value of this formatter should be a valid Markdown.
725 The return value of this formatter should be a valid Markdown.
719 """
726 """
720 format_type = Unicode('text/markdown')
727 format_type = Unicode('text/markdown')
721
728
722 print_method = ObjectName('_repr_markdown_')
729 print_method = ObjectName('_repr_markdown_')
723
730
724 class SVGFormatter(BaseFormatter):
731 class SVGFormatter(BaseFormatter):
725 """An SVG formatter.
732 """An SVG formatter.
726
733
727 To define the callables that compute the SVG representation of your
734 To define the callables that compute the SVG representation of your
728 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
735 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
729 or :meth:`for_type_by_name` methods to register functions that handle
736 or :meth:`for_type_by_name` methods to register functions that handle
730 this.
737 this.
731
738
732 The return value of this formatter should be valid SVG enclosed in
739 The return value of this formatter should be valid SVG enclosed in
733 ```<svg>``` tags, that could be injected into an existing DOM. It should
740 ```<svg>``` tags, that could be injected into an existing DOM. It should
734 *not* include the ```<html>`` or ```<body>`` tags.
741 *not* include the ```<html>`` or ```<body>`` tags.
735 """
742 """
736 format_type = Unicode('image/svg+xml')
743 format_type = Unicode('image/svg+xml')
737
744
738 print_method = ObjectName('_repr_svg_')
745 print_method = ObjectName('_repr_svg_')
739
746
740
747
741 class PNGFormatter(BaseFormatter):
748 class PNGFormatter(BaseFormatter):
742 """A PNG formatter.
749 """A PNG formatter.
743
750
744 To define the callables that compute the PNG representation of your
751 To define the callables that compute the PNG representation of your
745 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
752 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
746 or :meth:`for_type_by_name` methods to register functions that handle
753 or :meth:`for_type_by_name` methods to register functions that handle
747 this.
754 this.
748
755
749 The return value of this formatter should be raw PNG data, *not*
756 The return value of this formatter should be raw PNG data, *not*
750 base64 encoded.
757 base64 encoded.
751 """
758 """
752 format_type = Unicode('image/png')
759 format_type = Unicode('image/png')
753
760
754 print_method = ObjectName('_repr_png_')
761 print_method = ObjectName('_repr_png_')
755
762
756 _return_type = (bytes, unicode_type)
763 _return_type = (bytes, unicode_type)
757
764
758
765
759 class JPEGFormatter(BaseFormatter):
766 class JPEGFormatter(BaseFormatter):
760 """A JPEG formatter.
767 """A JPEG formatter.
761
768
762 To define the callables that compute the JPEG representation of your
769 To define the callables that compute the JPEG representation of your
763 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
770 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
764 or :meth:`for_type_by_name` methods to register functions that handle
771 or :meth:`for_type_by_name` methods to register functions that handle
765 this.
772 this.
766
773
767 The return value of this formatter should be raw JPEG data, *not*
774 The return value of this formatter should be raw JPEG data, *not*
768 base64 encoded.
775 base64 encoded.
769 """
776 """
770 format_type = Unicode('image/jpeg')
777 format_type = Unicode('image/jpeg')
771
778
772 print_method = ObjectName('_repr_jpeg_')
779 print_method = ObjectName('_repr_jpeg_')
773
780
774 _return_type = (bytes, unicode_type)
781 _return_type = (bytes, unicode_type)
775
782
776
783
777 class LatexFormatter(BaseFormatter):
784 class LatexFormatter(BaseFormatter):
778 """A LaTeX formatter.
785 """A LaTeX formatter.
779
786
780 To define the callables that compute the LaTeX representation of your
787 To define the callables that compute the LaTeX representation of your
781 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
788 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
782 or :meth:`for_type_by_name` methods to register functions that handle
789 or :meth:`for_type_by_name` methods to register functions that handle
783 this.
790 this.
784
791
785 The return value of this formatter should be a valid LaTeX equation,
792 The return value of this formatter should be a valid LaTeX equation,
786 enclosed in either ```$```, ```$$``` or another LaTeX equation
793 enclosed in either ```$```, ```$$``` or another LaTeX equation
787 environment.
794 environment.
788 """
795 """
789 format_type = Unicode('text/latex')
796 format_type = Unicode('text/latex')
790
797
791 print_method = ObjectName('_repr_latex_')
798 print_method = ObjectName('_repr_latex_')
792
799
793
800
794 class JSONFormatter(BaseFormatter):
801 class JSONFormatter(BaseFormatter):
795 """A JSON string formatter.
802 """A JSON string formatter.
796
803
797 To define the callables that compute the JSON string representation of
804 To define the callables that compute the JSONable representation of
798 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
805 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
799 or :meth:`for_type_by_name` methods to register functions that handle
806 or :meth:`for_type_by_name` methods to register functions that handle
800 this.
807 this.
801
808
802 The return value of this formatter should be a valid JSON string.
809 The return value of this formatter should be a JSONable list or dict.
810 JSON scalars (None, number, string) are not allowed, only dict or list containers.
803 """
811 """
804 format_type = Unicode('application/json')
812 format_type = Unicode('application/json')
813 _return_type = (list, dict)
805
814
806 print_method = ObjectName('_repr_json_')
815 print_method = ObjectName('_repr_json_')
816
817 def _check_return(self, r, obj):
818 """Check that a return value is appropriate
819
820 Return the value if so, None otherwise, warning if invalid.
821 """
822 if r is None:
823 return
824 md = None
825 if isinstance(r, tuple):
826 # unpack data, metadata tuple for type checking on first element
827 r, md = r
828
829 # handle deprecated JSON-as-string form from IPython < 3
830 if isinstance(r, string_types):
831 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
832 FormatterWarning)
833 r = json.loads(r)
834
835 if md is not None:
836 # put the tuple back together
837 r = (r, md)
838 return super(JSONFormatter, self)._check_return(r, obj)
807
839
808
840
809 class JavascriptFormatter(BaseFormatter):
841 class JavascriptFormatter(BaseFormatter):
810 """A Javascript formatter.
842 """A Javascript formatter.
811
843
812 To define the callables that compute the Javascript representation of
844 To define the callables that compute the Javascript representation of
813 your objects, define a :meth:`_repr_javascript_` method or use the
845 your objects, define a :meth:`_repr_javascript_` method or use the
814 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
846 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
815 that handle this.
847 that handle this.
816
848
817 The return value of this formatter should be valid Javascript code and
849 The return value of this formatter should be valid Javascript code and
818 should *not* be enclosed in ```<script>``` tags.
850 should *not* be enclosed in ```<script>``` tags.
819 """
851 """
820 format_type = Unicode('application/javascript')
852 format_type = Unicode('application/javascript')
821
853
822 print_method = ObjectName('_repr_javascript_')
854 print_method = ObjectName('_repr_javascript_')
823
855
824
856
825 class PDFFormatter(BaseFormatter):
857 class PDFFormatter(BaseFormatter):
826 """A PDF formatter.
858 """A PDF formatter.
827
859
828 To define the callables that compute the PDF representation of your
860 To define the callables that compute the PDF representation of your
829 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
861 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
830 or :meth:`for_type_by_name` methods to register functions that handle
862 or :meth:`for_type_by_name` methods to register functions that handle
831 this.
863 this.
832
864
833 The return value of this formatter should be raw PDF data, *not*
865 The return value of this formatter should be raw PDF data, *not*
834 base64 encoded.
866 base64 encoded.
835 """
867 """
836 format_type = Unicode('application/pdf')
868 format_type = Unicode('application/pdf')
837
869
838 print_method = ObjectName('_repr_pdf_')
870 print_method = ObjectName('_repr_pdf_')
839
871
840 _return_type = (bytes, unicode_type)
872 _return_type = (bytes, unicode_type)
841
873
842 class IPythonDisplayFormatter(BaseFormatter):
874 class IPythonDisplayFormatter(BaseFormatter):
843 """A Formatter for objects that know how to display themselves.
875 """A Formatter for objects that know how to display themselves.
844
876
845 To define the callables that compute the representation of your
877 To define the callables that compute the representation of your
846 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
878 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
847 or :meth:`for_type_by_name` methods to register functions that handle
879 or :meth:`for_type_by_name` methods to register functions that handle
848 this. Unlike mime-type displays, this method should not return anything,
880 this. Unlike mime-type displays, this method should not return anything,
849 instead calling any appropriate display methods itself.
881 instead calling any appropriate display methods itself.
850
882
851 This display formatter has highest priority.
883 This display formatter has highest priority.
852 If it fires, no other display formatter will be called.
884 If it fires, no other display formatter will be called.
853 """
885 """
854 print_method = ObjectName('_ipython_display_')
886 print_method = ObjectName('_ipython_display_')
855 _return_type = (type(None), bool)
887 _return_type = (type(None), bool)
856
888
857
889
858 @warn_format_error
890 @warn_format_error
859 def __call__(self, obj):
891 def __call__(self, obj):
860 """Compute the format for an object."""
892 """Compute the format for an object."""
861 if self.enabled:
893 if self.enabled:
862 # lookup registered printer
894 # lookup registered printer
863 try:
895 try:
864 printer = self.lookup(obj)
896 printer = self.lookup(obj)
865 except KeyError:
897 except KeyError:
866 pass
898 pass
867 else:
899 else:
868 printer(obj)
900 printer(obj)
869 return True
901 return True
870 # Finally look for special method names
902 # Finally look for special method names
871 method = _safe_get_formatter_method(obj, self.print_method)
903 method = _safe_get_formatter_method(obj, self.print_method)
872 if method is not None:
904 if method is not None:
873 method()
905 method()
874 return True
906 return True
875
907
876
908
877 FormatterABC.register(BaseFormatter)
909 FormatterABC.register(BaseFormatter)
878 FormatterABC.register(PlainTextFormatter)
910 FormatterABC.register(PlainTextFormatter)
879 FormatterABC.register(HTMLFormatter)
911 FormatterABC.register(HTMLFormatter)
880 FormatterABC.register(MarkdownFormatter)
912 FormatterABC.register(MarkdownFormatter)
881 FormatterABC.register(SVGFormatter)
913 FormatterABC.register(SVGFormatter)
882 FormatterABC.register(PNGFormatter)
914 FormatterABC.register(PNGFormatter)
883 FormatterABC.register(PDFFormatter)
915 FormatterABC.register(PDFFormatter)
884 FormatterABC.register(JPEGFormatter)
916 FormatterABC.register(JPEGFormatter)
885 FormatterABC.register(LatexFormatter)
917 FormatterABC.register(LatexFormatter)
886 FormatterABC.register(JSONFormatter)
918 FormatterABC.register(JSONFormatter)
887 FormatterABC.register(JavascriptFormatter)
919 FormatterABC.register(JavascriptFormatter)
888 FormatterABC.register(IPythonDisplayFormatter)
920 FormatterABC.register(IPythonDisplayFormatter)
889
921
890
922
891 def format_display_data(obj, include=None, exclude=None):
923 def format_display_data(obj, include=None, exclude=None):
892 """Return a format data dict for an object.
924 """Return a format data dict for an object.
893
925
894 By default all format types will be computed.
926 By default all format types will be computed.
895
927
896 The following MIME types are currently implemented:
928 The following MIME types are currently implemented:
897
929
898 * text/plain
930 * text/plain
899 * text/html
931 * text/html
900 * text/markdown
932 * text/markdown
901 * text/latex
933 * text/latex
902 * application/json
934 * application/json
903 * application/javascript
935 * application/javascript
904 * application/pdf
936 * application/pdf
905 * image/png
937 * image/png
906 * image/jpeg
938 * image/jpeg
907 * image/svg+xml
939 * image/svg+xml
908
940
909 Parameters
941 Parameters
910 ----------
942 ----------
911 obj : object
943 obj : object
912 The Python object whose format data will be computed.
944 The Python object whose format data will be computed.
913
945
914 Returns
946 Returns
915 -------
947 -------
916 format_dict : dict
948 format_dict : dict
917 A dictionary of key/value pairs, one or each format that was
949 A dictionary of key/value pairs, one or each format that was
918 generated for the object. The keys are the format types, which
950 generated for the object. The keys are the format types, which
919 will usually be MIME type strings and the values and JSON'able
951 will usually be MIME type strings and the values and JSON'able
920 data structure containing the raw data for the representation in
952 data structure containing the raw data for the representation in
921 that format.
953 that format.
922 include : list or tuple, optional
954 include : list or tuple, optional
923 A list of format type strings (MIME types) to include in the
955 A list of format type strings (MIME types) to include in the
924 format data dict. If this is set *only* the format types included
956 format data dict. If this is set *only* the format types included
925 in this list will be computed.
957 in this list will be computed.
926 exclude : list or tuple, optional
958 exclude : list or tuple, optional
927 A list of format type string (MIME types) to exclue in the format
959 A list of format type string (MIME types) to exclue in the format
928 data dict. If this is set all format types will be computed,
960 data dict. If this is set all format types will be computed,
929 except for those included in this argument.
961 except for those included in this argument.
930 """
962 """
931 from IPython.core.interactiveshell import InteractiveShell
963 from IPython.core.interactiveshell import InteractiveShell
932
964
933 InteractiveShell.instance().display_formatter.format(
965 InteractiveShell.instance().display_formatter.format(
934 obj,
966 obj,
935 include,
967 include,
936 exclude
968 exclude
937 )
969 )
938
970
@@ -1,611 +1,611 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3 from __future__ import print_function
3 from __future__ import print_function
4
4
5 import io
5 import io
6 import json
6 import json
7 import sys
7 import sys
8 from pprint import pformat
8 from pprint import pformat
9
9
10 from IPython.core import magic_arguments, page
10 from IPython.core import magic_arguments, page
11 from IPython.core.error import UsageError
11 from IPython.core.error import UsageError
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 from IPython.utils.text import format_screen, dedent, indent
13 from IPython.utils.text import format_screen, dedent, indent
14 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.testing.skipdoctest import skip_doctest
15 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
16 from IPython.utils.path import unquote_filename
16 from IPython.utils.path import unquote_filename
17 from IPython.utils.py3compat import unicode_type
17 from IPython.utils.py3compat import unicode_type
18 from IPython.utils.warn import warn, error
18 from IPython.utils.warn import warn, error
19
19
20
20
21 class MagicsDisplay(object):
21 class MagicsDisplay(object):
22 def __init__(self, magics_manager):
22 def __init__(self, magics_manager):
23 self.magics_manager = magics_manager
23 self.magics_manager = magics_manager
24
24
25 def _lsmagic(self):
25 def _lsmagic(self):
26 """The main implementation of the %lsmagic"""
26 """The main implementation of the %lsmagic"""
27 mesc = magic_escapes['line']
27 mesc = magic_escapes['line']
28 cesc = magic_escapes['cell']
28 cesc = magic_escapes['cell']
29 mman = self.magics_manager
29 mman = self.magics_manager
30 magics = mman.lsmagic()
30 magics = mman.lsmagic()
31 out = ['Available line magics:',
31 out = ['Available line magics:',
32 mesc + (' '+mesc).join(sorted(magics['line'])),
32 mesc + (' '+mesc).join(sorted(magics['line'])),
33 '',
33 '',
34 'Available cell magics:',
34 'Available cell magics:',
35 cesc + (' '+cesc).join(sorted(magics['cell'])),
35 cesc + (' '+cesc).join(sorted(magics['cell'])),
36 '',
36 '',
37 mman.auto_status()]
37 mman.auto_status()]
38 return '\n'.join(out)
38 return '\n'.join(out)
39
39
40 def _repr_pretty_(self, p, cycle):
40 def _repr_pretty_(self, p, cycle):
41 p.text(self._lsmagic())
41 p.text(self._lsmagic())
42
42
43 def __str__(self):
43 def __str__(self):
44 return self._lsmagic()
44 return self._lsmagic()
45
45
46 def _jsonable(self):
46 def _jsonable(self):
47 """turn magics dict into jsonable dict of the same structure
47 """turn magics dict into jsonable dict of the same structure
48
48
49 replaces object instances with their class names as strings
49 replaces object instances with their class names as strings
50 """
50 """
51 magic_dict = {}
51 magic_dict = {}
52 mman = self.magics_manager
52 mman = self.magics_manager
53 magics = mman.lsmagic()
53 magics = mman.lsmagic()
54 for key, subdict in magics.items():
54 for key, subdict in magics.items():
55 d = {}
55 d = {}
56 magic_dict[key] = d
56 magic_dict[key] = d
57 for name, obj in subdict.items():
57 for name, obj in subdict.items():
58 try:
58 try:
59 classname = obj.__self__.__class__.__name__
59 classname = obj.__self__.__class__.__name__
60 except AttributeError:
60 except AttributeError:
61 classname = 'Other'
61 classname = 'Other'
62
62
63 d[name] = classname
63 d[name] = classname
64 return magic_dict
64 return magic_dict
65
65
66 def _repr_json_(self):
66 def _repr_json_(self):
67 return json.dumps(self._jsonable())
67 return self._jsonable()
68
68
69
69
70 @magics_class
70 @magics_class
71 class BasicMagics(Magics):
71 class BasicMagics(Magics):
72 """Magics that provide central IPython functionality.
72 """Magics that provide central IPython functionality.
73
73
74 These are various magics that don't fit into specific categories but that
74 These are various magics that don't fit into specific categories but that
75 are all part of the base 'IPython experience'."""
75 are all part of the base 'IPython experience'."""
76
76
77 @magic_arguments.magic_arguments()
77 @magic_arguments.magic_arguments()
78 @magic_arguments.argument(
78 @magic_arguments.argument(
79 '-l', '--line', action='store_true',
79 '-l', '--line', action='store_true',
80 help="""Create a line magic alias."""
80 help="""Create a line magic alias."""
81 )
81 )
82 @magic_arguments.argument(
82 @magic_arguments.argument(
83 '-c', '--cell', action='store_true',
83 '-c', '--cell', action='store_true',
84 help="""Create a cell magic alias."""
84 help="""Create a cell magic alias."""
85 )
85 )
86 @magic_arguments.argument(
86 @magic_arguments.argument(
87 'name',
87 'name',
88 help="""Name of the magic to be created."""
88 help="""Name of the magic to be created."""
89 )
89 )
90 @magic_arguments.argument(
90 @magic_arguments.argument(
91 'target',
91 'target',
92 help="""Name of the existing line or cell magic."""
92 help="""Name of the existing line or cell magic."""
93 )
93 )
94 @line_magic
94 @line_magic
95 def alias_magic(self, line=''):
95 def alias_magic(self, line=''):
96 """Create an alias for an existing line or cell magic.
96 """Create an alias for an existing line or cell magic.
97
97
98 Examples
98 Examples
99 --------
99 --------
100 ::
100 ::
101
101
102 In [1]: %alias_magic t timeit
102 In [1]: %alias_magic t timeit
103 Created `%t` as an alias for `%timeit`.
103 Created `%t` as an alias for `%timeit`.
104 Created `%%t` as an alias for `%%timeit`.
104 Created `%%t` as an alias for `%%timeit`.
105
105
106 In [2]: %t -n1 pass
106 In [2]: %t -n1 pass
107 1 loops, best of 3: 954 ns per loop
107 1 loops, best of 3: 954 ns per loop
108
108
109 In [3]: %%t -n1
109 In [3]: %%t -n1
110 ...: pass
110 ...: pass
111 ...:
111 ...:
112 1 loops, best of 3: 954 ns per loop
112 1 loops, best of 3: 954 ns per loop
113
113
114 In [4]: %alias_magic --cell whereami pwd
114 In [4]: %alias_magic --cell whereami pwd
115 UsageError: Cell magic function `%%pwd` not found.
115 UsageError: Cell magic function `%%pwd` not found.
116 In [5]: %alias_magic --line whereami pwd
116 In [5]: %alias_magic --line whereami pwd
117 Created `%whereami` as an alias for `%pwd`.
117 Created `%whereami` as an alias for `%pwd`.
118
118
119 In [6]: %whereami
119 In [6]: %whereami
120 Out[6]: u'/home/testuser'
120 Out[6]: u'/home/testuser'
121 """
121 """
122 args = magic_arguments.parse_argstring(self.alias_magic, line)
122 args = magic_arguments.parse_argstring(self.alias_magic, line)
123 shell = self.shell
123 shell = self.shell
124 mman = self.shell.magics_manager
124 mman = self.shell.magics_manager
125 escs = ''.join(magic_escapes.values())
125 escs = ''.join(magic_escapes.values())
126
126
127 target = args.target.lstrip(escs)
127 target = args.target.lstrip(escs)
128 name = args.name.lstrip(escs)
128 name = args.name.lstrip(escs)
129
129
130 # Find the requested magics.
130 # Find the requested magics.
131 m_line = shell.find_magic(target, 'line')
131 m_line = shell.find_magic(target, 'line')
132 m_cell = shell.find_magic(target, 'cell')
132 m_cell = shell.find_magic(target, 'cell')
133 if args.line and m_line is None:
133 if args.line and m_line is None:
134 raise UsageError('Line magic function `%s%s` not found.' %
134 raise UsageError('Line magic function `%s%s` not found.' %
135 (magic_escapes['line'], target))
135 (magic_escapes['line'], target))
136 if args.cell and m_cell is None:
136 if args.cell and m_cell is None:
137 raise UsageError('Cell magic function `%s%s` not found.' %
137 raise UsageError('Cell magic function `%s%s` not found.' %
138 (magic_escapes['cell'], target))
138 (magic_escapes['cell'], target))
139
139
140 # If --line and --cell are not specified, default to the ones
140 # If --line and --cell are not specified, default to the ones
141 # that are available.
141 # that are available.
142 if not args.line and not args.cell:
142 if not args.line and not args.cell:
143 if not m_line and not m_cell:
143 if not m_line and not m_cell:
144 raise UsageError(
144 raise UsageError(
145 'No line or cell magic with name `%s` found.' % target
145 'No line or cell magic with name `%s` found.' % target
146 )
146 )
147 args.line = bool(m_line)
147 args.line = bool(m_line)
148 args.cell = bool(m_cell)
148 args.cell = bool(m_cell)
149
149
150 if args.line:
150 if args.line:
151 mman.register_alias(name, target, 'line')
151 mman.register_alias(name, target, 'line')
152 print('Created `%s%s` as an alias for `%s%s`.' % (
152 print('Created `%s%s` as an alias for `%s%s`.' % (
153 magic_escapes['line'], name,
153 magic_escapes['line'], name,
154 magic_escapes['line'], target))
154 magic_escapes['line'], target))
155
155
156 if args.cell:
156 if args.cell:
157 mman.register_alias(name, target, 'cell')
157 mman.register_alias(name, target, 'cell')
158 print('Created `%s%s` as an alias for `%s%s`.' % (
158 print('Created `%s%s` as an alias for `%s%s`.' % (
159 magic_escapes['cell'], name,
159 magic_escapes['cell'], name,
160 magic_escapes['cell'], target))
160 magic_escapes['cell'], target))
161
161
162 @line_magic
162 @line_magic
163 def lsmagic(self, parameter_s=''):
163 def lsmagic(self, parameter_s=''):
164 """List currently available magic functions."""
164 """List currently available magic functions."""
165 return MagicsDisplay(self.shell.magics_manager)
165 return MagicsDisplay(self.shell.magics_manager)
166
166
167 def _magic_docs(self, brief=False, rest=False):
167 def _magic_docs(self, brief=False, rest=False):
168 """Return docstrings from magic functions."""
168 """Return docstrings from magic functions."""
169 mman = self.shell.magics_manager
169 mman = self.shell.magics_manager
170 docs = mman.lsmagic_docs(brief, missing='No documentation')
170 docs = mman.lsmagic_docs(brief, missing='No documentation')
171
171
172 if rest:
172 if rest:
173 format_string = '**%s%s**::\n\n%s\n\n'
173 format_string = '**%s%s**::\n\n%s\n\n'
174 else:
174 else:
175 format_string = '%s%s:\n%s\n'
175 format_string = '%s%s:\n%s\n'
176
176
177 return ''.join(
177 return ''.join(
178 [format_string % (magic_escapes['line'], fname,
178 [format_string % (magic_escapes['line'], fname,
179 indent(dedent(fndoc)))
179 indent(dedent(fndoc)))
180 for fname, fndoc in sorted(docs['line'].items())]
180 for fname, fndoc in sorted(docs['line'].items())]
181 +
181 +
182 [format_string % (magic_escapes['cell'], fname,
182 [format_string % (magic_escapes['cell'], fname,
183 indent(dedent(fndoc)))
183 indent(dedent(fndoc)))
184 for fname, fndoc in sorted(docs['cell'].items())]
184 for fname, fndoc in sorted(docs['cell'].items())]
185 )
185 )
186
186
187 @line_magic
187 @line_magic
188 def magic(self, parameter_s=''):
188 def magic(self, parameter_s=''):
189 """Print information about the magic function system.
189 """Print information about the magic function system.
190
190
191 Supported formats: -latex, -brief, -rest
191 Supported formats: -latex, -brief, -rest
192 """
192 """
193
193
194 mode = ''
194 mode = ''
195 try:
195 try:
196 mode = parameter_s.split()[0][1:]
196 mode = parameter_s.split()[0][1:]
197 if mode == 'rest':
197 if mode == 'rest':
198 rest_docs = []
198 rest_docs = []
199 except IndexError:
199 except IndexError:
200 pass
200 pass
201
201
202 brief = (mode == 'brief')
202 brief = (mode == 'brief')
203 rest = (mode == 'rest')
203 rest = (mode == 'rest')
204 magic_docs = self._magic_docs(brief, rest)
204 magic_docs = self._magic_docs(brief, rest)
205
205
206 if mode == 'latex':
206 if mode == 'latex':
207 print(self.format_latex(magic_docs))
207 print(self.format_latex(magic_docs))
208 return
208 return
209 else:
209 else:
210 magic_docs = format_screen(magic_docs)
210 magic_docs = format_screen(magic_docs)
211
211
212 out = ["""
212 out = ["""
213 IPython's 'magic' functions
213 IPython's 'magic' functions
214 ===========================
214 ===========================
215
215
216 The magic function system provides a series of functions which allow you to
216 The magic function system provides a series of functions which allow you to
217 control the behavior of IPython itself, plus a lot of system-type
217 control the behavior of IPython itself, plus a lot of system-type
218 features. There are two kinds of magics, line-oriented and cell-oriented.
218 features. There are two kinds of magics, line-oriented and cell-oriented.
219
219
220 Line magics are prefixed with the % character and work much like OS
220 Line magics are prefixed with the % character and work much like OS
221 command-line calls: they get as an argument the rest of the line, where
221 command-line calls: they get as an argument the rest of the line, where
222 arguments are passed without parentheses or quotes. For example, this will
222 arguments are passed without parentheses or quotes. For example, this will
223 time the given statement::
223 time the given statement::
224
224
225 %timeit range(1000)
225 %timeit range(1000)
226
226
227 Cell magics are prefixed with a double %%, and they are functions that get as
227 Cell magics are prefixed with a double %%, and they are functions that get as
228 an argument not only the rest of the line, but also the lines below it in a
228 an argument not only the rest of the line, but also the lines below it in a
229 separate argument. These magics are called with two arguments: the rest of the
229 separate argument. These magics are called with two arguments: the rest of the
230 call line and the body of the cell, consisting of the lines below the first.
230 call line and the body of the cell, consisting of the lines below the first.
231 For example::
231 For example::
232
232
233 %%timeit x = numpy.random.randn((100, 100))
233 %%timeit x = numpy.random.randn((100, 100))
234 numpy.linalg.svd(x)
234 numpy.linalg.svd(x)
235
235
236 will time the execution of the numpy svd routine, running the assignment of x
236 will time the execution of the numpy svd routine, running the assignment of x
237 as part of the setup phase, which is not timed.
237 as part of the setup phase, which is not timed.
238
238
239 In a line-oriented client (the terminal or Qt console IPython), starting a new
239 In a line-oriented client (the terminal or Qt console IPython), starting a new
240 input with %% will automatically enter cell mode, and IPython will continue
240 input with %% will automatically enter cell mode, and IPython will continue
241 reading input until a blank line is given. In the notebook, simply type the
241 reading input until a blank line is given. In the notebook, simply type the
242 whole cell as one entity, but keep in mind that the %% escape can only be at
242 whole cell as one entity, but keep in mind that the %% escape can only be at
243 the very start of the cell.
243 the very start of the cell.
244
244
245 NOTE: If you have 'automagic' enabled (via the command line option or with the
245 NOTE: If you have 'automagic' enabled (via the command line option or with the
246 %automagic function), you don't need to type in the % explicitly for line
246 %automagic function), you don't need to type in the % explicitly for line
247 magics; cell magics always require an explicit '%%' escape. By default,
247 magics; cell magics always require an explicit '%%' escape. By default,
248 IPython ships with automagic on, so you should only rarely need the % escape.
248 IPython ships with automagic on, so you should only rarely need the % escape.
249
249
250 Example: typing '%cd mydir' (without the quotes) changes you working directory
250 Example: typing '%cd mydir' (without the quotes) changes you working directory
251 to 'mydir', if it exists.
251 to 'mydir', if it exists.
252
252
253 For a list of the available magic functions, use %lsmagic. For a description
253 For a list of the available magic functions, use %lsmagic. For a description
254 of any of them, type %magic_name?, e.g. '%cd?'.
254 of any of them, type %magic_name?, e.g. '%cd?'.
255
255
256 Currently the magic system has the following functions:""",
256 Currently the magic system has the following functions:""",
257 magic_docs,
257 magic_docs,
258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
259 str(self.lsmagic()),
259 str(self.lsmagic()),
260 ]
260 ]
261 page.page('\n'.join(out))
261 page.page('\n'.join(out))
262
262
263
263
264 @line_magic
264 @line_magic
265 def page(self, parameter_s=''):
265 def page(self, parameter_s=''):
266 """Pretty print the object and display it through a pager.
266 """Pretty print the object and display it through a pager.
267
267
268 %page [options] OBJECT
268 %page [options] OBJECT
269
269
270 If no object is given, use _ (last output).
270 If no object is given, use _ (last output).
271
271
272 Options:
272 Options:
273
273
274 -r: page str(object), don't pretty-print it."""
274 -r: page str(object), don't pretty-print it."""
275
275
276 # After a function contributed by Olivier Aubert, slightly modified.
276 # After a function contributed by Olivier Aubert, slightly modified.
277
277
278 # Process options/args
278 # Process options/args
279 opts, args = self.parse_options(parameter_s, 'r')
279 opts, args = self.parse_options(parameter_s, 'r')
280 raw = 'r' in opts
280 raw = 'r' in opts
281
281
282 oname = args and args or '_'
282 oname = args and args or '_'
283 info = self.shell._ofind(oname)
283 info = self.shell._ofind(oname)
284 if info['found']:
284 if info['found']:
285 txt = (raw and str or pformat)( info['obj'] )
285 txt = (raw and str or pformat)( info['obj'] )
286 page.page(txt)
286 page.page(txt)
287 else:
287 else:
288 print('Object `%s` not found' % oname)
288 print('Object `%s` not found' % oname)
289
289
290 @line_magic
290 @line_magic
291 def profile(self, parameter_s=''):
291 def profile(self, parameter_s=''):
292 """Print your currently active IPython profile.
292 """Print your currently active IPython profile.
293
293
294 See Also
294 See Also
295 --------
295 --------
296 prun : run code using the Python profiler
296 prun : run code using the Python profiler
297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
298 """
298 """
299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
300 from IPython.core.application import BaseIPythonApplication
300 from IPython.core.application import BaseIPythonApplication
301 if BaseIPythonApplication.initialized():
301 if BaseIPythonApplication.initialized():
302 print(BaseIPythonApplication.instance().profile)
302 print(BaseIPythonApplication.instance().profile)
303 else:
303 else:
304 error("profile is an application-level value, but you don't appear to be in an IPython application")
304 error("profile is an application-level value, but you don't appear to be in an IPython application")
305
305
306 @line_magic
306 @line_magic
307 def pprint(self, parameter_s=''):
307 def pprint(self, parameter_s=''):
308 """Toggle pretty printing on/off."""
308 """Toggle pretty printing on/off."""
309 ptformatter = self.shell.display_formatter.formatters['text/plain']
309 ptformatter = self.shell.display_formatter.formatters['text/plain']
310 ptformatter.pprint = bool(1 - ptformatter.pprint)
310 ptformatter.pprint = bool(1 - ptformatter.pprint)
311 print('Pretty printing has been turned',
311 print('Pretty printing has been turned',
312 ['OFF','ON'][ptformatter.pprint])
312 ['OFF','ON'][ptformatter.pprint])
313
313
314 @line_magic
314 @line_magic
315 def colors(self, parameter_s=''):
315 def colors(self, parameter_s=''):
316 """Switch color scheme for prompts, info system and exception handlers.
316 """Switch color scheme for prompts, info system and exception handlers.
317
317
318 Currently implemented schemes: NoColor, Linux, LightBG.
318 Currently implemented schemes: NoColor, Linux, LightBG.
319
319
320 Color scheme names are not case-sensitive.
320 Color scheme names are not case-sensitive.
321
321
322 Examples
322 Examples
323 --------
323 --------
324 To get a plain black and white terminal::
324 To get a plain black and white terminal::
325
325
326 %colors nocolor
326 %colors nocolor
327 """
327 """
328 def color_switch_err(name):
328 def color_switch_err(name):
329 warn('Error changing %s color schemes.\n%s' %
329 warn('Error changing %s color schemes.\n%s' %
330 (name, sys.exc_info()[1]))
330 (name, sys.exc_info()[1]))
331
331
332
332
333 new_scheme = parameter_s.strip()
333 new_scheme = parameter_s.strip()
334 if not new_scheme:
334 if not new_scheme:
335 raise UsageError(
335 raise UsageError(
336 "%colors: you must specify a color scheme. See '%colors?'")
336 "%colors: you must specify a color scheme. See '%colors?'")
337 # local shortcut
337 # local shortcut
338 shell = self.shell
338 shell = self.shell
339
339
340 import IPython.utils.rlineimpl as readline
340 import IPython.utils.rlineimpl as readline
341
341
342 if not shell.colors_force and \
342 if not shell.colors_force and \
343 not readline.have_readline and \
343 not readline.have_readline and \
344 (sys.platform == "win32" or sys.platform == "cli"):
344 (sys.platform == "win32" or sys.platform == "cli"):
345 msg = """\
345 msg = """\
346 Proper color support under MS Windows requires the pyreadline library.
346 Proper color support under MS Windows requires the pyreadline library.
347 You can find it at:
347 You can find it at:
348 http://ipython.org/pyreadline.html
348 http://ipython.org/pyreadline.html
349
349
350 Defaulting color scheme to 'NoColor'"""
350 Defaulting color scheme to 'NoColor'"""
351 new_scheme = 'NoColor'
351 new_scheme = 'NoColor'
352 warn(msg)
352 warn(msg)
353
353
354 # readline option is 0
354 # readline option is 0
355 if not shell.colors_force and not shell.has_readline:
355 if not shell.colors_force and not shell.has_readline:
356 new_scheme = 'NoColor'
356 new_scheme = 'NoColor'
357
357
358 # Set prompt colors
358 # Set prompt colors
359 try:
359 try:
360 shell.prompt_manager.color_scheme = new_scheme
360 shell.prompt_manager.color_scheme = new_scheme
361 except:
361 except:
362 color_switch_err('prompt')
362 color_switch_err('prompt')
363 else:
363 else:
364 shell.colors = \
364 shell.colors = \
365 shell.prompt_manager.color_scheme_table.active_scheme_name
365 shell.prompt_manager.color_scheme_table.active_scheme_name
366 # Set exception colors
366 # Set exception colors
367 try:
367 try:
368 shell.InteractiveTB.set_colors(scheme = new_scheme)
368 shell.InteractiveTB.set_colors(scheme = new_scheme)
369 shell.SyntaxTB.set_colors(scheme = new_scheme)
369 shell.SyntaxTB.set_colors(scheme = new_scheme)
370 except:
370 except:
371 color_switch_err('exception')
371 color_switch_err('exception')
372
372
373 # Set info (for 'object?') colors
373 # Set info (for 'object?') colors
374 if shell.color_info:
374 if shell.color_info:
375 try:
375 try:
376 shell.inspector.set_active_scheme(new_scheme)
376 shell.inspector.set_active_scheme(new_scheme)
377 except:
377 except:
378 color_switch_err('object inspector')
378 color_switch_err('object inspector')
379 else:
379 else:
380 shell.inspector.set_active_scheme('NoColor')
380 shell.inspector.set_active_scheme('NoColor')
381
381
382 @line_magic
382 @line_magic
383 def xmode(self, parameter_s=''):
383 def xmode(self, parameter_s=''):
384 """Switch modes for the exception handlers.
384 """Switch modes for the exception handlers.
385
385
386 Valid modes: Plain, Context and Verbose.
386 Valid modes: Plain, Context and Verbose.
387
387
388 If called without arguments, acts as a toggle."""
388 If called without arguments, acts as a toggle."""
389
389
390 def xmode_switch_err(name):
390 def xmode_switch_err(name):
391 warn('Error changing %s exception modes.\n%s' %
391 warn('Error changing %s exception modes.\n%s' %
392 (name,sys.exc_info()[1]))
392 (name,sys.exc_info()[1]))
393
393
394 shell = self.shell
394 shell = self.shell
395 new_mode = parameter_s.strip().capitalize()
395 new_mode = parameter_s.strip().capitalize()
396 try:
396 try:
397 shell.InteractiveTB.set_mode(mode=new_mode)
397 shell.InteractiveTB.set_mode(mode=new_mode)
398 print('Exception reporting mode:',shell.InteractiveTB.mode)
398 print('Exception reporting mode:',shell.InteractiveTB.mode)
399 except:
399 except:
400 xmode_switch_err('user')
400 xmode_switch_err('user')
401
401
402 @line_magic
402 @line_magic
403 def quickref(self,arg):
403 def quickref(self,arg):
404 """ Show a quick reference sheet """
404 """ Show a quick reference sheet """
405 from IPython.core.usage import quick_reference
405 from IPython.core.usage import quick_reference
406 qr = quick_reference + self._magic_docs(brief=True)
406 qr = quick_reference + self._magic_docs(brief=True)
407 page.page(qr)
407 page.page(qr)
408
408
409 @line_magic
409 @line_magic
410 def doctest_mode(self, parameter_s=''):
410 def doctest_mode(self, parameter_s=''):
411 """Toggle doctest mode on and off.
411 """Toggle doctest mode on and off.
412
412
413 This mode is intended to make IPython behave as much as possible like a
413 This mode is intended to make IPython behave as much as possible like a
414 plain Python shell, from the perspective of how its prompts, exceptions
414 plain Python shell, from the perspective of how its prompts, exceptions
415 and output look. This makes it easy to copy and paste parts of a
415 and output look. This makes it easy to copy and paste parts of a
416 session into doctests. It does so by:
416 session into doctests. It does so by:
417
417
418 - Changing the prompts to the classic ``>>>`` ones.
418 - Changing the prompts to the classic ``>>>`` ones.
419 - Changing the exception reporting mode to 'Plain'.
419 - Changing the exception reporting mode to 'Plain'.
420 - Disabling pretty-printing of output.
420 - Disabling pretty-printing of output.
421
421
422 Note that IPython also supports the pasting of code snippets that have
422 Note that IPython also supports the pasting of code snippets that have
423 leading '>>>' and '...' prompts in them. This means that you can paste
423 leading '>>>' and '...' prompts in them. This means that you can paste
424 doctests from files or docstrings (even if they have leading
424 doctests from files or docstrings (even if they have leading
425 whitespace), and the code will execute correctly. You can then use
425 whitespace), and the code will execute correctly. You can then use
426 '%history -t' to see the translated history; this will give you the
426 '%history -t' to see the translated history; this will give you the
427 input after removal of all the leading prompts and whitespace, which
427 input after removal of all the leading prompts and whitespace, which
428 can be pasted back into an editor.
428 can be pasted back into an editor.
429
429
430 With these features, you can switch into this mode easily whenever you
430 With these features, you can switch into this mode easily whenever you
431 need to do testing and changes to doctests, without having to leave
431 need to do testing and changes to doctests, without having to leave
432 your existing IPython session.
432 your existing IPython session.
433 """
433 """
434
434
435 # Shorthands
435 # Shorthands
436 shell = self.shell
436 shell = self.shell
437 pm = shell.prompt_manager
437 pm = shell.prompt_manager
438 meta = shell.meta
438 meta = shell.meta
439 disp_formatter = self.shell.display_formatter
439 disp_formatter = self.shell.display_formatter
440 ptformatter = disp_formatter.formatters['text/plain']
440 ptformatter = disp_formatter.formatters['text/plain']
441 # dstore is a data store kept in the instance metadata bag to track any
441 # dstore is a data store kept in the instance metadata bag to track any
442 # changes we make, so we can undo them later.
442 # changes we make, so we can undo them later.
443 dstore = meta.setdefault('doctest_mode',Struct())
443 dstore = meta.setdefault('doctest_mode',Struct())
444 save_dstore = dstore.setdefault
444 save_dstore = dstore.setdefault
445
445
446 # save a few values we'll need to recover later
446 # save a few values we'll need to recover later
447 mode = save_dstore('mode',False)
447 mode = save_dstore('mode',False)
448 save_dstore('rc_pprint',ptformatter.pprint)
448 save_dstore('rc_pprint',ptformatter.pprint)
449 save_dstore('xmode',shell.InteractiveTB.mode)
449 save_dstore('xmode',shell.InteractiveTB.mode)
450 save_dstore('rc_separate_out',shell.separate_out)
450 save_dstore('rc_separate_out',shell.separate_out)
451 save_dstore('rc_separate_out2',shell.separate_out2)
451 save_dstore('rc_separate_out2',shell.separate_out2)
452 save_dstore('rc_prompts_pad_left',pm.justify)
452 save_dstore('rc_prompts_pad_left',pm.justify)
453 save_dstore('rc_separate_in',shell.separate_in)
453 save_dstore('rc_separate_in',shell.separate_in)
454 save_dstore('rc_active_types',disp_formatter.active_types)
454 save_dstore('rc_active_types',disp_formatter.active_types)
455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
456
456
457 if mode == False:
457 if mode == False:
458 # turn on
458 # turn on
459 pm.in_template = '>>> '
459 pm.in_template = '>>> '
460 pm.in2_template = '... '
460 pm.in2_template = '... '
461 pm.out_template = ''
461 pm.out_template = ''
462
462
463 # Prompt separators like plain python
463 # Prompt separators like plain python
464 shell.separate_in = ''
464 shell.separate_in = ''
465 shell.separate_out = ''
465 shell.separate_out = ''
466 shell.separate_out2 = ''
466 shell.separate_out2 = ''
467
467
468 pm.justify = False
468 pm.justify = False
469
469
470 ptformatter.pprint = False
470 ptformatter.pprint = False
471 disp_formatter.active_types = ['text/plain']
471 disp_formatter.active_types = ['text/plain']
472
472
473 shell.magic('xmode Plain')
473 shell.magic('xmode Plain')
474 else:
474 else:
475 # turn off
475 # turn off
476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
477
477
478 shell.separate_in = dstore.rc_separate_in
478 shell.separate_in = dstore.rc_separate_in
479
479
480 shell.separate_out = dstore.rc_separate_out
480 shell.separate_out = dstore.rc_separate_out
481 shell.separate_out2 = dstore.rc_separate_out2
481 shell.separate_out2 = dstore.rc_separate_out2
482
482
483 pm.justify = dstore.rc_prompts_pad_left
483 pm.justify = dstore.rc_prompts_pad_left
484
484
485 ptformatter.pprint = dstore.rc_pprint
485 ptformatter.pprint = dstore.rc_pprint
486 disp_formatter.active_types = dstore.rc_active_types
486 disp_formatter.active_types = dstore.rc_active_types
487
487
488 shell.magic('xmode ' + dstore.xmode)
488 shell.magic('xmode ' + dstore.xmode)
489
489
490 # Store new mode and inform
490 # Store new mode and inform
491 dstore.mode = bool(1-int(mode))
491 dstore.mode = bool(1-int(mode))
492 mode_label = ['OFF','ON'][dstore.mode]
492 mode_label = ['OFF','ON'][dstore.mode]
493 print('Doctest mode is:', mode_label)
493 print('Doctest mode is:', mode_label)
494
494
495 @line_magic
495 @line_magic
496 def gui(self, parameter_s=''):
496 def gui(self, parameter_s=''):
497 """Enable or disable IPython GUI event loop integration.
497 """Enable or disable IPython GUI event loop integration.
498
498
499 %gui [GUINAME]
499 %gui [GUINAME]
500
500
501 This magic replaces IPython's threaded shells that were activated
501 This magic replaces IPython's threaded shells that were activated
502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
503 can now be enabled at runtime and keyboard
503 can now be enabled at runtime and keyboard
504 interrupts should work without any problems. The following toolkits
504 interrupts should work without any problems. The following toolkits
505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
506
506
507 %gui wx # enable wxPython event loop integration
507 %gui wx # enable wxPython event loop integration
508 %gui qt4|qt # enable PyQt4 event loop integration
508 %gui qt4|qt # enable PyQt4 event loop integration
509 %gui qt5 # enable PyQt5 event loop integration
509 %gui qt5 # enable PyQt5 event loop integration
510 %gui gtk # enable PyGTK event loop integration
510 %gui gtk # enable PyGTK event loop integration
511 %gui gtk3 # enable Gtk3 event loop integration
511 %gui gtk3 # enable Gtk3 event loop integration
512 %gui tk # enable Tk event loop integration
512 %gui tk # enable Tk event loop integration
513 %gui osx # enable Cocoa event loop integration
513 %gui osx # enable Cocoa event loop integration
514 # (requires %matplotlib 1.1)
514 # (requires %matplotlib 1.1)
515 %gui # disable all event loop integration
515 %gui # disable all event loop integration
516
516
517 WARNING: after any of these has been called you can simply create
517 WARNING: after any of these has been called you can simply create
518 an application object, but DO NOT start the event loop yourself, as
518 an application object, but DO NOT start the event loop yourself, as
519 we have already handled that.
519 we have already handled that.
520 """
520 """
521 opts, arg = self.parse_options(parameter_s, '')
521 opts, arg = self.parse_options(parameter_s, '')
522 if arg=='': arg = None
522 if arg=='': arg = None
523 try:
523 try:
524 return self.shell.enable_gui(arg)
524 return self.shell.enable_gui(arg)
525 except Exception as e:
525 except Exception as e:
526 # print simple error message, rather than traceback if we can't
526 # print simple error message, rather than traceback if we can't
527 # hook up the GUI
527 # hook up the GUI
528 error(str(e))
528 error(str(e))
529
529
530 @skip_doctest
530 @skip_doctest
531 @line_magic
531 @line_magic
532 def precision(self, s=''):
532 def precision(self, s=''):
533 """Set floating point precision for pretty printing.
533 """Set floating point precision for pretty printing.
534
534
535 Can set either integer precision or a format string.
535 Can set either integer precision or a format string.
536
536
537 If numpy has been imported and precision is an int,
537 If numpy has been imported and precision is an int,
538 numpy display precision will also be set, via ``numpy.set_printoptions``.
538 numpy display precision will also be set, via ``numpy.set_printoptions``.
539
539
540 If no argument is given, defaults will be restored.
540 If no argument is given, defaults will be restored.
541
541
542 Examples
542 Examples
543 --------
543 --------
544 ::
544 ::
545
545
546 In [1]: from math import pi
546 In [1]: from math import pi
547
547
548 In [2]: %precision 3
548 In [2]: %precision 3
549 Out[2]: u'%.3f'
549 Out[2]: u'%.3f'
550
550
551 In [3]: pi
551 In [3]: pi
552 Out[3]: 3.142
552 Out[3]: 3.142
553
553
554 In [4]: %precision %i
554 In [4]: %precision %i
555 Out[4]: u'%i'
555 Out[4]: u'%i'
556
556
557 In [5]: pi
557 In [5]: pi
558 Out[5]: 3
558 Out[5]: 3
559
559
560 In [6]: %precision %e
560 In [6]: %precision %e
561 Out[6]: u'%e'
561 Out[6]: u'%e'
562
562
563 In [7]: pi**10
563 In [7]: pi**10
564 Out[7]: 9.364805e+04
564 Out[7]: 9.364805e+04
565
565
566 In [8]: %precision
566 In [8]: %precision
567 Out[8]: u'%r'
567 Out[8]: u'%r'
568
568
569 In [9]: pi**10
569 In [9]: pi**10
570 Out[9]: 93648.047476082982
570 Out[9]: 93648.047476082982
571 """
571 """
572 ptformatter = self.shell.display_formatter.formatters['text/plain']
572 ptformatter = self.shell.display_formatter.formatters['text/plain']
573 ptformatter.float_precision = s
573 ptformatter.float_precision = s
574 return ptformatter.float_format
574 return ptformatter.float_format
575
575
576 @magic_arguments.magic_arguments()
576 @magic_arguments.magic_arguments()
577 @magic_arguments.argument(
577 @magic_arguments.argument(
578 '-e', '--export', action='store_true', default=False,
578 '-e', '--export', action='store_true', default=False,
579 help='Export IPython history as a notebook. The filename argument '
579 help='Export IPython history as a notebook. The filename argument '
580 'is used to specify the notebook name and format. For example '
580 'is used to specify the notebook name and format. For example '
581 'a filename of notebook.ipynb will result in a notebook name '
581 'a filename of notebook.ipynb will result in a notebook name '
582 'of "notebook" and a format of "json". Likewise using a ".py" '
582 'of "notebook" and a format of "json". Likewise using a ".py" '
583 'file extension will write the notebook as a Python script'
583 'file extension will write the notebook as a Python script'
584 )
584 )
585 @magic_arguments.argument(
585 @magic_arguments.argument(
586 'filename', type=unicode_type,
586 'filename', type=unicode_type,
587 help='Notebook name or filename'
587 help='Notebook name or filename'
588 )
588 )
589 @line_magic
589 @line_magic
590 def notebook(self, s):
590 def notebook(self, s):
591 """Export and convert IPython notebooks.
591 """Export and convert IPython notebooks.
592
592
593 This function can export the current IPython history to a notebook file.
593 This function can export the current IPython history to a notebook file.
594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
595 To export the history to "foo.py" do "%notebook -e foo.py".
595 To export the history to "foo.py" do "%notebook -e foo.py".
596 """
596 """
597 args = magic_arguments.parse_argstring(self.notebook, s)
597 args = magic_arguments.parse_argstring(self.notebook, s)
598
598
599 from IPython.nbformat import write, v4
599 from IPython.nbformat import write, v4
600 args.filename = unquote_filename(args.filename)
600 args.filename = unquote_filename(args.filename)
601 if args.export:
601 if args.export:
602 cells = []
602 cells = []
603 hist = list(self.shell.history_manager.get_range())
603 hist = list(self.shell.history_manager.get_range())
604 for session, execution_count, input in hist[:-1]:
604 for session, execution_count, input in hist[:-1]:
605 cells.append(v4.new_code_cell(
605 cells.append(v4.new_code_cell(
606 execution_count=execution_count,
606 execution_count=execution_count,
607 source=source
607 source=source
608 ))
608 ))
609 nb = v4.new_notebook(cells=cells)
609 nb = v4.new_notebook(cells=cells)
610 with io.open(args.filename, 'w', encoding='utf-8') as f:
610 with io.open(args.filename, 'w', encoding='utf-8') as f:
611 write(nb, f, version=4)
611 write(nb, f, version=4)
@@ -1,132 +1,148 b''
1 #-----------------------------------------------------------------------------
1 # Copyright (c) IPython Development Team.
2 # Copyright (C) 2010-2011 The IPython Development Team.
2 # Distributed under the terms of the Modified BSD License.
3 #
3
4 # Distributed under the terms of the BSD License.
4 import json
5 #
6 # The full license is in the file COPYING.txt, distributed with this software.
7 #-----------------------------------------------------------------------------
8 import os
5 import os
6 import warnings
9
7
10 import nose.tools as nt
8 import nose.tools as nt
11
9
12 from IPython.core import display
10 from IPython.core import display
13 from IPython.core.getipython import get_ipython
11 from IPython.core.getipython import get_ipython
14 from IPython.utils import path as ipath
12 from IPython.utils import path as ipath
15
13
16 import IPython.testing.decorators as dec
14 import IPython.testing.decorators as dec
17
15
18 def test_image_size():
16 def test_image_size():
19 """Simple test for display.Image(args, width=x,height=y)"""
17 """Simple test for display.Image(args, width=x,height=y)"""
20 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
18 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
21 img = display.Image(url=thisurl, width=200, height=200)
19 img = display.Image(url=thisurl, width=200, height=200)
22 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
20 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
23 img = display.Image(url=thisurl, width=200)
21 img = display.Image(url=thisurl, width=200)
24 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
22 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
25 img = display.Image(url=thisurl)
23 img = display.Image(url=thisurl)
26 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
24 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
27
25
28 def test_retina_png():
26 def test_retina_png():
29 here = os.path.dirname(__file__)
27 here = os.path.dirname(__file__)
30 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
28 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
31 nt.assert_equal(img.height, 1)
29 nt.assert_equal(img.height, 1)
32 nt.assert_equal(img.width, 1)
30 nt.assert_equal(img.width, 1)
33 data, md = img._repr_png_()
31 data, md = img._repr_png_()
34 nt.assert_equal(md['width'], 1)
32 nt.assert_equal(md['width'], 1)
35 nt.assert_equal(md['height'], 1)
33 nt.assert_equal(md['height'], 1)
36
34
37 def test_retina_jpeg():
35 def test_retina_jpeg():
38 here = os.path.dirname(__file__)
36 here = os.path.dirname(__file__)
39 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
37 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
40 nt.assert_equal(img.height, 1)
38 nt.assert_equal(img.height, 1)
41 nt.assert_equal(img.width, 1)
39 nt.assert_equal(img.width, 1)
42 data, md = img._repr_jpeg_()
40 data, md = img._repr_jpeg_()
43 nt.assert_equal(md['width'], 1)
41 nt.assert_equal(md['width'], 1)
44 nt.assert_equal(md['height'], 1)
42 nt.assert_equal(md['height'], 1)
45
43
46 def test_image_filename_defaults():
44 def test_image_filename_defaults():
47 '''test format constraint, and validity of jpeg and png'''
45 '''test format constraint, and validity of jpeg and png'''
48 tpath = ipath.get_ipython_package_dir()
46 tpath = ipath.get_ipython_package_dir()
49 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.gif'),
47 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.gif'),
50 embed=True)
48 embed=True)
51 nt.assert_raises(ValueError, display.Image)
49 nt.assert_raises(ValueError, display.Image)
52 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
50 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
53 from IPython.html import DEFAULT_STATIC_FILES_PATH
51 from IPython.html import DEFAULT_STATIC_FILES_PATH
54 # check boths paths to allow packages to test at build and install time
52 # check boths paths to allow packages to test at build and install time
55 imgfile = os.path.join(tpath, 'html/static/base/images/logo.png')
53 imgfile = os.path.join(tpath, 'html/static/base/images/logo.png')
56 if not os.path.exists(imgfile):
54 if not os.path.exists(imgfile):
57 imgfile = os.path.join(DEFAULT_STATIC_FILES_PATH, 'base/images/logo.png')
55 imgfile = os.path.join(DEFAULT_STATIC_FILES_PATH, 'base/images/logo.png')
58 img = display.Image(filename=imgfile)
56 img = display.Image(filename=imgfile)
59 nt.assert_equal('png', img.format)
57 nt.assert_equal('png', img.format)
60 nt.assert_is_not_none(img._repr_png_())
58 nt.assert_is_not_none(img._repr_png_())
61 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
59 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
62 nt.assert_equal('jpeg', img.format)
60 nt.assert_equal('jpeg', img.format)
63 nt.assert_is_none(img._repr_jpeg_())
61 nt.assert_is_none(img._repr_jpeg_())
64
62
65 def _get_inline_config():
63 def _get_inline_config():
66 from IPython.kernel.zmq.pylab.config import InlineBackend
64 from IPython.kernel.zmq.pylab.config import InlineBackend
67 return InlineBackend.instance()
65 return InlineBackend.instance()
68
66
69 @dec.skip_without('matplotlib')
67 @dec.skip_without('matplotlib')
70 def test_set_matplotlib_close():
68 def test_set_matplotlib_close():
71 cfg = _get_inline_config()
69 cfg = _get_inline_config()
72 cfg.close_figures = False
70 cfg.close_figures = False
73 display.set_matplotlib_close()
71 display.set_matplotlib_close()
74 assert cfg.close_figures
72 assert cfg.close_figures
75 display.set_matplotlib_close(False)
73 display.set_matplotlib_close(False)
76 assert not cfg.close_figures
74 assert not cfg.close_figures
77
75
78 _fmt_mime_map = {
76 _fmt_mime_map = {
79 'png': 'image/png',
77 'png': 'image/png',
80 'jpeg': 'image/jpeg',
78 'jpeg': 'image/jpeg',
81 'pdf': 'application/pdf',
79 'pdf': 'application/pdf',
82 'retina': 'image/png',
80 'retina': 'image/png',
83 'svg': 'image/svg+xml',
81 'svg': 'image/svg+xml',
84 }
82 }
85
83
86 @dec.skip_without('matplotlib')
84 @dec.skip_without('matplotlib')
87 def test_set_matplotlib_formats():
85 def test_set_matplotlib_formats():
88 from matplotlib.figure import Figure
86 from matplotlib.figure import Figure
89 formatters = get_ipython().display_formatter.formatters
87 formatters = get_ipython().display_formatter.formatters
90 for formats in [
88 for formats in [
91 ('png',),
89 ('png',),
92 ('pdf', 'svg'),
90 ('pdf', 'svg'),
93 ('jpeg', 'retina', 'png'),
91 ('jpeg', 'retina', 'png'),
94 (),
92 (),
95 ]:
93 ]:
96 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
94 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
97 display.set_matplotlib_formats(*formats)
95 display.set_matplotlib_formats(*formats)
98 for mime, f in formatters.items():
96 for mime, f in formatters.items():
99 if mime in active_mimes:
97 if mime in active_mimes:
100 nt.assert_in(Figure, f)
98 nt.assert_in(Figure, f)
101 else:
99 else:
102 nt.assert_not_in(Figure, f)
100 nt.assert_not_in(Figure, f)
103
101
104 @dec.skip_without('matplotlib')
102 @dec.skip_without('matplotlib')
105 def test_set_matplotlib_formats_kwargs():
103 def test_set_matplotlib_formats_kwargs():
106 from matplotlib.figure import Figure
104 from matplotlib.figure import Figure
107 ip = get_ipython()
105 ip = get_ipython()
108 cfg = _get_inline_config()
106 cfg = _get_inline_config()
109 cfg.print_figure_kwargs.update(dict(foo='bar'))
107 cfg.print_figure_kwargs.update(dict(foo='bar'))
110 kwargs = dict(quality=10)
108 kwargs = dict(quality=10)
111 display.set_matplotlib_formats('png', **kwargs)
109 display.set_matplotlib_formats('png', **kwargs)
112 formatter = ip.display_formatter.formatters['image/png']
110 formatter = ip.display_formatter.formatters['image/png']
113 f = formatter.lookup_by_type(Figure)
111 f = formatter.lookup_by_type(Figure)
114 cell = f.__closure__[0].cell_contents
112 cell = f.__closure__[0].cell_contents
115 expected = kwargs
113 expected = kwargs
116 expected.update(cfg.print_figure_kwargs)
114 expected.update(cfg.print_figure_kwargs)
117 nt.assert_equal(cell, expected)
115 nt.assert_equal(cell, expected)
118
116
119 def test_displayobject_repr():
117 def test_displayobject_repr():
120 h = display.HTML('<br />')
118 h = display.HTML('<br />')
121 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
119 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
122 h._show_mem_addr = True
120 h._show_mem_addr = True
123 nt.assert_equal(repr(h), object.__repr__(h))
121 nt.assert_equal(repr(h), object.__repr__(h))
124 h._show_mem_addr = False
122 h._show_mem_addr = False
125 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
123 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
126
124
127 j = display.Javascript('')
125 j = display.Javascript('')
128 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
126 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
129 j._show_mem_addr = True
127 j._show_mem_addr = True
130 nt.assert_equal(repr(j), object.__repr__(j))
128 nt.assert_equal(repr(j), object.__repr__(j))
131 j._show_mem_addr = False
129 j._show_mem_addr = False
132 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
130 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
131
132 def test_json():
133 d = {'a': 5}
134 lis = [d]
135 j = display.JSON(d)
136 nt.assert_equal(j._repr_json_(), d)
137 with warnings.catch_warnings(record=True) as w:
138 j = display.JSON(json.dumps(d))
139 assert len(w) == 1
140 nt.assert_equal(j._repr_json_(), d)
141 j = display.JSON(lis)
142 nt.assert_equal(j._repr_json_(), lis)
143 with warnings.catch_warnings(record=True) as w:
144 j = display.JSON(json.dumps(lis))
145 assert len(w) == 1
146 nt.assert_equal(j._repr_json_(), lis)
147
148 No newline at end of file
@@ -1,420 +1,433 b''
1 """Tests for the Formatters."""
1 """Tests for the Formatters."""
2
2
3 import warnings
3 from math import pi
4 from math import pi
4
5
5 try:
6 try:
6 import numpy
7 import numpy
7 except:
8 except:
8 numpy = None
9 numpy = None
9 import nose.tools as nt
10 import nose.tools as nt
10
11
12 from IPython import get_ipython
11 from IPython.config import Config
13 from IPython.config import Config
12 from IPython.core.formatters import (
14 from IPython.core.formatters import (
13 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
15 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
14 DisplayFormatter,
16 DisplayFormatter, JSONFormatter,
15 )
17 )
16 from IPython.utils.io import capture_output
18 from IPython.utils.io import capture_output
17
19
18 class A(object):
20 class A(object):
19 def __repr__(self):
21 def __repr__(self):
20 return 'A()'
22 return 'A()'
21
23
22 class B(A):
24 class B(A):
23 def __repr__(self):
25 def __repr__(self):
24 return 'B()'
26 return 'B()'
25
27
26 class C:
28 class C:
27 pass
29 pass
28
30
29 class BadRepr(object):
31 class BadRepr(object):
30 def __repr__(self):
32 def __repr__(self):
31 raise ValueError("bad repr")
33 raise ValueError("bad repr")
32
34
33 class BadPretty(object):
35 class BadPretty(object):
34 _repr_pretty_ = None
36 _repr_pretty_ = None
35
37
36 class GoodPretty(object):
38 class GoodPretty(object):
37 def _repr_pretty_(self, pp, cycle):
39 def _repr_pretty_(self, pp, cycle):
38 pp.text('foo')
40 pp.text('foo')
39
41
40 def __repr__(self):
42 def __repr__(self):
41 return 'GoodPretty()'
43 return 'GoodPretty()'
42
44
43 def foo_printer(obj, pp, cycle):
45 def foo_printer(obj, pp, cycle):
44 pp.text('foo')
46 pp.text('foo')
45
47
46 def test_pretty():
48 def test_pretty():
47 f = PlainTextFormatter()
49 f = PlainTextFormatter()
48 f.for_type(A, foo_printer)
50 f.for_type(A, foo_printer)
49 nt.assert_equal(f(A()), 'foo')
51 nt.assert_equal(f(A()), 'foo')
50 nt.assert_equal(f(B()), 'foo')
52 nt.assert_equal(f(B()), 'foo')
51 nt.assert_equal(f(GoodPretty()), 'foo')
53 nt.assert_equal(f(GoodPretty()), 'foo')
52 # Just don't raise an exception for the following:
54 # Just don't raise an exception for the following:
53 f(BadPretty())
55 f(BadPretty())
54
56
55 f.pprint = False
57 f.pprint = False
56 nt.assert_equal(f(A()), 'A()')
58 nt.assert_equal(f(A()), 'A()')
57 nt.assert_equal(f(B()), 'B()')
59 nt.assert_equal(f(B()), 'B()')
58 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
60 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
59
61
60
62
61 def test_deferred():
63 def test_deferred():
62 f = PlainTextFormatter()
64 f = PlainTextFormatter()
63
65
64 def test_precision():
66 def test_precision():
65 """test various values for float_precision."""
67 """test various values for float_precision."""
66 f = PlainTextFormatter()
68 f = PlainTextFormatter()
67 nt.assert_equal(f(pi), repr(pi))
69 nt.assert_equal(f(pi), repr(pi))
68 f.float_precision = 0
70 f.float_precision = 0
69 if numpy:
71 if numpy:
70 po = numpy.get_printoptions()
72 po = numpy.get_printoptions()
71 nt.assert_equal(po['precision'], 0)
73 nt.assert_equal(po['precision'], 0)
72 nt.assert_equal(f(pi), '3')
74 nt.assert_equal(f(pi), '3')
73 f.float_precision = 2
75 f.float_precision = 2
74 if numpy:
76 if numpy:
75 po = numpy.get_printoptions()
77 po = numpy.get_printoptions()
76 nt.assert_equal(po['precision'], 2)
78 nt.assert_equal(po['precision'], 2)
77 nt.assert_equal(f(pi), '3.14')
79 nt.assert_equal(f(pi), '3.14')
78 f.float_precision = '%g'
80 f.float_precision = '%g'
79 if numpy:
81 if numpy:
80 po = numpy.get_printoptions()
82 po = numpy.get_printoptions()
81 nt.assert_equal(po['precision'], 2)
83 nt.assert_equal(po['precision'], 2)
82 nt.assert_equal(f(pi), '3.14159')
84 nt.assert_equal(f(pi), '3.14159')
83 f.float_precision = '%e'
85 f.float_precision = '%e'
84 nt.assert_equal(f(pi), '3.141593e+00')
86 nt.assert_equal(f(pi), '3.141593e+00')
85 f.float_precision = ''
87 f.float_precision = ''
86 if numpy:
88 if numpy:
87 po = numpy.get_printoptions()
89 po = numpy.get_printoptions()
88 nt.assert_equal(po['precision'], 8)
90 nt.assert_equal(po['precision'], 8)
89 nt.assert_equal(f(pi), repr(pi))
91 nt.assert_equal(f(pi), repr(pi))
90
92
91 def test_bad_precision():
93 def test_bad_precision():
92 """test various invalid values for float_precision."""
94 """test various invalid values for float_precision."""
93 f = PlainTextFormatter()
95 f = PlainTextFormatter()
94 def set_fp(p):
96 def set_fp(p):
95 f.float_precision=p
97 f.float_precision=p
96 nt.assert_raises(ValueError, set_fp, '%')
98 nt.assert_raises(ValueError, set_fp, '%')
97 nt.assert_raises(ValueError, set_fp, '%.3f%i')
99 nt.assert_raises(ValueError, set_fp, '%.3f%i')
98 nt.assert_raises(ValueError, set_fp, 'foo')
100 nt.assert_raises(ValueError, set_fp, 'foo')
99 nt.assert_raises(ValueError, set_fp, -1)
101 nt.assert_raises(ValueError, set_fp, -1)
100
102
101 def test_for_type():
103 def test_for_type():
102 f = PlainTextFormatter()
104 f = PlainTextFormatter()
103
105
104 # initial return, None
106 # initial return, None
105 nt.assert_is(f.for_type(C, foo_printer), None)
107 nt.assert_is(f.for_type(C, foo_printer), None)
106 # no func queries
108 # no func queries
107 nt.assert_is(f.for_type(C), foo_printer)
109 nt.assert_is(f.for_type(C), foo_printer)
108 # shouldn't change anything
110 # shouldn't change anything
109 nt.assert_is(f.for_type(C), foo_printer)
111 nt.assert_is(f.for_type(C), foo_printer)
110 # None should do the same
112 # None should do the same
111 nt.assert_is(f.for_type(C, None), foo_printer)
113 nt.assert_is(f.for_type(C, None), foo_printer)
112 nt.assert_is(f.for_type(C, None), foo_printer)
114 nt.assert_is(f.for_type(C, None), foo_printer)
113
115
114 def test_for_type_string():
116 def test_for_type_string():
115 f = PlainTextFormatter()
117 f = PlainTextFormatter()
116
118
117 mod = C.__module__
119 mod = C.__module__
118
120
119 type_str = '%s.%s' % (C.__module__, 'C')
121 type_str = '%s.%s' % (C.__module__, 'C')
120
122
121 # initial return, None
123 # initial return, None
122 nt.assert_is(f.for_type(type_str, foo_printer), None)
124 nt.assert_is(f.for_type(type_str, foo_printer), None)
123 # no func queries
125 # no func queries
124 nt.assert_is(f.for_type(type_str), foo_printer)
126 nt.assert_is(f.for_type(type_str), foo_printer)
125 nt.assert_in(_mod_name_key(C), f.deferred_printers)
127 nt.assert_in(_mod_name_key(C), f.deferred_printers)
126 nt.assert_is(f.for_type(C), foo_printer)
128 nt.assert_is(f.for_type(C), foo_printer)
127 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
129 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
128 nt.assert_in(C, f.type_printers)
130 nt.assert_in(C, f.type_printers)
129
131
130 def test_for_type_by_name():
132 def test_for_type_by_name():
131 f = PlainTextFormatter()
133 f = PlainTextFormatter()
132
134
133 mod = C.__module__
135 mod = C.__module__
134
136
135 # initial return, None
137 # initial return, None
136 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
138 nt.assert_is(f.for_type_by_name(mod, 'C', foo_printer), None)
137 # no func queries
139 # no func queries
138 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
139 # shouldn't change anything
141 # shouldn't change anything
140 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
142 nt.assert_is(f.for_type_by_name(mod, 'C'), foo_printer)
141 # None should do the same
143 # None should do the same
142 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
144 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
143 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
145 nt.assert_is(f.for_type_by_name(mod, 'C', None), foo_printer)
144
146
145 def test_lookup():
147 def test_lookup():
146 f = PlainTextFormatter()
148 f = PlainTextFormatter()
147
149
148 f.for_type(C, foo_printer)
150 f.for_type(C, foo_printer)
149 nt.assert_is(f.lookup(C()), foo_printer)
151 nt.assert_is(f.lookup(C()), foo_printer)
150 with nt.assert_raises(KeyError):
152 with nt.assert_raises(KeyError):
151 f.lookup(A())
153 f.lookup(A())
152
154
153 def test_lookup_string():
155 def test_lookup_string():
154 f = PlainTextFormatter()
156 f = PlainTextFormatter()
155 type_str = '%s.%s' % (C.__module__, 'C')
157 type_str = '%s.%s' % (C.__module__, 'C')
156
158
157 f.for_type(type_str, foo_printer)
159 f.for_type(type_str, foo_printer)
158 nt.assert_is(f.lookup(C()), foo_printer)
160 nt.assert_is(f.lookup(C()), foo_printer)
159 # should move from deferred to imported dict
161 # should move from deferred to imported dict
160 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
162 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
161 nt.assert_in(C, f.type_printers)
163 nt.assert_in(C, f.type_printers)
162
164
163 def test_lookup_by_type():
165 def test_lookup_by_type():
164 f = PlainTextFormatter()
166 f = PlainTextFormatter()
165 f.for_type(C, foo_printer)
167 f.for_type(C, foo_printer)
166 nt.assert_is(f.lookup_by_type(C), foo_printer)
168 nt.assert_is(f.lookup_by_type(C), foo_printer)
167 type_str = '%s.%s' % (C.__module__, 'C')
169 type_str = '%s.%s' % (C.__module__, 'C')
168 with nt.assert_raises(KeyError):
170 with nt.assert_raises(KeyError):
169 f.lookup_by_type(A)
171 f.lookup_by_type(A)
170
172
171 def test_lookup_by_type_string():
173 def test_lookup_by_type_string():
172 f = PlainTextFormatter()
174 f = PlainTextFormatter()
173 type_str = '%s.%s' % (C.__module__, 'C')
175 type_str = '%s.%s' % (C.__module__, 'C')
174 f.for_type(type_str, foo_printer)
176 f.for_type(type_str, foo_printer)
175
177
176 # verify insertion
178 # verify insertion
177 nt.assert_in(_mod_name_key(C), f.deferred_printers)
179 nt.assert_in(_mod_name_key(C), f.deferred_printers)
178 nt.assert_not_in(C, f.type_printers)
180 nt.assert_not_in(C, f.type_printers)
179
181
180 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
182 nt.assert_is(f.lookup_by_type(type_str), foo_printer)
181 # lookup by string doesn't cause import
183 # lookup by string doesn't cause import
182 nt.assert_in(_mod_name_key(C), f.deferred_printers)
184 nt.assert_in(_mod_name_key(C), f.deferred_printers)
183 nt.assert_not_in(C, f.type_printers)
185 nt.assert_not_in(C, f.type_printers)
184
186
185 nt.assert_is(f.lookup_by_type(C), foo_printer)
187 nt.assert_is(f.lookup_by_type(C), foo_printer)
186 # should move from deferred to imported dict
188 # should move from deferred to imported dict
187 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
189 nt.assert_not_in(_mod_name_key(C), f.deferred_printers)
188 nt.assert_in(C, f.type_printers)
190 nt.assert_in(C, f.type_printers)
189
191
190 def test_in_formatter():
192 def test_in_formatter():
191 f = PlainTextFormatter()
193 f = PlainTextFormatter()
192 f.for_type(C, foo_printer)
194 f.for_type(C, foo_printer)
193 type_str = '%s.%s' % (C.__module__, 'C')
195 type_str = '%s.%s' % (C.__module__, 'C')
194 nt.assert_in(C, f)
196 nt.assert_in(C, f)
195 nt.assert_in(type_str, f)
197 nt.assert_in(type_str, f)
196
198
197 def test_string_in_formatter():
199 def test_string_in_formatter():
198 f = PlainTextFormatter()
200 f = PlainTextFormatter()
199 type_str = '%s.%s' % (C.__module__, 'C')
201 type_str = '%s.%s' % (C.__module__, 'C')
200 f.for_type(type_str, foo_printer)
202 f.for_type(type_str, foo_printer)
201 nt.assert_in(type_str, f)
203 nt.assert_in(type_str, f)
202 nt.assert_in(C, f)
204 nt.assert_in(C, f)
203
205
204 def test_pop():
206 def test_pop():
205 f = PlainTextFormatter()
207 f = PlainTextFormatter()
206 f.for_type(C, foo_printer)
208 f.for_type(C, foo_printer)
207 nt.assert_is(f.lookup_by_type(C), foo_printer)
209 nt.assert_is(f.lookup_by_type(C), foo_printer)
208 nt.assert_is(f.pop(C, None), foo_printer)
210 nt.assert_is(f.pop(C, None), foo_printer)
209 f.for_type(C, foo_printer)
211 f.for_type(C, foo_printer)
210 nt.assert_is(f.pop(C), foo_printer)
212 nt.assert_is(f.pop(C), foo_printer)
211 with nt.assert_raises(KeyError):
213 with nt.assert_raises(KeyError):
212 f.lookup_by_type(C)
214 f.lookup_by_type(C)
213 with nt.assert_raises(KeyError):
215 with nt.assert_raises(KeyError):
214 f.pop(C)
216 f.pop(C)
215 with nt.assert_raises(KeyError):
217 with nt.assert_raises(KeyError):
216 f.pop(A)
218 f.pop(A)
217 nt.assert_is(f.pop(A, None), None)
219 nt.assert_is(f.pop(A, None), None)
218
220
219 def test_pop_string():
221 def test_pop_string():
220 f = PlainTextFormatter()
222 f = PlainTextFormatter()
221 type_str = '%s.%s' % (C.__module__, 'C')
223 type_str = '%s.%s' % (C.__module__, 'C')
222
224
223 with nt.assert_raises(KeyError):
225 with nt.assert_raises(KeyError):
224 f.pop(type_str)
226 f.pop(type_str)
225
227
226 f.for_type(type_str, foo_printer)
228 f.for_type(type_str, foo_printer)
227 f.pop(type_str)
229 f.pop(type_str)
228 with nt.assert_raises(KeyError):
230 with nt.assert_raises(KeyError):
229 f.lookup_by_type(C)
231 f.lookup_by_type(C)
230 with nt.assert_raises(KeyError):
232 with nt.assert_raises(KeyError):
231 f.pop(type_str)
233 f.pop(type_str)
232
234
233 f.for_type(C, foo_printer)
235 f.for_type(C, foo_printer)
234 nt.assert_is(f.pop(type_str, None), foo_printer)
236 nt.assert_is(f.pop(type_str, None), foo_printer)
235 with nt.assert_raises(KeyError):
237 with nt.assert_raises(KeyError):
236 f.lookup_by_type(C)
238 f.lookup_by_type(C)
237 with nt.assert_raises(KeyError):
239 with nt.assert_raises(KeyError):
238 f.pop(type_str)
240 f.pop(type_str)
239 nt.assert_is(f.pop(type_str, None), None)
241 nt.assert_is(f.pop(type_str, None), None)
240
242
241
243
242 def test_error_method():
244 def test_error_method():
243 f = HTMLFormatter()
245 f = HTMLFormatter()
244 class BadHTML(object):
246 class BadHTML(object):
245 def _repr_html_(self):
247 def _repr_html_(self):
246 raise ValueError("Bad HTML")
248 raise ValueError("Bad HTML")
247 bad = BadHTML()
249 bad = BadHTML()
248 with capture_output() as captured:
250 with capture_output() as captured:
249 result = f(bad)
251 result = f(bad)
250 nt.assert_is(result, None)
252 nt.assert_is(result, None)
251 nt.assert_in("Traceback", captured.stdout)
253 nt.assert_in("Traceback", captured.stdout)
252 nt.assert_in("Bad HTML", captured.stdout)
254 nt.assert_in("Bad HTML", captured.stdout)
253 nt.assert_in("_repr_html_", captured.stdout)
255 nt.assert_in("_repr_html_", captured.stdout)
254
256
255 def test_nowarn_notimplemented():
257 def test_nowarn_notimplemented():
256 f = HTMLFormatter()
258 f = HTMLFormatter()
257 class HTMLNotImplemented(object):
259 class HTMLNotImplemented(object):
258 def _repr_html_(self):
260 def _repr_html_(self):
259 raise NotImplementedError
261 raise NotImplementedError
260 h = HTMLNotImplemented()
262 h = HTMLNotImplemented()
261 with capture_output() as captured:
263 with capture_output() as captured:
262 result = f(h)
264 result = f(h)
263 nt.assert_is(result, None)
265 nt.assert_is(result, None)
264 nt.assert_equal("", captured.stderr)
266 nt.assert_equal("", captured.stderr)
265 nt.assert_equal("", captured.stdout)
267 nt.assert_equal("", captured.stdout)
266
268
267 def test_warn_error_for_type():
269 def test_warn_error_for_type():
268 f = HTMLFormatter()
270 f = HTMLFormatter()
269 f.for_type(int, lambda i: name_error)
271 f.for_type(int, lambda i: name_error)
270 with capture_output() as captured:
272 with capture_output() as captured:
271 result = f(5)
273 result = f(5)
272 nt.assert_is(result, None)
274 nt.assert_is(result, None)
273 nt.assert_in("Traceback", captured.stdout)
275 nt.assert_in("Traceback", captured.stdout)
274 nt.assert_in("NameError", captured.stdout)
276 nt.assert_in("NameError", captured.stdout)
275 nt.assert_in("name_error", captured.stdout)
277 nt.assert_in("name_error", captured.stdout)
276
278
277 def test_error_pretty_method():
279 def test_error_pretty_method():
278 f = PlainTextFormatter()
280 f = PlainTextFormatter()
279 class BadPretty(object):
281 class BadPretty(object):
280 def _repr_pretty_(self):
282 def _repr_pretty_(self):
281 return "hello"
283 return "hello"
282 bad = BadPretty()
284 bad = BadPretty()
283 with capture_output() as captured:
285 with capture_output() as captured:
284 result = f(bad)
286 result = f(bad)
285 nt.assert_is(result, None)
287 nt.assert_is(result, None)
286 nt.assert_in("Traceback", captured.stdout)
288 nt.assert_in("Traceback", captured.stdout)
287 nt.assert_in("_repr_pretty_", captured.stdout)
289 nt.assert_in("_repr_pretty_", captured.stdout)
288 nt.assert_in("given", captured.stdout)
290 nt.assert_in("given", captured.stdout)
289 nt.assert_in("argument", captured.stdout)
291 nt.assert_in("argument", captured.stdout)
290
292
291
293
292 def test_bad_repr_traceback():
294 def test_bad_repr_traceback():
293 f = PlainTextFormatter()
295 f = PlainTextFormatter()
294 bad = BadRepr()
296 bad = BadRepr()
295 with capture_output() as captured:
297 with capture_output() as captured:
296 result = f(bad)
298 result = f(bad)
297 # catches error, returns None
299 # catches error, returns None
298 nt.assert_is(result, None)
300 nt.assert_is(result, None)
299 nt.assert_in("Traceback", captured.stdout)
301 nt.assert_in("Traceback", captured.stdout)
300 nt.assert_in("__repr__", captured.stdout)
302 nt.assert_in("__repr__", captured.stdout)
301 nt.assert_in("ValueError", captured.stdout)
303 nt.assert_in("ValueError", captured.stdout)
302
304
303
305
304 class MakePDF(object):
306 class MakePDF(object):
305 def _repr_pdf_(self):
307 def _repr_pdf_(self):
306 return 'PDF'
308 return 'PDF'
307
309
308 def test_pdf_formatter():
310 def test_pdf_formatter():
309 pdf = MakePDF()
311 pdf = MakePDF()
310 f = PDFFormatter()
312 f = PDFFormatter()
311 nt.assert_equal(f(pdf), 'PDF')
313 nt.assert_equal(f(pdf), 'PDF')
312
314
313 def test_print_method_bound():
315 def test_print_method_bound():
314 f = HTMLFormatter()
316 f = HTMLFormatter()
315 class MyHTML(object):
317 class MyHTML(object):
316 def _repr_html_(self):
318 def _repr_html_(self):
317 return "hello"
319 return "hello"
318 with capture_output() as captured:
320 with capture_output() as captured:
319 result = f(MyHTML)
321 result = f(MyHTML)
320 nt.assert_is(result, None)
322 nt.assert_is(result, None)
321 nt.assert_not_in("FormatterWarning", captured.stderr)
323 nt.assert_not_in("FormatterWarning", captured.stderr)
322
324
323 with capture_output() as captured:
325 with capture_output() as captured:
324 result = f(MyHTML())
326 result = f(MyHTML())
325 nt.assert_equal(result, "hello")
327 nt.assert_equal(result, "hello")
326 nt.assert_equal(captured.stderr, "")
328 nt.assert_equal(captured.stderr, "")
327
329
328 def test_print_method_weird():
330 def test_print_method_weird():
329
331
330 class TextMagicHat(object):
332 class TextMagicHat(object):
331 def __getattr__(self, key):
333 def __getattr__(self, key):
332 return key
334 return key
333
335
334 f = HTMLFormatter()
336 f = HTMLFormatter()
335
337
336 text_hat = TextMagicHat()
338 text_hat = TextMagicHat()
337 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
339 nt.assert_equal(text_hat._repr_html_, '_repr_html_')
338 with capture_output() as captured:
340 with capture_output() as captured:
339 result = f(text_hat)
341 result = f(text_hat)
340
342
341 nt.assert_is(result, None)
343 nt.assert_is(result, None)
342 nt.assert_not_in("FormatterWarning", captured.stderr)
344 nt.assert_not_in("FormatterWarning", captured.stderr)
343
345
344 class CallableMagicHat(object):
346 class CallableMagicHat(object):
345 def __getattr__(self, key):
347 def __getattr__(self, key):
346 return lambda : key
348 return lambda : key
347
349
348 call_hat = CallableMagicHat()
350 call_hat = CallableMagicHat()
349 with capture_output() as captured:
351 with capture_output() as captured:
350 result = f(call_hat)
352 result = f(call_hat)
351
353
352 nt.assert_equal(result, None)
354 nt.assert_equal(result, None)
353
355
354 class BadReprArgs(object):
356 class BadReprArgs(object):
355 def _repr_html_(self, extra, args):
357 def _repr_html_(self, extra, args):
356 return "html"
358 return "html"
357
359
358 bad = BadReprArgs()
360 bad = BadReprArgs()
359 with capture_output() as captured:
361 with capture_output() as captured:
360 result = f(bad)
362 result = f(bad)
361
363
362 nt.assert_is(result, None)
364 nt.assert_is(result, None)
363 nt.assert_not_in("FormatterWarning", captured.stderr)
365 nt.assert_not_in("FormatterWarning", captured.stderr)
364
366
365
367
366 def test_format_config():
368 def test_format_config():
367 """config objects don't pretend to support fancy reprs with lazy attrs"""
369 """config objects don't pretend to support fancy reprs with lazy attrs"""
368 f = HTMLFormatter()
370 f = HTMLFormatter()
369 cfg = Config()
371 cfg = Config()
370 with capture_output() as captured:
372 with capture_output() as captured:
371 result = f(cfg)
373 result = f(cfg)
372 nt.assert_is(result, None)
374 nt.assert_is(result, None)
373 nt.assert_equal(captured.stderr, "")
375 nt.assert_equal(captured.stderr, "")
374
376
375 with capture_output() as captured:
377 with capture_output() as captured:
376 result = f(Config)
378 result = f(Config)
377 nt.assert_is(result, None)
379 nt.assert_is(result, None)
378 nt.assert_equal(captured.stderr, "")
380 nt.assert_equal(captured.stderr, "")
379
381
380 def test_pretty_max_seq_length():
382 def test_pretty_max_seq_length():
381 f = PlainTextFormatter(max_seq_length=1)
383 f = PlainTextFormatter(max_seq_length=1)
382 lis = list(range(3))
384 lis = list(range(3))
383 text = f(lis)
385 text = f(lis)
384 nt.assert_equal(text, '[0, ...]')
386 nt.assert_equal(text, '[0, ...]')
385 f.max_seq_length = 0
387 f.max_seq_length = 0
386 text = f(lis)
388 text = f(lis)
387 nt.assert_equal(text, '[0, 1, 2]')
389 nt.assert_equal(text, '[0, 1, 2]')
388 text = f(list(range(1024)))
390 text = f(list(range(1024)))
389 lines = text.splitlines()
391 lines = text.splitlines()
390 nt.assert_equal(len(lines), 1024)
392 nt.assert_equal(len(lines), 1024)
391
393
392
394
393 def test_ipython_display_formatter():
395 def test_ipython_display_formatter():
394 """Objects with _ipython_display_ defined bypass other formatters"""
396 """Objects with _ipython_display_ defined bypass other formatters"""
395 f = get_ipython().display_formatter
397 f = get_ipython().display_formatter
396 catcher = []
398 catcher = []
397 class SelfDisplaying(object):
399 class SelfDisplaying(object):
398 def _ipython_display_(self):
400 def _ipython_display_(self):
399 catcher.append(self)
401 catcher.append(self)
400
402
401 class NotSelfDisplaying(object):
403 class NotSelfDisplaying(object):
402 def __repr__(self):
404 def __repr__(self):
403 return "NotSelfDisplaying"
405 return "NotSelfDisplaying"
404
406
405 def _ipython_display_(self):
407 def _ipython_display_(self):
406 raise NotImplementedError
408 raise NotImplementedError
407
409
408 yes = SelfDisplaying()
410 yes = SelfDisplaying()
409 no = NotSelfDisplaying()
411 no = NotSelfDisplaying()
410
412
411 d, md = f.format(no)
413 d, md = f.format(no)
412 nt.assert_equal(d, {'text/plain': repr(no)})
414 nt.assert_equal(d, {'text/plain': repr(no)})
413 nt.assert_equal(md, {})
415 nt.assert_equal(md, {})
414 nt.assert_equal(catcher, [])
416 nt.assert_equal(catcher, [])
415
417
416 d, md = f.format(yes)
418 d, md = f.format(yes)
417 nt.assert_equal(d, {})
419 nt.assert_equal(d, {})
418 nt.assert_equal(md, {})
420 nt.assert_equal(md, {})
419 nt.assert_equal(catcher, [yes])
421 nt.assert_equal(catcher, [yes])
420
422
423 def test_json_as_string_deprecated():
424 class JSONString(object):
425 def _repr_json_(self):
426 return '{}'
427
428 f = JSONFormatter()
429 with warnings.catch_warnings(record=True) as w:
430 d = f(JSONString())
431 nt.assert_equal(d, {})
432 nt.assert_equal(len(w), 1)
433 No newline at end of file
@@ -1,982 +1,994 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 import io
8 import io
9 import os
9 import os
10 import sys
10 import sys
11 import warnings
11 from unittest import TestCase, skipIf
12 from unittest import TestCase, skipIf
12
13
13 try:
14 try:
14 from importlib import invalidate_caches # Required from Python 3.3
15 from importlib import invalidate_caches # Required from Python 3.3
15 except ImportError:
16 except ImportError:
16 def invalidate_caches():
17 def invalidate_caches():
17 pass
18 pass
18
19
19 import nose.tools as nt
20 import nose.tools as nt
20
21
22 from IPython import get_ipython
21 from IPython.core import magic
23 from IPython.core import magic
22 from IPython.core.error import UsageError
24 from IPython.core.error import UsageError
23 from IPython.core.magic import (Magics, magics_class, line_magic,
25 from IPython.core.magic import (Magics, magics_class, line_magic,
24 cell_magic, line_cell_magic,
26 cell_magic, line_cell_magic,
25 register_line_magic, register_cell_magic,
27 register_line_magic, register_cell_magic,
26 register_line_cell_magic)
28 register_line_cell_magic)
27 from IPython.core.magics import execution, script, code
29 from IPython.core.magics import execution, script, code
28 from IPython.testing import decorators as dec
30 from IPython.testing import decorators as dec
29 from IPython.testing import tools as tt
31 from IPython.testing import tools as tt
30 from IPython.utils import py3compat
32 from IPython.utils import py3compat
31 from IPython.utils.io import capture_output
33 from IPython.utils.io import capture_output
32 from IPython.utils.tempdir import TemporaryDirectory
34 from IPython.utils.tempdir import TemporaryDirectory
33 from IPython.utils.process import find_cmd
35 from IPython.utils.process import find_cmd
34
36
35 if py3compat.PY3:
37 if py3compat.PY3:
36 from io import StringIO
38 from io import StringIO
37 else:
39 else:
38 from StringIO import StringIO
40 from StringIO import StringIO
39
41
40
42
41 @magic.magics_class
43 @magic.magics_class
42 class DummyMagics(magic.Magics): pass
44 class DummyMagics(magic.Magics): pass
43
45
44 def test_extract_code_ranges():
46 def test_extract_code_ranges():
45 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
47 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
46 expected = [(0, 1),
48 expected = [(0, 1),
47 (2, 3),
49 (2, 3),
48 (4, 6),
50 (4, 6),
49 (6, 9),
51 (6, 9),
50 (9, 14),
52 (9, 14),
51 (16, None),
53 (16, None),
52 (None, 9),
54 (None, 9),
53 (9, None),
55 (9, None),
54 (None, 13),
56 (None, 13),
55 (None, None)]
57 (None, None)]
56 actual = list(code.extract_code_ranges(instr))
58 actual = list(code.extract_code_ranges(instr))
57 nt.assert_equal(actual, expected)
59 nt.assert_equal(actual, expected)
58
60
59 def test_extract_symbols():
61 def test_extract_symbols():
60 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
62 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
61 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
63 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
62 expected = [([], ['a']),
64 expected = [([], ['a']),
63 (["def b():\n return 42\n"], []),
65 (["def b():\n return 42\n"], []),
64 (["class A: pass\n"], []),
66 (["class A: pass\n"], []),
65 (["class A: pass\n", "def b():\n return 42\n"], []),
67 (["class A: pass\n", "def b():\n return 42\n"], []),
66 (["class A: pass\n"], ['a']),
68 (["class A: pass\n"], ['a']),
67 ([], ['z'])]
69 ([], ['z'])]
68 for symbols, exp in zip(symbols_args, expected):
70 for symbols, exp in zip(symbols_args, expected):
69 nt.assert_equal(code.extract_symbols(source, symbols), exp)
71 nt.assert_equal(code.extract_symbols(source, symbols), exp)
70
72
71
73
72 def test_extract_symbols_raises_exception_with_non_python_code():
74 def test_extract_symbols_raises_exception_with_non_python_code():
73 source = ("=begin A Ruby program :)=end\n"
75 source = ("=begin A Ruby program :)=end\n"
74 "def hello\n"
76 "def hello\n"
75 "puts 'Hello world'\n"
77 "puts 'Hello world'\n"
76 "end")
78 "end")
77 with nt.assert_raises(SyntaxError):
79 with nt.assert_raises(SyntaxError):
78 code.extract_symbols(source, "hello")
80 code.extract_symbols(source, "hello")
79
81
80 def test_config():
82 def test_config():
81 """ test that config magic does not raise
83 """ test that config magic does not raise
82 can happen if Configurable init is moved too early into
84 can happen if Configurable init is moved too early into
83 Magics.__init__ as then a Config object will be registerd as a
85 Magics.__init__ as then a Config object will be registerd as a
84 magic.
86 magic.
85 """
87 """
86 ## should not raise.
88 ## should not raise.
87 _ip.magic('config')
89 _ip.magic('config')
88
90
89 def test_rehashx():
91 def test_rehashx():
90 # clear up everything
92 # clear up everything
91 _ip = get_ipython()
93 _ip = get_ipython()
92 _ip.alias_manager.clear_aliases()
94 _ip.alias_manager.clear_aliases()
93 del _ip.db['syscmdlist']
95 del _ip.db['syscmdlist']
94
96
95 _ip.magic('rehashx')
97 _ip.magic('rehashx')
96 # Practically ALL ipython development systems will have more than 10 aliases
98 # Practically ALL ipython development systems will have more than 10 aliases
97
99
98 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
100 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
99 for name, cmd in _ip.alias_manager.aliases:
101 for name, cmd in _ip.alias_manager.aliases:
100 # we must strip dots from alias names
102 # we must strip dots from alias names
101 nt.assert_not_in('.', name)
103 nt.assert_not_in('.', name)
102
104
103 # rehashx must fill up syscmdlist
105 # rehashx must fill up syscmdlist
104 scoms = _ip.db['syscmdlist']
106 scoms = _ip.db['syscmdlist']
105 nt.assert_true(len(scoms) > 10)
107 nt.assert_true(len(scoms) > 10)
106
108
107
109
108 def test_magic_parse_options():
110 def test_magic_parse_options():
109 """Test that we don't mangle paths when parsing magic options."""
111 """Test that we don't mangle paths when parsing magic options."""
110 ip = get_ipython()
112 ip = get_ipython()
111 path = 'c:\\x'
113 path = 'c:\\x'
112 m = DummyMagics(ip)
114 m = DummyMagics(ip)
113 opts = m.parse_options('-f %s' % path,'f:')[0]
115 opts = m.parse_options('-f %s' % path,'f:')[0]
114 # argv splitting is os-dependent
116 # argv splitting is os-dependent
115 if os.name == 'posix':
117 if os.name == 'posix':
116 expected = 'c:x'
118 expected = 'c:x'
117 else:
119 else:
118 expected = path
120 expected = path
119 nt.assert_equal(opts['f'], expected)
121 nt.assert_equal(opts['f'], expected)
120
122
121 def test_magic_parse_long_options():
123 def test_magic_parse_long_options():
122 """Magic.parse_options can handle --foo=bar long options"""
124 """Magic.parse_options can handle --foo=bar long options"""
123 ip = get_ipython()
125 ip = get_ipython()
124 m = DummyMagics(ip)
126 m = DummyMagics(ip)
125 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
127 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
126 nt.assert_in('foo', opts)
128 nt.assert_in('foo', opts)
127 nt.assert_in('bar', opts)
129 nt.assert_in('bar', opts)
128 nt.assert_equal(opts['bar'], "bubble")
130 nt.assert_equal(opts['bar'], "bubble")
129
131
130
132
131 @dec.skip_without('sqlite3')
133 @dec.skip_without('sqlite3')
132 def doctest_hist_f():
134 def doctest_hist_f():
133 """Test %hist -f with temporary filename.
135 """Test %hist -f with temporary filename.
134
136
135 In [9]: import tempfile
137 In [9]: import tempfile
136
138
137 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
139 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
138
140
139 In [11]: %hist -nl -f $tfile 3
141 In [11]: %hist -nl -f $tfile 3
140
142
141 In [13]: import os; os.unlink(tfile)
143 In [13]: import os; os.unlink(tfile)
142 """
144 """
143
145
144
146
145 @dec.skip_without('sqlite3')
147 @dec.skip_without('sqlite3')
146 def doctest_hist_r():
148 def doctest_hist_r():
147 """Test %hist -r
149 """Test %hist -r
148
150
149 XXX - This test is not recording the output correctly. For some reason, in
151 XXX - This test is not recording the output correctly. For some reason, in
150 testing mode the raw history isn't getting populated. No idea why.
152 testing mode the raw history isn't getting populated. No idea why.
151 Disabling the output checking for now, though at least we do run it.
153 Disabling the output checking for now, though at least we do run it.
152
154
153 In [1]: 'hist' in _ip.lsmagic()
155 In [1]: 'hist' in _ip.lsmagic()
154 Out[1]: True
156 Out[1]: True
155
157
156 In [2]: x=1
158 In [2]: x=1
157
159
158 In [3]: %hist -rl 2
160 In [3]: %hist -rl 2
159 x=1 # random
161 x=1 # random
160 %hist -r 2
162 %hist -r 2
161 """
163 """
162
164
163
165
164 @dec.skip_without('sqlite3')
166 @dec.skip_without('sqlite3')
165 def doctest_hist_op():
167 def doctest_hist_op():
166 """Test %hist -op
168 """Test %hist -op
167
169
168 In [1]: class b(float):
170 In [1]: class b(float):
169 ...: pass
171 ...: pass
170 ...:
172 ...:
171
173
172 In [2]: class s(object):
174 In [2]: class s(object):
173 ...: def __str__(self):
175 ...: def __str__(self):
174 ...: return 's'
176 ...: return 's'
175 ...:
177 ...:
176
178
177 In [3]:
179 In [3]:
178
180
179 In [4]: class r(b):
181 In [4]: class r(b):
180 ...: def __repr__(self):
182 ...: def __repr__(self):
181 ...: return 'r'
183 ...: return 'r'
182 ...:
184 ...:
183
185
184 In [5]: class sr(s,r): pass
186 In [5]: class sr(s,r): pass
185 ...:
187 ...:
186
188
187 In [6]:
189 In [6]:
188
190
189 In [7]: bb=b()
191 In [7]: bb=b()
190
192
191 In [8]: ss=s()
193 In [8]: ss=s()
192
194
193 In [9]: rr=r()
195 In [9]: rr=r()
194
196
195 In [10]: ssrr=sr()
197 In [10]: ssrr=sr()
196
198
197 In [11]: 4.5
199 In [11]: 4.5
198 Out[11]: 4.5
200 Out[11]: 4.5
199
201
200 In [12]: str(ss)
202 In [12]: str(ss)
201 Out[12]: 's'
203 Out[12]: 's'
202
204
203 In [13]:
205 In [13]:
204
206
205 In [14]: %hist -op
207 In [14]: %hist -op
206 >>> class b:
208 >>> class b:
207 ... pass
209 ... pass
208 ...
210 ...
209 >>> class s(b):
211 >>> class s(b):
210 ... def __str__(self):
212 ... def __str__(self):
211 ... return 's'
213 ... return 's'
212 ...
214 ...
213 >>>
215 >>>
214 >>> class r(b):
216 >>> class r(b):
215 ... def __repr__(self):
217 ... def __repr__(self):
216 ... return 'r'
218 ... return 'r'
217 ...
219 ...
218 >>> class sr(s,r): pass
220 >>> class sr(s,r): pass
219 >>>
221 >>>
220 >>> bb=b()
222 >>> bb=b()
221 >>> ss=s()
223 >>> ss=s()
222 >>> rr=r()
224 >>> rr=r()
223 >>> ssrr=sr()
225 >>> ssrr=sr()
224 >>> 4.5
226 >>> 4.5
225 4.5
227 4.5
226 >>> str(ss)
228 >>> str(ss)
227 's'
229 's'
228 >>>
230 >>>
229 """
231 """
230
232
231 def test_hist_pof():
233 def test_hist_pof():
232 ip = get_ipython()
234 ip = get_ipython()
233 ip.run_cell(u"1+2", store_history=True)
235 ip.run_cell(u"1+2", store_history=True)
234 #raise Exception(ip.history_manager.session_number)
236 #raise Exception(ip.history_manager.session_number)
235 #raise Exception(list(ip.history_manager._get_range_session()))
237 #raise Exception(list(ip.history_manager._get_range_session()))
236 with TemporaryDirectory() as td:
238 with TemporaryDirectory() as td:
237 tf = os.path.join(td, 'hist.py')
239 tf = os.path.join(td, 'hist.py')
238 ip.run_line_magic('history', '-pof %s' % tf)
240 ip.run_line_magic('history', '-pof %s' % tf)
239 assert os.path.isfile(tf)
241 assert os.path.isfile(tf)
240
242
241
243
242 @dec.skip_without('sqlite3')
244 @dec.skip_without('sqlite3')
243 def test_macro():
245 def test_macro():
244 ip = get_ipython()
246 ip = get_ipython()
245 ip.history_manager.reset() # Clear any existing history.
247 ip.history_manager.reset() # Clear any existing history.
246 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
248 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
247 for i, cmd in enumerate(cmds, start=1):
249 for i, cmd in enumerate(cmds, start=1):
248 ip.history_manager.store_inputs(i, cmd)
250 ip.history_manager.store_inputs(i, cmd)
249 ip.magic("macro test 1-3")
251 ip.magic("macro test 1-3")
250 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
252 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
251
253
252 # List macros
254 # List macros
253 nt.assert_in("test", ip.magic("macro"))
255 nt.assert_in("test", ip.magic("macro"))
254
256
255
257
256 @dec.skip_without('sqlite3')
258 @dec.skip_without('sqlite3')
257 def test_macro_run():
259 def test_macro_run():
258 """Test that we can run a multi-line macro successfully."""
260 """Test that we can run a multi-line macro successfully."""
259 ip = get_ipython()
261 ip = get_ipython()
260 ip.history_manager.reset()
262 ip.history_manager.reset()
261 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
263 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
262 "%macro test 2-3"]
264 "%macro test 2-3"]
263 for cmd in cmds:
265 for cmd in cmds:
264 ip.run_cell(cmd, store_history=True)
266 ip.run_cell(cmd, store_history=True)
265 nt.assert_equal(ip.user_ns["test"].value,
267 nt.assert_equal(ip.user_ns["test"].value,
266 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
268 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
267 with tt.AssertPrints("12"):
269 with tt.AssertPrints("12"):
268 ip.run_cell("test")
270 ip.run_cell("test")
269 with tt.AssertPrints("13"):
271 with tt.AssertPrints("13"):
270 ip.run_cell("test")
272 ip.run_cell("test")
271
273
272
274
273 def test_magic_magic():
275 def test_magic_magic():
274 """Test %magic"""
276 """Test %magic"""
275 ip = get_ipython()
277 ip = get_ipython()
276 with capture_output() as captured:
278 with capture_output() as captured:
277 ip.magic("magic")
279 ip.magic("magic")
278
280
279 stdout = captured.stdout
281 stdout = captured.stdout
280 nt.assert_in('%magic', stdout)
282 nt.assert_in('%magic', stdout)
281 nt.assert_in('IPython', stdout)
283 nt.assert_in('IPython', stdout)
282 nt.assert_in('Available', stdout)
284 nt.assert_in('Available', stdout)
283
285
284
286
285 @dec.skipif_not_numpy
287 @dec.skipif_not_numpy
286 def test_numpy_reset_array_undec():
288 def test_numpy_reset_array_undec():
287 "Test '%reset array' functionality"
289 "Test '%reset array' functionality"
288 _ip.ex('import numpy as np')
290 _ip.ex('import numpy as np')
289 _ip.ex('a = np.empty(2)')
291 _ip.ex('a = np.empty(2)')
290 nt.assert_in('a', _ip.user_ns)
292 nt.assert_in('a', _ip.user_ns)
291 _ip.magic('reset -f array')
293 _ip.magic('reset -f array')
292 nt.assert_not_in('a', _ip.user_ns)
294 nt.assert_not_in('a', _ip.user_ns)
293
295
294 def test_reset_out():
296 def test_reset_out():
295 "Test '%reset out' magic"
297 "Test '%reset out' magic"
296 _ip.run_cell("parrot = 'dead'", store_history=True)
298 _ip.run_cell("parrot = 'dead'", store_history=True)
297 # test '%reset -f out', make an Out prompt
299 # test '%reset -f out', make an Out prompt
298 _ip.run_cell("parrot", store_history=True)
300 _ip.run_cell("parrot", store_history=True)
299 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
301 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
300 _ip.magic('reset -f out')
302 _ip.magic('reset -f out')
301 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
303 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
302 nt.assert_equal(len(_ip.user_ns['Out']), 0)
304 nt.assert_equal(len(_ip.user_ns['Out']), 0)
303
305
304 def test_reset_in():
306 def test_reset_in():
305 "Test '%reset in' magic"
307 "Test '%reset in' magic"
306 # test '%reset -f in'
308 # test '%reset -f in'
307 _ip.run_cell("parrot", store_history=True)
309 _ip.run_cell("parrot", store_history=True)
308 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
310 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
309 _ip.magic('%reset -f in')
311 _ip.magic('%reset -f in')
310 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
312 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
311 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
313 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
312
314
313 def test_reset_dhist():
315 def test_reset_dhist():
314 "Test '%reset dhist' magic"
316 "Test '%reset dhist' magic"
315 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
317 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
316 _ip.magic('cd ' + os.path.dirname(nt.__file__))
318 _ip.magic('cd ' + os.path.dirname(nt.__file__))
317 _ip.magic('cd -')
319 _ip.magic('cd -')
318 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
320 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
319 _ip.magic('reset -f dhist')
321 _ip.magic('reset -f dhist')
320 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
322 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
321 _ip.run_cell("_dh = [d for d in tmp]") #restore
323 _ip.run_cell("_dh = [d for d in tmp]") #restore
322
324
323 def test_reset_in_length():
325 def test_reset_in_length():
324 "Test that '%reset in' preserves In[] length"
326 "Test that '%reset in' preserves In[] length"
325 _ip.run_cell("print 'foo'")
327 _ip.run_cell("print 'foo'")
326 _ip.run_cell("reset -f in")
328 _ip.run_cell("reset -f in")
327 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
329 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
328
330
329 def test_tb_syntaxerror():
331 def test_tb_syntaxerror():
330 """test %tb after a SyntaxError"""
332 """test %tb after a SyntaxError"""
331 ip = get_ipython()
333 ip = get_ipython()
332 ip.run_cell("for")
334 ip.run_cell("for")
333
335
334 # trap and validate stdout
336 # trap and validate stdout
335 save_stdout = sys.stdout
337 save_stdout = sys.stdout
336 try:
338 try:
337 sys.stdout = StringIO()
339 sys.stdout = StringIO()
338 ip.run_cell("%tb")
340 ip.run_cell("%tb")
339 out = sys.stdout.getvalue()
341 out = sys.stdout.getvalue()
340 finally:
342 finally:
341 sys.stdout = save_stdout
343 sys.stdout = save_stdout
342 # trim output, and only check the last line
344 # trim output, and only check the last line
343 last_line = out.rstrip().splitlines()[-1].strip()
345 last_line = out.rstrip().splitlines()[-1].strip()
344 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
346 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
345
347
346
348
347 def test_time():
349 def test_time():
348 ip = get_ipython()
350 ip = get_ipython()
349
351
350 with tt.AssertPrints("Wall time: "):
352 with tt.AssertPrints("Wall time: "):
351 ip.run_cell("%time None")
353 ip.run_cell("%time None")
352
354
353 ip.run_cell("def f(kmjy):\n"
355 ip.run_cell("def f(kmjy):\n"
354 " %time print (2*kmjy)")
356 " %time print (2*kmjy)")
355
357
356 with tt.AssertPrints("Wall time: "):
358 with tt.AssertPrints("Wall time: "):
357 with tt.AssertPrints("hihi", suppress=False):
359 with tt.AssertPrints("hihi", suppress=False):
358 ip.run_cell("f('hi')")
360 ip.run_cell("f('hi')")
359
361
360
362
361 @dec.skip_win32
363 @dec.skip_win32
362 def test_time2():
364 def test_time2():
363 ip = get_ipython()
365 ip = get_ipython()
364
366
365 with tt.AssertPrints("CPU times: user "):
367 with tt.AssertPrints("CPU times: user "):
366 ip.run_cell("%time None")
368 ip.run_cell("%time None")
367
369
368 def test_time3():
370 def test_time3():
369 """Erroneous magic function calls, issue gh-3334"""
371 """Erroneous magic function calls, issue gh-3334"""
370 ip = get_ipython()
372 ip = get_ipython()
371 ip.user_ns.pop('run', None)
373 ip.user_ns.pop('run', None)
372
374
373 with tt.AssertNotPrints("not found", channel='stderr'):
375 with tt.AssertNotPrints("not found", channel='stderr'):
374 ip.run_cell("%%time\n"
376 ip.run_cell("%%time\n"
375 "run = 0\n"
377 "run = 0\n"
376 "run += 1")
378 "run += 1")
377
379
378 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
380 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
379 def test_time_futures():
381 def test_time_futures():
380 "Test %time with __future__ environments"
382 "Test %time with __future__ environments"
381 ip = get_ipython()
383 ip = get_ipython()
382 ip.autocall = 0
384 ip.autocall = 0
383 ip.run_cell("from __future__ import division")
385 ip.run_cell("from __future__ import division")
384 with tt.AssertPrints('0.25'):
386 with tt.AssertPrints('0.25'):
385 ip.run_line_magic('time', 'print(1/4)')
387 ip.run_line_magic('time', 'print(1/4)')
386 ip.compile.reset_compiler_flags()
388 ip.compile.reset_compiler_flags()
387 with tt.AssertNotPrints('0.25'):
389 with tt.AssertNotPrints('0.25'):
388 ip.run_line_magic('time', 'print(1/4)')
390 ip.run_line_magic('time', 'print(1/4)')
389
391
390 def test_doctest_mode():
392 def test_doctest_mode():
391 "Toggle doctest_mode twice, it should be a no-op and run without error"
393 "Toggle doctest_mode twice, it should be a no-op and run without error"
392 _ip.magic('doctest_mode')
394 _ip.magic('doctest_mode')
393 _ip.magic('doctest_mode')
395 _ip.magic('doctest_mode')
394
396
395
397
396 def test_parse_options():
398 def test_parse_options():
397 """Tests for basic options parsing in magics."""
399 """Tests for basic options parsing in magics."""
398 # These are only the most minimal of tests, more should be added later. At
400 # These are only the most minimal of tests, more should be added later. At
399 # the very least we check that basic text/unicode calls work OK.
401 # the very least we check that basic text/unicode calls work OK.
400 m = DummyMagics(_ip)
402 m = DummyMagics(_ip)
401 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
403 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
402 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
404 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
403
405
404
406
405 def test_dirops():
407 def test_dirops():
406 """Test various directory handling operations."""
408 """Test various directory handling operations."""
407 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
409 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
408 curpath = py3compat.getcwd
410 curpath = py3compat.getcwd
409 startdir = py3compat.getcwd()
411 startdir = py3compat.getcwd()
410 ipdir = os.path.realpath(_ip.ipython_dir)
412 ipdir = os.path.realpath(_ip.ipython_dir)
411 try:
413 try:
412 _ip.magic('cd "%s"' % ipdir)
414 _ip.magic('cd "%s"' % ipdir)
413 nt.assert_equal(curpath(), ipdir)
415 nt.assert_equal(curpath(), ipdir)
414 _ip.magic('cd -')
416 _ip.magic('cd -')
415 nt.assert_equal(curpath(), startdir)
417 nt.assert_equal(curpath(), startdir)
416 _ip.magic('pushd "%s"' % ipdir)
418 _ip.magic('pushd "%s"' % ipdir)
417 nt.assert_equal(curpath(), ipdir)
419 nt.assert_equal(curpath(), ipdir)
418 _ip.magic('popd')
420 _ip.magic('popd')
419 nt.assert_equal(curpath(), startdir)
421 nt.assert_equal(curpath(), startdir)
420 finally:
422 finally:
421 os.chdir(startdir)
423 os.chdir(startdir)
422
424
423
425
424 def test_xmode():
426 def test_xmode():
425 # Calling xmode three times should be a no-op
427 # Calling xmode three times should be a no-op
426 xmode = _ip.InteractiveTB.mode
428 xmode = _ip.InteractiveTB.mode
427 for i in range(3):
429 for i in range(3):
428 _ip.magic("xmode")
430 _ip.magic("xmode")
429 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
431 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
430
432
431 def test_reset_hard():
433 def test_reset_hard():
432 monitor = []
434 monitor = []
433 class A(object):
435 class A(object):
434 def __del__(self):
436 def __del__(self):
435 monitor.append(1)
437 monitor.append(1)
436 def __repr__(self):
438 def __repr__(self):
437 return "<A instance>"
439 return "<A instance>"
438
440
439 _ip.user_ns["a"] = A()
441 _ip.user_ns["a"] = A()
440 _ip.run_cell("a")
442 _ip.run_cell("a")
441
443
442 nt.assert_equal(monitor, [])
444 nt.assert_equal(monitor, [])
443 _ip.magic("reset -f")
445 _ip.magic("reset -f")
444 nt.assert_equal(monitor, [1])
446 nt.assert_equal(monitor, [1])
445
447
446 class TestXdel(tt.TempFileMixin):
448 class TestXdel(tt.TempFileMixin):
447 def test_xdel(self):
449 def test_xdel(self):
448 """Test that references from %run are cleared by xdel."""
450 """Test that references from %run are cleared by xdel."""
449 src = ("class A(object):\n"
451 src = ("class A(object):\n"
450 " monitor = []\n"
452 " monitor = []\n"
451 " def __del__(self):\n"
453 " def __del__(self):\n"
452 " self.monitor.append(1)\n"
454 " self.monitor.append(1)\n"
453 "a = A()\n")
455 "a = A()\n")
454 self.mktmp(src)
456 self.mktmp(src)
455 # %run creates some hidden references...
457 # %run creates some hidden references...
456 _ip.magic("run %s" % self.fname)
458 _ip.magic("run %s" % self.fname)
457 # ... as does the displayhook.
459 # ... as does the displayhook.
458 _ip.run_cell("a")
460 _ip.run_cell("a")
459
461
460 monitor = _ip.user_ns["A"].monitor
462 monitor = _ip.user_ns["A"].monitor
461 nt.assert_equal(monitor, [])
463 nt.assert_equal(monitor, [])
462
464
463 _ip.magic("xdel a")
465 _ip.magic("xdel a")
464
466
465 # Check that a's __del__ method has been called.
467 # Check that a's __del__ method has been called.
466 nt.assert_equal(monitor, [1])
468 nt.assert_equal(monitor, [1])
467
469
468 def doctest_who():
470 def doctest_who():
469 """doctest for %who
471 """doctest for %who
470
472
471 In [1]: %reset -f
473 In [1]: %reset -f
472
474
473 In [2]: alpha = 123
475 In [2]: alpha = 123
474
476
475 In [3]: beta = 'beta'
477 In [3]: beta = 'beta'
476
478
477 In [4]: %who int
479 In [4]: %who int
478 alpha
480 alpha
479
481
480 In [5]: %who str
482 In [5]: %who str
481 beta
483 beta
482
484
483 In [6]: %whos
485 In [6]: %whos
484 Variable Type Data/Info
486 Variable Type Data/Info
485 ----------------------------
487 ----------------------------
486 alpha int 123
488 alpha int 123
487 beta str beta
489 beta str beta
488
490
489 In [7]: %who_ls
491 In [7]: %who_ls
490 Out[7]: ['alpha', 'beta']
492 Out[7]: ['alpha', 'beta']
491 """
493 """
492
494
493 def test_whos():
495 def test_whos():
494 """Check that whos is protected against objects where repr() fails."""
496 """Check that whos is protected against objects where repr() fails."""
495 class A(object):
497 class A(object):
496 def __repr__(self):
498 def __repr__(self):
497 raise Exception()
499 raise Exception()
498 _ip.user_ns['a'] = A()
500 _ip.user_ns['a'] = A()
499 _ip.magic("whos")
501 _ip.magic("whos")
500
502
501 @py3compat.u_format
503 @py3compat.u_format
502 def doctest_precision():
504 def doctest_precision():
503 """doctest for %precision
505 """doctest for %precision
504
506
505 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
507 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
506
508
507 In [2]: %precision 5
509 In [2]: %precision 5
508 Out[2]: {u}'%.5f'
510 Out[2]: {u}'%.5f'
509
511
510 In [3]: f.float_format
512 In [3]: f.float_format
511 Out[3]: {u}'%.5f'
513 Out[3]: {u}'%.5f'
512
514
513 In [4]: %precision %e
515 In [4]: %precision %e
514 Out[4]: {u}'%e'
516 Out[4]: {u}'%e'
515
517
516 In [5]: f(3.1415927)
518 In [5]: f(3.1415927)
517 Out[5]: {u}'3.141593e+00'
519 Out[5]: {u}'3.141593e+00'
518 """
520 """
519
521
520 def test_psearch():
522 def test_psearch():
521 with tt.AssertPrints("dict.fromkeys"):
523 with tt.AssertPrints("dict.fromkeys"):
522 _ip.run_cell("dict.fr*?")
524 _ip.run_cell("dict.fr*?")
523
525
524 def test_timeit_shlex():
526 def test_timeit_shlex():
525 """test shlex issues with timeit (#1109)"""
527 """test shlex issues with timeit (#1109)"""
526 _ip.ex("def f(*a,**kw): pass")
528 _ip.ex("def f(*a,**kw): pass")
527 _ip.magic('timeit -n1 "this is a bug".count(" ")')
529 _ip.magic('timeit -n1 "this is a bug".count(" ")')
528 _ip.magic('timeit -r1 -n1 f(" ", 1)')
530 _ip.magic('timeit -r1 -n1 f(" ", 1)')
529 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
531 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
530 _ip.magic('timeit -r1 -n1 ("a " + "b")')
532 _ip.magic('timeit -r1 -n1 ("a " + "b")')
531 _ip.magic('timeit -r1 -n1 f("a " + "b")')
533 _ip.magic('timeit -r1 -n1 f("a " + "b")')
532 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
534 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
533
535
534
536
535 def test_timeit_arguments():
537 def test_timeit_arguments():
536 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
538 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
537 _ip.magic("timeit ('#')")
539 _ip.magic("timeit ('#')")
538
540
539
541
540 def test_timeit_special_syntax():
542 def test_timeit_special_syntax():
541 "Test %%timeit with IPython special syntax"
543 "Test %%timeit with IPython special syntax"
542 @register_line_magic
544 @register_line_magic
543 def lmagic(line):
545 def lmagic(line):
544 ip = get_ipython()
546 ip = get_ipython()
545 ip.user_ns['lmagic_out'] = line
547 ip.user_ns['lmagic_out'] = line
546
548
547 # line mode test
549 # line mode test
548 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
550 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
549 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
551 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
550 # cell mode test
552 # cell mode test
551 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
553 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
552 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
554 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
553
555
554 def test_timeit_return():
556 def test_timeit_return():
555 """
557 """
556 test wether timeit -o return object
558 test wether timeit -o return object
557 """
559 """
558
560
559 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
561 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
560 assert(res is not None)
562 assert(res is not None)
561
563
562 def test_timeit_quiet():
564 def test_timeit_quiet():
563 """
565 """
564 test quiet option of timeit magic
566 test quiet option of timeit magic
565 """
567 """
566 with tt.AssertNotPrints("loops"):
568 with tt.AssertNotPrints("loops"):
567 _ip.run_cell("%timeit -n1 -r1 -q 1")
569 _ip.run_cell("%timeit -n1 -r1 -q 1")
568
570
569 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
571 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
570 def test_timeit_futures():
572 def test_timeit_futures():
571 "Test %timeit with __future__ environments"
573 "Test %timeit with __future__ environments"
572 ip = get_ipython()
574 ip = get_ipython()
573 ip.run_cell("from __future__ import division")
575 ip.run_cell("from __future__ import division")
574 with tt.AssertPrints('0.25'):
576 with tt.AssertPrints('0.25'):
575 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
577 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
576 ip.compile.reset_compiler_flags()
578 ip.compile.reset_compiler_flags()
577 with tt.AssertNotPrints('0.25'):
579 with tt.AssertNotPrints('0.25'):
578 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
580 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
579
581
580 @dec.skipif(execution.profile is None)
582 @dec.skipif(execution.profile is None)
581 def test_prun_special_syntax():
583 def test_prun_special_syntax():
582 "Test %%prun with IPython special syntax"
584 "Test %%prun with IPython special syntax"
583 @register_line_magic
585 @register_line_magic
584 def lmagic(line):
586 def lmagic(line):
585 ip = get_ipython()
587 ip = get_ipython()
586 ip.user_ns['lmagic_out'] = line
588 ip.user_ns['lmagic_out'] = line
587
589
588 # line mode test
590 # line mode test
589 _ip.run_line_magic('prun', '-q %lmagic my line')
591 _ip.run_line_magic('prun', '-q %lmagic my line')
590 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
592 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
591 # cell mode test
593 # cell mode test
592 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
594 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
593 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
595 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
594
596
595 @dec.skipif(execution.profile is None)
597 @dec.skipif(execution.profile is None)
596 def test_prun_quotes():
598 def test_prun_quotes():
597 "Test that prun does not clobber string escapes (GH #1302)"
599 "Test that prun does not clobber string escapes (GH #1302)"
598 _ip.magic(r"prun -q x = '\t'")
600 _ip.magic(r"prun -q x = '\t'")
599 nt.assert_equal(_ip.user_ns['x'], '\t')
601 nt.assert_equal(_ip.user_ns['x'], '\t')
600
602
601 def test_extension():
603 def test_extension():
602 tmpdir = TemporaryDirectory()
604 tmpdir = TemporaryDirectory()
603 orig_ipython_dir = _ip.ipython_dir
605 orig_ipython_dir = _ip.ipython_dir
604 try:
606 try:
605 _ip.ipython_dir = tmpdir.name
607 _ip.ipython_dir = tmpdir.name
606 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
608 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
607 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
609 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
608 _ip.magic("install_ext %s" % url)
610 _ip.magic("install_ext %s" % url)
609 _ip.user_ns.pop('arq', None)
611 _ip.user_ns.pop('arq', None)
610 invalidate_caches() # Clear import caches
612 invalidate_caches() # Clear import caches
611 _ip.magic("load_ext daft_extension")
613 _ip.magic("load_ext daft_extension")
612 nt.assert_equal(_ip.user_ns['arq'], 185)
614 nt.assert_equal(_ip.user_ns['arq'], 185)
613 _ip.magic("unload_ext daft_extension")
615 _ip.magic("unload_ext daft_extension")
614 assert 'arq' not in _ip.user_ns
616 assert 'arq' not in _ip.user_ns
615 finally:
617 finally:
616 _ip.ipython_dir = orig_ipython_dir
618 _ip.ipython_dir = orig_ipython_dir
617 tmpdir.cleanup()
619 tmpdir.cleanup()
618
620
619
621
620 # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf
622 # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf
621 @skipIf(dec.module_not_available('IPython.nbformat'), 'nbformat not importable')
623 @skipIf(dec.module_not_available('IPython.nbformat'), 'nbformat not importable')
622 class NotebookExportMagicTests(TestCase):
624 class NotebookExportMagicTests(TestCase):
623 def test_notebook_export_json(self):
625 def test_notebook_export_json(self):
624 with TemporaryDirectory() as td:
626 with TemporaryDirectory() as td:
625 outfile = os.path.join(td, "nb.ipynb")
627 outfile = os.path.join(td, "nb.ipynb")
626 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
628 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
627 _ip.magic("notebook -e %s" % outfile)
629 _ip.magic("notebook -e %s" % outfile)
628
630
629
631
630 class TestEnv(TestCase):
632 class TestEnv(TestCase):
631
633
632 def test_env(self):
634 def test_env(self):
633 env = _ip.magic("env")
635 env = _ip.magic("env")
634 self.assertTrue(isinstance(env, dict))
636 self.assertTrue(isinstance(env, dict))
635
637
636 def test_env_get_set_simple(self):
638 def test_env_get_set_simple(self):
637 env = _ip.magic("env var val1")
639 env = _ip.magic("env var val1")
638 self.assertEqual(env, None)
640 self.assertEqual(env, None)
639 self.assertEqual(os.environ['var'], 'val1')
641 self.assertEqual(os.environ['var'], 'val1')
640 self.assertEqual(_ip.magic("env var"), 'val1')
642 self.assertEqual(_ip.magic("env var"), 'val1')
641 env = _ip.magic("env var=val2")
643 env = _ip.magic("env var=val2")
642 self.assertEqual(env, None)
644 self.assertEqual(env, None)
643 self.assertEqual(os.environ['var'], 'val2')
645 self.assertEqual(os.environ['var'], 'val2')
644
646
645 def test_env_get_set_complex(self):
647 def test_env_get_set_complex(self):
646 env = _ip.magic("env var 'val1 '' 'val2")
648 env = _ip.magic("env var 'val1 '' 'val2")
647 self.assertEqual(env, None)
649 self.assertEqual(env, None)
648 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
650 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
649 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
651 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
650 env = _ip.magic('env var=val2 val3="val4')
652 env = _ip.magic('env var=val2 val3="val4')
651 self.assertEqual(env, None)
653 self.assertEqual(env, None)
652 self.assertEqual(os.environ['var'], 'val2 val3="val4')
654 self.assertEqual(os.environ['var'], 'val2 val3="val4')
653
655
654 def test_env_set_bad_input(self):
656 def test_env_set_bad_input(self):
655 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
657 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
656
658
657 def test_env_set_whitespace(self):
659 def test_env_set_whitespace(self):
658 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
660 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
659
661
660
662
661 class CellMagicTestCase(TestCase):
663 class CellMagicTestCase(TestCase):
662
664
663 def check_ident(self, magic):
665 def check_ident(self, magic):
664 # Manually called, we get the result
666 # Manually called, we get the result
665 out = _ip.run_cell_magic(magic, 'a', 'b')
667 out = _ip.run_cell_magic(magic, 'a', 'b')
666 nt.assert_equal(out, ('a','b'))
668 nt.assert_equal(out, ('a','b'))
667 # Via run_cell, it goes into the user's namespace via displayhook
669 # Via run_cell, it goes into the user's namespace via displayhook
668 _ip.run_cell('%%' + magic +' c\nd')
670 _ip.run_cell('%%' + magic +' c\nd')
669 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
671 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
670
672
671 def test_cell_magic_func_deco(self):
673 def test_cell_magic_func_deco(self):
672 "Cell magic using simple decorator"
674 "Cell magic using simple decorator"
673 @register_cell_magic
675 @register_cell_magic
674 def cellm(line, cell):
676 def cellm(line, cell):
675 return line, cell
677 return line, cell
676
678
677 self.check_ident('cellm')
679 self.check_ident('cellm')
678
680
679 def test_cell_magic_reg(self):
681 def test_cell_magic_reg(self):
680 "Cell magic manually registered"
682 "Cell magic manually registered"
681 def cellm(line, cell):
683 def cellm(line, cell):
682 return line, cell
684 return line, cell
683
685
684 _ip.register_magic_function(cellm, 'cell', 'cellm2')
686 _ip.register_magic_function(cellm, 'cell', 'cellm2')
685 self.check_ident('cellm2')
687 self.check_ident('cellm2')
686
688
687 def test_cell_magic_class(self):
689 def test_cell_magic_class(self):
688 "Cell magics declared via a class"
690 "Cell magics declared via a class"
689 @magics_class
691 @magics_class
690 class MyMagics(Magics):
692 class MyMagics(Magics):
691
693
692 @cell_magic
694 @cell_magic
693 def cellm3(self, line, cell):
695 def cellm3(self, line, cell):
694 return line, cell
696 return line, cell
695
697
696 _ip.register_magics(MyMagics)
698 _ip.register_magics(MyMagics)
697 self.check_ident('cellm3')
699 self.check_ident('cellm3')
698
700
699 def test_cell_magic_class2(self):
701 def test_cell_magic_class2(self):
700 "Cell magics declared via a class, #2"
702 "Cell magics declared via a class, #2"
701 @magics_class
703 @magics_class
702 class MyMagics2(Magics):
704 class MyMagics2(Magics):
703
705
704 @cell_magic('cellm4')
706 @cell_magic('cellm4')
705 def cellm33(self, line, cell):
707 def cellm33(self, line, cell):
706 return line, cell
708 return line, cell
707
709
708 _ip.register_magics(MyMagics2)
710 _ip.register_magics(MyMagics2)
709 self.check_ident('cellm4')
711 self.check_ident('cellm4')
710 # Check that nothing is registered as 'cellm33'
712 # Check that nothing is registered as 'cellm33'
711 c33 = _ip.find_cell_magic('cellm33')
713 c33 = _ip.find_cell_magic('cellm33')
712 nt.assert_equal(c33, None)
714 nt.assert_equal(c33, None)
713
715
714 def test_file():
716 def test_file():
715 """Basic %%file"""
717 """Basic %%file"""
716 ip = get_ipython()
718 ip = get_ipython()
717 with TemporaryDirectory() as td:
719 with TemporaryDirectory() as td:
718 fname = os.path.join(td, 'file1')
720 fname = os.path.join(td, 'file1')
719 ip.run_cell_magic("file", fname, u'\n'.join([
721 ip.run_cell_magic("file", fname, u'\n'.join([
720 'line1',
722 'line1',
721 'line2',
723 'line2',
722 ]))
724 ]))
723 with open(fname) as f:
725 with open(fname) as f:
724 s = f.read()
726 s = f.read()
725 nt.assert_in('line1\n', s)
727 nt.assert_in('line1\n', s)
726 nt.assert_in('line2', s)
728 nt.assert_in('line2', s)
727
729
728 def test_file_var_expand():
730 def test_file_var_expand():
729 """%%file $filename"""
731 """%%file $filename"""
730 ip = get_ipython()
732 ip = get_ipython()
731 with TemporaryDirectory() as td:
733 with TemporaryDirectory() as td:
732 fname = os.path.join(td, 'file1')
734 fname = os.path.join(td, 'file1')
733 ip.user_ns['filename'] = fname
735 ip.user_ns['filename'] = fname
734 ip.run_cell_magic("file", '$filename', u'\n'.join([
736 ip.run_cell_magic("file", '$filename', u'\n'.join([
735 'line1',
737 'line1',
736 'line2',
738 'line2',
737 ]))
739 ]))
738 with open(fname) as f:
740 with open(fname) as f:
739 s = f.read()
741 s = f.read()
740 nt.assert_in('line1\n', s)
742 nt.assert_in('line1\n', s)
741 nt.assert_in('line2', s)
743 nt.assert_in('line2', s)
742
744
743 def test_file_unicode():
745 def test_file_unicode():
744 """%%file with unicode cell"""
746 """%%file with unicode cell"""
745 ip = get_ipython()
747 ip = get_ipython()
746 with TemporaryDirectory() as td:
748 with TemporaryDirectory() as td:
747 fname = os.path.join(td, 'file1')
749 fname = os.path.join(td, 'file1')
748 ip.run_cell_magic("file", fname, u'\n'.join([
750 ip.run_cell_magic("file", fname, u'\n'.join([
749 u'linΓ©1',
751 u'linΓ©1',
750 u'linΓ©2',
752 u'linΓ©2',
751 ]))
753 ]))
752 with io.open(fname, encoding='utf-8') as f:
754 with io.open(fname, encoding='utf-8') as f:
753 s = f.read()
755 s = f.read()
754 nt.assert_in(u'linΓ©1\n', s)
756 nt.assert_in(u'linΓ©1\n', s)
755 nt.assert_in(u'linΓ©2', s)
757 nt.assert_in(u'linΓ©2', s)
756
758
757 def test_file_amend():
759 def test_file_amend():
758 """%%file -a amends files"""
760 """%%file -a amends files"""
759 ip = get_ipython()
761 ip = get_ipython()
760 with TemporaryDirectory() as td:
762 with TemporaryDirectory() as td:
761 fname = os.path.join(td, 'file2')
763 fname = os.path.join(td, 'file2')
762 ip.run_cell_magic("file", fname, u'\n'.join([
764 ip.run_cell_magic("file", fname, u'\n'.join([
763 'line1',
765 'line1',
764 'line2',
766 'line2',
765 ]))
767 ]))
766 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
768 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
767 'line3',
769 'line3',
768 'line4',
770 'line4',
769 ]))
771 ]))
770 with open(fname) as f:
772 with open(fname) as f:
771 s = f.read()
773 s = f.read()
772 nt.assert_in('line1\n', s)
774 nt.assert_in('line1\n', s)
773 nt.assert_in('line3\n', s)
775 nt.assert_in('line3\n', s)
774
776
775
777
776 def test_script_config():
778 def test_script_config():
777 ip = get_ipython()
779 ip = get_ipython()
778 ip.config.ScriptMagics.script_magics = ['whoda']
780 ip.config.ScriptMagics.script_magics = ['whoda']
779 sm = script.ScriptMagics(shell=ip)
781 sm = script.ScriptMagics(shell=ip)
780 nt.assert_in('whoda', sm.magics['cell'])
782 nt.assert_in('whoda', sm.magics['cell'])
781
783
782 @dec.skip_win32
784 @dec.skip_win32
783 def test_script_out():
785 def test_script_out():
784 ip = get_ipython()
786 ip = get_ipython()
785 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
787 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
786 nt.assert_equal(ip.user_ns['output'], 'hi\n')
788 nt.assert_equal(ip.user_ns['output'], 'hi\n')
787
789
788 @dec.skip_win32
790 @dec.skip_win32
789 def test_script_err():
791 def test_script_err():
790 ip = get_ipython()
792 ip = get_ipython()
791 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
793 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
792 nt.assert_equal(ip.user_ns['error'], 'hello\n')
794 nt.assert_equal(ip.user_ns['error'], 'hello\n')
793
795
794 @dec.skip_win32
796 @dec.skip_win32
795 def test_script_out_err():
797 def test_script_out_err():
796 ip = get_ipython()
798 ip = get_ipython()
797 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
799 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
798 nt.assert_equal(ip.user_ns['output'], 'hi\n')
800 nt.assert_equal(ip.user_ns['output'], 'hi\n')
799 nt.assert_equal(ip.user_ns['error'], 'hello\n')
801 nt.assert_equal(ip.user_ns['error'], 'hello\n')
800
802
801 @dec.skip_win32
803 @dec.skip_win32
802 def test_script_bg_out():
804 def test_script_bg_out():
803 ip = get_ipython()
805 ip = get_ipython()
804 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
806 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
805 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
807 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
806
808
807 @dec.skip_win32
809 @dec.skip_win32
808 def test_script_bg_err():
810 def test_script_bg_err():
809 ip = get_ipython()
811 ip = get_ipython()
810 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
812 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
811 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
813 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
812
814
813 @dec.skip_win32
815 @dec.skip_win32
814 def test_script_bg_out_err():
816 def test_script_bg_out_err():
815 ip = get_ipython()
817 ip = get_ipython()
816 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
818 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
817 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
819 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
818 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
820 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
819
821
820 def test_script_defaults():
822 def test_script_defaults():
821 ip = get_ipython()
823 ip = get_ipython()
822 for cmd in ['sh', 'bash', 'perl', 'ruby']:
824 for cmd in ['sh', 'bash', 'perl', 'ruby']:
823 try:
825 try:
824 find_cmd(cmd)
826 find_cmd(cmd)
825 except Exception:
827 except Exception:
826 pass
828 pass
827 else:
829 else:
828 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
830 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
829
831
830
832
831 @magics_class
833 @magics_class
832 class FooFoo(Magics):
834 class FooFoo(Magics):
833 """class with both %foo and %%foo magics"""
835 """class with both %foo and %%foo magics"""
834 @line_magic('foo')
836 @line_magic('foo')
835 def line_foo(self, line):
837 def line_foo(self, line):
836 "I am line foo"
838 "I am line foo"
837 pass
839 pass
838
840
839 @cell_magic("foo")
841 @cell_magic("foo")
840 def cell_foo(self, line, cell):
842 def cell_foo(self, line, cell):
841 "I am cell foo, not line foo"
843 "I am cell foo, not line foo"
842 pass
844 pass
843
845
844 def test_line_cell_info():
846 def test_line_cell_info():
845 """%%foo and %foo magics are distinguishable to inspect"""
847 """%%foo and %foo magics are distinguishable to inspect"""
846 ip = get_ipython()
848 ip = get_ipython()
847 ip.magics_manager.register(FooFoo)
849 ip.magics_manager.register(FooFoo)
848 oinfo = ip.object_inspect('foo')
850 oinfo = ip.object_inspect('foo')
849 nt.assert_true(oinfo['found'])
851 nt.assert_true(oinfo['found'])
850 nt.assert_true(oinfo['ismagic'])
852 nt.assert_true(oinfo['ismagic'])
851
853
852 oinfo = ip.object_inspect('%%foo')
854 oinfo = ip.object_inspect('%%foo')
853 nt.assert_true(oinfo['found'])
855 nt.assert_true(oinfo['found'])
854 nt.assert_true(oinfo['ismagic'])
856 nt.assert_true(oinfo['ismagic'])
855 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
857 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
856
858
857 oinfo = ip.object_inspect('%foo')
859 oinfo = ip.object_inspect('%foo')
858 nt.assert_true(oinfo['found'])
860 nt.assert_true(oinfo['found'])
859 nt.assert_true(oinfo['ismagic'])
861 nt.assert_true(oinfo['ismagic'])
860 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
862 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
861
863
862 def test_multiple_magics():
864 def test_multiple_magics():
863 ip = get_ipython()
865 ip = get_ipython()
864 foo1 = FooFoo(ip)
866 foo1 = FooFoo(ip)
865 foo2 = FooFoo(ip)
867 foo2 = FooFoo(ip)
866 mm = ip.magics_manager
868 mm = ip.magics_manager
867 mm.register(foo1)
869 mm.register(foo1)
868 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
870 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
869 mm.register(foo2)
871 mm.register(foo2)
870 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
872 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
871
873
872 def test_alias_magic():
874 def test_alias_magic():
873 """Test %alias_magic."""
875 """Test %alias_magic."""
874 ip = get_ipython()
876 ip = get_ipython()
875 mm = ip.magics_manager
877 mm = ip.magics_manager
876
878
877 # Basic operation: both cell and line magics are created, if possible.
879 # Basic operation: both cell and line magics are created, if possible.
878 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
880 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
879 nt.assert_in('timeit_alias', mm.magics['line'])
881 nt.assert_in('timeit_alias', mm.magics['line'])
880 nt.assert_in('timeit_alias', mm.magics['cell'])
882 nt.assert_in('timeit_alias', mm.magics['cell'])
881
883
882 # --cell is specified, line magic not created.
884 # --cell is specified, line magic not created.
883 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
885 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
884 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
886 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
885 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
887 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
886
888
887 # Test that line alias is created successfully.
889 # Test that line alias is created successfully.
888 ip.run_line_magic('alias_magic', '--line env_alias env')
890 ip.run_line_magic('alias_magic', '--line env_alias env')
889 nt.assert_equal(ip.run_line_magic('env', ''),
891 nt.assert_equal(ip.run_line_magic('env', ''),
890 ip.run_line_magic('env_alias', ''))
892 ip.run_line_magic('env_alias', ''))
891
893
892 def test_save():
894 def test_save():
893 """Test %save."""
895 """Test %save."""
894 ip = get_ipython()
896 ip = get_ipython()
895 ip.history_manager.reset() # Clear any existing history.
897 ip.history_manager.reset() # Clear any existing history.
896 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
898 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
897 for i, cmd in enumerate(cmds, start=1):
899 for i, cmd in enumerate(cmds, start=1):
898 ip.history_manager.store_inputs(i, cmd)
900 ip.history_manager.store_inputs(i, cmd)
899 with TemporaryDirectory() as tmpdir:
901 with TemporaryDirectory() as tmpdir:
900 file = os.path.join(tmpdir, "testsave.py")
902 file = os.path.join(tmpdir, "testsave.py")
901 ip.run_line_magic("save", "%s 1-10" % file)
903 ip.run_line_magic("save", "%s 1-10" % file)
902 with open(file) as f:
904 with open(file) as f:
903 content = f.read()
905 content = f.read()
904 nt.assert_equal(content.count(cmds[0]), 1)
906 nt.assert_equal(content.count(cmds[0]), 1)
905 nt.assert_in('coding: utf-8', content)
907 nt.assert_in('coding: utf-8', content)
906 ip.run_line_magic("save", "-a %s 1-10" % file)
908 ip.run_line_magic("save", "-a %s 1-10" % file)
907 with open(file) as f:
909 with open(file) as f:
908 content = f.read()
910 content = f.read()
909 nt.assert_equal(content.count(cmds[0]), 2)
911 nt.assert_equal(content.count(cmds[0]), 2)
910 nt.assert_in('coding: utf-8', content)
912 nt.assert_in('coding: utf-8', content)
911
913
912
914
913 def test_store():
915 def test_store():
914 """Test %store."""
916 """Test %store."""
915 ip = get_ipython()
917 ip = get_ipython()
916 ip.run_line_magic('load_ext', 'storemagic')
918 ip.run_line_magic('load_ext', 'storemagic')
917
919
918 # make sure the storage is empty
920 # make sure the storage is empty
919 ip.run_line_magic('store', '-z')
921 ip.run_line_magic('store', '-z')
920 ip.user_ns['var'] = 42
922 ip.user_ns['var'] = 42
921 ip.run_line_magic('store', 'var')
923 ip.run_line_magic('store', 'var')
922 ip.user_ns['var'] = 39
924 ip.user_ns['var'] = 39
923 ip.run_line_magic('store', '-r')
925 ip.run_line_magic('store', '-r')
924 nt.assert_equal(ip.user_ns['var'], 42)
926 nt.assert_equal(ip.user_ns['var'], 42)
925
927
926 ip.run_line_magic('store', '-d var')
928 ip.run_line_magic('store', '-d var')
927 ip.user_ns['var'] = 39
929 ip.user_ns['var'] = 39
928 ip.run_line_magic('store' , '-r')
930 ip.run_line_magic('store' , '-r')
929 nt.assert_equal(ip.user_ns['var'], 39)
931 nt.assert_equal(ip.user_ns['var'], 39)
930
932
931
933
932 def _run_edit_test(arg_s, exp_filename=None,
934 def _run_edit_test(arg_s, exp_filename=None,
933 exp_lineno=-1,
935 exp_lineno=-1,
934 exp_contents=None,
936 exp_contents=None,
935 exp_is_temp=None):
937 exp_is_temp=None):
936 ip = get_ipython()
938 ip = get_ipython()
937 M = code.CodeMagics(ip)
939 M = code.CodeMagics(ip)
938 last_call = ['','']
940 last_call = ['','']
939 opts,args = M.parse_options(arg_s,'prxn:')
941 opts,args = M.parse_options(arg_s,'prxn:')
940 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
942 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
941
943
942 if exp_filename is not None:
944 if exp_filename is not None:
943 nt.assert_equal(exp_filename, filename)
945 nt.assert_equal(exp_filename, filename)
944 if exp_contents is not None:
946 if exp_contents is not None:
945 with io.open(filename, 'r', encoding='utf-8') as f:
947 with io.open(filename, 'r', encoding='utf-8') as f:
946 contents = f.read()
948 contents = f.read()
947 nt.assert_equal(exp_contents, contents)
949 nt.assert_equal(exp_contents, contents)
948 if exp_lineno != -1:
950 if exp_lineno != -1:
949 nt.assert_equal(exp_lineno, lineno)
951 nt.assert_equal(exp_lineno, lineno)
950 if exp_is_temp is not None:
952 if exp_is_temp is not None:
951 nt.assert_equal(exp_is_temp, is_temp)
953 nt.assert_equal(exp_is_temp, is_temp)
952
954
953
955
954 def test_edit_interactive():
956 def test_edit_interactive():
955 """%edit on interactively defined objects"""
957 """%edit on interactively defined objects"""
956 ip = get_ipython()
958 ip = get_ipython()
957 n = ip.execution_count
959 n = ip.execution_count
958 ip.run_cell(u"def foo(): return 1", store_history=True)
960 ip.run_cell(u"def foo(): return 1", store_history=True)
959
961
960 try:
962 try:
961 _run_edit_test("foo")
963 _run_edit_test("foo")
962 except code.InteractivelyDefined as e:
964 except code.InteractivelyDefined as e:
963 nt.assert_equal(e.index, n)
965 nt.assert_equal(e.index, n)
964 else:
966 else:
965 raise AssertionError("Should have raised InteractivelyDefined")
967 raise AssertionError("Should have raised InteractivelyDefined")
966
968
967
969
968 def test_edit_cell():
970 def test_edit_cell():
969 """%edit [cell id]"""
971 """%edit [cell id]"""
970 ip = get_ipython()
972 ip = get_ipython()
971
973
972 ip.run_cell(u"def foo(): return 1", store_history=True)
974 ip.run_cell(u"def foo(): return 1", store_history=True)
973
975
974 # test
976 # test
975 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
977 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
976
978
977 def test_bookmark():
979 def test_bookmark():
978 ip = get_ipython()
980 ip = get_ipython()
979 ip.run_line_magic('bookmark', 'bmname')
981 ip.run_line_magic('bookmark', 'bmname')
980 with tt.AssertPrints('bmname'):
982 with tt.AssertPrints('bmname'):
981 ip.run_line_magic('bookmark', '-l')
983 ip.run_line_magic('bookmark', '-l')
982 ip.run_line_magic('bookmark', '-d bmname')
984 ip.run_line_magic('bookmark', '-d bmname')
985
986 def test_ls_magic():
987 ip = get_ipython()
988 json_formatter = ip.display_formatter.formatters['application/json']
989 json_formatter.enabled = True
990 lsmagic = ip.magic('lsmagic')
991 with warnings.catch_warnings(record=True) as w:
992 j = json_formatter(lsmagic)
993 nt.assert_equal(sorted(j), ['cell', 'line'])
994 nt.assert_equal(w, []) # no warnings
General Comments 0
You need to be logged in to leave comments. Login now