Skip to content

Commit

Permalink
Nteract support (pyecharts#570)
Browse files Browse the repository at this point in the history
* ✨ support nteract environment.

* 🔨 use temp file in system temp folder

* 🔬 test nteract function and update 📚

* 👕 whitening the code

* 📚 update demo and pump version number

* 📚 give reference to nteract.io

* 📚 update change log and 🐛 a bug fix on tmp file suffix
  • Loading branch information
chfw authored and chenjiandongx committed May 17, 2018
1 parent d8ec033 commit 4ab5ce2
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 25 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ So please see installation instruction and other usage at that repository.

pyecharts exposes chart API and template API so that it can work on other python frameworks.

### Integration with Jupyter Notebook
### Integration with Jupyter Notebook/nteract

In the Notebook cell, you can simply pass on chart instance itself to Jupyter, which will diplay the chart. Please note **render_notebook** function has been removed.

Expand All @@ -126,6 +126,18 @@ In the case of online jshost mode, you can also download as some file formats (i

![](https://user-images.githubusercontent.com/19553554/35104252-3e36cee2-fca3-11e7-8e43-09bbe8dbbd1e.png)

#### nteract

Since pyecharts 0.5.5+, [nteract](https://nteract.io) is supported. Once the following two lines should added to your notebook, you could use pyecharts in nteract in the same way as in jupyter notebook.

```
from pyecharts import enable_nteract
enable_nteract()
```

However, when rendering output as image, the instructions are the same as jupyter notebook. Only default html(including js) output should call `enable_nteract()`.

### Integrate With Web Framework

With the help of pyecharts API, it is easy to integrate pyecharts to your web projects, such as Flask and Django.
Expand Down
2 changes: 1 addition & 1 deletion docs/zh-cn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pyecharts 是一个用于生成 Echarts 图表的类库。Echarts 是百度开

**平台支持**

[Jupyter Notebook](zh-cn/jupyter_notebook) | [Flask](zh-cn/flask) | [Django](zh-cn/django) | [web 框架整合](zh-cn/web_integration)
[Jupyter Notebook/nteract](zh-cn/jupyter_notebook) | [Flask](zh-cn/flask) | [Django](zh-cn/django) | [web 框架整合](zh-cn/web_integration)

**其他资源**

Expand Down
3 changes: 2 additions & 1 deletion docs/zh-cn/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added
* [issue#565](https://github.com/pyecharts/pyecharts/issues/565) Geolines 图数据项可以新增数值维度
* 支持 jupyter notebook 家族的新成员 nteract

* ### version 0.5.4 - 2018.05.15(current)

Expand All @@ -13,7 +14,7 @@
### Fixed
* [issue#555](https://github.com/pyecharts/pyecharts/issues/555) 修复 v0.5.3 Polar 图不能显示的 bug
* [issue#541](https://github.com/pyecharts/pyecharts/issues/541) 修复 v0.5.3 Django + pyecharts 不能正常导入的 bug

* ### version 0.5.3 - 2018.05.10

#### Fixed
Expand Down
13 changes: 13 additions & 0 deletions docs/zh-cn/jupyter_notebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ configure(global_theme='dark')

然后在重新运行,奇迹就会发生。

## nteract

从 pyecharts 0.5.5+ 开始,[nteract](https://nteract.io) 也可以使用 pyecharts 了。目前来说,nteract 用户必需在最开始的时候声明 `enable_nteract()` 才能顺利进行绘图。而且,仅仅是在需要产生 html(js) 输出是需要调用 `enable_nteract()`


![nteract-demo](https://user-images.githubusercontent.com/4280312/40146181-75652024-595c-11e8-9a63-44fcfb8959c2.png)

但是,如果你需要输出图片,具体做法和上面提到的 jupyter notebook 的做法是一样的。

![nteract-image-output](https://user-images.githubusercontent.com/4280312/40167928-305385bc-59ba-11e8-9a23-56b5970f1a41.png)

## jupyterlab

[jupyterlab](https://github.com/jupyterlab/jupyterlab) 是下一代 Jupyter Notebook ,目前尚处于发展的雏形之中。我们将进一步关注项目发展,尽可能第一时间实现 pyecharts 的适配,敬请期待。


1 change: 1 addition & 0 deletions pyecharts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

# misc
from pyecharts.conf import online
from pyecharts.conf import enable_nteract
from pyecharts.conf import configure
from pyecharts.echarts.style import Style
from pyecharts.conf import jupyter_image
Expand Down
2 changes: 1 addition & 1 deletion pyecharts/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "0.5.4"
__version__ = "0.5.5"
__author__ = "chenjiandongx"
43 changes: 25 additions & 18 deletions pyecharts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import uuid
import warnings
from tempfile import mkstemp

from jinja2 import Markup

Expand Down Expand Up @@ -170,9 +171,9 @@ def cast(seq):

def render_notebook(self):
warnings.warn(
"Implementation has been removed. " +
"Please pass the chart instance directly to Jupyter." +
"If you need more help, please read documentation"
"Implementation has been removed. "
+ "Please pass the chart instance directly to Jupyter."
+ "If you need more help, please read documentation"
)

def _get_all_options(self, **kwargs):
Expand All @@ -186,18 +187,25 @@ def _repr_html_(self):
chart.js_dependencies => require_config => config_items, libraries
:return A unicode string.
"""
if CURRENT_CONFIG.jupyter_presentation != constants.DEFAULT_HTML:
return None
if CURRENT_CONFIG.jupyter_presentation == constants.DEFAULT_HTML:
require_config = CURRENT_CONFIG.produce_require_configuration(
self.js_dependencies
)
config_items = require_config["config_items"]
libraries = require_config["libraries"]
env = engine.create_default_environment(constants.DEFAULT_HTML)
return env.render_chart_to_notebook(
charts=(self,), config_items=config_items, libraries=libraries
)

require_config = CURRENT_CONFIG.produce_require_configuration(
self.js_dependencies
)
config_items = require_config["config_items"]
libraries = require_config["libraries"]
env = engine.create_default_environment(constants.DEFAULT_HTML)
return env.render_chart_to_notebook(
charts=(self,), config_items=config_items, libraries=libraries
)
elif CURRENT_CONFIG.jupyter_presentation == constants.NTERACT:
env = engine.create_default_environment(constants.DEFAULT_HTML)
return env.render_chart_to_notebook(
chart=self, template_name="nteract.html"
)

else:
return None

def _repr_svg_(self):
content = self._render_as_image(constants.SVG)
Expand Down Expand Up @@ -235,12 +243,11 @@ def _render_as_image(self, file_type):
)

env = engine.create_default_environment(file_type)
outfile = "tmp." + file_type
tmp_file_handle, tmp_file_path = mkstemp(suffix="."+file_type)
content = env.render_chart_to_file(
chart=self, path=outfile, verbose=False
chart=self, path=tmp_file_path, verbose=False
)
if content:
os.unlink(outfile)
os.close(tmp_file_handle)
return content

def _add_chinese_map(self, map_name_in_chinese):
Expand Down
7 changes: 7 additions & 0 deletions pyecharts/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ def online(host=None):
configure(jshost=host)


def enable_nteract(host=None):
configure(
output_image=constants.NTERACT,
jshost="https://pyecharts.github.io/assets/js",
)


@contextmanager
def jupyter_image(jupyter_presentation):
"""
Expand Down
3 changes: 2 additions & 1 deletion pyecharts/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
PNG = "png"
JPEG = "jpeg"
DEFAULT_HTML = "html"
JUPYTER_PRESENTATIONS = [SVG, PNG, JPEG, DEFAULT_HTML]
NTERACT = "nteract"
JUPYTER_PRESENTATIONS = [SVG, PNG, JPEG, DEFAULT_HTML, NTERACT]
ENVIRONMENT_PLUGIN_TYPE = "pyecharts_environment"
JS_EXTENSION_PLUGIN_TYPE = "pyecharts_js_extension"

Expand Down
6 changes: 4 additions & 2 deletions pyecharts/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,16 @@ def render_chart_to_file(
html = tpl.render(**kwargs)
utils.write_utf8_html_file(path, html)

def render_chart_to_notebook(self, **context):
def render_chart_to_notebook(
self, template_name="notebook.html", **context
):
"""
Return html string for rendering a chart/page to a notebook cell.
:param context: A dictionary containing data.
:return: A unicode string that will be displayed in notebook cell.
"""
tpl = self.get_template("notebook.html")
tpl = self.get_template(template_name)
return tpl.render(**context)


Expand Down
3 changes: 3 additions & 0 deletions pyecharts/templates/nteract.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{ echarts_container(chart) }}
{{ echarts_js_content(chart) }}
{{ echarts_js_dependencies(chart) }}
16 changes: 16 additions & 0 deletions test/test_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import json

from pyecharts import Bar, Line, Pie, Page, online
from pyecharts import enable_nteract, configure
import pyecharts.constants as constants
from pyecharts.conf import CURRENT_CONFIG
from test.constants import CLOTHES, WEEK

TITLE = "柱状图数据堆叠示例"
Expand Down Expand Up @@ -92,6 +95,7 @@ def test_online_feature():
html = bar._repr_html_()
expected_jshost = "https://pyecharts.github.io/jupyter-echarts/echarts"
assert expected_jshost in html
CURRENT_CONFIG.hosted_on_github = False


def test_online_with_custom_jshost():
Expand All @@ -100,3 +104,15 @@ def test_online_with_custom_jshost():
html = bar._repr_html_()
expected_jshost = "https://my-site.com/js"
assert expected_jshost in html
CURRENT_CONFIG.jshost = None


def test_nteract_feature():
enable_nteract()
bar = create_a_bar(TITLE)
html = bar._repr_html_()
assert "https://pyecharts.github.io/assets/js/echarts.min.js" in html
assert "require" not in html
# restore configuration
configure(output_image=constants.DEFAULT_HTML)
CURRENT_CONFIG.jshost = None

0 comments on commit 4ab5ce2

Please sign in to comment.