Skip to content

Commit b4579a8

Browse files
authored
Merge pull request #15 from highcharts-for-python/develop
PR for v.1.0.0-rc6
2 parents 853a2bc + fe44378 commit b4579a8

File tree

17 files changed

+290
-60
lines changed

17 files changed

+290
-60
lines changed

CHANGES.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
Release 1.0.0-rc6
2+
=========================================
3+
4+
* Fixed bug in deserialization of ``options.plot_options.base.MapBaseOptions.join_by``.
5+
* Fixed Heatmap and Highcharts Maps JavaScript import conflict.
6+
* Fixed bug in utility_classes.projections.ProjectionOptions.custom property.
7+
* Fixed serialization bugs in options.series.data.map_data.MapData.
8+
* Added ``properties`` support to data point classes in ``options.series.data.geometric``.
9+
* Updated Jupyter display logic to align with **Highcharts Core for Python** signatures.
10+
* Added demos to documentation.
11+
12+
---------------
13+
114
Release 1.0.0-rc5
215
=========================================
316

docs/demos.rst

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
################################
2+
Demos
3+
################################
4+
5+
.. contents::
6+
:depth: 2
7+
:backlinks: entry
8+
9+
-------------------
10+
11+
***********************************************
12+
Trying the Highcharts for Python Toolkit
13+
***********************************************
14+
15+
You are welcome to try the **Highcharts for Python** toolkit at your convenience and at no cost.
16+
You can do so by installing the libraries you need very simple:
17+
18+
.. tabs::
19+
20+
.. tab:: Highcharts Core for Python
21+
22+
To install **Highcharts Core for Python**, just execute:
23+
24+
.. code-block:: bash
25+
26+
$ pip install highcharts-core
27+
28+
.. tab:: Highcharts Stock for Python
29+
30+
To install **Highcharts Stock for Python**, just execute:
31+
32+
.. code-block:: bash
33+
34+
$ pip install highcharts-stock
35+
36+
.. tab:: Highcharts Maps for Python
37+
38+
To install **Highcharts Maps for Python**, just execute:
39+
40+
.. code-block:: bash
41+
42+
$ pip install highcharts-maps
43+
44+
.. tab:: Highcharts Gantt for Python
45+
46+
To install **Highcharts Gantt for Python**, just execute:
47+
48+
.. code-block:: bash
49+
50+
$ pip install highcharts-gantt
51+
52+
If you are evaluating the **Highcharts for Python Toolkit**, you are welcome
53+
to install this library and use it free of charge.
54+
55+
However, if you are using it for professional purposes - either to use
56+
Highcharts for your work, or to build an application that integrates the library -
57+
then you have to pay for both Highcharts Core (JS) itself *and* for your right
58+
to use the **Highcharts for Python Toolkit**.
59+
60+
You can purchase licenses for both from Highsoft A/S at:
61+
`https://shop.highcharts.com/ <https://shop.highcharts.com>`__.
62+
63+
---------------
64+
65+
********************************************************
66+
Demonstrating the Highcharts for Python Toolkit
67+
********************************************************
68+
69+
We have prepared an extensive set of demos showcasing much of the code and
70+
functionality of the **Highcharts for Python** toolkit. To see the demos in action,
71+
we recommend that you click the following badge:
72+
73+
.. image:: https://mybinder.org/badge_logo.svg
74+
:target: https://mybinder.org/v2/gh/highcharts-for-python/highcharts-for-python-demos/HEAD
75+
:alt: Binder: Highcharts for Python Demos
76+
77+
This will clone the `Highcharts for Python Demos <https://github.com/highcharts-for-python-demos>`__
78+
source repository within a Docker image, and launch `Jupyter Lab <https://jupyter.org>`__ within that
79+
Docker container. This will then let you browse, edit, and run any of the Jupyter Notebooks contained
80+
within the `Highcharts for Python Demos <https://github.com/highcharts-for-python-demos>`__ repo.
81+
82+
How the Demos are Organized
83+
==============================
84+
85+
.. sidebar::
86+
87+
You should be aware that the demos use a variety of Highcharts for Python features, including various
88+
ways of de-serializing chart configurations. Some might load data from files, others might load them
89+
from ``snake_case`` :class:`dict <python:dict>`, others from ``camelCase`` Javascript Object Literal
90+
Notation :class:`str <python:str>` values, and more.
91+
92+
To see the full flexibility that the toolkit provides, we recommend reviewing several of the demos.
93+
94+
Once you have launched the Binder, you can browse the folders and Notebooks in the Jupyter Lab
95+
environment. You'll notice that the Jupyter Lab environment has one folder for each of the core
96+
Highcharts for Python libraries, respectively: ``highcharts-core``, ``highcharts-stock``,
97+
``highcharts-maps``, and ``highcharts-gantt``. Within each of these folders, you will find sub-folders
98+
labeled in a way to describe their contents.
99+
100+
For example:
101+
102+
* the sub-folder ``line-charts`` would contain various Notebooks that demonstrate the
103+
generation of various Line Charts using the **Highcharts for Python** toolkit
104+
* the sub-folder ``python-features`` would contain various Notebooks that demonstrate
105+
the use of Python-specific features like the ``.from_pandas()`` convenience methods
106+
* etc.
107+
108+
Navigating the demos should be fairly intuitive - just pay attention to the folder names and the filenames of the Jupyter Notebooks.
109+
110+
Executing a Demo
111+
===================
112+
113+
Once you are reviewing the demos, you can run a demo either by stepping through the cells in the Notebook, or
114+
by running all the cells in sequence.
115+
116+
------------------
117+
118+
*******************************
119+
Running Demos Locally
120+
*******************************
121+
122+
.. info::
123+
124+
You can run the demos locally by following instructions in the
125+
`Highcharts for Python Demos <https://github.com/highcharts-for-python-demos>`__ Github repo's README.

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Highcharts Maps for Python
2222

