Repository: nteract/papermill

Issue:
Error on record() with new versions
Versions above 0.11 seems to present an error when running the record() function.
As the example on the readme file:

```python-traceback
"""notebook.ipynb"""
import papermill as pm

pm.record("hello", "world")
pm.record("number", 123)
pm.record("some_list", [1, 3, 5])
pm.record("some_dict", {"a": 1, "b": 2})`

gives:
`---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-20-447d49aec58c> in <module>()
      2 import papermill as pm
      3 
----> 4 pm.record("hello", "world")
      5 pm.record("number", 123)
      6 pm.record("some_list", [1, 3, 5])

~\Anaconda3\envs\mestrado\lib\site-packages\papermill\api.py in record(name, value)
     33     # IPython.display.display takes a tuple of objects as first parameter
     34     # `http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.display`
---> 35     ip_display(({RECORD_OUTPUT_TYPE: {name: value}},), raw=True)
     36 
     37 

~\Anaconda3\envs\mestrado\lib\site-packages\IPython\core\display.py in display(include, exclude, metadata, transient, display_id, *objs, **kwargs)
    293     for obj in objs:
    294         if raw:
--> 295             publish_display_data(data=obj, metadata=metadata, **kwargs)
    296         else:
    297             format_dict, md_dict = format(obj, include=include, exclude=exclude)

~\Anaconda3\envs\mestrado\lib\site-packages\IPython\core\display.py in publish_display_data(data, metadata, source, transient, **kwargs)
    118         data=data,
    119         metadata=metadata,
--> 120         **kwargs
    121     )
    122 

~\Anaconda3\envs\mestrado\lib\site-packages\ipykernel\zmqshell.py in publish(self, data, metadata, source, transient, update)
    115         if transient is None:
    116             transient = {}
--> 117         self._validate_data(data, metadata)
    118         content = {}
    119         content['data'] = encode_images(data)

~\Anaconda3\envs\mestrado\lib\site-packages\IPython\core\displaypub.py in _validate_data(self, data, metadata)
     48 
     49         if not isinstance(data, dict):
---> 50             raise TypeError('data must be a dict, got: %r' % data)
     51         if metadata is not None:
     52             if not isinstance(metadata, dict):

TypeError: data must be a dict, got: {'application/papermill.record+json': {'hello': 'world'}}`

```

Discussion:
rgbkrk: We'll want to get a patch release out for this pretty quick, records are generally broken right now.
rgbkrk: Weird that the push is failing, though it looks like we should be mocking the kernelspec lookup.
rgbkrk: I've re-kicked the one failing job since everything else passes.
codecov[bot]: # [Codecov](https://codecov.io/gh/nteract/papermill/pull/81?src=pr&el=h1) Report
> Merging [#81](https://codecov.io/gh/nteract/papermill/pull/81?src=pr&el=desc) into [master](https://codecov.io/gh/nteract/papermill/commit/f3eb72e0db1cdf4ddf2d99ddfa38615b30c97e7e?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `16.66%`.



```diff
@@           Coverage Diff           @@
##           master      #81   +/-   ##
=======================================
  Coverage   54.97%   54.97%           
=======================================
  Files           8        8           
  Lines         864      864           
=======================================
  Hits          475      475           
  Misses        389      389
```

rgbkrk: Added a basic test that really just verifies that the papermill record payload is passed through correctly.
rgbkrk: /cc @willingc 

Patch:
diff --git a/papermill/api.py b/papermill/api.py
index 15b2745..8f68c88 100644
--- a/papermill/api.py
+++ b/papermill/api.py
@@ -32,7 +32,7 @@ def record(name, value):
     """
     # IPython.display.display takes a tuple of objects as first parameter
     # `http://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.display`
-    ip_display(({RECORD_OUTPUT_TYPE: {name: value}},), raw=True)
+    ip_display(data={RECORD_OUTPUT_TYPE: {name: value}}, raw=True)
 
 
 def display(name, obj):
@@ -46,7 +46,7 @@ def display(name, obj):
     """
     data, metadata = IPython.core.formatters.format_display_data(obj)
     metadata['papermill'] = dict(name=name)
-    ip_display(data, metadata=metadata, raw=True)
+    ip_display(data=data, metadata=metadata, raw=True)
 
 
 def read_notebook(path):
@@ -171,7 +171,7 @@ class Notebook(object):
             raise PapermillException(
                 "Output Name '%s' is not available in this notebook.")
         output = outputs[name]
-        ip_display(output.data, metadata=output.metadata, raw=True)
+        ip_display(data=output.data, metadata=output.metadata, raw=True)
 
 
 def _get_papermill_metadata(nb, name, default=None):
@@ -245,11 +245,11 @@ class NotebookCollection(object):
     def display_output(self, key, output_name):
         """Display markdown of output"""
         if isinstance(key, string_types):
-            ip_display((Markdown("### %s" % str(key)),))
+            ip_display(Markdown("### %s" % str(key)))
             self[key].display_output(output_name)
         else:
             for i, k in enumerate(key):
                 if i > 0:
-                    ip_display((Markdown("<hr>"),))  # tag between outputs
-                ip_display((Markdown("### %s" % str(k)),))
+                    ip_display(Markdown("<hr>"))  # tag between outputs
+                ip_display(Markdown("### %s" % str(k)))
                 self[k].display_output(output_name)


Test patch:
diff --git a/papermill/tests/test_api.py b/papermill/tests/test_api.py
index a03710a..4fc1883 100644
--- a/papermill/tests/test_api.py
+++ b/papermill/tests/test_api.py
@@ -9,7 +9,7 @@ else:
 import pandas as pd
 from pandas.util.testing import assert_frame_equal
 
-from .. import display, read_notebook, read_notebooks, PapermillException
+from .. import display, read_notebook, read_notebooks, PapermillException, record
 from ..api import Notebook
 from . import get_notebook_path, get_notebook_dir
 
@@ -91,4 +91,11 @@ def test_display(format_display_data_mock, ip_display_mock):
     display('display_name', {'display_obj': 'hello'})
 
     format_display_data_mock.assert_called_once_with({'display_obj': 'hello'})
-    ip_display_mock.assert_called_once_with({'foo': 'bar'}, metadata={'metadata': 'baz', 'papermill': {'name': 'display_name'}}, raw=True)
+    ip_display_mock.assert_called_once_with(data={'foo': 'bar'}, metadata={'metadata': 'baz', 'papermill': {'name': 'display_name'}}, raw=True)
+
+
+
+@patch('papermill.api.ip_display')
+def test_record(ip_display_mock):
+    record('a', 3)
+    ip_display_mock.assert_called_once_with(data={'application/papermill.record+json': {'a': 3}}, raw=True)