Skip to content

Commit

Permalink
Merge pull request #12 from highcharts-for-python/develop
Browse files Browse the repository at this point in the history
PR for v.1.0.0-rc3
  • Loading branch information
hcpchris authored Apr 2, 2023
2 parents 128e9fd + 1f0ab92 commit 7abde84
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 51 deletions.
12 changes: 12 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
Release 1.0.0-rc3
=========================================

* Fixed unneeded ``python-dotenv`` dependency.
* Fixed JSON deserialization in ``.from_array()``.
* Added ``options.chart.ChartOptions.is_async`` property.
* Updated ``utility_classes.fetch_configuration.FetchConfiguration``
serialization to handle quote escaping.
* Fixed JS literal synchronization when ``options.chart.map`` is asynchronous.

--------------

Release 1.0.0-rc2
=========================================

Expand Down
2 changes: 1 addition & 1 deletion highcharts_maps/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.0.0-rc2'
__version__ = '1.0.0-rc3'
25 changes: 19 additions & 6 deletions highcharts_maps/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from highcharts_core.chart import Chart as ChartBase

from highcharts_maps import constants, errors
from highcharts_maps import constants, errors, utility_functions
from highcharts_maps.options import HighchartsOptions, HighchartsMapsOptions
from highcharts_maps.decorators import validate_types
from highcharts_maps.js_literal_functions import serialize_to_js_literal
Expand Down Expand Up @@ -218,6 +218,14 @@ def to_js_literal(self,
if self.is_async:
urls = []
topologies = []
if self.options.chart and self.options.chart.map:
url = self.options.chart.map.url
urls.append(url)
self.options.chart.map.fetch_counter = 1

map_data_as_str = self.options.chart.map.to_js_literal(encoding = encoding)
topologies.append(map_data_as_str)

for index, series in enumerate(self.options.series):
if series.is_async:
url = series.map_data.url
Expand All @@ -229,10 +237,7 @@ def to_js_literal(self,
map_data_as_str = series.map_data.to_js_literal(encoding = encoding)
topologies.append(map_data_as_str)

fetch_as_str = ''
for topology in topologies:
fetch_request = topology.to_js_literal(encoding = encoding)
fetch_as_str += f"""{fetch_request}\n"""
fetch_as_str = '\n'.join(topologies)

custom_projection_as_str = ''
if self.uses_custom_projection:
Expand All @@ -249,6 +254,11 @@ def to_js_literal(self,
options_as_str = ''
if self.options:
options_as_str = self.options.to_js_literal(encoding = encoding)
if self.options.chart and self.options.chart.map and self.options.chart.is_async:
chart_map_str = self.options.chart.map.to_js_literal(encoding = encoding)
chart_map_str = f"""'{chart_map_str}'"""
fetch_counter = self.options.chart.map.fetch_counter
options_as_str = options_as_str.replace(chart_map_str, f'topology{fetch_counter}')
options_as_str = f"""{options_as_str}"""
else:
options_as_str = """{}"""
Expand Down Expand Up @@ -285,7 +295,7 @@ def to_js_literal(self,
prefix = """document.addEventListener('DOMContentLoaded', function() {\n"""
if custom_projection_as_str:
prefix += custom_projection_as_str
prefix += """(async () => """
prefix += """(async () => { """
suffix = """})()});"""
as_str = fetch_as_str + '\n' + as_str
else:
Expand Down Expand Up @@ -1043,6 +1053,9 @@ def is_async(self) -> bool:
if not self.options or not self.options.series:
return False

if self.options.chart and self.options.chart.is_async:
return True

for series in self.options.series:
if hasattr(series, 'is_async') and series.is_async:
return True
Expand Down
43 changes: 5 additions & 38 deletions highcharts_maps/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,10 @@
from highcharts_core.constants import *


MAPS_INCLUDE_LIBS = [
'https://code.highcharts.com/highcharts.js',
'https://code.highcharts.com/highcharts-more.js',
'https://code.highcharts.com/highcharts-3d.js',
'https://code.highcharts.com/maps/modules/map.js',
'https://code.highcharts.com/modules/accessibility.js',
'https://code.highcharts.com/modules/annotations.js',
'https://code.highcharts.com/modules/boost.js',
'https://code.highcharts.com/modules/broken-axis.js',
'https://code.highcharts.com/modules/data.js',
'https://code.highcharts.com/modules/exporting.js',
'https://code.highcharts.com/modules/drilldown.js',
'https://code.highcharts.com/modules/funnel.js',
'https://code.highcharts.com/modules/heatmap.js',
'https://code.highcharts.com/modules/no-data-to-display.js',
'https://code.highcharts.com/modules/offline-exporting.js',
'https://code.highcharts.com/modules/solid-gauge.js',
'https://code.highcharts.com/modules/series-label.js',
'https://code.highcharts.com/modules/treemap.js'
MAPS_INCLUDE_LIBS = INCLUDE_LIBS + [
'https://code.highcharts.com/maps/modules/map.js'
]

MAPS_INCLUDE_STR = """<script src="https://code.highcharts.com/highcharts.js"/>
<script src="https://code.highcharts.com/highcharts-more.js"/>
<script src="https://code.highcharts.com/highcharts-3d.js"/>
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"/>
<script src="https://code.highcharts.com/modules/annotations.js"/>
<script src="https://code.highcharts.com/modules/boost.js"/>
<script src="https://code.highcharts.com/modules/broken-axis.js"/>
<script src="https://code.highcharts.com/modules/data.js"/>
<script src="https://code.highcharts.com/modules/exporting.js"/>
<script src="https://code.highcharts.com/modules/drilldown.js"/>
<script src="https://code.highcharts.com/modules/funnel.js"/>
<script src="https://code.highcharts.com/modules/heatmap.js"/>
<script src="https://code.highcharts.com/modules/no-data-to-display.js"/>
<script src="https://code.highcharts.com/modules/offline-exporting.js"/>
<script src="https://code.highcharts.com/modules/solid-gauge.js"/>
<script src="https://code.highcharts.com/modules/treemap.js"/>
<script src="https://code.highcharts.com/modules/series-label.js"/>
"""
MAPS_INCLUDE_STR = INCLUDE_STR + """
<script src="https://code.highcharts.com/maps/modules/map.js"/>
"""
9 changes: 6 additions & 3 deletions highcharts_maps/headless_export.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
from dotenv import load_dotenv
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass

from typing import Optional

from validator_collection import checkers
Expand All @@ -9,8 +14,6 @@
from highcharts_maps.options import HighchartsOptions, HighchartsMapsOptions
from highcharts_maps.global_options.shared_options import SharedOptions, SharedMapsOptions

load_dotenv()


class ExportServer(ExportServerBase):
"""Class that provides methods for interacting with the Highcharts
Expand Down
23 changes: 23 additions & 0 deletions highcharts_maps/options/chart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,26 @@ def _to_untrimmed_dict(self, in_cls = None) -> dict:
untrimmed[key] = parent_as_dict[key]

return untrimmed

@property
def is_async(self) -> bool:
"""Read-only property which indicates whether the data visualization should be
rendered using asynchronous logic.
.. note::
This property will only return ``True`` if one or more series rely on
:class:`AsyncMapData <highcharts_maps.options.series.data.map_data.AsyncMapData>`
:rtype: :class:`bool <python:bool>`
"""
if checkers.is_iterable(self.map):
for item in self.map:
if isinstance(item, (AsyncMapData)):
return True
return False

if isinstance(self.map, AsyncMapData):
return True

return False
15 changes: 15 additions & 0 deletions highcharts_maps/options/series/data/geometric.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ def value(self, value_):
def from_array(cls, value):
if not value:
return []
elif checkers.is_string(value):
try:
value = validators.json(value)
except (ValueError, TypeError):
pass
elif not checkers.is_iterable(value):
value = [value]

Expand Down Expand Up @@ -343,6 +348,11 @@ def z(self, value):
def from_array(cls, value):
if not value:
return []
elif checkers.is_string(value):
try:
value = validators.json(value)
except (ValueError, TypeError):
pass
elif not checkers.is_iterable(value):
value = [value]

Expand Down Expand Up @@ -521,6 +531,11 @@ def y(self, value):
def from_array(cls, value):
if not value:
return []
elif checkers.is_string(value):
try:
value = validators.json(value)
except (ValueError, TypeError):
pass
elif not checkers.is_iterable(value):
value = [value]

Expand Down
2 changes: 1 addition & 1 deletion highcharts_maps/options/series/data/map_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ def to_js_literal(self,
fetch_config = self.fetch_config
else:
fetch_config = FetchConfiguration(self.url)

if self.selector:
function = f"""const selector = {str(self.selector)};\n"""
fetch = f"""const topology = await {str(fetch_config)}.then(response => selector(response.json()));"""
Expand Down
4 changes: 2 additions & 2 deletions highcharts_maps/utility_classes/fetch_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ def __str__(self):
options_as_str = json.dumps(trimmed_options)

if not options_as_str:
as_str = f"""fetch('{self.url}')"""
as_str = f"""fetch("{self.url}")"""
else:
as_str = f"""fetch('{self.url}', options = {options_as_str})"""
as_str = f"""fetch("{self.url}", options = {options_as_str})"""

return as_str

Expand Down

0 comments on commit 7abde84

Please sign in to comment.