Repository: ipython/ipython

Issue:
display_* not respected if _repr_mimebundle_ defined. 
See https://github.com/ipython/ipython/pull/10496#issuecomment-300641192
![screen shot 2017-05-10 at 16 33 23](https://cloud.githubusercontent.com/assets/335567/25925610/73516ca8-359e-11e7-9b16-b8d5d1655f6d.png)



Discussion:
Currently looking into this one. 
@rgbkrk , @minrk should `_repr_mimebundle_` be given the `exclude`/`include` keywords to potentially skip computation of expensive representation, these are options of `display()`. 

Thought ? 

Resolving patch:
diff --git a/IPython/core/formatters.py b/IPython/core/formatters.py
--- a/IPython/core/formatters.py
+++ b/IPython/core/formatters.py
@@ -91,7 +91,7 @@ def format(self, obj, include=None, exclude=None):
 
         By default all format types will be computed.
 
-        The following MIME types are currently implemented:
+        The following MIME types are usually implemented:
 
         * text/plain
         * text/html
@@ -108,14 +108,15 @@ def format(self, obj, include=None, exclude=None):
         ----------
         obj : object
             The Python object whose format data will be computed.
-        include : list or tuple, optional
+        include : list, tuple or set; optional
             A list of format type strings (MIME types) to include in the
             format data dict. If this is set *only* the format types included
             in this list will be computed.
-        exclude : list or tuple, optional
+        exclude : list, tuple or set; optional
             A list of format type string (MIME types) to exclude in the format
             data dict. If this is set all format types will be computed,
             except for those included in this argument.
+            Mimetypes present in exclude will take precedence over the ones in include
 
         Returns
         -------
@@ -129,6 +130,15 @@ def format(self, obj, include=None, exclude=None):
             
             metadata_dict is a dictionary of metadata about each mime-type output.
             Its keys will be a strict subset of the keys in format_dict.
+
+        Notes
+        -----
+
+            If an object implement `_repr_mimebundle_` as well as various
+            `_repr_*_`, the data returned by `_repr_mimebundle_` will take
+            precedence and the corresponding `_repr_*_` for this mimetype will
+            not be called.
+
         """
         format_dict = {}
         md_dict = {}
@@ -139,6 +149,14 @@ def format(self, obj, include=None, exclude=None):
 
         format_dict, md_dict = self.mimebundle_formatter(obj)
 
+        if format_dict or md_dict:
+            if include:
+                format_dict = {k:v for k,v in format_dict.items() if k in include}
+                md_dict = {k:v for k,v in md_dict.items() if k in include}
+            if exclude:
+                format_dict = {k:v for k,v in format_dict.items() if k not in exclude}
+                md_dict = {k:v for k,v in md_dict.items() if k not in exclude}
+
         for format_type, formatter in self.formatters.items():
             if format_type in format_dict:
                 # already got it from mimebundle, don't render again
@@ -163,7 +181,6 @@ def format(self, obj, include=None, exclude=None):
                 format_dict[format_type] = data
             if md is not None:
                 md_dict[format_type] = md
-            
         return format_dict, md_dict
 
     @property
@@ -983,4 +1000,3 @@ def format_display_data(obj, include=None, exclude=None):
         include,
         exclude
     )
-


Test patch:
diff --git a/IPython/core/tests/test_formatters.py b/IPython/core/tests/test_formatters.py
--- a/IPython/core/tests/test_formatters.py
+++ b/IPython/core/tests/test_formatters.py
@@ -444,9 +444,13 @@ def _repr_mimebundle_(self):
             return {
                 'application/json+test.v2': {
                     'x': 'y'
-                }
+                },
+                'plain/text' : '<HasReprMime>',
+                'image/png' : 'i-overwrite'
             }
-        
+
+        def _repr_png_(self):
+            return 'should-be-overwritten'
         def _repr_html_(self):
             return '<b>hi!</b>'
     
@@ -458,9 +462,18 @@ def _repr_html_(self):
     d, md = f.format(obj)
     html_f.enabled = save_enabled
     
-    nt.assert_equal(sorted(d), ['application/json+test.v2', 'text/html', 'text/plain'])
+    nt.assert_equal(sorted(d), ['application/json+test.v2',
+                                'image/png',
+                                'plain/text',
+                                'text/html',
+                                'text/plain'])
     nt.assert_equal(md, {})
 
+    d, md = f.format(obj, include={'image/png'})
+    nt.assert_equal(list(d.keys()), ['image/png'],
+                    'Include should filter out even things from repr_mimebundle')
+    nt.assert_equal(d['image/png'], 'i-overwrite', '_repr_mimebundle_ take precedence')
+
 
 def test_repr_mime_meta():
     class HasReprMimeMeta(object):