2323
Home <self>
2424
Quickstart: Patterns and Best Practices <quickstart>
25+
Demos <demos>
2526
Supported Visualizations <visualizations>
2627
FAQ <faq>
2728
Toolkit Components and Roadmap <toolkit>

highcharts_maps/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.0.0-rc5'
1+
__version__ = '1.0.0-rc6'

highcharts_maps/chart.py

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def _jupyter_include_scripts(self):
6262
def _jupyter_javascript(self,
6363
global_options = None,
6464
container = None,
65+
random_slug = None,
6566
retries = 3,
6667
interval = 1000):
6768
"""Return the JavaScript code which Jupyter Labs will need to render the chart.
@@ -76,6 +77,10 @@ def _jupyter_javascript(self,
7677
property if set, and ``'highcharts_target_div'`` if not set.
7778
:type container: :class:`str <python:str>` or :obj:`None <python:None>`
7879
80+
:param random_slug: The random sequence of characters to append to the container name to ensure uniqueness.
81+
Defaults to :obj:`None <python:None>`
82+
:type random_slug: :class:`str <python:str>` or :obj:`None <python:None>`
83+
7984
:param retries: The number of times to retry rendering the chart. Used to avoid race conditions with the
8085
Highcharts script. Defaults to 3.
8186
:type retries: :class:`int <python:int>`
@@ -87,7 +92,11 @@ def _jupyter_javascript(self,
8792
:rtype: :class:`str <python:str>`
8893
"""
8994
original_container = self.container
90-
self.container = container or self.container or 'highcharts_target_div'
95+
new_container = container or self.container or 'highcharts_target_div'
96+
if not random_slug:
97+
self.container = new_container
98+
else:
99+
self.container = f'{new_container}_{random_slug}'
91100

