diff --git a/pyecharts/__init__.py b/pyecharts/__init__.py index cd2d1d0a..a634ef0f 100644 --- a/pyecharts/__init__.py +++ b/pyecharts/__init__.py @@ -38,4 +38,5 @@ from pyecharts.custom.timeline import Timeline # misc from pyecharts.template import online +from pyecharts.engine import configure from pyecharts.style import Style diff --git a/pyecharts/conf.py b/pyecharts/conf.py index 4affc9d7..b06fb040 100644 --- a/pyecharts/conf.py +++ b/pyecharts/conf.py @@ -2,11 +2,13 @@ # coding=utf-8 from __future__ import unicode_literals +from pyecharts.utils import get_resource_dir + class PyEchartsConfig(object): def __init__(self, echarts_template_dir='.', jshost=None, force_js_embed=False): self.echarts_template_dir = echarts_template_dir - jshost = jshost or '' + jshost = jshost or get_resource_dir('templates', 'js', 'echarts') if jshost[-1:] in ('/', '\\'): jshost = jshost[:-1] self._jshost = jshost.rstrip('/') diff --git a/pyecharts/engine.py b/pyecharts/engine.py index 1d56f051..f1f02aa5 100644 --- a/pyecharts/engine.py +++ b/pyecharts/engine.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from jinja2 import Environment, environmentfunction -from pyecharts.utils import get_resource_dir, json_dumps +from pyecharts.utils import json_dumps from pyecharts import constants from pyecharts.conf import DEFAULT_CONFIG @@ -16,11 +16,17 @@ class Helpers(object): :return: """ dependencies = [] + + def _add(_x): + if _x not in dependencies: + dependencies.append(_x) + for a in args: if hasattr(a, 'js_dependencies'): - dependencies.extend(a.js_dependencies) + for d in a.js_dependencies: + _add(d) else: - dependencies.append(a) + _add(a) return dependencies @staticmethod @@ -92,43 +98,52 @@ def echarts_container(env, chart): @environmentfunction -def echarts_js_content(env, chart): +def echarts_js_content(env, *charts): """ Render script html node for echarts initial code. :param env: :param chart: :return: """ - content_fmt = ''' - var myChart_{chart_id} = echarts.init(document.getElementById('{chart_id}')); - var option_{chart_id} = {options}; - myChart_{chart_id}.setOption(option_{chart_id}); - ''' - js_content = content_fmt.format( - chart_id=chart.chart_id, - options=json_dumps(chart.options, indent=4) - ) - return ''.format(js_content) + + print(charts) + contents = [] + for chart in charts: + content_fmt = ''' + var myChart_{chart_id} = echarts.init(document.getElementById('{chart_id}')); + var option_{chart_id} = {options}; + myChart_{chart_id}.setOption(option_{chart_id}); + ''' + js_content = content_fmt.format( + chart_id=chart.chart_id, + options=json_dumps(chart.options, indent=4) + ) + contents.append(js_content) + contents = '\n'.join(contents) + return ''.format(contents) @environmentfunction -def echarts_js_content_wrap(env, chart): +def echarts_js_content_wrap(env, *charts): """ Render echarts initial code for a chart. :param env: - :param chart: + :param charts: :return: """ - content_fmt = ''' - var myChart_{chart_id} = echarts.init(document.getElementById('{chart_id}')); - var option_{chart_id} = {options}; - myChart_{chart_id}.setOption(option_{chart_id}); - ''' - js_content = content_fmt.format( - chart_id=chart.chart_id, - options=json_dumps(chart.options, indent=4) - ) - return js_content + contents = [] + for chart in charts: + content_fmt = ''' + var myChart_{chart_id} = echarts.init(document.getElementById('{chart_id}')); + var option_{chart_id} = {options}; + myChart_{chart_id}.setOption(option_{chart_id}); + ''' + js_content = content_fmt.format( + chart_id=chart.chart_id, + options=json_dumps(chart.options, indent=4) + ) + contents.append(js_content) + return '\n'.join(contents) class EchartsEnvironment(Environment): diff --git a/pyecharts/templates/simple_page.html b/pyecharts/templates/simple_page.html index 82268701..e13f5143 100644 --- a/pyecharts/templates/simple_page.html +++ b/pyecharts/templates/simple_page.html @@ -9,6 +9,6 @@ {% for chart in page %} {{ echarts_container(chart) }} {% endfor %} -{{ echarts_js_content(page) }} +{{ echarts_js_content(*page) }} \ No newline at end of file diff --git a/pyecharts/utils.py b/pyecharts/utils.py index a9171ca3..26d06adc 100644 --- a/pyecharts/utils.py +++ b/pyecharts/utils.py @@ -50,14 +50,14 @@ def freeze_js(html_content): return html_content -def get_resource_dir(folder): +def get_resource_dir(*paths): """ - :param folder: + :param path: :return: """ current_path = os.path.dirname(__file__) - resource_path = os.path.join(current_path, folder) + resource_path = os.path.join(current_path, *paths) return resource_path diff --git a/test/test_conf.py b/test/test_conf.py index 90d51a11..1d122ba7 100644 --- a/test/test_conf.py +++ b/test/test_conf.py @@ -22,3 +22,6 @@ def test_config(): assert pec.js_embed pec.force_js_embed = False assert pec.js_embed + + pec1 = PyEchartsConfig(jshost='http://demo/') + assert pec1.jshost == 'http://demo' diff --git a/test/test_custom_render.py b/test/test_custom_render.py new file mode 100644 index 00000000..9d900d65 --- /dev/null +++ b/test/test_custom_render.py @@ -0,0 +1,44 @@ +# coding=utf8 +from __future__ import unicode_literals + +import json +import codecs +from test.constants import RANGE_COLOR, CLOTHES, WEEK +from pyecharts import ( + Bar, Scatter3D, Line, Pie, Map, + Kline, Radar, WordCloud, Liquid) +from pyecharts import Page +from pyecharts.utils import get_resource_dir +from pyecharts.engine import configure +from nose.tools import eq_ + + +def create_three(): + # bar + v1 = [5, 20, 36, 10, 75, 90] + v2 = [10, 25, 8, 60, 20, 80] + bar = Bar("柱状图数据堆叠示例") + bar.add("商家A", CLOTHES, v1, is_stack=True) + bar.add("商家B", CLOTHES, v2, is_stack=True) + + # scatter3D + import random + data = [ + [random.randint(0, 100), + random.randint(0, 100), + random.randint(0, 100)] for _ in range(80) + ] + scatter3d = Scatter3D("3D 散点图示例", width=1200, height=600) + scatter3d.add("", data, is_visualmap=True, visual_range_color=RANGE_COLOR) + + return Page.from_charts(bar, scatter3d) + + +def test_custom_templates(): + configure(jshost='https://chfw.github.io/jupyter-echarts/echarts') + page = create_three() + # page.js_dependencies = ['echarts.min'] + page.render(new_version=True, path='new_version_page.html') + with codecs.open('new_version_page.html', 'r', 'utf-8') as f: + actual_content = f.read() + assert "" in actual_content diff --git a/test/test_engine.py b/test/test_engine.py new file mode 100644 index 00000000..1d46260c --- /dev/null +++ b/test/test_engine.py @@ -0,0 +1,41 @@ +# coding=utf8 + +from __future__ import unicode_literals + +from pyecharts.engine import Helpers + +from nose.tools import eq_ + + +def test_merge_js_dependencies(): + # Helpers.merge_js_dependencies(str1, str2,...) + eq_(['echarts', 'fujian'], Helpers.merge_js_dependencies('echarts', 'fujian')) + + # Helpers.merge_js_dependencies(chart) + class MockChart(object): + def __init__(self, js_dependencies): + self.js_dependencies = js_dependencies + + ch1 = MockChart(['echarts', 'fujian', 'zhengjiang', 'anhui']) + eq_( + ['echarts', 'fujian', 'zhengjiang', 'anhui'], + Helpers.merge_js_dependencies(ch1) + ) + + # Helpers.merge_js_dependencies(chart1, chart2 ) + ch1 = MockChart(['echarts']) + ch2 = MockChart(['echarts', 'beijing']) + eq_( + ['echarts', 'beijing'], + Helpers.merge_js_dependencies(ch1, ch2) + ) + + # Helpers.merge_js_dependencies(*chart_list) + + mock_page = [ch1, ch2] + ch1 = MockChart(['echarts']) + ch2 = MockChart(['echarts', 'beijing']) + eq_( + ['echarts', 'beijing'], + Helpers.merge_js_dependencies(*mock_page) + ) diff --git a/test/test_template_function.py b/test/test_template_function.py index 9fe7945b..6d45aed8 100644 --- a/test/test_template_function.py +++ b/test/test_template_function.py @@ -1,8 +1,8 @@ # coding=utf8 -from pyecharts.template import online +from pyecharts.utils import get_resource_dir from pyecharts import Bar -from pyecharts.engine import EchartsEnvironment +from pyecharts.engine import EchartsEnvironment, configure ECHARTS_ENV = EchartsEnvironment() @@ -20,7 +20,7 @@ def create_demo_bar(chart_id_demo=None): def test_echarts_js_dependencies(): - online('http://localhost/echarts') + configure(jshost='http://localhost/echarts') tpl = ECHARTS_ENV.from_string('{{ echarts_js_dependencies(bar) }}') bar = create_demo_bar() html = tpl.render(bar=bar) @@ -28,12 +28,17 @@ def test_echarts_js_dependencies(): def test_echarts_js_dependencies_embed(): - online('https://chfw.github.io/jupyter-echarts/echarts') - tpl = ECHARTS_ENV.from_string('{{ echarts_js_dependencies("echarts.min") }}') + configure(jshost=get_resource_dir('templates', 'js', 'echarts')) + tpl = ECHARTS_ENV.from_string('{{ echarts_js_dependencies_embed("echarts.min") }}') bar = create_demo_bar() html = tpl.render(bar=bar) - with open('_cf.html', 'wb') as f: - f.write(html.encode('utf8')) + assert len(html) > 0 + + # echarts_js_dependencies equals echarts_js_dependencies_embed when use local host. + tpl2 = ECHARTS_ENV.from_string('{{ echarts_js_dependencies("echarts.min") }}') + html2 = tpl2.render(bar=bar) + assert len(html2) > 0 + assert html == html2 def test_echarts_js_container(): @@ -47,18 +52,21 @@ def test_echarts_js_container(): html = tpl.render(bar=bar) assert '
' == html + bar.width = '1024px' + bar.height = '768px' + html = tpl.render(bar=bar) + assert '
' == html + def test_echarts_js_content(): tpl = ECHARTS_ENV.from_string('{{ echarts_js_content(bar) }}') bar = create_demo_bar() html = tpl.render(bar=bar) - # with open('_tmp.html', 'w') as f: - # f.write(html) + assert len(html) > 0 def test_echarts_js_content_wrap(): tpl = ECHARTS_ENV.from_string('{{ echarts_js_content_wrap(bar) }}') bar = create_demo_bar() html = tpl.render(bar=bar) - # with open('_tc.html', 'w') as f: - # f.write(html) + assert len(html) > 0