diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml new file mode 100644 index 00000000..e6de3c53 --- /dev/null +++ b/.github/workflows/python-tests.yml @@ -0,0 +1,36 @@ +name: Python Tests + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] + fail-fast: false + + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools + pip install -r requirements.txt + python setup.py install + pip install coveralls + + - name: Run tests + run: coverage run --source=nvd3 setup.py test + + - name: Finish coveralls + run: coveralls + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 7664d829..78b8d019 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,9 @@ bower.json bower_components archive +env +myenv +nvd3_env htmlcov test_*.html diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2e4222da..00000000 --- a/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: python - -python: - - 2.7 - - 3.3 - - 3.4 - - 3.5 - -install: - - pip install -r requirements.txt - - python setup.py install - - pip install coveralls - -script: - #- python tests.py - - coverage run --source=nvd3 setup.py test -notifications: - email: true - -after_success: - coveralls diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 89477a5e..f0f16d1c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,13 @@ History ------- +0.15.0 - current +--------------------- + +* new settings show_controls & xAxis_rotateLabel +* add setting to add callback + + 0.14.0 - (2015-12-09) --------------------- @@ -73,7 +80,7 @@ History 0.10.0 (2013-10-02) ------------------- +------------------- * Support new chart linePlusBarWithFocusChart diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index ea2ed0b8..8afa5305 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -55,17 +55,17 @@ If you are proposing a feature: Get Started! ------------ -Ready to contribute? Here's how to set up `python-msspeak` for local development. +Ready to contribute? Here's how to set up `python-nvd3` for local development. -1. Fork the `python-msspeak` repo on GitHub. +1. Fork the `python-nvd3` repo on GitHub. 2. Clone your fork locally:: - $ git clone git@github.com:your_name_here/python-msspeak.git + $ git clone git@github.com:your_name_here/python-nvd3.git 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: - $ mkvirtualenv python-msspeak - $ cd python-msspeak/ + $ mkvirtualenv python-nvd3 + $ cd python-nvd3/ $ python setup.py develop 4. Create a branch for local development:: @@ -76,7 +76,7 @@ Ready to contribute? Here's how to set up `python-msspeak` for local development 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - $ flake8 python-msspeak tests + $ flake8 python-nvd3 tests $ python setup.py test $ tox diff --git a/MANIFEST.in b/MANIFEST.in index f3c2a648..7697f68b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ include CONTRIBUTING.rst -include HISTORY.rst +include CHANGELOG.rst include LICENSE include README.rst diff --git a/README.rst b/README.rst index 9e428c08..667d5ca5 100644 --- a/README.rst +++ b/README.rst @@ -10,9 +10,6 @@ Python Wrapper for NVD3 - It's time for beautiful charts .. _Areski: https://github.com/areski/ .. _Oz: https://github.com/oz123/ -.. image:: https://api.travis-ci.org/areski/python-nvd3.png?branch=develop - :target: https://travis-ci.org/areski/python-nvd3 - .. image:: https://coveralls.io/repos/areski/python-nvd3/badge.png?branch=develop :target: https://coveralls.io/r/areski/python-nvd3?branch=develop @@ -32,10 +29,6 @@ Python Wrapper for NVD3 - It's time for beautiful charts :target: https://pypi.python.org/pypi/python-nvd3/ :alt: License -.. image:: https://requires.io/github/areski/python-nvd3/requirements.svg?branch=develop - :target: https://requires.io/github/areski/python-nvd3/requirements/?branch=develop - :alt: Requirements Status - NVD3 is an attempt to build re-usable charts and chart components for d3.js without taking away the power that d3.js offers you. @@ -46,13 +39,11 @@ These graphs can be part of your web application: .. image:: https://raw.githubusercontent.com/areski/python-nvd3/develop/docs/showcase/multiple-charts.png - - Want to try it yourself? Install python-nvd3, enter your python shell and try this quick demo:: >>> from nvd3 import pieChart - >>> type = 'pieChart' - >>> chart = pieChart(name=type, color_category='category20c', height=450, width=450) + >>> chart_name = 'pieChart' + >>> chart = pieChart(name=chart_name, color_category='category20c', height=450, width=450) >>> xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] >>> ydata = [3, 4, 0, 1, 5, 7, 3] >>> extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} @@ -109,6 +100,7 @@ Check out the documentation on `Read the Docs`_ for some live Chart examples! .. _Read the Docs: http://python-nvd3.readthedocs.org + Installation ------------ @@ -119,8 +111,8 @@ Install, upgrade and uninstall python-nvd3 with these commands:: $ pip uninstall python-nvd3 -Dependecies ------------ +Dependencies +------------ D3 and NvD3 can be installed through bower (which itself can be installed through npm). See http://bower.io/ and https://npmjs.org for further information. @@ -132,8 +124,8 @@ Note : you might prefer to save your npm dependencies locally in a ``package.jso Then in the directory where you will use python-nvd3, just execute the following commands:: - $ bower install d3#3.3.8 - $ bower install nvd3#1.1.12-beta + $ bower install d3#3.5.17 + $ bower install nvd3#1.8.6 This will create a directory "bower_components" where d3 & nvd3 will be saved. @@ -161,3 +153,9 @@ License ------- Python-nvd3 is licensed under MIT, see `MIT-LICENSE.txt`. + + +Maintainers +----------- + +If you want to help maintain this project, please get in touch. diff --git a/docs/source/_templates/page.html b/docs/source/_templates/page.html index a58781ee..b6874d6c 100644 --- a/docs/source/_templates/page.html +++ b/docs/source/_templates/page.html @@ -5,9 +5,9 @@ {% endblock %} {% block extrahead %} - - - + + + {% endblock %} {%- block body %} diff --git a/docs/source/classes-doc/examples/NVD3Chart.html b/docs/source/classes-doc/examples/NVD3Chart.html new file mode 100644 index 00000000..5a00bfb5 --- /dev/null +++ b/docs/source/classes-doc/examples/NVD3Chart.html @@ -0,0 +1,4 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html diff --git a/docs/source/classes-doc/examples/bulletChart.html b/docs/source/classes-doc/examples/bulletChart.html new file mode 100644 index 00000000..5a00bfb5 --- /dev/null +++ b/docs/source/classes-doc/examples/bulletChart.html @@ -0,0 +1,4 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html diff --git a/docs/source/classes-doc/examples/cumulativeLineChart.html b/docs/source/classes-doc/examples/cumulativeLineChart.html new file mode 100644 index 00000000..306af9e8 --- /dev/null +++ b/docs/source/classes-doc/examples/cumulativeLineChart.html @@ -0,0 +1,62 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/discreteBarChart.html b/docs/source/classes-doc/examples/discreteBarChart.html new file mode 100644 index 00000000..2edf0818 --- /dev/null +++ b/docs/source/classes-doc/examples/discreteBarChart.html @@ -0,0 +1,58 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/lineChart.html b/docs/source/classes-doc/examples/lineChart.html new file mode 100644 index 00000000..e86db5a6 --- /dev/null +++ b/docs/source/classes-doc/examples/lineChart.html @@ -0,0 +1,71 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/linePlusBarChart.html b/docs/source/classes-doc/examples/linePlusBarChart.html new file mode 100644 index 00000000..9d03f2d4 --- /dev/null +++ b/docs/source/classes-doc/examples/linePlusBarChart.html @@ -0,0 +1,70 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/lineWithFocusChart.html b/docs/source/classes-doc/examples/lineWithFocusChart.html new file mode 100644 index 00000000..77dc3263 --- /dev/null +++ b/docs/source/classes-doc/examples/lineWithFocusChart.html @@ -0,0 +1,67 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/multiBarChart.html b/docs/source/classes-doc/examples/multiBarChart.html new file mode 100644 index 00000000..f3716400 --- /dev/null +++ b/docs/source/classes-doc/examples/multiBarChart.html @@ -0,0 +1,57 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/multiBarHorizontalChart.html b/docs/source/classes-doc/examples/multiBarHorizontalChart.html new file mode 100644 index 00000000..9bca3f85 --- /dev/null +++ b/docs/source/classes-doc/examples/multiBarHorizontalChart.html @@ -0,0 +1,59 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/multiChart.html b/docs/source/classes-doc/examples/multiChart.html new file mode 100644 index 00000000..5a00bfb5 --- /dev/null +++ b/docs/source/classes-doc/examples/multiChart.html @@ -0,0 +1,4 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html diff --git a/docs/source/classes-doc/examples/pieChart.html b/docs/source/classes-doc/examples/pieChart.html new file mode 100644 index 00000000..5bd122b9 --- /dev/null +++ b/docs/source/classes-doc/examples/pieChart.html @@ -0,0 +1,62 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/scatterChart.html b/docs/source/classes-doc/examples/scatterChart.html new file mode 100644 index 00000000..d8addb51 --- /dev/null +++ b/docs/source/classes-doc/examples/scatterChart.html @@ -0,0 +1,68 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/classes-doc/examples/stackedAreaChart.html b/docs/source/classes-doc/examples/stackedAreaChart.html new file mode 100644 index 00000000..7ed41e75 --- /dev/null +++ b/docs/source/classes-doc/examples/stackedAreaChart.html @@ -0,0 +1,57 @@ +.. + _Generated with generated_examples.sh script + +.. raw:: html + +
+ + + + diff --git a/docs/source/includes/introduction.txt b/docs/source/includes/introduction.txt index 414241ec..a32fe22f 100644 --- a/docs/source/includes/introduction.txt +++ b/docs/source/includes/introduction.txt @@ -52,9 +52,9 @@ After installation use python-nvd3 as follows :: # Open File to write the D3 Graph output_file = open('test-nvd3.html', 'w') - type = 'pieChart' - chart = pieChart(name=type, color_category='category20c', height=450, width=450) - chart.set_containerheader("\n\n

