Skip to content

Commit b18f4e1

Browse files
martinRenouSylvainCorlay
authored andcommitted
Implement rich display (jupyter-xeus#17)
* Implement display repr * Add missing repr handle * Create display_pub_data function * Add a global "display" function * Review * Remove useless if condition * Add warning for _ipython_display
1 parent 4cecafc commit b18f4e1

File tree

5 files changed

+105
-4
lines changed

5 files changed

+105
-4
lines changed

notebooks/marie.png

106 KB
Loading

notebooks/xeus-python.ipynb

+31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
{
22
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"from IPython.display import Image\n",
10+
"im = Image(url=\"marie.png\")\n",
11+
"im"
12+
]
13+
},
314
{
415
"cell_type": "code",
516
"execution_count": null,
@@ -63,6 +74,8 @@
6374
"source": [
6475
"b = 89\n",
6576
"\n",
77+
"display(im)\n",
78+
"\n",
6679
"def test(x):\n",
6780
" return x * 2\n",
6881
"\n",
@@ -114,6 +127,24 @@
114127
"b"
115128
]
116129
},
130+
{
131+
"cell_type": "code",
132+
"execution_count": null,
133+
"metadata": {},
134+
"outputs": [],
135+
"source": [
136+
"from ipywidgets import IntSlider"
137+
]
138+
},
139+
{
140+
"cell_type": "code",
141+
"execution_count": null,
142+
"metadata": {},
143+
"outputs": [],
144+
"source": [
145+
"IntSlider()"
146+
]
147+
},
117148
{
118149
"cell_type": "code",
119150
"execution_count": null,

src/xdisplay.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
* The full license is in the file LICENSE, distributed with this software. *
88
****************************************************************************/
99

10+
#include <string>
11+
12+
#include "xeus/xjson.hpp"
13+
1014
#include "pybind11/pybind11.h"
1115
#include "pybind11/embed.h"
1216

@@ -42,6 +46,64 @@ namespace xpyt
4246
}
4347
}
4448

49+
xeus::xjson display_pub_data(py::object obj)
50+
{
51+
py::module py_json = py::module::import("json");
52+
xeus::xjson pub_data;
53+
54+
if (hasattr(obj, "_repr_mimebundle_"))
55+
{
56+
pub_data = xeus::xjson::parse(static_cast<std::string>(
57+
py::str(py_json.attr("dumps")(obj.attr("_repr_mimebundle_")()))
58+
));
59+
}
60+
else
61+
{
62+
if (hasattr(obj, "_repr_html_"))
63+
{
64+
pub_data["text/html"] = static_cast<std::string>(
65+
py::str(obj.attr("_repr_html_")())
66+
);
67+
}
68+
if (hasattr(obj, "_repr_json_"))
69+
{
70+
pub_data["application/json"] = static_cast<std::string>(
71+
py::str(obj.attr("_repr_json_")())
72+
);
73+
}
74+
if (hasattr(obj, "_repr_jpeg_"))
75+
{
76+
pub_data["image/jpeg"] = static_cast<std::string>(
77+
py::str(obj.attr("_repr_jpeg_")())
78+
);
79+
}
80+
if (hasattr(obj, "_repr_png_"))
81+
{
82+
pub_data["image/png"] = static_cast<std::string>(
83+
py::str(obj.attr("_repr_png_")())
84+
);
85+
}
86+
if (hasattr(obj, "_repr_svg_"))
87+
{
88+
pub_data["image/svg+xml"] = static_cast<std::string>(
89+
py::str(obj.attr("_repr_svg_")())
90+
);
91+
}
92+
if (hasattr(obj, "_repr_latex_"))
93+
{
94+
pub_data["text/latex"] = static_cast<std::string>(
95+
py::str(obj.attr("_repr_latex_")())
96+
);
97+
}
98+
99+
pub_data["text/plain"] = static_cast<std::string>(
100+
py::str(obj.attr("__repr__")())
101+
);
102+
}
103+
104+
return pub_data;
105+
}
106+
45107
PYBIND11_EMBEDDED_MODULE(xeus_python_display, m) {
46108
py::class_<xdisplayhook>(m, "XPythonDisplay")
47109
.def(py::init<>())

src/xdisplay.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ namespace xpyt
3838
int m_execution_count;
3939
hooks_type m_hooks;
4040
};
41+
42+
xeus::xjson display_pub_data(py::object obj);
4143
}
4244

4345
#endif

src/xinterpreter.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "xpyt_config.hpp"
1919
#include "xinterpreter.hpp"
2020
#include "xlogger.hpp"
21+
#include "xdisplay.hpp"
2122

2223
namespace py = pybind11;
2324

@@ -244,14 +245,19 @@ namespace xpyt
244245
py::cpp_function publish_display = [this](int execution_counter, py::object obj){
245246
if (!obj.is_none())
246247
{
247-
xeus::xjson pub_data;
248-
pub_data["text/plain"] = py::str(obj);
249-
publish_execution_result(execution_counter, std::move(pub_data), xeus::xjson::object());
248+
if (hasattr(obj, "_ipython_display_"))
249+
{
250+
this->publish_stream("stderr", "_ipython_display_ is not supported");
251+
}
252+
253+
this->publish_execution_result(execution_counter, std::move(display_pub_data(obj)), xeus::xjson::object());
250254
}
251255
};
252256

253257
m_displayhook.attr("add_hook")(publish_display);
254-
255258
sys.attr("displayhook") = m_displayhook;
259+
260+
// Create a global "display" function
261+
py::globals()["display"] = m_displayhook;
256262
}
257263
}

0 commit comments

Comments
 (0)