From e7df0ac170fc56436a3ec78c9db37983a7a4187c 2011-05-17 22:41:05
From: Brian Granger <ellisonbg@gmail.com>
Date: 2011-05-17 22:41:05
Subject: [PATCH] Misc updates the display system.

* PNG base64 encoding is now done at the ZMQ level, not in the
  display formatter itself.
* All formatters are documented as to the exact nature of their
  return value. PNGs are not base64 encoded, LaTeX must include
  $/$$, Javascript should not have the <script> tags, etc.
* Updated the Circle display example in docs/examples/core.
* Renamed the sympy printing extension to sympyprinting.py.

---

diff --git a/IPython/core/formatters.py b/IPython/core/formatters.py
index 51553a1..19c519b 100644
--- a/IPython/core/formatters.py
+++ b/IPython/core/formatters.py
@@ -449,6 +449,10 @@ class HTMLFormatter(BaseFormatter):
     objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
     or :meth:`for_type_by_name` methods to register functions that handle
     this.
+
+    The return value of this formatter should be a valid HTML snippet that
+    could be injected into an existing DOM. It should *not* include the 
+    ```<html>`` or ```<body>`` tags.
     """
     format_type = Str('text/html')
 
@@ -462,6 +466,10 @@ class SVGFormatter(BaseFormatter):
     objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
     or :meth:`for_type_by_name` methods to register functions that handle
     this.
+
+    The return value of this formatter should be valid SVG enclosed in
+    ```<svg>``` tags, that could be injected into an existing DOM. It should
+    *not* include the ```<html>`` or ```<body>`` tags.
     """
     format_type = Str('image/svg+xml')
 
@@ -476,7 +484,8 @@ class PNGFormatter(BaseFormatter):
     or :meth:`for_type_by_name` methods to register functions that handle
     this.
 
-    The raw data should be the base64 encoded raw png data.
+    The return value of this formatter should be raw PNG data, *not*
+    base64 encoded.
     """
     format_type = Str('image/png')
 
@@ -490,6 +499,9 @@ class LatexFormatter(BaseFormatter):
     objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
     or :meth:`for_type_by_name` methods to register functions that handle
     this.
+
+    The return value of this formatter should be a valid LaTeX equation,
+    enclosed in either ```$``` or ```$$```.
     """
     format_type = Str('text/latex')
 
@@ -503,6 +515,8 @@ class JSONFormatter(BaseFormatter):
     your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
     or :meth:`for_type_by_name` methods to register functions that handle
     this.
+
+    The return value of this formatter should be a valid JSON string.
     """
     format_type = Str('application/json')
 
@@ -516,6 +530,9 @@ class JavascriptFormatter(BaseFormatter):
     your objects, define a :meth:`_repr_javascript_` method or use the 
     :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
     that handle this.
+
+    The return value of this formatter should be valid Javascript code and
+    should *not* be enclosed in ```<script>``` tags.
     """
     format_type = Str('application/javascript')
 
diff --git a/IPython/extensions/sympy_printing.py b/IPython/extensions/sympyprinting.py
similarity index 98%
rename from IPython/extensions/sympy_printing.py
rename to IPython/extensions/sympyprinting.py
index 57e2dde..a4190fc 100644
--- a/IPython/extensions/sympy_printing.py
+++ b/IPython/extensions/sympyprinting.py
@@ -45,7 +45,7 @@ def print_png(o):
     # them with suitable subs.
     s = s.replace('\\operatorname','')
     s = s.replace('\\overline', '\\bar')
-    png = latex_to_png(s, encode=True)
+    png = latex_to_png(s)
     return png
 
 _loaded = False
diff --git a/IPython/lib/latextools.py b/IPython/lib/latextools.py
index 3d97975..f7f8102 100644
--- a/IPython/lib/latextools.py
+++ b/IPython/lib/latextools.py
@@ -25,7 +25,7 @@ from base64 import encodestring
 #-----------------------------------------------------------------------------
 
 
-def latex_to_png(s, encode=True):
+def latex_to_png(s, encode=False):
     """Render a LaTeX string to PNG using matplotlib.mathtext.
 
     Parameters
diff --git a/IPython/zmq/zmqshell.py b/IPython/zmq/zmqshell.py
index 8306a20..8dea867 100644
--- a/IPython/zmq/zmqshell.py
+++ b/IPython/zmq/zmqshell.py
@@ -16,6 +16,7 @@ machinery.  This should thus be thought of as scaffolding.
 from __future__ import print_function
 
 # Stdlib
+from base64 import encodestring
 import inspect
 import os
 
@@ -67,6 +68,9 @@ class ZMQDisplayHook(DisplayHook):
             self.msg['content']['execution_count'] = self.prompt_count
 
     def write_format_data(self, format_dict):
+        pngdata = format_dict.get('image/png')
+        if pngdata is not None:
+            format_dict['image/png'] = encodestring(pngdata)
         self.msg['content']['data'] = format_dict
 
     def finish_displayhook(self):
diff --git a/docs/examples/core/display.py b/docs/examples/core/display.py
index 404272c..2d5ca50 100644
--- a/docs/examples/core/display.py
+++ b/docs/examples/core/display.py
@@ -1,9 +1,10 @@
 """Code that shows off the IPython display logic.
 """
 
+from IPython.lib.latextools import latex_to_png
 from IPython.core.display import (
     display, display_pretty, display_html,
-    display_svg, display_json
+    display_svg, display_json, display_png
 )
 
 class Circle(object):
@@ -22,3 +23,5 @@ class Circle(object):
 <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
 </svg>"""
 
+    def _repr_png_(self):
+        return latex_to_png('$\circle$')