" + type + "

\n\n") + chart_name = 'pieChart' + chart = pieChart(name=chart_name, color_category='category20c', height=450, width=450) + chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] ydata = [3, 4, 0, 1, 5, 7, 3] diff --git a/docs/source/index.rst b/docs/source/index.rst index 2915604c..30f22f45 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,8 +25,8 @@ These graphs can be part of your web application: Want to try it yourself? Install python-nvd3, enter your python shell and try this quick demo:: >>> from nvd3 import pieChart - >>> type = 'pieChart' - >>> chart = pieChart(name=type, color_category='category20c', height=450, width=450) + >>> chart_name = 'pieChart' + >>> chart = pieChart(name=chart_name, color_category='category20c', height=450, width=450) >>> xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] >>> ydata = [3, 4, 0, 1, 5, 7, 3] >>> extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} diff --git a/examples/cumulativeLineChart.py b/examples/cumulativeLineChart.py index d0864fd3..63ae11ec 100644 --- a/examples/cumulativeLineChart.py +++ b/examples/cumulativeLineChart.py @@ -21,9 +21,9 @@ # Open File for test output_file = open('test_cumulativeLineChart.html', 'w') -type = "cumulativeLineChart" -chart = cumulativeLineChart(name=type, height=350, x_is_date=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "cumulativeLineChart" +chart = cumulativeLineChart(name=chart_name, height=350, x_is_date=True) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] diff --git a/examples/demo_all.py b/examples/demo_all.py index bf43f7b0..8886a4c1 100644 --- a/examples/demo_all.py +++ b/examples/demo_all.py @@ -35,19 +35,19 @@ - - - - + + + + """ output_file.write(html_open) -type = "discreteBarChart" +chart_name = "discreteBarChart" chart = discreteBarChart(name='my graphname', height=400, width=800, jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = ["A", "B", "C", "D", "E", "F", "G"] ydata = [3, 12, -10, 5, 25, -7, 2] @@ -58,10 +58,10 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "pie Chart" -chart = pieChart(name=type, color_category='category20c', height=400, +chart_name = "pie Chart" +chart = pieChart(name=chart_name, color_category='category20c', height=400, width=400, jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") color_list = ['orange', 'yellow', '#C5E946', '#95b43f', 'red', '#FF2259', '#F6A641'] extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}, "color_list": color_list} @@ -74,7 +74,7 @@ # --------------------------------------- name = "lineChart-different-x-axis" -type = "lineChart" +chart_name = "lineChart" chart = lineChart(name=name, height=400, width=800, x_is_date=False, jquery_on_ready=True) @@ -98,11 +98,11 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "lineChart" +chart_name = "lineChart" chart = lineChart(height=400, width=800, x_is_date=True, x_axis_format="%d %b %Y %H", jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] ydata = [i + random.randint(1, 10) for i in range(nb_element)] @@ -123,12 +123,12 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "lineChartWithInteractiveGuideline" +chart_name = "lineChartWithInteractiveGuideline" chart = lineChart(name="lineChart-With-Interactive-Guideline", height=400, width=800, x_is_date=True, x_axis_format="%d %b %Y %H", jquery_on_ready=True, use_interactive_guideline=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] ydata = [i + random.randint(1, 10) for i in range(nb_element)] @@ -149,11 +149,11 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "lineWithFocusChart" +chart_name = "lineWithFocusChart" chart = lineWithFocusChart(color_category='category20b', x_is_date=True, height=400, width=800, x_axis_format="%d %b %Y", jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] @@ -177,10 +177,10 @@ # --------------------------------------- -type = "stackedAreaChart" +chart_name = "stackedAreaChart" chart = stackedAreaChart(height=400, width=800, x_is_date=True, x_axis_format="%d %b %Y %I", jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] @@ -197,11 +197,11 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "linePlusBarChart" +chart_name = "linePlusBarChart" chart = linePlusBarChart(height=400, width=800, x_is_date=True, x_axis_format="%d %b %Y", jquery_on_ready=True, focus_enable=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] @@ -219,11 +219,11 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "cumulativeLineChart" +chart_name = "cumulativeLineChart" chart = cumulativeLineChart(height=400, width=800, x_is_date=True, x_axis_format="%d %b %Y", jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] @@ -240,9 +240,9 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "multiBarHorizontalChart" +chart_name = "multiBarHorizontalChart" chart = multiBarHorizontalChart(height=400, width=800, jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 10 xdata = list(range(nb_element)) @@ -258,9 +258,9 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "multiBarChart" +chart_name = "multiBarChart" chart = multiBarChart(height=400, width=800, jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 10 xdata = list(range(nb_element)) ydata = [random.randint(1, 10) for i in range(nb_element)] @@ -275,9 +275,9 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "multiBarChartDate" -chart = multiBarChart(name=type, height=400, width=800, x_is_date=True, jquery_on_ready=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "multiBarChartDate" +chart = multiBarChart(name=chart_name, height=400, width=800, x_is_date=True, jquery_on_ready=True) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 100 start_time = int(time.mktime(datetime.datetime(2012, 6, 1).timetuple()) * 1000) xdata = range(nb_element) @@ -297,9 +297,9 @@ output_file.write(chart.htmlcontent) # --------------------------------------- -type = "scatterChart" -chart = scatterChart(name=type, height=350, width=800, x_is_date=False) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "scatterChart" +chart = scatterChart(name=chart_name, height=350, width=800, x_is_date=False) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 50 xdata = [i + random.randint(1, 10) for i in range(nb_element)] ydata = [i * random.randint(1, 10) for i in range(nb_element)] diff --git a/examples/discreteBarChart.py b/examples/discreteBarChart.py index 533d61e0..776a47b0 100644 --- a/examples/discreteBarChart.py +++ b/examples/discreteBarChart.py @@ -15,9 +15,28 @@ # Open File for test output_file = open('test_discreteBarChart.html', 'w') -type = "discreteBarChart" -chart = discreteBarChart(name='mygraphname', height=400, width=600) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "discreteBarChart" +chart = discreteBarChart(name='mygraphname', height=400, width=600, show_values=True, extras="d3.selectAll('#mygraphname text').style('fill', 'red')") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") +xdata = ["A", "B", "C", "D", "E", "F", "G"] +ydata = [3, 12, -10, 5, 25, -7, 2] + +extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} +chart.add_serie(y=ydata, x=xdata, extra=extra_serie) + +chart.buildhtml() +output_file.write(chart.htmlcontent) +# --------------------------------------- + +# close Html file +output_file.close() + +output_file = open('test_discreteBarChart2.html', 'w') + +chart_name = "discreteBarChart" +chart = discreteBarChart(name='mygraphname', height=400, width=600, + tooltips=False) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = ["A", "B", "C", "D", "E", "F", "G"] ydata = [3, 12, -10, 5, 25, -7, 2] diff --git a/examples/discreteBarChart_with_date.py b/examples/discreteBarChart_with_date.py index f8798657..ebafafd4 100644 --- a/examples/discreteBarChart_with_date.py +++ b/examples/discreteBarChart_with_date.py @@ -18,7 +18,7 @@ # Open File for test output_file = open('test_discreteBarChart_with_date.html', 'w') -type = "discreteBarChart" +chart_name = "discreteBarChart" start_time = int(time.mktime(datetime.datetime(2012, 6, 1).timetuple()) * 1000) nb_element = 10 @@ -27,8 +27,8 @@ xdata = [start_time + x * 1000000000 for x in xdata] ydata = [i + random.randint(1, 10) for i in range(nb_element)] -chart = discreteBarChart(name=type, height=400, width=600, x_is_date=True, x_axis_format="%d-%b") -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart = discreteBarChart(name=chart_name, height=400, width=600, x_is_date=True, x_axis_format="%d-%b") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} chart.add_serie(y=ydata, x=xdata, extra=extra_serie) diff --git a/examples/ipythonDemo.ipynb b/examples/ipythonDemo.ipynb index f2f5dd1c..46637d73 100644 --- a/examples/ipythonDemo.ipynb +++ b/examples/ipythonDemo.ipynb @@ -86,8 +86,8 @@ }, "outputs": [], "source": [ - "type = 'stackedAreaChart'\n", - "chart2 = nvd3.stackedAreaChart(name=type,height=450,width=500, \n", + "chart_name = 'stackedAreaChart'\n", + "chart2 = nvd3.stackedAreaChart(name=chart_name,height=450,width=500, \n", " use_interactive_guideline=True)\n", "nb_element = 50\n", "xdata = range(nb_element)\n", @@ -142,9 +142,9 @@ }, "outputs": [], "source": [ - "type = 'pieChart'\n", - "chart1 = nvd3.pieChart(name=type, color_category='category20c', height=450, width=450)\n", - "chart1.set_containerheader(\"\\n\\n

\" + type + \"

\\n\\n\")\n", + "chart_name = 'pieChart'\n", + "chart1 = nvd3.pieChart(name=chart_name, color_category='category20c', height=450, width=450)\n", + "chart1.set_containerheader(\"\\n\\n

\" + chart_name + \"

\\n\\n\")\n", "\n", "#Create the keys\n", "xdata = [\"Orange\", \"Banana\", \"Pear\", \"Kiwi\", \"Apple\", \"Strawberry\", \"Pineapple\"]\n", diff --git a/examples/lineChart.py b/examples/lineChart.py index 1dce1b9a..053b7e76 100644 --- a/examples/lineChart.py +++ b/examples/lineChart.py @@ -14,8 +14,8 @@ # Open File for test output_file = open('test_lineChart.html', 'w') # --------------------------------------- -type = "lineChart" -chart = lineChart(name=type, x_is_date=False, x_axis_format="AM_PM") +chart_name = "lineChart" +chart = lineChart(name=chart_name, x_is_date=False, x_axis_format="AM_PM") xdata = list(range(0, 24)) ydata = [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 4, 3, 3, 5, 7, 5, 3, 16, 6, 9, 15, 4, 12] diff --git a/examples/lineChartXY.py b/examples/lineChartXY.py index f74a1a9a..1e8ae2d8 100644 --- a/examples/lineChartXY.py +++ b/examples/lineChartXY.py @@ -14,8 +14,8 @@ output_file = open('test_lineChartXY.html', 'w') -type = "lineChart" -chart = lineChart(name=type, x_is_date=False, +chart_name = "lineChart" +chart = lineChart(name=chart_name, x_is_date=False, x_axis_format=".1f", y_axis_format=".1f", width=500, height=500, show_legend=False) diff --git a/examples/linePlusBarChart.py b/examples/linePlusBarChart.py index 3dbeba71..f8981df7 100644 --- a/examples/linePlusBarChart.py +++ b/examples/linePlusBarChart.py @@ -20,11 +20,11 @@ output_file = open('test_linePlusBarChart.html', 'w') -type = "linePlusBarChart" -chart = linePlusBarChart(name=type, height=350, width=750, +chart_name = "linePlusBarChart" +chart = linePlusBarChart(name=chart_name, height=350, width=750, x_is_date=True, x_axis_format="%d %b %Y", focus_enable=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] diff --git a/examples/lineWithFocusChart.py b/examples/lineWithFocusChart.py index 7d765019..bd71dfee 100644 --- a/examples/lineWithFocusChart.py +++ b/examples/lineWithFocusChart.py @@ -21,11 +21,11 @@ # Open File for test output_file = open('test_lineWithFocusChart.html', 'w') # --------------------------------------- -type = "lineWithFocusChart" -chart = lineWithFocusChart(name=type, height=550, width=850, +chart_name = "lineWithFocusChart" +chart = lineWithFocusChart(name=chart_name, height=550, width=850, color_category='category20b', x_is_date=True, x_axis_format="%d %b %Y %H", focus_enable=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") xdata = list(range(nb_element)) xdata = [start_time + x * 1000000000 for x in xdata] diff --git a/examples/multiBarChart.py b/examples/multiBarChart.py index 709e662d..d07876e9 100644 --- a/examples/multiBarChart.py +++ b/examples/multiBarChart.py @@ -15,10 +15,21 @@ # Open File for test output_file = open('test_multiBarChart.html', 'w') -type = "multiBarChart" -chart = multiBarChart(name=type, height=350) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "multiBarChart" +chart = multiBarChart(name=chart_name, height=350) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") +chart.callback = ''' + function(){ + d3.selectAll(".nv-bar").on('click', + function(d){ + console.log("barchart_callback_test: clicked on bar " + JSON.stringify(d)); + console.log('/app/call?x='.concat(d['x'])); + } + ''' nb_element = 10 + +# On multiBarChart the xdata needs to be numeric, +# if you want to use 'string' you should use discreteBarChart xdata = list(range(nb_element)) ydata = [random.randint(1, 10) for i in range(nb_element)] ydata2 = [x * 2 for x in ydata] diff --git a/examples/multiBarChart_date.py b/examples/multiBarChart_date.py index 39a12cd5..a4b65179 100644 --- a/examples/multiBarChart_date.py +++ b/examples/multiBarChart_date.py @@ -17,10 +17,10 @@ # Open File for test output_file = open('test_multiBarChart_date.html', 'w') -type = "multiBarChart" +chart_name = "multiBarChart" -chart = multiBarChart(name=type, height=350, x_is_date=True) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart = multiBarChart(name=chart_name, height=350, x_is_date=True) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 100 start_time = int(time.mktime(datetime.datetime(2013, 6, 1).timetuple()) * 1000) diff --git a/examples/multiBarHorizontalChart.py b/examples/multiBarHorizontalChart.py index c8b5c790..cd03fa9a 100644 --- a/examples/multiBarHorizontalChart.py +++ b/examples/multiBarHorizontalChart.py @@ -15,9 +15,9 @@ # Open File for test output_file = open('test_multiBarHorizontalChart.html', 'w') -type = "multiBarHorizontalChart" -chart = multiBarHorizontalChart(name=type, height=350) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "multiBarHorizontalChart" +chart = multiBarHorizontalChart(name=chart_name, height=350) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 10 xdata = list(range(nb_element)) diff --git a/examples/multiChart.py b/examples/multiChart.py new file mode 100644 index 00000000..f1960e5c --- /dev/null +++ b/examples/multiChart.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Examples for Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from nvd3 import multiChart + +# Open File for test +output_file = open('test_multiChart.html', 'w') +# --------------------------------------- +chart_name = "multiChart" +chart = multiChart(name=chart_name, x_is_date=False, x_axis_format="AM_PM") + +xdata = [1,2,3,4,5,6] +ydata = [115.5,160.5,108,145.5,84,70.5] +ydata2 = [48624,42944,43439,24194,38440,31651] + +kwargs1 = {'color': 'black'} +kwargs2 = {'color': 'red'} +extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"}} +chart.add_serie(y=ydata, x=xdata, type='line', yaxis=1, name='visits', extra=extra_serie, **kwargs1) +extra_serie = {"tooltip": {"y_start": "", "y_end": " min"}} +chart.add_serie(y=ydata2, x=xdata, type='bar', yaxis=2,name='spend', extra=extra_serie, **kwargs2) + +chart.buildhtml() + +output_file.write(chart.htmlcontent) + +# close Html file +output_file.close() diff --git a/examples/pieChart.py b/examples/pieChart.py index ed92f3e0..207695f4 100644 --- a/examples/pieChart.py +++ b/examples/pieChart.py @@ -15,9 +15,17 @@ # Open File for test output_file = open('test_pieChart.html', 'w') -type = "pieChart" -chart = pieChart(name=type, color_category='category20c', height=400, width=400) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "pieChart" +chart = pieChart(name=chart_name, color_category='category20c', height=400, width=400, extras="d3.selectAll('#piechart .nv-slice').style('opacity', 0.5);") +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") +chart.callback = ''' + function(){ + d3.selectAll(".nv-pie .nv-pie .nv-slice").on('click', + function(d){ + console.log("piechart_callback_test: clicked on slice " + JSON.stringify(d['data'])); + console.log('/app/fruit?type='.concat(d['data']['label'])); + } + ''' extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] diff --git a/examples/scatterChart.py b/examples/scatterChart.py index 51338907..97c70af8 100644 --- a/examples/scatterChart.py +++ b/examples/scatterChart.py @@ -15,9 +15,9 @@ # Open File for test output_file = open('test_scatterChart.html', 'w') -type = "scatterChart" -chart = scatterChart(name=type, height=350, width=800, x_is_date=False) -chart.set_containerheader("\n\n

" + type + "

\n\n") +chart_name = "scatterChart" +chart = scatterChart(name=chart_name, height=350, width=800, x_is_date=False) +chart.set_containerheader("\n\n

" + chart_name + "

\n\n") nb_element = 50 xdata = [i + random.randint(1, 10) for i in range(nb_element)] ydata = [i * random.randint(1, 10) for i in range(nb_element)] diff --git a/generate_examples.sh b/generate_examples.sh new file mode 100755 index 00000000..eda09418 --- /dev/null +++ b/generate_examples.sh @@ -0,0 +1,10 @@ +#!/bin/bash +mkdir "docs/source/classes-doc/examples/" +for file in nvd3/*Chart.py; do + html_filename="docs/source/classes-doc/examples/"`echo $file | sed "s/.*\///" | sed "s/\.py//"`".html" + echo $html_filename + echo -e "..\n _Generated with generated_examples.sh script\n\n.. raw:: html" > $html_filename + + cat $file | grep "Python example" -A1000 | grep -E "Javascript generated|Note that in case you" -m 1 -B 1000 | tail -n+2 | head -n-1 | sed "s/^[ \t]*//g" | python | sed "s/^/ /" >> $html_filename +done + diff --git a/nvd3/NVD3Chart.py b/nvd3/NVD3Chart.py index 66699363..83c0666c 100644 --- a/nvd3/NVD3Chart.py +++ b/nvd3/NVD3Chart.py @@ -45,7 +45,7 @@ class NVD3Chart(object): #: directory holding the assets (bower_components) assets_directory = './bower_components/' - # this attribute is overriden by children of this + # this attribute is overridden by children of this # class CHART_FILENAME = None template_environment = Environment(lstrip_blocks=True, trim_blocks=True, @@ -71,9 +71,16 @@ def __init__(self, **kwargs): :keyword: **margin_top** - default - ``30`` :keyword: **height** - default - ``''`` :keyword: **width** - default - ``''`` + :keyword: **show_values** - default - ``False`` :keyword: **stacked** - default - ``False`` :keyword: **focus_enable** - default - ``False`` :keyword: **resize** - define - ``False`` + :keyword: **no_data_message** - default - ``None`` or nvd3 default + :keyword: **xAxis_rotateLabel** - default - ``0`` + :keyword: **xAxis_staggerLabel** - default - ``False`` + :keyword: **xAxis_showMaxMin** - default - ``True`` + :keyword: **right_align_y_axis** - default - ``False`` + :keyword: **show_controls** - default - ``True`` :keyword: **show_legend** - default - ``True`` :keyword: **show_labels** - default - ``True`` :keyword: **tag_script_js** - default - ``True`` @@ -87,6 +94,8 @@ def __init__(self, **kwargs): Signal that x axis is a date axis :keyword: **date_format** - default - ``%x`` see https://github.com/mbostock/d3/wiki/Time-Formatting + :keyword: **y_axis_scale_min** - default - ``''``. + :keyword: **y_axis_scale_max** - default - ``''``. :keyword: **x_axis_format** - default - ``''``. :keyword: **y_axis_format** - default - ``''``. :keyword: **style** - default - ``''`` @@ -118,11 +127,19 @@ def __init__(self, **kwargs): self.margin_top = kwargs.get('margin_top', 30) self.height = kwargs.get('height', '') self.width = kwargs.get('width', '') + self.show_values = kwargs.get('show_values', False) self.stacked = kwargs.get('stacked', False) self.focus_enable = kwargs.get('focus_enable', False) self.resize = kwargs.get('resize', False) + self.no_data_message = kwargs.get('no_data_message', None) + self.xAxis_rotateLabel = kwargs.get('xAxis_rotateLabel', 0) + self.xAxis_staggerLabel = kwargs.get('xAxis_staggerLabel', False) + self.xAxis_showMaxMin = kwargs.get('xAxis_showMaxMin', True) + self.right_align_y_axis = kwargs.get('right_align_y_axis', False) + self.show_controls = kwargs.get('show_controls', True) self.show_legend = kwargs.get('show_legend', True) self.show_labels = kwargs.get('show_labels', True) + self.tooltip_separator = kwargs.get('tooltip_separator') self.tag_script_js = kwargs.get('tag_script_js', True) self.use_interactive_guideline = kwargs.get("use_interactive_guideline", False) @@ -131,12 +148,15 @@ def __init__(self, **kwargs): self.style = kwargs.get('style', '') self.date_format = kwargs.get('date_format', '%x') self.x_axis_date = kwargs.get('x_axis_date', False) + self.y_axis_scale_min = kwargs.get('y_axis_scale_min', '') + self.y_axis_scale_max = kwargs.get('y_axis_scale_max', '') #: x-axis contain date format or not # possible duplicate of x_axis_date self.date_flag = kwargs.get('date_flag', False) self.x_axis_format = kwargs.get('x_axis_format', '') # Load remote JS assets or use the local bower assets? self.remote_js_assets = kwargs.get('remote_js_assets', True) + self.callback = kwargs.get('callback', None) # None keywords attribute that should be modified by methods # We should change all these to _attr @@ -153,22 +173,21 @@ def __init__(self, **kwargs): self.header_css = [ '' % h for h in ( - 'https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.css' if self.remote_js_assets else self.assets_directory + 'nvd3/src/nv.d3.css', + 'https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css' if self.remote_js_assets else self.assets_directory + 'nvd3/src/nv.d3.css', ) ] self.header_js = [ '' % h for h in ( - 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js' if self.remote_js_assets else self.assets_directory + 'd3/d3.min.js', - 'https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.js' if self.remote_js_assets else self.assets_directory + 'nvd3/nv.d3.min.js' + 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js' if self.remote_js_assets else self.assets_directory + 'd3/d3.min.js', + 'https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.js' if self.remote_js_assets else self.assets_directory + 'nvd3/nv.d3.min.js' ) ] #: Javascript code as string self.jschart = None self.custom_tooltip_flag = False - self.tooltip_condition_string = '' self.charttooltip = '' self.serie_no = 1 @@ -267,27 +286,11 @@ def add_serie(self, y, x, name=None, extra=None, **kwargs): _start = ("'" + str(_start) + "' + ") if _start else '' _end = (" + '" + str(_end) + "'") if _end else '' - if self.model == 'linePlusBarChart': - if self.tooltip_condition_string: - self.tooltip_condition_string += stab(5) - self.tooltip_condition_string += stab(0) + "if(key.indexOf('" + name + "') > -1 ){\n" +\ - stab(6) + "var y = " + _start + " String(graph.point.y) " + _end + ";\n" +\ - stab(5) + "}\n" - elif self.model == 'cumulativeLineChart': - self.tooltip_condition_string += stab(0) + "if(key == '" + name + "'){\n" +\ - stab(6) + "var y = " + _start + " String(e) " + _end + ";\n" +\ - stab(5) + "}\n" - else: - self.tooltip_condition_string += stab(5) + "if(key == '" + name + "'){\n" +\ - stab(6) + "var y = " + _start + " String(graph.point.y) " + _end + ";\n" +\ - stab(5) + "}\n" - if self.model == 'pieChart': _start = extra['tooltip']['y_start'] _end = extra['tooltip']['y_end'] _start = ("'" + str(_start) + "' + ") if _start else '' _end = (" + '" + str(_end) + "'") if _end else '' - self.tooltip_condition_string += "var y = " + _start + " String(y) " + _end + ";\n" # Increment series counter & append self.serie_no += 1 @@ -349,7 +352,7 @@ def __str__(self): def buildcontent(self): """Build HTML content only, no header or body tags. To be useful this - will usually require the attribute `juqery_on_ready` to be set which + will usually require the attribute `jquery_on_ready` to be set which will wrap the js in $(function(){};) """ self.buildcontainer() @@ -408,11 +411,6 @@ def buildjschart(self): """generate javascript code for the chart""" self.jschart = '' - # add custom tooltip string in jschart - # default condition (if build_custom_tooltip is not called explicitly with date_flag=True) - if self.tooltip_condition_string == '': - self.tooltip_condition_string = 'var y = String(graph.point.y);\n' - # Include data self.series_js = json.dumps(self.series) @@ -473,7 +471,7 @@ class TemplateMixin(object): """ def buildcontent(self): """Build HTML content only, no header or body tags. To be useful this - will usually require the attribute `juqery_on_ready` to be set which + will usually require the attribute `jquery_on_ready` to be set which will wrap the js in $(function(){};) """ self.buildcontainer() diff --git a/nvd3/__init__.py b/nvd3/__init__.py index 5b737b45..71823c58 100755 --- a/nvd3/__init__.py +++ b/nvd3/__init__.py @@ -9,11 +9,12 @@ Project location : https://github.com/areski/python-nvd3 """ -__version__ = '0.15.0' +__version__ = '0.16.0' __all__ = ['lineChart', 'pieChart', 'lineWithFocusChart', 'stackedAreaChart', 'multiBarHorizontalChart', 'linePlusBarChart', 'cumulativeLineChart', - 'scatterChart', 'discreteBarChart', 'multiBarChart'] + 'scatterChart', 'discreteBarChart', 'multiBarChart', + 'bulletChart', 'multiChart'] from .lineChart import lineChart @@ -26,4 +27,6 @@ from .scatterChart import scatterChart from .discreteBarChart import discreteBarChart from .multiBarChart import multiBarChart +from .bulletChart import bulletChart +from .multiChart import multiChart from . import ipynb diff --git a/nvd3/bulletChart.py b/nvd3/bulletChart.py new file mode 100644 index 00000000..867c2e1a --- /dev/null +++ b/nvd3/bulletChart.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart, TemplateMixin + + +class bulletChart(TemplateMixin, NVD3Chart): + ''' + A bullet chart is a variation of a bar graph + used to indicate the value of a single variable + in relation to a set of qualitative ranges. It is + inspired by a dashboard gauge or thermometer chart. + + Python example: + + from nvd3.bulletChart import bulletChart + chart = bulletChart.bulletChart(name=chart_name, height=100, width=500) + title = 'Revenue', + subtitle = 'US$, in thousands' + ranges = [150, 225, 300] + measures = [220, 270] + markers = [250] + chart.add_serie( + title=title, + subtitle=subtitle, + ranges=ranges, + measures=measures, + markers=markers) + chart.buildhtml() + print(chart.content) + + JavaScript generated: + + .. include:: ./examples/bulletChart.html + + ''' + CHART_FILENAME = './bulletchart.html' + template_chart_nvd3 = NVD3Chart.template_environment.get_template( + CHART_FILENAME) + + def __init__(self, **kwargs): + super(bulletChart, self).__init__(**kwargs) + self.model = 'bulletChart' + + height = kwargs.get('height', None) + width = kwargs.get('width', 200) + + if height: + self.set_graph_height(height) + if width: + self.set_graph_width(width) + + def add_serie(self, ranges, measures, title, subtitle, markers=None, + name=None, **kwargs): + if not name: + name = "Serie %d" % (self.serie_no) + if markers: + serie = [{ + 'title': title, + 'subtitle': subtitle, + 'ranges': ranges, + 'measures': measures, + 'markers': markers + }] + else: + serie = [{ + 'title': title, + 'subtitle': subtitle, + 'ranges': ranges, + 'measures': measures, + }] + data_keyvalue = {'values': serie, 'key': name} + + self.serie_no += 1 + self.series.append(data_keyvalue) diff --git a/nvd3/cumulativeLineChart.py b/nvd3/cumulativeLineChart.py index d98d0867..30c8f6d4 100644 --- a/nvd3/cumulativeLineChart.py +++ b/nvd3/cumulativeLineChart.py @@ -21,7 +21,7 @@ class cumulativeLineChart(TemplateMixin, NVD3Chart): from nvd3 import cumulativeLineChart chart = cumulativeLineChart(name='cumulativeLineChart', x_is_date=True) - xdata = [1365026400000000, 1365026500000000, 1365026600000000] + xdata = [1365026400000, 1365026500000, 1365026600000] ydata = [6, 5, 1] y2data = [36, 55, 11] @@ -31,49 +31,14 @@ class cumulativeLineChart(TemplateMixin, NVD3Chart): extra_serie = {"tooltip": {"y_start": "", "y_end": " mins"}} chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) chart.buildhtml() + print(chart.content) + Javascript generated: - .. raw:: html - -
- + + .. include:: ./examples/cumulativeLineChart.html + """ diff --git a/nvd3/discreteBarChart.py b/nvd3/discreteBarChart.py index cf6c8a4a..1f5792da 100644 --- a/nvd3/discreteBarChart.py +++ b/nvd3/discreteBarChart.py @@ -17,6 +17,7 @@ class discreteBarChart(TemplateMixin, NVD3Chart): A discrete bar chart or bar graph is a chart with rectangular bars with lengths proportional to the values that they represent. + Python example:: from nvd3 import discreteBarChart @@ -27,12 +28,25 @@ class discreteBarChart(TemplateMixin, NVD3Chart): chart.add_serie(y=ydata, x=xdata) chart.buildhtml() + print(chart.content) Javascript generated: + .. include:: ./examples/discreteBarChart.html + + + + You can also disable the tooltips by passing ``tooltips=False`` when + creating the bar chart. + + Python example:: + + chart = discreteBarChart(name='discreteBarChart-notooltip', height=400, width=400, + tooltips=False) + .. raw:: html -
+
- """ CHART_FILENAME = "./discretebarchart.html" template_chart_nvd3 = NVD3Chart.template_environment.get_template(CHART_FILENAME) @@ -89,3 +102,9 @@ def __init__(self, **kwargs): self.set_graph_height(height) if width: self.set_graph_width(width) + + tooltips = kwargs.get('tooltips', True) + + if not tooltips: + self.chart_attr = {'tooltips': 'false'} + diff --git a/nvd3/ipynb.py b/nvd3/ipynb.py index f421afc0..8edb4e83 100644 --- a/nvd3/ipynb.py +++ b/nvd3/ipynb.py @@ -39,9 +39,9 @@ def _setup_ipython_formatter(ip): for chart_type in nvd3_all: html_formatter.for_type_by_name('nvd3.' + chart_type, chart_type, _print_html) - def initialize_javascript(d3_js_url='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js', - nvd3_js_url='https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.js', - nvd3_css_url='https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.css', + def initialize_javascript(d3_js_url='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js', + nvd3_js_url='https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.js', + nvd3_css_url='https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css', use_remote=False): '''Initialize the ipython notebook to be able to display nvd3 results. by instructing IPython to load the nvd3 JS and css files, and the d3 JS file. @@ -52,9 +52,9 @@ def initialize_javascript(d3_js_url='https://cdnjs.cloudflare.com/ajax/libs/d3/3 use_remote: use remote hosts for d3.js, nvd3.js, and nv.d3.css (default False) * Note: the following options are ignored if use_remote is False: - nvd3_css_url: location of nvd3 css file (default https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.css) - nvd3_js_url: location of nvd3 javascript file (default https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.7.0/nv.d3.min.css) - d3_js_url: location of d3 javascript file (default https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js) + nvd3_css_url: location of nvd3 css file (default https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css) + nvd3_js_url: location of nvd3 javascript file (default https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css) + d3_js_url: location of d3 javascript file (default https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js) ''' from IPython.display import display, Javascript, HTML @@ -71,7 +71,7 @@ def initialize_javascript(d3_js_url='https://cdnjs.cloudflare.com/ajax/libs/d3/3 rel="stylesheet"/>''' % (nvd3_css_url))) # The following two methods for loading the script file are redundant. # This is intentional. - # Ipython's loading of javscript in version 1.x is a bit squirrely, especially + # Ipython's loading of javascript in version 1.x is a bit squirrely, especially # when creating demos to view in nbviewer. # by trying twice, in two different ways (one using jquery and one using plain old # HTML), we maximize our chances of successfully loading the script. diff --git a/nvd3/lineChart.py b/nvd3/lineChart.py index c237d069..d114007e 100644 --- a/nvd3/lineChart.py +++ b/nvd3/lineChart.py @@ -28,60 +28,15 @@ class lineChart(TemplateMixin, NVD3Chart): ydata2 = [9, 8, 11, 8, 3, 7, 10, 8, 6, 6, 9, 6, 5, 4, 3, 10, 0, 6, 3, 1, 0, 0, 0, 1] extra_serie = {"tooltip": {"y_start": "There are ", "y_end": " calls"}} - chart.add_serie(y=ydata, x=xdata, name='sine', extra=extra_serie, **kwargs1) + chart.add_serie(y=ydata, x=xdata, name='sine', extra=extra_serie) extra_serie = {"tooltip": {"y_start": "", "y_end": " min"}} - chart.add_serie(y=ydata2, x=xdata, name='cose', extra=extra_serie, **kwargs2) + chart.add_serie(y=ydata2, x=xdata, name='cose', extra=extra_serie) chart.buildhtml() + print(chart.content) - Javascript renderd to: - - .. raw:: html - -
- + Javascript generated: + + .. include:: ./examples/lineChart.html See the source code of this page, to see the underlying javascript. """ diff --git a/nvd3/linePlusBarChart.py b/nvd3/linePlusBarChart.py index 4eaa5fc6..2cfe533b 100644 --- a/nvd3/linePlusBarChart.py +++ b/nvd3/linePlusBarChart.py @@ -39,7 +39,8 @@ class linePlusBarChart(TemplateMixin, NVD3Chart): extra_serie = {"tooltip": {"y_start": "There are ", "y_end": " min"}} chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) - chart.buildcontent() + chart.buildhtml() + print(chart.content) Note that in case you have two data serie with extreme different numbers, that you would like to format in different ways, @@ -51,44 +52,7 @@ class linePlusBarChart(TemplateMixin, NVD3Chart): Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/linePlusBarChart.html """ CHART_FILENAME = "./lineplusbarchart.html" diff --git a/nvd3/lineWithFocusChart.py b/nvd3/lineWithFocusChart.py index cd26cd47..b956d271 100644 --- a/nvd3/lineWithFocusChart.py +++ b/nvd3/lineWithFocusChart.py @@ -23,52 +23,19 @@ class lineWithFocusChart(TemplateMixin, NVD3Chart): from nvd3 import lineWithFocusChart chart = lineWithFocusChart(name='lineWithFocusChart', x_is_date=True, x_axis_format="%d %b %Y") - xdata = [1365026400000000, 1365026500000000, 1365026600000000, 1365026700000000, 1365026800000000, 1365026900000000, 1365027000000000] + xdata = [1365026400000, 1365026500000, 1365026600000, 1365026700000, 1365026800000, 1365026900000, 1365027000000] ydata = [-6, 5, -1, 2, 4, 8, 10] extra_serie = {"tooltip": {"y_start": "", "y_end": " ext"}, "date_format": "%d %b %Y"} chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) chart.buildhtml() + print(chart.content) Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/lineWithFocusChart.html + """ diff --git a/nvd3/multiBarChart.py b/nvd3/multiBarChart.py index cf335919..bab6adda 100644 --- a/nvd3/multiBarChart.py +++ b/nvd3/multiBarChart.py @@ -30,44 +30,11 @@ class multiBarChart(TemplateMixin, NVD3Chart): chart.add_serie(name="Serie 1", y=ydata1, x=xdata) chart.add_serie(name="Serie 2", y=ydata2, x=xdata) chart.buildhtml() + print(chart.content) Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/multiBarChart.html """ diff --git a/nvd3/multiBarHorizontalChart.py b/nvd3/multiBarHorizontalChart.py index ac969c31..0028e86a 100644 --- a/nvd3/multiBarHorizontalChart.py +++ b/nvd3/multiBarHorizontalChart.py @@ -29,58 +29,12 @@ class multiBarHorizontalChart(TemplateMixin, NVD3Chart): extra_serie = {"tooltip": {"y_start": "", "y_end": " calls"}} chart.add_serie(name="Serie 2", y=y2data, x=xdata, extra=extra_serie) - chart.buildcontent() + chart.buildhtml() + print(chart.content) Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/multiBarHorizontalChart.html """ diff --git a/nvd3/multiChart.py b/nvd3/multiChart.py new file mode 100644 index 00000000..2880fd82 --- /dev/null +++ b/nvd3/multiChart.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Python-nvd3 is a Python wrapper for NVD3 graph library. +NVD3 is an attempt to build re-usable charts and chart components +for d3.js without taking away the power that d3.js gives you. + +Project location : https://github.com/areski/python-nvd3 +""" + +from .NVD3Chart import NVD3Chart, TemplateMixin + + +class multiChart(TemplateMixin, NVD3Chart): + + """ + A multiChart is a type of chart which combines several plots of the same or different types. + + Python example:: + + from nvd3 import multiChart + chart_name = "multiChart" + chart = multiChart(name=chart_name, x_is_date=False, x_axis_format="AM_PM") + + xdata = [1,2,3,4,5,6] + ydata = [115.5,160.5,108,145.5,84,70.5] + ydata2 = [48624,42944,43439,24194,38440,31651] + + kwargs1 = {'color': 'black'} + kwargs2 = {'color': 'red'} + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"}} + chart.add_serie(y=ydata, x=xdata, type='line', yaxis=1, name='visits', extra=extra_serie, **kwargs1) + extra_serie = {"tooltip": {"y_start": "", "y_end": " min"}} + chart.add_serie(y=ydata2, x=xdata, type='bar', yaxis=2,name='spend', extra=extra_serie, **kwargs2) + chart.buildhtml() + print(chart.content) + + + Javascript rendered to: + + .. include:: ./examples/multiChart.html + + See the source code of this page, to see the underlying javascript. + """ + CHART_FILENAME = "./multichart.html" + template_chart_nvd3 = NVD3Chart.template_environment.get_template(CHART_FILENAME) + + def __init__(self, **kwargs): + super(multiChart, self).__init__(**kwargs) + self.model = 'multiChart' + + height = kwargs.get('height', 450) + width = kwargs.get('width', None) + + if kwargs.get('x_is_date', False): + self.set_date_flag(True) + self.create_x_axis('xAxis', + format=kwargs.get('x_axis_format', '%d %b %Y'), + date=True) + self.set_custom_tooltip_flag(True) + else: + if kwargs.get('x_axis_format') == 'AM_PM': + self.x_axis_format = format = 'AM_PM' + else: + format = kwargs.get('x_axis_format', 'r') + self.create_x_axis('xAxis', format=format, + custom_format=kwargs.get('x_custom_format', + False)) + self.create_y_axis( + 'yAxis1', + format=kwargs.get('y1_axis_format', '.02f'), + custom_format=kwargs.get('y1_custom_format', False)) + + self.create_y_axis( + 'yAxis2', + format=kwargs.get('y2_axis_format', '.02f'), + custom_format=kwargs.get('y2_custom_format', False)) + + # must have a specified height, otherwise it superimposes both chars + self.set_graph_height(height) + if width: + self.set_graph_width(width) diff --git a/nvd3/pieChart.py b/nvd3/pieChart.py index 1db76bdb..6c513d83 100644 --- a/nvd3/pieChart.py +++ b/nvd3/pieChart.py @@ -32,51 +32,11 @@ class pieChart(TemplateMixin, NVD3Chart): extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}} chart.add_serie(y=ydata, x=xdata, extra=extra_serie) chart.buildhtml() + print(chart.content) Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/pieChart.html """ CHART_FILENAME = "./piechart.html" @@ -99,3 +59,4 @@ def __init__(self, **kwargs): self.set_graph_width(width) self.donut = kwargs.get('donut', False) self.donutRatio = kwargs.get('donutRatio', 0.35) + self.callback = kwargs.get('callback', None) diff --git a/nvd3/scatterChart.py b/nvd3/scatterChart.py index c3a87d29..b622649b 100644 --- a/nvd3/scatterChart.py +++ b/nvd3/scatterChart.py @@ -38,69 +38,11 @@ class scatterChart(TemplateMixin, NVD3Chart): extra_serie = {"tooltip": {"y_start": "", "y_end": " min"}} chart.add_serie(name="series 2", y=ydata2, x=xdata, extra=extra_serie, **kwargs2) chart.buildhtml() + print(chart.content) Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/scatterChart.html """ diff --git a/nvd3/stackedAreaChart.py b/nvd3/stackedAreaChart.py index 8346cd2c..e246176f 100644 --- a/nvd3/stackedAreaChart.py +++ b/nvd3/stackedAreaChart.py @@ -30,47 +30,11 @@ class stackedAreaChart(TemplateMixin, NVD3Chart): chart.add_serie(name="Serie 1", y=ydata, x=xdata, extra=extra_serie) chart.add_serie(name="Serie 2", y=ydata2, x=xdata, extra=extra_serie) chart.buildhtml() + print(chart.content) Javascript generated: - .. raw:: html - -
- + .. include:: ./examples/stackedAreaChart.html """ diff --git a/nvd3/templates/bulletchart.html b/nvd3/templates/bulletchart.html new file mode 100644 index 00000000..985f4239 --- /dev/null +++ b/nvd3/templates/bulletchart.html @@ -0,0 +1,34 @@ +{# This template adds attributes unique + to bulletChart #} + +{% extends 'content.html' %} +{% block body %} + + {% block data %} + {{ super () }} + {% endblock data %} + + function transformedData(){ + return data_bulletchart[0]['values'][0] + } + + + + nv.addGraph(function() { + var chart = nv.models.bulletChart(); + + d3.select('svg') + .datum(transformedData()) + .transition().duration(1000) + .call(chart) + ; + + return chart; + }); + + {% block extras %} + {{ super () }} + {% endblock extras %} +{% endblock body %} + + diff --git a/nvd3/templates/content.html b/nvd3/templates/content.html index 787f39b5..70250c46 100644 --- a/nvd3/templates/content.html +++ b/nvd3/templates/content.html @@ -7,15 +7,17 @@ {% block body %} {% block data %} - data_{{ chart.name }}={{ chart.series_js }}; + data_{{ chart.name }}={{ chart.series_js|striptags }}; {% endblock data %} {% block init %} nv.addGraph(function() { - var chart = nv.models.{{ chart.model }}(){% if chart.use_interactive_guideline %}.useInteractiveGuideline(true){% endif %}; + var chart = nv.models.{{ chart.model }}(){% if chart.use_interactive_guideline %}.useInteractiveGuideline(true){% endif %}{% if not chart.show_controls %}.showControls(false){% endif %}{% if chart.right_align_y_axis %}.rightAlignYAxis(true){% endif %}; chart.margin({top: {{ chart.margin_top }}, right: {{ chart.margin_right }}, bottom: {{ chart.margin_bottom }}, left: {{ chart.margin_left }}}); - + chart.xAxis.rotateLabels({{chart.xAxis_rotateLabel}}) + chart.xAxis.staggerLabels({{chart.xAxis_staggerLabel|lower}}) + chart.xAxis.showMaxMin({{chart.xAxis_showMaxMin|lower}}) var datum = data_{{ chart.name }}; {% if not chart.color_list and chart.color_category %} @@ -23,10 +25,23 @@ {% endif %} {% endblock init %} + {% block rendering_opts %} {% if chart.stacked %} chart.stacked(true); {% endif %} + {% if chart.no_data_message %} + chart.noData('{{chart.no_data_message}}') + {% endif %} + {% if chart.show_controls == False %} + chart.showControls(false); + {% endif %} + {% if chart.show_values %} + chart.showValues(true); + {% endif %} + + {% endblock rendering_opts %} + {% block focus %} {% endblock focus %} @@ -50,23 +65,23 @@ {% if chart.model == 'pieChart' %} {% block pietooltip %} {% endblock pietooltip %} - {% else %} - chart.tooltipContent(function(key, y, e, graph) { - var x = String(graph.point.x); - var y = String(graph.point.y); - {{ chart.tooltip_condition_string }} - tooltip_str = '
'+key+'
' + y + ' at ' + x; - return tooltip_str; - }); {% endif %} {% else %} - chart.tooltipContent(function(key, y, e, graph) { - var x = d3.time.format("{{ chart.charttooltip_dateformat }}")(new Date(parseInt(graph.point.x))); - var y = String(graph.point.y); - {{ chart.tooltip_condition_string }} - tooltip_str = '
'+key+'
' + y + ' on ' + x; - return tooltip_str; - }); + {% if chart.model in ('discreteBarChart', ) %} + chart.tooltip.keyFormatter(function(d, i) { + return d3.time.format("{{ chart.charttooltip_dateformat }}")(new Date(parseInt(d))); + }); + {% endif %} + {% if chart.model in ('linePlusBarChart', 'lineChart', 'multiBarChart', 'cumulativeLineChart', 'lineWithFocusChart') %} + chart.tooltip.headerFormatter(function(d, i) { + return d3.time.format("{{ chart.charttooltip_dateformat }}")(new Date(parseInt(d))); + }); + {% endif %} + {% if chart.model in ('stackedAreaChart', ) %} + chart.interactiveLayer.tooltip.headerFormatter(function(d, i) { + return d3.time.format("{{ chart.charttooltip_dateformat }}")(new Date(parseInt(d))); + }); + {% endif %} {% endif %} {% endif %} {% endblock tooltip %} @@ -80,7 +95,7 @@ {% block custoattr %} {# add custom chart attributes #} {% for attr, value in chart.chart_attr.items() %} - {% if value is string and value.startswith(".") %}: + {% if value is string and value.startswith(".") %} chart.{{ attr }}{{ value }}; {% else %} chart.{{ attr }}({{ value }}); @@ -96,13 +111,19 @@ {% endblock custoattr %} + {% block y_axis_scale %} + {% if chart.y_axis_scale_min or chart.y_axis_scale_max %} + chart.forceY([{{ chart.y_axis_scale_min }},{{ chart.y_axis_scale_max }}]); + {% endif %} + {% endblock y_axis_scale %} + {% block inject %} {# Inject data to D3 #} d3.select('#{{ chart.name }} svg') .datum(datum) .transition().duration(500) {% if chart.width %} - .attr('width', {{ chart.width}}) + .attr('width', '{{ chart.width}}') {% endif %} {% if chart.height %} .attr('height', {{ chart.height}}) @@ -110,9 +131,16 @@ .call(chart); {% endblock inject %} - {# extra chart attributes #} - {% if chart.extras %} - {{ chart.extras }} + {% block extras %} + {# extra chart attributes #} + {% if chart.extras %} + {{ chart.extras }} + {% endif %} + {% endblock extras %} + + {# callback for clicking on charts #} + {% if chart.callback %} + },{{ chart.callback }}); {% endif %} {# closing nv.addGraph #} diff --git a/nvd3/templates/discretebarchart.html b/nvd3/templates/discretebarchart.html index 2e31ae48..adcc38d4 100644 --- a/nvd3/templates/discretebarchart.html +++ b/nvd3/templates/discretebarchart.html @@ -12,10 +12,18 @@ {{super()}} {% endblock init %} + {% block rendering_opts %} + {{super()}} + {% endblock rendering_opts %} + {% block axes %} {{super()}} {% endblock axes %} - + + {% block tooltip %} + {{super()}} + {% endblock tooltip %} + {% block custoattr %} {{super()}} {% endblock custoattr %} @@ -23,7 +31,11 @@ {% block inject %} {{ super() }} {% endblock inject %} - + + {% block extras %} + {{ super () }} + {% endblock extras %} + {% block close %} {{ super() }} {% endblock close %} diff --git a/nvd3/templates/linebarwfocuschart.html b/nvd3/templates/linebarwfocuschart.html index ad4866c8..7e4b9211 100644 --- a/nvd3/templates/linebarwfocuschart.html +++ b/nvd3/templates/linebarwfocuschart.html @@ -4,13 +4,16 @@ {% extends "content.html" %} {% block body %} {% block data %} - data_{{ chart.name }}={{ chart.series_js }}; + data_{{ chart.name }}={{ chart.series_js|striptags }}; {% endblock data %} {% block init %} {{super()}} {% endblock init %} + {% block rendering_opts %} + {{super()}} + {% endblock rendering_opts %} {% block axes %} {{super()}} {% endblock axes %} @@ -49,9 +52,9 @@ {{super()}} {% endblock inject %} - {% if chart.extras %} - {{ chart.extras }} - {% endif %} + {% block extras %} + {{ super () }} + {% endblock extras %} {% block close %} }); diff --git a/nvd3/templates/linechart.html b/nvd3/templates/linechart.html index cf15d330..d22aaa44 100644 --- a/nvd3/templates/linechart.html +++ b/nvd3/templates/linechart.html @@ -12,10 +12,18 @@ {{super()}} {% endblock init %} + {% block rendering_opts %} + {{super()}} + {% endblock rendering_opts %} + {% block axes %} {{super()}} {% endblock axes %} + {% block tooltip %} + {{super()}} + {% endblock tooltip %} + {% if chart.x_axis_format == 'AM_PM' %} function get_am_pm(d){ if (d > 12) { @@ -39,6 +47,10 @@ {{ super() }} {% endblock inject %} + {% block extras %} + {{ super () }} + {% endblock extras %} + {% block close %} {{ super() }} {% endblock close %} diff --git a/nvd3/templates/lineplusbarchart.html b/nvd3/templates/lineplusbarchart.html index 73aeceac..009a7050 100644 --- a/nvd3/templates/lineplusbarchart.html +++ b/nvd3/templates/lineplusbarchart.html @@ -24,6 +24,10 @@ {{super()}} {% endblock axes %} + {% block tooltip %} + {{super()}} + {% endblock tooltip %} + {% block legend %} {{super()}} {% endblock legend %} @@ -36,6 +40,10 @@ {{ super() }} {% endblock inject %} + {% block extras %} + {{ super () }} + {% endblock extras %} + {% block close %} {{ super() }} {% endblock close %} diff --git a/nvd3/templates/multichart.html b/nvd3/templates/multichart.html new file mode 100644 index 00000000..8264b00e --- /dev/null +++ b/nvd3/templates/multichart.html @@ -0,0 +1,55 @@ +{# This template adds attributes unique + to multiChart #} + +{% extends "content.html" %} +{% block body %} + + {% block data %} + {{super()}} + {% endblock data %} + + {% block init %} + {{super()}} + {% endblock init %} + + {% block rendering_opts %} + {{super()}} + {% endblock rendering_opts %} + + {% block axes %} + {{super()}} + {% endblock axes %} + + {% if chart.x_axis_format == 'AM_PM' %} + function get_am_pm(d){ + if (d > 12) { + d = d - 12; return (String(d) + 'PM'); + } + else { + return (String(d) + 'AM'); + } + }; + {% endif %} + + {% block legend %} + {{super()}} + {% endblock legend %} + + {% block custoattr %} + {{super()}} + {% endblock custoattr %} + + {% block inject %} + {{ super() }} + {% endblock inject %} + + {% block extras %} + {{ super () }} + {% endblock extras %} + + {% block close %} + {{ super() }} + {% endblock close %} + +{% endblock body %} + diff --git a/nvd3/templates/piechart.html b/nvd3/templates/piechart.html index a200e6d4..a707ac52 100644 --- a/nvd3/templates/piechart.html +++ b/nvd3/templates/piechart.html @@ -4,7 +4,7 @@ {% extends "content.html" %} {% block body %} - data_{{ chart.name }}={{ chart.series_js }}; + data_{{ chart.name }}={{ chart.series_js|striptags }}; nv.addGraph(function() { var chart = nv.models.{{ chart.model }}(){% if chart.use_interactive_guideline %}.useInteractiveGuideline(true){% endif %}; @@ -15,9 +15,9 @@ chart.color(d3.scale.{{ chart.color_category }}().range()); {% endif %} - chart.tooltipContent(function(key, y, e, graph) { - var x = String(key); - {{ chart.tooltip_condition_string }} + chart.tooltip.contentGenerator(function(d, elem) { + var x = String(d.data.label); + var y = String(d.data.value); tooltip_str = '
'+x+'
' + y; return tooltip_str; }); @@ -69,10 +69,30 @@ chart.color(mycolor); {% endif %} + {% block rendering_opts %} + {% if chart.no_data_message %} + chart.noData('{{chart.no_data_message}}') + {% endif %} + {% if chart.show_controls == False %} + chart.showControls(false); + {% endif %} + {% endblock rendering_opts %} + {% block inject %} {{super()}} {% endblock inject %} + {% block extras %} + {# extra chart attributes #} + {% if chart.extras %} + {{ chart.extras }} + {% endif %} + {% endblock extras %} + + {% if chart.callback %} + },{{ chart.callback }}); + {% endif %} + {% block close %} {{ super() }} {% endblock close %} diff --git a/nvd3/templates/scatterchart.html b/nvd3/templates/scatterchart.html index 8c2adaae..0a88a06c 100644 --- a/nvd3/templates/scatterchart.html +++ b/nvd3/templates/scatterchart.html @@ -12,6 +12,10 @@ {{super()}} {% endblock init %} + {% block rendering_opts %} + {{super()}} + {% endblock rendering_opts %} + {% block axes %} {{super()}} {% endblock axes %} @@ -45,6 +49,10 @@ {{ super() }} {% endblock inject %} + {% block extras %} + {{ super () }} + {% endblock extras %} + {% block close %} {{ super() }} {% endblock close %} diff --git a/setup.py b/setup.py index 4b658697..27a2741e 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ setup( name='python-nvd3', - version='0.15.0', + version='0.16.0', description="Python NVD3 - Chart Library for d3.js", long_description=readme + '\n\n' + history, keywords='plot, graph, nvd3, d3', @@ -61,6 +61,13 @@ 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Topic :: Multimedia :: Graphics :: Presentation', 'Topic :: Software Development :: Libraries :: Python Modules', ], diff --git a/tests.py b/tests.py index 861268ab..2f3d80dc 100644 --- a/tests.py +++ b/tests.py @@ -11,6 +11,8 @@ from nvd3 import discreteBarChart from nvd3 import pieChart from nvd3 import multiBarChart +from nvd3 import multiChart +from nvd3 import bulletChart from nvd3.NVD3Chart import stab from nvd3.translator import Function, AnonymousFunction, Assignment import random @@ -30,8 +32,8 @@ def test_chartWithBadName(self): def test_lineWithFocusChart(self): """Test Line With Focus Chart""" - type = "lineWithFocusChart" - chart = lineWithFocusChart(name=type, date=True, height=350) + chart_name = "lineWithFocusChart" + chart = lineWithFocusChart(name=chart_name, date=True, height=350) nb_element = 100 xdata = list(range(nb_element)) xdata = [1365026400000 + x * 100000 for x in xdata] @@ -43,8 +45,8 @@ def test_lineWithFocusChart(self): def test_lineChart(self): """Test Line Chart""" - type = "lineChart" - chart = lineChart(name=type, date=True, height=350) + chart_name = "lineChart" + chart = lineChart(name=chart_name, date=True, height=350) nb_element = 100 xdata = list(range(nb_element)) xdata = [1365026400000 + x * 100000 for x in xdata] @@ -59,8 +61,8 @@ def test_lineChart(self): def test_lineChart_tooltip(self): """Test Line Chart""" - type = "lineChart" - chart = lineChart(name=type, date=True, height=350) + chart_name = "lineChart" + chart = lineChart(name=chart_name, date=True, height=350) nb_element = 100 xdata = list(range(nb_element)) xdata = [1365026400000 + x * 100000 for x in xdata] @@ -77,10 +79,12 @@ def test_lineChart_tooltip(self): chart.buildhtml() + assert(".tickFormat(d3.format(',.02f'));" in chart.htmlcontent) + def test_linePlusBarChart(self): """Test line Plus Bar Chart""" - type = "linePlusBarChart" - chart = linePlusBarChart(name=type, date=True, height=350) + chart_name = "linePlusBarChart" + chart = linePlusBarChart(name=chart_name, date=True, height=350) start_time = int(time.mktime(datetime.datetime(2012, 6, 1).timetuple()) * 1000) nb_element = 100 xdata = list(range(nb_element)) @@ -95,8 +99,8 @@ def test_linePlusBarChart(self): def test_stackedAreaChart(self): """Test Stacked Area Chart""" - type = "stackedAreaChart" - chart = stackedAreaChart(name=type, height=400) + chart_name = "stackedAreaChart" + chart = stackedAreaChart(name=chart_name, height=400) nb_element = 100 xdata = list(range(nb_element)) xdata = [100 + x for x in xdata] @@ -108,8 +112,8 @@ def test_stackedAreaChart(self): def test_MultiBarChart(self): """Test Multi Bar Chart""" - type = "MultiBarChart" - chart = multiBarChart(name=type, height=400) + chart_name = "MultiBarChart" + chart = multiBarChart(name=chart_name, height=400) nb_element = 10 xdata = list(range(nb_element)) ydata = [random.randint(1, 10) for i in range(nb_element)] @@ -117,10 +121,34 @@ def test_MultiBarChart(self): chart.add_serie(y=ydata, x=xdata, extra=extra) chart.buildhtml() + def test_multiChart(self): + """Test Multi (line plus bar) Chart""" + chart_name = "multiChart" + chart = multiChart( + name=chart_name, x_is_date=False, x_axis_format="AM_PM", + no_data_message='custom message shows when there is no data', + xAxis_staggerLabel=True + ) + + xdata = [1,2,3,4,5,6] + ydata = [115.5,160.5,108,145.5,84,70.5] + ydata2 = [48624,42944,43439,24194,38440,31651] + kwargs1 = {'color': 'brown'} + kwargs2 = {'color': '#bada55'} + extra_serie = {"tooltip": {"y_start": "There is ", "y_end": " calls"}} + chart.add_serie(y=ydata, x=xdata, type='line', yaxis=1, name='visits', extra=extra_serie, **kwargs1) + extra_serie = {"tooltip": {"y_start": "", "y_end": " at this point"}} + chart.add_serie(y=ydata2, x=xdata, type='bar', yaxis=2,name='spend', extra=extra_serie, **kwargs2) + chart.buildhtml() + + assert("chart.noData('custom message shows when there is no data')" in chart.htmlcontent) + assert("function get_am_pm" in chart.htmlcontent) + + def test_multiBarHorizontalChart(self): """Test multi Bar Horizontal Chart""" - type = "multiBarHorizontalChart" - chart = multiBarHorizontalChart(name=type, height=350) + chart_name = "multiBarHorizontalChart" + chart = multiBarHorizontalChart(name=chart_name, height=350) nb_element = 10 xdata = list(range(nb_element)) ydata = [random.randint(-10, 10) for i in range(nb_element)] @@ -131,8 +159,8 @@ def test_multiBarHorizontalChart(self): def test_cumulativeLineChart(self): """Test Cumulative Line Chart""" - type = "cumulativeLineChart" - chart = cumulativeLineChart(name=type, height=400) + chart_name = "cumulativeLineChart" + chart = cumulativeLineChart(name=chart_name, height=400) start_time = int(time.mktime(datetime.datetime(2012, 6, 1).timetuple()) * 1000) nb_element = 100 xdata = list(range(nb_element)) @@ -145,8 +173,8 @@ def test_cumulativeLineChart(self): def test_scatterChart(self): """Test Scatter Chart""" - type = "scatterChart" - chart = scatterChart(name=type, date=True, height=350) + chart_name = "scatterChart" + chart = scatterChart(name=chart_name, date=True, height=350) nb_element = 100 xdata = [i + random.randint(1, 10) for i in range(nb_element)] ydata = [i * random.randint(1, 10) for i in range(nb_element)] @@ -163,8 +191,8 @@ def test_scatterChart(self): def test_discreteBarChart(self): """Test discrete Bar Chart""" - type = "discreteBarChart" - chart = discreteBarChart(name=type, height=350) + chart_name = "discreteBarChart" + chart = discreteBarChart(name=chart_name, height=350) xdata = ["A", "B", "C", "D", "E", "F", "G"] ydata = [3, 12, -10, 5, 35, -7, 2] @@ -172,12 +200,13 @@ def test_discreteBarChart(self): chart.buildhtml() # We don't modify the xAxis, so make sure that it's not invoked. - assert("chart.xAxis" not in chart.htmlcontent) + assert("chart.xAxis" in chart.htmlcontent) + assert("var chart = nv.models.discreteBarChart();" in chart.htmlcontent) def test_pieChart(self): """Test Pie Chart""" - type = "pieChart" - chart = pieChart(name=type, color_category='category20c', height=400, width=400) + chart_name = "pieChart" + chart = pieChart(name=chart_name, color_category='category20c', height=400, width=400) xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] color_list = ['orange', 'yellow', '#C5E946', '#95b43f', 'red', '#FF2259', '#F6A641'] extra_serie = {"tooltip": {"y_start": "", "y_end": " cal"}, "color_list": color_list} @@ -185,15 +214,88 @@ def test_pieChart(self): chart.add_serie(y=ydata, x=xdata, extra=extra_serie) chart.buildhtml() + assert("tooltip_str =" in chart.htmlcontent) + def test_donutPieChart(self): """Test Donut Pie Chart""" - type = "pieChart" - chart = pieChart(name=type, height=400, width=400, donut=True, donutRatio=0.2) + chart_name = "pieChart" + chart = pieChart(name=chart_name, height=400, width=400, donut=True, donutRatio=0.2) xdata = ["Orange", "Banana", "Pear", "Kiwi", "Apple", "Strawberry", "Pineapple"] ydata = [3, 4, 0, 1, 5, 7, 3] chart.add_serie(y=ydata, x=xdata) chart.buildhtml() + def test_can_create_bulletChart(self): + chart_name = 'bulletChart' + chart = bulletChart(name=chart_name, height=100, width=500) + title = 'Revenue', + subtitle = 'US$, in thousands' + ranges = [150, 225, 300] + measures = [220, 270] + markers = [250] + chart.add_serie( + title=title, + subtitle=subtitle, + ranges=ranges, + measures=measures, + markers=markers) + chart.buildhtml() + + def test_bulletChart_htmlcontent_correct(self): + chart_name = 'bulletChart' + chart = bulletChart(name=chart_name, height=100, width=500) + title = 'Revenue', + subtitle = 'USD, in mill' + ranges = [100, 250, 300] + measures = [220, 280] + markers = [260] + chart.add_serie( + title=title, + subtitle=subtitle, + ranges=ranges, + measures=measures, + markers=markers) + chart.buildhtml() + assert 'data_bulletchart' in chart.htmlcontent + assert '"title": ["Revenue"]' in chart.htmlcontent + assert '"ranges": [100, 250, 300]' in chart.htmlcontent + assert 'nv.models.bulletChart();' in chart.htmlcontent + + def test_bulletChart_marker_optional(self): + chart_name = 'bulletChart' + chart = bulletChart(name=chart_name, height=100, width=500) + title = 'Revenue', + subtitle = 'USD, in mill' + ranges = [100, 250, 300] + measures = [220, 280] + chart.add_serie( + title=title, + subtitle=subtitle, + ranges=ranges, + measures=measures + ) + chart.buildhtml() + assert 'data_bulletchart' in chart.htmlcontent + assert 'marker' not in chart.htmlcontent + + + def test_charts_with_extras(self): + # extras="d3.selectAll('#mygraphname text').style('opacity', 0.5)" + chart_name = 'bulletChart' + bullet_chart = bulletChart(name=chart_name, height=100, width=500, extras="d3.selectAll('#mygraphname text').style('opacity', 0.5)") + bullet_chart.buildhtml() + assert 'data_bulletchart' in bullet_chart.htmlcontent + assert "d3.selectAll('#mygraphname text').style('opacity', 0.5)" in bullet_chart.htmlcontent + + chart_name = "pieChart" + pie_chart = pieChart(name=chart_name, height=400, width=400, donut=True, donutRatio=0.2, extras="alert('Example of extra not even related to d3!')") + pie_chart.buildhtml() + assert "alert('Example of extra not even related to d3!')" in pie_chart.htmlcontent + + chart_name = "linePlusBarChart" + line_plus_bar_chart = linePlusBarChart(name=chart_name, date=True, height=350, extras="d3.selectAll('#mygraphname text').style('fill', 'red')") + line_plus_bar_chart.buildhtml() + assert "d3.selectAll('#mygraphname text').style('fill', 'red')" in line_plus_bar_chart.htmlcontent class FuncTest(unittest.TestCase): diff --git a/update_version.sh b/update_version.sh index 8be0cab8..c342e7b9 100755 --- a/update_version.sh +++ b/update_version.sh @@ -1,6 +1,6 @@ # # Usage: -# ./update_version.sh 0.12.0 +# ./update_version.sh 0.16.0 # git flow release start v$1 @@ -12,6 +12,6 @@ sed -i -e "s/version='.*'/version='$1'/g" setup.py #git commit docs nvd3/__init__.py -m "Update to version v$1" git commit -a -m "Update to version v$1" git flow release finish v$1 -python setup.py sdist +python setup.py sdist twine upload dist/python-nvd3-$1.tar.gz git push origin develop; git push origin master; git push --tags