Repository: altair-viz/altair

Issue:
Safer enabling of MIME rendering
Right now the `enable_mime_rendering()` function is not very safe:

* Can't call twice.
* Can't disable.

Easy to fix, but need to wait for #377 to be merged.

Discussion:

Patch:
diff --git a/altair/v1/__init__.py b/altair/v1/__init__.py
index 6239d9e1..62db76eb 100644
--- a/altair/v1/__init__.py
+++ b/altair/v1/__init__.py
@@ -43,6 +43,7 @@ from .api import (
     OneOfFilter,
     MaxRowsExceeded,
     enable_mime_rendering,
+    disable_mime_rendering
 )
 
 from ..datasets import (
diff --git a/altair/v1/api.py b/altair/v1/api.py
index 51135a9e..1b0ecea0 100644
--- a/altair/v1/api.py
+++ b/altair/v1/api.py
@@ -64,6 +64,8 @@ DEFAULT_MAX_ROWS = 5000
 # Rendering configuration
 #*************************************************************************
 
+_original_ipython_display_ = None
+
 # This is added to TopLevelMixin as a method if MIME rendering is enabled
 def _repr_mimebundle_(self, include, exclude, **kwargs):
     """Return a MIME-bundle for rich display in the Jupyter Notebook."""
@@ -75,8 +77,22 @@ def _repr_mimebundle_(self, include, exclude, **kwargs):
 def enable_mime_rendering():
     """Enable MIME bundle based rendering used in JupyterLab/nteract."""
     # This is what makes Python fun!
-    delattr(TopLevelMixin, '_ipython_display_')
-    TopLevelMixin._repr_mimebundle_ = _repr_mimebundle_
+    global _original_ipython_display_
+    if _original_ipython_display_ is None:
+        TopLevelMixin._repr_mimebundle_ = _repr_mimebundle_
+        _original_ipython_display_ = TopLevelMixin._ipython_display_
+        delattr(TopLevelMixin, '_ipython_display_')
+
+
+def disable_mime_rendering():
+    """Disable MIME bundle based rendering used in JupyterLab/nteract."""
+    global _original_ipython_display_
+    if _original_ipython_display_ is not None:
+        delattr(TopLevelMixin, '_repr_mimebundle_')
+        TopLevelMixin._ipython_display_ = _original_ipython_display_
+        _original_ipython_display_ = None
+
+
 
 #*************************************************************************
 # Channel Aliases


Test patch:
diff --git a/altair/expr/tests/test_expr.py b/altair/expr/tests/test_expr.py
index 2c3b981b..328d64e5 100644
--- a/altair/expr/tests/test_expr.py
+++ b/altair/expr/tests/test_expr.py
@@ -112,7 +112,7 @@ def test_getitem_list(data):
     assert set(dir(df2)) == {'xxx', 'yyy', 'calculated'}
 
     # changing df2 shouldn't affect df1
-    df2['qqq'] = df2.xxx / df2.yyy
+    df2['qqq'] = df2.xxx // df2.yyy
     assert set(dir(df2)) == {'xxx', 'yyy', 'calculated', 'qqq'}
     assert set(dir(df)) == {'xxx', 'yyy', 'zzz', 'calculated'}
 
diff --git a/altair/v1/tests/test_api.py b/altair/v1/tests/test_api.py
index b1e14e3a..75dacfce 100644
--- a/altair/v1/tests/test_api.py
+++ b/altair/v1/tests/test_api.py
@@ -448,7 +448,7 @@ def test_chart_serve():
 
 
 def test_formula_expression():
-     formula = Formula('blah', expr.log(expr.df.value) / expr.LN10)
+     formula = Formula('blah', expr.log(expr.df.value) // expr.LN10)
      assert formula.field == 'blah'
      assert formula.expr == '(log(datum.value)/LN10)'
 
@@ -579,3 +579,11 @@ def test_schema_url():
 
     # Make sure that $schema
     chart = Chart.from_dict(dct)
+
+
+def test_enable_mime_rendering():
+    # Make sure these functions are safe to call multiple times.
+    enable_mime_rendering()
+    enable_mime_rendering()
+    disable_mime_rendering()
+    disable_mime_rendering()