##// END OF EJS Templates
Merge pull request #6919 from minrk/self-display...
Thomas Kluyver -
r19392:7b537d1d merge
parent child Browse files
Show More
@@ -164,20 +164,13 b' def display(*objs, **kwargs):'
164 format = InteractiveShell.instance().display_formatter.format
164 format = InteractiveShell.instance().display_formatter.format
165
165
166 for obj in objs:
166 for obj in objs:
167
168 # If _ipython_display_ is defined, use that to display this object.
169 display_method = _safe_get_formatter_method(obj, '_ipython_display_')
170 if display_method is not None:
171 try:
172 display_method(**kwargs)
173 except NotImplementedError:
174 pass
175 else:
176 continue
177 if raw:
167 if raw:
178 publish_display_data(data=obj, metadata=metadata)
168 publish_display_data(data=obj, metadata=metadata)
179 else:
169 else:
180 format_dict, md_dict = format(obj, include=include, exclude=exclude)
170 format_dict, md_dict = format(obj, include=include, exclude=exclude)
171 if not format_dict:
172 # nothing to display (e.g. _ipython_display_ took over)
173 continue
181 if metadata:
174 if metadata:
182 # kwarg-specified metadata gets precedence
175 # kwarg-specified metadata gets precedence
183 _merge(md_dict, metadata)
176 _merge(md_dict, metadata)
@@ -221,19 +221,12 b' class DisplayHook(Configurable):'
221 """
221 """
222 self.check_for_underscore()
222 self.check_for_underscore()
223 if result is not None and not self.quiet():
223 if result is not None and not self.quiet():
224 # If _ipython_display_ is defined, use that to display this object.
225 display_method = _safe_get_formatter_method(result, '_ipython_display_')
226 if display_method is not None:
227 try:
228 return display_method()
229 except NotImplementedError:
230 pass
231
232 self.start_displayhook()
224 self.start_displayhook()
233 self.write_output_prompt()
225 self.write_output_prompt()
234 format_dict, md_dict = self.compute_format_data(result)
226 format_dict, md_dict = self.compute_format_data(result)
235 self.write_format_data(format_dict, md_dict)
236 self.update_user_ns(result)
227 self.update_user_ns(result)
228 if format_dict:
229 self.write_format_data(format_dict, md_dict)
237 self.log_output(format_dict)
230 self.log_output(format_dict)
238 self.finish_displayhook()
231 self.finish_displayhook()
239
232
@@ -14,7 +14,6 b' import abc'
14 import inspect
14 import inspect
15 import sys
15 import sys
16 import traceback
16 import traceback
17 import types
18 import warnings
17 import warnings
19
18
20 from IPython.external.decorator import decorator
19 from IPython.external.decorator import decorator
@@ -24,6 +23,7 b' from IPython.core.getipython import get_ipython'
24 from IPython.lib import pretty
23 from IPython.lib import pretty
25 from IPython.utils.traitlets import (
24 from IPython.utils.traitlets import (
26 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
25 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
26 ForwardDeclaredInstance,
27 )
27 )
28 from IPython.utils.py3compat import (
28 from IPython.utils.py3compat import (
29 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
29 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
@@ -89,6 +89,10 b' class DisplayFormatter(Configurable):'
89 else:
89 else:
90 formatter.enabled = False
90 formatter.enabled = False
91
91
92 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
93 def _ipython_display_formatter_default(self):
94 return IPythonDisplayFormatter(parent=self)
95
92 # A dict of formatter whose keys are format types (MIME types) and whose
96 # A dict of formatter whose keys are format types (MIME types) and whose
93 # values are subclasses of BaseFormatter.
97 # values are subclasses of BaseFormatter.
94 formatters = Dict()
98 formatters = Dict()
@@ -159,6 +163,10 b' class DisplayFormatter(Configurable):'
159 format_dict = {}
163 format_dict = {}
160 md_dict = {}
164 md_dict = {}
161
165
166 if self.ipython_display_formatter(obj):
167 # object handled itself, don't proceed
168 return {}, {}
169
162 for format_type, formatter in self.formatters.items():
170 for format_type, formatter in self.formatters.items():
163 if include and format_type not in include:
171 if include and format_type not in include:
164 continue
172 continue
@@ -831,6 +839,40 b' class PDFFormatter(BaseFormatter):'
831
839
832 _return_type = (bytes, unicode_type)
840 _return_type = (bytes, unicode_type)
833
841
842 class IPythonDisplayFormatter(BaseFormatter):
843 """A Formatter for objects that know how to display themselves.
844
845 To define the callables that compute the representation of your
846 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
848 this. Unlike mime-type displays, this method should not return anything,
849 instead calling any appropriate display methods itself.
850
851 This display formatter has highest priority.
852 If it fires, no other display formatter will be called.
853 """
854 print_method = ObjectName('_ipython_display_')
855 _return_type = (type(None), bool)
856
857
858 @warn_format_error
859 def __call__(self, obj):
860 """Compute the format for an object."""
861 if self.enabled:
862 # lookup registered printer
863 try:
864 printer = self.lookup(obj)
865 except KeyError:
866 pass
867 else:
868 printer(obj)
869 return True
870 # Finally look for special method names
871 method = _safe_get_formatter_method(obj, self.print_method)
872 if method is not None:
873 method()
874 return True
875
834
876
835 FormatterABC.register(BaseFormatter)
877 FormatterABC.register(BaseFormatter)
836 FormatterABC.register(PlainTextFormatter)
878 FormatterABC.register(PlainTextFormatter)
@@ -843,6 +885,7 b' FormatterABC.register(JPEGFormatter)'
843 FormatterABC.register(LatexFormatter)
885 FormatterABC.register(LatexFormatter)
844 FormatterABC.register(JSONFormatter)
886 FormatterABC.register(JSONFormatter)
845 FormatterABC.register(JavascriptFormatter)
887 FormatterABC.register(JavascriptFormatter)
888 FormatterABC.register(IPythonDisplayFormatter)
846
889
847
890
848 def format_display_data(obj, include=None, exclude=None):
891 def format_display_data(obj, include=None, exclude=None):
@@ -10,7 +10,8 b' import nose.tools as nt'
10
10
11 from IPython.config import Config
11 from IPython.config import Config
12 from IPython.core.formatters import (
12 from IPython.core.formatters import (
13 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key
13 PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
14 DisplayFormatter,
14 )
15 )
15 from IPython.utils.io import capture_output
16 from IPython.utils.io import capture_output
16
17
@@ -387,3 +388,33 b' def test_pretty_max_seq_length():'
387 text = f(list(range(1024)))
388 text = f(list(range(1024)))
388 lines = text.splitlines()
389 lines = text.splitlines()
389 nt.assert_equal(len(lines), 1024)
390 nt.assert_equal(len(lines), 1024)
391
392
393 def test_ipython_display_formatter():
394 """Objects with _ipython_display_ defined bypass other formatters"""
395 f = get_ipython().display_formatter
396 catcher = []
397 class SelfDisplaying(object):
398 def _ipython_display_(self):
399 catcher.append(self)
400
401 class NotSelfDisplaying(object):
402 def __repr__(self):
403 return "NotSelfDisplaying"
404
405 def _ipython_display_(self):
406 raise NotImplementedError
407
408 yes = SelfDisplaying()
409 no = NotSelfDisplaying()
410
411 d, md = f.format(no)
412 nt.assert_equal(d, {'text/plain': repr(no)})
413 nt.assert_equal(md, {})
414 nt.assert_equal(catcher, [])
415
416 d, md = f.format(yes)
417 nt.assert_equal(d, {})
418 nt.assert_equal(md, {})
419 nt.assert_equal(catcher, [yes])
420
General Comments 0
You need to be logged in to leave comments. Login now