diff --git a/CHANGES.rst b/CHANGES.rst index 1faa4d53..a45504d5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,24 @@ +Release 1.2.0 +========================================= + +* **ENHANCEMENT:** Align the API to **Highcharts (JS) v.11.1** (#52). In particular, this includes: + + * Added ``AccessibilityPoint.description_format`` property. + * Added support for ``.legend_symbol`` to plot options and series options. + * Added ``.border_radius`` support to ``FunnelOptions`` and ``FunnelSeries``. + * Added ``.interpolation`` support to ``HeatmapOptions`` and descendents. + * Added ``.point_description_format`` support to ``SeriesOptions`` and descendents. + * Added ``.fill_space`` support to ``TreegraphOptions`` and descendents. + * Added ``.crossing`` support to axes. + * Added ``.format`` support to ``Tooltip``. + +* **ENHANCEMENT:** Added support for the inclusion of scripts based on features used in the chart (#12). +* **ENHANCEMENT:** Added ``dict`` support to ``.style`` property on labels and titles. +* **DOCS:** Various documentation updates and fixes. +* **DEPENDENCY:** Bumped ``requests`` version for security patch. + +------------------ + Release 1.1.1 ========================================= diff --git a/README.rst b/README.rst index ddadf5a8..9f2f2fdf 100644 --- a/README.rst +++ b/README.rst @@ -15,7 +15,7 @@ visualization library, with full integration into the robust Python ecosystem, i dataframe. * ...and even more use-case specific integrations across the broader toolkit. -The library supports Highcharts (JS) v.10.2 and higher, including Highcharts (JS) v.11.0.0. +The library supports Highcharts (JS) v.10.2 and higher, including Highcharts (JS) v.11.1.0. **COMPLETE DOCUMENTATION:** https://core-docs.highchartspython.com/en/latest/index.html @@ -71,7 +71,7 @@ Before you install, please be aware of the following "hard" dependencies: * Highcharts Core (JS) v.10.2 or higher (not technically a Python dependency, but it won't work with earlier versions of Highcharts) * `esprima-python `__ v.4.0 or higher - * `requests `__ v.2.28 or higher + * `requests `__ v.2.31 or higher * `validator-collection `__ v.1.5 or higher diff --git a/docs/_contributors.rst b/docs/_contributors.rst index ebae4db5..6c33d97b 100644 --- a/docs/_contributors.rst +++ b/docs/_contributors.rst @@ -1,2 +1,3 @@ * Chris Modzelewski (`@hcpchris `__ / `@insightindustry `__) -* Erin Modzelewski (`@EBModz `__) \ No newline at end of file +* Erin Modzelewski (`@EBModz `__) +* Jitendra Mishra (`@jmishra01 `__) \ No newline at end of file diff --git a/docs/_dependencies.rst b/docs/_dependencies.rst index 31f1e2be..230dc555 100644 --- a/docs/_dependencies.rst +++ b/docs/_dependencies.rst @@ -32,7 +32,7 @@ not work properly if your rendering layer does not leverage Highcharts Core (JS). * `esprima-python `_ v.4.0 or higher - * `requests `_ v.2.28 or higher + * `requests `_ v.2.31 or higher * `validator-collection `_ v.1.5 or higher diff --git a/docs/_static/tiledwebmap-example.png b/docs/_static/tiledwebmap-example.png new file mode 100644 index 00000000..bbd70546 Binary files /dev/null and b/docs/_static/tiledwebmap-example.png differ diff --git a/docs/api.rst b/docs/api.rst index a0022c2b..502594e7 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -232,6 +232,7 @@ Core Components - :class:`ScrollablePlotArea ` * - :mod:`.options.chart.zooming ` - :class:`ZoomingOptions ` + :class:`MouseWheelOptions ` * - :mod:`.options.credits ` - :class:`Credits ` :class:`CreditStyleOptions ` diff --git a/docs/api/options/chart/index.rst b/docs/api/options/chart/index.rst index f2831345..b217fe0e 100644 --- a/docs/api/options/chart/index.rst +++ b/docs/api/options/chart/index.rst @@ -78,3 +78,4 @@ Sub-components - :class:`ScrollablePlotArea ` * - :mod:`.options.chart.zooming ` - :class:`ZoomingOptions ` + :class:`MouseWheelOptions ` diff --git a/docs/api/options/chart/zooming.rst b/docs/api/options/chart/zooming.rst index fae60154..40608c71 100644 --- a/docs/api/options/chart/zooming.rst +++ b/docs/api/options/chart/zooming.rst @@ -26,3 +26,21 @@ class: :class:`ZoomingOptions ` +******************************************************************************************************************** + +.. autoclass:: MouseWheelOptions + :members: + :inherited-members: + + .. collapse:: Class Inheritance + + .. inheritance-diagram:: MouseWheelOptions + :top-classes: highcharts_core.metaclasses.HighchartsMeta, highcharts_core.metaclasses.HighchartsMeta + :parts: -1 + + | diff --git a/docs/api/options/index.rst b/docs/api/options/index.rst index 9581d6c8..c7513994 100644 --- a/docs/api/options/index.rst +++ b/docs/api/options/index.rst @@ -161,6 +161,7 @@ Sub-components - :class:`ScrollablePlotArea ` * - :mod:`.options.chart.zooming ` - :class:`ZoomingOptions ` + :class:`MouseWheelOptions ` * - :mod:`.options.credits ` - :class:`Credits ` :class:`CreditStyleOptions ` diff --git a/docs/demos.rst b/docs/demos.rst index 60f32622..f93d1eb2 100644 --- a/docs/demos.rst +++ b/docs/demos.rst @@ -74,10 +74,10 @@ we recommend that you click the following badge: :target: https://mybinder.org/v2/gh/highcharts-for-python/highcharts-for-python-demos/HEAD :alt: Binder: Highcharts for Python Demos -This will clone the `Highcharts for Python Demos `__ +This will clone the `Highcharts for Python Demos `__ source repository within a Docker image, and launch `Jupyter Lab `__ within that Docker container. This will then let you browse, edit, and run any of the Jupyter Notebooks contained -within the `Highcharts for Python Demos `__ repo. +within the `Highcharts for Python Demos `__ repo. How the Demos are Organized ============================== @@ -122,4 +122,4 @@ Running Demos Locally .. note:: You can run the demos locally by following instructions in the - `Highcharts for Python Demos `__ Github repo's README. \ No newline at end of file + `Highcharts for Python Demos `__ Github repo's README. \ No newline at end of file diff --git a/docs/glossary.rst b/docs/glossary.rst index 247ef0b0..3e4d2503 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -172,6 +172,24 @@ Glossary * `Highcharts Node Export Server Documentation `__ + Format String + .. versionadded: v.1.2.0 + + Format strings are templates for labels introduced in Highcharts for Python v.1.2. + Since Highcharts (JS) v.11.1, format strings support logic. + + We recommend using format strings if you: + + * Need to save the chart configuration to JSON. + * Need to provide a GUI for end users so that callbacks are not practical, or XSS is a concern. + * Need to send the charts over to our export server to execute (all callbacks are stripped out). + * Are creating a wrapper for another programming language than JavaScript. + + .. seealso:: + + For a full overview over templating in format strings, please see the Highcharts (JS) + `Templating `__ article. + Formatter A particular type of :term:`callback function` used extensively in Highcharts. In general terms, a formatter receives a context (for example a data point) and returns diff --git a/docs/index.rst b/docs/index.rst index dd34bf92..62b604cf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -38,7 +38,7 @@ Highcharts Core for Python .. sidebar:: Version Compatibility - **Latest Highcharts (JS) version supported:** v.11.0.0 + **Latest Highcharts (JS) version supported:** v.11.1.0 **Highcharts Core for Python** is designed to be compatible with: diff --git a/docs/visualizations.rst b/docs/visualizations.rst index cb0e0083..531e27e8 100644 --- a/docs/visualizations.rst +++ b/docs/visualizations.rst @@ -692,7 +692,7 @@ to visualize your data. :class:`highcharts_maps.options.plot_options.mapline.MapLineOptions` :class:`highcharts_maps.options.series.mapline.MapLineSeries` - * - **Map** + * - **Map Point** - .. figure:: _static/mappoint-example.png :alt: Map Point Example Chart :width: 100% @@ -700,6 +700,14 @@ to visualize your data. :class:`highcharts_maps.options.plot_options.mappoint.MapPointOptions` :class:`highcharts_maps.options.series.mappoint.MapPointSeries` + * - **Tiled Web Map** + - .. figure:: _static/tiledwebmap-example.png + :alt: Tiled Web Map Example Chart + :width: 100% + + :class:`highcharts_maps.options.plot_options.tiledwebmap.TiledWebMapOptions` + + :class:`highcharts_maps.options.series.tiledwebmap.TiledWebMapSeries` .. tab:: Gantt diff --git a/highcharts_core/__version__.py b/highcharts_core/__version__.py index e9e169e2..e916218b 100644 --- a/highcharts_core/__version__.py +++ b/highcharts_core/__version__.py @@ -1 +1 @@ -__version__ = '1.1.1' \ No newline at end of file +__version__ = '1.2.0' \ No newline at end of file diff --git a/highcharts_core/chart.py b/highcharts_core/chart.py index 668973d2..2536d7fc 100644 --- a/highcharts_core/chart.py +++ b/highcharts_core/chart.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, List from collections import UserDict from validator_collection import validators, checkers @@ -22,6 +22,7 @@ def __init__(self, **kwargs): self._container = None self._options = None self._variable_name = None + self._module_url = None self._random_slug = {} @@ -29,35 +30,32 @@ def __init__(self, **kwargs): self.container = kwargs.get('container', None) self.options = kwargs.get('options', None) self.variable_name = kwargs.get('variable_name', None) + self.module_url = kwargs.get('module_url', 'https://code.highcharts.com/') super().__init__(**kwargs) def _jupyter_include_scripts(self): """Return the JavaScript code that is used to load the Highcharts JS libraries. - .. note:: - - Currently includes *all* `Highcharts JS `_ modules - in the HTML. This issue will be addressed when roadmap issue :issue:`2` is - released. - :rtype: :class:`str ` """ + required_modules = [f'{self.module_url}{x}' + for x in self.get_required_modules(include_extension = True)] js_str = '' - for item in constants.INCLUDE_LIBS: + for item in required_modules: js_str += utility_functions.jupyter_add_script(item) js_str += """.then(() => {""" - for item in constants.INCLUDE_LIBS: + for item in required_modules: js_str += """});""" return js_str - def _jupyter_javascript(self, - global_options = None, + def _jupyter_javascript(self, + global_options = None, container = None, random_slug = None, - retries = 3, + retries = 5, interval = 1000): """Return the JavaScript code which Jupyter Labs will need to render the chart. @@ -65,21 +63,21 @@ def _jupyter_javascript(self, Defaults to :obj:`None ` :type global_options: :class:`SharedOptions ` or :obj:`None ` - + :param container: The ID to apply to the HTML container when rendered in Jupyter Labs. Defaults to - :obj:`None `, which applies the :meth:`.container ` + :obj:`None `, which applies the :meth:`.container ` property if set, and ``'highcharts_target_div'`` if not set. :type container: :class:`str ` or :obj:`None ` - + :param random_slug: The random sequence of characters to append to the container name to ensure uniqueness. Defaults to :obj:`None ` :type random_slug: :class:`str ` or :obj:`None ` - - :param retries: The number of times to retry rendering the chart. Used to avoid race conditions with the + + :param retries: The number of times to retry rendering the chart. Used to avoid race conditions with the Highcharts script. Defaults to 3. :type retries: :class:`int ` - - :param interval: The number of milliseconds to wait between retrying rendering the chart. Defaults to 1000 (1 + + :param interval: The number of milliseconds to wait between retrying rendering the chart. Defaults to 1000 (1 seocnd). :type interval: :class:`int ` @@ -91,14 +89,13 @@ def _jupyter_javascript(self, self.container = new_container else: self.container = f'{new_container}_{random_slug}' - + if global_options is not None: global_options = validate_types(global_options, types = SharedOptions) - js_str = '' - js_str += utility_functions.get_retryHighcharts() - + js_str = utility_functions.get_retryHighcharts() + if global_options: js_str += '\n' + utility_functions.prep_js_for_jupyter(global_options.to_js_literal()) + '\n' @@ -118,11 +115,11 @@ def _jupyter_container_html(self, """Returns the Jupyter Labs HTML container for rendering the chart in Jupyter Labs context. :param container: The ID to apply to the HTML container when rendered in Jupyter Labs. Defaults to - :obj:`None `, which applies the :meth:`.container ` + :obj:`None `, which applies the :meth:`.container ` property if set, and ``'highcharts_target_div'`` if not set. :type container: :class:`str ` or :obj:`None ` - :param random_slug: The random sequence of characters to append to the container/function name to ensure + :param random_slug: The random sequence of characters to append to the container/function name to ensure uniqueness. Defaults to :obj:`None ` :type random_slug: :class:`str ` or :obj:`None ` @@ -155,6 +152,21 @@ def _repr_html_(self): """ return self.display() + def get_required_modules(self, include_extension = False) -> List[str]: + """Return the list of URLs from which the Highcharts JavaScript modules + needed to render the chart can be retrieved. + + :param include_extension: if ``True``, will return script names with the + ``'.js'`` extension included. Defaults to ``False``. + :type include_extension: :class:`bool ` + + :rtype: :class:`list ` + """ + initial_scripts = ['highcharts'] + scripts = self._process_required_modules(initial_scripts, include_extension) + + return scripts + @property def callback(self) -> Optional[CallbackFunction]: """A (JavaScript) function that is run when the chart has loaded and all external @@ -174,6 +186,49 @@ def callback(self) -> Optional[CallbackFunction]: def callback(self, value): self._callback = value + @property + def module_url(self) -> str: + """The URL from which Highcharts modules should be downloaded when + generating the ``