92101
if global_options is not None:
93102
global_options = validate_types(global_options,
@@ -101,6 +110,7 @@ def _jupyter_javascript(self,
101110

102111
js_str += utility_functions.prep_js_for_jupyter(self.to_js_literal(),
103112
container = self.container,
113+
random_slug = random_slug,
104114
retries = retries,
105115
interval = interval)
106116

@@ -254,7 +264,12 @@ def to_js_literal(self,
254264
options_as_str = ''
255265
if self.options:
256266
options_as_str = self.options.to_js_literal(encoding = encoding)
257-
if self.options.chart and self.options.chart.map and self.options.chart.is_async:
267+
if (
268+
self.is_maps_chart and
269+
hasattr(self.options.chart, 'map') and
270+
self.options.chart.map and
271+
self.options.chart.is_async
272+
):
258273
chart_map_str = self.options.chart.map.to_js_literal(encoding = encoding)
259274
chart_map_str = f"""'{chart_map_str}'"""
260275
fetch_counter = self.options.chart.map.fetch_counter
@@ -455,38 +470,6 @@ def from_series(cls, *series, kwargs = None):
455470

456471
instance.add_series(series)
457472

458-
def display(self, global_options = None):
459-
"""Display the chart in `Jupyter Labs <https://jupyter.org/>`_ or
460-
`Jupyter Notebooks <https://jupyter.org/>`_.
461-
462-
:raises HighchartsDependencyError: if
463-
`ipython <https://ipython.readthedocs.io/en/stable/>`_ is not available in the
464-
runtime environment
465-
"""
466-
try:
467-
from IPython import display
468-
except ImportError:
469-
raise errors.HighchartsDependencyError('Unable to import IPython.display. '
470-
'Make sure that it is available in '
471-
'your runtime environment. To install,'
472-
'use: pip install ipython')
473-
474-
if global_options is not None:
475-
global_options = validate_types(global_options,
476-
types = SharedMapsOptions)
477-
478-
if self.is_maps_chart:
479-
include_str = constants.MAPS_INCLUDE_STR
480-
else:
481-
include_str = constants.INCLUDE_STR
482-
483-
html_str = include_str + '\n'
484-
if global_options:
485-
html_str += global_options._repr_html_() + '\n'
486-
html_str += self._repr_html_()
487-
488-
display.display_html(html_str, raw = True)
489-
490473
@staticmethod
491474
def _get_options_obj(series_type, options_kwargs):
492475
"""Return an :class:`Options` descendent based on the series type.
@@ -1053,7 +1036,7 @@ def is_async(self) -> bool:
10531036
if not self.options or not self.options.series:
10541037
return False
10551038

1056-
if self.options.chart and self.options.chart.is_async:
1039+
if self.options.chart and hasattr(self.options.chart, 'is_async') and self.options.chart.is_async:
10571040
return True
10581041

10591042
for series in self.options.series:

highcharts_maps/constants.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"""Defines a set of constants that are used throughout the library."""
22
from highcharts_core.constants import *
33

4-
5-
MAPS_INCLUDE_LIBS = INCLUDE_LIBS + [
4+
MAPS_INCLUDE_LIBS = [x for x in INCLUDE_LIBS if x != 'https://code.highcharts.com/modules/heatmap.js']
5+
MAPS_INCLUDE_LIBS.extend([
66
'https://code.highcharts.com/maps/modules/map.js'
7-
]
7+
])
88

99
MAPS_INCLUDE_STR = INCLUDE_STR + """
1010
<script src="https://code.highcharts.com/maps/modules/map.js"/>

highcharts_maps/options/chart/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from highcharts_maps.options.series.data.map_data import MapData, AsyncMapData
1111

1212
from highcharts_core.options.chart import (PanningOptions,
13-
ChartOptions as ChartOptionsBase)
13+
ChartOptions as ChartOptionsBase)
1414

1515

1616
class ChartOptions(ChartOptionsBase):

highcharts_maps/options/plot_options/base.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import Optional, List
2+
from collections import UserDict
23

34
from validator_collection import validators, checkers
45

@@ -79,15 +80,18 @@ def join_by(self, value):
7980
self._join_by = None
8081
elif isinstance(value, constants.EnforcedNullType):
8182
self._join_by = constants.EnforcedNull
82-
elif checkers.is_iterable(value):
83+
elif checkers.is_iterable(value, forbid_literals = (str, bytes, dict, UserDict)):
8384
if len(value) > 2:
8485
raise errors.HighchartsValueError(f'join_by expects a 2-member iterable.'
8586
f'Received a {len(value)}-member '
8687
f'iterable.')
8788
elif len(value) == 2:
88-
self._join_by = validators.string(value[0])
89+
self._join_by = [
90+
validators.string(value[0]),
91+
validators.string(value[1])
92+
]
8993
else:
90-
self._join_by = [validators.string(x) for x in value]
94+
self._join_by = validators.string(value)
9195
else:
9296
self._join_by = validators.string(value)
9397

0 commit comments

Comments
 (0)