from typing import Optional
from decimal import Decimal
from validator_collection import validators
from highcharts_maps import errors
from highcharts_maps.decorators import class_sensitive
from highcharts_maps.metaclasses import HighchartsMeta, JavaScriptDict
from highcharts_core.options.plot_options.accessibility import TypeOptionsAccessibility
from highcharts_core.utility_classes.events import SeriesEvents
from highcharts_core.utility_classes.states import States
[docs]class ProviderOptions(HighchartsMeta):
"""Configuration of options enabling conncetion to the provider from which map images
(tiles) will be retrieved."""
def __init__(self, **kwargs):
self._api_key = None
self._subdomain = None
self._theme = None
self._type = None
self._url = None
self.api_key = kwargs.get('api_key', None)
self.subdomain = kwargs.get('subdomain', None)
self.theme = kwargs.get('theme', None)
self.type = kwargs.get('type', None)
self.url = kwargs.get('url', None)
@property
def api_key(self) -> Optional[str]:
"""API key used to authenticate against the provider. Applicable if the provider uses an API key.
Defaults to :obj:`None <python:None>`.
:rtype: :class:`str <python:str>`
"""
return self._api_key
@api_key.setter
def api_key(self, value):
self._api_key = validators.string(value, allow_empty = True)
@property
def subdomain(self) -> Optional[str]:
"""Subdomain required by the provider. Defaults to :obj:`None <python:None>`.
.. note::
Different providers require different subdomains to be specified. For more
information, please see
`Tiled Web Map Configuration: Providers Properties <https://www.highcharts.com/docs/maps/tiledwebmap#providers-properties>`__
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._subdomain
@subdomain.setter
def subdomain(self, value):
self._subdomain = validators.string(value, allow_empty = True)
@property
def theme(self) -> Optional[str]:
"""The tile theme to apply. Defaults to :obj:`None <python:None>`.
.. note::
Different providers offer different themes for their map tiles. For more
information, please see
`Tiled Web Map Configuration: Providers Properties <https://www.highcharts.com/docs/maps/tiledwebmap#providers-properties>`__
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._theme
@theme.setter
def theme(self, value):
self._theme = validators.string(value, allow_empty = True)
@property
def type(self) -> Optional[str]:
"""Indication of the provider to use, if not using a custom provider.
Defaults to :obj:`None <python:None>`.
.. warning::
The value is **case-sensitive**.
The following are provider types that are (currently) known / recognized:
* ``'OpenStreetMap'``
* ``'Thunderforest'``
* ``'Esri'``
* ``'Stamen'``
* ``'USGS'``
* ``'LimaLabs'``
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._type
@type.setter
def type(self, value):
self._type = validators.string(value, allow_empty = True)
@property
def url(self) -> Optional[str]:
"""Custom URL to use for a provider that is not identified using
:meth:`.type <highcharts_maps.options.plot_options.tiledwebmap.ProviderOptions.type>`.
The following variables are available to use, for example in URL parameters:
* ``'{x}'``
* ``'{y}'``
* ``'{z}'``
* ``'{zoom}'``
.. warning::
Remember to always specify a projection when using a custom URL!
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._url
@url.setter
def url(self, value):
self._url = validators.url(value, allow_empty = True)
@classmethod
def _get_kwargs_from_dict(cls, as_dict):
"""Convenience method which returns the keyword arguments used to initialize the
class from a Highcharts Javascript-compatible :class:`dict <python:dict>` object.
:param as_dict: The HighCharts JS compatible :class:`dict <python:dict>`
representation of the object.
:type as_dict: :class:`dict <python:dict>`
:returns: The keyword arguments that would be used to initialize an instance.
:rtype: :class:`dict <python:dict>`
"""
kwargs = {
'api_key': as_dict.get('apiKey', None),
'subdomain': as_dict.get('subdomain', None),
'theme': as_dict.get('theme', None),
'type': as_dict.get('type', None),
'url': as_dict.get('url', None),
}
return kwargs
def _to_untrimmed_dict(self, in_cls = None) -> dict:
untrimmed = {
'apiKey': self.api_key,
'subdomain': self.subdomain,
'theme': self.theme,
'type': self.type,
'url': self.url,
}
return untrimmed
[docs]class TiledWebMapOptions(HighchartsMeta):
"""A tiled web map series allows you to display dynamically joined individual images (tiles)
and join them together to create a map.
.. figure:: ../../../_static/tiledwebmap-example.png
:alt: Tiled Web Map Example chart
:align: center
"""
def __init__(self, **kwargs):
self._accessibility = None
self._class_name = None
self._custom = None
self._description = None
self._events = None
self._include_in_data_export = None
self._legend_symbol = None
self._opacity = None
self._point_description_format = None
self._provider = None
self._show_in_legend = None
self._skip_keyboard_navigation = None
self._states = None
self._visible = None
self._z_index = None
self.accessibility = kwargs.get('accessibility', None)
self.class_name = kwargs.get('class_name', None)
self.custom = kwargs.get('custom', None)
self.description = kwargs.get('description', None)
self.events = kwargs.get('events', None)
self.include_in_data_export = kwargs.get('include_in_data_export', None)
self.legend_symbol = kwargs.get('legend_symbol', None)
self.opacity = kwargs.get('opacity', None)
self.point_description_format = kwargs.get('point_description_format', None)
self.provider = kwargs.get('provider', None)
self.show_in_legend = kwargs.get('show_in_legend', None)
self.skip_keyboard_navigation = kwargs.get('skip_keyboard_navigation', None)
self.states = kwargs.get('states', None)
self.visible = kwargs.get('visible', None)
self.z_index = kwargs.get('z_index', None)
@property
def type(self) -> str:
"""Indicates the type of series that is represented by this instance.
.. warning::
This proprety is read-only!
:rtype: :class:`str <python:str>`
"""
class_name = self.__class__.__name__
class_name = class_name.replace('TypeOptions', '')
class_name = class_name.replace('Options', '')
if class_name.endswith('Series') and class_name != 'Series':
class_name = class_name.replace('Series', '')
return class_name.lower()
@type.setter
def type(self, value):
raise errors.HighchartsReadOnlyError('type is a read-only property and cannot be '
'set manually')
@property
def accessibility(self) -> Optional[TypeOptionsAccessibility]:
"""Accessibility options for a series.
:rtype: :class:`TypeOptionsAccessibility` or :obj:`None <python:None>`
"""
return self._accessibility
@accessibility.setter
@class_sensitive(TypeOptionsAccessibility)
def accessibility(self, value):
self._accessibility = value
@property
def class_name(self) -> Optional[str]:
"""The additional CSS class name to apply to the series' graphical elements.
.. note::
This option is additive to the default class names - it does not replace them.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._class_name
@class_name.setter
def class_name(self, value):
self._class_name = validators.string(value, allow_empty = True)
@property
def custom(self) -> Optional[JavaScriptDict]:
"""A reserved subspace to store options and values for customized functionality.
Here you can add additional data for your own event callbacks and formatter
callbacks.
:rtype: :class:`dict <python:dict>` or :obj:`None <python:None>`
"""
return self._custom
@custom.setter
@class_sensitive(JavaScriptDict)
def custom(self, value):
self._custom = value
@property
def description(self) -> Optional[str]:
"""A description of the series to add to the screen reader information about the
series.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._description
@description.setter
def description(self, value):
self._description = validators.string(value, allow_empty = True)
@property
def events(self) -> Optional[SeriesEvents]:
"""General event handlers for the series items.
.. note::
These event hooks can also be attached to the series at run time using the
(JavaScript) ``Highcharts.addEvent()`` function.
:rtype: :class:`SeriesEvents` or :obj:`None <python:None>`
"""
return self._events
@events.setter
@class_sensitive(SeriesEvents)
def events(self, value):
self._events = value
@property
def include_in_data_export(self) -> Optional[bool]:
"""If ``False``, will prevent the data series from being included in any form of
data export. Defaults to ``True``.
:rtype: :class:`bool <python:bool>` or :obj:`None <python:None>`
"""
return self._include_in_data_export
@include_in_data_export.setter
def include_in_data_export(self, value):
if value is None:
self._include_in_data_export = None
else:
self._include_in_data_export = bool(value)
@property
def legend_symbol(self) -> Optional[str]:
"""The type of legend symbol to render for the series. Accepts either
``'lineMarker'`` or ``'rectangle'``. Defaults to ``'rectangle'``.
:rtype: :class:`str <python:str>`
"""
return self._legend_symbol
@legend_symbol.setter
def legend_symbol(self, value):
if not value:
self._legend_symbol = None
else:
value = validators.string(value)
value = value.lower()
if value == 'linemarker':
value = 'lineMarker'
if value not in ['lineMarker', 'rectangle']:
raise errors.HighchartsValueError(f'legend_symbol expects either '
f'"lineMarker" or "rectangle". '
f'Received: "{value}".')
self._legend_symbol = value
@property
def opacity(self) -> Optional[float]:
"""Opacity of a series parts: line, fill (e.g. area), and labels.
:rtype: :class:`float <python:float>`
"""
return self._opacity
@opacity.setter
def opacity(self, value):
self._opacity = validators.float(value,
allow_empty = True,
minimum = 0.0,
maximum = 1.0)
@property
def point_description_format(self) -> Optional[str]:
"""A :term:`format string` to use instead of the default for
point descriptions on the series. Defaults to :obj:`None <python:None>`.
.. note::
Overrides the chart-wide configuration, as applicable.
:rtype: :class:`str <python:str>` or :obj:`None <python:None>`
"""
return self._point_description_format
@point_description_format.setter
def point_description_format(self, value):
self._point_description_format = validators.string(value, allow_empty = True)
@property
def provider(self) -> Optional[ProviderOptions]:
""""""
return self._provider
@provider.setter
@class_sensitive(ProviderOptions)
def provider(self, value):
self._provider = value
@property
def show_in_legend(self) -> Optional[bool]:
"""Whether to display this particular series or series type in the legend.
Standalone series are shown in the legend by default, and linked series are not.
:rtype: :class:`bool <python:bool>` or :obj:`None <python:None>`
"""
return self._show_in_legend
@show_in_legend.setter
def show_in_legend(self, value):
if value is None:
self._show_in_legend = None
else:
self._show_in_legend = bool(value)
@property
def skip_keyboard_navigation(self) -> Optional[bool]:
"""If ``True``, the accessibility module will skip past this series when executing
keyboard navigation.
:rtype: :class:`bool <python:bool>` or :obj:`None <python:None>`
"""
return self._skip_keyboard_navigation
@skip_keyboard_navigation.setter
def skip_keyboard_navigation(self, value):
if value is None:
self._skip_keyboard_navigation = None
else:
self._skip_keyboard_navigation = bool(value)
@property
def states(self) -> Optional[States]:
"""Configuration for state-specific configuration to apply to the data series.
:rtype: :class:`States` or :obj:`None <python:None>`
"""
return self._states
@states.setter
@class_sensitive(States)
def states(self, value):
self._states = value
@property
def visible(self) -> Optional[bool]:
"""If ``True``, the series is initially visible. If ``False``, the series is
hidden by default. Defaults to ``True``.
:rtype: :class:`bool <python:bool>` or :obj:`None <python:None>`
"""
return self._visible
@visible.setter
def visible(self, value):
if value is None:
self._visible = None
else:
self._visible = bool(value)
@property
def z_index(self) -> Optional[int | float | Decimal]:
"""Z-index of the series. Defaults to :obj:`None <python:None>`.
:rtype: numeric or :obj:`None <python:None>`
"""
return self._z_index
@z_index.setter
def z_index(self, value):
self._z_index = validators.numeric(value, allow_empty = True)
@classmethod
def _get_kwargs_from_dict(cls, as_dict):
"""Convenience method which returns the keyword arguments used to initialize the
class from a Highcharts Javascript-compatible :class:`dict <python:dict>` object.
:param as_dict: The HighCharts JS compatible :class:`dict <python:dict>`
representation of the object.
:type as_dict: :class:`dict <python:dict>`
:returns: The keyword arguments that would be used to initialize an instance.
:rtype: :class:`dict <python:dict>`
"""
kwargs = {
'accessibility': as_dict.get('accessibility', None),
'class_name': as_dict.get('className', None),
'custom': as_dict.get('custom', None),
'description': as_dict.get('description', None),
'events': as_dict.get('events', None),
'include_in_data_export': as_dict.get('includeInDataExport', None),
'legend_symbol': as_dict.get('legendSymbol', None),
'opacity': as_dict.get('opacity', None),
'point_description_format': as_dict.get('pointDescriptionFormat', None),
'provider': as_dict.get('provider', None),
'show_in_legend': as_dict.get('showInLegend', None),
'skip_keyboard_navigation': as_dict.get('skipKeyboardNavigation', None),
'states': as_dict.get('states', None),
'visible': as_dict.get('visible', None),
'z_index': as_dict.get('zIndex', None),
}
return kwargs
def _to_untrimmed_dict(self, in_cls = None) -> dict:
untrimmed = {
'accessibility': self.accessibility,
'className': self.class_name,
'custom': self.custom,
'description': self.description,
'events': self.events,
'includeInDataExport': self.include_in_data_export,
'legendSymbol': self.legend_symbol,
'opacity': self.opacity,
'pointDescriptionFormat': self.point_description_format,
'provider': self.provider,
'showInLegend': self.show_in_legend,
'skipKeyboardNavigation': self.skip_keyboard_navigation,
'states': self.states,
'visible': self.visible,
'type': self.type,
'zIndex': self.z_index,
}
return untrimmed